From 49ee4be1e01dd4881409bd89e2b9df398a03cbf2 Mon Sep 17 00:00:00 2001 From: John Marino Date: Wed, 28 May 2014 12:50:04 +0200 Subject: [PATCH] Removed copies of hostapd/wpa to prepare for branch merge The contrib directories for hostapd and wpa_supplicant were just copies of their respective vendor branches. They were never merged into the master branch. To prepare for their first merging, let's remove the existing copies of these two contrib subdirectories completely to avoid conflicts. This is the first of four steps to update WPA Supplicant in base. Step 2: Merge in hostapd and wpa_supplicant vendor branches (ver 2.1) Step 3: Add local modifications to hostapd and wpa_supplicant Step 4: Update makefile and conf files accordingly --- contrib/hostapd/COPYING | 340 -- contrib/hostapd/README | 19 - contrib/hostapd/README.DELETED | 36 - contrib/hostapd/README.DRAGONFLY | 23 - contrib/hostapd/hostapd/ChangeLog | 597 --- contrib/hostapd/hostapd/README | 390 -- contrib/hostapd/hostapd/README-WPS | 239 -- contrib/hostapd/hostapd/accounting.c | 510 --- contrib/hostapd/hostapd/accounting.h | 26 - contrib/hostapd/hostapd/ap.h | 139 - contrib/hostapd/hostapd/ap_list.c | 501 --- contrib/hostapd/hostapd/ap_list.h | 71 - contrib/hostapd/hostapd/beacon.c | 467 --- contrib/hostapd/hostapd/beacon.h | 24 - contrib/hostapd/hostapd/config.c | 2622 ------------- contrib/hostapd/hostapd/config.h | 415 -- contrib/hostapd/hostapd/ctrl_iface.c | 610 --- contrib/hostapd/hostapd/ctrl_iface.h | 21 - contrib/hostapd/hostapd/driver.h | 798 ---- contrib/hostapd/hostapd/driver_atheros.c | 1457 ------- contrib/hostapd/hostapd/driver_bsd.c | 839 ---- contrib/hostapd/hostapd/driver_hostap.c | 1279 ------- contrib/hostapd/hostapd/driver_madwifi.c | 1483 -------- contrib/hostapd/hostapd/driver_nl80211.c | 2708 ------------- contrib/hostapd/hostapd/driver_none.c | 62 - contrib/hostapd/hostapd/driver_prism54.c | 1091 ------ contrib/hostapd/hostapd/driver_test.c | 1300 ------- contrib/hostapd/hostapd/driver_wired.c | 372 -- contrib/hostapd/hostapd/drivers.c | 77 - contrib/hostapd/hostapd/eapol_sm.c | 1342 ------- contrib/hostapd/hostapd/eapol_sm.h | 260 -- contrib/hostapd/hostapd/hostap_common.h | 216 -- contrib/hostapd/hostapd/hostapd.c | 2039 ---------- contrib/hostapd/hostapd/hostapd.h | 238 -- contrib/hostapd/hostapd/hostapd_cli.c | 677 ---- contrib/hostapd/hostapd/hw_features.c | 494 --- contrib/hostapd/hostapd/hw_features.h | 62 - contrib/hostapd/hostapd/iapp.c | 553 --- contrib/hostapd/hostapd/iapp.h | 54 - contrib/hostapd/hostapd/ieee802_11.c | 1833 --------- contrib/hostapd/hostapd/ieee802_11.h | 56 - contrib/hostapd/hostapd/ieee802_11_auth.c | 523 --- contrib/hostapd/hostapd/ieee802_11_auth.h | 33 - contrib/hostapd/hostapd/ieee802_1x.c | 2042 ---------- contrib/hostapd/hostapd/ieee802_1x.h | 90 - contrib/hostapd/hostapd/logwatch/README | 9 - contrib/hostapd/hostapd/mlme.c | 180 - contrib/hostapd/hostapd/mlme.h | 40 - contrib/hostapd/hostapd/nt_password_hash.c | 52 - contrib/hostapd/hostapd/peerkey.c | 402 -- contrib/hostapd/hostapd/pmksa_cache.c | 455 --- contrib/hostapd/hostapd/pmksa_cache.h | 62 - contrib/hostapd/hostapd/preauth.c | 276 -- contrib/hostapd/hostapd/preauth.h | 58 - contrib/hostapd/hostapd/prism54.h | 177 - contrib/hostapd/hostapd/priv_netlink.h | 71 - contrib/hostapd/hostapd/radiotap.c | 287 -- contrib/hostapd/hostapd/radiotap.h | 242 -- contrib/hostapd/hostapd/radiotap_iter.h | 41 - contrib/hostapd/hostapd/sta_info.c | 711 ---- contrib/hostapd/hostapd/sta_info.h | 43 - contrib/hostapd/hostapd/vlan_init.c | 826 ---- contrib/hostapd/hostapd/vlan_init.h | 31 - contrib/hostapd/hostapd/wme.c | 335 -- contrib/hostapd/hostapd/wme.h | 112 - contrib/hostapd/hostapd/wpa.c | 2484 ------------ contrib/hostapd/hostapd/wpa.h | 284 -- contrib/hostapd/hostapd/wpa_auth_i.h | 221 -- contrib/hostapd/hostapd/wpa_auth_ie.c | 864 ----- contrib/hostapd/hostapd/wpa_auth_ie.h | 54 - contrib/hostapd/hostapd/wpa_ft.c | 1500 -------- contrib/hostapd/hostapd/wps_hostapd.c | 1029 ----- contrib/hostapd/hostapd/wps_hostapd.h | 48 - .../openssl-0.9.8-tls-extensions.patch | 429 --- .../openssl-0.9.8d-tls-extensions.patch | 429 --- .../openssl-0.9.8e-tls-extensions.patch | 353 -- .../openssl-0.9.8g-tls-extensions.patch | 330 -- .../openssl-0.9.8h-tls-extensions.patch | 344 -- .../openssl-0.9.8i-tls-extensions.patch | 404 -- .../openssl-0.9.9-session-ticket.patch | 374 -- contrib/hostapd/src/common/defs.h | 199 - contrib/hostapd/src/common/eapol_common.h | 47 - .../hostapd/src/common/ieee802_11_common.c | 259 -- .../hostapd/src/common/ieee802_11_common.h | 74 - contrib/hostapd/src/common/ieee802_11_defs.h | 593 --- contrib/hostapd/src/common/nl80211_copy.h | 1434 ------- contrib/hostapd/src/common/privsep_commands.h | 78 - contrib/hostapd/src/common/version.h | 6 - contrib/hostapd/src/common/wireless_copy.h | 1099 ------ contrib/hostapd/src/common/wpa_common.c | 570 --- contrib/hostapd/src/common/wpa_common.h | 335 -- contrib/hostapd/src/common/wpa_ctrl.c | 455 --- contrib/hostapd/src/common/wpa_ctrl.h | 213 -- contrib/hostapd/src/crypto/aes.c | 1127 ------ contrib/hostapd/src/crypto/aes.h | 25 - contrib/hostapd/src/crypto/aes_wrap.c | 533 --- contrib/hostapd/src/crypto/aes_wrap.h | 48 - contrib/hostapd/src/crypto/crypto.h | 431 --- contrib/hostapd/src/crypto/crypto_cryptoapi.c | 786 ---- contrib/hostapd/src/crypto/crypto_gnutls.c | 311 -- contrib/hostapd/src/crypto/crypto_internal.c | 836 ---- .../hostapd/src/crypto/crypto_libtomcrypt.c | 736 ---- contrib/hostapd/src/crypto/crypto_none.c | 28 - contrib/hostapd/src/crypto/crypto_openssl.c | 360 -- contrib/hostapd/src/crypto/des.c | 479 --- contrib/hostapd/src/crypto/dh_groups.c | 630 --- contrib/hostapd/src/crypto/dh_groups.h | 32 - contrib/hostapd/src/crypto/md4.c | 282 -- contrib/hostapd/src/crypto/md5.c | 394 -- contrib/hostapd/src/crypto/md5.h | 34 - contrib/hostapd/src/crypto/ms_funcs.c | 446 --- contrib/hostapd/src/crypto/ms_funcs.h | 64 - contrib/hostapd/src/crypto/rc4.c | 70 - contrib/hostapd/src/crypto/rc4.h | 21 - contrib/hostapd/src/crypto/sha1.c | 733 ---- contrib/hostapd/src/crypto/sha1.h | 42 - contrib/hostapd/src/crypto/sha256.c | 382 -- contrib/hostapd/src/crypto/sha256.h | 27 - contrib/hostapd/src/crypto/tls.h | 538 --- contrib/hostapd/src/crypto/tls_gnutls.c | 1428 ------- contrib/hostapd/src/crypto/tls_internal.c | 569 --- contrib/hostapd/src/crypto/tls_none.c | 234 -- contrib/hostapd/src/crypto/tls_openssl.c | 2671 ------------- contrib/hostapd/src/crypto/tls_schannel.c | 789 ---- contrib/hostapd/src/drivers/Apple80211.h | 156 - .../hostapd/src/drivers/MobileApple80211.c | 189 - .../hostapd/src/drivers/MobileApple80211.h | 43 - contrib/hostapd/src/drivers/driver.h | 1325 ------- contrib/hostapd/src/drivers/driver_atmel.c | 506 --- contrib/hostapd/src/drivers/driver_broadcom.c | 604 --- contrib/hostapd/src/drivers/driver_bsd.c | 794 ---- contrib/hostapd/src/drivers/driver_hostap.c | 513 --- contrib/hostapd/src/drivers/driver_hostap.h | 153 - contrib/hostapd/src/drivers/driver_ipw.c | 463 --- contrib/hostapd/src/drivers/driver_madwifi.c | 601 --- contrib/hostapd/src/drivers/driver_ndis.c | 3139 --------------- contrib/hostapd/src/drivers/driver_ndis.h | 64 - contrib/hostapd/src/drivers/driver_ndis_.c | 105 - .../hostapd/src/drivers/driver_ndiswrapper.c | 370 -- contrib/hostapd/src/drivers/driver_nl80211.c | 2766 -------------- contrib/hostapd/src/drivers/driver_prism54.c | 381 -- contrib/hostapd/src/drivers/driver_privsep.c | 820 ---- contrib/hostapd/src/drivers/driver_ps3.c | 186 - contrib/hostapd/src/drivers/driver_ralink.c | 1505 -------- contrib/hostapd/src/drivers/driver_ralink.h | 382 -- .../hostapd/src/drivers/driver_roboswitch.c | 476 --- contrib/hostapd/src/drivers/driver_test.c | 1230 ------ contrib/hostapd/src/drivers/driver_wext.c | 2375 ------------ contrib/hostapd/src/drivers/driver_wext.h | 82 - contrib/hostapd/src/drivers/driver_wired.c | 286 -- contrib/hostapd/src/drivers/drivers.c | 139 - contrib/hostapd/src/drivers/ndis_events.c | 808 ---- contrib/hostapd/src/drivers/priv_netlink.h | 104 - contrib/hostapd/src/drivers/radiotap.c | 287 -- contrib/hostapd/src/drivers/radiotap.h | 242 -- contrib/hostapd/src/drivers/radiotap_iter.h | 41 - contrib/hostapd/src/drivers/scan_helpers.c | 182 - contrib/hostapd/src/eap_common/chap.c | 35 - contrib/hostapd/src/eap_common/chap.h | 23 - contrib/hostapd/src/eap_common/eap_common.c | 184 - contrib/hostapd/src/eap_common/eap_common.h | 28 - contrib/hostapd/src/eap_common/eap_defs.h | 85 - .../hostapd/src/eap_common/eap_fast_common.c | 304 -- .../hostapd/src/eap_common/eap_fast_common.h | 113 - .../hostapd/src/eap_common/eap_gpsk_common.c | 426 --- .../hostapd/src/eap_common/eap_gpsk_common.h | 66 - .../hostapd/src/eap_common/eap_ikev2_common.c | 132 - .../hostapd/src/eap_common/eap_ikev2_common.h | 42 - .../hostapd/src/eap_common/eap_pax_common.c | 150 - .../hostapd/src/eap_common/eap_pax_common.h | 97 - .../hostapd/src/eap_common/eap_peap_common.c | 88 - .../hostapd/src/eap_common/eap_peap_common.h | 22 - .../hostapd/src/eap_common/eap_psk_common.c | 74 - .../hostapd/src/eap_common/eap_psk_common.h | 78 - .../hostapd/src/eap_common/eap_sake_common.c | 393 -- .../hostapd/src/eap_common/eap_sake_common.h | 102 - .../hostapd/src/eap_common/eap_sim_common.c | 1214 ------ .../hostapd/src/eap_common/eap_sim_common.h | 235 -- .../hostapd/src/eap_common/eap_tlv_common.h | 118 - contrib/hostapd/src/eap_common/eap_ttls.h | 71 - .../hostapd/src/eap_common/eap_wsc_common.c | 39 - .../hostapd/src/eap_common/eap_wsc_common.h | 33 - contrib/hostapd/src/eap_common/ikev2_common.c | 796 ---- contrib/hostapd/src/eap_common/ikev2_common.h | 344 -- contrib/hostapd/src/eap_peer/eap.c | 2075 ---------- contrib/hostapd/src/eap_peer/eap.h | 291 -- contrib/hostapd/src/eap_peer/eap_aka.c | 1391 ------- contrib/hostapd/src/eap_peer/eap_config.h | 660 ---- contrib/hostapd/src/eap_peer/eap_fast.c | 1712 --------- contrib/hostapd/src/eap_peer/eap_fast_pac.c | 921 ----- contrib/hostapd/src/eap_peer/eap_fast_pac.h | 56 - contrib/hostapd/src/eap_peer/eap_gpsk.c | 737 ---- contrib/hostapd/src/eap_peer/eap_gtc.c | 151 - contrib/hostapd/src/eap_peer/eap_i.h | 355 -- contrib/hostapd/src/eap_peer/eap_ikev2.c | 506 --- contrib/hostapd/src/eap_peer/eap_leap.c | 403 -- contrib/hostapd/src/eap_peer/eap_md5.c | 120 - contrib/hostapd/src/eap_peer/eap_methods.c | 528 --- contrib/hostapd/src/eap_peer/eap_methods.h | 92 - contrib/hostapd/src/eap_peer/eap_mschapv2.c | 877 ----- contrib/hostapd/src/eap_peer/eap_otp.c | 107 - contrib/hostapd/src/eap_peer/eap_pax.c | 532 --- contrib/hostapd/src/eap_peer/eap_peap.c | 1288 ------- contrib/hostapd/src/eap_peer/eap_psk.c | 482 --- contrib/hostapd/src/eap_peer/eap_sake.c | 499 --- contrib/hostapd/src/eap_peer/eap_sim.c | 1102 ------ contrib/hostapd/src/eap_peer/eap_tls.c | 289 -- contrib/hostapd/src/eap_peer/eap_tls_common.c | 1064 ------ contrib/hostapd/src/eap_peer/eap_tls_common.h | 139 - contrib/hostapd/src/eap_peer/eap_tnc.c | 433 --- contrib/hostapd/src/eap_peer/eap_ttls.c | 1983 ---------- .../hostapd/src/eap_peer/eap_vendor_test.c | 195 - contrib/hostapd/src/eap_peer/eap_wsc.c | 453 --- contrib/hostapd/src/eap_peer/ikev2.c | 1303 ------- contrib/hostapd/src/eap_peer/ikev2.h | 65 - contrib/hostapd/src/eap_peer/mschapv2.c | 119 - contrib/hostapd/src/eap_peer/mschapv2.h | 34 - contrib/hostapd/src/eap_peer/tncc.c | 1369 ------- contrib/hostapd/src/eap_peer/tncc.h | 42 - contrib/hostapd/src/eap_server/eap.c | 1345 ------- contrib/hostapd/src/eap_server/eap.h | 122 - contrib/hostapd/src/eap_server/eap_aka.c | 1278 ------- contrib/hostapd/src/eap_server/eap_fast.c | 1641 -------- contrib/hostapd/src/eap_server/eap_gpsk.c | 633 --- contrib/hostapd/src/eap_server/eap_gtc.c | 230 -- contrib/hostapd/src/eap_server/eap_i.h | 194 - contrib/hostapd/src/eap_server/eap_identity.c | 180 - contrib/hostapd/src/eap_server/eap_ikev2.c | 538 --- contrib/hostapd/src/eap_server/eap_md5.c | 176 - contrib/hostapd/src/eap_server/eap_methods.c | 308 -- contrib/hostapd/src/eap_server/eap_methods.h | 29 - contrib/hostapd/src/eap_server/eap_mschapv2.c | 568 --- contrib/hostapd/src/eap_server/eap_pax.c | 569 --- contrib/hostapd/src/eap_server/eap_peap.c | 1421 ------- contrib/hostapd/src/eap_server/eap_psk.c | 517 --- contrib/hostapd/src/eap_server/eap_sake.c | 542 --- contrib/hostapd/src/eap_server/eap_sim.c | 797 ---- contrib/hostapd/src/eap_server/eap_sim_db.c | 1337 ------- contrib/hostapd/src/eap_server/eap_sim_db.h | 107 - contrib/hostapd/src/eap_server/eap_tls.c | 286 -- .../hostapd/src/eap_server/eap_tls_common.c | 410 -- .../hostapd/src/eap_server/eap_tls_common.h | 64 - contrib/hostapd/src/eap_server/eap_tnc.c | 536 --- contrib/hostapd/src/eap_server/eap_ttls.c | 1477 ------- .../hostapd/src/eap_server/eap_vendor_test.c | 198 - contrib/hostapd/src/eap_server/eap_wsc.c | 498 --- contrib/hostapd/src/eap_server/ikev2.c | 1205 ------ contrib/hostapd/src/eap_server/ikev2.h | 67 - contrib/hostapd/src/eap_server/tncs.c | 1272 ------- contrib/hostapd/src/eap_server/tncs.h | 49 - .../hostapd/src/eapol_supp/eapol_supp_sm.c | 1876 --------- .../hostapd/src/eapol_supp/eapol_supp_sm.h | 342 -- contrib/hostapd/src/hlr_auc_gw/hlr_auc_gw.c | 714 ---- contrib/hostapd/src/hlr_auc_gw/milenage.c | 1142 ------ contrib/hostapd/src/hlr_auc_gw/milenage.h | 29 - contrib/hostapd/src/l2_packet/l2_packet.h | 130 - .../hostapd/src/l2_packet/l2_packet_freebsd.c | 285 -- .../hostapd/src/l2_packet/l2_packet_linux.c | 200 - .../hostapd/src/l2_packet/l2_packet_ndis.c | 516 --- .../hostapd/src/l2_packet/l2_packet_none.c | 123 - .../hostapd/src/l2_packet/l2_packet_pcap.c | 386 -- .../hostapd/src/l2_packet/l2_packet_privsep.c | 267 -- .../hostapd/src/l2_packet/l2_packet_winpcap.c | 341 -- contrib/hostapd/src/radius/radius.c | 1234 ------ contrib/hostapd/src/radius/radius.h | 272 -- contrib/hostapd/src/radius/radius_client.c | 1301 ------- contrib/hostapd/src/radius/radius_client.h | 108 - contrib/hostapd/src/radius/radius_server.c | 1311 ------- contrib/hostapd/src/radius/radius_server.h | 82 - contrib/hostapd/src/rsn_supp/peerkey.c | 1182 ------ contrib/hostapd/src/rsn_supp/peerkey.h | 87 - contrib/hostapd/src/rsn_supp/pmksa_cache.c | 511 --- contrib/hostapd/src/rsn_supp/pmksa_cache.h | 126 - contrib/hostapd/src/rsn_supp/preauth.c | 529 --- contrib/hostapd/src/rsn_supp/preauth.h | 78 - contrib/hostapd/src/rsn_supp/wpa.c | 2408 ------------ contrib/hostapd/src/rsn_supp/wpa.h | 320 -- contrib/hostapd/src/rsn_supp/wpa_ft.c | 872 ----- contrib/hostapd/src/rsn_supp/wpa_i.h | 245 -- contrib/hostapd/src/rsn_supp/wpa_ie.c | 536 --- contrib/hostapd/src/rsn_supp/wpa_ie.h | 52 - contrib/hostapd/src/tls/asn1.c | 209 - contrib/hostapd/src/tls/asn1.h | 71 - contrib/hostapd/src/tls/asn1_test.c | 210 - contrib/hostapd/src/tls/bignum.c | 230 -- contrib/hostapd/src/tls/bignum.h | 38 - contrib/hostapd/src/tls/libtommath.c | 3381 ----------------- contrib/hostapd/src/tls/rsa.c | 361 -- contrib/hostapd/src/tls/rsa.h | 29 - contrib/hostapd/src/tls/tlsv1_client.c | 671 ---- contrib/hostapd/src/tls/tlsv1_client.h | 59 - contrib/hostapd/src/tls/tlsv1_client_i.h | 87 - contrib/hostapd/src/tls/tlsv1_client_read.c | 976 ----- contrib/hostapd/src/tls/tlsv1_client_write.c | 802 ---- contrib/hostapd/src/tls/tlsv1_common.c | 241 -- contrib/hostapd/src/tls/tlsv1_common.h | 216 -- contrib/hostapd/src/tls/tlsv1_cred.c | 422 -- contrib/hostapd/src/tls/tlsv1_cred.h | 46 - contrib/hostapd/src/tls/tlsv1_record.c | 409 -- contrib/hostapd/src/tls/tlsv1_record.h | 74 - contrib/hostapd/src/tls/tlsv1_server.c | 596 --- contrib/hostapd/src/tls/tlsv1_server.h | 54 - contrib/hostapd/src/tls/tlsv1_server_i.h | 77 - contrib/hostapd/src/tls/tlsv1_server_read.c | 1138 ------ contrib/hostapd/src/tls/tlsv1_server_write.c | 796 ---- contrib/hostapd/src/tls/x509v3.c | 1724 --------- contrib/hostapd/src/tls/x509v3.h | 154 - contrib/hostapd/src/utils/base64.c | 189 - contrib/hostapd/src/utils/base64.h | 23 - contrib/hostapd/src/utils/build_config.h | 95 - contrib/hostapd/src/utils/common.c | 333 -- contrib/hostapd/src/utils/common.h | 458 --- contrib/hostapd/src/utils/eloop.c | 577 --- contrib/hostapd/src/utils/eloop.h | 340 -- contrib/hostapd/src/utils/eloop_none.c | 410 -- contrib/hostapd/src/utils/eloop_win.c | 622 --- contrib/hostapd/src/utils/includes.h | 59 - contrib/hostapd/src/utils/ip_addr.c | 83 - contrib/hostapd/src/utils/ip_addr.h | 33 - contrib/hostapd/src/utils/os.h | 501 --- contrib/hostapd/src/utils/os_internal.c | 466 --- contrib/hostapd/src/utils/os_none.c | 226 -- contrib/hostapd/src/utils/os_unix.c | 299 -- contrib/hostapd/src/utils/os_win32.c | 222 -- contrib/hostapd/src/utils/pcsc_funcs.c | 1238 ------ contrib/hostapd/src/utils/pcsc_funcs.h | 68 - contrib/hostapd/src/utils/state_machine.h | 144 - contrib/hostapd/src/utils/uuid.c | 107 - contrib/hostapd/src/utils/uuid.h | 25 - contrib/hostapd/src/utils/wpa_debug.c | 350 -- contrib/hostapd/src/utils/wpa_debug.h | 239 -- contrib/hostapd/src/utils/wpabuf.c | 216 -- contrib/hostapd/src/utils/wpabuf.h | 156 - contrib/hostapd/src/wps/httpread.c | 861 ----- contrib/hostapd/src/wps/httpread.h | 123 - contrib/hostapd/src/wps/wps.c | 335 -- contrib/hostapd/src/wps/wps.h | 533 --- contrib/hostapd/src/wps/wps_attr_build.c | 254 -- contrib/hostapd/src/wps/wps_attr_parse.c | 437 --- contrib/hostapd/src/wps/wps_attr_process.c | 323 -- contrib/hostapd/src/wps/wps_common.c | 305 -- contrib/hostapd/src/wps/wps_defs.h | 297 -- contrib/hostapd/src/wps/wps_dev_attr.c | 390 -- contrib/hostapd/src/wps/wps_dev_attr.h | 33 - contrib/hostapd/src/wps/wps_enrollee.c | 1211 ------ contrib/hostapd/src/wps/wps_i.h | 246 -- contrib/hostapd/src/wps/wps_registrar.c | 2640 ------------- contrib/hostapd/src/wps/wps_upnp.c | 1147 ------ contrib/hostapd/src/wps/wps_upnp.h | 67 - contrib/hostapd/src/wps/wps_upnp_event.c | 534 --- contrib/hostapd/src/wps/wps_upnp_i.h | 193 - contrib/hostapd/src/wps/wps_upnp_ssdp.c | 921 ----- contrib/hostapd/src/wps/wps_upnp_web.c | 1964 ---------- contrib/wpa_supplicant/COPYING | 340 -- contrib/wpa_supplicant/README | 19 - contrib/wpa_supplicant/README.DELETED | 84 - contrib/wpa_supplicant/README.DRAGONFLY | 27 - .../openssl-0.9.8-tls-extensions.patch | 429 --- .../openssl-0.9.8d-tls-extensions.patch | 429 --- .../openssl-0.9.8e-tls-extensions.patch | 353 -- .../openssl-0.9.8g-tls-extensions.patch | 330 -- .../openssl-0.9.8h-tls-extensions.patch | 344 -- .../openssl-0.9.8i-tls-extensions.patch | 404 -- .../openssl-0.9.9-session-ticket.patch | 374 -- contrib/wpa_supplicant/src/common/defs.h | 199 - .../wpa_supplicant/src/common/eapol_common.h | 47 - .../src/common/ieee802_11_common.c | 259 -- .../src/common/ieee802_11_common.h | 74 - .../src/common/ieee802_11_defs.h | 593 --- .../wpa_supplicant/src/common/nl80211_copy.h | 1434 ------- .../src/common/privsep_commands.h | 78 - contrib/wpa_supplicant/src/common/version.h | 6 - .../wpa_supplicant/src/common/wireless_copy.h | 1099 ------ .../wpa_supplicant/src/common/wpa_common.c | 570 --- .../wpa_supplicant/src/common/wpa_common.h | 335 -- contrib/wpa_supplicant/src/common/wpa_ctrl.c | 455 --- contrib/wpa_supplicant/src/common/wpa_ctrl.h | 213 -- contrib/wpa_supplicant/src/crypto/aes.c | 1127 ------ contrib/wpa_supplicant/src/crypto/aes.h | 25 - contrib/wpa_supplicant/src/crypto/aes_wrap.c | 533 --- contrib/wpa_supplicant/src/crypto/aes_wrap.h | 48 - contrib/wpa_supplicant/src/crypto/crypto.h | 431 --- .../src/crypto/crypto_cryptoapi.c | 786 ---- .../wpa_supplicant/src/crypto/crypto_gnutls.c | 311 -- .../src/crypto/crypto_internal.c | 836 ---- .../src/crypto/crypto_libtomcrypt.c | 736 ---- .../wpa_supplicant/src/crypto/crypto_none.c | 28 - .../src/crypto/crypto_openssl.c | 360 -- contrib/wpa_supplicant/src/crypto/des.c | 479 --- contrib/wpa_supplicant/src/crypto/dh_groups.c | 630 --- contrib/wpa_supplicant/src/crypto/dh_groups.h | 32 - contrib/wpa_supplicant/src/crypto/md4.c | 282 -- contrib/wpa_supplicant/src/crypto/md5.c | 394 -- contrib/wpa_supplicant/src/crypto/md5.h | 34 - contrib/wpa_supplicant/src/crypto/ms_funcs.c | 446 --- contrib/wpa_supplicant/src/crypto/ms_funcs.h | 64 - contrib/wpa_supplicant/src/crypto/rc4.c | 70 - contrib/wpa_supplicant/src/crypto/rc4.h | 21 - contrib/wpa_supplicant/src/crypto/sha1.c | 733 ---- contrib/wpa_supplicant/src/crypto/sha1.h | 42 - contrib/wpa_supplicant/src/crypto/sha256.c | 382 -- contrib/wpa_supplicant/src/crypto/sha256.h | 27 - contrib/wpa_supplicant/src/crypto/tls.h | 538 --- .../wpa_supplicant/src/crypto/tls_gnutls.c | 1428 ------- .../wpa_supplicant/src/crypto/tls_internal.c | 569 --- contrib/wpa_supplicant/src/crypto/tls_none.c | 234 -- .../wpa_supplicant/src/crypto/tls_openssl.c | 2671 ------------- .../wpa_supplicant/src/crypto/tls_schannel.c | 789 ---- .../wpa_supplicant/src/drivers/Apple80211.h | 156 - .../src/drivers/MobileApple80211.c | 189 - .../src/drivers/MobileApple80211.h | 43 - contrib/wpa_supplicant/src/drivers/driver.h | 1325 ------- .../wpa_supplicant/src/drivers/driver_atmel.c | 506 --- .../src/drivers/driver_broadcom.c | 604 --- .../wpa_supplicant/src/drivers/driver_bsd.c | 794 ---- .../src/drivers/driver_hostap.c | 513 --- .../src/drivers/driver_hostap.h | 153 - .../wpa_supplicant/src/drivers/driver_ipw.c | 463 --- .../src/drivers/driver_madwifi.c | 601 --- .../wpa_supplicant/src/drivers/driver_ndis.c | 3139 --------------- .../wpa_supplicant/src/drivers/driver_ndis.h | 64 - .../wpa_supplicant/src/drivers/driver_ndis_.c | 105 - .../src/drivers/driver_ndiswrapper.c | 370 -- .../src/drivers/driver_nl80211.c | 2766 -------------- .../src/drivers/driver_prism54.c | 381 -- .../src/drivers/driver_privsep.c | 820 ---- .../wpa_supplicant/src/drivers/driver_ps3.c | 186 - .../src/drivers/driver_ralink.c | 1505 -------- .../src/drivers/driver_ralink.h | 382 -- .../src/drivers/driver_roboswitch.c | 476 --- .../wpa_supplicant/src/drivers/driver_test.c | 1230 ------ .../wpa_supplicant/src/drivers/driver_wext.c | 2375 ------------ .../wpa_supplicant/src/drivers/driver_wext.h | 82 - .../wpa_supplicant/src/drivers/driver_wired.c | 286 -- contrib/wpa_supplicant/src/drivers/drivers.c | 139 - .../wpa_supplicant/src/drivers/ndis_events.c | 808 ---- .../wpa_supplicant/src/drivers/priv_netlink.h | 104 - contrib/wpa_supplicant/src/drivers/radiotap.c | 287 -- contrib/wpa_supplicant/src/drivers/radiotap.h | 242 -- .../src/drivers/radiotap_iter.h | 41 - .../wpa_supplicant/src/drivers/scan_helpers.c | 182 - contrib/wpa_supplicant/src/eap_common/chap.c | 35 - contrib/wpa_supplicant/src/eap_common/chap.h | 23 - .../src/eap_common/eap_common.c | 184 - .../src/eap_common/eap_common.h | 28 - .../wpa_supplicant/src/eap_common/eap_defs.h | 85 - .../src/eap_common/eap_fast_common.c | 304 -- .../src/eap_common/eap_fast_common.h | 113 - .../src/eap_common/eap_gpsk_common.c | 426 --- .../src/eap_common/eap_gpsk_common.h | 66 - .../src/eap_common/eap_ikev2_common.c | 132 - .../src/eap_common/eap_ikev2_common.h | 42 - .../src/eap_common/eap_pax_common.c | 150 - .../src/eap_common/eap_pax_common.h | 97 - .../src/eap_common/eap_peap_common.c | 88 - .../src/eap_common/eap_peap_common.h | 22 - .../src/eap_common/eap_psk_common.c | 74 - .../src/eap_common/eap_psk_common.h | 78 - .../src/eap_common/eap_sake_common.c | 393 -- .../src/eap_common/eap_sake_common.h | 102 - .../src/eap_common/eap_sim_common.c | 1214 ------ .../src/eap_common/eap_sim_common.h | 235 -- .../src/eap_common/eap_tlv_common.h | 118 - .../wpa_supplicant/src/eap_common/eap_ttls.h | 71 - .../src/eap_common/eap_wsc_common.c | 39 - .../src/eap_common/eap_wsc_common.h | 33 - .../src/eap_common/ikev2_common.c | 796 ---- .../src/eap_common/ikev2_common.h | 344 -- contrib/wpa_supplicant/src/eap_peer/eap.c | 2075 ---------- contrib/wpa_supplicant/src/eap_peer/eap.h | 291 -- contrib/wpa_supplicant/src/eap_peer/eap_aka.c | 1391 ------- .../wpa_supplicant/src/eap_peer/eap_config.h | 660 ---- .../wpa_supplicant/src/eap_peer/eap_fast.c | 1712 --------- .../src/eap_peer/eap_fast_pac.c | 921 ----- .../src/eap_peer/eap_fast_pac.h | 56 - .../wpa_supplicant/src/eap_peer/eap_gpsk.c | 737 ---- contrib/wpa_supplicant/src/eap_peer/eap_gtc.c | 151 - contrib/wpa_supplicant/src/eap_peer/eap_i.h | 355 -- .../wpa_supplicant/src/eap_peer/eap_ikev2.c | 506 --- .../wpa_supplicant/src/eap_peer/eap_leap.c | 403 -- contrib/wpa_supplicant/src/eap_peer/eap_md5.c | 120 - .../wpa_supplicant/src/eap_peer/eap_methods.c | 528 --- .../wpa_supplicant/src/eap_peer/eap_methods.h | 92 - .../src/eap_peer/eap_mschapv2.c | 877 ----- contrib/wpa_supplicant/src/eap_peer/eap_otp.c | 107 - contrib/wpa_supplicant/src/eap_peer/eap_pax.c | 532 --- .../wpa_supplicant/src/eap_peer/eap_peap.c | 1288 ------- contrib/wpa_supplicant/src/eap_peer/eap_psk.c | 482 --- .../wpa_supplicant/src/eap_peer/eap_sake.c | 499 --- contrib/wpa_supplicant/src/eap_peer/eap_sim.c | 1102 ------ contrib/wpa_supplicant/src/eap_peer/eap_tls.c | 289 -- .../src/eap_peer/eap_tls_common.c | 1064 ------ .../src/eap_peer/eap_tls_common.h | 139 - contrib/wpa_supplicant/src/eap_peer/eap_tnc.c | 433 --- .../wpa_supplicant/src/eap_peer/eap_ttls.c | 1983 ---------- .../src/eap_peer/eap_vendor_test.c | 195 - contrib/wpa_supplicant/src/eap_peer/eap_wsc.c | 453 --- contrib/wpa_supplicant/src/eap_peer/ikev2.c | 1303 ------- contrib/wpa_supplicant/src/eap_peer/ikev2.h | 65 - .../wpa_supplicant/src/eap_peer/mschapv2.c | 119 - .../wpa_supplicant/src/eap_peer/mschapv2.h | 34 - contrib/wpa_supplicant/src/eap_peer/tncc.c | 1369 ------- contrib/wpa_supplicant/src/eap_peer/tncc.h | 42 - contrib/wpa_supplicant/src/eap_server/eap.c | 1345 ------- contrib/wpa_supplicant/src/eap_server/eap.h | 122 - .../wpa_supplicant/src/eap_server/eap_aka.c | 1278 ------- .../wpa_supplicant/src/eap_server/eap_fast.c | 1641 -------- .../wpa_supplicant/src/eap_server/eap_gpsk.c | 633 --- .../wpa_supplicant/src/eap_server/eap_gtc.c | 230 -- contrib/wpa_supplicant/src/eap_server/eap_i.h | 194 - .../src/eap_server/eap_identity.c | 180 - .../wpa_supplicant/src/eap_server/eap_ikev2.c | 538 --- .../wpa_supplicant/src/eap_server/eap_md5.c | 176 - .../src/eap_server/eap_methods.c | 308 -- .../src/eap_server/eap_methods.h | 29 - .../src/eap_server/eap_mschapv2.c | 568 --- .../wpa_supplicant/src/eap_server/eap_pax.c | 569 --- .../wpa_supplicant/src/eap_server/eap_peap.c | 1421 ------- .../wpa_supplicant/src/eap_server/eap_psk.c | 517 --- .../wpa_supplicant/src/eap_server/eap_sake.c | 542 --- .../wpa_supplicant/src/eap_server/eap_sim.c | 797 ---- .../src/eap_server/eap_sim_db.c | 1337 ------- .../src/eap_server/eap_sim_db.h | 107 - .../wpa_supplicant/src/eap_server/eap_tls.c | 286 -- .../src/eap_server/eap_tls_common.c | 410 -- .../src/eap_server/eap_tls_common.h | 64 - .../wpa_supplicant/src/eap_server/eap_tnc.c | 536 --- .../wpa_supplicant/src/eap_server/eap_ttls.c | 1477 ------- .../src/eap_server/eap_vendor_test.c | 198 - .../wpa_supplicant/src/eap_server/eap_wsc.c | 498 --- contrib/wpa_supplicant/src/eap_server/ikev2.c | 1205 ------ contrib/wpa_supplicant/src/eap_server/ikev2.h | 67 - contrib/wpa_supplicant/src/eap_server/tncs.c | 1272 ------- contrib/wpa_supplicant/src/eap_server/tncs.h | 49 - .../src/eapol_supp/eapol_supp_sm.c | 1876 --------- .../src/eapol_supp/eapol_supp_sm.h | 342 -- .../src/hlr_auc_gw/hlr_auc_gw.c | 714 ---- .../wpa_supplicant/src/hlr_auc_gw/milenage.c | 1142 ------ .../wpa_supplicant/src/hlr_auc_gw/milenage.h | 29 - .../wpa_supplicant/src/l2_packet/l2_packet.h | 130 - .../src/l2_packet/l2_packet_freebsd.c | 285 -- .../src/l2_packet/l2_packet_linux.c | 200 - .../src/l2_packet/l2_packet_ndis.c | 516 --- .../src/l2_packet/l2_packet_none.c | 123 - .../src/l2_packet/l2_packet_pcap.c | 386 -- .../src/l2_packet/l2_packet_privsep.c | 267 -- .../src/l2_packet/l2_packet_winpcap.c | 341 -- contrib/wpa_supplicant/src/radius/radius.c | 1234 ------ contrib/wpa_supplicant/src/radius/radius.h | 272 -- .../wpa_supplicant/src/radius/radius_client.c | 1301 ------- .../wpa_supplicant/src/radius/radius_client.h | 108 - .../wpa_supplicant/src/radius/radius_server.c | 1311 ------- .../wpa_supplicant/src/radius/radius_server.h | 82 - contrib/wpa_supplicant/src/rsn_supp/peerkey.c | 1182 ------ contrib/wpa_supplicant/src/rsn_supp/peerkey.h | 87 - .../wpa_supplicant/src/rsn_supp/pmksa_cache.c | 511 --- .../wpa_supplicant/src/rsn_supp/pmksa_cache.h | 126 - contrib/wpa_supplicant/src/rsn_supp/preauth.c | 529 --- contrib/wpa_supplicant/src/rsn_supp/preauth.h | 78 - contrib/wpa_supplicant/src/rsn_supp/wpa.c | 2408 ------------ contrib/wpa_supplicant/src/rsn_supp/wpa.h | 320 -- contrib/wpa_supplicant/src/rsn_supp/wpa_ft.c | 872 ----- contrib/wpa_supplicant/src/rsn_supp/wpa_i.h | 245 -- contrib/wpa_supplicant/src/rsn_supp/wpa_ie.c | 536 --- contrib/wpa_supplicant/src/rsn_supp/wpa_ie.h | 52 - contrib/wpa_supplicant/src/tls/asn1.c | 209 - contrib/wpa_supplicant/src/tls/asn1.h | 71 - contrib/wpa_supplicant/src/tls/asn1_test.c | 210 - contrib/wpa_supplicant/src/tls/bignum.c | 230 -- contrib/wpa_supplicant/src/tls/bignum.h | 38 - contrib/wpa_supplicant/src/tls/libtommath.c | 3381 ----------------- contrib/wpa_supplicant/src/tls/rsa.c | 361 -- contrib/wpa_supplicant/src/tls/rsa.h | 29 - contrib/wpa_supplicant/src/tls/tlsv1_client.c | 671 ---- contrib/wpa_supplicant/src/tls/tlsv1_client.h | 59 - .../wpa_supplicant/src/tls/tlsv1_client_i.h | 87 - .../src/tls/tlsv1_client_read.c | 976 ----- .../src/tls/tlsv1_client_write.c | 802 ---- contrib/wpa_supplicant/src/tls/tlsv1_common.c | 241 -- contrib/wpa_supplicant/src/tls/tlsv1_common.h | 216 -- contrib/wpa_supplicant/src/tls/tlsv1_cred.c | 422 -- contrib/wpa_supplicant/src/tls/tlsv1_cred.h | 46 - contrib/wpa_supplicant/src/tls/tlsv1_record.c | 409 -- contrib/wpa_supplicant/src/tls/tlsv1_record.h | 74 - contrib/wpa_supplicant/src/tls/tlsv1_server.c | 596 --- contrib/wpa_supplicant/src/tls/tlsv1_server.h | 54 - .../wpa_supplicant/src/tls/tlsv1_server_i.h | 77 - .../src/tls/tlsv1_server_read.c | 1138 ------ .../src/tls/tlsv1_server_write.c | 796 ---- contrib/wpa_supplicant/src/tls/x509v3.c | 1724 --------- contrib/wpa_supplicant/src/tls/x509v3.h | 154 - contrib/wpa_supplicant/src/utils/base64.c | 189 - contrib/wpa_supplicant/src/utils/base64.h | 23 - .../wpa_supplicant/src/utils/build_config.h | 95 - contrib/wpa_supplicant/src/utils/common.c | 333 -- contrib/wpa_supplicant/src/utils/common.h | 458 --- contrib/wpa_supplicant/src/utils/eloop.c | 577 --- contrib/wpa_supplicant/src/utils/eloop.h | 340 -- contrib/wpa_supplicant/src/utils/eloop_none.c | 410 -- contrib/wpa_supplicant/src/utils/eloop_win.c | 622 --- contrib/wpa_supplicant/src/utils/includes.h | 59 - contrib/wpa_supplicant/src/utils/ip_addr.c | 83 - contrib/wpa_supplicant/src/utils/ip_addr.h | 33 - contrib/wpa_supplicant/src/utils/os.h | 501 --- .../wpa_supplicant/src/utils/os_internal.c | 466 --- contrib/wpa_supplicant/src/utils/os_none.c | 226 -- contrib/wpa_supplicant/src/utils/os_unix.c | 299 -- contrib/wpa_supplicant/src/utils/pcsc_funcs.c | 1238 ------ contrib/wpa_supplicant/src/utils/pcsc_funcs.h | 68 - .../wpa_supplicant/src/utils/state_machine.h | 144 - contrib/wpa_supplicant/src/utils/uuid.c | 107 - contrib/wpa_supplicant/src/utils/uuid.h | 25 - contrib/wpa_supplicant/src/utils/wpa_debug.c | 350 -- contrib/wpa_supplicant/src/utils/wpa_debug.h | 239 -- contrib/wpa_supplicant/src/utils/wpabuf.c | 216 -- contrib/wpa_supplicant/src/utils/wpabuf.h | 156 - contrib/wpa_supplicant/src/wps/httpread.c | 861 ----- contrib/wpa_supplicant/src/wps/httpread.h | 123 - contrib/wpa_supplicant/src/wps/wps.c | 335 -- contrib/wpa_supplicant/src/wps/wps.h | 533 --- .../wpa_supplicant/src/wps/wps_attr_build.c | 254 -- .../wpa_supplicant/src/wps/wps_attr_parse.c | 437 --- .../wpa_supplicant/src/wps/wps_attr_process.c | 323 -- contrib/wpa_supplicant/src/wps/wps_common.c | 305 -- contrib/wpa_supplicant/src/wps/wps_defs.h | 297 -- contrib/wpa_supplicant/src/wps/wps_dev_attr.c | 390 -- contrib/wpa_supplicant/src/wps/wps_dev_attr.h | 33 - contrib/wpa_supplicant/src/wps/wps_enrollee.c | 1211 ------ contrib/wpa_supplicant/src/wps/wps_i.h | 246 -- .../wpa_supplicant/src/wps/wps_registrar.c | 2640 ------------- contrib/wpa_supplicant/src/wps/wps_upnp.c | 1147 ------ contrib/wpa_supplicant/src/wps/wps_upnp.h | 67 - .../wpa_supplicant/src/wps/wps_upnp_event.c | 534 --- contrib/wpa_supplicant/src/wps/wps_upnp_i.h | 193 - .../wpa_supplicant/src/wps/wps_upnp_ssdp.c | 921 ----- contrib/wpa_supplicant/src/wps/wps_upnp_web.c | 1964 ---------- .../wpa_supplicant/wpa_supplicant/ChangeLog | 1196 ------ contrib/wpa_supplicant/wpa_supplicant/README | 1025 ----- .../wpa_supplicant/wpa_supplicant/README-WPS | 189 - .../wpa_supplicant/README-Windows.txt | 450 --- .../wpa_supplicant/wpa_supplicant/blacklist.c | 133 - .../wpa_supplicant/wpa_supplicant/blacklist.h | 30 - .../wpa_supplicant/wpa_supplicant/config.c | 1978 ---------- .../wpa_supplicant/wpa_supplicant/config.h | 392 -- .../wpa_supplicant/config_file.c | 942 ----- .../wpa_supplicant/config_none.c | 57 - .../wpa_supplicant/config_ssid.h | 347 -- .../wpa_supplicant/config_winreg.c | 980 ----- .../wpa_supplicant/ctrl_iface.c | 1875 --------- .../wpa_supplicant/ctrl_iface.h | 159 - .../wpa_supplicant/ctrl_iface_dbus.c | 1177 ------ .../wpa_supplicant/ctrl_iface_dbus.h | 162 - .../wpa_supplicant/ctrl_iface_dbus_handlers.c | 1491 -------- .../wpa_supplicant/ctrl_iface_dbus_handlers.h | 92 - .../wpa_supplicant/ctrl_iface_named_pipe.c | 835 ---- .../wpa_supplicant/ctrl_iface_udp.c | 561 --- .../wpa_supplicant/ctrl_iface_unix.c | 722 ---- .../wpa_supplicant/dbus_dict_helpers.c | 976 ----- .../wpa_supplicant/dbus_dict_helpers.h | 135 - .../wpa_supplicant/eapol_test.c | 1217 ------ .../wpa_supplicant/wpa_supplicant/events.c | 1182 ------ contrib/wpa_supplicant/wpa_supplicant/main.c | 264 -- .../wpa_supplicant/wpa_supplicant/main_none.c | 46 - .../wpa_supplicant/main_winmain.c | 84 - .../wpa_supplicant/main_winsvc.c | 464 --- contrib/wpa_supplicant/wpa_supplicant/mlme.c | 2993 --------------- contrib/wpa_supplicant/wpa_supplicant/mlme.h | 132 - .../wpa_supplicant/preauth_test.c | 375 -- contrib/wpa_supplicant/wpa_supplicant/scan.c | 285 -- .../wpa_supplicant/symbian/README.symbian | 24 - .../wpa_supplicant/tests/link_test.c | 83 - .../wpa_supplicant/tests/test_aes.c | 307 -- .../tests/test_eap_sim_common.c | 53 - .../wpa_supplicant/tests/test_md4.c | 99 - .../wpa_supplicant/tests/test_md5.c | 99 - .../wpa_supplicant/tests/test_ms_funcs.c | 119 - .../wpa_supplicant/tests/test_sha1.c | 347 -- .../wpa_supplicant/tests/test_sha256.c | 331 -- .../wpa_supplicant/tests/test_wpa.c | 394 -- .../wpa_supplicant/tests/test_x509v3.c | 69 - .../wpa_supplicant/win_if_list.c | 179 - .../wpa_supplicant/wpa_supplicant/wpa_cli.c | 1921 ---------- .../wpa_supplicant/wpa_gui-qt4/addinterface.h | 45 - .../wpa_supplicant/wpa_gui-qt4/eventhistory.h | 63 - .../wpa_supplicant/wpa_gui-qt4/icons/README | 7 - .../wpa_gui-qt4/networkconfig.h | 61 - .../wpa_supplicant/wpa_gui-qt4/scanresults.h | 46 - .../wpa_gui-qt4/userdatarequest.h | 46 - .../wpa_supplicant/wpa_gui-qt4/wpagui.h | 147 - .../wpa_supplicant/wpa_gui-qt4/wpamsg.h | 41 - .../wpa_supplicant/wpa_gui/eventhistory.ui.h | 41 - .../wpa_supplicant/wpa_gui/networkconfig.ui.h | 552 --- .../wpa_supplicant/wpa_gui/scanresults.ui.h | 101 - .../wpa_gui/userdatarequest.ui.h | 72 - .../wpa_supplicant/wpa_gui/wpagui.ui.h | 730 ---- .../wpa_supplicant/wpa_gui/wpamsg.h | 34 - .../wpa_supplicant/wpa_passphrase.c | 73 - .../wpa_supplicant/wpa_supplicant/wpa_priv.c | 1220 ------ .../wpa_supplicant/wpa_supplicant.c | 2201 ----------- .../wpa_supplicant/wpa_supplicant_i.h | 773 ---- .../wpa_supplicant/wpa_supplicant/wpas_glue.c | 642 ---- .../wpa_supplicant/wpa_supplicant/wpas_glue.h | 23 - .../wpa_supplicant/wps_supplicant.c | 928 ----- .../wpa_supplicant/wps_supplicant.h | 95 - 704 files changed, 358394 deletions(-) delete mode 100644 contrib/hostapd/COPYING delete mode 100644 contrib/hostapd/README delete mode 100644 contrib/hostapd/README.DELETED delete mode 100644 contrib/hostapd/README.DRAGONFLY delete mode 100644 contrib/hostapd/hostapd/ChangeLog delete mode 100644 contrib/hostapd/hostapd/README delete mode 100644 contrib/hostapd/hostapd/README-WPS delete mode 100644 contrib/hostapd/hostapd/accounting.c delete mode 100644 contrib/hostapd/hostapd/accounting.h delete mode 100644 contrib/hostapd/hostapd/ap.h delete mode 100644 contrib/hostapd/hostapd/ap_list.c delete mode 100644 contrib/hostapd/hostapd/ap_list.h delete mode 100644 contrib/hostapd/hostapd/beacon.c delete mode 100644 contrib/hostapd/hostapd/beacon.h delete mode 100644 contrib/hostapd/hostapd/config.c delete mode 100644 contrib/hostapd/hostapd/config.h delete mode 100644 contrib/hostapd/hostapd/ctrl_iface.c delete mode 100644 contrib/hostapd/hostapd/ctrl_iface.h delete mode 100644 contrib/hostapd/hostapd/driver.h delete mode 100644 contrib/hostapd/hostapd/driver_atheros.c delete mode 100644 contrib/hostapd/hostapd/driver_bsd.c delete mode 100644 contrib/hostapd/hostapd/driver_hostap.c delete mode 100644 contrib/hostapd/hostapd/driver_madwifi.c delete mode 100644 contrib/hostapd/hostapd/driver_nl80211.c delete mode 100644 contrib/hostapd/hostapd/driver_none.c delete mode 100644 contrib/hostapd/hostapd/driver_prism54.c delete mode 100644 contrib/hostapd/hostapd/driver_test.c delete mode 100644 contrib/hostapd/hostapd/driver_wired.c delete mode 100644 contrib/hostapd/hostapd/drivers.c delete mode 100644 contrib/hostapd/hostapd/eapol_sm.c delete mode 100644 contrib/hostapd/hostapd/eapol_sm.h delete mode 100644 contrib/hostapd/hostapd/hostap_common.h delete mode 100644 contrib/hostapd/hostapd/hostapd.c delete mode 100644 contrib/hostapd/hostapd/hostapd.h delete mode 100644 contrib/hostapd/hostapd/hostapd_cli.c delete mode 100644 contrib/hostapd/hostapd/hw_features.c delete mode 100644 contrib/hostapd/hostapd/hw_features.h delete mode 100644 contrib/hostapd/hostapd/iapp.c delete mode 100644 contrib/hostapd/hostapd/iapp.h delete mode 100644 contrib/hostapd/hostapd/ieee802_11.c delete mode 100644 contrib/hostapd/hostapd/ieee802_11.h delete mode 100644 contrib/hostapd/hostapd/ieee802_11_auth.c delete mode 100644 contrib/hostapd/hostapd/ieee802_11_auth.h delete mode 100644 contrib/hostapd/hostapd/ieee802_1x.c delete mode 100644 contrib/hostapd/hostapd/ieee802_1x.h delete mode 100644 contrib/hostapd/hostapd/logwatch/README delete mode 100644 contrib/hostapd/hostapd/mlme.c delete mode 100644 contrib/hostapd/hostapd/mlme.h delete mode 100644 contrib/hostapd/hostapd/nt_password_hash.c delete mode 100644 contrib/hostapd/hostapd/peerkey.c delete mode 100644 contrib/hostapd/hostapd/pmksa_cache.c delete mode 100644 contrib/hostapd/hostapd/pmksa_cache.h delete mode 100644 contrib/hostapd/hostapd/preauth.c delete mode 100644 contrib/hostapd/hostapd/preauth.h delete mode 100644 contrib/hostapd/hostapd/prism54.h delete mode 100644 contrib/hostapd/hostapd/priv_netlink.h delete mode 100644 contrib/hostapd/hostapd/radiotap.c delete mode 100644 contrib/hostapd/hostapd/radiotap.h delete mode 100644 contrib/hostapd/hostapd/radiotap_iter.h delete mode 100644 contrib/hostapd/hostapd/sta_info.c delete mode 100644 contrib/hostapd/hostapd/sta_info.h delete mode 100644 contrib/hostapd/hostapd/vlan_init.c delete mode 100644 contrib/hostapd/hostapd/vlan_init.h delete mode 100644 contrib/hostapd/hostapd/wme.c delete mode 100644 contrib/hostapd/hostapd/wme.h delete mode 100644 contrib/hostapd/hostapd/wpa.c delete mode 100644 contrib/hostapd/hostapd/wpa.h delete mode 100644 contrib/hostapd/hostapd/wpa_auth_i.h delete mode 100644 contrib/hostapd/hostapd/wpa_auth_ie.c delete mode 100644 contrib/hostapd/hostapd/wpa_auth_ie.h delete mode 100644 contrib/hostapd/hostapd/wpa_ft.c delete mode 100644 contrib/hostapd/hostapd/wps_hostapd.c delete mode 100644 contrib/hostapd/hostapd/wps_hostapd.h delete mode 100644 contrib/hostapd/patches/openssl-0.9.8-tls-extensions.patch delete mode 100644 contrib/hostapd/patches/openssl-0.9.8d-tls-extensions.patch delete mode 100644 contrib/hostapd/patches/openssl-0.9.8e-tls-extensions.patch delete mode 100644 contrib/hostapd/patches/openssl-0.9.8g-tls-extensions.patch delete mode 100644 contrib/hostapd/patches/openssl-0.9.8h-tls-extensions.patch delete mode 100644 contrib/hostapd/patches/openssl-0.9.8i-tls-extensions.patch delete mode 100644 contrib/hostapd/patches/openssl-0.9.9-session-ticket.patch delete mode 100644 contrib/hostapd/src/common/defs.h delete mode 100644 contrib/hostapd/src/common/eapol_common.h delete mode 100644 contrib/hostapd/src/common/ieee802_11_common.c delete mode 100644 contrib/hostapd/src/common/ieee802_11_common.h delete mode 100644 contrib/hostapd/src/common/ieee802_11_defs.h delete mode 100644 contrib/hostapd/src/common/nl80211_copy.h delete mode 100644 contrib/hostapd/src/common/privsep_commands.h delete mode 100644 contrib/hostapd/src/common/version.h delete mode 100644 contrib/hostapd/src/common/wireless_copy.h delete mode 100644 contrib/hostapd/src/common/wpa_common.c delete mode 100644 contrib/hostapd/src/common/wpa_common.h delete mode 100644 contrib/hostapd/src/common/wpa_ctrl.c delete mode 100644 contrib/hostapd/src/common/wpa_ctrl.h delete mode 100644 contrib/hostapd/src/crypto/aes.c delete mode 100644 contrib/hostapd/src/crypto/aes.h delete mode 100644 contrib/hostapd/src/crypto/aes_wrap.c delete mode 100644 contrib/hostapd/src/crypto/aes_wrap.h delete mode 100644 contrib/hostapd/src/crypto/crypto.h delete mode 100644 contrib/hostapd/src/crypto/crypto_cryptoapi.c delete mode 100644 contrib/hostapd/src/crypto/crypto_gnutls.c delete mode 100644 contrib/hostapd/src/crypto/crypto_internal.c delete mode 100644 contrib/hostapd/src/crypto/crypto_libtomcrypt.c delete mode 100644 contrib/hostapd/src/crypto/crypto_none.c delete mode 100644 contrib/hostapd/src/crypto/crypto_openssl.c delete mode 100644 contrib/hostapd/src/crypto/des.c delete mode 100644 contrib/hostapd/src/crypto/dh_groups.c delete mode 100644 contrib/hostapd/src/crypto/dh_groups.h delete mode 100644 contrib/hostapd/src/crypto/md4.c delete mode 100644 contrib/hostapd/src/crypto/md5.c delete mode 100644 contrib/hostapd/src/crypto/md5.h delete mode 100644 contrib/hostapd/src/crypto/ms_funcs.c delete mode 100644 contrib/hostapd/src/crypto/ms_funcs.h delete mode 100644 contrib/hostapd/src/crypto/rc4.c delete mode 100644 contrib/hostapd/src/crypto/rc4.h delete mode 100644 contrib/hostapd/src/crypto/sha1.c delete mode 100644 contrib/hostapd/src/crypto/sha1.h delete mode 100644 contrib/hostapd/src/crypto/sha256.c delete mode 100644 contrib/hostapd/src/crypto/sha256.h delete mode 100644 contrib/hostapd/src/crypto/tls.h delete mode 100644 contrib/hostapd/src/crypto/tls_gnutls.c delete mode 100644 contrib/hostapd/src/crypto/tls_internal.c delete mode 100644 contrib/hostapd/src/crypto/tls_none.c delete mode 100644 contrib/hostapd/src/crypto/tls_openssl.c delete mode 100644 contrib/hostapd/src/crypto/tls_schannel.c delete mode 100644 contrib/hostapd/src/drivers/Apple80211.h delete mode 100644 contrib/hostapd/src/drivers/MobileApple80211.c delete mode 100644 contrib/hostapd/src/drivers/MobileApple80211.h delete mode 100644 contrib/hostapd/src/drivers/driver.h delete mode 100644 contrib/hostapd/src/drivers/driver_atmel.c delete mode 100644 contrib/hostapd/src/drivers/driver_broadcom.c delete mode 100644 contrib/hostapd/src/drivers/driver_bsd.c delete mode 100644 contrib/hostapd/src/drivers/driver_hostap.c delete mode 100644 contrib/hostapd/src/drivers/driver_hostap.h delete mode 100644 contrib/hostapd/src/drivers/driver_ipw.c delete mode 100644 contrib/hostapd/src/drivers/driver_madwifi.c delete mode 100644 contrib/hostapd/src/drivers/driver_ndis.c delete mode 100644 contrib/hostapd/src/drivers/driver_ndis.h delete mode 100644 contrib/hostapd/src/drivers/driver_ndis_.c delete mode 100644 contrib/hostapd/src/drivers/driver_ndiswrapper.c delete mode 100644 contrib/hostapd/src/drivers/driver_nl80211.c delete mode 100644 contrib/hostapd/src/drivers/driver_prism54.c delete mode 100644 contrib/hostapd/src/drivers/driver_privsep.c delete mode 100644 contrib/hostapd/src/drivers/driver_ps3.c delete mode 100644 contrib/hostapd/src/drivers/driver_ralink.c delete mode 100644 contrib/hostapd/src/drivers/driver_ralink.h delete mode 100644 contrib/hostapd/src/drivers/driver_roboswitch.c delete mode 100644 contrib/hostapd/src/drivers/driver_test.c delete mode 100644 contrib/hostapd/src/drivers/driver_wext.c delete mode 100644 contrib/hostapd/src/drivers/driver_wext.h delete mode 100644 contrib/hostapd/src/drivers/driver_wired.c delete mode 100644 contrib/hostapd/src/drivers/drivers.c delete mode 100644 contrib/hostapd/src/drivers/ndis_events.c delete mode 100644 contrib/hostapd/src/drivers/priv_netlink.h delete mode 100644 contrib/hostapd/src/drivers/radiotap.c delete mode 100644 contrib/hostapd/src/drivers/radiotap.h delete mode 100644 contrib/hostapd/src/drivers/radiotap_iter.h delete mode 100644 contrib/hostapd/src/drivers/scan_helpers.c delete mode 100644 contrib/hostapd/src/eap_common/chap.c delete mode 100644 contrib/hostapd/src/eap_common/chap.h delete mode 100644 contrib/hostapd/src/eap_common/eap_common.c delete mode 100644 contrib/hostapd/src/eap_common/eap_common.h delete mode 100644 contrib/hostapd/src/eap_common/eap_defs.h delete mode 100644 contrib/hostapd/src/eap_common/eap_fast_common.c delete mode 100644 contrib/hostapd/src/eap_common/eap_fast_common.h delete mode 100644 contrib/hostapd/src/eap_common/eap_gpsk_common.c delete mode 100644 contrib/hostapd/src/eap_common/eap_gpsk_common.h delete mode 100644 contrib/hostapd/src/eap_common/eap_ikev2_common.c delete mode 100644 contrib/hostapd/src/eap_common/eap_ikev2_common.h delete mode 100644 contrib/hostapd/src/eap_common/eap_pax_common.c delete mode 100644 contrib/hostapd/src/eap_common/eap_pax_common.h delete mode 100644 contrib/hostapd/src/eap_common/eap_peap_common.c delete mode 100644 contrib/hostapd/src/eap_common/eap_peap_common.h delete mode 100644 contrib/hostapd/src/eap_common/eap_psk_common.c delete mode 100644 contrib/hostapd/src/eap_common/eap_psk_common.h delete mode 100644 contrib/hostapd/src/eap_common/eap_sake_common.c delete mode 100644 contrib/hostapd/src/eap_common/eap_sake_common.h delete mode 100644 contrib/hostapd/src/eap_common/eap_sim_common.c delete mode 100644 contrib/hostapd/src/eap_common/eap_sim_common.h delete mode 100644 contrib/hostapd/src/eap_common/eap_tlv_common.h delete mode 100644 contrib/hostapd/src/eap_common/eap_ttls.h delete mode 100644 contrib/hostapd/src/eap_common/eap_wsc_common.c delete mode 100644 contrib/hostapd/src/eap_common/eap_wsc_common.h delete mode 100644 contrib/hostapd/src/eap_common/ikev2_common.c delete mode 100644 contrib/hostapd/src/eap_common/ikev2_common.h delete mode 100644 contrib/hostapd/src/eap_peer/eap.c delete mode 100644 contrib/hostapd/src/eap_peer/eap.h delete mode 100644 contrib/hostapd/src/eap_peer/eap_aka.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_config.h delete mode 100644 contrib/hostapd/src/eap_peer/eap_fast.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_fast_pac.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_fast_pac.h delete mode 100644 contrib/hostapd/src/eap_peer/eap_gpsk.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_gtc.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_i.h delete mode 100644 contrib/hostapd/src/eap_peer/eap_ikev2.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_leap.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_md5.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_methods.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_methods.h delete mode 100644 contrib/hostapd/src/eap_peer/eap_mschapv2.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_otp.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_pax.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_peap.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_psk.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_sake.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_sim.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_tls.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_tls_common.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_tls_common.h delete mode 100644 contrib/hostapd/src/eap_peer/eap_tnc.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_ttls.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_vendor_test.c delete mode 100644 contrib/hostapd/src/eap_peer/eap_wsc.c delete mode 100644 contrib/hostapd/src/eap_peer/ikev2.c delete mode 100644 contrib/hostapd/src/eap_peer/ikev2.h delete mode 100644 contrib/hostapd/src/eap_peer/mschapv2.c delete mode 100644 contrib/hostapd/src/eap_peer/mschapv2.h delete mode 100644 contrib/hostapd/src/eap_peer/tncc.c delete mode 100644 contrib/hostapd/src/eap_peer/tncc.h delete mode 100644 contrib/hostapd/src/eap_server/eap.c delete mode 100644 contrib/hostapd/src/eap_server/eap.h delete mode 100644 contrib/hostapd/src/eap_server/eap_aka.c delete mode 100644 contrib/hostapd/src/eap_server/eap_fast.c delete mode 100644 contrib/hostapd/src/eap_server/eap_gpsk.c delete mode 100644 contrib/hostapd/src/eap_server/eap_gtc.c delete mode 100644 contrib/hostapd/src/eap_server/eap_i.h delete mode 100644 contrib/hostapd/src/eap_server/eap_identity.c delete mode 100644 contrib/hostapd/src/eap_server/eap_ikev2.c delete mode 100644 contrib/hostapd/src/eap_server/eap_md5.c delete mode 100644 contrib/hostapd/src/eap_server/eap_methods.c delete mode 100644 contrib/hostapd/src/eap_server/eap_methods.h delete mode 100644 contrib/hostapd/src/eap_server/eap_mschapv2.c delete mode 100644 contrib/hostapd/src/eap_server/eap_pax.c delete mode 100644 contrib/hostapd/src/eap_server/eap_peap.c delete mode 100644 contrib/hostapd/src/eap_server/eap_psk.c delete mode 100644 contrib/hostapd/src/eap_server/eap_sake.c delete mode 100644 contrib/hostapd/src/eap_server/eap_sim.c delete mode 100644 contrib/hostapd/src/eap_server/eap_sim_db.c delete mode 100644 contrib/hostapd/src/eap_server/eap_sim_db.h delete mode 100644 contrib/hostapd/src/eap_server/eap_tls.c delete mode 100644 contrib/hostapd/src/eap_server/eap_tls_common.c delete mode 100644 contrib/hostapd/src/eap_server/eap_tls_common.h delete mode 100644 contrib/hostapd/src/eap_server/eap_tnc.c delete mode 100644 contrib/hostapd/src/eap_server/eap_ttls.c delete mode 100644 contrib/hostapd/src/eap_server/eap_vendor_test.c delete mode 100644 contrib/hostapd/src/eap_server/eap_wsc.c delete mode 100644 contrib/hostapd/src/eap_server/ikev2.c delete mode 100644 contrib/hostapd/src/eap_server/ikev2.h delete mode 100644 contrib/hostapd/src/eap_server/tncs.c delete mode 100644 contrib/hostapd/src/eap_server/tncs.h delete mode 100644 contrib/hostapd/src/eapol_supp/eapol_supp_sm.c delete mode 100644 contrib/hostapd/src/eapol_supp/eapol_supp_sm.h delete mode 100644 contrib/hostapd/src/hlr_auc_gw/hlr_auc_gw.c delete mode 100644 contrib/hostapd/src/hlr_auc_gw/milenage.c delete mode 100644 contrib/hostapd/src/hlr_auc_gw/milenage.h delete mode 100644 contrib/hostapd/src/l2_packet/l2_packet.h delete mode 100644 contrib/hostapd/src/l2_packet/l2_packet_freebsd.c delete mode 100644 contrib/hostapd/src/l2_packet/l2_packet_linux.c delete mode 100644 contrib/hostapd/src/l2_packet/l2_packet_ndis.c delete mode 100644 contrib/hostapd/src/l2_packet/l2_packet_none.c delete mode 100644 contrib/hostapd/src/l2_packet/l2_packet_pcap.c delete mode 100644 contrib/hostapd/src/l2_packet/l2_packet_privsep.c delete mode 100644 contrib/hostapd/src/l2_packet/l2_packet_winpcap.c delete mode 100644 contrib/hostapd/src/radius/radius.c delete mode 100644 contrib/hostapd/src/radius/radius.h delete mode 100644 contrib/hostapd/src/radius/radius_client.c delete mode 100644 contrib/hostapd/src/radius/radius_client.h delete mode 100644 contrib/hostapd/src/radius/radius_server.c delete mode 100644 contrib/hostapd/src/radius/radius_server.h delete mode 100644 contrib/hostapd/src/rsn_supp/peerkey.c delete mode 100644 contrib/hostapd/src/rsn_supp/peerkey.h delete mode 100644 contrib/hostapd/src/rsn_supp/pmksa_cache.c delete mode 100644 contrib/hostapd/src/rsn_supp/pmksa_cache.h delete mode 100644 contrib/hostapd/src/rsn_supp/preauth.c delete mode 100644 contrib/hostapd/src/rsn_supp/preauth.h delete mode 100644 contrib/hostapd/src/rsn_supp/wpa.c delete mode 100644 contrib/hostapd/src/rsn_supp/wpa.h delete mode 100644 contrib/hostapd/src/rsn_supp/wpa_ft.c delete mode 100644 contrib/hostapd/src/rsn_supp/wpa_i.h delete mode 100644 contrib/hostapd/src/rsn_supp/wpa_ie.c delete mode 100644 contrib/hostapd/src/rsn_supp/wpa_ie.h delete mode 100644 contrib/hostapd/src/tls/asn1.c delete mode 100644 contrib/hostapd/src/tls/asn1.h delete mode 100644 contrib/hostapd/src/tls/asn1_test.c delete mode 100644 contrib/hostapd/src/tls/bignum.c delete mode 100644 contrib/hostapd/src/tls/bignum.h delete mode 100644 contrib/hostapd/src/tls/libtommath.c delete mode 100644 contrib/hostapd/src/tls/rsa.c delete mode 100644 contrib/hostapd/src/tls/rsa.h delete mode 100644 contrib/hostapd/src/tls/tlsv1_client.c delete mode 100644 contrib/hostapd/src/tls/tlsv1_client.h delete mode 100644 contrib/hostapd/src/tls/tlsv1_client_i.h delete mode 100644 contrib/hostapd/src/tls/tlsv1_client_read.c delete mode 100644 contrib/hostapd/src/tls/tlsv1_client_write.c delete mode 100644 contrib/hostapd/src/tls/tlsv1_common.c delete mode 100644 contrib/hostapd/src/tls/tlsv1_common.h delete mode 100644 contrib/hostapd/src/tls/tlsv1_cred.c delete mode 100644 contrib/hostapd/src/tls/tlsv1_cred.h delete mode 100644 contrib/hostapd/src/tls/tlsv1_record.c delete mode 100644 contrib/hostapd/src/tls/tlsv1_record.h delete mode 100644 contrib/hostapd/src/tls/tlsv1_server.c delete mode 100644 contrib/hostapd/src/tls/tlsv1_server.h delete mode 100644 contrib/hostapd/src/tls/tlsv1_server_i.h delete mode 100644 contrib/hostapd/src/tls/tlsv1_server_read.c delete mode 100644 contrib/hostapd/src/tls/tlsv1_server_write.c delete mode 100644 contrib/hostapd/src/tls/x509v3.c delete mode 100644 contrib/hostapd/src/tls/x509v3.h delete mode 100644 contrib/hostapd/src/utils/base64.c delete mode 100644 contrib/hostapd/src/utils/base64.h delete mode 100644 contrib/hostapd/src/utils/build_config.h delete mode 100644 contrib/hostapd/src/utils/common.c delete mode 100644 contrib/hostapd/src/utils/common.h delete mode 100644 contrib/hostapd/src/utils/eloop.c delete mode 100644 contrib/hostapd/src/utils/eloop.h delete mode 100644 contrib/hostapd/src/utils/eloop_none.c delete mode 100644 contrib/hostapd/src/utils/eloop_win.c delete mode 100644 contrib/hostapd/src/utils/includes.h delete mode 100644 contrib/hostapd/src/utils/ip_addr.c delete mode 100644 contrib/hostapd/src/utils/ip_addr.h delete mode 100644 contrib/hostapd/src/utils/os.h delete mode 100644 contrib/hostapd/src/utils/os_internal.c delete mode 100644 contrib/hostapd/src/utils/os_none.c delete mode 100644 contrib/hostapd/src/utils/os_unix.c delete mode 100644 contrib/hostapd/src/utils/os_win32.c delete mode 100644 contrib/hostapd/src/utils/pcsc_funcs.c delete mode 100644 contrib/hostapd/src/utils/pcsc_funcs.h delete mode 100644 contrib/hostapd/src/utils/state_machine.h delete mode 100644 contrib/hostapd/src/utils/uuid.c delete mode 100644 contrib/hostapd/src/utils/uuid.h delete mode 100644 contrib/hostapd/src/utils/wpa_debug.c delete mode 100644 contrib/hostapd/src/utils/wpa_debug.h delete mode 100644 contrib/hostapd/src/utils/wpabuf.c delete mode 100644 contrib/hostapd/src/utils/wpabuf.h delete mode 100644 contrib/hostapd/src/wps/httpread.c delete mode 100644 contrib/hostapd/src/wps/httpread.h delete mode 100644 contrib/hostapd/src/wps/wps.c delete mode 100644 contrib/hostapd/src/wps/wps.h delete mode 100644 contrib/hostapd/src/wps/wps_attr_build.c delete mode 100644 contrib/hostapd/src/wps/wps_attr_parse.c delete mode 100644 contrib/hostapd/src/wps/wps_attr_process.c delete mode 100644 contrib/hostapd/src/wps/wps_common.c delete mode 100644 contrib/hostapd/src/wps/wps_defs.h delete mode 100644 contrib/hostapd/src/wps/wps_dev_attr.c delete mode 100644 contrib/hostapd/src/wps/wps_dev_attr.h delete mode 100644 contrib/hostapd/src/wps/wps_enrollee.c delete mode 100644 contrib/hostapd/src/wps/wps_i.h delete mode 100644 contrib/hostapd/src/wps/wps_registrar.c delete mode 100644 contrib/hostapd/src/wps/wps_upnp.c delete mode 100644 contrib/hostapd/src/wps/wps_upnp.h delete mode 100644 contrib/hostapd/src/wps/wps_upnp_event.c delete mode 100644 contrib/hostapd/src/wps/wps_upnp_i.h delete mode 100644 contrib/hostapd/src/wps/wps_upnp_ssdp.c delete mode 100644 contrib/hostapd/src/wps/wps_upnp_web.c delete mode 100644 contrib/wpa_supplicant/COPYING delete mode 100644 contrib/wpa_supplicant/README delete mode 100644 contrib/wpa_supplicant/README.DELETED delete mode 100644 contrib/wpa_supplicant/README.DRAGONFLY delete mode 100644 contrib/wpa_supplicant/patches/openssl-0.9.8-tls-extensions.patch delete mode 100644 contrib/wpa_supplicant/patches/openssl-0.9.8d-tls-extensions.patch delete mode 100644 contrib/wpa_supplicant/patches/openssl-0.9.8e-tls-extensions.patch delete mode 100644 contrib/wpa_supplicant/patches/openssl-0.9.8g-tls-extensions.patch delete mode 100644 contrib/wpa_supplicant/patches/openssl-0.9.8h-tls-extensions.patch delete mode 100644 contrib/wpa_supplicant/patches/openssl-0.9.8i-tls-extensions.patch delete mode 100644 contrib/wpa_supplicant/patches/openssl-0.9.9-session-ticket.patch delete mode 100644 contrib/wpa_supplicant/src/common/defs.h delete mode 100644 contrib/wpa_supplicant/src/common/eapol_common.h delete mode 100644 contrib/wpa_supplicant/src/common/ieee802_11_common.c delete mode 100644 contrib/wpa_supplicant/src/common/ieee802_11_common.h delete mode 100644 contrib/wpa_supplicant/src/common/ieee802_11_defs.h delete mode 100644 contrib/wpa_supplicant/src/common/nl80211_copy.h delete mode 100644 contrib/wpa_supplicant/src/common/privsep_commands.h delete mode 100644 contrib/wpa_supplicant/src/common/version.h delete mode 100644 contrib/wpa_supplicant/src/common/wireless_copy.h delete mode 100644 contrib/wpa_supplicant/src/common/wpa_common.c delete mode 100644 contrib/wpa_supplicant/src/common/wpa_common.h delete mode 100644 contrib/wpa_supplicant/src/common/wpa_ctrl.c delete mode 100644 contrib/wpa_supplicant/src/common/wpa_ctrl.h delete mode 100644 contrib/wpa_supplicant/src/crypto/aes.c delete mode 100644 contrib/wpa_supplicant/src/crypto/aes.h delete mode 100644 contrib/wpa_supplicant/src/crypto/aes_wrap.c delete mode 100644 contrib/wpa_supplicant/src/crypto/aes_wrap.h delete mode 100644 contrib/wpa_supplicant/src/crypto/crypto.h delete mode 100644 contrib/wpa_supplicant/src/crypto/crypto_cryptoapi.c delete mode 100644 contrib/wpa_supplicant/src/crypto/crypto_gnutls.c delete mode 100644 contrib/wpa_supplicant/src/crypto/crypto_internal.c delete mode 100644 contrib/wpa_supplicant/src/crypto/crypto_libtomcrypt.c delete mode 100644 contrib/wpa_supplicant/src/crypto/crypto_none.c delete mode 100644 contrib/wpa_supplicant/src/crypto/crypto_openssl.c delete mode 100644 contrib/wpa_supplicant/src/crypto/des.c delete mode 100644 contrib/wpa_supplicant/src/crypto/dh_groups.c delete mode 100644 contrib/wpa_supplicant/src/crypto/dh_groups.h delete mode 100644 contrib/wpa_supplicant/src/crypto/md4.c delete mode 100644 contrib/wpa_supplicant/src/crypto/md5.c delete mode 100644 contrib/wpa_supplicant/src/crypto/md5.h delete mode 100644 contrib/wpa_supplicant/src/crypto/ms_funcs.c delete mode 100644 contrib/wpa_supplicant/src/crypto/ms_funcs.h delete mode 100644 contrib/wpa_supplicant/src/crypto/rc4.c delete mode 100644 contrib/wpa_supplicant/src/crypto/rc4.h delete mode 100644 contrib/wpa_supplicant/src/crypto/sha1.c delete mode 100644 contrib/wpa_supplicant/src/crypto/sha1.h delete mode 100644 contrib/wpa_supplicant/src/crypto/sha256.c delete mode 100644 contrib/wpa_supplicant/src/crypto/sha256.h delete mode 100644 contrib/wpa_supplicant/src/crypto/tls.h delete mode 100644 contrib/wpa_supplicant/src/crypto/tls_gnutls.c delete mode 100644 contrib/wpa_supplicant/src/crypto/tls_internal.c delete mode 100644 contrib/wpa_supplicant/src/crypto/tls_none.c delete mode 100644 contrib/wpa_supplicant/src/crypto/tls_openssl.c delete mode 100644 contrib/wpa_supplicant/src/crypto/tls_schannel.c delete mode 100644 contrib/wpa_supplicant/src/drivers/Apple80211.h delete mode 100644 contrib/wpa_supplicant/src/drivers/MobileApple80211.c delete mode 100644 contrib/wpa_supplicant/src/drivers/MobileApple80211.h delete mode 100644 contrib/wpa_supplicant/src/drivers/driver.h delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_atmel.c delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_broadcom.c delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_bsd.c delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_hostap.c delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_hostap.h delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_ipw.c delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_madwifi.c delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_ndis.c delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_ndis.h delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_ndis_.c delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_ndiswrapper.c delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_nl80211.c delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_prism54.c delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_privsep.c delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_ps3.c delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_ralink.c delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_ralink.h delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_roboswitch.c delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_test.c delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_wext.c delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_wext.h delete mode 100644 contrib/wpa_supplicant/src/drivers/driver_wired.c delete mode 100644 contrib/wpa_supplicant/src/drivers/drivers.c delete mode 100644 contrib/wpa_supplicant/src/drivers/ndis_events.c delete mode 100644 contrib/wpa_supplicant/src/drivers/priv_netlink.h delete mode 100644 contrib/wpa_supplicant/src/drivers/radiotap.c delete mode 100644 contrib/wpa_supplicant/src/drivers/radiotap.h delete mode 100644 contrib/wpa_supplicant/src/drivers/radiotap_iter.h delete mode 100644 contrib/wpa_supplicant/src/drivers/scan_helpers.c delete mode 100644 contrib/wpa_supplicant/src/eap_common/chap.c delete mode 100644 contrib/wpa_supplicant/src/eap_common/chap.h delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_common.c delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_common.h delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_defs.h delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_fast_common.c delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_fast_common.h delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_gpsk_common.c delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_gpsk_common.h delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_ikev2_common.c delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_ikev2_common.h delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_pax_common.c delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_pax_common.h delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_peap_common.c delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_peap_common.h delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_psk_common.c delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_psk_common.h delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_sake_common.c delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_sake_common.h delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_sim_common.c delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_sim_common.h delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_tlv_common.h delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_ttls.h delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_wsc_common.c delete mode 100644 contrib/wpa_supplicant/src/eap_common/eap_wsc_common.h delete mode 100644 contrib/wpa_supplicant/src/eap_common/ikev2_common.c delete mode 100644 contrib/wpa_supplicant/src/eap_common/ikev2_common.h delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap.h delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_aka.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_config.h delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_fast.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_fast_pac.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_fast_pac.h delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_gpsk.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_gtc.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_i.h delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_ikev2.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_leap.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_md5.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_methods.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_methods.h delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_mschapv2.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_otp.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_pax.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_peap.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_psk.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_sake.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_sim.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_tls.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_tls_common.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_tls_common.h delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_tnc.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_ttls.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_vendor_test.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/eap_wsc.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/ikev2.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/ikev2.h delete mode 100644 contrib/wpa_supplicant/src/eap_peer/mschapv2.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/mschapv2.h delete mode 100644 contrib/wpa_supplicant/src/eap_peer/tncc.c delete mode 100644 contrib/wpa_supplicant/src/eap_peer/tncc.h delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap.h delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_aka.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_fast.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_gpsk.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_gtc.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_i.h delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_identity.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_ikev2.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_md5.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_methods.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_methods.h delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_mschapv2.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_pax.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_peap.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_psk.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_sake.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_sim.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_sim_db.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_sim_db.h delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_tls.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_tls_common.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_tls_common.h delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_tnc.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_ttls.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_vendor_test.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/eap_wsc.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/ikev2.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/ikev2.h delete mode 100644 contrib/wpa_supplicant/src/eap_server/tncs.c delete mode 100644 contrib/wpa_supplicant/src/eap_server/tncs.h delete mode 100644 contrib/wpa_supplicant/src/eapol_supp/eapol_supp_sm.c delete mode 100644 contrib/wpa_supplicant/src/eapol_supp/eapol_supp_sm.h delete mode 100644 contrib/wpa_supplicant/src/hlr_auc_gw/hlr_auc_gw.c delete mode 100644 contrib/wpa_supplicant/src/hlr_auc_gw/milenage.c delete mode 100644 contrib/wpa_supplicant/src/hlr_auc_gw/milenage.h delete mode 100644 contrib/wpa_supplicant/src/l2_packet/l2_packet.h delete mode 100644 contrib/wpa_supplicant/src/l2_packet/l2_packet_freebsd.c delete mode 100644 contrib/wpa_supplicant/src/l2_packet/l2_packet_linux.c delete mode 100644 contrib/wpa_supplicant/src/l2_packet/l2_packet_ndis.c delete mode 100644 contrib/wpa_supplicant/src/l2_packet/l2_packet_none.c delete mode 100644 contrib/wpa_supplicant/src/l2_packet/l2_packet_pcap.c delete mode 100644 contrib/wpa_supplicant/src/l2_packet/l2_packet_privsep.c delete mode 100644 contrib/wpa_supplicant/src/l2_packet/l2_packet_winpcap.c delete mode 100644 contrib/wpa_supplicant/src/radius/radius.c delete mode 100644 contrib/wpa_supplicant/src/radius/radius.h delete mode 100644 contrib/wpa_supplicant/src/radius/radius_client.c delete mode 100644 contrib/wpa_supplicant/src/radius/radius_client.h delete mode 100644 contrib/wpa_supplicant/src/radius/radius_server.c delete mode 100644 contrib/wpa_supplicant/src/radius/radius_server.h delete mode 100644 contrib/wpa_supplicant/src/rsn_supp/peerkey.c delete mode 100644 contrib/wpa_supplicant/src/rsn_supp/peerkey.h delete mode 100644 contrib/wpa_supplicant/src/rsn_supp/pmksa_cache.c delete mode 100644 contrib/wpa_supplicant/src/rsn_supp/pmksa_cache.h delete mode 100644 contrib/wpa_supplicant/src/rsn_supp/preauth.c delete mode 100644 contrib/wpa_supplicant/src/rsn_supp/preauth.h delete mode 100644 contrib/wpa_supplicant/src/rsn_supp/wpa.c delete mode 100644 contrib/wpa_supplicant/src/rsn_supp/wpa.h delete mode 100644 contrib/wpa_supplicant/src/rsn_supp/wpa_ft.c delete mode 100644 contrib/wpa_supplicant/src/rsn_supp/wpa_i.h delete mode 100644 contrib/wpa_supplicant/src/rsn_supp/wpa_ie.c delete mode 100644 contrib/wpa_supplicant/src/rsn_supp/wpa_ie.h delete mode 100644 contrib/wpa_supplicant/src/tls/asn1.c delete mode 100644 contrib/wpa_supplicant/src/tls/asn1.h delete mode 100644 contrib/wpa_supplicant/src/tls/asn1_test.c delete mode 100644 contrib/wpa_supplicant/src/tls/bignum.c delete mode 100644 contrib/wpa_supplicant/src/tls/bignum.h delete mode 100644 contrib/wpa_supplicant/src/tls/libtommath.c delete mode 100644 contrib/wpa_supplicant/src/tls/rsa.c delete mode 100644 contrib/wpa_supplicant/src/tls/rsa.h delete mode 100644 contrib/wpa_supplicant/src/tls/tlsv1_client.c delete mode 100644 contrib/wpa_supplicant/src/tls/tlsv1_client.h delete mode 100644 contrib/wpa_supplicant/src/tls/tlsv1_client_i.h delete mode 100644 contrib/wpa_supplicant/src/tls/tlsv1_client_read.c delete mode 100644 contrib/wpa_supplicant/src/tls/tlsv1_client_write.c delete mode 100644 contrib/wpa_supplicant/src/tls/tlsv1_common.c delete mode 100644 contrib/wpa_supplicant/src/tls/tlsv1_common.h delete mode 100644 contrib/wpa_supplicant/src/tls/tlsv1_cred.c delete mode 100644 contrib/wpa_supplicant/src/tls/tlsv1_cred.h delete mode 100644 contrib/wpa_supplicant/src/tls/tlsv1_record.c delete mode 100644 contrib/wpa_supplicant/src/tls/tlsv1_record.h delete mode 100644 contrib/wpa_supplicant/src/tls/tlsv1_server.c delete mode 100644 contrib/wpa_supplicant/src/tls/tlsv1_server.h delete mode 100644 contrib/wpa_supplicant/src/tls/tlsv1_server_i.h delete mode 100644 contrib/wpa_supplicant/src/tls/tlsv1_server_read.c delete mode 100644 contrib/wpa_supplicant/src/tls/tlsv1_server_write.c delete mode 100644 contrib/wpa_supplicant/src/tls/x509v3.c delete mode 100644 contrib/wpa_supplicant/src/tls/x509v3.h delete mode 100644 contrib/wpa_supplicant/src/utils/base64.c delete mode 100644 contrib/wpa_supplicant/src/utils/base64.h delete mode 100644 contrib/wpa_supplicant/src/utils/build_config.h delete mode 100644 contrib/wpa_supplicant/src/utils/common.c delete mode 100644 contrib/wpa_supplicant/src/utils/common.h delete mode 100644 contrib/wpa_supplicant/src/utils/eloop.c delete mode 100644 contrib/wpa_supplicant/src/utils/eloop.h delete mode 100644 contrib/wpa_supplicant/src/utils/eloop_none.c delete mode 100644 contrib/wpa_supplicant/src/utils/eloop_win.c delete mode 100644 contrib/wpa_supplicant/src/utils/includes.h delete mode 100644 contrib/wpa_supplicant/src/utils/ip_addr.c delete mode 100644 contrib/wpa_supplicant/src/utils/ip_addr.h delete mode 100644 contrib/wpa_supplicant/src/utils/os.h delete mode 100644 contrib/wpa_supplicant/src/utils/os_internal.c delete mode 100644 contrib/wpa_supplicant/src/utils/os_none.c delete mode 100644 contrib/wpa_supplicant/src/utils/os_unix.c delete mode 100644 contrib/wpa_supplicant/src/utils/pcsc_funcs.c delete mode 100644 contrib/wpa_supplicant/src/utils/pcsc_funcs.h delete mode 100644 contrib/wpa_supplicant/src/utils/state_machine.h delete mode 100644 contrib/wpa_supplicant/src/utils/uuid.c delete mode 100644 contrib/wpa_supplicant/src/utils/uuid.h delete mode 100644 contrib/wpa_supplicant/src/utils/wpa_debug.c delete mode 100644 contrib/wpa_supplicant/src/utils/wpa_debug.h delete mode 100644 contrib/wpa_supplicant/src/utils/wpabuf.c delete mode 100644 contrib/wpa_supplicant/src/utils/wpabuf.h delete mode 100644 contrib/wpa_supplicant/src/wps/httpread.c delete mode 100644 contrib/wpa_supplicant/src/wps/httpread.h delete mode 100644 contrib/wpa_supplicant/src/wps/wps.c delete mode 100644 contrib/wpa_supplicant/src/wps/wps.h delete mode 100644 contrib/wpa_supplicant/src/wps/wps_attr_build.c delete mode 100644 contrib/wpa_supplicant/src/wps/wps_attr_parse.c delete mode 100644 contrib/wpa_supplicant/src/wps/wps_attr_process.c delete mode 100644 contrib/wpa_supplicant/src/wps/wps_common.c delete mode 100644 contrib/wpa_supplicant/src/wps/wps_defs.h delete mode 100644 contrib/wpa_supplicant/src/wps/wps_dev_attr.c delete mode 100644 contrib/wpa_supplicant/src/wps/wps_dev_attr.h delete mode 100644 contrib/wpa_supplicant/src/wps/wps_enrollee.c delete mode 100644 contrib/wpa_supplicant/src/wps/wps_i.h delete mode 100644 contrib/wpa_supplicant/src/wps/wps_registrar.c delete mode 100644 contrib/wpa_supplicant/src/wps/wps_upnp.c delete mode 100644 contrib/wpa_supplicant/src/wps/wps_upnp.h delete mode 100644 contrib/wpa_supplicant/src/wps/wps_upnp_event.c delete mode 100644 contrib/wpa_supplicant/src/wps/wps_upnp_i.h delete mode 100644 contrib/wpa_supplicant/src/wps/wps_upnp_ssdp.c delete mode 100644 contrib/wpa_supplicant/src/wps/wps_upnp_web.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/ChangeLog delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/README delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/README-WPS delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/README-Windows.txt delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/blacklist.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/blacklist.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/config.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/config.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/config_file.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/config_none.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/config_ssid.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/config_winreg.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/ctrl_iface.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/ctrl_iface.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/ctrl_iface_dbus.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/ctrl_iface_dbus.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/ctrl_iface_dbus_handlers.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/ctrl_iface_dbus_handlers.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/ctrl_iface_named_pipe.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/ctrl_iface_udp.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/ctrl_iface_unix.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/dbus_dict_helpers.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/dbus_dict_helpers.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/eapol_test.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/events.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/main.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/main_none.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/main_winmain.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/main_winsvc.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/mlme.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/mlme.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/preauth_test.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/scan.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/symbian/README.symbian delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/tests/link_test.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/tests/test_aes.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/tests/test_eap_sim_common.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/tests/test_md4.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/tests/test_md5.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/tests/test_ms_funcs.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/tests/test_sha1.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/tests/test_sha256.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/tests/test_wpa.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/tests/test_x509v3.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/win_if_list.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpa_cli.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpa_gui-qt4/addinterface.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpa_gui-qt4/eventhistory.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpa_gui-qt4/icons/README delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpa_gui-qt4/networkconfig.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpa_gui-qt4/scanresults.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpa_gui-qt4/userdatarequest.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpa_gui-qt4/wpagui.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpa_gui-qt4/wpamsg.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpa_gui/eventhistory.ui.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpa_gui/networkconfig.ui.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpa_gui/scanresults.ui.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpa_gui/userdatarequest.ui.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpa_gui/wpagui.ui.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpa_gui/wpamsg.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpa_passphrase.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpa_priv.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpa_supplicant.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpa_supplicant_i.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpas_glue.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wpas_glue.h delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wps_supplicant.c delete mode 100644 contrib/wpa_supplicant/wpa_supplicant/wps_supplicant.h diff --git a/contrib/hostapd/COPYING b/contrib/hostapd/COPYING deleted file mode 100644 index 14f5453722..0000000000 --- a/contrib/hostapd/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/contrib/hostapd/README b/contrib/hostapd/README deleted file mode 100644 index 9c6be85d9e..0000000000 --- a/contrib/hostapd/README +++ /dev/null @@ -1,19 +0,0 @@ -wpa_supplicant and hostapd v0.6.x ---------------------------------- - -Copyright (c) 2002-2007, Jouni Malinen and contributors -All Rights Reserved. - -These program is dual-licensed under both the GPL version 2 and BSD -license. Either license may be used at your option. - - -This package may include either wpa_supplicant, hostapd, or both. See -README file respective subdirectories (wpa_supplicant/README or -hostapd/README) for more details. - -Source code files have been moved around in v0.6.x releases and -compared to earlier releases, the programs are now build by first -going to a subdirectory (wpa_supplicant or hostapd) and creating -build configuration (.config) and running 'make' there (for -Linux/BSD/cygwin builds). diff --git a/contrib/hostapd/README.DELETED b/contrib/hostapd/README.DELETED deleted file mode 100644 index ff95c0cac9..0000000000 --- a/contrib/hostapd/README.DELETED +++ /dev/null @@ -1,36 +0,0 @@ -hostapd/.gitignore -hostapd/Makefile -hostapd/defconfig -hostapd/doc/ -hostapd/eap_testing.txt -hostapd/hostapd.8 -hostapd/hostapd.accept -hostapd/hostapd.conf -hostapd/hostapd.deny -hostapd/hostapd.eap_user -hostapd/hostapd.radius_clients -hostapd/hostapd.sim_db -hostapd/hostapd.vlan -hostapd/hostapd.wpa_psk -hostapd/hostapd_cli.1 -hostapd/logwatch/hostapd -hostapd/logwatch/hostapd.conf -hostapd/wired.conf -src/Makefile -src/common/Makefile -src/crypto/Makefile -src/drivers/Makefile -src/drivers/driver_iphone.m -src/drivers/driver_osx.m -src/eap_common/Makefile -src/eap_peer/Makefile -src/eap_server/Makefile -src/eapol_supp/Makefile -src/hlr_auc_gw/Makefile -src/hlr_auc_gw/hlr_auc_gw.milenage_db -src/l2_packet/Makefile -src/radius/Makefile -src/rsn_supp/Makefile -src/tls/Makefile -src/utils/Makefile -src/wps/Makefile diff --git a/contrib/hostapd/README.DRAGONFLY b/contrib/hostapd/README.DRAGONFLY deleted file mode 100644 index 276444866d..0000000000 --- a/contrib/hostapd/README.DRAGONFLY +++ /dev/null @@ -1,23 +0,0 @@ - HOSTAPD-0.6.10 AS USED BY DRAGONFLY - - This directory contains a selected set of files from the - hostapd-6.10.tar.gz distribution. No files have been moved - or modified from their extracted position. - - This distribution was downloaded from the following site: - - http://hostap.epitest.fi/hostapd/ - - MD5 (hostapd-0.6.10.tar.gz) = 1ac442d1f984273f108b3de579c1b70d - SHA1 (hostapd-0.6.10.tar.gz) = 2cacf994abd3cebad36679d32f64c9e9906ccff8 - - - DO NOT CREATE OR EDIT ANY FILES IN THIS DIRECTORY HIERARCHY! THIS - HIERARCHY REPRESENTS AN EXACT COPY, MINUS UNNEEDED FILES, OF THE - ORIGINAL ARCHIVE. All modifications are made on the master branch or in - src/usr.sbin/802_11. - - The only additional files added to this directory are README.DRAGONFLY - and README.DELETED. - - For mor information, check development(7). diff --git a/contrib/hostapd/hostapd/ChangeLog b/contrib/hostapd/hostapd/ChangeLog deleted file mode 100644 index 18af4b176b..0000000000 --- a/contrib/hostapd/hostapd/ChangeLog +++ /dev/null @@ -1,597 +0,0 @@ -ChangeLog for hostapd - -2010-01-12 - v0.6.10 - * fixed SHA-256 based key derivation function to match with the - standard when using CCMP (for IEEE 802.11r and IEEE 802.11w) - (note: this breaks interoperability with previous version) [Bug 307] - * fixed WPS selected registrar expiration for internal PIN registrar - * disable PMTU discovery for RADIUS packets - * fixed WPS UPnP SSDP on 32-bit targets - * fixed WPS AP reconfiguration with drivers that do not use hostapd - MLME - * fixed RSN parameter setting for multi-BSS case - * added WPS workarounds for known interoperability issues with broken, - deployed implementation - * update IEEE 802.11w implementation to match with the published - standard - * fixed OpCode when proxying WSC_ACK or WSC_NACK from WPS ER - * fixed proxying of WSC_NACK to WPS ER - * fixed compilation with newer GnuTLS versions - * added support for defining timeout for WPS PINs - * fixed WPS Probe Request processing to handle missing required - attribute - * fixed PKCS#12 use with OpenSSL 1.0.0 - -2009-03-23 - v0.6.9 - * driver_nl80211: fixed STA accounting data collection (TX/RX bytes - reported correctly; TX/RX packets not yet available from kernel) - * fixed EAPOL/EAP reauthentication when using an external RADIUS - authentication server - * driver_prism54: fixed segmentation fault on initialization - * fixed TNC with EAP-TTLS - * fixed IEEE 802.11r key derivation function to match with the standard - (note: this breaks interoperability with previous version) [Bug 303] - -2009-02-15 - v0.6.8 - * increased hostapd_cli ping interval to 5 seconds and made this - configurable with a new command line options (-G) - * driver_nl80211: use Linux socket filter to improve performance - * added support for external Registrars with WPS (UPnP transport) - -2009-01-06 - v0.6.7 - * added support for Wi-Fi Protected Setup (WPS) - (hostapd can now be configured to act as an integrated WPS Registrar - and provision credentials for WPS Enrollees using PIN and PBC - methods; external wireless Registrar can configure the AP, but - external WLAN Manager Registrars are not supported); WPS support can - be enabled by adding CONFIG_WPS=y into .config and setting the - runtime configuration variables in hostapd.conf (see WPS section in - the example configuration file); new hostapd_cli commands wps_pin and - wps_pbc are used to configure WPS negotiation; see README-WPS for - more details - * added IEEE 802.11n HT capability configuration (ht_capab) - * added support for generating Country IE based on nl80211 regulatory - information (added if ieee80211d=1 in configuration) - * fixed WEP authentication (both Open System and Shared Key) with - mac80211 - * added support for EAP-AKA' (draft-arkko-eap-aka-kdf) - * added support for using driver_test over UDP socket - * changed EAP-GPSK to use the IANA assigned EAP method type 51 - * updated management frame protection to use IEEE 802.11w/D7.0 - * fixed retransmission of EAP requests if no response is received - -2008-11-23 - v0.6.6 - * added a new configuration option, wpa_ptk_rekey, that can be used to - enforce frequent PTK rekeying, e.g., to mitigate some attacks against - TKIP deficiencies - * updated OpenSSL code for EAP-FAST to use an updated version of the - session ticket overriding API that was included into the upstream - OpenSSL 0.9.9 tree on 2008-11-15 (no additional OpenSSL patch is - needed with that version anymore) - * changed channel flags configuration to read the information from - the driver (e.g., via driver_nl80211 when using mac80211) instead of - using hostapd as the source of the regulatory information (i.e., - information from CRDA is now used with mac80211); this allows 5 GHz - channels to be used with hostapd (if allowed in the current - regulatory domain) - * fixed EAP-TLS message processing for the last TLS message if it is - large enough to require fragmentation (e.g., if a large Session - Ticket data is included) - * fixed listen interval configuration for nl80211 drivers - -2008-11-01 - v0.6.5 - * added support for SHA-256 as X.509 certificate digest when using the - internal X.509/TLSv1 implementation - * fixed EAP-FAST PAC-Opaque padding (0.6.4 broke this for some peer - identity lengths) - * fixed internal TLSv1 implementation for abbreviated handshake (used - by EAP-FAST server) - * added support for setting VLAN ID for STAs based on local MAC ACL - (accept_mac_file) as an alternative for RADIUS server-based - configuration - * updated management frame protection to use IEEE 802.11w/D6.0 - (adds a new association ping to protect against unauthenticated - authenticate or (re)associate request frames dropping association) - * added support for using SHA256-based stronger key derivation for WPA2 - (IEEE 802.11w) - * added new "driver wrapper" for RADIUS-only configuration - (driver=none in hostapd.conf; CONFIG_DRIVER_NONE=y in .config) - * fixed WPA/RSN IE validation to verify that the proto (WPA vs. WPA2) - is enabled in configuration - * changed EAP-FAST configuration to use separate fields for A-ID and - A-ID-Info (eap_fast_a_id_info) to allow A-ID to be set to a fixed - 16-octet len binary value for better interoperability with some peer - implementations; eap_fast_a_id is now configured as a hex string - * driver_nl80211: Updated to match the current Linux mac80211 AP mode - configuration (wireless-testing.git and Linux kernel releases - starting from 2.6.29) - -2008-08-10 - v0.6.4 - * added peer identity into EAP-FAST PAC-Opaque and skip Phase 2 - Identity Request if identity is already known - * added support for EAP Sequences in EAP-FAST Phase 2 - * added support for EAP-TNC (Trusted Network Connect) - (this version implements the EAP-TNC method and EAP-TTLS/EAP-FAST - changes needed to run two methods in sequence (IF-T) and the IF-IMV - and IF-TNCCS interfaces from TNCS) - * added support for optional cryptobinding with PEAPv0 - * added fragmentation support for EAP-TNC - * added support for fragmenting EAP-TTLS/PEAP/FAST Phase 2 (tunneled) - data - * added support for opportunistic key caching (OKC) - -2008-02-22 - v0.6.3 - * fixed Reassociation Response callback processing when using internal - MLME (driver_{hostap,nl80211,test}.c) - * updated FT support to use the latest draft, IEEE 802.11r/D9.0 - * copy optional Proxy-State attributes into RADIUS response when acting - as a RADIUS authentication server - * fixed EAPOL state machine to handle a case in which no response is - received from the RADIUS authentication server; previous version - could have triggered a crash in some cases after a timeout - * fixed EAP-SIM/AKA realm processing to allow decorated usernames to - be used - * added a workaround for EAP-SIM/AKA peers that include incorrect null - termination in the username - * fixed EAP-SIM/AKA protected result indication to include AT_COUNTER - attribute in notification messages only when using fast - reauthentication - * fixed EAP-SIM Start response processing for fast reauthentication - case - * added support for pending EAP processing in EAP-{PEAP,TTLS,FAST} - phase 2 to allow EAP-SIM and EAP-AKA to be used as the Phase 2 method - -2008-01-01 - v0.6.2 - * fixed EAP-SIM and EAP-AKA message parser to validate attribute - lengths properly to avoid potential crash caused by invalid messages - * added data structure for storing allocated buffers (struct wpabuf); - this does not affect hostapd usage, but many of the APIs changed - and various interfaces (e.g., EAP) is not compatible with old - versions - * added support for protecting EAP-AKA/Identity messages with - AT_CHECKCODE (optional feature in RFC 4187) - * added support for protected result indication with AT_RESULT_IND for - EAP-SIM and EAP-AKA (eap_sim_aka_result_ind=1) - * added support for configuring EAP-TTLS phase 2 non-EAP methods in - EAP server configuration; previously all four were enabled for every - phase 2 user, now all four are disabled by default and need to be - enabled with new method names TTLS-PAP, TTLS-CHAP, TTLS-MSCHAP, - TTLS-MSCHAPV2 - * removed old debug printing mechanism and the related 'debug' - parameter in the configuration file; debug verbosity is now set with - -d (or -dd) command line arguments - * added support for EAP-IKEv2 (draft-tschofenig-eap-ikev2-15.txt); - only shared key/password authentication is supported in this version - -2007-11-24 - v0.6.1 - * added experimental, integrated TLSv1 server implementation with the - needed X.509/ASN.1/RSA/bignum processing (this can be enabled by - setting CONFIG_TLS=internal and CONFIG_INTERNAL_LIBTOMMATH=y in - .config); this can be useful, e.g., if the target system does not - have a suitable TLS library and a minimal code size is required - * added support for EAP-FAST server method to the integrated EAP - server - * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest - draft (draft-ietf-emu-eap-gpsk-07.txt) - * added a new configuration parameter, rsn_pairwise, to allow different - pairwise cipher suites to be enabled for WPA and RSN/WPA2 - (note: if wpa_pairwise differs from rsn_pairwise, the driver will - either need to support this or will have to use the WPA/RSN IEs from - hostapd; currently, the included madwifi and bsd driver interfaces do - not have support for this) - * updated FT support to use the latest draft, IEEE 802.11r/D8.0 - -2007-05-28 - v0.6.0 - * added experimental IEEE 802.11r/D6.0 support - * updated EAP-SAKE to RFC 4763 and the IANA-allocated EAP type 48 - * updated EAP-PSK to use the IANA-allocated EAP type 47 - * fixed EAP-PSK bit ordering of the Flags field - * fixed configuration reloading (SIGHUP) to re-initialize WPA PSKs - by reading wpa_psk_file [Bug 181] - * fixed EAP-TTLS AVP parser processing for too short AVP lengths - * fixed IPv6 connection to RADIUS accounting server - * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest - draft (draft-ietf-emu-eap-gpsk-04.txt) - * hlr_auc_gw: read GSM triplet file into memory and rotate through the - entries instead of only using the same three triplets every time - (this does not work properly with tests using multiple clients, but - provides bit better triplet data for testing a single client; anyway, - if a better quality triplets are needed, GSM-Milenage should be used - instead of hardcoded triplet file) - * fixed EAP-MSCHAPv2 server to use a space between S and M parameters - in Success Request [Bug 203] - * added support for sending EAP-AKA Notifications in error cases - * updated to use IEEE 802.11w/D2.0 for management frame protection - (still experimental) - * RADIUS server: added support for processing duplicate messages - (retransmissions from RADIUS client) by replying with the previous - reply - -2006-11-24 - v0.5.6 - * added support for configuring and controlling multiple BSSes per - radio interface (bss= in hostapd.conf); this is only - available with Devicescape and test driver interfaces - * fixed PMKSA cache update in the end of successful RSN - pre-authentication - * added support for dynamic VLAN configuration (i.e., selecting VLAN-ID - for each STA based on RADIUS Access-Accept attributes); this requires - VLAN support from the kernel driver/802.11 stack and this is - currently only available with Devicescape and test driver interfaces - * driver_madwifi: fixed configuration of unencrypted modes (plaintext - and IEEE 802.1X without WEP) - * removed STAKey handshake since PeerKey handshake has replaced it in - IEEE 802.11ma and there are no known deployments of STAKey - * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest - draft (draft-ietf-emu-eap-gpsk-01.txt) - * added preliminary implementation of IEEE 802.11w/D1.0 (management - frame protection) - (Note: this requires driver support to work properly.) - (Note2: IEEE 802.11w is an unapproved draft and subject to change.) - * hlr_auc_gw: added support for GSM-Milenage (for EAP-SIM) - * hlr_auc_gw: added support for reading per-IMSI Milenage keys and - parameters from a text file to make it possible to implement proper - GSM/UMTS authentication server for multiple SIM/USIM cards using - EAP-SIM/EAP-AKA - * fixed session timeout processing with drivers that do not use - ieee802_11.c (e.g., madwifi) - -2006-08-27 - v0.5.5 - * added 'hostapd_cli new_sta ' command for adding a new STA into - hostapd (e.g., to initialize wired network authentication based on an - external signal) - * fixed hostapd to add PMKID KDE into 4-Way Handshake Message 1 when - using WPA2 even if PMKSA caching is not used - * added -P argument for hostapd to write the current process - id into a file - * added support for RADIUS Authentication Server MIB (RFC 2619) - -2006-06-20 - v0.5.4 - * fixed nt_password_hash build [Bug 144] - * added PeerKey handshake implementation for IEEE 802.11e - direct link setup (DLS) to replace STAKey handshake - * added support for EAP Generalized Pre-Shared Key (EAP-GPSK, - draft-clancy-emu-eap-shared-secret-00.txt) - * fixed a segmentation fault when RSN pre-authentication was completed - successfully [Bug 152] - -2006-04-27 - v0.5.3 - * do not build nt_password_hash and hlr_auc_gw by default to avoid - requiring a TLS library for a successful build; these programs can be - build with 'make nt_password_hash' and 'make hlr_auc_gw' - * added a new configuration option, eapol_version, that can be used to - set EAPOL version to 1 (default is 2) to work around broken client - implementations that drop EAPOL frames which use version number 2 - [Bug 89] - * added support for EAP-SAKE (no EAP method number allocated yet, so - this is using the same experimental type 255 as EAP-PSK) - * fixed EAP-MSCHAPv2 message length validation - -2006-03-19 - v0.5.2 - * fixed stdarg use in hostapd_logger(): if both stdout and syslog - logging was enabled, hostapd could trigger a segmentation fault in - vsyslog on some CPU -- C library combinations - * moved HLR/AuC gateway implementation for EAP-SIM/AKA into an external - program to make it easier to use for implementing real SS7 gateway; - eap_sim_db is not anymore used as a file name for GSM authentication - triplets; instead, it is path to UNIX domain socket that will be used - to communicate with the external gateway program (e.g., hlr_auc_gw) - * added example HLR/AuC gateway implementation, hlr_auc_gw, that uses - local information (GSM authentication triplets from a text file and - hardcoded AKA authentication data); this can be used to test EAP-SIM - and EAP-AKA - * added Milenage algorithm (example 3GPP AKA algorithm) to hlr_auc_gw - to make it possible to test EAP-AKA with real USIM cards (this is - disabled by default; define AKA_USE_MILENAGE when building hlr_auc_gw - to enable this) - * driver_madwifi: added support for getting station RSN IE from - madwifi-ng svn r1453 and newer; this fixes RSN that was apparently - broken with earlier change (r1357) in the driver - * changed EAP method registration to use a dynamic list of methods - instead of a static list generated at build time - * fixed WPA message 3/4 not to encrypt Key Data field (WPA IE) - [Bug 125] - * added ap_max_inactivity configuration parameter - -2006-01-29 - v0.5.1 - * driver_test: added better support for multiple APs and STAs by using - a directory with sockets that include MAC address for each device in - the name (test_socket=DIR:/tmp/test) - * added support for EAP expanded type (vendor specific EAP methods) - -2005-12-18 - v0.5.0 (beginning of 0.5.x development releases) - * added experimental STAKey handshake implementation for IEEE 802.11e - direct link setup (DLS); note: this is disabled by default in both - build and runtime configuration (can be enabled with CONFIG_STAKEY=y - and stakey=1) - * added support for EAP methods to use callbacks to external programs - by buffering a pending request and processing it after the EAP method - is ready to continue - * improved EAP-SIM database interface to allow external request to GSM - HLR/AuC without blocking hostapd process - * added support for using EAP-SIM pseudonyms and fast re-authentication - * added support for EAP-AKA in the integrated EAP authenticator - * added support for matching EAP identity prefixes (e.g., "1"*) in EAP - user database to allow EAP-SIM/AKA selection without extra roundtrip - for EAP-Nak negotiation - * added support for storing EAP user password as NtPasswordHash instead - of plaintext password when using MSCHAP or MSCHAPv2 for - authentication (hash:<16-octet hex value>); added nt_password_hash - tool for hashing password to generate NtPasswordHash - -2005-11-20 - v0.4.7 (beginning of 0.4.x stable releases) - * driver_wired: fixed EAPOL sending to optionally use PAE group address - as the destination instead of supplicant MAC address; this is - disabled by default, but should be enabled with use_pae_group_addr=1 - in configuration file if the wired interface is used by only one - device at the time (common switch configuration) - * driver_madwifi: configure driver to use TKIP countermeasures in order - to get correct behavior (IEEE 802.11 association failing; previously, - association succeeded, but hostpad forced disassociation immediately) - * driver_madwifi: added support for madwifi-ng - -2005-10-27 - v0.4.6 - * added support for replacing user identity from EAP with RADIUS - User-Name attribute from Access-Accept message, if that is included, - for the RADIUS accounting messages (e.g., for EAP-PEAP/TTLS to get - tunneled identity into accounting messages when the RADIUS server - does not support better way of doing this with Class attribute) - * driver_madwifi: fixed EAPOL packet receive for configuration where - ath# is part of a bridge interface - * added a configuration file and log analyzer script for logwatch - * fixed EAPOL state machine step function to process all state - transitions before processing new events; this resolves a race - condition in which EAPOL-Start message could trigger hostapd to send - two EAP-Response/Identity frames to the authentication server - -2005-09-25 - v0.4.5 - * added client CA list to the TLS certificate request in order to make - it easier for the client to select which certificate to use - * added experimental support for EAP-PSK - * added support for WE-19 (hostap, madwifi) - -2005-08-21 - v0.4.4 - * fixed build without CONFIG_RSN_PREAUTH - * fixed FreeBSD build - -2005-06-26 - v0.4.3 - * fixed PMKSA caching to copy User-Name and Class attributes so that - RADIUS accounting gets correct information - * start RADIUS accounting only after successful completion of WPA - 4-Way Handshake if WPA-PSK is used - * fixed PMKSA caching for the case where STA (re)associates without - first disassociating - -2005-06-12 - v0.4.2 - * EAP-PAX is now registered as EAP type 46 - * fixed EAP-PAX MAC calculation - * fixed EAP-PAX CK and ICK key derivation - * renamed eap_authenticator configuration variable to eap_server to - better match with RFC 3748 (EAP) terminology - * driver_test: added support for testing hostapd with wpa_supplicant - by using test driver interface without any kernel drivers or network - cards - -2005-05-22 - v0.4.1 - * fixed RADIUS server initialization when only auth or acct server - is configured and the other one is left empty - * driver_madwifi: added support for RADIUS accounting - * driver_madwifi: added preliminary support for compiling against 'BSD' - branch of madwifi CVS tree - * driver_madwifi: fixed pairwise key removal to allow WPA reauth - without disassociation - * added support for reading additional certificates from PKCS#12 files - and adding them to the certificate chain - * fixed RADIUS Class attribute processing to only use Access-Accept - packets to update Class; previously, other RADIUS authentication - packets could have cleared Class attribute - * added support for more than one Class attribute in RADIUS packets - * added support for verifying certificate revocation list (CRL) when - using integrated EAP authenticator for EAP-TLS; new hostapd.conf - options 'check_crl'; CRL must be included in the ca_cert file for now - -2005-04-25 - v0.4.0 (beginning of 0.4.x development releases) - * added support for including network information into - EAP-Request/Identity message (ASCII-0 (nul) in eap_message) - (e.g., to implement draft-adrange-eap-network-discovery-07.txt) - * fixed a bug which caused some RSN pre-authentication cases to use - freed memory and potentially crash hostapd - * fixed private key loading for cases where passphrase is not set - * added support for sending TLS alerts and aborting authentication - when receiving a TLS alert - * fixed WPA2 to add PMKSA cache entry when using integrated EAP - authenticator - * fixed PMKSA caching (EAP authentication was not skipped correctly - with the new state machine changes from IEEE 802.1X draft) - * added support for RADIUS over IPv6; own_ip_addr, auth_server_addr, - and acct_server_addr can now be IPv6 addresses (CONFIG_IPV6=y needs - to be added to .config to include IPv6 support); for RADIUS server, - radius_server_ipv6=1 needs to be set in hostapd.conf and addresses - in RADIUS clients file can then use IPv6 format - * added experimental support for EAP-PAX - * replaced hostapd control interface library (hostapd_ctrl.[ch]) with - the same implementation that wpa_supplicant is using (wpa_ctrl.[ch]) - -2005-02-12 - v0.3.7 (beginning of 0.3.x stable releases) - -2005-01-23 - v0.3.5 - * added support for configuring a forced PEAP version based on the - Phase 1 identity - * fixed PEAPv1 to use tunneled EAP-Success/Failure instead of EAP-TLV - to terminate authentication - * fixed EAP identifier duplicate processing with the new IEEE 802.1X - draft - * clear accounting data in the driver when starting a new accounting - session - * driver_madwifi: filter wireless events based on ifindex to allow more - than one network interface to be used - * fixed WPA message 2/4 processing not to cancel timeout for TimeoutEvt - setting if the packet does not pass MIC verification (e.g., due to - incorrect PSK); previously, message 1/4 was not tried again if an - invalid message 2/4 was received - * fixed reconfiguration of RADIUS client retransmission timer when - adding a new message to the pending list; previously, timer was not - updated at this point and if there was a pending message with long - time for the next retry, the new message needed to wait that long for - its first retry, too - -2005-01-09 - v0.3.4 - * added support for configuring multiple allowed EAP types for Phase 2 - authentication (EAP-PEAP, EAP-TTLS) - * fixed EAPOL-Start processing to trigger WPA reauthentication - (previously, only EAPOL authentication was done) - -2005-01-02 - v0.3.3 - * added support for EAP-PEAP in the integrated EAP authenticator - * added support for EAP-GTC in the integrated EAP authenticator - * added support for configuring list of EAP methods for Phase 1 so that - the integrated EAP authenticator can, e.g., use the wildcard entry - for EAP-TLS and EAP-PEAP - * added support for EAP-TTLS in the integrated EAP authenticator - * added support for EAP-SIM in the integrated EAP authenticator - * added support for using hostapd as a RADIUS authentication server - with the integrated EAP authenticator taking care of EAP - authentication (new hostapd.conf options: radius_server_clients and - radius_server_auth_port); this is not included in default build; use - CONFIG_RADIUS_SERVER=y in .config to include - -2004-12-19 - v0.3.2 - * removed 'daemonize' configuration file option since it has not really - been used at all for more than year - * driver_madwifi: fixed group key setup and added get_ssid method - * added support for EAP-MSCHAPv2 in the integrated EAP authenticator - -2004-12-12 - v0.3.1 - * added support for integrated EAP-TLS authentication (new hostapd.conf - variables: ca_cert, server_cert, private_key, private_key_passwd); - this enabled dynamic keying (WPA2/WPA/IEEE 802.1X/WEP) without - external RADIUS server - * added support for reading PKCS#12 (PFX) files (as a replacement for - PEM/DER) to get certificate and private key (CONFIG_PKCS12) - -2004-12-05 - v0.3.0 (beginning of 0.3.x development releases) - * added support for Acct-{Input,Output}-Gigawords - * added support for Event-Timestamp (in RADIUS Accounting-Requests) - * added support for RADIUS Authentication Client MIB (RFC2618) - * added support for RADIUS Accounting Client MIB (RFC2620) - * made EAP re-authentication period configurable (eap_reauth_period) - * fixed EAPOL reauthentication to trigger WPA/WPA2 reauthentication - * fixed EAPOL state machine to stop if STA is removed during - eapol_sm_step(); this fixes at least one segfault triggering bug with - IEEE 802.11i pre-authentication - * added support for multiple WPA pre-shared keys (e.g., one for each - client MAC address or keys shared by a group of clients); - new hostapd.conf field wpa_psk_file for setting path to a text file - containing PSKs, see hostapd.wpa_psk for an example - * added support for multiple driver interfaces to allow hostapd to be - used with other drivers - * added wired authenticator driver interface (driver=wired in - hostapd.conf, see wired.conf for example configuration) - * added madwifi driver interface (driver=madwifi in hostapd.conf, see - madwifi.conf for example configuration; Note: include files from - madwifi project is needed for building and a configuration file, - .config, needs to be created in hostapd directory with - CONFIG_DRIVER_MADWIFI=y to include this driver interface in hostapd - build) - * fixed an alignment issue that could cause SHA-1 to fail on some - platforms (e.g., Intel ixp425 with a compiler that does not 32-bit - align variables) - * fixed RADIUS reconnection after an error in sending interim - accounting packets - * added hostapd control interface for external programs and an example - CLI, hostapd_cli (like wpa_cli for wpa_supplicant) - * started adding dot11, dot1x, radius MIBs ('hostapd_cli mib', - 'hostapd_cli sta ') - * finished update from IEEE 802.1X-2001 to IEEE 802.1X-REV (now d11) - * added support for strict GTK rekeying (wpa_strict_rekey in - hostapd.conf) - * updated IAPP to use UDP port 3517 and multicast address 224.0.1.178 - (instead of broadcast) for IAPP ADD-notify (moved from draft 3 to - IEEE 802.11F-2003) - * added Prism54 driver interface (driver=prism54 in hostapd.conf; - note: .config needs to be created in hostapd directory with - CONFIG_DRIVER_PRISM54=y to include this driver interface in hostapd - build) - * dual-licensed hostapd (GPLv2 and BSD licenses) - * fixed RADIUS accounting to generate a new session id for cases where - a station reassociates without first being complete deauthenticated - * fixed STA disassociation handler to mark next timeout state to - deauthenticate the station, i.e., skip long wait for inactivity poll - and extra disassociation, if the STA disassociates without - deauthenticating - * added integrated EAP authenticator that can be used instead of - external RADIUS authentication server; currently, only EAP-MD5 is - supported, so this cannot yet be used for key distribution; the EAP - method interface is generic, though, so adding new EAP methods should - be straightforward; new hostapd.conf variables: 'eap_authenticator' - and 'eap_user_file'; this obsoletes "minimal authentication server" - ('minimal_eap' in hostapd.conf) which is now removed - * added support for FreeBSD and driver interface for the BSD net80211 - layer (driver=bsd in hostapd.conf and CONFIG_DRIVER_BSD=y in - .config); please note that some of the required kernel mods have not - yet been committed - -2004-07-17 - v0.2.4 (beginning of 0.2.x stable releases) - * fixed some accounting cases where Accounting-Start was sent when - IEEE 802.1X port was being deauthorized - -2004-06-20 - v0.2.3 - * modified RADIUS client to re-connect the socket in case of certain - error codes that are generated when a network interface state is - changes (e.g., when IP address changes or the interface is set UP) - * fixed couple of cases where EAPOL state for a station was freed - twice causing a segfault for hostapd - * fixed couple of bugs in processing WPA deauthentication (freed data - was used) - -2004-05-31 - v0.2.2 - * fixed WPA/WPA2 group rekeying to use key index correctly (GN/GM) - * fixed group rekeying to send zero TSC in EAPOL-Key messages to fix - cases where STAs dropped multicast frames as replay attacks - * added support for copying RADIUS Attribute 'Class' from - authentication messages into accounting messages - * send canned EAP failure if RADIUS server sends Access-Reject without - EAP message (previously, Supplicant was not notified in this case) - * fixed mixed WPA-PSK and WPA-EAP mode to work with WPA-PSK (i.e., do - not start EAPOL state machines if the STA selected to use WPA-PSK) - -2004-05-06 - v0.2.1 - * added WPA and IEEE 802.11i/RSN (WPA2) Authenticator functionality - - based on IEEE 802.11i/D10.0 but modified to interoperate with WPA - (i.e., IEEE 802.11i/D3.0) - - supports WPA-only, RSN-only, and mixed WPA/RSN mode - - both WPA-PSK and WPA-RADIUS/EAP are supported - - PMKSA caching and pre-authentication - - new hostapd.conf variables: wpa, wpa_psk, wpa_passphrase, - wpa_key_mgmt, wpa_pairwise, wpa_group_rekey, wpa_gmk_rekey, - rsn_preauth, rsn_preauth_interfaces - * fixed interim accounting to remove any pending accounting messages - to the STA before sending a new one - -2004-02-15 - v0.2.0 - * added support for Acct-Interim-Interval: - - draft-ietf-radius-acct-interim-01.txt - - use Acct-Interim-Interval attribute from Access-Accept if local - 'radius_acct_interim_interval' is not set - - allow different update intervals for each STA - * fixed event loop to call signal handlers only after returning from - the real signal handler - * reset sta->timeout_next after successful association to make sure - that the previously registered inactivity timer will not remove the - STA immediately (e.g., if STA deauthenticates and re-associates - before the timer is triggered). - * added new hostapd.conf variable, nas_identifier, that can be used to - add an optional RADIUS Attribute, NAS-Identifier, into authentication - and accounting messages - * added support for Accounting-On and Accounting-Off messages - * fixed accounting session handling to send Accounting-Start only once - per session and not to send Accounting-Stop if the session was not - initialized properly - * fixed Accounting-Stop statistics in cases where the message was - previously sent after the kernel entry for the STA (and/or IEEE - 802.1X data) was removed - - -Note: - -Older changes up to and including v0.1.0 are included in the ChangeLog -of the Host AP driver. diff --git a/contrib/hostapd/hostapd/README b/contrib/hostapd/hostapd/README deleted file mode 100644 index eb9aa4815b..0000000000 --- a/contrib/hostapd/hostapd/README +++ /dev/null @@ -1,390 +0,0 @@ -hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP - Authenticator and RADIUS authentication server -================================================================ - -Copyright (c) 2002-2009, Jouni Malinen and contributors -All Rights Reserved. - -This program is dual-licensed under both the GPL version 2 and BSD -license. Either license may be used at your option. - - - -License -------- - -GPL v2: - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License version 2 as -published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -(this copy of the license is in COPYING file) - - -Alternatively, this software may be distributed, used, and modified -under the terms of BSD license: - -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. - -3. Neither the name(s) of the above-listed copyright holder(s) nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT -OWNER 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. - - - -Introduction -============ - -Originally, hostapd was an optional user space component for Host AP -driver. It adds more features to the basic IEEE 802.11 management -included in the kernel driver: using external RADIUS authentication -server for MAC address based access control, IEEE 802.1X Authenticator -and dynamic WEP keying, RADIUS accounting, WPA/WPA2 (IEEE 802.11i/RSN) -Authenticator and dynamic TKIP/CCMP keying. - -The current version includes support for other drivers, an integrated -EAP server (i.e., allow full authentication without requiring -an external RADIUS authentication server), and RADIUS authentication -server for EAP authentication. - - -Requirements ------------- - -Current hardware/software requirements: -- drivers: - Host AP driver for Prism2/2.5/3. - (http://hostap.epitest.fi/) - Please note that station firmware version needs to be 1.7.0 or newer - to work in WPA mode. - - madwifi driver for cards based on Atheros chip set (ar521x) - (http://sourceforge.net/projects/madwifi/) - Please note that you will need to add the correct path for - madwifi driver root directory in .config (see defconfig file for - an example: CFLAGS += -I) - - Prism54 driver for Intersil/Conexant Prism GT/Duette/Indigo - (http://www.prism54.org/) - - mac80211-based drivers that support AP mode (with driver=nl80211). - This includes drivers for Atheros (ath9k) and Broadcom (b43) - chipsets. - - Any wired Ethernet driver for wired IEEE 802.1X authentication - (experimental code) - - FreeBSD -current (with some kernel mods that have not yet been - committed when hostapd v0.3.0 was released) - BSD net80211 layer (e.g., Atheros driver) - - -Build configuration -------------------- - -In order to be able to build hostapd, you will need to create a build -time configuration file, .config that selects which optional -components are included. See defconfig file for example configuration -and list of available options. - - - -IEEE 802.1X -=========== - -IEEE Std 802.1X-2001 is a standard for port-based network access -control. In case of IEEE 802.11 networks, a "virtual port" is used -between each associated station and the AP. IEEE 802.11 specifies -minimal authentication mechanism for stations, whereas IEEE 802.1X -introduces a extensible mechanism for authenticating and authorizing -users. - -IEEE 802.1X uses elements called Supplicant, Authenticator, Port -Access Entity, and Authentication Server. Supplicant is a component in -a station and it performs the authentication with the Authentication -Server. An access point includes an Authenticator that relays the packets -between a Supplicant and an Authentication Server. In addition, it has a -Port Access Entity (PAE) with Authenticator functionality for -controlling the virtual port authorization, i.e., whether to accept -packets from or to the station. - -IEEE 802.1X uses Extensible Authentication Protocol (EAP). The frames -between a Supplicant and an Authenticator are sent using EAP over LAN -(EAPOL) and the Authenticator relays these frames to the Authentication -Server (and similarly, relays the messages from the Authentication -Server to the Supplicant). The Authentication Server can be colocated with the -Authenticator, in which case there is no need for additional protocol -for EAP frame transmission. However, a more common configuration is to -use an external Authentication Server and encapsulate EAP frame in the -frames used by that server. RADIUS is suitable for this, but IEEE -802.1X would also allow other mechanisms. - -Host AP driver includes PAE functionality in the kernel driver. It -is a relatively simple mechanism for denying normal frames going to -or coming from an unauthorized port. PAE allows IEEE 802.1X related -frames to be passed between the Supplicant and the Authenticator even -on an unauthorized port. - -User space daemon, hostapd, includes Authenticator functionality. It -receives 802.1X (EAPOL) frames from the Supplicant using the wlan#ap -device that is also used with IEEE 802.11 management frames. The -frames to the Supplicant are sent using the same device. - -The normal configuration of the Authenticator would use an external -Authentication Server. hostapd supports RADIUS encapsulation of EAP -packets, so the Authentication Server should be a RADIUS server, like -FreeRADIUS (http://www.freeradius.org/). The Authenticator in hostapd -relays the frames between the Supplicant and the Authentication -Server. It also controls the PAE functionality in the kernel driver by -controlling virtual port authorization, i.e., station-AP -connection, based on the IEEE 802.1X state. - -When a station would like to use the services of an access point, it -will first perform IEEE 802.11 authentication. This is normally done -with open systems authentication, so there is no security. After -this, IEEE 802.11 association is performed. If IEEE 802.1X is -configured to be used, the virtual port for the station is set in -Unauthorized state and only IEEE 802.1X frames are accepted at this -point. The Authenticator will then ask the Supplicant to authenticate -with the Authentication Server. After this is completed successfully, -the virtual port is set to Authorized state and frames from and to the -station are accepted. - -Host AP configuration for IEEE 802.1X -------------------------------------- - -The user space daemon has its own configuration file that can be used to -define AP options. Distribution package contains an example -configuration file (hostapd/hostapd.conf) that can be used as a basis -for configuration. It includes examples of all supported configuration -options and short description of each option. hostapd should be started -with full path to the configuration file as the command line argument, -e.g., './hostapd /etc/hostapd.conf'. If you have more that one wireless -LAN card, you can use one hostapd process for multiple interfaces by -giving a list of configuration files (one per interface) in the command -line. - -hostapd includes a minimal co-located IEEE 802.1X server which can be -used to test IEEE 802.1X authentication. However, it should not be -used in normal use since it does not provide any security. This can be -configured by setting ieee8021x and minimal_eap options in the -configuration file. - -An external Authentication Server (RADIUS) is configured with -auth_server_{addr,port,shared_secret} options. In addition, -ieee8021x and own_ip_addr must be set for this mode. With such -configuration, the co-located Authentication Server is not used and EAP -frames will be relayed using EAPOL between the Supplicant and the -Authenticator and RADIUS encapsulation between the Authenticator and -the Authentication Server. Other than this, the functionality is similar -to the case with the co-located Authentication Server. - -Authentication Server and Supplicant ------------------------------------- - -Any RADIUS server supporting EAP should be usable as an IEEE 802.1X -Authentication Server with hostapd Authenticator. FreeRADIUS -(http://www.freeradius.org/) has been successfully tested with hostapd -Authenticator and both Xsupplicant (http://www.open1x.org) and Windows -XP Supplicants. EAP/TLS was used with Xsupplicant and -EAP/MD5-Challenge with Windows XP. - -http://www.missl.cs.umd.edu/wireless/eaptls/ has useful information -about using EAP/TLS with FreeRADIUS and Xsupplicant (just replace -Cisco access point with Host AP driver, hostapd daemon, and a Prism2 -card ;-). http://www.freeradius.org/doc/EAP-MD5.html has information -about using EAP/MD5 with FreeRADIUS, including instructions for WinXP -configuration. http://www.denobula.com/EAPTLS.pdf has a HOWTO on -EAP/TLS use with WinXP Supplicant. - -Automatic WEP key configuration -------------------------------- - -EAP/TLS generates a session key that can be used to send WEP keys from -an AP to authenticated stations. The Authenticator in hostapd can be -configured to automatically select a random default/broadcast key -(shared by all authenticated stations) with wep_key_len_broadcast -option (5 for 40-bit WEP or 13 for 104-bit WEP). In addition, -wep_key_len_unicast option can be used to configure individual unicast -keys for stations. This requires support for individual keys in the -station driver. - -WEP keys can be automatically updated by configuring rekeying. This -will improve security of the network since same WEP key will only be -used for a limited period of time. wep_rekey_period option sets the -interval for rekeying in seconds. - - -WPA/WPA2 -======== - -Features --------- - -Supported WPA/IEEE 802.11i features: -- WPA-PSK ("WPA-Personal") -- WPA with EAP (e.g., with RADIUS authentication server) ("WPA-Enterprise") -- key management for CCMP, TKIP, WEP104, WEP40 -- RSN/WPA2 (IEEE 802.11i), including PMKSA caching and pre-authentication - -WPA ---- - -The original security mechanism of IEEE 802.11 standard was not -designed to be strong and has proved to be insufficient for most -networks that require some kind of security. Task group I (Security) -of IEEE 802.11 working group (http://www.ieee802.org/11/) has worked -to address the flaws of the base standard and has in practice -completed its work in May 2004. The IEEE 802.11i amendment to the IEEE -802.11 standard was approved in June 2004 and this amendment is likely -to be published in July 2004. - -Wi-Fi Alliance (http://www.wi-fi.org/) used a draft version of the -IEEE 802.11i work (draft 3.0) to define a subset of the security -enhancements that can be implemented with existing wlan hardware. This -is called Wi-Fi Protected Access (WPA). This has now become a -mandatory component of interoperability testing and certification done -by Wi-Fi Alliance. Wi-Fi provides information about WPA at its web -site (http://www.wi-fi.org/OpenSection/protected_access.asp). - -IEEE 802.11 standard defined wired equivalent privacy (WEP) algorithm -for protecting wireless networks. WEP uses RC4 with 40-bit keys, -24-bit initialization vector (IV), and CRC32 to protect against packet -forgery. All these choices have proven to be insufficient: key space is -too small against current attacks, RC4 key scheduling is insufficient -(beginning of the pseudorandom stream should be skipped), IV space is -too small and IV reuse makes attacks easier, there is no replay -protection, and non-keyed authentication does not protect against bit -flipping packet data. - -WPA is an intermediate solution for the security issues. It uses -Temporal Key Integrity Protocol (TKIP) to replace WEP. TKIP is a -compromise on strong security and possibility to use existing -hardware. It still uses RC4 for the encryption like WEP, but with -per-packet RC4 keys. In addition, it implements replay protection, -keyed packet authentication mechanism (Michael MIC). - -Keys can be managed using two different mechanisms. WPA can either use -an external authentication server (e.g., RADIUS) and EAP just like -IEEE 802.1X is using or pre-shared keys without need for additional -servers. Wi-Fi calls these "WPA-Enterprise" and "WPA-Personal", -respectively. Both mechanisms will generate a master session key for -the Authenticator (AP) and Supplicant (client station). - -WPA implements a new key handshake (4-Way Handshake and Group Key -Handshake) for generating and exchanging data encryption keys between -the Authenticator and Supplicant. This handshake is also used to -verify that both Authenticator and Supplicant know the master session -key. These handshakes are identical regardless of the selected key -management mechanism (only the method for generating master session -key changes). - - -IEEE 802.11i / WPA2 -------------------- - -The design for parts of IEEE 802.11i that were not included in WPA has -finished (May 2004) and this amendment to IEEE 802.11 was approved in -June 2004. Wi-Fi Alliance is using the final IEEE 802.11i as a new -version of WPA called WPA2. This includes, e.g., support for more -robust encryption algorithm (CCMP: AES in Counter mode with CBC-MAC) -to replace TKIP and optimizations for handoff (reduced number of -messages in initial key handshake, pre-authentication, and PMKSA caching). - -Some wireless LAN vendors are already providing support for CCMP in -their WPA products. There is no "official" interoperability -certification for CCMP and/or mixed modes using both TKIP and CCMP, so -some interoperability issues can be expected even though many -combinations seem to be working with equipment from different vendors. -Testing for WPA2 is likely to start during the second half of 2004. - -hostapd configuration for WPA/WPA2 ----------------------------------- - -TODO - -# Enable WPA. Setting this variable configures the AP to require WPA (either -# WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either -# wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK. -# For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys), -# RADIUS authentication server must be configured, and WPA-EAP must be included -# in wpa_key_mgmt. -# This field is a bit field that can be used to enable WPA (IEEE 802.11i/D3.0) -# and/or WPA2 (full IEEE 802.11i/RSN): -# bit0 = WPA -# bit1 = IEEE 802.11i/RSN (WPA2) -#wpa=1 - -# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit -# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase -# (8..63 characters) that will be converted to PSK. This conversion uses SSID -# so the PSK changes when ASCII passphrase is used and the SSID is changed. -#wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef -#wpa_passphrase=secret passphrase - -# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The -# entries are separated with a space. -#wpa_key_mgmt=WPA-PSK WPA-EAP - -# Set of accepted cipher suites (encryption algorithms) for pairwise keys -# (unicast packets). This is a space separated list of algorithms: -# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i] -# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i] -# Group cipher suite (encryption algorithm for broadcast and multicast frames) -# is automatically selected based on this configuration. If only CCMP is -# allowed as the pairwise cipher, group cipher will also be CCMP. Otherwise, -# TKIP will be used as the group cipher. -#wpa_pairwise=TKIP CCMP - -# Time interval for rekeying GTK (broadcast/multicast encryption keys) in -# seconds. -#wpa_group_rekey=600 - -# Time interval for rekeying GMK (master key used internally to generate GTKs -# (in seconds). -#wpa_gmk_rekey=86400 - -# Enable IEEE 802.11i/RSN/WPA2 pre-authentication. This is used to speed up -# roaming be pre-authenticating IEEE 802.1X/EAP part of the full RSN -# authentication and key handshake before actually associating with a new AP. -#rsn_preauth=1 -# -# Space separated list of interfaces from which pre-authentication frames are -# accepted (e.g., 'eth0' or 'eth0 wlan0wds0'. This list should include all -# interface that are used for connections to other APs. This could include -# wired interfaces and WDS links. The normal wireless data interface towards -# associated stations (e.g., wlan0) should not be added, since -# pre-authentication is only used with APs other than the currently associated -# one. -#rsn_preauth_interfaces=eth0 diff --git a/contrib/hostapd/hostapd/README-WPS b/contrib/hostapd/hostapd/README-WPS deleted file mode 100644 index e0e370b5bc..0000000000 --- a/contrib/hostapd/hostapd/README-WPS +++ /dev/null @@ -1,239 +0,0 @@ -hostapd and Wi-Fi Protected Setup (WPS) -======================================= - -This document describes how the WPS implementation in hostapd can be -configured and how an external component on an AP (e.g., web UI) is -used to enable enrollment of client devices. - - -Introduction to WPS -------------------- - -Wi-Fi Protected Setup (WPS) is a mechanism for easy configuration of a -wireless network. It allows automated generation of random keys (WPA -passphrase/PSK) and configuration of an access point and client -devices. WPS includes number of methods for setting up connections -with PIN method and push-button configuration (PBC) being the most -commonly deployed options. - -While WPS can enable more home networks to use encryption in the -wireless network, it should be noted that the use of the PIN and -especially PBC mechanisms for authenticating the initial key setup is -not very secure. As such, use of WPS may not be suitable for -environments that require secure network access without chance for -allowing outsiders to gain access during the setup phase. - -WPS uses following terms to describe the entities participating in the -network setup: -- access point: the WLAN access point -- Registrar: a device that control a network and can authorize - addition of new devices); this may be either in the AP ("internal - Registrar") or in an external device, e.g., a laptop, ("external - Registrar") -- Enrollee: a device that is being authorized to use the network - -It should also be noted that the AP and a client device may change -roles (i.e., AP acts as an Enrollee and client device as a Registrar) -when WPS is used to configure the access point. - - -More information about WPS is available from Wi-Fi Alliance: -http://www.wi-fi.org/wifi-protected-setup - - -hostapd implementation ----------------------- - -hostapd includes an optional WPS component that can be used as an -internal WPS Registrar to manage addition of new WPS enabled clients -to the network. In addition, WPS Enrollee functionality in hostapd can -be used to allow external WPS Registrars to configure the access -point, e.g., for initial network setup. In addition, hostapd can proxy a -WPS registration between a wireless Enrollee and an external Registrar -(e.g., Microsoft Vista or Atheros JumpStart) with UPnP. - - -hostapd configuration ---------------------- - -WPS is an optional component that needs to be enabled in hostapd build -configuration (.config). Here is an example configuration that -includes WPS support and uses madwifi driver interface: - -CONFIG_DRIVER_MADWIFI=y -CFLAGS += -I/usr/src/madwifi-0.9.3 -CONFIG_EAP=y -CONFIG_WPS=y -CONFIG_WPS_UPNP=y - - -Following section shows an example runtime configuration -(hostapd.conf) that enables WPS: - -# Configure the driver and network interface -driver=madwifi -interface=ath0 - -# WPA2-Personal configuration for the AP -ssid=wps-test -wpa=2 -wpa_key_mgmt=WPA-PSK -wpa_pairwise=CCMP -# Default WPA passphrase for legacy (non-WPS) clients -wpa_passphrase=12345678 -# Enable random per-device PSK generation for WPS clients -# Please note that the file has to exists for hostapd to start (i.e., create an -# empty file as a starting point). -wpa_psk_file=/etc/hostapd.psk - -# Enable control interface for PBC/PIN entry -ctrl_interface=/var/run/hostapd - -# Enable internal EAP server for EAP-WSC (part of Wi-Fi Protected Setup) -eap_server=1 - -# WPS configuration (AP configured, do not allow external WPS Registrars) -wps_state=2 -ap_setup_locked=1 -# If UUID is not configured, it will be generated based on local MAC address. -uuid=87654321-9abc-def0-1234-56789abc0000 -wps_pin_requests=/var/run/hostapd.pin-req -device_name=Wireless AP -manufacturer=Company -model_name=WAP -model_number=123 -serial_number=12345 -device_type=6-0050F204-1 -os_version=01020300 -config_methods=label display push_button keypad - -# if external Registrars are allowed, UPnP support could be added: -#upnp_iface=br0 -#friendly_name=WPS Access Point - - -External operations -------------------- - -WPS requires either a device PIN code (usually, 8-digit number) or a -pushbutton event (for PBC) to allow a new WPS Enrollee to join the -network. hostapd uses the control interface as an input channel for -these events. - -When a client device (WPS Enrollee) connects to hostapd (WPS -Registrar) in order to start PIN mode negotiation for WPS, an -identifier (Enrollee UUID) is sent. hostapd will need to be configured -with a device password (PIN) for this Enrollee. This is an operation -that requires user interaction (assuming there are no pre-configured -PINs on the AP for a set of Enrollee). - -The PIN request with information about the device is appended to the -wps_pin_requests file (/var/run/hostapd.pin-req in this example). In -addition, hostapd control interface event is sent as a notification of -a new device. The AP could use, e.g., a web UI for showing active -Enrollees to the user and request a PIN for an Enrollee. - -The PIN request file has one line for every Enrollee that connected to -the AP, but for which there was no PIN. Following information is -provided for each Enrollee (separated with tabulators): -- timestamp (seconds from 1970-01-01) -- Enrollee UUID -- MAC address -- Device name -- Manufacturer -- Model Name -- Model Number -- Serial Number -- Device category - -Example line in the /var/run/hostapd.pin-req file: -1200188391 53b63a98-d29e-4457-a2ed-094d7e6a669c Intel(R) Centrino(R) Intel Corporation Intel(R) Centrino(R) - - 1-0050F204-1 - -Control interface data: -WPS-PIN-NEEDED [UUID-E|MAC Address|Device Name|Manufacturer|Model Name|Model Number|Serial Number|Device Category] -For example: -<2>WPS-PIN-NEEDED [53b63a98-d29e-4457-a2ed-094d7e6a669c|02:12:34:56:78:9a|Device|Manuf|Model|Model Number|Serial Number|1-0050F204-1] - -When the user enters a PIN for a pending Enrollee, e.g., on the web -UI), hostapd needs to be notified of the new PIN over the control -interface. This can be done either by using the UNIX domain socket --based control interface directly (src/common/wpa_ctrl.c provides -helper functions for using the interface) or by calling hostapd_cli. - -Example command to add a PIN (12345670) for an Enrollee: - -hostapd_cli wps_pin 53b63a98-d29e-4457-a2ed-094d7e6a669c 12345670 - -If the UUID-E is not available (e.g., Enrollee waits for the Registrar -to be selected before connecting), wildcard UUID may be used to allow -the PIN to be used once with any UUID: - -hostapd_cli wps_pin any 12345670 - -To reduce likelihood of PIN being used with other devices or of -forgetting an active PIN available for potential attackers, expiration -time can be set for the new PIN: - -hostapd_cli wps_pin any 12345670 300 - - -After this, the Enrollee can connect to the AP again and complete WPS -negotiation. At that point, a new, random WPA PSK is generated for the -client device and the client can then use that key to connect to the -AP to access the network. - - -If the AP includes a pushbutton, WPS PBC mode can be used. It is -enabled by pushing a button on both the AP and the client at about the -same time (2 minute window). hostapd needs to be notified about the AP -button pushed event over the control interface, e.g., by calling -hostapd_cli: - -hostapd_cli wps_pbc - -At this point, the client has two minutes to complete WPS negotiation -which will generate a new WPA PSK in the same way as the PIN method -described above. - - -Credential generation and configuration changes ------------------------------------------------ - -By default, hostapd generates credentials for Enrollees and processing -AP configuration updates internally. However, it is possible to -control these operations from external programs, if desired. - -The internal credential generation can be disabled with -skip_cred_build=1 option in the configuration. extra_cred option will -then need to be used to provide pre-configured Credential attribute(s) -for hostapd to use. The exact data from this binary file will be sent, -i.e., it will have to include valid WPS attributes. extra_cred can -also be used to add additional networks if the Registrar is used to -configure credentials for multiple networks. - -Processing of received configuration updates can be disabled with -wps_cred_processing=1 option. When this is used, an external program -is responsible for creating hostapd configuration files and processing -configuration updates based on messages received from hostapd over -control interface. This will also include the initial configuration on -first successful registration if the AP is initially set in -unconfigured state. - -Following control interface messages are sent out for external programs: - -WPS-REG-SUCCESS -For example: -<2>WPS-REG-SUCCESS 02:66:a0:ee:17:27 2b7093f1-d6fb-5108-adbb-bea66bb87333 - -This can be used to tricker change from unconfigured to configured -state (random configuration based on the first successful WPS -registration). In addition, this can be used to update AP UI about the -status of WPS registration progress. - - -WPS-NEW-AP-SETTINGS -For example: -<2>WPS-NEW-AP-SETTINGS 10260001011045000c6a6b6d2d7770732d74657374100300020020100f00020008102700403065346230343536633236366665306433396164313535346131663462663731323433376163666462376633393965353466316631623032306164343438623510200006024231cede15101e000844 - -This can be used to update the externally stored AP configuration and -then update hostapd configuration (followed by restarting of hostapd). diff --git a/contrib/hostapd/hostapd/accounting.c b/contrib/hostapd/hostapd/accounting.c deleted file mode 100644 index ce71678af4..0000000000 --- a/contrib/hostapd/hostapd/accounting.c +++ /dev/null @@ -1,510 +0,0 @@ -/* - * hostapd / RADIUS Accounting - * Copyright (c) 2002-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "hostapd.h" -#include "radius/radius.h" -#include "radius/radius_client.h" -#include "eloop.h" -#include "accounting.h" -#include "ieee802_1x.h" -#include "driver.h" - - -/* Default interval in seconds for polling TX/RX octets from the driver if - * STA is not using interim accounting. This detects wrap arounds for - * input/output octets and updates Acct-{Input,Output}-Gigawords. */ -#define ACCT_DEFAULT_UPDATE_INTERVAL 300 - -static void accounting_sta_get_id(struct hostapd_data *hapd, - struct sta_info *sta); - - -static struct radius_msg * accounting_msg(struct hostapd_data *hapd, - struct sta_info *sta, - int status_type) -{ - struct radius_msg *msg; - char buf[128]; - u8 *val; - size_t len; - int i; - - msg = radius_msg_new(RADIUS_CODE_ACCOUNTING_REQUEST, - radius_client_get_id(hapd->radius)); - if (msg == NULL) { - printf("Could not create net RADIUS packet\n"); - return NULL; - } - - if (sta) { - radius_msg_make_authenticator(msg, (u8 *) sta, sizeof(*sta)); - - os_snprintf(buf, sizeof(buf), "%08X-%08X", - sta->acct_session_id_hi, sta->acct_session_id_lo); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_ACCT_SESSION_ID, - (u8 *) buf, os_strlen(buf))) { - printf("Could not add Acct-Session-Id\n"); - goto fail; - } - } else { - radius_msg_make_authenticator(msg, (u8 *) hapd, sizeof(*hapd)); - } - - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_STATUS_TYPE, - status_type)) { - printf("Could not add Acct-Status-Type\n"); - goto fail; - } - - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_AUTHENTIC, - hapd->conf->ieee802_1x ? - RADIUS_ACCT_AUTHENTIC_RADIUS : - RADIUS_ACCT_AUTHENTIC_LOCAL)) { - printf("Could not add Acct-Authentic\n"); - goto fail; - } - - if (sta) { - val = ieee802_1x_get_identity(sta->eapol_sm, &len); - if (!val) { - os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, - MAC2STR(sta->addr)); - val = (u8 *) buf; - len = os_strlen(buf); - } - - if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, val, - len)) { - printf("Could not add User-Name\n"); - goto fail; - } - } - - if (hapd->conf->own_ip_addr.af == AF_INET && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, - (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) { - printf("Could not add NAS-IP-Address\n"); - goto fail; - } - -#ifdef CONFIG_IPV6 - if (hapd->conf->own_ip_addr.af == AF_INET6 && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS, - (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) { - printf("Could not add NAS-IPv6-Address\n"); - goto fail; - } -#endif /* CONFIG_IPV6 */ - - if (hapd->conf->nas_identifier && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER, - (u8 *) hapd->conf->nas_identifier, - os_strlen(hapd->conf->nas_identifier))) { - printf("Could not add NAS-Identifier\n"); - goto fail; - } - - if (sta && - !radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) { - printf("Could not add NAS-Port\n"); - goto fail; - } - - os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s", - MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID, - (u8 *) buf, os_strlen(buf))) { - printf("Could not add Called-Station-Id\n"); - goto fail; - } - - if (sta) { - os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, - MAC2STR(sta->addr)); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, - (u8 *) buf, os_strlen(buf))) { - printf("Could not add Calling-Station-Id\n"); - goto fail; - } - - if (!radius_msg_add_attr_int32( - msg, RADIUS_ATTR_NAS_PORT_TYPE, - RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { - printf("Could not add NAS-Port-Type\n"); - goto fail; - } - - os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s", - radius_sta_rate(hapd, sta) / 2, - (radius_sta_rate(hapd, sta) & 1) ? ".5" : "", - radius_mode_txt(hapd)); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, - (u8 *) buf, os_strlen(buf))) { - printf("Could not add Connect-Info\n"); - goto fail; - } - - for (i = 0; ; i++) { - val = ieee802_1x_get_radius_class(sta->eapol_sm, &len, - i); - if (val == NULL) - break; - - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CLASS, - val, len)) { - printf("Could not add Class\n"); - goto fail; - } - } - } - - return msg; - - fail: - radius_msg_free(msg); - os_free(msg); - return NULL; -} - - -static int accounting_sta_update_stats(struct hostapd_data *hapd, - struct sta_info *sta, - struct hostap_sta_driver_data *data) -{ - if (hostapd_read_sta_data(hapd, data, sta->addr)) - return -1; - - if (sta->last_rx_bytes > data->rx_bytes) - sta->acct_input_gigawords++; - if (sta->last_tx_bytes > data->tx_bytes) - sta->acct_output_gigawords++; - sta->last_rx_bytes = data->rx_bytes; - sta->last_tx_bytes = data->tx_bytes; - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, "updated TX/RX stats: " - "Acct-Input-Octets=%lu Acct-Input-Gigawords=%u " - "Acct-Output-Octets=%lu Acct-Output-Gigawords=%u", - sta->last_rx_bytes, sta->acct_input_gigawords, - sta->last_tx_bytes, sta->acct_output_gigawords); - - return 0; -} - - -static void accounting_interim_update(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - struct sta_info *sta = timeout_ctx; - int interval; - - if (sta->acct_interim_interval) { - accounting_sta_interim(hapd, sta); - interval = sta->acct_interim_interval; - } else { - struct hostap_sta_driver_data data; - accounting_sta_update_stats(hapd, sta, &data); - interval = ACCT_DEFAULT_UPDATE_INTERVAL; - } - - eloop_register_timeout(interval, 0, accounting_interim_update, - hapd, sta); -} - - -/** - * accounting_sta_start - Start STA accounting - * @hapd: hostapd BSS data - * @sta: The station - */ -void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta) -{ - struct radius_msg *msg; - int interval; - - if (sta->acct_session_started) - return; - - accounting_sta_get_id(hapd, sta); - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, - "starting accounting session %08X-%08X", - sta->acct_session_id_hi, sta->acct_session_id_lo); - - time(&sta->acct_session_start); - sta->last_rx_bytes = sta->last_tx_bytes = 0; - sta->acct_input_gigawords = sta->acct_output_gigawords = 0; - hostapd_sta_clear_stats(hapd, sta->addr); - - if (!hapd->conf->radius->acct_server) - return; - - if (sta->acct_interim_interval) - interval = sta->acct_interim_interval; - else - interval = ACCT_DEFAULT_UPDATE_INTERVAL; - eloop_register_timeout(interval, 0, accounting_interim_update, - hapd, sta); - - msg = accounting_msg(hapd, sta, RADIUS_ACCT_STATUS_TYPE_START); - if (msg) - radius_client_send(hapd->radius, msg, RADIUS_ACCT, sta->addr); - - sta->acct_session_started = 1; -} - - -static void accounting_sta_report(struct hostapd_data *hapd, - struct sta_info *sta, int stop) -{ - struct radius_msg *msg; - int cause = sta->acct_terminate_cause; - struct hostap_sta_driver_data data; - u32 gigawords; - - if (!hapd->conf->radius->acct_server) - return; - - msg = accounting_msg(hapd, sta, - stop ? RADIUS_ACCT_STATUS_TYPE_STOP : - RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE); - if (!msg) { - printf("Could not create RADIUS Accounting message\n"); - return; - } - - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_SESSION_TIME, - time(NULL) - sta->acct_session_start)) { - printf("Could not add Acct-Session-Time\n"); - goto fail; - } - - if (accounting_sta_update_stats(hapd, sta, &data) == 0) { - if (!radius_msg_add_attr_int32(msg, - RADIUS_ATTR_ACCT_INPUT_PACKETS, - data.rx_packets)) { - printf("Could not add Acct-Input-Packets\n"); - goto fail; - } - if (!radius_msg_add_attr_int32(msg, - RADIUS_ATTR_ACCT_OUTPUT_PACKETS, - data.tx_packets)) { - printf("Could not add Acct-Output-Packets\n"); - goto fail; - } - if (!radius_msg_add_attr_int32(msg, - RADIUS_ATTR_ACCT_INPUT_OCTETS, - data.rx_bytes)) { - printf("Could not add Acct-Input-Octets\n"); - goto fail; - } - gigawords = sta->acct_input_gigawords; -#if __WORDSIZE == 64 - gigawords += data.rx_bytes >> 32; -#endif - if (gigawords && - !radius_msg_add_attr_int32( - msg, RADIUS_ATTR_ACCT_INPUT_GIGAWORDS, - gigawords)) { - printf("Could not add Acct-Input-Gigawords\n"); - goto fail; - } - if (!radius_msg_add_attr_int32(msg, - RADIUS_ATTR_ACCT_OUTPUT_OCTETS, - data.tx_bytes)) { - printf("Could not add Acct-Output-Octets\n"); - goto fail; - } - gigawords = sta->acct_output_gigawords; -#if __WORDSIZE == 64 - gigawords += data.tx_bytes >> 32; -#endif - if (gigawords && - !radius_msg_add_attr_int32( - msg, RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS, - gigawords)) { - printf("Could not add Acct-Output-Gigawords\n"); - goto fail; - } - } - - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_EVENT_TIMESTAMP, - time(NULL))) { - printf("Could not add Event-Timestamp\n"); - goto fail; - } - - if (eloop_terminated()) - cause = RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_REBOOT; - - if (stop && cause && - !radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_TERMINATE_CAUSE, - cause)) { - printf("Could not add Acct-Terminate-Cause\n"); - goto fail; - } - - radius_client_send(hapd->radius, msg, - stop ? RADIUS_ACCT : RADIUS_ACCT_INTERIM, - sta->addr); - return; - - fail: - radius_msg_free(msg); - os_free(msg); -} - - -/** - * accounting_sta_interim - Send a interim STA accounting report - * @hapd: hostapd BSS data - * @sta: The station - */ -void accounting_sta_interim(struct hostapd_data *hapd, struct sta_info *sta) -{ - if (sta->acct_session_started) - accounting_sta_report(hapd, sta, 0); -} - - -/** - * accounting_sta_stop - Stop STA accounting - * @hapd: hostapd BSS data - * @sta: The station - */ -void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta) -{ - if (sta->acct_session_started) { - accounting_sta_report(hapd, sta, 1); - eloop_cancel_timeout(accounting_interim_update, hapd, sta); - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, - "stopped accounting session %08X-%08X", - sta->acct_session_id_hi, - sta->acct_session_id_lo); - sta->acct_session_started = 0; - } -} - - -static void accounting_sta_get_id(struct hostapd_data *hapd, - struct sta_info *sta) -{ - sta->acct_session_id_lo = hapd->acct_session_id_lo++; - if (hapd->acct_session_id_lo == 0) { - hapd->acct_session_id_hi++; - } - sta->acct_session_id_hi = hapd->acct_session_id_hi; -} - - -/** - * accounting_receive - Process the RADIUS frames from Accounting Server - * @msg: RADIUS response message - * @req: RADIUS request message - * @shared_secret: RADIUS shared secret - * @shared_secret_len: Length of shared_secret in octets - * @data: Context data (struct hostapd_data *) - * Returns: Processing status - */ -static RadiusRxResult -accounting_receive(struct radius_msg *msg, struct radius_msg *req, - const u8 *shared_secret, size_t shared_secret_len, - void *data) -{ - if (msg->hdr->code != RADIUS_CODE_ACCOUNTING_RESPONSE) { - printf("Unknown RADIUS message code\n"); - return RADIUS_RX_UNKNOWN; - } - - if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) { - printf("Incoming RADIUS packet did not have correct " - "Authenticator - dropped\n"); - return RADIUS_RX_INVALID_AUTHENTICATOR; - } - - return RADIUS_RX_PROCESSED; -} - - -static void accounting_report_state(struct hostapd_data *hapd, int on) -{ - struct radius_msg *msg; - - if (!hapd->conf->radius->acct_server || hapd->radius == NULL) - return; - - /* Inform RADIUS server that accounting will start/stop so that the - * server can close old accounting sessions. */ - msg = accounting_msg(hapd, NULL, - on ? RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON : - RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_OFF); - if (!msg) - return; - - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_TERMINATE_CAUSE, - RADIUS_ACCT_TERMINATE_CAUSE_NAS_REBOOT)) - { - printf("Could not add Acct-Terminate-Cause\n"); - radius_msg_free(msg); - os_free(msg); - return; - } - - radius_client_send(hapd->radius, msg, RADIUS_ACCT, NULL); -} - - -/** - * accounting_init: Initialize accounting - * @hapd: hostapd BSS data - * Returns: 0 on success, -1 on failure - */ -int accounting_init(struct hostapd_data *hapd) -{ - /* Acct-Session-Id should be unique over reboots. If reliable clock is - * not available, this could be replaced with reboot counter, etc. */ - hapd->acct_session_id_hi = time(NULL); - - if (radius_client_register(hapd->radius, RADIUS_ACCT, - accounting_receive, hapd)) - return -1; - - accounting_report_state(hapd, 1); - - return 0; -} - - -/** - * accounting_deinit: Deinitilize accounting - * @hapd: hostapd BSS data - */ -void accounting_deinit(struct hostapd_data *hapd) -{ - accounting_report_state(hapd, 0); -} - - -int accounting_reconfig(struct hostapd_data *hapd, - struct hostapd_config *oldconf) -{ - if (!hapd->radius_client_reconfigured) - return 0; - - accounting_deinit(hapd); - return accounting_init(hapd); -} diff --git a/contrib/hostapd/hostapd/accounting.h b/contrib/hostapd/hostapd/accounting.h deleted file mode 100644 index 51e6b4d498..0000000000 --- a/contrib/hostapd/hostapd/accounting.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * hostapd / RADIUS Accounting - * Copyright (c) 2002-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef ACCOUNTING_H -#define ACCOUNTING_H - -void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta); -void accounting_sta_interim(struct hostapd_data *hapd, struct sta_info *sta); -void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta); -int accounting_init(struct hostapd_data *hapd); -void accounting_deinit(struct hostapd_data *hapd); -int accounting_reconfig(struct hostapd_data *hapd, - struct hostapd_config *oldconf); - -#endif /* ACCOUNTING_H */ diff --git a/contrib/hostapd/hostapd/ap.h b/contrib/hostapd/hostapd/ap.h deleted file mode 100644 index 2c6d7e9799..0000000000 --- a/contrib/hostapd/hostapd/ap.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * hostapd / Station table data structures - * Copyright (c) 2002-2008, Jouni Malinen - * Copyright (c) 2007-2008, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef AP_H -#define AP_H - -#ifdef CONFIG_IEEE80211N -#include "ieee802_11_defs.h" -#endif /* CONFIG_IEEE80211N */ - -/* STA flags */ -#define WLAN_STA_AUTH BIT(0) -#define WLAN_STA_ASSOC BIT(1) -#define WLAN_STA_PS BIT(2) -#define WLAN_STA_TIM BIT(3) -#define WLAN_STA_PERM BIT(4) -#define WLAN_STA_AUTHORIZED BIT(5) -#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */ -#define WLAN_STA_SHORT_PREAMBLE BIT(7) -#define WLAN_STA_PREAUTH BIT(8) -#define WLAN_STA_WMM BIT(9) -#define WLAN_STA_MFP BIT(10) -#define WLAN_STA_HT BIT(11) -#define WLAN_STA_WPS BIT(12) -#define WLAN_STA_MAYBE_WPS BIT(13) -#define WLAN_STA_NONERP BIT(31) - -/* Maximum number of supported rates (from both Supported Rates and Extended - * Supported Rates IEs). */ -#define WLAN_SUPP_RATES_MAX 32 - - -struct sta_info { - struct sta_info *next; /* next entry in sta list */ - struct sta_info *hnext; /* next entry in hash table list */ - u8 addr[6]; - u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */ - u32 flags; - u16 capability; - u16 listen_interval; /* or beacon_int for APs */ - u8 supported_rates[WLAN_SUPP_RATES_MAX]; - int supported_rates_len; - - unsigned int nonerp_set:1; - unsigned int no_short_slot_time_set:1; - unsigned int no_short_preamble_set:1; - unsigned int no_ht_gf_set:1; - unsigned int no_ht_set:1; - unsigned int ht_20mhz_set:1; - - u16 auth_alg; - u8 previous_ap[6]; - - enum { - STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH, STA_REMOVE - } timeout_next; - - /* IEEE 802.1X related data */ - struct eapol_state_machine *eapol_sm; - - /* IEEE 802.11f (IAPP) related data */ - struct ieee80211_mgmt *last_assoc_req; - - u32 acct_session_id_hi; - u32 acct_session_id_lo; - time_t acct_session_start; - int acct_session_started; - int acct_terminate_cause; /* Acct-Terminate-Cause */ - int acct_interim_interval; /* Acct-Interim-Interval */ - - unsigned long last_rx_bytes; - unsigned long last_tx_bytes; - u32 acct_input_gigawords; /* Acct-Input-Gigawords */ - u32 acct_output_gigawords; /* Acct-Output-Gigawords */ - - u8 *challenge; /* IEEE 802.11 Shared Key Authentication Challenge */ - - struct wpa_state_machine *wpa_sm; - struct rsn_preauth_interface *preauth_iface; - - struct hostapd_ssid *ssid; /* SSID selection based on (Re)AssocReq */ - struct hostapd_ssid *ssid_probe; /* SSID selection based on ProbeReq */ - - int vlan_id; - -#ifdef CONFIG_IEEE80211N - struct ht_cap_ie ht_capabilities; /* IEEE 802.11n capabilities */ -#endif /* CONFIG_IEEE80211N */ - -#ifdef CONFIG_IEEE80211W - int sa_query_count; /* number of pending SA Query requests; - * 0 = no SA Query in progress */ - int sa_query_timed_out; - u8 *sa_query_trans_id; /* buffer of WLAN_SA_QUERY_TR_ID_LEN * - * sa_query_count octets of pending SA Query - * transaction identifiers */ - struct os_time sa_query_start; -#endif /* CONFIG_IEEE80211W */ - - struct wpabuf *wps_ie; /* WPS IE from (Re)Association Request */ -}; - - -/* Maximum number of AIDs to use for STAs; must be 2007 or lower - * (8802.11 limitation) */ -#define MAX_AID_TABLE_SIZE 128 - -#define STA_HASH_SIZE 256 -#define STA_HASH(sta) (sta[5]) - - -/* Default value for maximum station inactivity. After AP_MAX_INACTIVITY has - * passed since last received frame from the station, a nullfunc data frame is - * sent to the station. If this frame is not acknowledged and no other frames - * have been received, the station will be disassociated after - * AP_DISASSOC_DELAY seconds. Similarily, the station will be deauthenticated - * after AP_DEAUTH_DELAY seconds has passed after disassociation. */ -#define AP_MAX_INACTIVITY (5 * 60) -#define AP_DISASSOC_DELAY (1) -#define AP_DEAUTH_DELAY (1) -/* Number of seconds to keep STA entry with Authenticated flag after it has - * been disassociated. */ -#define AP_MAX_INACTIVITY_AFTER_DISASSOC (1 * 30) -/* Number of seconds to keep STA entry after it has been deauthenticated. */ -#define AP_MAX_INACTIVITY_AFTER_DEAUTH (1 * 5) - -#endif /* AP_H */ diff --git a/contrib/hostapd/hostapd/ap_list.c b/contrib/hostapd/hostapd/ap_list.c deleted file mode 100644 index 4f217dc541..0000000000 --- a/contrib/hostapd/hostapd/ap_list.c +++ /dev/null @@ -1,501 +0,0 @@ -/* - * hostapd / AP table - * Copyright (c) 2002-2003, Jouni Malinen - * Copyright (c) 2003-2004, Instant802 Networks, Inc. - * Copyright (c) 2006, Devicescape Software, Inc. - * Copyright (c) 2007-2008, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "hostapd.h" -#include "ieee802_11.h" -#include "eloop.h" -#include "ap_list.h" -#include "hw_features.h" -#include "beacon.h" - - -struct ieee80211_frame_info { - u32 version; - u32 length; - u64 mactime; - u64 hosttime; - u32 phytype; - u32 channel; - u32 datarate; - u32 antenna; - u32 priority; - u32 ssi_type; - u32 ssi_signal; - u32 ssi_noise; - u32 preamble; - u32 encoding; - - /* Note: this structure is otherwise identical to capture format used - * in linux-wlan-ng, but this additional field is used to provide meta - * data about the frame to hostapd. This was the easiest method for - * providing this information, but this might change in the future. */ - u32 msg_type; -} __attribute__ ((packed)); - - -enum ieee80211_phytype { - ieee80211_phytype_fhss_dot11_97 = 1, - ieee80211_phytype_dsss_dot11_97 = 2, - ieee80211_phytype_irbaseband = 3, - ieee80211_phytype_dsss_dot11_b = 4, - ieee80211_phytype_pbcc_dot11_b = 5, - ieee80211_phytype_ofdm_dot11_g = 6, - ieee80211_phytype_pbcc_dot11_g = 7, - ieee80211_phytype_ofdm_dot11_a = 8, - ieee80211_phytype_dsss_dot11_turbog = 255, - ieee80211_phytype_dsss_dot11_turbo = 256, -}; - - -/* AP list is a double linked list with head->prev pointing to the end of the - * list and tail->next = NULL. Entries are moved to the head of the list - * whenever a beacon has been received from the AP in question. The tail entry - * in this link will thus be the least recently used entry. */ - - -static void ap_list_new_ap(struct hostapd_iface *iface, struct ap_info *ap) -{ - wpa_printf(MSG_DEBUG, "New AP detected: " MACSTR, MAC2STR(ap->addr)); - - /* TODO: could send a notification message to an external program that - * would then determine whether a rogue AP has been detected */ -} - - -static void ap_list_expired_ap(struct hostapd_iface *iface, struct ap_info *ap) -{ - wpa_printf(MSG_DEBUG, "AP info expired: " MACSTR, MAC2STR(ap->addr)); - - /* TODO: could send a notification message to an external program */ -} - - -static int ap_list_beacon_olbc(struct hostapd_iface *iface, struct ap_info *ap) -{ - int i; - - if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G || - ap->phytype != ieee80211_phytype_pbcc_dot11_g || - iface->conf->channel != ap->channel) - return 0; - - if (ap->erp != -1 && (ap->erp & ERP_INFO_NON_ERP_PRESENT)) - return 1; - - for (i = 0; i < WLAN_SUPP_RATES_MAX; i++) { - int rate = (ap->supported_rates[i] & 0x7f) * 5; - if (rate == 60 || rate == 90 || rate > 110) - return 0; - } - - return 1; -} - - -#ifdef CONFIG_IEEE80211N -static int ap_list_beacon_olbc_ht(struct hostapd_iface *iface, - struct ap_info *ap) -{ - return !ap->ht_support; -} -#endif /* CONFIG_IEEE80211N */ - - -struct ap_info * ap_get_ap(struct hostapd_iface *iface, u8 *ap) -{ - struct ap_info *s; - - s = iface->ap_hash[STA_HASH(ap)]; - while (s != NULL && os_memcmp(s->addr, ap, ETH_ALEN) != 0) - s = s->hnext; - return s; -} - - -static void ap_ap_list_add(struct hostapd_iface *iface, struct ap_info *ap) -{ - if (iface->ap_list) { - ap->prev = iface->ap_list->prev; - iface->ap_list->prev = ap; - } else - ap->prev = ap; - ap->next = iface->ap_list; - iface->ap_list = ap; -} - - -static void ap_ap_list_del(struct hostapd_iface *iface, struct ap_info *ap) -{ - if (iface->ap_list == ap) - iface->ap_list = ap->next; - else - ap->prev->next = ap->next; - - if (ap->next) - ap->next->prev = ap->prev; - else if (iface->ap_list) - iface->ap_list->prev = ap->prev; -} - - -static void ap_ap_iter_list_add(struct hostapd_iface *iface, - struct ap_info *ap) -{ - if (iface->ap_iter_list) { - ap->iter_prev = iface->ap_iter_list->iter_prev; - iface->ap_iter_list->iter_prev = ap; - } else - ap->iter_prev = ap; - ap->iter_next = iface->ap_iter_list; - iface->ap_iter_list = ap; -} - - -static void ap_ap_iter_list_del(struct hostapd_iface *iface, - struct ap_info *ap) -{ - if (iface->ap_iter_list == ap) - iface->ap_iter_list = ap->iter_next; - else - ap->iter_prev->iter_next = ap->iter_next; - - if (ap->iter_next) - ap->iter_next->iter_prev = ap->iter_prev; - else if (iface->ap_iter_list) - iface->ap_iter_list->iter_prev = ap->iter_prev; -} - - -static void ap_ap_hash_add(struct hostapd_iface *iface, struct ap_info *ap) -{ - ap->hnext = iface->ap_hash[STA_HASH(ap->addr)]; - iface->ap_hash[STA_HASH(ap->addr)] = ap; -} - - -static void ap_ap_hash_del(struct hostapd_iface *iface, struct ap_info *ap) -{ - struct ap_info *s; - - s = iface->ap_hash[STA_HASH(ap->addr)]; - if (s == NULL) return; - if (os_memcmp(s->addr, ap->addr, ETH_ALEN) == 0) { - iface->ap_hash[STA_HASH(ap->addr)] = s->hnext; - return; - } - - while (s->hnext != NULL && - os_memcmp(s->hnext->addr, ap->addr, ETH_ALEN) != 0) - s = s->hnext; - if (s->hnext != NULL) - s->hnext = s->hnext->hnext; - else - printf("AP: could not remove AP " MACSTR " from hash table\n", - MAC2STR(ap->addr)); -} - - -static void ap_free_ap(struct hostapd_iface *iface, struct ap_info *ap) -{ - ap_ap_hash_del(iface, ap); - ap_ap_list_del(iface, ap); - ap_ap_iter_list_del(iface, ap); - - iface->num_ap--; - os_free(ap); -} - - -static void hostapd_free_aps(struct hostapd_iface *iface) -{ - struct ap_info *ap, *prev; - - ap = iface->ap_list; - - while (ap) { - prev = ap; - ap = ap->next; - ap_free_ap(iface, prev); - } - - iface->ap_list = NULL; -} - - -int ap_ap_for_each(struct hostapd_iface *iface, - int (*func)(struct ap_info *s, void *data), void *data) -{ - struct ap_info *s; - int ret = 0; - - s = iface->ap_list; - - while (s) { - ret = func(s, data); - if (ret) - break; - s = s->next; - } - - return ret; -} - - -static struct ap_info * ap_ap_add(struct hostapd_iface *iface, u8 *addr) -{ - struct ap_info *ap; - - ap = os_zalloc(sizeof(struct ap_info)); - if (ap == NULL) - return NULL; - - /* initialize AP info data */ - os_memcpy(ap->addr, addr, ETH_ALEN); - ap_ap_list_add(iface, ap); - iface->num_ap++; - ap_ap_hash_add(iface, ap); - ap_ap_iter_list_add(iface, ap); - - if (iface->num_ap > iface->conf->ap_table_max_size && ap != ap->prev) { - wpa_printf(MSG_DEBUG, "Removing the least recently used AP " - MACSTR " from AP table", MAC2STR(ap->prev->addr)); - if (iface->conf->passive_scan_interval > 0) - ap_list_expired_ap(iface, ap->prev); - ap_free_ap(iface, ap->prev); - } - - return ap; -} - - -void ap_list_process_beacon(struct hostapd_iface *iface, - struct ieee80211_mgmt *mgmt, - struct ieee802_11_elems *elems, - struct hostapd_frame_info *fi) -{ - struct ap_info *ap; - int new_ap = 0; - size_t len; - int set_beacon = 0; - - if (iface->conf->ap_table_max_size < 1) - return; - - ap = ap_get_ap(iface, mgmt->bssid); - if (!ap) { - ap = ap_ap_add(iface, mgmt->bssid); - if (!ap) { - printf("Failed to allocate AP information entry\n"); - return; - } - new_ap = 1; - } - - ap->beacon_int = le_to_host16(mgmt->u.beacon.beacon_int); - ap->capability = le_to_host16(mgmt->u.beacon.capab_info); - - if (elems->ssid) { - len = elems->ssid_len; - if (len >= sizeof(ap->ssid)) - len = sizeof(ap->ssid) - 1; - os_memcpy(ap->ssid, elems->ssid, len); - ap->ssid[len] = '\0'; - ap->ssid_len = len; - } - - os_memset(ap->supported_rates, 0, WLAN_SUPP_RATES_MAX); - len = 0; - if (elems->supp_rates) { - len = elems->supp_rates_len; - if (len > WLAN_SUPP_RATES_MAX) - len = WLAN_SUPP_RATES_MAX; - os_memcpy(ap->supported_rates, elems->supp_rates, len); - } - if (elems->ext_supp_rates) { - int len2; - if (len + elems->ext_supp_rates_len > WLAN_SUPP_RATES_MAX) - len2 = WLAN_SUPP_RATES_MAX - len; - else - len2 = elems->ext_supp_rates_len; - os_memcpy(ap->supported_rates + len, elems->ext_supp_rates, - len2); - } - - ap->wpa = elems->wpa_ie != NULL; - - if (elems->erp_info && elems->erp_info_len == 1) - ap->erp = elems->erp_info[0]; - else - ap->erp = -1; - - if (elems->ds_params && elems->ds_params_len == 1) - ap->channel = elems->ds_params[0]; - else if (fi) - ap->channel = fi->channel; - - if (elems->ht_capabilities) - ap->ht_support = 1; - else - ap->ht_support = 0; - - ap->num_beacons++; - time(&ap->last_beacon); - if (fi) { - ap->phytype = fi->phytype; - ap->ssi_signal = fi->ssi_signal; - ap->datarate = fi->datarate; - } - - if (new_ap) { - if (iface->conf->passive_scan_interval > 0) - ap_list_new_ap(iface, ap); - } else if (ap != iface->ap_list) { - /* move AP entry into the beginning of the list so that the - * oldest entry is always in the end of the list */ - ap_ap_list_del(iface, ap); - ap_ap_list_add(iface, ap); - } - - if (!iface->olbc && - ap_list_beacon_olbc(iface, ap)) { - iface->olbc = 1; - wpa_printf(MSG_DEBUG, "OLBC AP detected: " MACSTR " - enable " - "protection", MAC2STR(ap->addr)); - set_beacon++; - } - -#ifdef CONFIG_IEEE80211N - if (!iface->olbc_ht && ap_list_beacon_olbc_ht(iface, ap)) { - iface->olbc_ht = 1; - hostapd_ht_operation_update(iface); - wpa_printf(MSG_DEBUG, "OLBC HT AP detected: " MACSTR - " - enable protection", MAC2STR(ap->addr)); - set_beacon++; - } -#endif /* CONFIG_IEEE80211N */ - - if (set_beacon) - ieee802_11_set_beacons(iface); -} - - -static void ap_list_timer(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_iface *iface = eloop_ctx; - time_t now; - struct ap_info *ap; - int set_beacon = 0; - - eloop_register_timeout(10, 0, ap_list_timer, iface, NULL); - - if (!iface->ap_list) - return; - - time(&now); - - /* FIX: it looks like jkm-Purina ended up in busy loop in this - * function. Apparently, something can still cause a loop in the AP - * list.. */ - - while (iface->ap_list) { - ap = iface->ap_list->prev; - if (ap->last_beacon + iface->conf->ap_table_expiration_time >= - now) - break; - - if (iface->conf->passive_scan_interval > 0) - ap_list_expired_ap(iface, ap); - ap_free_ap(iface, ap); - } - - if (iface->olbc || iface->olbc_ht) { - int olbc = 0; - int olbc_ht = 0; - - ap = iface->ap_list; - while (ap && (olbc == 0 || olbc_ht == 0)) { - if (ap_list_beacon_olbc(iface, ap)) - olbc = 1; -#ifdef CONFIG_IEEE80211N - if (ap_list_beacon_olbc_ht(iface, ap)) - olbc_ht = 1; -#endif /* CONFIG_IEEE80211N */ - ap = ap->next; - } - if (!olbc && iface->olbc) { - wpa_printf(MSG_DEBUG, "OLBC not detected anymore"); - iface->olbc = 0; - set_beacon++; - } -#ifdef CONFIG_IEEE80211N - if (!olbc_ht && iface->olbc_ht) { - wpa_printf(MSG_DEBUG, "OLBC HT not detected anymore"); - iface->olbc_ht = 0; - hostapd_ht_operation_update(iface); - set_beacon++; - } -#endif /* CONFIG_IEEE80211N */ - } - - if (set_beacon) - ieee802_11_set_beacons(iface); -} - - -int ap_list_init(struct hostapd_iface *iface) -{ - eloop_register_timeout(10, 0, ap_list_timer, iface, NULL); - return 0; -} - - -void ap_list_deinit(struct hostapd_iface *iface) -{ - eloop_cancel_timeout(ap_list_timer, iface, NULL); - hostapd_free_aps(iface); -} - - -int ap_list_reconfig(struct hostapd_iface *iface, - struct hostapd_config *oldconf) -{ - time_t now; - struct ap_info *ap; - - if (iface->conf->ap_table_max_size == oldconf->ap_table_max_size && - iface->conf->ap_table_expiration_time == - oldconf->ap_table_expiration_time) - return 0; - - time(&now); - - while (iface->ap_list) { - ap = iface->ap_list->prev; - if (iface->num_ap <= iface->conf->ap_table_max_size && - ap->last_beacon + iface->conf->ap_table_expiration_time >= - now) - break; - - if (iface->conf->passive_scan_interval > 0) - ap_list_expired_ap(iface, iface->ap_list->prev); - ap_free_ap(iface, iface->ap_list->prev); - } - - return 0; -} diff --git a/contrib/hostapd/hostapd/ap_list.h b/contrib/hostapd/hostapd/ap_list.h deleted file mode 100644 index 93704f8bb6..0000000000 --- a/contrib/hostapd/hostapd/ap_list.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * hostapd / AP table - * Copyright (c) 2002-2003, Jouni Malinen - * Copyright (c) 2003-2004, Instant802 Networks, Inc. - * Copyright (c) 2006, Devicescape Software, Inc. - * Copyright (c) 2007-2008, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef AP_LIST_H -#define AP_LIST_H - -struct ap_info { - /* Note: next/prev pointers are updated whenever a new beacon is - * received because these are used to find the least recently used - * entries. iter_next/iter_prev are updated only when adding new BSSes - * and when removing old ones. These should be used when iterating - * through the table in a manner that allows beacons to be received - * during the iteration. */ - struct ap_info *next; /* next entry in AP list */ - struct ap_info *prev; /* previous entry in AP list */ - struct ap_info *hnext; /* next entry in hash table list */ - struct ap_info *iter_next; /* next entry in AP iteration list */ - struct ap_info *iter_prev; /* previous entry in AP iteration list */ - u8 addr[6]; - u16 beacon_int; - u16 capability; - u8 supported_rates[WLAN_SUPP_RATES_MAX]; - u8 ssid[33]; - size_t ssid_len; - int wpa; - int erp; /* ERP Info or -1 if ERP info element not present */ - - int phytype; /* .11a / .11b / .11g / Atheros Turbo */ - int channel; - int datarate; /* in 100 kbps */ - int ssi_signal; - - int ht_support; - - unsigned int num_beacons; /* number of beacon frames received */ - time_t last_beacon; - - int already_seen; /* whether API call AP-NEW has already fetched - * information about this AP */ -}; - -struct ieee802_11_elems; -struct hostapd_frame_info; - -struct ap_info * ap_get_ap(struct hostapd_iface *iface, u8 *sta); -int ap_ap_for_each(struct hostapd_iface *iface, - int (*func)(struct ap_info *s, void *data), void *data); -void ap_list_process_beacon(struct hostapd_iface *iface, - struct ieee80211_mgmt *mgmt, - struct ieee802_11_elems *elems, - struct hostapd_frame_info *fi); -int ap_list_init(struct hostapd_iface *iface); -void ap_list_deinit(struct hostapd_iface *iface); -int ap_list_reconfig(struct hostapd_iface *iface, - struct hostapd_config *oldconf); - -#endif /* AP_LIST_H */ diff --git a/contrib/hostapd/hostapd/beacon.c b/contrib/hostapd/hostapd/beacon.c deleted file mode 100644 index 1f82d9cb72..0000000000 --- a/contrib/hostapd/hostapd/beacon.c +++ /dev/null @@ -1,467 +0,0 @@ -/* - * hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response - * Copyright (c) 2002-2004, Instant802 Networks, Inc. - * Copyright (c) 2005-2006, Devicescape Software, Inc. - * Copyright (c) 2008, Jouni Malinen - * Copyright (c) 2007-2008, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#ifndef CONFIG_NATIVE_WINDOWS - -#include "hostapd.h" -#include "ieee802_11.h" -#include "wpa.h" -#include "wme.h" -#include "beacon.h" -#include "hw_features.h" -#include "driver.h" -#include "sta_info.h" -#include "wps_hostapd.h" - - -static u8 ieee802_11_erp_info(struct hostapd_data *hapd) -{ - u8 erp = 0; - - if (hapd->iface->current_mode == NULL || - hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G) - return 0; - - switch (hapd->iconf->cts_protection_type) { - case CTS_PROTECTION_FORCE_ENABLED: - erp |= ERP_INFO_NON_ERP_PRESENT | ERP_INFO_USE_PROTECTION; - break; - case CTS_PROTECTION_FORCE_DISABLED: - erp = 0; - break; - case CTS_PROTECTION_AUTOMATIC: - if (hapd->iface->olbc) - erp |= ERP_INFO_USE_PROTECTION; - /* continue */ - case CTS_PROTECTION_AUTOMATIC_NO_OLBC: - if (hapd->iface->num_sta_non_erp > 0) { - erp |= ERP_INFO_NON_ERP_PRESENT | - ERP_INFO_USE_PROTECTION; - } - break; - } - if (hapd->iface->num_sta_no_short_preamble > 0) - erp |= ERP_INFO_BARKER_PREAMBLE_MODE; - - return erp; -} - - -static u8 * hostapd_eid_ds_params(struct hostapd_data *hapd, u8 *eid) -{ - *eid++ = WLAN_EID_DS_PARAMS; - *eid++ = 1; - *eid++ = hapd->iconf->channel; - return eid; -} - - -static u8 * hostapd_eid_erp_info(struct hostapd_data *hapd, u8 *eid) -{ - if (hapd->iface->current_mode == NULL || - hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G) - return eid; - - /* Set NonERP_present and use_protection bits if there - * are any associated NonERP stations. */ - /* TODO: use_protection bit can be set to zero even if - * there are NonERP stations present. This optimization - * might be useful if NonERP stations are "quiet". - * See 802.11g/D6 E-1 for recommended practice. - * In addition, Non ERP present might be set, if AP detects Non ERP - * operation on other APs. */ - - /* Add ERP Information element */ - *eid++ = WLAN_EID_ERP_INFO; - *eid++ = 1; - *eid++ = ieee802_11_erp_info(hapd); - - return eid; -} - - -static u8 * hostapd_eid_country_add(u8 *pos, u8 *end, int chan_spacing, - struct hostapd_channel_data *start, - struct hostapd_channel_data *prev) -{ - if (end - pos < 3) - return pos; - - /* first channel number */ - *pos++ = start->chan; - /* number of channels */ - *pos++ = (prev->chan - start->chan) / chan_spacing + 1; - /* maximum transmit power level */ - *pos++ = start->max_tx_power; - - return pos; -} - - -static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid, - int max_len) -{ - u8 *pos = eid; - u8 *end = eid + max_len; - int i; - struct hostapd_hw_modes *mode; - struct hostapd_channel_data *start, *prev; - int chan_spacing = 1; - - if (!hapd->iconf->ieee80211d || max_len < 6 || - hapd->iface->current_mode == NULL) - return eid; - - *pos++ = WLAN_EID_COUNTRY; - pos++; /* length will be set later */ - os_memcpy(pos, hapd->iconf->country, 3); /* e.g., 'US ' */ - pos += 3; - - mode = hapd->iface->current_mode; - if (mode->mode == HOSTAPD_MODE_IEEE80211A) - chan_spacing = 4; - - start = prev = NULL; - for (i = 0; i < mode->num_channels; i++) { - struct hostapd_channel_data *chan = &mode->channels[i]; - if (chan->flag & HOSTAPD_CHAN_DISABLED) - continue; - if (start && prev && - prev->chan + chan_spacing == chan->chan && - start->max_tx_power == chan->max_tx_power) { - prev = chan; - continue; /* can use same entry */ - } - - if (start) { - pos = hostapd_eid_country_add(pos, end, chan_spacing, - start, prev); - start = NULL; - } - - /* Start new group */ - start = prev = chan; - } - - if (start) { - pos = hostapd_eid_country_add(pos, end, chan_spacing, - start, prev); - } - - if ((pos - eid) & 1) { - if (end - pos < 1) - return eid; - *pos++ = 0; /* pad for 16-bit alignment */ - } - - eid[1] = (pos - eid) - 2; - - return pos; -} - - -static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len, - struct sta_info *sta) -{ - const u8 *ie; - size_t ielen; - - ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen); - if (ie == NULL || ielen > len) - return eid; - - os_memcpy(eid, ie, ielen); - return eid + ielen; -} - - -void handle_probe_req(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, - size_t len) -{ - struct ieee80211_mgmt *resp; - struct ieee802_11_elems elems; - char *ssid; - u8 *pos, *epos, *ie; - size_t ssid_len, ie_len; - struct sta_info *sta = NULL; - - ie = mgmt->u.probe_req.variable; - ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)); - - hostapd_wps_probe_req_rx(hapd, mgmt->sa, ie, ie_len); - - if (!hapd->iconf->send_probe_response) - return; - - if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) { - wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR, - MAC2STR(mgmt->sa)); - return; - } - - ssid = NULL; - ssid_len = 0; - - if ((!elems.ssid || !elems.supp_rates)) { - wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request " - "without SSID or supported rates element", - MAC2STR(mgmt->sa)); - return; - } - - if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0) { - wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for " - "broadcast SSID ignored", MAC2STR(mgmt->sa)); - return; - } - - sta = ap_get_sta(hapd, mgmt->sa); - - if (elems.ssid_len == 0 || - (elems.ssid_len == hapd->conf->ssid.ssid_len && - os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) == - 0)) { - ssid = hapd->conf->ssid.ssid; - ssid_len = hapd->conf->ssid.ssid_len; - if (sta) - sta->ssid_probe = &hapd->conf->ssid; - } - - if (!ssid) { - if (!(mgmt->da[0] & 0x01)) { - char ssid_txt[33]; - ieee802_11_print_ssid(ssid_txt, elems.ssid, - elems.ssid_len); - wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR - " for foreign SSID '%s'", - MAC2STR(mgmt->sa), ssid_txt); - } - return; - } - - /* TODO: verify that supp_rates contains at least one matching rate - * with AP configuration */ -#define MAX_PROBERESP_LEN 768 - resp = os_zalloc(MAX_PROBERESP_LEN); - if (resp == NULL) - return; - epos = ((u8 *) resp) + MAX_PROBERESP_LEN; - - resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_PROBE_RESP); - os_memcpy(resp->da, mgmt->sa, ETH_ALEN); - os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN); - - os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN); - resp->u.probe_resp.beacon_int = - host_to_le16(hapd->iconf->beacon_int); - - /* hardware or low-level driver will setup seq_ctrl and timestamp */ - resp->u.probe_resp.capab_info = - host_to_le16(hostapd_own_capab_info(hapd, sta, 1)); - - pos = resp->u.probe_resp.variable; - *pos++ = WLAN_EID_SSID; - *pos++ = ssid_len; - os_memcpy(pos, ssid, ssid_len); - pos += ssid_len; - - /* Supported rates */ - pos = hostapd_eid_supp_rates(hapd, pos); - - /* DS Params */ - pos = hostapd_eid_ds_params(hapd, pos); - - pos = hostapd_eid_country(hapd, pos, epos - pos); - - /* ERP Information element */ - pos = hostapd_eid_erp_info(hapd, pos); - - /* Extended supported rates */ - pos = hostapd_eid_ext_supp_rates(hapd, pos); - - pos = hostapd_eid_wpa(hapd, pos, epos - pos, sta); - - /* Wi-Fi Alliance WMM */ - pos = hostapd_eid_wmm(hapd, pos); - - pos = hostapd_eid_ht_capabilities_info(hapd, pos); - pos = hostapd_eid_ht_operation(hapd, pos); - -#ifdef CONFIG_WPS - if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) { - os_memcpy(pos, hapd->wps_probe_resp_ie, - hapd->wps_probe_resp_ie_len); - pos += hapd->wps_probe_resp_ie_len; - } -#endif /* CONFIG_WPS */ - - if (hostapd_send_mgmt_frame(hapd, resp, pos - (u8 *) resp, 0) < 0) - perror("handle_probe_req: send"); - - os_free(resp); - - wpa_printf(MSG_MSGDUMP, "STA " MACSTR " sent probe request for %s " - "SSID", MAC2STR(mgmt->sa), - elems.ssid_len == 0 ? "broadcast" : "our"); -} - - -void ieee802_11_set_beacon(struct hostapd_data *hapd) -{ - struct ieee80211_mgmt *head; - u8 *pos, *tail, *tailpos; - int preamble; - u16 capab_info; - size_t head_len, tail_len; - int cts_protection = ((ieee802_11_erp_info(hapd) & - ERP_INFO_USE_PROTECTION) ? 1 : 0); - -#define BEACON_HEAD_BUF_SIZE 256 -#define BEACON_TAIL_BUF_SIZE 512 - head = os_zalloc(BEACON_HEAD_BUF_SIZE); - tailpos = tail = os_malloc(BEACON_TAIL_BUF_SIZE); - if (head == NULL || tail == NULL) { - wpa_printf(MSG_ERROR, "Failed to set beacon data"); - os_free(head); - os_free(tail); - return; - } - - head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_BEACON); - head->duration = host_to_le16(0); - os_memset(head->da, 0xff, ETH_ALEN); - - os_memcpy(head->sa, hapd->own_addr, ETH_ALEN); - os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN); - head->u.beacon.beacon_int = - host_to_le16(hapd->iconf->beacon_int); - - /* hardware or low-level driver will setup seq_ctrl and timestamp */ - capab_info = hostapd_own_capab_info(hapd, NULL, 0); - head->u.beacon.capab_info = host_to_le16(capab_info); - pos = &head->u.beacon.variable[0]; - - /* SSID */ - *pos++ = WLAN_EID_SSID; - if (hapd->conf->ignore_broadcast_ssid == 2) { - /* clear the data, but keep the correct length of the SSID */ - *pos++ = hapd->conf->ssid.ssid_len; - os_memset(pos, 0, hapd->conf->ssid.ssid_len); - pos += hapd->conf->ssid.ssid_len; - } else if (hapd->conf->ignore_broadcast_ssid) { - *pos++ = 0; /* empty SSID */ - } else { - *pos++ = hapd->conf->ssid.ssid_len; - os_memcpy(pos, hapd->conf->ssid.ssid, - hapd->conf->ssid.ssid_len); - pos += hapd->conf->ssid.ssid_len; - } - - /* Supported rates */ - pos = hostapd_eid_supp_rates(hapd, pos); - - /* DS Params */ - pos = hostapd_eid_ds_params(hapd, pos); - - head_len = pos - (u8 *) head; - - tailpos = hostapd_eid_country(hapd, tailpos, - tail + BEACON_TAIL_BUF_SIZE - tailpos); - - /* ERP Information element */ - tailpos = hostapd_eid_erp_info(hapd, tailpos); - - /* Extended supported rates */ - tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos); - - tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - - tailpos, NULL); - - /* Wi-Fi Alliance WMM */ - tailpos = hostapd_eid_wmm(hapd, tailpos); - -#ifdef CONFIG_IEEE80211N - if (hapd->iconf->ieee80211n) { - u8 *ht_capab, *ht_oper; - ht_capab = tailpos; - tailpos = hostapd_eid_ht_capabilities_info(hapd, tailpos); - - ht_oper = tailpos; - tailpos = hostapd_eid_ht_operation(hapd, tailpos); - - if (tailpos > ht_oper && ht_oper > ht_capab && - hostapd_set_ht_params(hapd->conf->iface, hapd, - ht_capab + 2, ht_capab[1], - ht_oper + 2, ht_oper[1])) { - wpa_printf(MSG_ERROR, "Could not set HT capabilities " - "for kernel driver"); - } - } -#endif /* CONFIG_IEEE80211N */ - -#ifdef CONFIG_WPS - if (hapd->conf->wps_state && hapd->wps_beacon_ie) { - os_memcpy(tailpos, hapd->wps_beacon_ie, - hapd->wps_beacon_ie_len); - tailpos += hapd->wps_beacon_ie_len; - } -#endif /* CONFIG_WPS */ - - tail_len = tailpos > tail ? tailpos - tail : 0; - - if (hostapd_set_beacon(hapd->conf->iface, hapd, (u8 *) head, head_len, - tail, tail_len)) - wpa_printf(MSG_ERROR, "Failed to set beacon head/tail"); - - os_free(tail); - os_free(head); - - if (hostapd_set_cts_protect(hapd, cts_protection)) - wpa_printf(MSG_ERROR, "Failed to set CTS protect in kernel " - "driver"); - - if (hapd->iface->current_mode && - hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && - hostapd_set_short_slot_time(hapd, - hapd->iface->num_sta_no_short_slot_time - > 0 ? 0 : 1)) - wpa_printf(MSG_ERROR, "Failed to set Short Slot Time option " - "in kernel driver"); - - if (hapd->iface->num_sta_no_short_preamble == 0 && - hapd->iconf->preamble == SHORT_PREAMBLE) - preamble = SHORT_PREAMBLE; - else - preamble = LONG_PREAMBLE; - if (hostapd_set_preamble(hapd, preamble)) - wpa_printf(MSG_ERROR, "Could not set preamble for kernel " - "driver"); -} - - -void ieee802_11_set_beacons(struct hostapd_iface *iface) -{ - size_t i; - for (i = 0; i < iface->num_bss; i++) - ieee802_11_set_beacon(iface->bss[i]); -} - -#endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/contrib/hostapd/hostapd/beacon.h b/contrib/hostapd/hostapd/beacon.h deleted file mode 100644 index 18e0da2e89..0000000000 --- a/contrib/hostapd/hostapd/beacon.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response - * Copyright (c) 2002-2004, Instant802 Networks, Inc. - * Copyright (c) 2005-2006, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef BEACON_H -#define BEACON_H - -void handle_probe_req(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, - size_t len); -void ieee802_11_set_beacon(struct hostapd_data *hapd); -void ieee802_11_set_beacons(struct hostapd_iface *iface); - -#endif /* BEACON_H */ diff --git a/contrib/hostapd/hostapd/config.c b/contrib/hostapd/hostapd/config.c deleted file mode 100644 index 692b1a412e..0000000000 --- a/contrib/hostapd/hostapd/config.c +++ /dev/null @@ -1,2622 +0,0 @@ -/* - * hostapd / Configuration file - * Copyright (c) 2003-2008, Jouni Malinen - * Copyright (c) 2007-2008, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#ifndef CONFIG_NATIVE_WINDOWS -#include -#endif /* CONFIG_NATIVE_WINDOWS */ - -#include "hostapd.h" -#include "driver.h" -#include "sha1.h" -#include "eap_server/eap.h" -#include "radius/radius_client.h" -#include "wpa_common.h" -#include "wpa.h" -#include "uuid.h" -#include "eap_common/eap_wsc_common.h" - - -#define MAX_STA_COUNT 2007 - -extern struct wpa_driver_ops *hostapd_drivers[]; - - -static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss, - const char *fname) -{ - FILE *f; - char buf[128], *pos, *pos2; - int line = 0, vlan_id; - struct hostapd_vlan *vlan; - - f = fopen(fname, "r"); - if (!f) { - wpa_printf(MSG_ERROR, "VLAN file '%s' not readable.", fname); - return -1; - } - - while (fgets(buf, sizeof(buf), f)) { - line++; - - if (buf[0] == '#') - continue; - pos = buf; - while (*pos != '\0') { - if (*pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } - if (buf[0] == '\0') - continue; - - if (buf[0] == '*') { - vlan_id = VLAN_ID_WILDCARD; - pos = buf + 1; - } else { - vlan_id = strtol(buf, &pos, 10); - if (buf == pos || vlan_id < 1 || - vlan_id > MAX_VLAN_ID) { - wpa_printf(MSG_ERROR, "Invalid VLAN ID at " - "line %d in '%s'", line, fname); - fclose(f); - return -1; - } - } - - while (*pos == ' ' || *pos == '\t') - pos++; - pos2 = pos; - while (*pos2 != ' ' && *pos2 != '\t' && *pos2 != '\0') - pos2++; - *pos2 = '\0'; - if (*pos == '\0' || os_strlen(pos) > IFNAMSIZ) { - wpa_printf(MSG_ERROR, "Invalid VLAN ifname at line %d " - "in '%s'", line, fname); - fclose(f); - return -1; - } - - vlan = os_malloc(sizeof(*vlan)); - if (vlan == NULL) { - wpa_printf(MSG_ERROR, "Out of memory while reading " - "VLAN interfaces from '%s'", fname); - fclose(f); - return -1; - } - - os_memset(vlan, 0, sizeof(*vlan)); - vlan->vlan_id = vlan_id; - os_strlcpy(vlan->ifname, pos, sizeof(vlan->ifname)); - if (bss->vlan_tail) - bss->vlan_tail->next = vlan; - else - bss->vlan = vlan; - bss->vlan_tail = vlan; - } - - fclose(f); - - return 0; -} - - -static void hostapd_config_free_vlan(struct hostapd_bss_config *bss) -{ - struct hostapd_vlan *vlan, *prev; - - vlan = bss->vlan; - prev = NULL; - while (vlan) { - prev = vlan; - vlan = vlan->next; - os_free(prev); - } - - bss->vlan = NULL; -} - - -/* convert floats with one decimal place to value*10 int, i.e., - * "1.5" will return 15 */ -static int hostapd_config_read_int10(const char *value) -{ - int i, d; - char *pos; - - i = atoi(value); - pos = os_strchr(value, '.'); - d = 0; - if (pos) { - pos++; - if (*pos >= '0' && *pos <= '9') - d = *pos - '0'; - } - - return i * 10 + d; -} - - -static void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) -{ - bss->logger_syslog_level = HOSTAPD_LEVEL_INFO; - bss->logger_stdout_level = HOSTAPD_LEVEL_INFO; - bss->logger_syslog = (unsigned int) -1; - bss->logger_stdout = (unsigned int) -1; - - bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED; - - bss->wep_rekeying_period = 300; - /* use key0 in individual key and key1 in broadcast key */ - bss->broadcast_key_idx_min = 1; - bss->broadcast_key_idx_max = 2; - bss->eap_reauth_period = 3600; - - bss->wpa_group_rekey = 600; - bss->wpa_gmk_rekey = 86400; - bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK; - bss->wpa_pairwise = WPA_CIPHER_TKIP; - bss->wpa_group = WPA_CIPHER_TKIP; - bss->rsn_pairwise = 0; - - bss->max_num_sta = MAX_STA_COUNT; - - bss->dtim_period = 2; - - bss->radius_server_auth_port = 1812; - bss->ap_max_inactivity = AP_MAX_INACTIVITY; - bss->eapol_version = EAPOL_VERSION; - - bss->max_listen_interval = 65535; - -#ifdef CONFIG_IEEE80211W - bss->assoc_sa_query_max_timeout = 1000; - bss->assoc_sa_query_retry_timeout = 201; -#endif /* CONFIG_IEEE80211W */ -#ifdef EAP_FAST - /* both anonymous and authenticated provisioning */ - bss->eap_fast_prov = 3; - bss->pac_key_lifetime = 7 * 24 * 60 * 60; - bss->pac_key_refresh_time = 1 * 24 * 60 * 60; -#endif /* EAP_FAST */ -} - - -static struct hostapd_config * hostapd_config_defaults(void) -{ - struct hostapd_config *conf; - struct hostapd_bss_config *bss; - int i; - const int aCWmin = 4, aCWmax = 10; - const struct hostapd_wmm_ac_params ac_bk = - { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */ - const struct hostapd_wmm_ac_params ac_be = - { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */ - const struct hostapd_wmm_ac_params ac_vi = /* video traffic */ - { aCWmin - 1, aCWmin, 2, 3000 / 32, 1 }; - const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */ - { aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 1 }; - - conf = os_zalloc(sizeof(*conf)); - bss = os_zalloc(sizeof(*bss)); - if (conf == NULL || bss == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate memory for " - "configuration data."); - os_free(conf); - os_free(bss); - return NULL; - } - - /* set default driver based on configuration */ - conf->driver = hostapd_drivers[0]; - if (conf->driver == NULL) { - wpa_printf(MSG_ERROR, "No driver wrappers registered!"); - os_free(conf); - os_free(bss); - return NULL; - } - - bss->radius = os_zalloc(sizeof(*bss->radius)); - if (bss->radius == NULL) { - os_free(conf); - os_free(bss); - return NULL; - } - - hostapd_config_defaults_bss(bss); - - conf->num_bss = 1; - conf->bss = bss; - - conf->beacon_int = 100; - conf->rts_threshold = -1; /* use driver default: 2347 */ - conf->fragm_threshold = -1; /* user driver default: 2346 */ - conf->send_probe_response = 1; - conf->bridge_packets = INTERNAL_BRIDGE_DO_NOT_CONTROL; - - for (i = 0; i < NUM_TX_QUEUES; i++) - conf->tx_queue[i].aifs = -1; /* use hw default */ - - conf->wmm_ac_params[0] = ac_be; - conf->wmm_ac_params[1] = ac_bk; - conf->wmm_ac_params[2] = ac_vi; - conf->wmm_ac_params[3] = ac_vo; - -#ifdef CONFIG_IEEE80211N - conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED; -#endif /* CONFIG_IEEE80211N */ - - return conf; -} - - -int hostapd_mac_comp(const void *a, const void *b) -{ - return os_memcmp(a, b, sizeof(macaddr)); -} - - -int hostapd_mac_comp_empty(const void *a) -{ - macaddr empty = { 0 }; - return os_memcmp(a, empty, sizeof(macaddr)); -} - - -static int hostapd_acl_comp(const void *a, const void *b) -{ - const struct mac_acl_entry *aa = a; - const struct mac_acl_entry *bb = b; - return os_memcmp(aa->addr, bb->addr, sizeof(macaddr)); -} - - -static int hostapd_config_read_maclist(const char *fname, - struct mac_acl_entry **acl, int *num) -{ - FILE *f; - char buf[128], *pos; - int line = 0; - u8 addr[ETH_ALEN]; - struct mac_acl_entry *newacl; - int vlan_id; - - if (!fname) - return 0; - - f = fopen(fname, "r"); - if (!f) { - wpa_printf(MSG_ERROR, "MAC list file '%s' not found.", fname); - return -1; - } - - while (fgets(buf, sizeof(buf), f)) { - line++; - - if (buf[0] == '#') - continue; - pos = buf; - while (*pos != '\0') { - if (*pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } - if (buf[0] == '\0') - continue; - - if (hwaddr_aton(buf, addr)) { - wpa_printf(MSG_ERROR, "Invalid MAC address '%s' at " - "line %d in '%s'", buf, line, fname); - fclose(f); - return -1; - } - - vlan_id = 0; - pos = buf; - while (*pos != '\0' && *pos != ' ' && *pos != '\t') - pos++; - while (*pos == ' ' || *pos == '\t') - pos++; - if (*pos != '\0') - vlan_id = atoi(pos); - - newacl = os_realloc(*acl, (*num + 1) * sizeof(**acl)); - if (newacl == NULL) { - wpa_printf(MSG_ERROR, "MAC list reallocation failed"); - fclose(f); - return -1; - } - - *acl = newacl; - os_memcpy((*acl)[*num].addr, addr, ETH_ALEN); - (*acl)[*num].vlan_id = vlan_id; - (*num)++; - } - - fclose(f); - - qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp); - - return 0; -} - - -static int hostapd_config_read_wpa_psk(const char *fname, - struct hostapd_ssid *ssid) -{ - FILE *f; - char buf[128], *pos; - int line = 0, ret = 0, len, ok; - u8 addr[ETH_ALEN]; - struct hostapd_wpa_psk *psk; - - if (!fname) - return 0; - - f = fopen(fname, "r"); - if (!f) { - wpa_printf(MSG_ERROR, "WPA PSK file '%s' not found.", fname); - return -1; - } - - while (fgets(buf, sizeof(buf), f)) { - line++; - - if (buf[0] == '#') - continue; - pos = buf; - while (*pos != '\0') { - if (*pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } - if (buf[0] == '\0') - continue; - - if (hwaddr_aton(buf, addr)) { - wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on " - "line %d in '%s'", buf, line, fname); - ret = -1; - break; - } - - psk = os_zalloc(sizeof(*psk)); - if (psk == NULL) { - wpa_printf(MSG_ERROR, "WPA PSK allocation failed"); - ret = -1; - break; - } - if (is_zero_ether_addr(addr)) - psk->group = 1; - else - os_memcpy(psk->addr, addr, ETH_ALEN); - - pos = buf + 17; - if (*pos == '\0') { - wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'", - line, fname); - os_free(psk); - ret = -1; - break; - } - pos++; - - ok = 0; - len = os_strlen(pos); - if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0) - ok = 1; - else if (len >= 8 && len < 64) { - pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len, - 4096, psk->psk, PMK_LEN); - ok = 1; - } - if (!ok) { - wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in " - "'%s'", pos, line, fname); - os_free(psk); - ret = -1; - break; - } - - psk->next = ssid->wpa_psk; - ssid->wpa_psk = psk; - } - - fclose(f); - - return ret; -} - - -int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf) -{ - struct hostapd_ssid *ssid = &conf->ssid; - - if (ssid->wpa_passphrase != NULL) { - if (ssid->wpa_psk != NULL) { - wpa_printf(MSG_ERROR, "Warning: both WPA PSK and " - "passphrase set. Using passphrase."); - os_free(ssid->wpa_psk); - } - ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk)); - if (ssid->wpa_psk == NULL) { - wpa_printf(MSG_ERROR, "Unable to alloc space for PSK"); - return -1; - } - wpa_hexdump_ascii(MSG_DEBUG, "SSID", - (u8 *) ssid->ssid, ssid->ssid_len); - wpa_hexdump_ascii(MSG_DEBUG, "PSK (ASCII passphrase)", - (u8 *) ssid->wpa_passphrase, - os_strlen(ssid->wpa_passphrase)); - pbkdf2_sha1(ssid->wpa_passphrase, - ssid->ssid, ssid->ssid_len, - 4096, ssid->wpa_psk->psk, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "PSK (from passphrase)", - ssid->wpa_psk->psk, PMK_LEN); - ssid->wpa_psk->group = 1; - } - - if (ssid->wpa_psk_file) { - if (hostapd_config_read_wpa_psk(ssid->wpa_psk_file, - &conf->ssid)) - return -1; - } - - return 0; -} - - -#ifdef EAP_SERVER -static int hostapd_config_read_eap_user(const char *fname, - struct hostapd_bss_config *conf) -{ - FILE *f; - char buf[512], *pos, *start, *pos2; - int line = 0, ret = 0, num_methods; - struct hostapd_eap_user *user, *tail = NULL; - - if (!fname) - return 0; - - f = fopen(fname, "r"); - if (!f) { - wpa_printf(MSG_ERROR, "EAP user file '%s' not found.", fname); - return -1; - } - - /* Lines: "user" METHOD,METHOD2 "password" (password optional) */ - while (fgets(buf, sizeof(buf), f)) { - line++; - - if (buf[0] == '#') - continue; - pos = buf; - while (*pos != '\0') { - if (*pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } - if (buf[0] == '\0') - continue; - - user = NULL; - - if (buf[0] != '"' && buf[0] != '*') { - wpa_printf(MSG_ERROR, "Invalid EAP identity (no \" in " - "start) on line %d in '%s'", line, fname); - goto failed; - } - - user = os_zalloc(sizeof(*user)); - if (user == NULL) { - wpa_printf(MSG_ERROR, "EAP user allocation failed"); - goto failed; - } - user->force_version = -1; - - if (buf[0] == '*') { - pos = buf; - } else { - pos = buf + 1; - start = pos; - while (*pos != '"' && *pos != '\0') - pos++; - if (*pos == '\0') { - wpa_printf(MSG_ERROR, "Invalid EAP identity " - "(no \" in end) on line %d in '%s'", - line, fname); - goto failed; - } - - user->identity = os_malloc(pos - start); - if (user->identity == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate " - "memory for EAP identity"); - goto failed; - } - os_memcpy(user->identity, start, pos - start); - user->identity_len = pos - start; - - if (pos[0] == '"' && pos[1] == '*') { - user->wildcard_prefix = 1; - pos++; - } - } - pos++; - while (*pos == ' ' || *pos == '\t') - pos++; - - if (*pos == '\0') { - wpa_printf(MSG_ERROR, "No EAP method on line %d in " - "'%s'", line, fname); - goto failed; - } - - start = pos; - while (*pos != ' ' && *pos != '\t' && *pos != '\0') - pos++; - if (*pos == '\0') { - pos = NULL; - } else { - *pos = '\0'; - pos++; - } - num_methods = 0; - while (*start) { - char *pos3 = os_strchr(start, ','); - if (pos3) { - *pos3++ = '\0'; - } - user->methods[num_methods].method = - eap_server_get_type( - start, - &user->methods[num_methods].vendor); - if (user->methods[num_methods].vendor == - EAP_VENDOR_IETF && - user->methods[num_methods].method == EAP_TYPE_NONE) - { - if (os_strcmp(start, "TTLS-PAP") == 0) { - user->ttls_auth |= EAP_TTLS_AUTH_PAP; - goto skip_eap; - } - if (os_strcmp(start, "TTLS-CHAP") == 0) { - user->ttls_auth |= EAP_TTLS_AUTH_CHAP; - goto skip_eap; - } - if (os_strcmp(start, "TTLS-MSCHAP") == 0) { - user->ttls_auth |= - EAP_TTLS_AUTH_MSCHAP; - goto skip_eap; - } - if (os_strcmp(start, "TTLS-MSCHAPV2") == 0) { - user->ttls_auth |= - EAP_TTLS_AUTH_MSCHAPV2; - goto skip_eap; - } - wpa_printf(MSG_ERROR, "Unsupported EAP type " - "'%s' on line %d in '%s'", - start, line, fname); - goto failed; - } - - num_methods++; - if (num_methods >= EAP_USER_MAX_METHODS) - break; - skip_eap: - if (pos3 == NULL) - break; - start = pos3; - } - if (num_methods == 0 && user->ttls_auth == 0) { - wpa_printf(MSG_ERROR, "No EAP types configured on " - "line %d in '%s'", line, fname); - goto failed; - } - - if (pos == NULL) - goto done; - - while (*pos == ' ' || *pos == '\t') - pos++; - if (*pos == '\0') - goto done; - - if (os_strncmp(pos, "[ver=0]", 7) == 0) { - user->force_version = 0; - goto done; - } - - if (os_strncmp(pos, "[ver=1]", 7) == 0) { - user->force_version = 1; - goto done; - } - - if (os_strncmp(pos, "[2]", 3) == 0) { - user->phase2 = 1; - goto done; - } - - if (*pos == '"') { - pos++; - start = pos; - while (*pos != '"' && *pos != '\0') - pos++; - if (*pos == '\0') { - wpa_printf(MSG_ERROR, "Invalid EAP password " - "(no \" in end) on line %d in '%s'", - line, fname); - goto failed; - } - - user->password = os_malloc(pos - start); - if (user->password == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate " - "memory for EAP password"); - goto failed; - } - os_memcpy(user->password, start, pos - start); - user->password_len = pos - start; - - pos++; - } else if (os_strncmp(pos, "hash:", 5) == 0) { - pos += 5; - pos2 = pos; - while (*pos2 != '\0' && *pos2 != ' ' && - *pos2 != '\t' && *pos2 != '#') - pos2++; - if (pos2 - pos != 32) { - wpa_printf(MSG_ERROR, "Invalid password hash " - "on line %d in '%s'", line, fname); - goto failed; - } - user->password = os_malloc(16); - if (user->password == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate " - "memory for EAP password hash"); - goto failed; - } - if (hexstr2bin(pos, user->password, 16) < 0) { - wpa_printf(MSG_ERROR, "Invalid hash password " - "on line %d in '%s'", line, fname); - goto failed; - } - user->password_len = 16; - user->password_hash = 1; - pos = pos2; - } else { - pos2 = pos; - while (*pos2 != '\0' && *pos2 != ' ' && - *pos2 != '\t' && *pos2 != '#') - pos2++; - if ((pos2 - pos) & 1) { - wpa_printf(MSG_ERROR, "Invalid hex password " - "on line %d in '%s'", line, fname); - goto failed; - } - user->password = os_malloc((pos2 - pos) / 2); - if (user->password == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate " - "memory for EAP password"); - goto failed; - } - if (hexstr2bin(pos, user->password, - (pos2 - pos) / 2) < 0) { - wpa_printf(MSG_ERROR, "Invalid hex password " - "on line %d in '%s'", line, fname); - goto failed; - } - user->password_len = (pos2 - pos) / 2; - pos = pos2; - } - - while (*pos == ' ' || *pos == '\t') - pos++; - if (os_strncmp(pos, "[2]", 3) == 0) { - user->phase2 = 1; - } - - done: - if (tail == NULL) { - tail = conf->eap_user = user; - } else { - tail->next = user; - tail = user; - } - continue; - - failed: - if (user) { - os_free(user->password); - os_free(user->identity); - os_free(user); - } - ret = -1; - break; - } - - fclose(f); - - return ret; -} -#endif /* EAP_SERVER */ - - -static int -hostapd_config_read_radius_addr(struct hostapd_radius_server **server, - int *num_server, const char *val, int def_port, - struct hostapd_radius_server **curr_serv) -{ - struct hostapd_radius_server *nserv; - int ret; - static int server_index = 1; - - nserv = os_realloc(*server, (*num_server + 1) * sizeof(*nserv)); - if (nserv == NULL) - return -1; - - *server = nserv; - nserv = &nserv[*num_server]; - (*num_server)++; - (*curr_serv) = nserv; - - os_memset(nserv, 0, sizeof(*nserv)); - nserv->port = def_port; - ret = hostapd_parse_ip_addr(val, &nserv->addr); - nserv->index = server_index++; - - return ret; -} - - -static int hostapd_config_parse_key_mgmt(int line, const char *value) -{ - int val = 0, last; - char *start, *end, *buf; - - buf = os_strdup(value); - if (buf == NULL) - return -1; - start = buf; - - while (*start != '\0') { - while (*start == ' ' || *start == '\t') - start++; - if (*start == '\0') - break; - end = start; - while (*end != ' ' && *end != '\t' && *end != '\0') - end++; - last = *end == '\0'; - *end = '\0'; - if (os_strcmp(start, "WPA-PSK") == 0) - val |= WPA_KEY_MGMT_PSK; - else if (os_strcmp(start, "WPA-EAP") == 0) - val |= WPA_KEY_MGMT_IEEE8021X; -#ifdef CONFIG_IEEE80211R - else if (os_strcmp(start, "FT-PSK") == 0) - val |= WPA_KEY_MGMT_FT_PSK; - else if (os_strcmp(start, "FT-EAP") == 0) - val |= WPA_KEY_MGMT_FT_IEEE8021X; -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - else if (os_strcmp(start, "WPA-PSK-SHA256") == 0) - val |= WPA_KEY_MGMT_PSK_SHA256; - else if (os_strcmp(start, "WPA-EAP-SHA256") == 0) - val |= WPA_KEY_MGMT_IEEE8021X_SHA256; -#endif /* CONFIG_IEEE80211W */ - else { - wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", - line, start); - os_free(buf); - return -1; - } - - if (last) - break; - start = end + 1; - } - - os_free(buf); - if (val == 0) { - wpa_printf(MSG_ERROR, "Line %d: no key_mgmt values " - "configured.", line); - return -1; - } - - return val; -} - - -static int hostapd_config_parse_cipher(int line, const char *value) -{ - int val = 0, last; - char *start, *end, *buf; - - buf = os_strdup(value); - if (buf == NULL) - return -1; - start = buf; - - while (*start != '\0') { - while (*start == ' ' || *start == '\t') - start++; - if (*start == '\0') - break; - end = start; - while (*end != ' ' && *end != '\t' && *end != '\0') - end++; - last = *end == '\0'; - *end = '\0'; - if (os_strcmp(start, "CCMP") == 0) - val |= WPA_CIPHER_CCMP; - else if (os_strcmp(start, "TKIP") == 0) - val |= WPA_CIPHER_TKIP; - else if (os_strcmp(start, "WEP104") == 0) - val |= WPA_CIPHER_WEP104; - else if (os_strcmp(start, "WEP40") == 0) - val |= WPA_CIPHER_WEP40; - else if (os_strcmp(start, "NONE") == 0) - val |= WPA_CIPHER_NONE; - else { - wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.", - line, start); - os_free(buf); - return -1; - } - - if (last) - break; - start = end + 1; - } - os_free(buf); - - if (val == 0) { - wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.", - line); - return -1; - } - return val; -} - - -static int hostapd_config_check_bss(struct hostapd_bss_config *bss, - struct hostapd_config *conf) -{ - if (bss->ieee802_1x && !bss->eap_server && - !bss->radius->auth_servers) { - wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no " - "EAP authenticator configured)."); - return -1; - } - - if (bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) && - bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL && - bss->ssid.wpa_psk_file == NULL) { - wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase " - "is not configured."); - return -1; - } - - if (hostapd_mac_comp_empty(bss->bssid) != 0) { - size_t i; - - for (i = 0; i < conf->num_bss; i++) { - if ((&conf->bss[i] != bss) && - (hostapd_mac_comp(conf->bss[i].bssid, - bss->bssid) == 0)) { - wpa_printf(MSG_ERROR, "Duplicate BSSID " MACSTR - " on interface '%s' and '%s'.", - MAC2STR(bss->bssid), - conf->bss[i].iface, bss->iface); - return -1; - } - } - } - -#ifdef CONFIG_IEEE80211R - if ((bss->wpa_key_mgmt & - (WPA_KEY_MGMT_FT_PSK | WPA_KEY_MGMT_FT_IEEE8021X)) && - (bss->nas_identifier == NULL || - os_strlen(bss->nas_identifier) < 1 || - os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) { - wpa_printf(MSG_ERROR, "FT (IEEE 802.11r) requires " - "nas_identifier to be configured as a 1..48 octet " - "string"); - return -1; - } -#endif /* CONFIG_IEEE80211R */ - -#ifdef CONFIG_IEEE80211N - if (conf->ieee80211n && bss->wpa && - !(bss->wpa_pairwise & WPA_CIPHER_CCMP) && - !(bss->rsn_pairwise & WPA_CIPHER_CCMP)) { - wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 " - "requires CCMP to be enabled"); - return -1; - } -#endif /* CONFIG_IEEE80211N */ - - return 0; -} - - -static int hostapd_config_check(struct hostapd_config *conf) -{ - size_t i; - - if (conf->ieee80211d && (!conf->country[0] || !conf->country[1])) { - wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11d without " - "setting the country_code"); - return -1; - } - - for (i = 0; i < conf->num_bss; i++) { - if (hostapd_config_check_bss(&conf->bss[i], conf)) - return -1; - } - - return 0; -} - - -static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx, - char *val) -{ - size_t len = os_strlen(val); - - if (keyidx < 0 || keyidx > 3 || wep->key[keyidx] != NULL) - return -1; - - if (val[0] == '"') { - if (len < 2 || val[len - 1] != '"') - return -1; - len -= 2; - wep->key[keyidx] = os_malloc(len); - if (wep->key[keyidx] == NULL) - return -1; - os_memcpy(wep->key[keyidx], val + 1, len); - wep->len[keyidx] = len; - } else { - if (len & 1) - return -1; - len /= 2; - wep->key[keyidx] = os_malloc(len); - if (wep->key[keyidx] == NULL) - return -1; - wep->len[keyidx] = len; - if (hexstr2bin(val, wep->key[keyidx], len) < 0) - return -1; - } - - wep->keys_set++; - - return 0; -} - - -static int hostapd_parse_rates(int **rate_list, char *val) -{ - int *list; - int count; - char *pos, *end; - - os_free(*rate_list); - *rate_list = NULL; - - pos = val; - count = 0; - while (*pos != '\0') { - if (*pos == ' ') - count++; - pos++; - } - - list = os_malloc(sizeof(int) * (count + 2)); - if (list == NULL) - return -1; - pos = val; - count = 0; - while (*pos != '\0') { - end = os_strchr(pos, ' '); - if (end) - *end = '\0'; - - list[count++] = atoi(pos); - if (!end) - break; - pos = end + 1; - } - list[count] = -1; - - *rate_list = list; - return 0; -} - - -static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname) -{ - struct hostapd_bss_config *bss; - - if (*ifname == '\0') - return -1; - - bss = os_realloc(conf->bss, (conf->num_bss + 1) * - sizeof(struct hostapd_bss_config)); - if (bss == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate memory for " - "multi-BSS entry"); - return -1; - } - conf->bss = bss; - - bss = &(conf->bss[conf->num_bss]); - os_memset(bss, 0, sizeof(*bss)); - bss->radius = os_zalloc(sizeof(*bss->radius)); - if (bss->radius == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate memory for " - "multi-BSS RADIUS data"); - return -1; - } - - conf->num_bss++; - conf->last_bss = bss; - - hostapd_config_defaults_bss(bss); - os_strlcpy(bss->iface, ifname, sizeof(bss->iface)); - os_memcpy(bss->ssid.vlan, bss->iface, IFNAMSIZ + 1); - - return 0; -} - - -static int valid_cw(int cw) -{ - return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 || - cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023); -} - - -enum { - IEEE80211_TX_QUEUE_DATA0 = 0, /* used for EDCA AC_VO data */ - IEEE80211_TX_QUEUE_DATA1 = 1, /* used for EDCA AC_VI data */ - IEEE80211_TX_QUEUE_DATA2 = 2, /* used for EDCA AC_BE data */ - IEEE80211_TX_QUEUE_DATA3 = 3, /* used for EDCA AC_BK data */ - IEEE80211_TX_QUEUE_DATA4 = 4, - IEEE80211_TX_QUEUE_AFTER_BEACON = 6, - IEEE80211_TX_QUEUE_BEACON = 7 -}; - -static int hostapd_config_tx_queue(struct hostapd_config *conf, char *name, - char *val) -{ - int num; - char *pos; - struct hostapd_tx_queue_params *queue; - - /* skip 'tx_queue_' prefix */ - pos = name + 9; - if (os_strncmp(pos, "data", 4) == 0 && - pos[4] >= '0' && pos[4] <= '9' && pos[5] == '_') { - num = pos[4] - '0'; - pos += 6; - } else if (os_strncmp(pos, "after_beacon_", 13) == 0) { - num = IEEE80211_TX_QUEUE_AFTER_BEACON; - pos += 13; - } else if (os_strncmp(pos, "beacon_", 7) == 0) { - num = IEEE80211_TX_QUEUE_BEACON; - pos += 7; - } else { - wpa_printf(MSG_ERROR, "Unknown tx_queue name '%s'", pos); - return -1; - } - - queue = &conf->tx_queue[num]; - - if (os_strcmp(pos, "aifs") == 0) { - queue->aifs = atoi(val); - if (queue->aifs < 0 || queue->aifs > 255) { - wpa_printf(MSG_ERROR, "Invalid AIFS value %d", - queue->aifs); - return -1; - } - } else if (os_strcmp(pos, "cwmin") == 0) { - queue->cwmin = atoi(val); - if (!valid_cw(queue->cwmin)) { - wpa_printf(MSG_ERROR, "Invalid cwMin value %d", - queue->cwmin); - return -1; - } - } else if (os_strcmp(pos, "cwmax") == 0) { - queue->cwmax = atoi(val); - if (!valid_cw(queue->cwmax)) { - wpa_printf(MSG_ERROR, "Invalid cwMax value %d", - queue->cwmax); - return -1; - } - } else if (os_strcmp(pos, "burst") == 0) { - queue->burst = hostapd_config_read_int10(val); - } else { - wpa_printf(MSG_ERROR, "Unknown tx_queue field '%s'", pos); - return -1; - } - - queue->configured = 1; - - return 0; -} - - -static int hostapd_config_wmm_ac(struct hostapd_config *conf, char *name, - char *val) -{ - int num, v; - char *pos; - struct hostapd_wmm_ac_params *ac; - - /* skip 'wme_ac_' or 'wmm_ac_' prefix */ - pos = name + 7; - if (os_strncmp(pos, "be_", 3) == 0) { - num = 0; - pos += 3; - } else if (os_strncmp(pos, "bk_", 3) == 0) { - num = 1; - pos += 3; - } else if (os_strncmp(pos, "vi_", 3) == 0) { - num = 2; - pos += 3; - } else if (os_strncmp(pos, "vo_", 3) == 0) { - num = 3; - pos += 3; - } else { - wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos); - return -1; - } - - ac = &conf->wmm_ac_params[num]; - - if (os_strcmp(pos, "aifs") == 0) { - v = atoi(val); - if (v < 1 || v > 255) { - wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v); - return -1; - } - ac->aifs = v; - } else if (os_strcmp(pos, "cwmin") == 0) { - v = atoi(val); - if (v < 0 || v > 12) { - wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v); - return -1; - } - ac->cwmin = v; - } else if (os_strcmp(pos, "cwmax") == 0) { - v = atoi(val); - if (v < 0 || v > 12) { - wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v); - return -1; - } - ac->cwmax = v; - } else if (os_strcmp(pos, "txop_limit") == 0) { - v = atoi(val); - if (v < 0 || v > 0xffff) { - wpa_printf(MSG_ERROR, "Invalid txop value %d", v); - return -1; - } - ac->txop_limit = v; - } else if (os_strcmp(pos, "acm") == 0) { - v = atoi(val); - if (v < 0 || v > 1) { - wpa_printf(MSG_ERROR, "Invalid acm value %d", v); - return -1; - } - ac->admission_control_mandatory = v; - } else { - wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos); - return -1; - } - - return 0; -} - - -#ifdef CONFIG_IEEE80211R -static int add_r0kh(struct hostapd_bss_config *bss, char *value) -{ - struct ft_remote_r0kh *r0kh; - char *pos, *next; - - r0kh = os_zalloc(sizeof(*r0kh)); - if (r0kh == NULL) - return -1; - - /* 02:01:02:03:04:05 a.example.com 000102030405060708090a0b0c0d0e0f */ - pos = value; - next = os_strchr(pos, ' '); - if (next) - *next++ = '\0'; - if (next == NULL || hwaddr_aton(pos, r0kh->addr)) { - wpa_printf(MSG_ERROR, "Invalid R0KH MAC address: '%s'", pos); - os_free(r0kh); - return -1; - } - - pos = next; - next = os_strchr(pos, ' '); - if (next) - *next++ = '\0'; - if (next == NULL || next - pos > FT_R0KH_ID_MAX_LEN) { - wpa_printf(MSG_ERROR, "Invalid R0KH-ID: '%s'", pos); - os_free(r0kh); - return -1; - } - r0kh->id_len = next - pos - 1; - os_memcpy(r0kh->id, pos, r0kh->id_len); - - pos = next; - if (hexstr2bin(pos, r0kh->key, sizeof(r0kh->key))) { - wpa_printf(MSG_ERROR, "Invalid R0KH key: '%s'", pos); - os_free(r0kh); - return -1; - } - - r0kh->next = bss->r0kh_list; - bss->r0kh_list = r0kh; - - return 0; -} - - -static int add_r1kh(struct hostapd_bss_config *bss, char *value) -{ - struct ft_remote_r1kh *r1kh; - char *pos, *next; - - r1kh = os_zalloc(sizeof(*r1kh)); - if (r1kh == NULL) - return -1; - - /* 02:01:02:03:04:05 02:01:02:03:04:05 - * 000102030405060708090a0b0c0d0e0f */ - pos = value; - next = os_strchr(pos, ' '); - if (next) - *next++ = '\0'; - if (next == NULL || hwaddr_aton(pos, r1kh->addr)) { - wpa_printf(MSG_ERROR, "Invalid R1KH MAC address: '%s'", pos); - os_free(r1kh); - return -1; - } - - pos = next; - next = os_strchr(pos, ' '); - if (next) - *next++ = '\0'; - if (next == NULL || hwaddr_aton(pos, r1kh->id)) { - wpa_printf(MSG_ERROR, "Invalid R1KH-ID: '%s'", pos); - os_free(r1kh); - return -1; - } - - pos = next; - if (hexstr2bin(pos, r1kh->key, sizeof(r1kh->key))) { - wpa_printf(MSG_ERROR, "Invalid R1KH key: '%s'", pos); - os_free(r1kh); - return -1; - } - - r1kh->next = bss->r1kh_list; - bss->r1kh_list = r1kh; - - return 0; -} -#endif /* CONFIG_IEEE80211R */ - - -#ifdef CONFIG_IEEE80211N -static int hostapd_config_ht_capab(struct hostapd_config *conf, - const char *capab) -{ - if (os_strstr(capab, "[LDPC]")) - conf->ht_capab |= HT_CAP_INFO_LDPC_CODING_CAP; - if (os_strstr(capab, "[HT40-]")) { - conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; - conf->secondary_channel = -1; - } - if (os_strstr(capab, "[HT40+]")) { - conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; - conf->secondary_channel = 1; - } - if (os_strstr(capab, "[SMPS-STATIC]")) { - conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK; - conf->ht_capab |= HT_CAP_INFO_SMPS_STATIC; - } - if (os_strstr(capab, "[SMPS-DYNAMIC]")) { - conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK; - conf->ht_capab |= HT_CAP_INFO_SMPS_DYNAMIC; - } - if (os_strstr(capab, "[GF]")) - conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD; - if (os_strstr(capab, "[SHORT-GI-20]")) - conf->ht_capab |= HT_CAP_INFO_SHORT_GI20MHZ; - if (os_strstr(capab, "[SHORT-GI-40]")) - conf->ht_capab |= HT_CAP_INFO_SHORT_GI40MHZ; - if (os_strstr(capab, "[TX-STBC]")) - conf->ht_capab |= HT_CAP_INFO_TX_STBC; - if (os_strstr(capab, "[RX-STBC1]")) { - conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK; - conf->ht_capab |= HT_CAP_INFO_RX_STBC_1; - } - if (os_strstr(capab, "[RX-STBC12]")) { - conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK; - conf->ht_capab |= HT_CAP_INFO_RX_STBC_12; - } - if (os_strstr(capab, "[RX-STBC123]")) { - conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK; - conf->ht_capab |= HT_CAP_INFO_RX_STBC_123; - } - if (os_strstr(capab, "[DELAYED-BA]")) - conf->ht_capab |= HT_CAP_INFO_DELAYED_BA; - if (os_strstr(capab, "[MAX-AMSDU-7935]")) - conf->ht_capab |= HT_CAP_INFO_MAX_AMSDU_SIZE; - if (os_strstr(capab, "[DSSS_CCK-40]")) - conf->ht_capab |= HT_CAP_INFO_DSSS_CCK40MHZ; - if (os_strstr(capab, "[PSMP]")) - conf->ht_capab |= HT_CAP_INFO_PSMP_SUPP; - if (os_strstr(capab, "[LSIG-TXOP-PROT]")) - conf->ht_capab |= HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT; - - return 0; -} -#endif /* CONFIG_IEEE80211N */ - - -/** - * hostapd_config_read - Read and parse a configuration file - * @fname: Configuration file name (including path, if needed) - * Returns: Allocated configuration data structure - */ -struct hostapd_config * hostapd_config_read(const char *fname) -{ - struct hostapd_config *conf; - struct hostapd_bss_config *bss; - FILE *f; - char buf[256], *pos; - int line = 0; - int errors = 0; - int pairwise; - size_t i; - - f = fopen(fname, "r"); - if (f == NULL) { - wpa_printf(MSG_ERROR, "Could not open configuration file '%s' " - "for reading.", fname); - return NULL; - } - - conf = hostapd_config_defaults(); - if (conf == NULL) { - fclose(f); - return NULL; - } - bss = conf->last_bss = conf->bss; - - while (fgets(buf, sizeof(buf), f)) { - bss = conf->last_bss; - line++; - - if (buf[0] == '#') - continue; - pos = buf; - while (*pos != '\0') { - if (*pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } - if (buf[0] == '\0') - continue; - - pos = os_strchr(buf, '='); - if (pos == NULL) { - wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'", - line, buf); - errors++; - continue; - } - *pos = '\0'; - pos++; - - if (os_strcmp(buf, "interface") == 0) { - os_strlcpy(conf->bss[0].iface, pos, - sizeof(conf->bss[0].iface)); - } else if (os_strcmp(buf, "bridge") == 0) { - os_strlcpy(bss->bridge, pos, sizeof(bss->bridge)); - } else if (os_strcmp(buf, "driver") == 0) { - int j; - /* clear to get error below if setting is invalid */ - conf->driver = NULL; - for (j = 0; hostapd_drivers[j]; j++) { - if (os_strcmp(pos, hostapd_drivers[j]->name) == - 0) { - conf->driver = hostapd_drivers[j]; - break; - } - } - if (conf->driver == NULL) { - wpa_printf(MSG_ERROR, "Line %d: invalid/" - "unknown driver '%s'", line, pos); - errors++; - } - } else if (os_strcmp(buf, "debug") == 0) { - wpa_printf(MSG_DEBUG, "Line %d: DEPRECATED: 'debug' " - "configuration variable is not used " - "anymore", line); - } else if (os_strcmp(buf, "logger_syslog_level") == 0) { - bss->logger_syslog_level = atoi(pos); - } else if (os_strcmp(buf, "logger_stdout_level") == 0) { - bss->logger_stdout_level = atoi(pos); - } else if (os_strcmp(buf, "logger_syslog") == 0) { - bss->logger_syslog = atoi(pos); - } else if (os_strcmp(buf, "logger_stdout") == 0) { - bss->logger_stdout = atoi(pos); - } else if (os_strcmp(buf, "dump_file") == 0) { - bss->dump_log_name = os_strdup(pos); - } else if (os_strcmp(buf, "ssid") == 0) { - bss->ssid.ssid_len = os_strlen(pos); - if (bss->ssid.ssid_len > HOSTAPD_MAX_SSID_LEN || - bss->ssid.ssid_len < 1) { - wpa_printf(MSG_ERROR, "Line %d: invalid SSID " - "'%s'", line, pos); - errors++; - } else { - os_memcpy(bss->ssid.ssid, pos, - bss->ssid.ssid_len); - bss->ssid.ssid[bss->ssid.ssid_len] = '\0'; - bss->ssid.ssid_set = 1; - } - } else if (os_strcmp(buf, "macaddr_acl") == 0) { - bss->macaddr_acl = atoi(pos); - if (bss->macaddr_acl != ACCEPT_UNLESS_DENIED && - bss->macaddr_acl != DENY_UNLESS_ACCEPTED && - bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) { - wpa_printf(MSG_ERROR, "Line %d: unknown " - "macaddr_acl %d", - line, bss->macaddr_acl); - } - } else if (os_strcmp(buf, "accept_mac_file") == 0) { - if (hostapd_config_read_maclist(pos, &bss->accept_mac, - &bss->num_accept_mac)) - { - wpa_printf(MSG_ERROR, "Line %d: Failed to " - "read accept_mac_file '%s'", - line, pos); - errors++; - } - } else if (os_strcmp(buf, "deny_mac_file") == 0) { - if (hostapd_config_read_maclist(pos, &bss->deny_mac, - &bss->num_deny_mac)) { - wpa_printf(MSG_ERROR, "Line %d: Failed to " - "read deny_mac_file '%s'", - line, pos); - errors++; - } - } else if (os_strcmp(buf, "ap_max_inactivity") == 0) { - bss->ap_max_inactivity = atoi(pos); - } else if (os_strcmp(buf, "country_code") == 0) { - os_memcpy(conf->country, pos, 2); - /* FIX: make this configurable */ - conf->country[2] = ' '; - } else if (os_strcmp(buf, "ieee80211d") == 0) { - conf->ieee80211d = atoi(pos); - } else if (os_strcmp(buf, "ieee8021x") == 0) { - bss->ieee802_1x = atoi(pos); - } else if (os_strcmp(buf, "eapol_version") == 0) { - bss->eapol_version = atoi(pos); - if (bss->eapol_version < 1 || - bss->eapol_version > 2) { - wpa_printf(MSG_ERROR, "Line %d: invalid EAPOL " - "version (%d): '%s'.", - line, bss->eapol_version, pos); - errors++; - } else - wpa_printf(MSG_DEBUG, "eapol_version=%d", - bss->eapol_version); -#ifdef EAP_SERVER - } else if (os_strcmp(buf, "eap_authenticator") == 0) { - bss->eap_server = atoi(pos); - wpa_printf(MSG_ERROR, "Line %d: obsolete " - "eap_authenticator used; this has been " - "renamed to eap_server", line); - } else if (os_strcmp(buf, "eap_server") == 0) { - bss->eap_server = atoi(pos); - } else if (os_strcmp(buf, "eap_user_file") == 0) { - if (hostapd_config_read_eap_user(pos, bss)) - errors++; - } else if (os_strcmp(buf, "ca_cert") == 0) { - os_free(bss->ca_cert); - bss->ca_cert = os_strdup(pos); - } else if (os_strcmp(buf, "server_cert") == 0) { - os_free(bss->server_cert); - bss->server_cert = os_strdup(pos); - } else if (os_strcmp(buf, "private_key") == 0) { - os_free(bss->private_key); - bss->private_key = os_strdup(pos); - } else if (os_strcmp(buf, "private_key_passwd") == 0) { - os_free(bss->private_key_passwd); - bss->private_key_passwd = os_strdup(pos); - } else if (os_strcmp(buf, "check_crl") == 0) { - bss->check_crl = atoi(pos); - } else if (os_strcmp(buf, "dh_file") == 0) { - os_free(bss->dh_file); - bss->dh_file = os_strdup(pos); -#ifdef EAP_FAST - } else if (os_strcmp(buf, "pac_opaque_encr_key") == 0) { - os_free(bss->pac_opaque_encr_key); - bss->pac_opaque_encr_key = os_malloc(16); - if (bss->pac_opaque_encr_key == NULL) { - wpa_printf(MSG_ERROR, "Line %d: No memory for " - "pac_opaque_encr_key", line); - errors++; - } else if (hexstr2bin(pos, bss->pac_opaque_encr_key, - 16)) { - wpa_printf(MSG_ERROR, "Line %d: Invalid " - "pac_opaque_encr_key", line); - errors++; - } - } else if (os_strcmp(buf, "eap_fast_a_id") == 0) { - size_t idlen = os_strlen(pos); - if (idlen & 1) { - wpa_printf(MSG_ERROR, "Line %d: Invalid " - "eap_fast_a_id", line); - errors++; - } else { - os_free(bss->eap_fast_a_id); - bss->eap_fast_a_id = os_malloc(idlen / 2); - if (bss->eap_fast_a_id == NULL || - hexstr2bin(pos, bss->eap_fast_a_id, - idlen / 2)) { - wpa_printf(MSG_ERROR, "Line %d: " - "Failed to parse " - "eap_fast_a_id", line); - errors++; - } else - bss->eap_fast_a_id_len = idlen / 2; - } - } else if (os_strcmp(buf, "eap_fast_a_id_info") == 0) { - os_free(bss->eap_fast_a_id_info); - bss->eap_fast_a_id_info = os_strdup(pos); - } else if (os_strcmp(buf, "eap_fast_prov") == 0) { - bss->eap_fast_prov = atoi(pos); - } else if (os_strcmp(buf, "pac_key_lifetime") == 0) { - bss->pac_key_lifetime = atoi(pos); - } else if (os_strcmp(buf, "pac_key_refresh_time") == 0) { - bss->pac_key_refresh_time = atoi(pos); -#endif /* EAP_FAST */ -#ifdef EAP_SIM - } else if (os_strcmp(buf, "eap_sim_db") == 0) { - os_free(bss->eap_sim_db); - bss->eap_sim_db = os_strdup(pos); - } else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) { - bss->eap_sim_aka_result_ind = atoi(pos); -#endif /* EAP_SIM */ -#ifdef EAP_TNC - } else if (os_strcmp(buf, "tnc") == 0) { - bss->tnc = atoi(pos); -#endif /* EAP_TNC */ -#endif /* EAP_SERVER */ - } else if (os_strcmp(buf, "eap_message") == 0) { - char *term; - bss->eap_req_id_text = os_strdup(pos); - if (bss->eap_req_id_text == NULL) { - wpa_printf(MSG_ERROR, "Line %d: Failed to " - "allocate memory for " - "eap_req_id_text", line); - errors++; - continue; - } - bss->eap_req_id_text_len = - os_strlen(bss->eap_req_id_text); - term = os_strstr(bss->eap_req_id_text, "\\0"); - if (term) { - *term++ = '\0'; - os_memmove(term, term + 1, - bss->eap_req_id_text_len - - (term - bss->eap_req_id_text) - 1); - bss->eap_req_id_text_len--; - } - } else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) { - bss->default_wep_key_len = atoi(pos); - if (bss->default_wep_key_len > 13) { - wpa_printf(MSG_ERROR, "Line %d: invalid WEP " - "key len %lu (= %lu bits)", line, - (unsigned long) - bss->default_wep_key_len, - (unsigned long) - bss->default_wep_key_len * 8); - errors++; - } - } else if (os_strcmp(buf, "wep_key_len_unicast") == 0) { - bss->individual_wep_key_len = atoi(pos); - if (bss->individual_wep_key_len < 0 || - bss->individual_wep_key_len > 13) { - wpa_printf(MSG_ERROR, "Line %d: invalid WEP " - "key len %d (= %d bits)", line, - bss->individual_wep_key_len, - bss->individual_wep_key_len * 8); - errors++; - } - } else if (os_strcmp(buf, "wep_rekey_period") == 0) { - bss->wep_rekeying_period = atoi(pos); - if (bss->wep_rekeying_period < 0) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "period %d", - line, bss->wep_rekeying_period); - errors++; - } - } else if (os_strcmp(buf, "eap_reauth_period") == 0) { - bss->eap_reauth_period = atoi(pos); - if (bss->eap_reauth_period < 0) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "period %d", - line, bss->eap_reauth_period); - errors++; - } - } else if (os_strcmp(buf, "eapol_key_index_workaround") == 0) { - bss->eapol_key_index_workaround = atoi(pos); -#ifdef CONFIG_IAPP - } else if (os_strcmp(buf, "iapp_interface") == 0) { - bss->ieee802_11f = 1; - os_strlcpy(bss->iapp_iface, pos, - sizeof(bss->iapp_iface)); -#endif /* CONFIG_IAPP */ - } else if (os_strcmp(buf, "own_ip_addr") == 0) { - if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) { - wpa_printf(MSG_ERROR, "Line %d: invalid IP " - "address '%s'", line, pos); - errors++; - } - } else if (os_strcmp(buf, "nas_identifier") == 0) { - bss->nas_identifier = os_strdup(pos); - } else if (os_strcmp(buf, "auth_server_addr") == 0) { - if (hostapd_config_read_radius_addr( - &bss->radius->auth_servers, - &bss->radius->num_auth_servers, pos, 1812, - &bss->radius->auth_server)) { - wpa_printf(MSG_ERROR, "Line %d: invalid IP " - "address '%s'", line, pos); - errors++; - } - } else if (bss->radius->auth_server && - os_strcmp(buf, "auth_server_port") == 0) { - bss->radius->auth_server->port = atoi(pos); - } else if (bss->radius->auth_server && - os_strcmp(buf, "auth_server_shared_secret") == 0) { - int len = os_strlen(pos); - if (len == 0) { - /* RFC 2865, Ch. 3 */ - wpa_printf(MSG_ERROR, "Line %d: empty shared " - "secret is not allowed.", line); - errors++; - } - bss->radius->auth_server->shared_secret = - (u8 *) os_strdup(pos); - bss->radius->auth_server->shared_secret_len = len; - } else if (os_strcmp(buf, "acct_server_addr") == 0) { - if (hostapd_config_read_radius_addr( - &bss->radius->acct_servers, - &bss->radius->num_acct_servers, pos, 1813, - &bss->radius->acct_server)) { - wpa_printf(MSG_ERROR, "Line %d: invalid IP " - "address '%s'", line, pos); - errors++; - } - } else if (bss->radius->acct_server && - os_strcmp(buf, "acct_server_port") == 0) { - bss->radius->acct_server->port = atoi(pos); - } else if (bss->radius->acct_server && - os_strcmp(buf, "acct_server_shared_secret") == 0) { - int len = os_strlen(pos); - if (len == 0) { - /* RFC 2865, Ch. 3 */ - wpa_printf(MSG_ERROR, "Line %d: empty shared " - "secret is not allowed.", line); - errors++; - } - bss->radius->acct_server->shared_secret = - (u8 *) os_strdup(pos); - bss->radius->acct_server->shared_secret_len = len; - } else if (os_strcmp(buf, "radius_retry_primary_interval") == - 0) { - bss->radius->retry_primary_interval = atoi(pos); - } else if (os_strcmp(buf, "radius_acct_interim_interval") == 0) - { - bss->radius->acct_interim_interval = atoi(pos); - } else if (os_strcmp(buf, "auth_algs") == 0) { - bss->auth_algs = atoi(pos); - if (bss->auth_algs == 0) { - wpa_printf(MSG_ERROR, "Line %d: no " - "authentication algorithms allowed", - line); - errors++; - } - } else if (os_strcmp(buf, "max_num_sta") == 0) { - bss->max_num_sta = atoi(pos); - if (bss->max_num_sta < 0 || - bss->max_num_sta > MAX_STA_COUNT) { - wpa_printf(MSG_ERROR, "Line %d: Invalid " - "max_num_sta=%d; allowed range " - "0..%d", line, bss->max_num_sta, - MAX_STA_COUNT); - errors++; - } - } else if (os_strcmp(buf, "wpa") == 0) { - bss->wpa = atoi(pos); - } else if (os_strcmp(buf, "wpa_group_rekey") == 0) { - bss->wpa_group_rekey = atoi(pos); - } else if (os_strcmp(buf, "wpa_strict_rekey") == 0) { - bss->wpa_strict_rekey = atoi(pos); - } else if (os_strcmp(buf, "wpa_gmk_rekey") == 0) { - bss->wpa_gmk_rekey = atoi(pos); - } else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) { - bss->wpa_ptk_rekey = atoi(pos); - } else if (os_strcmp(buf, "wpa_passphrase") == 0) { - int len = os_strlen(pos); - if (len < 8 || len > 63) { - wpa_printf(MSG_ERROR, "Line %d: invalid WPA " - "passphrase length %d (expected " - "8..63)", line, len); - errors++; - } else { - os_free(bss->ssid.wpa_passphrase); - bss->ssid.wpa_passphrase = os_strdup(pos); - } - } else if (os_strcmp(buf, "wpa_psk") == 0) { - os_free(bss->ssid.wpa_psk); - bss->ssid.wpa_psk = - os_zalloc(sizeof(struct hostapd_wpa_psk)); - if (bss->ssid.wpa_psk == NULL) - errors++; - else if (hexstr2bin(pos, bss->ssid.wpa_psk->psk, - PMK_LEN) || - pos[PMK_LEN * 2] != '\0') { - wpa_printf(MSG_ERROR, "Line %d: Invalid PSK " - "'%s'.", line, pos); - errors++; - } else { - bss->ssid.wpa_psk->group = 1; - } - } else if (os_strcmp(buf, "wpa_psk_file") == 0) { - os_free(bss->ssid.wpa_psk_file); - bss->ssid.wpa_psk_file = os_strdup(pos); - if (!bss->ssid.wpa_psk_file) { - wpa_printf(MSG_ERROR, "Line %d: allocation " - "failed", line); - errors++; - } - } else if (os_strcmp(buf, "wpa_key_mgmt") == 0) { - bss->wpa_key_mgmt = - hostapd_config_parse_key_mgmt(line, pos); - if (bss->wpa_key_mgmt == -1) - errors++; - } else if (os_strcmp(buf, "wpa_pairwise") == 0) { - bss->wpa_pairwise = - hostapd_config_parse_cipher(line, pos); - if (bss->wpa_pairwise == -1 || - bss->wpa_pairwise == 0) - errors++; - else if (bss->wpa_pairwise & - (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | - WPA_CIPHER_WEP104)) { - wpa_printf(MSG_ERROR, "Line %d: unsupported " - "pairwise cipher suite '%s'", - bss->wpa_pairwise, pos); - errors++; - } - } else if (os_strcmp(buf, "rsn_pairwise") == 0) { - bss->rsn_pairwise = - hostapd_config_parse_cipher(line, pos); - if (bss->rsn_pairwise == -1 || - bss->rsn_pairwise == 0) - errors++; - else if (bss->rsn_pairwise & - (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | - WPA_CIPHER_WEP104)) { - wpa_printf(MSG_ERROR, "Line %d: unsupported " - "pairwise cipher suite '%s'", - bss->rsn_pairwise, pos); - errors++; - } -#ifdef CONFIG_RSN_PREAUTH - } else if (os_strcmp(buf, "rsn_preauth") == 0) { - bss->rsn_preauth = atoi(pos); - } else if (os_strcmp(buf, "rsn_preauth_interfaces") == 0) { - bss->rsn_preauth_interfaces = os_strdup(pos); -#endif /* CONFIG_RSN_PREAUTH */ -#ifdef CONFIG_PEERKEY - } else if (os_strcmp(buf, "peerkey") == 0) { - bss->peerkey = atoi(pos); -#endif /* CONFIG_PEERKEY */ -#ifdef CONFIG_IEEE80211R - } else if (os_strcmp(buf, "mobility_domain") == 0) { - if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN || - hexstr2bin(pos, bss->mobility_domain, - MOBILITY_DOMAIN_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "Line %d: Invalid " - "mobility_domain '%s'", line, pos); - errors++; - continue; - } - } else if (os_strcmp(buf, "r1_key_holder") == 0) { - if (os_strlen(pos) != 2 * FT_R1KH_ID_LEN || - hexstr2bin(pos, bss->r1_key_holder, - FT_R1KH_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "Line %d: Invalid " - "r1_key_holder '%s'", line, pos); - errors++; - continue; - } - } else if (os_strcmp(buf, "r0_key_lifetime") == 0) { - bss->r0_key_lifetime = atoi(pos); - } else if (os_strcmp(buf, "reassociation_deadline") == 0) { - bss->reassociation_deadline = atoi(pos); - } else if (os_strcmp(buf, "r0kh") == 0) { - if (add_r0kh(bss, pos) < 0) { - wpa_printf(MSG_DEBUG, "Line %d: Invalid " - "r0kh '%s'", line, pos); - errors++; - continue; - } - } else if (os_strcmp(buf, "r1kh") == 0) { - if (add_r1kh(bss, pos) < 0) { - wpa_printf(MSG_DEBUG, "Line %d: Invalid " - "r1kh '%s'", line, pos); - errors++; - continue; - } - } else if (os_strcmp(buf, "pmk_r1_push") == 0) { - bss->pmk_r1_push = atoi(pos); -#endif /* CONFIG_IEEE80211R */ - } else if (os_strcmp(buf, "ctrl_interface") == 0) { - os_free(bss->ctrl_interface); - bss->ctrl_interface = os_strdup(pos); - } else if (os_strcmp(buf, "ctrl_interface_group") == 0) { -#ifndef CONFIG_NATIVE_WINDOWS - struct group *grp; - char *endp; - const char *group = pos; - - grp = getgrnam(group); - if (grp) { - bss->ctrl_interface_gid = grp->gr_gid; - bss->ctrl_interface_gid_set = 1; - wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d" - " (from group name '%s')", - bss->ctrl_interface_gid, group); - continue; - } - - /* Group name not found - try to parse this as gid */ - bss->ctrl_interface_gid = strtol(group, &endp, 10); - if (*group == '\0' || *endp != '\0') { - wpa_printf(MSG_DEBUG, "Line %d: Invalid group " - "'%s'", line, group); - errors++; - continue; - } - bss->ctrl_interface_gid_set = 1; - wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d", - bss->ctrl_interface_gid); -#endif /* CONFIG_NATIVE_WINDOWS */ -#ifdef RADIUS_SERVER - } else if (os_strcmp(buf, "radius_server_clients") == 0) { - os_free(bss->radius_server_clients); - bss->radius_server_clients = os_strdup(pos); - } else if (os_strcmp(buf, "radius_server_auth_port") == 0) { - bss->radius_server_auth_port = atoi(pos); - } else if (os_strcmp(buf, "radius_server_ipv6") == 0) { - bss->radius_server_ipv6 = atoi(pos); -#endif /* RADIUS_SERVER */ - } else if (os_strcmp(buf, "test_socket") == 0) { - os_free(bss->test_socket); - bss->test_socket = os_strdup(pos); - } else if (os_strcmp(buf, "use_pae_group_addr") == 0) { - bss->use_pae_group_addr = atoi(pos); - } else if (os_strcmp(buf, "hw_mode") == 0) { - if (os_strcmp(pos, "a") == 0) - conf->hw_mode = HOSTAPD_MODE_IEEE80211A; - else if (os_strcmp(pos, "b") == 0) - conf->hw_mode = HOSTAPD_MODE_IEEE80211B; - else if (os_strcmp(pos, "g") == 0) - conf->hw_mode = HOSTAPD_MODE_IEEE80211G; - else { - wpa_printf(MSG_ERROR, "Line %d: unknown " - "hw_mode '%s'", line, pos); - errors++; - } - } else if (os_strcmp(buf, "channel") == 0) { - conf->channel = atoi(pos); - } else if (os_strcmp(buf, "beacon_int") == 0) { - int val = atoi(pos); - /* MIB defines range as 1..65535, but very small values - * cause problems with the current implementation. - * Since it is unlikely that this small numbers are - * useful in real life scenarios, do not allow beacon - * period to be set below 15 TU. */ - if (val < 15 || val > 65535) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "beacon_int %d (expected " - "15..65535)", line, val); - errors++; - } else - conf->beacon_int = val; - } else if (os_strcmp(buf, "dtim_period") == 0) { - bss->dtim_period = atoi(pos); - if (bss->dtim_period < 1 || bss->dtim_period > 255) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "dtim_period %d", - line, bss->dtim_period); - errors++; - } - } else if (os_strcmp(buf, "rts_threshold") == 0) { - conf->rts_threshold = atoi(pos); - if (conf->rts_threshold < 0 || - conf->rts_threshold > 2347) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "rts_threshold %d", - line, conf->rts_threshold); - errors++; - } - } else if (os_strcmp(buf, "fragm_threshold") == 0) { - conf->fragm_threshold = atoi(pos); - if (conf->fragm_threshold < 256 || - conf->fragm_threshold > 2346) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "fragm_threshold %d", - line, conf->fragm_threshold); - errors++; - } - } else if (os_strcmp(buf, "send_probe_response") == 0) { - int val = atoi(pos); - if (val != 0 && val != 1) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "send_probe_response %d (expected " - "0 or 1)", line, val); - } else - conf->send_probe_response = val; - } else if (os_strcmp(buf, "supported_rates") == 0) { - if (hostapd_parse_rates(&conf->supported_rates, pos)) { - wpa_printf(MSG_ERROR, "Line %d: invalid rate " - "list", line); - errors++; - } - } else if (os_strcmp(buf, "basic_rates") == 0) { - if (hostapd_parse_rates(&conf->basic_rates, pos)) { - wpa_printf(MSG_ERROR, "Line %d: invalid rate " - "list", line); - errors++; - } - } else if (os_strcmp(buf, "preamble") == 0) { - if (atoi(pos)) - conf->preamble = SHORT_PREAMBLE; - else - conf->preamble = LONG_PREAMBLE; - } else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) { - bss->ignore_broadcast_ssid = atoi(pos); - } else if (os_strcmp(buf, "bridge_packets") == 0) { - conf->bridge_packets = atoi(pos); - } else if (os_strcmp(buf, "wep_default_key") == 0) { - bss->ssid.wep.idx = atoi(pos); - if (bss->ssid.wep.idx > 3) { - wpa_printf(MSG_ERROR, "Invalid " - "wep_default_key index %d", - bss->ssid.wep.idx); - errors++; - } - } else if (os_strcmp(buf, "wep_key0") == 0 || - os_strcmp(buf, "wep_key1") == 0 || - os_strcmp(buf, "wep_key2") == 0 || - os_strcmp(buf, "wep_key3") == 0) { - if (hostapd_config_read_wep(&bss->ssid.wep, - buf[7] - '0', pos)) { - wpa_printf(MSG_ERROR, "Line %d: invalid WEP " - "key '%s'", line, buf); - errors++; - } - } else if (os_strcmp(buf, "dynamic_vlan") == 0) { - bss->ssid.dynamic_vlan = atoi(pos); - } else if (os_strcmp(buf, "vlan_file") == 0) { - if (hostapd_config_read_vlan_file(bss, pos)) { - wpa_printf(MSG_ERROR, "Line %d: failed to " - "read VLAN file '%s'", line, pos); - errors++; - } -#ifdef CONFIG_FULL_DYNAMIC_VLAN - } else if (os_strcmp(buf, "vlan_tagged_interface") == 0) { - bss->ssid.vlan_tagged_interface = os_strdup(pos); -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - } else if (os_strcmp(buf, "passive_scan_interval") == 0) { - conf->passive_scan_interval = atoi(pos); - } else if (os_strcmp(buf, "passive_scan_listen") == 0) { - conf->passive_scan_listen = atoi(pos); - } else if (os_strcmp(buf, "passive_scan_mode") == 0) { - conf->passive_scan_mode = atoi(pos); - } else if (os_strcmp(buf, "ap_table_max_size") == 0) { - conf->ap_table_max_size = atoi(pos); - } else if (os_strcmp(buf, "ap_table_expiration_time") == 0) { - conf->ap_table_expiration_time = atoi(pos); - } else if (os_strncmp(buf, "tx_queue_", 9) == 0) { - if (hostapd_config_tx_queue(conf, buf, pos)) { - wpa_printf(MSG_ERROR, "Line %d: invalid TX " - "queue item", line); - errors++; - } - } else if (os_strcmp(buf, "wme_enabled") == 0 || - os_strcmp(buf, "wmm_enabled") == 0) { - bss->wmm_enabled = atoi(pos); - } else if (os_strncmp(buf, "wme_ac_", 7) == 0 || - os_strncmp(buf, "wmm_ac_", 7) == 0) { - if (hostapd_config_wmm_ac(conf, buf, pos)) { - wpa_printf(MSG_ERROR, "Line %d: invalid WMM " - "ac item", line); - errors++; - } - } else if (os_strcmp(buf, "bss") == 0) { - if (hostapd_config_bss(conf, pos)) { - wpa_printf(MSG_ERROR, "Line %d: invalid bss " - "item", line); - errors++; - } - } else if (os_strcmp(buf, "bssid") == 0) { - if (bss == conf->bss && - (!conf->driver || !conf->driver->init_bssid)) { - wpa_printf(MSG_ERROR, "Line %d: bssid item " - "not allowed for the default " - "interface and this driver", line); - errors++; - } else if (hwaddr_aton(pos, bss->bssid)) { - wpa_printf(MSG_ERROR, "Line %d: invalid bssid " - "item", line); - errors++; - } -#ifdef CONFIG_IEEE80211W - } else if (os_strcmp(buf, "ieee80211w") == 0) { - bss->ieee80211w = atoi(pos); - } else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) { - bss->assoc_sa_query_max_timeout = atoi(pos); - if (bss->assoc_sa_query_max_timeout == 0) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "assoc_sa_query_max_timeout", line); - errors++; - } - } else if (os_strcmp(buf, "assoc_sa_query_retry_timeout") == 0) - { - bss->assoc_sa_query_retry_timeout = atoi(pos); - if (bss->assoc_sa_query_retry_timeout == 0) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "assoc_sa_query_retry_timeout", - line); - errors++; - } -#endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_IEEE80211N - } else if (os_strcmp(buf, "ieee80211n") == 0) { - conf->ieee80211n = atoi(pos); - } else if (os_strcmp(buf, "ht_capab") == 0) { - if (hostapd_config_ht_capab(conf, pos) < 0) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "ht_capab", line); - errors++; - } -#endif /* CONFIG_IEEE80211N */ - } else if (os_strcmp(buf, "max_listen_interval") == 0) { - bss->max_listen_interval = atoi(pos); - } else if (os_strcmp(buf, "okc") == 0) { - bss->okc = atoi(pos); -#ifdef CONFIG_WPS - } else if (os_strcmp(buf, "wps_state") == 0) { - bss->wps_state = atoi(pos); - if (bss->wps_state < 0 || bss->wps_state > 2) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "wps_state", line); - errors++; - } - } else if (os_strcmp(buf, "ap_setup_locked") == 0) { - bss->ap_setup_locked = atoi(pos); - } else if (os_strcmp(buf, "uuid") == 0) { - if (uuid_str2bin(pos, bss->uuid)) { - wpa_printf(MSG_ERROR, "Line %d: invalid UUID", - line); - errors++; - } - } else if (os_strcmp(buf, "wps_pin_requests") == 0) { - os_free(bss->wps_pin_requests); - bss->wps_pin_requests = os_strdup(pos); - } else if (os_strcmp(buf, "device_name") == 0) { - if (os_strlen(pos) > 32) { - wpa_printf(MSG_ERROR, "Line %d: Too long " - "device_name", line); - errors++; - } - os_free(bss->device_name); - bss->device_name = os_strdup(pos); - } else if (os_strcmp(buf, "manufacturer") == 0) { - if (os_strlen(pos) > 64) { - wpa_printf(MSG_ERROR, "Line %d: Too long " - "manufacturer", line); - errors++; - } - os_free(bss->manufacturer); - bss->manufacturer = os_strdup(pos); - } else if (os_strcmp(buf, "model_name") == 0) { - if (os_strlen(pos) > 32) { - wpa_printf(MSG_ERROR, "Line %d: Too long " - "model_name", line); - errors++; - } - os_free(bss->model_name); - bss->model_name = os_strdup(pos); - } else if (os_strcmp(buf, "model_number") == 0) { - if (os_strlen(pos) > 32) { - wpa_printf(MSG_ERROR, "Line %d: Too long " - "model_number", line); - errors++; - } - os_free(bss->model_number); - bss->model_number = os_strdup(pos); - } else if (os_strcmp(buf, "serial_number") == 0) { - if (os_strlen(pos) > 32) { - wpa_printf(MSG_ERROR, "Line %d: Too long " - "serial_number", line); - errors++; - } - os_free(bss->serial_number); - bss->serial_number = os_strdup(pos); - } else if (os_strcmp(buf, "device_type") == 0) { - os_free(bss->device_type); - bss->device_type = os_strdup(pos); - } else if (os_strcmp(buf, "config_methods") == 0) { - os_free(bss->config_methods); - bss->config_methods = os_strdup(pos); - } else if (os_strcmp(buf, "os_version") == 0) { - if (hexstr2bin(pos, bss->os_version, 4)) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "os_version", line); - errors++; - } - } else if (os_strcmp(buf, "ap_pin") == 0) { - os_free(bss->ap_pin); - bss->ap_pin = os_strdup(pos); - } else if (os_strcmp(buf, "skip_cred_build") == 0) { - bss->skip_cred_build = atoi(pos); - } else if (os_strcmp(buf, "extra_cred") == 0) { - os_free(bss->extra_cred); - bss->extra_cred = - (u8 *) os_readfile(pos, &bss->extra_cred_len); - if (bss->extra_cred == NULL) { - wpa_printf(MSG_ERROR, "Line %d: could not " - "read Credentials from '%s'", - line, pos); - errors++; - } - } else if (os_strcmp(buf, "wps_cred_processing") == 0) { - bss->wps_cred_processing = atoi(pos); - } else if (os_strcmp(buf, "ap_settings") == 0) { - os_free(bss->ap_settings); - bss->ap_settings = - (u8 *) os_readfile(pos, &bss->ap_settings_len); - if (bss->ap_settings == NULL) { - wpa_printf(MSG_ERROR, "Line %d: could not " - "read AP Settings from '%s'", - line, pos); - errors++; - } - } else if (os_strcmp(buf, "upnp_iface") == 0) { - bss->upnp_iface = os_strdup(pos); - } else if (os_strcmp(buf, "friendly_name") == 0) { - os_free(bss->friendly_name); - bss->friendly_name = os_strdup(pos); - } else if (os_strcmp(buf, "manufacturer_url") == 0) { - os_free(bss->manufacturer_url); - bss->manufacturer_url = os_strdup(pos); - } else if (os_strcmp(buf, "model_description") == 0) { - os_free(bss->model_description); - bss->model_description = os_strdup(pos); - } else if (os_strcmp(buf, "model_url") == 0) { - os_free(bss->model_url); - bss->model_url = os_strdup(pos); - } else if (os_strcmp(buf, "upc") == 0) { - os_free(bss->upc); - bss->upc = os_strdup(pos); -#endif /* CONFIG_WPS */ - } else { - wpa_printf(MSG_ERROR, "Line %d: unknown configuration " - "item '%s'", line, buf); - errors++; - } - } - - fclose(f); - - for (i = 0; i < conf->num_bss; i++) { - bss = &conf->bss[i]; - - if (bss->individual_wep_key_len == 0) { - /* individual keys are not use; can use key idx0 for - * broadcast keys */ - bss->broadcast_key_idx_min = 0; - } - - /* Select group cipher based on the enabled pairwise cipher - * suites */ - pairwise = 0; - if (bss->wpa & 1) - pairwise |= bss->wpa_pairwise; - if (bss->wpa & 2) { - if (bss->rsn_pairwise == 0) - bss->rsn_pairwise = bss->wpa_pairwise; - pairwise |= bss->rsn_pairwise; - } - if (pairwise & WPA_CIPHER_TKIP) - bss->wpa_group = WPA_CIPHER_TKIP; - else - bss->wpa_group = WPA_CIPHER_CCMP; - - bss->radius->auth_server = bss->radius->auth_servers; - bss->radius->acct_server = bss->radius->acct_servers; - - if (bss->wpa && bss->ieee802_1x) { - bss->ssid.security_policy = SECURITY_WPA; - } else if (bss->wpa) { - bss->ssid.security_policy = SECURITY_WPA_PSK; - } else if (bss->ieee802_1x) { - bss->ssid.security_policy = SECURITY_IEEE_802_1X; - bss->ssid.wep.default_len = bss->default_wep_key_len; - } else if (bss->ssid.wep.keys_set) - bss->ssid.security_policy = SECURITY_STATIC_WEP; - else - bss->ssid.security_policy = SECURITY_PLAINTEXT; - } - - if (hostapd_config_check(conf)) - errors++; - - if (errors) { - wpa_printf(MSG_ERROR, "%d errors found in configuration file " - "'%s'", errors, fname); - hostapd_config_free(conf); - conf = NULL; - } - - return conf; -} - - -int hostapd_wep_key_cmp(struct hostapd_wep_keys *a, struct hostapd_wep_keys *b) -{ - int i; - - if (a->idx != b->idx || a->default_len != b->default_len) - return 1; - for (i = 0; i < NUM_WEP_KEYS; i++) - if (a->len[i] != b->len[i] || - os_memcmp(a->key[i], b->key[i], a->len[i]) != 0) - return 1; - return 0; -} - - -static void hostapd_config_free_radius(struct hostapd_radius_server *servers, - int num_servers) -{ - int i; - - for (i = 0; i < num_servers; i++) { - os_free(servers[i].shared_secret); - } - os_free(servers); -} - - -static void hostapd_config_free_eap_user(struct hostapd_eap_user *user) -{ - os_free(user->identity); - os_free(user->password); - os_free(user); -} - - -static void hostapd_config_free_wep(struct hostapd_wep_keys *keys) -{ - int i; - for (i = 0; i < NUM_WEP_KEYS; i++) { - os_free(keys->key[i]); - keys->key[i] = NULL; - } -} - - -static void hostapd_config_free_bss(struct hostapd_bss_config *conf) -{ - struct hostapd_wpa_psk *psk, *prev; - struct hostapd_eap_user *user, *prev_user; - - if (conf == NULL) - return; - - psk = conf->ssid.wpa_psk; - while (psk) { - prev = psk; - psk = psk->next; - os_free(prev); - } - - os_free(conf->ssid.wpa_passphrase); - os_free(conf->ssid.wpa_psk_file); -#ifdef CONFIG_FULL_DYNAMIC_VLAN - os_free(conf->ssid.vlan_tagged_interface); -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - - user = conf->eap_user; - while (user) { - prev_user = user; - user = user->next; - hostapd_config_free_eap_user(prev_user); - } - - os_free(conf->dump_log_name); - os_free(conf->eap_req_id_text); - os_free(conf->accept_mac); - os_free(conf->deny_mac); - os_free(conf->nas_identifier); - hostapd_config_free_radius(conf->radius->auth_servers, - conf->radius->num_auth_servers); - hostapd_config_free_radius(conf->radius->acct_servers, - conf->radius->num_acct_servers); - os_free(conf->rsn_preauth_interfaces); - os_free(conf->ctrl_interface); - os_free(conf->ca_cert); - os_free(conf->server_cert); - os_free(conf->private_key); - os_free(conf->private_key_passwd); - os_free(conf->dh_file); - os_free(conf->pac_opaque_encr_key); - os_free(conf->eap_fast_a_id); - os_free(conf->eap_fast_a_id_info); - os_free(conf->eap_sim_db); - os_free(conf->radius_server_clients); - os_free(conf->test_socket); - os_free(conf->radius); - hostapd_config_free_vlan(conf); - if (conf->ssid.dyn_vlan_keys) { - struct hostapd_ssid *ssid = &conf->ssid; - size_t i; - for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) { - if (ssid->dyn_vlan_keys[i] == NULL) - continue; - hostapd_config_free_wep(ssid->dyn_vlan_keys[i]); - os_free(ssid->dyn_vlan_keys[i]); - } - os_free(ssid->dyn_vlan_keys); - ssid->dyn_vlan_keys = NULL; - } - -#ifdef CONFIG_IEEE80211R - { - struct ft_remote_r0kh *r0kh, *r0kh_prev; - struct ft_remote_r1kh *r1kh, *r1kh_prev; - - r0kh = conf->r0kh_list; - conf->r0kh_list = NULL; - while (r0kh) { - r0kh_prev = r0kh; - r0kh = r0kh->next; - os_free(r0kh_prev); - } - - r1kh = conf->r1kh_list; - conf->r1kh_list = NULL; - while (r1kh) { - r1kh_prev = r1kh; - r1kh = r1kh->next; - os_free(r1kh_prev); - } - } -#endif /* CONFIG_IEEE80211R */ - -#ifdef CONFIG_WPS - os_free(conf->wps_pin_requests); - os_free(conf->device_name); - os_free(conf->manufacturer); - os_free(conf->model_name); - os_free(conf->model_number); - os_free(conf->serial_number); - os_free(conf->device_type); - os_free(conf->config_methods); - os_free(conf->ap_pin); - os_free(conf->extra_cred); - os_free(conf->ap_settings); - os_free(conf->upnp_iface); - os_free(conf->friendly_name); - os_free(conf->manufacturer_url); - os_free(conf->model_description); - os_free(conf->model_url); - os_free(conf->upc); -#endif /* CONFIG_WPS */ -} - - -/** - * hostapd_config_free - Free hostapd configuration - * @conf: Configuration data from hostapd_config_read(). - */ -void hostapd_config_free(struct hostapd_config *conf) -{ - size_t i; - - if (conf == NULL) - return; - - for (i = 0; i < conf->num_bss; i++) - hostapd_config_free_bss(&conf->bss[i]); - os_free(conf->bss); - os_free(conf->supported_rates); - os_free(conf->basic_rates); - - os_free(conf); -} - - -/** - * hostapd_maclist_found - Find a MAC address from a list - * @list: MAC address list - * @num_entries: Number of addresses in the list - * @addr: Address to search for - * @vlan_id: Buffer for returning VLAN ID or %NULL if not needed - * Returns: 1 if address is in the list or 0 if not. - * - * Perform a binary search for given MAC address from a pre-sorted list. - */ -int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries, - const u8 *addr, int *vlan_id) -{ - int start, end, middle, res; - - start = 0; - end = num_entries - 1; - - while (start <= end) { - middle = (start + end) / 2; - res = os_memcmp(list[middle].addr, addr, ETH_ALEN); - if (res == 0) { - if (vlan_id) - *vlan_id = list[middle].vlan_id; - return 1; - } - if (res < 0) - start = middle + 1; - else - end = middle - 1; - } - - return 0; -} - - -int hostapd_rate_found(int *list, int rate) -{ - int i; - - if (list == NULL) - return 0; - - for (i = 0; list[i] >= 0; i++) - if (list[i] == rate) - return 1; - - return 0; -} - - -const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id) -{ - struct hostapd_vlan *v = vlan; - while (v) { - if (v->vlan_id == vlan_id || v->vlan_id == VLAN_ID_WILDCARD) - return v->ifname; - v = v->next; - } - return NULL; -} - - -const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, - const u8 *addr, const u8 *prev_psk) -{ - struct hostapd_wpa_psk *psk; - int next_ok = prev_psk == NULL; - - for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) { - if (next_ok && - (psk->group || os_memcmp(psk->addr, addr, ETH_ALEN) == 0)) - return psk->psk; - - if (psk->psk == prev_psk) - next_ok = 1; - } - - return NULL; -} - - -const struct hostapd_eap_user * -hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity, - size_t identity_len, int phase2) -{ - struct hostapd_eap_user *user = conf->eap_user; - -#ifdef CONFIG_WPS - if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN && - os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) { - static struct hostapd_eap_user wsc_enrollee; - os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee)); - wsc_enrollee.methods[0].method = eap_server_get_type( - "WSC", &wsc_enrollee.methods[0].vendor); - return &wsc_enrollee; - } - - if (conf->wps_state && conf->ap_pin && - identity_len == WSC_ID_REGISTRAR_LEN && - os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) { - static struct hostapd_eap_user wsc_registrar; - os_memset(&wsc_registrar, 0, sizeof(wsc_registrar)); - wsc_registrar.methods[0].method = eap_server_get_type( - "WSC", &wsc_registrar.methods[0].vendor); - wsc_registrar.password = (u8 *) conf->ap_pin; - wsc_registrar.password_len = os_strlen(conf->ap_pin); - return &wsc_registrar; - } -#endif /* CONFIG_WPS */ - - while (user) { - if (!phase2 && user->identity == NULL) { - /* Wildcard match */ - break; - } - - if (user->phase2 == !!phase2 && user->wildcard_prefix && - identity_len >= user->identity_len && - os_memcmp(user->identity, identity, user->identity_len) == - 0) { - /* Wildcard prefix match */ - break; - } - - if (user->phase2 == !!phase2 && - user->identity_len == identity_len && - os_memcmp(user->identity, identity, identity_len) == 0) - break; - user = user->next; - } - - return user; -} diff --git a/contrib/hostapd/hostapd/config.h b/contrib/hostapd/hostapd/config.h deleted file mode 100644 index ea530d45d1..0000000000 --- a/contrib/hostapd/hostapd/config.h +++ /dev/null @@ -1,415 +0,0 @@ -/* - * hostapd / Configuration file - * Copyright (c) 2003-2007, Jouni Malinen - * Copyright (c) 2007-2008, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef CONFIG_H -#define CONFIG_H - -#include "defs.h" -#include "ip_addr.h" -#include "wpa_common.h" - -#ifndef IFNAMSIZ -#define IFNAMSIZ 16 -#endif - -typedef u8 macaddr[ETH_ALEN]; - -struct mac_acl_entry { - macaddr addr; - int vlan_id; -}; - -struct hostapd_radius_servers; -struct ft_remote_r0kh; -struct ft_remote_r1kh; - -#define HOSTAPD_MAX_SSID_LEN 32 - -#define NUM_WEP_KEYS 4 -struct hostapd_wep_keys { - u8 idx; - u8 *key[NUM_WEP_KEYS]; - size_t len[NUM_WEP_KEYS]; - int keys_set; - size_t default_len; /* key length used for dynamic key generation */ -}; - -typedef enum hostap_security_policy { - SECURITY_PLAINTEXT = 0, - SECURITY_STATIC_WEP = 1, - SECURITY_IEEE_802_1X = 2, - SECURITY_WPA_PSK = 3, - SECURITY_WPA = 4 -} secpolicy; - -struct hostapd_ssid { - char ssid[HOSTAPD_MAX_SSID_LEN + 1]; - size_t ssid_len; - int ssid_set; - - char vlan[IFNAMSIZ + 1]; - secpolicy security_policy; - - struct hostapd_wpa_psk *wpa_psk; - char *wpa_passphrase; - char *wpa_psk_file; - - struct hostapd_wep_keys wep; - -#define DYNAMIC_VLAN_DISABLED 0 -#define DYNAMIC_VLAN_OPTIONAL 1 -#define DYNAMIC_VLAN_REQUIRED 2 - int dynamic_vlan; -#ifdef CONFIG_FULL_DYNAMIC_VLAN - char *vlan_tagged_interface; -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - struct hostapd_wep_keys **dyn_vlan_keys; - size_t max_dyn_vlan_keys; -}; - - -#define VLAN_ID_WILDCARD -1 - -struct hostapd_vlan { - struct hostapd_vlan *next; - int vlan_id; /* VLAN ID or -1 (VLAN_ID_WILDCARD) for wildcard entry */ - char ifname[IFNAMSIZ + 1]; - int dynamic_vlan; -#ifdef CONFIG_FULL_DYNAMIC_VLAN - -#define DVLAN_CLEAN_BR 0x1 -#define DVLAN_CLEAN_VLAN 0x2 -#define DVLAN_CLEAN_VLAN_PORT 0x4 -#define DVLAN_CLEAN_WLAN_PORT 0x8 - int clean; -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ -}; - -#define PMK_LEN 32 -struct hostapd_wpa_psk { - struct hostapd_wpa_psk *next; - int group; - u8 psk[PMK_LEN]; - u8 addr[ETH_ALEN]; -}; - -#define EAP_USER_MAX_METHODS 8 -struct hostapd_eap_user { - struct hostapd_eap_user *next; - u8 *identity; - size_t identity_len; - struct { - int vendor; - u32 method; - } methods[EAP_USER_MAX_METHODS]; - u8 *password; - size_t password_len; - int phase2; - int force_version; - unsigned int wildcard_prefix:1; - unsigned int password_hash:1; /* whether password is hashed with - * nt_password_hash() */ - int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */ -}; - - -#define NUM_TX_QUEUES 8 - -struct hostapd_tx_queue_params { - int aifs; - int cwmin; - int cwmax; - int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */ - int configured; -}; - -struct hostapd_wmm_ac_params { - int cwmin; - int cwmax; - int aifs; - int txop_limit; /* in units of 32us */ - int admission_control_mandatory; -}; - - -/** - * struct hostapd_bss_config - Per-BSS configuration - */ -struct hostapd_bss_config { - char iface[IFNAMSIZ + 1]; - char bridge[IFNAMSIZ + 1]; - - enum hostapd_logger_level logger_syslog_level, logger_stdout_level; - - unsigned int logger_syslog; /* module bitfield */ - unsigned int logger_stdout; /* module bitfield */ - - char *dump_log_name; /* file name for state dump (SIGUSR1) */ - - int max_num_sta; /* maximum number of STAs in station table */ - - int dtim_period; - - int ieee802_1x; /* use IEEE 802.1X */ - int eapol_version; - int eap_server; /* Use internal EAP server instead of external - * RADIUS server */ - struct hostapd_eap_user *eap_user; - char *eap_sim_db; - struct hostapd_ip_addr own_ip_addr; - char *nas_identifier; - struct hostapd_radius_servers *radius; - - struct hostapd_ssid ssid; - - char *eap_req_id_text; /* optional displayable message sent with - * EAP Request-Identity */ - size_t eap_req_id_text_len; - int eapol_key_index_workaround; - - size_t default_wep_key_len; - int individual_wep_key_len; - int wep_rekeying_period; - int broadcast_key_idx_min, broadcast_key_idx_max; - int eap_reauth_period; - - int ieee802_11f; /* use IEEE 802.11f (IAPP) */ - char iapp_iface[IFNAMSIZ + 1]; /* interface used with IAPP broadcast - * frames */ - - enum { - ACCEPT_UNLESS_DENIED = 0, - DENY_UNLESS_ACCEPTED = 1, - USE_EXTERNAL_RADIUS_AUTH = 2 - } macaddr_acl; - struct mac_acl_entry *accept_mac; - int num_accept_mac; - struct mac_acl_entry *deny_mac; - int num_deny_mac; - - int auth_algs; /* bitfield of allowed IEEE 802.11 authentication - * algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */ - - int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */ - int wpa_key_mgmt; -#ifdef CONFIG_IEEE80211W - enum { - NO_IEEE80211W = 0, - IEEE80211W_OPTIONAL = 1, - IEEE80211W_REQUIRED = 2 - } ieee80211w; - /* dot11AssociationSAQueryMaximumTimeout (in TUs) */ - unsigned int assoc_sa_query_max_timeout; - /* dot11AssociationSAQueryRetryTimeout (in TUs) */ - int assoc_sa_query_retry_timeout; -#endif /* CONFIG_IEEE80211W */ - int wpa_pairwise; - int wpa_group; - int wpa_group_rekey; - int wpa_strict_rekey; - int wpa_gmk_rekey; - int wpa_ptk_rekey; - int rsn_pairwise; - int rsn_preauth; - char *rsn_preauth_interfaces; - int peerkey; - -#ifdef CONFIG_IEEE80211R - /* 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 reassociation_deadline; - struct ft_remote_r0kh *r0kh_list; - struct ft_remote_r1kh *r1kh_list; - int pmk_r1_push; -#endif /* CONFIG_IEEE80211R */ - - char *ctrl_interface; /* directory for UNIX domain sockets */ - gid_t ctrl_interface_gid; - int ctrl_interface_gid_set; - - char *ca_cert; - char *server_cert; - char *private_key; - char *private_key_passwd; - int check_crl; - char *dh_file; - u8 *pac_opaque_encr_key; - u8 *eap_fast_a_id; - size_t eap_fast_a_id_len; - char *eap_fast_a_id_info; - int eap_fast_prov; - int pac_key_lifetime; - int pac_key_refresh_time; - int eap_sim_aka_result_ind; - int tnc; - - char *radius_server_clients; - int radius_server_auth_port; - int radius_server_ipv6; - - char *test_socket; /* UNIX domain socket path for driver_test */ - - int use_pae_group_addr; /* Whether to send EAPOL frames to PAE group - * address instead of individual address - * (for driver_wired.c). - */ - - int ap_max_inactivity; - int ignore_broadcast_ssid; - - int wmm_enabled; - - struct hostapd_vlan *vlan, *vlan_tail; - - macaddr bssid; - - /* - * Maximum listen interval that STAs can use when associating with this - * BSS. If a STA tries to use larger value, the association will be - * denied with status code 51. - */ - u16 max_listen_interval; - - int okc; /* Opportunistic Key Caching */ - - int wps_state; -#ifdef CONFIG_WPS - int ap_setup_locked; - u8 uuid[16]; - char *wps_pin_requests; - char *device_name; - char *manufacturer; - char *model_name; - char *model_number; - char *serial_number; - char *device_type; - char *config_methods; - u8 os_version[4]; - char *ap_pin; - int skip_cred_build; - u8 *extra_cred; - size_t extra_cred_len; - int wps_cred_processing; - u8 *ap_settings; - size_t ap_settings_len; - char *upnp_iface; - char *friendly_name; - char *manufacturer_url; - char *model_description; - char *model_url; - char *upc; -#endif /* CONFIG_WPS */ -}; - - -typedef enum { - HOSTAPD_MODE_IEEE80211B, - HOSTAPD_MODE_IEEE80211G, - HOSTAPD_MODE_IEEE80211A, - NUM_HOSTAPD_MODES -} hostapd_hw_mode; - - -/** - * struct hostapd_config - Per-radio interface configuration - */ -struct hostapd_config { - struct hostapd_bss_config *bss, *last_bss; - size_t num_bss; - - u16 beacon_int; - int rts_threshold; - int fragm_threshold; - u8 send_probe_response; - u8 channel; - hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */ - enum { - LONG_PREAMBLE = 0, - SHORT_PREAMBLE = 1 - } preamble; - enum { - CTS_PROTECTION_AUTOMATIC = 0, - CTS_PROTECTION_FORCE_ENABLED = 1, - CTS_PROTECTION_FORCE_DISABLED = 2, - CTS_PROTECTION_AUTOMATIC_NO_OLBC = 3, - } cts_protection_type; - - int *supported_rates; - int *basic_rates; - - const struct wpa_driver_ops *driver; - - int passive_scan_interval; /* seconds, 0 = disabled */ - int passive_scan_listen; /* usec */ - int passive_scan_mode; - int ap_table_max_size; - int ap_table_expiration_time; - - char country[3]; /* first two octets: country code as described in - * ISO/IEC 3166-1. Third octet: - * ' ' (ascii 32): all environments - * 'O': Outdoor environemnt only - * 'I': Indoor environment only - */ - - int ieee80211d; - - struct hostapd_tx_queue_params tx_queue[NUM_TX_QUEUES]; - - /* - * WMM AC parameters, in same order as 802.1D, i.e. - * 0 = BE (best effort) - * 1 = BK (background) - * 2 = VI (video) - * 3 = VO (voice) - */ - struct hostapd_wmm_ac_params wmm_ac_params[4]; - - enum { - INTERNAL_BRIDGE_DO_NOT_CONTROL = -1, - INTERNAL_BRIDGE_DISABLED = 0, - INTERNAL_BRIDGE_ENABLED = 1 - } bridge_packets; - -#ifdef CONFIG_IEEE80211N - int ht_op_mode_fixed; - u16 ht_capab; -#endif /* CONFIG_IEEE80211N */ - int ieee80211n; - int secondary_channel; -}; - - -int hostapd_mac_comp(const void *a, const void *b); -int hostapd_mac_comp_empty(const void *a); -struct hostapd_config * hostapd_config_read(const char *fname); -void hostapd_config_free(struct hostapd_config *conf); -int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries, - const u8 *addr, int *vlan_id); -int hostapd_rate_found(int *list, int rate); -int hostapd_wep_key_cmp(struct hostapd_wep_keys *a, - struct hostapd_wep_keys *b); -const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, - const u8 *addr, const u8 *prev_psk); -int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf); -const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, - int vlan_id); -const struct hostapd_eap_user * -hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity, - size_t identity_len, int phase2); - -#endif /* CONFIG_H */ diff --git a/contrib/hostapd/hostapd/ctrl_iface.c b/contrib/hostapd/hostapd/ctrl_iface.c deleted file mode 100644 index 9dec7247cd..0000000000 --- a/contrib/hostapd/hostapd/ctrl_iface.c +++ /dev/null @@ -1,610 +0,0 @@ -/* - * hostapd / UNIX domain socket -based control interface - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#ifndef CONFIG_NATIVE_WINDOWS - -#include -#include -#include - -#include "hostapd.h" -#include "eloop.h" -#include "config.h" -#include "ieee802_1x.h" -#include "wpa.h" -#include "radius/radius_client.h" -#include "ieee802_11.h" -#include "ctrl_iface.h" -#include "sta_info.h" -#include "accounting.h" -#include "wps_hostapd.h" - - -struct wpa_ctrl_dst { - struct wpa_ctrl_dst *next; - struct sockaddr_un addr; - socklen_t addrlen; - int debug_level; - int errors; -}; - - -static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, - const char *buf, size_t len); - - -static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd, - struct sockaddr_un *from, - socklen_t fromlen) -{ - struct wpa_ctrl_dst *dst; - - dst = os_zalloc(sizeof(*dst)); - if (dst == NULL) - return -1; - os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un)); - dst->addrlen = fromlen; - dst->debug_level = MSG_INFO; - dst->next = hapd->ctrl_dst; - hapd->ctrl_dst = dst; - wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached", - (u8 *) from->sun_path, - fromlen - offsetof(struct sockaddr_un, sun_path)); - return 0; -} - - -static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd, - struct sockaddr_un *from, - socklen_t fromlen) -{ - struct wpa_ctrl_dst *dst, *prev = NULL; - - dst = hapd->ctrl_dst; - while (dst) { - if (fromlen == dst->addrlen && - os_memcmp(from->sun_path, dst->addr.sun_path, - fromlen - offsetof(struct sockaddr_un, sun_path)) - == 0) { - if (prev == NULL) - hapd->ctrl_dst = dst->next; - else - prev->next = dst->next; - os_free(dst); - wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached", - (u8 *) from->sun_path, - fromlen - - offsetof(struct sockaddr_un, sun_path)); - return 0; - } - prev = dst; - dst = dst->next; - } - return -1; -} - - -static int hostapd_ctrl_iface_level(struct hostapd_data *hapd, - struct sockaddr_un *from, - socklen_t fromlen, - char *level) -{ - struct wpa_ctrl_dst *dst; - - wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); - - dst = hapd->ctrl_dst; - while (dst) { - if (fromlen == dst->addrlen && - os_memcmp(from->sun_path, dst->addr.sun_path, - fromlen - offsetof(struct sockaddr_un, sun_path)) - == 0) { - wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor " - "level", (u8 *) from->sun_path, fromlen - - offsetof(struct sockaddr_un, sun_path)); - dst->debug_level = atoi(level); - return 0; - } - dst = dst->next; - } - - return -1; -} - - -static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, - struct sta_info *sta, - char *buf, size_t buflen) -{ - int len, res, ret; - - if (sta == NULL) { - ret = os_snprintf(buf, buflen, "FAIL\n"); - if (ret < 0 || (size_t) ret >= buflen) - return 0; - return ret; - } - - len = 0; - ret = os_snprintf(buf + len, buflen - len, MACSTR "\n", - MAC2STR(sta->addr)); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - res = ieee802_11_get_mib_sta(hapd, sta, buf + len, buflen - len); - if (res >= 0) - len += res; - res = wpa_get_mib_sta(sta->wpa_sm, buf + len, buflen - len); - if (res >= 0) - len += res; - res = ieee802_1x_get_mib_sta(hapd, sta, buf + len, buflen - len); - if (res >= 0) - len += res; - - return len; -} - - -static int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd, - char *buf, size_t buflen) -{ - return hostapd_ctrl_iface_sta_mib(hapd, hapd->sta_list, buf, buflen); -} - - -static int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, - const char *txtaddr, - char *buf, size_t buflen) -{ - u8 addr[ETH_ALEN]; - int ret; - - if (hwaddr_aton(txtaddr, addr)) { - ret = os_snprintf(buf, buflen, "FAIL\n"); - if (ret < 0 || (size_t) ret >= buflen) - return 0; - return ret; - } - return hostapd_ctrl_iface_sta_mib(hapd, ap_get_sta(hapd, addr), - buf, buflen); -} - - -static int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, - const char *txtaddr, - char *buf, size_t buflen) -{ - u8 addr[ETH_ALEN]; - struct sta_info *sta; - int ret; - - if (hwaddr_aton(txtaddr, addr) || - (sta = ap_get_sta(hapd, addr)) == NULL) { - ret = os_snprintf(buf, buflen, "FAIL\n"); - if (ret < 0 || (size_t) ret >= buflen) - return 0; - return ret; - } - return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen); -} - - -static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd, - const char *txtaddr) -{ - u8 addr[ETH_ALEN]; - struct sta_info *sta; - - wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr); - - if (hwaddr_aton(txtaddr, addr)) - return -1; - - sta = ap_get_sta(hapd, addr); - if (sta) - return 0; - - wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface " - "notification", MAC2STR(addr)); - sta = ap_sta_add(hapd, addr); - if (sta == NULL) - return -1; - - hostapd_new_assoc_sta(hapd, sta, 0); - return 0; -} - - -#ifdef CONFIG_IEEE80211W -static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, - const char *txtaddr) -{ - u8 addr[ETH_ALEN]; - u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; - - wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr); - - if (hwaddr_aton(txtaddr, addr)) - return -1; - - os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN); - ieee802_11_send_sa_query_req(hapd, addr, trans_id); - - return 0; -} -#endif /* CONFIG_IEEE80211W */ - - -#ifdef CONFIG_WPS -static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt) -{ - char *pin = os_strchr(txt, ' '); - char *timeout_txt; - int timeout; - - if (pin == NULL) - return -1; - *pin++ = '\0'; - - timeout_txt = os_strchr(pin, ' '); - if (timeout_txt) { - *timeout_txt++ = '\0'; - timeout = atoi(timeout_txt); - } else - timeout = 0; - - return hostapd_wps_add_pin(hapd, txt, pin, timeout); -} -#endif /* CONFIG_WPS */ - - -static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, - void *sock_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - char buf[256]; - int res; - struct sockaddr_un from; - socklen_t fromlen = sizeof(from); - char *reply; - const int reply_size = 4096; - int reply_len; - - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, - (struct sockaddr *) &from, &fromlen); - if (res < 0) { - perror("recvfrom(ctrl_iface)"); - return; - } - buf[res] = '\0'; - wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", (u8 *) buf, res); - - reply = os_malloc(reply_size); - if (reply == NULL) { - sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, - fromlen); - return; - } - - os_memcpy(reply, "OK\n", 3); - reply_len = 3; - - if (os_strcmp(buf, "PING") == 0) { - os_memcpy(reply, "PONG\n", 5); - reply_len = 5; - } else if (os_strcmp(buf, "MIB") == 0) { - reply_len = ieee802_11_get_mib(hapd, reply, reply_size); - if (reply_len >= 0) { - res = wpa_get_mib(hapd->wpa_auth, reply + reply_len, - reply_size - reply_len); - if (res < 0) - reply_len = -1; - else - reply_len += res; - } - if (reply_len >= 0) { - res = ieee802_1x_get_mib(hapd, reply + reply_len, - reply_size - reply_len); - if (res < 0) - reply_len = -1; - else - reply_len += res; - } - if (reply_len >= 0) { - res = radius_client_get_mib(hapd->radius, - reply + reply_len, - reply_size - reply_len); - if (res < 0) - reply_len = -1; - else - reply_len += res; - } - } else if (os_strcmp(buf, "STA-FIRST") == 0) { - reply_len = hostapd_ctrl_iface_sta_first(hapd, reply, - reply_size); - } else if (os_strncmp(buf, "STA ", 4) == 0) { - reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply, - reply_size); - } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { - reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply, - reply_size); - } else if (os_strcmp(buf, "ATTACH") == 0) { - if (hostapd_ctrl_iface_attach(hapd, &from, fromlen)) - reply_len = -1; - } else if (os_strcmp(buf, "DETACH") == 0) { - if (hostapd_ctrl_iface_detach(hapd, &from, fromlen)) - reply_len = -1; - } else if (os_strncmp(buf, "LEVEL ", 6) == 0) { - if (hostapd_ctrl_iface_level(hapd, &from, fromlen, - buf + 6)) - reply_len = -1; - } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) { - if (hostapd_ctrl_iface_new_sta(hapd, buf + 8)) - reply_len = -1; -#ifdef CONFIG_IEEE80211W - } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) { - if (hostapd_ctrl_iface_sa_query(hapd, buf + 9)) - reply_len = -1; -#endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_WPS - } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { - if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8)) - reply_len = -1; - } else if (os_strcmp(buf, "WPS_PBC") == 0) { - if (hostapd_wps_button_pushed(hapd)) - reply_len = -1; -#endif /* CONFIG_WPS */ - } else { - os_memcpy(reply, "UNKNOWN COMMAND\n", 16); - reply_len = 16; - } - - if (reply_len < 0) { - os_memcpy(reply, "FAIL\n", 5); - reply_len = 5; - } - sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen); - os_free(reply); -} - - -static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd) -{ - char *buf; - size_t len; - - if (hapd->conf->ctrl_interface == NULL) - return NULL; - - len = os_strlen(hapd->conf->ctrl_interface) + - os_strlen(hapd->conf->iface) + 2; - buf = os_malloc(len); - if (buf == NULL) - return NULL; - - os_snprintf(buf, len, "%s/%s", - hapd->conf->ctrl_interface, hapd->conf->iface); - buf[len - 1] = '\0'; - return buf; -} - - -static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, - const char *txt, size_t len) -{ - struct hostapd_data *hapd = ctx; - if (hapd == NULL) - return; - hostapd_ctrl_iface_send(hapd, level, txt, len); -} - - -int hostapd_ctrl_iface_init(struct hostapd_data *hapd) -{ - struct sockaddr_un addr; - int s = -1; - char *fname = NULL; - - hapd->ctrl_sock = -1; - - if (hapd->conf->ctrl_interface == NULL) - return 0; - - if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { - if (errno == EEXIST) { - wpa_printf(MSG_DEBUG, "Using existing control " - "interface directory."); - } else { - perror("mkdir[ctrl_interface]"); - goto fail; - } - } - - if (hapd->conf->ctrl_interface_gid_set && - chown(hapd->conf->ctrl_interface, 0, - hapd->conf->ctrl_interface_gid) < 0) { - perror("chown[ctrl_interface]"); - return -1; - } - - if (os_strlen(hapd->conf->ctrl_interface) + 1 + - os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path)) - goto fail; - - s = socket(PF_UNIX, SOCK_DGRAM, 0); - if (s < 0) { - perror("socket(PF_UNIX)"); - goto fail; - } - - os_memset(&addr, 0, sizeof(addr)); -#ifdef __FreeBSD__ - addr.sun_len = sizeof(addr); -#endif /* __FreeBSD__ */ - addr.sun_family = AF_UNIX; - fname = hostapd_ctrl_iface_path(hapd); - if (fname == NULL) - goto fail; - os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); - if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", - strerror(errno)); - if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" - " allow connections - assuming it was left" - "over from forced program termination"); - if (unlink(fname) < 0) { - perror("unlink[ctrl_iface]"); - wpa_printf(MSG_ERROR, "Could not unlink " - "existing ctrl_iface socket '%s'", - fname); - goto fail; - } - if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < - 0) { - perror("bind(PF_UNIX)"); - goto fail; - } - wpa_printf(MSG_DEBUG, "Successfully replaced leftover " - "ctrl_iface socket '%s'", fname); - } else { - wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " - "be in use - cannot override it"); - wpa_printf(MSG_INFO, "Delete '%s' manually if it is " - "not used anymore", fname); - os_free(fname); - fname = NULL; - goto fail; - } - } - - if (hapd->conf->ctrl_interface_gid_set && - chown(fname, 0, hapd->conf->ctrl_interface_gid) < 0) { - perror("chown[ctrl_interface/ifname]"); - goto fail; - } - - if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { - perror("chmod[ctrl_interface/ifname]"); - goto fail; - } - os_free(fname); - - hapd->ctrl_sock = s; - eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd, - NULL); - wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); - - return 0; - -fail: - if (s >= 0) - close(s); - if (fname) { - unlink(fname); - os_free(fname); - } - return -1; -} - - -void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd) -{ - struct wpa_ctrl_dst *dst, *prev; - - if (hapd->ctrl_sock > -1) { - char *fname; - eloop_unregister_read_sock(hapd->ctrl_sock); - close(hapd->ctrl_sock); - hapd->ctrl_sock = -1; - fname = hostapd_ctrl_iface_path(hapd); - if (fname) - unlink(fname); - os_free(fname); - - if (hapd->conf->ctrl_interface && - rmdir(hapd->conf->ctrl_interface) < 0) { - if (errno == ENOTEMPTY) { - wpa_printf(MSG_DEBUG, "Control interface " - "directory not empty - leaving it " - "behind"); - } else { - perror("rmdir[ctrl_interface]"); - } - } - } - - dst = hapd->ctrl_dst; - while (dst) { - prev = dst; - dst = dst->next; - os_free(prev); - } -} - - -static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, - const char *buf, size_t len) -{ - struct wpa_ctrl_dst *dst, *next; - struct msghdr msg; - int idx; - struct iovec io[2]; - char levelstr[10]; - - dst = hapd->ctrl_dst; - if (hapd->ctrl_sock < 0 || dst == NULL) - return; - - os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); - io[0].iov_base = levelstr; - io[0].iov_len = os_strlen(levelstr); - io[1].iov_base = (char *) buf; - io[1].iov_len = len; - os_memset(&msg, 0, sizeof(msg)); - msg.msg_iov = io; - msg.msg_iovlen = 2; - - idx = 0; - while (dst) { - next = dst->next; - if (level >= dst->debug_level) { - wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send", - (u8 *) dst->addr.sun_path, dst->addrlen - - offsetof(struct sockaddr_un, sun_path)); - msg.msg_name = &dst->addr; - msg.msg_namelen = dst->addrlen; - if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) { - int _errno = errno; - wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: " - "%d - %s", - idx, errno, strerror(errno)); - dst->errors++; - if (dst->errors > 10 || _errno == ENOENT) { - hostapd_ctrl_iface_detach( - hapd, &dst->addr, - dst->addrlen); - } - } else - dst->errors = 0; - } - idx++; - dst = next; - } -} - -#endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/contrib/hostapd/hostapd/ctrl_iface.h b/contrib/hostapd/hostapd/ctrl_iface.h deleted file mode 100644 index d86de8c940..0000000000 --- a/contrib/hostapd/hostapd/ctrl_iface.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * hostapd / UNIX domain socket -based control interface - * Copyright (c) 2004, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef CTRL_IFACE_H -#define CTRL_IFACE_H - -int hostapd_ctrl_iface_init(struct hostapd_data *hapd); -void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd); - -#endif /* CTRL_IFACE_H */ diff --git a/contrib/hostapd/hostapd/driver.h b/contrib/hostapd/hostapd/driver.h deleted file mode 100644 index 45f5460873..0000000000 --- a/contrib/hostapd/hostapd/driver.h +++ /dev/null @@ -1,798 +0,0 @@ -/* - * hostapd - driver interface definition - * Copyright (c) 2002-2007, Jouni Malinen - * Copyright (c) 2007-2008, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef DRIVER_H -#define DRIVER_H - -struct hostapd_sta_add_params { - const u8 *addr; - u16 aid; - u16 capability; - const u8 *supp_rates; - size_t supp_rates_len; - int flags; - u16 listen_interval; - const struct ht_cap_ie *ht_capabilities; -}; - -struct hostapd_freq_params { - int mode; - int freq; - int ht_enabled; - int sec_channel_offset; /* 0 = HT40 disabled, -1 = HT40 enabled, - * secondary channel below primary, 1 = HT40 - * enabled, secondary channel above primary */ -}; - -enum hostapd_driver_if_type { - HOSTAPD_IF_VLAN, HOSTAPD_IF_WDS -}; - -struct wpa_driver_ops { - const char *name; /* as appears in the config file */ - - void * (*init)(struct hostapd_data *hapd); - void * (*init_bssid)(struct hostapd_data *hapd, const u8 *bssid); - void (*deinit)(void *priv); - - int (*wireless_event_init)(void *priv); - void (*wireless_event_deinit)(void *priv); - - /** - * set_8021x - enable/disable IEEE 802.1X support - * @ifname: Interface name (for multi-SSID/VLAN support) - * @priv: driver private data - * @enabled: 1 = enable, 0 = disable - * - * Returns: 0 on success, -1 on failure - * - * Configure the kernel driver to enable/disable 802.1X support. - * This may be an empty function if 802.1X support is always enabled. - */ - int (*set_ieee8021x)(const char *ifname, void *priv, int enabled); - - /** - * set_privacy - enable/disable privacy - * @priv: driver private data - * @enabled: 1 = privacy enabled, 0 = disabled - * - * Return: 0 on success, -1 on failure - * - * Configure privacy. - */ - int (*set_privacy)(const char *ifname, void *priv, int enabled); - - int (*set_encryption)(const char *ifname, void *priv, const char *alg, - const u8 *addr, int idx, - const u8 *key, size_t key_len, int txkey); - int (*get_seqnum)(const char *ifname, void *priv, const u8 *addr, - int idx, u8 *seq); - int (*get_seqnum_igtk)(const char *ifname, void *priv, const u8 *addr, - int idx, u8 *seq); - int (*flush)(void *priv); - int (*set_generic_elem)(const char *ifname, void *priv, const u8 *elem, - size_t elem_len); - - int (*read_sta_data)(void *priv, struct hostap_sta_driver_data *data, - const u8 *addr); - int (*send_eapol)(void *priv, const u8 *addr, const u8 *data, - size_t data_len, int encrypt, const u8 *own_addr); - int (*sta_deauth)(void *priv, const u8 *addr, int reason); - int (*sta_disassoc)(void *priv, const u8 *addr, int reason); - int (*sta_remove)(void *priv, const u8 *addr); - int (*get_ssid)(const char *ifname, void *priv, u8 *buf, int len); - int (*set_ssid)(const char *ifname, void *priv, const u8 *buf, - int len); - int (*set_countermeasures)(void *priv, int enabled); - int (*send_mgmt_frame)(void *priv, const void *msg, size_t len, - int flags); - int (*set_assoc_ap)(void *priv, const u8 *addr); - /* note: sta_add() is deprecated; use sta_add2() instead */ - int (*sta_add)(const char *ifname, void *priv, const u8 *addr, u16 aid, - u16 capability, u8 *supp_rates, size_t supp_rates_len, - int flags, u16 listen_interval); - int (*sta_add2)(const char *ifname, void *priv, - struct hostapd_sta_add_params *params); - int (*get_inact_sec)(void *priv, const u8 *addr); - int (*sta_clear_stats)(void *priv, const u8 *addr); - - /* note: set_freq() is deprecated; use set_freq2() instead */ - int (*set_freq)(void *priv, int mode, int freq); - int (*set_freq2)(void *priv, struct hostapd_freq_params *freq); - int (*set_rts)(void *priv, int rts); - int (*get_rts)(void *priv, int *rts); - int (*set_frag)(void *priv, int frag); - int (*get_frag)(void *priv, int *frag); - int (*set_retry)(void *priv, int short_retry, int long_retry); - int (*get_retry)(void *priv, int *short_retry, int *long_retry); - - int (*sta_set_flags)(void *priv, const u8 *addr, - int total_flags, int flags_or, int flags_and); - int (*set_rate_sets)(void *priv, int *supp_rates, int *basic_rates, - int mode); - int (*set_regulatory_domain)(void *priv, unsigned int rd); - int (*set_country)(void *priv, const char *country); - int (*set_ieee80211d)(void *priv, int enabled); - int (*set_beacon)(const char *ifname, void *priv, - u8 *head, size_t head_len, - u8 *tail, size_t tail_len); - - /* Configure internal bridge: - * 0 = disabled, i.e., client separation is enabled (no bridging of - * packets between associated STAs - * 1 = enabled, i.e., bridge packets between associated STAs (default) - */ - int (*set_internal_bridge)(void *priv, int value); - int (*set_beacon_int)(void *priv, int value); - int (*set_dtim_period)(const char *ifname, void *priv, int value); - /* Configure broadcast SSID mode: - * 0 = include SSID in Beacon frames and reply to Probe Request frames - * that use broadcast SSID - * 1 = hide SSID from Beacon frames and ignore Probe Request frames for - * broadcast SSID - */ - int (*set_broadcast_ssid)(void *priv, int value); - int (*set_cts_protect)(void *priv, int value); - int (*set_key_tx_rx_threshold)(void *priv, int value); - int (*set_preamble)(void *priv, int value); - int (*set_short_slot_time)(void *priv, int value); - int (*set_tx_queue_params)(void *priv, int queue, int aifs, int cw_min, - int cw_max, int burst_time); - int (*bss_add)(void *priv, const char *ifname, const u8 *bssid); - int (*bss_remove)(void *priv, const char *ifname); - int (*valid_bss_mask)(void *priv, const u8 *addr, const u8 *mask); - int (*passive_scan)(void *priv, int now, int our_mode_only, - int interval, int _listen, int *channel, - int *last_rx); - struct hostapd_hw_modes * (*get_hw_feature_data)(void *priv, - u16 *num_modes, - u16 *flags); - int (*if_add)(const char *iface, void *priv, - enum hostapd_driver_if_type type, char *ifname, - const u8 *addr); - int (*if_update)(void *priv, enum hostapd_driver_if_type type, - char *ifname, const u8 *addr); - int (*if_remove)(void *priv, enum hostapd_driver_if_type type, - const char *ifname, const u8 *addr); - int (*set_sta_vlan)(void *priv, const u8 *addr, const char *ifname, - int vlan_id); - /** - * commit - Optional commit changes handler - * @priv: driver private data - * Returns: 0 on success, -1 on failure - * - * This optional handler function can be registered if the driver - * interface implementation needs to commit changes (e.g., by setting - * network interface up) at the end of initial configuration. If set, - * this handler will be called after initial setup has been completed. - */ - int (*commit)(void *priv); - - int (*send_ether)(void *priv, const u8 *dst, const u8 *src, u16 proto, - const u8 *data, size_t data_len); - - int (*set_radius_acl_auth)(void *priv, const u8 *mac, int accepted, - u32 session_timeout); - int (*set_radius_acl_expire)(void *priv, const u8 *mac); - - int (*set_ht_params)(const char *ifname, void *priv, - const u8 *ht_capab, size_t ht_capab_len, - const u8 *ht_oper, size_t ht_oper_len); - - int (*set_wps_beacon_ie)(const char *ifname, void *priv, - const u8 *ie, size_t len); - int (*set_wps_probe_resp_ie)(const char *ifname, void *priv, - const u8 *ie, size_t len); -}; - -static inline void * -hostapd_driver_init(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || hapd->driver->init == NULL) - return NULL; - return hapd->driver->init(hapd); -} - -static inline void * -hostapd_driver_init_bssid(struct hostapd_data *hapd, const u8 *bssid) -{ - if (hapd->driver == NULL || hapd->driver->init_bssid == NULL) - return NULL; - return hapd->driver->init_bssid(hapd, bssid); -} - -static inline void -hostapd_driver_deinit(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || hapd->driver->deinit == NULL) - return; - hapd->driver->deinit(hapd->drv_priv); -} - -static inline int -hostapd_wireless_event_init(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || - hapd->driver->wireless_event_init == NULL) - return 0; - return hapd->driver->wireless_event_init(hapd->drv_priv); -} - -static inline void -hostapd_wireless_event_deinit(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || - hapd->driver->wireless_event_deinit == NULL) - return; - hapd->driver->wireless_event_deinit(hapd->drv_priv); -} - -static inline int -hostapd_set_ieee8021x(const char *ifname, struct hostapd_data *hapd, - int enabled) -{ - if (hapd->driver == NULL || hapd->driver->set_ieee8021x == NULL) - return 0; - return hapd->driver->set_ieee8021x(ifname, hapd->drv_priv, enabled); -} - -static inline int -hostapd_set_privacy(struct hostapd_data *hapd, int enabled) -{ - if (hapd->driver == NULL || hapd->driver->set_privacy == NULL) - return 0; - return hapd->driver->set_privacy(hapd->conf->iface, hapd->drv_priv, - enabled); -} - -static inline int -hostapd_set_encryption(const char *ifname, struct hostapd_data *hapd, - const char *alg, const u8 *addr, int idx, - u8 *key, size_t key_len, int txkey) -{ - if (hapd->driver == NULL || hapd->driver->set_encryption == NULL) - return 0; - return hapd->driver->set_encryption(ifname, hapd->drv_priv, alg, addr, - idx, key, key_len, txkey); -} - -static inline int -hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd, - const u8 *addr, int idx, u8 *seq) -{ - if (hapd->driver == NULL || hapd->driver->get_seqnum == NULL) - return 0; - return hapd->driver->get_seqnum(ifname, hapd->drv_priv, addr, idx, - seq); -} - -static inline int -hostapd_get_seqnum_igtk(const char *ifname, struct hostapd_data *hapd, - const u8 *addr, int idx, u8 *seq) -{ - if (hapd->driver == NULL || hapd->driver->get_seqnum_igtk == NULL) - return -1; - return hapd->driver->get_seqnum_igtk(ifname, hapd->drv_priv, addr, idx, - seq); -} - -static inline int -hostapd_flush(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || hapd->driver->flush == NULL) - return 0; - return hapd->driver->flush(hapd->drv_priv); -} - -static inline int -hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem, - size_t elem_len) -{ - if (hapd->driver == NULL || hapd->driver->set_generic_elem == NULL) - return 0; - return hapd->driver->set_generic_elem(hapd->conf->iface, - hapd->drv_priv, elem, elem_len); -} - -static inline int -hostapd_read_sta_data(struct hostapd_data *hapd, - struct hostap_sta_driver_data *data, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->read_sta_data == NULL) - return -1; - return hapd->driver->read_sta_data(hapd->drv_priv, data, addr); -} - -static inline int -hostapd_send_eapol(struct hostapd_data *hapd, const u8 *addr, const u8 *data, - size_t data_len, int encrypt) -{ - if (hapd->driver == NULL || hapd->driver->send_eapol == NULL) - return 0; - return hapd->driver->send_eapol(hapd->drv_priv, addr, data, data_len, - encrypt, hapd->own_addr); -} - -static inline int -hostapd_sta_deauth(struct hostapd_data *hapd, const u8 *addr, int reason) -{ - if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL) - return 0; - return hapd->driver->sta_deauth(hapd->drv_priv, addr, reason); -} - -static inline int -hostapd_sta_disassoc(struct hostapd_data *hapd, const u8 *addr, int reason) -{ - if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL) - return 0; - return hapd->driver->sta_disassoc(hapd->drv_priv, addr, reason); -} - -static inline int -hostapd_sta_remove(struct hostapd_data *hapd, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->sta_remove == NULL) - return 0; - return hapd->driver->sta_remove(hapd->drv_priv, addr); -} - -static inline int -hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len) -{ - if (hapd->driver == NULL || hapd->driver->get_ssid == NULL) - return 0; - return hapd->driver->get_ssid(hapd->conf->iface, hapd->drv_priv, buf, - len); -} - -static inline int -hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len) -{ - if (hapd->driver == NULL || hapd->driver->set_ssid == NULL) - return 0; - return hapd->driver->set_ssid(hapd->conf->iface, hapd->drv_priv, buf, - len); -} - -static inline int -hostapd_send_mgmt_frame(struct hostapd_data *hapd, const void *msg, size_t len, - int flags) -{ - if (hapd->driver == NULL || hapd->driver->send_mgmt_frame == NULL) - return 0; - return hapd->driver->send_mgmt_frame(hapd->drv_priv, msg, len, flags); -} - -static inline int -hostapd_set_assoc_ap(struct hostapd_data *hapd, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->set_assoc_ap == NULL) - return 0; - return hapd->driver->set_assoc_ap(hapd->drv_priv, addr); -} - -static inline int -hostapd_set_countermeasures(struct hostapd_data *hapd, int enabled) -{ - if (hapd->driver == NULL || hapd->driver->set_countermeasures == NULL) - return 0; - return hapd->driver->set_countermeasures(hapd->drv_priv, enabled); -} - -static inline int -hostapd_sta_add(const char *ifname, struct hostapd_data *hapd, const u8 *addr, - u16 aid, u16 capability, const u8 *supp_rates, - size_t supp_rates_len, int flags, u16 listen_interval, - const struct ht_cap_ie *ht_capabilities) -{ - if (hapd->driver == NULL) - return 0; - - if (hapd->driver->sta_add2) { - struct hostapd_sta_add_params params; - os_memset(¶ms, 0, sizeof(params)); - params.addr = addr; - params.aid = aid; - params.capability = capability; - params.supp_rates = supp_rates; - params.supp_rates_len = supp_rates_len; - params.flags = flags; - params.listen_interval = listen_interval; - params.ht_capabilities = ht_capabilities; - return hapd->driver->sta_add2(ifname, hapd->drv_priv, ¶ms); - } - - if (hapd->driver->sta_add == NULL) - return 0; - return hapd->driver->sta_add(ifname, hapd->drv_priv, addr, aid, - capability, (u8 *) supp_rates, - supp_rates_len, - flags, listen_interval); -} - -static inline int -hostapd_get_inact_sec(struct hostapd_data *hapd, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->get_inact_sec == NULL) - return 0; - return hapd->driver->get_inact_sec(hapd->drv_priv, addr); -} - -static inline int -hostapd_set_freq(struct hostapd_data *hapd, int mode, int freq, int ht_enabled, - int sec_channel_offset) -{ - if (hapd->driver == NULL) - return 0; - if (hapd->driver->set_freq2) { - struct hostapd_freq_params data; - os_memset(&data, 0, sizeof(data)); - data.mode = mode; - data.freq = freq; - data.ht_enabled = ht_enabled; - data.sec_channel_offset = sec_channel_offset; - return hapd->driver->set_freq2(hapd->drv_priv, &data); - } - - if (hapd->driver->set_freq == NULL) - return 0; - return hapd->driver->set_freq(hapd->drv_priv, mode, freq); -} - -static inline int -hostapd_set_rts(struct hostapd_data *hapd, int rts) -{ - if (hapd->driver == NULL || hapd->driver->set_rts == NULL) - return 0; - return hapd->driver->set_rts(hapd->drv_priv, rts); -} - -static inline int -hostapd_get_rts(struct hostapd_data *hapd, int *rts) -{ - if (hapd->driver == NULL || hapd->driver->get_rts == NULL) - return 0; - return hapd->driver->get_rts(hapd->drv_priv, rts); -} - -static inline int -hostapd_set_frag(struct hostapd_data *hapd, int frag) -{ - if (hapd->driver == NULL || hapd->driver->set_frag == NULL) - return 0; - return hapd->driver->set_frag(hapd->drv_priv, frag); -} - -static inline int -hostapd_get_frag(struct hostapd_data *hapd, int *frag) -{ - if (hapd->driver == NULL || hapd->driver->get_frag == NULL) - return 0; - return hapd->driver->get_frag(hapd->drv_priv, frag); -} - -static inline int -hostapd_set_retry(struct hostapd_data *hapd, int short_retry, int long_retry) -{ - if (hapd->driver == NULL || hapd->driver->set_retry == NULL) - return 0; - return hapd->driver->set_retry(hapd->drv_priv, short_retry, - long_retry); -} - -static inline int -hostapd_get_retry(struct hostapd_data *hapd, int *short_retry, int *long_retry) -{ - if (hapd->driver == NULL || hapd->driver->get_retry == NULL) - return 0; - return hapd->driver->get_retry(hapd->drv_priv, short_retry, - long_retry); -} - -static inline int -hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, - int total_flags, int flags_or, int flags_and) -{ - if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL) - return 0; - return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags, - flags_or, flags_and); -} - -static inline int -hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates, - int *basic_rates, int mode) -{ - if (hapd->driver == NULL || hapd->driver->set_rate_sets == NULL) - return 0; - return hapd->driver->set_rate_sets(hapd->drv_priv, supp_rates, - basic_rates, mode); -} - -static inline int -hostapd_set_regulatory_domain(struct hostapd_data *hapd, unsigned int rd) -{ - if (hapd->driver == NULL || - hapd->driver->set_regulatory_domain == NULL) - return 0; - return hapd->driver->set_regulatory_domain(hapd->drv_priv, rd); -} - -static inline int -hostapd_set_country(struct hostapd_data *hapd, const char *country) -{ - if (hapd->driver == NULL || - hapd->driver->set_country == NULL) - return 0; - return hapd->driver->set_country(hapd->drv_priv, country); -} - -static inline int -hostapd_set_ieee80211d(struct hostapd_data *hapd, int enabled) -{ - if (hapd->driver == NULL || - hapd->driver->set_ieee80211d == NULL) - return 0; - return hapd->driver->set_ieee80211d(hapd->drv_priv, enabled); -} - -static inline int -hostapd_sta_clear_stats(struct hostapd_data *hapd, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->sta_clear_stats == NULL) - return 0; - return hapd->driver->sta_clear_stats(hapd->drv_priv, addr); -} - -static inline int -hostapd_set_beacon(const char *ifname, struct hostapd_data *hapd, - u8 *head, size_t head_len, - u8 *tail, size_t tail_len) -{ - if (hapd->driver == NULL || hapd->driver->set_beacon == NULL) - return 0; - return hapd->driver->set_beacon(ifname, hapd->drv_priv, head, head_len, - tail, tail_len); -} - -static inline int -hostapd_set_internal_bridge(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_internal_bridge == NULL) - return 0; - return hapd->driver->set_internal_bridge(hapd->drv_priv, value); -} - -static inline int -hostapd_set_beacon_int(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_beacon_int == NULL) - return 0; - return hapd->driver->set_beacon_int(hapd->drv_priv, value); -} - -static inline int -hostapd_set_dtim_period(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_dtim_period == NULL) - return 0; - return hapd->driver->set_dtim_period(hapd->conf->iface, hapd->drv_priv, - value); -} - -static inline int -hostapd_set_broadcast_ssid(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_broadcast_ssid == NULL) - return 0; - return hapd->driver->set_broadcast_ssid(hapd->drv_priv, value); -} - -static inline int -hostapd_set_cts_protect(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_cts_protect == NULL) - return 0; - return hapd->driver->set_cts_protect(hapd->drv_priv, value); -} - -static inline int -hostapd_set_key_tx_rx_threshold(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || - hapd->driver->set_key_tx_rx_threshold == NULL) - return 0; - return hapd->driver->set_key_tx_rx_threshold(hapd->drv_priv, value); -} - -static inline int -hostapd_set_preamble(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_preamble == NULL) - return 0; - return hapd->driver->set_preamble(hapd->drv_priv, value); -} - -static inline int -hostapd_set_short_slot_time(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_short_slot_time == NULL) - return 0; - return hapd->driver->set_short_slot_time(hapd->drv_priv, value); -} - -static inline int -hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs, - int cw_min, int cw_max, int burst_time) -{ - if (hapd->driver == NULL || hapd->driver->set_tx_queue_params == NULL) - return 0; - return hapd->driver->set_tx_queue_params(hapd->drv_priv, queue, aifs, - cw_min, cw_max, burst_time); -} - -static inline int -hostapd_bss_add(struct hostapd_data *hapd, const char *ifname, const u8 *bssid) -{ - if (hapd->driver == NULL || hapd->driver->bss_add == NULL) - return 0; - return hapd->driver->bss_add(hapd->drv_priv, ifname, bssid); -} - -static inline int -hostapd_bss_remove(struct hostapd_data *hapd, const char *ifname) -{ - if (hapd->driver == NULL || hapd->driver->bss_remove == NULL) - return 0; - return hapd->driver->bss_remove(hapd->drv_priv, ifname); -} - -static inline int -hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr, - const u8 *mask) -{ - if (hapd->driver == NULL || hapd->driver->valid_bss_mask == NULL) - return 1; - return hapd->driver->valid_bss_mask(hapd->drv_priv, addr, mask); -} - -static inline int -hostapd_if_add(struct hostapd_data *hapd, enum hostapd_driver_if_type type, - char *ifname, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->if_add == NULL) - return -1; - return hapd->driver->if_add(hapd->conf->iface, hapd->drv_priv, type, - ifname, addr); -} - -static inline int -hostapd_if_update(struct hostapd_data *hapd, enum hostapd_driver_if_type type, - char *ifname, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->if_update == NULL) - return -1; - return hapd->driver->if_update(hapd->drv_priv, type, ifname, addr); -} - -static inline int -hostapd_if_remove(struct hostapd_data *hapd, enum hostapd_driver_if_type type, - char *ifname, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->if_remove == NULL) - return -1; - return hapd->driver->if_remove(hapd->drv_priv, type, ifname, addr); -} - -static inline int -hostapd_passive_scan(struct hostapd_data *hapd, int now, int our_mode_only, - int interval, int _listen, int *channel, - int *last_rx) -{ - if (hapd->driver == NULL || hapd->driver->passive_scan == NULL) - return -1; - return hapd->driver->passive_scan(hapd->drv_priv, now, our_mode_only, - interval, _listen, channel, last_rx); -} - -static inline struct hostapd_hw_modes * -hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, - u16 *flags) -{ - 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); -} - -static inline int -hostapd_set_sta_vlan(const char *ifname, struct hostapd_data *hapd, - const u8 *addr, int vlan_id) -{ - if (hapd->driver == NULL || hapd->driver->set_sta_vlan == NULL) - return 0; - return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname, vlan_id); -} - -static inline int -hostapd_driver_commit(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || hapd->driver->commit == NULL) - return 0; - return hapd->driver->commit(hapd->drv_priv); -} - -static inline int -hostapd_set_radius_acl_auth(struct hostapd_data *hapd, const u8 *mac, - int accepted, u32 session_timeout) -{ - if (hapd->driver == NULL || hapd->driver->set_radius_acl_auth == NULL) - return 0; - return hapd->driver->set_radius_acl_auth(hapd->drv_priv, mac, accepted, - session_timeout); -} - -static inline int -hostapd_set_radius_acl_expire(struct hostapd_data *hapd, const u8 *mac) -{ - if (hapd->driver == NULL || - hapd->driver->set_radius_acl_expire == NULL) - return 0; - return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac); -} - -#ifdef CONFIG_IEEE80211N -static inline int -hostapd_set_ht_params(const char *ifname, struct hostapd_data *hapd, - const u8 *ht_capab, size_t ht_capab_len, - const u8 *ht_oper, size_t ht_oper_len) -{ - if (hapd->driver == NULL || hapd->driver->set_ht_params == NULL || - ht_capab == NULL || ht_oper == NULL) - return 0; - return hapd->driver->set_ht_params( - ifname, hapd->drv_priv, ht_capab, ht_capab_len, - ht_oper, ht_oper_len); -} -#endif /* CONFIG_IEEE80211N */ - -static inline int -hostapd_drv_none(struct hostapd_data *hapd) -{ - return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0; -} - -static inline int -hostapd_set_wps_beacon_ie(struct hostapd_data *hapd, const u8 *ie, size_t len) -{ - if (hapd->driver == NULL || hapd->driver->set_wps_beacon_ie == NULL) - return 0; - return hapd->driver->set_wps_beacon_ie(hapd->conf->iface, - hapd->drv_priv, ie, len); -} - -static inline int -hostapd_set_wps_probe_resp_ie(struct hostapd_data *hapd, const u8 *ie, - size_t len) -{ - if (hapd->driver == NULL || - hapd->driver->set_wps_probe_resp_ie == NULL) - return 0; - return hapd->driver->set_wps_probe_resp_ie(hapd->conf->iface, - hapd->drv_priv, ie, len); -} - -#endif /* DRIVER_H */ diff --git a/contrib/hostapd/hostapd/driver_atheros.c b/contrib/hostapd/hostapd/driver_atheros.c deleted file mode 100644 index 558a8bbf2b..0000000000 --- a/contrib/hostapd/hostapd/driver_atheros.c +++ /dev/null @@ -1,1457 +0,0 @@ -/* - * hostapd / Driver interaction with Atheros driver - * Copyright (c) 2004, Sam Leffler - * Copyright (c) 2004, Video54 Technologies - * Copyright (c) 2005-2007, Jouni Malinen - * Copyright (c) 2009, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include - -#include "common.h" -#ifndef _BYTE_ORDER -#ifdef WORDS_BIGENDIAN -#define _BYTE_ORDER _BIG_ENDIAN -#else -#define _BYTE_ORDER _LITTLE_ENDIAN -#endif -#endif /* _BYTE_ORDER */ - -#include -#include -#include - -/* - * Note, the ATH_WPS_IE setting must match with the driver build.. If the - * driver does not include this, the IEEE80211_IOCTL_GETWPAIE ioctl will fail. - */ -#define ATH_WPS_IE -#include - -#ifdef CONFIG_WPS -#ifdef IEEE80211_IOCTL_FILTERFRAME -#include - -#ifndef ETH_P_80211_RAW -#define ETH_P_80211_RAW 0x0019 -#endif -#endif /* IEEE80211_IOCTL_FILTERFRAME */ -#endif /* CONFIG_WPS */ - -/* - * Avoid conflicts with hostapd definitions by undefining couple of defines - * from madwifi header files. - */ -#undef WPA_OUI_TYPE -#undef WME_OUI_TYPE - -#include "wireless_copy.h" - -#include "hostapd.h" -#include "driver.h" -#include "eloop.h" -#include "priv_netlink.h" -#include "l2_packet/l2_packet.h" - -#include "wps_hostapd.h" -#include "ieee802_11_defs.h" - - -struct madwifi_driver_data { - struct hostapd_data *hapd; /* back pointer */ - - char iface[IFNAMSIZ + 1]; - int ifindex; - struct l2_packet_data *sock_xmit; /* raw packet xmit socket */ - struct l2_packet_data *sock_recv; /* raw packet recv socket */ - int ioctl_sock; /* socket for ioctl() use */ - int wext_sock; /* socket for wireless events */ - int we_version; - u8 acct_mac[ETH_ALEN]; - struct hostap_sta_driver_data acct_data; - - struct l2_packet_data *sock_raw; /* raw 802.11 management frames */ -}; - -static int madwifi_sta_deauth(void *priv, const u8 *addr, int reason_code); - -/* hostapd 0.7.x compatibility - START */ -#include "ieee802_1x.h" -#include "sta_info.h" -#include "wpa.h" -#include "radius/radius.h" -#include "ieee802_11.h" -#include "accounting.h" - -static int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, - const u8 *ie, size_t ielen) -{ - struct sta_info *sta; - int new_assoc, res; - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "associated"); - - sta = ap_get_sta(hapd, addr); - if (sta) { - accounting_sta_stop(hapd, sta); - } else { - sta = ap_sta_add(hapd, addr); - if (sta == NULL) - return -1; - } - sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); - - if (hapd->conf->wpa) { - if (ie == NULL || ielen == 0) { - if (hapd->conf->wps_state) { - wpa_printf(MSG_DEBUG, "STA did not include " - "WPA/RSN IE in (Re)Association " - "Request - possible WPS use"); - sta->flags |= WLAN_STA_MAYBE_WPS; - goto skip_wpa_check; - } - - wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA"); - return -1; - } - if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 && - os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) { - sta->flags |= WLAN_STA_WPS; - goto skip_wpa_check; - } - - if (sta->wpa_sm == NULL) - sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, - sta->addr); - if (sta->wpa_sm == NULL) { - wpa_printf(MSG_ERROR, "Failed to initialize WPA state " - "machine"); - return -1; - } - res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, - ie, ielen, NULL, 0); - if (res != WPA_IE_OK) { - wpa_printf(MSG_DEBUG, "WPA/RSN information element " - "rejected? (res %u)", res); - wpa_hexdump(MSG_DEBUG, "IE", ie, ielen); - return -1; - } - } else if (hapd->conf->wps_state) { - if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 && - os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) { - sta->flags |= WLAN_STA_WPS; - } else - sta->flags |= WLAN_STA_MAYBE_WPS; - } -skip_wpa_check: - - new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0; - sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; - wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); - - hostapd_new_assoc_sta(hapd, sta, !new_assoc); - - ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); - - return 0; -} - - -static void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr) -{ - struct sta_info *sta; - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "disassociated"); - - sta = ap_get_sta(hapd, addr); - if (sta == NULL) { - wpa_printf(MSG_DEBUG, "Disassociation notification for " - "unknown STA " MACSTR, MAC2STR(addr)); - return; - } - - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); - wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); - sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; - ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - ap_free_sta(hapd, sta); -} - - -static void hostapd_eapol_receive(struct hostapd_data *hapd, const u8 *sa, - const u8 *buf, size_t len) -{ - ieee802_1x_receive(hapd, sa, buf, len); -} - - -static void hostapd_michael_mic_failure(struct hostapd_data *hapd, - const u8 *addr) -{ - ieee80211_michael_mic_failure(hapd, addr, 1); -} -/* hostapd 0.7.x compatibility - END */ - -static int -set80211priv(struct madwifi_driver_data *drv, int op, void *data, int len) -{ - struct iwreq iwr; - int do_inline = len < IFNAMSIZ; - - /* Certain ioctls must use the non-inlined method */ - if (op == IEEE80211_IOCTL_SET_APPIEBUF || - op == IEEE80211_IOCTL_FILTERFRAME) - do_inline = 0; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - if (do_inline) { - /* - * Argument data fits inline; put it there. - */ - memcpy(iwr.u.name, data, len); - } else { - /* - * Argument data too big for inline transfer; setup a - * parameter block instead; the kernel will transfer - * the data for the driver. - */ - iwr.u.data.pointer = data; - iwr.u.data.length = len; - } - - if (ioctl(drv->ioctl_sock, op, &iwr) < 0) { - int first = IEEE80211_IOCTL_SETPARAM; - static const char *opnames[] = { - "ioctl[IEEE80211_IOCTL_SETPARAM]", - "ioctl[IEEE80211_IOCTL_GETPARAM]", - "ioctl[IEEE80211_IOCTL_SETKEY]", - "ioctl[IEEE80211_IOCTL_SETWMMPARAMS]", - "ioctl[IEEE80211_IOCTL_DELKEY]", - "ioctl[IEEE80211_IOCTL_GETWMMPARAMS]", - "ioctl[IEEE80211_IOCTL_SETMLME]", - "ioctl[IEEE80211_IOCTL_GETCHANINFO]", - "ioctl[IEEE80211_IOCTL_SETOPTIE]", - "ioctl[IEEE80211_IOCTL_GETOPTIE]", - "ioctl[IEEE80211_IOCTL_ADDMAC]", - "ioctl[IEEE80211_IOCTL_DELMAC]", - "ioctl[IEEE80211_IOCTL_GETCHANLIST]", - "ioctl[IEEE80211_IOCTL_SETCHANLIST]", - "ioctl[IEEE80211_IOCTL_KICKMAC]", - "ioctl[IEEE80211_IOCTL_CHANSWITCH]", - "ioctl[IEEE80211_IOCTL_GETMODE]", - "ioctl[IEEE80211_IOCTL_SETMODE]", - "ioctl[IEEE80211_IOCTL_GET_APPIEBUF]", - "ioctl[IEEE80211_IOCTL_SET_APPIEBUF]", - NULL, - "ioctl[IEEE80211_IOCTL_FILTERFRAME]", - }; - int idx = op - first; - if (first <= op && - idx < (int) (sizeof(opnames) / sizeof(opnames[0])) && - opnames[idx]) - perror(opnames[idx]); - else { - perror("ioctl[unknown???]"); - wpa_printf(MSG_DEBUG, "Failed ioctl: 0x%x", op); - } - return -1; - } - return 0; -} - -static int -set80211param(struct madwifi_driver_data *drv, int op, int arg) -{ - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.mode = op; - memcpy(iwr.u.name+sizeof(__u32), &arg, sizeof(arg)); - - if (ioctl(drv->ioctl_sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) { - perror("ioctl[IEEE80211_IOCTL_SETPARAM]"); - wpa_printf(MSG_DEBUG, "%s: Failed to set parameter (op %d " - "arg %d)", __func__, op, arg); - return -1; - } - return 0; -} - -#ifndef CONFIG_NO_STDOUT_DEBUG -static const char * -ether_sprintf(const u8 *addr) -{ - static char buf[sizeof(MACSTR)]; - - if (addr != NULL) - snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr)); - else - snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0); - return buf; -} -#endif /* CONFIG_NO_STDOUT_DEBUG */ - -/* - * Configure WPA parameters. - */ -static int -madwifi_configure_wpa(struct madwifi_driver_data *drv) -{ - struct hostapd_data *hapd = drv->hapd; - struct hostapd_bss_config *conf = hapd->conf; - int v; - - switch (conf->wpa_group) { - case WPA_CIPHER_CCMP: - v = IEEE80211_CIPHER_AES_CCM; - break; - case WPA_CIPHER_TKIP: - v = IEEE80211_CIPHER_TKIP; - break; - case WPA_CIPHER_WEP104: - v = IEEE80211_CIPHER_WEP; - break; - case WPA_CIPHER_WEP40: - v = IEEE80211_CIPHER_WEP; - break; - case WPA_CIPHER_NONE: - v = IEEE80211_CIPHER_NONE; - break; - default: - wpa_printf(MSG_ERROR, "Unknown group key cipher %u", - conf->wpa_group); - return -1; - } - wpa_printf(MSG_DEBUG, "%s: group key cipher=%d", __func__, v); - if (set80211param(drv, IEEE80211_PARAM_MCASTCIPHER, v)) { - printf("Unable to set group key cipher to %u\n", v); - return -1; - } - if (v == IEEE80211_CIPHER_WEP) { - /* key length is done only for specific ciphers */ - v = (conf->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5); - if (set80211param(drv, IEEE80211_PARAM_MCASTKEYLEN, v)) { - printf("Unable to set group key length to %u\n", v); - return -1; - } - } - - v = 0; - if (conf->wpa_pairwise & WPA_CIPHER_CCMP) - v |= 1<wpa_pairwise & WPA_CIPHER_TKIP) - v |= 1<wpa_pairwise & WPA_CIPHER_NONE) - v |= 1<wpa_key_mgmt); - if (set80211param(drv, IEEE80211_PARAM_KEYMGTALGS, conf->wpa_key_mgmt)) { - printf("Unable to set key management algorithms to 0x%x\n", - conf->wpa_key_mgmt); - return -1; - } - - v = 0; - if (conf->rsn_preauth) - v |= BIT(0); - wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x", - __func__, conf->rsn_preauth); - if (set80211param(drv, IEEE80211_PARAM_RSNCAPS, v)) { - printf("Unable to set RSN capabilities to 0x%x\n", v); - return -1; - } - - wpa_printf(MSG_DEBUG, "%s: enable WPA=0x%x", __func__, conf->wpa); - if (set80211param(drv, IEEE80211_PARAM_WPA, conf->wpa)) { - printf("Unable to set WPA to %u\n", conf->wpa); - return -1; - } - return 0; -} - - -static int -madwifi_set_iface_flags(void *priv, int dev_up) -{ - struct madwifi_driver_data *drv = priv; - struct ifreq ifr; - - wpa_printf(MSG_DEBUG, "%s: dev_up=%d", __func__, dev_up); - - if (drv->ioctl_sock < 0) - return -1; - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ); - - if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCGIFFLAGS]"); - return -1; - } - - if (dev_up) - ifr.ifr_flags |= IFF_UP; - else - ifr.ifr_flags &= ~IFF_UP; - - if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCSIFFLAGS]"); - return -1; - } - - if (dev_up) { - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ); - ifr.ifr_mtu = HOSTAPD_MTU; - if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) { - perror("ioctl[SIOCSIFMTU]"); - printf("Setting MTU failed - trying to survive with " - "current value\n"); - } - } - - return 0; -} - -static int -madwifi_set_ieee8021x(const char *ifname, void *priv, int enabled) -{ - struct madwifi_driver_data *drv = priv; - struct hostapd_data *hapd = drv->hapd; - struct hostapd_bss_config *conf = hapd->conf; - - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - - if (!enabled) { - /* XXX restore state */ - return set80211param(priv, IEEE80211_PARAM_AUTHMODE, - IEEE80211_AUTH_AUTO); - } - if (!conf->wpa && !conf->ieee802_1x) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER, - HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!"); - return -1; - } - if (conf->wpa && madwifi_configure_wpa(drv) != 0) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER, - HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!"); - return -1; - } - if (set80211param(priv, IEEE80211_PARAM_AUTHMODE, - (conf->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER, - HOSTAPD_LEVEL_WARNING, "Error enabling WPA/802.1X!"); - return -1; - } - - return 0; -} - -static int -madwifi_set_privacy(const char *ifname, void *priv, int enabled) -{ - struct madwifi_driver_data *drv = priv; - - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - - return set80211param(drv, IEEE80211_PARAM_PRIVACY, enabled); -} - -static int -madwifi_set_sta_authorized(void *priv, const u8 *addr, int authorized) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s authorized=%d", - __func__, ether_sprintf(addr), authorized); - - if (authorized) - mlme.im_op = IEEE80211_MLME_AUTHORIZE; - else - mlme.im_op = IEEE80211_MLME_UNAUTHORIZE; - mlme.im_reason = 0; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to %sauthorize STA " MACSTR, - __func__, authorized ? "" : "un", MAC2STR(addr)); - } - - return ret; -} - -static int -madwifi_sta_set_flags(void *priv, const u8 *addr, int total_flags, - int flags_or, int flags_and) -{ - /* For now, only support setting Authorized flag */ - if (flags_or & WLAN_STA_AUTHORIZED) - return madwifi_set_sta_authorized(priv, addr, 1); - if (!(flags_and & WLAN_STA_AUTHORIZED)) - return madwifi_set_sta_authorized(priv, addr, 0); - return 0; -} - -static int -madwifi_del_key(void *priv, const u8 *addr, int key_idx) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_del_key wk; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s key_idx=%d", - __func__, ether_sprintf(addr), key_idx); - - memset(&wk, 0, sizeof(wk)); - if (addr != NULL) { - memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); - wk.idk_keyix = (u8) IEEE80211_KEYIX_NONE; - } else { - wk.idk_keyix = key_idx; - } - - ret = set80211priv(drv, IEEE80211_IOCTL_DELKEY, &wk, sizeof(wk)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to delete key (addr %s" - " key_idx %d)", __func__, ether_sprintf(addr), - key_idx); - } - - return ret; -} - -static int -madwifi_set_key(const char *ifname, void *priv, const char *alg, - const u8 *addr, int key_idx, - const u8 *key, size_t key_len, int txkey) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_key wk; - u_int8_t cipher; - int ret; - - if (strcmp(alg, "none") == 0) - return madwifi_del_key(drv, addr, key_idx); - - wpa_printf(MSG_DEBUG, "%s: alg=%s addr=%s key_idx=%d", - __func__, alg, ether_sprintf(addr), key_idx); - - if (strcmp(alg, "WEP") == 0) - cipher = IEEE80211_CIPHER_WEP; - else if (strcmp(alg, "TKIP") == 0) - cipher = IEEE80211_CIPHER_TKIP; - else if (strcmp(alg, "CCMP") == 0) - cipher = IEEE80211_CIPHER_AES_CCM; - else { - printf("%s: unknown/unsupported algorithm %s\n", - __func__, alg); - return -1; - } - - if (key_len > sizeof(wk.ik_keydata)) { - printf("%s: key length %lu too big\n", __func__, - (unsigned long) key_len); - return -3; - } - - memset(&wk, 0, sizeof(wk)); - wk.ik_type = cipher; - wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT; - if (addr == NULL) { - memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); - wk.ik_keyix = key_idx; - wk.ik_flags |= IEEE80211_KEY_DEFAULT; - } else { - memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); - wk.ik_keyix = IEEE80211_KEYIX_NONE; - } - wk.ik_keylen = key_len; - memcpy(wk.ik_keydata, key, key_len); - - ret = set80211priv(drv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to set key (addr %s" - " key_idx %d alg '%s' key_len %lu txkey %d)", - __func__, ether_sprintf(wk.ik_macaddr), key_idx, - alg, (unsigned long) key_len, txkey); - } - - return ret; -} - - -static int -madwifi_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx, - u8 *seq) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_key wk; - - wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d", - __func__, ether_sprintf(addr), idx); - - memset(&wk, 0, sizeof(wk)); - if (addr == NULL) - memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); - else - memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); - wk.ik_keyix = idx; - - if (set80211priv(drv, IEEE80211_IOCTL_GETKEY, &wk, sizeof(wk))) { - wpa_printf(MSG_DEBUG, "%s: Failed to get encryption data " - "(addr " MACSTR " key_idx %d)", - __func__, MAC2STR(wk.ik_macaddr), idx); - return -1; - } - -#ifdef WORDS_BIGENDIAN - { - /* - * wk.ik_keytsc is in host byte order (big endian), need to - * swap it to match with the byte order used in WPA. - */ - int i; - u8 tmp[WPA_KEY_RSC_LEN]; - memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); - for (i = 0; i < WPA_KEY_RSC_LEN; i++) { - seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1]; - } - } -#else /* WORDS_BIGENDIAN */ - memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); -#endif /* WORDS_BIGENDIAN */ - return 0; -} - - -static int -madwifi_flush(void *priv) -{ - u8 allsta[IEEE80211_ADDR_LEN]; - memset(allsta, 0xff, IEEE80211_ADDR_LEN); - return madwifi_sta_deauth(priv, allsta, IEEE80211_REASON_AUTH_LEAVE); -} - - -static int -madwifi_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data, - const u8 *addr) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_sta_stats stats; - - memset(data, 0, sizeof(*data)); - - /* - * Fetch statistics for station from the system. - */ - memset(&stats, 0, sizeof(stats)); - memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN); - if (set80211priv(drv, IEEE80211_IOCTL_STA_STATS, - &stats, sizeof(stats))) { - wpa_printf(MSG_DEBUG, "%s: Failed to fetch STA stats (addr " - MACSTR ")", __func__, MAC2STR(addr)); - if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) { - memcpy(data, &drv->acct_data, sizeof(*data)); - return 0; - } - - printf("Failed to get station stats information element.\n"); - return -1; - } - - data->rx_packets = stats.is_stats.ns_rx_data; - data->rx_bytes = stats.is_stats.ns_rx_bytes; - data->tx_packets = stats.is_stats.ns_tx_data; - data->tx_bytes = stats.is_stats.ns_tx_bytes; - return 0; -} - - -static int -madwifi_sta_clear_stats(void *priv, const u8 *addr) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s", __func__, ether_sprintf(addr)); - - mlme.im_op = IEEE80211_MLME_CLEAR_STATS; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, - sizeof(mlme)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to clear STA stats (addr " - MACSTR ")", __func__, MAC2STR(addr)); - } - - return ret; -} - - -static int -madwifi_set_opt_ie(const char *ifname, void *priv, const u8 *ie, size_t ie_len) -{ - /* - * Do nothing; we setup parameters at startup that define the - * contents of the beacon information element. - */ - return 0; -} - -static int -madwifi_sta_deauth(void *priv, const u8 *addr, int reason_code) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d", - __func__, ether_sprintf(addr), reason_code); - - mlme.im_op = IEEE80211_MLME_DEAUTH; - mlme.im_reason = reason_code; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to deauth STA (addr " MACSTR - " reason %d)", - __func__, MAC2STR(addr), reason_code); - } - - return ret; -} - -static int -madwifi_sta_disassoc(void *priv, const u8 *addr, int reason_code) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d", - __func__, ether_sprintf(addr), reason_code); - - mlme.im_op = IEEE80211_MLME_DISASSOC; - mlme.im_reason = reason_code; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to disassoc STA (addr " - MACSTR " reason %d)", - __func__, MAC2STR(addr), reason_code); - } - - return ret; -} - -#ifdef CONFIG_WPS -static void madwifi_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf, - size_t len) -{ - struct madwifi_driver_data *drv = ctx; - const struct ieee80211_mgmt *mgmt; - const u8 *end, *ie; - u16 fc; - size_t ie_len; - - /* Send Probe Request information to WPS processing */ - - if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)) - return; - mgmt = (const struct ieee80211_mgmt *) buf; - - fc = le_to_host16(mgmt->frame_control); - if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT || - WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_PROBE_REQ) - return; - - end = buf + len; - ie = mgmt->u.probe_req.variable; - ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)); - - hostapd_wps_probe_req_rx(drv->hapd, mgmt->sa, ie, ie_len); -} -#endif /* CONFIG_WPS */ - -static int madwifi_receive_probe_req(struct madwifi_driver_data *drv) -{ - int ret = 0; -#ifdef CONFIG_WPS - struct ieee80211req_set_filter filt; - - wpa_printf(MSG_DEBUG, "%s Enter", __func__); - filt.app_filterype = IEEE80211_FILTER_TYPE_PROBE_REQ; - - ret = set80211priv(drv, IEEE80211_IOCTL_FILTERFRAME, &filt, - sizeof(struct ieee80211req_set_filter)); - if (ret) - return ret; - - drv->sock_raw = l2_packet_init(drv->iface, NULL, ETH_P_80211_RAW, - madwifi_raw_receive, drv, 1); - if (drv->sock_raw == NULL) - return -1; -#endif /* CONFIG_WPS */ - return ret; -} - -#ifdef CONFIG_WPS -static int -madwifi_set_wps_ie(void *priv, const u8 *ie, size_t len, u32 frametype) -{ - struct madwifi_driver_data *drv = priv; - u8 buf[256]; - struct ieee80211req_getset_appiebuf *beac_ie; - - wpa_printf(MSG_DEBUG, "%s buflen = %lu", __func__, - (unsigned long) len); - - beac_ie = (struct ieee80211req_getset_appiebuf *) buf; - beac_ie->app_frmtype = frametype; - beac_ie->app_buflen = len; - memcpy(&(beac_ie->app_buf[0]), ie, len); - - return set80211priv(drv, IEEE80211_IOCTL_SET_APPIEBUF, beac_ie, - sizeof(struct ieee80211req_getset_appiebuf) + len); -} - -static int -madwifi_set_wps_beacon_ie(const char *ifname, void *priv, const u8 *ie, - size_t len) -{ - return madwifi_set_wps_ie(priv, ie, len, IEEE80211_APPIE_FRAME_BEACON); -} - -static int -madwifi_set_wps_probe_resp_ie(const char *ifname, void *priv, const u8 *ie, - size_t len) -{ - return madwifi_set_wps_ie(priv, ie, len, - IEEE80211_APPIE_FRAME_PROBE_RESP); -} -#else /* CONFIG_WPS */ -#define madwifi_set_wps_beacon_ie NULL -#define madwifi_set_wps_probe_resp_ie NULL -#endif /* CONFIG_WPS */ - -static int -madwifi_new_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN]) -{ - struct hostapd_data *hapd = drv->hapd; - struct ieee80211req_wpaie ie; - int ielen = 0, res; - u8 *iebuf = NULL; - - /* - * Fetch negotiated WPA/RSN parameters from the system. - */ - memset(&ie, 0, sizeof(ie)); - memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN); - if (set80211priv(drv, IEEE80211_IOCTL_GETWPAIE, &ie, sizeof(ie))) { - /* - * See ATH_WPS_IE comment in the beginning of the file for a - * possible cause for the failure.. - */ - wpa_printf(MSG_DEBUG, "%s: Failed to get WPA/RSN IE: %s", - __func__, strerror(errno)); - goto no_ie; - } - wpa_hexdump(MSG_MSGDUMP, "madwifi req WPA IE", - ie.wpa_ie, IEEE80211_MAX_OPT_IE); - wpa_hexdump(MSG_MSGDUMP, "madwifi req RSN IE", - ie.rsn_ie, IEEE80211_MAX_OPT_IE); - iebuf = ie.wpa_ie; - /* madwifi seems to return some random data if WPA/RSN IE is not set. - * Assume the IE was not included if the IE type is unknown. */ - if (iebuf[0] != WLAN_EID_VENDOR_SPECIFIC) - iebuf[1] = 0; - if (iebuf[1] == 0 && ie.rsn_ie[1] > 0) { - /* madwifi-ng svn #1453 added rsn_ie. Use it, if wpa_ie was not - * set. This is needed for WPA2. */ - iebuf = ie.rsn_ie; - if (iebuf[0] != WLAN_EID_RSN) - iebuf[1] = 0; - } - - ielen = iebuf[1]; - if (ielen == 0) - iebuf = NULL; - else - ielen += 2; - -no_ie: - res = hostapd_notif_assoc(hapd, addr, iebuf, ielen); - - if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) { - /* Cached accounting data is not valid anymore. */ - memset(drv->acct_mac, 0, ETH_ALEN); - memset(&drv->acct_data, 0, sizeof(drv->acct_data)); - } - - return res; -} - -static void -madwifi_wireless_event_wireless_custom(struct madwifi_driver_data *drv, - char *custom, char *end) -{ - wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom); - - if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) { - char *pos; - u8 addr[ETH_ALEN]; - pos = strstr(custom, "addr="); - if (pos == NULL) { - wpa_printf(MSG_DEBUG, - "MLME-MICHAELMICFAILURE.indication " - "without sender address ignored"); - return; - } - pos += 5; - if (hwaddr_aton(pos, addr) == 0) { - hostapd_michael_mic_failure(drv->hapd, addr); - } else { - wpa_printf(MSG_DEBUG, - "MLME-MICHAELMICFAILURE.indication " - "with invalid MAC address"); - } - } else if (strncmp(custom, "STA-TRAFFIC-STAT", 16) == 0) { - char *key, *value; - u32 val; - key = custom; - while ((key = strchr(key, '\n')) != NULL) { - key++; - value = strchr(key, '='); - if (value == NULL) - continue; - *value++ = '\0'; - val = strtoul(value, NULL, 10); - if (strcmp(key, "mac") == 0) - hwaddr_aton(value, drv->acct_mac); - else if (strcmp(key, "rx_packets") == 0) - drv->acct_data.rx_packets = val; - else if (strcmp(key, "tx_packets") == 0) - drv->acct_data.tx_packets = val; - else if (strcmp(key, "rx_bytes") == 0) - drv->acct_data.rx_bytes = val; - else if (strcmp(key, "tx_bytes") == 0) - drv->acct_data.tx_bytes = val; - key = value; - } -#ifdef CONFIG_WPS - } else if (strncmp(custom, "PUSH-BUTTON.indication", 22) == 0) { - /* Some atheros kernels send push button as a wireless event */ - /* PROBLEM! this event is received for ALL BSSs ... - * so all are enabled for WPS... ugh. - */ - hostapd_wps_button_pushed(drv->hapd); - } else if (strncmp(custom, "Manage.prob_req ", 16) == 0) { - /* - * Atheros driver uses a hack to pass Probe Request frames as a - * binary data in the custom wireless event. The old way (using - * packet sniffing) didn't work when bridging. - * Format: "Manage.prob_req " | zero padding | frame - */ -#define WPS_FRAM_TAG_SIZE 30 /* hardcoded in driver */ - int len = atoi(custom + 16); - if (len < 0 || custom + WPS_FRAM_TAG_SIZE + len > end) { - wpa_printf(MSG_DEBUG, "Invalid Manage.prob_req event " - "length %d", len); - return; - } - madwifi_raw_receive(drv, NULL, - (u8 *) custom + WPS_FRAM_TAG_SIZE, len); -#endif /* CONFIG_WPS */ - } -} - -static void -madwifi_wireless_event_wireless(struct madwifi_driver_data *drv, - char *data, int len) -{ - struct iw_event iwe_buf, *iwe = &iwe_buf; - char *pos, *end, *custom, *buf; - - pos = data; - end = data + len; - - while (pos + IW_EV_LCP_LEN <= end) { - /* Event data may be unaligned, so make a local, aligned copy - * before processing. */ - memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); - wpa_printf(MSG_MSGDUMP, "Wireless event: cmd=0x%x len=%d", - iwe->cmd, iwe->len); - if (iwe->len <= IW_EV_LCP_LEN) - return; - - custom = pos + IW_EV_POINT_LEN; - if (drv->we_version > 18 && - (iwe->cmd == IWEVMICHAELMICFAILURE || - iwe->cmd == IWEVASSOCREQIE || - iwe->cmd == IWEVCUSTOM)) { - /* WE-19 removed the pointer from struct iw_point */ - char *dpos = (char *) &iwe_buf.u.data.length; - int dlen = dpos - (char *) &iwe_buf; - memcpy(dpos, pos + IW_EV_LCP_LEN, - sizeof(struct iw_event) - dlen); - } else { - memcpy(&iwe_buf, pos, sizeof(struct iw_event)); - custom += IW_EV_POINT_OFF; - } - - switch (iwe->cmd) { - case IWEVEXPIRED: - hostapd_notif_disassoc(drv->hapd, - (u8 *) iwe->u.addr.sa_data); - break; - case IWEVREGISTERED: - madwifi_new_sta(drv, (u8 *) iwe->u.addr.sa_data); - break; - case IWEVASSOCREQIE: - /* Driver hack.. Use IWEVASSOCREQIE to bypass - * IWEVCUSTOM size limitations. Need to handle this - * just like IWEVCUSTOM. - */ - case IWEVCUSTOM: - if (custom + iwe->u.data.length > end) - return; - buf = malloc(iwe->u.data.length + 1); - if (buf == NULL) - return; /* XXX */ - memcpy(buf, custom, iwe->u.data.length); - buf[iwe->u.data.length] = '\0'; - madwifi_wireless_event_wireless_custom( - drv, buf, buf + iwe->u.data.length); - free(buf); - break; - } - - pos += iwe->len; - } -} - - -static void -madwifi_wireless_event_rtm_newlink(struct madwifi_driver_data *drv, - struct nlmsghdr *h, int len) -{ - struct ifinfomsg *ifi; - int attrlen, nlmsg_len, rta_len; - struct rtattr * attr; - - if (len < (int) sizeof(*ifi)) - return; - - ifi = NLMSG_DATA(h); - - if (ifi->ifi_index != drv->ifindex) - return; - - nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); - - attrlen = h->nlmsg_len - nlmsg_len; - if (attrlen < 0) - return; - - attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_WIRELESS) { - madwifi_wireless_event_wireless( - drv, ((char *) attr) + rta_len, - attr->rta_len - rta_len); - } - attr = RTA_NEXT(attr, attrlen); - } -} - - -static void -madwifi_wireless_event_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - char buf[256]; - int left; - struct sockaddr_nl from; - socklen_t fromlen; - struct nlmsghdr *h; - struct madwifi_driver_data *drv = eloop_ctx; - - fromlen = sizeof(from); - left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, - (struct sockaddr *) &from, &fromlen); - if (left < 0) { - if (errno != EINTR && errno != EAGAIN) - perror("recvfrom(netlink)"); - return; - } - - h = (struct nlmsghdr *) buf; - while (left >= (int) sizeof(*h)) { - int len, plen; - - len = h->nlmsg_len; - plen = len - sizeof(*h); - if (len > left || plen < 0) { - printf("Malformed netlink message: " - "len=%d left=%d plen=%d\n", - len, left, plen); - break; - } - - switch (h->nlmsg_type) { - case RTM_NEWLINK: - madwifi_wireless_event_rtm_newlink(drv, h, plen); - break; - } - - len = NLMSG_ALIGN(len); - left -= len; - h = (struct nlmsghdr *) ((char *) h + len); - } - - if (left > 0) { - printf("%d extra bytes in the end of netlink message\n", left); - } -} - - -static int -madwifi_get_we_version(struct madwifi_driver_data *drv) -{ - struct iw_range *range; - struct iwreq iwr; - int minlen; - size_t buflen; - - drv->we_version = 0; - - /* - * Use larger buffer than struct iw_range in order to allow the - * structure to grow in the future. - */ - buflen = sizeof(struct iw_range) + 500; - range = os_zalloc(buflen); - if (range == NULL) - return -1; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) range; - iwr.u.data.length = buflen; - - minlen = ((char *) &range->enc_capa) - (char *) range + - sizeof(range->enc_capa); - - if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) { - perror("ioctl[SIOCGIWRANGE]"); - free(range); - return -1; - } else if (iwr.u.data.length >= minlen && - range->we_version_compiled >= 18) { - wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d " - "WE(source)=%d enc_capa=0x%x", - range->we_version_compiled, - range->we_version_source, - range->enc_capa); - drv->we_version = range->we_version_compiled; - } - - free(range); - return 0; -} - - -static int -madwifi_wireless_event_init(void *priv) -{ - struct madwifi_driver_data *drv = priv; - int s; - struct sockaddr_nl local; - - madwifi_get_we_version(drv); - - drv->wext_sock = -1; - - s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (s < 0) { - perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)"); - return -1; - } - - memset(&local, 0, sizeof(local)); - local.nl_family = AF_NETLINK; - local.nl_groups = RTMGRP_LINK; - if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) { - perror("bind(netlink)"); - close(s); - return -1; - } - - eloop_register_read_sock(s, madwifi_wireless_event_receive, drv, NULL); - drv->wext_sock = s; - - return 0; -} - - -static void -madwifi_wireless_event_deinit(void *priv) -{ - struct madwifi_driver_data *drv = priv; - - if (drv != NULL) { - if (drv->wext_sock < 0) - return; - eloop_unregister_read_sock(drv->wext_sock); - close(drv->wext_sock); - } -} - - -static int -madwifi_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len, - int encrypt, const u8 *own_addr) -{ - struct madwifi_driver_data *drv = priv; - unsigned char buf[3000]; - unsigned char *bp = buf; - struct l2_ethhdr *eth; - size_t len; - int status; - - /* - * Prepend the Ethernet header. If the caller left us - * space at the front we could just insert it but since - * we don't know we copy to a local buffer. Given the frequency - * and size of frames this probably doesn't matter. - */ - len = data_len + sizeof(struct l2_ethhdr); - if (len > sizeof(buf)) { - bp = malloc(len); - if (bp == NULL) { - printf("EAPOL frame discarded, cannot malloc temp " - "buffer of size %lu!\n", (unsigned long) len); - return -1; - } - } - eth = (struct l2_ethhdr *) bp; - memcpy(eth->h_dest, addr, ETH_ALEN); - memcpy(eth->h_source, own_addr, ETH_ALEN); - eth->h_proto = host_to_be16(ETH_P_EAPOL); - memcpy(eth+1, data, data_len); - - wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len); - - status = l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, bp, len); - - if (bp != buf) - free(bp); - return status; -} - -static void -handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) -{ - struct madwifi_driver_data *drv = ctx; - hostapd_eapol_receive(drv->hapd, src_addr, - buf + sizeof(struct l2_ethhdr), - len - sizeof(struct l2_ethhdr)); -} - -static void * -madwifi_init(struct hostapd_data *hapd) -{ - struct madwifi_driver_data *drv; - struct ifreq ifr; - struct iwreq iwr; - - drv = os_zalloc(sizeof(struct madwifi_driver_data)); - if (drv == NULL) { - printf("Could not allocate memory for madwifi driver data\n"); - return NULL; - } - - drv->hapd = hapd; - drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->ioctl_sock < 0) { - perror("socket[PF_INET,SOCK_DGRAM]"); - goto bad; - } - memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface)); - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name)); - if (ioctl(drv->ioctl_sock, SIOCGIFINDEX, &ifr) != 0) { - perror("ioctl(SIOCGIFINDEX)"); - goto bad; - } - drv->ifindex = ifr.ifr_ifindex; - - drv->sock_xmit = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL, - handle_read, drv, 1); - if (drv->sock_xmit == NULL) - goto bad; - if (l2_packet_get_own_addr(drv->sock_xmit, hapd->own_addr)) - goto bad; - if (hapd->conf->bridge[0] != '\0') { - wpa_printf(MSG_DEBUG, "Configure bridge %s for EAPOL traffic.", - hapd->conf->bridge); - drv->sock_recv = l2_packet_init(hapd->conf->bridge, NULL, - ETH_P_EAPOL, handle_read, drv, - 1); - if (drv->sock_recv == NULL) - goto bad; - } else - drv->sock_recv = drv->sock_xmit; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - - iwr.u.mode = IW_MODE_MASTER; - - if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) { - perror("ioctl[SIOCSIWMODE]"); - printf("Could not set interface to master mode!\n"); - goto bad; - } - - madwifi_set_iface_flags(drv, 0); /* mark down during setup */ - madwifi_set_privacy(drv->iface, drv, 0); /* default to no privacy */ - - madwifi_receive_probe_req(drv); - - return drv; -bad: - if (drv->sock_xmit != NULL) - l2_packet_deinit(drv->sock_xmit); - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - if (drv != NULL) - free(drv); - return NULL; -} - - -static void -madwifi_deinit(void *priv) -{ - struct madwifi_driver_data *drv = priv; - - (void) madwifi_set_iface_flags(drv, 0); - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - if (drv->sock_recv != NULL && drv->sock_recv != drv->sock_xmit) - l2_packet_deinit(drv->sock_recv); - if (drv->sock_xmit != NULL) - l2_packet_deinit(drv->sock_xmit); - if (drv->sock_raw) - l2_packet_deinit(drv->sock_raw); - free(drv); -} - -static int -madwifi_set_ssid(const char *ifname, void *priv, const u8 *buf, int len) -{ - struct madwifi_driver_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.essid.flags = 1; /* SSID active */ - iwr.u.essid.pointer = (caddr_t) buf; - iwr.u.essid.length = len + 1; - - if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) { - perror("ioctl[SIOCSIWESSID]"); - printf("len=%d\n", len); - return -1; - } - return 0; -} - -static int -madwifi_get_ssid(const char *ifname, void *priv, u8 *buf, int len) -{ - struct madwifi_driver_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.essid.pointer = (caddr_t) buf; - iwr.u.essid.length = len; - - if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) { - perror("ioctl[SIOCGIWESSID]"); - ret = -1; - } else - ret = iwr.u.essid.length; - - return ret; -} - -static int -madwifi_set_countermeasures(void *priv, int enabled) -{ - struct madwifi_driver_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - return set80211param(drv, IEEE80211_PARAM_COUNTERMEASURES, enabled); -} - -static int -madwifi_commit(void *priv) -{ - return madwifi_set_iface_flags(priv, 1); -} - -const struct wpa_driver_ops wpa_driver_atheros_ops = { - .name = "atheros", - .init = madwifi_init, - .deinit = madwifi_deinit, - .set_ieee8021x = madwifi_set_ieee8021x, - .set_privacy = madwifi_set_privacy, - .set_encryption = madwifi_set_key, - .get_seqnum = madwifi_get_seqnum, - .flush = madwifi_flush, - .set_generic_elem = madwifi_set_opt_ie, - .wireless_event_init = madwifi_wireless_event_init, - .wireless_event_deinit = madwifi_wireless_event_deinit, - .sta_set_flags = madwifi_sta_set_flags, - .read_sta_data = madwifi_read_sta_driver_data, - .send_eapol = madwifi_send_eapol, - .sta_disassoc = madwifi_sta_disassoc, - .sta_deauth = madwifi_sta_deauth, - .set_ssid = madwifi_set_ssid, - .get_ssid = madwifi_get_ssid, - .set_countermeasures = madwifi_set_countermeasures, - .sta_clear_stats = madwifi_sta_clear_stats, - .commit = madwifi_commit, - .set_wps_beacon_ie = madwifi_set_wps_beacon_ie, - .set_wps_probe_resp_ie = madwifi_set_wps_probe_resp_ie, -}; diff --git a/contrib/hostapd/hostapd/driver_bsd.c b/contrib/hostapd/hostapd/driver_bsd.c deleted file mode 100644 index 43d57d9091..0000000000 --- a/contrib/hostapd/hostapd/driver_bsd.c +++ /dev/null @@ -1,839 +0,0 @@ -/* - * hostapd / Driver interaction with BSD net80211 layer - * Copyright (c) 2004, Sam Leffler - * Copyright (c) 2004, 2Wire, Inc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include - -#include -#include -#include - -/* - * Avoid conflicts with hostapd definitions by undefining couple of defines - * from net80211 header files. - */ -#undef RSN_VERSION -#undef WPA_VERSION -#undef WPA_OUI_TYPE -#undef WME_OUI_TYPE - -#include "hostapd.h" -#include "driver.h" -#include "ieee802_1x.h" -#include "eloop.h" -#include "sta_info.h" -#include "l2_packet/l2_packet.h" - -#include "eapol_sm.h" -#include "wpa.h" -#include "radius/radius.h" -#include "ieee802_11.h" -#include "common.h" - -struct bsd_driver_data { - struct hostapd_data *hapd; /* back pointer */ - - char iface[IFNAMSIZ + 1]; - struct l2_packet_data *sock_xmit; /* raw packet xmit socket */ - int ioctl_sock; /* socket for ioctl() use */ - int wext_sock; /* socket for wireless events */ -}; - -static int bsd_sta_deauth(void *priv, const u8 *addr, int reason_code); - -static int -set80211var(struct bsd_driver_data *drv, int op, const void *arg, int arg_len) -{ - struct ieee80211req ireq; - - memset(&ireq, 0, sizeof(ireq)); - os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ); - ireq.i_type = op; - ireq.i_len = arg_len; - ireq.i_data = (void *) arg; - - if (ioctl(drv->ioctl_sock, SIOCS80211, &ireq) < 0) { - perror("ioctl[SIOCS80211]"); - return -1; - } - return 0; -} - -static int -get80211var(struct bsd_driver_data *drv, int op, void *arg, int arg_len) -{ - struct ieee80211req ireq; - - memset(&ireq, 0, sizeof(ireq)); - os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ); - ireq.i_type = op; - ireq.i_len = arg_len; - ireq.i_data = arg; - - if (ioctl(drv->ioctl_sock, SIOCG80211, &ireq) < 0) { - perror("ioctl[SIOCG80211]"); - return -1; - } - return ireq.i_len; -} - -static int -set80211param(struct bsd_driver_data *drv, int op, int arg) -{ - struct ieee80211req ireq; - - memset(&ireq, 0, sizeof(ireq)); - os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ); - ireq.i_type = op; - ireq.i_val = arg; - - if (ioctl(drv->ioctl_sock, SIOCS80211, &ireq) < 0) { - perror("ioctl[SIOCS80211]"); - return -1; - } - return 0; -} - -static const char * -ether_sprintf(const u8 *addr) -{ - static char buf[sizeof(MACSTR)]; - - if (addr != NULL) - snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr)); - else - snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0); - return buf; -} - -/* - * Configure WPA parameters. - */ -static int -bsd_configure_wpa(struct bsd_driver_data *drv) -{ - static const char *ciphernames[] = - { "WEP", "TKIP", "AES-OCB", "AES-CCM", "CKIP", "NONE" }; - struct hostapd_data *hapd = drv->hapd; - struct hostapd_bss_config *conf = hapd->conf; - int v; - - switch (conf->wpa_group) { - case WPA_CIPHER_CCMP: - v = IEEE80211_CIPHER_AES_CCM; - break; - case WPA_CIPHER_TKIP: - v = IEEE80211_CIPHER_TKIP; - break; - case WPA_CIPHER_WEP104: - v = IEEE80211_CIPHER_WEP; - break; - case WPA_CIPHER_WEP40: - v = IEEE80211_CIPHER_WEP; - break; - case WPA_CIPHER_NONE: - v = IEEE80211_CIPHER_NONE; - break; - default: - printf("Unknown group key cipher %u\n", - conf->wpa_group); - return -1; - } - wpa_printf(MSG_DEBUG, "%s: group key cipher=%s (%u)", - __func__, ciphernames[v], v); - if (set80211param(drv, IEEE80211_IOC_MCASTCIPHER, v)) { - printf("Unable to set group key cipher to %u (%s)\n", - v, ciphernames[v]); - return -1; - } - if (v == IEEE80211_CIPHER_WEP) { - /* key length is done only for specific ciphers */ - v = (conf->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5); - if (set80211param(drv, IEEE80211_IOC_MCASTKEYLEN, v)) { - printf("Unable to set group key length to %u\n", v); - return -1; - } - } - - v = 0; - if (conf->wpa_pairwise & WPA_CIPHER_CCMP) - v |= 1<wpa_pairwise & WPA_CIPHER_TKIP) - v |= 1<wpa_pairwise & WPA_CIPHER_NONE) - v |= 1<wpa_key_mgmt); - if (set80211param(drv, IEEE80211_IOC_KEYMGTALGS, conf->wpa_key_mgmt)) { - printf("Unable to set key management algorithms to 0x%x\n", - conf->wpa_key_mgmt); - return -1; - } - - v = 0; - if (conf->rsn_preauth) - v |= BIT(0); - wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x", - __func__, conf->rsn_preauth); - if (set80211param(drv, IEEE80211_IOC_RSNCAPS, v)) { - printf("Unable to set RSN capabilities to 0x%x\n", v); - return -1; - } - - wpa_printf(MSG_DEBUG, "%s: enable WPA= 0x%x", __func__, conf->wpa); - if (set80211param(drv, IEEE80211_IOC_WPA, conf->wpa)) { - printf("Unable to set WPA to %u\n", conf->wpa); - return -1; - } - return 0; -} - - -static int -bsd_set_iface_flags(void *priv, int dev_up) -{ - struct bsd_driver_data *drv = priv; - struct ifreq ifr; - - wpa_printf(MSG_DEBUG, "%s: dev_up=%d", __func__, dev_up); - - if (drv->ioctl_sock < 0) - return -1; - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ); - - if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCGIFFLAGS]"); - return -1; - } - - if (dev_up) - ifr.ifr_flags |= IFF_UP; - else - ifr.ifr_flags &= ~IFF_UP; - - if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCSIFFLAGS]"); - return -1; - } - - if (dev_up) { - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ); - ifr.ifr_mtu = HOSTAPD_MTU; - if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) { - perror("ioctl[SIOCSIFMTU]"); - printf("Setting MTU failed - trying to survive with " - "current value\n"); - } - } - - return 0; -} - -static int -bsd_set_ieee8021x(const char *ifname, void *priv, int enabled) -{ - struct bsd_driver_data *drv = priv; - struct hostapd_data *hapd = drv->hapd; - struct hostapd_bss_config *conf = hapd->conf; - - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - - if (!enabled) { - /* XXX restore state */ - return set80211param(priv, IEEE80211_IOC_AUTHMODE, - IEEE80211_AUTH_AUTO); - } - if (!conf->wpa && !conf->ieee802_1x) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER, - HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!"); - return -1; - } - if (conf->wpa && bsd_configure_wpa(drv) != 0) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER, - HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!"); - return -1; - } - if (set80211param(priv, IEEE80211_IOC_AUTHMODE, - (conf->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER, - HOSTAPD_LEVEL_WARNING, "Error enabling WPA/802.1X!"); - return -1; - } - return bsd_set_iface_flags(priv, 1); -} - -static int -bsd_set_privacy(const char *ifname, void *priv, int enabled) -{ - struct bsd_driver_data *drv = priv; - - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - - return set80211param(drv, IEEE80211_IOC_PRIVACY, enabled); -} - -static int -bsd_set_sta_authorized(void *priv, const u8 *addr, int authorized) -{ - struct bsd_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - - wpa_printf(MSG_DEBUG, "%s: addr=%s authorized=%d", - __func__, ether_sprintf(addr), authorized); - - if (authorized) - mlme.im_op = IEEE80211_MLME_AUTHORIZE; - else - mlme.im_op = IEEE80211_MLME_UNAUTHORIZE; - mlme.im_reason = 0; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); -} - -static int -bsd_sta_set_flags(void *priv, const u8 *addr, int total_flags, int flags_or, - int flags_and) -{ - /* For now, only support setting Authorized flag */ - if (flags_or & WLAN_STA_AUTHORIZED) - return bsd_set_sta_authorized(priv, addr, 1); - if (!(flags_and & WLAN_STA_AUTHORIZED)) - return bsd_set_sta_authorized(priv, addr, 0); - return 0; -} - -static int -bsd_del_key(void *priv, const u8 *addr, int key_idx) -{ - struct bsd_driver_data *drv = priv; - struct ieee80211req_del_key wk; - - wpa_printf(MSG_DEBUG, "%s: addr=%s key_idx=%d", - __func__, ether_sprintf(addr), key_idx); - - memset(&wk, 0, sizeof(wk)); - if (addr != NULL) { - memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); - wk.idk_keyix = (u_int8_t) IEEE80211_KEYIX_NONE; /* XXX */ - } else { - wk.idk_keyix = key_idx; - } - - return set80211var(drv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk)); -} - -static int -bsd_set_key(const char *ifname, void *priv, const char *alg, - const u8 *addr, int key_idx, - const u8 *key, size_t key_len, int txkey) -{ - struct bsd_driver_data *drv = priv; - struct ieee80211req_key wk; - u_int8_t cipher; - - if (strcmp(alg, "none") == 0) - return bsd_del_key(drv, addr, key_idx); - - wpa_printf(MSG_DEBUG, "%s: alg=%s addr=%s key_idx=%d", - __func__, alg, ether_sprintf(addr), key_idx); - - if (strcmp(alg, "WEP") == 0) - cipher = IEEE80211_CIPHER_WEP; - else if (strcmp(alg, "TKIP") == 0) - cipher = IEEE80211_CIPHER_TKIP; - else if (strcmp(alg, "CCMP") == 0) - cipher = IEEE80211_CIPHER_AES_CCM; - else { - printf("%s: unknown/unsupported algorithm %s\n", - __func__, alg); - return -1; - } - - if (key_len > sizeof(wk.ik_keydata)) { - printf("%s: key length %d too big\n", __func__, key_len); - return -3; - } - - memset(&wk, 0, sizeof(wk)); - wk.ik_type = cipher; - wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT; - if (addr == NULL) { - memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); - wk.ik_keyix = key_idx; - wk.ik_flags |= IEEE80211_KEY_DEFAULT; - } else { - memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); - wk.ik_keyix = IEEE80211_KEYIX_NONE; - } - wk.ik_keylen = key_len; - memcpy(wk.ik_keydata, key, key_len); - - return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)); -} - - -static int -bsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx, - u8 *seq) -{ - struct bsd_driver_data *drv = priv; - struct ieee80211req_key wk; - - wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d", - __func__, ether_sprintf(addr), idx); - - memset(&wk, 0, sizeof(wk)); - if (addr == NULL) - memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); - else - memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); - wk.ik_keyix = idx; - - if (get80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)) < 0) { - printf("Failed to get encryption.\n"); - return -1; - } - -#ifdef WORDS_BIGENDIAN - { - /* - * wk.ik_keytsc is in host byte order (big endian), need to - * swap it to match with the byte order used in WPA. - */ - int i; - u8 tmp[WPA_KEY_RSC_LEN]; - memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); - for (i = 0; i < WPA_KEY_RSC_LEN; i++) { - seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1]; - } - } -#else /* WORDS_BIGENDIAN */ - memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); -#endif /* WORDS_BIGENDIAN */ - return 0; -} - - -static int -bsd_flush(void *priv) -{ - u8 allsta[IEEE80211_ADDR_LEN]; - - memset(allsta, 0xff, IEEE80211_ADDR_LEN); - return bsd_sta_deauth(priv, allsta, IEEE80211_REASON_AUTH_LEAVE); -} - - -static int -bsd_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data, - const u8 *addr) -{ - struct bsd_driver_data *drv = priv; - struct ieee80211req_sta_stats stats; - - memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN); - if (get80211var(drv, IEEE80211_IOC_STA_STATS, &stats, sizeof(stats)) > 0) { - /* XXX? do packets counts include non-data frames? */ - data->rx_packets = stats.is_stats.ns_rx_data; - data->rx_bytes = stats.is_stats.ns_rx_bytes; - data->tx_packets = stats.is_stats.ns_tx_data; - data->tx_bytes = stats.is_stats.ns_tx_bytes; - } - return 0; -} - -static int -bsd_set_opt_ie(const char *ifname, void *priv, const u8 *ie, size_t ie_len) -{ - /* - * Do nothing; we setup parameters at startup that define the - * contents of the beacon information element. - */ - return 0; -} - -static int -bsd_sta_deauth(void *priv, const u8 *addr, int reason_code) -{ - struct bsd_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - - wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d", - __func__, ether_sprintf(addr), reason_code); - - mlme.im_op = IEEE80211_MLME_DEAUTH; - mlme.im_reason = reason_code; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); -} - -static int -bsd_sta_disassoc(void *priv, const u8 *addr, int reason_code) -{ - struct bsd_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - - wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d", - __func__, ether_sprintf(addr), reason_code); - - mlme.im_op = IEEE80211_MLME_DISASSOC; - mlme.im_reason = reason_code; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); -} - -static int -bsd_del_sta(struct bsd_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN]) -{ - struct hostapd_data *hapd = drv->hapd; - struct hostapd_bss_config *conf = hapd->conf; - struct sta_info *sta; - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "deassociated"); - - sta = ap_get_sta(hapd, addr); - if (sta != NULL) { - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); - if (conf->wpa) - wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); - sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; - ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - ap_free_sta(hapd, sta); - } - return 0; -} - -static int -bsd_new_sta(struct bsd_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN]) -{ - struct hostapd_data *hapd = drv->hapd; - struct hostapd_bss_config *conf = hapd->conf; - struct sta_info *sta; - struct ieee80211req_wpaie ie; - int new_assoc, ielen, res; - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "associated"); - - sta = ap_sta_add(hapd, addr); - if (sta == NULL) - return -1; - /* - * Fetch and validate any negotiated WPA/RSN parameters. - */ - if (conf->wpa) { - memset(&ie, 0, sizeof(ie)); - memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN); - if (get80211var(drv, IEEE80211_IOC_WPAIE, &ie, sizeof(ie)) < 0) { - printf("Failed to get WPA/RSN information element.\n"); - return -1; /* XXX not right */ - } - ielen = ie.wpa_ie[1]; - if (ielen == 0) { - printf("No WPA/RSN information element for station!\n"); - return -1; /* XXX not right */ - } - ielen += 2; - if (sta->wpa_sm == NULL) - sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, - sta->addr); - if (sta->wpa_sm == NULL) { - printf("Failed to initialize WPA state machine\n"); - return -1; - } - res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, - ie.wpa_ie, ielen, NULL, 0); - if (res != WPA_IE_OK) { - printf("WPA/RSN information element rejected? " - "(res %u)\n", res); - return -1; - } - } - - /* - * Now that the internal station state is setup - * kick the authenticator into action. - */ - new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0; - sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; - wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); - hostapd_new_assoc_sta(hapd, sta, !new_assoc); - ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); - return 0; -} - -#include -#include - -static void -bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx) -{ - struct bsd_driver_data *drv = ctx; - struct hostapd_data *hapd = drv->hapd; - char buf[2048]; - struct if_announcemsghdr *ifan; - struct rt_msghdr *rtm; - struct ieee80211_michael_event *mic; - struct ieee80211_join_event *join; - struct ieee80211_leave_event *leave; - int n; - - n = read(sock, buf, sizeof(buf)); - if (n < 0) { - if (errno != EINTR && errno != EAGAIN) - perror("read(PF_ROUTE)"); - return; - } - - rtm = (struct rt_msghdr *) buf; - if (rtm->rtm_version != RTM_VERSION) { - wpa_printf(MSG_DEBUG, "Routing message version %d not " - "understood\n", rtm->rtm_version); - return; - } - ifan = (struct if_announcemsghdr *) rtm; - switch (rtm->rtm_type) { - case RTM_IEEE80211: - switch (ifan->ifan_what) { - case RTM_IEEE80211_ASSOC: - case RTM_IEEE80211_REASSOC: - case RTM_IEEE80211_DISASSOC: - case RTM_IEEE80211_SCAN: - break; - case RTM_IEEE80211_LEAVE: - leave = (struct ieee80211_leave_event *) &ifan[1]; - bsd_del_sta(drv, leave->iev_addr); - break; - case RTM_IEEE80211_JOIN: -#ifdef RTM_IEEE80211_REJOIN - case RTM_IEEE80211_REJOIN: -#endif - join = (struct ieee80211_join_event *) &ifan[1]; - bsd_new_sta(drv, join->iev_addr); - break; - case RTM_IEEE80211_REPLAY: - /* ignore */ - break; - case RTM_IEEE80211_MICHAEL: - mic = (struct ieee80211_michael_event *) &ifan[1]; - wpa_printf(MSG_DEBUG, - "Michael MIC failure wireless event: " - "keyix=%u src_addr=" MACSTR, mic->iev_keyix, - MAC2STR(mic->iev_src)); - ieee80211_michael_mic_failure(hapd, mic->iev_src, 1); - break; - } - break; - } -} - -static int -bsd_wireless_event_init(void *priv) -{ - struct bsd_driver_data *drv = priv; - int s; - - drv->wext_sock = -1; - - s = socket(PF_ROUTE, SOCK_RAW, 0); - if (s < 0) { - perror("socket(PF_ROUTE,SOCK_RAW)"); - return -1; - } - eloop_register_read_sock(s, bsd_wireless_event_receive, drv, NULL); - drv->wext_sock = s; - - return 0; -} - -static void -bsd_wireless_event_deinit(void *priv) -{ - struct bsd_driver_data *drv = priv; - - if (drv != NULL) { - if (drv->wext_sock < 0) - return; - eloop_unregister_read_sock(drv->wext_sock); - close(drv->wext_sock); - } -} - - -static int -bsd_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len, - int encrypt, const u8 *own_addr) -{ - struct bsd_driver_data *drv = priv; - unsigned char buf[3000]; - unsigned char *bp = buf; - struct l2_ethhdr *eth; - size_t len; - int status; - - /* - * Prepend the Etherent header. If the caller left us - * space at the front we could just insert it but since - * we don't know we copy to a local buffer. Given the frequency - * and size of frames this probably doesn't matter. - */ - len = data_len + sizeof(struct l2_ethhdr); - if (len > sizeof(buf)) { - bp = malloc(len); - if (bp == NULL) { - printf("EAPOL frame discarded, cannot malloc temp " - "buffer of size %u!\n", len); - return -1; - } - } - eth = (struct l2_ethhdr *) bp; - memcpy(eth->h_dest, addr, ETH_ALEN); - memcpy(eth->h_source, own_addr, ETH_ALEN); - eth->h_proto = htons(ETH_P_EAPOL); - memcpy(eth+1, data, data_len); - - wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len); - - status = l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, bp, len); - - if (bp != buf) - free(bp); - return status; -} - -static void -handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) -{ - struct bsd_driver_data *drv = ctx; - struct hostapd_data *hapd = drv->hapd; - struct sta_info *sta; - - sta = ap_get_sta(hapd, src_addr); - if (!sta || !(sta->flags & WLAN_STA_ASSOC)) { - printf("Data frame from not associated STA %s\n", - ether_sprintf(src_addr)); - /* XXX cannot happen */ - return; - } - ieee802_1x_receive(hapd, src_addr, buf + sizeof(struct l2_ethhdr), - len - sizeof(struct l2_ethhdr)); -} - -static int -bsd_get_ssid(const char *ifname, void *priv, u8 *buf, int len) -{ - struct bsd_driver_data *drv = priv; - int ssid_len = get80211var(drv, IEEE80211_IOC_SSID, buf, len); - - wpa_printf(MSG_DEBUG, "%s: ssid=\"%.*s\"", __func__, ssid_len, buf); - - return ssid_len; -} - -static int -bsd_set_ssid(const char *ifname, void *priv, const u8 *buf, int len) -{ - struct bsd_driver_data *drv = priv; - - wpa_printf(MSG_DEBUG, "%s: ssid=\"%.*s\"", __func__, len, buf); - - return set80211var(drv, IEEE80211_IOC_SSID, buf, len); -} - -static void * -bsd_init(struct hostapd_data *hapd) -{ - struct bsd_driver_data *drv; - - drv = os_zalloc(sizeof(struct bsd_driver_data)); - if (drv == NULL) { - printf("Could not allocate memory for bsd driver data\n"); - goto bad; - } - - drv->hapd = hapd; - drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->ioctl_sock < 0) { - perror("socket[PF_INET,SOCK_DGRAM]"); - goto bad; - } - memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface)); - - drv->sock_xmit = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL, - handle_read, drv, 1); - if (drv->sock_xmit == NULL) - goto bad; - if (l2_packet_get_own_addr(drv->sock_xmit, hapd->own_addr)) - goto bad; - - bsd_set_iface_flags(drv, 0); /* mark down during setup */ - - return drv; -bad: - if (drv->sock_xmit != NULL) - l2_packet_deinit(drv->sock_xmit); - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - if (drv != NULL) - free(drv); - return NULL; -} - - -static void -bsd_deinit(void *priv) -{ - struct bsd_driver_data *drv = priv; - - (void) bsd_set_iface_flags(drv, 0); - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - if (drv->sock_xmit != NULL) - l2_packet_deinit(drv->sock_xmit); - free(drv); -} - -const struct wpa_driver_ops wpa_driver_bsd_ops = { - .name = "bsd", - .init = bsd_init, - .deinit = bsd_deinit, - .set_ieee8021x = bsd_set_ieee8021x, - .set_privacy = bsd_set_privacy, - .set_encryption = bsd_set_key, - .get_seqnum = bsd_get_seqnum, - .flush = bsd_flush, - .set_generic_elem = bsd_set_opt_ie, - .wireless_event_init = bsd_wireless_event_init, - .wireless_event_deinit = bsd_wireless_event_deinit, - .sta_set_flags = bsd_sta_set_flags, - .read_sta_data = bsd_read_sta_driver_data, - .send_eapol = bsd_send_eapol, - .sta_disassoc = bsd_sta_disassoc, - .sta_deauth = bsd_sta_deauth, - .set_ssid = bsd_set_ssid, - .get_ssid = bsd_get_ssid, -}; diff --git a/contrib/hostapd/hostapd/driver_hostap.c b/contrib/hostapd/hostapd/driver_hostap.c deleted file mode 100644 index ceff099891..0000000000 --- a/contrib/hostapd/hostapd/driver_hostap.c +++ /dev/null @@ -1,1279 +0,0 @@ -/* - * hostapd / Kernel driver communication with Linux Host AP driver - * Copyright (c) 2002-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#ifdef USE_KERNEL_HEADERS -/* compat-wireless does not include linux/compiler.h to define __user, so - * define it here */ -#ifndef __user -#define __user -#endif /* __user */ -#include -#include -#include /* The L2 protocols */ -#include -#include -#else /* USE_KERNEL_HEADERS */ -#include -#include -#include "wireless_copy.h" -#endif /* USE_KERNEL_HEADERS */ - -#include "hostapd.h" -#include "driver.h" -#include "ieee802_1x.h" -#include "eloop.h" -#include "priv_netlink.h" -#include "ieee802_11.h" -#include "sta_info.h" -#include "hostap_common.h" -#include "hw_features.h" - - -struct hostap_driver_data { - struct hostapd_data *hapd; - - char iface[IFNAMSIZ + 1]; - int sock; /* raw packet socket for driver access */ - int ioctl_sock; /* socket for ioctl() use */ - int wext_sock; /* socket for wireless events */ - - int we_version; - - u8 *generic_ie; - size_t generic_ie_len; - u8 *wps_ie; - size_t wps_ie_len; -}; - - -static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param, - int len); -static int hostap_set_iface_flags(void *priv, int dev_up); - -static void handle_data(struct hostapd_data *hapd, u8 *buf, size_t len, - u16 stype) -{ - struct ieee80211_hdr *hdr; - u16 fc, ethertype; - u8 *pos, *sa; - size_t left; - struct sta_info *sta; - - if (len < sizeof(struct ieee80211_hdr)) - return; - - hdr = (struct ieee80211_hdr *) buf; - fc = le_to_host16(hdr->frame_control); - - if ((fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) != WLAN_FC_TODS) { - printf("Not ToDS data frame (fc=0x%04x)\n", fc); - return; - } - - sa = hdr->addr2; - sta = ap_get_sta(hapd, sa); - if (!sta || !(sta->flags & WLAN_STA_ASSOC)) { - printf("Data frame from not associated STA " MACSTR "\n", - MAC2STR(sa)); - if (sta && (sta->flags & WLAN_STA_AUTH)) - hostapd_sta_disassoc( - hapd, sa, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - else - hostapd_sta_deauth( - hapd, sa, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - return; - } - - pos = (u8 *) (hdr + 1); - left = len - sizeof(*hdr); - - if (left < sizeof(rfc1042_header)) { - printf("Too short data frame\n"); - return; - } - - if (memcmp(pos, rfc1042_header, sizeof(rfc1042_header)) != 0) { - printf("Data frame with no RFC1042 header\n"); - return; - } - pos += sizeof(rfc1042_header); - left -= sizeof(rfc1042_header); - - if (left < 2) { - printf("No ethertype in data frame\n"); - return; - } - - ethertype = WPA_GET_BE16(pos); - pos += 2; - left -= 2; - switch (ethertype) { - case ETH_P_PAE: - ieee802_1x_receive(hapd, sa, pos, left); - break; - - default: - printf("Unknown ethertype 0x%04x in data frame\n", ethertype); - break; - } -} - - -static void handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len, - int ok) -{ - struct ieee80211_hdr *hdr; - u16 fc, type, stype; - struct sta_info *sta; - - hdr = (struct ieee80211_hdr *) buf; - fc = le_to_host16(hdr->frame_control); - - type = WLAN_FC_GET_TYPE(fc); - stype = WLAN_FC_GET_STYPE(fc); - - switch (type) { - case WLAN_FC_TYPE_MGMT: - wpa_printf(MSG_DEBUG, "MGMT (TX callback) %s", - ok ? "ACK" : "fail"); - ieee802_11_mgmt_cb(hapd, buf, len, stype, ok); - break; - case WLAN_FC_TYPE_CTRL: - wpa_printf(MSG_DEBUG, "CTRL (TX callback) %s", - ok ? "ACK" : "fail"); - break; - case WLAN_FC_TYPE_DATA: - wpa_printf(MSG_DEBUG, "DATA (TX callback) %s", - ok ? "ACK" : "fail"); - sta = ap_get_sta(hapd, hdr->addr1); - if (sta && sta->flags & WLAN_STA_PENDING_POLL) { - wpa_printf(MSG_DEBUG, "STA " MACSTR - " %s pending activity poll", - MAC2STR(sta->addr), - ok ? "ACKed" : "did not ACK"); - if (ok) - sta->flags &= ~WLAN_STA_PENDING_POLL; - } - if (sta) - ieee802_1x_tx_status(hapd, sta, buf, len, ok); - break; - default: - printf("unknown TX callback frame type %d\n", type); - break; - } -} - - -static void handle_frame(struct hostapd_data *hapd, u8 *buf, size_t len) -{ - struct ieee80211_hdr *hdr; - u16 fc, extra_len, type, stype; - unsigned char *extra = NULL; - size_t data_len = len; - int ver; - - /* PSPOLL is only 16 bytes, but driver does not (at least yet) pass - * these to user space */ - if (len < 24) { - wpa_printf(MSG_MSGDUMP, "handle_frame: too short (%lu)", - (unsigned long) len); - return; - } - - hdr = (struct ieee80211_hdr *) buf; - fc = le_to_host16(hdr->frame_control); - type = WLAN_FC_GET_TYPE(fc); - stype = WLAN_FC_GET_STYPE(fc); - - if (type != WLAN_FC_TYPE_MGMT || stype != WLAN_FC_STYPE_BEACON) { - wpa_hexdump(MSG_MSGDUMP, "Received management frame", - buf, len); - } - - ver = fc & WLAN_FC_PVER; - - /* protocol version 3 is reserved for indicating extra data after the - * payload, version 2 for indicating ACKed frame (TX callbacks), and - * version 1 for indicating failed frame (no ACK, TX callbacks) */ - if (ver == 3) { - u8 *pos = buf + len - 2; - extra_len = WPA_GET_LE16(pos); - printf("extra data in frame (elen=%d)\n", extra_len); - if ((size_t) extra_len + 2 > len) { - printf(" extra data overflow\n"); - return; - } - len -= extra_len + 2; - extra = buf + len; - } else if (ver == 1 || ver == 2) { - handle_tx_callback(hapd, buf, data_len, ver == 2 ? 1 : 0); - return; - } else if (ver != 0) { - printf("unknown protocol version %d\n", ver); - return; - } - - switch (type) { - case WLAN_FC_TYPE_MGMT: - if (stype != WLAN_FC_STYPE_BEACON) - wpa_printf(MSG_MSGDUMP, "MGMT"); - ieee802_11_mgmt(hapd, buf, data_len, stype, NULL); - break; - case WLAN_FC_TYPE_CTRL: - wpa_printf(MSG_DEBUG, "CTRL"); - break; - case WLAN_FC_TYPE_DATA: - wpa_printf(MSG_DEBUG, "DATA"); - handle_data(hapd, buf, data_len, stype); - break; - default: - wpa_printf(MSG_DEBUG, "unknown frame type %d", type); - break; - } -} - - -static void handle_read(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx; - int len; - unsigned char buf[3000]; - - len = recv(sock, buf, sizeof(buf), 0); - if (len < 0) { - perror("recv"); - return; - } - - handle_frame(hapd, buf, len); -} - - -static int hostap_init_sockets(struct hostap_driver_data *drv) -{ - struct ifreq ifr; - struct sockaddr_ll addr; - - drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (drv->sock < 0) { - perror("socket[PF_PACKET,SOCK_RAW]"); - return -1; - } - - if (eloop_register_read_sock(drv->sock, handle_read, drv->hapd, NULL)) - { - printf("Could not register read socket\n"); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%sap", drv->iface); - if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) { - perror("ioctl(SIOCGIFINDEX)"); - return -1; - } - - if (hostap_set_iface_flags(drv, 1)) { - return -1; - } - - memset(&addr, 0, sizeof(addr)); - addr.sll_family = AF_PACKET; - addr.sll_ifindex = ifr.ifr_ifindex; - wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d", - addr.sll_ifindex); - - if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind"); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name)); - if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) { - perror("ioctl(SIOCGIFHWADDR)"); - return -1; - } - - if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { - printf("Invalid HW-addr family 0x%04x\n", - ifr.ifr_hwaddr.sa_family); - return -1; - } - memcpy(drv->hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); - - return 0; -} - - -static int hostap_send_mgmt_frame(void *priv, const void *msg, size_t len, - int flags) -{ - struct hostap_driver_data *drv = priv; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) msg; - int res; - - /* Request TX callback */ - hdr->frame_control |= host_to_le16(BIT(1)); - res = send(drv->sock, msg, len, flags); - hdr->frame_control &= ~host_to_le16(BIT(1)); - - return res; -} - - -static int hostap_send_eapol(void *priv, const u8 *addr, const u8 *data, - size_t data_len, int encrypt, const u8 *own_addr) -{ - struct hostap_driver_data *drv = priv; - struct ieee80211_hdr *hdr; - size_t len; - u8 *pos; - int res; - - len = sizeof(*hdr) + sizeof(rfc1042_header) + 2 + data_len; - hdr = os_zalloc(len); - if (hdr == NULL) { - printf("malloc() failed for hostapd_send_data(len=%lu)\n", - (unsigned long) len); - return -1; - } - - hdr->frame_control = - IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA); - hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS); - if (encrypt) - hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); - memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN); - memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN); - memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN); - - pos = (u8 *) (hdr + 1); - memcpy(pos, rfc1042_header, sizeof(rfc1042_header)); - pos += sizeof(rfc1042_header); - *((u16 *) pos) = htons(ETH_P_PAE); - pos += 2; - memcpy(pos, data, data_len); - - res = hostap_send_mgmt_frame(drv, (u8 *) hdr, len, 0); - free(hdr); - - if (res < 0) { - perror("hostapd_send_eapol: send"); - printf("hostapd_send_eapol - packet len: %lu - failed\n", - (unsigned long) len); - } - - return res; -} - - -static int hostap_sta_set_flags(void *priv, const u8 *addr, - int total_flags, int flags_or, int flags_and) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_SET_FLAGS_STA; - memcpy(param.sta_addr, addr, ETH_ALEN); - param.u.set_flags_sta.flags_or = flags_or; - param.u.set_flags_sta.flags_and = flags_and; - return hostapd_ioctl(drv, ¶m, sizeof(param)); -} - - -static int hostap_set_iface_flags(void *priv, int dev_up) -{ - struct hostap_driver_data *drv = priv; - struct ifreq ifr; - - if (drv->ioctl_sock < 0) - return -1; - - memset(&ifr, 0, sizeof(ifr)); - snprintf(ifr.ifr_name, IFNAMSIZ, "%sap", drv->iface); - - if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCGIFFLAGS]"); - return -1; - } - - if (dev_up) - ifr.ifr_flags |= IFF_UP; - else - ifr.ifr_flags &= ~IFF_UP; - - if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCSIFFLAGS]"); - return -1; - } - - if (dev_up) { - memset(&ifr, 0, sizeof(ifr)); - snprintf(ifr.ifr_name, IFNAMSIZ, "%sap", drv->iface); - ifr.ifr_mtu = HOSTAPD_MTU; - if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) { - perror("ioctl[SIOCSIFMTU]"); - printf("Setting MTU failed - trying to survive with " - "current value\n"); - } - } - - return 0; -} - - -static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param, - int len) -{ - struct hostap_driver_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) param; - iwr.u.data.length = len; - - if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) { - perror("ioctl[PRISM2_IOCTL_HOSTAPD]"); - return -1; - } - - return 0; -} - - -static int hostap_set_encryption(const char *ifname, void *priv, - const char *alg, const u8 *addr, - int idx, const u8 *key, size_t key_len, - int txkey) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param *param; - u8 *buf; - size_t blen; - int ret = 0; - - blen = sizeof(*param) + key_len; - buf = os_zalloc(blen); - if (buf == NULL) - return -1; - - param = (struct prism2_hostapd_param *) buf; - param->cmd = PRISM2_SET_ENCRYPTION; - if (addr == NULL) - memset(param->sta_addr, 0xff, ETH_ALEN); - else - memcpy(param->sta_addr, addr, ETH_ALEN); - os_strlcpy((char *) param->u.crypt.alg, alg, - HOSTAP_CRYPT_ALG_NAME_LEN); - param->u.crypt.flags = txkey ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0; - param->u.crypt.idx = idx; - param->u.crypt.key_len = key_len; - memcpy((u8 *) (param + 1), key, key_len); - - if (hostapd_ioctl(drv, param, blen)) { - printf("Failed to set encryption.\n"); - ret = -1; - } - free(buf); - - return ret; -} - - -static int hostap_get_seqnum(const char *ifname, void *priv, const u8 *addr, - int idx, u8 *seq) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param *param; - u8 *buf; - size_t blen; - int ret = 0; - - blen = sizeof(*param) + 32; - buf = os_zalloc(blen); - if (buf == NULL) - return -1; - - param = (struct prism2_hostapd_param *) buf; - param->cmd = PRISM2_GET_ENCRYPTION; - if (addr == NULL) - memset(param->sta_addr, 0xff, ETH_ALEN); - else - memcpy(param->sta_addr, addr, ETH_ALEN); - param->u.crypt.idx = idx; - - if (hostapd_ioctl(drv, param, blen)) { - printf("Failed to get encryption.\n"); - ret = -1; - } else { - memcpy(seq, param->u.crypt.seq, 8); - } - free(buf); - - return ret; -} - - -static int hostap_ioctl_prism2param(void *priv, int param, int value) -{ - struct hostap_driver_data *drv = priv; - struct iwreq iwr; - int *i; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - i = (int *) iwr.u.name; - *i++ = param; - *i++ = value; - - if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_PRISM2_PARAM, &iwr) < 0) { - perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]"); - return -1; - } - - return 0; -} - - -static int hostap_set_ieee8021x(const char *ifname, void *priv, int enabled) -{ - struct hostap_driver_data *drv = priv; - - /* enable kernel driver support for IEEE 802.1X */ - if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_IEEE_802_1X, enabled)) { - printf("Could not setup IEEE 802.1X support in kernel driver." - "\n"); - return -1; - } - - if (!enabled) - return 0; - - /* use host driver implementation of encryption to allow - * individual keys and passing plaintext EAPOL frames */ - if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOST_DECRYPT, 1) || - hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOST_ENCRYPT, 1)) { - printf("Could not setup host-based encryption in kernel " - "driver.\n"); - return -1; - } - - return 0; -} - - -static int hostap_set_privacy(const char *ifname, void *priv, int enabled) -{ - struct hostap_drvier_data *drv = priv; - - return hostap_ioctl_prism2param(drv, PRISM2_PARAM_PRIVACY_INVOKED, - enabled); -} - - -static int hostap_set_ssid(const char *ifname, void *priv, const u8 *buf, - int len) -{ - struct hostap_driver_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.essid.flags = 1; /* SSID active */ - iwr.u.essid.pointer = (caddr_t) buf; - iwr.u.essid.length = len + 1; - - if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) { - perror("ioctl[SIOCSIWESSID]"); - printf("len=%d\n", len); - return -1; - } - - return 0; -} - - -static int hostap_flush(void *priv) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_FLUSH; - return hostapd_ioctl(drv, ¶m, sizeof(param)); -} - - -static int hostap_read_sta_data(void *priv, - struct hostap_sta_driver_data *data, - const u8 *addr) -{ - struct hostap_driver_data *drv = priv; - char buf[1024], line[128], *pos; - FILE *f; - unsigned long val; - - memset(data, 0, sizeof(*data)); - snprintf(buf, sizeof(buf), "/proc/net/hostap/%s/" MACSTR, - drv->iface, MAC2STR(addr)); - - f = fopen(buf, "r"); - if (!f) - return -1; - /* Need to read proc file with in one piece, so use large enough - * buffer. */ - setbuffer(f, buf, sizeof(buf)); - - while (fgets(line, sizeof(line), f)) { - pos = strchr(line, '='); - if (!pos) - continue; - *pos++ = '\0'; - val = strtoul(pos, NULL, 10); - if (strcmp(line, "rx_packets") == 0) - data->rx_packets = val; - else if (strcmp(line, "tx_packets") == 0) - data->tx_packets = val; - else if (strcmp(line, "rx_bytes") == 0) - data->rx_bytes = val; - else if (strcmp(line, "tx_bytes") == 0) - data->tx_bytes = val; - } - - fclose(f); - - return 0; -} - - -static int hostap_sta_add(const char *ifname, void *priv, const u8 *addr, - u16 aid, u16 capability, u8 *supp_rates, - size_t supp_rates_len, int flags, - u16 listen_interval) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - int tx_supp_rates = 0; - size_t i; - -#define WLAN_RATE_1M BIT(0) -#define WLAN_RATE_2M BIT(1) -#define WLAN_RATE_5M5 BIT(2) -#define WLAN_RATE_11M BIT(3) - - for (i = 0; i < supp_rates_len; i++) { - if ((supp_rates[i] & 0x7f) == 2) - tx_supp_rates |= WLAN_RATE_1M; - if ((supp_rates[i] & 0x7f) == 4) - tx_supp_rates |= WLAN_RATE_2M; - if ((supp_rates[i] & 0x7f) == 11) - tx_supp_rates |= WLAN_RATE_5M5; - if ((supp_rates[i] & 0x7f) == 22) - tx_supp_rates |= WLAN_RATE_11M; - } - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_ADD_STA; - memcpy(param.sta_addr, addr, ETH_ALEN); - param.u.add_sta.aid = aid; - param.u.add_sta.capability = capability; - param.u.add_sta.tx_supp_rates = tx_supp_rates; - return hostapd_ioctl(drv, ¶m, sizeof(param)); -} - - -static int hostap_sta_remove(void *priv, const u8 *addr) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - - hostap_sta_set_flags(drv, addr, 0, 0, ~WLAN_STA_AUTHORIZED); - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_REMOVE_STA; - memcpy(param.sta_addr, addr, ETH_ALEN); - if (hostapd_ioctl(drv, ¶m, sizeof(param))) { - printf("Could not remove station from kernel driver.\n"); - return -1; - } - return 0; -} - - -static int hostap_get_inact_sec(void *priv, const u8 *addr) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_GET_INFO_STA; - memcpy(param.sta_addr, addr, ETH_ALEN); - if (hostapd_ioctl(drv, ¶m, sizeof(param))) { - return -1; - } - - return param.u.get_info_sta.inactive_sec; -} - - -static int hostap_sta_clear_stats(void *priv, const u8 *addr) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_STA_CLEAR_STATS; - memcpy(param.sta_addr, addr, ETH_ALEN); - if (hostapd_ioctl(drv, ¶m, sizeof(param))) { - return -1; - } - - return 0; -} - - -static int hostap_set_assoc_ap(void *priv, const u8 *addr) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR; - memcpy(param.sta_addr, addr, ETH_ALEN); - if (hostapd_ioctl(drv, ¶m, sizeof(param))) - return -1; - - return 0; -} - - -static int hostapd_ioctl_set_generic_elem(struct hostap_driver_data *drv) -{ - struct prism2_hostapd_param *param; - int res; - size_t blen, elem_len; - - elem_len = drv->generic_ie_len + drv->wps_ie_len; - blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + elem_len; - if (blen < sizeof(*param)) - blen = sizeof(*param); - - param = os_zalloc(blen); - if (param == NULL) - return -1; - - param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT; - param->u.generic_elem.len = elem_len; - if (drv->generic_ie) { - os_memcpy(param->u.generic_elem.data, drv->generic_ie, - drv->generic_ie_len); - } - if (drv->wps_ie) { - os_memcpy(¶m->u.generic_elem.data[drv->generic_ie_len], - drv->wps_ie, drv->wps_ie_len); - } - wpa_hexdump(MSG_DEBUG, "hostap: Set generic IE", - param->u.generic_elem.data, elem_len); - res = hostapd_ioctl(drv, param, blen); - - os_free(param); - - return res; -} - - -static int hostap_set_generic_elem(const char *ifname, void *priv, - const u8 *elem, size_t elem_len) -{ - struct hostap_driver_data *drv = priv; - - os_free(drv->generic_ie); - drv->generic_ie = NULL; - drv->generic_ie_len = 0; - if (elem) { - drv->generic_ie = os_malloc(elem_len); - if (drv->generic_ie == NULL) - return -1; - os_memcpy(drv->generic_ie, elem, elem_len); - drv->generic_ie_len = elem_len; - } - - return hostapd_ioctl_set_generic_elem(drv); -} - - -static int hostap_set_wps_beacon_ie(const char *ifname, void *priv, - const u8 *ie, size_t len) -{ - /* Host AP driver supports only one set of extra IEs, so we need to - * use the ProbeResp IEs also for Beacon frames since they include more - * information. */ - return 0; -} - - -static int hostap_set_wps_probe_resp_ie(const char *ifname, void *priv, - const u8 *ie, size_t len) -{ - struct hostap_driver_data *drv = priv; - - os_free(drv->wps_ie); - drv->wps_ie = NULL; - drv->wps_ie_len = 0; - if (ie) { - drv->wps_ie = os_malloc(len); - if (drv->wps_ie == NULL) - return -1; - os_memcpy(drv->wps_ie, ie, len); - drv->wps_ie_len = len; - } - - return hostapd_ioctl_set_generic_elem(drv); -} - - -static void -hostapd_wireless_event_wireless_custom(struct hostap_driver_data *drv, - char *custom) -{ - wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom); - - if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) { - char *pos; - u8 addr[ETH_ALEN]; - pos = strstr(custom, "addr="); - if (pos == NULL) { - wpa_printf(MSG_DEBUG, - "MLME-MICHAELMICFAILURE.indication " - "without sender address ignored"); - return; - } - pos += 5; - if (hwaddr_aton(pos, addr) == 0) { - ieee80211_michael_mic_failure(drv->hapd, addr, 1); - } else { - wpa_printf(MSG_DEBUG, - "MLME-MICHAELMICFAILURE.indication " - "with invalid MAC address"); - } - } -} - - -static void hostapd_wireless_event_wireless(struct hostap_driver_data *drv, - char *data, int len) -{ - struct iw_event iwe_buf, *iwe = &iwe_buf; - char *pos, *end, *custom, *buf; - - pos = data; - end = data + len; - - while (pos + IW_EV_LCP_LEN <= end) { - /* Event data may be unaligned, so make a local, aligned copy - * before processing. */ - memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); - wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d", - iwe->cmd, iwe->len); - if (iwe->len <= IW_EV_LCP_LEN) - return; - - custom = pos + IW_EV_POINT_LEN; - if (drv->we_version > 18 && - (iwe->cmd == IWEVMICHAELMICFAILURE || - iwe->cmd == IWEVCUSTOM)) { - /* WE-19 removed the pointer from struct iw_point */ - char *dpos = (char *) &iwe_buf.u.data.length; - int dlen = dpos - (char *) &iwe_buf; - memcpy(dpos, pos + IW_EV_LCP_LEN, - sizeof(struct iw_event) - dlen); - } else { - memcpy(&iwe_buf, pos, sizeof(struct iw_event)); - custom += IW_EV_POINT_OFF; - } - - switch (iwe->cmd) { - case IWEVCUSTOM: - if (custom + iwe->u.data.length > end) - return; - buf = malloc(iwe->u.data.length + 1); - if (buf == NULL) - return; - memcpy(buf, custom, iwe->u.data.length); - buf[iwe->u.data.length] = '\0'; - hostapd_wireless_event_wireless_custom(drv, buf); - free(buf); - break; - } - - pos += iwe->len; - } -} - - -static void hostapd_wireless_event_rtm_newlink(struct hostap_driver_data *drv, - struct nlmsghdr *h, int len) -{ - struct ifinfomsg *ifi; - int attrlen, nlmsg_len, rta_len; - struct rtattr * attr; - - if (len < (int) sizeof(*ifi)) - return; - - ifi = NLMSG_DATA(h); - - /* TODO: use ifi->ifi_index to filter out wireless events from other - * interfaces */ - - nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); - - attrlen = h->nlmsg_len - nlmsg_len; - if (attrlen < 0) - return; - - attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_WIRELESS) { - hostapd_wireless_event_wireless( - drv, ((char *) attr) + rta_len, - attr->rta_len - rta_len); - } - attr = RTA_NEXT(attr, attrlen); - } -} - - -static void hostapd_wireless_event_receive(int sock, void *eloop_ctx, - void *sock_ctx) -{ - char buf[256]; - int left; - struct sockaddr_nl from; - socklen_t fromlen; - struct nlmsghdr *h; - struct hostap_driver_data *drv = eloop_ctx; - - fromlen = sizeof(from); - left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, - (struct sockaddr *) &from, &fromlen); - if (left < 0) { - if (errno != EINTR && errno != EAGAIN) - perror("recvfrom(netlink)"); - return; - } - - h = (struct nlmsghdr *) buf; - while (left >= (int) sizeof(*h)) { - int len, plen; - - len = h->nlmsg_len; - plen = len - sizeof(*h); - if (len > left || plen < 0) { - printf("Malformed netlink message: " - "len=%d left=%d plen=%d\n", - len, left, plen); - break; - } - - switch (h->nlmsg_type) { - case RTM_NEWLINK: - hostapd_wireless_event_rtm_newlink(drv, h, plen); - break; - } - - len = NLMSG_ALIGN(len); - left -= len; - h = (struct nlmsghdr *) ((char *) h + len); - } - - if (left > 0) { - printf("%d extra bytes in the end of netlink message\n", left); - } -} - - -static int hostap_get_we_version(struct hostap_driver_data *drv) -{ - struct iw_range *range; - struct iwreq iwr; - int minlen; - size_t buflen; - - drv->we_version = 0; - - /* - * Use larger buffer than struct iw_range in order to allow the - * structure to grow in the future. - */ - buflen = sizeof(struct iw_range) + 500; - range = os_zalloc(buflen); - if (range == NULL) - return -1; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) range; - iwr.u.data.length = buflen; - - minlen = ((char *) &range->enc_capa) - (char *) range + - sizeof(range->enc_capa); - - if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) { - perror("ioctl[SIOCGIWRANGE]"); - free(range); - return -1; - } else if (iwr.u.data.length >= minlen && - range->we_version_compiled >= 18) { - wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d " - "WE(source)=%d enc_capa=0x%x", - range->we_version_compiled, - range->we_version_source, - range->enc_capa); - drv->we_version = range->we_version_compiled; - } - - free(range); - return 0; -} - - -static int hostap_wireless_event_init(void *priv) -{ - struct hostap_driver_data *drv = priv; - int s; - struct sockaddr_nl local; - - hostap_get_we_version(drv); - - drv->wext_sock = -1; - - s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (s < 0) { - perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)"); - return -1; - } - - memset(&local, 0, sizeof(local)); - local.nl_family = AF_NETLINK; - local.nl_groups = RTMGRP_LINK; - if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) { - perror("bind(netlink)"); - close(s); - return -1; - } - - eloop_register_read_sock(s, hostapd_wireless_event_receive, drv, - NULL); - drv->wext_sock = s; - - return 0; -} - - -static void hostap_wireless_event_deinit(void *priv) -{ - struct hostap_driver_data *drv = priv; - if (drv->wext_sock < 0) - return; - eloop_unregister_read_sock(drv->wext_sock); - close(drv->wext_sock); -} - - -static void * hostap_init(struct hostapd_data *hapd) -{ - struct hostap_driver_data *drv; - - drv = os_zalloc(sizeof(struct hostap_driver_data)); - if (drv == NULL) { - printf("Could not allocate memory for hostapd driver data\n"); - return NULL; - } - - drv->hapd = hapd; - drv->ioctl_sock = drv->sock = -1; - memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface)); - - drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->ioctl_sock < 0) { - perror("socket[PF_INET,SOCK_DGRAM]"); - free(drv); - return NULL; - } - - if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 1)) { - printf("Could not enable hostapd mode for interface %s\n", - drv->iface); - close(drv->ioctl_sock); - free(drv); - return NULL; - } - - if (hostap_init_sockets(drv)) { - close(drv->ioctl_sock); - free(drv); - return NULL; - } - - return drv; -} - - -static void hostap_driver_deinit(void *priv) -{ - struct hostap_driver_data *drv = priv; - - (void) hostap_set_iface_flags(drv, 0); - (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 0); - (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD_STA, 0); - - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - - if (drv->sock >= 0) - close(drv->sock); - - os_free(drv->generic_ie); - os_free(drv->wps_ie); - - free(drv); -} - - -static int hostap_sta_deauth(void *priv, const u8 *addr, int reason) -{ - struct hostap_driver_data *drv = priv; - struct ieee80211_mgmt mgmt; - - memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DEAUTH); - memcpy(mgmt.da, addr, ETH_ALEN); - memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN); - memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN); - mgmt.u.deauth.reason_code = host_to_le16(reason); - return hostap_send_mgmt_frame(drv, &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.deauth), 0); -} - - -static int hostap_sta_disassoc(void *priv, const u8 *addr, int reason) -{ - struct hostap_driver_data *drv = priv; - struct ieee80211_mgmt mgmt; - - memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DISASSOC); - memcpy(mgmt.da, addr, ETH_ALEN); - memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN); - memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN); - mgmt.u.disassoc.reason_code = host_to_le16(reason); - return hostap_send_mgmt_frame(drv, &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.disassoc), 0); -} - - -static struct hostapd_hw_modes * hostap_get_hw_feature_data(void *priv, - u16 *num_modes, - u16 *flags) -{ - struct hostapd_hw_modes *mode; - int i, clen, rlen; - const short chan2freq[14] = { - 2412, 2417, 2422, 2427, 2432, 2437, 2442, - 2447, 2452, 2457, 2462, 2467, 2472, 2484 - }; - - mode = os_zalloc(sizeof(struct hostapd_hw_modes)); - if (mode == NULL) - return NULL; - - *num_modes = 1; - *flags = 0; - - mode->mode = HOSTAPD_MODE_IEEE80211B; - mode->num_channels = 14; - mode->num_rates = 4; - - clen = mode->num_channels * sizeof(struct hostapd_channel_data); - rlen = mode->num_rates * sizeof(struct hostapd_rate_data); - - mode->channels = os_zalloc(clen); - mode->rates = os_zalloc(rlen); - if (mode->channels == NULL || mode->rates == NULL) { - hostapd_free_hw_features(mode, *num_modes); - return NULL; - } - - for (i = 0; i < 14; i++) { - mode->channels[i].chan = i + 1; - mode->channels[i].freq = chan2freq[i]; - /* TODO: Get allowed channel list from the driver */ - if (i >= 11) - mode->channels[i].flag = HOSTAPD_CHAN_DISABLED; - } - - mode->rates[0].rate = 10; - mode->rates[0].flags = HOSTAPD_RATE_CCK; - mode->rates[1].rate = 20; - mode->rates[1].flags = HOSTAPD_RATE_CCK; - mode->rates[2].rate = 55; - mode->rates[2].flags = HOSTAPD_RATE_CCK; - mode->rates[3].rate = 110; - mode->rates[3].flags = HOSTAPD_RATE_CCK; - - return mode; -} - - -const struct wpa_driver_ops wpa_driver_hostap_ops = { - .name = "hostap", - .init = hostap_init, - .deinit = hostap_driver_deinit, - .wireless_event_init = hostap_wireless_event_init, - .wireless_event_deinit = hostap_wireless_event_deinit, - .set_ieee8021x = hostap_set_ieee8021x, - .set_privacy = hostap_set_privacy, - .set_encryption = hostap_set_encryption, - .get_seqnum = hostap_get_seqnum, - .flush = hostap_flush, - .set_generic_elem = hostap_set_generic_elem, - .read_sta_data = hostap_read_sta_data, - .send_eapol = hostap_send_eapol, - .sta_set_flags = hostap_sta_set_flags, - .sta_deauth = hostap_sta_deauth, - .sta_disassoc = hostap_sta_disassoc, - .sta_remove = hostap_sta_remove, - .set_ssid = hostap_set_ssid, - .send_mgmt_frame = hostap_send_mgmt_frame, - .set_assoc_ap = hostap_set_assoc_ap, - .sta_add = hostap_sta_add, - .get_inact_sec = hostap_get_inact_sec, - .sta_clear_stats = hostap_sta_clear_stats, - .get_hw_feature_data = hostap_get_hw_feature_data, - .set_wps_beacon_ie = hostap_set_wps_beacon_ie, - .set_wps_probe_resp_ie = hostap_set_wps_probe_resp_ie, -}; diff --git a/contrib/hostapd/hostapd/driver_madwifi.c b/contrib/hostapd/hostapd/driver_madwifi.c deleted file mode 100644 index 4083fda29b..0000000000 --- a/contrib/hostapd/hostapd/driver_madwifi.c +++ /dev/null @@ -1,1483 +0,0 @@ -/* - * hostapd / Driver interaction with MADWIFI 802.11 driver - * Copyright (c) 2004, Sam Leffler - * Copyright (c) 2004, Video54 Technologies - * Copyright (c) 2005-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include - -#include -#include -#ifdef WME_NUM_AC -/* Assume this is built against BSD branch of madwifi driver. */ -#define MADWIFI_BSD -#include -#endif /* WME_NUM_AC */ -#include -#include - -#ifdef CONFIG_WPS -#ifdef IEEE80211_IOCTL_FILTERFRAME -#include - -#ifndef ETH_P_80211_RAW -#define ETH_P_80211_RAW 0x0019 -#endif -#endif /* IEEE80211_IOCTL_FILTERFRAME */ -#endif /* CONFIG_WPS */ - -/* - * Avoid conflicts with hostapd definitions by undefining couple of defines - * from madwifi header files. - */ -#undef RSN_VERSION -#undef WPA_VERSION -#undef WPA_OUI_TYPE -#undef WME_OUI_TYPE - - -#ifdef IEEE80211_IOCTL_SETWMMPARAMS -/* Assume this is built against madwifi-ng */ -#define MADWIFI_NG -#endif /* IEEE80211_IOCTL_SETWMMPARAMS */ - -#include "wireless_copy.h" - -#include "hostapd.h" -#include "driver.h" -#include "ieee802_1x.h" -#include "eloop.h" -#include "priv_netlink.h" -#include "sta_info.h" -#include "l2_packet/l2_packet.h" - -#include "wpa.h" -#include "radius/radius.h" -#include "ieee802_11.h" -#include "accounting.h" -#include "common.h" -#include "wps_hostapd.h" - - -struct madwifi_driver_data { - struct hostapd_data *hapd; /* back pointer */ - - char iface[IFNAMSIZ + 1]; - int ifindex; - struct l2_packet_data *sock_xmit; /* raw packet xmit socket */ - struct l2_packet_data *sock_recv; /* raw packet recv socket */ - int ioctl_sock; /* socket for ioctl() use */ - int wext_sock; /* socket for wireless events */ - int we_version; - u8 acct_mac[ETH_ALEN]; - struct hostap_sta_driver_data acct_data; - - struct l2_packet_data *sock_raw; /* raw 802.11 management frames */ -}; - -static int madwifi_sta_deauth(void *priv, const u8 *addr, int reason_code); - -static int -set80211priv(struct madwifi_driver_data *drv, int op, void *data, int len) -{ - struct iwreq iwr; - int do_inline = len < IFNAMSIZ; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); -#ifdef IEEE80211_IOCTL_FILTERFRAME - /* FILTERFRAME must be NOT inline, regardless of size. */ - if (op == IEEE80211_IOCTL_FILTERFRAME) - do_inline = 0; -#endif /* IEEE80211_IOCTL_FILTERFRAME */ - if (op == IEEE80211_IOCTL_SET_APPIEBUF) - do_inline = 0; - if (do_inline) { - /* - * Argument data fits inline; put it there. - */ - memcpy(iwr.u.name, data, len); - } else { - /* - * Argument data too big for inline transfer; setup a - * parameter block instead; the kernel will transfer - * the data for the driver. - */ - iwr.u.data.pointer = data; - iwr.u.data.length = len; - } - - if (ioctl(drv->ioctl_sock, op, &iwr) < 0) { -#ifdef MADWIFI_NG - int first = IEEE80211_IOCTL_SETPARAM; - static const char *opnames[] = { - "ioctl[IEEE80211_IOCTL_SETPARAM]", - "ioctl[IEEE80211_IOCTL_GETPARAM]", - "ioctl[IEEE80211_IOCTL_SETMODE]", - "ioctl[IEEE80211_IOCTL_GETMODE]", - "ioctl[IEEE80211_IOCTL_SETWMMPARAMS]", - "ioctl[IEEE80211_IOCTL_GETWMMPARAMS]", - "ioctl[IEEE80211_IOCTL_SETCHANLIST]", - "ioctl[IEEE80211_IOCTL_GETCHANLIST]", - "ioctl[IEEE80211_IOCTL_CHANSWITCH]", - "ioctl[IEEE80211_IOCTL_GET_APPIEBUF]", - "ioctl[IEEE80211_IOCTL_SET_APPIEBUF]", - "ioctl[IEEE80211_IOCTL_GETSCANRESULTS]", - "ioctl[IEEE80211_IOCTL_FILTERFRAME]", - "ioctl[IEEE80211_IOCTL_GETCHANINFO]", - "ioctl[IEEE80211_IOCTL_SETOPTIE]", - "ioctl[IEEE80211_IOCTL_GETOPTIE]", - "ioctl[IEEE80211_IOCTL_SETMLME]", - NULL, - "ioctl[IEEE80211_IOCTL_SETKEY]", - NULL, - "ioctl[IEEE80211_IOCTL_DELKEY]", - NULL, - "ioctl[IEEE80211_IOCTL_ADDMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_DELMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_WDSMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_WDSDELMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_KICKMAC]", - }; -#else /* MADWIFI_NG */ - int first = IEEE80211_IOCTL_SETPARAM; - static const char *opnames[] = { - "ioctl[IEEE80211_IOCTL_SETPARAM]", - "ioctl[IEEE80211_IOCTL_GETPARAM]", - "ioctl[IEEE80211_IOCTL_SETKEY]", - "ioctl[SIOCIWFIRSTPRIV+3]", - "ioctl[IEEE80211_IOCTL_DELKEY]", - "ioctl[SIOCIWFIRSTPRIV+5]", - "ioctl[IEEE80211_IOCTL_SETMLME]", - "ioctl[SIOCIWFIRSTPRIV+7]", - "ioctl[IEEE80211_IOCTL_SETOPTIE]", - "ioctl[IEEE80211_IOCTL_GETOPTIE]", - "ioctl[IEEE80211_IOCTL_ADDMAC]", - "ioctl[SIOCIWFIRSTPRIV+11]", - "ioctl[IEEE80211_IOCTL_DELMAC]", - "ioctl[SIOCIWFIRSTPRIV+13]", - "ioctl[IEEE80211_IOCTL_CHANLIST]", - "ioctl[SIOCIWFIRSTPRIV+15]", - "ioctl[IEEE80211_IOCTL_GETRSN]", - "ioctl[SIOCIWFIRSTPRIV+17]", - "ioctl[IEEE80211_IOCTL_GETKEY]", - }; -#endif /* MADWIFI_NG */ - int idx = op - first; - if (first <= op && - idx < (int) (sizeof(opnames) / sizeof(opnames[0])) && - opnames[idx]) - perror(opnames[idx]); - else - perror("ioctl[unknown???]"); - return -1; - } - return 0; -} - -static int -set80211param(struct madwifi_driver_data *drv, int op, int arg) -{ - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.mode = op; - memcpy(iwr.u.name+sizeof(__u32), &arg, sizeof(arg)); - - if (ioctl(drv->ioctl_sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) { - perror("ioctl[IEEE80211_IOCTL_SETPARAM]"); - wpa_printf(MSG_DEBUG, "%s: Failed to set parameter (op %d " - "arg %d)", __func__, op, arg); - return -1; - } - return 0; -} - -static const char * -ether_sprintf(const u8 *addr) -{ - static char buf[sizeof(MACSTR)]; - - if (addr != NULL) - snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr)); - else - snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0); - return buf; -} - -/* - * Configure WPA parameters. - */ -static int -madwifi_configure_wpa(struct madwifi_driver_data *drv) -{ - struct hostapd_data *hapd = drv->hapd; - struct hostapd_bss_config *conf = hapd->conf; - int v; - - switch (conf->wpa_group) { - case WPA_CIPHER_CCMP: - v = IEEE80211_CIPHER_AES_CCM; - break; - case WPA_CIPHER_TKIP: - v = IEEE80211_CIPHER_TKIP; - break; - case WPA_CIPHER_WEP104: - v = IEEE80211_CIPHER_WEP; - break; - case WPA_CIPHER_WEP40: - v = IEEE80211_CIPHER_WEP; - break; - case WPA_CIPHER_NONE: - v = IEEE80211_CIPHER_NONE; - break; - default: - wpa_printf(MSG_ERROR, "Unknown group key cipher %u", - conf->wpa_group); - return -1; - } - wpa_printf(MSG_DEBUG, "%s: group key cipher=%d", __func__, v); - if (set80211param(drv, IEEE80211_PARAM_MCASTCIPHER, v)) { - printf("Unable to set group key cipher to %u\n", v); - return -1; - } - if (v == IEEE80211_CIPHER_WEP) { - /* key length is done only for specific ciphers */ - v = (conf->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5); - if (set80211param(drv, IEEE80211_PARAM_MCASTKEYLEN, v)) { - printf("Unable to set group key length to %u\n", v); - return -1; - } - } - - v = 0; - if (conf->wpa_pairwise & WPA_CIPHER_CCMP) - v |= 1<wpa_pairwise & WPA_CIPHER_TKIP) - v |= 1<wpa_pairwise & WPA_CIPHER_NONE) - v |= 1<wpa_key_mgmt); - if (set80211param(drv, IEEE80211_PARAM_KEYMGTALGS, conf->wpa_key_mgmt)) { - printf("Unable to set key management algorithms to 0x%x\n", - conf->wpa_key_mgmt); - return -1; - } - - v = 0; - if (conf->rsn_preauth) - v |= BIT(0); - wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x", - __func__, conf->rsn_preauth); - if (set80211param(drv, IEEE80211_PARAM_RSNCAPS, v)) { - printf("Unable to set RSN capabilities to 0x%x\n", v); - return -1; - } - - wpa_printf(MSG_DEBUG, "%s: enable WPA=0x%x", __func__, conf->wpa); - if (set80211param(drv, IEEE80211_PARAM_WPA, conf->wpa)) { - printf("Unable to set WPA to %u\n", conf->wpa); - return -1; - } - return 0; -} - - -static int -madwifi_set_iface_flags(void *priv, int dev_up) -{ - struct madwifi_driver_data *drv = priv; - struct ifreq ifr; - - wpa_printf(MSG_DEBUG, "%s: dev_up=%d", __func__, dev_up); - - if (drv->ioctl_sock < 0) - return -1; - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ); - - if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCGIFFLAGS]"); - return -1; - } - - if (dev_up) - ifr.ifr_flags |= IFF_UP; - else - ifr.ifr_flags &= ~IFF_UP; - - if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCSIFFLAGS]"); - return -1; - } - - if (dev_up) { - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ); - ifr.ifr_mtu = HOSTAPD_MTU; - if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) { - perror("ioctl[SIOCSIFMTU]"); - printf("Setting MTU failed - trying to survive with " - "current value\n"); - } - } - - return 0; -} - -static int -madwifi_set_ieee8021x(const char *ifname, void *priv, int enabled) -{ - struct madwifi_driver_data *drv = priv; - struct hostapd_data *hapd = drv->hapd; - struct hostapd_bss_config *conf = hapd->conf; - - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - - if (!enabled) { - /* XXX restore state */ - return set80211param(priv, IEEE80211_PARAM_AUTHMODE, - IEEE80211_AUTH_AUTO); - } - if (!conf->wpa && !conf->ieee802_1x) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER, - HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!"); - return -1; - } - if (conf->wpa && madwifi_configure_wpa(drv) != 0) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER, - HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!"); - return -1; - } - if (set80211param(priv, IEEE80211_PARAM_AUTHMODE, - (conf->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER, - HOSTAPD_LEVEL_WARNING, "Error enabling WPA/802.1X!"); - return -1; - } - - return 0; -} - -static int -madwifi_set_privacy(const char *ifname, void *priv, int enabled) -{ - struct madwifi_driver_data *drv = priv; - - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - - return set80211param(drv, IEEE80211_PARAM_PRIVACY, enabled); -} - -static int -madwifi_set_sta_authorized(void *priv, const u8 *addr, int authorized) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s authorized=%d", - __func__, ether_sprintf(addr), authorized); - - if (authorized) - mlme.im_op = IEEE80211_MLME_AUTHORIZE; - else - mlme.im_op = IEEE80211_MLME_UNAUTHORIZE; - mlme.im_reason = 0; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to %sauthorize STA " MACSTR, - __func__, authorized ? "" : "un", MAC2STR(addr)); - } - - return ret; -} - -static int -madwifi_sta_set_flags(void *priv, const u8 *addr, int total_flags, - int flags_or, int flags_and) -{ - /* For now, only support setting Authorized flag */ - if (flags_or & WLAN_STA_AUTHORIZED) - return madwifi_set_sta_authorized(priv, addr, 1); - if (!(flags_and & WLAN_STA_AUTHORIZED)) - return madwifi_set_sta_authorized(priv, addr, 0); - return 0; -} - -static int -madwifi_del_key(void *priv, const u8 *addr, int key_idx) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_del_key wk; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s key_idx=%d", - __func__, ether_sprintf(addr), key_idx); - - memset(&wk, 0, sizeof(wk)); - if (addr != NULL) { - memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); - wk.idk_keyix = (u8) IEEE80211_KEYIX_NONE; - } else { - wk.idk_keyix = key_idx; - } - - ret = set80211priv(drv, IEEE80211_IOCTL_DELKEY, &wk, sizeof(wk)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to delete key (addr %s" - " key_idx %d)", __func__, ether_sprintf(addr), - key_idx); - } - - return ret; -} - -static int -madwifi_set_key(const char *ifname, void *priv, const char *alg, - const u8 *addr, int key_idx, - const u8 *key, size_t key_len, int txkey) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_key wk; - u_int8_t cipher; - int ret; - - if (strcmp(alg, "none") == 0) - return madwifi_del_key(drv, addr, key_idx); - - wpa_printf(MSG_DEBUG, "%s: alg=%s addr=%s key_idx=%d", - __func__, alg, ether_sprintf(addr), key_idx); - - if (strcmp(alg, "WEP") == 0) - cipher = IEEE80211_CIPHER_WEP; - else if (strcmp(alg, "TKIP") == 0) - cipher = IEEE80211_CIPHER_TKIP; - else if (strcmp(alg, "CCMP") == 0) - cipher = IEEE80211_CIPHER_AES_CCM; - else { - printf("%s: unknown/unsupported algorithm %s\n", - __func__, alg); - return -1; - } - - if (key_len > sizeof(wk.ik_keydata)) { - printf("%s: key length %lu too big\n", __func__, - (unsigned long) key_len); - return -3; - } - - memset(&wk, 0, sizeof(wk)); - wk.ik_type = cipher; - wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT; - if (addr == NULL) { - memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); - wk.ik_keyix = key_idx; - wk.ik_flags |= IEEE80211_KEY_DEFAULT; - } else { - memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); - wk.ik_keyix = IEEE80211_KEYIX_NONE; - } - wk.ik_keylen = key_len; - memcpy(wk.ik_keydata, key, key_len); - - ret = set80211priv(drv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to set key (addr %s" - " key_idx %d alg '%s' key_len %lu txkey %d)", - __func__, ether_sprintf(wk.ik_macaddr), key_idx, - alg, (unsigned long) key_len, txkey); - } - - return ret; -} - - -static int -madwifi_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx, - u8 *seq) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_key wk; - - wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d", - __func__, ether_sprintf(addr), idx); - - memset(&wk, 0, sizeof(wk)); - if (addr == NULL) - memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); - else - memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); - wk.ik_keyix = idx; - - if (set80211priv(drv, IEEE80211_IOCTL_GETKEY, &wk, sizeof(wk))) { - wpa_printf(MSG_DEBUG, "%s: Failed to get encryption data " - "(addr " MACSTR " key_idx %d)", - __func__, MAC2STR(wk.ik_macaddr), idx); - return -1; - } - -#ifdef WORDS_BIGENDIAN - { - /* - * wk.ik_keytsc is in host byte order (big endian), need to - * swap it to match with the byte order used in WPA. - */ - int i; - u8 tmp[WPA_KEY_RSC_LEN]; - memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); - for (i = 0; i < WPA_KEY_RSC_LEN; i++) { - seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1]; - } - } -#else /* WORDS_BIGENDIAN */ - memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); -#endif /* WORDS_BIGENDIAN */ - return 0; -} - - -static int -madwifi_flush(void *priv) -{ -#ifdef MADWIFI_BSD - u8 allsta[IEEE80211_ADDR_LEN]; - memset(allsta, 0xff, IEEE80211_ADDR_LEN); - return madwifi_sta_deauth(priv, allsta, IEEE80211_REASON_AUTH_LEAVE); -#else /* MADWIFI_BSD */ - return 0; /* XXX */ -#endif /* MADWIFI_BSD */ -} - - -static int -madwifi_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data, - const u8 *addr) -{ - struct madwifi_driver_data *drv = priv; - -#ifdef MADWIFI_BSD - struct ieee80211req_sta_stats stats; - - memset(data, 0, sizeof(*data)); - - /* - * Fetch statistics for station from the system. - */ - memset(&stats, 0, sizeof(stats)); - memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN); - if (set80211priv(drv, -#ifdef MADWIFI_NG - IEEE80211_IOCTL_STA_STATS, -#else /* MADWIFI_NG */ - IEEE80211_IOCTL_GETSTASTATS, -#endif /* MADWIFI_NG */ - &stats, sizeof(stats))) { - wpa_printf(MSG_DEBUG, "%s: Failed to fetch STA stats (addr " - MACSTR ")", __func__, MAC2STR(addr)); - if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) { - memcpy(data, &drv->acct_data, sizeof(*data)); - return 0; - } - - printf("Failed to get station stats information element.\n"); - return -1; - } - - data->rx_packets = stats.is_stats.ns_rx_data; - data->rx_bytes = stats.is_stats.ns_rx_bytes; - data->tx_packets = stats.is_stats.ns_tx_data; - data->tx_bytes = stats.is_stats.ns_tx_bytes; - return 0; - -#else /* MADWIFI_BSD */ - - char buf[1024], line[128], *pos; - FILE *f; - unsigned long val; - - memset(data, 0, sizeof(*data)); - snprintf(buf, sizeof(buf), "/proc/net/madwifi/%s/" MACSTR, - drv->iface, MAC2STR(addr)); - - f = fopen(buf, "r"); - if (!f) { - if (memcmp(addr, drv->acct_mac, ETH_ALEN) != 0) - return -1; - memcpy(data, &drv->acct_data, sizeof(*data)); - return 0; - } - /* Need to read proc file with in one piece, so use large enough - * buffer. */ - setbuffer(f, buf, sizeof(buf)); - - while (fgets(line, sizeof(line), f)) { - pos = strchr(line, '='); - if (!pos) - continue; - *pos++ = '\0'; - val = strtoul(pos, NULL, 10); - if (strcmp(line, "rx_packets") == 0) - data->rx_packets = val; - else if (strcmp(line, "tx_packets") == 0) - data->tx_packets = val; - else if (strcmp(line, "rx_bytes") == 0) - data->rx_bytes = val; - else if (strcmp(line, "tx_bytes") == 0) - data->tx_bytes = val; - } - - fclose(f); - - return 0; -#endif /* MADWIFI_BSD */ -} - - -static int -madwifi_sta_clear_stats(void *priv, const u8 *addr) -{ -#if defined(MADWIFI_BSD) && defined(IEEE80211_MLME_CLEAR_STATS) - struct madwifi_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s", __func__, ether_sprintf(addr)); - - mlme.im_op = IEEE80211_MLME_CLEAR_STATS; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, - sizeof(mlme)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to clear STA stats (addr " - MACSTR ")", __func__, MAC2STR(addr)); - } - - return ret; -#else /* MADWIFI_BSD && IEEE80211_MLME_CLEAR_STATS */ - return 0; /* FIX */ -#endif /* MADWIFI_BSD && IEEE80211_MLME_CLEAR_STATS */ -} - - -static int -madwifi_set_opt_ie(const char *ifname, void *priv, const u8 *ie, size_t ie_len) -{ - /* - * Do nothing; we setup parameters at startup that define the - * contents of the beacon information element. - */ - return 0; -} - -static int -madwifi_sta_deauth(void *priv, const u8 *addr, int reason_code) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d", - __func__, ether_sprintf(addr), reason_code); - - mlme.im_op = IEEE80211_MLME_DEAUTH; - mlme.im_reason = reason_code; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to deauth STA (addr " MACSTR - " reason %d)", - __func__, MAC2STR(addr), reason_code); - } - - return ret; -} - -static int -madwifi_sta_disassoc(void *priv, const u8 *addr, int reason_code) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d", - __func__, ether_sprintf(addr), reason_code); - - mlme.im_op = IEEE80211_MLME_DISASSOC; - mlme.im_reason = reason_code; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to disassoc STA (addr " - MACSTR " reason %d)", - __func__, MAC2STR(addr), reason_code); - } - - return ret; -} - -#ifdef CONFIG_WPS -#ifdef IEEE80211_IOCTL_FILTERFRAME -static void madwifi_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf, - size_t len) -{ - struct madwifi_driver_data *drv = ctx; - const struct ieee80211_mgmt *mgmt; - const u8 *end, *ie; - u16 fc; - size_t ie_len; - - /* Send Probe Request information to WPS processing */ - - if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)) - return; - mgmt = (const struct ieee80211_mgmt *) buf; - - fc = le_to_host16(mgmt->frame_control); - if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT || - WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_PROBE_REQ) - return; - - end = buf + len; - ie = mgmt->u.probe_req.variable; - ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)); - - hostapd_wps_probe_req_rx(drv->hapd, mgmt->sa, ie, ie_len); -} -#endif /* IEEE80211_IOCTL_FILTERFRAME */ -#endif /* CONFIG_WPS */ - -static int madwifi_receive_probe_req(struct madwifi_driver_data *drv) -{ - int ret = 0; -#ifdef CONFIG_WPS -#ifdef IEEE80211_IOCTL_FILTERFRAME - struct ieee80211req_set_filter filt; - - wpa_printf(MSG_DEBUG, "%s Enter", __func__); - filt.app_filterype = IEEE80211_FILTER_TYPE_PROBE_REQ; - - ret = set80211priv(drv, IEEE80211_IOCTL_FILTERFRAME, &filt, - sizeof(struct ieee80211req_set_filter)); - if (ret) - return ret; - - drv->sock_raw = l2_packet_init(drv->iface, NULL, ETH_P_80211_RAW, - madwifi_raw_receive, drv, 1); - if (drv->sock_raw == NULL) - return -1; -#endif /* IEEE80211_IOCTL_FILTERFRAME */ -#endif /* CONFIG_WPS */ - return ret; -} - -static int -madwifi_del_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN]) -{ - struct hostapd_data *hapd = drv->hapd; - struct sta_info *sta; - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "disassociated"); - - sta = ap_get_sta(hapd, addr); - if (sta != NULL) { - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); - wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); - sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; - ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - ap_free_sta(hapd, sta); - } - return 0; -} - -#ifdef CONFIG_WPS -static int -madwifi_set_wps_ie(void *priv, const u8 *ie, size_t len, u32 frametype) -{ - struct madwifi_driver_data *drv = priv; - u8 buf[256]; - struct ieee80211req_getset_appiebuf *beac_ie; - - wpa_printf(MSG_DEBUG, "%s buflen = %lu", __func__, - (unsigned long) len); - - beac_ie = (struct ieee80211req_getset_appiebuf *) buf; - beac_ie->app_frmtype = frametype; - beac_ie->app_buflen = len; - memcpy(&(beac_ie->app_buf[0]), ie, len); - - return set80211priv(drv, IEEE80211_IOCTL_SET_APPIEBUF, beac_ie, - sizeof(struct ieee80211req_getset_appiebuf) + len); -} - -static int -madwifi_set_wps_beacon_ie(const char *ifname, void *priv, const u8 *ie, - size_t len) -{ - return madwifi_set_wps_ie(priv, ie, len, IEEE80211_APPIE_FRAME_BEACON); -} - -static int -madwifi_set_wps_probe_resp_ie(const char *ifname, void *priv, const u8 *ie, - size_t len) -{ - return madwifi_set_wps_ie(priv, ie, len, - IEEE80211_APPIE_FRAME_PROBE_RESP); -} -#else /* CONFIG_WPS */ -#define madwifi_set_wps_beacon_ie NULL -#define madwifi_set_wps_probe_resp_ie NULL -#endif /* CONFIG_WPS */ - -static int -madwifi_process_wpa_ie(struct madwifi_driver_data *drv, struct sta_info *sta) -{ - struct hostapd_data *hapd = drv->hapd; - struct ieee80211req_wpaie ie; - int ielen, res; - u8 *iebuf; - - /* - * Fetch negotiated WPA/RSN parameters from the system. - */ - memset(&ie, 0, sizeof(ie)); - memcpy(ie.wpa_macaddr, sta->addr, IEEE80211_ADDR_LEN); - if (set80211priv(drv, IEEE80211_IOCTL_GETWPAIE, &ie, sizeof(ie))) { - wpa_printf(MSG_ERROR, "%s: Failed to get WPA/RSN IE", - __func__); - printf("Failed to get WPA/RSN information element.\n"); - return -1; /* XXX not right */ - } - wpa_hexdump(MSG_MSGDUMP, "madwifi req WPA IE", - ie.wpa_ie, IEEE80211_MAX_OPT_IE); - iebuf = ie.wpa_ie; - /* madwifi seems to return some random data if WPA/RSN IE is not set. - * Assume the IE was not included if the IE type is unknown. */ - if (iebuf[0] != WLAN_EID_VENDOR_SPECIFIC) - iebuf[1] = 0; -#ifdef MADWIFI_NG - wpa_hexdump(MSG_MSGDUMP, "madwifi req RSN IE", - ie.rsn_ie, IEEE80211_MAX_OPT_IE); - if (iebuf[1] == 0 && ie.rsn_ie[1] > 0) { - /* madwifi-ng svn #1453 added rsn_ie. Use it, if wpa_ie was not - * set. This is needed for WPA2. */ - iebuf = ie.rsn_ie; - if (iebuf[0] != WLAN_EID_RSN) - iebuf[1] = 0; - } -#endif /* MADWIFI_NG */ - ielen = iebuf[1]; - if (ielen == 0) { -#ifdef CONFIG_WPS - if (hapd->conf->wps_state) { - wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE " - "in (Re)Association Request - possible WPS " - "use"); - sta->flags |= WLAN_STA_MAYBE_WPS; - return 0; - } -#endif /* CONFIG_WPS */ - printf("No WPA/RSN information element for station!?\n"); - return -1; /* XXX not right */ - } - ielen += 2; - if (sta->wpa_sm == NULL) - sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr); - if (sta->wpa_sm == NULL) { - printf("Failed to initialize WPA state machine\n"); - return -1; - } - res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, - iebuf, ielen, NULL, 0); - if (res != WPA_IE_OK) { - printf("WPA/RSN information element rejected? (res %u)\n", res); - return -1; - } - return 0; -} - -static int -madwifi_new_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN]) -{ - struct hostapd_data *hapd = drv->hapd; - struct sta_info *sta; - int new_assoc; - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "associated"); - - sta = ap_get_sta(hapd, addr); - if (sta) { - accounting_sta_stop(hapd, sta); - } else { - sta = ap_sta_add(hapd, addr); - if (sta == NULL) - return -1; - } - - if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) { - /* Cached accounting data is not valid anymore. */ - memset(drv->acct_mac, 0, ETH_ALEN); - memset(&drv->acct_data, 0, sizeof(drv->acct_data)); - } - - if (hapd->conf->wpa) { - if (madwifi_process_wpa_ie(drv, sta)) - return -1; - } - - /* - * Now that the internal station state is setup - * kick the authenticator into action. - */ - new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0; - sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; - wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); - hostapd_new_assoc_sta(hapd, sta, !new_assoc); - ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); - return 0; -} - -static void -madwifi_wireless_event_wireless_custom(struct madwifi_driver_data *drv, - char *custom) -{ - wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom); - - if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) { - char *pos; - u8 addr[ETH_ALEN]; - pos = strstr(custom, "addr="); - if (pos == NULL) { - wpa_printf(MSG_DEBUG, - "MLME-MICHAELMICFAILURE.indication " - "without sender address ignored"); - return; - } - pos += 5; - if (hwaddr_aton(pos, addr) == 0) { - ieee80211_michael_mic_failure(drv->hapd, addr, 1); - } else { - wpa_printf(MSG_DEBUG, - "MLME-MICHAELMICFAILURE.indication " - "with invalid MAC address"); - } - } else if (strncmp(custom, "STA-TRAFFIC-STAT", 16) == 0) { - char *key, *value; - u32 val; - key = custom; - while ((key = strchr(key, '\n')) != NULL) { - key++; - value = strchr(key, '='); - if (value == NULL) - continue; - *value++ = '\0'; - val = strtoul(value, NULL, 10); - if (strcmp(key, "mac") == 0) - hwaddr_aton(value, drv->acct_mac); - else if (strcmp(key, "rx_packets") == 0) - drv->acct_data.rx_packets = val; - else if (strcmp(key, "tx_packets") == 0) - drv->acct_data.tx_packets = val; - else if (strcmp(key, "rx_bytes") == 0) - drv->acct_data.rx_bytes = val; - else if (strcmp(key, "tx_bytes") == 0) - drv->acct_data.tx_bytes = val; - key = value; - } - } -} - -static void -madwifi_wireless_event_wireless(struct madwifi_driver_data *drv, - char *data, int len) -{ - struct iw_event iwe_buf, *iwe = &iwe_buf; - char *pos, *end, *custom, *buf; - - pos = data; - end = data + len; - - while (pos + IW_EV_LCP_LEN <= end) { - /* Event data may be unaligned, so make a local, aligned copy - * before processing. */ - memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); - wpa_printf(MSG_MSGDUMP, "Wireless event: cmd=0x%x len=%d", - iwe->cmd, iwe->len); - if (iwe->len <= IW_EV_LCP_LEN) - return; - - custom = pos + IW_EV_POINT_LEN; - if (drv->we_version > 18 && - (iwe->cmd == IWEVMICHAELMICFAILURE || - iwe->cmd == IWEVCUSTOM)) { - /* WE-19 removed the pointer from struct iw_point */ - char *dpos = (char *) &iwe_buf.u.data.length; - int dlen = dpos - (char *) &iwe_buf; - memcpy(dpos, pos + IW_EV_LCP_LEN, - sizeof(struct iw_event) - dlen); - } else { - memcpy(&iwe_buf, pos, sizeof(struct iw_event)); - custom += IW_EV_POINT_OFF; - } - - switch (iwe->cmd) { - case IWEVEXPIRED: - madwifi_del_sta(drv, (u8 *) iwe->u.addr.sa_data); - break; - case IWEVREGISTERED: - madwifi_new_sta(drv, (u8 *) iwe->u.addr.sa_data); - break; - case IWEVCUSTOM: - if (custom + iwe->u.data.length > end) - return; - buf = malloc(iwe->u.data.length + 1); - if (buf == NULL) - return; /* XXX */ - memcpy(buf, custom, iwe->u.data.length); - buf[iwe->u.data.length] = '\0'; - madwifi_wireless_event_wireless_custom(drv, buf); - free(buf); - break; - } - - pos += iwe->len; - } -} - - -static void -madwifi_wireless_event_rtm_newlink(struct madwifi_driver_data *drv, - struct nlmsghdr *h, int len) -{ - struct ifinfomsg *ifi; - int attrlen, nlmsg_len, rta_len; - struct rtattr * attr; - - if (len < (int) sizeof(*ifi)) - return; - - ifi = NLMSG_DATA(h); - - if (ifi->ifi_index != drv->ifindex) - return; - - nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); - - attrlen = h->nlmsg_len - nlmsg_len; - if (attrlen < 0) - return; - - attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_WIRELESS) { - madwifi_wireless_event_wireless( - drv, ((char *) attr) + rta_len, - attr->rta_len - rta_len); - } - attr = RTA_NEXT(attr, attrlen); - } -} - - -static void -madwifi_wireless_event_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - char buf[256]; - int left; - struct sockaddr_nl from; - socklen_t fromlen; - struct nlmsghdr *h; - struct madwifi_driver_data *drv = eloop_ctx; - - fromlen = sizeof(from); - left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, - (struct sockaddr *) &from, &fromlen); - if (left < 0) { - if (errno != EINTR && errno != EAGAIN) - perror("recvfrom(netlink)"); - return; - } - - h = (struct nlmsghdr *) buf; - while (left >= (int) sizeof(*h)) { - int len, plen; - - len = h->nlmsg_len; - plen = len - sizeof(*h); - if (len > left || plen < 0) { - printf("Malformed netlink message: " - "len=%d left=%d plen=%d\n", - len, left, plen); - break; - } - - switch (h->nlmsg_type) { - case RTM_NEWLINK: - madwifi_wireless_event_rtm_newlink(drv, h, plen); - break; - } - - len = NLMSG_ALIGN(len); - left -= len; - h = (struct nlmsghdr *) ((char *) h + len); - } - - if (left > 0) { - printf("%d extra bytes in the end of netlink message\n", left); - } -} - - -static int -madwifi_get_we_version(struct madwifi_driver_data *drv) -{ - struct iw_range *range; - struct iwreq iwr; - int minlen; - size_t buflen; - - drv->we_version = 0; - - /* - * Use larger buffer than struct iw_range in order to allow the - * structure to grow in the future. - */ - buflen = sizeof(struct iw_range) + 500; - range = os_zalloc(buflen); - if (range == NULL) - return -1; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) range; - iwr.u.data.length = buflen; - - minlen = ((char *) &range->enc_capa) - (char *) range + - sizeof(range->enc_capa); - - if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) { - perror("ioctl[SIOCGIWRANGE]"); - free(range); - return -1; - } else if (iwr.u.data.length >= minlen && - range->we_version_compiled >= 18) { - wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d " - "WE(source)=%d enc_capa=0x%x", - range->we_version_compiled, - range->we_version_source, - range->enc_capa); - drv->we_version = range->we_version_compiled; - } - - free(range); - return 0; -} - - -static int -madwifi_wireless_event_init(void *priv) -{ - struct madwifi_driver_data *drv = priv; - int s; - struct sockaddr_nl local; - - madwifi_get_we_version(drv); - - drv->wext_sock = -1; - - s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (s < 0) { - perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)"); - return -1; - } - - memset(&local, 0, sizeof(local)); - local.nl_family = AF_NETLINK; - local.nl_groups = RTMGRP_LINK; - if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) { - perror("bind(netlink)"); - close(s); - return -1; - } - - eloop_register_read_sock(s, madwifi_wireless_event_receive, drv, NULL); - drv->wext_sock = s; - - return 0; -} - - -static void -madwifi_wireless_event_deinit(void *priv) -{ - struct madwifi_driver_data *drv = priv; - - if (drv != NULL) { - if (drv->wext_sock < 0) - return; - eloop_unregister_read_sock(drv->wext_sock); - close(drv->wext_sock); - } -} - - -static int -madwifi_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len, - int encrypt, const u8 *own_addr) -{ - struct madwifi_driver_data *drv = priv; - unsigned char buf[3000]; - unsigned char *bp = buf; - struct l2_ethhdr *eth; - size_t len; - int status; - - /* - * Prepend the Ethernet header. If the caller left us - * space at the front we could just insert it but since - * we don't know we copy to a local buffer. Given the frequency - * and size of frames this probably doesn't matter. - */ - len = data_len + sizeof(struct l2_ethhdr); - if (len > sizeof(buf)) { - bp = malloc(len); - if (bp == NULL) { - printf("EAPOL frame discarded, cannot malloc temp " - "buffer of size %lu!\n", (unsigned long) len); - return -1; - } - } - eth = (struct l2_ethhdr *) bp; - memcpy(eth->h_dest, addr, ETH_ALEN); - memcpy(eth->h_source, own_addr, ETH_ALEN); - eth->h_proto = htons(ETH_P_EAPOL); - memcpy(eth+1, data, data_len); - - wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len); - - status = l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, bp, len); - - if (bp != buf) - free(bp); - return status; -} - -static void -handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) -{ - struct madwifi_driver_data *drv = ctx; - struct hostapd_data *hapd = drv->hapd; - struct sta_info *sta; - - sta = ap_get_sta(hapd, src_addr); - if (!sta || !(sta->flags & WLAN_STA_ASSOC)) { - printf("Data frame from not associated STA %s\n", - ether_sprintf(src_addr)); - /* XXX cannot happen */ - return; - } - ieee802_1x_receive(hapd, src_addr, buf + sizeof(struct l2_ethhdr), - len - sizeof(struct l2_ethhdr)); -} - -static void * -madwifi_init(struct hostapd_data *hapd) -{ - struct madwifi_driver_data *drv; - struct ifreq ifr; - struct iwreq iwr; - - drv = os_zalloc(sizeof(struct madwifi_driver_data)); - if (drv == NULL) { - printf("Could not allocate memory for madwifi driver data\n"); - return NULL; - } - - drv->hapd = hapd; - drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->ioctl_sock < 0) { - perror("socket[PF_INET,SOCK_DGRAM]"); - goto bad; - } - memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface)); - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name)); - if (ioctl(drv->ioctl_sock, SIOCGIFINDEX, &ifr) != 0) { - perror("ioctl(SIOCGIFINDEX)"); - goto bad; - } - drv->ifindex = ifr.ifr_ifindex; - - drv->sock_xmit = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL, - handle_read, drv, 1); - if (drv->sock_xmit == NULL) - goto bad; - if (l2_packet_get_own_addr(drv->sock_xmit, hapd->own_addr)) - goto bad; - if (hapd->conf->bridge[0] != '\0') { - wpa_printf(MSG_DEBUG, "Configure bridge %s for EAPOL traffic.", - hapd->conf->bridge); - drv->sock_recv = l2_packet_init(hapd->conf->bridge, NULL, - ETH_P_EAPOL, handle_read, drv, - 1); - if (drv->sock_recv == NULL) - goto bad; - } else - drv->sock_recv = drv->sock_xmit; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - - iwr.u.mode = IW_MODE_MASTER; - - if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) { - perror("ioctl[SIOCSIWMODE]"); - printf("Could not set interface to master mode!\n"); - goto bad; - } - - madwifi_set_iface_flags(drv, 0); /* mark down during setup */ - madwifi_set_privacy(drv->iface, drv, 0); /* default to no privacy */ - - madwifi_receive_probe_req(drv); - - return drv; -bad: - if (drv->sock_xmit != NULL) - l2_packet_deinit(drv->sock_xmit); - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - if (drv != NULL) - free(drv); - return NULL; -} - - -static void -madwifi_deinit(void *priv) -{ - struct madwifi_driver_data *drv = priv; - - (void) madwifi_set_iface_flags(drv, 0); - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - if (drv->sock_recv != NULL && drv->sock_recv != drv->sock_xmit) - l2_packet_deinit(drv->sock_recv); - if (drv->sock_xmit != NULL) - l2_packet_deinit(drv->sock_xmit); - if (drv->sock_raw) - l2_packet_deinit(drv->sock_raw); - free(drv); -} - -static int -madwifi_set_ssid(const char *ifname, void *priv, const u8 *buf, int len) -{ - struct madwifi_driver_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.essid.flags = 1; /* SSID active */ - iwr.u.essid.pointer = (caddr_t) buf; - iwr.u.essid.length = len + 1; - - if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) { - perror("ioctl[SIOCSIWESSID]"); - printf("len=%d\n", len); - return -1; - } - return 0; -} - -static int -madwifi_get_ssid(const char *ifname, void *priv, u8 *buf, int len) -{ - struct madwifi_driver_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.essid.pointer = (caddr_t) buf; - iwr.u.essid.length = len; - - if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) { - perror("ioctl[SIOCGIWESSID]"); - ret = -1; - } else - ret = iwr.u.essid.length; - - return ret; -} - -static int -madwifi_set_countermeasures(void *priv, int enabled) -{ - struct madwifi_driver_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - return set80211param(drv, IEEE80211_PARAM_COUNTERMEASURES, enabled); -} - -static int -madwifi_commit(void *priv) -{ - return madwifi_set_iface_flags(priv, 1); -} - -const struct wpa_driver_ops wpa_driver_madwifi_ops = { - .name = "madwifi", - .init = madwifi_init, - .deinit = madwifi_deinit, - .set_ieee8021x = madwifi_set_ieee8021x, - .set_privacy = madwifi_set_privacy, - .set_encryption = madwifi_set_key, - .get_seqnum = madwifi_get_seqnum, - .flush = madwifi_flush, - .set_generic_elem = madwifi_set_opt_ie, - .wireless_event_init = madwifi_wireless_event_init, - .wireless_event_deinit = madwifi_wireless_event_deinit, - .sta_set_flags = madwifi_sta_set_flags, - .read_sta_data = madwifi_read_sta_driver_data, - .send_eapol = madwifi_send_eapol, - .sta_disassoc = madwifi_sta_disassoc, - .sta_deauth = madwifi_sta_deauth, - .set_ssid = madwifi_set_ssid, - .get_ssid = madwifi_get_ssid, - .set_countermeasures = madwifi_set_countermeasures, - .sta_clear_stats = madwifi_sta_clear_stats, - .commit = madwifi_commit, - .set_wps_beacon_ie = madwifi_set_wps_beacon_ie, - .set_wps_probe_resp_ie = madwifi_set_wps_probe_resp_ie, -}; diff --git a/contrib/hostapd/hostapd/driver_nl80211.c b/contrib/hostapd/hostapd/driver_nl80211.c deleted file mode 100644 index 4599e99ead..0000000000 --- a/contrib/hostapd/hostapd/driver_nl80211.c +++ /dev/null @@ -1,2708 +0,0 @@ -/* - * hostapd / Kernel driver communication via nl80211 - * Copyright (c) 2002-2007, Jouni Malinen - * Copyright (c) 2003-2004, Instant802 Networks, Inc. - * Copyright (c) 2005-2006, Devicescape Software, Inc. - * Copyright (c) 2007, Johannes Berg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include -#include -#include -#include -#include -#include -#include "nl80211_copy.h" -#include -#include -#include "wireless_copy.h" -#include -#include - -#include "hostapd.h" -#include "driver.h" -#include "ieee802_1x.h" -#include "eloop.h" -#include "ieee802_11.h" -#include "sta_info.h" -#include "hw_features.h" -#include "mlme.h" -#include "radiotap.h" -#include "radiotap_iter.h" - -#ifdef CONFIG_LIBNL20 -/* libnl 2.0 compatibility code */ -#define nl_handle_alloc_cb nl_socket_alloc_cb -#define nl_handle_destroy nl_socket_free -#endif /* CONFIG_LIBNL20 */ - -enum ieee80211_msg_type { - ieee80211_msg_normal = 0, - ieee80211_msg_tx_callback_ack = 1, - ieee80211_msg_tx_callback_fail = 2, -}; - -struct i802_driver_data { - struct hostapd_data *hapd; - - char iface[IFNAMSIZ + 1]; - int bridge; - int ioctl_sock; /* socket for ioctl() use */ - int wext_sock; /* socket for wireless events */ - int eapol_sock; /* socket for EAPOL frames */ - int monitor_sock; /* socket for monitor */ - int monitor_ifidx; - - int default_if_indices[16]; - int *if_indices; - int num_if_indices; - - int we_version; - struct nl_handle *nl_handle; - struct nl_cache *nl_cache; - struct nl_cb *nl_cb; - struct genl_family *nl80211; - int dtim_period, beacon_int; - unsigned int beacon_set:1; - unsigned int ieee802_1x_active:1; - - int last_freq; - int last_freq_ht; -}; - - -static void add_ifidx(struct i802_driver_data *drv, int ifidx) -{ - int i; - int *old; - - for (i = 0; i < drv->num_if_indices; i++) { - if (drv->if_indices[i] == 0) { - drv->if_indices[i] = ifidx; - return; - } - } - - if (drv->if_indices != drv->default_if_indices) - old = drv->if_indices; - else - old = NULL; - - drv->if_indices = realloc(old, - sizeof(int) * (drv->num_if_indices + 1)); - if (!drv->if_indices) { - if (!old) - drv->if_indices = drv->default_if_indices; - else - drv->if_indices = old; - wpa_printf(MSG_ERROR, "Failed to reallocate memory for " - "interfaces"); - wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx); - return; - } - drv->if_indices[drv->num_if_indices] = ifidx; - drv->num_if_indices++; -} - - -static void del_ifidx(struct i802_driver_data *drv, int ifidx) -{ - int i; - - for (i = 0; i < drv->num_if_indices; i++) { - if (drv->if_indices[i] == ifidx) { - drv->if_indices[i] = 0; - break; - } - } -} - - -static int have_ifidx(struct i802_driver_data *drv, int ifidx) -{ - int i; - - if (ifidx == drv->bridge) - return 1; - - for (i = 0; i < drv->num_if_indices; i++) - if (drv->if_indices[i] == ifidx) - return 1; - - return 0; -} - - -/* nl80211 code */ -static int ack_handler(struct nl_msg *msg, void *arg) -{ - int *err = arg; - *err = 0; - return NL_STOP; -} - -static int finish_handler(struct nl_msg *msg, void *arg) -{ - int *ret = arg; - *ret = 0; - return NL_SKIP; -} - -static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, - void *arg) -{ - int *ret = arg; - *ret = err->error; - return NL_SKIP; -} - -static int send_and_recv_msgs(struct i802_driver_data *drv, - struct nl_msg *msg, - int (*valid_handler)(struct nl_msg *, void *), - void *valid_data) -{ - struct nl_cb *cb; - int err = -ENOMEM; - - cb = nl_cb_clone(drv->nl_cb); - if (!cb) - goto out; - - err = nl_send_auto_complete(drv->nl_handle, msg); - if (err < 0) - goto out; - - err = 1; - - nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); - nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); - nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); - - if (valid_handler) - nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, - valid_handler, valid_data); - - while (err > 0) - nl_recvmsgs(drv->nl_handle, cb); - out: - nl_cb_put(cb); - nlmsg_free(msg); - return err; -} - -static int hostapd_set_iface_flags(struct i802_driver_data *drv, - const char *ifname, int dev_up) -{ - struct ifreq ifr; - - if (drv->ioctl_sock < 0) - return -1; - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); - - if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCGIFFLAGS]"); - wpa_printf(MSG_DEBUG, "Could not read interface flags (%s)", - drv->iface); - return -1; - } - - if (dev_up) - ifr.ifr_flags |= IFF_UP; - else - ifr.ifr_flags &= ~IFF_UP; - - if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCSIFFLAGS]"); - return -1; - } - - return 0; -} - - -static int nl_set_encr(int ifindex, struct i802_driver_data *drv, - const char *alg, const u8 *addr, int idx, const u8 *key, - size_t key_len, int txkey) -{ - struct nl_msg *msg; - int ret; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - if (strcmp(alg, "none") == 0) { - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_DEL_KEY, 0); - } else { - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_NEW_KEY, 0); - NLA_PUT(msg, NL80211_ATTR_KEY_DATA, key_len, key); - if (strcmp(alg, "WEP") == 0) { - if (key_len == 5) - NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, - 0x000FAC01); - else - NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, - 0x000FAC05); - } else if (strcmp(alg, "TKIP") == 0) - NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC02); - else if (strcmp(alg, "CCMP") == 0) - NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC04); - else if (strcmp(alg, "IGTK") == 0) - NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC06); - else { - wpa_printf(MSG_ERROR, "%s: Unsupported encryption " - "algorithm '%s'", __func__, alg); - nlmsg_free(msg); - return -1; - } - } - - if (addr) - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (ret == -ENOENT) - ret = 0; - - /* - * If we failed or don't need to set the default TX key (below), - * we're done here. - */ - if (ret || !txkey || addr) - return ret; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_KEY, 0); - NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); - if (strcmp(alg, "IGTK") == 0) - NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT_MGMT); - else - NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (ret == -ENOENT) - ret = 0; - return ret; - nla_put_failure: - return -ENOBUFS; -} - - -static int i802_set_encryption(const char *iface, void *priv, const char *alg, - const u8 *addr, int idx, const u8 *key, - size_t key_len, int txkey) -{ - struct i802_driver_data *drv = priv; - int ret; - - ret = nl_set_encr(if_nametoindex(iface), drv, alg, addr, idx, key, - key_len, txkey); - if (ret < 0) - return ret; - - return ret; -} - - -static inline int min_int(int a, int b) -{ - if (a < b) - return a; - return b; -} - - -static int get_key_handler(struct nl_msg *msg, void *arg) -{ - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - /* - * TODO: validate the key index and mac address! - * Otherwise, there's a race condition as soon as - * the kernel starts sending key notifications. - */ - - if (tb[NL80211_ATTR_KEY_SEQ]) - memcpy(arg, nla_data(tb[NL80211_ATTR_KEY_SEQ]), - min_int(nla_len(tb[NL80211_ATTR_KEY_SEQ]), 6)); - return NL_SKIP; -} - - -static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr, - int idx, u8 *seq) -{ - struct i802_driver_data *drv = priv; - struct nl_msg *msg; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_GET_KEY, 0); - - if (addr) - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface)); - - memset(seq, 0, 6); - - return send_and_recv_msgs(drv, msg, get_key_handler, seq); - nla_put_failure: - return -ENOBUFS; -} - - -static int i802_set_rate_sets(void *priv, int *supp_rates, int *basic_rates, - int mode) -{ - struct i802_driver_data *drv = priv; - struct nl_msg *msg; - u8 rates[NL80211_MAX_SUPP_RATES]; - u8 rates_len = 0; - int i; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_SET_BSS, 0); - - for (i = 0; i < NL80211_MAX_SUPP_RATES && basic_rates[i] >= 0; i++) - rates[rates_len++] = basic_rates[i] / 5; - - NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates); - - /* TODO: multi-BSS support */ - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); - - return send_and_recv_msgs(drv, msg, NULL, NULL); - nla_put_failure: - return -ENOBUFS; -} - - -static int i802_send_frame(void *priv, const void *data, size_t len, - int encrypt, int flags) -{ - __u8 rtap_hdr[] = { - 0x00, 0x00, /* radiotap version */ - 0x0e, 0x00, /* radiotap length */ - 0x02, 0xc0, 0x00, 0x00, /* bmap: flags, tx and rx flags */ - IEEE80211_RADIOTAP_F_FRAG, /* F_FRAG (fragment if required) */ - 0x00, /* padding */ - 0x00, 0x00, /* RX and TX flags to indicate that */ - 0x00, 0x00, /* this is the injected frame directly */ - }; - struct i802_driver_data *drv = priv; - struct iovec iov[2] = { - { - .iov_base = &rtap_hdr, - .iov_len = sizeof(rtap_hdr), - }, - { - .iov_base = (void*)data, - .iov_len = len, - } - }; - struct msghdr msg = { - .msg_name = NULL, - .msg_namelen = 0, - .msg_iov = iov, - .msg_iovlen = 2, - .msg_control = NULL, - .msg_controllen = 0, - .msg_flags = 0, - }; - - if (encrypt) - rtap_hdr[8] |= IEEE80211_RADIOTAP_F_WEP; - - return sendmsg(drv->monitor_sock, &msg, flags); -} - -static int i802_send_mgmt_frame(void *priv, const void *data, size_t len, - int flags) -{ - struct ieee80211_mgmt *mgmt; - int do_not_encrypt = 0; - u16 fc; - - mgmt = (struct ieee80211_mgmt *) data; - fc = le_to_host16(mgmt->frame_control); - - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && - WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_AUTH) { - /* - * Only one of the authentication frame types is encrypted. - * In order for static WEP encryption to work properly (i.e., - * to not encrypt the frame), we need to tell mac80211 about - * the frames that must not be encrypted. - */ - u16 auth_alg = le_to_host16(mgmt->u.auth.auth_alg); - u16 auth_trans = le_to_host16(mgmt->u.auth.auth_transaction); - if (auth_alg == WLAN_AUTH_OPEN || - (auth_alg == WLAN_AUTH_SHARED_KEY && auth_trans != 3)) - do_not_encrypt = 1; - } - - return i802_send_frame(priv, data, len, !do_not_encrypt, flags); -} - -/* Set kernel driver on given frequency (MHz) */ -static int i802_set_freq2(void *priv, struct hostapd_freq_params *freq) -{ - struct i802_driver_data *drv = priv; - struct nl_msg *msg; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - drv->last_freq = freq->freq; - drv->last_freq_ht = freq->ht_enabled; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_SET_WIPHY, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq); - if (freq->ht_enabled) { - switch (freq->sec_channel_offset) { - case -1: - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, - NL80211_CHAN_HT40MINUS); - break; - case 1: - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, - NL80211_CHAN_HT40PLUS); - break; - default: - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, - NL80211_CHAN_HT20); - break; - } - } - - if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) - return 0; - nla_put_failure: - return -1; -} - - -static int i802_set_rts(void *priv, int rts) -{ - struct i802_driver_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ); - iwr.u.rts.value = rts; - iwr.u.rts.fixed = 1; - - if (ioctl(drv->ioctl_sock, SIOCSIWRTS, &iwr) < 0) { - perror("ioctl[SIOCSIWRTS]"); - return -1; - } - - return 0; -} - - -static int i802_get_rts(void *priv, int *rts) -{ - struct i802_driver_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ); - - if (ioctl(drv->ioctl_sock, SIOCGIWRTS, &iwr) < 0) { - perror("ioctl[SIOCGIWRTS]"); - return -1; - } - - *rts = iwr.u.rts.value; - - return 0; -} - - -static int i802_set_frag(void *priv, int frag) -{ - struct i802_driver_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ); - iwr.u.frag.value = frag; - iwr.u.frag.fixed = 1; - - if (ioctl(drv->ioctl_sock, SIOCSIWFRAG, &iwr) < 0) { - perror("ioctl[SIOCSIWFRAG]"); - return -1; - } - - return 0; -} - - -static int i802_get_frag(void *priv, int *frag) -{ - struct i802_driver_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ); - - if (ioctl(drv->ioctl_sock, SIOCGIWFRAG, &iwr) < 0) { - perror("ioctl[SIOCGIWFRAG]"); - return -1; - } - - *frag = iwr.u.frag.value; - - return 0; -} - - -static int i802_set_retry(void *priv, int short_retry, int long_retry) -{ - struct i802_driver_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ); - - iwr.u.retry.value = short_retry; - iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; - if (ioctl(drv->ioctl_sock, SIOCSIWRETRY, &iwr) < 0) { - perror("ioctl[SIOCSIWRETRY(short)]"); - return -1; - } - - iwr.u.retry.value = long_retry; - iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; - if (ioctl(drv->ioctl_sock, SIOCSIWRETRY, &iwr) < 0) { - perror("ioctl[SIOCSIWRETRY(long)]"); - return -1; - } - - return 0; -} - - -static int i802_get_retry(void *priv, int *short_retry, int *long_retry) -{ - struct i802_driver_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ); - - iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; - if (ioctl(drv->ioctl_sock, SIOCGIWRETRY, &iwr) < 0) { - perror("ioctl[SIOCGIWFRAG(short)]"); - return -1; - } - *short_retry = iwr.u.retry.value; - - iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; - if (ioctl(drv->ioctl_sock, SIOCGIWRETRY, &iwr) < 0) { - perror("ioctl[SIOCGIWFRAG(long)]"); - return -1; - } - *long_retry = iwr.u.retry.value; - - return 0; -} - - -static int i802_flush(void *priv) -{ - struct i802_driver_data *drv = priv; - struct nl_msg *msg; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_DEL_STATION, 0); - - /* - * XXX: FIX! this needs to flush all VLANs too - */ - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(drv->iface)); - - return send_and_recv_msgs(drv, msg, NULL, NULL); - nla_put_failure: - return -ENOBUFS; -} - - -static int get_sta_handler(struct nl_msg *msg, void *arg) -{ - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct hostap_sta_driver_data *data = arg; - struct nlattr *stats[NL80211_STA_INFO_MAX + 1]; - static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = { - [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 }, - [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 }, - [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 }, - [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 }, - [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 }, - }; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - /* - * TODO: validate the interface and mac address! - * Otherwise, there's a race condition as soon as - * the kernel starts sending station notifications. - */ - - if (!tb[NL80211_ATTR_STA_INFO]) { - wpa_printf(MSG_DEBUG, "sta stats missing!"); - return NL_SKIP; - } - if (nla_parse_nested(stats, NL80211_STA_INFO_MAX, - tb[NL80211_ATTR_STA_INFO], - stats_policy)) { - wpa_printf(MSG_DEBUG, "failed to parse nested attributes!"); - return NL_SKIP; - } - - if (stats[NL80211_STA_INFO_INACTIVE_TIME]) - data->inactive_msec = - nla_get_u32(stats[NL80211_STA_INFO_INACTIVE_TIME]); - if (stats[NL80211_STA_INFO_RX_BYTES]) - data->rx_bytes = nla_get_u32(stats[NL80211_STA_INFO_RX_BYTES]); - if (stats[NL80211_STA_INFO_TX_BYTES]) - data->tx_bytes = nla_get_u32(stats[NL80211_STA_INFO_TX_BYTES]); - if (stats[NL80211_STA_INFO_RX_PACKETS]) - data->rx_packets = - nla_get_u32(stats[NL80211_STA_INFO_RX_PACKETS]); - if (stats[NL80211_STA_INFO_TX_PACKETS]) - data->tx_packets = - nla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]); - - return NL_SKIP; -} - -static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data, - const u8 *addr) -{ - struct i802_driver_data *drv = priv; - struct nl_msg *msg; - - os_memset(data, 0, sizeof(*data)); - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_GET_STATION, 0); - - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); - - return send_and_recv_msgs(drv, msg, get_sta_handler, data); - nla_put_failure: - return -ENOBUFS; -} - - -static int i802_send_eapol(void *priv, const u8 *addr, const u8 *data, - size_t data_len, int encrypt, const u8 *own_addr) -{ - struct i802_driver_data *drv = priv; - struct ieee80211_hdr *hdr; - size_t len; - u8 *pos; - int res; -#if 0 /* FIX */ - int qos = sta->flags & WLAN_STA_WME; -#else - int qos = 0; -#endif - - len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 + - data_len; - hdr = os_zalloc(len); - if (hdr == NULL) { - printf("malloc() failed for i802_send_data(len=%lu)\n", - (unsigned long) len); - return -1; - } - - hdr->frame_control = - IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA); - hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS); - if (encrypt) - hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); -#if 0 /* To be enabled if qos determination is added above */ - if (qos) { - hdr->frame_control |= - host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4); - } -#endif - - memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN); - memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN); - memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN); - pos = (u8 *) (hdr + 1); - -#if 0 /* To be enabled if qos determination is added above */ - if (qos) { - /* add an empty QoS header if needed */ - pos[0] = 0; - pos[1] = 0; - pos += 2; - } -#endif - - memcpy(pos, rfc1042_header, sizeof(rfc1042_header)); - pos += sizeof(rfc1042_header); - WPA_PUT_BE16(pos, ETH_P_PAE); - pos += 2; - memcpy(pos, data, data_len); - - res = i802_send_frame(drv, (u8 *) hdr, len, encrypt, 0); - free(hdr); - - if (res < 0) { - perror("i802_send_eapol: send"); - printf("i802_send_eapol - packet len: %lu - failed\n", - (unsigned long) len); - } - - return res; -} - - -static int i802_sta_add2(const char *ifname, void *priv, - struct hostapd_sta_add_params *params) -{ - struct i802_driver_data *drv = priv; - struct nl_msg *msg; - int ret = -ENOBUFS; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_NEW_STATION, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(drv->iface)); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr); - NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid); - NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, params->supp_rates_len, - params->supp_rates); - NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL, - params->listen_interval); - -#ifdef CONFIG_IEEE80211N - if (params->ht_capabilities) { - NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY, - params->ht_capabilities->length, - ¶ms->ht_capabilities->data); - } -#endif /* CONFIG_IEEE80211N */ - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (ret) - wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_NEW_STATION " - "result: %d (%s)", ret, strerror(-ret)); - if (ret == -EEXIST) - ret = 0; - nla_put_failure: - return ret; -} - - -static int i802_sta_remove(void *priv, const u8 *addr) -{ - struct i802_driver_data *drv = priv; - struct nl_msg *msg; - int ret; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_DEL_STATION, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(drv->iface)); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (ret == -ENOENT) - return 0; - return ret; - nla_put_failure: - return -ENOBUFS; -} - - -static int i802_sta_set_flags(void *priv, const u8 *addr, - int total_flags, int flags_or, int flags_and) -{ - struct i802_driver_data *drv = priv; - struct nl_msg *msg, *flags = NULL; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - flags = nlmsg_alloc(); - if (!flags) { - nlmsg_free(msg); - return -ENOMEM; - } - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_STATION, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(drv->iface)); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - - if (total_flags & WLAN_STA_AUTHORIZED || !drv->ieee802_1x_active) - NLA_PUT_FLAG(flags, NL80211_STA_FLAG_AUTHORIZED); - - if (total_flags & WLAN_STA_WMM) - NLA_PUT_FLAG(flags, NL80211_STA_FLAG_WME); - - if (total_flags & WLAN_STA_SHORT_PREAMBLE) - NLA_PUT_FLAG(flags, NL80211_STA_FLAG_SHORT_PREAMBLE); - - if (total_flags & WLAN_STA_MFP) - NLA_PUT_FLAG(flags, NL80211_STA_FLAG_MFP); - - if (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags)) - goto nla_put_failure; - - nlmsg_free(flags); - - return send_and_recv_msgs(drv, msg, NULL, NULL); - nla_put_failure: - nlmsg_free(flags); - return -ENOBUFS; -} - - -static int i802_set_regulatory_domain(void *priv, unsigned int rd) -{ - return -1; -} - - -static int i802_set_tx_queue_params(void *priv, int queue, int aifs, - int cw_min, int cw_max, int burst_time) -{ - struct i802_driver_data *drv = priv; - struct nl_msg *msg; - struct nlattr *txq, *params; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_WIPHY, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); - - txq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS); - if (!txq) - goto nla_put_failure; - - /* We are only sending parameters for a single TXQ at a time */ - params = nla_nest_start(msg, 1); - if (!params) - goto nla_put_failure; - - NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, queue); - /* Burst time is configured in units of 0.1 msec and TXOP parameter in - * 32 usec, so need to convert the value here. */ - NLA_PUT_U16(msg, NL80211_TXQ_ATTR_TXOP, (burst_time * 100 + 16) / 32); - NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMIN, cw_min); - NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMAX, cw_max); - NLA_PUT_U8(msg, NL80211_TXQ_ATTR_AIFS, aifs); - - nla_nest_end(msg, params); - - nla_nest_end(msg, txq); - - if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) - return 0; - nla_put_failure: - return -1; -} - - -static void nl80211_remove_iface(struct i802_driver_data *drv, int ifidx) -{ - struct nl_msg *msg; - - /* stop listening for EAPOL on this interface */ - del_ifidx(drv, ifidx); - - msg = nlmsg_alloc(); - if (!msg) - goto nla_put_failure; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_DEL_INTERFACE, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx); - - if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) - return; - nla_put_failure: - printf("Failed to remove interface.\n"); -} - - -static int nl80211_create_iface(struct i802_driver_data *drv, - const char *ifname, - enum nl80211_iftype iftype, - const u8 *addr) -{ - struct nl_msg *msg, *flags = NULL; - int ifidx; - struct ifreq ifreq; - struct iwreq iwr; - int ret = -ENOBUFS; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_NEW_INTERFACE, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(drv->hapd->conf->iface)); - NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ifname); - NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype); - - if (iftype == NL80211_IFTYPE_MONITOR) { - int err; - - flags = nlmsg_alloc(); - if (!flags) - goto nla_put_failure; - - NLA_PUT_FLAG(flags, NL80211_MNTR_FLAG_COOK_FRAMES); - - err = nla_put_nested(msg, NL80211_ATTR_MNTR_FLAGS, flags); - - nlmsg_free(flags); - - if (err) - goto nla_put_failure; - } - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (ret) { - nla_put_failure: - printf("Failed to create interface %s.\n", ifname); - return ret; - } - - ifidx = if_nametoindex(ifname); - - if (ifidx <= 0) - return -1; - - /* start listening for EAPOL on this interface */ - add_ifidx(drv, ifidx); - - if (addr) { - switch (iftype) { - case NL80211_IFTYPE_AP: - os_strlcpy(ifreq.ifr_name, ifname, IFNAMSIZ); - memcpy(ifreq.ifr_hwaddr.sa_data, addr, ETH_ALEN); - ifreq.ifr_hwaddr.sa_family = ARPHRD_ETHER; - - if (ioctl(drv->ioctl_sock, SIOCSIFHWADDR, &ifreq)) { - nl80211_remove_iface(drv, ifidx); - return -1; - } - break; - case NL80211_IFTYPE_WDS: - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, ifname, IFNAMSIZ); - iwr.u.addr.sa_family = ARPHRD_ETHER; - memcpy(iwr.u.addr.sa_data, addr, ETH_ALEN); - if (ioctl(drv->ioctl_sock, SIOCSIWAP, &iwr)) - return -1; - break; - default: - /* nothing */ - break; - } - } - - return ifidx; -} - - -static int i802_bss_add(void *priv, const char *ifname, const u8 *bssid) -{ - int ifidx; - - /* - * The kernel supports that when the low-level driver does, - * but we currently don't because we need per-BSS data that - * currently we can't handle easily. - */ - return -1; - - ifidx = nl80211_create_iface(priv, ifname, NL80211_IFTYPE_AP, bssid); - if (ifidx < 0) - return -1; - if (hostapd_set_iface_flags(priv, ifname, 1)) { - nl80211_remove_iface(priv, ifidx); - return -1; - } - return 0; -} - - -static int i802_bss_remove(void *priv, const char *ifname) -{ - nl80211_remove_iface(priv, if_nametoindex(ifname)); - return 0; -} - - -static int i802_set_beacon(const char *iface, void *priv, - u8 *head, size_t head_len, - u8 *tail, size_t tail_len) -{ - struct i802_driver_data *drv = priv; - struct nl_msg *msg; - u8 cmd = NL80211_CMD_NEW_BEACON; - int ret; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - if (drv->beacon_set) - cmd = NL80211_CMD_SET_BEACON; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, cmd, 0); - NLA_PUT(msg, NL80211_ATTR_BEACON_HEAD, head_len, head); - NLA_PUT(msg, NL80211_ATTR_BEACON_TAIL, tail_len, tail); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface)); - NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, drv->beacon_int); - - if (!drv->dtim_period) - drv->dtim_period = 2; - NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, drv->dtim_period); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (!ret) - drv->beacon_set = 1; - return ret; - nla_put_failure: - return -ENOBUFS; -} - - -static int i802_del_beacon(struct i802_driver_data *drv) -{ - struct nl_msg *msg; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_DEL_BEACON, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); - - return send_and_recv_msgs(drv, msg, NULL, NULL); - nla_put_failure: - return -ENOBUFS; -} - - -static int i802_set_ieee8021x(const char *ifname, void *priv, int enabled) -{ - struct i802_driver_data *drv = priv; - - /* - * FIXME: This needs to be per interface (BSS) - */ - drv->ieee802_1x_active = enabled; - return 0; -} - - -static int i802_set_privacy(const char *ifname, void *priv, int enabled) -{ - struct i802_driver_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - - os_strlcpy(iwr.ifr_name, ifname, IFNAMSIZ); - iwr.u.param.flags = IW_AUTH_PRIVACY_INVOKED; - iwr.u.param.value = enabled; - - ioctl(drv->ioctl_sock, SIOCSIWAUTH, &iwr); - - /* ignore errors, the kernel/driver might not care */ - return 0; -} - - -static int i802_set_internal_bridge(void *priv, int value) -{ - return -1; -} - - -static int i802_set_beacon_int(void *priv, int value) -{ - struct i802_driver_data *drv = priv; - struct nl_msg *msg; - - drv->beacon_int = value; - - if (!drv->beacon_set) - return 0; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_BEACON, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); - - NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, value); - - return send_and_recv_msgs(drv, msg, NULL, NULL); - nla_put_failure: - return -ENOBUFS; -} - - -static int i802_set_dtim_period(const char *iface, void *priv, int value) -{ - struct i802_driver_data *drv = priv; - struct nl_msg *msg; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_BEACON, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface)); - - drv->dtim_period = value; - NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, drv->dtim_period); - - return send_and_recv_msgs(drv, msg, NULL, NULL); - nla_put_failure: - return -ENOBUFS; -} - - -static int i802_set_bss(void *priv, int cts, int preamble, int slot) -{ - struct i802_driver_data *drv = priv; - struct nl_msg *msg; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_SET_BSS, 0); - - if (cts >= 0) - NLA_PUT_U8(msg, NL80211_ATTR_BSS_CTS_PROT, cts); - if (preamble >= 0) - NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_PREAMBLE, preamble); - if (slot >= 0) - NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot); - - /* TODO: multi-BSS support */ - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); - - return send_and_recv_msgs(drv, msg, NULL, NULL); - nla_put_failure: - return -ENOBUFS; -} - - -static int i802_set_cts_protect(void *priv, int value) -{ - return i802_set_bss(priv, value, -1, -1); -} - - -static int i802_set_preamble(void *priv, int value) -{ - return i802_set_bss(priv, -1, value, -1); -} - - -static int i802_set_short_slot_time(void *priv, int value) -{ - return i802_set_bss(priv, -1, -1, value); -} - - -static enum nl80211_iftype i802_if_type(enum hostapd_driver_if_type type) -{ - switch (type) { - case HOSTAPD_IF_VLAN: - return NL80211_IFTYPE_AP_VLAN; - case HOSTAPD_IF_WDS: - return NL80211_IFTYPE_WDS; - } - return -1; -} - - -static int i802_if_add(const char *iface, void *priv, - enum hostapd_driver_if_type type, char *ifname, - const u8 *addr) -{ - if (nl80211_create_iface(priv, ifname, i802_if_type(type), addr) < 0) - return -1; - return 0; -} - - -static int i802_if_update(void *priv, enum hostapd_driver_if_type type, - char *ifname, const u8 *addr) -{ - /* unused at the moment */ - return -1; -} - - -static int i802_if_remove(void *priv, enum hostapd_driver_if_type type, - const char *ifname, const u8 *addr) -{ - nl80211_remove_iface(priv, if_nametoindex(ifname)); - return 0; -} - - -struct phy_info_arg { - u16 *num_modes; - struct hostapd_hw_modes *modes; -}; - -static int phy_info_handler(struct nl_msg *msg, void *arg) -{ - struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct phy_info_arg *phy_info = arg; - - struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1]; - - struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1]; - static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = { - [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 }, - [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG }, - [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG }, - [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG }, - [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG }, - [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 }, - }; - - struct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1]; - static struct nla_policy rate_policy[NL80211_BITRATE_ATTR_MAX + 1] = { - [NL80211_BITRATE_ATTR_RATE] = { .type = NLA_U32 }, - [NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE] = { .type = NLA_FLAG }, - }; - - struct nlattr *nl_band; - struct nlattr *nl_freq; - struct nlattr *nl_rate; - int rem_band, rem_freq, rem_rate; - struct hostapd_hw_modes *mode; - int idx, mode_is_set; - - nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - if (!tb_msg[NL80211_ATTR_WIPHY_BANDS]) - return NL_SKIP; - - nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band) { - mode = realloc(phy_info->modes, (*phy_info->num_modes + 1) * sizeof(*mode)); - if (!mode) - return NL_SKIP; - phy_info->modes = mode; - - mode_is_set = 0; - - mode = &phy_info->modes[*(phy_info->num_modes)]; - memset(mode, 0, sizeof(*mode)); - *(phy_info->num_modes) += 1; - - nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band), - nla_len(nl_band), NULL); - - if (tb_band[NL80211_BAND_ATTR_HT_CAPA]) { - mode->ht_capab = nla_get_u16( - tb_band[NL80211_BAND_ATTR_HT_CAPA]); - } - - nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) { - nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq), - nla_len(nl_freq), freq_policy); - if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) - continue; - mode->num_channels++; - } - - mode->channels = calloc(mode->num_channels, sizeof(struct hostapd_channel_data)); - if (!mode->channels) - return NL_SKIP; - - idx = 0; - - nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) { - nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq), - nla_len(nl_freq), freq_policy); - if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) - continue; - - mode->channels[idx].freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); - mode->channels[idx].flag = 0; - - if (!mode_is_set) { - /* crude heuristic */ - if (mode->channels[idx].freq < 4000) - mode->mode = HOSTAPD_MODE_IEEE80211B; - else - mode->mode = HOSTAPD_MODE_IEEE80211A; - mode_is_set = 1; - } - - /* crude heuristic */ - if (mode->channels[idx].freq < 4000) - if (mode->channels[idx].freq == 2484) - mode->channels[idx].chan = 14; - else - mode->channels[idx].chan = (mode->channels[idx].freq - 2407) / 5; - else - mode->channels[idx].chan = mode->channels[idx].freq/5 - 1000; - - if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) - mode->channels[idx].flag |= - HOSTAPD_CHAN_DISABLED; - if (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN]) - mode->channels[idx].flag |= - HOSTAPD_CHAN_PASSIVE_SCAN; - if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IBSS]) - mode->channels[idx].flag |= - HOSTAPD_CHAN_NO_IBSS; - if (tb_freq[NL80211_FREQUENCY_ATTR_RADAR]) - mode->channels[idx].flag |= - HOSTAPD_CHAN_RADAR; - - if (tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] && - !tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) - mode->channels[idx].max_tx_power = - nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]) / 100; - - idx++; - } - - nla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) { - nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate), - nla_len(nl_rate), rate_policy); - if (!tb_rate[NL80211_BITRATE_ATTR_RATE]) - continue; - mode->num_rates++; - } - - mode->rates = calloc(mode->num_rates, sizeof(struct hostapd_rate_data)); - if (!mode->rates) - return NL_SKIP; - - idx = 0; - - nla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) { - nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate), - nla_len(nl_rate), rate_policy); - if (!tb_rate[NL80211_BITRATE_ATTR_RATE]) - continue; - mode->rates[idx].rate = nla_get_u32(tb_rate[NL80211_BITRATE_ATTR_RATE]); - - /* crude heuristic */ - if (mode->mode == HOSTAPD_MODE_IEEE80211B && - mode->rates[idx].rate > 200) - mode->mode = HOSTAPD_MODE_IEEE80211G; - - if (tb_rate[NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE]) - mode->rates[idx].flags |= HOSTAPD_RATE_PREAMBLE2; - - idx++; - } - } - - return NL_SKIP; -} - -static struct hostapd_hw_modes *i802_add_11b(struct hostapd_hw_modes *modes, - u16 *num_modes) -{ - u16 m; - struct hostapd_hw_modes *mode11g = NULL, *nmodes, *mode; - int i, mode11g_idx = -1; - - /* If only 802.11g mode is included, use it to construct matching - * 802.11b mode data. */ - - for (m = 0; m < *num_modes; m++) { - if (modes[m].mode == HOSTAPD_MODE_IEEE80211B) - return modes; /* 802.11b already included */ - if (modes[m].mode == HOSTAPD_MODE_IEEE80211G) - mode11g_idx = m; - } - - if (mode11g_idx < 0) - return modes; /* 2.4 GHz band not supported at all */ - - nmodes = os_realloc(modes, (*num_modes + 1) * sizeof(*nmodes)); - if (nmodes == NULL) - return modes; /* Could not add 802.11b mode */ - - mode = &nmodes[*num_modes]; - os_memset(mode, 0, sizeof(*mode)); - (*num_modes)++; - modes = nmodes; - - mode->mode = HOSTAPD_MODE_IEEE80211B; - - mode11g = &modes[mode11g_idx]; - mode->num_channels = mode11g->num_channels; - mode->channels = os_malloc(mode11g->num_channels * - sizeof(struct hostapd_channel_data)); - if (mode->channels == NULL) { - (*num_modes)--; - return modes; /* Could not add 802.11b mode */ - } - os_memcpy(mode->channels, mode11g->channels, - mode11g->num_channels * sizeof(struct hostapd_channel_data)); - - mode->num_rates = 0; - mode->rates = os_malloc(4 * sizeof(struct hostapd_rate_data)); - if (mode->rates == NULL) { - os_free(mode->channels); - (*num_modes)--; - return modes; /* Could not add 802.11b mode */ - } - - for (i = 0; i < mode11g->num_rates; i++) { - if (mode11g->rates[i].rate > 110 || - mode11g->rates[i].flags & - (HOSTAPD_RATE_ERP | HOSTAPD_RATE_OFDM)) - continue; - mode->rates[mode->num_rates] = mode11g->rates[i]; - mode->num_rates++; - if (mode->num_rates == 4) - break; - } - - if (mode->num_rates == 0) { - os_free(mode->channels); - os_free(mode->rates); - (*num_modes)--; - return modes; /* No 802.11b rates */ - } - - wpa_printf(MSG_DEBUG, "nl80211: Added 802.11b mode based on 802.11g " - "information"); - - return modes; -} - -static struct hostapd_hw_modes *i802_get_hw_feature_data(void *priv, - u16 *num_modes, - u16 *flags) -{ - struct i802_driver_data *drv = priv; - struct nl_msg *msg; - struct phy_info_arg result = { - .num_modes = num_modes, - .modes = NULL, - }; - - *num_modes = 0; - *flags = 0; - - msg = nlmsg_alloc(); - if (!msg) - return NULL; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_GET_WIPHY, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface)); - - if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) - return i802_add_11b(result.modes, num_modes); - nla_put_failure: - return NULL; -} - - -static int i802_set_sta_vlan(void *priv, const u8 *addr, - const char *ifname, int vlan_id) -{ - struct i802_driver_data *drv = priv; - struct nl_msg *msg; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_STATION, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(drv->iface)); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(ifname)); - - return send_and_recv_msgs(drv, msg, NULL, NULL); - nla_put_failure: - return -ENOBUFS; -} - - -static int i802_set_country(void *priv, const char *country) -{ - struct i802_driver_data *drv = priv; - struct nl_msg *msg; - char alpha2[3]; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_REQ_SET_REG, 0); - - alpha2[0] = country[0]; - alpha2[1] = country[1]; - alpha2[2] = '\0'; - NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2); - - return send_and_recv_msgs(drv, msg, NULL, NULL); - nla_put_failure: - return -ENOBUFS; -} - - -static void handle_unknown_sta(struct hostapd_data *hapd, u8 *ta) -{ - struct sta_info *sta; - - sta = ap_get_sta(hapd, ta); - if (!sta || !(sta->flags & WLAN_STA_ASSOC)) { - printf("Data/PS-poll frame from not associated STA " - MACSTR "\n", MAC2STR(ta)); - if (sta && (sta->flags & WLAN_STA_AUTH)) - hostapd_sta_disassoc( - hapd, ta, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - else - hostapd_sta_deauth( - hapd, ta, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - } -} - - -static void handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len, - int ok) -{ - struct ieee80211_hdr *hdr; - u16 fc, type, stype; - struct sta_info *sta; - - hdr = (struct ieee80211_hdr *) buf; - fc = le_to_host16(hdr->frame_control); - - type = WLAN_FC_GET_TYPE(fc); - stype = WLAN_FC_GET_STYPE(fc); - - switch (type) { - case WLAN_FC_TYPE_MGMT: - wpa_printf(MSG_DEBUG, "MGMT (TX callback) %s", - ok ? "ACK" : "fail"); - ieee802_11_mgmt_cb(hapd, buf, len, stype, ok); - break; - case WLAN_FC_TYPE_CTRL: - wpa_printf(MSG_DEBUG, "CTRL (TX callback) %s", - ok ? "ACK" : "fail"); - break; - case WLAN_FC_TYPE_DATA: - sta = ap_get_sta(hapd, hdr->addr1); - if (sta && sta->flags & WLAN_STA_PENDING_POLL) { - wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending " - "activity poll", MAC2STR(sta->addr), - ok ? "ACKed" : "did not ACK"); - if (ok) - sta->flags &= ~WLAN_STA_PENDING_POLL; - } - if (sta) - ieee802_1x_tx_status(hapd, sta, buf, len, ok); - break; - default: - printf("unknown TX callback frame type %d\n", type); - break; - } -} - - -static void handle_frame(struct hostapd_iface *iface, u8 *buf, size_t len, - struct hostapd_frame_info *hfi, - enum ieee80211_msg_type msg_type) -{ - struct ieee80211_hdr *hdr; - u16 fc, type, stype; - size_t data_len = len; - struct hostapd_data *hapd = NULL; - int broadcast_bssid = 0; - size_t i; - u8 *bssid; - - /* - * PS-Poll frames are 16 bytes. All other frames are - * 24 bytes or longer. - */ - if (len < 16) - return; - - hdr = (struct ieee80211_hdr *) buf; - fc = le_to_host16(hdr->frame_control); - - type = WLAN_FC_GET_TYPE(fc); - stype = WLAN_FC_GET_STYPE(fc); - - switch (type) { - case WLAN_FC_TYPE_DATA: - if (len < 24) - return; - switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) { - case WLAN_FC_TODS: - bssid = hdr->addr1; - break; - case WLAN_FC_FROMDS: - bssid = hdr->addr2; - break; - default: - /* discard */ - return; - } - break; - case WLAN_FC_TYPE_CTRL: - /* discard non-ps-poll frames */ - if (stype != WLAN_FC_STYPE_PSPOLL) - return; - bssid = hdr->addr1; - break; - case WLAN_FC_TYPE_MGMT: - bssid = hdr->addr3; - break; - default: - /* discard */ - return; - } - - /* find interface frame belongs to */ - for (i = 0; i < iface->num_bss; i++) { - if (memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0) { - hapd = iface->bss[i]; - break; - } - } - - if (hapd == NULL) { - hapd = iface->bss[0]; - - if (bssid[0] != 0xff || bssid[1] != 0xff || - bssid[2] != 0xff || bssid[3] != 0xff || - bssid[4] != 0xff || bssid[5] != 0xff) { - /* - * Unknown BSSID - drop frame if this is not from - * passive scanning or a beacon (at least ProbeReq - * frames to other APs may be allowed through RX - * filtering in the wlan hw/driver) - */ - if ((type != WLAN_FC_TYPE_MGMT || - stype != WLAN_FC_STYPE_BEACON)) - return; - } else - broadcast_bssid = 1; - } - - switch (msg_type) { - case ieee80211_msg_normal: - /* continue processing */ - break; - case ieee80211_msg_tx_callback_ack: - handle_tx_callback(hapd, buf, data_len, 1); - return; - case ieee80211_msg_tx_callback_fail: - handle_tx_callback(hapd, buf, data_len, 0); - return; - } - - switch (type) { - case WLAN_FC_TYPE_MGMT: - if (stype != WLAN_FC_STYPE_BEACON && - stype != WLAN_FC_STYPE_PROBE_REQ) - wpa_printf(MSG_MSGDUMP, "MGMT"); - if (broadcast_bssid) { - for (i = 0; i < iface->num_bss; i++) - ieee802_11_mgmt(iface->bss[i], buf, data_len, - stype, hfi); - } else - ieee802_11_mgmt(hapd, buf, data_len, stype, hfi); - break; - case WLAN_FC_TYPE_CTRL: - /* can only get here with PS-Poll frames */ - wpa_printf(MSG_DEBUG, "CTRL"); - handle_unknown_sta(hapd, hdr->addr2); - break; - case WLAN_FC_TYPE_DATA: - handle_unknown_sta(hapd, hdr->addr2); - break; - } -} - - -static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct i802_driver_data *drv = eloop_ctx; - struct hostapd_data *hapd = drv->hapd; - struct sockaddr_ll lladdr; - unsigned char buf[3000]; - int len; - socklen_t fromlen = sizeof(lladdr); - - len = recvfrom(sock, buf, sizeof(buf), 0, - (struct sockaddr *)&lladdr, &fromlen); - if (len < 0) { - perror("recv"); - return; - } - - if (have_ifidx(drv, lladdr.sll_ifindex)) - ieee802_1x_receive(hapd, lladdr.sll_addr, buf, len); -} - - -static void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct i802_driver_data *drv = eloop_ctx; - int len; - unsigned char buf[3000]; - struct hostapd_data *hapd = drv->hapd; - struct ieee80211_radiotap_iterator iter; - int ret; - struct hostapd_frame_info hfi; - int injected = 0, failed = 0, msg_type, rxflags = 0; - - len = recv(sock, buf, sizeof(buf), 0); - if (len < 0) { - perror("recv"); - return; - } - - if (ieee80211_radiotap_iterator_init(&iter, (void*)buf, len)) { - printf("received invalid radiotap frame\n"); - return; - } - - memset(&hfi, 0, sizeof(hfi)); - - while (1) { - ret = ieee80211_radiotap_iterator_next(&iter); - if (ret == -ENOENT) - break; - if (ret) { - printf("received invalid radiotap frame (%d)\n", ret); - return; - } - switch (iter.this_arg_index) { - case IEEE80211_RADIOTAP_FLAGS: - if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS) - len -= 4; - break; - case IEEE80211_RADIOTAP_RX_FLAGS: - rxflags = 1; - break; - case IEEE80211_RADIOTAP_TX_FLAGS: - injected = 1; - failed = le_to_host16((*(uint16_t *) iter.this_arg)) & - IEEE80211_RADIOTAP_F_TX_FAIL; - break; - case IEEE80211_RADIOTAP_DATA_RETRIES: - break; - case IEEE80211_RADIOTAP_CHANNEL: - /* TODO convert from freq/flags to channel number - hfi.channel = XXX; - hfi.phytype = XXX; - */ - break; - case IEEE80211_RADIOTAP_RATE: - hfi.datarate = *iter.this_arg * 5; - break; - case IEEE80211_RADIOTAP_DB_ANTSIGNAL: - hfi.ssi_signal = *iter.this_arg; - break; - } - } - - if (rxflags && injected) - return; - - if (!injected) - msg_type = ieee80211_msg_normal; - else if (failed) - msg_type = ieee80211_msg_tx_callback_fail; - else - msg_type = ieee80211_msg_tx_callback_ack; - - handle_frame(hapd->iface, buf + iter.max_length, - len - iter.max_length, &hfi, msg_type); -} - - -/* - * we post-process the filter code later and rewrite - * this to the offset to the last instruction - */ -#define PASS 0xFF -#define FAIL 0xFE - -static struct sock_filter msock_filter_insns[] = { - /* - * do a little-endian load of the radiotap length field - */ - /* load lower byte into A */ - BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 2), - /* put it into X (== index register) */ - BPF_STMT(BPF_MISC| BPF_TAX, 0), - /* load upper byte into A */ - BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 3), - /* left-shift it by 8 */ - BPF_STMT(BPF_ALU | BPF_LSH | BPF_K, 8), - /* or with X */ - BPF_STMT(BPF_ALU | BPF_OR | BPF_X, 0), - /* put result into X */ - BPF_STMT(BPF_MISC| BPF_TAX, 0), - - /* - * Allow management frames through, this also gives us those - * management frames that we sent ourselves with status - */ - /* load the lower byte of the IEEE 802.11 frame control field */ - BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0), - /* mask off frame type and version */ - BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0xF), - /* accept frame if it's both 0, fall through otherwise */ - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, PASS, 0), - - /* - * TODO: add a bit to radiotap RX flags that indicates - * that the sending station is not associated, then - * add a filter here that filters on our DA and that flag - * to allow us to deauth frames to that bad station. - * - * Not a regression -- we didn't do it before either. - */ - -#if 0 - /* - * drop non-data frames, WDS frames - */ - /* load the lower byte of the frame control field */ - BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0), - /* mask off QoS bit */ - BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0c), - /* drop non-data frames */ - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 8, 0, FAIL), - /* load the upper byte of the frame control field */ - BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0), - /* mask off toDS/fromDS */ - BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x03), - /* drop WDS frames */ - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 3, FAIL, 0), -#endif - - /* - * add header length to index - */ - /* load the lower byte of the frame control field */ - BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0), - /* mask off QoS bit */ - BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x80), - /* right shift it by 6 to give 0 or 2 */ - BPF_STMT(BPF_ALU | BPF_RSH | BPF_K, 6), - /* add data frame header length */ - BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 24), - /* add index, was start of 802.11 header */ - BPF_STMT(BPF_ALU | BPF_ADD | BPF_X, 0), - /* move to index, now start of LL header */ - BPF_STMT(BPF_MISC | BPF_TAX, 0), - - /* - * Accept empty data frames, we use those for - * polling activity. - */ - BPF_STMT(BPF_LD | BPF_W | BPF_LEN, 0), - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_X, 0, PASS, 0), - - /* - * Accept EAPOL frames - */ - BPF_STMT(BPF_LD | BPF_W | BPF_IND, 0), - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0xAAAA0300, 0, FAIL), - BPF_STMT(BPF_LD | BPF_W | BPF_IND, 4), - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0000888E, PASS, FAIL), - - /* keep these last two statements or change the code below */ - /* return 0 == "DROP" */ - BPF_STMT(BPF_RET | BPF_K, 0), - /* return ~0 == "keep all" */ - BPF_STMT(BPF_RET | BPF_K, ~0), -}; - -static struct sock_fprog msock_filter = { - .len = sizeof(msock_filter_insns)/sizeof(msock_filter_insns[0]), - .filter = msock_filter_insns, -}; - - -static int add_monitor_filter(int s) -{ - int idx; - - /* rewrite all PASS/FAIL jump offsets */ - for (idx = 0; idx < msock_filter.len; idx++) { - struct sock_filter *insn = &msock_filter_insns[idx]; - - if (BPF_CLASS(insn->code) == BPF_JMP) { - if (insn->code == (BPF_JMP|BPF_JA)) { - if (insn->k == PASS) - insn->k = msock_filter.len - idx - 2; - else if (insn->k == FAIL) - insn->k = msock_filter.len - idx - 3; - } - - if (insn->jt == PASS) - insn->jt = msock_filter.len - idx - 2; - else if (insn->jt == FAIL) - insn->jt = msock_filter.len - idx - 3; - - if (insn->jf == PASS) - insn->jf = msock_filter.len - idx - 2; - else if (insn->jf == FAIL) - insn->jf = msock_filter.len - idx - 3; - } - } - - if (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, - &msock_filter, sizeof(msock_filter))) { - perror("SO_ATTACH_FILTER"); - return -1; - } - - return 0; -} - - -static int nl80211_create_monitor_interface(struct i802_driver_data *drv) -{ - char buf[IFNAMSIZ]; - struct sockaddr_ll ll; - int optval; - socklen_t optlen; - - snprintf(buf, IFNAMSIZ, "mon.%s", drv->iface); - buf[IFNAMSIZ - 1] = '\0'; - - drv->monitor_ifidx = - nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL); - - if (drv->monitor_ifidx < 0) - return -1; - - if (hostapd_set_iface_flags(drv, buf, 1)) - goto error; - - memset(&ll, 0, sizeof(ll)); - ll.sll_family = AF_PACKET; - ll.sll_ifindex = drv->monitor_ifidx; - drv->monitor_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (drv->monitor_sock < 0) { - perror("socket[PF_PACKET,SOCK_RAW]"); - goto error; - } - - if (add_monitor_filter(drv->monitor_sock)) { - wpa_printf(MSG_INFO, "Failed to set socket filter for monitor " - "interface; do filtering in user space"); - /* This works, but will cost in performance. */ - } - - if (bind(drv->monitor_sock, (struct sockaddr *) &ll, - sizeof(ll)) < 0) { - perror("monitor socket bind"); - goto error; - } - - optlen = sizeof(optval); - optval = 20; - if (setsockopt - (drv->monitor_sock, SOL_SOCKET, SO_PRIORITY, &optval, optlen)) { - perror("Failed to set socket priority"); - goto error; - } - - if (eloop_register_read_sock(drv->monitor_sock, handle_monitor_read, - drv, NULL)) { - printf("Could not register monitor read socket\n"); - goto error; - } - - return 0; - error: - nl80211_remove_iface(drv, drv->monitor_ifidx); - return -1; -} - - -static int nl80211_set_master_mode(struct i802_driver_data *drv, - const char *ifname) -{ - struct nl_msg *msg; - int ret = -ENOBUFS; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_INTERFACE, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(ifname)); - NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_AP); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (!ret) - return 0; - nla_put_failure: - wpa_printf(MSG_ERROR, "Failed to set interface %s to master " - "mode.", ifname); - return ret; -} - - -static int i802_init_sockets(struct i802_driver_data *drv, const u8 *bssid) -{ - struct ifreq ifr; - struct sockaddr_ll addr; - - drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->ioctl_sock < 0) { - perror("socket[PF_INET,SOCK_DGRAM]"); - return -1; - } - - /* start listening for EAPOL on the default AP interface */ - add_ifidx(drv, if_nametoindex(drv->iface)); - - if (hostapd_set_iface_flags(drv, drv->iface, 0)) - return -1; - - if (bssid) { - os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ); - memcpy(ifr.ifr_hwaddr.sa_data, bssid, ETH_ALEN); - ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; - - if (ioctl(drv->ioctl_sock, SIOCSIFHWADDR, &ifr)) { - perror("ioctl(SIOCSIFHWADDR)"); - return -1; - } - } - - /* - * initialise generic netlink and nl80211 - */ - drv->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); - if (!drv->nl_cb) { - printf("Failed to allocate netlink callbacks.\n"); - return -1; - } - - drv->nl_handle = nl_handle_alloc_cb(drv->nl_cb); - if (!drv->nl_handle) { - printf("Failed to allocate netlink handle.\n"); - return -1; - } - - if (genl_connect(drv->nl_handle)) { - printf("Failed to connect to generic netlink.\n"); - return -1; - } - -#ifdef CONFIG_LIBNL20 - if (genl_ctrl_alloc_cache(drv->nl_handle, &drv->nl_cache) < 0) { - printf("Failed to allocate generic netlink cache.\n"); - return -1; - } -#else /* CONFIG_LIBNL20 */ - drv->nl_cache = genl_ctrl_alloc_cache(drv->nl_handle); - if (!drv->nl_cache) { - printf("Failed to allocate generic netlink cache.\n"); - return -1; - } -#endif /* CONFIG_LIBNL20 */ - - drv->nl80211 = genl_ctrl_search_by_name(drv->nl_cache, "nl80211"); - if (!drv->nl80211) { - printf("nl80211 not found.\n"); - return -1; - } - - /* Initialise a monitor interface */ - if (nl80211_create_monitor_interface(drv)) - return -1; - - if (nl80211_set_master_mode(drv, drv->iface)) - goto fail1; - - if (hostapd_set_iface_flags(drv, drv->iface, 1)) - goto fail1; - - memset(&addr, 0, sizeof(addr)); - addr.sll_family = AF_PACKET; - addr.sll_ifindex = ifr.ifr_ifindex; - wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d", - addr.sll_ifindex); - - drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE)); - if (drv->eapol_sock < 0) { - perror("socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE)"); - goto fail1; - } - - if (eloop_register_read_sock(drv->eapol_sock, handle_eapol, drv, NULL)) - { - printf("Could not register read socket for eapol\n"); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name)); - if (ioctl(drv->ioctl_sock, SIOCGIFHWADDR, &ifr) != 0) { - perror("ioctl(SIOCGIFHWADDR)"); - goto fail1; - } - - if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { - printf("Invalid HW-addr family 0x%04x\n", - ifr.ifr_hwaddr.sa_family); - goto fail1; - } - memcpy(drv->hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); - - return 0; - -fail1: - nl80211_remove_iface(drv, drv->monitor_ifidx); - return -1; -} - - -static int i802_get_inact_sec(void *priv, const u8 *addr) -{ - struct hostap_sta_driver_data data; - int ret; - - data.inactive_msec = (unsigned long) -1; - ret = i802_read_sta_data(priv, &data, addr); - if (ret || data.inactive_msec == (unsigned long) -1) - return -1; - return data.inactive_msec / 1000; -} - - -static int i802_sta_clear_stats(void *priv, const u8 *addr) -{ -#if 0 - /* TODO */ -#endif - return 0; -} - - -static void -hostapd_wireless_event_wireless_custom(struct i802_driver_data *drv, - char *custom) -{ - wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom); - - if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) { - char *pos; - u8 addr[ETH_ALEN]; - pos = strstr(custom, "addr="); - if (pos == NULL) { - wpa_printf(MSG_DEBUG, - "MLME-MICHAELMICFAILURE.indication " - "without sender address ignored"); - return; - } - pos += 5; - if (hwaddr_aton(pos, addr) == 0) { - ieee80211_michael_mic_failure(drv->hapd, addr, 1); - } else { - wpa_printf(MSG_DEBUG, - "MLME-MICHAELMICFAILURE.indication " - "with invalid MAC address"); - } - } -} - - -static void hostapd_wireless_event_wireless(struct i802_driver_data *drv, - char *data, int len) -{ - struct iw_event iwe_buf, *iwe = &iwe_buf; - char *pos, *end, *custom, *buf; - - pos = data; - end = data + len; - - while (pos + IW_EV_LCP_LEN <= end) { - /* Event data may be unaligned, so make a local, aligned copy - * before processing. */ - memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); - wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d", - iwe->cmd, iwe->len); - if (iwe->len <= IW_EV_LCP_LEN) - return; - - custom = pos + IW_EV_POINT_LEN; - if (drv->we_version > 18 && - (iwe->cmd == IWEVMICHAELMICFAILURE || - iwe->cmd == IWEVCUSTOM)) { - /* WE-19 removed the pointer from struct iw_point */ - char *dpos = (char *) &iwe_buf.u.data.length; - int dlen = dpos - (char *) &iwe_buf; - memcpy(dpos, pos + IW_EV_LCP_LEN, - sizeof(struct iw_event) - dlen); - } else { - memcpy(&iwe_buf, pos, sizeof(struct iw_event)); - custom += IW_EV_POINT_OFF; - } - - switch (iwe->cmd) { - case IWEVCUSTOM: - if (custom + iwe->u.data.length > end) - return; - buf = malloc(iwe->u.data.length + 1); - if (buf == NULL) - return; - memcpy(buf, custom, iwe->u.data.length); - buf[iwe->u.data.length] = '\0'; - hostapd_wireless_event_wireless_custom(drv, buf); - free(buf); - break; - } - - pos += iwe->len; - } -} - - -static void hostapd_wireless_event_rtm_newlink(struct i802_driver_data *drv, - struct nlmsghdr *h, int len) -{ - struct ifinfomsg *ifi; - int attrlen, _nlmsg_len, rta_len; - struct rtattr *attr; - - if (len < (int) sizeof(*ifi)) - return; - - ifi = NLMSG_DATA(h); - - /* TODO: use ifi->ifi_index to filter out wireless events from other - * interfaces */ - - _nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); - - attrlen = h->nlmsg_len - _nlmsg_len; - if (attrlen < 0) - return; - - attr = (struct rtattr *) (((char *) ifi) + _nlmsg_len); - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_WIRELESS) { - hostapd_wireless_event_wireless( - drv, ((char *) attr) + rta_len, - attr->rta_len - rta_len); - } - attr = RTA_NEXT(attr, attrlen); - } -} - - -static void hostapd_wireless_event_receive(int sock, void *eloop_ctx, - void *sock_ctx) -{ - char buf[256]; - int left; - struct sockaddr_nl from; - socklen_t fromlen; - struct nlmsghdr *h; - struct i802_driver_data *drv = eloop_ctx; - - fromlen = sizeof(from); - left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, - (struct sockaddr *) &from, &fromlen); - if (left < 0) { - if (errno != EINTR && errno != EAGAIN) - perror("recvfrom(netlink)"); - return; - } - - h = (struct nlmsghdr *) buf; - while (left >= (int) sizeof(*h)) { - int len, plen; - - len = h->nlmsg_len; - plen = len - sizeof(*h); - if (len > left || plen < 0) { - printf("Malformed netlink message: " - "len=%d left=%d plen=%d\n", - len, left, plen); - break; - } - - switch (h->nlmsg_type) { - case RTM_NEWLINK: - hostapd_wireless_event_rtm_newlink(drv, h, plen); - break; - } - - len = NLMSG_ALIGN(len); - left -= len; - h = (struct nlmsghdr *) ((char *) h + len); - } - - if (left > 0) { - printf("%d extra bytes in the end of netlink message\n", left); - } -} - - -static int hostap_get_we_version(struct i802_driver_data *drv) -{ - struct iw_range *range; - struct iwreq iwr; - int minlen; - size_t buflen; - - drv->we_version = 0; - - /* - * Use larger buffer than struct iw_range in order to allow the - * structure to grow in the future. - */ - buflen = sizeof(struct iw_range) + 500; - range = os_zalloc(buflen); - if (range == NULL) - return -1; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) range; - iwr.u.data.length = buflen; - - minlen = ((char *) &range->enc_capa) - (char *) range + - sizeof(range->enc_capa); - - if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) { - perror("ioctl[SIOCGIWRANGE]"); - free(range); - return -1; - } else if (iwr.u.data.length >= minlen && - range->we_version_compiled >= 18) { - wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d " - "WE(source)=%d enc_capa=0x%x", - range->we_version_compiled, - range->we_version_source, - range->enc_capa); - drv->we_version = range->we_version_compiled; - } - - free(range); - return 0; -} - - -static int i802_wireless_event_init(void *priv) -{ - struct i802_driver_data *drv = priv; - int s; - struct sockaddr_nl local; - - hostap_get_we_version(drv); - - drv->wext_sock = -1; - - s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (s < 0) { - perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)"); - return -1; - } - - memset(&local, 0, sizeof(local)); - local.nl_family = AF_NETLINK; - local.nl_groups = RTMGRP_LINK; - if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) { - perror("bind(netlink)"); - close(s); - return -1; - } - - eloop_register_read_sock(s, hostapd_wireless_event_receive, drv, - NULL); - drv->wext_sock = s; - - return 0; -} - - -static void i802_wireless_event_deinit(void *priv) -{ - struct i802_driver_data *drv = priv; - if (drv->wext_sock < 0) - return; - eloop_unregister_read_sock(drv->wext_sock); - close(drv->wext_sock); -} - - -static int i802_sta_deauth(void *priv, const u8 *addr, int reason) -{ - struct i802_driver_data *drv = priv; - struct ieee80211_mgmt mgmt; - - memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DEAUTH); - memcpy(mgmt.da, addr, ETH_ALEN); - memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN); - memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN); - mgmt.u.deauth.reason_code = host_to_le16(reason); - return i802_send_mgmt_frame(drv, &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.deauth), 0); -} - - -static int i802_sta_disassoc(void *priv, const u8 *addr, int reason) -{ - struct i802_driver_data *drv = priv; - struct ieee80211_mgmt mgmt; - - memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DISASSOC); - memcpy(mgmt.da, addr, ETH_ALEN); - memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN); - memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN); - mgmt.u.disassoc.reason_code = host_to_le16(reason); - return i802_send_mgmt_frame(drv, &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.disassoc), 0); -} - - -static void *i802_init_bssid(struct hostapd_data *hapd, const u8 *bssid) -{ - struct i802_driver_data *drv; - - drv = os_zalloc(sizeof(struct i802_driver_data)); - if (drv == NULL) { - printf("Could not allocate memory for i802 driver data\n"); - return NULL; - } - - drv->hapd = hapd; - memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface)); - - drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int); - drv->if_indices = drv->default_if_indices; - drv->bridge = if_nametoindex(hapd->conf->bridge); - - if (i802_init_sockets(drv, bssid)) - goto failed; - - return drv; - -failed: - free(drv); - return NULL; -} - - -static void *i802_init(struct hostapd_data *hapd) -{ - return i802_init_bssid(hapd, NULL); -} - - -static void i802_deinit(void *priv) -{ - struct i802_driver_data *drv = priv; - - if (drv->last_freq_ht) { - /* Clear HT flags from the driver */ - struct hostapd_freq_params freq; - os_memset(&freq, 0, sizeof(freq)); - freq.freq = drv->last_freq; - i802_set_freq2(priv, &freq); - } - - i802_del_beacon(drv); - - /* remove monitor interface */ - nl80211_remove_iface(drv, drv->monitor_ifidx); - - (void) hostapd_set_iface_flags(drv, drv->iface, 0); - - if (drv->monitor_sock >= 0) { - eloop_unregister_read_sock(drv->monitor_sock); - close(drv->monitor_sock); - } - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - if (drv->eapol_sock >= 0) { - eloop_unregister_read_sock(drv->eapol_sock); - close(drv->eapol_sock); - } - - genl_family_put(drv->nl80211); - nl_cache_free(drv->nl_cache); - nl_handle_destroy(drv->nl_handle); - nl_cb_put(drv->nl_cb); - - if (drv->if_indices != drv->default_if_indices) - free(drv->if_indices); - - free(drv); -} - - -const struct wpa_driver_ops wpa_driver_nl80211_ops = { - .name = "nl80211", - .init = i802_init, - .init_bssid = i802_init_bssid, - .deinit = i802_deinit, - .wireless_event_init = i802_wireless_event_init, - .wireless_event_deinit = i802_wireless_event_deinit, - .set_ieee8021x = i802_set_ieee8021x, - .set_privacy = i802_set_privacy, - .set_encryption = i802_set_encryption, - .get_seqnum = i802_get_seqnum, - .flush = i802_flush, - .read_sta_data = i802_read_sta_data, - .send_eapol = i802_send_eapol, - .sta_set_flags = i802_sta_set_flags, - .sta_deauth = i802_sta_deauth, - .sta_disassoc = i802_sta_disassoc, - .sta_remove = i802_sta_remove, - .send_mgmt_frame = i802_send_mgmt_frame, - .sta_add2 = i802_sta_add2, - .get_inact_sec = i802_get_inact_sec, - .sta_clear_stats = i802_sta_clear_stats, - .set_freq2 = i802_set_freq2, - .set_rts = i802_set_rts, - .get_rts = i802_get_rts, - .set_frag = i802_set_frag, - .get_frag = i802_get_frag, - .set_retry = i802_set_retry, - .get_retry = i802_get_retry, - .set_rate_sets = i802_set_rate_sets, - .set_regulatory_domain = i802_set_regulatory_domain, - .set_beacon = i802_set_beacon, - .set_internal_bridge = i802_set_internal_bridge, - .set_beacon_int = i802_set_beacon_int, - .set_dtim_period = i802_set_dtim_period, - .set_cts_protect = i802_set_cts_protect, - .set_preamble = i802_set_preamble, - .set_short_slot_time = i802_set_short_slot_time, - .set_tx_queue_params = i802_set_tx_queue_params, - .bss_add = i802_bss_add, - .bss_remove = i802_bss_remove, - .if_add = i802_if_add, - .if_update = i802_if_update, - .if_remove = i802_if_remove, - .get_hw_feature_data = i802_get_hw_feature_data, - .set_sta_vlan = i802_set_sta_vlan, - .set_country = i802_set_country, -}; diff --git a/contrib/hostapd/hostapd/driver_none.c b/contrib/hostapd/hostapd/driver_none.c deleted file mode 100644 index 96e7e644e5..0000000000 --- a/contrib/hostapd/hostapd/driver_none.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * hostapd / Driver interface for RADIUS server only (no driver) - * Copyright (c) 2008, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "hostapd.h" -#include "driver.h" - - -struct none_driver_data { - struct hostapd_data *hapd; -}; - - -static void * none_driver_init(struct hostapd_data *hapd) -{ - struct none_driver_data *drv; - - drv = os_zalloc(sizeof(struct none_driver_data)); - if (drv == NULL) { - wpa_printf(MSG_ERROR, "Could not allocate memory for none " - "driver data"); - return NULL; - } - drv->hapd = hapd; - - return drv; -} - - -static void none_driver_deinit(void *priv) -{ - struct none_driver_data *drv = priv; - - os_free(drv); -} - - -static int none_driver_send_ether(void *priv, const u8 *dst, const u8 *src, - u16 proto, const u8 *data, size_t data_len) -{ - return 0; -} - - -const struct wpa_driver_ops wpa_driver_none_ops = { - .name = "none", - .init = none_driver_init, - .deinit = none_driver_deinit, - .send_ether = none_driver_send_ether, -}; diff --git a/contrib/hostapd/hostapd/driver_prism54.c b/contrib/hostapd/hostapd/driver_prism54.c deleted file mode 100644 index 4e2189aeb5..0000000000 --- a/contrib/hostapd/hostapd/driver_prism54.c +++ /dev/null @@ -1,1091 +0,0 @@ -/* - * hostapd / Driver interaction with Prism54 PIMFOR interface - * Copyright (c) 2004, Bell Kin - * based on hostap driver.c, ieee802_11.c - * Copyright (c) 2002-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include - -#ifdef USE_KERNEL_HEADERS -/* compat-wireless does not include linux/compiler.h to define __user, so - * define it here */ -#ifndef __user -#define __user -#endif /* __user */ -#include -#include -#include /* The L2 protocols */ -#include -#include -#else /* USE_KERNEL_HEADERS */ -#include -#include -#include "wireless_copy.h" -#endif /* USE_KERNEL_HEADERS */ - -#include "hostapd.h" -#include "driver.h" -#include "ieee802_1x.h" -#include "eloop.h" -#include "ieee802_11.h" -#include "prism54.h" -#include "wpa.h" -#include "radius/radius.h" -#include "sta_info.h" -#include "accounting.h" - -const int PIM_BUF_SIZE = 4096; - -struct prism54_driver_data { - struct hostapd_data *hapd; - char iface[IFNAMSIZ + 1]; - int sock; /* raw packet socket for 802.3 access */ - int pim_sock; /* socket for pimfor packet */ - char macs[2007][6]; -}; - - -static int mac_id_refresh(struct prism54_driver_data *data, int id, char *mac) -{ - if (id < 0 || id > 2006) { - return -1; - } - memcpy(&data->macs[id][0], mac, ETH_ALEN); - return 0; -} - - -static char * mac_id_get(struct prism54_driver_data *data, int id) -{ - if (id < 0 || id > 2006) { - return NULL; - } - return &data->macs[id][0]; -} - - -/* wait for a specific pimfor, timeout in 10ms resolution */ -/* pim_sock must be non-block to prevent dead lock from no response */ -/* or same response type in series */ -static int prism54_waitpim(void *priv, unsigned long oid, void *buf, int len, - int timeout) -{ - struct prism54_driver_data *drv = priv; - struct timeval tv, stv, ctv; - fd_set pfd; - int rlen; - pimdev_hdr *pkt; - - pkt = malloc(8192); - if (pkt == NULL) - return -1; - - FD_ZERO(&pfd); - gettimeofday(&stv, NULL); - do { - FD_SET(drv->pim_sock, &pfd); - tv.tv_sec = 0; - tv.tv_usec = 10000; - if (select(drv->pim_sock + 1, &pfd, NULL, NULL, &tv)) { - rlen = recv(drv->pim_sock, pkt, 8192, 0); - if (rlen > 0) { - if (pkt->oid == htonl(oid)) { - if (rlen <= len) { - if (buf != NULL) { - memcpy(buf, pkt, rlen); - } - free(pkt); - return rlen; - } else { - printf("buffer too small\n"); - free(pkt); - return -1; - } - } else { - gettimeofday(&ctv, NULL); - continue; - } - } - } - gettimeofday(&ctv, NULL); - } while (((ctv.tv_sec - stv.tv_sec) * 100 + - (ctv.tv_usec - stv.tv_usec) / 10000) > timeout); - free(pkt); - return 0; -} - - -/* send an eapol packet */ -static int prism54_send_eapol(void *priv, const u8 *addr, - const u8 *data, size_t data_len, int encrypt, - const u8 *own_addr) -{ - struct prism54_driver_data *drv = priv; - ieee802_3_hdr *hdr; - size_t len; - u8 *pos; - int res; - - len = sizeof(*hdr) + data_len; - hdr = os_zalloc(len); - if (hdr == NULL) { - printf("malloc() failed for prism54_send_data(len=%lu)\n", - (unsigned long) len); - return -1; - } - - memcpy(&hdr->da[0], addr, ETH_ALEN); - memcpy(&hdr->sa[0], own_addr, ETH_ALEN); - hdr->type = htons(ETH_P_PAE); - pos = (u8 *) (hdr + 1); - memcpy(pos, data, data_len); - - res = send(drv->sock, hdr, len, 0); - free(hdr); - - if (res < 0) { - perror("hostapd_send_eapol: send"); - printf("hostapd_send_eapol - packet len: %lu - failed\n", - (unsigned long) len); - } - - return res; -} - - -/* open data channel(auth-1) or eapol only(unauth-0) */ -static int prism54_set_sta_authorized(void *priv, const u8 *addr, - int authorized) -{ - struct prism54_driver_data *drv = priv; - pimdev_hdr *hdr; - char *pos; - - hdr = malloc(sizeof(*hdr) + ETH_ALEN); - if (hdr == NULL) - return -1; - hdr->op = htonl(PIMOP_SET); - if (authorized) { - hdr->oid = htonl(DOT11_OID_EAPAUTHSTA); - } else { - hdr->oid = htonl(DOT11_OID_EAPUNAUTHSTA); - } - pos = (char *) (hdr + 1); - memcpy(pos, addr, ETH_ALEN); - send(drv->pim_sock, hdr, sizeof(*hdr) + ETH_ALEN, 0); - prism54_waitpim(priv, hdr->oid, hdr, sizeof(*hdr) + ETH_ALEN, 10); - free(hdr); - return 0; -} - - -static int -prism54_sta_set_flags(void *priv, const u8 *addr, int total_flags, - int flags_or, int flags_and) -{ - /* For now, only support setting Authorized flag */ - if (flags_or & WLAN_STA_AUTHORIZED) - return prism54_set_sta_authorized(priv, addr, 1); - if (flags_and & WLAN_STA_AUTHORIZED) - return prism54_set_sta_authorized(priv, addr, 0); - return 0; -} - - -/* set per station key */ -static int prism54_set_encryption(const char *ifname, void *priv, - const char *alg, const u8 *addr, - int idx, const u8 *key, size_t key_len, - int txkey) -{ - struct prism54_driver_data *drv = priv; - pimdev_hdr *hdr; - struct obj_stakey *keys; - u8 *buf; - size_t blen; - int ret = 0; - - blen = sizeof(struct obj_stakey) + sizeof(pimdev_hdr); - hdr = malloc(blen); - if (hdr == NULL) { - printf("memory low\n"); - return -1; - } - keys = (struct obj_stakey *) &hdr[1]; - if (!addr) { - memset(&keys->address[0], 0xff, ETH_ALEN); - } else { - memcpy(&keys->address[0], addr, ETH_ALEN); - } - if (!strcmp(alg, "WEP")) { - keys->type = DOT11_PRIV_WEP; - } else if (!strcmp(alg, "TKIP")) { - keys->type = DOT11_PRIV_TKIP; - } else if (!strcmp(alg, "none")) { - /* the only way to clear the key is to deauth it */ - /* and prism54 is capable to receive unencrypted packet */ - /* so we do nothing here */ - free(hdr); - return 0; - } else { - printf("bad auth type: %s\n", alg); - } - buf = (u8 *) &keys->key[0]; - keys->length = key_len; - keys->keyid = idx; - keys->options = htons(DOT11_STAKEY_OPTION_DEFAULTKEY); - keys->reserved = 0; - - hdr->op = htonl(PIMOP_SET); - hdr->oid = htonl(DOT11_OID_STAKEY); - - memcpy(buf, key, key_len); - - ret = send(drv->pim_sock, hdr, blen, 0); - if (ret < 0) { - free(hdr); - return ret; - } - prism54_waitpim(priv, hdr->oid, hdr, blen, 10); - - free(hdr); - - return 0; -} - - -/* get TKIP station sequence counter, prism54 is only 6 bytes */ -static int prism54_get_seqnum(const char *ifname, void *priv, const u8 *addr, - int idx, u8 *seq) -{ - struct prism54_driver_data *drv = priv; - struct obj_stasc *stasc; - pimdev_hdr *hdr; - size_t blen; - int ret = 0; - - blen = sizeof(*stasc) + sizeof(*hdr); - hdr = malloc(blen); - if (hdr == NULL) - return -1; - - stasc = (struct obj_stasc *) &hdr[1]; - - if (addr == NULL) - memset(&stasc->address[0], 0xff, ETH_ALEN); - else - memcpy(&stasc->address[0], addr, ETH_ALEN); - - hdr->oid = htonl(DOT11_OID_STASC); - hdr->op = htonl(PIMOP_GET); - stasc->keyid = idx; - if (send(drv->pim_sock,hdr,blen,0) <= 0) { - free(hdr); - return -1; - } - if (prism54_waitpim(priv, DOT11_OID_STASC, hdr, blen, 10) <= 0) { - ret = -1; - } else { - if (hdr->op == (int) htonl(PIMOP_RESPONSE)) { - memcpy(seq + 2, &stasc->sc_high, ETH_ALEN); - memset(seq, 0, 2); - } else { - ret = -1; - } - } - free(hdr); - - return ret; -} - - -/* include unencrypted, set mlme autolevel to extended */ -static int prism54_init_1x(void *priv) -{ - struct prism54_driver_data *drv = priv; - pimdev_hdr *hdr; - unsigned long *ul; - int blen = sizeof(*hdr) + sizeof(*ul); - - hdr = malloc(blen); - if (hdr == NULL) - return -1; - - ul = (unsigned long *) &hdr[1]; - hdr->op = htonl(PIMOP_SET); - hdr->oid = htonl(DOT11_OID_EXUNENCRYPTED); - *ul = htonl(DOT11_BOOL_TRUE); /* not accept */ - send(drv->pim_sock, hdr, blen, 0); - prism54_waitpim(priv, DOT11_OID_EXUNENCRYPTED, hdr, blen, 10); - hdr->op = htonl(PIMOP_SET); - hdr->oid = htonl(DOT11_OID_MLMEAUTOLEVEL); - *ul = htonl(DOT11_MLME_EXTENDED); - send(drv->pim_sock, hdr, blen, 0); - prism54_waitpim(priv, DOT11_OID_MLMEAUTOLEVEL, hdr, blen, 10); - hdr->op = htonl(PIMOP_SET); - hdr->oid = htonl(DOT11_OID_DOT1XENABLE); - *ul = htonl(DOT11_BOOL_TRUE); - send(drv->pim_sock, hdr, blen, 0); - prism54_waitpim(priv, DOT11_OID_DOT1XENABLE, hdr, blen, 10); - hdr->op = htonl(PIMOP_SET); - hdr->oid = htonl(DOT11_OID_AUTHENABLE); - *ul = htonl(DOT11_AUTH_OS); /* OS */ - send(drv->pim_sock, hdr, blen, 0); - prism54_waitpim(priv, DOT11_OID_AUTHENABLE, hdr, blen, 10); - free(hdr); - return 0; -} - - -static int prism54_set_privacy_invoked(const char *ifname, void *priv, - int flag) -{ - struct prism54_driver_data *drv = priv; - pimdev_hdr *hdr; - unsigned long *ul; - int ret; - int blen = sizeof(*hdr) + sizeof(*ul); - hdr = malloc(blen); - if (hdr == NULL) - return -1; - ul = (unsigned long *) &hdr[1]; - hdr->op = htonl(PIMOP_SET); - hdr->oid = htonl(DOT11_OID_PRIVACYINVOKED); - if (flag) { - *ul = htonl(DOT11_BOOL_TRUE); /* has privacy */ - } else { - *ul = 0; - } - ret = send(drv->pim_sock, hdr, blen, 0); - if (ret >= 0) { - ret = prism54_waitpim(priv, DOT11_OID_PRIVACYINVOKED, hdr, - blen, 10); - } - free(hdr); - return ret; -} - - -static int prism54_ioctl_setiwessid(const char *ifname, void *priv, - const u8 *buf, int len) -{ -#if 0 - struct prism54_driver_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.essid.flags = 1; /* SSID active */ - iwr.u.essid.pointer = (caddr_t) buf; - iwr.u.essid.length = len + 1; - - if (ioctl(drv->pim_sock, SIOCSIWESSID, &iwr) < 0) { - perror("ioctl[SIOCSIWESSID]"); - printf("len=%d\n", len); - return -1; - } -#endif - return 0; -} - - -/* kick all stations */ -/* does not work during init, but at least it won't crash firmware */ -static int prism54_flush(void *priv) -{ - struct prism54_driver_data *drv = priv; - struct obj_mlmeex *mlme; - pimdev_hdr *hdr; - int ret; - unsigned int i; - long *nsta; - int blen = sizeof(*hdr) + sizeof(*mlme); - char *mac_id; - - hdr = os_zalloc(blen); - if (hdr == NULL) - return -1; - - mlme = (struct obj_mlmeex *) &hdr[1]; - nsta = (long *) &hdr[1]; - hdr->op = htonl(PIMOP_GET); - hdr->oid = htonl(DOT11_OID_CLIENTS); - ret = send(drv->pim_sock, hdr, sizeof(*hdr) + sizeof(long), 0); - ret = prism54_waitpim(priv, DOT11_OID_CLIENTS, hdr, blen, 10); - if ((ret < 0) || (hdr->op != (int) htonl(PIMOP_RESPONSE)) || - (le_to_host32(*nsta) > 2007)) { - free(hdr); - return 0; - } - for (i = 0; i < le_to_host32(*nsta); i++) { - mlme->id = -1; - mac_id = mac_id_get(drv, i); - if (mac_id) - memcpy(&mlme->address[0], mac_id, ETH_ALEN); - mlme->code = host_to_le16(WLAN_REASON_UNSPECIFIED); - mlme->state = htons(DOT11_STATE_NONE); - mlme->size = 0; - hdr->op = htonl(PIMOP_SET); - hdr->oid = htonl(DOT11_OID_DISASSOCIATEEX); - ret = send(drv->pim_sock, hdr, blen, 0); - prism54_waitpim(priv, DOT11_OID_DISASSOCIATEEX, hdr, blen, - 100); - } - for (i = 0; i < le_to_host32(*nsta); i++) { - mlme->id = -1; - mac_id = mac_id_get(drv, i); - if (mac_id) - memcpy(&mlme->address[0], mac_id, ETH_ALEN); - mlme->code = host_to_le16(WLAN_REASON_UNSPECIFIED); - mlme->state = htons(DOT11_STATE_NONE); - mlme->size = 0; - hdr->op = htonl(PIMOP_SET); - hdr->oid = htonl(DOT11_OID_DEAUTHENTICATEEX); - ret = send(drv->pim_sock, hdr, blen, 0); - prism54_waitpim(priv, DOT11_OID_DEAUTHENTICATEEX, hdr, blen, - 100); - } - free(hdr); - return 0; -} - - -static int prism54_sta_deauth(void *priv, const u8 *addr, int reason) -{ - struct prism54_driver_data *drv = priv; - pimdev_hdr *hdr; - struct obj_mlmeex *mlme; - int ret; - int blen = sizeof(*hdr) + sizeof(*mlme); - hdr = malloc(blen); - if (hdr == NULL) - return -1; - mlme = (struct obj_mlmeex *) &hdr[1]; - hdr->op = htonl(PIMOP_SET); - hdr->oid = htonl(DOT11_OID_DEAUTHENTICATEEX); - memcpy(&mlme->address[0], addr, ETH_ALEN); - mlme->id = -1; - mlme->state = htons(DOT11_STATE_NONE); - mlme->code = host_to_le16(reason); - mlme->size = 0; - ret = send(drv->pim_sock, hdr, blen, 0); - prism54_waitpim(priv, DOT11_OID_DEAUTHENTICATEEX, hdr, blen, 10); - free(hdr); - return ret; -} - - -static int prism54_sta_disassoc(void *priv, const u8 *addr, int reason) -{ - struct prism54_driver_data *drv = priv; - pimdev_hdr *hdr; - struct obj_mlmeex *mlme; - int ret; - int blen = sizeof(*hdr) + sizeof(*mlme); - hdr = malloc(blen); - if (hdr == NULL) - return -1; - mlme = (struct obj_mlmeex *) &hdr[1]; - hdr->op = htonl(PIMOP_SET); - hdr->oid = htonl(DOT11_OID_DISASSOCIATEEX); - memcpy(&mlme->address[0], addr, ETH_ALEN); - mlme->id = -1; - mlme->state = htons(DOT11_STATE_NONE); - mlme->code = host_to_le16(reason); - mlme->size = 0; - ret = send(drv->pim_sock, hdr, blen, 0); - prism54_waitpim(priv, DOT11_OID_DISASSOCIATEEX, hdr, blen, 10); - free(hdr); - return ret; -} - - -static int prism54_get_inact_sec(void *priv, const u8 *addr) -{ - struct prism54_driver_data *drv = priv; - pimdev_hdr *hdr; - struct obj_sta *sta; - int blen = sizeof(*hdr) + sizeof(*sta); - int ret; - - hdr = malloc(blen); - if (hdr == NULL) - return -1; - hdr->op = htonl(PIMOP_GET); - hdr->oid = htonl(DOT11_OID_CLIENTFIND); - sta = (struct obj_sta *) &hdr[1]; - memcpy(&sta->address[0], addr, ETH_ALEN); - ret = send(drv->pim_sock, hdr, blen, 0); - ret = prism54_waitpim(priv, DOT11_OID_CLIENTFIND, hdr, blen, 10); - if (ret != blen) { - printf("get_inact_sec: bad return %d\n", ret); - free(hdr); - return -1; - } - if (hdr->op != (int) htonl(PIMOP_RESPONSE)) { - printf("get_inact_sec: bad resp\n"); - free(hdr); - return -1; - } - free(hdr); - return le_to_host16(sta->age); -} - - -/* set attachments */ -static int prism54_set_generic_elem(const char *ifname, void *priv, - const u8 *elem, size_t elem_len) -{ - struct prism54_driver_data *drv = priv; - pimdev_hdr *hdr; - char *pos; - struct obj_attachment_hdr *attach; - size_t blen = sizeof(*hdr) + sizeof(*attach) + elem_len; - hdr = os_zalloc(blen); - if (hdr == NULL) { - printf("%s: memory low\n", __func__); - return -1; - } - hdr->op = htonl(PIMOP_SET); - hdr->oid = htonl(DOT11_OID_ATTACHMENT); - attach = (struct obj_attachment_hdr *)&hdr[1]; - attach->type = DOT11_PKT_BEACON; - attach->id = -1; - attach->size = host_to_le16((short)elem_len); - pos = ((char*) attach) + sizeof(*attach); - if (elem) - memcpy(pos, elem, elem_len); - send(drv->pim_sock, hdr, blen, 0); - attach->type = DOT11_PKT_PROBE_RESP; - send(drv->pim_sock, hdr, blen, 0); - free(hdr); - return 0; -} - - -/* tell the card to auth the sta */ -static void prism54_handle_probe(struct prism54_driver_data *drv, - void *buf, size_t len) -{ - struct obj_mlmeex *mlme; - pimdev_hdr *hdr; - struct sta_info *sta; - hdr = (pimdev_hdr *)buf; - mlme = (struct obj_mlmeex *) &hdr[1]; - sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]); - if (sta != NULL) { - if (sta->flags & (WLAN_STA_AUTH | WLAN_STA_ASSOC)) - return; - } - if (len < sizeof(*mlme)) { - printf("bad probe packet\n"); - return; - } - mlme->state = htons(DOT11_STATE_AUTHING); - mlme->code = 0; - hdr->op = htonl(PIMOP_SET); - hdr->oid = htonl(DOT11_OID_AUTHENTICATEEX); - mlme->size = 0; - send(drv->pim_sock, hdr, sizeof(*hdr)+sizeof(*mlme), 0); -} - - -static void prism54_handle_deauth(struct prism54_driver_data *drv, - void *buf, size_t len) -{ - struct obj_mlme *mlme; - pimdev_hdr *hdr; - struct sta_info *sta; - char *mac_id; - - hdr = (pimdev_hdr *) buf; - mlme = (struct obj_mlme *) &hdr[1]; - sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]); - mac_id = mac_id_get(drv, mlme->id); - if (sta == NULL || mac_id == NULL) - return; - memcpy(&mlme->address[0], mac_id, ETH_ALEN); - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); - wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH); - sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; - ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - ap_free_sta(drv->hapd, sta); -} - - -static void prism54_handle_disassoc(struct prism54_driver_data *drv, - void *buf, size_t len) -{ - struct obj_mlme *mlme; - pimdev_hdr *hdr; - struct sta_info *sta; - char *mac_id; - - hdr = (pimdev_hdr *) buf; - mlme = (struct obj_mlme *) &hdr[1]; - mac_id = mac_id_get(drv, mlme->id); - if (mac_id == NULL) - return; - memcpy(&mlme->address[0], mac_id, ETH_ALEN); - sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]); - if (sta == NULL) { - return; - } - sta->flags &= ~WLAN_STA_ASSOC; - wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); - sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; - ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - accounting_sta_stop(drv->hapd, sta); - ieee802_1x_free_station(sta); -} - - -/* to auth it, just allow it now, later for os/sk */ -static void prism54_handle_auth(struct prism54_driver_data *drv, - void *buf, size_t len) -{ - struct obj_mlmeex *mlme; - pimdev_hdr *hdr; - struct sta_info *sta; - int resp; - - hdr = (pimdev_hdr *) buf; - mlme = (struct obj_mlmeex *) &hdr[1]; - if (len < sizeof(*mlme)) { - printf("bad auth packet\n"); - return; - } - - if (mlme->state == htons(DOT11_STATE_AUTHING)) { - sta = ap_sta_add(drv->hapd, (u8 *) &mlme->address[0]); - if (drv->hapd->tkip_countermeasures) { - resp = WLAN_REASON_MICHAEL_MIC_FAILURE; - goto fail; - } - mac_id_refresh(drv, mlme->id, &mlme->address[0]); - if (!sta) { - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - sta->flags &= ~WLAN_STA_PREAUTH; - - ieee802_1x_notify_pre_auth(sta->eapol_sm, 0); - sta->flags |= WLAN_STA_AUTH; - wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH); - mlme->code = 0; - mlme->state=htons(DOT11_STATE_AUTH); - hdr->op = htonl(PIMOP_SET); - hdr->oid = htonl(DOT11_OID_AUTHENTICATEEX); - mlme->size = 0; - sta->timeout_next = STA_NULLFUNC; - send(drv->pim_sock, hdr, sizeof(*hdr) + sizeof(*mlme), 0); - } - return; - -fail: - printf("auth fail: %x\n", resp); - mlme->code = host_to_le16(resp); - mlme->size = 0; - if (sta) - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); - hdr->oid = htonl(DOT11_OID_DEAUTHENTICATEEX); - hdr->op = htonl(PIMOP_SET); - send(drv->pim_sock, hdr, sizeof(*hdr)+sizeof(*mlme), 0); -} - - -/* do the wpa thing */ -static void prism54_handle_assoc(struct prism54_driver_data *drv, - void *buf, size_t len) -{ - pimdev_hdr *hdr; - struct obj_mlmeex *mlme; - struct ieee802_11_elems elems; - struct sta_info *sta; - u8 *wpa_ie; - u8 *cb; - int ieofs = 0; - size_t wpa_ie_len; - int resp, new_assoc; - char *mac_id; - - resp = 0; - hdr = (pimdev_hdr *) buf; - mlme = (struct obj_mlmeex *) &hdr[1]; - switch (ntohl(hdr->oid)) { - case DOT11_OID_ASSOCIATE: - case DOT11_OID_REASSOCIATE: - mlme->size = 0; - default: - break; - } - if ((mlme->state == (int) htonl(DOT11_STATE_ASSOCING)) || - (mlme->state == (int) htonl(DOT11_STATE_REASSOCING))) { - if (len < sizeof(pimdev_hdr) + sizeof(struct obj_mlme)) { - printf("bad assoc packet\n"); - return; - } - mac_id = mac_id_get(drv, mlme->id); - if (mac_id == NULL) - return; - memcpy(&mlme->address[0], mac_id, ETH_ALEN); - sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]); - if (sta == NULL) { - printf("cannot get sta\n"); - return; - } - cb = (u8 *) &mlme->data[0]; - if (hdr->oid == htonl(DOT11_OID_ASSOCIATEEX)) { - ieofs = 4; - } else if (hdr->oid == htonl(DOT11_OID_REASSOCIATEEX)) { - ieofs = 10; - } - if (le_to_host16(mlme->size) <= ieofs) { - printf("attach too small\n"); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - if (ieee802_11_parse_elems(cb + ieofs, - le_to_host16(mlme->size) - ieofs, - &elems, 1) == ParseFailed) { - printf("STA " MACSTR " sent invalid association " - "request\n", MAC2STR(sta->addr)); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - if ((drv->hapd->conf->wpa & WPA_PROTO_RSN) && - elems.rsn_ie) { - wpa_ie = elems.rsn_ie; - wpa_ie_len = elems.rsn_ie_len; - } else if ((drv->hapd->conf->wpa & WPA_PROTO_WPA) && - elems.wpa_ie) { - wpa_ie = elems.wpa_ie; - wpa_ie_len = elems.wpa_ie_len; - } else { - wpa_ie = NULL; - wpa_ie_len = 0; - } - if (drv->hapd->conf->wpa && wpa_ie == NULL) { - printf("STA " MACSTR ": No WPA/RSN IE in association " - "request\n", MAC2STR(sta->addr)); - resp = WLAN_STATUS_INVALID_IE; - goto fail; - } - if (drv->hapd->conf->wpa) { - int res; - wpa_ie -= 2; - wpa_ie_len += 2; - if (sta->wpa_sm == NULL) - sta->wpa_sm = wpa_auth_sta_init( - drv->hapd->wpa_auth, sta->addr); - if (sta->wpa_sm == NULL) { - printf("Failed to initialize WPA state " - "machine\n"); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - res = wpa_validate_wpa_ie(drv->hapd->wpa_auth, - sta->wpa_sm, - wpa_ie, wpa_ie_len, - NULL, 0); - if (res == WPA_INVALID_GROUP) - resp = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; - else if (res == WPA_INVALID_PAIRWISE) - resp = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; - else if (res == WPA_INVALID_AKMP) - resp = WLAN_STATUS_AKMP_NOT_VALID; - else if (res == WPA_ALLOC_FAIL) - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - else if (res != WPA_IE_OK) - resp = WLAN_STATUS_INVALID_IE; - if (resp != WLAN_STATUS_SUCCESS) - goto fail; - } - hdr->oid = (hdr->oid == htonl(DOT11_OID_ASSOCIATEEX)) ? - htonl(DOT11_OID_ASSOCIATEEX) : - htonl(DOT11_OID_REASSOCIATEEX); - hdr->op = htonl(PIMOP_SET); - mlme->code = 0; - mlme->state = htons(DOT11_STATE_ASSOC); - mlme->size = 0; - send(drv->pim_sock, hdr, sizeof(*hdr) + sizeof(*mlme), 0); - return; - } else if (mlme->state==htons(DOT11_STATE_ASSOC)) { - if (len < sizeof(pimdev_hdr) + sizeof(struct obj_mlme)) { - printf("bad assoc packet\n"); - return; - } - mac_id = mac_id_get(drv, mlme->id); - if (mac_id == NULL) - return; - memcpy(&mlme->address[0], mac_id, ETH_ALEN); - sta = ap_get_sta(drv->hapd, (u8 *) &mlme->address[0]); - if (sta == NULL) { - printf("cannot get sta\n"); - return; - } - new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0; - sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; - wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); - hostapd_new_assoc_sta(drv->hapd, sta, !new_assoc); - ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); - sta->timeout_next = STA_NULLFUNC; - return; - } - return; - -fail: - printf("Prism54: assoc fail: %x\n", resp); - mlme->code = host_to_le16(resp); - mlme->size = 0; - mlme->state = htons(DOT11_STATE_ASSOCING); - hdr->oid = htonl(DOT11_OID_DISASSOCIATEEX); - hdr->op = htonl(PIMOP_SET); - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); - send(drv->pim_sock, hdr, sizeof(*hdr) + sizeof(*mlme), 0); -} - - -static void handle_pim(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct prism54_driver_data *drv = eloop_ctx; - int len; - pimdev_hdr *hdr; - - hdr = malloc(PIM_BUF_SIZE); - if (hdr == NULL) - return; - len = recv(sock, hdr, PIM_BUF_SIZE, 0); - if (len < 0) { - perror("recv"); - free(hdr); - return; - } - if (len < 8) { - printf("handle_pim: too short (%d)\n", len); - free(hdr); - return; - } - - if (hdr->op != (int) htonl(PIMOP_TRAP)) { - free(hdr); - return; - } - switch (ntohl(hdr->oid)) { - case DOT11_OID_PROBE: - prism54_handle_probe(drv, hdr, len); - break; - case DOT11_OID_DEAUTHENTICATEEX: - case DOT11_OID_DEAUTHENTICATE: - prism54_handle_deauth(drv, hdr, len); - break; - case DOT11_OID_DISASSOCIATEEX: - case DOT11_OID_DISASSOCIATE: - prism54_handle_disassoc(drv, hdr, len); - break; - case DOT11_OID_AUTHENTICATEEX: - case DOT11_OID_AUTHENTICATE: - prism54_handle_auth(drv, hdr, len); - break; - case DOT11_OID_ASSOCIATEEX: - case DOT11_OID_REASSOCIATEEX: - case DOT11_OID_ASSOCIATE: - case DOT11_OID_REASSOCIATE: - prism54_handle_assoc(drv, hdr, len); - default: - break; - } - - free(hdr); -} - - -static void handle_802_3(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx; - int len; - ieee802_3_hdr *hdr; - - hdr = malloc(PIM_BUF_SIZE); - if (hdr == NULL) - return; - len = recv(sock, hdr, PIM_BUF_SIZE, 0); - if (len < 0) { - perror("recv"); - free(hdr); - return; - } - if (len < 14) { - wpa_printf(MSG_MSGDUMP, "handle_802_3: too short (%d)", len); - free(hdr); - return; - } - if (hdr->type == htons(ETH_P_PAE)) { - ieee802_1x_receive(hapd, (u8 *) &hdr->sa[0], (u8 *) &hdr[1], - len - sizeof(*hdr)); - } - free(hdr); -} - - -static int prism54_init_sockets(struct prism54_driver_data *drv) -{ - struct hostapd_data *hapd = drv->hapd; - struct ifreq ifr; - struct sockaddr_ll addr; - - drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE)); - if (drv->sock < 0) { - perror("socket[PF_PACKET,SOCK_RAW]"); - return -1; - } - - if (eloop_register_read_sock(drv->sock, handle_802_3, drv->hapd, NULL)) - { - printf("Could not register read socket\n"); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - if (hapd->conf->bridge[0] != '\0') { - printf("opening bridge: %s\n", hapd->conf->bridge); - os_strlcpy(ifr.ifr_name, hapd->conf->bridge, - sizeof(ifr.ifr_name)); - } else { - os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name)); - } - if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) { - perror("ioctl(SIOCGIFINDEX)"); - return -1; - } - - memset(&addr, 0, sizeof(addr)); - addr.sll_family = AF_PACKET; - addr.sll_ifindex = ifr.ifr_ifindex; - addr.sll_protocol = htons(ETH_P_PAE); - wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d", - addr.sll_ifindex); - - if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind"); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name)); - if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) { - perror("ioctl(SIOCGIFHWADDR)"); - return -1; - } - - if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { - printf("Invalid HW-addr family 0x%04x\n", - ifr.ifr_hwaddr.sa_family); - return -1; - } - memcpy(drv->hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); - - drv->pim_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (drv->pim_sock < 0) { - perror("socket[PF_PACKET,SOCK_RAW]"); - return -1; - } - - if (eloop_register_read_sock(drv->pim_sock, handle_pim, drv, NULL)) { - printf("Could not register read socket\n"); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%sap", drv->iface); - if (ioctl(drv->pim_sock, SIOCGIFINDEX, &ifr) != 0) { - perror("ioctl(SIOCGIFINDEX)"); - return -1; - } - - memset(&addr, 0, sizeof(addr)); - addr.sll_family = AF_PACKET; - addr.sll_ifindex = ifr.ifr_ifindex; - addr.sll_protocol = htons(ETH_P_ALL); - wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d", - addr.sll_ifindex); - - if (bind(drv->pim_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind"); - return -1; - } - - return 0; -} - - -static void * prism54_driver_init(struct hostapd_data *hapd) -{ - struct prism54_driver_data *drv; - - drv = os_zalloc(sizeof(struct prism54_driver_data)); - if (drv == NULL) { - printf("Could not allocate memory for hostapd Prism54 driver " - "data\n"); - return NULL; - } - - drv->hapd = hapd; - drv->pim_sock = drv->sock = -1; - memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface)); - - if (prism54_init_sockets(drv)) { - free(drv); - return NULL; - } - prism54_init_1x(drv); - /* must clean previous elems */ - prism54_set_generic_elem(drv->iface, drv, NULL, 0); - - return drv; -} - - -static void prism54_driver_deinit(void *priv) -{ - struct prism54_driver_data *drv = priv; - - if (drv->pim_sock >= 0) - close(drv->pim_sock); - - if (drv->sock >= 0) - close(drv->sock); - - free(drv); -} - - -const struct wpa_driver_ops wpa_driver_prism54_ops = { - .name = "prism54", - .init = prism54_driver_init, - .deinit = prism54_driver_deinit, - /* .set_ieee8021x = prism54_init_1x, */ - .set_privacy = prism54_set_privacy_invoked, - .set_encryption = prism54_set_encryption, - .get_seqnum = prism54_get_seqnum, - .flush = prism54_flush, - .set_generic_elem = prism54_set_generic_elem, - .send_eapol = prism54_send_eapol, - .sta_set_flags = prism54_sta_set_flags, - .sta_deauth = prism54_sta_deauth, - .sta_disassoc = prism54_sta_disassoc, - .set_ssid = prism54_ioctl_setiwessid, - .get_inact_sec = prism54_get_inact_sec, -}; diff --git a/contrib/hostapd/hostapd/driver_test.c b/contrib/hostapd/hostapd/driver_test.c deleted file mode 100644 index 9930a82847..0000000000 --- a/contrib/hostapd/hostapd/driver_test.c +++ /dev/null @@ -1,1300 +0,0 @@ -/* - * hostapd / Driver interface for development testing - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include - -#include "hostapd.h" -#include "driver.h" -#include "sha1.h" -#include "eloop.h" -#include "ieee802_1x.h" -#include "sta_info.h" -#include "wpa.h" -#include "accounting.h" -#include "radius/radius.h" -#include "l2_packet/l2_packet.h" -#include "ieee802_11.h" -#include "hw_features.h" -#include "wps_hostapd.h" - - -struct test_client_socket { - struct test_client_socket *next; - u8 addr[ETH_ALEN]; - struct sockaddr_un un; - socklen_t unlen; - struct test_driver_bss *bss; -}; - -struct test_driver_bss { - struct test_driver_bss *next; - char ifname[IFNAMSIZ + 1]; - u8 bssid[ETH_ALEN]; - u8 *ie; - size_t ielen; - u8 *wps_beacon_ie; - size_t wps_beacon_ie_len; - u8 *wps_probe_resp_ie; - size_t wps_probe_resp_ie_len; - u8 ssid[32]; - size_t ssid_len; - int privacy; -}; - -struct test_driver_data { - struct hostapd_data *hapd; - struct test_client_socket *cli; - int test_socket; - struct test_driver_bss *bss; - char *socket_dir; - char *own_socket_path; - int udp_port; -}; - - -static void test_driver_free_bss(struct test_driver_bss *bss) -{ - free(bss->ie); - free(bss->wps_beacon_ie); - free(bss->wps_probe_resp_ie); - free(bss); -} - - -static void test_driver_free_priv(struct test_driver_data *drv) -{ - struct test_driver_bss *bss, *prev; - - if (drv == NULL) - return; - - bss = drv->bss; - while (bss) { - prev = bss; - bss = bss->next; - test_driver_free_bss(prev); - } - free(drv->own_socket_path); - free(drv->socket_dir); - free(drv); -} - - -static struct test_client_socket * -test_driver_get_cli(struct test_driver_data *drv, struct sockaddr_un *from, - socklen_t fromlen) -{ - struct test_client_socket *cli = drv->cli; - - while (cli) { - if (cli->unlen == fromlen && - strncmp(cli->un.sun_path, from->sun_path, - fromlen - sizeof(cli->un.sun_family)) == 0) - return cli; - cli = cli->next; - } - - return NULL; -} - - -static int test_driver_send_eapol(void *priv, const u8 *addr, const u8 *data, - size_t data_len, int encrypt, - const u8 *own_addr) -{ - struct test_driver_data *drv = priv; - struct test_client_socket *cli; - struct msghdr msg; - struct iovec io[3]; - struct l2_ethhdr eth; - - if (drv->test_socket < 0) - return -1; - - cli = drv->cli; - while (cli) { - if (memcmp(cli->addr, addr, ETH_ALEN) == 0) - break; - cli = cli->next; - } - - if (!cli) { - wpa_printf(MSG_DEBUG, "%s: no destination client entry", - __func__); - return -1; - } - - memcpy(eth.h_dest, addr, ETH_ALEN); - memcpy(eth.h_source, own_addr, ETH_ALEN); - eth.h_proto = host_to_be16(ETH_P_EAPOL); - - io[0].iov_base = "EAPOL "; - io[0].iov_len = 6; - io[1].iov_base = ð - io[1].iov_len = sizeof(eth); - io[2].iov_base = (u8 *) data; - io[2].iov_len = data_len; - - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = io; - msg.msg_iovlen = 3; - msg.msg_name = &cli->un; - msg.msg_namelen = cli->unlen; - return sendmsg(drv->test_socket, &msg, 0); -} - - -static int test_driver_send_ether(void *priv, const u8 *dst, const u8 *src, - u16 proto, const u8 *data, size_t data_len) -{ - struct test_driver_data *drv = priv; - struct msghdr msg; - struct iovec io[3]; - struct l2_ethhdr eth; - char desttxt[30]; - struct sockaddr_un addr; - struct dirent *dent; - DIR *dir; - int ret = 0, broadcast = 0, count = 0; - - if (drv->test_socket < 0 || drv->socket_dir == NULL) { - wpa_printf(MSG_DEBUG, "%s: invalid parameters (sock=%d " - "socket_dir=%p)", - __func__, drv->test_socket, drv->socket_dir); - return -1; - } - - broadcast = memcmp(dst, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0; - snprintf(desttxt, sizeof(desttxt), MACSTR, MAC2STR(dst)); - - memcpy(eth.h_dest, dst, ETH_ALEN); - memcpy(eth.h_source, src, ETH_ALEN); - eth.h_proto = host_to_be16(proto); - - io[0].iov_base = "ETHER "; - io[0].iov_len = 6; - io[1].iov_base = ð - io[1].iov_len = sizeof(eth); - io[2].iov_base = (u8 *) data; - io[2].iov_len = data_len; - - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = io; - msg.msg_iovlen = 3; - - dir = opendir(drv->socket_dir); - if (dir == NULL) { - perror("test_driver: opendir"); - return -1; - } - while ((dent = readdir(dir))) { -#ifdef _DIRENT_HAVE_D_TYPE - /* Skip the file if it is not a socket. Also accept - * DT_UNKNOWN (0) in case the C library or underlying file - * system does not support d_type. */ - if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN) - continue; -#endif /* _DIRENT_HAVE_D_TYPE */ - if (strcmp(dent->d_name, ".") == 0 || - strcmp(dent->d_name, "..") == 0) - continue; - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", - drv->socket_dir, dent->d_name); - - if (strcmp(addr.sun_path, drv->own_socket_path) == 0) - continue; - if (!broadcast && strstr(dent->d_name, desttxt) == NULL) - continue; - - wpa_printf(MSG_DEBUG, "%s: Send ether frame to %s", - __func__, dent->d_name); - - msg.msg_name = &addr; - msg.msg_namelen = sizeof(addr); - ret = sendmsg(drv->test_socket, &msg, 0); - if (ret < 0) - perror("driver_test: sendmsg"); - count++; - } - closedir(dir); - - if (!broadcast && count == 0) { - wpa_printf(MSG_DEBUG, "%s: Destination " MACSTR " not found", - __func__, MAC2STR(dst)); - return -1; - } - - return ret; -} - - -static int test_driver_send_mgmt_frame(void *priv, const void *buf, - size_t len, int flags) -{ - struct test_driver_data *drv = priv; - struct msghdr msg; - struct iovec io[2]; - const u8 *dest; - int ret = 0, broadcast = 0; - char desttxt[30]; - struct sockaddr_un addr; - struct dirent *dent; - DIR *dir; - struct ieee80211_hdr *hdr; - u16 fc; - - if (drv->test_socket < 0 || len < 10 || drv->socket_dir == NULL) { - wpa_printf(MSG_DEBUG, "%s: invalid parameters (sock=%d len=%lu" - " socket_dir=%p)", - __func__, drv->test_socket, (unsigned long) len, - drv->socket_dir); - return -1; - } - - dest = buf; - dest += 4; - broadcast = memcmp(dest, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0; - snprintf(desttxt, sizeof(desttxt), MACSTR, MAC2STR(dest)); - - io[0].iov_base = "MLME "; - io[0].iov_len = 5; - io[1].iov_base = (void *) buf; - io[1].iov_len = len; - - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = io; - msg.msg_iovlen = 2; - - dir = opendir(drv->socket_dir); - if (dir == NULL) { - perror("test_driver: opendir"); - return -1; - } - while ((dent = readdir(dir))) { -#ifdef _DIRENT_HAVE_D_TYPE - /* Skip the file if it is not a socket. Also accept - * DT_UNKNOWN (0) in case the C library or underlying file - * system does not support d_type. */ - if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN) - continue; -#endif /* _DIRENT_HAVE_D_TYPE */ - if (strcmp(dent->d_name, ".") == 0 || - strcmp(dent->d_name, "..") == 0) - continue; - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", - drv->socket_dir, dent->d_name); - - if (strcmp(addr.sun_path, drv->own_socket_path) == 0) - continue; - if (!broadcast && strstr(dent->d_name, desttxt) == NULL) - continue; - - wpa_printf(MSG_DEBUG, "%s: Send management frame to %s", - __func__, dent->d_name); - - msg.msg_name = &addr; - msg.msg_namelen = sizeof(addr); - ret = sendmsg(drv->test_socket, &msg, 0); - if (ret < 0) - perror("driver_test: sendmsg"); - } - closedir(dir); - - hdr = (struct ieee80211_hdr *) buf; - fc = le_to_host16(hdr->frame_control); - ieee802_11_mgmt_cb(drv->hapd, (u8 *) buf, len, WLAN_FC_GET_STYPE(fc), - ret >= 0); - - return ret; -} - - -static void test_driver_scan(struct test_driver_data *drv, - struct sockaddr_un *from, socklen_t fromlen, - char *data) -{ - char buf[512], *pos, *end; - int ret; - struct test_driver_bss *bss; - u8 sa[ETH_ALEN]; - u8 ie[512]; - size_t ielen; - - /* data: optional [ ' ' | STA-addr | ' ' | IEs(hex) ] */ - - wpa_printf(MSG_DEBUG, "test_driver: SCAN"); - - if (*data) { - if (*data != ' ' || - hwaddr_aton(data + 1, sa)) { - wpa_printf(MSG_DEBUG, "test_driver: Unexpected SCAN " - "command format"); - return; - } - - data += 18; - while (*data == ' ') - data++; - ielen = os_strlen(data) / 2; - if (ielen > sizeof(ie)) - ielen = sizeof(ie); - if (hexstr2bin(data, ie, ielen) < 0) - ielen = 0; - - wpa_printf(MSG_DEBUG, "test_driver: Scan from " MACSTR, - MAC2STR(sa)); - wpa_hexdump(MSG_MSGDUMP, "test_driver: scan IEs", ie, ielen); - - hostapd_wps_probe_req_rx(drv->hapd, sa, ie, ielen); - } - - for (bss = drv->bss; bss; bss = bss->next) { - pos = buf; - end = buf + sizeof(buf); - - /* reply: SCANRESP BSSID SSID IEs */ - ret = snprintf(pos, end - pos, "SCANRESP " MACSTR " ", - MAC2STR(bss->bssid)); - if (ret < 0 || ret >= end - pos) - return; - pos += ret; - pos += wpa_snprintf_hex(pos, end - pos, - bss->ssid, bss->ssid_len); - ret = snprintf(pos, end - pos, " "); - if (ret < 0 || ret >= end - pos) - return; - pos += ret; - pos += wpa_snprintf_hex(pos, end - pos, bss->ie, bss->ielen); - pos += wpa_snprintf_hex(pos, end - pos, bss->wps_probe_resp_ie, - bss->wps_probe_resp_ie_len); - - if (bss->privacy) { - ret = snprintf(pos, end - pos, " PRIVACY"); - if (ret < 0 || ret >= end - pos) - return; - pos += ret; - } - - sendto(drv->test_socket, buf, pos - buf, 0, - (struct sockaddr *) from, fromlen); - } -} - - -static struct hostapd_data * test_driver_get_hapd(struct test_driver_data *drv, - struct test_driver_bss *bss) -{ - struct hostapd_iface *iface = drv->hapd->iface; - struct hostapd_data *hapd = NULL; - size_t i; - - if (bss == NULL) { - wpa_printf(MSG_DEBUG, "%s: bss == NULL", __func__); - return NULL; - } - - for (i = 0; i < iface->num_bss; i++) { - hapd = iface->bss[i]; - if (memcmp(hapd->own_addr, bss->bssid, ETH_ALEN) == 0) - break; - } - if (i == iface->num_bss) { - wpa_printf(MSG_DEBUG, "%s: no matching interface entry found " - "for BSSID " MACSTR, __func__, MAC2STR(bss->bssid)); - return NULL; - } - - return hapd; -} - - -static int test_driver_new_sta(struct test_driver_data *drv, - struct test_driver_bss *bss, const u8 *addr, - const u8 *ie, size_t ielen) -{ - struct hostapd_data *hapd; - struct sta_info *sta; - int new_assoc, res; - - hapd = test_driver_get_hapd(drv, bss); - if (hapd == NULL) - return -1; - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "associated"); - - sta = ap_get_sta(hapd, addr); - if (sta) { - accounting_sta_stop(hapd, sta); - } else { - sta = ap_sta_add(hapd, addr); - if (sta == NULL) - return -1; - } - sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); - - if (hapd->conf->wpa) { - if (ie == NULL || ielen == 0) { - if (hapd->conf->wps_state) { - sta->flags |= WLAN_STA_WPS; - goto skip_wpa_check; - } - - printf("test_driver: no IE from STA\n"); - return -1; - } - if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 && - os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) { - sta->flags |= WLAN_STA_WPS; - goto skip_wpa_check; - } - - if (sta->wpa_sm == NULL) - sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, - sta->addr); - if (sta->wpa_sm == NULL) { - printf("test_driver: Failed to initialize WPA state " - "machine\n"); - return -1; - } - res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, - ie, ielen, NULL, 0); - if (res != WPA_IE_OK) { - printf("WPA/RSN information element rejected? " - "(res %u)\n", res); - wpa_hexdump(MSG_DEBUG, "IE", ie, ielen); - return -1; - } - } -skip_wpa_check: - - new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0; - sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; - wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); - - hostapd_new_assoc_sta(hapd, sta, !new_assoc); - - ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); - - return 0; -} - - -static void test_driver_assoc(struct test_driver_data *drv, - struct sockaddr_un *from, socklen_t fromlen, - char *data) -{ - struct test_client_socket *cli; - u8 ie[256], ssid[32]; - size_t ielen, ssid_len = 0; - char *pos, *pos2, cmd[50]; - struct test_driver_bss *bss; - - /* data: STA-addr SSID(hex) IEs(hex) */ - - cli = os_zalloc(sizeof(*cli)); - if (cli == NULL) - return; - - if (hwaddr_aton(data, cli->addr)) { - printf("test_socket: Invalid MAC address '%s' in ASSOC\n", - data); - free(cli); - return; - } - pos = data + 17; - while (*pos == ' ') - pos++; - pos2 = strchr(pos, ' '); - ielen = 0; - if (pos2) { - ssid_len = (pos2 - pos) / 2; - if (hexstr2bin(pos, ssid, ssid_len) < 0) { - wpa_printf(MSG_DEBUG, "%s: Invalid SSID", __func__); - free(cli); - return; - } - wpa_hexdump_ascii(MSG_DEBUG, "test_driver_assoc: SSID", - ssid, ssid_len); - - pos = pos2 + 1; - ielen = strlen(pos) / 2; - if (ielen > sizeof(ie)) - ielen = sizeof(ie); - if (hexstr2bin(pos, ie, ielen) < 0) - ielen = 0; - } - - for (bss = drv->bss; bss; bss = bss->next) { - if (bss->ssid_len == ssid_len && - memcmp(bss->ssid, ssid, ssid_len) == 0) - break; - } - if (bss == NULL) { - wpa_printf(MSG_DEBUG, "%s: No matching SSID found from " - "configured BSSes", __func__); - free(cli); - return; - } - - cli->bss = bss; - memcpy(&cli->un, from, sizeof(cli->un)); - cli->unlen = fromlen; - cli->next = drv->cli; - drv->cli = cli; - wpa_hexdump_ascii(MSG_DEBUG, "test_socket: ASSOC sun_path", - (const u8 *) cli->un.sun_path, - cli->unlen - sizeof(cli->un.sun_family)); - - snprintf(cmd, sizeof(cmd), "ASSOCRESP " MACSTR " 0", - MAC2STR(bss->bssid)); - sendto(drv->test_socket, cmd, strlen(cmd), 0, - (struct sockaddr *) from, fromlen); - - if (test_driver_new_sta(drv, bss, cli->addr, ie, ielen) < 0) { - wpa_printf(MSG_DEBUG, "test_driver: failed to add new STA"); - } -} - - -static void test_driver_disassoc(struct test_driver_data *drv, - struct sockaddr_un *from, socklen_t fromlen) -{ - struct test_client_socket *cli; - struct sta_info *sta; - - cli = test_driver_get_cli(drv, from, fromlen); - if (!cli) - return; - - hostapd_logger(drv->hapd, cli->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "disassociated"); - - sta = ap_get_sta(drv->hapd, cli->addr); - if (sta != NULL) { - sta->flags &= ~WLAN_STA_ASSOC; - wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); - sta->acct_terminate_cause = - RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; - ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - ap_free_sta(drv->hapd, sta); - } -} - - -static void test_driver_eapol(struct test_driver_data *drv, - struct sockaddr_un *from, socklen_t fromlen, - u8 *data, size_t datalen) -{ - struct test_client_socket *cli; - if (datalen > 14) { - /* Skip Ethernet header */ - wpa_printf(MSG_DEBUG, "test_driver: dst=" MACSTR " src=" - MACSTR " proto=%04x", - MAC2STR(data), MAC2STR(data + ETH_ALEN), - WPA_GET_BE16(data + 2 * ETH_ALEN)); - data += 14; - datalen -= 14; - } - cli = test_driver_get_cli(drv, from, fromlen); - if (cli) { - struct hostapd_data *hapd; - hapd = test_driver_get_hapd(drv, cli->bss); - if (hapd == NULL) - return; - ieee802_1x_receive(hapd, cli->addr, data, datalen); - } else { - wpa_printf(MSG_DEBUG, "test_socket: EAPOL from unknown " - "client"); - } -} - - -static void test_driver_ether(struct test_driver_data *drv, - struct sockaddr_un *from, socklen_t fromlen, - u8 *data, size_t datalen) -{ - struct l2_ethhdr *eth; - - if (datalen < sizeof(*eth)) - return; - - eth = (struct l2_ethhdr *) data; - wpa_printf(MSG_DEBUG, "test_driver: RX ETHER dst=" MACSTR " src=" - MACSTR " proto=%04x", - MAC2STR(eth->h_dest), MAC2STR(eth->h_source), - be_to_host16(eth->h_proto)); - -#ifdef CONFIG_IEEE80211R - if (be_to_host16(eth->h_proto) == ETH_P_RRB) { - wpa_ft_rrb_rx(drv->hapd->wpa_auth, eth->h_source, - data + sizeof(*eth), datalen - sizeof(*eth)); - } -#endif /* CONFIG_IEEE80211R */ -} - - -static void test_driver_mlme(struct test_driver_data *drv, - struct sockaddr_un *from, socklen_t fromlen, - u8 *data, size_t datalen) -{ - struct ieee80211_hdr *hdr; - u16 fc; - - hdr = (struct ieee80211_hdr *) data; - - if (test_driver_get_cli(drv, from, fromlen) == NULL && datalen >= 16) { - struct test_client_socket *cli; - cli = os_zalloc(sizeof(*cli)); - if (cli == NULL) - return; - wpa_printf(MSG_DEBUG, "Adding client entry for " MACSTR, - MAC2STR(hdr->addr2)); - memcpy(cli->addr, hdr->addr2, ETH_ALEN); - memcpy(&cli->un, from, sizeof(cli->un)); - cli->unlen = fromlen; - cli->next = drv->cli; - drv->cli = cli; - } - - wpa_hexdump(MSG_MSGDUMP, "test_driver_mlme: received frame", - data, datalen); - fc = le_to_host16(hdr->frame_control); - if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT) { - wpa_printf(MSG_ERROR, "%s: received non-mgmt frame", - __func__); - return; - } - ieee802_11_mgmt(drv->hapd, data, datalen, WLAN_FC_GET_STYPE(fc), NULL); -} - - -static void test_driver_receive_unix(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct test_driver_data *drv = eloop_ctx; - char buf[2000]; - int res; - struct sockaddr_un from; - socklen_t fromlen = sizeof(from); - - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, - (struct sockaddr *) &from, &fromlen); - if (res < 0) { - perror("recvfrom(test_socket)"); - return; - } - buf[res] = '\0'; - - wpa_printf(MSG_DEBUG, "test_driver: received %u bytes", res); - - if (strncmp(buf, "SCAN", 4) == 0) { - test_driver_scan(drv, &from, fromlen, buf + 4); - } else if (strncmp(buf, "ASSOC ", 6) == 0) { - test_driver_assoc(drv, &from, fromlen, buf + 6); - } else if (strcmp(buf, "DISASSOC") == 0) { - test_driver_disassoc(drv, &from, fromlen); - } else if (strncmp(buf, "EAPOL ", 6) == 0) { - test_driver_eapol(drv, &from, fromlen, (u8 *) buf + 6, - res - 6); - } else if (strncmp(buf, "ETHER ", 6) == 0) { - test_driver_ether(drv, &from, fromlen, (u8 *) buf + 6, - res - 6); - } else if (strncmp(buf, "MLME ", 5) == 0) { - test_driver_mlme(drv, &from, fromlen, (u8 *) buf + 5, res - 5); - } else { - wpa_hexdump_ascii(MSG_DEBUG, "Unknown test_socket command", - (u8 *) buf, res); - } -} - - -static struct test_driver_bss * -test_driver_get_bss(struct test_driver_data *drv, const char *ifname) -{ - struct test_driver_bss *bss; - - for (bss = drv->bss; bss; bss = bss->next) { - if (strcmp(bss->ifname, ifname) == 0) - return bss; - } - return NULL; -} - - -static int test_driver_set_generic_elem(const char *ifname, void *priv, - const u8 *elem, size_t elem_len) -{ - struct test_driver_data *drv = priv; - struct test_driver_bss *bss; - - bss = test_driver_get_bss(drv, ifname); - if (bss == NULL) - return -1; - - free(bss->ie); - - if (elem == NULL) { - bss->ie = NULL; - bss->ielen = 0; - return 0; - } - - bss->ie = malloc(elem_len); - if (bss->ie == NULL) { - bss->ielen = 0; - return -1; - } - - memcpy(bss->ie, elem, elem_len); - bss->ielen = elem_len; - return 0; -} - - -static int test_driver_set_wps_beacon_ie(const char *ifname, void *priv, - const u8 *ie, size_t len) -{ - struct test_driver_data *drv = priv; - struct test_driver_bss *bss; - - wpa_hexdump(MSG_DEBUG, "test_driver: Beacon WPS IE", ie, len); - bss = test_driver_get_bss(drv, ifname); - if (bss == NULL) - return -1; - - free(bss->wps_beacon_ie); - - if (ie == NULL) { - bss->wps_beacon_ie = NULL; - bss->wps_beacon_ie_len = 0; - return 0; - } - - bss->wps_beacon_ie = malloc(len); - if (bss->wps_beacon_ie == NULL) { - bss->wps_beacon_ie_len = 0; - return -1; - } - - memcpy(bss->wps_beacon_ie, ie, len); - bss->wps_beacon_ie_len = len; - return 0; -} - - -static int test_driver_set_wps_probe_resp_ie(const char *ifname, void *priv, - const u8 *ie, size_t len) -{ - struct test_driver_data *drv = priv; - struct test_driver_bss *bss; - - wpa_hexdump(MSG_DEBUG, "test_driver: ProbeResp WPS IE", ie, len); - bss = test_driver_get_bss(drv, ifname); - if (bss == NULL) - return -1; - - free(bss->wps_probe_resp_ie); - - if (ie == NULL) { - bss->wps_probe_resp_ie = NULL; - bss->wps_probe_resp_ie_len = 0; - return 0; - } - - bss->wps_probe_resp_ie = malloc(len); - if (bss->wps_probe_resp_ie == NULL) { - bss->wps_probe_resp_ie_len = 0; - return -1; - } - - memcpy(bss->wps_probe_resp_ie, ie, len); - bss->wps_probe_resp_ie_len = len; - return 0; -} - - -static int test_driver_sta_deauth(void *priv, const u8 *addr, int reason) -{ - struct test_driver_data *drv = priv; - struct test_client_socket *cli; - - if (drv->test_socket < 0) - return -1; - - cli = drv->cli; - while (cli) { - if (memcmp(cli->addr, addr, ETH_ALEN) == 0) - break; - cli = cli->next; - } - - if (!cli) - return -1; - - return sendto(drv->test_socket, "DEAUTH", 6, 0, - (struct sockaddr *) &cli->un, cli->unlen); -} - - -static int test_driver_sta_disassoc(void *priv, const u8 *addr, int reason) -{ - struct test_driver_data *drv = priv; - struct test_client_socket *cli; - - if (drv->test_socket < 0) - return -1; - - cli = drv->cli; - while (cli) { - if (memcmp(cli->addr, addr, ETH_ALEN) == 0) - break; - cli = cli->next; - } - - if (!cli) - return -1; - - return sendto(drv->test_socket, "DISASSOC", 8, 0, - (struct sockaddr *) &cli->un, cli->unlen); -} - - -static struct hostapd_hw_modes * -test_driver_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) -{ - struct hostapd_hw_modes *modes; - - *num_modes = 3; - *flags = 0; - modes = os_zalloc(*num_modes * sizeof(struct hostapd_hw_modes)); - if (modes == NULL) - return NULL; - modes[0].mode = HOSTAPD_MODE_IEEE80211G; - modes[0].num_channels = 1; - modes[0].num_rates = 1; - modes[0].channels = os_zalloc(sizeof(struct hostapd_channel_data)); - modes[0].rates = os_zalloc(sizeof(struct hostapd_rate_data)); - if (modes[0].channels == NULL || modes[0].rates == NULL) { - hostapd_free_hw_features(modes, *num_modes); - return NULL; - } - modes[0].channels[0].chan = 1; - modes[0].channels[0].freq = 2412; - modes[0].channels[0].flag = 0; - modes[0].rates[0].rate = 10; - modes[0].rates[0].flags = HOSTAPD_RATE_BASIC | HOSTAPD_RATE_SUPPORTED | - HOSTAPD_RATE_CCK | HOSTAPD_RATE_MANDATORY; - - modes[1].mode = HOSTAPD_MODE_IEEE80211B; - modes[1].num_channels = 1; - modes[1].num_rates = 1; - modes[1].channels = os_zalloc(sizeof(struct hostapd_channel_data)); - modes[1].rates = os_zalloc(sizeof(struct hostapd_rate_data)); - if (modes[1].channels == NULL || modes[1].rates == NULL) { - hostapd_free_hw_features(modes, *num_modes); - return NULL; - } - modes[1].channels[0].chan = 1; - modes[1].channels[0].freq = 2412; - modes[1].channels[0].flag = 0; - modes[1].rates[0].rate = 10; - modes[1].rates[0].flags = HOSTAPD_RATE_BASIC | HOSTAPD_RATE_SUPPORTED | - HOSTAPD_RATE_CCK | HOSTAPD_RATE_MANDATORY; - - modes[2].mode = HOSTAPD_MODE_IEEE80211A; - modes[2].num_channels = 1; - modes[2].num_rates = 1; - modes[2].channels = os_zalloc(sizeof(struct hostapd_channel_data)); - modes[2].rates = os_zalloc(sizeof(struct hostapd_rate_data)); - if (modes[2].channels == NULL || modes[2].rates == NULL) { - hostapd_free_hw_features(modes, *num_modes); - return NULL; - } - modes[2].channels[0].chan = 60; - modes[2].channels[0].freq = 5300; - modes[2].channels[0].flag = 0; - modes[2].rates[0].rate = 60; - modes[2].rates[0].flags = HOSTAPD_RATE_BASIC | HOSTAPD_RATE_SUPPORTED | - HOSTAPD_RATE_MANDATORY; - - return modes; -} - - -static int test_driver_bss_add(void *priv, const char *ifname, const u8 *bssid) -{ - struct test_driver_data *drv = priv; - struct test_driver_bss *bss; - - wpa_printf(MSG_DEBUG, "%s(ifname=%s bssid=" MACSTR ")", - __func__, ifname, MAC2STR(bssid)); - - bss = os_zalloc(sizeof(*bss)); - if (bss == NULL) - return -1; - - os_strlcpy(bss->ifname, ifname, IFNAMSIZ); - memcpy(bss->bssid, bssid, ETH_ALEN); - - bss->next = drv->bss; - drv->bss = bss; - - return 0; -} - - -static int test_driver_bss_remove(void *priv, const char *ifname) -{ - struct test_driver_data *drv = priv; - struct test_driver_bss *bss, *prev; - struct test_client_socket *cli, *prev_c; - - wpa_printf(MSG_DEBUG, "%s(ifname=%s)", __func__, ifname); - - for (prev = NULL, bss = drv->bss; bss; prev = bss, bss = bss->next) { - if (strcmp(bss->ifname, ifname) != 0) - continue; - - if (prev) - prev->next = bss->next; - else - drv->bss = bss->next; - - for (prev_c = NULL, cli = drv->cli; cli; - prev_c = cli, cli = cli->next) { - if (cli->bss != bss) - continue; - if (prev_c) - prev_c->next = cli->next; - else - drv->cli = cli->next; - free(cli); - break; - } - - test_driver_free_bss(bss); - return 0; - } - - return -1; -} - - -static int test_driver_if_add(const char *iface, void *priv, - enum hostapd_driver_if_type type, char *ifname, - const u8 *addr) -{ - wpa_printf(MSG_DEBUG, "%s(iface=%s type=%d ifname=%s)", - __func__, iface, type, ifname); - return 0; -} - - -static int test_driver_if_update(void *priv, enum hostapd_driver_if_type type, - char *ifname, const u8 *addr) -{ - wpa_printf(MSG_DEBUG, "%s(type=%d ifname=%s)", __func__, type, ifname); - return 0; -} - - -static int test_driver_if_remove(void *priv, enum hostapd_driver_if_type type, - const char *ifname, const u8 *addr) -{ - wpa_printf(MSG_DEBUG, "%s(type=%d ifname=%s)", __func__, type, ifname); - return 0; -} - - -static int test_driver_valid_bss_mask(void *priv, const u8 *addr, - const u8 *mask) -{ - return 0; -} - - -static int test_driver_set_ssid(const char *ifname, void *priv, const u8 *buf, - int len) -{ - struct test_driver_data *drv = priv; - struct test_driver_bss *bss; - - wpa_printf(MSG_DEBUG, "%s(ifname=%s)", __func__, ifname); - wpa_hexdump_ascii(MSG_DEBUG, "test_driver_set_ssid: SSID", buf, len); - - for (bss = drv->bss; bss; bss = bss->next) { - if (strcmp(bss->ifname, ifname) != 0) - continue; - - if (len < 0 || (size_t) len > sizeof(bss->ssid)) - return -1; - - memcpy(bss->ssid, buf, len); - bss->ssid_len = len; - - return 0; - } - - return -1; -} - - -static int test_driver_set_privacy(const char *ifname, void *priv, int enabled) -{ - struct test_driver_data *drv = priv; - struct test_driver_bss *bss; - - wpa_printf(MSG_DEBUG, "%s(ifname=%s enabled=%d)", - __func__, ifname, enabled); - - for (bss = drv->bss; bss; bss = bss->next) { - if (strcmp(bss->ifname, ifname) != 0) - continue; - - bss->privacy = enabled; - - return 0; - } - - return -1; -} - - -static int test_driver_set_encryption(const char *iface, void *priv, - const char *alg, const u8 *addr, int idx, - const u8 *key, size_t key_len, int txkey) -{ - wpa_printf(MSG_DEBUG, "%s(iface=%s alg=%s idx=%d txkey=%d)", - __func__, iface, alg, idx, txkey); - if (addr) - wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr)); - if (key) - wpa_hexdump_key(MSG_DEBUG, " key", key, key_len); - return 0; -} - - -static int test_driver_set_sta_vlan(void *priv, const u8 *addr, - const char *ifname, int vlan_id) -{ - wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " ifname=%s vlan_id=%d)", - __func__, MAC2STR(addr), ifname, vlan_id); - return 0; -} - - -static int test_driver_sta_add(const char *ifname, void *priv, const u8 *addr, - u16 aid, u16 capability, u8 *supp_rates, - size_t supp_rates_len, int flags, - u16 listen_interval) -{ - struct test_driver_data *drv = priv; - struct test_client_socket *cli; - struct test_driver_bss *bss; - - wpa_printf(MSG_DEBUG, "%s(ifname=%s addr=" MACSTR " aid=%d " - "capability=0x%x flags=0x%x listen_interval=%d)", - __func__, ifname, MAC2STR(addr), aid, capability, flags, - listen_interval); - wpa_hexdump(MSG_DEBUG, "test_driver_sta_add - supp_rates", - supp_rates, supp_rates_len); - - cli = drv->cli; - while (cli) { - if (memcmp(cli->addr, addr, ETH_ALEN) == 0) - break; - cli = cli->next; - } - if (!cli) { - wpa_printf(MSG_DEBUG, "%s: no matching client entry", - __func__); - return -1; - } - - for (bss = drv->bss; bss; bss = bss->next) { - if (strcmp(ifname, bss->ifname) == 0) - break; - } - if (bss == NULL) { - wpa_printf(MSG_DEBUG, "%s: No matching interface found from " - "configured BSSes", __func__); - return -1; - } - - cli->bss = bss; - - return 0; -} - - -static void * test_driver_init(struct hostapd_data *hapd) -{ - struct test_driver_data *drv; - struct sockaddr_un addr_un; - struct sockaddr_in addr_in; - struct sockaddr *addr; - socklen_t alen; - - drv = os_zalloc(sizeof(struct test_driver_data)); - if (drv == NULL) { - printf("Could not allocate memory for test driver data\n"); - return NULL; - } - drv->bss = os_zalloc(sizeof(*drv->bss)); - if (drv->bss == NULL) { - printf("Could not allocate memory for test driver BSS data\n"); - free(drv); - return NULL; - } - - drv->hapd = hapd; - - /* Generate a MAC address to help testing with multiple APs */ - hapd->own_addr[0] = 0x02; /* locally administered */ - sha1_prf((const u8 *) hapd->conf->iface, strlen(hapd->conf->iface), - "hostapd test bssid generation", - (const u8 *) hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len, - hapd->own_addr + 1, ETH_ALEN - 1); - - os_strlcpy(drv->bss->ifname, hapd->conf->iface, IFNAMSIZ); - memcpy(drv->bss->bssid, hapd->own_addr, ETH_ALEN); - - if (hapd->conf->test_socket) { - if (strlen(hapd->conf->test_socket) >= - sizeof(addr_un.sun_path)) { - printf("Too long test_socket path\n"); - test_driver_free_priv(drv); - return NULL; - } - if (strncmp(hapd->conf->test_socket, "DIR:", 4) == 0) { - size_t len = strlen(hapd->conf->test_socket) + 30; - drv->socket_dir = strdup(hapd->conf->test_socket + 4); - drv->own_socket_path = malloc(len); - if (drv->own_socket_path) { - snprintf(drv->own_socket_path, len, - "%s/AP-" MACSTR, - hapd->conf->test_socket + 4, - MAC2STR(hapd->own_addr)); - } - } else if (strncmp(hapd->conf->test_socket, "UDP:", 4) == 0) { - drv->udp_port = atoi(hapd->conf->test_socket + 4); - } else { - drv->own_socket_path = strdup(hapd->conf->test_socket); - } - if (drv->own_socket_path == NULL && drv->udp_port == 0) { - test_driver_free_priv(drv); - return NULL; - } - - drv->test_socket = socket(drv->udp_port ? PF_INET : PF_UNIX, - SOCK_DGRAM, 0); - if (drv->test_socket < 0) { - perror("socket"); - test_driver_free_priv(drv); - return NULL; - } - - if (drv->udp_port) { - os_memset(&addr_in, 0, sizeof(addr_in)); - addr_in.sin_family = AF_INET; - addr_in.sin_port = htons(drv->udp_port); - addr = (struct sockaddr *) &addr_in; - alen = sizeof(addr_in); - } else { - os_memset(&addr_un, 0, sizeof(addr_un)); - addr_un.sun_family = AF_UNIX; - os_strlcpy(addr_un.sun_path, drv->own_socket_path, - sizeof(addr_un.sun_path)); - addr = (struct sockaddr *) &addr_un; - alen = sizeof(addr_un); - } - if (bind(drv->test_socket, addr, alen) < 0) { - perror("bind(PF_UNIX)"); - close(drv->test_socket); - if (drv->own_socket_path) - unlink(drv->own_socket_path); - test_driver_free_priv(drv); - return NULL; - } - eloop_register_read_sock(drv->test_socket, - test_driver_receive_unix, drv, NULL); - } else - drv->test_socket = -1; - - return drv; -} - - -static void test_driver_deinit(void *priv) -{ - struct test_driver_data *drv = priv; - struct test_client_socket *cli, *prev; - - cli = drv->cli; - while (cli) { - prev = cli; - cli = cli->next; - free(prev); - } - - if (drv->test_socket >= 0) { - eloop_unregister_read_sock(drv->test_socket); - close(drv->test_socket); - if (drv->own_socket_path) - unlink(drv->own_socket_path); - } - - /* There should be only one BSS remaining at this point. */ - if (drv->bss == NULL) - wpa_printf(MSG_ERROR, "%s: drv->bss == NULL", __func__); - else if (drv->bss->next) - wpa_printf(MSG_ERROR, "%s: drv->bss->next != NULL", __func__); - - test_driver_free_priv(drv); -} - - -const struct wpa_driver_ops wpa_driver_test_ops = { - .name = "test", - .init = test_driver_init, - .deinit = test_driver_deinit, - .send_eapol = test_driver_send_eapol, - .send_mgmt_frame = test_driver_send_mgmt_frame, - .set_generic_elem = test_driver_set_generic_elem, - .sta_deauth = test_driver_sta_deauth, - .sta_disassoc = test_driver_sta_disassoc, - .get_hw_feature_data = test_driver_get_hw_feature_data, - .bss_add = test_driver_bss_add, - .bss_remove = test_driver_bss_remove, - .if_add = test_driver_if_add, - .if_update = test_driver_if_update, - .if_remove = test_driver_if_remove, - .valid_bss_mask = test_driver_valid_bss_mask, - .set_ssid = test_driver_set_ssid, - .set_privacy = test_driver_set_privacy, - .set_encryption = test_driver_set_encryption, - .set_sta_vlan = test_driver_set_sta_vlan, - .sta_add = test_driver_sta_add, - .send_ether = test_driver_send_ether, - .set_wps_beacon_ie = test_driver_set_wps_beacon_ie, - .set_wps_probe_resp_ie = test_driver_set_wps_probe_resp_ie, -}; diff --git a/contrib/hostapd/hostapd/driver_wired.c b/contrib/hostapd/hostapd/driver_wired.c deleted file mode 100644 index 61cb667cca..0000000000 --- a/contrib/hostapd/hostapd/driver_wired.c +++ /dev/null @@ -1,372 +0,0 @@ -/* - * hostapd / Kernel driver communication for wired (Ethernet) drivers - * Copyright (c) 2002-2007, Jouni Malinen - * Copyright (c) 2004, Gunter Burchardt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#ifdef USE_KERNEL_HEADERS -#include -#include -#include /* The L2 protocols */ -#include -#include -#else /* USE_KERNEL_HEADERS */ -#include -#include -#include -#endif /* USE_KERNEL_HEADERS */ - -#include "hostapd.h" -#include "ieee802_1x.h" -#include "eloop.h" -#include "sta_info.h" -#include "driver.h" -#include "accounting.h" - - -struct wired_driver_data { - struct hostapd_data *hapd; - - int sock; /* raw packet socket for driver access */ - int dhcp_sock; /* socket for dhcp packets */ - int use_pae_group_addr; -}; - - -#define WIRED_EAPOL_MULTICAST_GROUP {0x01,0x80,0xc2,0x00,0x00,0x03} - - -/* TODO: detecting new devices should eventually be changed from using DHCP - * snooping to trigger on any packet from a new layer 2 MAC address, e.g., - * based on ebtables, etc. */ - -struct dhcp_message { - u_int8_t op; - u_int8_t htype; - u_int8_t hlen; - u_int8_t hops; - u_int32_t xid; - u_int16_t secs; - u_int16_t flags; - u_int32_t ciaddr; - u_int32_t yiaddr; - u_int32_t siaddr; - u_int32_t giaddr; - u_int8_t chaddr[16]; - u_int8_t sname[64]; - u_int8_t file[128]; - u_int32_t cookie; - u_int8_t options[308]; /* 312 - cookie */ -}; - - -static void wired_possible_new_sta(struct hostapd_data *hapd, u8 *addr) -{ - struct sta_info *sta; - - sta = ap_get_sta(hapd, addr); - if (sta) - return; - - wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR - " - adding a new STA", MAC2STR(addr)); - sta = ap_sta_add(hapd, addr); - if (sta) { - hostapd_new_assoc_sta(hapd, sta, 0); - } else { - wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR, - MAC2STR(addr)); - } -} - - -static void handle_data(struct hostapd_data *hapd, unsigned char *buf, - size_t len) -{ - struct ieee8023_hdr *hdr; - u8 *pos, *sa; - size_t left; - - /* must contain at least ieee8023_hdr 6 byte source, 6 byte dest, - * 2 byte ethertype */ - if (len < 14) { - wpa_printf(MSG_MSGDUMP, "handle_data: too short (%lu)", - (unsigned long) len); - return; - } - - hdr = (struct ieee8023_hdr *) buf; - - switch (ntohs(hdr->ethertype)) { - case ETH_P_PAE: - wpa_printf(MSG_MSGDUMP, "Received EAPOL packet"); - sa = hdr->src; - wired_possible_new_sta(hapd, sa); - - pos = (u8 *) (hdr + 1); - left = len - sizeof(*hdr); - - ieee802_1x_receive(hapd, sa, pos, left); - break; - - default: - wpa_printf(MSG_DEBUG, "Unknown ethertype 0x%04x in data frame", - ntohs(hdr->ethertype)); - break; - } -} - - -static void handle_read(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx; - int len; - unsigned char buf[3000]; - - len = recv(sock, buf, sizeof(buf), 0); - if (len < 0) { - perror("recv"); - return; - } - - handle_data(hapd, buf, len); -} - - -static void handle_dhcp(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx; - int len; - unsigned char buf[3000]; - struct dhcp_message *msg; - u8 *mac_address; - - len = recv(sock, buf, sizeof(buf), 0); - if (len < 0) { - perror("recv"); - return; - } - - /* must contain at least dhcp_message->chaddr */ - if (len < 44) { - wpa_printf(MSG_MSGDUMP, "handle_dhcp: too short (%d)", len); - return; - } - - msg = (struct dhcp_message *) buf; - mac_address = (u8 *) &(msg->chaddr); - - wpa_printf(MSG_MSGDUMP, "Got DHCP broadcast packet from " MACSTR, - MAC2STR(mac_address)); - - wired_possible_new_sta(hapd, mac_address); -} - - -static int wired_init_sockets(struct wired_driver_data *drv) -{ - struct hostapd_data *hapd = drv->hapd; - struct ifreq ifr; - struct sockaddr_ll addr; - struct sockaddr_in addr2; - struct packet_mreq mreq; - u8 multicastgroup_eapol[6] = WIRED_EAPOL_MULTICAST_GROUP; - int n = 1; - - drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE)); - if (drv->sock < 0) { - perror("socket[PF_PACKET,SOCK_RAW]"); - return -1; - } - - if (eloop_register_read_sock(drv->sock, handle_read, hapd, NULL)) { - printf("Could not register read socket\n"); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, hapd->conf->iface, sizeof(ifr.ifr_name)); - if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) { - perror("ioctl(SIOCGIFINDEX)"); - return -1; - } - - - memset(&addr, 0, sizeof(addr)); - addr.sll_family = AF_PACKET; - addr.sll_ifindex = ifr.ifr_ifindex; - wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d", - addr.sll_ifindex); - - if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind"); - return -1; - } - - /* filter multicast address */ - memset(&mreq, 0, sizeof(mreq)); - mreq.mr_ifindex = ifr.ifr_ifindex; - mreq.mr_type = PACKET_MR_MULTICAST; - mreq.mr_alen = 6; - memcpy(mreq.mr_address, multicastgroup_eapol, mreq.mr_alen); - - if (setsockopt(drv->sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, - sizeof(mreq)) < 0) { - perror("setsockopt[SOL_SOCKET,PACKET_ADD_MEMBERSHIP]"); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, hapd->conf->iface, sizeof(ifr.ifr_name)); - if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) { - perror("ioctl(SIOCGIFHWADDR)"); - return -1; - } - - if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { - printf("Invalid HW-addr family 0x%04x\n", - ifr.ifr_hwaddr.sa_family); - return -1; - } - memcpy(hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); - - /* setup dhcp listen socket for sta detection */ - if ((drv->dhcp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { - perror("socket call failed for dhcp"); - return -1; - } - - if (eloop_register_read_sock(drv->dhcp_sock, handle_dhcp, hapd, NULL)) - { - printf("Could not register read socket\n"); - return -1; - } - - memset(&addr2, 0, sizeof(addr2)); - addr2.sin_family = AF_INET; - addr2.sin_port = htons(67); - addr2.sin_addr.s_addr = INADDR_ANY; - - if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &n, - sizeof(n)) == -1) { - perror("setsockopt[SOL_SOCKET,SO_REUSEADDR]"); - return -1; - } - if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BROADCAST, (char *) &n, - sizeof(n)) == -1) { - perror("setsockopt[SOL_SOCKET,SO_BROADCAST]"); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_ifrn.ifrn_name, hapd->conf->iface, IFNAMSIZ); - if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BINDTODEVICE, - (char *) &ifr, sizeof(ifr)) < 0) { - perror("setsockopt[SOL_SOCKET,SO_BINDTODEVICE]"); - return -1; - } - - if (bind(drv->dhcp_sock, (struct sockaddr *) &addr2, - sizeof(struct sockaddr)) == -1) { - perror("bind"); - return -1; - } - - return 0; -} - - -static int wired_send_eapol(void *priv, const u8 *addr, - const u8 *data, size_t data_len, int encrypt, - const u8 *own_addr) -{ - struct wired_driver_data *drv = priv; - u8 pae_group_addr[ETH_ALEN] = WIRED_EAPOL_MULTICAST_GROUP; - struct ieee8023_hdr *hdr; - size_t len; - u8 *pos; - int res; - - len = sizeof(*hdr) + data_len; - hdr = os_zalloc(len); - if (hdr == NULL) { - printf("malloc() failed for wired_send_eapol(len=%lu)\n", - (unsigned long) len); - return -1; - } - - memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr, - ETH_ALEN); - memcpy(hdr->src, own_addr, ETH_ALEN); - hdr->ethertype = htons(ETH_P_PAE); - - pos = (u8 *) (hdr + 1); - memcpy(pos, data, data_len); - - res = send(drv->sock, (u8 *) hdr, len, 0); - free(hdr); - - if (res < 0) { - perror("wired_send_eapol: send"); - printf("wired_send_eapol - packet len: %lu - failed\n", - (unsigned long) len); - } - - return res; -} - - -static void * wired_driver_init(struct hostapd_data *hapd) -{ - struct wired_driver_data *drv; - - drv = os_zalloc(sizeof(struct wired_driver_data)); - if (drv == NULL) { - printf("Could not allocate memory for wired driver data\n"); - return NULL; - } - - drv->hapd = hapd; - drv->use_pae_group_addr = hapd->conf->use_pae_group_addr; - - if (wired_init_sockets(drv)) { - free(drv); - return NULL; - } - - return drv; -} - - -static void wired_driver_deinit(void *priv) -{ - struct wired_driver_data *drv = priv; - - if (drv->sock >= 0) - close(drv->sock); - - if (drv->dhcp_sock >= 0) - close(drv->dhcp_sock); - - free(drv); -} - - -const struct wpa_driver_ops wpa_driver_wired_ops = { - .name = "wired", - .init = wired_driver_init, - .deinit = wired_driver_deinit, - .send_eapol = wired_send_eapol, -}; diff --git a/contrib/hostapd/hostapd/drivers.c b/contrib/hostapd/hostapd/drivers.c deleted file mode 100644 index bde6e609f3..0000000000 --- a/contrib/hostapd/hostapd/drivers.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * hostapd / driver interface list - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - - -#ifdef CONFIG_DRIVER_HOSTAP -extern struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */ -#endif /* CONFIG_DRIVER_HOSTAP */ -#ifdef CONFIG_DRIVER_NL80211 -extern struct wpa_driver_ops wpa_driver_nl80211_ops; /* driver_nl80211.c */ -#endif /* CONFIG_DRIVER_NL80211 */ -#ifdef CONFIG_DRIVER_PRISM54 -extern struct wpa_driver_ops wpa_driver_prism54_ops; /* driver_prism54.c */ -#endif /* CONFIG_DRIVER_PRISM54 */ -#ifdef CONFIG_DRIVER_MADWIFI -extern struct wpa_driver_ops wpa_driver_madwifi_ops; /* driver_madwifi.c */ -#endif /* CONFIG_DRIVER_MADWIFI */ -#ifdef CONFIG_DRIVER_ATHEROS -extern struct wpa_driver_ops wpa_driver_atheros_ops; /* driver_atheros.c */ -#endif /* CONFIG_DRIVER_ATHEROS */ -#ifdef CONFIG_DRIVER_BSD -extern struct wpa_driver_ops wpa_driver_bsd_ops; /* driver_bsd.c */ -#endif /* CONFIG_DRIVER_BSD */ -#ifdef CONFIG_DRIVER_WIRED -extern struct wpa_driver_ops wpa_driver_wired_ops; /* driver_wired.c */ -#endif /* CONFIG_DRIVER_WIRED */ -#ifdef CONFIG_DRIVER_TEST -extern struct wpa_driver_ops wpa_driver_test_ops; /* driver_test.c */ -#endif /* CONFIG_DRIVER_TEST */ -#ifdef CONFIG_DRIVER_NONE -extern struct wpa_driver_ops wpa_driver_none_ops; /* driver_none.c */ -#endif /* CONFIG_DRIVER_NONE */ - - -struct wpa_driver_ops *hostapd_drivers[] = -{ -#ifdef CONFIG_DRIVER_HOSTAP - &wpa_driver_hostap_ops, -#endif /* CONFIG_DRIVER_HOSTAP */ -#ifdef CONFIG_DRIVER_NL80211 - &wpa_driver_nl80211_ops, -#endif /* CONFIG_DRIVER_NL80211 */ -#ifdef CONFIG_DRIVER_PRISM54 - &wpa_driver_prism54_ops, -#endif /* CONFIG_DRIVER_PRISM54 */ -#ifdef CONFIG_DRIVER_MADWIFI - &wpa_driver_madwifi_ops, -#endif /* CONFIG_DRIVER_MADWIFI */ -#ifdef CONFIG_DRIVER_ATHEROS - &wpa_driver_atheros_ops, -#endif /* CONFIG_DRIVER_ATHEROS */ -#ifdef CONFIG_DRIVER_BSD - &wpa_driver_bsd_ops, -#endif /* CONFIG_DRIVER_BSD */ -#ifdef CONFIG_DRIVER_WIRED - &wpa_driver_wired_ops, -#endif /* CONFIG_DRIVER_WIRED */ -#ifdef CONFIG_DRIVER_TEST - &wpa_driver_test_ops, -#endif /* CONFIG_DRIVER_TEST */ -#ifdef CONFIG_DRIVER_NONE - &wpa_driver_none_ops, -#endif /* CONFIG_DRIVER_NONE */ - NULL -}; diff --git a/contrib/hostapd/hostapd/eapol_sm.c b/contrib/hostapd/hostapd/eapol_sm.c deleted file mode 100644 index 8e9d56c796..0000000000 --- a/contrib/hostapd/hostapd/eapol_sm.c +++ /dev/null @@ -1,1342 +0,0 @@ -/* - * hostapd / IEEE 802.1X-2004 Authenticator - EAPOL state machine - * Copyright (c) 2002-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "hostapd.h" -#include "ieee802_1x.h" -#include "eapol_sm.h" -#include "eloop.h" -#include "wpa.h" -#include "preauth.h" -#include "sta_info.h" -#include "eap_server/eap.h" -#include "state_machine.h" -#include "eap_common/eap_common.h" - -#define STATE_MACHINE_DATA struct eapol_state_machine -#define STATE_MACHINE_DEBUG_PREFIX "IEEE 802.1X" -#define STATE_MACHINE_ADDR sm->addr - -static struct eapol_callbacks eapol_cb; - -/* EAPOL state machines are described in IEEE Std 802.1X-2004, Chap. 8.2 */ - -#define setPortAuthorized() \ -sm->eapol->cb.set_port_authorized(sm->hapd, sm->sta, 1) -#define setPortUnauthorized() \ -sm->eapol->cb.set_port_authorized(sm->hapd, sm->sta, 0) - -/* procedures */ -#define txCannedFail() eapol_auth_tx_canned_eap(sm, 0) -#define txCannedSuccess() eapol_auth_tx_canned_eap(sm, 1) -#define txReq() eapol_auth_tx_req(sm) -#define abortAuth() sm->eapol->cb.abort_auth(sm->hapd, sm->sta) -#define txKey() sm->eapol->cb.tx_key(sm->hapd, sm->sta) -#define processKey() do { } while (0) - - -static void eapol_sm_step_run(struct eapol_state_machine *sm); -static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx); - - -static void eapol_auth_logger(struct eapol_authenticator *eapol, - const u8 *addr, logger_level level, - const char *txt) -{ - if (eapol->cb.logger == NULL) - return; - eapol->cb.logger(eapol->conf.hapd, addr, level, txt); -} - - -static void eapol_auth_vlogger(struct eapol_authenticator *eapol, - const u8 *addr, logger_level level, - const char *fmt, ...) -{ - char *format; - int maxlen; - va_list ap; - - if (eapol->cb.logger == NULL) - return; - - maxlen = os_strlen(fmt) + 100; - format = os_malloc(maxlen); - if (!format) - return; - - va_start(ap, fmt); - vsnprintf(format, maxlen, fmt, ap); - va_end(ap); - - eapol_auth_logger(eapol, addr, level, format); - - os_free(format); -} - - -static void eapol_auth_tx_canned_eap(struct eapol_state_machine *sm, - int success) -{ - struct eap_hdr eap; - - os_memset(&eap, 0, sizeof(eap)); - - eap.code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE; - eap.identifier = ++sm->last_eap_id; - eap.length = host_to_be16(sizeof(eap)); - - eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG, - "Sending canned EAP packet %s (identifier %d)", - success ? "SUCCESS" : "FAILURE", eap.identifier); - sm->eapol->cb.eapol_send(sm->hapd, sm->sta, IEEE802_1X_TYPE_EAP_PACKET, - (u8 *) &eap, sizeof(eap)); - sm->dot1xAuthEapolFramesTx++; -} - - -static void eapol_auth_tx_req(struct eapol_state_machine *sm) -{ - if (sm->eap_if->eapReqData == NULL || - wpabuf_len(sm->eap_if->eapReqData) < sizeof(struct eap_hdr)) { - eapol_auth_logger(sm->eapol, sm->addr, - EAPOL_LOGGER_DEBUG, - "TxReq called, but there is no EAP request " - "from authentication server"); - return; - } - - if (sm->flags & EAPOL_SM_WAIT_START) { - wpa_printf(MSG_DEBUG, "EAPOL: Drop EAPOL TX to " MACSTR - " while waiting for EAPOL-Start", - MAC2STR(sm->addr)); - return; - } - - sm->last_eap_id = eap_get_id(sm->eap_if->eapReqData); - eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG, - "Sending EAP Packet (identifier %d)", - sm->last_eap_id); - sm->eapol->cb.eapol_send(sm->hapd, sm->sta, IEEE802_1X_TYPE_EAP_PACKET, - wpabuf_head(sm->eap_if->eapReqData), - wpabuf_len(sm->eap_if->eapReqData)); - sm->dot1xAuthEapolFramesTx++; - if (eap_get_type(sm->eap_if->eapReqData) == EAP_TYPE_IDENTITY) - sm->dot1xAuthEapolReqIdFramesTx++; - else - sm->dot1xAuthEapolReqFramesTx++; -} - - -/** - * eapol_port_timers_tick - Port Timers state machine - * @eloop_ctx: struct eapol_state_machine * - * @timeout_ctx: Not used - * - * This statemachine is implemented as a function that will be called - * once a second as a registered event loop timeout. - */ -static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx) -{ - struct eapol_state_machine *state = timeout_ctx; - - if (state->aWhile > 0) { - state->aWhile--; - if (state->aWhile == 0) { - wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR - " - aWhile --> 0", - MAC2STR(state->addr)); - } - } - - if (state->quietWhile > 0) { - state->quietWhile--; - if (state->quietWhile == 0) { - wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR - " - quietWhile --> 0", - MAC2STR(state->addr)); - } - } - - if (state->reAuthWhen > 0) { - state->reAuthWhen--; - if (state->reAuthWhen == 0) { - wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR - " - reAuthWhen --> 0", - MAC2STR(state->addr)); - } - } - - if (state->eap_if->retransWhile > 0) { - state->eap_if->retransWhile--; - if (state->eap_if->retransWhile == 0) { - wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR - " - (EAP) retransWhile --> 0", - MAC2STR(state->addr)); - } - } - - eapol_sm_step_run(state); - - eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state); -} - - - -/* Authenticator PAE state machine */ - -SM_STATE(AUTH_PAE, INITIALIZE) -{ - SM_ENTRY_MA(AUTH_PAE, INITIALIZE, auth_pae); - sm->portMode = Auto; -} - - -SM_STATE(AUTH_PAE, DISCONNECTED) -{ - int from_initialize = sm->auth_pae_state == AUTH_PAE_INITIALIZE; - - if (sm->eapolLogoff) { - if (sm->auth_pae_state == AUTH_PAE_CONNECTING) - sm->authEapLogoffsWhileConnecting++; - else if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED) - sm->authAuthEapLogoffWhileAuthenticated++; - } - - SM_ENTRY_MA(AUTH_PAE, DISCONNECTED, auth_pae); - - sm->authPortStatus = Unauthorized; - setPortUnauthorized(); - sm->reAuthCount = 0; - sm->eapolLogoff = FALSE; - if (!from_initialize) { - sm->eapol->cb.finished(sm->hapd, sm->sta, 0, - sm->flags & EAPOL_SM_PREAUTH); - } -} - - -SM_STATE(AUTH_PAE, RESTART) -{ - if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED) { - if (sm->reAuthenticate) - sm->authAuthReauthsWhileAuthenticated++; - if (sm->eapolStart) - sm->authAuthEapStartsWhileAuthenticated++; - if (sm->eapolLogoff) - sm->authAuthEapLogoffWhileAuthenticated++; - } - - SM_ENTRY_MA(AUTH_PAE, RESTART, auth_pae); - - sm->eap_if->eapRestart = TRUE; -} - - -SM_STATE(AUTH_PAE, CONNECTING) -{ - if (sm->auth_pae_state != AUTH_PAE_CONNECTING) - sm->authEntersConnecting++; - - SM_ENTRY_MA(AUTH_PAE, CONNECTING, auth_pae); - - sm->reAuthenticate = FALSE; - sm->reAuthCount++; -} - - -SM_STATE(AUTH_PAE, HELD) -{ - if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authFail) - sm->authAuthFailWhileAuthenticating++; - - SM_ENTRY_MA(AUTH_PAE, HELD, auth_pae); - - sm->authPortStatus = Unauthorized; - setPortUnauthorized(); - sm->quietWhile = sm->quietPeriod; - sm->eapolLogoff = FALSE; - - eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_WARNING, - "authentication failed - EAP type: %d (%s)", - sm->eap_type_authsrv, - eap_type_text(sm->eap_type_authsrv)); - if (sm->eap_type_authsrv != sm->eap_type_supp) { - eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO, - "Supplicant used different EAP type: " - "%d (%s)", sm->eap_type_supp, - eap_type_text(sm->eap_type_supp)); - } - sm->eapol->cb.finished(sm->hapd, sm->sta, 0, - sm->flags & EAPOL_SM_PREAUTH); -} - - -SM_STATE(AUTH_PAE, AUTHENTICATED) -{ - char *extra = ""; - - if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authSuccess) - sm->authAuthSuccessesWhileAuthenticating++; - - SM_ENTRY_MA(AUTH_PAE, AUTHENTICATED, auth_pae); - - sm->authPortStatus = Authorized; - setPortAuthorized(); - sm->reAuthCount = 0; - if (sm->flags & EAPOL_SM_PREAUTH) - extra = " (pre-authentication)"; - else if (wpa_auth_sta_get_pmksa(sm->sta->wpa_sm)) - extra = " (PMKSA cache)"; - eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO, - "authenticated - EAP type: %d (%s)%s", - sm->eap_type_authsrv, - eap_type_text(sm->eap_type_authsrv), extra); - sm->eapol->cb.finished(sm->hapd, sm->sta, 1, - sm->flags & EAPOL_SM_PREAUTH); -} - - -SM_STATE(AUTH_PAE, AUTHENTICATING) -{ - SM_ENTRY_MA(AUTH_PAE, AUTHENTICATING, auth_pae); - - sm->eapolStart = FALSE; - sm->authSuccess = FALSE; - sm->authFail = FALSE; - sm->authTimeout = FALSE; - sm->authStart = TRUE; - sm->keyRun = FALSE; - sm->keyDone = FALSE; -} - - -SM_STATE(AUTH_PAE, ABORTING) -{ - if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING) { - if (sm->authTimeout) - sm->authAuthTimeoutsWhileAuthenticating++; - if (sm->eapolStart) - sm->authAuthEapStartsWhileAuthenticating++; - if (sm->eapolLogoff) - sm->authAuthEapLogoffWhileAuthenticating++; - } - - SM_ENTRY_MA(AUTH_PAE, ABORTING, auth_pae); - - sm->authAbort = TRUE; - sm->keyRun = FALSE; - sm->keyDone = FALSE; -} - - -SM_STATE(AUTH_PAE, FORCE_AUTH) -{ - SM_ENTRY_MA(AUTH_PAE, FORCE_AUTH, auth_pae); - - sm->authPortStatus = Authorized; - setPortAuthorized(); - sm->portMode = ForceAuthorized; - sm->eapolStart = FALSE; - txCannedSuccess(); -} - - -SM_STATE(AUTH_PAE, FORCE_UNAUTH) -{ - SM_ENTRY_MA(AUTH_PAE, FORCE_UNAUTH, auth_pae); - - sm->authPortStatus = Unauthorized; - setPortUnauthorized(); - sm->portMode = ForceUnauthorized; - sm->eapolStart = FALSE; - txCannedFail(); -} - - -SM_STEP(AUTH_PAE) -{ - if ((sm->portControl == Auto && sm->portMode != sm->portControl) || - sm->initialize || !sm->eap_if->portEnabled) - SM_ENTER_GLOBAL(AUTH_PAE, INITIALIZE); - else if (sm->portControl == ForceAuthorized && - sm->portMode != sm->portControl && - !(sm->initialize || !sm->eap_if->portEnabled)) - SM_ENTER_GLOBAL(AUTH_PAE, FORCE_AUTH); - else if (sm->portControl == ForceUnauthorized && - sm->portMode != sm->portControl && - !(sm->initialize || !sm->eap_if->portEnabled)) - SM_ENTER_GLOBAL(AUTH_PAE, FORCE_UNAUTH); - else { - switch (sm->auth_pae_state) { - case AUTH_PAE_INITIALIZE: - SM_ENTER(AUTH_PAE, DISCONNECTED); - break; - case AUTH_PAE_DISCONNECTED: - SM_ENTER(AUTH_PAE, RESTART); - break; - case AUTH_PAE_RESTART: - if (!sm->eap_if->eapRestart) - SM_ENTER(AUTH_PAE, CONNECTING); - break; - case AUTH_PAE_HELD: - if (sm->quietWhile == 0) - SM_ENTER(AUTH_PAE, RESTART); - break; - case AUTH_PAE_CONNECTING: - if (sm->eapolLogoff || sm->reAuthCount > sm->reAuthMax) - SM_ENTER(AUTH_PAE, DISCONNECTED); - else if ((sm->eap_if->eapReq && - sm->reAuthCount <= sm->reAuthMax) || - sm->eap_if->eapSuccess || sm->eap_if->eapFail) - SM_ENTER(AUTH_PAE, AUTHENTICATING); - break; - case AUTH_PAE_AUTHENTICATED: - if (sm->eapolStart || sm->reAuthenticate) - SM_ENTER(AUTH_PAE, RESTART); - else if (sm->eapolLogoff || !sm->portValid) - SM_ENTER(AUTH_PAE, DISCONNECTED); - break; - case AUTH_PAE_AUTHENTICATING: - if (sm->authSuccess && sm->portValid) - SM_ENTER(AUTH_PAE, AUTHENTICATED); - else if (sm->authFail || - (sm->keyDone && !sm->portValid)) - SM_ENTER(AUTH_PAE, HELD); - else if (sm->eapolStart || sm->eapolLogoff || - sm->authTimeout) - SM_ENTER(AUTH_PAE, ABORTING); - break; - case AUTH_PAE_ABORTING: - if (sm->eapolLogoff && !sm->authAbort) - SM_ENTER(AUTH_PAE, DISCONNECTED); - else if (!sm->eapolLogoff && !sm->authAbort) - SM_ENTER(AUTH_PAE, RESTART); - break; - case AUTH_PAE_FORCE_AUTH: - if (sm->eapolStart) - SM_ENTER(AUTH_PAE, FORCE_AUTH); - break; - case AUTH_PAE_FORCE_UNAUTH: - if (sm->eapolStart) - SM_ENTER(AUTH_PAE, FORCE_UNAUTH); - break; - } - } -} - - - -/* Backend Authentication state machine */ - -SM_STATE(BE_AUTH, INITIALIZE) -{ - SM_ENTRY_MA(BE_AUTH, INITIALIZE, be_auth); - - abortAuth(); - sm->eap_if->eapNoReq = FALSE; - sm->authAbort = FALSE; -} - - -SM_STATE(BE_AUTH, REQUEST) -{ - SM_ENTRY_MA(BE_AUTH, REQUEST, be_auth); - - txReq(); - sm->eap_if->eapReq = FALSE; - sm->backendOtherRequestsToSupplicant++; - - /* - * Clearing eapolEap here is not specified in IEEE Std 802.1X-2004, but - * it looks like this would be logical thing to do there since the old - * EAP response would not be valid anymore after the new EAP request - * was sent out. - * - * A race condition has been reported, in which hostapd ended up - * sending out EAP-Response/Identity as a response to the first - * EAP-Request from the main EAP method. This can be avoided by - * clearing eapolEap here. - */ - sm->eapolEap = FALSE; -} - - -SM_STATE(BE_AUTH, RESPONSE) -{ - SM_ENTRY_MA(BE_AUTH, RESPONSE, be_auth); - - sm->authTimeout = FALSE; - sm->eapolEap = FALSE; - sm->eap_if->eapNoReq = FALSE; - sm->aWhile = sm->serverTimeout; - sm->eap_if->eapResp = TRUE; - /* sendRespToServer(); */ - sm->backendResponses++; -} - - -SM_STATE(BE_AUTH, SUCCESS) -{ - SM_ENTRY_MA(BE_AUTH, SUCCESS, be_auth); - - txReq(); - sm->authSuccess = TRUE; - sm->keyRun = TRUE; -} - - -SM_STATE(BE_AUTH, FAIL) -{ - SM_ENTRY_MA(BE_AUTH, FAIL, be_auth); - - txReq(); - sm->authFail = TRUE; -} - - -SM_STATE(BE_AUTH, TIMEOUT) -{ - SM_ENTRY_MA(BE_AUTH, TIMEOUT, be_auth); - - sm->authTimeout = TRUE; -} - - -SM_STATE(BE_AUTH, IDLE) -{ - SM_ENTRY_MA(BE_AUTH, IDLE, be_auth); - - sm->authStart = FALSE; -} - - -SM_STATE(BE_AUTH, IGNORE) -{ - SM_ENTRY_MA(BE_AUTH, IGNORE, be_auth); - - sm->eap_if->eapNoReq = FALSE; -} - - -SM_STEP(BE_AUTH) -{ - if (sm->portControl != Auto || sm->initialize || sm->authAbort) { - SM_ENTER_GLOBAL(BE_AUTH, INITIALIZE); - return; - } - - switch (sm->be_auth_state) { - case BE_AUTH_INITIALIZE: - SM_ENTER(BE_AUTH, IDLE); - break; - case BE_AUTH_REQUEST: - if (sm->eapolEap) - SM_ENTER(BE_AUTH, RESPONSE); - else if (sm->eap_if->eapReq) - SM_ENTER(BE_AUTH, REQUEST); - else if (sm->eap_if->eapTimeout) - SM_ENTER(BE_AUTH, TIMEOUT); - break; - case BE_AUTH_RESPONSE: - if (sm->eap_if->eapNoReq) - SM_ENTER(BE_AUTH, IGNORE); - if (sm->eap_if->eapReq) { - sm->backendAccessChallenges++; - SM_ENTER(BE_AUTH, REQUEST); - } else if (sm->aWhile == 0) - SM_ENTER(BE_AUTH, TIMEOUT); - else if (sm->eap_if->eapFail) { - sm->backendAuthFails++; - SM_ENTER(BE_AUTH, FAIL); - } else if (sm->eap_if->eapSuccess) { - sm->backendAuthSuccesses++; - SM_ENTER(BE_AUTH, SUCCESS); - } - break; - case BE_AUTH_SUCCESS: - SM_ENTER(BE_AUTH, IDLE); - break; - case BE_AUTH_FAIL: - SM_ENTER(BE_AUTH, IDLE); - break; - case BE_AUTH_TIMEOUT: - SM_ENTER(BE_AUTH, IDLE); - break; - case BE_AUTH_IDLE: - if (sm->eap_if->eapFail && sm->authStart) - SM_ENTER(BE_AUTH, FAIL); - else if (sm->eap_if->eapReq && sm->authStart) - SM_ENTER(BE_AUTH, REQUEST); - else if (sm->eap_if->eapSuccess && sm->authStart) - SM_ENTER(BE_AUTH, SUCCESS); - break; - case BE_AUTH_IGNORE: - if (sm->eapolEap) - SM_ENTER(BE_AUTH, RESPONSE); - else if (sm->eap_if->eapReq) - SM_ENTER(BE_AUTH, REQUEST); - else if (sm->eap_if->eapTimeout) - SM_ENTER(BE_AUTH, TIMEOUT); - break; - } -} - - - -/* Reauthentication Timer state machine */ - -SM_STATE(REAUTH_TIMER, INITIALIZE) -{ - SM_ENTRY_MA(REAUTH_TIMER, INITIALIZE, reauth_timer); - - sm->reAuthWhen = sm->reAuthPeriod; -} - - -SM_STATE(REAUTH_TIMER, REAUTHENTICATE) -{ - SM_ENTRY_MA(REAUTH_TIMER, REAUTHENTICATE, reauth_timer); - - sm->reAuthenticate = TRUE; - wpa_auth_sm_event(sm->sta->wpa_sm, WPA_REAUTH_EAPOL); -} - - -SM_STEP(REAUTH_TIMER) -{ - if (sm->portControl != Auto || sm->initialize || - sm->authPortStatus == Unauthorized || !sm->reAuthEnabled) { - SM_ENTER_GLOBAL(REAUTH_TIMER, INITIALIZE); - return; - } - - switch (sm->reauth_timer_state) { - case REAUTH_TIMER_INITIALIZE: - if (sm->reAuthWhen == 0) - SM_ENTER(REAUTH_TIMER, REAUTHENTICATE); - break; - case REAUTH_TIMER_REAUTHENTICATE: - SM_ENTER(REAUTH_TIMER, INITIALIZE); - break; - } -} - - - -/* Authenticator Key Transmit state machine */ - -SM_STATE(AUTH_KEY_TX, NO_KEY_TRANSMIT) -{ - SM_ENTRY_MA(AUTH_KEY_TX, NO_KEY_TRANSMIT, auth_key_tx); -} - - -SM_STATE(AUTH_KEY_TX, KEY_TRANSMIT) -{ - SM_ENTRY_MA(AUTH_KEY_TX, KEY_TRANSMIT, auth_key_tx); - - txKey(); - sm->eap_if->eapKeyAvailable = FALSE; - sm->keyDone = TRUE; -} - - -SM_STEP(AUTH_KEY_TX) -{ - if (sm->initialize || sm->portControl != Auto) { - SM_ENTER_GLOBAL(AUTH_KEY_TX, NO_KEY_TRANSMIT); - return; - } - - switch (sm->auth_key_tx_state) { - case AUTH_KEY_TX_NO_KEY_TRANSMIT: - if (sm->keyTxEnabled && sm->eap_if->eapKeyAvailable && - sm->keyRun && !wpa_auth_sta_wpa_version(sm->sta->wpa_sm)) - SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT); - break; - case AUTH_KEY_TX_KEY_TRANSMIT: - if (!sm->keyTxEnabled || !sm->keyRun) - SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT); - else if (sm->eap_if->eapKeyAvailable) - SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT); - break; - } -} - - - -/* Key Receive state machine */ - -SM_STATE(KEY_RX, NO_KEY_RECEIVE) -{ - SM_ENTRY_MA(KEY_RX, NO_KEY_RECEIVE, key_rx); -} - - -SM_STATE(KEY_RX, KEY_RECEIVE) -{ - SM_ENTRY_MA(KEY_RX, KEY_RECEIVE, key_rx); - - processKey(); - sm->rxKey = FALSE; -} - - -SM_STEP(KEY_RX) -{ - if (sm->initialize || !sm->eap_if->portEnabled) { - SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE); - return; - } - - switch (sm->key_rx_state) { - case KEY_RX_NO_KEY_RECEIVE: - if (sm->rxKey) - SM_ENTER(KEY_RX, KEY_RECEIVE); - break; - case KEY_RX_KEY_RECEIVE: - if (sm->rxKey) - SM_ENTER(KEY_RX, KEY_RECEIVE); - break; - } -} - - - -/* Controlled Directions state machine */ - -SM_STATE(CTRL_DIR, FORCE_BOTH) -{ - SM_ENTRY_MA(CTRL_DIR, FORCE_BOTH, ctrl_dir); - sm->operControlledDirections = Both; -} - - -SM_STATE(CTRL_DIR, IN_OR_BOTH) -{ - SM_ENTRY_MA(CTRL_DIR, IN_OR_BOTH, ctrl_dir); - sm->operControlledDirections = sm->adminControlledDirections; -} - - -SM_STEP(CTRL_DIR) -{ - if (sm->initialize) { - SM_ENTER_GLOBAL(CTRL_DIR, IN_OR_BOTH); - return; - } - - switch (sm->ctrl_dir_state) { - case CTRL_DIR_FORCE_BOTH: - if (sm->eap_if->portEnabled && sm->operEdge) - SM_ENTER(CTRL_DIR, IN_OR_BOTH); - break; - case CTRL_DIR_IN_OR_BOTH: - if (sm->operControlledDirections != - sm->adminControlledDirections) - SM_ENTER(CTRL_DIR, IN_OR_BOTH); - if (!sm->eap_if->portEnabled || !sm->operEdge) - SM_ENTER(CTRL_DIR, FORCE_BOTH); - break; - } -} - - - -struct eapol_state_machine * -eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr, - int preauth, struct sta_info *sta) -{ - struct eapol_state_machine *sm; - struct hostapd_data *hapd; /* TODO: to be removed */ - struct eap_config eap_conf; - - if (eapol == NULL) - return NULL; - hapd = eapol->conf.hapd; - - sm = os_zalloc(sizeof(*sm)); - if (sm == NULL) { - wpa_printf(MSG_DEBUG, "IEEE 802.1X state machine allocation " - "failed"); - return NULL; - } - sm->radius_identifier = -1; - os_memcpy(sm->addr, addr, ETH_ALEN); - if (preauth) - sm->flags |= EAPOL_SM_PREAUTH; - - sm->hapd = hapd; - sm->eapol = eapol; - sm->sta = sta; - - /* Set default values for state machine constants */ - sm->auth_pae_state = AUTH_PAE_INITIALIZE; - sm->quietPeriod = AUTH_PAE_DEFAULT_quietPeriod; - sm->reAuthMax = AUTH_PAE_DEFAULT_reAuthMax; - - sm->be_auth_state = BE_AUTH_INITIALIZE; - sm->serverTimeout = BE_AUTH_DEFAULT_serverTimeout; - - sm->reauth_timer_state = REAUTH_TIMER_INITIALIZE; - sm->reAuthPeriod = eapol->conf.eap_reauth_period; - sm->reAuthEnabled = eapol->conf.eap_reauth_period > 0 ? TRUE : FALSE; - - sm->auth_key_tx_state = AUTH_KEY_TX_NO_KEY_TRANSMIT; - - sm->key_rx_state = KEY_RX_NO_KEY_RECEIVE; - - sm->ctrl_dir_state = CTRL_DIR_IN_OR_BOTH; - - sm->portControl = Auto; - - if (!eapol->conf.wpa && - (hapd->default_wep_key || eapol->conf.individual_wep_key_len > 0)) - sm->keyTxEnabled = TRUE; - else - sm->keyTxEnabled = FALSE; - if (eapol->conf.wpa) - sm->portValid = FALSE; - else - sm->portValid = TRUE; - - os_memset(&eap_conf, 0, sizeof(eap_conf)); - eap_conf.eap_server = eapol->conf.eap_server; - eap_conf.ssl_ctx = eapol->conf.ssl_ctx; - eap_conf.eap_sim_db_priv = eapol->conf.eap_sim_db_priv; - eap_conf.pac_opaque_encr_key = eapol->conf.pac_opaque_encr_key; - eap_conf.eap_fast_a_id = eapol->conf.eap_fast_a_id; - eap_conf.eap_fast_a_id_len = eapol->conf.eap_fast_a_id_len; - eap_conf.eap_fast_a_id_info = eapol->conf.eap_fast_a_id_info; - eap_conf.eap_fast_prov = eapol->conf.eap_fast_prov; - eap_conf.pac_key_lifetime = eapol->conf.pac_key_lifetime; - eap_conf.pac_key_refresh_time = eapol->conf.pac_key_refresh_time; - eap_conf.eap_sim_aka_result_ind = eapol->conf.eap_sim_aka_result_ind; - eap_conf.tnc = eapol->conf.tnc; - eap_conf.wps = eapol->conf.wps; - eap_conf.assoc_wps_ie = sta->wps_ie; - sm->eap = eap_server_sm_init(sm, &eapol_cb, &eap_conf); - if (sm->eap == NULL) { - eapol_auth_free(sm); - return NULL; - } - sm->eap_if = eap_get_interface(sm->eap); - - eapol_auth_initialize(sm); - - return sm; -} - - -void eapol_auth_free(struct eapol_state_machine *sm) -{ - if (sm == NULL) - return; - - eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); - eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL); - if (sm->eap) - eap_server_sm_deinit(sm->eap); - os_free(sm); -} - - -static int eapol_sm_sta_entry_alive(struct eapol_authenticator *eapol, - const u8 *addr) -{ - return eapol->cb.sta_entry_alive(eapol->conf.hapd, addr); -} - - -static void eapol_sm_step_run(struct eapol_state_machine *sm) -{ - struct eapol_authenticator *eapol = sm->eapol; - u8 addr[ETH_ALEN]; - unsigned int prev_auth_pae, prev_be_auth, prev_reauth_timer, - prev_auth_key_tx, prev_key_rx, prev_ctrl_dir; - int max_steps = 100; - - os_memcpy(addr, sm->addr, ETH_ALEN); - - /* - * Allow EAPOL state machines to run as long as there are state - * changes, but exit and return here through event loop if more than - * 100 steps is needed as a precaution against infinite loops inside - * eloop callback. - */ -restart: - prev_auth_pae = sm->auth_pae_state; - prev_be_auth = sm->be_auth_state; - prev_reauth_timer = sm->reauth_timer_state; - prev_auth_key_tx = sm->auth_key_tx_state; - prev_key_rx = sm->key_rx_state; - prev_ctrl_dir = sm->ctrl_dir_state; - - SM_STEP_RUN(AUTH_PAE); - if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) - SM_STEP_RUN(BE_AUTH); - if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) - SM_STEP_RUN(REAUTH_TIMER); - if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) - SM_STEP_RUN(AUTH_KEY_TX); - if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) - SM_STEP_RUN(KEY_RX); - if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) - SM_STEP_RUN(CTRL_DIR); - - if (prev_auth_pae != sm->auth_pae_state || - prev_be_auth != sm->be_auth_state || - prev_reauth_timer != sm->reauth_timer_state || - prev_auth_key_tx != sm->auth_key_tx_state || - prev_key_rx != sm->key_rx_state || - prev_ctrl_dir != sm->ctrl_dir_state) { - if (--max_steps > 0) - goto restart; - /* Re-run from eloop timeout */ - eapol_auth_step(sm); - return; - } - - if (eapol_sm_sta_entry_alive(eapol, addr) && sm->eap) { - if (eap_server_sm_step(sm->eap)) { - if (--max_steps > 0) - goto restart; - /* Re-run from eloop timeout */ - eapol_auth_step(sm); - return; - } - - /* TODO: find a better location for this */ - if (sm->eap_if->aaaEapResp) { - sm->eap_if->aaaEapResp = FALSE; - if (sm->eap_if->aaaEapRespData == NULL) { - wpa_printf(MSG_DEBUG, "EAPOL: aaaEapResp set, " - "but no aaaEapRespData available"); - return; - } - sm->eapol->cb.aaa_send( - sm->hapd, sm->sta, - wpabuf_head(sm->eap_if->aaaEapRespData), - wpabuf_len(sm->eap_if->aaaEapRespData)); - } - } - - if (eapol_sm_sta_entry_alive(eapol, addr)) - wpa_auth_sm_notify(sm->sta->wpa_sm); -} - - -static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx) -{ - struct eapol_state_machine *sm = eloop_ctx; - eapol_sm_step_run(sm); -} - - -/** - * eapol_auth_step - Advance EAPOL state machines - * @sm: EAPOL state machine - * - * This function is called to advance EAPOL state machines after any change - * that could affect their state. - */ -void eapol_auth_step(struct eapol_state_machine *sm) -{ - /* - * Run eapol_sm_step_run from a registered timeout to make sure that - * other possible timeouts/events are processed and to avoid long - * function call chains. - */ - - eloop_register_timeout(0, 0, eapol_sm_step_cb, sm, NULL); -} - - -void eapol_auth_initialize(struct eapol_state_machine *sm) -{ - sm->initializing = TRUE; - /* Initialize the state machines by asserting initialize and then - * deasserting it after one step */ - sm->initialize = TRUE; - eapol_sm_step_run(sm); - sm->initialize = FALSE; - eapol_sm_step_run(sm); - sm->initializing = FALSE; - - /* Start one second tick for port timers state machine */ - eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); - eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm); -} - - -#ifdef HOSTAPD_DUMP_STATE -static inline const char * port_type_txt(PortTypes pt) -{ - switch (pt) { - case ForceUnauthorized: return "ForceUnauthorized"; - case ForceAuthorized: return "ForceAuthorized"; - case Auto: return "Auto"; - default: return "Unknown"; - } -} - - -static inline const char * port_state_txt(PortState ps) -{ - switch (ps) { - case Unauthorized: return "Unauthorized"; - case Authorized: return "Authorized"; - default: return "Unknown"; - } -} - - -static inline const char * ctrl_dir_txt(ControlledDirection dir) -{ - switch (dir) { - case Both: return "Both"; - case In: return "In"; - default: return "Unknown"; - } -} - - -static inline const char * auth_pae_state_txt(int s) -{ - switch (s) { - case AUTH_PAE_INITIALIZE: return "INITIALIZE"; - case AUTH_PAE_DISCONNECTED: return "DISCONNECTED"; - case AUTH_PAE_CONNECTING: return "CONNECTING"; - case AUTH_PAE_AUTHENTICATING: return "AUTHENTICATING"; - case AUTH_PAE_AUTHENTICATED: return "AUTHENTICATED"; - case AUTH_PAE_ABORTING: return "ABORTING"; - case AUTH_PAE_HELD: return "HELD"; - case AUTH_PAE_FORCE_AUTH: return "FORCE_AUTH"; - case AUTH_PAE_FORCE_UNAUTH: return "FORCE_UNAUTH"; - case AUTH_PAE_RESTART: return "RESTART"; - default: return "Unknown"; - } -} - - -static inline const char * be_auth_state_txt(int s) -{ - switch (s) { - case BE_AUTH_REQUEST: return "REQUEST"; - case BE_AUTH_RESPONSE: return "RESPONSE"; - case BE_AUTH_SUCCESS: return "SUCCESS"; - case BE_AUTH_FAIL: return "FAIL"; - case BE_AUTH_TIMEOUT: return "TIMEOUT"; - case BE_AUTH_IDLE: return "IDLE"; - case BE_AUTH_INITIALIZE: return "INITIALIZE"; - case BE_AUTH_IGNORE: return "IGNORE"; - default: return "Unknown"; - } -} - - -static inline const char * reauth_timer_state_txt(int s) -{ - switch (s) { - case REAUTH_TIMER_INITIALIZE: return "INITIALIZE"; - case REAUTH_TIMER_REAUTHENTICATE: return "REAUTHENTICATE"; - default: return "Unknown"; - } -} - - -static inline const char * auth_key_tx_state_txt(int s) -{ - switch (s) { - case AUTH_KEY_TX_NO_KEY_TRANSMIT: return "NO_KEY_TRANSMIT"; - case AUTH_KEY_TX_KEY_TRANSMIT: return "KEY_TRANSMIT"; - default: return "Unknown"; - } -} - - -static inline const char * key_rx_state_txt(int s) -{ - switch (s) { - case KEY_RX_NO_KEY_RECEIVE: return "NO_KEY_RECEIVE"; - case KEY_RX_KEY_RECEIVE: return "KEY_RECEIVE"; - default: return "Unknown"; - } -} - - -static inline const char * ctrl_dir_state_txt(int s) -{ - switch (s) { - case CTRL_DIR_FORCE_BOTH: return "FORCE_BOTH"; - case CTRL_DIR_IN_OR_BOTH: return "IN_OR_BOTH"; - default: return "Unknown"; - } -} - - -void eapol_auth_dump_state(FILE *f, const char *prefix, - struct eapol_state_machine *sm) -{ - fprintf(f, "%sEAPOL state machine:\n", prefix); - fprintf(f, "%s aWhile=%d quietWhile=%d reAuthWhen=%d\n", prefix, - sm->aWhile, sm->quietWhile, sm->reAuthWhen); -#define _SB(b) ((b) ? "TRUE" : "FALSE") - fprintf(f, - "%s authAbort=%s authFail=%s authPortStatus=%s authStart=%s\n" - "%s authTimeout=%s authSuccess=%s eapFail=%s eapolEap=%s\n" - "%s eapSuccess=%s eapTimeout=%s initialize=%s " - "keyAvailable=%s\n" - "%s keyDone=%s keyRun=%s keyTxEnabled=%s portControl=%s\n" - "%s portEnabled=%s portValid=%s reAuthenticate=%s\n", - prefix, _SB(sm->authAbort), _SB(sm->authFail), - port_state_txt(sm->authPortStatus), _SB(sm->authStart), - prefix, _SB(sm->authTimeout), _SB(sm->authSuccess), - _SB(sm->eap_if->eapFail), _SB(sm->eapolEap), - prefix, _SB(sm->eap_if->eapSuccess), - _SB(sm->eap_if->eapTimeout), - _SB(sm->initialize), _SB(sm->eap_if->eapKeyAvailable), - prefix, _SB(sm->keyDone), _SB(sm->keyRun), - _SB(sm->keyTxEnabled), port_type_txt(sm->portControl), - prefix, _SB(sm->eap_if->portEnabled), _SB(sm->portValid), - _SB(sm->reAuthenticate)); - - fprintf(f, "%s Authenticator PAE:\n" - "%s state=%s\n" - "%s eapolLogoff=%s eapolStart=%s eapRestart=%s\n" - "%s portMode=%s reAuthCount=%d\n" - "%s quietPeriod=%d reAuthMax=%d\n" - "%s authEntersConnecting=%d\n" - "%s authEapLogoffsWhileConnecting=%d\n" - "%s authEntersAuthenticating=%d\n" - "%s authAuthSuccessesWhileAuthenticating=%d\n" - "%s authAuthTimeoutsWhileAuthenticating=%d\n" - "%s authAuthFailWhileAuthenticating=%d\n" - "%s authAuthEapStartsWhileAuthenticating=%d\n" - "%s authAuthEapLogoffWhileAuthenticating=%d\n" - "%s authAuthReauthsWhileAuthenticated=%d\n" - "%s authAuthEapStartsWhileAuthenticated=%d\n" - "%s authAuthEapLogoffWhileAuthenticated=%d\n", - prefix, prefix, auth_pae_state_txt(sm->auth_pae_state), prefix, - _SB(sm->eapolLogoff), _SB(sm->eapolStart), - _SB(sm->eap_if->eapRestart), - prefix, port_type_txt(sm->portMode), sm->reAuthCount, - prefix, sm->quietPeriod, sm->reAuthMax, - prefix, sm->authEntersConnecting, - prefix, sm->authEapLogoffsWhileConnecting, - prefix, sm->authEntersAuthenticating, - prefix, sm->authAuthSuccessesWhileAuthenticating, - prefix, sm->authAuthTimeoutsWhileAuthenticating, - prefix, sm->authAuthFailWhileAuthenticating, - prefix, sm->authAuthEapStartsWhileAuthenticating, - prefix, sm->authAuthEapLogoffWhileAuthenticating, - prefix, sm->authAuthReauthsWhileAuthenticated, - prefix, sm->authAuthEapStartsWhileAuthenticated, - prefix, sm->authAuthEapLogoffWhileAuthenticated); - - fprintf(f, "%s Backend Authentication:\n" - "%s state=%s\n" - "%s eapNoReq=%s eapReq=%s eapResp=%s\n" - "%s serverTimeout=%d\n" - "%s backendResponses=%d\n" - "%s backendAccessChallenges=%d\n" - "%s backendOtherRequestsToSupplicant=%d\n" - "%s backendAuthSuccesses=%d\n" - "%s backendAuthFails=%d\n", - prefix, prefix, - be_auth_state_txt(sm->be_auth_state), - prefix, _SB(sm->eap_if->eapNoReq), _SB(sm->eap_if->eapReq), - _SB(sm->eap_if->eapResp), - prefix, sm->serverTimeout, - prefix, sm->backendResponses, - prefix, sm->backendAccessChallenges, - prefix, sm->backendOtherRequestsToSupplicant, - prefix, sm->backendAuthSuccesses, - prefix, sm->backendAuthFails); - - fprintf(f, "%s Reauthentication Timer:\n" - "%s state=%s\n" - "%s reAuthPeriod=%d reAuthEnabled=%s\n", prefix, prefix, - reauth_timer_state_txt(sm->reauth_timer_state), prefix, - sm->reAuthPeriod, _SB(sm->reAuthEnabled)); - - fprintf(f, "%s Authenticator Key Transmit:\n" - "%s state=%s\n", prefix, prefix, - auth_key_tx_state_txt(sm->auth_key_tx_state)); - - fprintf(f, "%s Key Receive:\n" - "%s state=%s\n" - "%s rxKey=%s\n", prefix, prefix, - key_rx_state_txt(sm->key_rx_state), prefix, _SB(sm->rxKey)); - - fprintf(f, "%s Controlled Directions:\n" - "%s state=%s\n" - "%s adminControlledDirections=%s " - "operControlledDirections=%s\n" - "%s operEdge=%s\n", prefix, prefix, - ctrl_dir_state_txt(sm->ctrl_dir_state), - prefix, ctrl_dir_txt(sm->adminControlledDirections), - ctrl_dir_txt(sm->operControlledDirections), - prefix, _SB(sm->operEdge)); -#undef _SB -} -#endif /* HOSTAPD_DUMP_STATE */ - - -static int eapol_sm_get_eap_user(void *ctx, const u8 *identity, - size_t identity_len, int phase2, - struct eap_user *user) -{ - struct eapol_state_machine *sm = ctx; - return sm->eapol->cb.get_eap_user(sm->hapd, identity, identity_len, - phase2, user); -} - - -static const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len) -{ - struct eapol_state_machine *sm = ctx; - *len = sm->eapol->conf.eap_req_id_text_len; - return sm->eapol->conf.eap_req_id_text; -} - - -static struct eapol_callbacks eapol_cb = -{ - .get_eap_user = eapol_sm_get_eap_user, - .get_eap_req_id_text = eapol_sm_get_eap_req_id_text, -}; - - -int eapol_auth_eap_pending_cb(struct eapol_state_machine *sm, void *ctx) -{ - if (sm == NULL || ctx != sm->eap) - return -1; - - eap_sm_pending_cb(sm->eap); - eapol_auth_step(sm); - - return 0; -} - - -static int eapol_auth_conf_clone(struct eapol_auth_config *dst, - struct eapol_auth_config *src) -{ - dst->hapd = src->hapd; - dst->eap_reauth_period = src->eap_reauth_period; - dst->wpa = src->wpa; - dst->individual_wep_key_len = src->individual_wep_key_len; - dst->eap_server = src->eap_server; - dst->ssl_ctx = src->ssl_ctx; - dst->eap_sim_db_priv = src->eap_sim_db_priv; - os_free(dst->eap_req_id_text); - if (src->eap_req_id_text) { - dst->eap_req_id_text = os_malloc(src->eap_req_id_text_len); - if (dst->eap_req_id_text == NULL) - return -1; - os_memcpy(dst->eap_req_id_text, src->eap_req_id_text, - src->eap_req_id_text_len); - dst->eap_req_id_text_len = src->eap_req_id_text_len; - } else { - dst->eap_req_id_text = NULL; - dst->eap_req_id_text_len = 0; - } - if (src->pac_opaque_encr_key) { - dst->pac_opaque_encr_key = os_malloc(16); - os_memcpy(dst->pac_opaque_encr_key, src->pac_opaque_encr_key, - 16); - } else - dst->pac_opaque_encr_key = NULL; - if (src->eap_fast_a_id) { - dst->eap_fast_a_id = os_malloc(src->eap_fast_a_id_len); - if (dst->eap_fast_a_id == NULL) { - os_free(dst->eap_req_id_text); - return -1; - } - os_memcpy(dst->eap_fast_a_id, src->eap_fast_a_id, - src->eap_fast_a_id_len); - dst->eap_fast_a_id_len = src->eap_fast_a_id_len; - } else - dst->eap_fast_a_id = NULL; - if (src->eap_fast_a_id_info) { - dst->eap_fast_a_id_info = os_strdup(src->eap_fast_a_id_info); - if (dst->eap_fast_a_id_info == NULL) { - os_free(dst->eap_req_id_text); - os_free(dst->eap_fast_a_id); - return -1; - } - } else - dst->eap_fast_a_id_info = NULL; - dst->eap_fast_prov = src->eap_fast_prov; - dst->pac_key_lifetime = src->pac_key_lifetime; - dst->pac_key_refresh_time = src->pac_key_refresh_time; - dst->eap_sim_aka_result_ind = src->eap_sim_aka_result_ind; - dst->tnc = src->tnc; - dst->wps = src->wps; - return 0; -} - - -static void eapol_auth_conf_free(struct eapol_auth_config *conf) -{ - os_free(conf->eap_req_id_text); - conf->eap_req_id_text = NULL; - os_free(conf->pac_opaque_encr_key); - conf->pac_opaque_encr_key = NULL; - os_free(conf->eap_fast_a_id); - conf->eap_fast_a_id = NULL; - os_free(conf->eap_fast_a_id_info); - conf->eap_fast_a_id_info = NULL; -} - - -struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf, - struct eapol_auth_cb *cb) -{ - struct eapol_authenticator *eapol; - - eapol = os_zalloc(sizeof(*eapol)); - if (eapol == NULL) - return NULL; - - if (eapol_auth_conf_clone(&eapol->conf, conf) < 0) { - os_free(eapol); - return NULL; - } - - eapol->cb.eapol_send = cb->eapol_send; - eapol->cb.aaa_send = cb->aaa_send; - eapol->cb.finished = cb->finished; - eapol->cb.get_eap_user = cb->get_eap_user; - eapol->cb.sta_entry_alive = cb->sta_entry_alive; - eapol->cb.logger = cb->logger; - eapol->cb.set_port_authorized = cb->set_port_authorized; - eapol->cb.abort_auth = cb->abort_auth; - eapol->cb.tx_key = cb->tx_key; - - return eapol; -} - - -void eapol_auth_deinit(struct eapol_authenticator *eapol) -{ - if (eapol == NULL) - return; - - eapol_auth_conf_free(&eapol->conf); - os_free(eapol); -} diff --git a/contrib/hostapd/hostapd/eapol_sm.h b/contrib/hostapd/hostapd/eapol_sm.h deleted file mode 100644 index 7a13e8e7c0..0000000000 --- a/contrib/hostapd/hostapd/eapol_sm.h +++ /dev/null @@ -1,260 +0,0 @@ -/* - * hostapd / IEEE 802.1X-2004 Authenticator - EAPOL state machine - * Copyright (c) 2002-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAPOL_SM_H -#define EAPOL_SM_H - -#include "defs.h" - -/* IEEE Std 802.1X-2004, Ch. 8.2 */ - -typedef enum { ForceUnauthorized = 1, ForceAuthorized = 3, Auto = 2 } - PortTypes; -typedef enum { Unauthorized = 2, Authorized = 1 } PortState; -typedef enum { Both = 0, In = 1 } ControlledDirection; -typedef unsigned int Counter; - -struct eap_sm; - -struct radius_attr_data { - u8 *data; - size_t len; -}; - -struct radius_class_data { - struct radius_attr_data *attr; - size_t count; -}; - - -struct eapol_auth_config { - int eap_reauth_period; - int wpa; - int individual_wep_key_len; - int eap_server; - void *ssl_ctx; - void *eap_sim_db_priv; - char *eap_req_id_text; /* a copy of this will be allocated */ - size_t eap_req_id_text_len; - u8 *pac_opaque_encr_key; - u8 *eap_fast_a_id; - size_t eap_fast_a_id_len; - char *eap_fast_a_id_info; - int eap_fast_prov; - int pac_key_lifetime; - int pac_key_refresh_time; - int eap_sim_aka_result_ind; - int tnc; - struct wps_context *wps; - - /* - * Pointer to hostapd data. This is a temporary workaround for - * transition phase and will be removed once IEEE 802.1X/EAPOL code is - * separated more cleanly from rest of hostapd. - */ - struct hostapd_data *hapd; -}; - -struct eap_user; - -typedef enum { - EAPOL_LOGGER_DEBUG, EAPOL_LOGGER_INFO, EAPOL_LOGGER_WARNING -} eapol_logger_level; - -struct eapol_auth_cb { - void (*eapol_send)(void *ctx, void *sta_ctx, u8 type, const u8 *data, - size_t datalen); - void (*aaa_send)(void *ctx, void *sta_ctx, const u8 *data, - size_t datalen); - void (*finished)(void *ctx, void *sta_ctx, int success, int preauth); - int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len, - int phase2, struct eap_user *user); - int (*sta_entry_alive)(void *ctx, const u8 *addr); - void (*logger)(void *ctx, const u8 *addr, eapol_logger_level level, - const char *txt); - void (*set_port_authorized)(void *ctx, void *sta_ctx, int authorized); - void (*abort_auth)(void *ctx, void *sta_ctx); - void (*tx_key)(void *ctx, void *sta_ctx); -}; - -/** - * struct eapol_authenticator - Global EAPOL authenticator data - */ -struct eapol_authenticator { - struct eapol_auth_config conf; - struct eapol_auth_cb cb; -}; - - -/** - * struct eapol_state_machine - Per-Supplicant Authenticator state machines - */ -struct eapol_state_machine { - /* timers */ - int aWhile; - int quietWhile; - int reAuthWhen; - - /* global variables */ - Boolean authAbort; - Boolean authFail; - PortState authPortStatus; - Boolean authStart; - Boolean authTimeout; - Boolean authSuccess; - Boolean eapolEap; - Boolean initialize; - Boolean keyDone; - Boolean keyRun; - Boolean keyTxEnabled; - PortTypes portControl; - Boolean portValid; - Boolean reAuthenticate; - - /* Port Timers state machine */ - /* 'Boolean tick' implicitly handled as registered timeout */ - - /* Authenticator PAE state machine */ - enum { AUTH_PAE_INITIALIZE, AUTH_PAE_DISCONNECTED, AUTH_PAE_CONNECTING, - AUTH_PAE_AUTHENTICATING, AUTH_PAE_AUTHENTICATED, - AUTH_PAE_ABORTING, AUTH_PAE_HELD, AUTH_PAE_FORCE_AUTH, - AUTH_PAE_FORCE_UNAUTH, AUTH_PAE_RESTART } auth_pae_state; - /* variables */ - Boolean eapolLogoff; - Boolean eapolStart; - PortTypes portMode; - unsigned int reAuthCount; - /* constants */ - unsigned int quietPeriod; /* default 60; 0..65535 */ -#define AUTH_PAE_DEFAULT_quietPeriod 60 - unsigned int reAuthMax; /* default 2 */ -#define AUTH_PAE_DEFAULT_reAuthMax 2 - /* counters */ - Counter authEntersConnecting; - Counter authEapLogoffsWhileConnecting; - Counter authEntersAuthenticating; - Counter authAuthSuccessesWhileAuthenticating; - Counter authAuthTimeoutsWhileAuthenticating; - Counter authAuthFailWhileAuthenticating; - Counter authAuthEapStartsWhileAuthenticating; - Counter authAuthEapLogoffWhileAuthenticating; - Counter authAuthReauthsWhileAuthenticated; - Counter authAuthEapStartsWhileAuthenticated; - Counter authAuthEapLogoffWhileAuthenticated; - - /* Backend Authentication state machine */ - enum { BE_AUTH_REQUEST, BE_AUTH_RESPONSE, BE_AUTH_SUCCESS, - BE_AUTH_FAIL, BE_AUTH_TIMEOUT, BE_AUTH_IDLE, BE_AUTH_INITIALIZE, - BE_AUTH_IGNORE - } be_auth_state; - /* constants */ - unsigned int serverTimeout; /* default 30; 1..X */ -#define BE_AUTH_DEFAULT_serverTimeout 30 - /* counters */ - Counter backendResponses; - Counter backendAccessChallenges; - Counter backendOtherRequestsToSupplicant; - Counter backendAuthSuccesses; - Counter backendAuthFails; - - /* Reauthentication Timer state machine */ - enum { REAUTH_TIMER_INITIALIZE, REAUTH_TIMER_REAUTHENTICATE - } reauth_timer_state; - /* constants */ - unsigned int reAuthPeriod; /* default 3600 s */ - Boolean reAuthEnabled; - - /* Authenticator Key Transmit state machine */ - enum { AUTH_KEY_TX_NO_KEY_TRANSMIT, AUTH_KEY_TX_KEY_TRANSMIT - } auth_key_tx_state; - - /* Key Receive state machine */ - enum { KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE } key_rx_state; - /* variables */ - Boolean rxKey; - - /* Controlled Directions state machine */ - enum { CTRL_DIR_FORCE_BOTH, CTRL_DIR_IN_OR_BOTH } ctrl_dir_state; - /* variables */ - ControlledDirection adminControlledDirections; - ControlledDirection operControlledDirections; - Boolean operEdge; - - /* Authenticator Statistics Table */ - Counter dot1xAuthEapolFramesRx; - Counter dot1xAuthEapolFramesTx; - Counter dot1xAuthEapolStartFramesRx; - Counter dot1xAuthEapolLogoffFramesRx; - Counter dot1xAuthEapolRespIdFramesRx; - Counter dot1xAuthEapolRespFramesRx; - Counter dot1xAuthEapolReqIdFramesTx; - Counter dot1xAuthEapolReqFramesTx; - Counter dot1xAuthInvalidEapolFramesRx; - Counter dot1xAuthEapLengthErrorFramesRx; - Counter dot1xAuthLastEapolFrameVersion; - - /* Other variables - not defined in IEEE 802.1X */ - u8 addr[ETH_ALEN]; /* Supplicant address */ -#define EAPOL_SM_PREAUTH BIT(0) -#define EAPOL_SM_WAIT_START BIT(1) - int flags; /* EAPOL_SM_* */ - - /* EAPOL/AAA <-> EAP full authenticator interface */ - struct eap_eapol_interface *eap_if; - - int radius_identifier; - /* TODO: check when the last messages can be released */ - struct radius_msg *last_recv_radius; - u8 last_eap_id; /* last used EAP Identifier */ - u8 *identity; - size_t identity_len; - u8 eap_type_authsrv; /* EAP type of the last EAP packet from - * Authentication server */ - u8 eap_type_supp; /* EAP type of the last EAP packet from Supplicant */ - struct radius_class_data radius_class; - - /* Keys for encrypting and signing EAPOL-Key frames */ - u8 *eapol_key_sign; - size_t eapol_key_sign_len; - u8 *eapol_key_crypt; - size_t eapol_key_crypt_len; - - struct eap_sm *eap; - - Boolean initializing; /* in process of initializing state machines */ - Boolean changed; - - struct eapol_authenticator *eapol; - - /* Somewhat nasty pointers to global hostapd and STA data to avoid - * passing these to every function */ - struct hostapd_data *hapd; - struct sta_info *sta; -}; - - -struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf, - struct eapol_auth_cb *cb); -void eapol_auth_deinit(struct eapol_authenticator *eapol); -struct eapol_state_machine * -eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr, - int preauth, struct sta_info *sta); -void eapol_auth_free(struct eapol_state_machine *sm); -void eapol_auth_step(struct eapol_state_machine *sm); -void eapol_auth_initialize(struct eapol_state_machine *sm); -void eapol_auth_dump_state(FILE *f, const char *prefix, - struct eapol_state_machine *sm); -int eapol_auth_eap_pending_cb(struct eapol_state_machine *sm, void *ctx); - -#endif /* EAPOL_SM_H */ diff --git a/contrib/hostapd/hostapd/hostap_common.h b/contrib/hostapd/hostapd/hostap_common.h deleted file mode 100644 index 5a57dca46d..0000000000 --- a/contrib/hostapd/hostapd/hostap_common.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * hostapd / Kernel driver communication with Linux Host AP driver - * Copyright (c) 2002-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef HOSTAP_COMMON_H -#define HOSTAP_COMMON_H - -/* netdevice private ioctls (used, e.g., with iwpriv from user space) */ - -/* New wireless extensions API - SET/GET convention (even ioctl numbers are - * root only) - */ -#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0) -#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1) -#define PRISM2_IOCTL_WRITEMIF (SIOCIWFIRSTPRIV + 2) -#define PRISM2_IOCTL_READMIF (SIOCIWFIRSTPRIV + 3) -#define PRISM2_IOCTL_MONITOR (SIOCIWFIRSTPRIV + 4) -#define PRISM2_IOCTL_RESET (SIOCIWFIRSTPRIV + 6) -#define PRISM2_IOCTL_INQUIRE (SIOCIWFIRSTPRIV + 8) -#define PRISM2_IOCTL_WDS_ADD (SIOCIWFIRSTPRIV + 10) -#define PRISM2_IOCTL_WDS_DEL (SIOCIWFIRSTPRIV + 12) -#define PRISM2_IOCTL_SET_RID_WORD (SIOCIWFIRSTPRIV + 14) -#define PRISM2_IOCTL_MACCMD (SIOCIWFIRSTPRIV + 16) -#define PRISM2_IOCTL_ADDMAC (SIOCIWFIRSTPRIV + 18) -#define PRISM2_IOCTL_DELMAC (SIOCIWFIRSTPRIV + 20) -#define PRISM2_IOCTL_KICKMAC (SIOCIWFIRSTPRIV + 22) - -/* following are not in SIOCGIWPRIV list; check permission in the driver code - */ -#define PRISM2_IOCTL_DOWNLOAD (SIOCDEVPRIVATE + 13) -#define PRISM2_IOCTL_HOSTAPD (SIOCDEVPRIVATE + 14) - - -/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes: */ -enum { - /* PRISM2_PARAM_PTYPE = 1, */ /* REMOVED 2003-10-22 */ - PRISM2_PARAM_TXRATECTRL = 2, - PRISM2_PARAM_BEACON_INT = 3, - PRISM2_PARAM_PSEUDO_IBSS = 4, - PRISM2_PARAM_ALC = 5, - /* PRISM2_PARAM_TXPOWER = 6, */ /* REMOVED 2003-10-22 */ - PRISM2_PARAM_DUMP = 7, - PRISM2_PARAM_OTHER_AP_POLICY = 8, - PRISM2_PARAM_AP_MAX_INACTIVITY = 9, - PRISM2_PARAM_AP_BRIDGE_PACKETS = 10, - PRISM2_PARAM_DTIM_PERIOD = 11, - PRISM2_PARAM_AP_NULLFUNC_ACK = 12, - PRISM2_PARAM_MAX_WDS = 13, - PRISM2_PARAM_AP_AUTOM_AP_WDS = 14, - PRISM2_PARAM_AP_AUTH_ALGS = 15, - PRISM2_PARAM_MONITOR_ALLOW_FCSERR = 16, - PRISM2_PARAM_HOST_ENCRYPT = 17, - PRISM2_PARAM_HOST_DECRYPT = 18, - PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX = 19, - PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX = 20, - PRISM2_PARAM_HOST_ROAMING = 21, - PRISM2_PARAM_BCRX_STA_KEY = 22, - PRISM2_PARAM_IEEE_802_1X = 23, - PRISM2_PARAM_ANTSEL_TX = 24, - PRISM2_PARAM_ANTSEL_RX = 25, - PRISM2_PARAM_MONITOR_TYPE = 26, - PRISM2_PARAM_WDS_TYPE = 27, - PRISM2_PARAM_HOSTSCAN = 28, - PRISM2_PARAM_AP_SCAN = 29, - PRISM2_PARAM_ENH_SEC = 30, - PRISM2_PARAM_IO_DEBUG = 31, - PRISM2_PARAM_BASIC_RATES = 32, - PRISM2_PARAM_OPER_RATES = 33, - PRISM2_PARAM_HOSTAPD = 34, - PRISM2_PARAM_HOSTAPD_STA = 35, - PRISM2_PARAM_WPA = 36, - PRISM2_PARAM_PRIVACY_INVOKED = 37, - PRISM2_PARAM_TKIP_COUNTERMEASURES = 38, - PRISM2_PARAM_DROP_UNENCRYPTED = 39, - PRISM2_PARAM_SCAN_CHANNEL_MASK = 40, -}; - -enum { HOSTAP_ANTSEL_DO_NOT_TOUCH = 0, HOSTAP_ANTSEL_DIVERSITY = 1, - HOSTAP_ANTSEL_LOW = 2, HOSTAP_ANTSEL_HIGH = 3 }; - - -/* PRISM2_IOCTL_MACCMD ioctl() subcommands: */ -enum { AP_MAC_CMD_POLICY_OPEN = 0, AP_MAC_CMD_POLICY_ALLOW = 1, - AP_MAC_CMD_POLICY_DENY = 2, AP_MAC_CMD_FLUSH = 3, - AP_MAC_CMD_KICKALL = 4 }; - - -/* PRISM2_IOCTL_DOWNLOAD ioctl() dl_cmd: */ -enum { - PRISM2_DOWNLOAD_VOLATILE = 1 /* RAM */, - /* Note! Old versions of prism2_srec have a fatal error in CRC-16 - * calculation, which will corrupt all non-volatile downloads. - * PRISM2_DOWNLOAD_NON_VOLATILE used to be 2, but it is now 3 to - * prevent use of old versions of prism2_srec for non-volatile - * download. */ - PRISM2_DOWNLOAD_NON_VOLATILE = 3 /* FLASH */, - PRISM2_DOWNLOAD_VOLATILE_GENESIS = 4 /* RAM in Genesis mode */, - /* Persistent versions of volatile download commands (keep firmware - * data in memory and automatically re-download after hw_reset */ - PRISM2_DOWNLOAD_VOLATILE_PERSISTENT = 5, - PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT = 6, -}; - -struct prism2_download_param { - u32 dl_cmd; - u32 start_addr; - u32 num_areas; - struct prism2_download_area { - u32 addr; /* wlan card address */ - u32 len; - caddr_t ptr; /* pointer to data in user space */ - } data[0]; -}; - -#define PRISM2_MAX_DOWNLOAD_AREA_LEN 131072 -#define PRISM2_MAX_DOWNLOAD_LEN 262144 - - -/* PRISM2_IOCTL_HOSTAPD ioctl() cmd: */ -enum { - PRISM2_HOSTAPD_FLUSH = 1, - PRISM2_HOSTAPD_ADD_STA = 2, - PRISM2_HOSTAPD_REMOVE_STA = 3, - PRISM2_HOSTAPD_GET_INFO_STA = 4, - /* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */ - PRISM2_SET_ENCRYPTION = 6, - PRISM2_GET_ENCRYPTION = 7, - PRISM2_HOSTAPD_SET_FLAGS_STA = 8, - PRISM2_HOSTAPD_GET_RID = 9, - PRISM2_HOSTAPD_SET_RID = 10, - PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR = 11, - PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12, - PRISM2_HOSTAPD_MLME = 13, - PRISM2_HOSTAPD_SCAN_REQ = 14, - PRISM2_HOSTAPD_STA_CLEAR_STATS = 15, -}; - -#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024 -#define PRISM2_HOSTAPD_RID_HDR_LEN \ -((size_t) (&((struct prism2_hostapd_param *) 0)->u.rid.data)) -#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \ -((size_t) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data)) - -/* Maximum length for algorithm names (-1 for nul termination) used in ioctl() - */ -#define HOSTAP_CRYPT_ALG_NAME_LEN 16 - - -struct prism2_hostapd_param { - u32 cmd; - u8 sta_addr[ETH_ALEN]; - union { - struct { - u16 aid; - u16 capability; - u8 tx_supp_rates; - } add_sta; - struct { - u32 inactive_sec; - } get_info_sta; - struct { - u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN]; - u32 flags; - u32 err; - u8 idx; - u8 seq[8]; /* sequence counter (set: RX, get: TX) */ - u16 key_len; - u8 key[0]; - } crypt; - struct { - u32 flags_and; - u32 flags_or; - } set_flags_sta; - struct { - u16 rid; - u16 len; - u8 data[0]; - } rid; - struct { - u8 len; - u8 data[0]; - } generic_elem; - struct { -#define MLME_STA_DEAUTH 0 -#define MLME_STA_DISASSOC 1 - u16 cmd; - u16 reason_code; - } mlme; - struct { - u8 ssid_len; - u8 ssid[32]; - } scan_req; - } u; -}; - -#define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT(0) -#define HOSTAP_CRYPT_FLAG_PERMANENT BIT(1) - -#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2 -#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3 -#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4 -#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5 -#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6 -#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7 - -#endif /* HOSTAP_COMMON_H */ diff --git a/contrib/hostapd/hostapd/hostapd.c b/contrib/hostapd/hostapd/hostapd.c deleted file mode 100644 index 3fbd3d0b03..0000000000 --- a/contrib/hostapd/hostapd/hostapd.c +++ /dev/null @@ -1,2039 +0,0 @@ -/* - * hostapd / Initialization and configuration - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#ifndef CONFIG_NATIVE_WINDOWS -#include -#endif /* CONFIG_NATIVE_WINDOWS */ - -#include "eloop.h" -#include "hostapd.h" -#include "ieee802_1x.h" -#include "ieee802_11.h" -#include "beacon.h" -#include "hw_features.h" -#include "accounting.h" -#include "eapol_sm.h" -#include "iapp.h" -#include "ap.h" -#include "ieee802_11_auth.h" -#include "ap_list.h" -#include "sta_info.h" -#include "driver.h" -#include "radius/radius_client.h" -#include "radius/radius_server.h" -#include "wpa.h" -#include "preauth.h" -#include "wme.h" -#include "vlan_init.h" -#include "ctrl_iface.h" -#include "tls.h" -#include "eap_server/eap_sim_db.h" -#include "eap_server/eap.h" -#include "eap_server/tncs.h" -#include "version.h" -#include "l2_packet/l2_packet.h" -#include "wps_hostapd.h" - - -static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity, - size_t identity_len, int phase2, - struct eap_user *user); -static int hostapd_flush_old_stations(struct hostapd_data *hapd); -static int hostapd_setup_wpa(struct hostapd_data *hapd); -static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd); - -struct hapd_interfaces { - size_t count; - struct hostapd_iface **iface; -}; - -unsigned char rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; - - -extern int wpa_debug_level; -extern int wpa_debug_show_keys; -extern int wpa_debug_timestamp; - - -static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module, - int level, const char *txt, size_t len) -{ - struct hostapd_data *hapd = ctx; - char *format, *module_str; - int maxlen; - int conf_syslog_level, conf_stdout_level; - unsigned int conf_syslog, conf_stdout; - - maxlen = len + 100; - format = os_malloc(maxlen); - if (!format) - return; - - if (hapd && hapd->conf) { - conf_syslog_level = hapd->conf->logger_syslog_level; - conf_stdout_level = hapd->conf->logger_stdout_level; - conf_syslog = hapd->conf->logger_syslog; - conf_stdout = hapd->conf->logger_stdout; - } else { - conf_syslog_level = conf_stdout_level = 0; - conf_syslog = conf_stdout = (unsigned int) -1; - } - - switch (module) { - case HOSTAPD_MODULE_IEEE80211: - module_str = "IEEE 802.11"; - break; - case HOSTAPD_MODULE_IEEE8021X: - module_str = "IEEE 802.1X"; - break; - case HOSTAPD_MODULE_RADIUS: - module_str = "RADIUS"; - break; - case HOSTAPD_MODULE_WPA: - module_str = "WPA"; - break; - case HOSTAPD_MODULE_DRIVER: - module_str = "DRIVER"; - break; - case HOSTAPD_MODULE_IAPP: - module_str = "IAPP"; - break; - case HOSTAPD_MODULE_MLME: - module_str = "MLME"; - break; - default: - module_str = NULL; - break; - } - - if (hapd && hapd->conf && addr) - os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s", - hapd->conf->iface, MAC2STR(addr), - module_str ? " " : "", module_str, txt); - else if (hapd && hapd->conf) - os_snprintf(format, maxlen, "%s:%s%s %s", - hapd->conf->iface, module_str ? " " : "", - module_str, txt); - else if (addr) - os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s", - MAC2STR(addr), module_str ? " " : "", - module_str, txt); - else - os_snprintf(format, maxlen, "%s%s%s", - module_str, module_str ? ": " : "", txt); - - if ((conf_stdout & module) && level >= conf_stdout_level) { - wpa_debug_print_timestamp(); - printf("%s\n", format); - } - -#ifndef CONFIG_NATIVE_WINDOWS - if ((conf_syslog & module) && level >= conf_syslog_level) { - int priority; - switch (level) { - case HOSTAPD_LEVEL_DEBUG_VERBOSE: - case HOSTAPD_LEVEL_DEBUG: - priority = LOG_DEBUG; - break; - case HOSTAPD_LEVEL_INFO: - priority = LOG_INFO; - break; - case HOSTAPD_LEVEL_NOTICE: - priority = LOG_NOTICE; - break; - case HOSTAPD_LEVEL_WARNING: - priority = LOG_WARNING; - break; - default: - priority = LOG_INFO; - break; - } - syslog(priority, "%s", format); - } -#endif /* CONFIG_NATIVE_WINDOWS */ - - os_free(format); -} - - -static void hostapd_deauth_all_stas(struct hostapd_data *hapd) -{ - u8 addr[ETH_ALEN]; - - /* New Prism2.5/3 STA firmware versions seem to have issues with this - * broadcast deauth frame. This gets the firmware in odd state where - * nothing works correctly, so let's skip sending this for the hostap - * driver. */ - - if (hapd->driver && os_strcmp(hapd->driver->name, "hostap") != 0) { - os_memset(addr, 0xff, ETH_ALEN); - hostapd_sta_deauth(hapd, addr, - WLAN_REASON_PREV_AUTH_NOT_VALID); - } -} - - -/** - * hostapd_prune_associations - Remove extraneous associations - * @hapd: Pointer to BSS data for the most recent association - * @sta: Pointer to the associated STA data - * - * This function looks through all radios and BSS's for previous - * (stale) associations of STA. If any are found they are removed. - */ -static void hostapd_prune_associations(struct hostapd_data *hapd, - struct sta_info *sta) -{ - struct sta_info *osta; - struct hostapd_data *ohapd; - size_t i, j; - struct hapd_interfaces *interfaces = eloop_get_user_data(); - - for (i = 0; i < interfaces->count; i++) { - for (j = 0; j < interfaces->iface[i]->num_bss; j++) { - ohapd = interfaces->iface[i]->bss[j]; - if (ohapd == hapd) - continue; - osta = ap_get_sta(ohapd, sta->addr); - if (!osta) - continue; - - ap_sta_disassociate(ohapd, osta, - WLAN_REASON_UNSPECIFIED); - } - } -} - - -/** - * hostapd_new_assoc_sta - Notify that a new station associated with the AP - * @hapd: Pointer to BSS data - * @sta: Pointer to the associated STA data - * @reassoc: 1 to indicate this was a re-association; 0 = first association - * - * This function will be called whenever a station associates with the AP. It - * can be called for ieee802_11.c for drivers that export MLME to hostapd and - * from driver_*.c for drivers that take care of management frames (IEEE 802.11 - * authentication and association) internally. - */ -void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, - int reassoc) -{ - if (hapd->tkip_countermeasures) { - hostapd_sta_deauth(hapd, sta->addr, - WLAN_REASON_MICHAEL_MIC_FAILURE); - return; - } - - hostapd_prune_associations(hapd, sta); - - /* IEEE 802.11F (IAPP) */ - if (hapd->conf->ieee802_11f) - iapp_new_station(hapd->iapp, sta); - - /* Start accounting here, if IEEE 802.1X and WPA are not used. - * IEEE 802.1X/WPA code will start accounting after the station has - * been authorized. */ - if (!hapd->conf->ieee802_1x && !hapd->conf->wpa) - accounting_sta_start(hapd, sta); - - hostapd_wmm_sta_config(hapd, sta); - - /* Start IEEE 802.1X authentication process for new stations */ - ieee802_1x_new_station(hapd, sta); - if (reassoc) { - if (sta->auth_alg != WLAN_AUTH_FT && - !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) - wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH); - } else - wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm); -} - - -#ifdef EAP_SERVER -static int hostapd_sim_db_cb_sta(struct hostapd_data *hapd, - struct sta_info *sta, void *ctx) -{ - if (eapol_auth_eap_pending_cb(sta->eapol_sm, ctx) == 0) - return 1; - return 0; -} - - -static void hostapd_sim_db_cb(void *ctx, void *session_ctx) -{ - struct hostapd_data *hapd = ctx; - if (ap_for_each_sta(hapd, hostapd_sim_db_cb_sta, session_ctx) == 0) - radius_server_eap_pending_cb(hapd->radius_srv, session_ctx); -} -#endif /* EAP_SERVER */ - - -/** - * handle_term - SIGINT and SIGTERM handler to terminate hostapd process - */ -static void handle_term(int sig, void *eloop_ctx, void *signal_ctx) -{ - wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig); - eloop_terminate(); -} - - -static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, - struct wpa_auth_config *wconf) -{ - wconf->wpa = conf->wpa; - wconf->wpa_key_mgmt = conf->wpa_key_mgmt; - wconf->wpa_pairwise = conf->wpa_pairwise; - wconf->wpa_group = conf->wpa_group; - wconf->wpa_group_rekey = conf->wpa_group_rekey; - wconf->wpa_strict_rekey = conf->wpa_strict_rekey; - wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey; - wconf->wpa_ptk_rekey = conf->wpa_ptk_rekey; - wconf->rsn_pairwise = conf->rsn_pairwise; - wconf->rsn_preauth = conf->rsn_preauth; - wconf->eapol_version = conf->eapol_version; - wconf->peerkey = conf->peerkey; - wconf->wmm_enabled = conf->wmm_enabled; - wconf->okc = conf->okc; -#ifdef CONFIG_IEEE80211W - wconf->ieee80211w = conf->ieee80211w; -#endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_IEEE80211R - wconf->ssid_len = conf->ssid.ssid_len; - if (wconf->ssid_len > SSID_LEN) - wconf->ssid_len = SSID_LEN; - os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len); - os_memcpy(wconf->mobility_domain, conf->mobility_domain, - MOBILITY_DOMAIN_ID_LEN); - if (conf->nas_identifier && - os_strlen(conf->nas_identifier) <= FT_R0KH_ID_MAX_LEN) { - wconf->r0_key_holder_len = os_strlen(conf->nas_identifier); - os_memcpy(wconf->r0_key_holder, conf->nas_identifier, - wconf->r0_key_holder_len); - } - os_memcpy(wconf->r1_key_holder, conf->r1_key_holder, FT_R1KH_ID_LEN); - wconf->r0_key_lifetime = conf->r0_key_lifetime; - wconf->reassociation_deadline = conf->reassociation_deadline; - wconf->r0kh_list = conf->r0kh_list; - wconf->r1kh_list = conf->r1kh_list; - wconf->pmk_r1_push = conf->pmk_r1_push; -#endif /* CONFIG_IEEE80211R */ -} - - -int hostapd_reload_config(struct hostapd_iface *iface) -{ - struct hostapd_data *hapd = iface->bss[0]; - struct hostapd_config *newconf, *oldconf; - struct wpa_auth_config wpa_auth_conf; - size_t j; - - newconf = hostapd_config_read(iface->config_fname); - if (newconf == NULL) - return -1; - - /* - * Deauthenticate all stations since the new configuration may not - * allow them to use the BSS anymore. - */ - for (j = 0; j < iface->num_bss; j++) - hostapd_flush_old_stations(iface->bss[j]); - - /* TODO: update dynamic data based on changed configuration - * items (e.g., open/close sockets, etc.) */ - radius_client_flush(hapd->radius, 0); - - oldconf = hapd->iconf; - hapd->iconf = newconf; - hapd->conf = &newconf->bss[0]; - iface->conf = newconf; - - if (hostapd_setup_wpa_psk(hapd->conf)) { - wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK " - "after reloading configuration"); - } - - if (hapd->conf->wpa && hapd->wpa_auth == NULL) - hostapd_setup_wpa(hapd); - else if (hapd->conf->wpa) { - hostapd_wpa_auth_conf(&newconf->bss[0], &wpa_auth_conf); - wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf); - } else if (hapd->wpa_auth) { - wpa_deinit(hapd->wpa_auth); - hapd->wpa_auth = NULL; - hostapd_set_privacy(hapd, 0); - hostapd_setup_encryption(hapd->conf->iface, hapd); - } - - ieee802_11_set_beacon(hapd); - - if (hapd->conf->ssid.ssid_set && - hostapd_set_ssid(hapd, (u8 *) hapd->conf->ssid.ssid, - hapd->conf->ssid.ssid_len)) { - wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver"); - /* try to continue */ - } - - if (hapd->conf->ieee802_1x || hapd->conf->wpa) - hostapd_set_ieee8021x(hapd->conf->iface, hapd, 1); - - hostapd_config_free(oldconf); - - wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface); - - return 0; -} - - -#ifndef CONFIG_NATIVE_WINDOWS -/** - * handle_reload - SIGHUP handler to reload configuration - */ -static void handle_reload(int sig, void *eloop_ctx, void *signal_ctx) -{ - struct hapd_interfaces *hapds = (struct hapd_interfaces *) eloop_ctx; - size_t i; - - wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration", - sig); - - for (i = 0; i < hapds->count; i++) { - if (hostapd_reload_config(hapds->iface[i]) < 0) { - wpa_printf(MSG_WARNING, "Failed to read new " - "configuration file - continuing with " - "old."); - continue; - } - } -} - - -#ifdef HOSTAPD_DUMP_STATE -/** - * hostapd_dump_state - SIGUSR1 handler to dump hostapd state to a text file - */ -static void hostapd_dump_state(struct hostapd_data *hapd) -{ - FILE *f; - time_t now; - struct sta_info *sta; - int i; - char *buf; - - if (!hapd->conf->dump_log_name) { - wpa_printf(MSG_DEBUG, "Dump file not defined - ignoring dump " - "request"); - return; - } - - wpa_printf(MSG_DEBUG, "Dumping hostapd state to '%s'", - hapd->conf->dump_log_name); - f = fopen(hapd->conf->dump_log_name, "w"); - if (f == NULL) { - wpa_printf(MSG_WARNING, "Could not open dump file '%s' for " - "writing.", hapd->conf->dump_log_name); - return; - } - - time(&now); - fprintf(f, "hostapd state dump - %s", ctime(&now)); - fprintf(f, "num_sta=%d num_sta_non_erp=%d " - "num_sta_no_short_slot_time=%d\n" - "num_sta_no_short_preamble=%d\n", - hapd->num_sta, hapd->iface->num_sta_non_erp, - hapd->iface->num_sta_no_short_slot_time, - hapd->iface->num_sta_no_short_preamble); - - for (sta = hapd->sta_list; sta != NULL; sta = sta->next) { - fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr)); - - fprintf(f, - " AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s\n" - " capability=0x%x listen_interval=%d\n", - sta->aid, - sta->flags, - (sta->flags & WLAN_STA_AUTH ? "[AUTH]" : ""), - (sta->flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""), - (sta->flags & WLAN_STA_PS ? "[PS]" : ""), - (sta->flags & WLAN_STA_TIM ? "[TIM]" : ""), - (sta->flags & WLAN_STA_PERM ? "[PERM]" : ""), - (sta->flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : - ""), - (sta->flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" : - ""), - (sta->flags & WLAN_STA_SHORT_PREAMBLE ? - "[SHORT_PREAMBLE]" : ""), - (sta->flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""), - (sta->flags & WLAN_STA_WMM ? "[WMM]" : ""), - (sta->flags & WLAN_STA_MFP ? "[MFP]" : ""), - (sta->flags & WLAN_STA_WPS ? "[WPS]" : ""), - (sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""), - (sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""), - sta->capability, - sta->listen_interval); - - fprintf(f, " supported_rates="); - for (i = 0; i < sta->supported_rates_len; i++) - fprintf(f, "%02x ", sta->supported_rates[i]); - fprintf(f, "\n"); - - fprintf(f, - " timeout_next=%s\n", - (sta->timeout_next == STA_NULLFUNC ? "NULLFUNC POLL" : - (sta->timeout_next == STA_DISASSOC ? "DISASSOC" : - "DEAUTH"))); - - ieee802_1x_dump_state(f, " ", sta); - } - - buf = os_malloc(4096); - if (buf) { - int count = radius_client_get_mib(hapd->radius, buf, 4096); - if (count < 0) - count = 0; - else if (count > 4095) - count = 4095; - buf[count] = '\0'; - fprintf(f, "%s", buf); - - count = radius_server_get_mib(hapd->radius_srv, buf, 4096); - if (count < 0) - count = 0; - else if (count > 4095) - count = 4095; - buf[count] = '\0'; - fprintf(f, "%s", buf); - os_free(buf); - } - fclose(f); -} -#endif /* HOSTAPD_DUMP_STATE */ - - -static void handle_dump_state(int sig, void *eloop_ctx, void *signal_ctx) -{ -#ifdef HOSTAPD_DUMP_STATE - struct hapd_interfaces *hapds = (struct hapd_interfaces *) eloop_ctx; - size_t i, j; - - for (i = 0; i < hapds->count; i++) { - struct hostapd_iface *hapd_iface = hapds->iface[i]; - for (j = 0; j < hapd_iface->num_bss; j++) - hostapd_dump_state(hapd_iface->bss[j]); - } -#endif /* HOSTAPD_DUMP_STATE */ -} -#endif /* CONFIG_NATIVE_WINDOWS */ - -static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd, - char *ifname) -{ - int i; - - for (i = 0; i < NUM_WEP_KEYS; i++) { - if (hostapd_set_encryption(ifname, hapd, "none", NULL, i, NULL, - 0, i == 0 ? 1 : 0)) { - wpa_printf(MSG_DEBUG, "Failed to clear default " - "encryption keys (ifname=%s keyidx=%d)", - ifname, i); - } - } -#ifdef CONFIG_IEEE80211W - if (hapd->conf->ieee80211w) { - for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) { - if (hostapd_set_encryption(ifname, hapd, "none", NULL, - i, NULL, 0, - i == 0 ? 1 : 0)) { - wpa_printf(MSG_DEBUG, "Failed to clear " - "default mgmt encryption keys " - "(ifname=%s keyidx=%d)", ifname, i); - } - } - } -#endif /* CONFIG_IEEE80211W */ -} - - -static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd) -{ - hostapd_broadcast_key_clear_iface(hapd, hapd->conf->iface); - return 0; -} - - -static int hostapd_broadcast_wep_set(struct hostapd_data *hapd) -{ - int errors = 0, idx; - struct hostapd_ssid *ssid = &hapd->conf->ssid; - - idx = ssid->wep.idx; - if (ssid->wep.default_len && - hostapd_set_encryption(hapd->conf->iface, - hapd, "WEP", NULL, idx, - ssid->wep.key[idx], - ssid->wep.len[idx], - idx == ssid->wep.idx)) { - wpa_printf(MSG_WARNING, "Could not set WEP encryption."); - errors++; - } - - if (ssid->dyn_vlan_keys) { - size_t i; - for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) { - const char *ifname; - struct hostapd_wep_keys *key = ssid->dyn_vlan_keys[i]; - if (key == NULL) - continue; - ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, - i); - if (ifname == NULL) - continue; - - idx = key->idx; - if (hostapd_set_encryption(ifname, hapd, "WEP", NULL, - idx, key->key[idx], - key->len[idx], - idx == key->idx)) { - wpa_printf(MSG_WARNING, "Could not set " - "dynamic VLAN WEP encryption."); - errors++; - } - } - } - - return errors; -} - -/** - * hostapd_cleanup - Per-BSS cleanup (deinitialization) - * @hapd: Pointer to BSS data - * - * This function is used to free all per-BSS data structures and resources. - * This gets called in a loop for each BSS between calls to - * hostapd_cleanup_iface_pre() and hostapd_cleanup_iface() when an interface - * is deinitialized. Most of the modules that are initialized in - * hostapd_setup_bss() are deinitialized here. - */ -static void hostapd_cleanup(struct hostapd_data *hapd) -{ - hostapd_ctrl_iface_deinit(hapd); - - os_free(hapd->default_wep_key); - hapd->default_wep_key = NULL; - iapp_deinit(hapd->iapp); - hapd->iapp = NULL; - accounting_deinit(hapd); - rsn_preauth_iface_deinit(hapd); - if (hapd->wpa_auth) { - wpa_deinit(hapd->wpa_auth); - hapd->wpa_auth = NULL; - - if (hostapd_set_privacy(hapd, 0)) { - wpa_printf(MSG_DEBUG, "Could not disable " - "PrivacyInvoked for interface %s", - hapd->conf->iface); - } - - if (hostapd_set_generic_elem(hapd, (u8 *) "", 0)) { - wpa_printf(MSG_DEBUG, "Could not remove generic " - "information element from interface %s", - hapd->conf->iface); - } - } - ieee802_1x_deinit(hapd); - vlan_deinit(hapd); - hostapd_acl_deinit(hapd); - radius_client_deinit(hapd->radius); - hapd->radius = NULL; - radius_server_deinit(hapd->radius_srv); - hapd->radius_srv = NULL; - -#ifdef CONFIG_IEEE80211R - l2_packet_deinit(hapd->l2); -#endif /* CONFIG_IEEE80211R */ - - hostapd_deinit_wps(hapd); - - hostapd_wireless_event_deinit(hapd); - -#ifdef EAP_TLS_FUNCS - if (hapd->ssl_ctx) { - tls_deinit(hapd->ssl_ctx); - hapd->ssl_ctx = NULL; - } -#endif /* EAP_TLS_FUNCS */ - -#ifdef EAP_SERVER - if (hapd->eap_sim_db_priv) { - eap_sim_db_deinit(hapd->eap_sim_db_priv); - hapd->eap_sim_db_priv = NULL; - } -#endif /* EAP_SERVER */ - - if (hapd->interface_added && - hostapd_bss_remove(hapd, hapd->conf->iface)) { - wpa_printf(MSG_WARNING, "Failed to remove BSS interface %s", - hapd->conf->iface); - } -} - - -/** - * hostapd_cleanup_iface_pre - Preliminary per-interface cleanup - * @iface: Pointer to interface data - * - * This function is called before per-BSS data structures are deinitialized - * with hostapd_cleanup(). - */ -static void hostapd_cleanup_iface_pre(struct hostapd_iface *iface) -{ -} - - -/** - * hostapd_cleanup_iface - Complete per-interface cleanup - * @iface: Pointer to interface data - * - * This function is called after per-BSS data structures are deinitialized - * with hostapd_cleanup(). - */ -static void hostapd_cleanup_iface(struct hostapd_iface *iface) -{ - hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); - iface->hw_features = NULL; - os_free(iface->current_rates); - iface->current_rates = NULL; - ap_list_deinit(iface); - hostapd_config_free(iface->conf); - iface->conf = NULL; - - os_free(iface->config_fname); - os_free(iface->bss); - os_free(iface); -} - - -static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd) -{ - int i; - - hostapd_broadcast_wep_set(hapd); - - if (hapd->conf->ssid.wep.default_len) - return 0; - - for (i = 0; i < 4; i++) { - if (hapd->conf->ssid.wep.key[i] && - hostapd_set_encryption(iface, hapd, "WEP", NULL, - i, hapd->conf->ssid.wep.key[i], - hapd->conf->ssid.wep.len[i], - i == hapd->conf->ssid.wep.idx)) { - wpa_printf(MSG_WARNING, "Could not set WEP " - "encryption."); - return -1; - } - if (hapd->conf->ssid.wep.key[i] && - i == hapd->conf->ssid.wep.idx) - hostapd_set_privacy(hapd, 1); - } - - return 0; -} - - -static int hostapd_flush_old_stations(struct hostapd_data *hapd) -{ - int ret = 0; - - if (hostapd_drv_none(hapd)) - return 0; - - wpa_printf(MSG_DEBUG, "Flushing old station entries"); - if (hostapd_flush(hapd)) { - wpa_printf(MSG_WARNING, "Could not connect to kernel driver."); - ret = -1; - } - wpa_printf(MSG_DEBUG, "Deauthenticate all stations"); - hostapd_deauth_all_stas(hapd); - - return ret; -} - - -static void hostapd_wpa_auth_logger(void *ctx, const u8 *addr, - logger_level level, const char *txt) -{ - struct hostapd_data *hapd = ctx; - int hlevel; - - switch (level) { - case LOGGER_WARNING: - hlevel = HOSTAPD_LEVEL_WARNING; - break; - case LOGGER_INFO: - hlevel = HOSTAPD_LEVEL_INFO; - break; - case LOGGER_DEBUG: - default: - hlevel = HOSTAPD_LEVEL_DEBUG; - break; - } - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_WPA, hlevel, "%s", txt); -} - - -static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr, - u16 reason) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta; - - wpa_printf(MSG_DEBUG, "%s: WPA authenticator requests disconnect: " - "STA " MACSTR " reason %d", - __func__, MAC2STR(addr), reason); - - sta = ap_get_sta(hapd, addr); - hostapd_sta_deauth(hapd, addr, reason); - if (sta == NULL) - return; - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED); - eloop_cancel_timeout(ap_handle_timer, hapd, sta); - eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta); - sta->timeout_next = STA_REMOVE; -} - - -static void hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr) -{ - struct hostapd_data *hapd = ctx; - ieee80211_michael_mic_failure(hapd, addr, 0); -} - - -static void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr, - wpa_eapol_variable var, int value) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta = ap_get_sta(hapd, addr); - if (sta == NULL) - return; - switch (var) { - case WPA_EAPOL_portEnabled: - ieee802_1x_notify_port_enabled(sta->eapol_sm, value); - break; - case WPA_EAPOL_portValid: - ieee802_1x_notify_port_valid(sta->eapol_sm, value); - break; - case WPA_EAPOL_authorized: - ieee802_1x_set_sta_authorized(hapd, sta, value); - break; - case WPA_EAPOL_portControl_Auto: - if (sta->eapol_sm) - sta->eapol_sm->portControl = Auto; - break; - case WPA_EAPOL_keyRun: - if (sta->eapol_sm) - sta->eapol_sm->keyRun = value ? TRUE : FALSE; - break; - case WPA_EAPOL_keyAvailable: - if (sta->eapol_sm) - sta->eapol_sm->eap_if->eapKeyAvailable = - value ? TRUE : FALSE; - break; - case WPA_EAPOL_keyDone: - if (sta->eapol_sm) - sta->eapol_sm->keyDone = value ? TRUE : FALSE; - break; - case WPA_EAPOL_inc_EapolFramesTx: - if (sta->eapol_sm) - sta->eapol_sm->dot1xAuthEapolFramesTx++; - break; - } -} - - -static int hostapd_wpa_auth_get_eapol(void *ctx, const u8 *addr, - wpa_eapol_variable var) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta = ap_get_sta(hapd, addr); - if (sta == NULL || sta->eapol_sm == NULL) - return -1; - switch (var) { - case WPA_EAPOL_keyRun: - return sta->eapol_sm->keyRun; - case WPA_EAPOL_keyAvailable: - return sta->eapol_sm->eap_if->eapKeyAvailable; - default: - return -1; - } -} - - -static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr, - const u8 *prev_psk) -{ - struct hostapd_data *hapd = ctx; - return hostapd_get_psk(hapd->conf, addr, prev_psk); -} - - -static int hostapd_wpa_auth_get_msk(void *ctx, const u8 *addr, u8 *msk, - size_t *len) -{ - struct hostapd_data *hapd = ctx; - const u8 *key; - size_t keylen; - struct sta_info *sta; - - sta = ap_get_sta(hapd, addr); - if (sta == NULL) - return -1; - - key = ieee802_1x_get_key(sta->eapol_sm, &keylen); - if (key == NULL) - return -1; - - if (keylen > *len) - keylen = *len; - os_memcpy(msk, key, keylen); - *len = keylen; - - return 0; -} - - -static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, const char *alg, - const u8 *addr, int idx, u8 *key, - size_t key_len) -{ - struct hostapd_data *hapd = ctx; - const char *ifname = hapd->conf->iface; - - if (vlan_id > 0) { - ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id); - if (ifname == NULL) - return -1; - } - - return hostapd_set_encryption(ifname, hapd, alg, addr, idx, - key, key_len, 1); -} - - -static int hostapd_wpa_auth_get_seqnum(void *ctx, const u8 *addr, int idx, - u8 *seq) -{ - struct hostapd_data *hapd = ctx; - return hostapd_get_seqnum(hapd->conf->iface, hapd, addr, idx, seq); -} - - -static int hostapd_wpa_auth_get_seqnum_igtk(void *ctx, const u8 *addr, int idx, - u8 *seq) -{ - struct hostapd_data *hapd = ctx; - return hostapd_get_seqnum_igtk(hapd->conf->iface, hapd, addr, idx, - seq); -} - - -static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr, - const u8 *data, size_t data_len, - int encrypt) -{ - struct hostapd_data *hapd = ctx; - return hostapd_send_eapol(hapd, addr, data, data_len, encrypt); -} - - -static int hostapd_wpa_auth_for_each_sta( - void *ctx, int (*cb)(struct wpa_state_machine *sm, void *ctx), - void *cb_ctx) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta; - - for (sta = hapd->sta_list; sta; sta = sta->next) { - if (sta->wpa_sm && cb(sta->wpa_sm, cb_ctx)) - return 1; - } - return 0; -} - - -static int hostapd_wpa_auth_for_each_auth( - void *ctx, int (*cb)(struct wpa_authenticator *sm, void *ctx), - void *cb_ctx) -{ - struct hostapd_data *ohapd; - size_t i, j; - struct hapd_interfaces *interfaces = eloop_get_user_data(); - - for (i = 0; i < interfaces->count; i++) { - for (j = 0; j < interfaces->iface[i]->num_bss; j++) { - ohapd = interfaces->iface[i]->bss[j]; - if (cb(ohapd->wpa_auth, cb_ctx)) - return 1; - } - } - - return 0; -} - - -static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto, - const u8 *data, size_t data_len) -{ - struct hostapd_data *hapd = ctx; - - if (hapd->driver && hapd->driver->send_ether) - return hapd->driver->send_ether(hapd->drv_priv, dst, - hapd->own_addr, proto, - data, data_len); - if (hapd->l2 == NULL) - return -1; - return l2_packet_send(hapd->l2, dst, proto, data, data_len); -} - - -#ifdef CONFIG_IEEE80211R - -static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst, - const u8 *data, size_t data_len) -{ - struct hostapd_data *hapd = ctx; - int res; - struct ieee80211_mgmt *m; - size_t mlen; - struct sta_info *sta; - - sta = ap_get_sta(hapd, dst); - if (sta == NULL || sta->wpa_sm == NULL) - return -1; - - m = os_zalloc(sizeof(*m) + data_len); - if (m == NULL) - return -1; - mlen = ((u8 *) &m->u - (u8 *) m) + data_len; - m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_ACTION); - os_memcpy(m->da, dst, ETH_ALEN); - os_memcpy(m->sa, hapd->own_addr, ETH_ALEN); - os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN); - os_memcpy(&m->u, data, data_len); - - res = hostapd_send_mgmt_frame(hapd, (u8 *) m, mlen, 0); - os_free(m); - return res; -} - - -static struct wpa_state_machine * -hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta; - - sta = ap_sta_add(hapd, sta_addr); - if (sta == NULL) - return NULL; - if (sta->wpa_sm) - return sta->wpa_sm; - - sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr); - if (sta->wpa_sm == NULL) { - ap_free_sta(hapd, sta); - return NULL; - } - sta->auth_alg = WLAN_AUTH_FT; - - return sta->wpa_sm; -} - - -static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf, - size_t len) -{ - struct hostapd_data *hapd = ctx; - wpa_ft_rrb_rx(hapd->wpa_auth, src_addr, buf, len); -} - -#endif /* CONFIG_IEEE80211R */ - - -/** - * hostapd_validate_bssid_configuration - Validate BSSID configuration - * @iface: Pointer to interface data - * Returns: 0 on success, -1 on failure - * - * This function is used to validate that the configured BSSIDs are valid. - */ -static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface) -{ - u8 mask[ETH_ALEN] = { 0 }; - struct hostapd_data *hapd = iface->bss[0]; - unsigned int i = iface->conf->num_bss, bits = 0, j; - int res; - - if (hostapd_drv_none(hapd)) - return 0; - - /* Generate BSSID mask that is large enough to cover the BSSIDs. */ - - /* Determine the bits necessary to cover the number of BSSIDs. */ - for (i--; i; i >>= 1) - bits++; - - /* Determine the bits necessary to any configured BSSIDs, - if they are higher than the number of BSSIDs. */ - for (j = 0; j < iface->conf->num_bss; j++) { - if (hostapd_mac_comp_empty(iface->conf->bss[j].bssid) == 0) - continue; - - for (i = 0; i < ETH_ALEN; i++) { - mask[i] |= - iface->conf->bss[j].bssid[i] ^ - hapd->own_addr[i]; - } - } - - for (i = 0; i < ETH_ALEN && mask[i] == 0; i++) - ; - j = 0; - if (i < ETH_ALEN) { - j = (5 - i) * 8; - - while (mask[i] != 0) { - mask[i] >>= 1; - j++; - } - } - - if (bits < j) - bits = j; - - if (bits > 40) - return -1; - - os_memset(mask, 0xff, ETH_ALEN); - j = bits / 8; - for (i = 5; i > 5 - j; i--) - mask[i] = 0; - j = bits % 8; - while (j--) - mask[i] <<= 1; - - wpa_printf(MSG_DEBUG, "BSS count %lu, BSSID mask " MACSTR " (%d bits)", - (unsigned long) iface->conf->num_bss, MAC2STR(mask), bits); - - res = hostapd_valid_bss_mask(hapd, hapd->own_addr, mask); - if (res == 0) - return 0; - - if (res < 0) { - wpa_printf(MSG_ERROR, "Driver did not accept BSSID mask " - MACSTR " for start address " MACSTR ".", - MAC2STR(mask), MAC2STR(hapd->own_addr)); - return -1; - } - - for (i = 0; i < ETH_ALEN; i++) { - if ((hapd->own_addr[i] & mask[i]) != hapd->own_addr[i]) { - wpa_printf(MSG_ERROR, "Invalid BSSID mask " MACSTR - " for start address " MACSTR ".", - MAC2STR(mask), MAC2STR(hapd->own_addr)); - wpa_printf(MSG_ERROR, "Start address must be the " - "first address in the block (i.e., addr " - "AND mask == addr)."); - return -1; - } - } - - return 0; -} - - -static int mac_in_conf(struct hostapd_config *conf, const void *a) -{ - size_t i; - - for (i = 0; i < conf->num_bss; i++) { - if (hostapd_mac_comp(conf->bss[i].bssid, a) == 0) { - return 1; - } - } - - return 0; -} - - -static int hostapd_setup_wpa(struct hostapd_data *hapd) -{ - struct wpa_auth_config _conf; - struct wpa_auth_callbacks cb; - const u8 *wpa_ie; - size_t wpa_ie_len; - - hostapd_wpa_auth_conf(hapd->conf, &_conf); - os_memset(&cb, 0, sizeof(cb)); - cb.ctx = hapd; - cb.logger = hostapd_wpa_auth_logger; - cb.disconnect = hostapd_wpa_auth_disconnect; - cb.mic_failure_report = hostapd_wpa_auth_mic_failure_report; - cb.set_eapol = hostapd_wpa_auth_set_eapol; - cb.get_eapol = hostapd_wpa_auth_get_eapol; - cb.get_psk = hostapd_wpa_auth_get_psk; - cb.get_msk = hostapd_wpa_auth_get_msk; - cb.set_key = hostapd_wpa_auth_set_key; - cb.get_seqnum = hostapd_wpa_auth_get_seqnum; - cb.get_seqnum_igtk = hostapd_wpa_auth_get_seqnum_igtk; - cb.send_eapol = hostapd_wpa_auth_send_eapol; - cb.for_each_sta = hostapd_wpa_auth_for_each_sta; - cb.for_each_auth = hostapd_wpa_auth_for_each_auth; - cb.send_ether = hostapd_wpa_auth_send_ether; -#ifdef CONFIG_IEEE80211R - cb.send_ft_action = hostapd_wpa_auth_send_ft_action; - cb.add_sta = hostapd_wpa_auth_add_sta; -#endif /* CONFIG_IEEE80211R */ - hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb); - if (hapd->wpa_auth == NULL) { - wpa_printf(MSG_ERROR, "WPA initialization failed."); - return -1; - } - - if (hostapd_set_privacy(hapd, 1)) { - wpa_printf(MSG_ERROR, "Could not set PrivacyInvoked " - "for interface %s", hapd->conf->iface); - return -1; - } - - wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len); - if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len)) { - wpa_printf(MSG_ERROR, "Failed to configure WPA IE for " - "the kernel driver."); - return -1; - } - - if (rsn_preauth_iface_init(hapd)) { - wpa_printf(MSG_ERROR, "Initialization of RSN " - "pre-authentication failed."); - return -1; - } - - return 0; - -} - - -static int hostapd_setup_radius_srv(struct hostapd_data *hapd, - struct hostapd_bss_config *conf) -{ - struct radius_server_conf srv; - os_memset(&srv, 0, sizeof(srv)); - srv.client_file = conf->radius_server_clients; - srv.auth_port = conf->radius_server_auth_port; - srv.conf_ctx = conf; - srv.eap_sim_db_priv = hapd->eap_sim_db_priv; - srv.ssl_ctx = hapd->ssl_ctx; - srv.pac_opaque_encr_key = conf->pac_opaque_encr_key; - srv.eap_fast_a_id = conf->eap_fast_a_id; - srv.eap_fast_a_id_len = conf->eap_fast_a_id_len; - srv.eap_fast_a_id_info = conf->eap_fast_a_id_info; - srv.eap_fast_prov = conf->eap_fast_prov; - srv.pac_key_lifetime = conf->pac_key_lifetime; - srv.pac_key_refresh_time = conf->pac_key_refresh_time; - srv.eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind; - srv.tnc = conf->tnc; - srv.wps = hapd->wps; - srv.ipv6 = conf->radius_server_ipv6; - srv.get_eap_user = hostapd_radius_get_eap_user; - srv.eap_req_id_text = conf->eap_req_id_text; - srv.eap_req_id_text_len = conf->eap_req_id_text_len; - - hapd->radius_srv = radius_server_init(&srv); - if (hapd->radius_srv == NULL) { - wpa_printf(MSG_ERROR, "RADIUS server initialization failed."); - return -1; - } - - return 0; -} - - -/** - * hostapd_setup_bss - Per-BSS setup (initialization) - * @hapd: Pointer to BSS data - * @first: Whether this BSS is the first BSS of an interface - * - * This function is used to initialize all per-BSS data structures and - * resources. This gets called in a loop for each BSS when an interface is - * initialized. Most of the modules that are initialized here will be - * deinitialized in hostapd_cleanup(). - */ -static int hostapd_setup_bss(struct hostapd_data *hapd, int first) -{ - struct hostapd_bss_config *conf = hapd->conf; - u8 ssid[HOSTAPD_MAX_SSID_LEN + 1]; - int ssid_len, set_ssid; - - if (!first) { - if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) { - /* Allocate the next available BSSID. */ - do { - inc_byte_array(hapd->own_addr, ETH_ALEN); - } while (mac_in_conf(hapd->iconf, hapd->own_addr)); - } else { - /* Allocate the configured BSSID. */ - os_memcpy(hapd->own_addr, hapd->conf->bssid, ETH_ALEN); - - if (hostapd_mac_comp(hapd->own_addr, - hapd->iface->bss[0]->own_addr) == - 0) { - wpa_printf(MSG_ERROR, "BSS '%s' may not have " - "BSSID set to the MAC address of " - "the radio", hapd->conf->iface); - return -1; - } - } - - hapd->interface_added = 1; - if (hostapd_bss_add(hapd->iface->bss[0], hapd->conf->iface, - hapd->own_addr)) { - wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID=" - MACSTR ")", MAC2STR(hapd->own_addr)); - return -1; - } - } - - hostapd_flush_old_stations(hapd); - hostapd_set_privacy(hapd, 0); - - hostapd_broadcast_wep_clear(hapd); - if (hostapd_setup_encryption(hapd->conf->iface, hapd)) - return -1; - - /* - * Fetch the SSID from the system and use it or, - * if one was specified in the config file, verify they - * match. - */ - ssid_len = hostapd_get_ssid(hapd, ssid, sizeof(ssid)); - if (ssid_len < 0) { - wpa_printf(MSG_ERROR, "Could not read SSID from system"); - return -1; - } - if (conf->ssid.ssid_set) { - /* - * If SSID is specified in the config file and it differs - * from what is being used then force installation of the - * new SSID. - */ - set_ssid = (conf->ssid.ssid_len != (size_t) ssid_len || - os_memcmp(conf->ssid.ssid, ssid, ssid_len) != 0); - } else { - /* - * No SSID in the config file; just use the one we got - * from the system. - */ - set_ssid = 0; - conf->ssid.ssid_len = ssid_len; - os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len); - conf->ssid.ssid[conf->ssid.ssid_len] = '\0'; - } - - if (!hostapd_drv_none(hapd)) { - wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR - " and ssid '%s'", - hapd->conf->iface, MAC2STR(hapd->own_addr), - hapd->conf->ssid.ssid); - } - - if (hostapd_setup_wpa_psk(conf)) { - wpa_printf(MSG_ERROR, "WPA-PSK setup failed."); - return -1; - } - - /* Set flag for whether SSID is broadcast in beacons */ - if (hostapd_set_broadcast_ssid(hapd, - !!hapd->conf->ignore_broadcast_ssid)) { - wpa_printf(MSG_ERROR, "Could not set broadcast SSID flag for " - "kernel driver"); - return -1; - } - - if (hostapd_set_dtim_period(hapd, hapd->conf->dtim_period)) { - wpa_printf(MSG_ERROR, "Could not set DTIM period for kernel " - "driver"); - return -1; - } - - /* Set SSID for the kernel driver (to be used in beacon and probe - * response frames) */ - if (set_ssid && hostapd_set_ssid(hapd, (u8 *) conf->ssid.ssid, - conf->ssid.ssid_len)) { - wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver"); - return -1; - } - - if (wpa_debug_level == MSG_MSGDUMP) - conf->radius->msg_dumps = 1; - hapd->radius = radius_client_init(hapd, conf->radius); - if (hapd->radius == NULL) { - wpa_printf(MSG_ERROR, "RADIUS client initialization failed."); - return -1; - } - - if (hostapd_acl_init(hapd)) { - wpa_printf(MSG_ERROR, "ACL initialization failed."); - return -1; - } - if (hostapd_init_wps(hapd, conf)) - return -1; - - if (ieee802_1x_init(hapd)) { - wpa_printf(MSG_ERROR, "IEEE 802.1X initialization failed."); - return -1; - } - - if (hapd->conf->wpa && hostapd_setup_wpa(hapd)) - return -1; - - if (accounting_init(hapd)) { - wpa_printf(MSG_ERROR, "Accounting initialization failed."); - return -1; - } - - if (hapd->conf->ieee802_11f && - (hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface)) == NULL) { - wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization " - "failed."); - return -1; - } - - if (hostapd_ctrl_iface_init(hapd)) { - wpa_printf(MSG_ERROR, "Failed to setup control interface"); - return -1; - } - - if (!hostapd_drv_none(hapd) && vlan_init(hapd)) { - wpa_printf(MSG_ERROR, "VLAN initialization failed."); - return -1; - } - -#ifdef CONFIG_IEEE80211R - if (!hostapd_drv_none(hapd)) { - hapd->l2 = l2_packet_init(hapd->conf->iface, NULL, ETH_P_RRB, - hostapd_rrb_receive, hapd, 0); - if (hapd->l2 == NULL && - (hapd->driver == NULL || - hapd->driver->send_ether == NULL)) { - wpa_printf(MSG_ERROR, "Failed to open l2_packet " - "interface"); - return -1; - } - } -#endif /* CONFIG_IEEE80211R */ - - ieee802_11_set_beacon(hapd); - - if (conf->radius_server_clients && - hostapd_setup_radius_srv(hapd, conf)) - return -1; - - return 0; -} - - -static void hostapd_tx_queue_params(struct hostapd_iface *iface) -{ - struct hostapd_data *hapd = iface->bss[0]; - int i; - struct hostapd_tx_queue_params *p; - - for (i = 0; i < NUM_TX_QUEUES; i++) { - p = &iface->conf->tx_queue[i]; - - if (!p->configured) - continue; - - if (hostapd_set_tx_queue_params(hapd, i, p->aifs, p->cwmin, - p->cwmax, p->burst)) { - wpa_printf(MSG_DEBUG, "Failed to set TX queue " - "parameters for queue %d.", i); - /* Continue anyway */ - } - } -} - - -static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity, - size_t identity_len, int phase2, - struct eap_user *user) -{ - const struct hostapd_eap_user *eap_user; - int i, count; - - eap_user = hostapd_get_eap_user(ctx, identity, identity_len, phase2); - if (eap_user == NULL) - return -1; - - if (user == NULL) - return 0; - - os_memset(user, 0, sizeof(*user)); - count = EAP_USER_MAX_METHODS; - if (count > EAP_MAX_METHODS) - count = EAP_MAX_METHODS; - for (i = 0; i < count; i++) { - user->methods[i].vendor = eap_user->methods[i].vendor; - user->methods[i].method = eap_user->methods[i].method; - } - - if (eap_user->password) { - user->password = os_malloc(eap_user->password_len); - if (user->password == NULL) - return -1; - os_memcpy(user->password, eap_user->password, - eap_user->password_len); - user->password_len = eap_user->password_len; - user->password_hash = eap_user->password_hash; - } - user->force_version = eap_user->force_version; - user->ttls_auth = eap_user->ttls_auth; - - return 0; -} - - -static int setup_interface(struct hostapd_iface *iface) -{ - struct hostapd_data *hapd = iface->bss[0]; - struct hostapd_bss_config *conf = hapd->conf; - size_t i; - char country[4]; - u8 *b = conf->bssid; - int freq; - size_t j; - u8 *prev_addr; - - /* - * Initialize the driver interface and make sure that all BSSes get - * configured with a pointer to this driver interface. - */ - if (b[0] | b[1] | b[2] | b[3] | b[4] | b[5]) { - hapd->drv_priv = hostapd_driver_init_bssid(hapd, b); - } else { - hapd->drv_priv = hostapd_driver_init(hapd); - } - - if (hapd->drv_priv == NULL) { - wpa_printf(MSG_ERROR, "%s driver initialization failed.", - hapd->driver ? hapd->driver->name : "Unknown"); - hapd->driver = NULL; - return -1; - } - for (i = 0; i < iface->num_bss; i++) { - iface->bss[i]->driver = hapd->driver; - iface->bss[i]->drv_priv = hapd->drv_priv; - } - - if (hostapd_validate_bssid_configuration(iface)) - return -1; - -#ifdef CONFIG_IEEE80211N - SET_2BIT_LE16(&iface->ht_op_mode, - HT_INFO_OPERATION_MODE_OP_MODE_OFFSET, - OP_MODE_PURE); -#endif /* CONFIG_IEEE80211N */ - - if (hapd->iconf->country[0] && hapd->iconf->country[1]) { - os_memcpy(country, hapd->iconf->country, 3); - country[3] = '\0'; - if (hostapd_set_country(hapd, country) < 0) { - wpa_printf(MSG_ERROR, "Failed to set country code"); - return -1; - } - } - - if (hapd->iconf->ieee80211d && - hostapd_set_ieee80211d(hapd, 1) < 0) { - wpa_printf(MSG_ERROR, "Failed to set ieee80211d (%d)", - hapd->iconf->ieee80211d); - return -1; - } - - if (hapd->iconf->bridge_packets != INTERNAL_BRIDGE_DO_NOT_CONTROL && - hostapd_set_internal_bridge(hapd, hapd->iconf->bridge_packets)) { - wpa_printf(MSG_ERROR, "Failed to set bridge_packets for " - "kernel driver"); - return -1; - } - - /* TODO: merge with hostapd_driver_init() ? */ - if (hostapd_wireless_event_init(hapd) < 0) - return -1; - - if (hostapd_get_hw_features(iface)) { - /* Not all drivers support this yet, so continue without hw - * feature data. */ - } else { - int ret = hostapd_select_hw_mode(iface); - if (ret < 0) { - wpa_printf(MSG_ERROR, "Could not select hw_mode and " - "channel. (%d)", ret); - return -1; - } - } - - if (hapd->iconf->channel) { - freq = hostapd_hw_get_freq(hapd, hapd->iconf->channel); - wpa_printf(MSG_DEBUG, "Mode: %s Channel: %d " - "Frequency: %d MHz", - hostapd_hw_mode_txt(hapd->iconf->hw_mode), - hapd->iconf->channel, freq); - - if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, freq, - hapd->iconf->ieee80211n, - hapd->iconf->secondary_channel)) { - wpa_printf(MSG_ERROR, "Could not set channel for " - "kernel driver"); - return -1; - } - } - - hostapd_set_beacon_int(hapd, hapd->iconf->beacon_int); - - if (hapd->iconf->rts_threshold > -1 && - hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) { - wpa_printf(MSG_ERROR, "Could not set RTS threshold for " - "kernel driver"); - return -1; - } - - if (hapd->iconf->fragm_threshold > -1 && - hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) { - wpa_printf(MSG_ERROR, "Could not set fragmentation threshold " - "for kernel driver"); - return -1; - } - - prev_addr = hapd->own_addr; - - for (j = 0; j < iface->num_bss; j++) { - hapd = iface->bss[j]; - if (j) - os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN); - if (hostapd_setup_bss(hapd, j == 0)) - return -1; - if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) - prev_addr = hapd->own_addr; - } - - hostapd_tx_queue_params(iface); - - ap_list_init(iface); - - if (hostapd_driver_commit(hapd) < 0) { - wpa_printf(MSG_ERROR, "%s: Failed to commit driver " - "configuration", __func__); - return -1; - } - - return 0; -} - - -/** - * hostapd_setup_interface - Setup of an interface - * @iface: Pointer to interface data. - * Returns: 0 on success, -1 on failure - * - * Initializes the driver interface, validates the configuration, - * and sets driver parameters based on the configuration. - * Flushes old stations, sets the channel, encryption, - * beacons, and WDS links based on the configuration. - */ -static int hostapd_setup_interface(struct hostapd_iface *iface) -{ - int ret; - - ret = setup_interface(iface); - if (ret) { - wpa_printf(MSG_DEBUG, "%s: Unable to setup interface.", - iface->bss[0]->conf->iface); - eloop_terminate(); - return -1; - } else if (!hostapd_drv_none(iface->bss[0])) { - wpa_printf(MSG_DEBUG, "%s: Setup of interface done.", - iface->bss[0]->conf->iface); - } - - return 0; -} - - -static void show_version(void) -{ - fprintf(stderr, - "hostapd v" VERSION_STR "\n" - "User space daemon for IEEE 802.11 AP management,\n" - "IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n" - "Copyright (c) 2002-2009, Jouni Malinen " - "and contributors\n"); -} - - -static void usage(void) -{ - show_version(); - fprintf(stderr, - "\n" - "usage: hostapd [-hdBKtv] [-P ] " - "\n" - "\n" - "options:\n" - " -h show this usage\n" - " -d show more debug messages (-dd for even more)\n" - " -B run daemon in the background\n" - " -P PID file\n" - " -K include key data in debug messages\n" - " -t include timestamps in some debug messages\n" - " -v show hostapd version\n"); - - exit(1); -} - - -/** - * hostapd_alloc_bss_data - Allocate and initialize per-BSS data - * @hapd_iface: Pointer to interface data - * @conf: Pointer to per-interface configuration - * @bss: Pointer to per-BSS configuration for this BSS - * Returns: Pointer to allocated BSS data - * - * This function is used to allocate per-BSS data structure. This data will be - * freed after hostapd_cleanup() is called for it during interface - * deinitialization. - */ -static struct hostapd_data * -hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface, - struct hostapd_config *conf, - struct hostapd_bss_config *bss) -{ - struct hostapd_data *hapd; - - hapd = os_zalloc(sizeof(*hapd)); - if (hapd == NULL) - return NULL; - - hapd->iconf = conf; - hapd->conf = bss; - hapd->iface = hapd_iface; - - if (hapd->conf->individual_wep_key_len > 0) { - /* use key0 in individual key and key1 in broadcast key */ - hapd->default_wep_key_idx = 1; - } - -#ifdef EAP_TLS_FUNCS - if (hapd->conf->eap_server && - (hapd->conf->ca_cert || hapd->conf->server_cert || - hapd->conf->dh_file)) { - struct tls_connection_params params; - - hapd->ssl_ctx = tls_init(NULL); - if (hapd->ssl_ctx == NULL) { - wpa_printf(MSG_ERROR, "Failed to initialize TLS"); - goto fail; - } - - os_memset(¶ms, 0, sizeof(params)); - params.ca_cert = hapd->conf->ca_cert; - params.client_cert = hapd->conf->server_cert; - params.private_key = hapd->conf->private_key; - params.private_key_passwd = hapd->conf->private_key_passwd; - params.dh_file = hapd->conf->dh_file; - - if (tls_global_set_params(hapd->ssl_ctx, ¶ms)) { - wpa_printf(MSG_ERROR, "Failed to set TLS parameters"); - goto fail; - } - - if (tls_global_set_verify(hapd->ssl_ctx, - hapd->conf->check_crl)) { - wpa_printf(MSG_ERROR, "Failed to enable check_crl"); - goto fail; - } - } -#endif /* EAP_TLS_FUNCS */ - -#ifdef EAP_SERVER - if (hapd->conf->eap_sim_db) { - hapd->eap_sim_db_priv = - eap_sim_db_init(hapd->conf->eap_sim_db, - hostapd_sim_db_cb, hapd); - if (hapd->eap_sim_db_priv == NULL) { - wpa_printf(MSG_ERROR, "Failed to initialize EAP-SIM " - "database interface"); - goto fail; - } - } -#endif /* EAP_SERVER */ - - hapd->driver = hapd->iconf->driver; - - return hapd; - -#if defined(EAP_TLS_FUNCS) || defined(EAP_SERVER) -fail: -#endif - /* TODO: cleanup allocated resources(?) */ - os_free(hapd); - return NULL; -} - - -/** - * hostapd_init - Allocate and initialize per-interface data - * @config_file: Path to the configuration file - * Returns: Pointer to the allocated interface data or %NULL on failure - * - * This function is used to allocate main data structures for per-interface - * data. The allocated data buffer will be freed by calling - * hostapd_cleanup_iface(). - */ -static struct hostapd_iface * hostapd_init(const char *config_file) -{ - struct hostapd_iface *hapd_iface = NULL; - struct hostapd_config *conf = NULL; - struct hostapd_data *hapd; - size_t i; - - hapd_iface = os_zalloc(sizeof(*hapd_iface)); - if (hapd_iface == NULL) - goto fail; - - hapd_iface->config_fname = os_strdup(config_file); - if (hapd_iface->config_fname == NULL) - goto fail; - - conf = hostapd_config_read(hapd_iface->config_fname); - if (conf == NULL) - goto fail; - hapd_iface->conf = conf; - - hapd_iface->num_bss = conf->num_bss; - hapd_iface->bss = os_zalloc(conf->num_bss * - sizeof(struct hostapd_data *)); - if (hapd_iface->bss == NULL) - goto fail; - - for (i = 0; i < conf->num_bss; i++) { - hapd = hapd_iface->bss[i] = - hostapd_alloc_bss_data(hapd_iface, conf, - &conf->bss[i]); - if (hapd == NULL) - goto fail; - } - - return hapd_iface; - -fail: - if (conf) - hostapd_config_free(conf); - if (hapd_iface) { - for (i = 0; hapd_iface->bss && i < hapd_iface->num_bss; i++) { - hapd = hapd_iface->bss[i]; - if (hapd && hapd->ssl_ctx) - tls_deinit(hapd->ssl_ctx); - } - - os_free(hapd_iface->config_fname); - os_free(hapd_iface->bss); - os_free(hapd_iface); - } - return NULL; -} - - -int main(int argc, char *argv[]) -{ - struct hapd_interfaces interfaces; - int ret = 1, k; - size_t i, j; - int c, debug = 0, daemonize = 0, tnc = 0; - char *pid_file = NULL; - - hostapd_logger_register_cb(hostapd_logger_cb); - - for (;;) { - c = getopt(argc, argv, "BdhKP:tv"); - if (c < 0) - break; - switch (c) { - case 'h': - usage(); - break; - case 'd': - debug++; - if (wpa_debug_level > 0) - wpa_debug_level--; - break; - case 'B': - daemonize++; - break; - case 'K': - wpa_debug_show_keys++; - break; - case 'P': - os_free(pid_file); - pid_file = os_rel2abs_path(optarg); - break; - case 't': - wpa_debug_timestamp++; - break; - case 'v': - show_version(); - exit(1); - break; - - default: - usage(); - break; - } - } - - if (optind == argc) - usage(); - - if (eap_server_register_methods()) { - wpa_printf(MSG_ERROR, "Failed to register EAP methods"); - return -1; - } - - interfaces.count = argc - optind; - - interfaces.iface = os_malloc(interfaces.count * - sizeof(struct hostapd_iface *)); - if (interfaces.iface == NULL) { - wpa_printf(MSG_ERROR, "malloc failed\n"); - return -1; - } - - if (eloop_init(&interfaces)) { - wpa_printf(MSG_ERROR, "Failed to initialize event loop"); - return -1; - } - -#ifndef CONFIG_NATIVE_WINDOWS - eloop_register_signal(SIGHUP, handle_reload, NULL); - eloop_register_signal(SIGUSR1, handle_dump_state, NULL); -#endif /* CONFIG_NATIVE_WINDOWS */ - eloop_register_signal_terminate(handle_term, NULL); - - /* Initialize interfaces */ - for (i = 0; i < interfaces.count; i++) { - wpa_printf(MSG_ERROR, "Configuration file: %s", - argv[optind + i]); - interfaces.iface[i] = hostapd_init(argv[optind + i]); - if (!interfaces.iface[i]) - goto out; - for (k = 0; k < debug; k++) { - if (interfaces.iface[i]->bss[0]->conf-> - logger_stdout_level > 0) - interfaces.iface[i]->bss[0]->conf-> - logger_stdout_level--; - } - - ret = hostapd_setup_interface(interfaces.iface[i]); - if (ret) - goto out; - - for (k = 0; k < (int) interfaces.iface[i]->num_bss; k++) { - if (interfaces.iface[i]->bss[0]->conf->tnc) - tnc++; - } - } - -#ifdef EAP_TNC - if (tnc && tncs_global_init() < 0) { - wpa_printf(MSG_ERROR, "Failed to initialize TNCS"); - goto out; - } -#endif /* EAP_TNC */ - - if (daemonize && os_daemonize(pid_file)) { - perror("daemon"); - goto out; - } - -#ifndef CONFIG_NATIVE_WINDOWS - openlog("hostapd", 0, LOG_DAEMON); -#endif /* CONFIG_NATIVE_WINDOWS */ - - eloop_run(); - - /* Disconnect associated stations from all interfaces and BSSes */ - for (i = 0; i < interfaces.count; i++) { - for (j = 0; j < interfaces.iface[i]->num_bss; j++) { - struct hostapd_data *hapd = - interfaces.iface[i]->bss[j]; - hostapd_free_stas(hapd); - hostapd_flush_old_stations(hapd); - } - } - - ret = 0; - - out: - /* Deinitialize all interfaces */ - for (i = 0; i < interfaces.count; i++) { - if (!interfaces.iface[i]) - continue; - hostapd_cleanup_iface_pre(interfaces.iface[i]); - for (j = 0; j < interfaces.iface[i]->num_bss; j++) { - struct hostapd_data *hapd = - interfaces.iface[i]->bss[j]; - hostapd_cleanup(hapd); - if (j == interfaces.iface[i]->num_bss - 1 && - hapd->driver) - hostapd_driver_deinit(hapd); - } - for (j = 0; j < interfaces.iface[i]->num_bss; j++) - os_free(interfaces.iface[i]->bss[j]); - hostapd_cleanup_iface(interfaces.iface[i]); - } - os_free(interfaces.iface); - -#ifdef EAP_TNC - tncs_global_deinit(); -#endif /* EAP_TNC */ - - eloop_destroy(); - -#ifndef CONFIG_NATIVE_WINDOWS - closelog(); -#endif /* CONFIG_NATIVE_WINDOWS */ - - eap_server_unregister_methods(); - - os_daemonize_terminate(pid_file); - os_free(pid_file); - - return ret; -} diff --git a/contrib/hostapd/hostapd/hostapd.h b/contrib/hostapd/hostapd/hostapd.h deleted file mode 100644 index 26f30d7016..0000000000 --- a/contrib/hostapd/hostapd/hostapd.h +++ /dev/null @@ -1,238 +0,0 @@ -/* - * hostapd / Initialization and configuration - * Host AP kernel driver - * Copyright (c) 2002-2008, Jouni Malinen - * Copyright (c) 2007-2008, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef HOSTAPD_H -#define HOSTAPD_H - -#include "common.h" -#include "ap.h" - -#ifndef ETH_ALEN -#define ETH_ALEN 6 -#endif -#ifndef IFNAMSIZ -#define IFNAMSIZ 16 -#endif -#ifndef ETH_P_ALL -#define ETH_P_ALL 0x0003 -#endif -#ifndef ETH_P_PAE -#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ -#endif /* ETH_P_PAE */ -#ifndef ETH_P_EAPOL -#define ETH_P_EAPOL ETH_P_PAE -#endif /* ETH_P_EAPOL */ - -#ifndef ETH_P_RRB -#define ETH_P_RRB 0x890D -#endif /* ETH_P_RRB */ - -#include "config.h" - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -#define MAX_VLAN_ID 4094 - -struct ieee8023_hdr { - u8 dest[6]; - u8 src[6]; - u16 ethertype; -} STRUCT_PACKED; - - -struct ieee80211_hdr { - le16 frame_control; - le16 duration_id; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; - le16 seq_ctrl; - /* followed by 'u8 addr4[6];' if ToDS and FromDS is set in data frame - */ -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -#define IEEE80211_DA_FROMDS addr1 -#define IEEE80211_BSSID_FROMDS addr2 -#define IEEE80211_SA_FROMDS addr3 - -#define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr)) - -#define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4)) - -/* MTU to be set for the wlan#ap device; this is mainly needed for IEEE 802.1X - * frames that might be longer than normal default MTU and they are not - * fragmented */ -#define HOSTAPD_MTU 2290 - -extern unsigned char rfc1042_header[6]; - -struct hostap_sta_driver_data { - unsigned long rx_packets, tx_packets, rx_bytes, tx_bytes; - unsigned long current_tx_rate; - unsigned long inactive_msec; - unsigned long flags; - unsigned long num_ps_buf_frames; - unsigned long tx_retry_failed; - unsigned long tx_retry_count; - int last_rssi; - int last_ack_rssi; -}; - -struct wpa_driver_ops; -struct wpa_ctrl_dst; -struct radius_server_data; -struct upnp_wps_device_sm; - -#ifdef CONFIG_FULL_DYNAMIC_VLAN -struct full_dynamic_vlan; -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - -/** - * struct hostapd_data - hostapd per-BSS data structure - */ -struct hostapd_data { - struct hostapd_iface *iface; - struct hostapd_config *iconf; - struct hostapd_bss_config *conf; - int interface_added; /* virtual interface added for this BSS */ - - u8 own_addr[ETH_ALEN]; - - int num_sta; /* number of entries in sta_list */ - struct sta_info *sta_list; /* STA info list head */ - struct sta_info *sta_hash[STA_HASH_SIZE]; - - /* pointers to STA info; based on allocated AID or NULL if AID free - * AID is in the range 1-2007, so sta_aid[0] corresponders to AID 1 - * and so on - */ - struct sta_info *sta_aid[MAX_AID_TABLE_SIZE]; - - const struct wpa_driver_ops *driver; - void *drv_priv; - - u8 *default_wep_key; - u8 default_wep_key_idx; - - struct radius_client_data *radius; - int radius_client_reconfigured; - u32 acct_session_id_hi, acct_session_id_lo; - - struct iapp_data *iapp; - - struct hostapd_cached_radius_acl *acl_cache; - struct hostapd_acl_query_data *acl_queries; - - struct wpa_authenticator *wpa_auth; - struct eapol_authenticator *eapol_auth; - - struct rsn_preauth_interface *preauth_iface; - time_t michael_mic_failure; - int michael_mic_failures; - int tkip_countermeasures; - - int ctrl_sock; - struct wpa_ctrl_dst *ctrl_dst; - - void *ssl_ctx; - void *eap_sim_db_priv; - struct radius_server_data *radius_srv; - - int parameter_set_count; - -#ifdef CONFIG_FULL_DYNAMIC_VLAN - struct full_dynamic_vlan *full_dynamic_vlan; -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - - struct l2_packet_data *l2; - struct wps_context *wps; - -#ifdef CONFIG_WPS - u8 *wps_beacon_ie; - size_t wps_beacon_ie_len; - u8 *wps_probe_resp_ie; - size_t wps_probe_resp_ie_len; - unsigned int ap_pin_failures; - struct upnp_wps_device_sm *wps_upnp; -#endif /* CONFIG_WPS */ -}; - - -/** - * struct hostapd_iface - hostapd per-interface data structure - */ -struct hostapd_iface { - char *config_fname; - struct hostapd_config *conf; - - size_t num_bss; - struct hostapd_data **bss; - - int num_ap; /* number of entries in ap_list */ - struct ap_info *ap_list; /* AP info list head */ - struct ap_info *ap_hash[STA_HASH_SIZE]; - struct ap_info *ap_iter_list; - - struct hostapd_hw_modes *hw_features; - int num_hw_features; - struct hostapd_hw_modes *current_mode; - /* Rates that are currently used (i.e., filtered copy of - * current_mode->channels */ - int num_rates; - struct hostapd_rate_data *current_rates; - - u16 hw_flags; - - /* Number of associated Non-ERP stations (i.e., stations using 802.11b - * in 802.11g BSS) */ - int num_sta_non_erp; - - /* Number of associated stations that do not support Short Slot Time */ - int num_sta_no_short_slot_time; - - /* Number of associated stations that do not support Short Preamble */ - int num_sta_no_short_preamble; - - int olbc; /* Overlapping Legacy BSS Condition */ - - /* Number of HT associated stations that do not support greenfield */ - int num_sta_ht_no_gf; - - /* Number of associated non-HT stations */ - int num_sta_no_ht; - - /* Number of HT associated stations 20 MHz */ - int num_sta_ht_20mhz; - - /* Overlapping BSS information */ - int olbc_ht; - -#ifdef CONFIG_IEEE80211N - u16 ht_op_mode; -#endif /* CONFIG_IEEE80211N */ -}; - -void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, - int reassoc); -int hostapd_reload_config(struct hostapd_iface *iface); - -#endif /* HOSTAPD_H */ diff --git a/contrib/hostapd/hostapd/hostapd_cli.c b/contrib/hostapd/hostapd/hostapd_cli.c deleted file mode 100644 index c2ecd4e23c..0000000000 --- a/contrib/hostapd/hostapd/hostapd_cli.c +++ /dev/null @@ -1,677 +0,0 @@ -/* - * hostapd - command line interface for hostapd daemon - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "wpa_ctrl.h" -#include "common.h" -#include "version.h" - - -static const char *hostapd_cli_version = -"hostapd_cli v" VERSION_STR "\n" -"Copyright (c) 2004-2009, Jouni Malinen and contributors"; - - -static const char *hostapd_cli_license = -"This program is free software. You can distribute it and/or modify it\n" -"under the terms of the GNU General Public License version 2.\n" -"\n" -"Alternatively, this software may be distributed under the terms of the\n" -"BSD license. See README and COPYING for more details.\n"; - -static const char *hostapd_cli_full_license = -"This program is free software; you can redistribute it and/or modify\n" -"it under the terms of the GNU General Public License version 2 as\n" -"published by the Free Software Foundation.\n" -"\n" -"This program is distributed in the hope that it will be useful,\n" -"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" -"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" -"GNU General Public License for more details.\n" -"\n" -"You should have received a copy of the GNU General Public License\n" -"along with this program; if not, write to the Free Software\n" -"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n" -"\n" -"Alternatively, this software may be distributed under the terms of the\n" -"BSD license.\n" -"\n" -"Redistribution and use in source and binary forms, with or without\n" -"modification, are permitted provided that the following conditions are\n" -"met:\n" -"\n" -"1. Redistributions of source code must retain the above copyright\n" -" notice, this list of conditions and the following disclaimer.\n" -"\n" -"2. Redistributions in binary form must reproduce the above copyright\n" -" notice, this list of conditions and the following disclaimer in the\n" -" documentation and/or other materials provided with the distribution.\n" -"\n" -"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n" -" names of its contributors may be used to endorse or promote products\n" -" derived from this software without specific prior written permission.\n" -"\n" -"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" -"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" -"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" -"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" -"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" -"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" -"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" -"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" -"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" -"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" -"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" -"\n"; - -static const char *commands_help = -"Commands:\n" -" mib get MIB variables (dot1x, dot11, radius)\n" -" sta get MIB variables for one station\n" -" all_sta get MIB variables for all stations\n" -" new_sta add a new station\n" -#ifdef CONFIG_IEEE80211W -" sa_query send SA Query to a station\n" -#endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_WPS -" wps_pin [timeout] add WPS Enrollee PIN (Device Password)\n" -" wps_pbc indicate button pushed to initiate PBC\n" -#endif /* CONFIG_WPS */ -" help show this usage help\n" -" interface [ifname] show interfaces/select interface\n" -" level change debug level\n" -" license show full hostapd_cli license\n" -" quit exit hostapd_cli\n"; - -static struct wpa_ctrl *ctrl_conn; -static int hostapd_cli_quit = 0; -static int hostapd_cli_attached = 0; -static const char *ctrl_iface_dir = "/var/run/hostapd"; -static char *ctrl_ifname = NULL; -static int ping_interval = 5; - - -static void usage(void) -{ - fprintf(stderr, "%s\n", hostapd_cli_version); - fprintf(stderr, - "\n" - "usage: hostapd_cli [-p] [-i] [-hv] " - "[-G] \\\n" - " [command..]\n" - "\n" - "Options:\n" - " -h help (show this usage text)\n" - " -v shown version information\n" - " -p path to find control sockets (default: " - "/var/run/hostapd)\n" - " -i Interface to listen on (default: first " - "interface found in the\n" - " socket path)\n\n" - "%s", - commands_help); -} - - -static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname) -{ - char *cfile; - int flen; - - if (ifname == NULL) - return NULL; - - flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2; - cfile = malloc(flen); - if (cfile == NULL) - return NULL; - snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname); - - ctrl_conn = wpa_ctrl_open(cfile); - free(cfile); - return ctrl_conn; -} - - -static void hostapd_cli_close_connection(void) -{ - if (ctrl_conn == NULL) - return; - - if (hostapd_cli_attached) { - wpa_ctrl_detach(ctrl_conn); - hostapd_cli_attached = 0; - } - wpa_ctrl_close(ctrl_conn); - ctrl_conn = NULL; -} - - -static void hostapd_cli_msg_cb(char *msg, size_t len) -{ - printf("%s\n", msg); -} - - -static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print) -{ - char buf[4096]; - size_t len; - int ret; - - if (ctrl_conn == NULL) { - printf("Not connected to hostapd - command dropped.\n"); - return -1; - } - len = sizeof(buf) - 1; - ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, - hostapd_cli_msg_cb); - if (ret == -2) { - printf("'%s' command timed out.\n", cmd); - return -2; - } else if (ret < 0) { - printf("'%s' command failed.\n", cmd); - return -1; - } - if (print) { - buf[len] = '\0'; - printf("%s", buf); - } - return 0; -} - - -static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd) -{ - return _wpa_ctrl_command(ctrl, cmd, 1); -} - - -static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "PING"); -} - - -static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "MIB"); -} - - -static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char buf[64]; - if (argc != 1) { - printf("Invalid 'sta' command - exactly one argument, STA " - "address, is required.\n"); - return -1; - } - snprintf(buf, sizeof(buf), "STA %s", argv[0]); - return wpa_ctrl_command(ctrl, buf); -} - - -static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char buf[64]; - if (argc != 1) { - printf("Invalid 'new_sta' command - exactly one argument, STA " - "address, is required.\n"); - return -1; - } - snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]); - return wpa_ctrl_command(ctrl, buf); -} - - -#ifdef CONFIG_IEEE80211W -static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char buf[64]; - if (argc != 1) { - printf("Invalid 'sa_query' command - exactly one argument, " - "STA address, is required.\n"); - return -1; - } - snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]); - return wpa_ctrl_command(ctrl, buf); -} -#endif /* CONFIG_IEEE80211W */ - - -#ifdef CONFIG_WPS -static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char buf[64]; - if (argc < 2) { - printf("Invalid 'wps_pin' command - at least two arguments, " - "UUID and PIN, are required.\n"); - return -1; - } - if (argc > 2) - snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s", - argv[0], argv[1], argv[2]); - else - snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]); - return wpa_ctrl_command(ctrl, buf); -} - - -static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "WPS_PBC"); -} -#endif /* CONFIG_WPS */ - - -static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd, - char *addr, size_t addr_len) -{ - char buf[4096], *pos; - size_t len; - int ret; - - if (ctrl_conn == NULL) { - printf("Not connected to hostapd - command dropped.\n"); - return -1; - } - len = sizeof(buf) - 1; - ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, - hostapd_cli_msg_cb); - if (ret == -2) { - printf("'%s' command timed out.\n", cmd); - return -2; - } else if (ret < 0) { - printf("'%s' command failed.\n", cmd); - return -1; - } - - buf[len] = '\0'; - if (memcmp(buf, "FAIL", 4) == 0) - return -1; - printf("%s", buf); - - pos = buf; - while (*pos != '\0' && *pos != '\n') - pos++; - *pos = '\0'; - os_strlcpy(addr, buf, addr_len); - return 0; -} - - -static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char addr[32], cmd[64]; - - if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr))) - return 0; - do { - snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr); - } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0); - - return -1; -} - - -static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - printf("%s", commands_help); - return 0; -} - - -static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license); - return 0; -} - - -static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - hostapd_cli_quit = 1; - return 0; -} - - -static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256]; - if (argc != 1) { - printf("Invalid LEVEL command: needs one argument (debug " - "level)\n"); - return 0; - } - snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]); - return wpa_ctrl_command(ctrl, cmd); -} - - -static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl) -{ - struct dirent *dent; - DIR *dir; - - dir = opendir(ctrl_iface_dir); - if (dir == NULL) { - printf("Control interface directory '%s' could not be " - "openned.\n", ctrl_iface_dir); - return; - } - - printf("Available interfaces:\n"); - while ((dent = readdir(dir))) { - if (strcmp(dent->d_name, ".") == 0 || - strcmp(dent->d_name, "..") == 0) - continue; - printf("%s\n", dent->d_name); - } - closedir(dir); -} - - -static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - if (argc < 1) { - hostapd_cli_list_interfaces(ctrl); - return 0; - } - - hostapd_cli_close_connection(); - free(ctrl_ifname); - ctrl_ifname = strdup(argv[0]); - - if (hostapd_cli_open_connection(ctrl_ifname)) { - printf("Connected to interface '%s.\n", ctrl_ifname); - if (wpa_ctrl_attach(ctrl_conn) == 0) { - hostapd_cli_attached = 1; - } else { - printf("Warning: Failed to attach to " - "hostapd.\n"); - } - } else { - printf("Could not connect to interface '%s' - re-trying\n", - ctrl_ifname); - } - return 0; -} - - -struct hostapd_cli_cmd { - const char *cmd; - int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]); -}; - -static struct hostapd_cli_cmd hostapd_cli_commands[] = { - { "ping", hostapd_cli_cmd_ping }, - { "mib", hostapd_cli_cmd_mib }, - { "sta", hostapd_cli_cmd_sta }, - { "all_sta", hostapd_cli_cmd_all_sta }, - { "new_sta", hostapd_cli_cmd_new_sta }, -#ifdef CONFIG_IEEE80211W - { "sa_query", hostapd_cli_cmd_sa_query }, -#endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_WPS - { "wps_pin", hostapd_cli_cmd_wps_pin }, - { "wps_pbc", hostapd_cli_cmd_wps_pbc }, -#endif /* CONFIG_WPS */ - { "help", hostapd_cli_cmd_help }, - { "interface", hostapd_cli_cmd_interface }, - { "level", hostapd_cli_cmd_level }, - { "license", hostapd_cli_cmd_license }, - { "quit", hostapd_cli_cmd_quit }, - { NULL, NULL } -}; - - -static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - struct hostapd_cli_cmd *cmd, *match = NULL; - int count; - - count = 0; - cmd = hostapd_cli_commands; - while (cmd->cmd) { - if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) { - match = cmd; - count++; - } - cmd++; - } - - if (count > 1) { - printf("Ambiguous command '%s'; possible commands:", argv[0]); - cmd = hostapd_cli_commands; - while (cmd->cmd) { - if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == - 0) { - printf(" %s", cmd->cmd); - } - cmd++; - } - printf("\n"); - } else if (count == 0) { - printf("Unknown command '%s'\n", argv[0]); - } else { - match->handler(ctrl, argc - 1, &argv[1]); - } -} - - -static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read) -{ - int first = 1; - if (ctrl_conn == NULL) - return; - while (wpa_ctrl_pending(ctrl)) { - char buf[256]; - size_t len = sizeof(buf) - 1; - if (wpa_ctrl_recv(ctrl, buf, &len) == 0) { - buf[len] = '\0'; - if (in_read && first) - printf("\n"); - first = 0; - printf("%s\n", buf); - } else { - printf("Could not read pending message.\n"); - break; - } - } -} - - -static void hostapd_cli_interactive(void) -{ - const int max_args = 10; - char cmd[256], *res, *argv[max_args], *pos; - int argc; - - printf("\nInteractive mode\n\n"); - - do { - hostapd_cli_recv_pending(ctrl_conn, 0); - printf("> "); - alarm(ping_interval); - res = fgets(cmd, sizeof(cmd), stdin); - alarm(0); - if (res == NULL) - break; - pos = cmd; - while (*pos != '\0') { - if (*pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } - argc = 0; - pos = cmd; - for (;;) { - while (*pos == ' ') - pos++; - if (*pos == '\0') - break; - argv[argc] = pos; - argc++; - if (argc == max_args) - break; - while (*pos != '\0' && *pos != ' ') - pos++; - if (*pos == ' ') - *pos++ = '\0'; - } - if (argc) - wpa_request(ctrl_conn, argc, argv); - } while (!hostapd_cli_quit); -} - - -static void hostapd_cli_terminate(int sig) -{ - hostapd_cli_close_connection(); - exit(0); -} - - -static void hostapd_cli_alarm(int sig) -{ - if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) { - printf("Connection to hostapd lost - trying to reconnect\n"); - hostapd_cli_close_connection(); - } - if (!ctrl_conn) { - ctrl_conn = hostapd_cli_open_connection(ctrl_ifname); - if (ctrl_conn) { - printf("Connection to hostapd re-established\n"); - if (wpa_ctrl_attach(ctrl_conn) == 0) { - hostapd_cli_attached = 1; - } else { - printf("Warning: Failed to attach to " - "hostapd.\n"); - } - } - } - if (ctrl_conn) - hostapd_cli_recv_pending(ctrl_conn, 1); - alarm(ping_interval); -} - - -int main(int argc, char *argv[]) -{ - int interactive; - int warning_displayed = 0; - int c; - - for (;;) { - c = getopt(argc, argv, "hG:i:p:v"); - if (c < 0) - break; - switch (c) { - case 'G': - ping_interval = atoi(optarg); - break; - case 'h': - usage(); - return 0; - case 'v': - printf("%s\n", hostapd_cli_version); - return 0; - case 'i': - free(ctrl_ifname); - ctrl_ifname = strdup(optarg); - break; - case 'p': - ctrl_iface_dir = optarg; - break; - default: - usage(); - return -1; - } - } - - interactive = argc == optind; - - if (interactive) { - printf("%s\n\n%s\n\n", hostapd_cli_version, - hostapd_cli_license); - } - - for (;;) { - if (ctrl_ifname == NULL) { - struct dirent *dent; - DIR *dir = opendir(ctrl_iface_dir); - if (dir) { - while ((dent = readdir(dir))) { - if (strcmp(dent->d_name, ".") == 0 || - strcmp(dent->d_name, "..") == 0) - continue; - printf("Selected interface '%s'\n", - dent->d_name); - ctrl_ifname = strdup(dent->d_name); - break; - } - closedir(dir); - } - } - ctrl_conn = hostapd_cli_open_connection(ctrl_ifname); - if (ctrl_conn) { - if (warning_displayed) - printf("Connection established.\n"); - break; - } - - if (!interactive) { - perror("Failed to connect to hostapd - " - "wpa_ctrl_open"); - return -1; - } - - if (!warning_displayed) { - printf("Could not connect to hostapd - re-trying\n"); - warning_displayed = 1; - } - sleep(1); - continue; - } - - signal(SIGINT, hostapd_cli_terminate); - signal(SIGTERM, hostapd_cli_terminate); - signal(SIGALRM, hostapd_cli_alarm); - - if (interactive) { - if (wpa_ctrl_attach(ctrl_conn) == 0) { - hostapd_cli_attached = 1; - } else { - printf("Warning: Failed to attach to hostapd.\n"); - } - hostapd_cli_interactive(); - } else - wpa_request(ctrl_conn, argc - optind, &argv[optind]); - - free(ctrl_ifname); - hostapd_cli_close_connection(); - return 0; -} diff --git a/contrib/hostapd/hostapd/hw_features.c b/contrib/hostapd/hostapd/hw_features.c deleted file mode 100644 index 1d6299e625..0000000000 --- a/contrib/hostapd/hostapd/hw_features.c +++ /dev/null @@ -1,494 +0,0 @@ -/* - * hostapd / Hardware feature query and different modes - * Copyright 2002-2003, Instant802 Networks, Inc. - * Copyright 2005-2006, Devicescape Software, Inc. - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "hostapd.h" -#include "hw_features.h" -#include "driver.h" -#include "config.h" - - -void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, - size_t num_hw_features) -{ - size_t i; - - if (hw_features == NULL) - return; - - for (i = 0; i < num_hw_features; i++) { - os_free(hw_features[i].channels); - os_free(hw_features[i].rates); - } - - os_free(hw_features); -} - - -int hostapd_get_hw_features(struct hostapd_iface *iface) -{ - struct hostapd_data *hapd = iface->bss[0]; - int ret = 0, i, j; - u16 num_modes, flags; - struct hostapd_hw_modes *modes; - - if (hostapd_drv_none(hapd)) - return -1; - modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags); - if (modes == NULL) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "Fetching hardware channel/rate support not " - "supported."); - return -1; - } - - iface->hw_flags = flags; - - hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); - iface->hw_features = modes; - iface->num_hw_features = num_modes; - - for (i = 0; i < num_modes; i++) { - struct hostapd_hw_modes *feature = &modes[i]; - /* set flag for channels we can use in current regulatory - * domain */ - for (j = 0; j < feature->num_channels; j++) { - /* - * Disable all channels that are marked not to allow - * IBSS operation or active scanning. In addition, - * disable all channels that require radar detection, - * since that (in addition to full DFS) is not yet - * supported. - */ - if (feature->channels[j].flag & - (HOSTAPD_CHAN_NO_IBSS | - HOSTAPD_CHAN_PASSIVE_SCAN | - HOSTAPD_CHAN_RADAR)) - feature->channels[j].flag |= - HOSTAPD_CHAN_DISABLED; - if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED) - continue; - wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d " - "chan=%d freq=%d MHz max_tx_power=%d dBm", - feature->mode, - feature->channels[j].chan, - feature->channels[j].freq, - feature->channels[j].max_tx_power); - } - } - - return ret; -} - - -static int hostapd_prepare_rates(struct hostapd_data *hapd, - struct hostapd_hw_modes *mode) -{ - int i, num_basic_rates = 0; - int basic_rates_a[] = { 60, 120, 240, -1 }; - int basic_rates_b[] = { 10, 20, -1 }; - int basic_rates_g[] = { 10, 20, 55, 110, -1 }; - int *basic_rates; - - if (hapd->iconf->basic_rates) - basic_rates = hapd->iconf->basic_rates; - else switch (mode->mode) { - case HOSTAPD_MODE_IEEE80211A: - basic_rates = basic_rates_a; - break; - case HOSTAPD_MODE_IEEE80211B: - basic_rates = basic_rates_b; - break; - case HOSTAPD_MODE_IEEE80211G: - basic_rates = basic_rates_g; - break; - default: - return -1; - } - - if (hostapd_set_rate_sets(hapd, hapd->iconf->supported_rates, - basic_rates, mode->mode)) { - wpa_printf(MSG_ERROR, "Failed to update rate sets in kernel " - "module"); - } - - os_free(hapd->iface->current_rates); - hapd->iface->num_rates = 0; - - hapd->iface->current_rates = - os_malloc(mode->num_rates * sizeof(struct hostapd_rate_data)); - if (!hapd->iface->current_rates) { - wpa_printf(MSG_ERROR, "Failed to allocate memory for rate " - "table."); - return -1; - } - - for (i = 0; i < mode->num_rates; i++) { - struct hostapd_rate_data *rate; - - if (hapd->iconf->supported_rates && - !hostapd_rate_found(hapd->iconf->supported_rates, - mode->rates[i].rate)) - continue; - - rate = &hapd->iface->current_rates[hapd->iface->num_rates]; - os_memcpy(rate, &mode->rates[i], - sizeof(struct hostapd_rate_data)); - if (hostapd_rate_found(basic_rates, rate->rate)) { - rate->flags |= HOSTAPD_RATE_BASIC; - num_basic_rates++; - } else - rate->flags &= ~HOSTAPD_RATE_BASIC; - wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x", - hapd->iface->num_rates, rate->rate, rate->flags); - hapd->iface->num_rates++; - } - - if (hapd->iface->num_rates == 0 || num_basic_rates == 0) { - wpa_printf(MSG_ERROR, "No rates remaining in supported/basic " - "rate sets (%d,%d).", - hapd->iface->num_rates, num_basic_rates); - return -1; - } - - return 0; -} - - -#ifdef CONFIG_IEEE80211N -static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface) -{ - int sec_chan, ok, j, first; - int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, - 184, 192 }; - size_t k; - - if (!iface->conf->secondary_channel) - return 1; /* HT40 not used */ - - sec_chan = iface->conf->channel + iface->conf->secondary_channel * 4; - wpa_printf(MSG_DEBUG, "HT40: control channel: %d " - "secondary channel: %d", - iface->conf->channel, sec_chan); - - /* Verify that HT40 secondary channel is an allowed 20 MHz - * channel */ - ok = 0; - for (j = 0; j < iface->current_mode->num_channels; j++) { - struct hostapd_channel_data *chan = - &iface->current_mode->channels[j]; - if (!(chan->flag & HOSTAPD_CHAN_DISABLED) && - chan->chan == sec_chan) { - ok = 1; - break; - } - } - if (!ok) { - wpa_printf(MSG_ERROR, "HT40 secondary channel %d not allowed", - sec_chan); - return 0; - } - - /* - * Verify that HT40 primary,secondary channel pair is allowed per - * IEEE 802.11n Annex J. This is only needed for 5 GHz band since - * 2.4 GHz rules allow all cases where the secondary channel fits into - * the list of allowed channels (already checked above). - */ - if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A) - return 1; - - if (iface->conf->secondary_channel > 0) - first = iface->conf->channel; - else - first = sec_chan; - - ok = 0; - for (k = 0; k < sizeof(allowed) / sizeof(allowed[0]); k++) { - if (first == allowed[k]) { - ok = 1; - break; - } - } - if (!ok) { - wpa_printf(MSG_ERROR, "HT40 channel pair (%d, %d) not allowed", - iface->conf->channel, - iface->conf->secondary_channel); - return 0; - } - - return 1; -} - - -static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface) -{ - u16 hw = iface->current_mode->ht_capab; - u16 conf = iface->conf->ht_capab; - - if (!iface->conf->ieee80211n) - return 1; - - if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) && - !(hw & HT_CAP_INFO_LDPC_CODING_CAP)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [LDPC]"); - return 0; - } - - if ((conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) && - !(hw & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [HT40*]"); - return 0; - } - - if ((conf & HT_CAP_INFO_SMPS_MASK) != (hw & HT_CAP_INFO_SMPS_MASK) && - (conf & HT_CAP_INFO_SMPS_MASK) != HT_CAP_INFO_SMPS_DISABLED) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [SMPS-*]"); - return 0; - } - - if ((conf & HT_CAP_INFO_GREEN_FIELD) && - !(hw & HT_CAP_INFO_GREEN_FIELD)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [GF]"); - return 0; - } - - if ((conf & HT_CAP_INFO_SHORT_GI20MHZ) && - !(hw & HT_CAP_INFO_SHORT_GI20MHZ)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [SHORT-GI-20]"); - return 0; - } - - if ((conf & HT_CAP_INFO_SHORT_GI40MHZ) && - !(hw & HT_CAP_INFO_SHORT_GI40MHZ)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [SHORT-GI-40]"); - return 0; - } - - if ((conf & HT_CAP_INFO_TX_STBC) && !(hw & HT_CAP_INFO_TX_STBC)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [TX-STBC]"); - return 0; - } - - if ((conf & HT_CAP_INFO_RX_STBC_MASK) > - (hw & HT_CAP_INFO_RX_STBC_MASK)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [RX-STBC*]"); - return 0; - } - - if ((conf & HT_CAP_INFO_DELAYED_BA) && - !(hw & HT_CAP_INFO_DELAYED_BA)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [DELAYED-BA]"); - return 0; - } - - if ((conf & HT_CAP_INFO_MAX_AMSDU_SIZE) && - !(hw & HT_CAP_INFO_MAX_AMSDU_SIZE)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [MAX-AMSDU-7935]"); - return 0; - } - - if ((conf & HT_CAP_INFO_DSSS_CCK40MHZ) && - !(hw & HT_CAP_INFO_DSSS_CCK40MHZ)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [DSSS_CCK-40]"); - return 0; - } - - if ((conf & HT_CAP_INFO_PSMP_SUPP) && !(hw & HT_CAP_INFO_PSMP_SUPP)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [PSMP]"); - return 0; - } - - if ((conf & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT) && - !(hw & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [LSIG-TXOP-PROT]"); - return 0; - } - - return 1; -} -#endif /* CONFIG_IEEE80211N */ - - -/** - * hostapd_select_hw_mode - Select the hardware mode - * @iface: Pointer to interface data. - * Returns: 0 on success, -1 on failure - * - * Sets up the hardware mode, channel, rates, and passive scanning - * based on the configuration. - */ -int hostapd_select_hw_mode(struct hostapd_iface *iface) -{ - int i, j, ok, ret; - - if (iface->num_hw_features < 1) - return -1; - - iface->current_mode = NULL; - for (i = 0; i < iface->num_hw_features; i++) { - struct hostapd_hw_modes *mode = &iface->hw_features[i]; - if (mode->mode == (int) iface->conf->hw_mode) { - iface->current_mode = mode; - break; - } - } - - if (iface->current_mode == NULL) { - wpa_printf(MSG_ERROR, "Hardware does not support configured " - "mode"); - hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_WARNING, - "Hardware does not support configured mode " - "(%d)", (int) iface->conf->hw_mode); - return -1; - } - - ok = 0; - for (j = 0; j < iface->current_mode->num_channels; j++) { - struct hostapd_channel_data *chan = - &iface->current_mode->channels[j]; - if (!(chan->flag & HOSTAPD_CHAN_DISABLED) && - (chan->chan == iface->conf->channel)) { - ok = 1; - break; - } - } - if (iface->conf->channel == 0) { - /* TODO: could request a scan of neighboring BSSes and select - * the channel automatically */ - wpa_printf(MSG_ERROR, "Channel not configured " - "(hw_mode/channel in hostapd.conf)"); - return -1; - } - if (ok == 0 && iface->conf->channel != 0) { - hostapd_logger(iface->bss[0], NULL, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_WARNING, - "Configured channel (%d) not found from the " - "channel list of current mode (%d) %s", - iface->conf->channel, - iface->current_mode->mode, - hostapd_hw_mode_txt(iface->current_mode->mode)); - iface->current_mode = NULL; - } - - if (iface->current_mode == NULL) { - hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_WARNING, - "Hardware does not support configured channel"); - return -1; - } - -#ifdef CONFIG_IEEE80211N - if (!ieee80211n_allowed_ht40_channel_pair(iface)) - return -1; - if (!ieee80211n_supported_ht_capab(iface)) - return -1; -#endif /* CONFIG_IEEE80211N */ - - if (hostapd_prepare_rates(iface->bss[0], iface->current_mode)) { - wpa_printf(MSG_ERROR, "Failed to prepare rates table."); - hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_WARNING, - "Failed to prepare rates table."); - return -1; - } - - ret = hostapd_passive_scan(iface->bss[0], 0, - iface->conf->passive_scan_mode, - iface->conf->passive_scan_interval, - iface->conf->passive_scan_listen, - NULL, NULL); - if (ret) { - if (ret == -1) { - wpa_printf(MSG_DEBUG, "Passive scanning not " - "supported"); - } else { - wpa_printf(MSG_ERROR, "Could not set passive " - "scanning: %s", strerror(ret)); - } - ret = 0; - } - - return ret; -} - - -const char * hostapd_hw_mode_txt(int mode) -{ - switch (mode) { - case HOSTAPD_MODE_IEEE80211A: - return "IEEE 802.11a"; - case HOSTAPD_MODE_IEEE80211B: - return "IEEE 802.11b"; - case HOSTAPD_MODE_IEEE80211G: - return "IEEE 802.11g"; - default: - return "UNKNOWN"; - } -} - - -int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan) -{ - int i; - - if (!hapd->iface->current_mode) - return 0; - - for (i = 0; i < hapd->iface->current_mode->num_channels; i++) { - struct hostapd_channel_data *ch = - &hapd->iface->current_mode->channels[i]; - if (ch->chan == chan) - return ch->freq; - } - - return 0; -} - - -int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq) -{ - int i; - - if (!hapd->iface->current_mode) - return 0; - - for (i = 0; i < hapd->iface->current_mode->num_channels; i++) { - struct hostapd_channel_data *ch = - &hapd->iface->current_mode->channels[i]; - if (ch->freq == freq) - return ch->chan; - } - - return 0; -} diff --git a/contrib/hostapd/hostapd/hw_features.h b/contrib/hostapd/hostapd/hw_features.h deleted file mode 100644 index 7d43c89b66..0000000000 --- a/contrib/hostapd/hostapd/hw_features.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * hostapd / Hardware feature query and different modes - * Copyright 2002-2003, Instant802 Networks, Inc. - * Copyright 2005-2006, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef HW_FEATURES_H -#define HW_FEATURES_H - -#define HOSTAPD_CHAN_DISABLED 0x00000001 -#define HOSTAPD_CHAN_PASSIVE_SCAN 0x00000002 -#define HOSTAPD_CHAN_NO_IBSS 0x00000004 -#define HOSTAPD_CHAN_RADAR 0x00000008 - -struct hostapd_channel_data { - short chan; /* channel number (IEEE 802.11) */ - short freq; /* frequency in MHz */ - int flag; /* flag for hostapd use (HOSTAPD_CHAN_*) */ - u8 max_tx_power; /* maximum transmit power in dBm */ -}; - -#define HOSTAPD_RATE_ERP 0x00000001 -#define HOSTAPD_RATE_BASIC 0x00000002 -#define HOSTAPD_RATE_PREAMBLE2 0x00000004 -#define HOSTAPD_RATE_SUPPORTED 0x00000010 -#define HOSTAPD_RATE_OFDM 0x00000020 -#define HOSTAPD_RATE_CCK 0x00000040 -#define HOSTAPD_RATE_MANDATORY 0x00000100 - -struct hostapd_rate_data { - int rate; /* rate in 100 kbps */ - int flags; /* HOSTAPD_RATE_ flags */ -}; - -struct hostapd_hw_modes { - int mode; - int num_channels; - struct hostapd_channel_data *channels; - int num_rates; - struct hostapd_rate_data *rates; - u16 ht_capab; -}; - - -void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, - size_t num_hw_features); -int hostapd_get_hw_features(struct hostapd_iface *iface); -int hostapd_select_hw_mode(struct hostapd_iface *iface); -const char * hostapd_hw_mode_txt(int mode); -int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan); -int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq); - -#endif /* HW_FEATURES_H */ diff --git a/contrib/hostapd/hostapd/iapp.c b/contrib/hostapd/hostapd/iapp.c deleted file mode 100644 index 6d6dba8f7b..0000000000 --- a/contrib/hostapd/hostapd/iapp.c +++ /dev/null @@ -1,553 +0,0 @@ -/* - * hostapd / IEEE 802.11F-2003 Inter-Access Point Protocol (IAPP) - * Copyright (c) 2002-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * Note: IEEE 802.11F-2003 was a experimental use specification. It has expired - * and IEEE has withdrawn it. In other words, it is likely better to look at - * using some other mechanism for AP-to-AP communication than extending the - * implementation here. - */ - -/* TODO: - * Level 1: no administrative or security support - * (e.g., static BSSID to IP address mapping in each AP) - * Level 2: support for dynamic mapping of BSSID to IP address - * Level 3: support for encryption and authentication of IAPP messages - * - add support for MOVE-notify and MOVE-response (this requires support for - * finding out IP address for previous AP using RADIUS) - * - add support for Send- and ACK-Security-Block to speedup IEEE 802.1X during - * reassociation to another AP - * - implement counters etc. for IAPP MIB - * - verify endianness of fields in IAPP messages; are they big-endian as - * used here? - * - RADIUS connection for AP registration and BSSID to IP address mapping - * - TCP connection for IAPP MOVE, CACHE - * - broadcast ESP for IAPP ADD-notify - * - ESP for IAPP MOVE messages - * - security block sending/processing - * - IEEE 802.11 context transfer - */ - -#include "includes.h" -#include -#include -#ifdef USE_KERNEL_HEADERS -#include -#else /* USE_KERNEL_HEADERS */ -#include -#endif /* USE_KERNEL_HEADERS */ - -#include "hostapd.h" -#include "ieee802_11.h" -#include "iapp.h" -#include "eloop.h" -#include "sta_info.h" - - -#define IAPP_MULTICAST "224.0.1.178" -#define IAPP_UDP_PORT 3517 -#define IAPP_TCP_PORT 3517 - -struct iapp_hdr { - u8 version; - u8 command; - be16 identifier; - be16 length; - /* followed by length-6 octets of data */ -} __attribute__ ((packed)); - -#define IAPP_VERSION 0 - -enum IAPP_COMMAND { - IAPP_CMD_ADD_notify = 0, - IAPP_CMD_MOVE_notify = 1, - IAPP_CMD_MOVE_response = 2, - IAPP_CMD_Send_Security_Block = 3, - IAPP_CMD_ACK_Security_Block = 4, - IAPP_CMD_CACHE_notify = 5, - IAPP_CMD_CACHE_response = 6, -}; - - -/* ADD-notify - multicast UDP on the local LAN */ -struct iapp_add_notify { - u8 addr_len; /* ETH_ALEN */ - u8 reserved; - u8 mac_addr[ETH_ALEN]; - be16 seq_num; -} __attribute__ ((packed)); - - -/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ -struct iapp_layer2_update { - u8 da[ETH_ALEN]; /* broadcast */ - u8 sa[ETH_ALEN]; /* STA addr */ - be16 len; /* 6 */ - u8 dsap; /* null DSAP address */ - u8 ssap; /* null SSAP address, CR=Response */ - u8 control; - u8 xid_info[3]; -} __attribute__ ((packed)); - - -/* MOVE-notify - unicast TCP */ -struct iapp_move_notify { - u8 addr_len; /* ETH_ALEN */ - u8 reserved; - u8 mac_addr[ETH_ALEN]; - u16 seq_num; - u16 ctx_block_len; - /* followed by ctx_block_len bytes */ -} __attribute__ ((packed)); - - -/* MOVE-response - unicast TCP */ -struct iapp_move_response { - u8 addr_len; /* ETH_ALEN */ - u8 status; - u8 mac_addr[ETH_ALEN]; - u16 seq_num; - u16 ctx_block_len; - /* followed by ctx_block_len bytes */ -} __attribute__ ((packed)); - -enum { - IAPP_MOVE_SUCCESSFUL = 0, - IAPP_MOVE_DENIED = 1, - IAPP_MOVE_STALE_MOVE = 2, -}; - - -/* CACHE-notify */ -struct iapp_cache_notify { - u8 addr_len; /* ETH_ALEN */ - u8 reserved; - u8 mac_addr[ETH_ALEN]; - u16 seq_num; - u8 current_ap[ETH_ALEN]; - u16 ctx_block_len; - /* ctx_block_len bytes of context block followed by 16-bit context - * timeout */ -} __attribute__ ((packed)); - - -/* CACHE-response - unicast TCP */ -struct iapp_cache_response { - u8 addr_len; /* ETH_ALEN */ - u8 status; - u8 mac_addr[ETH_ALEN]; - u16 seq_num; -} __attribute__ ((packed)); - -enum { - IAPP_CACHE_SUCCESSFUL = 0, - IAPP_CACHE_STALE_CACHE = 1, -}; - - -/* Send-Security-Block - unicast TCP */ -struct iapp_send_security_block { - u8 iv[8]; - u16 sec_block_len; - /* followed by sec_block_len bytes of security block */ -} __attribute__ ((packed)); - - -/* ACK-Security-Block - unicast TCP */ -struct iapp_ack_security_block { - u8 iv[8]; - u8 new_ap_ack_authenticator[48]; -} __attribute__ ((packed)); - - -struct iapp_data { - struct hostapd_data *hapd; - u16 identifier; /* next IAPP identifier */ - struct in_addr own, multicast; - int udp_sock; - int packet_sock; -}; - - -static void iapp_send_add(struct iapp_data *iapp, u8 *mac_addr, u16 seq_num) -{ - char buf[128]; - struct iapp_hdr *hdr; - struct iapp_add_notify *add; - struct sockaddr_in addr; - - /* Send IAPP ADD-notify to remove possible association from other APs - */ - - hdr = (struct iapp_hdr *) buf; - hdr->version = IAPP_VERSION; - hdr->command = IAPP_CMD_ADD_notify; - hdr->identifier = host_to_be16(iapp->identifier++); - hdr->length = host_to_be16(sizeof(*hdr) + sizeof(*add)); - - add = (struct iapp_add_notify *) (hdr + 1); - add->addr_len = ETH_ALEN; - add->reserved = 0; - os_memcpy(add->mac_addr, mac_addr, ETH_ALEN); - - add->seq_num = host_to_be16(seq_num); - - os_memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = iapp->multicast.s_addr; - addr.sin_port = htons(IAPP_UDP_PORT); - if (sendto(iapp->udp_sock, buf, (char *) (add + 1) - buf, 0, - (struct sockaddr *) &addr, sizeof(addr)) < 0) - perror("sendto[IAPP-ADD]"); -} - - -static void iapp_send_layer2_update(struct iapp_data *iapp, u8 *addr) -{ - struct iapp_layer2_update msg; - - /* Send Level 2 Update Frame to update forwarding tables in layer 2 - * bridge devices */ - - /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID) - * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ - - os_memset(msg.da, 0xff, ETH_ALEN); - os_memcpy(msg.sa, addr, ETH_ALEN); - msg.len = host_to_be16(6); - msg.dsap = 0; /* NULL DSAP address */ - msg.ssap = 0x01; /* NULL SSAP address, CR Bit: Response */ - msg.control = 0xaf; /* XID response lsb.1111F101. - * F=0 (no poll command; unsolicited frame) */ - msg.xid_info[0] = 0x81; /* XID format identifier */ - msg.xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */ - msg.xid_info[2] = 1 << 1; /* XID sender's receive window size (RW) - * FIX: what is correct RW with 802.11? */ - - if (send(iapp->packet_sock, &msg, sizeof(msg), 0) < 0) - perror("send[L2 Update]"); -} - - -/** - * iapp_new_station - IAPP processing for a new STA - * @iapp: IAPP data - * @sta: The associated station - */ -void iapp_new_station(struct iapp_data *iapp, struct sta_info *sta) -{ - struct ieee80211_mgmt *assoc; - u16 seq; - - if (iapp == NULL) - return; - - assoc = sta->last_assoc_req; - seq = assoc ? WLAN_GET_SEQ_SEQ(le_to_host16(assoc->seq_ctrl)) : 0; - - /* IAPP-ADD.request(MAC Address, Sequence Number, Timeout) */ - hostapd_logger(iapp->hapd, sta->addr, HOSTAPD_MODULE_IAPP, - HOSTAPD_LEVEL_DEBUG, "IAPP-ADD.request(seq=%d)", seq); - iapp_send_layer2_update(iapp, sta->addr); - iapp_send_add(iapp, sta->addr, seq); - - if (assoc && WLAN_FC_GET_STYPE(le_to_host16(assoc->frame_control)) == - WLAN_FC_STYPE_REASSOC_REQ) { - /* IAPP-MOVE.request(MAC Address, Sequence Number, Old AP, - * Context Block, Timeout) - */ - /* TODO: Send IAPP-MOVE to the old AP; Map Old AP BSSID to - * IP address */ - } -} - - -static void iapp_process_add_notify(struct iapp_data *iapp, - struct sockaddr_in *from, - struct iapp_hdr *hdr, int len) -{ - struct iapp_add_notify *add = (struct iapp_add_notify *) (hdr + 1); - struct sta_info *sta; - - if (len != sizeof(*add)) { - printf("Invalid IAPP-ADD packet length %d (expected %lu)\n", - len, (unsigned long) sizeof(*add)); - return; - } - - sta = ap_get_sta(iapp->hapd, add->mac_addr); - - /* IAPP-ADD.indication(MAC Address, Sequence Number) */ - hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP, - HOSTAPD_LEVEL_INFO, - "Received IAPP ADD-notify (seq# %d) from %s:%d%s", - be_to_host16(add->seq_num), - inet_ntoa(from->sin_addr), ntohs(from->sin_port), - sta ? "" : " (STA not found)"); - - if (!sta) - return; - - /* TODO: could use seq_num to try to determine whether last association - * to this AP is newer than the one advertised in IAPP-ADD. Although, - * this is not really a reliable verification. */ - - hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP, - HOSTAPD_LEVEL_DEBUG, - "Removing STA due to IAPP ADD-notify"); - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED); - eloop_cancel_timeout(ap_handle_timer, iapp->hapd, sta); - eloop_register_timeout(0, 0, ap_handle_timer, iapp->hapd, sta); - sta->timeout_next = STA_REMOVE; -} - - -/** - * iapp_receive_udp - Process IAPP UDP frames - * @sock: File descriptor for the socket - * @eloop_ctx: IAPP data (struct iapp_data *) - * @sock_ctx: Not used - */ -static void iapp_receive_udp(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct iapp_data *iapp = eloop_ctx; - int len, hlen; - unsigned char buf[128]; - struct sockaddr_in from; - socklen_t fromlen; - struct iapp_hdr *hdr; - - /* Handle incoming IAPP frames (over UDP/IP) */ - - fromlen = sizeof(from); - len = recvfrom(iapp->udp_sock, buf, sizeof(buf), 0, - (struct sockaddr *) &from, &fromlen); - if (len < 0) { - perror("recvfrom"); - return; - } - - if (from.sin_addr.s_addr == iapp->own.s_addr) - return; /* ignore own IAPP messages */ - - hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP, - HOSTAPD_LEVEL_DEBUG, - "Received %d byte IAPP frame from %s%s\n", - len, inet_ntoa(from.sin_addr), - len < (int) sizeof(*hdr) ? " (too short)" : ""); - - if (len < (int) sizeof(*hdr)) - return; - - hdr = (struct iapp_hdr *) buf; - hlen = be_to_host16(hdr->length); - hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP, - HOSTAPD_LEVEL_DEBUG, - "RX: version=%d command=%d id=%d len=%d\n", - hdr->version, hdr->command, - be_to_host16(hdr->identifier), hlen); - if (hdr->version != IAPP_VERSION) { - printf("Dropping IAPP frame with unknown version %d\n", - hdr->version); - return; - } - if (hlen > len) { - printf("Underflow IAPP frame (hlen=%d len=%d)\n", hlen, len); - return; - } - if (hlen < len) { - printf("Ignoring %d extra bytes from IAPP frame\n", - len - hlen); - len = hlen; - } - - switch (hdr->command) { - case IAPP_CMD_ADD_notify: - iapp_process_add_notify(iapp, &from, hdr, hlen - sizeof(*hdr)); - break; - case IAPP_CMD_MOVE_notify: - /* TODO: MOVE is using TCP; so move this to TCP handler once it - * is implemented.. */ - /* IAPP-MOVE.indication(MAC Address, New BSSID, - * Sequence Number, AP Address, Context Block) */ - /* TODO: process */ - break; - default: - printf("Unknown IAPP command %d\n", hdr->command); - break; - } -} - - -struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface) -{ - struct ifreq ifr; - struct sockaddr_ll addr; - int ifindex; - struct sockaddr_in *paddr, uaddr; - struct iapp_data *iapp; - struct ip_mreqn mreq; - - iapp = os_zalloc(sizeof(*iapp)); - if (iapp == NULL) - return NULL; - iapp->hapd = hapd; - iapp->udp_sock = iapp->packet_sock = -1; - - /* TODO: - * open socket for sending and receiving IAPP frames over TCP - */ - - iapp->udp_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (iapp->udp_sock < 0) { - perror("socket[PF_INET,SOCK_DGRAM]"); - iapp_deinit(iapp); - return NULL; - } - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); - if (ioctl(iapp->udp_sock, SIOCGIFINDEX, &ifr) != 0) { - perror("ioctl(SIOCGIFINDEX)"); - iapp_deinit(iapp); - return NULL; - } - ifindex = ifr.ifr_ifindex; - - if (ioctl(iapp->udp_sock, SIOCGIFADDR, &ifr) != 0) { - perror("ioctl(SIOCGIFADDR)"); - iapp_deinit(iapp); - return NULL; - } - paddr = (struct sockaddr_in *) &ifr.ifr_addr; - if (paddr->sin_family != AF_INET) { - printf("Invalid address family %i (SIOCGIFADDR)\n", - paddr->sin_family); - iapp_deinit(iapp); - return NULL; - } - iapp->own.s_addr = paddr->sin_addr.s_addr; - - if (ioctl(iapp->udp_sock, SIOCGIFBRDADDR, &ifr) != 0) { - perror("ioctl(SIOCGIFBRDADDR)"); - iapp_deinit(iapp); - return NULL; - } - paddr = (struct sockaddr_in *) &ifr.ifr_addr; - if (paddr->sin_family != AF_INET) { - printf("Invalid address family %i (SIOCGIFBRDADDR)\n", - paddr->sin_family); - iapp_deinit(iapp); - return NULL; - } - inet_aton(IAPP_MULTICAST, &iapp->multicast); - - os_memset(&uaddr, 0, sizeof(uaddr)); - uaddr.sin_family = AF_INET; - uaddr.sin_port = htons(IAPP_UDP_PORT); - if (bind(iapp->udp_sock, (struct sockaddr *) &uaddr, - sizeof(uaddr)) < 0) { - perror("bind[UDP]"); - iapp_deinit(iapp); - return NULL; - } - - os_memset(&mreq, 0, sizeof(mreq)); - mreq.imr_multiaddr = iapp->multicast; - mreq.imr_address.s_addr = INADDR_ANY; - mreq.imr_ifindex = 0; - if (setsockopt(iapp->udp_sock, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, - sizeof(mreq)) < 0) { - perror("setsockopt[UDP,IP_ADD_MEMBERSHIP]"); - iapp_deinit(iapp); - return NULL; - } - - iapp->packet_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (iapp->packet_sock < 0) { - perror("socket[PF_PACKET,SOCK_RAW]"); - iapp_deinit(iapp); - return NULL; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sll_family = AF_PACKET; - addr.sll_ifindex = ifindex; - if (bind(iapp->packet_sock, (struct sockaddr *) &addr, - sizeof(addr)) < 0) { - perror("bind[PACKET]"); - iapp_deinit(iapp); - return NULL; - } - - if (eloop_register_read_sock(iapp->udp_sock, iapp_receive_udp, - iapp, NULL)) { - printf("Could not register read socket for IAPP.\n"); - iapp_deinit(iapp); - return NULL; - } - - printf("IEEE 802.11F (IAPP) using interface %s\n", iface); - - /* TODO: For levels 2 and 3: send RADIUS Initiate-Request, receive - * RADIUS Initiate-Accept or Initiate-Reject. IAPP port should actually - * be openned only after receiving Initiate-Accept. If Initiate-Reject - * is received, IAPP is not started. */ - - return iapp; -} - - -void iapp_deinit(struct iapp_data *iapp) -{ - struct ip_mreqn mreq; - - if (iapp == NULL) - return; - - if (iapp->udp_sock >= 0) { - os_memset(&mreq, 0, sizeof(mreq)); - mreq.imr_multiaddr = iapp->multicast; - mreq.imr_address.s_addr = INADDR_ANY; - mreq.imr_ifindex = 0; - if (setsockopt(iapp->udp_sock, SOL_IP, IP_DROP_MEMBERSHIP, - &mreq, sizeof(mreq)) < 0) { - perror("setsockopt[UDP,IP_DEL_MEMBERSHIP]"); - } - - eloop_unregister_read_sock(iapp->udp_sock); - close(iapp->udp_sock); - } - if (iapp->packet_sock >= 0) { - eloop_unregister_read_sock(iapp->packet_sock); - close(iapp->packet_sock); - } - os_free(iapp); -} - -int iapp_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss) -{ - if (hapd->conf->ieee802_11f != oldbss->ieee802_11f || - os_strcmp(hapd->conf->iapp_iface, oldbss->iapp_iface) != 0) { - iapp_deinit(hapd->iapp); - hapd->iapp = NULL; - - if (hapd->conf->ieee802_11f) { - hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface); - if (hapd->iapp == NULL) - return -1; - } - } - - return 0; -} diff --git a/contrib/hostapd/hostapd/iapp.h b/contrib/hostapd/hostapd/iapp.h deleted file mode 100644 index 86de592560..0000000000 --- a/contrib/hostapd/hostapd/iapp.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * hostapd / IEEE 802.11F-2003 Inter-Access Point Protocol (IAPP) - * Copyright (c) 2002-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IAPP_H -#define IAPP_H - -struct iapp_data; - -#ifdef CONFIG_IAPP - -void iapp_new_station(struct iapp_data *iapp, struct sta_info *sta); -struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface); -void iapp_deinit(struct iapp_data *iapp); -int iapp_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss); - -#else /* CONFIG_IAPP */ - -static inline void iapp_new_station(struct iapp_data *iapp, - struct sta_info *sta) -{ -} - -static inline struct iapp_data * iapp_init(struct hostapd_data *hapd, - const char *iface) -{ - return NULL; -} - -static inline void iapp_deinit(struct iapp_data *iapp) -{ -} - -static inline int -iapp_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss) -{ - return 0; -} - -#endif /* CONFIG_IAPP */ - -#endif /* IAPP_H */ diff --git a/contrib/hostapd/hostapd/ieee802_11.c b/contrib/hostapd/hostapd/ieee802_11.c deleted file mode 100644 index 70491b4fa2..0000000000 --- a/contrib/hostapd/hostapd/ieee802_11.c +++ /dev/null @@ -1,1833 +0,0 @@ -/* - * hostapd / IEEE 802.11 Management - * Copyright (c) 2002-2008, Jouni Malinen - * Copyright (c) 2007-2008, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#ifndef CONFIG_NATIVE_WINDOWS - -#include - -#include "eloop.h" -#include "hostapd.h" -#include "ieee802_11.h" -#include "beacon.h" -#include "hw_features.h" -#include "radius/radius.h" -#include "radius/radius_client.h" -#include "ieee802_11_auth.h" -#include "sta_info.h" -#include "rc4.h" -#include "ieee802_1x.h" -#include "wpa.h" -#include "wme.h" -#include "ap_list.h" -#include "accounting.h" -#include "driver.h" -#include "mlme.h" - - -u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid) -{ - u8 *pos = eid; - int i, num, count; - - if (hapd->iface->current_rates == NULL) - return eid; - - *pos++ = WLAN_EID_SUPP_RATES; - num = hapd->iface->num_rates; - if (num > 8) { - /* rest of the rates are encoded in Extended supported - * rates element */ - num = 8; - } - - *pos++ = num; - count = 0; - for (i = 0, count = 0; i < hapd->iface->num_rates && count < num; - i++) { - count++; - *pos = hapd->iface->current_rates[i].rate / 5; - if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC) - *pos |= 0x80; - pos++; - } - - return pos; -} - - -u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid) -{ - u8 *pos = eid; - int i, num, count; - - if (hapd->iface->current_rates == NULL) - return eid; - - num = hapd->iface->num_rates; - if (num <= 8) - return eid; - num -= 8; - - *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos++ = num; - count = 0; - for (i = 0, count = 0; i < hapd->iface->num_rates && count < num + 8; - i++) { - count++; - if (count <= 8) - continue; /* already in SuppRates IE */ - *pos = hapd->iface->current_rates[i].rate / 5; - if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC) - *pos |= 0x80; - pos++; - } - - return pos; -} - - -u8 * hostapd_eid_ht_capabilities_info(struct hostapd_data *hapd, u8 *eid) -{ -#ifdef CONFIG_IEEE80211N - struct ieee80211_ht_capability *cap; - u8 *pos = eid; - - if (!hapd->iconf->ieee80211n) - return eid; - - *pos++ = WLAN_EID_HT_CAP; - *pos++ = sizeof(*cap); - - cap = (struct ieee80211_ht_capability *) pos; - os_memset(cap, 0, sizeof(*cap)); - SET_2BIT_U8(&cap->mac_ht_params_info, - MAC_HT_PARAM_INFO_MAX_RX_AMPDU_FACTOR_OFFSET, - MAX_RX_AMPDU_FACTOR_64KB); - - cap->capabilities_info = host_to_le16(hapd->iconf->ht_capab); - - cap->supported_mcs_set[0] = 0xff; - cap->supported_mcs_set[1] = 0xff; - - pos += sizeof(*cap); - - return pos; -#else /* CONFIG_IEEE80211N */ - return eid; -#endif /* CONFIG_IEEE80211N */ -} - - -u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid) -{ -#ifdef CONFIG_IEEE80211N - struct ieee80211_ht_operation *oper; - u8 *pos = eid; - - if (!hapd->iconf->ieee80211n) - return eid; - - *pos++ = WLAN_EID_HT_OPERATION; - *pos++ = sizeof(*oper); - - oper = (struct ieee80211_ht_operation *) pos; - os_memset(oper, 0, sizeof(*oper)); - - oper->control_chan = hapd->iconf->channel; - oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode); - if (hapd->iconf->secondary_channel == 1) - oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE | - HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH; - if (hapd->iconf->secondary_channel == -1) - oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW | - HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH; - - pos += sizeof(*oper); - - return pos; -#else /* CONFIG_IEEE80211N */ - return eid; -#endif /* CONFIG_IEEE80211N */ -} - - -#ifdef CONFIG_IEEE80211N - -/* -op_mode -Set to 0 (HT pure) under the followign conditions - - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or - - all STAs in the BSS are 20 MHz HT in 20 MHz BSS -Set to 1 (HT non-member protection) if there may be non-HT STAs - in both the primary and the secondary channel -Set to 2 if only HT STAs are associated in BSS, - however and at least one 20 MHz HT STA is associated -Set to 3 (HT mixed mode) when one or more non-HT STAs are associated - (currently non-GF HT station is considered as non-HT STA also) -*/ -int hostapd_ht_operation_update(struct hostapd_iface *iface) -{ - u16 cur_op_mode, new_op_mode; - int op_mode_changes = 0; - - if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed) - return 0; - - wpa_printf(MSG_DEBUG, "%s current operation mode=0x%X", - __func__, iface->ht_op_mode); - - if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) - && iface->num_sta_ht_no_gf) { - iface->ht_op_mode |= - HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT; - op_mode_changes++; - } else if ((iface->ht_op_mode & - HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) && - iface->num_sta_ht_no_gf == 0) { - iface->ht_op_mode &= - ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT; - op_mode_changes++; - } - - if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) && - (iface->num_sta_no_ht || iface->olbc_ht)) { - iface->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT; - op_mode_changes++; - } else if ((iface->ht_op_mode & - HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) && - (iface->num_sta_no_ht == 0 && !iface->olbc_ht)) { - iface->ht_op_mode &= - ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT; - op_mode_changes++; - } - - /* Note: currently we switch to the MIXED op mode if HT non-greenfield - * station is associated. Probably it's a theoretical case, since - * it looks like all known HT STAs support greenfield. - */ - new_op_mode = 0; - if (iface->num_sta_no_ht || - (iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)) - new_op_mode = OP_MODE_MIXED; - else if ((iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) - && iface->num_sta_ht_20mhz) - new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED; - else if (iface->olbc_ht) - new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS; - else - new_op_mode = OP_MODE_PURE; - - cur_op_mode = iface->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK; - if (cur_op_mode != new_op_mode) { - iface->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK; - iface->ht_op_mode |= new_op_mode; - op_mode_changes++; - } - - wpa_printf(MSG_DEBUG, "%s new operation mode=0x%X changes=%d", - __func__, iface->ht_op_mode, op_mode_changes); - - return op_mode_changes; -} - -#endif /* CONFIG_IEEE80211N */ - - -u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta, - int probe) -{ - int capab = WLAN_CAPABILITY_ESS; - int privacy; - - if (hapd->iface->num_sta_no_short_preamble == 0 && - hapd->iconf->preamble == SHORT_PREAMBLE) - capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; - - privacy = hapd->conf->ssid.wep.keys_set; - - if (hapd->conf->ieee802_1x && - (hapd->conf->default_wep_key_len || - hapd->conf->individual_wep_key_len)) - privacy = 1; - - if (hapd->conf->wpa) - privacy = 1; - - if (sta) { - int policy, def_klen; - if (probe && sta->ssid_probe) { - policy = sta->ssid_probe->security_policy; - def_klen = sta->ssid_probe->wep.default_len; - } else { - policy = sta->ssid->security_policy; - def_klen = sta->ssid->wep.default_len; - } - privacy = policy != SECURITY_PLAINTEXT; - if (policy == SECURITY_IEEE_802_1X && def_klen == 0) - privacy = 0; - } - - if (privacy) - capab |= WLAN_CAPABILITY_PRIVACY; - - if (hapd->iface->current_mode && - hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && - hapd->iface->num_sta_no_short_slot_time == 0) - capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; - - return capab; -} - - -#ifdef CONFIG_IEEE80211W -static u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd, - struct sta_info *sta, u8 *eid) -{ - u8 *pos = eid; - u32 timeout, tu; - struct os_time now, passed; - - *pos++ = WLAN_EID_TIMEOUT_INTERVAL; - *pos++ = 5; - *pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK; - os_get_time(&now); - os_time_sub(&now, &sta->sa_query_start, &passed); - tu = (passed.sec * 1000000 + passed.usec) / 1024; - if (hapd->conf->assoc_sa_query_max_timeout > tu) - timeout = hapd->conf->assoc_sa_query_max_timeout - tu; - else - timeout = 0; - if (timeout < hapd->conf->assoc_sa_query_max_timeout) - timeout++; /* add some extra time for local timers */ - WPA_PUT_LE32(pos, timeout); - pos += 4; - - return pos; -} -#endif /* CONFIG_IEEE80211W */ - - -void ieee802_11_print_ssid(char *buf, const u8 *ssid, u8 len) -{ - int i; - if (len > HOSTAPD_MAX_SSID_LEN) - len = HOSTAPD_MAX_SSID_LEN; - for (i = 0; i < len; i++) { - if (ssid[i] >= 32 && ssid[i] < 127) - buf[i] = ssid[i]; - else - buf[i] = '.'; - } - buf[len] = '\0'; -} - - -/** - * ieee802_11_send_deauth - Send Deauthentication frame - * @hapd: hostapd BSS data - * @addr: Address of the destination STA - * @reason: Reason code for Deauthentication - */ -void ieee802_11_send_deauth(struct hostapd_data *hapd, u8 *addr, u16 reason) -{ - struct ieee80211_mgmt mgmt; - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "deauthenticate - reason %d", reason); - os_memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DEAUTH); - 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.deauth.reason_code = host_to_le16(reason); - if (hostapd_send_mgmt_frame(hapd, &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.deauth), 0) < 0) - perror("ieee802_11_send_deauth: send"); -} - - -static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta, - u16 auth_transaction, u8 *challenge, int iswep) -{ - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "authentication (shared key, transaction %d)", - auth_transaction); - - if (auth_transaction == 1) { - if (!sta->challenge) { - /* Generate a pseudo-random challenge */ - u8 key[8]; - time_t now; - int r; - sta->challenge = os_zalloc(WLAN_AUTH_CHALLENGE_LEN); - if (sta->challenge == NULL) - return WLAN_STATUS_UNSPECIFIED_FAILURE; - - now = time(NULL); - r = random(); - os_memcpy(key, &now, 4); - os_memcpy(key + 4, &r, 4); - rc4_skip(key, sizeof(key), 0, - sta->challenge, WLAN_AUTH_CHALLENGE_LEN); - } - return 0; - } - - if (auth_transaction != 3) - return WLAN_STATUS_UNSPECIFIED_FAILURE; - - /* Transaction 3 */ - if (!iswep || !sta->challenge || !challenge || - os_memcmp(sta->challenge, challenge, WLAN_AUTH_CHALLENGE_LEN)) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, - "shared key authentication - invalid " - "challenge-response"); - return WLAN_STATUS_CHALLENGE_FAIL; - } - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "authentication OK (shared key)"); -#ifdef IEEE80211_REQUIRE_AUTH_ACK - /* Station will be marked authenticated if it ACKs the - * authentication reply. */ -#else - sta->flags |= WLAN_STA_AUTH; - wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH); -#endif - os_free(sta->challenge); - sta->challenge = NULL; - - return 0; -} - - -static void send_auth_reply(struct hostapd_data *hapd, - const u8 *dst, const u8 *bssid, - u16 auth_alg, u16 auth_transaction, u16 resp, - const u8 *ies, size_t ies_len) -{ - struct ieee80211_mgmt *reply; - u8 *buf; - size_t rlen; - - rlen = IEEE80211_HDRLEN + sizeof(reply->u.auth) + ies_len; - buf = os_zalloc(rlen); - if (buf == NULL) - return; - - reply = (struct ieee80211_mgmt *) buf; - reply->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_AUTH); - os_memcpy(reply->da, dst, ETH_ALEN); - os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN); - os_memcpy(reply->bssid, bssid, ETH_ALEN); - - reply->u.auth.auth_alg = host_to_le16(auth_alg); - reply->u.auth.auth_transaction = host_to_le16(auth_transaction); - reply->u.auth.status_code = host_to_le16(resp); - - if (ies && ies_len) - os_memcpy(reply->u.auth.variable, ies, ies_len); - - wpa_printf(MSG_DEBUG, "authentication reply: STA=" MACSTR - " auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu)", - MAC2STR(dst), auth_alg, auth_transaction, - resp, (unsigned long) ies_len); - if (hostapd_send_mgmt_frame(hapd, reply, rlen, 0) < 0) - perror("send_auth_reply: send"); - - os_free(buf); -} - - -#ifdef CONFIG_IEEE80211R -static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid, - u16 auth_transaction, u16 status, - const u8 *ies, size_t ies_len) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta; - - send_auth_reply(hapd, dst, bssid, WLAN_AUTH_FT, auth_transaction, - status, ies, ies_len); - - if (status != WLAN_STATUS_SUCCESS) - return; - - sta = ap_get_sta(hapd, dst); - if (sta == NULL) - return; - - hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)"); - sta->flags |= WLAN_STA_AUTH; - mlme_authenticate_indication(hapd, sta); -} -#endif /* CONFIG_IEEE80211R */ - - -static void handle_auth(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, - size_t len) -{ - u16 auth_alg, auth_transaction, status_code; - u16 resp = WLAN_STATUS_SUCCESS; - struct sta_info *sta = NULL; - int res; - u16 fc; - u8 *challenge = NULL; - u32 session_timeout, acct_interim_interval; - int vlan_id = 0; - u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN]; - size_t resp_ies_len = 0; - - if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) { - printf("handle_auth - too short payload (len=%lu)\n", - (unsigned long) len); - return; - } - - auth_alg = le_to_host16(mgmt->u.auth.auth_alg); - auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction); - status_code = le_to_host16(mgmt->u.auth.status_code); - fc = le_to_host16(mgmt->frame_control); - - if (len >= IEEE80211_HDRLEN + sizeof(mgmt->u.auth) + - 2 + WLAN_AUTH_CHALLENGE_LEN && - mgmt->u.auth.variable[0] == WLAN_EID_CHALLENGE && - mgmt->u.auth.variable[1] == WLAN_AUTH_CHALLENGE_LEN) - challenge = &mgmt->u.auth.variable[2]; - - wpa_printf(MSG_DEBUG, "authentication: STA=" MACSTR " auth_alg=%d " - "auth_transaction=%d status_code=%d wep=%d%s", - MAC2STR(mgmt->sa), auth_alg, auth_transaction, - status_code, !!(fc & WLAN_FC_ISWEP), - challenge ? " challenge" : ""); - - if (hapd->tkip_countermeasures) { - resp = WLAN_REASON_MICHAEL_MIC_FAILURE; - goto fail; - } - - if (!(((hapd->conf->auth_algs & WPA_AUTH_ALG_OPEN) && - auth_alg == WLAN_AUTH_OPEN) || -#ifdef CONFIG_IEEE80211R - (hapd->conf->wpa && - (hapd->conf->wpa_key_mgmt & - (WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK)) && - auth_alg == WLAN_AUTH_FT) || -#endif /* CONFIG_IEEE80211R */ - ((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) && - auth_alg == WLAN_AUTH_SHARED_KEY))) { - printf("Unsupported authentication algorithm (%d)\n", - auth_alg); - resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; - goto fail; - } - - if (!(auth_transaction == 1 || - (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) { - printf("Unknown authentication transaction number (%d)\n", - auth_transaction); - resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; - goto fail; - } - - if (os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) { - printf("Station " MACSTR " not allowed to authenticate.\n", - MAC2STR(mgmt->sa)); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len, - &session_timeout, - &acct_interim_interval, &vlan_id); - if (res == HOSTAPD_ACL_REJECT) { - printf("Station " MACSTR " not allowed to authenticate.\n", - MAC2STR(mgmt->sa)); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - if (res == HOSTAPD_ACL_PENDING) { - wpa_printf(MSG_DEBUG, "Authentication frame from " MACSTR - " waiting for an external authentication", - MAC2STR(mgmt->sa)); - /* Authentication code will re-send the authentication frame - * after it has received (and cached) information from the - * external source. */ - return; - } - - sta = ap_sta_add(hapd, mgmt->sa); - if (!sta) { - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - if (vlan_id > 0) { - if (hostapd_get_vlan_id_ifname(hapd->conf->vlan, - vlan_id) == NULL) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, "Invalid VLAN ID " - "%d received from RADIUS server", - vlan_id); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - sta->vlan_id = vlan_id; - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id); - } - - sta->flags &= ~WLAN_STA_PREAUTH; - ieee802_1x_notify_pre_auth(sta->eapol_sm, 0); - - if (hapd->conf->radius->acct_interim_interval == 0 && - acct_interim_interval) - sta->acct_interim_interval = acct_interim_interval; - if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT) - ap_sta_session_timeout(hapd, sta, session_timeout); - else - ap_sta_no_session_timeout(hapd, sta); - - switch (auth_alg) { - case WLAN_AUTH_OPEN: - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "authentication OK (open system)"); -#ifdef IEEE80211_REQUIRE_AUTH_ACK - /* Station will be marked authenticated if it ACKs the - * authentication reply. */ -#else - sta->flags |= WLAN_STA_AUTH; - wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH); - sta->auth_alg = WLAN_AUTH_OPEN; - mlme_authenticate_indication(hapd, sta); -#endif - break; - case WLAN_AUTH_SHARED_KEY: - resp = auth_shared_key(hapd, sta, auth_transaction, challenge, - fc & WLAN_FC_ISWEP); - sta->auth_alg = WLAN_AUTH_SHARED_KEY; - mlme_authenticate_indication(hapd, sta); - if (sta->challenge && auth_transaction == 1) { - resp_ies[0] = WLAN_EID_CHALLENGE; - resp_ies[1] = WLAN_AUTH_CHALLENGE_LEN; - os_memcpy(resp_ies + 2, sta->challenge, - WLAN_AUTH_CHALLENGE_LEN); - resp_ies_len = 2 + WLAN_AUTH_CHALLENGE_LEN; - } - break; -#ifdef CONFIG_IEEE80211R - case WLAN_AUTH_FT: - sta->auth_alg = WLAN_AUTH_FT; - if (sta->wpa_sm == NULL) - sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, - sta->addr); - if (sta->wpa_sm == NULL) { - wpa_printf(MSG_DEBUG, "FT: Failed to initialize WPA " - "state machine"); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - wpa_ft_process_auth(sta->wpa_sm, mgmt->bssid, - auth_transaction, mgmt->u.auth.variable, - len - IEEE80211_HDRLEN - - sizeof(mgmt->u.auth), - handle_auth_ft_finish, hapd); - /* handle_auth_ft_finish() callback will complete auth. */ - return; -#endif /* CONFIG_IEEE80211R */ - } - - fail: - send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg, - auth_transaction + 1, resp, resp_ies, resp_ies_len); -} - - -static void handle_assoc(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, size_t len, int reassoc) -{ - u16 capab_info, listen_interval; - u16 resp = WLAN_STATUS_SUCCESS; - u8 *pos, *wpa_ie; - size_t wpa_ie_len; - int send_deauth = 0, send_len, left, i; - struct sta_info *sta; - struct ieee802_11_elems elems; - u8 buf[sizeof(struct ieee80211_mgmt) + 512]; - struct ieee80211_mgmt *reply; - - if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) : - sizeof(mgmt->u.assoc_req))) { - printf("handle_assoc(reassoc=%d) - too short payload (len=%lu)" - "\n", reassoc, (unsigned long) len); - return; - } - - if (reassoc) { - capab_info = le_to_host16(mgmt->u.reassoc_req.capab_info); - listen_interval = le_to_host16( - mgmt->u.reassoc_req.listen_interval); - wpa_printf(MSG_DEBUG, "reassociation request: STA=" MACSTR - " capab_info=0x%02x listen_interval=%d current_ap=" - MACSTR, - MAC2STR(mgmt->sa), capab_info, listen_interval, - MAC2STR(mgmt->u.reassoc_req.current_ap)); - left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.reassoc_req)); - pos = mgmt->u.reassoc_req.variable; - } else { - capab_info = le_to_host16(mgmt->u.assoc_req.capab_info); - listen_interval = le_to_host16( - mgmt->u.assoc_req.listen_interval); - wpa_printf(MSG_DEBUG, "association request: STA=" MACSTR - " capab_info=0x%02x listen_interval=%d", - MAC2STR(mgmt->sa), capab_info, listen_interval); - left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_req)); - pos = mgmt->u.assoc_req.variable; - } - - sta = ap_get_sta(hapd, mgmt->sa); -#ifdef CONFIG_IEEE80211R - if (sta && sta->auth_alg == WLAN_AUTH_FT && - (sta->flags & WLAN_STA_AUTH) == 0) { - wpa_printf(MSG_DEBUG, "FT: Allow STA " MACSTR " to associate " - "prior to authentication since it is using " - "over-the-DS FT", MAC2STR(mgmt->sa)); - } else -#endif /* CONFIG_IEEE80211R */ - if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) { - printf("STA " MACSTR " trying to associate before " - "authentication\n", MAC2STR(mgmt->sa)); - if (sta) { - printf(" sta: addr=" MACSTR " aid=%d flags=0x%04x\n", - MAC2STR(sta->addr), sta->aid, sta->flags); - } - send_deauth = 1; - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - if (hapd->tkip_countermeasures) { - resp = WLAN_REASON_MICHAEL_MIC_FAILURE; - goto fail; - } - - if (listen_interval > hapd->conf->max_listen_interval) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "Too large Listen Interval (%d)", - listen_interval); - resp = WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE; - goto fail; - } - - sta->capability = capab_info; - sta->listen_interval = listen_interval; - - /* followed by SSID and Supported rates; and HT capabilities if 802.11n - * is used */ - if (ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed || - !elems.ssid) { - printf("STA " MACSTR " sent invalid association request\n", - MAC2STR(sta->addr)); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - if (elems.ssid_len != hapd->conf->ssid.ssid_len || - os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) != 0) - { - char ssid_txt[33]; - ieee802_11_print_ssid(ssid_txt, elems.ssid, elems.ssid_len); - printf("Station " MACSTR " tried to associate with " - "unknown SSID '%s'\n", MAC2STR(sta->addr), ssid_txt); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - sta->flags &= ~WLAN_STA_WMM; - if (elems.wmm && hapd->conf->wmm_enabled) { - if (hostapd_eid_wmm_valid(hapd, elems.wmm, elems.wmm_len)) - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_WPA, - HOSTAPD_LEVEL_DEBUG, - "invalid WMM element in association " - "request"); - else - sta->flags |= WLAN_STA_WMM; - } - - if (!elems.supp_rates) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "No supported rates element in AssocReq"); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - if (elems.supp_rates_len > sizeof(sta->supported_rates)) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "Invalid supported rates element length %d", - elems.supp_rates_len); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - os_memset(sta->supported_rates, 0, sizeof(sta->supported_rates)); - os_memcpy(sta->supported_rates, elems.supp_rates, - elems.supp_rates_len); - sta->supported_rates_len = elems.supp_rates_len; - - if (elems.ext_supp_rates) { - if (elems.supp_rates_len + elems.ext_supp_rates_len > - sizeof(sta->supported_rates)) { - hostapd_logger(hapd, mgmt->sa, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "Invalid supported rates element length" - " %d+%d", elems.supp_rates_len, - elems.ext_supp_rates_len); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - os_memcpy(sta->supported_rates + elems.supp_rates_len, - elems.ext_supp_rates, elems.ext_supp_rates_len); - sta->supported_rates_len += elems.ext_supp_rates_len; - } - -#ifdef CONFIG_IEEE80211N - /* save HT capabilities in the sta object */ - os_memset(&sta->ht_capabilities, 0, sizeof(sta->ht_capabilities)); - if (elems.ht_capabilities && - elems.ht_capabilities_len >= - sizeof(struct ieee80211_ht_capability)) { - sta->flags |= WLAN_STA_HT; - sta->ht_capabilities.id = WLAN_EID_HT_CAP; - sta->ht_capabilities.length = - sizeof(struct ieee80211_ht_capability); - os_memcpy(&sta->ht_capabilities.data, - elems.ht_capabilities, - sizeof(struct ieee80211_ht_capability)); - } else - sta->flags &= ~WLAN_STA_HT; -#endif /* CONFIG_IEEE80211N */ - - if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) { - wpa_ie = elems.rsn_ie; - wpa_ie_len = elems.rsn_ie_len; - } else if ((hapd->conf->wpa & WPA_PROTO_WPA) && - elems.wpa_ie) { - wpa_ie = elems.wpa_ie; - wpa_ie_len = elems.wpa_ie_len; - } else { - wpa_ie = NULL; - wpa_ie_len = 0; - } -#ifdef CONFIG_WPS - sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); - if (hapd->conf->wps_state && wpa_ie == NULL) { - if (elems.wps_ie) { - wpa_printf(MSG_DEBUG, "STA included WPS IE in " - "(Re)Association Request - assume WPS is " - "used"); - sta->flags |= WLAN_STA_WPS; - wpabuf_free(sta->wps_ie); - sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, - elems.wps_ie_len - 4); - } else { - wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE " - "in (Re)Association Request - possible WPS " - "use"); - sta->flags |= WLAN_STA_MAYBE_WPS; - } - } else -#endif /* CONFIG_WPS */ - if (hapd->conf->wpa && wpa_ie == NULL) { - printf("STA " MACSTR ": No WPA/RSN IE in association " - "request\n", MAC2STR(sta->addr)); - resp = WLAN_STATUS_INVALID_IE; - goto fail; - } - - if (hapd->conf->wpa && wpa_ie) { - int res; - wpa_ie -= 2; - wpa_ie_len += 2; - if (sta->wpa_sm == NULL) - sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, - sta->addr); - if (sta->wpa_sm == NULL) { - printf("Failed to initialize WPA state machine\n"); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, - wpa_ie, wpa_ie_len, - elems.mdie, elems.mdie_len); - if (res == WPA_INVALID_GROUP) - resp = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; - else if (res == WPA_INVALID_PAIRWISE) - resp = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; - else if (res == WPA_INVALID_AKMP) - resp = WLAN_STATUS_AKMP_NOT_VALID; - else if (res == WPA_ALLOC_FAIL) - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; -#ifdef CONFIG_IEEE80211W - else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) - resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; - else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) - resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; -#endif /* CONFIG_IEEE80211W */ - else if (res == WPA_INVALID_MDIE) - resp = WLAN_STATUS_INVALID_MDIE; - else if (res != WPA_IE_OK) - resp = WLAN_STATUS_INVALID_IE; - if (resp != WLAN_STATUS_SUCCESS) - goto fail; -#ifdef CONFIG_IEEE80211W - if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out && - sta->sa_query_count > 0) - ap_check_sa_query_timeout(hapd, sta); - if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out && - (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) { - /* - * STA has already been associated with MFP and SA - * Query timeout has not been reached. Reject the - * association attempt temporarily and start SA Query, - * if one is not pending. - */ - - if (sta->sa_query_count == 0) - ap_sta_start_sa_query(hapd, sta); - - resp = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; - goto fail; - } - - if (wpa_auth_uses_mfp(sta->wpa_sm)) - sta->flags |= WLAN_STA_MFP; - else - sta->flags &= ~WLAN_STA_MFP; -#endif /* CONFIG_IEEE80211W */ - -#ifdef CONFIG_IEEE80211R - if (sta->auth_alg == WLAN_AUTH_FT) { - if (!reassoc) { - wpa_printf(MSG_DEBUG, "FT: " MACSTR " tried " - "to use association (not " - "re-association) with FT auth_alg", - MAC2STR(sta->addr)); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - resp = wpa_ft_validate_reassoc(sta->wpa_sm, pos, left); - if (resp != WLAN_STATUS_SUCCESS) - goto fail; - } -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211N - if ((sta->flags & WLAN_STA_HT) && - wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) { - wpa_printf(MSG_DEBUG, "HT: " MACSTR " tried to " - "use TKIP with HT association", - MAC2STR(sta->addr)); - resp = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; - goto fail; - } -#endif /* CONFIG_IEEE80211N */ - } else - wpa_auth_sta_no_wpa(sta->wpa_sm); - - if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) - sta->flags |= WLAN_STA_NONERP; - for (i = 0; i < sta->supported_rates_len; i++) { - if ((sta->supported_rates[i] & 0x7f) > 22) { - sta->flags &= ~WLAN_STA_NONERP; - break; - } - } - if (sta->flags & WLAN_STA_NONERP && !sta->nonerp_set) { - sta->nonerp_set = 1; - hapd->iface->num_sta_non_erp++; - if (hapd->iface->num_sta_non_erp == 1) - ieee802_11_set_beacons(hapd->iface); - } - - if (!(sta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) && - !sta->no_short_slot_time_set) { - sta->no_short_slot_time_set = 1; - hapd->iface->num_sta_no_short_slot_time++; - if (hapd->iface->current_mode->mode == - HOSTAPD_MODE_IEEE80211G && - hapd->iface->num_sta_no_short_slot_time == 1) - ieee802_11_set_beacons(hapd->iface); - } - - if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - sta->flags |= WLAN_STA_SHORT_PREAMBLE; - else - sta->flags &= ~WLAN_STA_SHORT_PREAMBLE; - - if (!(sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && - !sta->no_short_preamble_set) { - sta->no_short_preamble_set = 1; - hapd->iface->num_sta_no_short_preamble++; - if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G - && hapd->iface->num_sta_no_short_preamble == 1) - ieee802_11_set_beacons(hapd->iface); - } - -#ifdef CONFIG_IEEE80211N - if (sta->flags & WLAN_STA_HT) { - u16 ht_capab = le_to_host16( - sta->ht_capabilities.data.capabilities_info); - wpa_printf(MSG_DEBUG, "HT: STA " MACSTR " HT Capabilities " - "Info: 0x%04x", MAC2STR(sta->addr), ht_capab); - if ((ht_capab & HT_CAP_INFO_GREEN_FIELD) == 0) { - if (!sta->no_ht_gf_set) { - sta->no_ht_gf_set = 1; - hapd->iface->num_sta_ht_no_gf++; - } - wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no " - "greenfield, num of non-gf stations %d", - __func__, MAC2STR(sta->addr), - hapd->iface->num_sta_ht_no_gf); - } - if ((ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) == 0) { - if (!sta->ht_20mhz_set) { - sta->ht_20mhz_set = 1; - hapd->iface->num_sta_ht_20mhz++; - } - wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - 20 MHz HT, " - "num of 20MHz HT STAs %d", - __func__, MAC2STR(sta->addr), - hapd->iface->num_sta_ht_20mhz); - } - } else { - if (!sta->no_ht_set) { - sta->no_ht_set = 1; - hapd->iface->num_sta_no_ht++; - } - if (hapd->iconf->ieee80211n) { - wpa_printf(MSG_DEBUG, "%s STA " MACSTR - " - no HT, num of non-HT stations %d", - __func__, MAC2STR(sta->addr), - hapd->iface->num_sta_no_ht); - } - } - - if (hostapd_ht_operation_update(hapd->iface) > 0) - ieee802_11_set_beacons(hapd->iface); -#endif /* CONFIG_IEEE80211N */ - - /* get a unique AID */ - if (sta->aid > 0) { - wpa_printf(MSG_DEBUG, " old AID %d", sta->aid); - } else { - for (sta->aid = 1; sta->aid <= MAX_AID_TABLE_SIZE; sta->aid++) - if (hapd->sta_aid[sta->aid - 1] == NULL) - break; - if (sta->aid > MAX_AID_TABLE_SIZE) { - sta->aid = 0; - resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - wpa_printf(MSG_ERROR, " no room for more AIDs"); - goto fail; - } else { - hapd->sta_aid[sta->aid - 1] = sta; - wpa_printf(MSG_DEBUG, " new AID %d", sta->aid); - } - } - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "association OK (aid %d)", sta->aid); - /* Station will be marked associated, after it acknowledges AssocResp - */ - -#ifdef CONFIG_IEEE80211W - if ((sta->flags & WLAN_STA_MFP) && sta->sa_query_timed_out) { - wpa_printf(MSG_DEBUG, "Allowing %sassociation after timed out " - "SA Query procedure", reassoc ? "re" : ""); - /* TODO: Send a protected Disassociate frame to the STA using - * the old key and Reason Code "Previous Authentication no - * longer valid". Make sure this is only sent protected since - * unprotected frame would be received by the STA that is now - * trying to associate. - */ - } -#endif /* CONFIG_IEEE80211W */ - - if (reassoc) { - os_memcpy(sta->previous_ap, mgmt->u.reassoc_req.current_ap, - ETH_ALEN); - } - - if (sta->last_assoc_req) - os_free(sta->last_assoc_req); - sta->last_assoc_req = os_malloc(len); - if (sta->last_assoc_req) - os_memcpy(sta->last_assoc_req, mgmt, len); - - /* Make sure that the previously registered inactivity timer will not - * remove the STA immediately. */ - sta->timeout_next = STA_NULLFUNC; - - fail: - os_memset(buf, 0, sizeof(buf)); - reply = (struct ieee80211_mgmt *) buf; - reply->frame_control = - IEEE80211_FC(WLAN_FC_TYPE_MGMT, - (send_deauth ? WLAN_FC_STYPE_DEAUTH : - (reassoc ? WLAN_FC_STYPE_REASSOC_RESP : - WLAN_FC_STYPE_ASSOC_RESP))); - os_memcpy(reply->da, mgmt->sa, ETH_ALEN); - os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN); - os_memcpy(reply->bssid, mgmt->bssid, ETH_ALEN); - - send_len = IEEE80211_HDRLEN; - if (send_deauth) { - send_len += sizeof(reply->u.deauth); - reply->u.deauth.reason_code = host_to_le16(resp); - } else { - u8 *p; - send_len += sizeof(reply->u.assoc_resp); - reply->u.assoc_resp.capab_info = - host_to_le16(hostapd_own_capab_info(hapd, sta, 0)); - reply->u.assoc_resp.status_code = host_to_le16(resp); - reply->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0) - | BIT(14) | BIT(15)); - /* Supported rates */ - p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable); - /* Extended supported rates */ - p = hostapd_eid_ext_supp_rates(hapd, p); - if (sta->flags & WLAN_STA_WMM) - p = hostapd_eid_wmm(hapd, p); - - p = hostapd_eid_ht_capabilities_info(hapd, p); - p = hostapd_eid_ht_operation(hapd, p); - -#ifdef CONFIG_IEEE80211R - if (resp == WLAN_STATUS_SUCCESS) { - /* IEEE 802.11r: Mobility Domain Information, Fast BSS - * Transition Information, RSN */ - p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p, - buf + sizeof(buf) - p, - sta->auth_alg); - } -#endif /* CONFIG_IEEE80211R */ - -#ifdef CONFIG_IEEE80211W - if (resp == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) - p = hostapd_eid_assoc_comeback_time(hapd, sta, p); -#endif /* CONFIG_IEEE80211W */ - - send_len += p - reply->u.assoc_resp.variable; - } - - if (hostapd_send_mgmt_frame(hapd, reply, send_len, 0) < 0) - perror("handle_assoc: send"); -} - - -static void handle_disassoc(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, size_t len) -{ - struct sta_info *sta; - - if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.disassoc)) { - printf("handle_disassoc - too short payload (len=%lu)\n", - (unsigned long) len); - return; - } - - wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d", - MAC2STR(mgmt->sa), - le_to_host16(mgmt->u.disassoc.reason_code)); - - sta = ap_get_sta(hapd, mgmt->sa); - if (sta == NULL) { - printf("Station " MACSTR " trying to disassociate, but it " - "is not associated.\n", MAC2STR(mgmt->sa)); - return; - } - - sta->flags &= ~WLAN_STA_ASSOC; - wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "disassociated"); - sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; - ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - /* Stop Accounting and IEEE 802.1X sessions, but leave the STA - * authenticated. */ - accounting_sta_stop(hapd, sta); - ieee802_1x_free_station(sta); - hostapd_sta_remove(hapd, sta->addr); - - if (sta->timeout_next == STA_NULLFUNC || - sta->timeout_next == STA_DISASSOC) { - sta->timeout_next = STA_DEAUTH; - eloop_cancel_timeout(ap_handle_timer, hapd, sta); - eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, - hapd, sta); - } - - mlme_disassociate_indication( - hapd, sta, le_to_host16(mgmt->u.disassoc.reason_code)); -} - - -static void handle_deauth(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, size_t len) -{ - struct sta_info *sta; - - if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) { - printf("handle_deauth - too short payload (len=%lu)\n", - (unsigned long) len); - return; - } - - wpa_printf(MSG_DEBUG, "deauthentication: STA=" MACSTR - " reason_code=%d", - MAC2STR(mgmt->sa), - le_to_host16(mgmt->u.deauth.reason_code)); - - sta = ap_get_sta(hapd, mgmt->sa); - if (sta == NULL) { - printf("Station " MACSTR " trying to deauthenticate, but it " - "is not authenticated.\n", MAC2STR(mgmt->sa)); - return; - } - - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); - wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH); - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "deauthenticated"); - mlme_deauthenticate_indication( - hapd, sta, le_to_host16(mgmt->u.deauth.reason_code)); - sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; - ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - ap_free_sta(hapd, sta); -} - - -static void handle_beacon(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, size_t len, - struct hostapd_frame_info *fi) -{ - struct ieee802_11_elems elems; - - if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.beacon)) { - printf("handle_beacon - too short payload (len=%lu)\n", - (unsigned long) len); - return; - } - - (void) ieee802_11_parse_elems(mgmt->u.beacon.variable, - len - (IEEE80211_HDRLEN + - sizeof(mgmt->u.beacon)), &elems, - 0); - - ap_list_process_beacon(hapd->iface, mgmt, &elems, fi); -} - - -#ifdef CONFIG_IEEE80211W - -/* MLME-SAQuery.request */ -void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, - const u8 *addr, const u8 *trans_id) -{ - struct ieee80211_mgmt mgmt; - u8 *end; - - wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Request to " - MACSTR, MAC2STR(addr)); - 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, - WLAN_SA_QUERY_TR_ID_LEN); - end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; - if (hostapd_send_mgmt_frame(hapd, &mgmt, end - (u8 *) &mgmt, 0) < 0) - perror("ieee802_11_send_sa_query_req: send"); -} - - -static void hostapd_sa_query_action(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, size_t len) -{ - struct sta_info *sta; - u8 *end; - int i; - - end = mgmt->u.action.u.sa_query_resp.trans_id + - WLAN_SA_QUERY_TR_ID_LEN; - if (((u8 *) mgmt) + len < end) { - wpa_printf(MSG_DEBUG, "IEEE 802.11: Too short SA Query Action " - "frame (len=%lu)", (unsigned long) len); - return; - } - - if (mgmt->u.action.u.sa_query_resp.action != WLAN_SA_QUERY_RESPONSE) { - wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query " - "Action %d", mgmt->u.action.u.sa_query_resp.action); - return; - } - - wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Response from " - MACSTR, MAC2STR(mgmt->sa)); - wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", - mgmt->u.action.u.sa_query_resp.trans_id, - WLAN_SA_QUERY_TR_ID_LEN); - - /* MLME-SAQuery.confirm */ - - sta = ap_get_sta(hapd, mgmt->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"); - return; - } - - for (i = 0; i < sta->sa_query_count; i++) { - if (os_memcmp(sta->sa_query_trans_id + - i * WLAN_SA_QUERY_TR_ID_LEN, - mgmt->u.action.u.sa_query_resp.trans_id, - WLAN_SA_QUERY_TR_ID_LEN) == 0) - break; - } - - if (i >= sta->sa_query_count) { - wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching SA Query " - "transaction identifier found"); - return; - } - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "Reply to pending SA Query received"); - ap_sta_stop_sa_query(hapd, sta); -} - - -static int robust_action_frame(u8 category) -{ - return category != WLAN_ACTION_PUBLIC && - category != WLAN_ACTION_HT; -} -#endif /* CONFIG_IEEE80211W */ - - -static void handle_action(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, size_t len) -{ - struct sta_info *sta; - - if (len < IEEE80211_HDRLEN + 1) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "handle_action - too short payload (len=%lu)", - (unsigned long) len); - return; - } - - sta = ap_get_sta(hapd, mgmt->sa); -#ifdef CONFIG_IEEE80211W - if (sta && (sta->flags & WLAN_STA_MFP) && - !(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP) && - robust_action_frame(mgmt->u.action.category))) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "Dropped unprotected Robust Action frame from " - "an MFP STA"); - return; - } -#endif /* CONFIG_IEEE80211W */ - - switch (mgmt->u.action.category) { -#ifdef CONFIG_IEEE80211R - case WLAN_ACTION_FT: - { - if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) { - wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored FT Action " - "frame from unassociated STA " MACSTR, - MAC2STR(mgmt->sa)); - return; - } - - if (wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action, - len - IEEE80211_HDRLEN)) - break; - - return; - } -#endif /* CONFIG_IEEE80211R */ - case WLAN_ACTION_WMM: - hostapd_wmm_action(hapd, mgmt, len); - return; -#ifdef CONFIG_IEEE80211W - case WLAN_ACTION_SA_QUERY: - hostapd_sa_query_action(hapd, mgmt, len); - return; -#endif /* CONFIG_IEEE80211W */ - } - - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "handle_action - unknown action category %d or invalid " - "frame", - mgmt->u.action.category); - if (!(mgmt->da[0] & 0x01) && !(mgmt->u.action.category & 0x80) && - !(mgmt->sa[0] & 0x01)) { - /* - * IEEE 802.11-REVma/D9.0 - 7.3.1.11 - * Return the Action frame to the source without change - * except that MSB of the Category set to 1. - */ - wpa_printf(MSG_DEBUG, "IEEE 802.11: Return unknown Action " - "frame back to sender"); - os_memcpy(mgmt->da, mgmt->sa, ETH_ALEN); - os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); - os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); - mgmt->u.action.category |= 0x80; - - hostapd_send_mgmt_frame(hapd, mgmt, len, 0); - } -} - - -/** - * ieee802_11_mgmt - process incoming IEEE 802.11 management frames - * @hapd: hostapd BSS data structure (the BSS to which the management frame was - * sent to) - * @buf: management frame data (starting from IEEE 802.11 header) - * @len: length of frame data in octets - * @stype: management frame subtype from frame control field - * @fi: meta data about received frame (signal level, etc.) - * - * Process all incoming IEEE 802.11 management frames. This will be called for - * each frame received from the kernel driver through wlan#ap interface. In - * addition, it can be called to re-inserted pending frames (e.g., when using - * external RADIUS server as an MAC ACL). - */ -void ieee802_11_mgmt(struct hostapd_data *hapd, u8 *buf, size_t len, u16 stype, - struct hostapd_frame_info *fi) -{ - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf; - int broadcast; - - if (stype == WLAN_FC_STYPE_BEACON) { - handle_beacon(hapd, mgmt, len, fi); - return; - } - - if (fi && fi->passive_scan) - return; - - broadcast = mgmt->bssid[0] == 0xff && mgmt->bssid[1] == 0xff && - mgmt->bssid[2] == 0xff && mgmt->bssid[3] == 0xff && - mgmt->bssid[4] == 0xff && mgmt->bssid[5] == 0xff; - - if (!broadcast && - os_memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0) { - printf("MGMT: BSSID=" MACSTR " not our address\n", - MAC2STR(mgmt->bssid)); - return; - } - - - if (stype == WLAN_FC_STYPE_PROBE_REQ) { - handle_probe_req(hapd, mgmt, len); - return; - } - - if (os_memcmp(mgmt->da, hapd->own_addr, ETH_ALEN) != 0) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "MGMT: DA=" MACSTR " not our address", - MAC2STR(mgmt->da)); - return; - } - - switch (stype) { - case WLAN_FC_STYPE_AUTH: - wpa_printf(MSG_DEBUG, "mgmt::auth"); - handle_auth(hapd, mgmt, len); - break; - case WLAN_FC_STYPE_ASSOC_REQ: - wpa_printf(MSG_DEBUG, "mgmt::assoc_req"); - handle_assoc(hapd, mgmt, len, 0); - break; - case WLAN_FC_STYPE_REASSOC_REQ: - wpa_printf(MSG_DEBUG, "mgmt::reassoc_req"); - handle_assoc(hapd, mgmt, len, 1); - break; - case WLAN_FC_STYPE_DISASSOC: - wpa_printf(MSG_DEBUG, "mgmt::disassoc"); - handle_disassoc(hapd, mgmt, len); - break; - case WLAN_FC_STYPE_DEAUTH: - wpa_printf(MSG_DEBUG, "mgmt::deauth"); - handle_deauth(hapd, mgmt, len); - break; - case WLAN_FC_STYPE_ACTION: - wpa_printf(MSG_DEBUG, "mgmt::action"); - handle_action(hapd, mgmt, len); - break; - default: - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "unknown mgmt frame subtype %d", stype); - break; - } -} - - -static void handle_auth_cb(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, - size_t len, int ok) -{ - u16 auth_alg, auth_transaction, status_code; - struct sta_info *sta; - - if (!ok) { - hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_NOTICE, - "did not acknowledge authentication response"); - return; - } - - if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) { - printf("handle_auth_cb - too short payload (len=%lu)\n", - (unsigned long) len); - return; - } - - auth_alg = le_to_host16(mgmt->u.auth.auth_alg); - auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction); - status_code = le_to_host16(mgmt->u.auth.status_code); - - sta = ap_get_sta(hapd, mgmt->da); - if (!sta) { - printf("handle_auth_cb: STA " MACSTR " not found\n", - MAC2STR(mgmt->da)); - return; - } - - if (status_code == WLAN_STATUS_SUCCESS && - ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 2) || - (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 4))) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "authenticated"); - sta->flags |= WLAN_STA_AUTH; - } -} - - -#ifdef CONFIG_IEEE80211N -static void -hostapd_get_ht_capab(struct hostapd_data *hapd, - struct ht_cap_ie *ht_cap_ie, - struct ht_cap_ie *neg_ht_cap_ie) -{ - u16 cap; - - os_memcpy(neg_ht_cap_ie, ht_cap_ie, sizeof(struct ht_cap_ie)); - cap = le_to_host16(neg_ht_cap_ie->data.capabilities_info); - cap &= hapd->iconf->ht_capab; - cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_DISABLED); - - /* FIXME: Rx STBC needs to be handled specially */ - cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_RX_STBC_MASK); - neg_ht_cap_ie->data.capabilities_info = host_to_le16(cap); -} -#endif /* CONFIG_IEEE80211N */ - - -static void handle_assoc_cb(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, - size_t len, int reassoc, int ok) -{ - u16 status; - struct sta_info *sta; - int new_assoc = 1; -#ifdef CONFIG_IEEE80211N - struct ht_cap_ie ht_cap; -#endif /* CONFIG_IEEE80211N */ - struct ht_cap_ie *ht_cap_ptr = NULL; - int set_flags, flags_and, flags_or; - - if (!ok) { - hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "did not acknowledge association response"); - return; - } - - if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) : - sizeof(mgmt->u.assoc_resp))) { - printf("handle_assoc_cb(reassoc=%d) - too short payload " - "(len=%lu)\n", reassoc, (unsigned long) len); - return; - } - - if (reassoc) - status = le_to_host16(mgmt->u.reassoc_resp.status_code); - else - status = le_to_host16(mgmt->u.assoc_resp.status_code); - - sta = ap_get_sta(hapd, mgmt->da); - if (!sta) { - printf("handle_assoc_cb: STA " MACSTR " not found\n", - MAC2STR(mgmt->da)); - return; - } - - if (status != WLAN_STATUS_SUCCESS) - goto fail; - - /* Stop previous accounting session, if one is started, and allocate - * new session id for the new session. */ - accounting_sta_stop(hapd, sta); - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, - "associated (aid %d)", - sta->aid); - - if (sta->flags & WLAN_STA_ASSOC) - new_assoc = 0; - sta->flags |= WLAN_STA_ASSOC; - - if (reassoc) - mlme_reassociate_indication(hapd, sta); - else - mlme_associate_indication(hapd, sta); - -#ifdef CONFIG_IEEE80211N - if (sta->flags & WLAN_STA_HT) { - ht_cap_ptr = &ht_cap; - hostapd_get_ht_capab(hapd, &sta->ht_capabilities, ht_cap_ptr); - } -#endif /* CONFIG_IEEE80211N */ - -#ifdef CONFIG_IEEE80211W - sta->sa_query_timed_out = 0; -#endif /* CONFIG_IEEE80211W */ - - /* - * Remove the STA entry in order to make sure the STA PS state gets - * cleared and configuration gets updated in case of reassociation back - * to the same AP. - */ - hostapd_sta_remove(hapd, sta->addr); - - if (hostapd_sta_add(hapd->conf->iface, hapd, sta->addr, sta->aid, - sta->capability, sta->supported_rates, - sta->supported_rates_len, 0, sta->listen_interval, - ht_cap_ptr)) - { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_NOTICE, - "Could not add STA to kernel driver"); - } - - if (sta->eapol_sm == NULL) { - /* - * This STA does not use RADIUS server for EAP authentication, - * so bind it to the selected VLAN interface now, since the - * interface selection is not going to change anymore. - */ - ap_sta_bind_vlan(hapd, sta, 0); - } else if (sta->vlan_id) { - /* VLAN ID already set (e.g., by PMKSA caching), so bind STA */ - ap_sta_bind_vlan(hapd, sta, 0); - } - - set_flags = WLAN_STA_SHORT_PREAMBLE | WLAN_STA_WMM | WLAN_STA_MFP; - if (!hapd->conf->ieee802_1x && !hapd->conf->wpa && - sta->flags & WLAN_STA_AUTHORIZED) - set_flags |= WLAN_STA_AUTHORIZED; - flags_or = sta->flags & set_flags; - flags_and = sta->flags | ~set_flags; - hostapd_sta_set_flags(hapd, sta->addr, sta->flags, - flags_or, flags_and); - - if (sta->auth_alg == WLAN_AUTH_FT) - wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT); - else - wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); - hostapd_new_assoc_sta(hapd, sta, !new_assoc); - - ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); - - fail: - /* Copy of the association request is not needed anymore */ - if (sta->last_assoc_req) { - os_free(sta->last_assoc_req); - sta->last_assoc_req = NULL; - } -} - - -/** - * ieee802_11_mgmt_cb - Process management frame TX status callback - * @hapd: hostapd BSS data structure (the BSS from which the management frame - * was sent from) - * @buf: management frame data (starting from IEEE 802.11 header) - * @len: length of frame data in octets - * @stype: management frame subtype from frame control field - * @ok: Whether the frame was ACK'ed - */ -void ieee802_11_mgmt_cb(struct hostapd_data *hapd, u8 *buf, size_t len, - u16 stype, int ok) -{ - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf; - - switch (stype) { - case WLAN_FC_STYPE_AUTH: - wpa_printf(MSG_DEBUG, "mgmt::auth cb"); - handle_auth_cb(hapd, mgmt, len, ok); - break; - case WLAN_FC_STYPE_ASSOC_RESP: - wpa_printf(MSG_DEBUG, "mgmt::assoc_resp cb"); - handle_assoc_cb(hapd, mgmt, len, 0, ok); - break; - case WLAN_FC_STYPE_REASSOC_RESP: - wpa_printf(MSG_DEBUG, "mgmt::reassoc_resp cb"); - handle_assoc_cb(hapd, mgmt, len, 1, ok); - break; - case WLAN_FC_STYPE_PROBE_RESP: - wpa_printf(MSG_DEBUG, "mgmt::proberesp cb"); - break; - case WLAN_FC_STYPE_DEAUTH: - /* ignore */ - break; - case WLAN_FC_STYPE_ACTION: - wpa_printf(MSG_DEBUG, "mgmt::action cb"); - break; - default: - printf("unknown mgmt cb frame subtype %d\n", stype); - break; - } -} - - -static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx, - void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - hapd->tkip_countermeasures = 0; - hostapd_set_countermeasures(hapd, 0); - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended"); -} - - -static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd) -{ - struct sta_info *sta; - - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated"); - - wpa_auth_countermeasures_start(hapd->wpa_auth); - hapd->tkip_countermeasures = 1; - hostapd_set_countermeasures(hapd, 1); - wpa_gtk_rekey(hapd->wpa_auth); - eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL); - eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop, - hapd, NULL); - for (sta = hapd->sta_list; sta != NULL; sta = sta->next) { - hostapd_sta_deauth(hapd, sta->addr, - WLAN_REASON_MICHAEL_MIC_FAILURE); - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | - WLAN_STA_AUTHORIZED); - hostapd_sta_remove(hapd, sta->addr); - } -} - - -void ieee80211_michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, - int local) -{ - time_t now; - - if (addr && local) { - struct sta_info *sta = ap_get_sta(hapd, addr); - if (sta != NULL) { - wpa_auth_sta_local_mic_failure_report(sta->wpa_sm); - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, - "Michael MIC failure detected in " - "received frame"); - mlme_michaelmicfailure_indication(hapd, addr); - } else { - wpa_printf(MSG_DEBUG, - "MLME-MICHAELMICFAILURE.indication " - "for not associated STA (" MACSTR - ") ignored", MAC2STR(addr)); - return; - } - } - - time(&now); - if (now > hapd->michael_mic_failure + 60) { - hapd->michael_mic_failures = 1; - } else { - hapd->michael_mic_failures++; - if (hapd->michael_mic_failures > 1) - ieee80211_tkip_countermeasures_start(hapd); - } - hapd->michael_mic_failure = now; -} - - -int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen) -{ - /* TODO */ - return 0; -} - - -int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, - char *buf, size_t buflen) -{ - /* TODO */ - return 0; -} - -#endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/contrib/hostapd/hostapd/ieee802_11.h b/contrib/hostapd/hostapd/ieee802_11.h deleted file mode 100644 index ca8ef93c09..0000000000 --- a/contrib/hostapd/hostapd/ieee802_11.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * hostapd / IEEE 802.11 Management - * Copyright (c) 2002-2006, Jouni Malinen - * Copyright (c) 2007-2008, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IEEE802_11_H -#define IEEE802_11_H - -#include "ieee802_11_defs.h" -#include "ieee802_11_common.h" - -struct hostapd_frame_info { - u32 phytype; - u32 channel; - u32 datarate; - u32 ssi_signal; - - unsigned int passive_scan:1; -}; - -struct hostapd_iface; -struct hostapd_data; -struct sta_info; - -void ieee802_11_send_deauth(struct hostapd_data *hapd, u8 *addr, u16 reason); -void ieee802_11_mgmt(struct hostapd_data *hapd, u8 *buf, size_t len, - u16 stype, struct hostapd_frame_info *fi); -void ieee802_11_mgmt_cb(struct hostapd_data *hapd, u8 *buf, size_t len, - u16 stype, int ok); -void ieee802_11_print_ssid(char *buf, const u8 *ssid, u8 len); -void ieee80211_michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, - int local); -int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen); -int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, - char *buf, size_t buflen); -u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta, - int probe); -u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid); -u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid); -u8 * hostapd_eid_ht_capabilities_info(struct hostapd_data *hapd, u8 *eid); -u8 * hostapd_eid_ht_operation(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, - const u8 *addr, const u8 *trans_id); - -#endif /* IEEE802_11_H */ diff --git a/contrib/hostapd/hostapd/ieee802_11_auth.c b/contrib/hostapd/hostapd/ieee802_11_auth.c deleted file mode 100644 index 9aba1fe854..0000000000 --- a/contrib/hostapd/hostapd/ieee802_11_auth.c +++ /dev/null @@ -1,523 +0,0 @@ -/* - * hostapd / IEEE 802.11 authentication (ACL) - * Copyright (c) 2003-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * Access control list for IEEE 802.11 authentication can uses statically - * configured ACL from configuration files or an external RADIUS server. - * Results from external RADIUS queries are cached to allow faster - * authentication frame processing. - */ - -#include "includes.h" - -#ifndef CONFIG_NATIVE_WINDOWS - -#include "hostapd.h" -#include "ieee802_11.h" -#include "ieee802_11_auth.h" -#include "radius/radius.h" -#include "radius/radius_client.h" -#include "eloop.h" -#include "driver.h" - -#define RADIUS_ACL_TIMEOUT 30 - - -struct hostapd_cached_radius_acl { - time_t timestamp; - macaddr addr; - int accepted; /* HOSTAPD_ACL_* */ - struct hostapd_cached_radius_acl *next; - u32 session_timeout; - u32 acct_interim_interval; - int vlan_id; -}; - - -struct hostapd_acl_query_data { - time_t timestamp; - u8 radius_id; - macaddr addr; - u8 *auth_msg; /* IEEE 802.11 authentication frame from station */ - size_t auth_msg_len; - struct hostapd_acl_query_data *next; -}; - - -static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache) -{ - struct hostapd_cached_radius_acl *prev; - - while (acl_cache) { - prev = acl_cache; - acl_cache = acl_cache->next; - os_free(prev); - } -} - - -static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr, - u32 *session_timeout, - u32 *acct_interim_interval, int *vlan_id) -{ - struct hostapd_cached_radius_acl *entry; - time_t now; - - time(&now); - entry = hapd->acl_cache; - - while (entry) { - if (os_memcmp(entry->addr, addr, ETH_ALEN) == 0) { - if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) - return -1; /* entry has expired */ - if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT) - if (session_timeout) - *session_timeout = - entry->session_timeout; - if (acct_interim_interval) - *acct_interim_interval = - entry->acct_interim_interval; - if (vlan_id) - *vlan_id = entry->vlan_id; - return entry->accepted; - } - - entry = entry->next; - } - - return -1; -} - - -static void hostapd_acl_query_free(struct hostapd_acl_query_data *query) -{ - if (query == NULL) - return; - os_free(query->auth_msg); - os_free(query); -} - - -static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr, - struct hostapd_acl_query_data *query) -{ - struct radius_msg *msg; - char buf[128]; - - query->radius_id = radius_client_get_id(hapd->radius); - msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, query->radius_id); - if (msg == NULL) - return -1; - - radius_msg_make_authenticator(msg, addr, ETH_ALEN); - - os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(addr)); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, (u8 *) buf, - os_strlen(buf))) { - wpa_printf(MSG_DEBUG, "Could not add User-Name"); - goto fail; - } - - if (!radius_msg_add_attr_user_password( - msg, (u8 *) buf, os_strlen(buf), - hapd->conf->radius->auth_server->shared_secret, - hapd->conf->radius->auth_server->shared_secret_len)) { - wpa_printf(MSG_DEBUG, "Could not add User-Password"); - goto fail; - } - - if (hapd->conf->own_ip_addr.af == AF_INET && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, - (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) { - wpa_printf(MSG_DEBUG, "Could not add NAS-IP-Address"); - goto fail; - } - -#ifdef CONFIG_IPV6 - if (hapd->conf->own_ip_addr.af == AF_INET6 && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS, - (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) { - wpa_printf(MSG_DEBUG, "Could not add NAS-IPv6-Address"); - goto fail; - } -#endif /* CONFIG_IPV6 */ - - if (hapd->conf->nas_identifier && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER, - (u8 *) hapd->conf->nas_identifier, - os_strlen(hapd->conf->nas_identifier))) { - wpa_printf(MSG_DEBUG, "Could not add NAS-Identifier"); - goto fail; - } - - os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s", - MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID, - (u8 *) buf, os_strlen(buf))) { - wpa_printf(MSG_DEBUG, "Could not add Called-Station-Id"); - goto fail; - } - - os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, - MAC2STR(addr)); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, - (u8 *) buf, os_strlen(buf))) { - wpa_printf(MSG_DEBUG, "Could not add Calling-Station-Id"); - goto fail; - } - - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE, - RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { - wpa_printf(MSG_DEBUG, "Could not add NAS-Port-Type"); - goto fail; - } - - os_snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b"); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, - (u8 *) buf, os_strlen(buf))) { - wpa_printf(MSG_DEBUG, "Could not add Connect-Info"); - goto fail; - } - - radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr); - return 0; - - fail: - radius_msg_free(msg); - os_free(msg); - return -1; -} - - -/** - * hostapd_allowed_address - Check whether a specified STA can be authenticated - * @hapd: hostapd BSS data - * @addr: MAC address of the STA - * @msg: Authentication message - * @len: Length of msg in octets - * @session_timeout: Buffer for returning session timeout (from RADIUS) - * @acct_interim_interval: Buffer for returning account interval (from RADIUS) - * @vlan_id: Buffer for returning VLAN ID - * Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING - */ -int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, - const u8 *msg, size_t len, u32 *session_timeout, - u32 *acct_interim_interval, int *vlan_id) -{ - if (session_timeout) - *session_timeout = 0; - if (acct_interim_interval) - *acct_interim_interval = 0; - if (vlan_id) - *vlan_id = 0; - - if (hostapd_maclist_found(hapd->conf->accept_mac, - hapd->conf->num_accept_mac, addr, vlan_id)) - return HOSTAPD_ACL_ACCEPT; - - if (hostapd_maclist_found(hapd->conf->deny_mac, - hapd->conf->num_deny_mac, addr, vlan_id)) - return HOSTAPD_ACL_REJECT; - - if (hapd->conf->macaddr_acl == ACCEPT_UNLESS_DENIED) - return HOSTAPD_ACL_ACCEPT; - if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED) - return HOSTAPD_ACL_REJECT; - - if (hapd->conf->macaddr_acl == USE_EXTERNAL_RADIUS_AUTH) { - struct hostapd_acl_query_data *query; - - /* Check whether ACL cache has an entry for this station */ - int res = hostapd_acl_cache_get(hapd, addr, session_timeout, - acct_interim_interval, - vlan_id); - if (res == HOSTAPD_ACL_ACCEPT || - res == HOSTAPD_ACL_ACCEPT_TIMEOUT) - return res; - if (res == HOSTAPD_ACL_REJECT) - return HOSTAPD_ACL_REJECT; - - query = hapd->acl_queries; - while (query) { - if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) { - /* pending query in RADIUS retransmit queue; - * do not generate a new one */ - return HOSTAPD_ACL_PENDING; - } - query = query->next; - } - - if (!hapd->conf->radius->auth_server) - return HOSTAPD_ACL_REJECT; - - /* No entry in the cache - query external RADIUS server */ - query = os_zalloc(sizeof(*query)); - if (query == NULL) { - wpa_printf(MSG_ERROR, "malloc for query data failed"); - return HOSTAPD_ACL_REJECT; - } - time(&query->timestamp); - os_memcpy(query->addr, addr, ETH_ALEN); - if (hostapd_radius_acl_query(hapd, addr, query)) { - wpa_printf(MSG_DEBUG, "Failed to send Access-Request " - "for ACL query."); - hostapd_acl_query_free(query); - return HOSTAPD_ACL_REJECT; - } - - query->auth_msg = os_malloc(len); - if (query->auth_msg == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate memory for " - "auth frame."); - hostapd_acl_query_free(query); - return HOSTAPD_ACL_REJECT; - } - os_memcpy(query->auth_msg, msg, len); - query->auth_msg_len = len; - query->next = hapd->acl_queries; - hapd->acl_queries = query; - - /* Queued data will be processed in hostapd_acl_recv_radius() - * when RADIUS server replies to the sent Access-Request. */ - return HOSTAPD_ACL_PENDING; - } - - return HOSTAPD_ACL_REJECT; -} - - -static void hostapd_acl_expire_cache(struct hostapd_data *hapd, time_t now) -{ - struct hostapd_cached_radius_acl *prev, *entry, *tmp; - - prev = NULL; - entry = hapd->acl_cache; - - while (entry) { - if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) { - wpa_printf(MSG_DEBUG, "Cached ACL entry for " MACSTR - " has expired.", MAC2STR(entry->addr)); - if (prev) - prev->next = entry->next; - else - hapd->acl_cache = entry->next; -#ifdef CONFIG_DRIVER_RADIUS_ACL - hostapd_set_radius_acl_expire(hapd, entry->addr); -#endif /* CONFIG_DRIVER_RADIUS_ACL */ - tmp = entry; - entry = entry->next; - os_free(tmp); - continue; - } - - prev = entry; - entry = entry->next; - } -} - - -static void hostapd_acl_expire_queries(struct hostapd_data *hapd, time_t now) -{ - struct hostapd_acl_query_data *prev, *entry, *tmp; - - prev = NULL; - entry = hapd->acl_queries; - - while (entry) { - if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) { - wpa_printf(MSG_DEBUG, "ACL query for " MACSTR - " has expired.", MAC2STR(entry->addr)); - if (prev) - prev->next = entry->next; - else - hapd->acl_queries = entry->next; - - tmp = entry; - entry = entry->next; - hostapd_acl_query_free(tmp); - continue; - } - - prev = entry; - entry = entry->next; - } -} - - -/** - * hostapd_acl_expire - ACL cache expiration callback - * @eloop_ctx: struct hostapd_data * - * @timeout_ctx: Not used - */ -static void hostapd_acl_expire(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - time_t now; - - time(&now); - hostapd_acl_expire_cache(hapd, now); - hostapd_acl_expire_queries(hapd, now); - - eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL); -} - - -/** - * hostapd_acl_recv_radius - Process incoming RADIUS Authentication messages - * @msg: RADIUS response message - * @req: RADIUS request message - * @shared_secret: RADIUS shared secret - * @shared_secret_len: Length of shared_secret in octets - * @data: Context data (struct hostapd_data *) - * Returns: RADIUS_RX_PROCESSED if RADIUS message was a reply to ACL query (and - * was processed here) or RADIUS_RX_UNKNOWN if not. - */ -static RadiusRxResult -hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, - const u8 *shared_secret, size_t shared_secret_len, - void *data) -{ - struct hostapd_data *hapd = data; - struct hostapd_acl_query_data *query, *prev; - struct hostapd_cached_radius_acl *cache; - - query = hapd->acl_queries; - prev = NULL; - while (query) { - if (query->radius_id == msg->hdr->identifier) - break; - prev = query; - query = query->next; - } - if (query == NULL) - return RADIUS_RX_UNKNOWN; - - wpa_printf(MSG_DEBUG, "Found matching Access-Request for RADIUS " - "message (id=%d)", query->radius_id); - - if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) { - wpa_printf(MSG_INFO, "Incoming RADIUS packet did not have " - "correct authenticator - dropped\n"); - return RADIUS_RX_INVALID_AUTHENTICATOR; - } - - if (msg->hdr->code != RADIUS_CODE_ACCESS_ACCEPT && - msg->hdr->code != RADIUS_CODE_ACCESS_REJECT) { - wpa_printf(MSG_DEBUG, "Unknown RADIUS message code %d to ACL " - "query", msg->hdr->code); - return RADIUS_RX_UNKNOWN; - } - - /* Insert Accept/Reject info into ACL cache */ - cache = os_zalloc(sizeof(*cache)); - if (cache == NULL) { - wpa_printf(MSG_DEBUG, "Failed to add ACL cache entry"); - goto done; - } - time(&cache->timestamp); - os_memcpy(cache->addr, query->addr, sizeof(cache->addr)); - if (msg->hdr->code == RADIUS_CODE_ACCESS_ACCEPT) { - if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT, - &cache->session_timeout) == 0) - cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT; - else - cache->accepted = HOSTAPD_ACL_ACCEPT; - - if (radius_msg_get_attr_int32( - msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL, - &cache->acct_interim_interval) == 0 && - cache->acct_interim_interval < 60) { - wpa_printf(MSG_DEBUG, "Ignored too small " - "Acct-Interim-Interval %d for STA " MACSTR, - cache->acct_interim_interval, - MAC2STR(query->addr)); - cache->acct_interim_interval = 0; - } - - cache->vlan_id = radius_msg_get_vlanid(msg); - } else - cache->accepted = HOSTAPD_ACL_REJECT; - cache->next = hapd->acl_cache; - hapd->acl_cache = cache; - -#ifdef CONFIG_DRIVER_RADIUS_ACL - hostapd_set_radius_acl_auth(hapd, query->addr, cache->accepted, - cache->session_timeout); -#else /* CONFIG_DRIVER_RADIUS_ACL */ - /* Re-send original authentication frame for 802.11 processing */ - wpa_printf(MSG_DEBUG, "Re-sending authentication frame after " - "successful RADIUS ACL query"); - ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len, - WLAN_FC_STYPE_AUTH, NULL); -#endif /* CONFIG_DRIVER_RADIUS_ACL */ - - done: - if (prev == NULL) - hapd->acl_queries = query->next; - else - prev->next = query->next; - - hostapd_acl_query_free(query); - - return RADIUS_RX_PROCESSED; -} - - -/** - * hostapd_acl_init: Initialize IEEE 802.11 ACL - * @hapd: hostapd BSS data - * Returns: 0 on success, -1 on failure - */ -int hostapd_acl_init(struct hostapd_data *hapd) -{ - if (radius_client_register(hapd->radius, RADIUS_AUTH, - hostapd_acl_recv_radius, hapd)) - return -1; - - eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL); - - return 0; -} - - -/** - * hostapd_acl_deinit - Deinitialize IEEE 802.11 ACL - * @hapd: hostapd BSS data - */ -void hostapd_acl_deinit(struct hostapd_data *hapd) -{ - struct hostapd_acl_query_data *query, *prev; - - eloop_cancel_timeout(hostapd_acl_expire, hapd, NULL); - - hostapd_acl_cache_free(hapd->acl_cache); - - query = hapd->acl_queries; - while (query) { - prev = query; - query = query->next; - hostapd_acl_query_free(prev); - } -} - - -int hostapd_acl_reconfig(struct hostapd_data *hapd, - struct hostapd_config *oldconf) -{ - if (!hapd->radius_client_reconfigured) - return 0; - - hostapd_acl_deinit(hapd); - return hostapd_acl_init(hapd); -} - -#endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/contrib/hostapd/hostapd/ieee802_11_auth.h b/contrib/hostapd/hostapd/ieee802_11_auth.h deleted file mode 100644 index 0eed825e29..0000000000 --- a/contrib/hostapd/hostapd/ieee802_11_auth.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * hostapd / IEEE 802.11 authentication (ACL) - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IEEE802_11_AUTH_H -#define IEEE802_11_AUTH_H - -enum { - HOSTAPD_ACL_REJECT = 0, - HOSTAPD_ACL_ACCEPT = 1, - HOSTAPD_ACL_PENDING = 2, - HOSTAPD_ACL_ACCEPT_TIMEOUT = 3 -}; - -int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, - const u8 *msg, size_t len, u32 *session_timeout, - u32 *acct_interim_interval, int *vlan_id); -int hostapd_acl_init(struct hostapd_data *hapd); -void hostapd_acl_deinit(struct hostapd_data *hapd); -int hostapd_acl_reconfig(struct hostapd_data *hapd, - struct hostapd_config *oldconf); - -#endif /* IEEE802_11_AUTH_H */ diff --git a/contrib/hostapd/hostapd/ieee802_1x.c b/contrib/hostapd/hostapd/ieee802_1x.c deleted file mode 100644 index 7fd8028057..0000000000 --- a/contrib/hostapd/hostapd/ieee802_1x.c +++ /dev/null @@ -1,2042 +0,0 @@ -/* - * hostapd / IEEE 802.1X-2004 Authenticator - * Copyright (c) 2002-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "hostapd.h" -#include "ieee802_1x.h" -#include "accounting.h" -#include "radius/radius.h" -#include "radius/radius_client.h" -#include "eapol_sm.h" -#include "md5.h" -#include "rc4.h" -#include "eloop.h" -#include "sta_info.h" -#include "wpa.h" -#include "preauth.h" -#include "pmksa_cache.h" -#include "driver.h" -#include "hw_features.h" -#include "eap_server/eap.h" -#include "ieee802_11_defs.h" - - -static void ieee802_1x_finished(struct hostapd_data *hapd, - struct sta_info *sta, int success); - - -static void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta, - u8 type, const u8 *data, size_t datalen) -{ - u8 *buf; - struct ieee802_1x_hdr *xhdr; - size_t len; - int encrypt = 0; - - len = sizeof(*xhdr) + datalen; - buf = os_zalloc(len); - if (buf == NULL) { - wpa_printf(MSG_ERROR, "malloc() failed for " - "ieee802_1x_send(len=%lu)", - (unsigned long) len); - return; - } - - xhdr = (struct ieee802_1x_hdr *) buf; - xhdr->version = hapd->conf->eapol_version; - xhdr->type = type; - xhdr->length = host_to_be16(datalen); - - if (datalen > 0 && data != NULL) - os_memcpy(xhdr + 1, data, datalen); - - if (wpa_auth_pairwise_set(sta->wpa_sm)) - encrypt = 1; - if (sta->flags & WLAN_STA_PREAUTH) { - rsn_preauth_send(hapd, sta, buf, len); - } else { - hostapd_send_eapol(hapd, sta->addr, buf, len, encrypt); - } - - os_free(buf); -} - - -void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd, - struct sta_info *sta, int authorized) -{ - int res; - - if (sta->flags & WLAN_STA_PREAUTH) - return; - - if (authorized) { - sta->flags |= WLAN_STA_AUTHORIZED; - res = hostapd_sta_set_flags(hapd, sta->addr, sta->flags, - WLAN_STA_AUTHORIZED, ~0); - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "authorizing port"); - } else { - sta->flags &= ~WLAN_STA_AUTHORIZED; - res = hostapd_sta_set_flags(hapd, sta->addr, sta->flags, - 0, ~WLAN_STA_AUTHORIZED); - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "unauthorizing port"); - } - - if (res && errno != ENOENT) { - printf("Could not set station " MACSTR " flags for kernel " - "driver (errno=%d).\n", MAC2STR(sta->addr), errno); - } - - if (authorized) - accounting_sta_start(hapd, sta); -} - - -static void ieee802_1x_tx_key_one(struct hostapd_data *hapd, - struct sta_info *sta, - int idx, int broadcast, - u8 *key_data, size_t key_len) -{ - u8 *buf, *ekey; - struct ieee802_1x_hdr *hdr; - struct ieee802_1x_eapol_key *key; - size_t len, ekey_len; - struct eapol_state_machine *sm = sta->eapol_sm; - - if (sm == NULL) - return; - - len = sizeof(*key) + key_len; - buf = os_zalloc(sizeof(*hdr) + len); - if (buf == NULL) - return; - - hdr = (struct ieee802_1x_hdr *) buf; - key = (struct ieee802_1x_eapol_key *) (hdr + 1); - key->type = EAPOL_KEY_TYPE_RC4; - key->key_length = htons(key_len); - wpa_get_ntp_timestamp(key->replay_counter); - - if (os_get_random(key->key_iv, sizeof(key->key_iv))) { - wpa_printf(MSG_ERROR, "Could not get random numbers"); - os_free(buf); - return; - } - - key->key_index = idx | (broadcast ? 0 : BIT(7)); - if (hapd->conf->eapol_key_index_workaround) { - /* According to some information, WinXP Supplicant seems to - * interpret bit7 as an indication whether the key is to be - * activated, so make it possible to enable workaround that - * sets this bit for all keys. */ - key->key_index |= BIT(7); - } - - /* Key is encrypted using "Key-IV + MSK[0..31]" as the RC4-key and - * MSK[32..63] is used to sign the message. */ - if (sm->eap_if->eapKeyData == NULL || sm->eap_if->eapKeyDataLen < 64) { - wpa_printf(MSG_ERROR, "No eapKeyData available for encrypting " - "and signing EAPOL-Key"); - os_free(buf); - return; - } - os_memcpy((u8 *) (key + 1), key_data, key_len); - ekey_len = sizeof(key->key_iv) + 32; - ekey = os_malloc(ekey_len); - if (ekey == NULL) { - wpa_printf(MSG_ERROR, "Could not encrypt key"); - os_free(buf); - return; - } - os_memcpy(ekey, key->key_iv, sizeof(key->key_iv)); - os_memcpy(ekey + sizeof(key->key_iv), sm->eap_if->eapKeyData, 32); - rc4_skip(ekey, ekey_len, 0, (u8 *) (key + 1), key_len); - os_free(ekey); - - /* This header is needed here for HMAC-MD5, but it will be regenerated - * in ieee802_1x_send() */ - hdr->version = hapd->conf->eapol_version; - hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; - hdr->length = host_to_be16(len); - hmac_md5(sm->eap_if->eapKeyData + 32, 32, buf, sizeof(*hdr) + len, - key->key_signature); - - wpa_printf(MSG_DEBUG, "IEEE 802.1X: Sending EAPOL-Key to " MACSTR - " (%s index=%d)", MAC2STR(sm->addr), - broadcast ? "broadcast" : "unicast", idx); - ieee802_1x_send(hapd, sta, IEEE802_1X_TYPE_EAPOL_KEY, (u8 *) key, len); - if (sta->eapol_sm) - sta->eapol_sm->dot1xAuthEapolFramesTx++; - os_free(buf); -} - - -static struct hostapd_wep_keys * -ieee802_1x_group_alloc(struct hostapd_data *hapd, const char *ifname) -{ - struct hostapd_wep_keys *key; - - key = os_zalloc(sizeof(*key)); - if (key == NULL) - return NULL; - - key->default_len = hapd->conf->default_wep_key_len; - - if (key->idx >= hapd->conf->broadcast_key_idx_max || - key->idx < hapd->conf->broadcast_key_idx_min) - key->idx = hapd->conf->broadcast_key_idx_min; - else - key->idx++; - - if (!key->key[key->idx]) - key->key[key->idx] = os_malloc(key->default_len); - if (key->key[key->idx] == NULL || - os_get_random(key->key[key->idx], key->default_len)) { - printf("Could not generate random WEP key (dynamic VLAN).\n"); - os_free(key->key[key->idx]); - key->key[key->idx] = NULL; - os_free(key); - return NULL; - } - key->len[key->idx] = key->default_len; - - wpa_printf(MSG_DEBUG, "%s: Default WEP idx %d for dynamic VLAN\n", - ifname, key->idx); - wpa_hexdump_key(MSG_DEBUG, "Default WEP key (dynamic VLAN)", - key->key[key->idx], key->len[key->idx]); - - if (hostapd_set_encryption(ifname, hapd, "WEP", NULL, key->idx, - key->key[key->idx], key->len[key->idx], 1)) - printf("Could not set dynamic VLAN WEP encryption key.\n"); - - hostapd_set_ieee8021x(ifname, hapd, 1); - - return key; -} - - -static struct hostapd_wep_keys * -ieee802_1x_get_group(struct hostapd_data *hapd, struct hostapd_ssid *ssid, - size_t vlan_id) -{ - const char *ifname; - - if (vlan_id == 0) - return &ssid->wep; - - if (vlan_id <= ssid->max_dyn_vlan_keys && ssid->dyn_vlan_keys && - ssid->dyn_vlan_keys[vlan_id]) - return ssid->dyn_vlan_keys[vlan_id]; - - wpa_printf(MSG_DEBUG, "IEEE 802.1X: Creating new group " - "state machine for VLAN ID %lu", - (unsigned long) vlan_id); - - ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id); - if (ifname == NULL) { - wpa_printf(MSG_DEBUG, "IEEE 802.1X: Unknown VLAN ID %lu - " - "cannot create group key state machine", - (unsigned long) vlan_id); - return NULL; - } - - if (ssid->dyn_vlan_keys == NULL) { - int size = (vlan_id + 1) * sizeof(ssid->dyn_vlan_keys[0]); - ssid->dyn_vlan_keys = os_zalloc(size); - if (ssid->dyn_vlan_keys == NULL) - return NULL; - ssid->max_dyn_vlan_keys = vlan_id; - } - - if (ssid->max_dyn_vlan_keys < vlan_id) { - struct hostapd_wep_keys **na; - int size = (vlan_id + 1) * sizeof(ssid->dyn_vlan_keys[0]); - na = os_realloc(ssid->dyn_vlan_keys, size); - if (na == NULL) - return NULL; - ssid->dyn_vlan_keys = na; - os_memset(&ssid->dyn_vlan_keys[ssid->max_dyn_vlan_keys + 1], 0, - (vlan_id - ssid->max_dyn_vlan_keys) * - sizeof(ssid->dyn_vlan_keys[0])); - ssid->max_dyn_vlan_keys = vlan_id; - } - - ssid->dyn_vlan_keys[vlan_id] = ieee802_1x_group_alloc(hapd, ifname); - - return ssid->dyn_vlan_keys[vlan_id]; -} - - -void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta) -{ - struct hostapd_wep_keys *key = NULL; - struct eapol_state_machine *sm = sta->eapol_sm; - int vlan_id; - - if (sm == NULL || !sm->eap_if->eapKeyData) - return; - - wpa_printf(MSG_DEBUG, "IEEE 802.1X: Sending EAPOL-Key(s) to " MACSTR, - MAC2STR(sta->addr)); - - vlan_id = sta->vlan_id; - if (vlan_id < 0 || vlan_id > MAX_VLAN_ID) - vlan_id = 0; - - if (vlan_id) { - key = ieee802_1x_get_group(hapd, sta->ssid, vlan_id); - if (key && key->key[key->idx]) - ieee802_1x_tx_key_one(hapd, sta, key->idx, 1, - key->key[key->idx], - key->len[key->idx]); - } else if (hapd->default_wep_key) { - ieee802_1x_tx_key_one(hapd, sta, hapd->default_wep_key_idx, 1, - hapd->default_wep_key, - hapd->conf->default_wep_key_len); - } - - if (hapd->conf->individual_wep_key_len > 0) { - u8 *ikey; - ikey = os_malloc(hapd->conf->individual_wep_key_len); - if (ikey == NULL || - os_get_random(ikey, hapd->conf->individual_wep_key_len)) { - wpa_printf(MSG_ERROR, "Could not generate random " - "individual WEP key."); - os_free(ikey); - return; - } - - wpa_hexdump_key(MSG_DEBUG, "Individual WEP key", - ikey, hapd->conf->individual_wep_key_len); - - ieee802_1x_tx_key_one(hapd, sta, 0, 0, ikey, - hapd->conf->individual_wep_key_len); - - /* TODO: set encryption in TX callback, i.e., only after STA - * has ACKed EAPOL-Key frame */ - if (hostapd_set_encryption(hapd->conf->iface, hapd, "WEP", - sta->addr, 0, ikey, - hapd->conf->individual_wep_key_len, - 1)) { - wpa_printf(MSG_ERROR, "Could not set individual WEP " - "encryption."); - } - - os_free(ikey); - } -} - - -const char *radius_mode_txt(struct hostapd_data *hapd) -{ - if (hapd->iface->current_mode == NULL) - return "802.11"; - - switch (hapd->iface->current_mode->mode) { - case HOSTAPD_MODE_IEEE80211A: - return "802.11a"; - case HOSTAPD_MODE_IEEE80211G: - return "802.11g"; - case HOSTAPD_MODE_IEEE80211B: - default: - return "802.11b"; - } -} - - -int radius_sta_rate(struct hostapd_data *hapd, struct sta_info *sta) -{ - int i; - u8 rate = 0; - - for (i = 0; i < sta->supported_rates_len; i++) - if ((sta->supported_rates[i] & 0x7f) > rate) - rate = sta->supported_rates[i] & 0x7f; - - return rate; -} - - -static void ieee802_1x_learn_identity(struct hostapd_data *hapd, - struct eapol_state_machine *sm, - const u8 *eap, size_t len) -{ - const u8 *identity; - size_t identity_len; - - if (len <= sizeof(struct eap_hdr) || - eap[sizeof(struct eap_hdr)] != EAP_TYPE_IDENTITY) - return; - - identity = eap_get_identity(sm->eap, &identity_len); - if (identity == NULL) - return; - - /* Save station identity for future RADIUS packets */ - os_free(sm->identity); - sm->identity = os_malloc(identity_len + 1); - if (sm->identity == NULL) { - sm->identity_len = 0; - return; - } - - os_memcpy(sm->identity, identity, identity_len); - sm->identity_len = identity_len; - sm->identity[identity_len] = '\0'; - hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "STA identity '%s'", sm->identity); - sm->dot1xAuthEapolRespIdFramesRx++; -} - - -static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd, - struct sta_info *sta, - const u8 *eap, size_t len) -{ - struct radius_msg *msg; - char buf[128]; - struct eapol_state_machine *sm = sta->eapol_sm; - - if (sm == NULL) - return; - - ieee802_1x_learn_identity(hapd, sm, eap, len); - - wpa_printf(MSG_DEBUG, "Encapsulating EAP message into a RADIUS " - "packet"); - - sm->radius_identifier = radius_client_get_id(hapd->radius); - msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, - sm->radius_identifier); - if (msg == NULL) { - printf("Could not create net RADIUS packet\n"); - return; - } - - radius_msg_make_authenticator(msg, (u8 *) sta, sizeof(*sta)); - - if (sm->identity && - !radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, - sm->identity, sm->identity_len)) { - printf("Could not add User-Name\n"); - goto fail; - } - - if (hapd->conf->own_ip_addr.af == AF_INET && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, - (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) { - printf("Could not add NAS-IP-Address\n"); - goto fail; - } - -#ifdef CONFIG_IPV6 - if (hapd->conf->own_ip_addr.af == AF_INET6 && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS, - (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) { - printf("Could not add NAS-IPv6-Address\n"); - goto fail; - } -#endif /* CONFIG_IPV6 */ - - if (hapd->conf->nas_identifier && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER, - (u8 *) hapd->conf->nas_identifier, - os_strlen(hapd->conf->nas_identifier))) { - printf("Could not add NAS-Identifier\n"); - goto fail; - } - - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) { - printf("Could not add NAS-Port\n"); - goto fail; - } - - os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s", - MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid); - buf[sizeof(buf) - 1] = '\0'; - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID, - (u8 *) buf, os_strlen(buf))) { - printf("Could not add Called-Station-Id\n"); - goto fail; - } - - os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, - MAC2STR(sta->addr)); - buf[sizeof(buf) - 1] = '\0'; - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, - (u8 *) buf, os_strlen(buf))) { - printf("Could not add Calling-Station-Id\n"); - goto fail; - } - - /* TODO: should probably check MTU from driver config; 2304 is max for - * IEEE 802.11, but use 1400 to avoid problems with too large packets - */ - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) { - printf("Could not add Framed-MTU\n"); - goto fail; - } - - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE, - RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { - printf("Could not add NAS-Port-Type\n"); - goto fail; - } - - if (sta->flags & WLAN_STA_PREAUTH) { - os_strlcpy(buf, "IEEE 802.11i Pre-Authentication", - sizeof(buf)); - } else { - os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s", - radius_sta_rate(hapd, sta) / 2, - (radius_sta_rate(hapd, sta) & 1) ? ".5" : "", - radius_mode_txt(hapd)); - buf[sizeof(buf) - 1] = '\0'; - } - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, - (u8 *) buf, os_strlen(buf))) { - printf("Could not add Connect-Info\n"); - goto fail; - } - - if (eap && !radius_msg_add_eap(msg, eap, len)) { - printf("Could not add EAP-Message\n"); - goto fail; - } - - /* State attribute must be copied if and only if this packet is - * Access-Request reply to the previous Access-Challenge */ - if (sm->last_recv_radius && sm->last_recv_radius->hdr->code == - RADIUS_CODE_ACCESS_CHALLENGE) { - int res = radius_msg_copy_attr(msg, sm->last_recv_radius, - RADIUS_ATTR_STATE); - if (res < 0) { - printf("Could not copy State attribute from previous " - "Access-Challenge\n"); - goto fail; - } - if (res > 0) { - wpa_printf(MSG_DEBUG, "Copied RADIUS State Attribute"); - } - } - - radius_client_send(hapd->radius, msg, RADIUS_AUTH, sta->addr); - return; - - fail: - radius_msg_free(msg); - os_free(msg); -} - - -char *eap_type_text(u8 type) -{ - switch (type) { - case EAP_TYPE_IDENTITY: return "Identity"; - case EAP_TYPE_NOTIFICATION: return "Notification"; - case EAP_TYPE_NAK: return "Nak"; - case EAP_TYPE_MD5: return "MD5-Challenge"; - case EAP_TYPE_OTP: return "One-Time Password"; - case EAP_TYPE_GTC: return "Generic Token Card"; - case EAP_TYPE_TLS: return "TLS"; - case EAP_TYPE_TTLS: return "TTLS"; - case EAP_TYPE_PEAP: return "PEAP"; - case EAP_TYPE_SIM: return "SIM"; - case EAP_TYPE_FAST: return "FAST"; - case EAP_TYPE_SAKE: return "SAKE"; - case EAP_TYPE_PSK: return "PSK"; - case EAP_TYPE_PAX: return "PAX"; - default: return "Unknown"; - } -} - - -static void handle_eap_response(struct hostapd_data *hapd, - struct sta_info *sta, struct eap_hdr *eap, - size_t len) -{ - u8 type, *data; - struct eapol_state_machine *sm = sta->eapol_sm; - if (sm == NULL) - return; - - data = (u8 *) (eap + 1); - - if (len < sizeof(*eap) + 1) { - printf("handle_eap_response: too short response data\n"); - return; - } - - sm->eap_type_supp = type = data[0]; - - hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "received EAP packet (code=%d " - "id=%d len=%d) from STA: EAP Response-%s (%d)", - eap->code, eap->identifier, be_to_host16(eap->length), - eap_type_text(type), type); - - sm->dot1xAuthEapolRespFramesRx++; - - wpabuf_free(sm->eap_if->eapRespData); - sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len); - sm->eapolEap = TRUE; -} - - -/* Process incoming EAP packet from Supplicant */ -static void handle_eap(struct hostapd_data *hapd, struct sta_info *sta, - u8 *buf, size_t len) -{ - struct eap_hdr *eap; - u16 eap_len; - - if (len < sizeof(*eap)) { - printf(" too short EAP packet\n"); - return; - } - - eap = (struct eap_hdr *) buf; - - eap_len = be_to_host16(eap->length); - wpa_printf(MSG_DEBUG, "EAP: code=%d identifier=%d length=%d", - eap->code, eap->identifier, eap_len); - if (eap_len < sizeof(*eap)) { - wpa_printf(MSG_DEBUG, " Invalid EAP length"); - return; - } else if (eap_len > len) { - wpa_printf(MSG_DEBUG, " Too short frame to contain this EAP " - "packet"); - return; - } else if (eap_len < len) { - wpa_printf(MSG_DEBUG, " Ignoring %lu extra bytes after EAP " - "packet", (unsigned long) len - eap_len); - } - - switch (eap->code) { - case EAP_CODE_REQUEST: - wpa_printf(MSG_DEBUG, " (request)"); - return; - case EAP_CODE_RESPONSE: - wpa_printf(MSG_DEBUG, " (response)"); - handle_eap_response(hapd, sta, eap, eap_len); - break; - case EAP_CODE_SUCCESS: - wpa_printf(MSG_DEBUG, " (success)"); - return; - case EAP_CODE_FAILURE: - wpa_printf(MSG_DEBUG, " (failure)"); - return; - default: - wpa_printf(MSG_DEBUG, " (unknown code)"); - return; - } -} - - -/** - * ieee802_1x_receive - Process the EAPOL frames from the Supplicant - * @hapd: hostapd BSS data - * @sa: Source address (sender of the EAPOL frame) - * @buf: EAPOL frame - * @len: Length of buf in octets - * - * This function is called for each incoming EAPOL frame from the interface - */ -void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, - size_t len) -{ - struct sta_info *sta; - struct ieee802_1x_hdr *hdr; - struct ieee802_1x_eapol_key *key; - u16 datalen; - struct rsn_pmksa_cache_entry *pmksa; - - if (!hapd->conf->ieee802_1x && !hapd->conf->wpa && - !hapd->conf->wps_state) - return; - - wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR, - (unsigned long) len, MAC2STR(sa)); - sta = ap_get_sta(hapd, sa); - if (!sta) { - printf(" no station information available\n"); - return; - } - - if (len < sizeof(*hdr)) { - printf(" too short IEEE 802.1X packet\n"); - return; - } - - hdr = (struct ieee802_1x_hdr *) buf; - datalen = be_to_host16(hdr->length); - wpa_printf(MSG_DEBUG, " IEEE 802.1X: version=%d type=%d length=%d", - hdr->version, hdr->type, datalen); - - if (len - sizeof(*hdr) < datalen) { - printf(" frame too short for this IEEE 802.1X packet\n"); - if (sta->eapol_sm) - sta->eapol_sm->dot1xAuthEapLengthErrorFramesRx++; - return; - } - if (len - sizeof(*hdr) > datalen) { - wpa_printf(MSG_DEBUG, " ignoring %lu extra octets after " - "IEEE 802.1X packet", - (unsigned long) len - sizeof(*hdr) - datalen); - } - - if (sta->eapol_sm) { - sta->eapol_sm->dot1xAuthLastEapolFrameVersion = hdr->version; - sta->eapol_sm->dot1xAuthEapolFramesRx++; - } - - key = (struct ieee802_1x_eapol_key *) (hdr + 1); - if (datalen >= sizeof(struct ieee802_1x_eapol_key) && - hdr->type == IEEE802_1X_TYPE_EAPOL_KEY && - (key->type == EAPOL_KEY_TYPE_WPA || - key->type == EAPOL_KEY_TYPE_RSN)) { - wpa_receive(hapd->wpa_auth, sta->wpa_sm, (u8 *) hdr, - sizeof(*hdr) + datalen); - return; - } - - if ((!hapd->conf->ieee802_1x && - !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) || - wpa_key_mgmt_wpa_psk(wpa_auth_sta_key_mgmt(sta->wpa_sm))) - return; - - if (!sta->eapol_sm) { - sta->eapol_sm = eapol_auth_alloc(hapd->eapol_auth, sta->addr, - sta->flags & WLAN_STA_PREAUTH, - sta); - if (!sta->eapol_sm) - return; - -#ifdef CONFIG_WPS - if (!hapd->conf->ieee802_1x && - ((sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) == - WLAN_STA_MAYBE_WPS)) { - /* - * Delay EAPOL frame transmission until a possible WPS - * STA initiates the handshake with EAPOL-Start. - */ - sta->eapol_sm->flags |= EAPOL_SM_WAIT_START; - } -#endif /* CONFIG_WPS */ - - sta->eapol_sm->eap_if->portEnabled = TRUE; - } - - /* since we support version 1, we can ignore version field and proceed - * as specified in version 1 standard [IEEE Std 802.1X-2001, 7.5.5] */ - /* TODO: actually, we are not version 1 anymore.. However, Version 2 - * does not change frame contents, so should be ok to process frames - * more or less identically. Some changes might be needed for - * verification of fields. */ - - switch (hdr->type) { - case IEEE802_1X_TYPE_EAP_PACKET: - handle_eap(hapd, sta, (u8 *) (hdr + 1), datalen); - break; - - case IEEE802_1X_TYPE_EAPOL_START: - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "received EAPOL-Start " - "from STA"); - sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START; - pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm); - if (pmksa) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, - HOSTAPD_LEVEL_DEBUG, "cached PMKSA " - "available - ignore it since " - "STA sent EAPOL-Start"); - wpa_auth_sta_clear_pmksa(sta->wpa_sm, pmksa); - } - sta->eapol_sm->eapolStart = TRUE; - sta->eapol_sm->dot1xAuthEapolStartFramesRx++; - wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL); - break; - - case IEEE802_1X_TYPE_EAPOL_LOGOFF: - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "received EAPOL-Logoff " - "from STA"); - sta->acct_terminate_cause = - RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; - accounting_sta_stop(hapd, sta); - sta->eapol_sm->eapolLogoff = TRUE; - sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++; - break; - - case IEEE802_1X_TYPE_EAPOL_KEY: - wpa_printf(MSG_DEBUG, " EAPOL-Key"); - if (!(sta->flags & WLAN_STA_AUTHORIZED)) { - wpa_printf(MSG_DEBUG, " Dropped key data from " - "unauthorized Supplicant"); - break; - } - break; - - case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT: - wpa_printf(MSG_DEBUG, " EAPOL-Encapsulated-ASF-Alert"); - /* TODO: implement support for this; show data */ - break; - - default: - wpa_printf(MSG_DEBUG, " unknown IEEE 802.1X packet type"); - sta->eapol_sm->dot1xAuthInvalidEapolFramesRx++; - break; - } - - eapol_auth_step(sta->eapol_sm); -} - - -/** - * ieee802_1x_new_station - Start IEEE 802.1X authentication - * @hapd: hostapd BSS data - * @sta: The station - * - * This function is called to start IEEE 802.1X authentication when a new - * station completes IEEE 802.11 association. - */ -void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) -{ - struct rsn_pmksa_cache_entry *pmksa; - int reassoc = 1; - int force_1x = 0; - -#ifdef CONFIG_WPS - if (hapd->conf->wps_state && hapd->conf->wpa && - (sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) { - /* - * Need to enable IEEE 802.1X/EAPOL state machines for possible - * WPS handshake even if IEEE 802.1X/EAPOL is not used for - * authentication in this BSS. - */ - force_1x = 1; - } -#endif /* CONFIG_WPS */ - - if ((!force_1x && !hapd->conf->ieee802_1x) || - wpa_key_mgmt_wpa_psk(wpa_auth_sta_key_mgmt(sta->wpa_sm))) - return; - - if (sta->eapol_sm == NULL) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "start authentication"); - sta->eapol_sm = eapol_auth_alloc(hapd->eapol_auth, sta->addr, - sta->flags & WLAN_STA_PREAUTH, - sta); - if (sta->eapol_sm == NULL) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_INFO, - "failed to allocate state machine"); - return; - } - reassoc = 0; - } - -#ifdef CONFIG_WPS - sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START; - if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS)) { - /* - * Delay EAPOL frame transmission until a possible WPS - * initiates the handshake with EAPOL-Start. - */ - sta->eapol_sm->flags |= EAPOL_SM_WAIT_START; - } -#endif /* CONFIG_WPS */ - - sta->eapol_sm->eap_if->portEnabled = TRUE; - - pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm); - if (pmksa) { - int old_vlanid; - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, - "PMK from PMKSA cache - skip IEEE 802.1X/EAP"); - /* Setup EAPOL state machines to already authenticated state - * because of existing PMKSA information in the cache. */ - sta->eapol_sm->keyRun = TRUE; - sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; - sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING; - sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS; - sta->eapol_sm->authSuccess = TRUE; - if (sta->eapol_sm->eap) - eap_sm_notify_cached(sta->eapol_sm->eap); - old_vlanid = sta->vlan_id; - pmksa_cache_to_eapol_data(pmksa, sta->eapol_sm); - if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED) - sta->vlan_id = 0; - ap_sta_bind_vlan(hapd, sta, old_vlanid); - } else { - if (reassoc) { - /* - * Force EAPOL state machines to start - * re-authentication without having to wait for the - * Supplicant to send EAPOL-Start. - */ - sta->eapol_sm->reAuthenticate = TRUE; - } - eapol_auth_step(sta->eapol_sm); - } -} - - -void ieee802_1x_free_radius_class(struct radius_class_data *class) -{ - size_t i; - if (class == NULL) - return; - for (i = 0; i < class->count; i++) - os_free(class->attr[i].data); - os_free(class->attr); - class->attr = NULL; - class->count = 0; -} - - -int ieee802_1x_copy_radius_class(struct radius_class_data *dst, - const struct radius_class_data *src) -{ - size_t i; - - if (src->attr == NULL) - return 0; - - dst->attr = os_zalloc(src->count * sizeof(struct radius_attr_data)); - if (dst->attr == NULL) - return -1; - - dst->count = 0; - - for (i = 0; i < src->count; i++) { - dst->attr[i].data = os_malloc(src->attr[i].len); - if (dst->attr[i].data == NULL) - break; - dst->count++; - os_memcpy(dst->attr[i].data, src->attr[i].data, - src->attr[i].len); - dst->attr[i].len = src->attr[i].len; - } - - return 0; -} - - -void ieee802_1x_free_station(struct sta_info *sta) -{ - struct eapol_state_machine *sm = sta->eapol_sm; - - if (sm == NULL) - return; - - sta->eapol_sm = NULL; - - if (sm->last_recv_radius) { - radius_msg_free(sm->last_recv_radius); - os_free(sm->last_recv_radius); - } - - os_free(sm->identity); - ieee802_1x_free_radius_class(&sm->radius_class); - eapol_auth_free(sm); -} - - -static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd, - struct sta_info *sta) -{ - u8 *eap; - size_t len; - struct eap_hdr *hdr; - int eap_type = -1; - char buf[64]; - struct radius_msg *msg; - struct eapol_state_machine *sm = sta->eapol_sm; - - if (sm == NULL || sm->last_recv_radius == NULL) { - if (sm) - sm->eap_if->aaaEapNoReq = TRUE; - return; - } - - msg = sm->last_recv_radius; - - eap = radius_msg_get_eap(msg, &len); - if (eap == NULL) { - /* RFC 3579, Chap. 2.6.3: - * RADIUS server SHOULD NOT send Access-Reject/no EAP-Message - * attribute */ - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_WARNING, "could not extract " - "EAP-Message from RADIUS message"); - sm->eap_if->aaaEapNoReq = TRUE; - return; - } - - if (len < sizeof(*hdr)) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_WARNING, "too short EAP packet " - "received from authentication server"); - os_free(eap); - sm->eap_if->aaaEapNoReq = TRUE; - return; - } - - if (len > sizeof(*hdr)) - eap_type = eap[sizeof(*hdr)]; - - hdr = (struct eap_hdr *) eap; - switch (hdr->code) { - case EAP_CODE_REQUEST: - if (eap_type >= 0) - sm->eap_type_authsrv = eap_type; - os_snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)", - eap_type >= 0 ? eap_type_text(eap_type) : "??", - eap_type); - break; - case EAP_CODE_RESPONSE: - os_snprintf(buf, sizeof(buf), "EAP Response-%s (%d)", - eap_type >= 0 ? eap_type_text(eap_type) : "??", - eap_type); - break; - case EAP_CODE_SUCCESS: - os_strlcpy(buf, "EAP Success", sizeof(buf)); - break; - case EAP_CODE_FAILURE: - os_strlcpy(buf, "EAP Failure", sizeof(buf)); - break; - default: - os_strlcpy(buf, "unknown EAP code", sizeof(buf)); - break; - } - buf[sizeof(buf) - 1] = '\0'; - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "decapsulated EAP packet (code=%d " - "id=%d len=%d) from RADIUS server: %s", - hdr->code, hdr->identifier, be_to_host16(hdr->length), - buf); - sm->eap_if->aaaEapReq = TRUE; - - wpabuf_free(sm->eap_if->aaaEapReqData); - sm->eap_if->aaaEapReqData = wpabuf_alloc_ext_data(eap, len); -} - - -static void ieee802_1x_get_keys(struct hostapd_data *hapd, - struct sta_info *sta, struct radius_msg *msg, - struct radius_msg *req, - const u8 *shared_secret, - size_t shared_secret_len) -{ - struct radius_ms_mppe_keys *keys; - struct eapol_state_machine *sm = sta->eapol_sm; - if (sm == NULL) - return; - - keys = radius_msg_get_ms_keys(msg, req, shared_secret, - shared_secret_len); - - if (keys && keys->send && keys->recv) { - size_t len = keys->send_len + keys->recv_len; - wpa_hexdump_key(MSG_DEBUG, "MS-MPPE-Send-Key", - keys->send, keys->send_len); - wpa_hexdump_key(MSG_DEBUG, "MS-MPPE-Recv-Key", - keys->recv, keys->recv_len); - - os_free(sm->eap_if->aaaEapKeyData); - sm->eap_if->aaaEapKeyData = os_malloc(len); - if (sm->eap_if->aaaEapKeyData) { - os_memcpy(sm->eap_if->aaaEapKeyData, keys->recv, - keys->recv_len); - os_memcpy(sm->eap_if->aaaEapKeyData + keys->recv_len, - keys->send, keys->send_len); - sm->eap_if->aaaEapKeyDataLen = len; - sm->eap_if->aaaEapKeyAvailable = TRUE; - } - } - - if (keys) { - os_free(keys->send); - os_free(keys->recv); - os_free(keys); - } -} - - -static void ieee802_1x_store_radius_class(struct hostapd_data *hapd, - struct sta_info *sta, - struct radius_msg *msg) -{ - u8 *class; - size_t class_len; - struct eapol_state_machine *sm = sta->eapol_sm; - int count, i; - struct radius_attr_data *nclass; - size_t nclass_count; - - if (!hapd->conf->radius->acct_server || hapd->radius == NULL || - sm == NULL) - return; - - ieee802_1x_free_radius_class(&sm->radius_class); - count = radius_msg_count_attr(msg, RADIUS_ATTR_CLASS, 1); - if (count <= 0) - return; - - nclass = os_zalloc(count * sizeof(struct radius_attr_data)); - if (nclass == NULL) - return; - - nclass_count = 0; - - class = NULL; - for (i = 0; i < count; i++) { - do { - if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CLASS, - &class, &class_len, - class) < 0) { - i = count; - break; - } - } while (class_len < 1); - - nclass[nclass_count].data = os_malloc(class_len); - if (nclass[nclass_count].data == NULL) - break; - - os_memcpy(nclass[nclass_count].data, class, class_len); - nclass[nclass_count].len = class_len; - nclass_count++; - } - - sm->radius_class.attr = nclass; - sm->radius_class.count = nclass_count; - wpa_printf(MSG_DEBUG, "IEEE 802.1X: Stored %lu RADIUS Class " - "attributes for " MACSTR, - (unsigned long) sm->radius_class.count, - MAC2STR(sta->addr)); -} - - -/* Update sta->identity based on User-Name attribute in Access-Accept */ -static void ieee802_1x_update_sta_identity(struct hostapd_data *hapd, - struct sta_info *sta, - struct radius_msg *msg) -{ - u8 *buf, *identity; - size_t len; - struct eapol_state_machine *sm = sta->eapol_sm; - - if (sm == NULL) - return; - - if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, &buf, &len, - NULL) < 0) - return; - - identity = os_malloc(len + 1); - if (identity == NULL) - return; - - os_memcpy(identity, buf, len); - identity[len] = '\0'; - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "old identity '%s' updated with " - "User-Name from Access-Accept '%s'", - sm->identity ? (char *) sm->identity : "N/A", - (char *) identity); - - os_free(sm->identity); - sm->identity = identity; - sm->identity_len = len; -} - - -struct sta_id_search { - u8 identifier; - struct eapol_state_machine *sm; -}; - - -static int ieee802_1x_select_radius_identifier(struct hostapd_data *hapd, - struct sta_info *sta, - void *ctx) -{ - struct sta_id_search *id_search = ctx; - struct eapol_state_machine *sm = sta->eapol_sm; - - if (sm && sm->radius_identifier >= 0 && - sm->radius_identifier == id_search->identifier) { - id_search->sm = sm; - return 1; - } - return 0; -} - - -static struct eapol_state_machine * -ieee802_1x_search_radius_identifier(struct hostapd_data *hapd, u8 identifier) -{ - struct sta_id_search id_search; - id_search.identifier = identifier; - id_search.sm = NULL; - ap_for_each_sta(hapd, ieee802_1x_select_radius_identifier, &id_search); - return id_search.sm; -} - - -/** - * ieee802_1x_receive_auth - Process RADIUS frames from Authentication Server - * @msg: RADIUS response message - * @req: RADIUS request message - * @shared_secret: RADIUS shared secret - * @shared_secret_len: Length of shared_secret in octets - * @data: Context data (struct hostapd_data *) - * Returns: Processing status - */ -static RadiusRxResult -ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, - const u8 *shared_secret, size_t shared_secret_len, - void *data) -{ - struct hostapd_data *hapd = data; - struct sta_info *sta; - u32 session_timeout = 0, termination_action, acct_interim_interval; - int session_timeout_set, old_vlanid = 0; - struct eapol_state_machine *sm; - int override_eapReq = 0; - - sm = ieee802_1x_search_radius_identifier(hapd, msg->hdr->identifier); - if (sm == NULL) { - wpa_printf(MSG_DEBUG, "IEEE 802.1X: Could not find matching " - "station for this RADIUS message"); - return RADIUS_RX_UNKNOWN; - } - sta = sm->sta; - - /* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be - * present when packet contains an EAP-Message attribute */ - if (msg->hdr->code == RADIUS_CODE_ACCESS_REJECT && - radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL, - 0) < 0 && - radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) { - wpa_printf(MSG_DEBUG, "Allowing RADIUS Access-Reject without " - "Message-Authenticator since it does not include " - "EAP-Message"); - } else if (radius_msg_verify(msg, shared_secret, shared_secret_len, - req, 1)) { - printf("Incoming RADIUS packet did not have correct " - "Message-Authenticator - dropped\n"); - return RADIUS_RX_INVALID_AUTHENTICATOR; - } - - if (msg->hdr->code != RADIUS_CODE_ACCESS_ACCEPT && - msg->hdr->code != RADIUS_CODE_ACCESS_REJECT && - msg->hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) { - printf("Unknown RADIUS message code\n"); - return RADIUS_RX_UNKNOWN; - } - - sm->radius_identifier = -1; - wpa_printf(MSG_DEBUG, "RADIUS packet matching with station " MACSTR, - MAC2STR(sta->addr)); - - if (sm->last_recv_radius) { - radius_msg_free(sm->last_recv_radius); - os_free(sm->last_recv_radius); - } - - sm->last_recv_radius = msg; - - session_timeout_set = - !radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT, - &session_timeout); - if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_TERMINATION_ACTION, - &termination_action)) - termination_action = RADIUS_TERMINATION_ACTION_DEFAULT; - - if (hapd->conf->radius->acct_interim_interval == 0 && - msg->hdr->code == RADIUS_CODE_ACCESS_ACCEPT && - radius_msg_get_attr_int32(msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL, - &acct_interim_interval) == 0) { - if (acct_interim_interval < 60) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_INFO, - "ignored too small " - "Acct-Interim-Interval %d", - acct_interim_interval); - } else - sta->acct_interim_interval = acct_interim_interval; - } - - - switch (msg->hdr->code) { - case RADIUS_CODE_ACCESS_ACCEPT: - if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED) - sta->vlan_id = 0; - else { - old_vlanid = sta->vlan_id; - sta->vlan_id = radius_msg_get_vlanid(msg); - } - if (sta->vlan_id > 0 && - hostapd_get_vlan_id_ifname(hapd->conf->vlan, - sta->vlan_id)) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, - "VLAN ID %d", sta->vlan_id); - } else if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_REQUIRED) { - sta->eapol_sm->authFail = TRUE; - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_INFO, "authentication " - "server did not include required VLAN " - "ID in Access-Accept"); - break; - } - - ap_sta_bind_vlan(hapd, sta, old_vlanid); - - /* RFC 3580, Ch. 3.17 */ - if (session_timeout_set && termination_action == - RADIUS_TERMINATION_ACTION_RADIUS_REQUEST) { - sm->reAuthPeriod = session_timeout; - } else if (session_timeout_set) - ap_sta_session_timeout(hapd, sta, session_timeout); - - sm->eap_if->aaaSuccess = TRUE; - override_eapReq = 1; - ieee802_1x_get_keys(hapd, sta, msg, req, shared_secret, - shared_secret_len); - ieee802_1x_store_radius_class(hapd, sta, msg); - ieee802_1x_update_sta_identity(hapd, sta, msg); - if (sm->eap_if->eapKeyAvailable && - wpa_auth_pmksa_add(sta->wpa_sm, sm->eapol_key_crypt, - session_timeout_set ? - (int) session_timeout : -1, sm) == 0) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, - HOSTAPD_LEVEL_DEBUG, - "Added PMKSA cache entry"); - } - break; - case RADIUS_CODE_ACCESS_REJECT: - sm->eap_if->aaaFail = TRUE; - override_eapReq = 1; - break; - case RADIUS_CODE_ACCESS_CHALLENGE: - sm->eap_if->aaaEapReq = TRUE; - if (session_timeout_set) { - /* RFC 2869, Ch. 2.3.2; RFC 3580, Ch. 3.17 */ - sm->eap_if->aaaMethodTimeout = session_timeout; - hostapd_logger(hapd, sm->addr, - HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, - "using EAP timeout of %d seconds (from " - "RADIUS)", - sm->eap_if->aaaMethodTimeout); - } else { - /* - * Use dynamic retransmission behavior per EAP - * specification. - */ - sm->eap_if->aaaMethodTimeout = 0; - } - break; - } - - ieee802_1x_decapsulate_radius(hapd, sta); - if (override_eapReq) - sm->eap_if->aaaEapReq = FALSE; - - eapol_auth_step(sm); - - return RADIUS_RX_QUEUED; -} - - -void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta) -{ - struct eapol_state_machine *sm = sta->eapol_sm; - if (sm == NULL) - return; - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "aborting authentication"); - - if (sm->last_recv_radius) { - radius_msg_free(sm->last_recv_radius); - os_free(sm->last_recv_radius); - sm->last_recv_radius = NULL; - } - - if (sm->eap_if->eapTimeout) { - /* - * Disconnect the STA since it did not reply to the last EAP - * request and we cannot continue EAP processing (EAP-Failure - * could only be sent if the EAP peer actually replied). - */ - sm->eap_if->portEnabled = FALSE; - hostapd_sta_deauth(hapd, sta->addr, - WLAN_REASON_PREV_AUTH_NOT_VALID); - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | - WLAN_STA_AUTHORIZED); - eloop_cancel_timeout(ap_handle_timer, hapd, sta); - eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta); - sta->timeout_next = STA_REMOVE; - } -} - - -#ifdef HOSTAPD_DUMP_STATE -static void fprint_char(FILE *f, char c) -{ - if (c >= 32 && c < 127) - fprintf(f, "%c", c); - else - fprintf(f, "<%02x>", c); -} - - -void ieee802_1x_dump_state(FILE *f, const char *prefix, struct sta_info *sta) -{ - struct eapol_state_machine *sm = sta->eapol_sm; - if (sm == NULL) - return; - - fprintf(f, "%sIEEE 802.1X:\n", prefix); - - if (sm->identity) { - size_t i; - fprintf(f, "%sidentity=", prefix); - for (i = 0; i < sm->identity_len; i++) - fprint_char(f, sm->identity[i]); - fprintf(f, "\n"); - } - - fprintf(f, "%slast EAP type: Authentication Server: %d (%s) " - "Supplicant: %d (%s)\n", prefix, - sm->eap_type_authsrv, eap_type_text(sm->eap_type_authsrv), - sm->eap_type_supp, eap_type_text(sm->eap_type_supp)); - - fprintf(f, "%scached_packets=%s\n", prefix, - sm->last_recv_radius ? "[RX RADIUS]" : ""); - - eapol_auth_dump_state(f, prefix, sm); -} -#endif /* HOSTAPD_DUMP_STATE */ - - -static int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd) -{ - if (hapd->conf->default_wep_key_len < 1) - return 0; - - os_free(hapd->default_wep_key); - hapd->default_wep_key = os_malloc(hapd->conf->default_wep_key_len); - if (hapd->default_wep_key == NULL || - os_get_random(hapd->default_wep_key, - hapd->conf->default_wep_key_len)) { - printf("Could not generate random WEP key.\n"); - os_free(hapd->default_wep_key); - hapd->default_wep_key = NULL; - return -1; - } - - wpa_hexdump_key(MSG_DEBUG, "IEEE 802.1X: New default WEP key", - hapd->default_wep_key, - hapd->conf->default_wep_key_len); - - return 0; -} - - -static int ieee802_1x_sta_key_available(struct hostapd_data *hapd, - struct sta_info *sta, void *ctx) -{ - if (sta->eapol_sm) { - sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; - eapol_auth_step(sta->eapol_sm); - } - return 0; -} - - -static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - - if (hapd->default_wep_key_idx >= 3) - hapd->default_wep_key_idx = - hapd->conf->individual_wep_key_len > 0 ? 1 : 0; - else - hapd->default_wep_key_idx++; - - wpa_printf(MSG_DEBUG, "IEEE 802.1X: New default WEP key index %d", - hapd->default_wep_key_idx); - - if (ieee802_1x_rekey_broadcast(hapd)) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_WARNING, "failed to generate a " - "new broadcast key"); - os_free(hapd->default_wep_key); - hapd->default_wep_key = NULL; - return; - } - - /* TODO: Could setup key for RX here, but change default TX keyid only - * after new broadcast key has been sent to all stations. */ - if (hostapd_set_encryption(hapd->conf->iface, hapd, "WEP", NULL, - hapd->default_wep_key_idx, - hapd->default_wep_key, - hapd->conf->default_wep_key_len, 1)) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_WARNING, "failed to configure a " - "new broadcast key"); - os_free(hapd->default_wep_key); - hapd->default_wep_key = NULL; - return; - } - - ap_for_each_sta(hapd, ieee802_1x_sta_key_available, NULL); - - if (hapd->conf->wep_rekeying_period > 0) { - eloop_register_timeout(hapd->conf->wep_rekeying_period, 0, - ieee802_1x_rekey, hapd, NULL); - } -} - - -static void ieee802_1x_eapol_send(void *ctx, void *sta_ctx, u8 type, - const u8 *data, size_t datalen) -{ - ieee802_1x_send(ctx, sta_ctx, type, data, datalen); -} - - -static void ieee802_1x_aaa_send(void *ctx, void *sta_ctx, - const u8 *data, size_t datalen) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta = sta_ctx; - - ieee802_1x_encapsulate_radius(hapd, sta, data, datalen); -} - - -static void _ieee802_1x_finished(void *ctx, void *sta_ctx, int success, - int preauth) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta = sta_ctx; - if (preauth) - rsn_preauth_finished(hapd, sta, success); - else - ieee802_1x_finished(hapd, sta, success); -} - - -static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity, - size_t identity_len, int phase2, - struct eap_user *user) -{ - struct hostapd_data *hapd = ctx; - const struct hostapd_eap_user *eap_user; - int i, count; - - eap_user = hostapd_get_eap_user(hapd->conf, identity, - identity_len, phase2); - if (eap_user == NULL) - return -1; - - os_memset(user, 0, sizeof(*user)); - user->phase2 = phase2; - count = EAP_USER_MAX_METHODS; - if (count > EAP_MAX_METHODS) - count = EAP_MAX_METHODS; - for (i = 0; i < count; i++) { - user->methods[i].vendor = eap_user->methods[i].vendor; - user->methods[i].method = eap_user->methods[i].method; - } - - if (eap_user->password) { - user->password = os_malloc(eap_user->password_len); - if (user->password == NULL) - return -1; - os_memcpy(user->password, eap_user->password, - eap_user->password_len); - user->password_len = eap_user->password_len; - } - user->force_version = eap_user->force_version; - user->ttls_auth = eap_user->ttls_auth; - - return 0; -} - - -static int ieee802_1x_sta_entry_alive(void *ctx, const u8 *addr) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta; - sta = ap_get_sta(hapd, addr); - if (sta == NULL || sta->eapol_sm == NULL) - return 0; - return 1; -} - - -static void ieee802_1x_logger(void *ctx, const u8 *addr, - eapol_logger_level level, const char *txt) -{ - struct hostapd_data *hapd = ctx; - int hlevel; - - switch (level) { - case EAPOL_LOGGER_WARNING: - hlevel = HOSTAPD_LEVEL_WARNING; - break; - case EAPOL_LOGGER_INFO: - hlevel = HOSTAPD_LEVEL_INFO; - break; - case EAPOL_LOGGER_DEBUG: - default: - hlevel = HOSTAPD_LEVEL_DEBUG; - break; - } - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE8021X, hlevel, "%s", - txt); -} - - -static void ieee802_1x_set_port_authorized(void *ctx, void *sta_ctx, - int authorized) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta = sta_ctx; - ieee802_1x_set_sta_authorized(hapd, sta, authorized); -} - - -static void _ieee802_1x_abort_auth(void *ctx, void *sta_ctx) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta = sta_ctx; - ieee802_1x_abort_auth(hapd, sta); -} - - -static void _ieee802_1x_tx_key(void *ctx, void *sta_ctx) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta = sta_ctx; - ieee802_1x_tx_key(hapd, sta); -} - - -int ieee802_1x_init(struct hostapd_data *hapd) -{ - int i; - struct eapol_auth_config conf; - struct eapol_auth_cb cb; - - os_memset(&conf, 0, sizeof(conf)); - conf.hapd = hapd; - conf.eap_reauth_period = hapd->conf->eap_reauth_period; - conf.wpa = hapd->conf->wpa; - conf.individual_wep_key_len = hapd->conf->individual_wep_key_len; - conf.eap_server = hapd->conf->eap_server; - conf.ssl_ctx = hapd->ssl_ctx; - conf.eap_sim_db_priv = hapd->eap_sim_db_priv; - conf.eap_req_id_text = hapd->conf->eap_req_id_text; - conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len; - conf.pac_opaque_encr_key = hapd->conf->pac_opaque_encr_key; - conf.eap_fast_a_id = hapd->conf->eap_fast_a_id; - conf.eap_fast_a_id_len = hapd->conf->eap_fast_a_id_len; - conf.eap_fast_a_id_info = hapd->conf->eap_fast_a_id_info; - conf.eap_fast_prov = hapd->conf->eap_fast_prov; - conf.pac_key_lifetime = hapd->conf->pac_key_lifetime; - conf.pac_key_refresh_time = hapd->conf->pac_key_refresh_time; - conf.eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind; - conf.tnc = hapd->conf->tnc; - conf.wps = hapd->wps; - - os_memset(&cb, 0, sizeof(cb)); - cb.eapol_send = ieee802_1x_eapol_send; - cb.aaa_send = ieee802_1x_aaa_send; - cb.finished = _ieee802_1x_finished; - cb.get_eap_user = ieee802_1x_get_eap_user; - cb.sta_entry_alive = ieee802_1x_sta_entry_alive; - cb.logger = ieee802_1x_logger; - cb.set_port_authorized = ieee802_1x_set_port_authorized; - cb.abort_auth = _ieee802_1x_abort_auth; - cb.tx_key = _ieee802_1x_tx_key; - - hapd->eapol_auth = eapol_auth_init(&conf, &cb); - if (hapd->eapol_auth == NULL) - return -1; - - if ((hapd->conf->ieee802_1x || hapd->conf->wpa) && - hostapd_set_ieee8021x(hapd->conf->iface, hapd, 1)) - return -1; - - if (radius_client_register(hapd->radius, RADIUS_AUTH, - ieee802_1x_receive_auth, hapd)) - return -1; - - if (hapd->conf->default_wep_key_len) { - hostapd_set_privacy(hapd, 1); - - for (i = 0; i < 4; i++) - hostapd_set_encryption(hapd->conf->iface, hapd, - "none", NULL, i, NULL, 0, 0); - - ieee802_1x_rekey(hapd, NULL); - - if (hapd->default_wep_key == NULL) - return -1; - } - - return 0; -} - - -void ieee802_1x_deinit(struct hostapd_data *hapd) -{ - eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL); - - if (hapd->driver != NULL && - (hapd->conf->ieee802_1x || hapd->conf->wpa)) - hostapd_set_ieee8021x(hapd->conf->iface, hapd, 0); - - eapol_auth_deinit(hapd->eapol_auth); - hapd->eapol_auth = NULL; -} - - -int ieee802_1x_reconfig(struct hostapd_data *hapd, - struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss) -{ - ieee802_1x_deinit(hapd); - return ieee802_1x_init(hapd); -} - - -int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta, - u8 *buf, size_t len, int ack) -{ - struct ieee80211_hdr *hdr; - struct ieee802_1x_hdr *xhdr; - struct ieee802_1x_eapol_key *key; - u8 *pos; - const unsigned char rfc1042_hdr[ETH_ALEN] = - { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; - - if (sta == NULL) - return -1; - if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2 + sizeof(*xhdr)) - return 0; - - hdr = (struct ieee80211_hdr *) buf; - pos = (u8 *) (hdr + 1); - if (os_memcmp(pos, rfc1042_hdr, sizeof(rfc1042_hdr)) != 0) - return 0; - pos += sizeof(rfc1042_hdr); - if (WPA_GET_BE16(pos) != ETH_P_PAE) - return 0; - pos += 2; - - xhdr = (struct ieee802_1x_hdr *) pos; - pos += sizeof(*xhdr); - - wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " TX status - version=%d " - "type=%d length=%d - ack=%d", - MAC2STR(sta->addr), xhdr->version, xhdr->type, - be_to_host16(xhdr->length), ack); - - /* EAPOL EAP-Packet packets are eventually re-sent by either Supplicant - * or Authenticator state machines, but EAPOL-Key packets are not - * retransmitted in case of failure. Try to re-sent failed EAPOL-Key - * packets couple of times because otherwise STA keys become - * unsynchronized with AP. */ - if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY && !ack && - pos + sizeof(*key) <= buf + len) { - key = (struct ieee802_1x_eapol_key *) pos; - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "did not Ack EAPOL-Key " - "frame (%scast index=%d)", - key->key_index & BIT(7) ? "uni" : "broad", - key->key_index & ~BIT(7)); - /* TODO: re-send EAPOL-Key couple of times (with short delay - * between them?). If all attempt fail, report error and - * deauthenticate STA so that it will get new keys when - * authenticating again (e.g., after returning in range). - * Separate limit/transmit state needed both for unicast and - * broadcast keys(?) */ - } - /* TODO: could move unicast key configuration from ieee802_1x_tx_key() - * to here and change the key only if the EAPOL-Key packet was Acked. - */ - - return 1; -} - - -u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len) -{ - if (sm == NULL || sm->identity == NULL) - return NULL; - - *len = sm->identity_len; - return sm->identity; -} - - -u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len, - int idx) -{ - if (sm == NULL || sm->radius_class.attr == NULL || - idx >= (int) sm->radius_class.count) - return NULL; - - *len = sm->radius_class.attr[idx].len; - return sm->radius_class.attr[idx].data; -} - - -const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len) -{ - if (sm == NULL) - return NULL; - - *len = sm->eap_if->eapKeyDataLen; - return sm->eap_if->eapKeyData; -} - - -void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm, - int enabled) -{ - if (sm == NULL) - return; - sm->eap_if->portEnabled = enabled ? TRUE : FALSE; - eapol_auth_step(sm); -} - - -void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, - int valid) -{ - if (sm == NULL) - return; - sm->portValid = valid ? TRUE : FALSE; - eapol_auth_step(sm); -} - - -void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth) -{ - if (sm == NULL) - return; - if (pre_auth) - sm->flags |= EAPOL_SM_PREAUTH; - else - sm->flags &= ~EAPOL_SM_PREAUTH; -} - - -static const char * bool_txt(Boolean bool) -{ - return bool ? "TRUE" : "FALSE"; -} - - -int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen) -{ - /* TODO */ - return 0; -} - - -int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, - char *buf, size_t buflen) -{ - int len = 0, ret; - struct eapol_state_machine *sm = sta->eapol_sm; - - if (sm == NULL) - return 0; - - ret = os_snprintf(buf + len, buflen - len, - "dot1xPaePortNumber=%d\n" - "dot1xPaePortProtocolVersion=%d\n" - "dot1xPaePortCapabilities=1\n" - "dot1xPaePortInitialize=%d\n" - "dot1xPaePortReauthenticate=FALSE\n", - sta->aid, - EAPOL_VERSION, - sm->initialize); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - /* dot1xAuthConfigTable */ - ret = os_snprintf(buf + len, buflen - len, - "dot1xAuthPaeState=%d\n" - "dot1xAuthBackendAuthState=%d\n" - "dot1xAuthAdminControlledDirections=%d\n" - "dot1xAuthOperControlledDirections=%d\n" - "dot1xAuthAuthControlledPortStatus=%d\n" - "dot1xAuthAuthControlledPortControl=%d\n" - "dot1xAuthQuietPeriod=%u\n" - "dot1xAuthServerTimeout=%u\n" - "dot1xAuthReAuthPeriod=%u\n" - "dot1xAuthReAuthEnabled=%s\n" - "dot1xAuthKeyTxEnabled=%s\n", - sm->auth_pae_state + 1, - sm->be_auth_state + 1, - sm->adminControlledDirections, - sm->operControlledDirections, - sm->authPortStatus, - sm->portControl, - sm->quietPeriod, - sm->serverTimeout, - sm->reAuthPeriod, - bool_txt(sm->reAuthEnabled), - bool_txt(sm->keyTxEnabled)); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - /* dot1xAuthStatsTable */ - ret = os_snprintf(buf + len, buflen - len, - "dot1xAuthEapolFramesRx=%u\n" - "dot1xAuthEapolFramesTx=%u\n" - "dot1xAuthEapolStartFramesRx=%u\n" - "dot1xAuthEapolLogoffFramesRx=%u\n" - "dot1xAuthEapolRespIdFramesRx=%u\n" - "dot1xAuthEapolRespFramesRx=%u\n" - "dot1xAuthEapolReqIdFramesTx=%u\n" - "dot1xAuthEapolReqFramesTx=%u\n" - "dot1xAuthInvalidEapolFramesRx=%u\n" - "dot1xAuthEapLengthErrorFramesRx=%u\n" - "dot1xAuthLastEapolFrameVersion=%u\n" - "dot1xAuthLastEapolFrameSource=" MACSTR "\n", - sm->dot1xAuthEapolFramesRx, - sm->dot1xAuthEapolFramesTx, - sm->dot1xAuthEapolStartFramesRx, - sm->dot1xAuthEapolLogoffFramesRx, - sm->dot1xAuthEapolRespIdFramesRx, - sm->dot1xAuthEapolRespFramesRx, - sm->dot1xAuthEapolReqIdFramesTx, - sm->dot1xAuthEapolReqFramesTx, - sm->dot1xAuthInvalidEapolFramesRx, - sm->dot1xAuthEapLengthErrorFramesRx, - sm->dot1xAuthLastEapolFrameVersion, - MAC2STR(sm->addr)); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - /* dot1xAuthDiagTable */ - ret = os_snprintf(buf + len, buflen - len, - "dot1xAuthEntersConnecting=%u\n" - "dot1xAuthEapLogoffsWhileConnecting=%u\n" - "dot1xAuthEntersAuthenticating=%u\n" - "dot1xAuthAuthSuccessesWhileAuthenticating=%u\n" - "dot1xAuthAuthTimeoutsWhileAuthenticating=%u\n" - "dot1xAuthAuthFailWhileAuthenticating=%u\n" - "dot1xAuthAuthEapStartsWhileAuthenticating=%u\n" - "dot1xAuthAuthEapLogoffWhileAuthenticating=%u\n" - "dot1xAuthAuthReauthsWhileAuthenticated=%u\n" - "dot1xAuthAuthEapStartsWhileAuthenticated=%u\n" - "dot1xAuthAuthEapLogoffWhileAuthenticated=%u\n" - "dot1xAuthBackendResponses=%u\n" - "dot1xAuthBackendAccessChallenges=%u\n" - "dot1xAuthBackendOtherRequestsToSupplicant=%u\n" - "dot1xAuthBackendAuthSuccesses=%u\n" - "dot1xAuthBackendAuthFails=%u\n", - sm->authEntersConnecting, - sm->authEapLogoffsWhileConnecting, - sm->authEntersAuthenticating, - sm->authAuthSuccessesWhileAuthenticating, - sm->authAuthTimeoutsWhileAuthenticating, - sm->authAuthFailWhileAuthenticating, - sm->authAuthEapStartsWhileAuthenticating, - sm->authAuthEapLogoffWhileAuthenticating, - sm->authAuthReauthsWhileAuthenticated, - sm->authAuthEapStartsWhileAuthenticated, - sm->authAuthEapLogoffWhileAuthenticated, - sm->backendResponses, - sm->backendAccessChallenges, - sm->backendOtherRequestsToSupplicant, - sm->backendAuthSuccesses, - sm->backendAuthFails); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - /* dot1xAuthSessionStatsTable */ - ret = os_snprintf(buf + len, buflen - len, - /* TODO: dot1xAuthSessionOctetsRx */ - /* TODO: dot1xAuthSessionOctetsTx */ - /* TODO: dot1xAuthSessionFramesRx */ - /* TODO: dot1xAuthSessionFramesTx */ - "dot1xAuthSessionId=%08X-%08X\n" - "dot1xAuthSessionAuthenticMethod=%d\n" - "dot1xAuthSessionTime=%u\n" - "dot1xAuthSessionTerminateCause=999\n" - "dot1xAuthSessionUserName=%s\n", - sta->acct_session_id_hi, sta->acct_session_id_lo, - (wpa_key_mgmt_wpa_ieee8021x( - wpa_auth_sta_key_mgmt(sta->wpa_sm))) ? - 1 : 2, - (unsigned int) (time(NULL) - - sta->acct_session_start), - sm->identity); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - return len; -} - - -static void ieee802_1x_finished(struct hostapd_data *hapd, - struct sta_info *sta, int success) -{ - const u8 *key; - size_t len; - /* TODO: get PMKLifetime from WPA parameters */ - static const int dot11RSNAConfigPMKLifetime = 43200; - - key = ieee802_1x_get_key(sta->eapol_sm, &len); - if (success && key && len >= PMK_LEN && - wpa_auth_pmksa_add(sta->wpa_sm, key, dot11RSNAConfigPMKLifetime, - sta->eapol_sm) == 0) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, - HOSTAPD_LEVEL_DEBUG, - "Added PMKSA cache entry (IEEE 802.1X)"); - } -} diff --git a/contrib/hostapd/hostapd/ieee802_1x.h b/contrib/hostapd/hostapd/ieee802_1x.h deleted file mode 100644 index 94cff93563..0000000000 --- a/contrib/hostapd/hostapd/ieee802_1x.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * hostapd / IEEE 802.1X-2004 Authenticator - * Copyright (c) 2002-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IEEE802_1X_H -#define IEEE802_1X_H - -struct hostapd_data; -struct sta_info; -struct eapol_state_machine; -struct hostapd_config; -struct hostapd_bss_config; - -/* RFC 3580, 4. RC4 EAPOL-Key Frame */ - -struct ieee802_1x_eapol_key { - u8 type; - u16 key_length; - u8 replay_counter[8]; /* does not repeat within the life of the keying - * material used to encrypt the Key field; - * 64-bit NTP timestamp MAY be used here */ - u8 key_iv[16]; /* cryptographically random number */ - u8 key_index; /* key flag in the most significant bit: - * 0 = broadcast (default key), - * 1 = unicast (key mapping key); key index is in the - * 7 least significant bits */ - u8 key_signature[16]; /* HMAC-MD5 message integrity check computed with - * MS-MPPE-Send-Key as the key */ - - /* followed by key: if packet body length = 44 + key length, then the - * key field (of key_length bytes) contains the key in encrypted form; - * if packet body length = 44, key field is absent and key_length - * represents the number of least significant octets from - * MS-MPPE-Send-Key attribute to be used as the keying material; - * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */ -} __attribute__ ((packed)); - - -void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, - size_t len); -void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta); -void ieee802_1x_free_station(struct sta_info *sta); - -void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta); -void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta); -void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd, - struct sta_info *sta, int authorized); -void ieee802_1x_dump_state(FILE *f, const char *prefix, struct sta_info *sta); -int ieee802_1x_init(struct hostapd_data *hapd); -void ieee802_1x_deinit(struct hostapd_data *hapd); -int ieee802_1x_reconfig(struct hostapd_data *hapd, - struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss); -int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta, - u8 *buf, size_t len, int ack); -u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len); -u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len, - int idx); -const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len); -void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm, - int enabled); -void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, - int valid); -void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth); -int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen); -int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, - char *buf, size_t buflen); -void hostapd_get_ntp_timestamp(u8 *buf); -char *eap_type_text(u8 type); - -struct radius_class_data; - -void ieee802_1x_free_radius_class(struct radius_class_data *class); -int ieee802_1x_copy_radius_class(struct radius_class_data *dst, - const struct radius_class_data *src); - -const char *radius_mode_txt(struct hostapd_data *hapd); -int radius_sta_rate(struct hostapd_data *hapd, struct sta_info *sta); - -#endif /* IEEE802_1X_H */ diff --git a/contrib/hostapd/hostapd/logwatch/README b/contrib/hostapd/hostapd/logwatch/README deleted file mode 100644 index 3cba511909..0000000000 --- a/contrib/hostapd/hostapd/logwatch/README +++ /dev/null @@ -1,9 +0,0 @@ -Logwatch is a utility for analyzing system logs and provide a human -readable summary. This directory has a configuration file and a log -analyzer script for parsing hostapd system log entries for logwatch. -These files can be installed by copying them to following locations: - -/etc/log.d/conf/services/hostapd.conf -/etc/log.d/scripts/services/hostapd - -More information about logwatch is available from http://www.logwatch.org/ diff --git a/contrib/hostapd/hostapd/mlme.c b/contrib/hostapd/hostapd/mlme.c deleted file mode 100644 index d883931cf4..0000000000 --- a/contrib/hostapd/hostapd/mlme.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * hostapd / IEEE 802.11 MLME - * Copyright 2003-2006, Jouni Malinen - * Copyright 2003-2004, Instant802 Networks, Inc. - * Copyright 2005-2006, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "hostapd.h" -#include "ieee802_11.h" -#include "wpa.h" -#include "mlme.h" - - -static const char * mlme_auth_alg_str(int alg) -{ - switch (alg) { - case WLAN_AUTH_OPEN: - return "OPEN_SYSTEM"; - case WLAN_AUTH_SHARED_KEY: - return "SHARED_KEY"; - case WLAN_AUTH_FT: - return "FT"; - } - - return "unknown"; -} - - -/** - * mlme_authenticate_indication - Report the establishment of an authentication - * relationship with a specific peer MAC entity - * @hapd: BSS data - * @sta: peer STA data - * - * MLME calls this function as a result of the establishment of an - * authentication relationship with a specific peer MAC entity that - * resulted from an authentication procedure that was initiated by - * that specific peer MAC entity. - * - * PeerSTAAddress = sta->addr - * AuthenticationType = sta->auth_alg (WLAN_AUTH_OPEN / WLAN_AUTH_SHARED_KEY) - */ -void mlme_authenticate_indication(struct hostapd_data *hapd, - struct sta_info *sta) -{ - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, - HOSTAPD_LEVEL_DEBUG, - "MLME-AUTHENTICATE.indication(" MACSTR ", %s)", - MAC2STR(sta->addr), mlme_auth_alg_str(sta->auth_alg)); - if (sta->auth_alg != WLAN_AUTH_FT && !(sta->flags & WLAN_STA_MFP)) - mlme_deletekeys_request(hapd, sta); -} - - -/** - * mlme_deauthenticate_indication - Report the invalidation of an - * authentication relationship with a specific peer MAC entity - * @hapd: BSS data - * @sta: Peer STA data - * @reason_code: ReasonCode from Deauthentication frame - * - * MLME calls this function as a result of the invalidation of an - * authentication relationship with a specific peer MAC entity. - * - * PeerSTAAddress = sta->addr - */ -void mlme_deauthenticate_indication(struct hostapd_data *hapd, - struct sta_info *sta, u16 reason_code) -{ - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, - HOSTAPD_LEVEL_DEBUG, - "MLME-DEAUTHENTICATE.indication(" MACSTR ", %d)", - MAC2STR(sta->addr), reason_code); - mlme_deletekeys_request(hapd, sta); -} - - -/** - * mlme_associate_indication - Report the establishment of an association with - * a specific peer MAC entity - * @hapd: BSS data - * @sta: peer STA data - * - * MLME calls this function as a result of the establishment of an - * association with a specific peer MAC entity that resulted from an - * association procedure that was initiated by that specific peer MAC entity. - * - * PeerSTAAddress = sta->addr - */ -void mlme_associate_indication(struct hostapd_data *hapd, struct sta_info *sta) -{ - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, - HOSTAPD_LEVEL_DEBUG, - "MLME-ASSOCIATE.indication(" MACSTR ")", - MAC2STR(sta->addr)); - if (sta->auth_alg != WLAN_AUTH_FT) - mlme_deletekeys_request(hapd, sta); -} - - -/** - * mlme_reassociate_indication - Report the establishment of an reassociation - * with a specific peer MAC entity - * @hapd: BSS data - * @sta: peer STA data - * - * MLME calls this function as a result of the establishment of an - * reassociation with a specific peer MAC entity that resulted from a - * reassociation procedure that was initiated by that specific peer MAC entity. - * - * PeerSTAAddress = sta->addr - * - * sta->previous_ap contains the "Current AP" information from ReassocReq. - */ -void mlme_reassociate_indication(struct hostapd_data *hapd, - struct sta_info *sta) -{ - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, - HOSTAPD_LEVEL_DEBUG, - "MLME-REASSOCIATE.indication(" MACSTR ")", - MAC2STR(sta->addr)); - if (sta->auth_alg != WLAN_AUTH_FT) - mlme_deletekeys_request(hapd, sta); -} - - -/** - * mlme_disassociate_indication - Report disassociation with a specific peer - * MAC entity - * @hapd: BSS data - * @sta: Peer STA data - * @reason_code: ReasonCode from Disassociation frame - * - * MLME calls this function as a result of the invalidation of an association - * relationship with a specific peer MAC entity. - * - * PeerSTAAddress = sta->addr - */ -void mlme_disassociate_indication(struct hostapd_data *hapd, - struct sta_info *sta, u16 reason_code) -{ - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, - HOSTAPD_LEVEL_DEBUG, - "MLME-DISASSOCIATE.indication(" MACSTR ", %d)", - MAC2STR(sta->addr), reason_code); - mlme_deletekeys_request(hapd, sta); -} - - -void mlme_michaelmicfailure_indication(struct hostapd_data *hapd, - const u8 *addr) -{ - hostapd_logger(hapd, addr, HOSTAPD_MODULE_MLME, - HOSTAPD_LEVEL_DEBUG, - "MLME-MichaelMICFailure.indication(" MACSTR ")", - MAC2STR(addr)); -} - - -void mlme_deletekeys_request(struct hostapd_data *hapd, struct sta_info *sta) -{ - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, - HOSTAPD_LEVEL_DEBUG, - "MLME-DELETEKEYS.request(" MACSTR ")", - MAC2STR(sta->addr)); - - if (sta->wpa_sm) - wpa_remove_ptk(sta->wpa_sm); -} diff --git a/contrib/hostapd/hostapd/mlme.h b/contrib/hostapd/hostapd/mlme.h deleted file mode 100644 index c77a9390a8..0000000000 --- a/contrib/hostapd/hostapd/mlme.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * hostapd / IEEE 802.11 MLME - * Copyright 2003, Jouni Malinen - * Copyright 2003-2004, Instant802 Networks, Inc. - * Copyright 2005-2006, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef MLME_H -#define MLME_H - -void mlme_authenticate_indication(struct hostapd_data *hapd, - struct sta_info *sta); - -void mlme_deauthenticate_indication(struct hostapd_data *hapd, - struct sta_info *sta, u16 reason_code); - -void mlme_associate_indication(struct hostapd_data *hapd, - struct sta_info *sta); - -void mlme_reassociate_indication(struct hostapd_data *hapd, - struct sta_info *sta); - -void mlme_disassociate_indication(struct hostapd_data *hapd, - struct sta_info *sta, u16 reason_code); - -void mlme_michaelmicfailure_indication(struct hostapd_data *hapd, - const u8 *addr); - -void mlme_deletekeys_request(struct hostapd_data *hapd, struct sta_info *sta); - -#endif /* MLME_H */ diff --git a/contrib/hostapd/hostapd/nt_password_hash.c b/contrib/hostapd/hostapd/nt_password_hash.c deleted file mode 100644 index 9df307d54a..0000000000 --- a/contrib/hostapd/hostapd/nt_password_hash.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * hostapd - Plaintext password to NtPasswordHash - * Copyright (c) 2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "ms_funcs.h" - - -int main(int argc, char *argv[]) -{ - unsigned char password_hash[16]; - size_t i; - char *password, buf[64], *pos; - - if (argc > 1) - password = argv[1]; - else { - if (fgets(buf, sizeof(buf), stdin) == NULL) { - printf("Failed to read password\n"); - return 1; - } - buf[sizeof(buf) - 1] = '\0'; - pos = buf; - while (*pos != '\0') { - if (*pos == '\r' || *pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } - password = buf; - } - - nt_password_hash((u8 *) password, strlen(password), password_hash); - for (i = 0; i < sizeof(password_hash); i++) - printf("%02x", password_hash[i]); - printf("\n"); - - return 0; -} diff --git a/contrib/hostapd/hostapd/peerkey.c b/contrib/hostapd/hostapd/peerkey.c deleted file mode 100644 index 83f3ce513d..0000000000 --- a/contrib/hostapd/hostapd/peerkey.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * hostapd - PeerKey for Direct Link Setup (DLS) - * Copyright (c) 2006-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eloop.h" -#include "sha1.h" -#include "sha256.h" -#include "wpa.h" -#include "defs.h" -#include "wpa_auth_i.h" -#include "wpa_auth_ie.h" - -#ifdef CONFIG_PEERKEY - -static void wpa_stsl_step(void *eloop_ctx, void *timeout_ctx) -{ -#if 0 - struct wpa_authenticator *wpa_auth = eloop_ctx; - struct wpa_stsl_negotiation *neg = timeout_ctx; -#endif - - /* TODO: ? */ -} - - -struct wpa_stsl_search { - const u8 *addr; - struct wpa_state_machine *sm; -}; - - -static int wpa_stsl_select_sta(struct wpa_state_machine *sm, void *ctx) -{ - struct wpa_stsl_search *search = ctx; - if (os_memcmp(search->addr, sm->addr, ETH_ALEN) == 0) { - search->sm = sm; - return 1; - } - return 0; -} - - -static void wpa_smk_send_error(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, const u8 *peer, - u16 mui, u16 error_type) -{ - u8 kde[2 + RSN_SELECTOR_LEN + ETH_ALEN + - 2 + RSN_SELECTOR_LEN + sizeof(struct rsn_error_kde)]; - u8 *pos; - struct rsn_error_kde error; - - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, - "Sending SMK Error"); - - pos = kde; - - if (peer) { - pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN, - NULL, 0); - } - - error.mui = host_to_be16(mui); - error.error_type = host_to_be16(error_type); - pos = wpa_add_kde(pos, RSN_KEY_DATA_ERROR, - (u8 *) &error, sizeof(error), NULL, 0); - - __wpa_send_eapol(wpa_auth, sm, - WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_ERROR, - NULL, NULL, kde, pos - kde, 0, 0, 0); -} - - -void wpa_smk_m1(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, struct wpa_eapol_key *key) -{ - struct wpa_eapol_ie_parse kde; - struct wpa_stsl_search search; - u8 *buf, *pos; - size_t buf_len; - - if (wpa_parse_kde_ies((const u8 *) (key + 1), - WPA_GET_BE16(key->key_data_length), &kde) < 0) { - wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M1"); - return; - } - - 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 M1"); - return; - } - - /* Initiator = sm->addr; Peer = kde.mac_addr */ - - search.addr = kde.mac_addr; - search.sm = NULL; - if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) == - 0 || search.sm == NULL) { - wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR - " aborted - STA not associated anymore", - MAC2STR(kde.mac_addr)); - wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK, - STK_ERR_STA_NR); - /* FIX: wpa_stsl_remove(wpa_auth, neg); */ - return; - } - - buf_len = kde.rsn_ie_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN; - buf = os_malloc(buf_len); - if (buf == NULL) - return; - /* Initiator RSN IE */ - os_memcpy(buf, kde.rsn_ie, kde.rsn_ie_len); - pos = buf + kde.rsn_ie_len; - /* Initiator MAC Address */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, sm->addr, ETH_ALEN, - NULL, 0); - - /* SMK M2: - * EAPOL-Key(S=1, M=1, A=1, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce, - * MIC=MIC, DataKDs=(RSNIE_I, MAC_I KDE) - */ - - wpa_auth_logger(wpa_auth, search.sm->addr, LOGGER_DEBUG, - "Sending SMK M2"); - - __wpa_send_eapol(wpa_auth, search.sm, - WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE, - NULL, key->key_nonce, buf, pos - buf, 0, 0, 0); - - os_free(buf); -} - - -static void wpa_send_smk_m4(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, - struct wpa_eapol_key *key, - struct wpa_eapol_ie_parse *kde, - const u8 *smk) -{ - u8 *buf, *pos; - size_t buf_len; - u32 lifetime; - - /* SMK M4: - * EAPOL-Key(S=1, M=1, A=0, I=1, K=0, SM=1, KeyRSC=0, Nonce=PNonce, - * MIC=MIC, DataKDs=(MAC_I KDE, INonce KDE, SMK KDE, - * Lifetime KDE) - */ - - buf_len = 2 + RSN_SELECTOR_LEN + ETH_ALEN + - 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN + - 2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN + - 2 + RSN_SELECTOR_LEN + sizeof(lifetime); - pos = buf = os_malloc(buf_len); - if (buf == NULL) - return; - - /* Initiator MAC Address */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, kde->mac_addr, ETH_ALEN, - NULL, 0); - - /* Initiator Nonce */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, kde->nonce, WPA_NONCE_LEN, - NULL, 0); - - /* SMK with PNonce */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN, - key->key_nonce, WPA_NONCE_LEN); - - /* Lifetime */ - lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME, - (u8 *) &lifetime, sizeof(lifetime), NULL, 0); - - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "Sending SMK M4"); - - __wpa_send_eapol(wpa_auth, sm, - WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_SMK_MESSAGE, - NULL, key->key_nonce, buf, pos - buf, 0, 1, 0); - - os_free(buf); -} - - -static void wpa_send_smk_m5(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, - struct wpa_eapol_key *key, - struct wpa_eapol_ie_parse *kde, - const u8 *smk, const u8 *peer) -{ - u8 *buf, *pos; - size_t buf_len; - u32 lifetime; - - /* SMK M5: - * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce, - * MIC=MIC, DataKDs=(RSNIE_P, MAC_P KDE, PNonce, SMK KDE, - * Lifetime KDE)) - */ - - buf_len = kde->rsn_ie_len + - 2 + RSN_SELECTOR_LEN + ETH_ALEN + - 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN + - 2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN + - 2 + RSN_SELECTOR_LEN + sizeof(lifetime); - pos = buf = os_malloc(buf_len); - if (buf == NULL) - return; - - /* Peer RSN IE */ - os_memcpy(buf, kde->rsn_ie, kde->rsn_ie_len); - pos = buf + kde->rsn_ie_len; - - /* Peer MAC Address */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN, NULL, 0); - - /* PNonce */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, key->key_nonce, - WPA_NONCE_LEN, NULL, 0); - - /* SMK and INonce */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN, - kde->nonce, WPA_NONCE_LEN); - - /* Lifetime */ - lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME, - (u8 *) &lifetime, sizeof(lifetime), NULL, 0); - - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "Sending SMK M5"); - - __wpa_send_eapol(wpa_auth, sm, - WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_SMK_MESSAGE, - NULL, kde->nonce, buf, pos - buf, 0, 1, 0); - - os_free(buf); -} - - -void wpa_smk_m3(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, struct wpa_eapol_key *key) -{ - struct wpa_eapol_ie_parse kde; - struct wpa_stsl_search search; - u8 smk[32], buf[ETH_ALEN + 8 + 2 * WPA_NONCE_LEN], *pos; - - if (wpa_parse_kde_ies((const u8 *) (key + 1), - WPA_GET_BE16(key->key_data_length), &kde) < 0) { - wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M3"); - return; - } - - if (kde.rsn_ie == NULL || - kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN || - kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN) { - wpa_printf(MSG_INFO, "RSN: No RSN IE, MAC address KDE, or " - "Nonce KDE in SMK M3"); - return; - } - - /* Peer = sm->addr; Initiator = kde.mac_addr; - * Peer Nonce = key->key_nonce; Initiator Nonce = kde.nonce */ - - search.addr = kde.mac_addr; - search.sm = NULL; - if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) == - 0 || search.sm == NULL) { - wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR - " aborted - STA not associated anymore", - MAC2STR(kde.mac_addr)); - wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK, - STK_ERR_STA_NR); - /* FIX: wpa_stsl_remove(wpa_auth, neg); */ - return; - } - - if (os_get_random(smk, PMK_LEN)) { - wpa_printf(MSG_DEBUG, "RSN: Failed to generate SMK"); - return; - } - - /* SMK = PRF-256(Random number, "SMK Derivation", - * AA || Time || INonce || PNonce) - */ - os_memcpy(buf, wpa_auth->addr, ETH_ALEN); - pos = buf + ETH_ALEN; - wpa_get_ntp_timestamp(pos); - pos += 8; - os_memcpy(pos, kde.nonce, WPA_NONCE_LEN); - pos += WPA_NONCE_LEN; - os_memcpy(pos, key->key_nonce, WPA_NONCE_LEN); -#ifdef CONFIG_IEEE80211W - sha256_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf), - smk, PMK_LEN); -#else /* CONFIG_IEEE80211W */ - sha1_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf), - smk, PMK_LEN); -#endif /* CONFIG_IEEE80211W */ - - wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", smk, PMK_LEN); - - wpa_send_smk_m4(wpa_auth, sm, key, &kde, smk); - wpa_send_smk_m5(wpa_auth, search.sm, key, &kde, smk, sm->addr); - - /* Authenticator does not need SMK anymore and it is required to forget - * it. */ - os_memset(smk, 0, sizeof(*smk)); -} - - -void wpa_smk_error(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, struct wpa_eapol_key *key) -{ - struct wpa_eapol_ie_parse kde; - struct wpa_stsl_search search; - struct rsn_error_kde error; - u16 mui, error_type; - - if (wpa_parse_kde_ies((const u8 *) (key + 1), - WPA_GET_BE16(key->key_data_length), &kde) < 0) { - wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error"); - return; - } - - if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN || - kde.error == NULL || kde.error_len < sizeof(error)) { - wpa_printf(MSG_INFO, "RSN: No MAC address or Error KDE in " - "SMK Error"); - return; - } - - search.addr = kde.mac_addr; - search.sm = NULL; - if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) == - 0 || search.sm == NULL) { - wpa_printf(MSG_DEBUG, "RSN: Peer STA " MACSTR " not " - "associated for SMK Error message from " MACSTR, - MAC2STR(kde.mac_addr), MAC2STR(sm->addr)); - return; - } - - os_memcpy(&error, kde.error, sizeof(error)); - mui = be_to_host16(error.mui); - error_type = be_to_host16(error.error_type); - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "STA reported SMK Error: Peer " MACSTR - " MUI %d Error Type %d", - MAC2STR(kde.mac_addr), mui, error_type); - - wpa_smk_send_error(wpa_auth, search.sm, sm->addr, mui, error_type); -} - - -int wpa_stsl_remove(struct wpa_authenticator *wpa_auth, - struct wpa_stsl_negotiation *neg) -{ - struct wpa_stsl_negotiation *pos, *prev; - - if (wpa_auth == NULL) - return -1; - pos = wpa_auth->stsl_negotiations; - prev = NULL; - while (pos) { - if (pos == neg) { - if (prev) - prev->next = pos->next; - else - wpa_auth->stsl_negotiations = pos->next; - - eloop_cancel_timeout(wpa_stsl_step, wpa_auth, pos); - os_free(pos); - return 0; - } - prev = pos; - pos = pos->next; - } - - return -1; -} - -#endif /* CONFIG_PEERKEY */ diff --git a/contrib/hostapd/hostapd/pmksa_cache.c b/contrib/hostapd/hostapd/pmksa_cache.c deleted file mode 100644 index 5f54a34c11..0000000000 --- a/contrib/hostapd/hostapd/pmksa_cache.c +++ /dev/null @@ -1,455 +0,0 @@ -/* - * hostapd - PMKSA cache for IEEE 802.11i RSN - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "ap.h" -#include "config.h" -#include "common.h" -#include "eloop.h" -#include "sha1.h" -#include "sha256.h" -#include "ieee802_1x.h" -#include "eapol_sm.h" -#include "pmksa_cache.h" - - -static const int pmksa_cache_max_entries = 1024; -static const int dot11RSNAConfigPMKLifetime = 43200; - -struct rsn_pmksa_cache { -#define PMKID_HASH_SIZE 128 -#define PMKID_HASH(pmkid) (unsigned int) ((pmkid)[0] & 0x7f) - struct rsn_pmksa_cache_entry *pmkid[PMKID_HASH_SIZE]; - struct rsn_pmksa_cache_entry *pmksa; - int pmksa_count; - - void (*free_cb)(struct rsn_pmksa_cache_entry *entry, void *ctx); - void *ctx; -}; - - -/** - * rsn_pmkid - Calculate PMK identifier - * @pmk: Pairwise master key - * @pmk_len: Length of pmk in bytes - * @aa: Authenticator address - * @spa: Supplicant address - * @pmkid: Buffer for PMKID - * @use_sha256: Whether to use SHA256-based KDF - * - * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy - * PMKID = HMAC-SHA1-128(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) -{ - char *title = "PMK Name"; - const u8 *addr[3]; - const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; - unsigned char hash[SHA256_MAC_LEN]; - - addr[0] = (u8 *) title; - addr[1] = aa; - addr[2] = spa; - -#ifdef CONFIG_IEEE80211W - if (use_sha256) - hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash); - else -#endif /* CONFIG_IEEE80211W */ - hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash); - os_memcpy(pmkid, hash, PMKID_LEN); -} - - -static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa); - - -static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry) -{ - if (entry == NULL) - return; - os_free(entry->identity); - ieee802_1x_free_radius_class(&entry->radius_class); - os_free(entry); -} - - -static void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa, - struct rsn_pmksa_cache_entry *entry) -{ - struct rsn_pmksa_cache_entry *pos, *prev; - - pmksa->pmksa_count--; - pmksa->free_cb(entry, pmksa->ctx); - pos = pmksa->pmkid[PMKID_HASH(entry->pmkid)]; - prev = NULL; - while (pos) { - if (pos == entry) { - if (prev != NULL) { - prev->hnext = pos->hnext; - } else { - pmksa->pmkid[PMKID_HASH(entry->pmkid)] = - pos->hnext; - } - break; - } - prev = pos; - pos = pos->hnext; - } - - pos = pmksa->pmksa; - prev = NULL; - while (pos) { - if (pos == entry) { - if (prev != NULL) - prev->next = pos->next; - else - pmksa->pmksa = pos->next; - break; - } - prev = pos; - pos = pos->next; - } - _pmksa_cache_free_entry(entry); -} - - -static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx) -{ - struct rsn_pmksa_cache *pmksa = eloop_ctx; - struct os_time now; - - os_get_time(&now); - while (pmksa->pmksa && pmksa->pmksa->expiration <= now.sec) { - struct rsn_pmksa_cache_entry *entry = pmksa->pmksa; - pmksa->pmksa = entry->next; - wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for " - MACSTR, MAC2STR(entry->spa)); - pmksa_cache_free_entry(pmksa, entry); - } - - pmksa_cache_set_expiration(pmksa); -} - - -static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa) -{ - int sec; - struct os_time now; - - eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL); - if (pmksa->pmksa == NULL) - return; - os_get_time(&now); - sec = pmksa->pmksa->expiration - now.sec; - if (sec < 0) - sec = 0; - eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, pmksa, NULL); -} - - -static void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry, - struct eapol_state_machine *eapol) -{ - if (eapol == NULL) - return; - - if (eapol->identity) { - entry->identity = os_malloc(eapol->identity_len); - if (entry->identity) { - entry->identity_len = eapol->identity_len; - os_memcpy(entry->identity, eapol->identity, - eapol->identity_len); - } - } - - ieee802_1x_copy_radius_class(&entry->radius_class, - &eapol->radius_class); - - entry->eap_type_authsrv = eapol->eap_type_authsrv; - entry->vlan_id = eapol->sta->vlan_id; -} - - -void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry, - struct eapol_state_machine *eapol) -{ - if (entry == NULL || eapol == NULL) - return; - - if (entry->identity) { - os_free(eapol->identity); - eapol->identity = os_malloc(entry->identity_len); - if (eapol->identity) { - eapol->identity_len = entry->identity_len; - os_memcpy(eapol->identity, entry->identity, - entry->identity_len); - } - wpa_hexdump_ascii(MSG_DEBUG, "STA identity from PMKSA", - eapol->identity, eapol->identity_len); - } - - ieee802_1x_free_radius_class(&eapol->radius_class); - ieee802_1x_copy_radius_class(&eapol->radius_class, - &entry->radius_class); - if (eapol->radius_class.attr) { - wpa_printf(MSG_DEBUG, "Copied %lu Class attribute(s) from " - "PMKSA", (unsigned long) eapol->radius_class.count); - } - - eapol->eap_type_authsrv = entry->eap_type_authsrv; - eapol->sta->vlan_id = entry->vlan_id; -} - - -static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa, - struct rsn_pmksa_cache_entry *entry) -{ - struct rsn_pmksa_cache_entry *pos, *prev; - - /* Add the new entry; order by expiration time */ - pos = pmksa->pmksa; - prev = NULL; - while (pos) { - if (pos->expiration > entry->expiration) - break; - prev = pos; - pos = pos->next; - } - if (prev == NULL) { - entry->next = pmksa->pmksa; - pmksa->pmksa = entry; - } else { - entry->next = prev->next; - prev->next = entry; - } - entry->hnext = pmksa->pmkid[PMKID_HASH(entry->pmkid)]; - pmksa->pmkid[PMKID_HASH(entry->pmkid)] = entry; - - pmksa->pmksa_count++; - wpa_printf(MSG_DEBUG, "RSN: added PMKSA cache entry for " MACSTR, - MAC2STR(entry->spa)); - wpa_hexdump(MSG_DEBUG, "RSN: added PMKID", entry->pmkid, PMKID_LEN); -} - - -/** - * pmksa_cache_add - Add a PMKSA cache entry - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() - * @pmk: The new pairwise master key - * @pmk_len: PMK length in bytes, usually PMK_LEN (32) - * @aa: Authenticator address - * @spa: Supplicant address - * @session_timeout: Session timeout - * @eapol: Pointer to EAPOL state machine data - * @akmp: WPA_KEY_MGMT_* used in key derivation - * 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 - * cache. If an old entry is already in the cache for the same Supplicant, - * this entry will be replaced with the new entry. PMKID will be calculated - * based on the PMK. - */ -struct rsn_pmksa_cache_entry * -pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, - const u8 *aa, const u8 *spa, int session_timeout, - struct eapol_state_machine *eapol, int akmp) -{ - struct rsn_pmksa_cache_entry *entry, *pos; - struct os_time now; - - if (pmk_len > PMK_LEN) - return NULL; - - entry = os_zalloc(sizeof(*entry)); - if (entry == NULL) - return NULL; - os_memcpy(entry->pmk, pmk, pmk_len); - entry->pmk_len = pmk_len; - rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, - wpa_key_mgmt_sha256(akmp)); - os_get_time(&now); - entry->expiration = now.sec; - if (session_timeout > 0) - entry->expiration += session_timeout; - else - entry->expiration += dot11RSNAConfigPMKLifetime; - entry->akmp = akmp; - os_memcpy(entry->spa, spa, ETH_ALEN); - pmksa_cache_from_eapol_data(entry, eapol); - - /* Replace an old entry for the same STA (if found) with the new entry - */ - pos = pmksa_cache_get(pmksa, spa, NULL); - if (pos) - pmksa_cache_free_entry(pmksa, pos); - - if (pmksa->pmksa_count >= pmksa_cache_max_entries && pmksa->pmksa) { - /* Remove the oldest entry to make room for the new entry */ - wpa_printf(MSG_DEBUG, "RSN: removed the oldest PMKSA cache " - "entry (for " MACSTR ") to make room for new one", - MAC2STR(pmksa->pmksa->spa)); - pmksa_cache_free_entry(pmksa, pmksa->pmksa); - } - - pmksa_cache_link_entry(pmksa, entry); - - return 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) -{ - struct rsn_pmksa_cache_entry *entry; - - entry = os_zalloc(sizeof(*entry)); - if (entry == NULL) - return NULL; - os_memcpy(entry->pmkid, pmkid, PMKID_LEN); - os_memcpy(entry->pmk, old_entry->pmk, old_entry->pmk_len); - entry->pmk_len = old_entry->pmk_len; - entry->expiration = old_entry->expiration; - entry->akmp = old_entry->akmp; - os_memcpy(entry->spa, old_entry->spa, ETH_ALEN); - entry->opportunistic = 1; - if (old_entry->identity) { - entry->identity = os_malloc(old_entry->identity_len); - if (entry->identity) { - entry->identity_len = old_entry->identity_len; - os_memcpy(entry->identity, old_entry->identity, - old_entry->identity_len); - } - } - ieee802_1x_copy_radius_class(&entry->radius_class, - &old_entry->radius_class); - entry->eap_type_authsrv = old_entry->eap_type_authsrv; - entry->vlan_id = old_entry->vlan_id; - entry->opportunistic = 1; - - pmksa_cache_link_entry(pmksa, entry); - - return entry; -} - - -/** - * pmksa_cache_deinit - Free all entries in PMKSA cache - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() - */ -void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa) -{ - struct rsn_pmksa_cache_entry *entry, *prev; - int i; - - if (pmksa == NULL) - return; - - entry = pmksa->pmksa; - while (entry) { - prev = entry; - entry = entry->next; - _pmksa_cache_free_entry(prev); - } - eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL); - for (i = 0; i < PMKID_HASH_SIZE; i++) - pmksa->pmkid[i] = NULL; - os_free(pmksa); -} - - -/** - * pmksa_cache_get - Fetch a PMKSA cache entry - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() - * @spa: Supplicant address or %NULL to match any - * @pmkid: PMKID or %NULL to match 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 *spa, const u8 *pmkid) -{ - struct rsn_pmksa_cache_entry *entry; - - if (pmkid) - entry = pmksa->pmkid[PMKID_HASH(pmkid)]; - else - entry = pmksa->pmksa; - while (entry) { - if ((spa == NULL || - os_memcmp(entry->spa, spa, ETH_ALEN) == 0) && - (pmkid == NULL || - os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0)) - return entry; - entry = pmkid ? entry->hnext : entry->next; - } - return NULL; -} - - -/** - * pmksa_cache_get_okc - Fetch a PMKSA cache entry using OKC - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() - * @aa: Authenticator address - * @spa: Supplicant address - * @pmkid: PMKID - * Returns: Pointer to PMKSA cache entry or %NULL if no match was found - * - * Use opportunistic key caching (OKC) to find a PMK for a supplicant. - */ -struct rsn_pmksa_cache_entry * pmksa_cache_get_okc( - struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *spa, - const u8 *pmkid) -{ - struct rsn_pmksa_cache_entry *entry; - u8 new_pmkid[PMKID_LEN]; - - entry = pmksa->pmksa; - while (entry) { - if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0) - continue; - rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid, - wpa_key_mgmt_sha256(entry->akmp)); - if (os_memcmp(new_pmkid, pmkid, PMKID_LEN) == 0) - return entry; - entry = entry->next; - } - return NULL; -} - - -/** - * pmksa_cache_init - Initialize PMKSA cache - * @free_cb: Callback function to be called when a PMKSA cache entry is freed - * @ctx: Context pointer for free_cb function - * Returns: Pointer to PMKSA cache data or %NULL on failure - */ -struct rsn_pmksa_cache * -pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, - void *ctx), void *ctx) -{ - struct rsn_pmksa_cache *pmksa; - - pmksa = os_zalloc(sizeof(*pmksa)); - if (pmksa) { - pmksa->free_cb = free_cb; - pmksa->ctx = ctx; - } - - return pmksa; -} diff --git a/contrib/hostapd/hostapd/pmksa_cache.h b/contrib/hostapd/hostapd/pmksa_cache.h deleted file mode 100644 index 6ba2da6073..0000000000 --- a/contrib/hostapd/hostapd/pmksa_cache.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * hostapd - PMKSA cache for IEEE 802.11i RSN - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef PMKSA_CACHE_H -#define PMKSA_CACHE_H - -/** - * struct rsn_pmksa_cache_entry - PMKSA cache entry - */ -struct rsn_pmksa_cache_entry { - struct rsn_pmksa_cache_entry *next, *hnext; - u8 pmkid[PMKID_LEN]; - u8 pmk[PMK_LEN]; - size_t pmk_len; - os_time_t expiration; - int akmp; /* WPA_KEY_MGMT_* */ - u8 spa[ETH_ALEN]; - - u8 *identity; - size_t identity_len; - struct radius_class_data radius_class; - u8 eap_type_authsrv; - int vlan_id; - int opportunistic; -}; - -struct rsn_pmksa_cache; - -struct rsn_pmksa_cache * -pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, - void *ctx), void *ctx); -void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa); -struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa, - const u8 *spa, const u8 *pmkid); -struct rsn_pmksa_cache_entry * pmksa_cache_get_okc( - struct rsn_pmksa_cache *pmksa, const u8 *spa, const u8 *aa, - const u8 *pmkid); -struct rsn_pmksa_cache_entry * -pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, - const u8 *aa, const u8 *spa, int session_timeout, - struct eapol_state_machine *eapol, int akmp); -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); -void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry, - struct eapol_state_machine *eapol); -void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, - u8 *pmkid, int use_sha256); - -#endif /* PMKSA_CACHE_H */ diff --git a/contrib/hostapd/hostapd/preauth.c b/contrib/hostapd/hostapd/preauth.c deleted file mode 100644 index 9ab41eda0b..0000000000 --- a/contrib/hostapd/hostapd/preauth.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * hostapd - Authenticator for IEEE 802.11i RSN pre-authentication - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#ifdef CONFIG_RSN_PREAUTH - -#include "hostapd.h" -#include "l2_packet/l2_packet.h" -#include "ieee802_1x.h" -#include "eloop.h" -#include "sta_info.h" -#include "wpa_common.h" -#include "eapol_sm.h" -#include "wpa.h" -#include "preauth.h" - -#ifndef ETH_P_PREAUTH -#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */ -#endif /* ETH_P_PREAUTH */ - -static const int dot11RSNAConfigPMKLifetime = 43200; - -struct rsn_preauth_interface { - struct rsn_preauth_interface *next; - struct hostapd_data *hapd; - struct l2_packet_data *l2; - char *ifname; - int ifindex; -}; - - -static void rsn_preauth_receive(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len) -{ - struct rsn_preauth_interface *piface = ctx; - struct hostapd_data *hapd = piface->hapd; - struct ieee802_1x_hdr *hdr; - struct sta_info *sta; - struct l2_ethhdr *ethhdr; - - wpa_printf(MSG_DEBUG, "RSN: receive pre-auth packet " - "from interface '%s'", piface->ifname); - if (len < sizeof(*ethhdr) + sizeof(*hdr)) { - wpa_printf(MSG_DEBUG, "RSN: too short pre-auth packet " - "(len=%lu)", (unsigned long) len); - return; - } - - ethhdr = (struct l2_ethhdr *) buf; - hdr = (struct ieee802_1x_hdr *) (ethhdr + 1); - - if (os_memcmp(ethhdr->h_dest, hapd->own_addr, ETH_ALEN) != 0) { - wpa_printf(MSG_DEBUG, "RSN: pre-auth for foreign address " - MACSTR, MAC2STR(ethhdr->h_dest)); - return; - } - - sta = ap_get_sta(hapd, ethhdr->h_source); - if (sta && (sta->flags & WLAN_STA_ASSOC)) { - wpa_printf(MSG_DEBUG, "RSN: pre-auth for already association " - "STA " MACSTR, MAC2STR(sta->addr)); - return; - } - if (!sta && hdr->type == IEEE802_1X_TYPE_EAPOL_START) { - sta = ap_sta_add(hapd, ethhdr->h_source); - if (sta == NULL) - return; - sta->flags = WLAN_STA_PREAUTH; - - ieee802_1x_new_station(hapd, sta); - if (sta->eapol_sm == NULL) { - ap_free_sta(hapd, sta); - sta = NULL; - } else { - sta->eapol_sm->radius_identifier = -1; - sta->eapol_sm->portValid = TRUE; - sta->eapol_sm->flags |= EAPOL_SM_PREAUTH; - } - } - if (sta == NULL) - return; - sta->preauth_iface = piface; - ieee802_1x_receive(hapd, ethhdr->h_source, (u8 *) (ethhdr + 1), - len - sizeof(*ethhdr)); -} - - -static int rsn_preauth_iface_add(struct hostapd_data *hapd, const char *ifname) -{ - struct rsn_preauth_interface *piface; - - wpa_printf(MSG_DEBUG, "RSN pre-auth interface '%s'", ifname); - - piface = os_zalloc(sizeof(*piface)); - if (piface == NULL) - return -1; - piface->hapd = hapd; - - piface->ifname = os_strdup(ifname); - if (piface->ifname == NULL) { - goto fail1; - } - - piface->l2 = l2_packet_init(piface->ifname, NULL, ETH_P_PREAUTH, - rsn_preauth_receive, piface, 1); - if (piface->l2 == NULL) { - wpa_printf(MSG_ERROR, "Failed to open register layer 2 access " - "to ETH_P_PREAUTH"); - goto fail2; - } - - piface->next = hapd->preauth_iface; - hapd->preauth_iface = piface; - return 0; - -fail2: - os_free(piface->ifname); -fail1: - os_free(piface); - return -1; -} - - -void rsn_preauth_iface_deinit(struct hostapd_data *hapd) -{ - struct rsn_preauth_interface *piface, *prev; - - piface = hapd->preauth_iface; - hapd->preauth_iface = NULL; - while (piface) { - prev = piface; - piface = piface->next; - l2_packet_deinit(prev->l2); - os_free(prev->ifname); - os_free(prev); - } -} - - -int rsn_preauth_iface_init(struct hostapd_data *hapd) -{ - char *tmp, *start, *end; - - if (hapd->conf->rsn_preauth_interfaces == NULL) - return 0; - - tmp = os_strdup(hapd->conf->rsn_preauth_interfaces); - if (tmp == NULL) - return -1; - start = tmp; - for (;;) { - while (*start == ' ') - start++; - if (*start == '\0') - break; - end = os_strchr(start, ' '); - if (end) - *end = '\0'; - - if (rsn_preauth_iface_add(hapd, start)) { - rsn_preauth_iface_deinit(hapd); - os_free(tmp); - return -1; - } - - if (end) - start = end + 1; - else - break; - } - os_free(tmp); - return 0; -} - - -static void rsn_preauth_finished_cb(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - struct sta_info *sta = timeout_ctx; - wpa_printf(MSG_DEBUG, "RSN: Removing pre-authentication STA entry for " - MACSTR, MAC2STR(sta->addr)); - ap_free_sta(hapd, sta); -} - - -void rsn_preauth_finished(struct hostapd_data *hapd, struct sta_info *sta, - int success) -{ - const u8 *key; - size_t len; - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, - HOSTAPD_LEVEL_INFO, "pre-authentication %s", - success ? "succeeded" : "failed"); - - key = ieee802_1x_get_key(sta->eapol_sm, &len); - if (len > PMK_LEN) - len = PMK_LEN; - if (success && key) { - if (wpa_auth_pmksa_add_preauth(hapd->wpa_auth, key, len, - sta->addr, - dot11RSNAConfigPMKLifetime, - sta->eapol_sm) == 0) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, - HOSTAPD_LEVEL_DEBUG, - "added PMKSA cache entry (pre-auth)"); - } else { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, - HOSTAPD_LEVEL_DEBUG, - "failed to add PMKSA cache entry " - "(pre-auth)"); - } - } - - /* - * Finish STA entry removal from timeout in order to avoid freeing - * STA data before the caller has finished processing. - */ - eloop_register_timeout(0, 0, rsn_preauth_finished_cb, hapd, sta); -} - - -void rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta, - u8 *buf, size_t len) -{ - struct rsn_preauth_interface *piface; - struct l2_ethhdr *ethhdr; - - piface = hapd->preauth_iface; - while (piface) { - if (piface == sta->preauth_iface) - break; - piface = piface->next; - } - - if (piface == NULL) { - wpa_printf(MSG_DEBUG, "RSN: Could not find pre-authentication " - "interface for " MACSTR, MAC2STR(sta->addr)); - return; - } - - ethhdr = os_malloc(sizeof(*ethhdr) + len); - if (ethhdr == NULL) - return; - - os_memcpy(ethhdr->h_dest, sta->addr, ETH_ALEN); - os_memcpy(ethhdr->h_source, hapd->own_addr, ETH_ALEN); - ethhdr->h_proto = htons(ETH_P_PREAUTH); - os_memcpy(ethhdr + 1, buf, len); - - if (l2_packet_send(piface->l2, sta->addr, ETH_P_PREAUTH, (u8 *) ethhdr, - sizeof(*ethhdr) + len) < 0) { - wpa_printf(MSG_ERROR, "Failed to send preauth packet using " - "l2_packet_send\n"); - } - os_free(ethhdr); -} - - -void rsn_preauth_free_station(struct hostapd_data *hapd, struct sta_info *sta) -{ - eloop_cancel_timeout(rsn_preauth_finished_cb, hapd, sta); -} - -#endif /* CONFIG_RSN_PREAUTH */ diff --git a/contrib/hostapd/hostapd/preauth.h b/contrib/hostapd/hostapd/preauth.h deleted file mode 100644 index 5348bee9bf..0000000000 --- a/contrib/hostapd/hostapd/preauth.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * hostapd - Authenticator for IEEE 802.11i RSN pre-authentication - * Copyright (c) 2004-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef PREAUTH_H -#define PREAUTH_H - -#ifdef CONFIG_RSN_PREAUTH - -int rsn_preauth_iface_init(struct hostapd_data *hapd); -void rsn_preauth_iface_deinit(struct hostapd_data *hapd); -void rsn_preauth_finished(struct hostapd_data *hapd, struct sta_info *sta, - int success); -void rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta, - u8 *buf, size_t len); -void rsn_preauth_free_station(struct hostapd_data *hapd, struct sta_info *sta); - -#else /* CONFIG_RSN_PREAUTH */ - -static inline int rsn_preauth_iface_init(struct hostapd_data *hapd) -{ - return 0; -} - -static inline void rsn_preauth_iface_deinit(struct hostapd_data *hapd) -{ -} - -static inline void rsn_preauth_finished(struct hostapd_data *hapd, - struct sta_info *sta, - int success) -{ -} - -static inline void rsn_preauth_send(struct hostapd_data *hapd, - struct sta_info *sta, - u8 *buf, size_t len) -{ -} - -static inline void rsn_preauth_free_station(struct hostapd_data *hapd, - struct sta_info *sta) -{ -} - -#endif /* CONFIG_RSN_PREAUTH */ - -#endif /* PREAUTH_H */ diff --git a/contrib/hostapd/hostapd/prism54.h b/contrib/hostapd/hostapd/prism54.h deleted file mode 100644 index cb0a9a19ba..0000000000 --- a/contrib/hostapd/hostapd/prism54.h +++ /dev/null @@ -1,177 +0,0 @@ -#ifndef PRISM54_H -#define PRISM54_H - -struct ieee802_3_hdr_s { - unsigned char da[6]; - unsigned char sa[6]; - unsigned short type; -} __attribute__ ((packed)); - -typedef struct ieee802_3_hdr_s ieee802_3_hdr; - -#define PIMOP_GET 0 -#define PIMOP_SET 1 -#define PIMOP_RESPONSE 2 -#define PIMOP_ERROR 3 -#define PIMOP_TRAP 4 - -struct pimdev_hdr_s { - int op; - unsigned long oid; -} __attribute__ ((packed)); - -typedef struct pimdev_hdr_s pimdev_hdr; - -#define DOT11_OID_ATTACHMENT 0x19000003 - -/* really need to check */ -#define DOT11_PKT_BEACON 0x80 -#define DOT11_PKT_ASSOC_RESP 0x10 -#define DOT11_PKT_REASSOC_RESP 0x30 -#define DOT11_PKT_PROBE_RESP 0x50 - -struct obj_attachment_hdr { - char type; - char reserved; - short id; - short size; -} __attribute__ ((packed)); - -struct obj_attachment { - char type; - char reserved; - short id; - short size; - char data[1]; -} __attribute__ ((packed)); - -#define DOT11_OID_MLMEAUTOLEVEL 0x19000001 -#define DOT11_MLME_AUTO 0 -#define DOT11_MLME_INTERMEDIATE 0x01000000 -#define DOT11_MLME_EXTENDED 0x02000000 - -#define DOT11_OID_DEAUTHENTICATE 0x18000000 -#define DOT11_OID_AUTHENTICATE 0x18000001 -#define DOT11_OID_DISASSOCIATE 0x18000002 -#define DOT11_OID_ASSOCIATE 0x18000003 -#define DOT11_OID_BEACON 0x18000005 -#define DOT11_OID_PROBE 0x18000006 -#define DOT11_OID_REASSOCIATE 0x1800000b - -struct obj_mlme { - char address[6]; - short id; - short state; - short code; -} __attribute__ ((packed)); - -#define DOT11_OID_DEAUTHENTICATEEX 0x18000007 -#define DOT11_OID_AUTHENTICATEEX 0x18000008 -#define DOT11_OID_DISASSOCIATEEX 0x18000009 -#define DOT11_OID_ASSOCIATEEX 0x1800000a -#define DOT11_OID_REASSOCIATEEX 0x1800000c - -struct obj_mlmeex { - char address[6]; - short id; - short state; - short code; - short size; - char data[1]; -} __attribute__ ((packed)); - -#define DOT11_OID_STAKEY 0x12000008 - -#define DOT11_PRIV_WEP 0 -#define DOT11_PRIV_TKIP 1 - -/* endian reversed to bigger endian */ -#define DOT11_STAKEY_OPTION_DEFAULTKEY 0x100 - -struct obj_stakey { - char address[6]; - char keyid; - char reserved; - short options; - char type; - char length; - char key[32]; -} __attribute__ ((packed)); - -#define DOT11_OID_DEFKEYID 0x12000003 -#define DOT11_OID_DEFKEY1 0x12000004 -#define DOT11_OID_DEFKEY2 0x12000005 -#define DOT11_OID_DEFKEY3 0x12000006 -#define DOT11_OID_DEFKEY4 0x12000007 - -struct obj_key { - char type; - char length; - char key[32]; -} __attribute__ ((packed)); - -#define DOT11_OID_STASC 0x1200000a - -struct obj_stasc { - char address[6]; - char keyid; - char tx_sc; - unsigned long sc_high; - unsigned short sc_low; -} __attribute__ ((packed)); - -#define DOT11_OID_CLIENTS 0x15000001 -#define DOT11_OID_CLIENTSASSOCIATED 0x15000002 -#define DOT11_OID_CLIENTST 0x15000003 -#define DOT11_OID_CLIENTEND 0x150007d9 -#define DOT11_OID_CLIENTFIND 0x150007db - -#define DOT11_NODE_UNKNOWN -#define DOT11_NODE_CLIENT -#define DOT11_NODE_AP - -/* endian reversed to bigger endian */ -#define DOT11_STATE_NONE 0 -#define DOT11_STATE_AUTHING 0x100 -#define DOT11_STATE_AUTH 0x200 -#define DOT11_STATE_ASSOCING 0x300 -#define DOT11_STATE_REASSOCING 0x400 -#define DOT11_STATE_ASSOC 0x500 -#define DOT11_STATE_WDS 0x600 - -struct obj_sta { - char address[6]; - char pad[2]; - char state; - char node; - short age; - char reserved1; - char rssi; - char rate; - char reserved2; -} __attribute__ ((packed)); - -#define DOT11_OID_SSID 0x10000002 -#define DOT11_OID_SSIDOVERRIDE 0x10000006 - -struct obj_ssid { - char length; - char octets[33]; -} __attribute__ ((packed)); - -#define DOT11_OID_EAPAUTHSTA 0x150007de -#define DOT11_OID_EAPUNAUTHSTA 0x150007df -/* not in 38801 datasheet??? */ -#define DOT11_OID_DOT1XENABLE 0x150007e0 -#define DOT11_OID_MICFAILURE 0x150007e1 -#define DOT11_OID_AUTHENABLE 0x12000000 -#define DOT11_OID_PRIVACYINVOKED 0x12000001 -#define DOT11_OID_EXUNENCRYPTED 0x12000002 - -#define DOT11_AUTH_OS 0x01000000 -#define DOT11_AUTH_SK 0x02000000 -#define DOT11_AUTH_BOTH 0x03000000 - -#define DOT11_BOOL_TRUE 0x01000000 - -#endif /* PRISM54_H */ diff --git a/contrib/hostapd/hostapd/priv_netlink.h b/contrib/hostapd/hostapd/priv_netlink.h deleted file mode 100644 index d1f6f663eb..0000000000 --- a/contrib/hostapd/hostapd/priv_netlink.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef PRIV_NETLINK_H -#define PRIV_NETLINK_H - -/* Private copy of needed Linux netlink/rtnetlink definitions. - * - * This should be replaced with user space header once one is available with C - * library, etc.. - */ - -#ifndef IFLA_IFNAME -#define IFLA_IFNAME 3 -#endif -#ifndef IFLA_WIRELESS -#define IFLA_WIRELESS 11 -#endif - -#define NETLINK_ROUTE 0 -#define RTMGRP_LINK 1 -#define RTM_BASE 0x10 -#define RTM_NEWLINK (RTM_BASE + 0) -#define RTM_DELLINK (RTM_BASE + 1) - -#define NLMSG_ALIGNTO 4 -#define NLMSG_ALIGN(len) (((len) + NLMSG_ALIGNTO - 1) & ~(NLMSG_ALIGNTO - 1)) -#define NLMSG_LENGTH(len) ((len) + NLMSG_ALIGN(sizeof(struct nlmsghdr))) -#define NLMSG_DATA(nlh) ((void*) (((char*) nlh) + NLMSG_LENGTH(0))) - -#define RTA_ALIGNTO 4 -#define RTA_ALIGN(len) (((len) + RTA_ALIGNTO - 1) & ~(RTA_ALIGNTO - 1)) -#define RTA_OK(rta,len) \ -((len) > 0 && (rta)->rta_len >= sizeof(struct rtattr) && \ -(rta)->rta_len <= (len)) -#define RTA_NEXT(rta,attrlen) \ -((attrlen) -= RTA_ALIGN((rta)->rta_len), \ -(struct rtattr *) (((char *)(rta)) + RTA_ALIGN((rta)->rta_len))) - - -struct sockaddr_nl -{ - sa_family_t nl_family; - unsigned short nl_pad; - u32 nl_pid; - u32 nl_groups; -}; - -struct nlmsghdr -{ - u32 nlmsg_len; - u16 nlmsg_type; - u16 nlmsg_flags; - u32 nlmsg_seq; - u32 nlmsg_pid; -}; - -struct ifinfomsg -{ - unsigned char ifi_family; - unsigned char __ifi_pad; - unsigned short ifi_type; - int ifi_index; - unsigned ifi_flags; - unsigned ifi_change; -}; - -struct rtattr -{ - unsigned short rta_len; - unsigned short rta_type; -}; - -#endif /* PRIV_NETLINK_H */ diff --git a/contrib/hostapd/hostapd/radiotap.c b/contrib/hostapd/hostapd/radiotap.c deleted file mode 100644 index 804473fa4b..0000000000 --- a/contrib/hostapd/hostapd/radiotap.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Radiotap parser - * - * Copyright 2007 Andy Green - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * - * Modified for userspace by Johannes Berg - * I only modified some things on top to ease syncing should bugs be found. - */ - -#include "includes.h" - -#include "common.h" -#include "radiotap_iter.h" - -#define le16_to_cpu le_to_host16 -#define le32_to_cpu le_to_host32 -#define __le32 uint32_t -#define ulong unsigned long -#define unlikely(cond) (cond) -#define get_unaligned(p) \ -({ \ - struct packed_dummy_struct { \ - typeof(*(p)) __val; \ - } __attribute__((packed)) *__ptr = (void *) (p); \ - \ - __ptr->__val; \ -}) - -/* function prototypes and related defs are in radiotap_iter.h */ - -/** - * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization - * @iterator: radiotap_iterator to initialize - * @radiotap_header: radiotap header to parse - * @max_length: total length we can parse into (eg, whole packet length) - * - * Returns: 0 or a negative error code if there is a problem. - * - * This function initializes an opaque iterator struct which can then - * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap - * argument which is present in the header. It knows about extended - * present headers and handles them. - * - * How to use: - * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator - * struct ieee80211_radiotap_iterator (no need to init the struct beforehand) - * checking for a good 0 return code. Then loop calling - * __ieee80211_radiotap_iterator_next()... it returns either 0, - * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem. - * The iterator's @this_arg member points to the start of the argument - * associated with the current argument index that is present, which can be - * found in the iterator's @this_arg_index member. This arg index corresponds - * to the IEEE80211_RADIOTAP_... defines. - * - * Radiotap header length: - * You can find the CPU-endian total radiotap header length in - * iterator->max_length after executing ieee80211_radiotap_iterator_init() - * successfully. - * - * Alignment Gotcha: - * You must take care when dereferencing iterator.this_arg - * for multibyte types... the pointer is not aligned. Use - * get_unaligned((type *)iterator.this_arg) to dereference - * iterator.this_arg for type "type" safely on all arches. - * - * Example code: - * See Documentation/networking/radiotap-headers.txt - */ - -int ieee80211_radiotap_iterator_init( - struct ieee80211_radiotap_iterator *iterator, - struct ieee80211_radiotap_header *radiotap_header, - int max_length) -{ - /* Linux only supports version 0 radiotap format */ - if (radiotap_header->it_version) - return -EINVAL; - - /* sanity check for allowed length and radiotap length field */ - if (max_length < le16_to_cpu(get_unaligned(&radiotap_header->it_len))) - return -EINVAL; - - iterator->rtheader = radiotap_header; - iterator->max_length = le16_to_cpu(get_unaligned( - &radiotap_header->it_len)); - iterator->arg_index = 0; - iterator->bitmap_shifter = le32_to_cpu(get_unaligned( - &radiotap_header->it_present)); - iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header); - iterator->this_arg = NULL; - - /* find payload start allowing for extended bitmap(s) */ - - if (unlikely(iterator->bitmap_shifter & (1<arg)) & - (1<arg += sizeof(u32); - - /* - * check for insanity where the present bitmaps - * keep claiming to extend up to or even beyond the - * stated radiotap header length - */ - - if (((ulong)iterator->arg - (ulong)iterator->rtheader) - > (ulong)iterator->max_length) - return -EINVAL; - } - - iterator->arg += sizeof(u32); - - /* - * no need to check again for blowing past stated radiotap - * header length, because ieee80211_radiotap_iterator_next - * checks it before it is dereferenced - */ - } - - /* we are all initialized happily */ - - return 0; -} - - -/** - * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg - * @iterator: radiotap_iterator to move to next arg (if any) - * - * Returns: 0 if there is an argument to handle, - * -ENOENT if there are no more args or -EINVAL - * if there is something else wrong. - * - * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*) - * in @this_arg_index and sets @this_arg to point to the - * payload for the field. It takes care of alignment handling and extended - * present fields. @this_arg can be changed by the caller (eg, - * incremented to move inside a compound argument like - * IEEE80211_RADIOTAP_CHANNEL). The args pointed to are in - * little-endian format whatever the endianess of your CPU. - * - * Alignment Gotcha: - * You must take care when dereferencing iterator.this_arg - * for multibyte types... the pointer is not aligned. Use - * get_unaligned((type *)iterator.this_arg) to dereference - * iterator.this_arg for type "type" safely on all arches. - */ - -int ieee80211_radiotap_iterator_next( - struct ieee80211_radiotap_iterator *iterator) -{ - - /* - * small length lookup table for all radiotap types we heard of - * starting from b0 in the bitmap, so we can walk the payload - * area of the radiotap header - * - * There is a requirement to pad args, so that args - * of a given length must begin at a boundary of that length - * -- but note that compound args are allowed (eg, 2 x u16 - * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not - * a reliable indicator of alignment requirement. - * - * upper nybble: content alignment for arg - * lower nybble: content length for arg - */ - - static const u8 rt_sizes[] = { - [IEEE80211_RADIOTAP_TSFT] = 0x88, - [IEEE80211_RADIOTAP_FLAGS] = 0x11, - [IEEE80211_RADIOTAP_RATE] = 0x11, - [IEEE80211_RADIOTAP_CHANNEL] = 0x24, - [IEEE80211_RADIOTAP_FHSS] = 0x22, - [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11, - [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11, - [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22, - [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22, - [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22, - [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11, - [IEEE80211_RADIOTAP_ANTENNA] = 0x11, - [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11, - [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11, - [IEEE80211_RADIOTAP_RX_FLAGS] = 0x22, - [IEEE80211_RADIOTAP_TX_FLAGS] = 0x22, - [IEEE80211_RADIOTAP_RTS_RETRIES] = 0x11, - [IEEE80211_RADIOTAP_DATA_RETRIES] = 0x11, - /* - * add more here as they are defined in - * include/net/ieee80211_radiotap.h - */ - }; - - /* - * for every radiotap entry we can at - * least skip (by knowing the length)... - */ - - while (iterator->arg_index < (int) sizeof(rt_sizes)) { - int hit = 0; - int pad; - - if (!(iterator->bitmap_shifter & 1)) - goto next_entry; /* arg not present */ - - /* - * arg is present, account for alignment padding - * 8-bit args can be at any alignment - * 16-bit args must start on 16-bit boundary - * 32-bit args must start on 32-bit boundary - * 64-bit args must start on 64-bit boundary - * - * note that total arg size can differ from alignment of - * elements inside arg, so we use upper nybble of length - * table to base alignment on - * - * also note: these alignments are ** relative to the - * start of the radiotap header **. There is no guarantee - * that the radiotap header itself is aligned on any - * kind of boundary. - * - * the above is why get_unaligned() is used to dereference - * multibyte elements from the radiotap area - */ - - pad = (((ulong)iterator->arg) - - ((ulong)iterator->rtheader)) & - ((rt_sizes[iterator->arg_index] >> 4) - 1); - - if (pad) - iterator->arg += - (rt_sizes[iterator->arg_index] >> 4) - pad; - - /* - * this is what we will return to user, but we need to - * move on first so next call has something fresh to test - */ - iterator->this_arg_index = iterator->arg_index; - iterator->this_arg = iterator->arg; - hit = 1; - - /* internally move on the size of this arg */ - iterator->arg += rt_sizes[iterator->arg_index] & 0x0f; - - /* - * check for insanity where we are given a bitmap that - * claims to have more arg content than the length of the - * radiotap section. We will normally end up equalling this - * max_length on the last arg, never exceeding it. - */ - - if (((ulong)iterator->arg - (ulong)iterator->rtheader) > - (ulong) iterator->max_length) - return -EINVAL; - - next_entry: - iterator->arg_index++; - if (unlikely((iterator->arg_index & 31) == 0)) { - /* completed current u32 bitmap */ - if (iterator->bitmap_shifter & 1) { - /* b31 was set, there is more */ - /* move to next u32 bitmap */ - iterator->bitmap_shifter = le32_to_cpu( - get_unaligned(iterator->next_bitmap)); - iterator->next_bitmap++; - } else - /* no more bitmaps: end */ - iterator->arg_index = sizeof(rt_sizes); - } else /* just try the next bit */ - iterator->bitmap_shifter >>= 1; - - /* if we found a valid arg earlier, return it now */ - if (hit) - return 0; - } - - /* we don't know how to handle any more args, we're done */ - return -ENOENT; -} diff --git a/contrib/hostapd/hostapd/radiotap.h b/contrib/hostapd/hostapd/radiotap.h deleted file mode 100644 index 508264c4cf..0000000000 --- a/contrib/hostapd/hostapd/radiotap.h +++ /dev/null @@ -1,242 +0,0 @@ -/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */ -/* $NetBSD: ieee80211_radiotap.h,v 1.11 2005/06/22 06:16:02 dyoung Exp $ */ - -/*- - * Copyright (c) 2003, 2004 David Young. 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. - * 3. The name of David Young may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``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 DAVID - * YOUNG 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. - */ - -/* - * Modifications to fit into the linux IEEE 802.11 stack, - * Mike Kershaw (dragorn@kismetwireless.net) - */ - -#ifndef IEEE80211RADIOTAP_H -#define IEEE80211RADIOTAP_H - -#include - -/* Base version of the radiotap packet header data */ -#define PKTHDR_RADIOTAP_VERSION 0 - -/* A generic radio capture format is desirable. There is one for - * Linux, but it is neither rigidly defined (there were not even - * units given for some fields) nor easily extensible. - * - * I suggest the following extensible radio capture format. It is - * based on a bitmap indicating which fields are present. - * - * I am trying to describe precisely what the application programmer - * should expect in the following, and for that reason I tell the - * units and origin of each measurement (where it applies), or else I - * use sufficiently weaselly language ("is a monotonically nondecreasing - * function of...") that I cannot set false expectations for lawyerly - * readers. - */ - -/* The radio capture header precedes the 802.11 header. - * All data in the header is little endian on all platforms. - */ -struct ieee80211_radiotap_header { - uint8_t it_version; /* Version 0. Only increases - * for drastic changes, - * introduction of compatible - * new fields does not count. - */ - uint8_t it_pad; - uint16_t it_len; /* length of the whole - * header in bytes, including - * it_version, it_pad, - * it_len, and data fields. - */ - uint32_t it_present; /* A bitmap telling which - * fields are present. Set bit 31 - * (0x80000000) to extend the - * bitmap by another 32 bits. - * Additional extensions are made - * by setting bit 31. - */ -}; - -/* Name Data type Units - * ---- --------- ----- - * - * IEEE80211_RADIOTAP_TSFT __le64 microseconds - * - * Value in microseconds of the MAC's 64-bit 802.11 Time - * Synchronization Function timer when the first bit of the - * MPDU arrived at the MAC. For received frames, only. - * - * IEEE80211_RADIOTAP_CHANNEL 2 x uint16_t MHz, bitmap - * - * Tx/Rx frequency in MHz, followed by flags (see below). - * - * IEEE80211_RADIOTAP_FHSS uint16_t see below - * - * For frequency-hopping radios, the hop set (first byte) - * and pattern (second byte). - * - * IEEE80211_RADIOTAP_RATE u8 500kb/s - * - * Tx/Rx data rate - * - * IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from - * one milliwatt (dBm) - * - * RF signal power at the antenna, decibel difference from - * one milliwatt. - * - * IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from - * one milliwatt (dBm) - * - * RF noise power at the antenna, decibel difference from one - * milliwatt. - * - * IEEE80211_RADIOTAP_DB_ANTSIGNAL u8 decibel (dB) - * - * RF signal power at the antenna, decibel difference from an - * arbitrary, fixed reference. - * - * IEEE80211_RADIOTAP_DB_ANTNOISE u8 decibel (dB) - * - * RF noise power at the antenna, decibel difference from an - * arbitrary, fixed reference point. - * - * IEEE80211_RADIOTAP_LOCK_QUALITY uint16_t unitless - * - * Quality of Barker code lock. Unitless. Monotonically - * nondecreasing with "better" lock strength. Called "Signal - * Quality" in datasheets. (Is there a standard way to measure - * this?) - * - * IEEE80211_RADIOTAP_TX_ATTENUATION uint16_t unitless - * - * Transmit power expressed as unitless distance from max - * power set at factory calibration. 0 is max power. - * Monotonically nondecreasing with lower power levels. - * - * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t decibels (dB) - * - * Transmit power expressed as decibel distance from max power - * set at factory calibration. 0 is max power. Monotonically - * nondecreasing with lower power levels. - * - * IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from - * one milliwatt (dBm) - * - * Transmit power expressed as dBm (decibels from a 1 milliwatt - * reference). This is the absolute power level measured at - * the antenna port. - * - * IEEE80211_RADIOTAP_FLAGS u8 bitmap - * - * Properties of transmitted and received frames. See flags - * defined below. - * - * IEEE80211_RADIOTAP_ANTENNA u8 antenna index - * - * Unitless indication of the Rx/Tx antenna for this packet. - * The first antenna is antenna 0. - * - * IEEE80211_RADIOTAP_RX_FLAGS uint16_t bitmap - * - * Properties of received frames. See flags defined below. - * - * IEEE80211_RADIOTAP_TX_FLAGS uint16_t bitmap - * - * Properties of transmitted frames. See flags defined below. - * - * IEEE80211_RADIOTAP_RTS_RETRIES u8 data - * - * Number of rts retries a transmitted frame used. - * - * IEEE80211_RADIOTAP_DATA_RETRIES u8 data - * - * Number of unicast retries a transmitted frame used. - * - */ -enum ieee80211_radiotap_type { - IEEE80211_RADIOTAP_TSFT = 0, - IEEE80211_RADIOTAP_FLAGS = 1, - IEEE80211_RADIOTAP_RATE = 2, - IEEE80211_RADIOTAP_CHANNEL = 3, - IEEE80211_RADIOTAP_FHSS = 4, - IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, - IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, - IEEE80211_RADIOTAP_LOCK_QUALITY = 7, - IEEE80211_RADIOTAP_TX_ATTENUATION = 8, - IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, - IEEE80211_RADIOTAP_DBM_TX_POWER = 10, - IEEE80211_RADIOTAP_ANTENNA = 11, - IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, - IEEE80211_RADIOTAP_DB_ANTNOISE = 13, - IEEE80211_RADIOTAP_RX_FLAGS = 14, - IEEE80211_RADIOTAP_TX_FLAGS = 15, - IEEE80211_RADIOTAP_RTS_RETRIES = 16, - IEEE80211_RADIOTAP_DATA_RETRIES = 17, - IEEE80211_RADIOTAP_EXT = 31 -}; - -/* Channel flags. */ -#define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */ -#define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */ -#define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */ -#define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */ -#define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */ -#define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */ -#define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */ -#define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */ - -/* For IEEE80211_RADIOTAP_FLAGS */ -#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received - * during CFP - */ -#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received - * with short - * preamble - */ -#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received - * with WEP encryption - */ -#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received - * with fragmentation - */ -#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */ -#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between - * 802.11 header and payload - * (to 32-bit boundary) - */ -/* For IEEE80211_RADIOTAP_RX_FLAGS */ -#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */ - -/* For IEEE80211_RADIOTAP_TX_FLAGS */ -#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive - * retries */ -#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */ -#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */ - -#endif /* IEEE80211_RADIOTAP_H */ diff --git a/contrib/hostapd/hostapd/radiotap_iter.h b/contrib/hostapd/hostapd/radiotap_iter.h deleted file mode 100644 index 92a798a670..0000000000 --- a/contrib/hostapd/hostapd/radiotap_iter.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __RADIOTAP_ITER_H -#define __RADIOTAP_ITER_H - -#include "radiotap.h" - -/* Radiotap header iteration - * implemented in radiotap.c - */ -/** - * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args - * @rtheader: pointer to the radiotap header we are walking through - * @max_length: length of radiotap header in cpu byte ordering - * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg - * @this_arg: pointer to current radiotap arg - * @arg_index: internal next argument index - * @arg: internal next argument pointer - * @next_bitmap: internal pointer to next present u32 - * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present - */ - -struct ieee80211_radiotap_iterator { - struct ieee80211_radiotap_header *rtheader; - int max_length; - int this_arg_index; - unsigned char *this_arg; - - int arg_index; - unsigned char *arg; - uint32_t *next_bitmap; - uint32_t bitmap_shifter; -}; - -extern int ieee80211_radiotap_iterator_init( - struct ieee80211_radiotap_iterator *iterator, - struct ieee80211_radiotap_header *radiotap_header, - int max_length); - -extern int ieee80211_radiotap_iterator_next( - struct ieee80211_radiotap_iterator *iterator); - -#endif /* __RADIOTAP_ITER_H */ diff --git a/contrib/hostapd/hostapd/sta_info.c b/contrib/hostapd/hostapd/sta_info.c deleted file mode 100644 index a139ba9bdf..0000000000 --- a/contrib/hostapd/hostapd/sta_info.c +++ /dev/null @@ -1,711 +0,0 @@ -/* - * hostapd / Station table - * Copyright (c) 2002-2008, Jouni Malinen - * Copyright (c) 2007-2008, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "hostapd.h" -#include "sta_info.h" -#include "eloop.h" -#include "accounting.h" -#include "ieee802_1x.h" -#include "ieee802_11.h" -#include "radius/radius.h" -#include "wpa.h" -#include "preauth.h" -#include "radius/radius_client.h" -#include "driver.h" -#include "beacon.h" -#include "hw_features.h" -#include "mlme.h" -#include "vlan_init.h" - -static int ap_sta_in_other_bss(struct hostapd_data *hapd, - struct sta_info *sta, u32 flags); -static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx); -#ifdef CONFIG_IEEE80211W -static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx); -#endif /* CONFIG_IEEE80211W */ - -int ap_for_each_sta(struct hostapd_data *hapd, - int (*cb)(struct hostapd_data *hapd, struct sta_info *sta, - void *ctx), - void *ctx) -{ - struct sta_info *sta; - - for (sta = hapd->sta_list; sta; sta = sta->next) { - if (cb(hapd, sta, ctx)) - return 1; - } - - return 0; -} - - -struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta) -{ - struct sta_info *s; - - s = hapd->sta_hash[STA_HASH(sta)]; - while (s != NULL && os_memcmp(s->addr, sta, 6) != 0) - s = s->hnext; - return s; -} - - -static void ap_sta_list_del(struct hostapd_data *hapd, struct sta_info *sta) -{ - struct sta_info *tmp; - - if (hapd->sta_list == sta) { - hapd->sta_list = sta->next; - return; - } - - tmp = hapd->sta_list; - while (tmp != NULL && tmp->next != sta) - tmp = tmp->next; - if (tmp == NULL) { - wpa_printf(MSG_DEBUG, "Could not remove STA " MACSTR " from " - "list.", MAC2STR(sta->addr)); - } else - tmp->next = sta->next; -} - - -void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta) -{ - sta->hnext = hapd->sta_hash[STA_HASH(sta->addr)]; - hapd->sta_hash[STA_HASH(sta->addr)] = sta; -} - - -static void ap_sta_hash_del(struct hostapd_data *hapd, struct sta_info *sta) -{ - struct sta_info *s; - - s = hapd->sta_hash[STA_HASH(sta->addr)]; - if (s == NULL) return; - if (os_memcmp(s->addr, sta->addr, 6) == 0) { - hapd->sta_hash[STA_HASH(sta->addr)] = s->hnext; - return; - } - - while (s->hnext != NULL && - os_memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0) - s = s->hnext; - if (s->hnext != NULL) - s->hnext = s->hnext->hnext; - else - wpa_printf(MSG_DEBUG, "AP: could not remove STA " MACSTR - " from hash table", MAC2STR(sta->addr)); -} - - -void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) -{ - int set_beacon = 0; - - accounting_sta_stop(hapd, sta); - - if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC) && - !(sta->flags & WLAN_STA_PREAUTH)) - hostapd_sta_remove(hapd, sta->addr); - - ap_sta_hash_del(hapd, sta); - ap_sta_list_del(hapd, sta); - - if (sta->aid > 0) - hapd->sta_aid[sta->aid - 1] = NULL; - - hapd->num_sta--; - if (sta->nonerp_set) { - sta->nonerp_set = 0; - hapd->iface->num_sta_non_erp--; - if (hapd->iface->num_sta_non_erp == 0) - set_beacon++; - } - - if (sta->no_short_slot_time_set) { - sta->no_short_slot_time_set = 0; - hapd->iface->num_sta_no_short_slot_time--; - if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G - && hapd->iface->num_sta_no_short_slot_time == 0) - set_beacon++; - } - - if (sta->no_short_preamble_set) { - sta->no_short_preamble_set = 0; - hapd->iface->num_sta_no_short_preamble--; - if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G - && hapd->iface->num_sta_no_short_preamble == 0) - set_beacon++; - } - -#ifdef CONFIG_IEEE80211N - if (sta->no_ht_gf_set) { - sta->no_ht_gf_set = 0; - hapd->iface->num_sta_ht_no_gf--; - } - - if (sta->no_ht_set) { - sta->no_ht_set = 0; - hapd->iface->num_sta_no_ht--; - } - - if (sta->ht_20mhz_set) { - sta->ht_20mhz_set = 0; - hapd->iface->num_sta_ht_20mhz--; - } - - if (hostapd_ht_operation_update(hapd->iface) > 0) - set_beacon++; -#endif /* CONFIG_IEEE80211N */ - - if (set_beacon) - ieee802_11_set_beacons(hapd->iface); - - eloop_cancel_timeout(ap_handle_timer, hapd, sta); - eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); - - ieee802_1x_free_station(sta); - wpa_auth_sta_deinit(sta->wpa_sm); - rsn_preauth_free_station(hapd, sta); - radius_client_flush_auth(hapd->radius, sta->addr); - - os_free(sta->last_assoc_req); - os_free(sta->challenge); - -#ifdef CONFIG_IEEE80211W - os_free(sta->sa_query_trans_id); - eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); -#endif /* CONFIG_IEEE80211W */ - - wpabuf_free(sta->wps_ie); - - os_free(sta); -} - - -void hostapd_free_stas(struct hostapd_data *hapd) -{ - struct sta_info *sta, *prev; - - sta = hapd->sta_list; - - while (sta) { - prev = sta; - if (sta->flags & WLAN_STA_AUTH) { - mlme_deauthenticate_indication( - hapd, sta, WLAN_REASON_UNSPECIFIED); - } - sta = sta->next; - wpa_printf(MSG_DEBUG, "Removing station " MACSTR, - MAC2STR(prev->addr)); - ap_free_sta(hapd, prev); - } -} - - -/** - * ap_handle_timer - Per STA timer handler - * @eloop_ctx: struct hostapd_data * - * @timeout_ctx: struct sta_info * - * - * This function is called to check station activity and to remove inactive - * stations. - */ -void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - struct sta_info *sta = timeout_ctx; - unsigned long next_time = 0; - - if (sta->timeout_next == STA_REMOVE) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "deauthenticated due to " - "local deauth request"); - ap_free_sta(hapd, sta); - return; - } - - if ((sta->flags & WLAN_STA_ASSOC) && - (sta->timeout_next == STA_NULLFUNC || - sta->timeout_next == STA_DISASSOC)) { - int inactive_sec; - wpa_printf(MSG_DEBUG, "Checking STA " MACSTR " inactivity:", - MAC2STR(sta->addr)); - inactive_sec = hostapd_get_inact_sec(hapd, sta->addr); - if (inactive_sec == -1) { - wpa_printf(MSG_DEBUG, "Could not get station info " - "from kernel driver for " MACSTR ".", - MAC2STR(sta->addr)); - } else if (inactive_sec < hapd->conf->ap_max_inactivity && - sta->flags & WLAN_STA_ASSOC) { - /* station activity detected; reset timeout state */ - wpa_printf(MSG_DEBUG, " Station has been active"); - sta->timeout_next = STA_NULLFUNC; - next_time = hapd->conf->ap_max_inactivity - - inactive_sec; - } - } - - if ((sta->flags & WLAN_STA_ASSOC) && - sta->timeout_next == STA_DISASSOC && - !(sta->flags & WLAN_STA_PENDING_POLL)) { - wpa_printf(MSG_DEBUG, " Station has ACKed data poll"); - /* data nullfunc frame poll did not produce TX errors; assume - * station ACKed it */ - sta->timeout_next = STA_NULLFUNC; - next_time = hapd->conf->ap_max_inactivity; - } - - if (next_time) { - eloop_register_timeout(next_time, 0, ap_handle_timer, hapd, - sta); - return; - } - - if (sta->timeout_next == STA_NULLFUNC && - (sta->flags & WLAN_STA_ASSOC)) { - /* send data frame to poll STA and check whether this frame - * is ACKed */ - struct ieee80211_hdr hdr; - - wpa_printf(MSG_DEBUG, " Polling STA with data frame"); - sta->flags |= WLAN_STA_PENDING_POLL; - -#ifndef CONFIG_NATIVE_WINDOWS - os_memset(&hdr, 0, sizeof(hdr)); - if (hapd->driver && - os_strcmp(hapd->driver->name, "hostap") == 0) { - /* - * WLAN_FC_STYPE_NULLFUNC would be more appropriate, - * but it is apparently not retried so TX Exc events - * are not received for it. - */ - hdr.frame_control = - IEEE80211_FC(WLAN_FC_TYPE_DATA, - WLAN_FC_STYPE_DATA); - } else { - hdr.frame_control = - IEEE80211_FC(WLAN_FC_TYPE_DATA, - WLAN_FC_STYPE_NULLFUNC); - } - - hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS); - os_memcpy(hdr.IEEE80211_DA_FROMDS, sta->addr, ETH_ALEN); - os_memcpy(hdr.IEEE80211_BSSID_FROMDS, hapd->own_addr, - ETH_ALEN); - os_memcpy(hdr.IEEE80211_SA_FROMDS, hapd->own_addr, ETH_ALEN); - - if (hostapd_send_mgmt_frame(hapd, &hdr, sizeof(hdr), 0) < 0) - perror("ap_handle_timer: send"); -#endif /* CONFIG_NATIVE_WINDOWS */ - } else if (sta->timeout_next != STA_REMOVE) { - int deauth = sta->timeout_next == STA_DEAUTH; - - wpa_printf(MSG_DEBUG, "Sending %s info to STA " MACSTR, - deauth ? "deauthentication" : "disassociation", - MAC2STR(sta->addr)); - - if (deauth) { - hostapd_sta_deauth(hapd, sta->addr, - WLAN_REASON_PREV_AUTH_NOT_VALID); - } else { - hostapd_sta_disassoc( - hapd, sta->addr, - WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); - } - } - - switch (sta->timeout_next) { - case STA_NULLFUNC: - sta->timeout_next = STA_DISASSOC; - eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer, - hapd, sta); - break; - case STA_DISASSOC: - sta->flags &= ~WLAN_STA_ASSOC; - ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - if (!sta->acct_terminate_cause) - sta->acct_terminate_cause = - RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; - accounting_sta_stop(hapd, sta); - ieee802_1x_free_station(sta); - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "disassociated due to " - "inactivity"); - sta->timeout_next = STA_DEAUTH; - eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, - hapd, sta); - mlme_disassociate_indication( - hapd, sta, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); - break; - case STA_DEAUTH: - case STA_REMOVE: - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "deauthenticated due to " - "inactivity"); - if (!sta->acct_terminate_cause) - sta->acct_terminate_cause = - RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; - mlme_deauthenticate_indication( - hapd, sta, - WLAN_REASON_PREV_AUTH_NOT_VALID); - ap_free_sta(hapd, sta); - break; - } -} - - -static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - struct sta_info *sta = timeout_ctx; - u8 addr[ETH_ALEN]; - - if (!(sta->flags & WLAN_STA_AUTH)) - return; - - mlme_deauthenticate_indication(hapd, sta, - WLAN_REASON_PREV_AUTH_NOT_VALID); - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "deauthenticated due to " - "session timeout"); - sta->acct_terminate_cause = - RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT; - os_memcpy(addr, sta->addr, ETH_ALEN); - ap_free_sta(hapd, sta); - hostapd_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); -} - - -void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta, - u32 session_timeout) -{ - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "setting session timeout to %d " - "seconds", session_timeout); - eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); - eloop_register_timeout(session_timeout, 0, ap_handle_session_timer, - hapd, sta); -} - - -void ap_sta_no_session_timeout(struct hostapd_data *hapd, struct sta_info *sta) -{ - eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); -} - - -struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr) -{ - struct sta_info *sta; - - sta = ap_get_sta(hapd, addr); - if (sta) - return sta; - - wpa_printf(MSG_DEBUG, " New STA"); - if (hapd->num_sta >= hapd->conf->max_num_sta) { - /* FIX: might try to remove some old STAs first? */ - wpa_printf(MSG_DEBUG, "no more room for new STAs (%d/%d)", - hapd->num_sta, hapd->conf->max_num_sta); - return NULL; - } - - sta = os_zalloc(sizeof(struct sta_info)); - if (sta == NULL) { - wpa_printf(MSG_ERROR, "malloc failed"); - return NULL; - } - sta->acct_interim_interval = hapd->conf->radius->acct_interim_interval; - - /* initialize STA info data */ - eloop_register_timeout(hapd->conf->ap_max_inactivity, 0, - ap_handle_timer, hapd, sta); - os_memcpy(sta->addr, addr, ETH_ALEN); - sta->next = hapd->sta_list; - hapd->sta_list = sta; - hapd->num_sta++; - ap_sta_hash_add(hapd, sta); - sta->ssid = &hapd->conf->ssid; - - return sta; -} - - -static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta) -{ - ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - - wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver", - MAC2STR(sta->addr)); - if (hostapd_sta_remove(hapd, sta->addr) && - sta->flags & WLAN_STA_ASSOC) { - wpa_printf(MSG_DEBUG, "Could not remove station " MACSTR - " from kernel driver.", MAC2STR(sta->addr)); - return -1; - } - return 0; -} - - -static int ap_sta_in_other_bss(struct hostapd_data *hapd, - struct sta_info *sta, u32 flags) -{ - struct hostapd_iface *iface = hapd->iface; - size_t i; - - for (i = 0; i < iface->num_bss; i++) { - struct hostapd_data *bss = iface->bss[i]; - struct sta_info *sta2; - /* bss should always be set during operation, but it may be - * NULL during reconfiguration. Assume the STA is not - * associated to another BSS in that case to avoid NULL pointer - * dereferences. */ - if (bss == hapd || bss == NULL) - continue; - sta2 = ap_get_sta(bss, sta->addr); - if (sta2 && ((sta2->flags & flags) == flags)) - return 1; - } - - return 0; -} - - -void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta, - u16 reason) -{ - wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR, - hapd->conf->iface, MAC2STR(sta->addr)); - sta->flags &= ~WLAN_STA_ASSOC; - if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC)) - ap_sta_remove(hapd, sta); - sta->timeout_next = STA_DEAUTH; - eloop_cancel_timeout(ap_handle_timer, hapd, sta); - eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0, - ap_handle_timer, hapd, sta); - accounting_sta_stop(hapd, sta); - ieee802_1x_free_station(sta); - - mlme_disassociate_indication(hapd, sta, reason); -} - - -void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta, - u16 reason) -{ - wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR, - hapd->conf->iface, MAC2STR(sta->addr)); - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); - if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC)) - ap_sta_remove(hapd, sta); - sta->timeout_next = STA_REMOVE; - eloop_cancel_timeout(ap_handle_timer, hapd, sta); - eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0, - ap_handle_timer, hapd, sta); - accounting_sta_stop(hapd, sta); - ieee802_1x_free_station(sta); - - mlme_deauthenticate_indication(hapd, sta, reason); -} - - -int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta, - int old_vlanid) -{ - const char *iface; - struct hostapd_vlan *vlan = NULL; - - /* - * Do not proceed furthur if the vlan id remains same. We do not want - * duplicate dynamic vlan entries. - */ - if (sta->vlan_id == old_vlanid) - return 0; - - /* - * During 1x reauth, if the vlan id changes, then remove the old id and - * proceed furthur to add the new one. - */ - if (old_vlanid > 0) - vlan_remove_dynamic(hapd, old_vlanid); - - iface = hapd->conf->iface; - if (sta->ssid->vlan[0]) - iface = sta->ssid->vlan; - - if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED) - sta->vlan_id = 0; - else if (sta->vlan_id > 0) { - vlan = hapd->conf->vlan; - while (vlan) { - if (vlan->vlan_id == sta->vlan_id || - vlan->vlan_id == VLAN_ID_WILDCARD) { - iface = vlan->ifname; - break; - } - vlan = vlan->next; - } - } - - if (sta->vlan_id > 0 && vlan == NULL) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "could not find VLAN for " - "binding station to (vlan_id=%d)", - sta->vlan_id); - return -1; - } else if (sta->vlan_id > 0 && vlan->vlan_id == VLAN_ID_WILDCARD) { - vlan = vlan_add_dynamic(hapd, vlan, sta->vlan_id); - if (vlan == NULL) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "could not add " - "dynamic VLAN interface for vlan_id=%d", - sta->vlan_id); - return -1; - } - - iface = vlan->ifname; - if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "could not " - "configure encryption for dynamic VLAN " - "interface for vlan_id=%d", - sta->vlan_id); - } - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "added new dynamic VLAN " - "interface '%s'", iface); - } else if (vlan && vlan->vlan_id == sta->vlan_id) { - if (sta->vlan_id > 0) { - vlan->dynamic_vlan++; - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "updated existing " - "dynamic VLAN interface '%s'", iface); - } - - /* - * Update encryption configuration for statically generated - * VLAN interface. This is only used for static WEP - * configuration for the case where hostapd did not yet know - * which keys are to be used when the interface was added. - */ - if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "could not " - "configure encryption for VLAN " - "interface for vlan_id=%d", - sta->vlan_id); - } - } - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "binding station to interface " - "'%s'", iface); - - if (wpa_auth_sta_set_vlan(sta->wpa_sm, sta->vlan_id) < 0) - wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA"); - - return hostapd_set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id); -} - - -#ifdef CONFIG_IEEE80211W - -int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta) -{ - u32 tu; - struct os_time now, passed; - os_get_time(&now); - os_time_sub(&now, &sta->sa_query_start, &passed); - tu = (passed.sec * 1000000 + passed.usec) / 1024; - if (hapd->conf->assoc_sa_query_max_timeout < tu) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "association SA Query timed out"); - sta->sa_query_timed_out = 1; - os_free(sta->sa_query_trans_id); - sta->sa_query_trans_id = NULL; - sta->sa_query_count = 0; - eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); - return 1; - } - - return 0; -} - - -static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - struct sta_info *sta = timeout_ctx; - unsigned int timeout, sec, usec; - u8 *trans_id, *nbuf; - - if (sta->sa_query_count > 0 && - ap_check_sa_query_timeout(hapd, sta)) - return; - - nbuf = os_realloc(sta->sa_query_trans_id, - (sta->sa_query_count + 1) * WLAN_SA_QUERY_TR_ID_LEN); - if (nbuf == NULL) - return; - if (sta->sa_query_count == 0) { - /* Starting a new SA Query procedure */ - os_get_time(&sta->sa_query_start); - } - trans_id = nbuf + sta->sa_query_count * WLAN_SA_QUERY_TR_ID_LEN; - sta->sa_query_trans_id = nbuf; - sta->sa_query_count++; - - os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN); - - timeout = hapd->conf->assoc_sa_query_retry_timeout; - sec = ((timeout / 1000) * 1024) / 1000; - usec = (timeout % 1000) * 1024; - eloop_register_timeout(sec, usec, ap_sa_query_timer, hapd, sta); - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "association SA Query attempt %d", sta->sa_query_count); - - ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id); -} - - -void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta) -{ - ap_sa_query_timer(hapd, sta); -} - - -void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta) -{ - eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); - os_free(sta->sa_query_trans_id); - sta->sa_query_trans_id = NULL; - sta->sa_query_count = 0; -} - -#endif /* CONFIG_IEEE80211W */ diff --git a/contrib/hostapd/hostapd/sta_info.h b/contrib/hostapd/hostapd/sta_info.h deleted file mode 100644 index e835970923..0000000000 --- a/contrib/hostapd/hostapd/sta_info.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * hostapd / Station table - * Copyright (c) 2002-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef STA_INFO_H -#define STA_INFO_H - -int ap_for_each_sta(struct hostapd_data *hapd, - int (*cb)(struct hostapd_data *hapd, struct sta_info *sta, - void *ctx), - void *ctx); -struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta); -void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta); -void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta); -void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta); -void hostapd_free_stas(struct hostapd_data *hapd); -void ap_handle_timer(void *eloop_ctx, void *timeout_ctx); -void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta, - u32 session_timeout); -void ap_sta_no_session_timeout(struct hostapd_data *hapd, - struct sta_info *sta); -struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr); -void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta, - u16 reason); -void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta, - u16 reason); -int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta, - int old_vlanid); -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); - -#endif /* STA_INFO_H */ diff --git a/contrib/hostapd/hostapd/vlan_init.c b/contrib/hostapd/hostapd/vlan_init.c deleted file mode 100644 index 87c61e2c01..0000000000 --- a/contrib/hostapd/hostapd/vlan_init.c +++ /dev/null @@ -1,826 +0,0 @@ -/* - * hostapd / VLAN initialization - * Copyright 2003, Instant802 Networks, Inc. - * Copyright 2005-2006, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "hostapd.h" -#include "driver.h" -#include "vlan_init.h" - - -#ifdef CONFIG_FULL_DYNAMIC_VLAN - -#include -#include -#include -#include -#include - -#include "priv_netlink.h" -#include "eloop.h" - - -struct full_dynamic_vlan { - int s; /* socket on which to listen for new/removed interfaces. */ -}; - - -static int ifconfig_helper(const char *if_name, int up) -{ - int fd; - struct ifreq ifr; - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); - return -1; - } - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, if_name, IFNAMSIZ); - - if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCGIFFLAGS]"); - close(fd); - return -1; - } - - if (up) - ifr.ifr_flags |= IFF_UP; - else - ifr.ifr_flags &= ~IFF_UP; - - if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCSIFFLAGS]"); - close(fd); - return -1; - } - - close(fd); - return 0; -} - - -static int ifconfig_up(const char *if_name) -{ - return ifconfig_helper(if_name, 1); -} - - -static int ifconfig_down(const char *if_name) -{ - return ifconfig_helper(if_name, 0); -} - - -/* - * These are only available in recent linux headers (without the leading - * underscore). - */ -#define _GET_VLAN_REALDEV_NAME_CMD 8 -#define _GET_VLAN_VID_CMD 9 - -/* This value should be 256 ONLY. If it is something else, then hostapd - * might crash!, as this value has been hard-coded in 2.4.x kernel - * bridging code. - */ -#define MAX_BR_PORTS 256 - -static int br_delif(const char *br_name, const char *if_name) -{ - int fd; - struct ifreq ifr; - unsigned long args[2]; - int if_index; - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); - return -1; - } - - if_index = if_nametoindex(if_name); - - if (if_index == 0) { - printf("Failure determining interface index for '%s'\n", - if_name); - close(fd); - return -1; - } - - args[0] = BRCTL_DEL_IF; - args[1] = if_index; - - os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name)); - ifr.ifr_data = (__caddr_t) args; - - if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0 && errno != EINVAL) { - /* No error if interface already removed. */ - perror("ioctl[SIOCDEVPRIVATE,BRCTL_DEL_IF]"); - close(fd); - return -1; - } - - close(fd); - return 0; -} - - -/* - Add interface 'if_name' to the bridge 'br_name' - - returns -1 on error - returns 1 if the interface is already part of the bridge - returns 0 otherwise -*/ -static int br_addif(const char *br_name, const char *if_name) -{ - int fd; - struct ifreq ifr; - unsigned long args[2]; - int if_index; - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); - return -1; - } - - if_index = if_nametoindex(if_name); - - if (if_index == 0) { - printf("Failure determining interface index for '%s'\n", - if_name); - close(fd); - return -1; - } - - args[0] = BRCTL_ADD_IF; - args[1] = if_index; - - os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name)); - ifr.ifr_data = (__caddr_t) args; - - if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) { - if (errno == EBUSY) { - /* The interface is already added. */ - close(fd); - return 1; - } - - perror("ioctl[SIOCDEVPRIVATE,BRCTL_ADD_IF]"); - close(fd); - return -1; - } - - close(fd); - return 0; -} - - -static int br_delbr(const char *br_name) -{ - int fd; - unsigned long arg[2]; - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); - return -1; - } - - arg[0] = BRCTL_DEL_BRIDGE; - arg[1] = (unsigned long) br_name; - - if (ioctl(fd, SIOCGIFBR, arg) < 0 && errno != ENXIO) { - /* No error if bridge already removed. */ - perror("ioctl[BRCTL_DEL_BRIDGE]"); - close(fd); - return -1; - } - - close(fd); - return 0; -} - - -/* - Add a bridge with the name 'br_name'. - - returns -1 on error - returns 1 if the bridge already exists - returns 0 otherwise -*/ -static int br_addbr(const char *br_name) -{ - int fd; - unsigned long arg[2]; - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); - return -1; - } - - arg[0] = BRCTL_ADD_BRIDGE; - arg[1] = (unsigned long) br_name; - - if (ioctl(fd, SIOCGIFBR, arg) < 0) { - if (errno == EEXIST) { - /* The bridge is already added. */ - close(fd); - return 1; - } else { - perror("ioctl[BRCTL_ADD_BRIDGE]"); - close(fd); - return -1; - } - } - - close(fd); - return 0; -} - - -static int br_getnumports(const char *br_name) -{ - int fd; - int i; - int port_cnt = 0; - unsigned long arg[4]; - int ifindices[MAX_BR_PORTS]; - struct ifreq ifr; - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); - return -1; - } - - arg[0] = BRCTL_GET_PORT_LIST; - arg[1] = (unsigned long) ifindices; - arg[2] = MAX_BR_PORTS; - arg[3] = 0; - - os_memset(ifindices, 0, sizeof(ifindices)); - os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name)); - ifr.ifr_data = (__caddr_t) arg; - - if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) { - perror("ioctl[SIOCDEVPRIVATE,BRCTL_GET_PORT_LIST]"); - close(fd); - return -1; - } - - for (i = 1; i < MAX_BR_PORTS; i++) { - if (ifindices[i] > 0) { - port_cnt++; - } - } - - close(fd); - return port_cnt; -} - - -static int vlan_rem(const char *if_name) -{ - int fd; - struct vlan_ioctl_args if_request; - - if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) { - fprintf(stderr, "Interface name to long.\n"); - return -1; - } - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); - return -1; - } - - os_memset(&if_request, 0, sizeof(if_request)); - - os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1)); - if_request.cmd = DEL_VLAN_CMD; - - if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { - perror("ioctl[SIOCSIFVLAN,DEL_VLAN_CMD]"); - close(fd); - return -1; - } - - close(fd); - return 0; -} - - -/* - Add a vlan interface with VLAN ID 'vid' and tagged interface - 'if_name'. - - returns -1 on error - returns 1 if the interface already exists - returns 0 otherwise -*/ -static int vlan_add(const char *if_name, int vid) -{ - int fd; - struct vlan_ioctl_args if_request; - - ifconfig_up(if_name); - - if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) { - fprintf(stderr, "Interface name to long.\n"); - return -1; - } - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); - return -1; - } - - os_memset(&if_request, 0, sizeof(if_request)); - - /* Determine if a suitable vlan device already exists. */ - - os_snprintf(if_request.device1, sizeof(if_request.device1), "vlan%d", - vid); - - if_request.cmd = _GET_VLAN_VID_CMD; - - if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0) { - - if (if_request.u.VID == vid) { - if_request.cmd = _GET_VLAN_REALDEV_NAME_CMD; - - if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 && - os_strncmp(if_request.u.device2, if_name, - sizeof(if_request.u.device2)) == 0) { - close(fd); - return 1; - } - } - } - - /* A suitable vlan device does not already exist, add one. */ - - os_memset(&if_request, 0, sizeof(if_request)); - os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1)); - if_request.u.VID = vid; - if_request.cmd = ADD_VLAN_CMD; - - if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { - perror("ioctl[SIOCSIFVLAN,ADD_VLAN_CMD]"); - close(fd); - return -1; - } - - close(fd); - return 0; -} - - -static int vlan_set_name_type(unsigned int name_type) -{ - int fd; - struct vlan_ioctl_args if_request; - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); - return -1; - } - - os_memset(&if_request, 0, sizeof(if_request)); - - if_request.u.name_type = name_type; - if_request.cmd = SET_VLAN_NAME_TYPE_CMD; - if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { - perror("ioctl[SIOCSIFVLAN,SET_VLAN_NAME_TYPE_CMD]"); - close(fd); - return -1; - } - - close(fd); - return 0; -} - - -static void vlan_newlink(char *ifname, struct hostapd_data *hapd) -{ - char vlan_ifname[IFNAMSIZ]; - char br_name[IFNAMSIZ]; - struct hostapd_vlan *vlan = hapd->conf->vlan; - char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface; - - while (vlan) { - if (os_strcmp(ifname, vlan->ifname) == 0) { - - os_snprintf(br_name, sizeof(br_name), "brvlan%d", - vlan->vlan_id); - - if (!br_addbr(br_name)) - vlan->clean |= DVLAN_CLEAN_BR; - - ifconfig_up(br_name); - - if (tagged_interface) { - - if (!vlan_add(tagged_interface, vlan->vlan_id)) - vlan->clean |= DVLAN_CLEAN_VLAN; - - os_snprintf(vlan_ifname, sizeof(vlan_ifname), - "vlan%d", vlan->vlan_id); - - if (!br_addif(br_name, vlan_ifname)) - vlan->clean |= DVLAN_CLEAN_VLAN_PORT; - - ifconfig_up(vlan_ifname); - } - - if (!br_addif(br_name, ifname)) - vlan->clean |= DVLAN_CLEAN_WLAN_PORT; - - ifconfig_up(ifname); - - break; - } - vlan = vlan->next; - } -} - - -static void vlan_dellink(char *ifname, struct hostapd_data *hapd) -{ - char vlan_ifname[IFNAMSIZ]; - char br_name[IFNAMSIZ]; - struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan; - char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface; - int numports; - - first = prev = vlan; - - while (vlan) { - if (os_strcmp(ifname, vlan->ifname) == 0) { - os_snprintf(br_name, sizeof(br_name), "brvlan%d", - vlan->vlan_id); - - if (tagged_interface) { - os_snprintf(vlan_ifname, sizeof(vlan_ifname), - "vlan%d", vlan->vlan_id); - - numports = br_getnumports(br_name); - if (numports == 1) { - br_delif(br_name, vlan_ifname); - - vlan_rem(vlan_ifname); - - ifconfig_down(br_name); - br_delbr(br_name); - } - } - - if (vlan == first) { - hapd->conf->vlan = vlan->next; - } else { - prev->next = vlan->next; - } - os_free(vlan); - - break; - } - prev = vlan; - vlan = vlan->next; - } -} - - -static void -vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del, - struct hostapd_data *hapd) -{ - struct ifinfomsg *ifi; - int attrlen, nlmsg_len, rta_len; - struct rtattr *attr; - - if (len < sizeof(*ifi)) - return; - - ifi = NLMSG_DATA(h); - - nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); - - attrlen = h->nlmsg_len - nlmsg_len; - if (attrlen < 0) - return; - - attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - char ifname[IFNAMSIZ + 1]; - - if (attr->rta_type == IFLA_IFNAME) { - int n = attr->rta_len - rta_len; - if (n < 0) - break; - - os_memset(ifname, 0, sizeof(ifname)); - - if ((size_t) n > sizeof(ifname)) - n = sizeof(ifname); - os_memcpy(ifname, ((char *) attr) + rta_len, n); - - if (del) - vlan_dellink(ifname, hapd); - else - vlan_newlink(ifname, hapd); - } - - attr = RTA_NEXT(attr, attrlen); - } -} - - -static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - char buf[8192]; - int left; - struct sockaddr_nl from; - socklen_t fromlen; - struct nlmsghdr *h; - struct hostapd_data *hapd = eloop_ctx; - - fromlen = sizeof(from); - left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, - (struct sockaddr *) &from, &fromlen); - if (left < 0) { - if (errno != EINTR && errno != EAGAIN) - perror("recvfrom(netlink)"); - return; - } - - h = (struct nlmsghdr *) buf; - while (left >= (int) sizeof(*h)) { - int len, plen; - - len = h->nlmsg_len; - plen = len - sizeof(*h); - if (len > left || plen < 0) { - printf("Malformed netlink message: " - "len=%d left=%d plen=%d", len, left, plen); - break; - } - - switch (h->nlmsg_type) { - case RTM_NEWLINK: - vlan_read_ifnames(h, plen, 0, hapd); - break; - case RTM_DELLINK: - vlan_read_ifnames(h, plen, 1, hapd); - break; - } - - len = NLMSG_ALIGN(len); - left -= len; - h = (struct nlmsghdr *) ((char *) h + len); - } - - if (left > 0) { - printf("%d extra bytes in the end of netlink message", - left); - } -} - - -static struct full_dynamic_vlan * -full_dynamic_vlan_init(struct hostapd_data *hapd) -{ - struct sockaddr_nl local; - struct full_dynamic_vlan *priv; - - priv = os_zalloc(sizeof(*priv)); - if (priv == NULL) - return NULL; - - vlan_set_name_type(VLAN_NAME_TYPE_PLUS_VID_NO_PAD); - - priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (priv->s < 0) { - perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)"); - os_free(priv); - return NULL; - } - - os_memset(&local, 0, sizeof(local)); - local.nl_family = AF_NETLINK; - local.nl_groups = RTMGRP_LINK; - if (bind(priv->s, (struct sockaddr *) &local, sizeof(local)) < 0) { - perror("bind(netlink)"); - close(priv->s); - os_free(priv); - return NULL; - } - - if (eloop_register_read_sock(priv->s, vlan_event_receive, hapd, NULL)) - { - close(priv->s); - os_free(priv); - return NULL; - } - - return priv; -} - - -static void full_dynamic_vlan_deinit(struct full_dynamic_vlan *priv) -{ - if (priv == NULL) - return; - eloop_unregister_read_sock(priv->s); - close(priv->s); - os_free(priv); -} -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - - -int vlan_setup_encryption_dyn(struct hostapd_data *hapd, - struct hostapd_ssid *mssid, const char *dyn_vlan) -{ - int i; - - if (dyn_vlan == NULL) - return 0; - - /* Static WEP keys are set here; IEEE 802.1X and WPA uses their own - * functions for setting up dynamic broadcast keys. */ - for (i = 0; i < 4; i++) { - if (mssid->wep.key[i] && - hostapd_set_encryption(dyn_vlan, hapd, "WEP", NULL, - i, mssid->wep.key[i], - mssid->wep.len[i], - i == mssid->wep.idx)) { - printf("VLAN: Could not set WEP encryption for " - "dynamic VLAN.\n"); - return -1; - } - } - - return 0; -} - - -static int vlan_dynamic_add(struct hostapd_data *hapd, - struct hostapd_vlan *vlan) -{ - while (vlan) { - if (vlan->vlan_id != VLAN_ID_WILDCARD && - hostapd_if_add(hapd, HOSTAPD_IF_VLAN, vlan->ifname, NULL)) - { - if (errno != EEXIST) { - printf("Could not add VLAN iface: %s: %s\n", - vlan->ifname, strerror(errno)); - return -1; - } - } - - vlan = vlan->next; - } - - return 0; -} - - -static void vlan_dynamic_remove(struct hostapd_data *hapd, - struct hostapd_vlan *vlan) -{ - struct hostapd_vlan *next; - - while (vlan) { - next = vlan->next; - - if (vlan->vlan_id != VLAN_ID_WILDCARD && - hostapd_if_remove(hapd, HOSTAPD_IF_VLAN, vlan->ifname, - NULL)) { - printf("Could not remove VLAN iface: %s: %s\n", - vlan->ifname, strerror(errno)); - } -#ifdef CONFIG_FULL_DYNAMIC_VLAN - if (vlan->clean) - vlan_dellink(vlan->ifname, hapd); -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - - vlan = next; - } -} - - -int vlan_init(struct hostapd_data *hapd) -{ - if (vlan_dynamic_add(hapd, hapd->conf->vlan)) - return -1; - -#ifdef CONFIG_FULL_DYNAMIC_VLAN - hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd); -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - - return 0; -} - - -void vlan_deinit(struct hostapd_data *hapd) -{ - vlan_dynamic_remove(hapd, hapd->conf->vlan); - -#ifdef CONFIG_FULL_DYNAMIC_VLAN - full_dynamic_vlan_deinit(hapd->full_dynamic_vlan); -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ -} - - -int vlan_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss) -{ - vlan_dynamic_remove(hapd, oldbss->vlan); - if (vlan_dynamic_add(hapd, hapd->conf->vlan)) - return -1; - - return 0; -} - - -struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, - struct hostapd_vlan *vlan, - int vlan_id) -{ - struct hostapd_vlan *n; - char *ifname, *pos; - - if (vlan == NULL || vlan_id <= 0 || vlan_id > MAX_VLAN_ID || - vlan->vlan_id != VLAN_ID_WILDCARD) - return NULL; - - ifname = os_strdup(vlan->ifname); - if (ifname == NULL) - return NULL; - pos = os_strchr(ifname, '#'); - if (pos == NULL) { - os_free(ifname); - return NULL; - } - *pos++ = '\0'; - - n = os_zalloc(sizeof(*n)); - if (n == NULL) { - os_free(ifname); - return NULL; - } - - n->vlan_id = vlan_id; - n->dynamic_vlan = 1; - - os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname, vlan_id, - pos); - os_free(ifname); - - if (hostapd_if_add(hapd, HOSTAPD_IF_VLAN, n->ifname, NULL)) { - os_free(n); - return NULL; - } - - n->next = hapd->conf->vlan; - hapd->conf->vlan = n; - - return n; -} - - -int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id) -{ - struct hostapd_vlan *vlan; - - if (vlan_id <= 0 || vlan_id > MAX_VLAN_ID) - return 1; - - vlan = hapd->conf->vlan; - while (vlan) { - if (vlan->vlan_id == vlan_id && vlan->dynamic_vlan > 0) { - vlan->dynamic_vlan--; - break; - } - vlan = vlan->next; - } - - if (vlan == NULL) - return 1; - - if (vlan->dynamic_vlan == 0) - hostapd_if_remove(hapd, HOSTAPD_IF_VLAN, vlan->ifname, NULL); - - return 0; -} diff --git a/contrib/hostapd/hostapd/vlan_init.h b/contrib/hostapd/hostapd/vlan_init.h deleted file mode 100644 index cf55ac2462..0000000000 --- a/contrib/hostapd/hostapd/vlan_init.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * hostapd / VLAN initialization - * Copyright 2003, Instant802 Networks, Inc. - * Copyright 2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef VLAN_INIT_H -#define VLAN_INIT_H - -int vlan_init(struct hostapd_data *hapd); -void vlan_deinit(struct hostapd_data *hapd); -int vlan_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss); -struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, - struct hostapd_vlan *vlan, - int vlan_id); -int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id); -int vlan_setup_encryption_dyn(struct hostapd_data *hapd, - struct hostapd_ssid *mssid, - const char *dyn_vlan); - -#endif /* VLAN_INIT_H */ diff --git a/contrib/hostapd/hostapd/wme.c b/contrib/hostapd/hostapd/wme.c deleted file mode 100644 index f2bbbd9cc2..0000000000 --- a/contrib/hostapd/hostapd/wme.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * hostapd / WMM (Wi-Fi Multimedia) - * Copyright 2002-2003, Instant802 Networks, Inc. - * Copyright 2005-2006, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "hostapd.h" -#include "ieee802_11.h" -#include "wme.h" -#include "sta_info.h" -#include "driver.h" - - -/* TODO: maintain separate sequence and fragment numbers for each AC - * TODO: IGMP snooping to track which multicasts to forward - and use QOS-DATA - * if only WMM stations are receiving a certain group */ - - -static inline u8 wmm_aci_aifsn(int aifsn, int acm, int aci) -{ - u8 ret; - ret = (aifsn << WMM_AC_AIFNS_SHIFT) & WMM_AC_AIFSN_MASK; - if (acm) - ret |= WMM_AC_ACM; - ret |= (aci << WMM_AC_ACI_SHIFT) & WMM_AC_ACI_MASK; - return ret; -} - - -static inline u8 wmm_ecw(int ecwmin, int ecwmax) -{ - return ((ecwmin << WMM_AC_ECWMIN_SHIFT) & WMM_AC_ECWMIN_MASK) | - ((ecwmax << WMM_AC_ECWMAX_SHIFT) & WMM_AC_ECWMAX_MASK); -} - - -/* - * Add WMM Parameter Element to Beacon, Probe Response, and (Re)Association - * Response frames. - */ -u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid) -{ - u8 *pos = eid; - struct wmm_parameter_element *wmm = - (struct wmm_parameter_element *) (pos + 2); - int e; - - if (!hapd->conf->wmm_enabled) - return eid; - eid[0] = WLAN_EID_VENDOR_SPECIFIC; - wmm->oui[0] = 0x00; - wmm->oui[1] = 0x50; - wmm->oui[2] = 0xf2; - wmm->oui_type = WMM_OUI_TYPE; - wmm->oui_subtype = WMM_OUI_SUBTYPE_PARAMETER_ELEMENT; - wmm->version = WMM_VERSION; - wmm->qos_info = hapd->parameter_set_count & 0xf; - - /* fill in a parameter set record for each AC */ - for (e = 0; e < 4; e++) { - struct wmm_ac_parameter *ac = &wmm->ac[e]; - struct hostapd_wmm_ac_params *acp = - &hapd->iconf->wmm_ac_params[e]; - - ac->aci_aifsn = wmm_aci_aifsn(acp->aifs, - acp->admission_control_mandatory, - e); - ac->cw = wmm_ecw(acp->cwmin, acp->cwmax); - ac->txop_limit = host_to_le16(acp->txop_limit); - } - - pos = (u8 *) (wmm + 1); - eid[1] = pos - eid - 2; /* element length */ - - return pos; -} - - -/* This function is called when a station sends an association request with - * WMM info element. The function returns zero on success or non-zero on any - * error in WMM element. eid does not include Element ID and Length octets. */ -int hostapd_eid_wmm_valid(struct hostapd_data *hapd, u8 *eid, size_t len) -{ - struct wmm_information_element *wmm; - - wpa_hexdump(MSG_MSGDUMP, "WMM IE", eid, len); - - if (len < sizeof(struct wmm_information_element)) { - wpa_printf(MSG_DEBUG, "Too short WMM IE (len=%lu)", - (unsigned long) len); - return -1; - } - - wmm = (struct wmm_information_element *) eid; - wpa_printf(MSG_DEBUG, "Validating WMM IE: OUI %02x:%02x:%02x " - "OUI type %d OUI sub-type %d version %d QoS info 0x%x", - wmm->oui[0], wmm->oui[1], wmm->oui[2], wmm->oui_type, - wmm->oui_subtype, wmm->version, wmm->qos_info); - if (wmm->oui_subtype != WMM_OUI_SUBTYPE_INFORMATION_ELEMENT || - wmm->version != WMM_VERSION) { - wpa_printf(MSG_DEBUG, "Unsupported WMM IE Subtype/Version"); - return -1; - } - - return 0; -} - - -/* This function is called when a station sends an ACK frame for an AssocResp - * frame (status=success) and the matching AssocReq contained a WMM element. - */ -int hostapd_wmm_sta_config(struct hostapd_data *hapd, struct sta_info *sta) -{ - /* update kernel STA data for WMM related items (WLAN_STA_WPA flag) */ - if (sta->flags & WLAN_STA_WMM) - hostapd_sta_set_flags(hapd, sta->addr, sta->flags, - WLAN_STA_WMM, ~0); - else - hostapd_sta_set_flags(hapd, sta->addr, sta->flags, - 0, ~WLAN_STA_WMM); - - return 0; -} - - -static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr, - const struct wmm_tspec_element *tspec, - u8 action_code, u8 dialogue_token, u8 status_code) -{ - u8 buf[256]; - struct ieee80211_mgmt *m = (struct ieee80211_mgmt *) buf; - struct wmm_tspec_element *t = (struct wmm_tspec_element *) - m->u.action.u.wmm_action.variable; - int len; - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "action response - reason %d", status_code); - os_memset(buf, 0, sizeof(buf)); - m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_ACTION); - os_memcpy(m->da, addr, ETH_ALEN); - os_memcpy(m->sa, hapd->own_addr, ETH_ALEN); - os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN); - m->u.action.category = WLAN_ACTION_WMM; - m->u.action.u.wmm_action.action_code = action_code; - m->u.action.u.wmm_action.dialog_token = dialogue_token; - m->u.action.u.wmm_action.status_code = status_code; - os_memcpy(t, tspec, sizeof(struct wmm_tspec_element)); - len = ((u8 *) (t + 1)) - buf; - - if (hostapd_send_mgmt_frame(hapd, m, len, 0) < 0) - perror("wmm_send_action: send"); -} - - -static void wmm_addts_req(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, - struct wmm_tspec_element *tspec, size_t len) -{ - u8 *end = ((u8 *) mgmt) + len; - int medium_time, pps, duration; - int up, psb, dir, tid; - u16 val, surplus; - - if ((u8 *) (tspec + 1) > end) { - wpa_printf(MSG_DEBUG, "WMM: TSPEC overflow in ADDTS Request"); - return; - } - - wpa_printf(MSG_DEBUG, "WMM: ADDTS Request (Dialog Token %d) for TSPEC " - "from " MACSTR, - mgmt->u.action.u.wmm_action.dialog_token, - MAC2STR(mgmt->sa)); - - up = (tspec->ts_info[1] >> 3) & 0x07; - psb = (tspec->ts_info[1] >> 2) & 0x01; - dir = (tspec->ts_info[0] >> 5) & 0x03; - tid = (tspec->ts_info[0] >> 1) & 0x0f; - wpa_printf(MSG_DEBUG, "WMM: TS Info: UP=%d PSB=%d Direction=%d TID=%d", - up, psb, dir, tid); - val = le_to_host16(tspec->nominal_msdu_size); - wpa_printf(MSG_DEBUG, "WMM: Nominal MSDU Size: %d%s", - val & 0x7fff, val & 0x8000 ? " (fixed)" : ""); - wpa_printf(MSG_DEBUG, "WMM: Mean Data Rate: %u bps", - le_to_host32(tspec->mean_data_rate)); - wpa_printf(MSG_DEBUG, "WMM: Minimum PHY Rate: %u bps", - le_to_host32(tspec->minimum_phy_rate)); - val = le_to_host16(tspec->surplus_bandwidth_allowance); - wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance: %u.%04u", - val >> 13, 10000 * (val & 0x1fff) / 0x2000); - - val = le_to_host16(tspec->nominal_msdu_size); - if (val == 0) { - wpa_printf(MSG_DEBUG, "WMM: Invalid Nominal MSDU Size (0)"); - goto invalid; - } - /* pps = Ceiling((Mean Data Rate / 8) / Nominal MSDU Size) */ - pps = ((le_to_host32(tspec->mean_data_rate) / 8) + val - 1) / val; - wpa_printf(MSG_DEBUG, "WMM: Packets-per-second estimate for TSPEC: %d", - pps); - - if (le_to_host32(tspec->minimum_phy_rate) < 1000000) { - wpa_printf(MSG_DEBUG, "WMM: Too small Minimum PHY Rate"); - goto invalid; - } - - duration = (le_to_host16(tspec->nominal_msdu_size) & 0x7fff) * 8 / - (le_to_host32(tspec->minimum_phy_rate) / 1000000) + - 50 /* FIX: proper SIFS + ACK duration */; - - /* unsigned binary number with an implicit binary point after the - * leftmost 3 bits, i.e., 0x2000 = 1.0 */ - surplus = le_to_host16(tspec->surplus_bandwidth_allowance); - if (surplus <= 0x2000) { - wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance not " - "greater than unity"); - goto invalid; - } - - medium_time = surplus * pps * duration / 0x2000; - wpa_printf(MSG_DEBUG, "WMM: Estimated medium time: %u", medium_time); - - /* - * TODO: store list of granted (and still active) TSPECs and check - * whether there is available medium time for this request. For now, - * just refuse requests that would by themselves take very large - * portion of the available bandwidth. - */ - if (medium_time > 750000) { - wpa_printf(MSG_DEBUG, "WMM: Refuse TSPEC request for over " - "75%% of available bandwidth"); - wmm_send_action(hapd, mgmt->sa, tspec, - WMM_ACTION_CODE_ADDTS_RESP, - mgmt->u.action.u.wmm_action.dialog_token, - WMM_ADDTS_STATUS_REFUSED); - return; - } - - /* Convert to 32 microseconds per second unit */ - tspec->medium_time = host_to_le16(medium_time / 32); - - wmm_send_action(hapd, mgmt->sa, tspec, WMM_ACTION_CODE_ADDTS_RESP, - mgmt->u.action.u.wmm_action.dialog_token, - WMM_ADDTS_STATUS_ADMISSION_ACCEPTED); - return; - -invalid: - wmm_send_action(hapd, mgmt->sa, tspec, - WMM_ACTION_CODE_ADDTS_RESP, - mgmt->u.action.u.wmm_action.dialog_token, - WMM_ADDTS_STATUS_INVALID_PARAMETERS); -} - - -void hostapd_wmm_action(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, - size_t len) -{ - int action_code; - int left = len - IEEE80211_HDRLEN - 4; - u8 *pos = ((u8 *) mgmt) + IEEE80211_HDRLEN + 4; - struct ieee802_11_elems elems; - struct sta_info *sta = ap_get_sta(hapd, mgmt->sa); - - /* check that the request comes from a valid station */ - if (!sta || - (sta->flags & (WLAN_STA_ASSOC | WLAN_STA_WMM)) != - (WLAN_STA_ASSOC | WLAN_STA_WMM)) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "wmm action received is not from associated wmm" - " station"); - /* TODO: respond with action frame refused status code */ - return; - } - - /* extract the tspec info element */ - if (ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "hostapd_wmm_action - could not parse wmm " - "action"); - /* TODO: respond with action frame invalid parameters status - * code */ - return; - } - - if (!elems.wmm_tspec || - elems.wmm_tspec_len != (sizeof(struct wmm_tspec_element) - 2)) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "hostapd_wmm_action - missing or wrong length " - "tspec"); - /* TODO: respond with action frame invalid parameters status - * code */ - return; - } - - /* TODO: check the request is for an AC with ACM set, if not, refuse - * request */ - - action_code = mgmt->u.action.u.wmm_action.action_code; - switch (action_code) { - case WMM_ACTION_CODE_ADDTS_REQ: - wmm_addts_req(hapd, mgmt, (struct wmm_tspec_element *) - (elems.wmm_tspec - 2), len); - return; -#if 0 - /* TODO: needed for client implementation */ - case WMM_ACTION_CODE_ADDTS_RESP: - wmm_setup_request(hapd, mgmt, len); - return; - /* TODO: handle station teardown requests */ - case WMM_ACTION_CODE_DELTS: - wmm_teardown(hapd, mgmt, len); - return; -#endif - } - - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "hostapd_wmm_action - unknown action code %d", - action_code); -} diff --git a/contrib/hostapd/hostapd/wme.h b/contrib/hostapd/hostapd/wme.h deleted file mode 100644 index e06b5bcab3..0000000000 --- a/contrib/hostapd/hostapd/wme.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * hostapd / WMM (Wi-Fi Multimedia) - * Copyright 2002-2003, Instant802 Networks, Inc. - * Copyright 2005-2006, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WME_H -#define WME_H - -/* - * WMM Information Element (used in (Re)Association Request frames; may also be - * used in Beacon frames) - */ -struct wmm_information_element { - /* Element ID: 221 (0xdd); Length: 7 */ - /* required fields for WMM version 1 */ - u8 oui[3]; /* 00:50:f2 */ - u8 oui_type; /* 2 */ - u8 oui_subtype; /* 0 */ - u8 version; /* 1 for WMM version 1.0 */ - u8 qos_info; /* AP/STA specific QoS info */ - -} __attribute__ ((packed)); - -#define WMM_AC_AIFSN_MASK 0x0f -#define WMM_AC_AIFNS_SHIFT 0 -#define WMM_AC_ACM 0x10 -#define WMM_AC_ACI_MASK 0x60 -#define WMM_AC_ACI_SHIFT 5 - -#define WMM_AC_ECWMIN_MASK 0x0f -#define WMM_AC_ECWMIN_SHIFT 0 -#define WMM_AC_ECWMAX_MASK 0xf0 -#define WMM_AC_ECWMAX_SHIFT 4 - -struct wmm_ac_parameter { - u8 aci_aifsn; /* AIFSN, ACM, ACI */ - u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */ - le16 txop_limit; -} __attribute__ ((packed)); - -/* - * WMM Parameter Element (used in Beacon, Probe Response, and (Re)Association - * Response frmaes) - */ -struct wmm_parameter_element { - /* Element ID: 221 (0xdd); Length: 24 */ - /* required fields for WMM version 1 */ - u8 oui[3]; /* 00:50:f2 */ - u8 oui_type; /* 2 */ - u8 oui_subtype; /* 1 */ - u8 version; /* 1 for WMM version 1.0 */ - u8 qos_info; /* AP/STA specif QoS info */ - u8 reserved; /* 0 */ - struct wmm_ac_parameter ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */ - -} __attribute__ ((packed)); - -/* WMM TSPEC Element */ -struct wmm_tspec_element { - u8 eid; /* 221 = 0xdd */ - u8 length; /* 6 + 55 = 61 */ - u8 oui[3]; /* 00:50:f2 */ - u8 oui_type; /* 2 */ - u8 oui_subtype; /* 2 */ - u8 version; /* 1 */ - /* WMM TSPEC body (55 octets): */ - u8 ts_info[3]; - le16 nominal_msdu_size; - le16 maximum_msdu_size; - le32 minimum_service_interval; - le32 maximum_service_interval; - le32 inactivity_interval; - le32 suspension_interval; - le32 service_start_time; - le32 minimum_data_rate; - le32 mean_data_rate; - le32 peak_data_rate; - le32 maximum_burst_size; - le32 delay_bound; - le32 minimum_phy_rate; - le16 surplus_bandwidth_allowance; - le16 medium_time; -} __attribute__ ((packed)); - - -/* Access Categories / ACI to AC coding */ -enum { - WMM_AC_BE = 0 /* Best Effort */, - WMM_AC_BK = 1 /* Background */, - WMM_AC_VI = 2 /* Video */, - WMM_AC_VO = 3 /* Voice */ -}; - -struct ieee80211_mgmt; - -u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid); -int hostapd_eid_wmm_valid(struct hostapd_data *hapd, u8 *eid, size_t len); -int hostapd_wmm_sta_config(struct hostapd_data *hapd, struct sta_info *sta); -void hostapd_wmm_action(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, - size_t len); - -#endif /* WME_H */ diff --git a/contrib/hostapd/hostapd/wpa.c b/contrib/hostapd/hostapd/wpa.c deleted file mode 100644 index 19b11d59d3..0000000000 --- a/contrib/hostapd/hostapd/wpa.c +++ /dev/null @@ -1,2484 +0,0 @@ -/* - * hostapd - IEEE 802.11i-2004 / WPA Authenticator - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#ifndef CONFIG_NATIVE_WINDOWS - -#include "common.h" -#include "config.h" -#include "eapol_sm.h" -#include "wpa.h" -#include "sha1.h" -#include "sha256.h" -#include "rc4.h" -#include "aes_wrap.h" -#include "crypto.h" -#include "eloop.h" -#include "ieee802_11.h" -#include "pmksa_cache.h" -#include "state_machine.h" -#include "wpa_auth_i.h" -#include "wpa_auth_ie.h" - -#define STATE_MACHINE_DATA struct wpa_state_machine -#define STATE_MACHINE_DEBUG_PREFIX "WPA" -#define STATE_MACHINE_ADDR sm->addr - - -static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx); -static void wpa_sm_step(struct wpa_state_machine *sm); -static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len); -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); -static void wpa_request_new_ptk(struct wpa_state_machine *sm); -static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, - struct wpa_group *group); - -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 */ - -/* TODO: make these configurable */ -static const int dot11RSNAConfigPMKLifetime = 43200; -static const int dot11RSNAConfigPMKReauthThreshold = 70; -static const int dot11RSNAConfigSATimeout = 60; - - -static inline void wpa_auth_mic_failure_report( - struct wpa_authenticator *wpa_auth, const u8 *addr) -{ - if (wpa_auth->cb.mic_failure_report) - wpa_auth->cb.mic_failure_report(wpa_auth->cb.ctx, addr); -} - - -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); -} - - -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) - return -1; - 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 *prev_psk) -{ - if (wpa_auth->cb.get_psk == NULL) - return NULL; - return wpa_auth->cb.get_psk(wpa_auth->cb.ctx, addr, prev_psk); -} - - -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) - return -1; - return wpa_auth->cb.get_msk(wpa_auth->cb.ctx, addr, msk, len); -} - - -static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, - int vlan_id, - const char *alg, const u8 *addr, int idx, - u8 *key, size_t key_len) -{ - 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); -} - - -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) - return -1; - return wpa_auth->cb.get_seqnum(wpa_auth->cb.ctx, addr, idx, seq); -} - - -static inline int wpa_auth_get_seqnum_igtk(struct wpa_authenticator *wpa_auth, - const u8 *addr, int idx, u8 *seq) -{ - if (wpa_auth->cb.get_seqnum_igtk == NULL) - return -1; - return wpa_auth->cb.get_seqnum_igtk(wpa_auth->cb.ctx, addr, idx, seq); -} - - -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) - return -1; - return wpa_auth->cb.send_eapol(wpa_auth->cb.ctx, addr, data, data_len, - encrypt); -} - - -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) - return 0; - return wpa_auth->cb.for_each_sta(wpa_auth->cb.ctx, cb, cb_ctx); -} - - -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) - return 0; - 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) - return; - wpa_auth->cb.logger(wpa_auth->cb.ctx, addr, level, txt); -} - - -void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, - logger_level level, const char *fmt, ...) -{ - char *format; - int maxlen; - va_list ap; - - if (wpa_auth->cb.logger == NULL) - return; - - maxlen = os_strlen(fmt) + 100; - format = os_malloc(maxlen); - if (!format) - return; - - va_start(ap, fmt); - vsnprintf(format, maxlen, fmt, ap); - va_end(ap); - - wpa_auth_logger(wpa_auth, addr, level, format); - - os_free(format); -} - - -static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth, - const u8 *addr) -{ - if (wpa_auth->cb.disconnect == NULL) - return; - wpa_auth->cb.disconnect(wpa_auth->cb.ctx, addr, - WLAN_REASON_PREV_AUTH_NOT_VALID); -} - - -static int wpa_use_aes_cmac(struct wpa_state_machine *sm) -{ - 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 */ - return ret; -} - - -static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_authenticator *wpa_auth = eloop_ctx; - - if (os_get_random(wpa_auth->group->GMK, WPA_GMK_LEN)) { - wpa_printf(MSG_ERROR, "Failed to get random data for WPA " - "initialization."); - } else { - wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd"); - } - - if (wpa_auth->conf.wpa_gmk_rekey) { - eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0, - wpa_rekey_gmk, wpa_auth, NULL); - } -} - - -static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_authenticator *wpa_auth = eloop_ctx; - struct wpa_group *group; - - wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK"); - for (group = wpa_auth->group; group; group = group->next) { - group->GTKReKey = TRUE; - do { - group->changed = FALSE; - wpa_group_sm_step(wpa_auth, group); - } while (group->changed); - } - - if (wpa_auth->conf.wpa_group_rekey) { - eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, - 0, wpa_rekey_gtk, wpa_auth, NULL); - } -} - - -static void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_authenticator *wpa_auth = eloop_ctx; - struct wpa_state_machine *sm = timeout_ctx; - - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK"); - wpa_request_new_ptk(sm); - wpa_sm_step(sm); -} - - -static int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx) -{ - if (sm->pmksa == ctx) - sm->pmksa = NULL; - return 0; -} - - -static void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry, - void *ctx) -{ - struct wpa_authenticator *wpa_auth = ctx; - wpa_auth_for_each_sta(wpa_auth, wpa_auth_pmksa_clear_cb, entry); -} - - -static void wpa_group_set_key_len(struct wpa_group *group, int cipher) -{ - switch (cipher) { - case WPA_CIPHER_CCMP: - group->GTK_len = 16; - break; - case WPA_CIPHER_TKIP: - group->GTK_len = 32; - break; - case WPA_CIPHER_WEP104: - group->GTK_len = 13; - break; - case WPA_CIPHER_WEP40: - group->GTK_len = 5; - break; - } -} - - -static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth, - int vlan_id) -{ - struct wpa_group *group; - u8 buf[ETH_ALEN + 8 + sizeof(group)]; - u8 rkey[32]; - - group = os_zalloc(sizeof(struct wpa_group)); - if (group == NULL) - return NULL; - - group->GTKAuthenticator = TRUE; - group->vlan_id = vlan_id; - - wpa_group_set_key_len(group, wpa_auth->conf.wpa_group); - - /* Counter = PRF-256(Random number, "Init Counter", - * Local MAC Address || Time) - */ - os_memcpy(buf, wpa_auth->addr, ETH_ALEN); - wpa_get_ntp_timestamp(buf + ETH_ALEN); - os_memcpy(buf + ETH_ALEN + 8, &group, sizeof(group)); - if (os_get_random(rkey, sizeof(rkey)) || - os_get_random(group->GMK, WPA_GMK_LEN)) { - wpa_printf(MSG_ERROR, "Failed to get random data for WPA " - "initialization."); - os_free(group); - return NULL; - } - - sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf), - group->Counter, WPA_NONCE_LEN); - - group->GInit = TRUE; - wpa_group_sm_step(wpa_auth, group); - group->GInit = FALSE; - wpa_group_sm_step(wpa_auth, group); - - return group; -} - - -/** - * wpa_init - Initialize WPA authenticator - * @addr: Authenticator address - * @conf: Configuration for WPA authenticator - * @cb: Callback functions for WPA authenticator - * Returns: Pointer to WPA authenticator data or %NULL on failure - */ -struct wpa_authenticator * wpa_init(const u8 *addr, - struct wpa_auth_config *conf, - struct wpa_auth_callbacks *cb) -{ - struct wpa_authenticator *wpa_auth; - - wpa_auth = os_zalloc(sizeof(struct wpa_authenticator)); - if (wpa_auth == NULL) - 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)); - - if (wpa_auth_gen_wpa_ie(wpa_auth)) { - wpa_printf(MSG_ERROR, "Could not generate WPA IE."); - os_free(wpa_auth); - return NULL; - } - - wpa_auth->group = wpa_group_init(wpa_auth, 0); - if (wpa_auth->group == NULL) { - os_free(wpa_auth->wpa_ie); - os_free(wpa_auth); - return NULL; - } - - wpa_auth->pmksa = pmksa_cache_init(wpa_auth_pmksa_free_cb, wpa_auth); - if (wpa_auth->pmksa == NULL) { - wpa_printf(MSG_ERROR, "PMKSA cache initialization failed."); - os_free(wpa_auth->wpa_ie); - os_free(wpa_auth); - return NULL; - } - -#ifdef CONFIG_IEEE80211R - 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."); - os_free(wpa_auth->wpa_ie); - pmksa_cache_deinit(wpa_auth->pmksa); - os_free(wpa_auth); - return NULL; - } -#endif /* CONFIG_IEEE80211R */ - - if (wpa_auth->conf.wpa_gmk_rekey) { - eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0, - wpa_rekey_gmk, wpa_auth, NULL); - } - - if (wpa_auth->conf.wpa_group_rekey) { - eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0, - wpa_rekey_gtk, wpa_auth, NULL); - } - - return wpa_auth; -} - - -/** - * wpa_deinit - Deinitialize WPA authenticator - * @wpa_auth: Pointer to WPA authenticator data from wpa_init() - */ -void wpa_deinit(struct wpa_authenticator *wpa_auth) -{ - struct wpa_group *group, *prev; - - 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_deinit(wpa_auth->pmksa); - -#ifdef CONFIG_IEEE80211R - wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache); - wpa_auth->ft_pmk_cache = NULL; -#endif /* CONFIG_IEEE80211R */ - - os_free(wpa_auth->wpa_ie); - - group = wpa_auth->group; - while (group) { - prev = group; - group = group->next; - os_free(prev); - } - - os_free(wpa_auth); -} - - -/** - * wpa_reconfig - Update WPA authenticator configuration - * @wpa_auth: Pointer to WPA authenticator data from wpa_init() - * @conf: Configuration for WPA authenticator - */ -int wpa_reconfig(struct wpa_authenticator *wpa_auth, - struct wpa_auth_config *conf) -{ - struct wpa_group *group; - if (wpa_auth == NULL) - return 0; - - os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); - if (wpa_auth_gen_wpa_ie(wpa_auth)) { - wpa_printf(MSG_ERROR, "Could not generate WPA IE."); - return -1; - } - - /* - * Reinitialize GTK to make sure it is suitable for the new - * configuration. - */ - group = wpa_auth->group; - wpa_group_set_key_len(group, wpa_auth->conf.wpa_group); - group->GInit = TRUE; - wpa_group_sm_step(wpa_auth, group); - group->GInit = FALSE; - wpa_group_sm_step(wpa_auth, group); - - return 0; -} - - -struct wpa_state_machine * -wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr) -{ - struct wpa_state_machine *sm; - - sm = os_zalloc(sizeof(struct wpa_state_machine)); - if (sm == NULL) - return NULL; - os_memcpy(sm->addr, addr, ETH_ALEN); - - sm->wpa_auth = wpa_auth; - sm->group = wpa_auth->group; - - return sm; -} - - -void wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm) -{ - if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) - return; - -#ifdef CONFIG_IEEE80211R - if (sm->ft_completed) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, - "FT authentication already completed - do not " - "start 4-way handshake"); - return; - } -#endif /* CONFIG_IEEE80211R */ - - if (sm->started) { - os_memset(&sm->key_replay, 0, sizeof(sm->key_replay)); - sm->ReAuthenticationRequest = TRUE; - wpa_sm_step(sm); - return; - } - - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, - "start authentication"); - sm->started = 1; - - sm->Init = TRUE; - wpa_sm_step(sm); - sm->Init = FALSE; - sm->AuthenticationRequest = TRUE; - wpa_sm_step(sm); -} - - -void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm) -{ - /* WPA/RSN was not used - clear WPA state. This is needed if the STA - * reassociates back to the same AP while the previous entry for the - * STA has not yet been removed. */ - if (sm == NULL) - return; - - sm->wpa_key_mgmt = 0; -} - - -static void wpa_free_sta_sm(struct wpa_state_machine *sm) -{ - os_free(sm->last_rx_eapol_key); - os_free(sm->wpa_ie); - os_free(sm); -} - - -void wpa_auth_sta_deinit(struct wpa_state_machine *sm) -{ - if (sm == NULL) - return; - - if (sm->wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) { - 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); - } - - eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); - eloop_cancel_timeout(wpa_sm_call_step, sm, NULL); - eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); - 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(). */ - wpa_printf(MSG_DEBUG, "WPA: Registering pending STA state " - "machine deinit for " MACSTR, MAC2STR(sm->addr)); - sm->pending_deinit = 1; - } else - wpa_free_sta_sm(sm); -} - - -static void wpa_request_new_ptk(struct wpa_state_machine *sm) -{ - if (sm == NULL) - return; - - sm->PTKRequest = TRUE; - sm->PTK_valid = 0; -} - - -static int wpa_replay_counter_valid(struct wpa_state_machine *sm, - const u8 *replay_counter) -{ - int i; - for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { - if (!sm->key_replay[i].valid) - break; - if (os_memcmp(replay_counter, sm->key_replay[i].counter, - WPA_REPLAY_COUNTER_LEN) == 0) - return 1; - } - return 0; -} - - -void wpa_receive(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, - u8 *data, size_t data_len) -{ - struct ieee802_1x_hdr *hdr; - struct wpa_eapol_key *key; - u16 key_info, key_data_length; - enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST, - SMK_M1, SMK_M3, SMK_ERROR } msg; - char *msgtxt; - struct wpa_eapol_ie_parse kde; - - if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) - return; - - if (data_len < sizeof(*hdr) + sizeof(*key)) - return; - - hdr = (struct ieee802_1x_hdr *) data; - key = (struct wpa_eapol_key *) (hdr + 1); - key_info = WPA_GET_BE16(key->key_info); - key_data_length = WPA_GET_BE16(key->key_data_length); - if (key_data_length > data_len - sizeof(*hdr) - sizeof(*key)) { - wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - " - "key_data overflow (%d > %lu)", - key_data_length, - (unsigned long) (data_len - sizeof(*hdr) - - sizeof(*key))); - return; - } - - if (sm->wpa == WPA_VERSION_WPA2) { - if (key->type != EAPOL_KEY_TYPE_RSN) { - wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " - "unexpected type %d in RSN mode", - key->type); - return; - } - } else { - if (key->type != EAPOL_KEY_TYPE_WPA) { - wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " - "unexpected type %d in WPA mode", - key->type); - return; - } - } - - /* 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) { - 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) { - msg = PAIRWISE_4; - msgtxt = "4/4 Pairwise"; - } else { - msg = PAIRWISE_2; - 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) { - if (wpa_use_aes_cmac(sm) && - ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { - wpa_auth_logger(wpa_auth, sm->addr, - LOGGER_WARNING, - "advertised support for " - "AES-128-CMAC, but did not " - "use it"); - return; - } - - if (!wpa_use_aes_cmac(sm) && - ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - wpa_auth_logger(wpa_auth, sm->addr, - LOGGER_WARNING, - "did not use HMAC-SHA1-AES " - "with CCMP"); - return; - } - } - } - - if (key_info & WPA_KEY_INFO_REQUEST) { - if (sm->req_replay_counter_used && - os_memcmp(key->replay_counter, sm->req_replay_counter, - WPA_REPLAY_COUNTER_LEN) <= 0) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, - "received EAPOL-Key request with " - "replayed counter"); - return; - } - } - - if (!(key_info & WPA_KEY_INFO_REQUEST) && - !wpa_replay_counter_valid(sm, key->replay_counter)) { - int i; - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key %s with unexpected " - "replay counter", msgtxt); - for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { - if (!sm->key_replay[i].valid) - break; - wpa_hexdump(MSG_DEBUG, "pending replay counter", - sm->key_replay[i].counter, - WPA_REPLAY_COUNTER_LEN); - } - wpa_hexdump(MSG_DEBUG, "received replay counter", - key->replay_counter, WPA_REPLAY_COUNTER_LEN); - return; - } - - switch (msg) { - case PAIRWISE_2: - if (sm->wpa_ptk_state != WPA_PTK_PTKSTART && - sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING) { - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key msg 2/4 in " - "invalid state (%d) - dropped", - sm->wpa_ptk_state); - return; - } - if (sm->wpa_ie == NULL || - sm->wpa_ie_len != key_data_length || - os_memcmp(sm->wpa_ie, key + 1, key_data_length) != 0) { - 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", - (u8 *) (key + 1), key_data_length); - /* MLME-DEAUTHENTICATE.request */ - wpa_sta_disconnect(wpa_auth, sm->addr); - return; - } - break; - case PAIRWISE_4: - if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING || - !sm->PTK_valid) { - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key msg 4/4 in " - "invalid state (%d) - dropped", - sm->wpa_ptk_state); - return; - } - break; - case GROUP_2: - if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING - || !sm->PTK_valid) { - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key msg 2/2 in " - "invalid state (%d) - dropped", - sm->wpa_ptk_group_state); - 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; - } - - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, - "received EAPOL-Key frame (%s)", msgtxt); - - if (key_info & WPA_KEY_INFO_ACK) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received invalid EAPOL-Key: Key Ack set"); - return; - } - - if (!(key_info & WPA_KEY_INFO_MIC)) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received invalid EAPOL-Key: Key MIC not set"); - return; - } - - sm->MICVerified = FALSE; - if (sm->PTK_valid) { - if (wpa_verify_key_mic(&sm->PTK, data, data_len)) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key with invalid MIC"); - return; - } - sm->MICVerified = TRUE; - eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); - } - - if (key_info & WPA_KEY_INFO_REQUEST) { - if (sm->MICVerified) { - sm->req_replay_counter_used = 1; - os_memcpy(sm->req_replay_counter, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - } else { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key request with " - "invalid MIC"); - return; - } - - /* - * TODO: should decrypt key data field if encryption was used; - * 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); -#endif /* CONFIG_PEERKEY */ - return; - } else if (key_info & WPA_KEY_INFO_ERROR) { - /* Supplicant reported a Michael MIC error */ - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key Error Request " - "(STA detected Michael MIC failure)"); - wpa_auth_mic_failure_report(wpa_auth, sm->addr); - sm->dot11RSNAStatsTKIPRemoteMICFailures++; - wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++; - /* Error report is not a request for a new key - * handshake, but since Authenticator may do it, let's - * change the keys now anyway. */ - wpa_request_new_ptk(sm); - } else if (key_info & WPA_KEY_INFO_KEY_TYPE) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "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); -#endif /* CONFIG_PEERKEY */ - } else if (key_data_length > 0 && - wpa_parse_kde_ies((const u8 *) (key + 1), - key_data_length, &kde) == 0 && - kde.mac_addr) { - } else { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key Request for GTK " - "rekeying"); - /* FIX: why was this triggering PTK rekeying for the - * STA that requested Group Key rekeying?? */ - /* wpa_request_new_ptk(sta->wpa_sm); */ - eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); - wpa_rekey_gtk(wpa_auth, NULL); - } - } else { - /* Do not allow the same key replay counter to be reused. This - * does also invalidate all other pending replay counters if - * retransmissions were used, i.e., we will only process one of - * the pending replies and ignore rest if more than one is - * received. */ - sm->key_replay[0].valid = FALSE; - } - -#ifdef CONFIG_PEERKEY - if (msg == SMK_M3) { - wpa_smk_m3(wpa_auth, sm, key); - return; - } -#endif /* CONFIG_PEERKEY */ - - os_free(sm->last_rx_eapol_key); - sm->last_rx_eapol_key = os_malloc(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->EAPOLKeyReceived = TRUE; - sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); - sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST); - os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN); - wpa_sm_step(sm); -} - - -static void wpa_gmk_to_gtk(const u8 *gmk, const u8 *addr, const u8 *gnonce, - u8 *gtk, size_t gtk_len) -{ - u8 data[ETH_ALEN + WPA_NONCE_LEN]; - - /* GTK = PRF-X(GMK, "Group key expansion", AA || GNonce) */ - os_memcpy(data, addr, ETH_ALEN); - os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN); - -#ifdef CONFIG_IEEE80211W - sha256_prf(gmk, WPA_GMK_LEN, "Group key expansion", - data, sizeof(data), gtk, gtk_len); -#else /* CONFIG_IEEE80211W */ - sha1_prf(gmk, WPA_GMK_LEN, "Group key expansion", - data, sizeof(data), gtk, gtk_len); -#endif /* CONFIG_IEEE80211W */ - - wpa_hexdump_key(MSG_DEBUG, "GMK", gmk, WPA_GMK_LEN); - wpa_hexdump_key(MSG_DEBUG, "GTK", gtk, gtk_len); -} - - -static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_authenticator *wpa_auth = eloop_ctx; - struct wpa_state_machine *sm = timeout_ctx; - - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout"); - sm->TimeoutEvt = TRUE; - wpa_sm_step(sm); -} - - -void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, int key_info, - const u8 *key_rsc, const u8 *nonce, - const u8 *kde, size_t kde_len, - int keyidx, int encr, int force_version) -{ - struct ieee802_1x_hdr *hdr; - struct wpa_eapol_key *key; - size_t len; - int alg; - int key_data_len, pad_len = 0; - u8 *buf, *pos; - int version, pairwise; - int i; - - len = sizeof(struct ieee802_1x_hdr) + sizeof(struct wpa_eapol_key); - - if (force_version) - version = force_version; - else if (wpa_use_aes_cmac(sm)) - version = WPA_KEY_INFO_TYPE_AES_128_CMAC; - else if (sm->pairwise == WPA_CIPHER_CCMP) - version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; - else - version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; - - pairwise = key_info & WPA_KEY_INFO_KEY_TYPE; - - wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(version=%d secure=%d mic=%d " - "ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d " - "encr=%d)", - version, - (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0, - (key_info & WPA_KEY_INFO_MIC) ? 1 : 0, - (key_info & WPA_KEY_INFO_ACK) ? 1 : 0, - (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0, - pairwise, (unsigned long) kde_len, keyidx, encr); - - key_data_len = kde_len; - - if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || - version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) { - pad_len = key_data_len % 8; - if (pad_len) - pad_len = 8 - pad_len; - key_data_len += pad_len + 8; - } - - len += key_data_len; - - hdr = os_zalloc(len); - if (hdr == NULL) - return; - hdr->version = wpa_auth->conf.eapol_version; - hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; - hdr->length = host_to_be16(len - sizeof(*hdr)); - key = (struct wpa_eapol_key *) (hdr + 1); - - key->type = sm->wpa == WPA_VERSION_WPA2 ? - EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; - key_info |= version; - if (encr && sm->wpa == WPA_VERSION_WPA2) - key_info |= WPA_KEY_INFO_ENCR_KEY_DATA; - if (sm->wpa != WPA_VERSION_WPA2) - key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT; - WPA_PUT_BE16(key->key_info, key_info); - - alg = pairwise ? sm->pairwise : wpa_auth->conf.wpa_group; - switch (alg) { - case WPA_CIPHER_CCMP: - WPA_PUT_BE16(key->key_length, 16); - break; - case WPA_CIPHER_TKIP: - WPA_PUT_BE16(key->key_length, 32); - break; - case WPA_CIPHER_WEP40: - WPA_PUT_BE16(key->key_length, 5); - break; - case WPA_CIPHER_WEP104: - WPA_PUT_BE16(key->key_length, 13); - break; - } - if (key_info & WPA_KEY_INFO_SMK_MESSAGE) - WPA_PUT_BE16(key->key_length, 0); - - /* 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, - sm->key_replay[i - 1].counter, - WPA_REPLAY_COUNTER_LEN); - } - inc_byte_array(sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN); - os_memcpy(key->replay_counter, sm->key_replay[0].counter, - WPA_REPLAY_COUNTER_LEN); - sm->key_replay[0].valid = TRUE; - - if (nonce) - os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN); - - if (key_rsc) - os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN); - - if (kde && !encr) { - os_memcpy(key + 1, kde, kde_len); - WPA_PUT_BE16(key->key_data_length, kde_len); - } else if (encr && kde) { - buf = os_zalloc(key_data_len); - if (buf == NULL) { - os_free(hdr); - return; - } - pos = buf; - os_memcpy(pos, kde, kde_len); - pos += kde_len; - - if (pad_len) - *pos++ = 0xdd; - - wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data", - buf, key_data_len); - if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || - version == WPA_KEY_INFO_TYPE_AES_128_CMAC) { - if (aes_wrap(sm->PTK.kek, (key_data_len - 8) / 8, buf, - (u8 *) (key + 1))) { - os_free(hdr); - os_free(buf); - return; - } - WPA_PUT_BE16(key->key_data_length, key_data_len); - } else { - u8 ek[32]; - os_memcpy(key->key_iv, - sm->group->Counter + WPA_NONCE_LEN - 16, 16); - inc_byte_array(sm->group->Counter, WPA_NONCE_LEN); - os_memcpy(ek, key->key_iv, 16); - os_memcpy(ek + 16, sm->PTK.kek, 16); - os_memcpy(key + 1, buf, key_data_len); - rc4_skip(ek, 32, 256, (u8 *) (key + 1), key_data_len); - WPA_PUT_BE16(key->key_data_length, key_data_len); - } - os_free(buf); - } - - if (key_info & WPA_KEY_INFO_MIC) { - if (!sm->PTK_valid) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, - "PTK not valid when sending EAPOL-Key " - "frame"); - os_free(hdr); - return; - } - wpa_eapol_key_mic(sm->PTK.kck, version, (u8 *) hdr, len, - key->key_mic); - } - - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, - 1); - wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len, - sm->pairwise_set); - os_free(hdr); -} - - -static void wpa_send_eapol(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, int key_info, - const u8 *key_rsc, const u8 *nonce, - const u8 *kde, size_t kde_len, - int keyidx, int encr) -{ - int timeout_ms; - int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE; - int ctr; - - if (sm == NULL) - return; - - __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len, - keyidx, encr, 0); - - ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr; - if (ctr == 1) - timeout_ms = eapol_key_timeout_first; - else - timeout_ms = eapol_key_timeout_subseq; - eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000, - wpa_send_eapol_timeout, wpa_auth, sm); -} - - -static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len) -{ - struct ieee802_1x_hdr *hdr; - struct wpa_eapol_key *key; - u16 key_info; - int ret = 0; - u8 mic[16]; - - if (data_len < sizeof(*hdr) + sizeof(*key)) - return -1; - - hdr = (struct ieee802_1x_hdr *) data; - key = (struct wpa_eapol_key *) (hdr + 1); - key_info = WPA_GET_BE16(key->key_info); - os_memcpy(mic, key->key_mic, 16); - os_memset(key->key_mic, 0, 16); - if (wpa_eapol_key_mic(PTK->kck, key_info & WPA_KEY_INFO_TYPE_MASK, - data, data_len, key->key_mic) || - os_memcmp(mic, key->key_mic, 16) != 0) - ret = -1; - os_memcpy(key->key_mic, mic, 16); - return ret; -} - - -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, "none", sm->addr, 0, (u8 *) "", 0); - sm->pairwise_set = FALSE; - eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); -} - - -void wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event) -{ - int remove_ptk = 1; - - if (sm == NULL) - return; - - wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "event %d notification", event); - - switch (event) { - case WPA_AUTH: - case WPA_ASSOC: - break; - case WPA_DEAUTH: - case WPA_DISASSOC: - sm->DeauthenticationRequest = TRUE; - break; - case WPA_REAUTH: - case WPA_REAUTH_EAPOL: - if (sm->GUpdateStationKeys) { - /* - * Reauthentication cancels the pending group key - * update for this STA. - */ - sm->group->GKeyDoneStations--; - sm->GUpdateStationKeys = FALSE; - sm->PtkGroupInit = TRUE; - } - sm->ReAuthenticationRequest = TRUE; - break; - case WPA_ASSOC_FT: -#ifdef CONFIG_IEEE80211R - /* Using FT protocol, not WPA auth state machine */ - sm->ft_completed = 1; - return; -#else /* CONFIG_IEEE80211R */ - break; -#endif /* CONFIG_IEEE80211R */ - } - -#ifdef CONFIG_IEEE80211R - sm->ft_completed = 0; -#endif /* CONFIG_IEEE80211R */ - -#ifdef CONFIG_IEEE80211W - if (sm->mgmt_frame_prot && event == WPA_AUTH) - remove_ptk = 0; -#endif /* CONFIG_IEEE80211W */ - - if (remove_ptk) { - sm->PTK_valid = FALSE; - os_memset(&sm->PTK, 0, sizeof(sm->PTK)); - - if (event != WPA_REAUTH_EAPOL) - wpa_remove_ptk(sm); - } - - wpa_sm_step(sm); -} - - -static const char * wpa_alg_txt(int alg) -{ - switch (alg) { - case WPA_CIPHER_CCMP: - return "CCMP"; - case WPA_CIPHER_TKIP: - return "TKIP"; - case WPA_CIPHER_WEP104: - case WPA_CIPHER_WEP40: - return "WEP"; - default: - return ""; - } -} - - -SM_STATE(WPA_PTK, INITIALIZE) -{ - SM_ENTRY_MA(WPA_PTK, INITIALIZE, wpa_ptk); - if (sm->Init) { - /* Init flag is not cleared here, so avoid busy - * loop by claiming nothing changed. */ - sm->changed = FALSE; - } - - sm->keycount = 0; - if (sm->GUpdateStationKeys) - sm->group->GKeyDoneStations--; - sm->GUpdateStationKeys = FALSE; - if (sm->wpa == WPA_VERSION_WPA) - sm->PInitAKeys = FALSE; - if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and - * Local AA > Remote AA)) */) { - sm->Pair = TRUE; - } - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0); - 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)) { - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, - WPA_EAPOL_authorized, 0); - } -} - - -SM_STATE(WPA_PTK, DISCONNECT) -{ - SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk); - sm->Disconnect = FALSE; - wpa_sta_disconnect(sm->wpa_auth, sm->addr); -} - - -SM_STATE(WPA_PTK, DISCONNECTED) -{ - SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk); - sm->DeauthenticationRequest = FALSE; -} - - -SM_STATE(WPA_PTK, AUTHENTICATION) -{ - SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk); - os_memset(&sm->PTK, 0, sizeof(sm->PTK)); - sm->PTK_valid = FALSE; - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto, - 1); - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1); - sm->AuthenticationRequest = FALSE; -} - - -SM_STATE(WPA_PTK, AUTHENTICATION2) -{ - SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk); - os_memcpy(sm->ANonce, sm->group->Counter, WPA_NONCE_LEN); - inc_byte_array(sm->group->Counter, WPA_NONCE_LEN); - sm->ReAuthenticationRequest = FALSE; - /* IEEE 802.11i does not clear TimeoutCtr here, but this is more - * logical place than INITIALIZE since AUTHENTICATION2 can be - * re-entered on ReAuthenticationRequest without going through - * INITIALIZE. */ - sm->TimeoutCtr = 0; -} - - -SM_STATE(WPA_PTK, INITPMK) -{ - u8 msk[2 * PMK_LEN]; - size_t len = 2 * PMK_LEN; - - SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk); -#ifdef CONFIG_IEEE80211R - sm->xxkey_len = 0; -#endif /* CONFIG_IEEE80211R */ - if (sm->pmksa) { - wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache"); - os_memcpy(sm->PMK, sm->pmksa->pmk, PMK_LEN); - } else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) { - wpa_printf(MSG_DEBUG, "WPA: PMK from EAPOL state machine " - "(len=%lu)", (unsigned long) len); - os_memcpy(sm->PMK, msk, PMK_LEN); -#ifdef CONFIG_IEEE80211R - if (len >= 2 * PMK_LEN) { - os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN); - sm->xxkey_len = PMK_LEN; - } -#endif /* CONFIG_IEEE80211R */ - } else { - wpa_printf(MSG_DEBUG, "WPA: Could not get PMK"); - } - - sm->req_replay_counter_used = 0; - /* IEEE 802.11i does not set keyRun to FALSE, but not doing this - * will break reauthentication since EAPOL state machines may not be - * get into AUTHENTICATING state that clears keyRun before WPA state - * machine enters AUTHENTICATION2 state and goes immediately to INITPMK - * state and takes PMK from the previously used AAA Key. This will - * eventually fail in 4-Way Handshake because Supplicant uses PMK - * derived from the new AAA Key. Setting keyRun = FALSE here seems to - * be good workaround for this issue. */ - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, 0); -} - - -SM_STATE(WPA_PTK, INITPSK) -{ - const u8 *psk; - SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk); - psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL); - if (psk) { - os_memcpy(sm->PMK, psk, PMK_LEN); -#ifdef CONFIG_IEEE80211R - os_memcpy(sm->xxkey, psk, PMK_LEN); - sm->xxkey_len = PMK_LEN; -#endif /* CONFIG_IEEE80211R */ - } - sm->req_replay_counter_used = 0; -} - - -SM_STATE(WPA_PTK, PTKSTART) -{ - u8 buf[2 + RSN_SELECTOR_LEN + PMKID_LEN], *pmkid = NULL; - size_t pmkid_len = 0; - - SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk); - sm->PTKRequest = FALSE; - sm->TimeoutEvt = FALSE; - - sm->TimeoutCtr++; - if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) { - /* No point in sending the EAPOL-Key - we will disconnect - * immediately following this. */ - return; - } - - 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. - */ - if (sm->wpa == WPA_VERSION_WPA2 && - wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt)) { - pmkid = buf; - pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; - pmkid[0] = WLAN_EID_VENDOR_SPECIFIC; - pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN; - RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID); - if (sm->pmksa) - os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN], - sm->pmksa->pmkid, PMKID_LEN); - else { - /* - * Calculate PMKID since no PMKSA cache entry was - * available with pre-calculated PMKID. - */ - rsn_pmkid(sm->PMK, PMK_LEN, sm->wpa_auth->addr, - sm->addr, &pmkid[2 + RSN_SELECTOR_LEN], - wpa_key_mgmt_sha256(sm->wpa_key_mgmt)); - } - } - wpa_send_eapol(sm->wpa_auth, sm, - WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL, - sm->ANonce, pmkid, pmkid_len, 0, 0); -} - - -static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *pmk, - struct wpa_ptk *ptk) -{ - size_t ptk_len = sm->pairwise == WPA_CIPHER_CCMP ? 48 : 64; -#ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) - return wpa_auth_derive_ptk_ft(sm, pmk, ptk, ptk_len); -#endif /* CONFIG_IEEE80211R */ - - wpa_pmk_to_ptk(pmk, PMK_LEN, "Pairwise key expansion", - sm->wpa_auth->addr, sm->addr, sm->ANonce, sm->SNonce, - (u8 *) ptk, ptk_len, - wpa_key_mgmt_sha256(sm->wpa_key_mgmt)); - - return 0; -} - - -SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) -{ - struct wpa_ptk PTK; - int ok = 0; - const u8 *pmk = NULL; - - SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk); - sm->EAPOLKeyReceived = FALSE; - - /* 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)) { - pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, pmk); - if (pmk == NULL) - break; - } else - pmk = sm->PMK; - - wpa_derive_ptk(sm, pmk, &PTK); - - if (wpa_verify_key_mic(&PTK, sm->last_rx_eapol_key, - sm->last_rx_eapol_key_len) == 0) { - ok = 1; - break; - } - - if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) - break; - } - - if (!ok) { - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "invalid MIC in msg 2/4 of 4-Way Handshake"); - return; - } - - eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); - - if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { - /* PSK may have changed from the previous choice, so update - * state machine data based on whatever PSK was selected here. - */ - os_memcpy(sm->PMK, pmk, PMK_LEN); - } - - sm->MICVerified = TRUE; - - os_memcpy(&sm->PTK, &PTK, sizeof(PTK)); - sm->PTK_valid = TRUE; -} - - -SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2) -{ - SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING2, wpa_ptk); - sm->TimeoutCtr = 0; -} - - -#ifdef CONFIG_IEEE80211W - -static int ieee80211w_kde_len(struct wpa_state_machine *sm) -{ - if (sm->mgmt_frame_prot) { - return 2 + RSN_SELECTOR_LEN + sizeof(struct wpa_igtk_kde); - } - - return 0; -} - - -static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) -{ - struct wpa_igtk_kde igtk; - struct wpa_group *gsm = sm->group; - - if (!sm->mgmt_frame_prot) - return pos; - - igtk.keyid[0] = gsm->GN_igtk; - igtk.keyid[1] = 0; - if (wpa_auth_get_seqnum_igtk(sm->wpa_auth, NULL, gsm->GN_igtk, igtk.pn) - < 0) - os_memset(igtk.pn, 0, sizeof(igtk.pn)); - os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN); - pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK, - (const u8 *) &igtk, sizeof(igtk), NULL, 0); - - return pos; -} - -#else /* CONFIG_IEEE80211W */ - -static int ieee80211w_kde_len(struct wpa_state_machine *sm) -{ - return 0; -} - - -static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) -{ - return pos; -} - -#endif /* CONFIG_IEEE80211W */ - - -SM_STATE(WPA_PTK, PTKINITNEGOTIATING) -{ - u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos; - size_t gtk_len, kde_len; - struct wpa_group *gsm = sm->group; - u8 *wpa_ie; - int wpa_ie_len, secure, keyidx, encr = 0; - - SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); - sm->TimeoutEvt = FALSE; - - sm->TimeoutCtr++; - if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) { - /* No point in sending the EAPOL-Key - we will disconnect - * immediately following this. */ - return; - } - - /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, GTK[GN]) - */ - os_memset(rsc, 0, WPA_KEY_RSC_LEN); - wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); - 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 */ - 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"); - 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; - } - - kde_len = wpa_ie_len + ieee80211w_kde_len(sm); - if (gtk) - kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; - kde = os_malloc(kde_len); - if (kde == NULL) - return; - - pos = kde; - os_memcpy(pos, wpa_ie, wpa_ie_len); - pos += wpa_ie_len; - 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); - } - pos = ieee80211w_kde_add(sm, pos); - - wpa_send_eapol(sm->wpa_auth, sm, - (secure ? WPA_KEY_INFO_SECURE : 0) | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | - WPA_KEY_INFO_KEY_TYPE, - _rsc, sm->ANonce, kde, pos - kde, keyidx, encr); - os_free(kde); -} - - -SM_STATE(WPA_PTK, PTKINITDONE) -{ - SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk); - sm->EAPOLKeyReceived = FALSE; - if (sm->Pair) { - char *alg; - int klen; - if (sm->pairwise == WPA_CIPHER_TKIP) { - alg = "TKIP"; - klen = 32; - } else { - alg = "CCMP"; - klen = 16; - } - if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, - sm->PTK.tk1, klen)) { - wpa_sta_disconnect(sm->wpa_auth, sm->addr); - 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); - } - - if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, - WPA_EAPOL_authorized, 1); - } - } - - if (0 /* IBSS == TRUE */) { - sm->keycount++; - if (sm->keycount == 2) { - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, - WPA_EAPOL_portValid, 1); - } - } else { - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, - 1); - } - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable, 0); - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, 1); - if (sm->wpa == WPA_VERSION_WPA) - sm->PInitAKeys = TRUE; - else - sm->has_GTK = TRUE; - wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, - "pairwise key handshake completed (%s)", - sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); - -#ifdef CONFIG_IEEE80211R - wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr); -#endif /* CONFIG_IEEE80211R */ -} - - -SM_STEP(WPA_PTK) -{ - struct wpa_authenticator *wpa_auth = sm->wpa_auth; - - if (sm->Init) - SM_ENTER(WPA_PTK, INITIALIZE); - else if (sm->Disconnect - /* || FIX: dot11RSNAConfigSALifetime timeout */) - SM_ENTER(WPA_PTK, DISCONNECT); - else if (sm->DeauthenticationRequest) - SM_ENTER(WPA_PTK, DISCONNECTED); - else if (sm->AuthenticationRequest) - SM_ENTER(WPA_PTK, AUTHENTICATION); - else if (sm->ReAuthenticationRequest) - SM_ENTER(WPA_PTK, AUTHENTICATION2); - else if (sm->PTKRequest) - SM_ENTER(WPA_PTK, PTKSTART); - else switch (sm->wpa_ptk_state) { - case WPA_PTK_INITIALIZE: - break; - case WPA_PTK_DISCONNECT: - SM_ENTER(WPA_PTK, DISCONNECTED); - break; - case WPA_PTK_DISCONNECTED: - SM_ENTER(WPA_PTK, INITIALIZE); - break; - case WPA_PTK_AUTHENTICATION: - SM_ENTER(WPA_PTK, AUTHENTICATION2); - break; - case WPA_PTK_AUTHENTICATION2: - if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) && - 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) - /* FIX: && 802.1X::keyRun */) - SM_ENTER(WPA_PTK, INITPSK); - break; - case WPA_PTK_INITPMK: - if (wpa_auth_get_eapol(sm->wpa_auth, sm->addr, - WPA_EAPOL_keyAvailable) > 0) - SM_ENTER(WPA_PTK, PTKSTART); - else { - wpa_auth->dot11RSNA4WayHandshakeFailures++; - SM_ENTER(WPA_PTK, DISCONNECT); - } - break; - case WPA_PTK_INITPSK: - if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL)) - SM_ENTER(WPA_PTK, PTKSTART); - else { - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, - "no PSK configured for the STA"); - wpa_auth->dot11RSNA4WayHandshakeFailures++; - SM_ENTER(WPA_PTK, DISCONNECT); - } - break; - case WPA_PTK_PTKSTART: - if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && - sm->EAPOLKeyPairwise) - SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); - else if (sm->TimeoutCtr > - (int) dot11RSNAConfigPairwiseUpdateCount) { - wpa_auth->dot11RSNA4WayHandshakeFailures++; - SM_ENTER(WPA_PTK, DISCONNECT); - } else if (sm->TimeoutEvt) - SM_ENTER(WPA_PTK, PTKSTART); - break; - case WPA_PTK_PTKCALCNEGOTIATING: - if (sm->MICVerified) - SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING2); - else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && - sm->EAPOLKeyPairwise) - SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); - else if (sm->TimeoutEvt) - SM_ENTER(WPA_PTK, PTKSTART); - break; - case WPA_PTK_PTKCALCNEGOTIATING2: - SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); - break; - case WPA_PTK_PTKINITNEGOTIATING: - if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && - sm->EAPOLKeyPairwise && sm->MICVerified) - SM_ENTER(WPA_PTK, PTKINITDONE); - else if (sm->TimeoutCtr > - (int) dot11RSNAConfigPairwiseUpdateCount) { - wpa_auth->dot11RSNA4WayHandshakeFailures++; - SM_ENTER(WPA_PTK, DISCONNECT); - } else if (sm->TimeoutEvt) - SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); - break; - case WPA_PTK_PTKINITDONE: - break; - } -} - - -SM_STATE(WPA_PTK_GROUP, IDLE) -{ - SM_ENTRY_MA(WPA_PTK_GROUP, IDLE, wpa_ptk_group); - if (sm->Init) { - /* Init flag is not cleared here, so avoid busy - * loop by claiming nothing changed. */ - sm->changed = FALSE; - } - sm->GTimeoutCtr = 0; -} - - -SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) -{ - u8 rsc[WPA_KEY_RSC_LEN]; - struct wpa_group *gsm = sm->group; - u8 *kde, *pos, hdr[2]; - size_t kde_len; - - SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group); - - sm->GTimeoutCtr++; - if (sm->GTimeoutCtr > (int) dot11RSNAConfigGroupUpdateCount) { - /* No point in sending the EAPOL-Key - we will disconnect - * immediately following this. */ - return; - } - - if (sm->wpa == WPA_VERSION_WPA) - sm->PInitAKeys = FALSE; - sm->TimeoutEvt = FALSE; - /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */ - os_memset(rsc, 0, WPA_KEY_RSC_LEN); - if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE) - wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "sending 1/2 msg of Group Key Handshake"); - - if (sm->wpa == WPA_VERSION_WPA2) { - kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len + - ieee80211w_kde_len(sm); - kde = os_malloc(kde_len); - if (kde == NULL) - return; - - pos = kde; - hdr[0] = gsm->GN & 0x03; - hdr[1] = 0; - pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, - gsm->GTK[gsm->GN - 1], gsm->GTK_len); - pos = ieee80211w_kde_add(sm, pos); - } else { - kde = gsm->GTK[gsm->GN - 1]; - pos = kde + gsm->GTK_len; - } - - wpa_send_eapol(sm->wpa_auth, sm, - WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_ACK | - (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0), - rsc, gsm->GNonce, kde, pos - kde, gsm->GN, 1); - if (sm->wpa == WPA_VERSION_WPA2) - os_free(kde); -} - - -SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) -{ - SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group); - sm->EAPOLKeyReceived = FALSE; - if (sm->GUpdateStationKeys) - sm->group->GKeyDoneStations--; - sm->GUpdateStationKeys = FALSE; - sm->GTimeoutCtr = 0; - /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */ - wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, - "group key handshake completed (%s)", - sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); - sm->has_GTK = TRUE; -} - - -SM_STATE(WPA_PTK_GROUP, KEYERROR) -{ - SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group); - if (sm->GUpdateStationKeys) - sm->group->GKeyDoneStations--; - sm->GUpdateStationKeys = FALSE; - sm->Disconnect = TRUE; -} - - -SM_STEP(WPA_PTK_GROUP) -{ - if (sm->Init || sm->PtkGroupInit) { - SM_ENTER(WPA_PTK_GROUP, IDLE); - sm->PtkGroupInit = FALSE; - } else switch (sm->wpa_ptk_group_state) { - case WPA_PTK_GROUP_IDLE: - if (sm->GUpdateStationKeys || - (sm->wpa == WPA_VERSION_WPA && sm->PInitAKeys)) - SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); - break; - case WPA_PTK_GROUP_REKEYNEGOTIATING: - if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && - !sm->EAPOLKeyPairwise && sm->MICVerified) - SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED); - else if (sm->GTimeoutCtr > - (int) dot11RSNAConfigGroupUpdateCount) - SM_ENTER(WPA_PTK_GROUP, KEYERROR); - else if (sm->TimeoutEvt) - SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); - break; - case WPA_PTK_GROUP_KEYERROR: - SM_ENTER(WPA_PTK_GROUP, IDLE); - break; - case WPA_PTK_GROUP_REKEYESTABLISHED: - SM_ENTER(WPA_PTK_GROUP, IDLE); - break; - } -} - - -static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, - struct wpa_group *group) -{ - int ret = 0; - - /* FIX: is this the correct way of getting GNonce? */ - os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); - inc_byte_array(group->Counter, WPA_NONCE_LEN); - wpa_gmk_to_gtk(group->GMK, wpa_auth->addr, group->GNonce, - group->GTK[group->GN - 1], group->GTK_len); - -#ifdef CONFIG_IEEE80211W - if (wpa_auth->conf.ieee80211w != WPA_NO_IEEE80211W) { - if (os_get_random(group->IGTK[group->GN_igtk - 4], - WPA_IGTK_LEN) < 0) { - wpa_printf(MSG_INFO, "RSN: Failed to get new random " - "IGTK"); - ret = -1; - } - wpa_hexdump_key(MSG_DEBUG, "IGTK", - group->IGTK[group->GN_igtk - 4], WPA_IGTK_LEN); - } -#endif /* CONFIG_IEEE80211W */ - - return ret; -} - - -static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth, - struct wpa_group *group) -{ - wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " - "GTK_INIT (VLAN-ID %d)", group->vlan_id); - group->changed = FALSE; /* GInit is not cleared here; avoid loop */ - group->wpa_group_state = WPA_GROUP_GTK_INIT; - - /* GTK[0..N] = 0 */ - os_memset(group->GTK, 0, sizeof(group->GTK)); - group->GN = 1; - group->GM = 2; -#ifdef CONFIG_IEEE80211W - group->GN_igtk = 4; - group->GM_igtk = 5; -#endif /* CONFIG_IEEE80211W */ - /* GTK[GN] = CalcGTK() */ - wpa_gtk_update(wpa_auth, group); -} - - -static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx) -{ - if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) { - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "Not in PTKINITDONE; skip Group Key update"); - return 0; - } - if (sm->GUpdateStationKeys) { - /* - * This should not really happen, but just in case, make sure - * we do not count the same STA twice in GKeyDoneStations. - */ - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "GUpdateStationKeys already set - do not " - "increment GKeyDoneStations"); - } else { - sm->group->GKeyDoneStations++; - sm->GUpdateStationKeys = TRUE; - } - wpa_sm_step(sm); - return 0; -} - - -static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth, - struct wpa_group *group) -{ - int tmp; - - wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " - "SETKEYS (VLAN-ID %d)", group->vlan_id); - group->changed = TRUE; - group->wpa_group_state = WPA_GROUP_SETKEYS; - group->GTKReKey = FALSE; - tmp = group->GM; - group->GM = group->GN; - group->GN = tmp; -#ifdef CONFIG_IEEE80211W - tmp = group->GM_igtk; - group->GM_igtk = group->GN_igtk; - group->GN_igtk = tmp; -#endif /* CONFIG_IEEE80211W */ - /* "GKeyDoneStations = GNoStations" is done in more robust way by - * counting the STAs that are marked with GUpdateStationKeys instead of - * including all STAs that could be in not-yet-completed state. */ - wpa_gtk_update(wpa_auth, group); - - wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, NULL); - wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d", - group->GKeyDoneStations); -} - - -static void wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth, - struct wpa_group *group) -{ - wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " - "SETKEYSDONE (VLAN-ID %d)", group->vlan_id); - group->changed = TRUE; - group->wpa_group_state = WPA_GROUP_SETKEYSDONE; - wpa_auth_set_key(wpa_auth, group->vlan_id, - wpa_alg_txt(wpa_auth->conf.wpa_group), - NULL, group->GN, group->GTK[group->GN - 1], - group->GTK_len); - -#ifdef CONFIG_IEEE80211W - if (wpa_auth->conf.ieee80211w != WPA_NO_IEEE80211W) { - wpa_auth_set_key(wpa_auth, group->vlan_id, "IGTK", - NULL, group->GN_igtk, - group->IGTK[group->GN_igtk - 4], - WPA_IGTK_LEN); - } -#endif /* CONFIG_IEEE80211W */ -} - - -static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, - struct wpa_group *group) -{ - if (group->GInit) { - wpa_group_gtk_init(wpa_auth, group); - } else if (group->wpa_group_state == WPA_GROUP_GTK_INIT && - group->GTKAuthenticator) { - wpa_group_setkeysdone(wpa_auth, group); - } else if (group->wpa_group_state == WPA_GROUP_SETKEYSDONE && - group->GTKReKey) { - wpa_group_setkeys(wpa_auth, group); - } else if (group->wpa_group_state == WPA_GROUP_SETKEYS) { - if (group->GKeyDoneStations == 0) - wpa_group_setkeysdone(wpa_auth, group); - else if (group->GTKReKey) - wpa_group_setkeys(wpa_auth, group); - } -} - - -static void wpa_sm_step(struct wpa_state_machine *sm) -{ - if (sm == NULL) - return; - - if (sm->in_step_loop) { - /* This should not happen, but if it does, make sure we do not - * end up freeing the state machine too early by exiting the - * recursive call. */ - wpa_printf(MSG_ERROR, "WPA: wpa_sm_step() called recursively"); - return; - } - - sm->in_step_loop = 1; - do { - if (sm->pending_deinit) - break; - - sm->changed = FALSE; - sm->wpa_auth->group->changed = FALSE; - - SM_STEP_RUN(WPA_PTK); - if (sm->pending_deinit) - break; - SM_STEP_RUN(WPA_PTK_GROUP); - if (sm->pending_deinit) - break; - wpa_group_sm_step(sm->wpa_auth, sm->group); - } while (sm->changed || sm->wpa_auth->group->changed); - sm->in_step_loop = 0; - - if (sm->pending_deinit) { - wpa_printf(MSG_DEBUG, "WPA: Completing pending STA state " - "machine deinit for " MACSTR, MAC2STR(sm->addr)); - wpa_free_sta_sm(sm); - } -} - - -static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_state_machine *sm = eloop_ctx; - wpa_sm_step(sm); -} - - -void wpa_auth_sm_notify(struct wpa_state_machine *sm) -{ - if (sm == NULL) - return; - eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL); -} - - -void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth) -{ - int tmp, i; - struct wpa_group *group; - - if (wpa_auth == NULL) - return; - - group = wpa_auth->group; - - for (i = 0; i < 2; i++) { - tmp = group->GM; - group->GM = group->GN; - group->GN = tmp; -#ifdef CONFIG_IEEE80211W - tmp = group->GM_igtk; - group->GM_igtk = group->GN_igtk; - group->GN_igtk = tmp; -#endif /* CONFIG_IEEE80211W */ - wpa_gtk_update(wpa_auth, group); - } -} - - -static const char * wpa_bool_txt(int bool) -{ - return bool ? "TRUE" : "FALSE"; -} - - -static int wpa_cipher_bits(int cipher) -{ - switch (cipher) { - case WPA_CIPHER_CCMP: - return 128; - case WPA_CIPHER_TKIP: - return 256; - case WPA_CIPHER_WEP104: - return 104; - case WPA_CIPHER_WEP40: - return 40; - default: - return 0; - } -} - - -#define RSN_SUITE "%02x-%02x-%02x-%d" -#define RSN_SUITE_ARG(s) \ -((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff - -int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen) -{ - int len = 0, ret; - char pmkid_txt[PMKID_LEN * 2 + 1]; - - if (wpa_auth == NULL) - return len; - - ret = os_snprintf(buf + len, buflen - len, - "dot11RSNAOptionImplemented=TRUE\n" -#ifdef CONFIG_RSN_PREAUTH - "dot11RSNAPreauthenticationImplemented=TRUE\n" -#else /* CONFIG_RSN_PREAUTH */ - "dot11RSNAPreauthenticationImplemented=FALSE\n" -#endif /* CONFIG_RSN_PREAUTH */ - "dot11RSNAEnabled=%s\n" - "dot11RSNAPreauthenticationEnabled=%s\n", - wpa_bool_txt(wpa_auth->conf.wpa & WPA_PROTO_RSN), - wpa_bool_txt(wpa_auth->conf.rsn_preauth)); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt), - wpa_auth->dot11RSNAPMKIDUsed, PMKID_LEN); - - ret = os_snprintf( - buf + len, buflen - len, - "dot11RSNAConfigVersion=%u\n" - "dot11RSNAConfigPairwiseKeysSupported=9999\n" - /* FIX: dot11RSNAConfigGroupCipher */ - /* FIX: dot11RSNAConfigGroupRekeyMethod */ - /* FIX: dot11RSNAConfigGroupRekeyTime */ - /* FIX: dot11RSNAConfigGroupRekeyPackets */ - "dot11RSNAConfigGroupRekeyStrict=%u\n" - "dot11RSNAConfigGroupUpdateCount=%u\n" - "dot11RSNAConfigPairwiseUpdateCount=%u\n" - "dot11RSNAConfigGroupCipherSize=%u\n" - "dot11RSNAConfigPMKLifetime=%u\n" - "dot11RSNAConfigPMKReauthThreshold=%u\n" - "dot11RSNAConfigNumberOfPTKSAReplayCounters=0\n" - "dot11RSNAConfigSATimeout=%u\n" - "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n" - "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n" - "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n" - "dot11RSNAPMKIDUsed=%s\n" - "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n" - "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n" - "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n" - "dot11RSNATKIPCounterMeasuresInvoked=%u\n" - "dot11RSNA4WayHandshakeFailures=%u\n" - "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n", - RSN_VERSION, - !!wpa_auth->conf.wpa_strict_rekey, - dot11RSNAConfigGroupUpdateCount, - dot11RSNAConfigPairwiseUpdateCount, - wpa_cipher_bits(wpa_auth->conf.wpa_group), - dot11RSNAConfigPMKLifetime, - dot11RSNAConfigPMKReauthThreshold, - dot11RSNAConfigSATimeout, - RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteSelected), - RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherSelected), - RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherSelected), - pmkid_txt, - RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteRequested), - RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherRequested), - RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherRequested), - wpa_auth->dot11RSNATKIPCounterMeasuresInvoked, - wpa_auth->dot11RSNA4WayHandshakeFailures); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - /* TODO: dot11RSNAConfigPairwiseCiphersTable */ - /* TODO: dot11RSNAConfigAuthenticationSuitesTable */ - - /* Private MIB */ - ret = os_snprintf(buf + len, buflen - len, "hostapdWPAGroupState=%d\n", - wpa_auth->group->wpa_group_state); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - return len; -} - - -int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen) -{ - int len = 0, ret; - u32 pairwise = 0; - - if (sm == NULL) - return 0; - - /* TODO: FF-FF-FF-FF-FF-FF entry for broadcast/multicast stats */ - - /* dot11RSNAStatsEntry */ - - if (sm->wpa == WPA_VERSION_WPA) { - if (sm->pairwise == WPA_CIPHER_CCMP) - pairwise = WPA_CIPHER_SUITE_CCMP; - else if (sm->pairwise == WPA_CIPHER_TKIP) - pairwise = WPA_CIPHER_SUITE_TKIP; - else if (sm->pairwise == WPA_CIPHER_WEP104) - pairwise = WPA_CIPHER_SUITE_WEP104; - else if (sm->pairwise == WPA_CIPHER_WEP40) - pairwise = WPA_CIPHER_SUITE_WEP40; - else if (sm->pairwise == WPA_CIPHER_NONE) - pairwise = WPA_CIPHER_SUITE_NONE; - } else if (sm->wpa == WPA_VERSION_WPA2) { - if (sm->pairwise == WPA_CIPHER_CCMP) - pairwise = RSN_CIPHER_SUITE_CCMP; - else if (sm->pairwise == WPA_CIPHER_TKIP) - pairwise = RSN_CIPHER_SUITE_TKIP; - else if (sm->pairwise == WPA_CIPHER_WEP104) - pairwise = RSN_CIPHER_SUITE_WEP104; - else if (sm->pairwise == WPA_CIPHER_WEP40) - pairwise = RSN_CIPHER_SUITE_WEP40; - else if (sm->pairwise == WPA_CIPHER_NONE) - pairwise = RSN_CIPHER_SUITE_NONE; - } else - return 0; - - ret = os_snprintf( - buf + len, buflen - len, - /* TODO: dot11RSNAStatsIndex */ - "dot11RSNAStatsSTAAddress=" MACSTR "\n" - "dot11RSNAStatsVersion=1\n" - "dot11RSNAStatsSelectedPairwiseCipher=" RSN_SUITE "\n" - /* TODO: dot11RSNAStatsTKIPICVErrors */ - "dot11RSNAStatsTKIPLocalMICFailures=%u\n" - "dot11RSNAStatsTKIPRemoveMICFailures=%u\n" - /* TODO: dot11RSNAStatsCCMPReplays */ - /* TODO: dot11RSNAStatsCCMPDecryptErrors */ - /* TODO: dot11RSNAStatsTKIPReplays */, - MAC2STR(sm->addr), - RSN_SUITE_ARG(pairwise), - sm->dot11RSNAStatsTKIPLocalMICFailures, - sm->dot11RSNAStatsTKIPRemoteMICFailures); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - /* Private MIB */ - ret = os_snprintf(buf + len, buflen - len, - "hostapdWPAPTKState=%d\n" - "hostapdWPAPTKGroupState=%d\n", - sm->wpa_ptk_state, - sm->wpa_ptk_group_state); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - return len; -} - - -void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth) -{ - if (wpa_auth) - wpa_auth->dot11RSNATKIPCounterMeasuresInvoked++; -} - - -int wpa_auth_pairwise_set(struct wpa_state_machine *sm) -{ - return sm && sm->pairwise_set; -} - - -int wpa_auth_get_pairwise(struct wpa_state_machine *sm) -{ - return sm->pairwise; -} - - -int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm) -{ - if (sm == NULL) - return -1; - return sm->wpa_key_mgmt; -} - - -int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm) -{ - if (sm == NULL) - return 0; - return sm->wpa; -} - - -int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, - struct rsn_pmksa_cache_entry *entry) -{ - if (sm == NULL || sm->pmksa != entry) - return -1; - sm->pmksa = NULL; - return 0; -} - - -struct rsn_pmksa_cache_entry * -wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm) -{ - return sm ? sm->pmksa : NULL; -} - - -void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm) -{ - if (sm) - sm->dot11RSNAStatsTKIPLocalMICFailures++; -} - - -const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len) -{ - if (wpa_auth == NULL) - return NULL; - *len = wpa_auth->wpa_ie_len; - return wpa_auth->wpa_ie; -} - - -int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk, - int session_timeout, struct eapol_state_machine *eapol) -{ - if (sm == NULL || sm->wpa != WPA_VERSION_WPA2) - return -1; - - if (pmksa_cache_add(sm->wpa_auth->pmksa, pmk, PMK_LEN, - sm->wpa_auth->addr, sm->addr, session_timeout, - eapol, sm->wpa_key_mgmt)) - return 0; - - return -1; -} - - -int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth, - const u8 *pmk, size_t len, const u8 *sta_addr, - int session_timeout, - struct eapol_state_machine *eapol) -{ - if (wpa_auth == NULL) - return -1; - - if (pmksa_cache_add(wpa_auth->pmksa, pmk, len, wpa_auth->addr, - sta_addr, session_timeout, eapol, - WPA_KEY_MGMT_IEEE8021X)) - return 0; - - return -1; -} - - -static struct wpa_group * -wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id) -{ - struct wpa_group *group; - - if (wpa_auth == NULL || wpa_auth->group == NULL) - return NULL; - - wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d", - vlan_id); - group = wpa_group_init(wpa_auth, vlan_id); - if (group == NULL) - return NULL; - - group->next = wpa_auth->group->next; - wpa_auth->group->next = group; - - return group; -} - - -int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id) -{ - struct wpa_group *group; - - if (sm == NULL || sm->wpa_auth == NULL) - return 0; - - group = sm->wpa_auth->group; - while (group) { - if (group->vlan_id == vlan_id) - break; - group = group->next; - } - - if (group == NULL) { - group = wpa_auth_add_group(sm->wpa_auth, vlan_id); - if (group == NULL) - return -1; - } - - if (sm->group == group) - return 0; - - wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state " - "machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id); - - sm->group = group; - return 0; -} - -#endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/contrib/hostapd/hostapd/wpa.h b/contrib/hostapd/hostapd/wpa.h deleted file mode 100644 index 7d9b3d3106..0000000000 --- a/contrib/hostapd/hostapd/wpa.h +++ /dev/null @@ -1,284 +0,0 @@ -/* - * hostapd - IEEE 802.11i-2004 / WPA Authenticator - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPA_AUTH_H -#define WPA_AUTH_H - -#include "eapol_common.h" -#include "wpa_common.h" - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -/* IEEE Std 802.11r-2008, 11A.10.3 - Remote request/response frame definition - */ -struct ft_rrb_frame { - u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */ - u8 packet_type; /* FT_PACKET_REQUEST/FT_PACKET_RESPONSE */ - le16 action_length; /* little endian length of action_frame */ - u8 ap_address[ETH_ALEN]; - /* - * Followed by action_length bytes of FT Action frame (from Category - * field to the end of Action Frame body. - */ -} STRUCT_PACKED; - -#define RSN_REMOTE_FRAME_TYPE_FT_RRB 1 - -#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 - -#ifndef ETH_P_RRB -#define ETH_P_RRB 0x890D -#endif /* ETH_P_RRB */ - -#define FT_R0KH_R1KH_PULL_DATA_LEN 44 -#define FT_R0KH_R1KH_RESP_DATA_LEN 76 -#define FT_R0KH_R1KH_PUSH_DATA_LEN 80 - -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[16]; - u8 pmk_r0_name[WPA_PMK_NAME_LEN]; - u8 r1kh_id[FT_R1KH_ID_LEN]; - u8 s1kh_id[ETH_ALEN]; - u8 pad[4]; /* 8-octet boundary for AES key wrap */ - u8 key_wrap_extra[8]; -} STRUCT_PACKED; - -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 (76) */ - u8 ap_address[ETH_ALEN]; - - u8 nonce[16]; /* 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]; - u8 pad[4]; /* 8-octet boundary for AES key wrap */ - u8 key_wrap_extra[8]; -} STRUCT_PACKED; - -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 (80) */ - u8 ap_address[ETH_ALEN]; - - /* 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]; - u8 key_wrap_extra[8]; -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -/* per STA state machine data */ - -struct wpa_authenticator; -struct wpa_state_machine; -struct rsn_pmksa_cache_entry; -struct eapol_state_machine; - - -struct ft_remote_r0kh { - struct ft_remote_r0kh *next; - u8 addr[ETH_ALEN]; - u8 id[FT_R0KH_ID_MAX_LEN]; - size_t id_len; - u8 key[16]; -}; - - -struct ft_remote_r1kh { - struct ft_remote_r1kh *next; - u8 addr[ETH_ALEN]; - u8 id[FT_R1KH_ID_LEN]; - u8 key[16]; -}; - - -struct wpa_auth_config { - int wpa; - int wpa_key_mgmt; - int wpa_pairwise; - int wpa_group; - int wpa_group_rekey; - int wpa_strict_rekey; - int wpa_gmk_rekey; - int wpa_ptk_rekey; - int rsn_pairwise; - int rsn_preauth; - int eapol_version; - int peerkey; - int wmm_enabled; - int okc; -#ifdef CONFIG_IEEE80211W - enum { - WPA_NO_IEEE80211W = 0, - WPA_IEEE80211W_OPTIONAL = 1, - WPA_IEEE80211W_REQUIRED = 2 - } ieee80211w; -#endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_IEEE80211R -#define SSID_LEN 32 - u8 ssid[SSID_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 reassociation_deadline; - struct ft_remote_r0kh *r0kh_list; - struct ft_remote_r1kh *r1kh_list; - int pmk_r1_push; -#endif /* CONFIG_IEEE80211R */ -}; - -typedef enum { - LOGGER_DEBUG, LOGGER_INFO, LOGGER_WARNING -} logger_level; - -typedef enum { - WPA_EAPOL_portEnabled, WPA_EAPOL_portValid, WPA_EAPOL_authorized, - WPA_EAPOL_portControl_Auto, WPA_EAPOL_keyRun, WPA_EAPOL_keyAvailable, - WPA_EAPOL_keyDone, WPA_EAPOL_inc_EapolFramesTx -} 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); - void (*mic_failure_report)(void *ctx, const u8 *addr); - void (*set_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var, - 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 *prev_psk); - int (*get_msk)(void *ctx, const u8 *addr, u8 *msk, size_t *len); - int (*set_key)(void *ctx, int vlan_id, const char *alg, const u8 *addr, - int idx, u8 *key, size_t key_len); - int (*get_seqnum)(void *ctx, const u8 *addr, int idx, u8 *seq); - int (*get_seqnum_igtk)(void *ctx, const u8 *addr, int idx, u8 *seq); - int (*send_eapol)(void *ctx, const u8 *addr, const u8 *data, - size_t data_len, int encrypt); - int (*for_each_sta)(void *ctx, int (*cb)(struct wpa_state_machine *sm, - void *ctx), void *cb_ctx); - int (*for_each_auth)(void *ctx, int (*cb)(struct wpa_authenticator *a, - 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 - struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr); - int (*send_ft_action)(void *ctx, const u8 *dst, - const u8 *data, size_t data_len); -#endif /* CONFIG_IEEE80211R */ -}; - -struct wpa_authenticator * wpa_init(const u8 *addr, - struct wpa_auth_config *conf, - struct wpa_auth_callbacks *cb); -void wpa_deinit(struct wpa_authenticator *wpa_auth); -int wpa_reconfig(struct wpa_authenticator *wpa_auth, - struct wpa_auth_config *conf); - -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 -}; - -int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, - const u8 *wpa_ie, size_t wpa_ie_len, - const u8 *mdie, size_t mdie_len); -int wpa_auth_uses_mfp(struct wpa_state_machine *sm); -struct wpa_state_machine * -wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr); -void wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm); -void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm); -void wpa_auth_sta_deinit(struct wpa_state_machine *sm); -void wpa_receive(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, - u8 *data, size_t data_len); -typedef enum { - WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH, - WPA_REAUTH_EAPOL, WPA_ASSOC_FT -} wpa_event; -void wpa_remove_ptk(struct wpa_state_machine *sm); -void wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event); -void wpa_auth_sm_notify(struct wpa_state_machine *sm); -void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth); -int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen); -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); -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_clear_pmksa(struct wpa_state_machine *sm, - struct rsn_pmksa_cache_entry *entry); -struct rsn_pmksa_cache_entry * -wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm); -void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm); -const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, - size_t *len); -int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk, - int session_timeout, struct eapol_state_machine *eapol); -int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth, - const u8 *pmk, size_t len, const u8 *sta_addr, - int session_timeout, - struct eapol_state_machine *eapol); -int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id); - -#ifdef CONFIG_IEEE80211R -u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, - size_t max_len, int auth_alg); -void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid, - u16 auth_transaction, const u8 *ies, size_t ies_len, - void (*cb)(void *ctx, const u8 *dst, const u8 *bssid, - u16 auth_transaction, u16 resp, - const u8 *ies, size_t ies_len), - void *ctx); -u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, - size_t ies_len); -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_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr); -#endif /* CONFIG_IEEE80211R */ - -#endif /* WPA_AUTH_H */ diff --git a/contrib/hostapd/hostapd/wpa_auth_i.h b/contrib/hostapd/hostapd/wpa_auth_i.h deleted file mode 100644 index 925d3ee459..0000000000 --- a/contrib/hostapd/hostapd/wpa_auth_i.h +++ /dev/null @@ -1,221 +0,0 @@ -/* - * hostapd - IEEE 802.11i-2004 / WPA Authenticator: Internal definitions - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPA_AUTH_I_H -#define WPA_AUTH_I_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]; - - enum { - WPA_PTK_INITIALIZE, WPA_PTK_DISCONNECT, WPA_PTK_DISCONNECTED, - WPA_PTK_AUTHENTICATION, WPA_PTK_AUTHENTICATION2, - WPA_PTK_INITPMK, WPA_PTK_INITPSK, WPA_PTK_PTKSTART, - WPA_PTK_PTKCALCNEGOTIATING, WPA_PTK_PTKCALCNEGOTIATING2, - WPA_PTK_PTKINITNEGOTIATING, WPA_PTK_PTKINITDONE - } wpa_ptk_state; - - enum { - WPA_PTK_GROUP_IDLE = 0, - WPA_PTK_GROUP_REKEYNEGOTIATING, - WPA_PTK_GROUP_REKEYESTABLISHED, - WPA_PTK_GROUP_KEYERROR - } wpa_ptk_group_state; - - Boolean Init; - Boolean DeauthenticationRequest; - Boolean AuthenticationRequest; - Boolean ReAuthenticationRequest; - Boolean Disconnect; - int TimeoutCtr; - int GTimeoutCtr; - Boolean TimeoutEvt; - Boolean EAPOLKeyReceived; - Boolean EAPOLKeyPairwise; - Boolean EAPOLKeyRequest; - Boolean MICVerified; - Boolean GUpdateStationKeys; - u8 ANonce[WPA_NONCE_LEN]; - u8 SNonce[WPA_NONCE_LEN]; - u8 PMK[PMK_LEN]; - struct wpa_ptk PTK; - Boolean PTK_valid; - Boolean pairwise_set; - int keycount; - Boolean Pair; - struct { - u8 counter[WPA_REPLAY_COUNTER_LEN]; - Boolean valid; - } key_replay[RSNA_MAX_EAPOL_RETRIES]; - Boolean PInitAKeys; /* WPA only, not in IEEE 802.11i */ - Boolean PTKRequest; /* not in IEEE 802.11i state machine */ - Boolean has_GTK; - Boolean PtkGroupInit; /* init request for PTK Group state machine */ - - u8 *last_rx_eapol_key; /* starting from IEEE 802.1X header */ - size_t last_rx_eapol_key_len; - - unsigned int changed:1; - unsigned int in_step_loop:1; - unsigned int pending_deinit:1; - unsigned int started:1; - unsigned int mgmt_frame_prot:1; -#ifdef CONFIG_IEEE80211R - unsigned int ft_completed:1; - unsigned int pmk_r1_name_valid:1; -#endif /* CONFIG_IEEE80211R */ - - u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN]; - int req_replay_counter_used; - - u8 *wpa_ie; - size_t wpa_ie_len; - - enum { - WPA_VERSION_NO_WPA = 0 /* WPA not used */, - WPA_VERSION_WPA = 1 /* WPA / IEEE 802.11i/D3.0 */, - WPA_VERSION_WPA2 = 2 /* WPA2 / IEEE 802.11i */ - } wpa; - int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */ - int wpa_key_mgmt; /* the selected WPA_KEY_MGMT_* */ - struct rsn_pmksa_cache_entry *pmksa; - - u32 dot11RSNAStatsTKIPLocalMICFailures; - u32 dot11RSNAStatsTKIPRemoteMICFailures; - -#ifdef CONFIG_IEEE80211R - u8 xxkey[PMK_LEN]; /* PSK or the second 256 bits of MSK */ - size_t xxkey_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 */ - size_t r0kh_id_len; -#endif /* CONFIG_IEEE80211R */ -}; - - -/* per group key state machine data */ -struct wpa_group { - struct wpa_group *next; - int vlan_id; - - Boolean GInit; - int GKeyDoneStations; - Boolean GTKReKey; - int GTK_len; - int GN, GM; - Boolean GTKAuthenticator; - u8 Counter[WPA_NONCE_LEN]; - - enum { - WPA_GROUP_GTK_INIT = 0, - WPA_GROUP_SETKEYS, WPA_GROUP_SETKEYSDONE - } wpa_group_state; - - u8 GMK[WPA_GMK_LEN]; - u8 GTK[2][WPA_GTK_MAX_LEN]; - u8 GNonce[WPA_NONCE_LEN]; - Boolean changed; -#ifdef CONFIG_IEEE80211W - u8 IGTK[2][WPA_IGTK_LEN]; - int GN_igtk, GM_igtk; -#endif /* CONFIG_IEEE80211W */ -}; - - -struct wpa_ft_pmk_cache; - -/* per authenticator data */ -struct wpa_authenticator { - struct wpa_group *group; - - unsigned int dot11RSNAStatsTKIPRemoteMICFailures; - u32 dot11RSNAAuthenticationSuiteSelected; - u32 dot11RSNAPairwiseCipherSelected; - u32 dot11RSNAGroupCipherSelected; - u8 dot11RSNAPMKIDUsed[PMKID_LEN]; - u32 dot11RSNAAuthenticationSuiteRequested; /* FIX: update */ - u32 dot11RSNAPairwiseCipherRequested; /* FIX: update */ - u32 dot11RSNAGroupCipherRequested; /* FIX: update */ - unsigned int dot11RSNATKIPCounterMeasuresInvoked; - unsigned int dot11RSNA4WayHandshakeFailures; - - struct wpa_stsl_negotiation *stsl_negotiations; - - struct wpa_auth_config conf; - struct wpa_auth_callbacks cb; - - u8 *wpa_ie; - size_t wpa_ie_len; - - u8 addr[ETH_ALEN]; - - struct rsn_pmksa_cache *pmksa; - struct wpa_ft_pmk_cache *ft_pmk_cache; -}; - - -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, - logger_level level, const char *txt); -void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, - logger_level level, const char *fmt, ...); -void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, int key_info, - const u8 *key_rsc, const u8 *nonce, - const u8 *kde, size_t kde_len, - int keyidx, int encr, int force_version); -int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth, - int (*cb)(struct wpa_state_machine *sm, void *ctx), - void *cb_ctx); -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, struct wpa_eapol_key *key); -void wpa_smk_m1(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, struct wpa_eapol_key *key); -void wpa_smk_m3(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, struct wpa_eapol_key *key); -#endif /* CONFIG_PEERKEY */ - -#ifdef CONFIG_IEEE80211R -int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len); -int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, - struct wpa_ptk *ptk, size_t ptk_len); -struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void); -void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache); -#endif /* CONFIG_IEEE80211R */ - -#endif /* WPA_AUTH_I_H */ diff --git a/contrib/hostapd/hostapd/wpa_auth_ie.c b/contrib/hostapd/hostapd/wpa_auth_ie.c deleted file mode 100644 index 7e01635284..0000000000 --- a/contrib/hostapd/hostapd/wpa_auth_ie.c +++ /dev/null @@ -1,864 +0,0 @@ -/* - * hostapd - WPA/RSN IE and KDE definitions - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "config.h" -#include "ieee802_11.h" -#include "eapol_sm.h" -#include "wpa.h" -#include "pmksa_cache.h" -#include "wpa_auth_ie.h" -#include "wpa_auth_i.h" - - -static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len) -{ - struct wpa_ie_hdr *hdr; - int num_suites; - u8 *pos, *count; - - hdr = (struct wpa_ie_hdr *) buf; - hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC; - RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE); - WPA_PUT_LE16(hdr->version, WPA_VERSION); - pos = (u8 *) (hdr + 1); - - if (conf->wpa_group == WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP); - } else if (conf->wpa_group == WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP); - } else if (conf->wpa_group == WPA_CIPHER_WEP104) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP104); - } else if (conf->wpa_group == WPA_CIPHER_WEP40) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP40); - } else { - wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", - conf->wpa_group); - return -1; - } - pos += WPA_SELECTOR_LEN; - - num_suites = 0; - count = pos; - pos += 2; - - if (conf->wpa_pairwise & WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP); - pos += WPA_SELECTOR_LEN; - num_suites++; - } - if (conf->wpa_pairwise & WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP); - pos += WPA_SELECTOR_LEN; - num_suites++; - } - if (conf->wpa_pairwise & WPA_CIPHER_NONE) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE); - pos += WPA_SELECTOR_LEN; - num_suites++; - } - - if (num_suites == 0) { - wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", - conf->wpa_pairwise); - return -1; - } - WPA_PUT_LE16(count, num_suites); - - num_suites = 0; - count = pos; - pos += 2; - - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { - RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X); - pos += WPA_SELECTOR_LEN; - num_suites++; - } - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { - RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X); - pos += WPA_SELECTOR_LEN; - num_suites++; - } - - if (num_suites == 0) { - wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", - conf->wpa_key_mgmt); - return -1; - } - WPA_PUT_LE16(count, num_suites); - - /* WPA Capabilities; use defaults, so no need to include it */ - - hdr->len = (pos - buf) - 2; - - return pos - buf; -} - - -int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, - const u8 *pmkid) -{ - struct rsn_ie_hdr *hdr; - int num_suites; - u8 *pos, *count; - u16 capab; - - hdr = (struct rsn_ie_hdr *) buf; - hdr->elem_id = WLAN_EID_RSN; - WPA_PUT_LE16(hdr->version, RSN_VERSION); - pos = (u8 *) (hdr + 1); - - if (conf->wpa_group == WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - } else if (conf->wpa_group == WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); - } else if (conf->wpa_group == WPA_CIPHER_WEP104) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP104); - } else if (conf->wpa_group == WPA_CIPHER_WEP40) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP40); - } else { - wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", - conf->wpa_group); - return -1; - } - pos += RSN_SELECTOR_LEN; - - num_suites = 0; - count = pos; - pos += 2; - - if (conf->rsn_pairwise & WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - pos += RSN_SELECTOR_LEN; - num_suites++; - } - if (conf->rsn_pairwise & WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); - pos += RSN_SELECTOR_LEN; - num_suites++; - } - if (conf->rsn_pairwise & WPA_CIPHER_NONE) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE); - pos += RSN_SELECTOR_LEN; - num_suites++; - } - - if (num_suites == 0) { - wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", - conf->rsn_pairwise); - return -1; - } - WPA_PUT_LE16(count, num_suites); - - num_suites = 0; - count = pos; - pos += 2; - - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X); - pos += RSN_SELECTOR_LEN; - num_suites++; - } - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X); - pos += RSN_SELECTOR_LEN; - num_suites++; - } -#ifdef CONFIG_IEEE80211R - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X); - pos += RSN_SELECTOR_LEN; - num_suites++; - } - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); - pos += RSN_SELECTOR_LEN; - num_suites++; - } -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256); - pos += RSN_SELECTOR_LEN; - num_suites++; - } - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256); - pos += RSN_SELECTOR_LEN; - num_suites++; - } -#endif /* CONFIG_IEEE80211W */ - - if (num_suites == 0) { - wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", - conf->wpa_key_mgmt); - return -1; - } - WPA_PUT_LE16(count, num_suites); - - /* RSN Capabilities */ - capab = 0; - if (conf->rsn_preauth) - capab |= WPA_CAPABILITY_PREAUTH; - if (conf->peerkey) - capab |= WPA_CAPABILITY_PEERKEY_ENABLED; - if (conf->wmm_enabled) { - /* 4 PTKSA replay counters when using WMM */ - capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2); - } -#ifdef CONFIG_IEEE80211W - if (conf->ieee80211w != WPA_NO_IEEE80211W) { - capab |= WPA_CAPABILITY_MFPC; - if (conf->ieee80211w == IEEE80211W_REQUIRED) - capab |= WPA_CAPABILITY_MFPR; - } -#endif /* CONFIG_IEEE80211W */ - WPA_PUT_LE16(pos, capab); - pos += 2; - - if (pmkid) { - if (pos + 2 + PMKID_LEN > buf + len) - return -1; - /* PMKID Count */ - WPA_PUT_LE16(pos, 1); - pos += 2; - os_memcpy(pos, pmkid, PMKID_LEN); - pos += PMKID_LEN; - } - -#ifdef CONFIG_IEEE80211W - if (conf->ieee80211w != WPA_NO_IEEE80211W) { - if (pos + 2 + 4 > buf + len) - return -1; - if (pmkid == NULL) { - /* PMKID Count */ - WPA_PUT_LE16(pos, 0); - pos += 2; - } - - /* Management Group Cipher Suite */ - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); - pos += RSN_SELECTOR_LEN; - } -#endif /* CONFIG_IEEE80211W */ - - hdr->len = (pos - buf) - 2; - - return pos - buf; -} - - -int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) -{ - u8 *pos, buf[128]; - int res; - - pos = buf; - - if (wpa_auth->conf.wpa & WPA_PROTO_RSN) { - res = wpa_write_rsn_ie(&wpa_auth->conf, - pos, buf + sizeof(buf) - pos, NULL); - if (res < 0) - return res; - pos += res; - } -#ifdef CONFIG_IEEE80211R - if (wpa_auth->conf.wpa_key_mgmt & - (WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK)) { - res = wpa_write_mdie(&wpa_auth->conf, pos, - buf + sizeof(buf) - pos); - if (res < 0) - return res; - pos += res; - } -#endif /* CONFIG_IEEE80211R */ - if (wpa_auth->conf.wpa & WPA_PROTO_WPA) { - res = wpa_write_wpa_ie(&wpa_auth->conf, - pos, buf + sizeof(buf) - pos); - if (res < 0) - return res; - pos += res; - } - - os_free(wpa_auth->wpa_ie); - wpa_auth->wpa_ie = os_malloc(pos - buf); - if (wpa_auth->wpa_ie == NULL) - return -1; - os_memcpy(wpa_auth->wpa_ie, buf, pos - buf); - wpa_auth->wpa_ie_len = pos - buf; - - return 0; -} - - -u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len, - const u8 *data2, size_t data2_len) -{ - *pos++ = WLAN_EID_VENDOR_SPECIFIC; - *pos++ = RSN_SELECTOR_LEN + data_len + data2_len; - RSN_SELECTOR_PUT(pos, kde); - pos += RSN_SELECTOR_LEN; - os_memcpy(pos, data, data_len); - pos += data_len; - if (data2) { - os_memcpy(pos, data2, data2_len); - pos += data2_len; - } - return pos; -} - - -static int wpa_selector_to_bitfield(const u8 *s) -{ - if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE) - return WPA_CIPHER_NONE; - if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP40) - return WPA_CIPHER_WEP40; - if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP) - return WPA_CIPHER_TKIP; - if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP) - return WPA_CIPHER_CCMP; - if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP104) - return WPA_CIPHER_WEP104; - return 0; -} - - -static int wpa_key_mgmt_to_bitfield(const u8 *s) -{ - if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X) - return WPA_KEY_MGMT_IEEE8021X; - if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X) - return WPA_KEY_MGMT_PSK; - if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE) - return WPA_KEY_MGMT_WPA_NONE; - return 0; -} - - -static int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, - struct wpa_ie_data *data) -{ - const struct wpa_ie_hdr *hdr; - const u8 *pos; - int left; - int i, count; - - os_memset(data, 0, sizeof(*data)); - data->pairwise_cipher = WPA_CIPHER_TKIP; - data->group_cipher = WPA_CIPHER_TKIP; - data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; - data->mgmt_group_cipher = 0; - - if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) - return -1; - - hdr = (const struct wpa_ie_hdr *) wpa_ie; - - if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC || - hdr->len != wpa_ie_len - 2 || - RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE || - WPA_GET_LE16(hdr->version) != WPA_VERSION) { - return -2; - } - - pos = (const u8 *) (hdr + 1); - left = wpa_ie_len - sizeof(*hdr); - - if (left >= WPA_SELECTOR_LEN) { - data->group_cipher = wpa_selector_to_bitfield(pos); - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } else if (left > 0) - return -3; - - if (left >= 2) { - data->pairwise_cipher = 0; - count = WPA_GET_LE16(pos); - pos += 2; - left -= 2; - if (count == 0 || left < count * WPA_SELECTOR_LEN) - return -4; - for (i = 0; i < count; i++) { - data->pairwise_cipher |= wpa_selector_to_bitfield(pos); - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } - } else if (left == 1) - return -5; - - if (left >= 2) { - data->key_mgmt = 0; - count = WPA_GET_LE16(pos); - pos += 2; - left -= 2; - if (count == 0 || left < count * WPA_SELECTOR_LEN) - return -6; - for (i = 0; i < count; i++) { - data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos); - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } - } else if (left == 1) - return -7; - - if (left >= 2) { - data->capabilities = WPA_GET_LE16(pos); - pos += 2; - left -= 2; - } - - if (left > 0) { - return -8; - } - - return 0; -} - - -struct wpa_auth_okc_iter_data { - struct rsn_pmksa_cache_entry *pmksa; - const u8 *aa; - const u8 *spa; - const u8 *pmkid; -}; - - -static int wpa_auth_okc_iter(struct wpa_authenticator *a, void *ctx) -{ - struct wpa_auth_okc_iter_data *data = ctx; - data->pmksa = pmksa_cache_get_okc(a->pmksa, data->aa, data->spa, - data->pmkid); - if (data->pmksa) - return 1; - return 0; -} - - -int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, - const u8 *wpa_ie, size_t wpa_ie_len, - const u8 *mdie, size_t mdie_len) -{ - struct wpa_ie_data data; - int ciphers, key_mgmt, res, version; - u32 selector; - size_t i; - const u8 *pmkid = NULL; - - if (wpa_auth == NULL || sm == NULL) - return WPA_NOT_ENABLED; - - if (wpa_ie == NULL || wpa_ie_len < 1) - return WPA_INVALID_IE; - - if (wpa_ie[0] == WLAN_EID_RSN) - version = WPA_PROTO_RSN; - else - version = WPA_PROTO_WPA; - - if (!(wpa_auth->conf.wpa & version)) { - wpa_printf(MSG_DEBUG, "Invalid WPA proto (%d) from " MACSTR, - version, MAC2STR(sm->addr)); - return WPA_INVALID_PROTO; - } - - if (version == WPA_PROTO_RSN) { - res = wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, &data); - - selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; - if (0) { - } -#ifdef CONFIG_IEEE80211R - else if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) - selector = RSN_AUTH_KEY_MGMT_FT_802_1X; - else if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) - selector = RSN_AUTH_KEY_MGMT_FT_PSK; -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) - selector = RSN_AUTH_KEY_MGMT_802_1X_SHA256; - else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) - selector = RSN_AUTH_KEY_MGMT_PSK_SHA256; -#endif /* CONFIG_IEEE80211W */ - else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) - selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; - else if (data.key_mgmt & WPA_KEY_MGMT_PSK) - selector = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X; - wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector; - - selector = RSN_CIPHER_SUITE_CCMP; - if (data.pairwise_cipher & WPA_CIPHER_CCMP) - selector = RSN_CIPHER_SUITE_CCMP; - else if (data.pairwise_cipher & WPA_CIPHER_TKIP) - selector = RSN_CIPHER_SUITE_TKIP; - else if (data.pairwise_cipher & WPA_CIPHER_WEP104) - selector = RSN_CIPHER_SUITE_WEP104; - else if (data.pairwise_cipher & WPA_CIPHER_WEP40) - selector = RSN_CIPHER_SUITE_WEP40; - else if (data.pairwise_cipher & WPA_CIPHER_NONE) - selector = RSN_CIPHER_SUITE_NONE; - wpa_auth->dot11RSNAPairwiseCipherSelected = selector; - - selector = RSN_CIPHER_SUITE_CCMP; - if (data.group_cipher & WPA_CIPHER_CCMP) - selector = RSN_CIPHER_SUITE_CCMP; - else if (data.group_cipher & WPA_CIPHER_TKIP) - selector = RSN_CIPHER_SUITE_TKIP; - else if (data.group_cipher & WPA_CIPHER_WEP104) - selector = RSN_CIPHER_SUITE_WEP104; - else if (data.group_cipher & WPA_CIPHER_WEP40) - selector = RSN_CIPHER_SUITE_WEP40; - else if (data.group_cipher & WPA_CIPHER_NONE) - selector = RSN_CIPHER_SUITE_NONE; - wpa_auth->dot11RSNAGroupCipherSelected = selector; - } else { - res = wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, &data); - - selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X; - if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) - selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X; - else if (data.key_mgmt & WPA_KEY_MGMT_PSK) - selector = WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X; - wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector; - - selector = WPA_CIPHER_SUITE_TKIP; - if (data.pairwise_cipher & WPA_CIPHER_CCMP) - selector = WPA_CIPHER_SUITE_CCMP; - else if (data.pairwise_cipher & WPA_CIPHER_TKIP) - selector = WPA_CIPHER_SUITE_TKIP; - else if (data.pairwise_cipher & WPA_CIPHER_WEP104) - selector = WPA_CIPHER_SUITE_WEP104; - else if (data.pairwise_cipher & WPA_CIPHER_WEP40) - selector = WPA_CIPHER_SUITE_WEP40; - else if (data.pairwise_cipher & WPA_CIPHER_NONE) - selector = WPA_CIPHER_SUITE_NONE; - wpa_auth->dot11RSNAPairwiseCipherSelected = selector; - - selector = WPA_CIPHER_SUITE_TKIP; - if (data.group_cipher & WPA_CIPHER_CCMP) - selector = WPA_CIPHER_SUITE_CCMP; - else if (data.group_cipher & WPA_CIPHER_TKIP) - selector = WPA_CIPHER_SUITE_TKIP; - else if (data.group_cipher & WPA_CIPHER_WEP104) - selector = WPA_CIPHER_SUITE_WEP104; - else if (data.group_cipher & WPA_CIPHER_WEP40) - selector = WPA_CIPHER_SUITE_WEP40; - else if (data.group_cipher & WPA_CIPHER_NONE) - selector = WPA_CIPHER_SUITE_NONE; - wpa_auth->dot11RSNAGroupCipherSelected = selector; - } - if (res) { - wpa_printf(MSG_DEBUG, "Failed to parse WPA/RSN IE from " - MACSTR " (res=%d)", MAC2STR(sm->addr), res); - wpa_hexdump(MSG_DEBUG, "WPA/RSN IE", wpa_ie, wpa_ie_len); - return WPA_INVALID_IE; - } - - if (data.group_cipher != wpa_auth->conf.wpa_group) { - wpa_printf(MSG_DEBUG, "Invalid WPA group cipher (0x%x) from " - MACSTR, data.group_cipher, MAC2STR(sm->addr)); - return WPA_INVALID_GROUP; - } - - key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt; - if (!key_mgmt) { - wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from " - MACSTR, data.key_mgmt, MAC2STR(sm->addr)); - return WPA_INVALID_AKMP; - } - if (0) { - } -#ifdef CONFIG_IEEE80211R - else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) - sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X; - else if (key_mgmt & WPA_KEY_MGMT_FT_PSK) - sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK; -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) - sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256; - else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256) - sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256; -#endif /* CONFIG_IEEE80211W */ - else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X) - sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X; - else - sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK; - - if (version == WPA_PROTO_RSN) - ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise; - else - ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise; - if (!ciphers) { - wpa_printf(MSG_DEBUG, "Invalid %s pairwise cipher (0x%x) " - "from " MACSTR, - version == WPA_PROTO_RSN ? "RSN" : "WPA", - data.pairwise_cipher, MAC2STR(sm->addr)); - return WPA_INVALID_PAIRWISE; - } - -#ifdef CONFIG_IEEE80211W - if (wpa_auth->conf.ieee80211w == WPA_IEEE80211W_REQUIRED) { - if (!(data.capabilities & WPA_CAPABILITY_MFPC)) { - wpa_printf(MSG_DEBUG, "Management frame protection " - "required, but client did not enable it"); - return WPA_MGMT_FRAME_PROTECTION_VIOLATION; - } - - if (ciphers & WPA_CIPHER_TKIP) { - wpa_printf(MSG_DEBUG, "Management frame protection " - "cannot use TKIP"); - return WPA_MGMT_FRAME_PROTECTION_VIOLATION; - } - - if (data.mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) { - wpa_printf(MSG_DEBUG, "Unsupported management group " - "cipher %d", data.mgmt_group_cipher); - return WPA_INVALID_MGMT_GROUP_CIPHER; - } - } - - if (wpa_auth->conf.ieee80211w == WPA_NO_IEEE80211W || - !(data.capabilities & WPA_CAPABILITY_MFPC)) - sm->mgmt_frame_prot = 0; - else - sm->mgmt_frame_prot = 1; -#endif /* CONFIG_IEEE80211W */ - -#ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { - if (mdie == NULL || mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) { - wpa_printf(MSG_DEBUG, "RSN: Trying to use FT, but " - "MDIE not included"); - return WPA_INVALID_MDIE; - } - if (os_memcmp(mdie, wpa_auth->conf.mobility_domain, - MOBILITY_DOMAIN_ID_LEN) != 0) { - wpa_hexdump(MSG_DEBUG, "RSN: Attempted to use unknown " - "MDIE", mdie, MOBILITY_DOMAIN_ID_LEN); - return WPA_INVALID_MDIE; - } - } -#endif /* CONFIG_IEEE80211R */ - - if (ciphers & WPA_CIPHER_CCMP) - sm->pairwise = WPA_CIPHER_CCMP; - else - sm->pairwise = WPA_CIPHER_TKIP; - - /* TODO: clear WPA/WPA2 state if STA changes from one to another */ - if (wpa_ie[0] == WLAN_EID_RSN) - sm->wpa = WPA_VERSION_WPA2; - else - sm->wpa = WPA_VERSION_WPA; - - sm->pmksa = NULL; - for (i = 0; i < data.num_pmkid; i++) { - wpa_hexdump(MSG_DEBUG, "RSN IE: STA PMKID", - &data.pmkid[i * PMKID_LEN], PMKID_LEN); - sm->pmksa = pmksa_cache_get(wpa_auth->pmksa, sm->addr, - &data.pmkid[i * PMKID_LEN]); - if (sm->pmksa) { - pmkid = sm->pmksa->pmkid; - break; - } - } - for (i = 0; sm->pmksa == NULL && wpa_auth->conf.okc && - i < data.num_pmkid; i++) { - struct wpa_auth_okc_iter_data idata; - idata.pmksa = NULL; - idata.aa = wpa_auth->addr; - idata.spa = sm->addr; - idata.pmkid = &data.pmkid[i * PMKID_LEN]; - wpa_auth_for_each_auth(wpa_auth, wpa_auth_okc_iter, &idata); - if (idata.pmksa) { - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, - "OKC match for PMKID"); - sm->pmksa = pmksa_cache_add_okc(wpa_auth->pmksa, - idata.pmksa, - wpa_auth->addr, - idata.pmkid); - pmkid = idata.pmkid; - break; - } - } - if (sm->pmksa) { - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, - "PMKID found from PMKSA cache " - "eap_type=%d vlan_id=%d", - sm->pmksa->eap_type_authsrv, - sm->pmksa->vlan_id); - os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmkid, PMKID_LEN); - } - - if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) { - os_free(sm->wpa_ie); - sm->wpa_ie = os_malloc(wpa_ie_len); - if (sm->wpa_ie == NULL) - return WPA_ALLOC_FAIL; - } - os_memcpy(sm->wpa_ie, wpa_ie, wpa_ie_len); - sm->wpa_ie_len = wpa_ie_len; - - return WPA_IE_OK; -} - - -/** - * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs - * @pos: Pointer to the IE header - * @end: Pointer to the end of the Key Data buffer - * @ie: Pointer to parsed IE data - * Returns: 0 on success, 1 if end mark is found, -1 on failure - */ -static int wpa_parse_generic(const u8 *pos, const u8 *end, - struct wpa_eapol_ie_parse *ie) -{ - if (pos[1] == 0) - return 1; - - if (pos[1] >= 6 && - RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE && - pos[2 + WPA_SELECTOR_LEN] == 1 && - pos[2 + WPA_SELECTOR_LEN + 1] == 0) { - ie->wpa_ie = pos; - ie->wpa_ie_len = pos[1] + 2; - return 0; - } - - if (pos + 1 + RSN_SELECTOR_LEN < end && - pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { - ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { - ie->gtk = pos + 2 + RSN_SELECTOR_LEN; - ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) { - ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN; - ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN; - 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; - 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; - 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; - 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; - return 0; - } -#endif /* CONFIG_PEERKEY */ - -#ifdef CONFIG_IEEE80211W - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) { - ie->igtk = pos + 2 + RSN_SELECTOR_LEN; - ie->igtk_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } -#endif /* CONFIG_IEEE80211W */ - - return 0; -} - - -/** - * wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs - * @buf: Pointer to the Key Data buffer - * @len: Key Data Length - * @ie: Pointer to parsed IE data - * Returns: 0 on success, -1 on failure - */ -int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie) -{ - const u8 *pos, *end; - int ret = 0; - - os_memset(ie, 0, sizeof(*ie)); - for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) { - if (pos[0] == 0xdd && - ((pos == buf + len - 1) || pos[1] == 0)) { - /* Ignore padding */ - break; - } - if (pos + 2 + pos[1] > end) { - wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data " - "underflow (ie=%d len=%d pos=%d)", - pos[0], pos[1], (int) (pos - buf)); - wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data", - buf, len); - ret = -1; - break; - } - if (*pos == WLAN_EID_RSN) { - ie->rsn_ie = pos; - ie->rsn_ie_len = pos[1] + 2; -#ifdef CONFIG_IEEE80211R - } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) { - ie->mdie = pos; - ie->mdie_len = pos[1] + 2; -#endif /* CONFIG_IEEE80211R */ - } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { - ret = wpa_parse_generic(pos, end, ie); - if (ret < 0) - break; - if (ret > 0) { - ret = 0; - break; - } - } else { - wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key " - "Key Data IE", pos, 2 + pos[1]); - } - } - - return ret; -} - - -int wpa_auth_uses_mfp(struct wpa_state_machine *sm) -{ - return sm ? sm->mgmt_frame_prot : 0; -} diff --git a/contrib/hostapd/hostapd/wpa_auth_ie.h b/contrib/hostapd/hostapd/wpa_auth_ie.h deleted file mode 100644 index 9968d2d92a..0000000000 --- a/contrib/hostapd/hostapd/wpa_auth_ie.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * hostapd - WPA/RSN IE and KDE definitions - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPA_AUTH_IE_H -#define WPA_AUTH_IE_H - -struct wpa_eapol_ie_parse { - const u8 *wpa_ie; - size_t wpa_ie_len; - const u8 *rsn_ie; - size_t rsn_ie_len; - const u8 *pmkid; - const u8 *gtk; - 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 - const u8 *mdie; - size_t mdie_len; -#endif /* CONFIG_IEEE80211R */ -}; - -int wpa_parse_kde_ies(const u8 *buf, size_t len, - struct wpa_eapol_ie_parse *ie); -u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len, - const u8 *data2, size_t data2_len); -int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth); - -#endif /* WPA_AUTH_IE_H */ diff --git a/contrib/hostapd/hostapd/wpa_ft.c b/contrib/hostapd/hostapd/wpa_ft.c deleted file mode 100644 index 31391051fe..0000000000 --- a/contrib/hostapd/hostapd/wpa_ft.c +++ /dev/null @@ -1,1500 +0,0 @@ -/* - * hostapd - IEEE 802.11r - Fast BSS Transition - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "config.h" -#include "wpa.h" -#include "aes_wrap.h" -#include "ieee802_11.h" -#include "defs.h" -#include "wpa_auth_i.h" -#include "wpa_auth_ie.h" - - -#ifdef CONFIG_IEEE80211R - -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) - return -1; - return wpa_auth->cb.send_ether(wpa_auth->cb.ctx, dst, ETH_P_RRB, - 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) - return -1; - return wpa_auth->cb.send_ft_action(wpa_auth->cb.ctx, dst, - data, data_len); -} - - -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) - return NULL; - return wpa_auth->cb.add_sta(wpa_auth->cb.ctx, sta_addr); -} - - -int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len) -{ - u8 *pos = buf; - u8 capab; - if (len < 2 + sizeof(struct rsn_mdie)) - return -1; - - *pos++ = WLAN_EID_MOBILITY_DOMAIN; - *pos++ = MOBILITY_DOMAIN_ID_LEN + 1; - os_memcpy(pos, conf->mobility_domain, MOBILITY_DOMAIN_ID_LEN); - pos += MOBILITY_DOMAIN_ID_LEN; - capab = RSN_FT_CAPAB_FT_OVER_DS; - *pos++ = capab; - - return pos - buf; -} - - -static int wpa_write_ftie(struct wpa_auth_config *conf, 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; - - if (len < 2 + sizeof(*hdr) + 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); - - /* Optional Parameters */ - *pos++ = FTIE_SUBELEM_R1KH_ID; - *pos++ = FT_R1KH_ID_LEN; - os_memcpy(pos, conf->r1_key_holder, FT_R1KH_ID_LEN); - pos += FT_R1KH_ID_LEN; - - if (r0kh_id) { - *pos++ = FTIE_SUBELEM_R0KH_ID; - *pos++ = r0kh_id_len; - os_memcpy(pos, r0kh_id, r0kh_id_len); - pos += r0kh_id_len; - } - - if (subelem) { - os_memcpy(pos, subelem, subelem_len); - pos += subelem_len; - } - - *ielen = pos - buf - 2; - - return pos - buf; -} - - -struct wpa_ft_pmk_r0_sa { - struct wpa_ft_pmk_r0_sa *next; - u8 pmk_r0[PMK_LEN]; - u8 pmk_r0_name[WPA_PMK_NAME_LEN]; - u8 spa[ETH_ALEN]; - /* TODO: expiration, identity, radius_class, EAP type, VLAN ID */ - int pmk_r1_pushed; -}; - -struct wpa_ft_pmk_r1_sa { - struct wpa_ft_pmk_r1_sa *next; - u8 pmk_r1[PMK_LEN]; - u8 pmk_r1_name[WPA_PMK_NAME_LEN]; - u8 spa[ETH_ALEN]; - /* TODO: expiration, identity, radius_class, EAP type, VLAN ID */ -}; - -struct wpa_ft_pmk_cache { - struct wpa_ft_pmk_r0_sa *pmk_r0; - struct wpa_ft_pmk_r1_sa *pmk_r1; -}; - -struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void) -{ - struct wpa_ft_pmk_cache *cache; - - cache = os_zalloc(sizeof(*cache)); - - return cache; -} - - -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); - } - - r1 = cache->pmk_r1; - while (r1) { - r1prev = r1; - r1 = r1->next; - os_memset(r1prev->pmk_r1, 0, PMK_LEN); - os_free(r1prev); - } - - os_free(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) -{ - struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache; - struct wpa_ft_pmk_r0_sa *r0; - - /* TODO: add expiration and limit on number of entries in cache */ - - r0 = os_zalloc(sizeof(*r0)); - if (r0 == NULL) - return -1; - - os_memcpy(r0->pmk_r0, pmk_r0, PMK_LEN); - os_memcpy(r0->pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN); - os_memcpy(r0->spa, spa, ETH_ALEN); - - r0->next = cache->pmk_r0; - cache->pmk_r0 = r0; - - return 0; -} - - -static int wpa_ft_fetch_pmk_r0(struct wpa_authenticator *wpa_auth, - const u8 *spa, const u8 *pmk_r0_name, - u8 *pmk_r0) -{ - struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache; - struct wpa_ft_pmk_r0_sa *r0; - - r0 = cache->pmk_r0; - while (r0) { - if (os_memcmp(r0->spa, spa, ETH_ALEN) == 0 && - os_memcmp(r0->pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN) - == 0) { - os_memcpy(pmk_r0, r0->pmk_r0, PMK_LEN); - return 0; - } - - r0 = r0->next; - } - - 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) -{ - struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache; - struct wpa_ft_pmk_r1_sa *r1; - - /* TODO: add expiration and limit on number of entries in cache */ - - r1 = os_zalloc(sizeof(*r1)); - if (r1 == NULL) - return -1; - - os_memcpy(r1->pmk_r1, pmk_r1, PMK_LEN); - os_memcpy(r1->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN); - os_memcpy(r1->spa, spa, ETH_ALEN); - - r1->next = cache->pmk_r1; - cache->pmk_r1 = r1; - - return 0; -} - - -static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth, - const u8 *spa, const u8 *pmk_r1_name, - u8 *pmk_r1) -{ - struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache; - struct wpa_ft_pmk_r1_sa *r1; - - r1 = cache->pmk_r1; - while (r1) { - if (os_memcmp(r1->spa, spa, ETH_ALEN) == 0 && - os_memcmp(r1->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN) - == 0) { - os_memcpy(pmk_r1, r1->pmk_r1, PMK_LEN); - return 0; - } - - r1 = r1->next; - } - - return -1; -} - - -static int wpa_ft_pull_pmk_r1(struct wpa_authenticator *wpa_auth, - const u8 *s1kh_id, const u8 *r0kh_id, - size_t r0kh_id_len, const u8 *pmk_r0_name) -{ - struct ft_remote_r0kh *r0kh; - struct ft_r0kh_r1kh_pull_frame frame, f; - - r0kh = wpa_auth->conf.r0kh_list; - while (r0kh) { - if (r0kh->id_len == r0kh_id_len && - os_memcmp(r0kh->id, r0kh_id, r0kh_id_len) == 0) - break; - r0kh = r0kh->next; - } - if (r0kh == NULL) - return -1; - - 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, wpa_auth->addr, ETH_ALEN); - - /* aes_wrap() does not support inplace encryption, so use a temporary - * buffer for the data. */ - if (os_get_random(f.nonce, sizeof(f.nonce))) { - wpa_printf(MSG_DEBUG, "FT: Failed to get random data for " - "nonce"); - return -1; - } - os_memcpy(f.pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN); - os_memcpy(f.r1kh_id, wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN); - os_memcpy(f.s1kh_id, s1kh_id, ETH_ALEN); - - if (aes_wrap(r0kh->key, (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8, - f.nonce, frame.nonce) < 0) - return -1; - - wpa_ft_rrb_send(wpa_auth, r0kh->addr, (u8 *) &frame, sizeof(frame)); - - return 0; -} - - -int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, - struct wpa_ptk *ptk, size_t ptk_len) -{ - u8 pmk_r0[PMK_LEN], pmk_r0_name[WPA_PMK_NAME_LEN]; - u8 pmk_r1[PMK_LEN], pmk_r1_name[WPA_PMK_NAME_LEN]; - 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; - size_t r0kh_len = sm->wpa_auth->conf.r0_key_holder_len; - 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; - - - if (sm->xxkey_len == 0) { - wpa_printf(MSG_DEBUG, "FT: XXKey not available for key " - "derivation"); - 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); - - wpa_derive_pmk_r1(pmk_r0, pmk_r0_name, r1kh, sm->addr, - pmk_r1, pmk_r1_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN); - wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, pmk_r1_name); - - wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr, - sm->wpa_auth->addr, pmk_r1_name, - (u8 *) ptk, ptk_len, ptk_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PTK", (u8 *) ptk, ptk_len); - wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); - - return 0; -} - - -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) - return -1; - return wpa_auth->cb.get_seqnum(wpa_auth->cb.ctx, addr, idx, seq); -} - - -#ifdef CONFIG_IEEE80211W -static inline int wpa_auth_get_seqnum_igtk(struct wpa_authenticator *wpa_auth, - const u8 *addr, int idx, u8 *seq) -{ - if (wpa_auth->cb.get_seqnum_igtk == NULL) - return -1; - return wpa_auth->cb.get_seqnum_igtk(wpa_auth->cb.ctx, addr, idx, seq); -} -#endif /* CONFIG_IEEE80211W */ - - -static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len) -{ - u8 *subelem; - struct wpa_group *gsm = sm->group; - size_t subelem_len, pad_len; - const u8 *key; - size_t key_len; - u8 keybuf[32]; - - key_len = gsm->GTK_len; - if (key_len > sizeof(keybuf)) - return NULL; - - /* - * Pad key for AES Key Wrap if it is not multiple of 8 bytes or is less - * than 16 bytes. - */ - pad_len = key_len % 8; - if (pad_len) - pad_len = 8 - pad_len; - if (key_len + pad_len < 16) - pad_len += 8; - if (pad_len) { - os_memcpy(keybuf, gsm->GTK[gsm->GN - 1], key_len); - os_memset(keybuf + key_len, 0, pad_len); - keybuf[key_len] = 0xdd; - key_len += pad_len; - key = keybuf; - } else - key = gsm->GTK[gsm->GN - 1]; - - /* - * Sub-elem ID[1] | Length[1] | Key Info[1] | Key Length[1] | RSC[8] | - * Key[5..32]. - */ - subelem_len = 12 + key_len + 8; - subelem = os_zalloc(subelem_len); - if (subelem == NULL) - return NULL; - - subelem[0] = FTIE_SUBELEM_GTK; - subelem[1] = 10 + key_len + 8; - subelem[2] = gsm->GN & 0x03; /* Key ID in B0-B1 of Key Info */ - subelem[3] = gsm->GTK_len; - wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 4); - if (aes_wrap(sm->PTK.kek, key_len / 8, key, subelem + 12)) { - os_free(subelem); - return NULL; - } - - *len = subelem_len; - return subelem; -} - - -#ifdef CONFIG_IEEE80211W -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; - - /* 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 = os_zalloc(subelem_len); - if (subelem == NULL) - return NULL; - - pos = subelem; - *pos++ = FTIE_SUBELEM_IGTK; - *pos++ = subelem_len - 2; - WPA_PUT_LE16(pos, gsm->GN_igtk); - pos += 2; - wpa_auth_get_seqnum_igtk(sm->wpa_auth, NULL, gsm->GN_igtk, pos); - pos += 6; - *pos++ = WPA_IGTK_LEN; - if (aes_wrap(sm->PTK.kek, WPA_IGTK_LEN / 8, - gsm->IGTK[gsm->GN_igtk - 4], pos)) { - os_free(subelem); - return NULL; - } - - *len = subelem_len; - return subelem; -} -#endif /* CONFIG_IEEE80211W */ - - -u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, - size_t max_len, int auth_alg) -{ - u8 *end, *mdie, *ftie, *rsnie, *r0kh_id, *subelem = NULL; - size_t mdie_len, ftie_len, rsnie_len, r0kh_id_len, subelem_len = 0; - int res; - struct wpa_auth_config *conf; - struct rsn_ftie *_ftie; - - if (sm == NULL) - return pos; - - conf = &sm->wpa_auth->conf; - - if (sm->wpa_key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X && - sm->wpa_key_mgmt != WPA_KEY_MGMT_FT_PSK) - return pos; - - end = pos + max_len; - - /* RSN */ - res = wpa_write_rsn_ie(conf, pos, end - pos, sm->pmk_r1_name); - if (res < 0) - return pos; - rsnie = pos; - rsnie_len = res; - pos += res; - - /* Mobility Domain Information */ - res = wpa_write_mdie(conf, pos, end - pos); - if (res < 0) - return pos; - mdie = pos; - mdie_len = res; - pos += res; - - /* Fast BSS Transition Information */ - if (auth_alg == WLAN_AUTH_FT) { - subelem = wpa_ft_gtk_subelem(sm, &subelem_len); - r0kh_id = sm->r0kh_id; - r0kh_id_len = sm->r0kh_id_len; -#ifdef CONFIG_IEEE80211W - if (sm->mgmt_frame_prot) { - u8 *igtk; - size_t igtk_len; - u8 *nbuf; - igtk = wpa_ft_igtk_subelem(sm, &igtk_len); - if (igtk == NULL) { - os_free(subelem); - return pos; - } - nbuf = os_realloc(subelem, subelem_len + igtk_len); - if (nbuf == NULL) { - os_free(subelem); - os_free(igtk); - return pos; - } - subelem = nbuf; - os_memcpy(subelem + subelem_len, igtk, igtk_len); - subelem_len += igtk_len; - os_free(igtk); - } -#endif /* CONFIG_IEEE80211W */ - } else { - r0kh_id = conf->r0_key_holder; - r0kh_id_len = conf->r0_key_holder_len; - } - res = wpa_write_ftie(conf, r0kh_id, r0kh_id_len, NULL, NULL, pos, - end - pos, subelem, subelem_len); - os_free(subelem); - if (res < 0) - return pos; - ftie = pos; - ftie_len = res; - pos += res; - - _ftie = (struct rsn_ftie *) (ftie + 2); - _ftie->mic_control[1] = 3; /* Information element count */ - if (wpa_ft_mic(sm->PTK.kck, sm->addr, sm->wpa_auth->addr, 6, - mdie, mdie_len, ftie, ftie_len, - rsnie, rsnie_len, NULL, 0, _ftie->mic) < 0) - wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC"); - - return pos; -} - - -struct wpa_ft_ies { - const u8 *mdie; - size_t mdie_len; - const u8 *ftie; - size_t ftie_len; - const u8 *r1kh_id; - const u8 *gtk; - size_t gtk_len; - const u8 *r0kh_id; - size_t r0kh_id_len; - const u8 *rsn; - size_t rsn_len; - const u8 *rsn_pmkid; -}; - - -static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len, - struct wpa_ft_ies *parse) -{ - const u8 *end, *pos; - - parse->ftie = ie; - parse->ftie_len = ie_len; - - pos = ie + sizeof(struct rsn_ftie); - end = ie + ie_len; - - while (pos + 2 <= end && pos + 2 + pos[1] <= end) { - switch (pos[0]) { - case FTIE_SUBELEM_R1KH_ID: - if (pos[1] != FT_R1KH_ID_LEN) { - wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID " - "length in FTIE: %d", pos[1]); - return -1; - } - parse->r1kh_id = pos + 2; - break; - case FTIE_SUBELEM_GTK: - parse->gtk = pos + 2; - parse->gtk_len = pos[1]; - break; - case FTIE_SUBELEM_R0KH_ID: - if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) { - wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID " - "length in FTIE: %d", pos[1]); - return -1; - } - parse->r0kh_id = pos + 2; - parse->r0kh_id_len = pos[1]; - break; - } - - pos += 2 + pos[1]; - } - - return 0; -} - - -static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, - struct wpa_ft_ies *parse) -{ - const u8 *end, *pos; - struct wpa_ie_data data; - int ret; - - os_memset(parse, 0, sizeof(*parse)); - if (ies == NULL) - return 0; - - pos = ies; - end = ies + ies_len; - while (pos + 2 <= end && pos + 2 + pos[1] <= end) { - switch (pos[0]) { - case WLAN_EID_RSN: - parse->rsn = pos + 2; - parse->rsn_len = pos[1]; - ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2, - parse->rsn_len + 2, - &data); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to parse " - "RSN IE: %d", ret); - return -1; - } - if (data.num_pmkid == 1 && data.pmkid) - parse->rsn_pmkid = data.pmkid; - break; - case WLAN_EID_MOBILITY_DOMAIN: - parse->mdie = pos + 2; - parse->mdie_len = pos[1]; - break; - case WLAN_EID_FAST_BSS_TRANSITION: - if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0) - return -1; - break; - } - - pos += 2 + pos[1]; - } - - return 0; -} - - -static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, - int vlan_id, - const char *alg, const u8 *addr, int idx, - u8 *key, size_t key_len) -{ - 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); -} - - -static void wpa_ft_install_ptk(struct wpa_state_machine *sm) -{ - char *alg; - int klen; - - /* MLME-SETKEYS.request(PTK) */ - if (sm->pairwise == WPA_CIPHER_TKIP) { - alg = "TKIP"; - klen = 32; - } else if (sm->pairwise == WPA_CIPHER_CCMP) { - alg = "CCMP"; - klen = 16; - } else - return; - - /* FIX: add STA entry to kernel/driver here? The set_key will fail - * most likely without this.. At the moment, STA entry is added only - * after association has been completed. Alternatively, could - * re-configure PTK at that point(?). - */ - if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, - sm->PTK.tk1, klen)) - return; - - /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ - sm->pairwise_set = TRUE; -} - - -static u16 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 ptk_name[WPA_PMK_NAME_LEN]; - struct wpa_auth_config *conf; - struct wpa_ft_ies parse; - size_t buflen, ptk_len; - int ret; - u8 *pos, *end; - - *resp_ies = NULL; - *resp_ies_len = 0; - - sm->pmk_r1_name_valid = 0; - conf = &sm->wpa_auth->conf; - - wpa_hexdump(MSG_DEBUG, "FT: Received authentication frame IEs", - ies, ies_len); - - if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - mdie = (struct rsn_mdie *) parse.mdie; - if (mdie == NULL || parse.mdie_len < sizeof(*mdie) || - os_memcmp(mdie->mobility_domain, - sm->wpa_auth->conf.mobility_domain, - MOBILITY_DOMAIN_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: Invalid MDIE"); - 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; - } - - os_memcpy(sm->SNonce, ftie->snonce, WPA_NONCE_LEN); - - if (parse.r0kh_id == NULL) { - wpa_printf(MSG_DEBUG, "FT: Invalid FTIE - no R0KH-ID"); - return WLAN_STATUS_INVALID_FTIE; - } - - wpa_hexdump(MSG_DEBUG, "FT: STA R0KH-ID", - parse.r0kh_id, parse.r0kh_id_len); - os_memcpy(sm->r0kh_id, parse.r0kh_id, parse.r0kh_id_len); - sm->r0kh_id_len = parse.r0kh_id_len; - - if (parse.rsn_pmkid == NULL) { - wpa_printf(MSG_DEBUG, "FT: No PMKID in RSNIE"); - return WLAN_STATUS_INVALID_PMKID; - } - - 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); - 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) < - 0) { - if (wpa_ft_pull_pmk_r1(sm->wpa_auth, sm->addr, sm->r0kh_id, - sm->r0kh_id_len, parse.rsn_pmkid) < 0) { - wpa_printf(MSG_DEBUG, "FT: Did not have matching " - "PMK-R1 and unknown R0KH-ID"); - return WLAN_STATUS_INVALID_PMKID; - } - - /* - * TODO: Should return "status pending" (and the caller should - * not send out response now). The real response will be sent - * once the response from R0KH is received. - */ - return WLAN_STATUS_INVALID_PMKID; - } - - wpa_hexdump_key(MSG_DEBUG, "FT: Selected PMK-R1", pmk_r1, PMK_LEN); - sm->pmk_r1_name_valid = 1; - os_memcpy(sm->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN); - - if (os_get_random(sm->ANonce, WPA_NONCE_LEN)) { - wpa_printf(MSG_DEBUG, "FT: Failed to get random data for " - "ANonce"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", - sm->SNonce, WPA_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "FT: Generated ANonce", - sm->ANonce, WPA_NONCE_LEN); - - ptk_len = sm->pairwise == WPA_CIPHER_CCMP ? 48 : 64; - wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr, - sm->wpa_auth->addr, pmk_r1_name, - (u8 *) &sm->PTK, ptk_len, ptk_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PTK", - (u8 *) &sm->PTK, ptk_len); - wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); - - wpa_ft_install_ptk(sm); - - 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; - } - - 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; - } - 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; - } - pos += ret; - - ret = wpa_write_ftie(conf, 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; - } - pos += ret; - - *resp_ies_len = pos - *resp_ies; - - return WLAN_STATUS_SUCCESS; -} - - -void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid, - u16 auth_transaction, const u8 *ies, size_t ies_len, - void (*cb)(void *ctx, const u8 *dst, const u8 *bssid, - u16 auth_transaction, u16 status, - const u8 *ies, size_t ies_len), - void *ctx) -{ - u16 status; - u8 *resp_ies; - size_t resp_ies_len; - - if (sm == NULL) { - wpa_printf(MSG_DEBUG, "FT: Received authentication frame, but " - "WPA SM not available"); - return; - } - - wpa_printf(MSG_DEBUG, "FT: Received authentication frame: STA=" MACSTR - " BSSID=" MACSTR " transaction=%d", - MAC2STR(sm->addr), MAC2STR(bssid), auth_transaction); - status = wpa_ft_process_auth_req(sm, ies, ies_len, &resp_ies, - &resp_ies_len); - - wpa_printf(MSG_DEBUG, "FT: FT authentication response: dst=" MACSTR - " auth_transaction=%d status=%d", - MAC2STR(sm->addr), auth_transaction + 1, status); - wpa_hexdump(MSG_DEBUG, "FT: Response IEs", resp_ies, resp_ies_len); - cb(ctx, sm->addr, bssid, auth_transaction + 1, status, - resp_ies, resp_ies_len); - os_free(resp_ies); -} - - -u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, - size_t ies_len) -{ - struct wpa_ft_ies parse; - struct rsn_mdie *mdie; - struct rsn_ftie *ftie; - u8 mic[16]; - - if (sm == NULL) - return WLAN_STATUS_UNSPECIFIED_FAILURE; - - wpa_hexdump(MSG_DEBUG, "FT: Reassoc Req IEs", ies, ies_len); - - if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - if (parse.rsn == NULL) { - wpa_printf(MSG_DEBUG, "FT: No RSNIE in Reassoc Req"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - if (parse.rsn_pmkid == NULL) { - wpa_printf(MSG_DEBUG, "FT: No PMKID in RSNIE"); - return WLAN_STATUS_INVALID_PMKID; - } - - if (os_memcmp(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0) - { - wpa_printf(MSG_DEBUG, "FT: PMKID in Reassoc Req did not match " - "with the PMKR1Name derived from auth request"); - return WLAN_STATUS_INVALID_PMKID; - } - - mdie = (struct rsn_mdie *) parse.mdie; - if (mdie == NULL || parse.mdie_len < sizeof(*mdie) || - os_memcmp(mdie->mobility_domain, - sm->wpa_auth->conf.mobility_domain, - MOBILITY_DOMAIN_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: Invalid MDIE"); - 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; - } - - /* - * Assume that MDIE, FTIE, and RSN IE are protected and that there is - * no RIC, so total of 3 protected IEs. - */ - if (ftie->mic_control[1] != 3) { - wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in FTIE (%d)", - ftie->mic_control[1]); - return WLAN_STATUS_INVALID_FTIE; - } - - if (wpa_ft_mic(sm->PTK.kck, 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, NULL, 0, - mic) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - if (os_memcmp(mic, ftie->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: Calculated MIC", mic, 16); - return WLAN_STATUS_INVALID_FTIE; - } - - return WLAN_STATUS_SUCCESS; -} - - -int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len) -{ - const u8 *sta_addr, *target_ap; - const u8 *ies; - size_t ies_len; - u8 action; - struct ft_rrb_frame *frame; - - if (sm == NULL) - return -1; - - /* - * data: Category[1] Action[1] STA_Address[6] Target_AP_Address[6] - * FT Request action frame body[variable] - */ - - if (len < 14) { - wpa_printf(MSG_DEBUG, "FT: Too short FT Action frame " - "(len=%lu)", (unsigned long) len); - return -1; - } - - action = data[1]; - sta_addr = data + 2; - target_ap = data + 8; - ies = data + 14; - ies_len = len - 14; - - wpa_printf(MSG_DEBUG, "FT: Received FT Action frame (STA=" MACSTR - " Target AP=" MACSTR " Action=%d)", - MAC2STR(sta_addr), MAC2STR(target_ap), action); - - if (os_memcmp(sta_addr, sm->addr, ETH_ALEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: Mismatch in FT Action STA address: " - "STA=" MACSTR " STA-Address=" MACSTR, - MAC2STR(sm->addr), MAC2STR(sta_addr)); - return -1; - } - - /* - * Do some sanity checking on the target AP address (not own and not - * broadcast. This could be extended to filter based on a list of known - * APs in the MD (if such a list were configured). - */ - if ((target_ap[0] & 0x01) || - os_memcmp(target_ap, sm->wpa_auth->addr, ETH_ALEN) == 0) { - wpa_printf(MSG_DEBUG, "FT: Invalid Target AP in FT Action " - "frame"); - return -1; - } - - wpa_hexdump(MSG_MSGDUMP, "FT: Action frame body", ies, ies_len); - - /* RRB - Forward action frame to the target AP */ - frame = os_malloc(sizeof(*frame) + len); - frame->frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB; - frame->packet_type = FT_PACKET_REQUEST; - frame->action_length = host_to_le16(len); - os_memcpy(frame->ap_address, sm->wpa_auth->addr, ETH_ALEN); - os_memcpy(frame + 1, data, len); - - wpa_ft_rrb_send(sm->wpa_auth, target_ap, (u8 *) frame, - sizeof(*frame) + len); - os_free(frame); - - return 0; -} - - -static int wpa_ft_rrb_rx_request(struct wpa_authenticator *wpa_auth, - const u8 *current_ap, const u8 *sta_addr, - const u8 *body, size_t len) -{ - struct wpa_state_machine *sm; - u16 status; - u8 *resp_ies, *pos; - size_t resp_ies_len, rlen; - struct ft_rrb_frame *frame; - - sm = wpa_ft_add_sta(wpa_auth, sta_addr); - if (sm == NULL) { - wpa_printf(MSG_DEBUG, "FT: Failed to add new STA based on " - "RRB Request"); - return -1; - } - - wpa_hexdump(MSG_MSGDUMP, "FT: RRB Request Frame body", body, len); - - status = wpa_ft_process_auth_req(sm, body, len, &resp_ies, - &resp_ies_len); - - wpa_printf(MSG_DEBUG, "FT: RRB authentication response: STA=" MACSTR - " CurrentAP=" MACSTR " status=%d", - MAC2STR(sm->addr), MAC2STR(current_ap), status); - wpa_hexdump(MSG_DEBUG, "FT: Response IEs", resp_ies, resp_ies_len); - - /* RRB - Forward action frame response to the Current AP */ - - /* - * data: Category[1] Action[1] STA_Address[6] Target_AP_Address[6] - * Status_Code[2] FT Request action frame body[variable] - */ - rlen = 2 + 2 * ETH_ALEN + 2 + resp_ies_len; - - frame = os_malloc(sizeof(*frame) + rlen); - frame->frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB; - frame->packet_type = FT_PACKET_RESPONSE; - frame->action_length = host_to_le16(rlen); - os_memcpy(frame->ap_address, wpa_auth->addr, ETH_ALEN); - pos = (u8 *) (frame + 1); - *pos++ = WLAN_ACTION_FT; - *pos++ = 2; /* Action: Response */ - os_memcpy(pos, sta_addr, ETH_ALEN); - pos += ETH_ALEN; - os_memcpy(pos, wpa_auth->addr, ETH_ALEN); - pos += ETH_ALEN; - WPA_PUT_LE16(pos, status); - pos += 2; - if (resp_ies) { - os_memcpy(pos, resp_ies, resp_ies_len); - os_free(resp_ies); - } - - wpa_ft_rrb_send(wpa_auth, current_ap, (u8 *) frame, - sizeof(*frame) + rlen); - os_free(frame); - - return 0; -} - - -static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth, - const u8 *src_addr, - const u8 *data, size_t data_len) -{ - struct ft_r0kh_r1kh_pull_frame *frame, f; - struct ft_remote_r1kh *r1kh; - struct ft_r0kh_r1kh_resp_frame resp, r; - u8 pmk_r0[PMK_LEN]; - - wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull"); - - if (data_len < sizeof(*frame)) - return -1; - - r1kh = wpa_auth->conf.r1kh_list; - while (r1kh) { - if (os_memcmp(r1kh->addr, src_addr, ETH_ALEN) == 0) - break; - r1kh = r1kh->next; - } - 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; - } - - frame = (struct ft_r0kh_r1kh_pull_frame *) data; - /* aes_unwrap() does not support inplace decryption, so use a temporary - * buffer for the data. */ - if (aes_unwrap(r1kh->key, (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8, - frame->nonce, f.nonce) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull " - "request from " MACSTR, MAC2STR(src_addr)); - return -1; - } - - 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) < - 0) { - wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name found for " - "PMK-R1 pull"); - return -1; - } - - 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); - - if (aes_wrap(r1kh->key, (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8, - r.nonce, resp.nonce) < 0) { - os_memset(pmk_r0, 0, PMK_LEN); - return -1; - } - - os_memset(pmk_r0, 0, PMK_LEN); - - wpa_ft_rrb_send(wpa_auth, src_addr, (u8 *) &resp, sizeof(resp)); - - return 0; -} - - -static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth, - const u8 *src_addr, - const u8 *data, size_t data_len) -{ - struct ft_r0kh_r1kh_resp_frame *frame, f; - struct ft_remote_r0kh *r0kh; - - wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull response"); - - if (data_len < sizeof(*frame)) - return -1; - - 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)); - return -1; - } - - frame = (struct ft_r0kh_r1kh_resp_frame *) data; - /* aes_unwrap() does not support inplace decryption, so use a temporary - * buffer for the data. */ - if (aes_unwrap(r0kh->key, (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8, - frame->nonce, f.nonce) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull " - "response from " MACSTR, MAC2STR(src_addr)); - return -1; - } - - if (os_memcmp(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"); - return -1; - } - - /* TODO: verify that matches with a pending request - * and call this requests callback function to finish request - * processing */ - - 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, MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id)); - 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); - - wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name); - os_memset(f.pmk_r1, 0, PMK_LEN); - - return 0; -} - - -static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth, - const u8 *src_addr, - const u8 *data, size_t data_len) -{ - struct ft_r0kh_r1kh_push_frame *frame, f; - struct ft_remote_r0kh *r0kh; - struct os_time now; - os_time_t tsend; - - wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 push"); - - if (data_len < sizeof(*frame)) - return -1; - - 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 push source address " MACSTR, - MAC2STR(src_addr)); - return -1; - } - - frame = (struct ft_r0kh_r1kh_push_frame *) data; - /* aes_unwrap() does not support inplace decryption, so use a temporary - * buffer for the data. */ - if (aes_unwrap(r0kh->key, (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8, - frame->timestamp, f.timestamp) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 push from " - MACSTR, MAC2STR(src_addr)); - return -1; - } - - 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 (os_memcmp(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; - } - - wpa_printf(MSG_DEBUG, "FT: PMK-R1 push - R1KH-ID=" MACSTR " S1KH-ID=" - MACSTR, MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id)); - 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); - - wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name); - os_memset(f.pmk_r1, 0, PMK_LEN); - - return 0; -} - - -int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr, - const u8 *data, size_t data_len) -{ - struct ft_rrb_frame *frame; - u16 alen; - const u8 *pos, *end, *start; - u8 action; - const u8 *sta_addr, *target_ap_addr; - - wpa_printf(MSG_DEBUG, "FT: RRB received frame from remote AP " MACSTR, - MAC2STR(src_addr)); - - if (data_len < sizeof(*frame)) { - wpa_printf(MSG_DEBUG, "FT: Too short RRB frame (data_len=%lu)", - (unsigned long) data_len); - return -1; - } - - pos = data; - frame = (struct ft_rrb_frame *) pos; - pos += sizeof(*frame); - - alen = le_to_host16(frame->action_length); - wpa_printf(MSG_DEBUG, "FT: RRB frame - frame_type=%d packet_type=%d " - "action_length=%d ap_address=" MACSTR, - frame->frame_type, frame->packet_type, alen, - MAC2STR(frame->ap_address)); - - if (frame->frame_type != RSN_REMOTE_FRAME_TYPE_FT_RRB) { - /* Discard frame per IEEE Std 802.11r-2008, 11A.10.3 */ - wpa_printf(MSG_DEBUG, "FT: RRB discarded frame with " - "unrecognized type %d", frame->frame_type); - return -1; - } - - if (alen > data_len - sizeof(*frame)) { - wpa_printf(MSG_DEBUG, "FT: RRB frame too short for action " - "frame"); - 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) { - wpa_printf(MSG_DEBUG, "FT: Too short RRB frame (not enough " - "room for Action Frame body); alen=%lu", - (unsigned long) alen); - return -1; - } - start = pos; - end = pos + alen; - - if (*pos != WLAN_ACTION_FT) { - wpa_printf(MSG_DEBUG, "FT: Unexpected Action frame category " - "%d", *pos); - return -1; - } - - pos++; - action = *pos++; - sta_addr = pos; - pos += ETH_ALEN; - target_ap_addr = pos; - pos += ETH_ALEN; - wpa_printf(MSG_DEBUG, "FT: RRB Action Frame: action=%d sta_addr=" - MACSTR " target_ap_addr=" MACSTR, - action, MAC2STR(sta_addr), MAC2STR(target_ap_addr)); - - if (frame->packet_type == FT_PACKET_REQUEST) { - wpa_printf(MSG_DEBUG, "FT: FT Packet Type - Request"); - - if (action != 1) { - wpa_printf(MSG_DEBUG, "FT: Unexpected Action %d in " - "RRB Request", action); - return -1; - } - - if (os_memcmp(target_ap_addr, wpa_auth->addr, ETH_ALEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: Target AP address in the " - "RRB Request does not match with own " - "address"); - return -1; - } - - if (wpa_ft_rrb_rx_request(wpa_auth, frame->ap_address, - sta_addr, pos, end - pos) < 0) - return -1; - } else if (frame->packet_type == FT_PACKET_RESPONSE) { - u16 status_code; - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "FT: Not enough room for status " - "code in RRB Response"); - return -1; - } - status_code = WPA_GET_LE16(pos); - pos += 2; - - wpa_printf(MSG_DEBUG, "FT: FT Packet Type - Response " - "(status_code=%d)", status_code); - - if (wpa_ft_action_send(wpa_auth, sta_addr, start, alen) < 0) - return -1; - } else { - wpa_printf(MSG_DEBUG, "FT: RRB discarded frame with unknown " - "packet_type %d", frame->packet_type); - return -1; - } - - return 0; -} - - -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) -{ - struct ft_r0kh_r1kh_push_frame frame, f; - struct os_time now; - - 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); - if (aes_wrap(r1kh->key, (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8, - f.timestamp, frame.timestamp) < 0) - return; - - wpa_ft_rrb_send(wpa_auth, r1kh->addr, (u8 *) &frame, sizeof(frame)); -} - - -void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr) -{ - struct wpa_ft_pmk_r0_sa *r0; - struct ft_remote_r1kh *r1kh; - - if (!wpa_auth->conf.pmk_r1_push) - return; - - r0 = wpa_auth->ft_pmk_cache->pmk_r0; - while (r0) { - if (os_memcmp(r0->spa, addr, ETH_ALEN) == 0) - break; - r0 = r0->next; - } - - if (r0 == NULL || r0->pmk_r1_pushed) - return; - r0->pmk_r1_pushed = 1; - - 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); - r1kh = r1kh->next; - } -} - -#endif /* CONFIG_IEEE80211R */ diff --git a/contrib/hostapd/hostapd/wps_hostapd.c b/contrib/hostapd/hostapd/wps_hostapd.c deleted file mode 100644 index 818767ef46..0000000000 --- a/contrib/hostapd/hostapd/wps_hostapd.c +++ /dev/null @@ -1,1029 +0,0 @@ -/* - * hostapd / WPS integration - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "hostapd.h" -#include "driver.h" -#include "eloop.h" -#include "uuid.h" -#include "wpa_ctrl.h" -#include "ieee802_11_defs.h" -#include "sta_info.h" -#include "eapol_sm.h" -#include "wps/wps.h" -#include "wps/wps_defs.h" -#include "wps/wps_dev_attr.h" -#include "wps_hostapd.h" - - -#ifdef CONFIG_WPS_UPNP -#include "wps/wps_upnp.h" -static int hostapd_wps_upnp_init(struct hostapd_data *hapd, - struct wps_context *wps); -static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd); -#endif /* CONFIG_WPS_UPNP */ - - -static int hostapd_wps_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *psk, - size_t psk_len) -{ - struct hostapd_data *hapd = ctx; - struct hostapd_wpa_psk *p; - struct hostapd_ssid *ssid = &hapd->conf->ssid; - - wpa_printf(MSG_DEBUG, "Received new WPA/WPA2-PSK from WPS for STA " - MACSTR, MAC2STR(mac_addr)); - wpa_hexdump_key(MSG_DEBUG, "Per-device PSK", psk, psk_len); - - if (psk_len != PMK_LEN) { - wpa_printf(MSG_DEBUG, "Unexpected PSK length %lu", - (unsigned long) psk_len); - return -1; - } - - /* Add the new PSK to runtime PSK list */ - p = os_zalloc(sizeof(*p)); - if (p == NULL) - return -1; - os_memcpy(p->addr, mac_addr, ETH_ALEN); - os_memcpy(p->psk, psk, PMK_LEN); - - p->next = ssid->wpa_psk; - ssid->wpa_psk = p; - - if (ssid->wpa_psk_file) { - FILE *f; - char hex[PMK_LEN * 2 + 1]; - /* Add the new PSK to PSK list file */ - f = fopen(ssid->wpa_psk_file, "a"); - if (f == NULL) { - wpa_printf(MSG_DEBUG, "Failed to add the PSK to " - "'%s'", ssid->wpa_psk_file); - return -1; - } - - wpa_snprintf_hex(hex, sizeof(hex), psk, psk_len); - fprintf(f, MACSTR " %s\n", MAC2STR(mac_addr), hex); - fclose(f); - } - - return 0; -} - - -static int hostapd_wps_set_ie_cb(void *ctx, const u8 *beacon_ie, - size_t beacon_ie_len, const u8 *probe_resp_ie, - size_t probe_resp_ie_len) -{ - struct hostapd_data *hapd = ctx; - - os_free(hapd->wps_beacon_ie); - if (beacon_ie_len == 0) { - hapd->wps_beacon_ie = NULL; - hapd->wps_beacon_ie_len = 0; - } else { - hapd->wps_beacon_ie = os_malloc(beacon_ie_len); - if (hapd->wps_beacon_ie == NULL) { - hapd->wps_beacon_ie_len = 0; - return -1; - } - os_memcpy(hapd->wps_beacon_ie, beacon_ie, beacon_ie_len); - hapd->wps_beacon_ie_len = beacon_ie_len; - } - hostapd_set_wps_beacon_ie(hapd, hapd->wps_beacon_ie, - hapd->wps_beacon_ie_len); - - os_free(hapd->wps_probe_resp_ie); - if (probe_resp_ie_len == 0) { - hapd->wps_probe_resp_ie = NULL; - hapd->wps_probe_resp_ie_len = 0; - } else { - hapd->wps_probe_resp_ie = os_malloc(probe_resp_ie_len); - if (hapd->wps_probe_resp_ie == NULL) { - hapd->wps_probe_resp_ie_len = 0; - return -1; - } - os_memcpy(hapd->wps_probe_resp_ie, probe_resp_ie, - probe_resp_ie_len); - hapd->wps_probe_resp_ie_len = probe_resp_ie_len; - } - hostapd_set_wps_probe_resp_ie(hapd, hapd->wps_probe_resp_ie, - hapd->wps_probe_resp_ie_len); - - return 0; -} - - -static void hostapd_wps_pin_needed_cb(void *ctx, const u8 *uuid_e, - const struct wps_device_data *dev) -{ - struct hostapd_data *hapd = ctx; - char uuid[40], txt[400]; - int len; - if (uuid_bin2str(uuid_e, uuid, sizeof(uuid))) - return; - wpa_printf(MSG_DEBUG, "WPS: PIN needed for E-UUID %s", uuid); - len = os_snprintf(txt, sizeof(txt), WPS_EVENT_PIN_NEEDED - "%s " MACSTR " [%s|%s|%s|%s|%s|%d-%08X-%d]", - uuid, MAC2STR(dev->mac_addr), dev->device_name, - dev->manufacturer, dev->model_name, - dev->model_number, dev->serial_number, - dev->categ, dev->oui, dev->sub_categ); - if (len > 0 && len < (int) sizeof(txt)) - wpa_msg(hapd, MSG_INFO, "%s", txt); - - if (hapd->conf->wps_pin_requests) { - FILE *f; - struct os_time t; - f = fopen(hapd->conf->wps_pin_requests, "a"); - if (f == NULL) - return; - os_get_time(&t); - fprintf(f, "%ld\t%s\t" MACSTR "\t%s\t%s\t%s\t%s\t%s" - "\t%d-%08X-%d\n", - t.sec, uuid, MAC2STR(dev->mac_addr), dev->device_name, - dev->manufacturer, dev->model_name, dev->model_number, - dev->serial_number, - dev->categ, dev->oui, dev->sub_categ); - fclose(f); - } -} - - -static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr, - const u8 *uuid_e) -{ - struct hostapd_data *hapd = ctx; - char uuid[40]; - if (uuid_bin2str(uuid_e, uuid, sizeof(uuid))) - return; - wpa_msg(hapd, MSG_INFO, WPS_EVENT_REG_SUCCESS MACSTR " %s", - MAC2STR(mac_addr), uuid); -} - - -static int str_starts(const char *str, const char *start) -{ - return os_strncmp(str, start, os_strlen(start)) == 0; -} - - -static void wps_reload_config(void *eloop_data, void *user_ctx) -{ - struct hostapd_iface *iface = eloop_data; - - wpa_printf(MSG_DEBUG, "WPS: Reload configuration data"); - if (hostapd_reload_config(iface) < 0) { - wpa_printf(MSG_WARNING, "WPS: Failed to reload the updated " - "configuration"); - } -} - - -static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred) -{ - struct hostapd_data *hapd = ctx; - FILE *oconf, *nconf; - size_t len, i; - char *tmp_fname; - char buf[1024]; - int multi_bss; - int wpa; - - wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute", - cred->cred_attr, cred->cred_attr_len); - - wpa_printf(MSG_DEBUG, "WPS: Received new AP Settings"); - wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", cred->ssid, cred->ssid_len); - wpa_printf(MSG_DEBUG, "WPS: Authentication Type 0x%x", - cred->auth_type); - wpa_printf(MSG_DEBUG, "WPS: Encryption Type 0x%x", cred->encr_type); - wpa_printf(MSG_DEBUG, "WPS: Network Key Index %d", cred->key_idx); - wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key", - cred->key, cred->key_len); - wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR, - MAC2STR(cred->mac_addr)); - - if ((hapd->conf->wps_cred_processing == 1 || - hapd->conf->wps_cred_processing == 2) && cred->cred_attr) { - size_t blen = cred->cred_attr_len * 2 + 1; - char *_buf = os_malloc(blen); - if (_buf) { - wpa_snprintf_hex(_buf, blen, - cred->cred_attr, cred->cred_attr_len); - wpa_msg(hapd, MSG_INFO, "%s%s", - WPS_EVENT_NEW_AP_SETTINGS, _buf); - os_free(_buf); - } - } else - wpa_msg(hapd, MSG_INFO, WPS_EVENT_NEW_AP_SETTINGS); - - if (hapd->conf->wps_cred_processing == 1) - return 0; - - os_memcpy(hapd->wps->ssid, cred->ssid, cred->ssid_len); - hapd->wps->ssid_len = cred->ssid_len; - hapd->wps->encr_types = cred->encr_type; - hapd->wps->auth_types = cred->auth_type; - if (cred->key_len == 0) { - os_free(hapd->wps->network_key); - hapd->wps->network_key = NULL; - hapd->wps->network_key_len = 0; - } else { - if (hapd->wps->network_key == NULL || - hapd->wps->network_key_len < cred->key_len) { - hapd->wps->network_key_len = 0; - os_free(hapd->wps->network_key); - hapd->wps->network_key = os_malloc(cred->key_len); - if (hapd->wps->network_key == NULL) - return -1; - } - hapd->wps->network_key_len = cred->key_len; - os_memcpy(hapd->wps->network_key, cred->key, cred->key_len); - } - hapd->wps->wps_state = WPS_STATE_CONFIGURED; - - len = os_strlen(hapd->iface->config_fname) + 5; - tmp_fname = os_malloc(len); - if (tmp_fname == NULL) - return -1; - os_snprintf(tmp_fname, len, "%s-new", hapd->iface->config_fname); - - oconf = fopen(hapd->iface->config_fname, "r"); - if (oconf == NULL) { - wpa_printf(MSG_WARNING, "WPS: Could not open current " - "configuration file"); - os_free(tmp_fname); - return -1; - } - - nconf = fopen(tmp_fname, "w"); - if (nconf == NULL) { - wpa_printf(MSG_WARNING, "WPS: Could not write updated " - "configuration file"); - os_free(tmp_fname); - fclose(oconf); - return -1; - } - - fprintf(nconf, "# WPS configuration - START\n"); - - fprintf(nconf, "wps_state=2\n"); - - fprintf(nconf, "ssid="); - for (i = 0; i < cred->ssid_len; i++) - fputc(cred->ssid[i], nconf); - fprintf(nconf, "\n"); - - if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) && - (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK))) - wpa = 3; - else if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) - wpa = 2; - else if (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK)) - wpa = 1; - else - wpa = 0; - - if (wpa) { - char *prefix; - fprintf(nconf, "wpa=%d\n", wpa); - - fprintf(nconf, "wpa_key_mgmt="); - prefix = ""; - if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA)) { - fprintf(nconf, "WPA-EAP"); - prefix = " "; - } - if (cred->auth_type & (WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK)) - fprintf(nconf, "%sWPA-PSK", prefix); - fprintf(nconf, "\n"); - - fprintf(nconf, "wpa_pairwise="); - prefix = ""; - if (cred->encr_type & WPS_ENCR_AES) { - fprintf(nconf, "CCMP"); - prefix = " "; - } - if (cred->encr_type & WPS_ENCR_TKIP) { - fprintf(nconf, "%sTKIP", prefix); - } - fprintf(nconf, "\n"); - - if (cred->key_len >= 8 && cred->key_len < 64) { - fprintf(nconf, "wpa_passphrase="); - for (i = 0; i < cred->key_len; i++) - fputc(cred->key[i], nconf); - fprintf(nconf, "\n"); - } else if (cred->key_len == 64) { - fprintf(nconf, "wpa_psk="); - for (i = 0; i < cred->key_len; i++) - fputc(cred->key[i], nconf); - fprintf(nconf, "\n"); - } else { - wpa_printf(MSG_WARNING, "WPS: Invalid key length %lu " - "for WPA/WPA2", - (unsigned long) cred->key_len); - } - - fprintf(nconf, "auth_algs=1\n"); - } else { - if ((cred->auth_type & WPS_AUTH_OPEN) && - (cred->auth_type & WPS_AUTH_SHARED)) - fprintf(nconf, "auth_algs=3\n"); - else if (cred->auth_type & WPS_AUTH_SHARED) - fprintf(nconf, "auth_algs=2\n"); - else - fprintf(nconf, "auth_algs=1\n"); - - if (cred->encr_type & WPS_ENCR_WEP && cred->key_idx <= 4) { - int key_idx = cred->key_idx; - if (key_idx) - key_idx--; - fprintf(nconf, "wep_default_key=%d\n", key_idx); - fprintf(nconf, "wep_key%d=", key_idx); - if (cred->key_len == 10 || cred->key_len == 26) { - /* WEP key as a hex string */ - for (i = 0; i < cred->key_len; i++) - fputc(cred->key[i], nconf); - } else { - /* Raw WEP key; convert to hex */ - for (i = 0; i < cred->key_len; i++) - fprintf(nconf, "%02x", cred->key[i]); - } - fprintf(nconf, "\n"); - } - } - - fprintf(nconf, "# WPS configuration - END\n"); - - multi_bss = 0; - while (fgets(buf, sizeof(buf), oconf)) { - if (os_strncmp(buf, "bss=", 4) == 0) - multi_bss = 1; - if (!multi_bss && - (str_starts(buf, "ssid=") || - str_starts(buf, "auth_algs=") || - str_starts(buf, "wps_state=") || - str_starts(buf, "wpa=") || - str_starts(buf, "wpa_psk=") || - str_starts(buf, "wpa_pairwise=") || - str_starts(buf, "rsn_pairwise=") || - str_starts(buf, "wpa_key_mgmt=") || - str_starts(buf, "wpa_passphrase="))) { - fprintf(nconf, "#WPS# %s", buf); - } else - fprintf(nconf, "%s", buf); - } - - fclose(nconf); - fclose(oconf); - - if (rename(tmp_fname, hapd->iface->config_fname) < 0) { - wpa_printf(MSG_WARNING, "WPS: Failed to rename the updated " - "configuration file: %s", strerror(errno)); - os_free(tmp_fname); - return -1; - } - - os_free(tmp_fname); - - /* Schedule configuration reload after short period of time to allow - * EAP-WSC to be finished. - */ - eloop_register_timeout(0, 100000, wps_reload_config, hapd->iface, - NULL); - - /* TODO: dualband AP may need to update multiple configuration files */ - - wpa_printf(MSG_DEBUG, "WPS: AP configuration updated"); - - return 0; -} - - -static void hostapd_pwd_auth_fail(struct hostapd_data *hapd, - struct wps_event_pwd_auth_fail *data) -{ - FILE *f; - - if (!data->enrollee) - return; - - /* - * Registrar failed to prove its knowledge of the AP PIN. Lock AP setup - * if this happens multiple times. - */ - hapd->ap_pin_failures++; - if (hapd->ap_pin_failures < 4) - return; - - wpa_msg(hapd, MSG_INFO, WPS_EVENT_AP_SETUP_LOCKED); - hapd->wps->ap_setup_locked = 1; - - wps_registrar_update_ie(hapd->wps->registrar); - - if (hapd->conf->wps_cred_processing == 1) - return; - - f = fopen(hapd->iface->config_fname, "a"); - if (f == NULL) { - wpa_printf(MSG_WARNING, "WPS: Could not append to the current " - "configuration file"); - return; - } - - fprintf(f, "# WPS AP Setup Locked based on possible attack\n"); - fprintf(f, "ap_setup_locked=1\n"); - fclose(f); - - /* TODO: dualband AP may need to update multiple configuration files */ - - wpa_printf(MSG_DEBUG, "WPS: AP configuration updated"); -} - - -static void hostapd_wps_event_cb(void *ctx, enum wps_event event, - union wps_event_data *data) -{ - struct hostapd_data *hapd = ctx; - - if (event == WPS_EV_PWD_AUTH_FAIL) - hostapd_pwd_auth_fail(hapd, &data->pwd_auth_fail); -} - - -static void hostapd_wps_clear_ies(struct hostapd_data *hapd) -{ - os_free(hapd->wps_beacon_ie); - hapd->wps_beacon_ie = NULL; - hapd->wps_beacon_ie_len = 0; - hostapd_set_wps_beacon_ie(hapd, NULL, 0); - - os_free(hapd->wps_probe_resp_ie); - hapd->wps_probe_resp_ie = NULL; - hapd->wps_probe_resp_ie_len = 0; - hostapd_set_wps_probe_resp_ie(hapd, NULL, 0); -} - - -int hostapd_init_wps(struct hostapd_data *hapd, - struct hostapd_bss_config *conf) -{ - struct wps_context *wps; - struct wps_registrar_config cfg; - - if (conf->wps_state == 0) { - hostapd_wps_clear_ies(hapd); - return 0; - } - - wps = os_zalloc(sizeof(*wps)); - if (wps == NULL) - return -1; - - wps->cred_cb = hostapd_wps_cred_cb; - wps->event_cb = hostapd_wps_event_cb; - wps->cb_ctx = hapd; - - os_memset(&cfg, 0, sizeof(cfg)); - wps->wps_state = hapd->conf->wps_state; - wps->ap_setup_locked = hapd->conf->ap_setup_locked; - if (is_nil_uuid(hapd->conf->uuid)) { - uuid_gen_mac_addr(hapd->own_addr, wps->uuid); - wpa_hexdump(MSG_DEBUG, "WPS: UUID based on MAC address", - wps->uuid, UUID_LEN); - } else - os_memcpy(wps->uuid, hapd->conf->uuid, UUID_LEN); - wps->ssid_len = hapd->conf->ssid.ssid_len; - os_memcpy(wps->ssid, hapd->conf->ssid.ssid, wps->ssid_len); - wps->ap = 1; - os_memcpy(wps->dev.mac_addr, hapd->own_addr, ETH_ALEN); - wps->dev.device_name = hapd->conf->device_name ? - os_strdup(hapd->conf->device_name) : NULL; - wps->dev.manufacturer = hapd->conf->manufacturer ? - os_strdup(hapd->conf->manufacturer) : NULL; - wps->dev.model_name = hapd->conf->model_name ? - os_strdup(hapd->conf->model_name) : NULL; - wps->dev.model_number = hapd->conf->model_number ? - os_strdup(hapd->conf->model_number) : NULL; - wps->dev.serial_number = hapd->conf->serial_number ? - os_strdup(hapd->conf->serial_number) : NULL; - if (hapd->conf->config_methods) { - char *m = hapd->conf->config_methods; - if (os_strstr(m, "label")) - wps->config_methods |= WPS_CONFIG_LABEL; - if (os_strstr(m, "display")) - wps->config_methods |= WPS_CONFIG_DISPLAY; - if (os_strstr(m, "push_button")) - wps->config_methods |= WPS_CONFIG_PUSHBUTTON; - if (os_strstr(m, "keypad")) - wps->config_methods |= WPS_CONFIG_KEYPAD; - } - if (hapd->conf->device_type) { - char *pos; - u8 oui[4]; - /* -- */ - wps->dev.categ = atoi(hapd->conf->device_type); - pos = os_strchr(hapd->conf->device_type, '-'); - if (pos == NULL) { - wpa_printf(MSG_ERROR, "WPS: Invalid device_type"); - os_free(wps); - return -1; - } - pos++; - if (hexstr2bin(pos, oui, 4)) { - wpa_printf(MSG_ERROR, "WPS: Invalid device_type OUI"); - os_free(wps); - return -1; - } - wps->dev.oui = WPA_GET_BE32(oui); - pos = os_strchr(pos, '-'); - if (pos == NULL) { - wpa_printf(MSG_ERROR, "WPS: Invalid device_type"); - os_free(wps); - return -1; - } - pos++; - wps->dev.sub_categ = atoi(pos); - } - wps->dev.os_version = WPA_GET_BE32(hapd->conf->os_version); - wps->dev.rf_bands = hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ? - WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */ - - if (conf->wpa & WPA_PROTO_RSN) { - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) - wps->auth_types |= WPS_AUTH_WPA2PSK; - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) - wps->auth_types |= WPS_AUTH_WPA2; - - if (conf->rsn_pairwise & WPA_CIPHER_CCMP) - wps->encr_types |= WPS_ENCR_AES; - if (conf->rsn_pairwise & WPA_CIPHER_TKIP) - wps->encr_types |= WPS_ENCR_TKIP; - } - - if (conf->wpa & WPA_PROTO_WPA) { - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) - wps->auth_types |= WPS_AUTH_WPAPSK; - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) - wps->auth_types |= WPS_AUTH_WPA; - - if (conf->wpa_pairwise & WPA_CIPHER_CCMP) - wps->encr_types |= WPS_ENCR_AES; - if (conf->wpa_pairwise & WPA_CIPHER_TKIP) - wps->encr_types |= WPS_ENCR_TKIP; - } - - if (conf->ssid.security_policy == SECURITY_PLAINTEXT) { - wps->encr_types |= WPS_ENCR_NONE; - wps->auth_types |= WPS_AUTH_OPEN; - } else if (conf->ssid.security_policy == SECURITY_STATIC_WEP) { - wps->encr_types |= WPS_ENCR_WEP; - if (conf->auth_algs & WPA_AUTH_ALG_OPEN) - wps->auth_types |= WPS_AUTH_OPEN; - if (conf->auth_algs & WPA_AUTH_ALG_SHARED) - wps->auth_types |= WPS_AUTH_SHARED; - } else if (conf->ssid.security_policy == SECURITY_IEEE_802_1X) { - wps->auth_types |= WPS_AUTH_OPEN; - if (conf->default_wep_key_len) - wps->encr_types |= WPS_ENCR_WEP; - else - wps->encr_types |= WPS_ENCR_NONE; - } - - if (conf->ssid.wpa_psk_file) { - /* Use per-device PSKs */ - } else if (conf->ssid.wpa_passphrase) { - wps->network_key = (u8 *) os_strdup(conf->ssid.wpa_passphrase); - wps->network_key_len = os_strlen(conf->ssid.wpa_passphrase); - } else if (conf->ssid.wpa_psk) { - wps->network_key = os_malloc(2 * PMK_LEN + 1); - if (wps->network_key == NULL) { - os_free(wps); - return -1; - } - wpa_snprintf_hex((char *) wps->network_key, 2 * PMK_LEN + 1, - conf->ssid.wpa_psk->psk, PMK_LEN); - wps->network_key_len = 2 * PMK_LEN; - } else if (conf->ssid.wep.keys_set && conf->ssid.wep.key[0]) { - wps->network_key = os_malloc(conf->ssid.wep.len[0]); - if (wps->network_key == NULL) { - os_free(wps); - return -1; - } - os_memcpy(wps->network_key, conf->ssid.wep.key[0], - conf->ssid.wep.len[0]); - wps->network_key_len = conf->ssid.wep.len[0]; - } - - if (conf->wps_state == WPS_STATE_NOT_CONFIGURED) { - /* Override parameters to enable security by default */ - wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK; - wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP; - } - - wps->ap_settings = conf->ap_settings; - wps->ap_settings_len = conf->ap_settings_len; - - cfg.new_psk_cb = hostapd_wps_new_psk_cb; - cfg.set_ie_cb = hostapd_wps_set_ie_cb; - cfg.pin_needed_cb = hostapd_wps_pin_needed_cb; - cfg.reg_success_cb = hostapd_wps_reg_success_cb; - cfg.cb_ctx = hapd; - cfg.skip_cred_build = conf->skip_cred_build; - cfg.extra_cred = conf->extra_cred; - cfg.extra_cred_len = conf->extra_cred_len; - cfg.disable_auto_conf = (hapd->conf->wps_cred_processing == 1) && - conf->skip_cred_build; - if (conf->ssid.security_policy == SECURITY_STATIC_WEP) - cfg.static_wep_only = 1; - - wps->registrar = wps_registrar_init(wps, &cfg); - if (wps->registrar == NULL) { - printf("Failed to initialize WPS Registrar\n"); - os_free(wps->network_key); - os_free(wps); - return -1; - } - -#ifdef CONFIG_WPS_UPNP - wps->friendly_name = hapd->conf->friendly_name; - wps->manufacturer_url = hapd->conf->manufacturer_url; - wps->model_description = hapd->conf->model_description; - wps->model_url = hapd->conf->model_url; - wps->upc = hapd->conf->upc; - - if (hostapd_wps_upnp_init(hapd, wps) < 0) { - wpa_printf(MSG_ERROR, "Failed to initialize WPS UPnP"); - wps_registrar_deinit(wps->registrar); - os_free(wps->network_key); - os_free(wps); - return -1; - } -#endif /* CONFIG_WPS_UPNP */ - - hapd->wps = wps; - - return 0; -} - - -void hostapd_deinit_wps(struct hostapd_data *hapd) -{ - if (hapd->wps == NULL) - return; -#ifdef CONFIG_WPS_UPNP - hostapd_wps_upnp_deinit(hapd); -#endif /* CONFIG_WPS_UPNP */ - wps_registrar_deinit(hapd->wps->registrar); - os_free(hapd->wps->network_key); - wps_device_data_free(&hapd->wps->dev); - wps_free_pending_msgs(hapd->wps->upnp_msgs); - os_free(hapd->wps); - hapd->wps = NULL; - hostapd_wps_clear_ies(hapd); -} - - -int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid, - const char *pin, int timeout) -{ - u8 u[UUID_LEN]; - int any = 0; - - if (hapd->wps == NULL) - return -1; - if (os_strcmp(uuid, "any") == 0) - any = 1; - else if (uuid_str2bin(uuid, u)) - return -1; - return wps_registrar_add_pin(hapd->wps->registrar, any ? NULL : u, - (const u8 *) pin, os_strlen(pin), - timeout); -} - - -int hostapd_wps_button_pushed(struct hostapd_data *hapd) -{ - if (hapd->wps == NULL) - return -1; - return wps_registrar_button_pushed(hapd->wps->registrar); -} - - -void hostapd_wps_probe_req_rx(struct hostapd_data *hapd, const u8 *addr, - const u8 *ie, size_t ie_len) -{ - struct wpabuf *wps_ie; - const u8 *end, *pos, *wps; - - if (hapd->wps == NULL) - return; - - pos = ie; - end = ie + ie_len; - wps = NULL; - - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) - return; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - WPA_GET_BE32(&pos[2]) == WPS_DEV_OUI_WFA) { - wps = pos; - break; - } - pos += 2 + pos[1]; - } - - if (wps == NULL) - return; /* No WPS IE in Probe Request */ - - wps_ie = wpabuf_alloc(ie_len); - if (wps_ie == NULL) - return; - - /* There may be multiple WPS IEs in the message, so need to concatenate - * their WPS Data fields */ - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) - break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - WPA_GET_BE32(&pos[2]) == WPS_DEV_OUI_WFA) - wpabuf_put_data(wps_ie, pos + 6, pos[1] - 4); - pos += 2 + pos[1]; - } - - if (wpabuf_len(wps_ie) > 0) { - wps_registrar_probe_req_rx(hapd->wps->registrar, addr, wps_ie); -#ifdef CONFIG_WPS_UPNP - /* FIX: what exactly should be included in the WLANEvent? - * WPS attributes? Full ProbeReq frame? */ - upnp_wps_device_send_wlan_event(hapd->wps_upnp, addr, - UPNP_WPS_WLANEVENT_TYPE_PROBE, - wps_ie); -#endif /* CONFIG_WPS_UPNP */ - } - - wpabuf_free(wps_ie); -} - - -#ifdef CONFIG_WPS_UPNP - -static struct wpabuf * -hostapd_rx_req_get_device_info(void *priv, struct upnp_wps_peer *peer) -{ - struct hostapd_data *hapd = priv; - struct wps_config cfg; - struct wps_data *wps; - enum wsc_op_code op_code; - struct wpabuf *m1; - - /* - * Request for DeviceInfo, i.e., M1 TLVs. This is a start of WPS - * registration over UPnP with the AP acting as an Enrollee. It should - * be noted that this is frequently used just to get the device data, - * i.e., there may not be any intent to actually complete the - * registration. - */ - - if (peer->wps) - wps_deinit(peer->wps); - - os_memset(&cfg, 0, sizeof(cfg)); - cfg.wps = hapd->wps; - cfg.pin = (u8 *) hapd->conf->ap_pin; - cfg.pin_len = os_strlen(hapd->conf->ap_pin); - wps = wps_init(&cfg); - if (wps == NULL) - return NULL; - - m1 = wps_get_msg(wps, &op_code); - if (m1 == NULL) { - wps_deinit(wps); - return NULL; - } - - peer->wps = wps; - - return m1; -} - - -static struct wpabuf * -hostapd_rx_req_put_message(void *priv, struct upnp_wps_peer *peer, - const struct wpabuf *msg) -{ - enum wps_process_res res; - enum wsc_op_code op_code; - - /* PutMessage: msg = InMessage, return OutMessage */ - res = wps_process_msg(peer->wps, WSC_UPnP, msg); - if (res == WPS_FAILURE) - return NULL; - return wps_get_msg(peer->wps, &op_code); -} - - -static struct wpabuf * -hostapd_rx_req_get_ap_settings(void *priv, const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return NULL; -} - - -static int hostapd_rx_req_set_ap_settings(void *priv, const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return -1; -} - - -static int hostapd_rx_req_del_ap_settings(void *priv, const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return -1; -} - - -static struct wpabuf * -hostapd_rx_req_get_sta_settings(void *priv, const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return NULL; -} - - -static int hostapd_rx_req_set_sta_settings(void *priv, - const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return -1; -} - - -static int hostapd_rx_req_del_sta_settings(void *priv, - const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return -1; -} - - -static int hostapd_rx_req_put_wlan_response( - void *priv, enum upnp_wps_wlanevent_type ev_type, - const u8 *mac_addr, const struct wpabuf *msg, - enum wps_msg_type msg_type) -{ - struct hostapd_data *hapd = priv; - struct sta_info *sta; - struct upnp_pending_message *p; - - wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse ev_type=%d mac_addr=" - MACSTR, ev_type, MAC2STR(mac_addr)); - wpa_hexdump(MSG_MSGDUMP, "WPS UPnP: PutWLANResponse NewMessage", - wpabuf_head(msg), wpabuf_len(msg)); - if (ev_type != UPNP_WPS_WLANEVENT_TYPE_EAP) { - wpa_printf(MSG_DEBUG, "WPS UPnP: Ignored unexpected " - "PutWLANResponse WLANEventType %d", ev_type); - return -1; - } - - /* - * EAP response to ongoing to WPS Registration. Send it to EAP-WSC - * server implementation for delivery to the peer. - */ - - sta = ap_get_sta(hapd, mac_addr); - if (!sta) { - /* - * Workaround - Intel wsccmd uses bogus NewWLANEventMAC: - * Pick STA that is in an ongoing WPS registration without - * checking the MAC address. - */ - wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found based " - "on NewWLANEventMAC; try wildcard match"); - for (sta = hapd->sta_list; sta; sta = sta->next) { - if (sta->eapol_sm && (sta->flags & WLAN_STA_WPS)) - break; - } - } - - if (!sta) { - wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found"); - return 0; - } - - p = os_zalloc(sizeof(*p)); - if (p == NULL) - return -1; - os_memcpy(p->addr, sta->addr, ETH_ALEN); - p->msg = wpabuf_dup(msg); - p->type = msg_type; - p->next = hapd->wps->upnp_msgs; - hapd->wps->upnp_msgs = p; - - return eapol_auth_eap_pending_cb(sta->eapol_sm, sta->eapol_sm->eap); -} - - -static int hostapd_rx_req_set_selected_registrar(void *priv, - const struct wpabuf *msg) -{ - struct hostapd_data *hapd = priv; - return wps_registrar_set_selected_registrar(hapd->wps->registrar, msg); -} - - -static int hostapd_rx_req_reboot_ap(void *priv, const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return -1; -} - - -static int hostapd_rx_req_reset_ap(void *priv, const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return -1; -} - - -static int hostapd_rx_req_reboot_sta(void *priv, const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return -1; -} - - -static int hostapd_rx_req_reset_sta(void *priv, const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return -1; -} - - -static int hostapd_wps_upnp_init(struct hostapd_data *hapd, - struct wps_context *wps) -{ - struct upnp_wps_device_ctx *ctx; - - if (!hapd->conf->upnp_iface) - return 0; - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) - return -1; - - ctx->rx_req_get_device_info = hostapd_rx_req_get_device_info; - ctx->rx_req_put_message = hostapd_rx_req_put_message; - ctx->rx_req_get_ap_settings = hostapd_rx_req_get_ap_settings; - ctx->rx_req_set_ap_settings = hostapd_rx_req_set_ap_settings; - ctx->rx_req_del_ap_settings = hostapd_rx_req_del_ap_settings; - ctx->rx_req_get_sta_settings = hostapd_rx_req_get_sta_settings; - ctx->rx_req_set_sta_settings = hostapd_rx_req_set_sta_settings; - ctx->rx_req_del_sta_settings = hostapd_rx_req_del_sta_settings; - ctx->rx_req_put_wlan_response = hostapd_rx_req_put_wlan_response; - ctx->rx_req_set_selected_registrar = - hostapd_rx_req_set_selected_registrar; - ctx->rx_req_reboot_ap = hostapd_rx_req_reboot_ap; - ctx->rx_req_reset_ap = hostapd_rx_req_reset_ap; - ctx->rx_req_reboot_sta = hostapd_rx_req_reboot_sta; - ctx->rx_req_reset_sta = hostapd_rx_req_reset_sta; - - hapd->wps_upnp = upnp_wps_device_init(ctx, wps, hapd); - if (hapd->wps_upnp == NULL) { - os_free(ctx); - return -1; - } - wps->wps_upnp = hapd->wps_upnp; - - if (upnp_wps_device_start(hapd->wps_upnp, hapd->conf->upnp_iface)) { - upnp_wps_device_deinit(hapd->wps_upnp); - hapd->wps_upnp = NULL; - return -1; - } - - return 0; -} - - -static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd) -{ - upnp_wps_device_deinit(hapd->wps_upnp); -} - -#endif /* CONFIG_WPS_UPNP */ diff --git a/contrib/hostapd/hostapd/wps_hostapd.h b/contrib/hostapd/hostapd/wps_hostapd.h deleted file mode 100644 index e949bee87a..0000000000 --- a/contrib/hostapd/hostapd/wps_hostapd.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * hostapd / WPS integration - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPS_HOSTAPD_H -#define WPS_HOSTAPD_H - -#ifdef CONFIG_WPS - -int hostapd_init_wps(struct hostapd_data *hapd, - struct hostapd_bss_config *conf); -void hostapd_deinit_wps(struct hostapd_data *hapd); -int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid, - const char *pin, int timeout); -int hostapd_wps_button_pushed(struct hostapd_data *hapd); -void hostapd_wps_probe_req_rx(struct hostapd_data *hapd, const u8 *addr, - const u8 *ie, size_t ie_len); - -#else /* CONFIG_WPS */ - -static inline int hostapd_init_wps(struct hostapd_data *hapd, - struct hostapd_bss_config *conf) -{ - return 0; -} - -static inline void hostapd_deinit_wps(struct hostapd_data *hapd) -{ -} - -static inline void hostapd_wps_probe_req_rx(struct hostapd_data *hapd, - const u8 *addr, - const u8 *ie, size_t ie_len) -{ -} -#endif /* CONFIG_WPS */ - -#endif /* WPS_HOSTAPD_H */ diff --git a/contrib/hostapd/patches/openssl-0.9.8-tls-extensions.patch b/contrib/hostapd/patches/openssl-0.9.8-tls-extensions.patch deleted file mode 100644 index 44490cca22..0000000000 --- a/contrib/hostapd/patches/openssl-0.9.8-tls-extensions.patch +++ /dev/null @@ -1,429 +0,0 @@ -This patch is adding support for TLS hello extensions and externally -generated pre-shared key material to OpenSSL 0.9.8. This is -based on the patch from Alexey Kobozev -(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300). - - - -diff -uprN openssl-0.9.8.orig/include/openssl/ssl.h openssl-0.9.8/include/openssl/ssl.h ---- openssl-0.9.8.orig/include/openssl/ssl.h 2005-06-10 12:51:16.000000000 -0700 -+++ openssl-0.9.8/include/openssl/ssl.h 2005-07-19 20:02:15.000000000 -0700 -@@ -340,6 +340,7 @@ extern "C" { - * 'struct ssl_st *' function parameters used to prototype callbacks - * in SSL_CTX. */ - typedef struct ssl_st *ssl_crock_st; -+typedef struct tls_extension_st TLS_EXTENSION; - - /* used to hold info on the particular ciphers used */ - typedef struct ssl_cipher_st -@@ -361,6 +362,8 @@ DECLARE_STACK_OF(SSL_CIPHER) - typedef struct ssl_st SSL; - typedef struct ssl_ctx_st SSL_CTX; - -+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); -+ - /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ - typedef struct ssl_method_st - { -@@ -968,6 +971,15 @@ struct ssl_st - int first_packet; - int client_version; /* what was passed, used for - * SSLv3/TLS rollback check */ -+ -+ /* TLS externsions */ -+ TLS_EXTENSION *tls_extension; -+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg); -+ void *tls_extension_cb_arg; -+ -+ /* TLS pre-shared secret session resumption */ -+ tls_session_secret_cb_fn tls_session_secret_cb; -+ void *tls_session_secret_cb_arg; - }; - - #ifdef __cplusplus -@@ -1533,6 +1545,13 @@ void *SSL_COMP_get_compression_methods(v - int SSL_COMP_add_compression_method(int id,void *cm); - #endif - -+/* TLS extensions functions */ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); -+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg); -+ -+/* Pre-shared secret session resumption functions */ -+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); -+ - /* BEGIN ERROR CODES */ - /* The following lines are auto generated by the script mkerr.pl. Any changes - * made after this point may be overwritten when the script is next run. -@@ -1714,6 +1733,7 @@ void ERR_load_SSL_strings(void); - #define SSL_F_TLS1_ENC 210 - #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 - #define SSL_F_WRITE_PENDING 212 -+#define SSL_F_SSL_SET_HELLO_EXTENSION 213 - - /* Reason codes. */ - #define SSL_R_APP_DATA_IN_HANDSHAKE 100 -diff -uprN openssl-0.9.8.orig/include/openssl/tls1.h openssl-0.9.8/include/openssl/tls1.h ---- openssl-0.9.8.orig/include/openssl/tls1.h 2003-07-22 05:34:21.000000000 -0700 -+++ openssl-0.9.8/include/openssl/tls1.h 2005-07-19 20:02:15.000000000 -0700 -@@ -282,6 +282,14 @@ extern "C" { - #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ - #endif - -+/* TLS extension struct */ -+struct tls_extension_st -+{ -+ unsigned short type; -+ unsigned short length; -+ void *data; -+}; -+ - #ifdef __cplusplus - } - #endif -diff -uprN openssl-0.9.8.orig/ssl/Makefile openssl-0.9.8/ssl/Makefile ---- openssl-0.9.8.orig/ssl/Makefile 2005-05-30 16:20:30.000000000 -0700 -+++ openssl-0.9.8/ssl/Makefile 2005-07-19 20:02:15.000000000 -0700 -@@ -24,7 +24,7 @@ LIBSRC= \ - s2_meth.c s2_srvr.c s2_clnt.c s2_lib.c s2_enc.c s2_pkt.c \ - s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c \ - s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \ -- t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \ -+ t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c t1_ext.c \ - d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \ - d1_both.c d1_enc.c \ - ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \ -@@ -35,7 +35,7 @@ LIBOBJ= \ - s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \ - s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \ - s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \ -- t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o \ -+ t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o t1_ext.o \ - d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \ - d1_both.o d1_enc.o \ - ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \ -@@ -968,3 +968,4 @@ t1_srvr.o: ../include/openssl/ssl23.h .. - t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h - t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h - t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c -+t1_ext.o: t1_ext.c ssl_locl.h -diff -uprN openssl-0.9.8.orig/ssl/s3_clnt.c openssl-0.9.8/ssl/s3_clnt.c ---- openssl-0.9.8.orig/ssl/s3_clnt.c 2005-05-16 03:11:03.000000000 -0700 -+++ openssl-0.9.8/ssl/s3_clnt.c 2005-07-19 20:02:15.000000000 -0700 -@@ -606,6 +606,20 @@ int ssl3_client_hello(SSL *s) - } - *(p++)=0; /* Add the NULL method */ - -+ /* send client hello extensions if any */ -+ if (s->version >= TLS1_VERSION && s->tls_extension) -+ { -+ // set the total extensions length -+ s2n(s->tls_extension->length + 4, p); -+ -+ // put the extensions with type and length -+ s2n(s->tls_extension->type, p); -+ s2n(s->tls_extension->length, p); -+ -+ memcpy(p, s->tls_extension->data, s->tls_extension->length); -+ p+=s->tls_extension->length; -+ } -+ - l=(p-d); - d=buf; - *(d++)=SSL3_MT_CLIENT_HELLO; -@@ -628,7 +642,7 @@ int ssl3_get_server_hello(SSL *s) - STACK_OF(SSL_CIPHER) *sk; - SSL_CIPHER *c; - unsigned char *p,*d; -- int i,al,ok; -+ int i,al,ok,pre_shared; - unsigned int j; - long n; - SSL_COMP *comp; -@@ -693,7 +707,24 @@ int ssl3_get_server_hello(SSL *s) - goto f_err; - } - -- if (j != 0 && j == s->session->session_id_length -+ /* check if we want to resume the session based on external pre-shared secret */ -+ pre_shared = 0; -+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, -+ NULL, &pref_cipher, s->tls_session_secret_cb_arg)) -+ { -+ s->hit=1; -+ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j); -+ s->session->session_id_length = j; -+ memcpy(s->session->session_id, p, j); -+ pre_shared = 1; -+ } -+ } -+ -+ if ((pre_shared || j != 0) && j == s->session->session_id_length - && memcmp(p,s->session->session_id,j) == 0) - { - if(s->sid_ctx_length != s->session->sid_ctx_length -diff -uprN openssl-0.9.8.orig/ssl/s3_srvr.c openssl-0.9.8/ssl/s3_srvr.c ---- openssl-0.9.8.orig/ssl/s3_srvr.c 2005-05-22 17:32:55.000000000 -0700 -+++ openssl-0.9.8/ssl/s3_srvr.c 2005-07-19 20:02:15.000000000 -0700 -@@ -955,6 +955,75 @@ int ssl3_get_client_hello(SSL *s) - } - #endif - -+ /* Check for TLS client hello extension here */ -+ if (p < (d+n) && s->version >= TLS1_VERSION) -+ { -+ if (s->tls_extension_cb) -+ { -+ TLS_EXTENSION tls_ext; -+ unsigned short ext_total_len; -+ -+ n2s(p, ext_total_len); -+ n2s(p, tls_ext.type); -+ n2s(p, tls_ext.length); -+ -+ // sanity check in TLS extension len -+ if (tls_ext.length > (d+n) - p) -+ { -+ // just cut the lenth to packet border -+ tls_ext.length = (d+n) - p; -+ } -+ -+ tls_ext.data = p; -+ -+ // returns an alert code or 0 -+ al = s->tls_extension_cb(s, &tls_ext, s->tls_extension_cb_arg); -+ if (al != 0) -+ { -+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PEER_ERROR); -+ goto f_err; -+ } -+ } -+ } -+ -+ /* Check if we want to use external pre-shared secret for this handshake */ -+ /* for not reused session only */ -+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, -+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) -+ { -+ s->hit=1; -+ s->session->ciphers=ciphers; -+ s->session->verify_result=X509_V_OK; -+ -+ ciphers=NULL; -+ -+ /* check if some cipher was preferred by call back */ -+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); -+ if (pref_cipher == NULL) -+ { -+ al=SSL_AD_HANDSHAKE_FAILURE; -+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); -+ goto f_err; -+ } -+ -+ s->session->cipher=pref_cipher; -+ -+ if (s->cipher_list) -+ sk_SSL_CIPHER_free(s->cipher_list); -+ -+ if (s->cipher_list_by_id) -+ sk_SSL_CIPHER_free(s->cipher_list_by_id); -+ -+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); -+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); -+ } -+ } -+ - /* Given s->session->ciphers and SSL_get_ciphers, we must - * pick a cipher */ - -diff -uprN openssl-0.9.8.orig/ssl/ssl_err.c openssl-0.9.8/ssl/ssl_err.c ---- openssl-0.9.8.orig/ssl/ssl_err.c 2005-06-10 12:51:16.000000000 -0700 -+++ openssl-0.9.8/ssl/ssl_err.c 2005-07-19 20:02:15.000000000 -0700 -@@ -242,6 +242,7 @@ static ERR_STRING_DATA SSL_str_functs[]= - {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"}, - {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, - {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, -+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"}, - {0,NULL} - }; - -diff -uprN openssl-0.9.8.orig/ssl/ssl.h openssl-0.9.8/ssl/ssl.h ---- openssl-0.9.8.orig/ssl/ssl.h 2005-06-10 12:51:16.000000000 -0700 -+++ openssl-0.9.8/ssl/ssl.h 2005-07-19 20:02:15.000000000 -0700 -@@ -340,6 +340,7 @@ extern "C" { - * 'struct ssl_st *' function parameters used to prototype callbacks - * in SSL_CTX. */ - typedef struct ssl_st *ssl_crock_st; -+typedef struct tls_extension_st TLS_EXTENSION; - - /* used to hold info on the particular ciphers used */ - typedef struct ssl_cipher_st -@@ -361,6 +362,8 @@ DECLARE_STACK_OF(SSL_CIPHER) - typedef struct ssl_st SSL; - typedef struct ssl_ctx_st SSL_CTX; - -+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); -+ - /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ - typedef struct ssl_method_st - { -@@ -968,6 +971,15 @@ struct ssl_st - int first_packet; - int client_version; /* what was passed, used for - * SSLv3/TLS rollback check */ -+ -+ /* TLS externsions */ -+ TLS_EXTENSION *tls_extension; -+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg); -+ void *tls_extension_cb_arg; -+ -+ /* TLS pre-shared secret session resumption */ -+ tls_session_secret_cb_fn tls_session_secret_cb; -+ void *tls_session_secret_cb_arg; - }; - - #ifdef __cplusplus -@@ -1533,6 +1545,13 @@ void *SSL_COMP_get_compression_methods(v - int SSL_COMP_add_compression_method(int id,void *cm); - #endif - -+/* TLS extensions functions */ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); -+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg); -+ -+/* Pre-shared secret session resumption functions */ -+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); -+ - /* BEGIN ERROR CODES */ - /* The following lines are auto generated by the script mkerr.pl. Any changes - * made after this point may be overwritten when the script is next run. -@@ -1714,6 +1733,7 @@ void ERR_load_SSL_strings(void); - #define SSL_F_TLS1_ENC 210 - #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 - #define SSL_F_WRITE_PENDING 212 -+#define SSL_F_SSL_SET_HELLO_EXTENSION 213 - - /* Reason codes. */ - #define SSL_R_APP_DATA_IN_HANDSHAKE 100 -diff -uprN openssl-0.9.8.orig/ssl/ssl_sess.c openssl-0.9.8/ssl/ssl_sess.c ---- openssl-0.9.8.orig/ssl/ssl_sess.c 2005-04-29 13:10:06.000000000 -0700 -+++ openssl-0.9.8/ssl/ssl_sess.c 2005-07-19 20:02:15.000000000 -0700 -@@ -656,6 +656,15 @@ long SSL_CTX_get_timeout(const SSL_CTX * - return(s->session_timeout); - } - -+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, -+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) -+{ -+ if (s == NULL) return(0); -+ s->tls_session_secret_cb = tls_session_secret_cb; -+ s->tls_session_secret_cb_arg = arg; -+ return(1); -+} -+ - typedef struct timeout_param_st - { - SSL_CTX *ctx; -diff -uprN openssl-0.9.8.orig/ssl/t1_ext.c openssl-0.9.8/ssl/t1_ext.c ---- openssl-0.9.8.orig/ssl/t1_ext.c 1969-12-31 16:00:00.000000000 -0800 -+++ openssl-0.9.8/ssl/t1_ext.c 2005-07-19 20:03:29.000000000 -0700 -@@ -0,0 +1,48 @@ -+ -+#include -+#include "ssl_locl.h" -+ -+ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len) -+{ -+ if(s->version >= TLS1_VERSION) -+ { -+ if(s->tls_extension) -+ { -+ OPENSSL_free(s->tls_extension); -+ s->tls_extension = NULL; -+ } -+ -+ if(ext_data) -+ { -+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len); -+ if(!s->tls_extension) -+ { -+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE); -+ return 0; -+ } -+ -+ s->tls_extension->type = ext_type; -+ s->tls_extension->length = ext_len; -+ s->tls_extension->data = s->tls_extension + 1; -+ memcpy(s->tls_extension->data, ext_data, ext_len); -+ } -+ -+ return 1; -+ } -+ -+ return 0; -+} -+ -+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg) -+{ -+ if(s->version >= TLS1_VERSION) -+ { -+ s->tls_extension_cb = cb; -+ s->tls_extension_cb_arg = arg; -+ -+ return 1; -+ } -+ -+ return 0; -+} -diff -uprN openssl-0.9.8.orig/ssl/t1_lib.c openssl-0.9.8/ssl/t1_lib.c ---- openssl-0.9.8.orig/ssl/t1_lib.c 2005-04-26 09:02:40.000000000 -0700 -+++ openssl-0.9.8/ssl/t1_lib.c 2005-07-19 20:02:15.000000000 -0700 -@@ -131,6 +131,10 @@ int tls1_new(SSL *s) - - void tls1_free(SSL *s) - { -+ if(s->tls_extension) -+ { -+ OPENSSL_free(s->tls_extension); -+ } - ssl3_free(s); - } - -diff -uprN openssl-0.9.8.orig/ssl/tls1.h openssl-0.9.8/ssl/tls1.h ---- openssl-0.9.8.orig/ssl/tls1.h 2003-07-22 05:34:21.000000000 -0700 -+++ openssl-0.9.8/ssl/tls1.h 2005-07-19 20:02:15.000000000 -0700 -@@ -282,6 +282,14 @@ extern "C" { - #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ - #endif - -+/* TLS extension struct */ -+struct tls_extension_st -+{ -+ unsigned short type; -+ unsigned short length; -+ void *data; -+}; -+ - #ifdef __cplusplus - } - #endif -diff -uprN openssl-0.9.8.orig/util/ssleay.num openssl-0.9.8/util/ssleay.num ---- openssl-0.9.8.orig/util/ssleay.num 2005-05-08 17:22:02.000000000 -0700 -+++ openssl-0.9.8/util/ssleay.num 2005-07-19 20:02:15.000000000 -0700 -@@ -226,3 +226,6 @@ DTLSv1_server_method - SSL_COMP_get_compression_methods 276 EXIST:!VMS:FUNCTION:COMP - SSL_COMP_get_compress_methods 276 EXIST:VMS:FUNCTION:COMP - SSL_SESSION_get_id 277 EXIST::FUNCTION: -+SSL_set_hello_extension 278 EXIST::FUNCTION: -+SSL_set_hello_extension_cb 279 EXIST::FUNCTION: -+SSL_set_session_secret_cb 280 EXIST::FUNCTION: diff --git a/contrib/hostapd/patches/openssl-0.9.8d-tls-extensions.patch b/contrib/hostapd/patches/openssl-0.9.8d-tls-extensions.patch deleted file mode 100644 index eec6db8a13..0000000000 --- a/contrib/hostapd/patches/openssl-0.9.8d-tls-extensions.patch +++ /dev/null @@ -1,429 +0,0 @@ -This patch is adding support for TLS hello extensions and externally -generated pre-shared key material to OpenSSL 0.9.8d. This is -based on the patch from Alexey Kobozev -(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300). - - - -diff -uprN openssl-0.9.8d.orig/include/openssl/ssl.h openssl-0.9.8d/include/openssl/ssl.h ---- openssl-0.9.8d.orig/include/openssl/ssl.h 2006-06-14 06:52:49.000000000 -0700 -+++ openssl-0.9.8d/include/openssl/ssl.h 2006-12-10 08:20:02.000000000 -0800 -@@ -345,6 +345,7 @@ extern "C" { - * 'struct ssl_st *' function parameters used to prototype callbacks - * in SSL_CTX. */ - typedef struct ssl_st *ssl_crock_st; -+typedef struct tls_extension_st TLS_EXTENSION; - - /* used to hold info on the particular ciphers used */ - typedef struct ssl_cipher_st -@@ -366,6 +367,8 @@ DECLARE_STACK_OF(SSL_CIPHER) - typedef struct ssl_st SSL; - typedef struct ssl_ctx_st SSL_CTX; - -+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); -+ - /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ - typedef struct ssl_method_st - { -@@ -973,6 +976,15 @@ struct ssl_st - int first_packet; - int client_version; /* what was passed, used for - * SSLv3/TLS rollback check */ -+ -+ /* TLS externsions */ -+ TLS_EXTENSION *tls_extension; -+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg); -+ void *tls_extension_cb_arg; -+ -+ /* TLS pre-shared secret session resumption */ -+ tls_session_secret_cb_fn tls_session_secret_cb; -+ void *tls_session_secret_cb_arg; - }; - - #ifdef __cplusplus -@@ -1538,6 +1550,13 @@ void *SSL_COMP_get_compression_methods(v - int SSL_COMP_add_compression_method(int id,void *cm); - #endif - -+/* TLS extensions functions */ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); -+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg); -+ -+/* Pre-shared secret session resumption functions */ -+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); -+ - /* BEGIN ERROR CODES */ - /* The following lines are auto generated by the script mkerr.pl. Any changes - * made after this point may be overwritten when the script is next run. -@@ -1719,6 +1738,7 @@ void ERR_load_SSL_strings(void); - #define SSL_F_TLS1_ENC 210 - #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 - #define SSL_F_WRITE_PENDING 212 -+#define SSL_F_SSL_SET_HELLO_EXTENSION 213 - - /* Reason codes. */ - #define SSL_R_APP_DATA_IN_HANDSHAKE 100 -diff -uprN openssl-0.9.8d.orig/include/openssl/tls1.h openssl-0.9.8d/include/openssl/tls1.h ---- openssl-0.9.8d.orig/include/openssl/tls1.h 2006-06-14 10:52:01.000000000 -0700 -+++ openssl-0.9.8d/include/openssl/tls1.h 2006-12-10 08:20:02.000000000 -0800 -@@ -296,6 +296,14 @@ extern "C" { - #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ - #endif - -+/* TLS extension struct */ -+struct tls_extension_st -+{ -+ unsigned short type; -+ unsigned short length; -+ void *data; -+}; -+ - #ifdef __cplusplus - } - #endif -diff -uprN openssl-0.9.8d.orig/ssl/Makefile openssl-0.9.8d/ssl/Makefile ---- openssl-0.9.8d.orig/ssl/Makefile 2006-02-03 17:49:35.000000000 -0800 -+++ openssl-0.9.8d/ssl/Makefile 2006-12-10 08:20:02.000000000 -0800 -@@ -24,7 +24,7 @@ LIBSRC= \ - s2_meth.c s2_srvr.c s2_clnt.c s2_lib.c s2_enc.c s2_pkt.c \ - s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c \ - s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \ -- t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \ -+ t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c t1_ext.c \ - d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \ - d1_both.c d1_enc.c \ - ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \ -@@ -35,7 +35,7 @@ LIBOBJ= \ - s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \ - s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \ - s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \ -- t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o \ -+ t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o t1_ext.o \ - d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \ - d1_both.o d1_enc.o \ - ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \ -@@ -968,3 +968,4 @@ t1_srvr.o: ../include/openssl/ssl23.h .. - t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h - t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h - t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c -+t1_ext.o: t1_ext.c ssl_locl.h -diff -uprN openssl-0.9.8d.orig/ssl/s3_clnt.c openssl-0.9.8d/ssl/s3_clnt.c ---- openssl-0.9.8d.orig/ssl/s3_clnt.c 2005-12-12 23:41:46.000000000 -0800 -+++ openssl-0.9.8d/ssl/s3_clnt.c 2006-12-10 08:20:02.000000000 -0800 -@@ -601,6 +601,20 @@ int ssl3_client_hello(SSL *s) - #endif - *(p++)=0; /* Add the NULL method */ - -+ /* send client hello extensions if any */ -+ if (s->version >= TLS1_VERSION && s->tls_extension) -+ { -+ // set the total extensions length -+ s2n(s->tls_extension->length + 4, p); -+ -+ // put the extensions with type and length -+ s2n(s->tls_extension->type, p); -+ s2n(s->tls_extension->length, p); -+ -+ memcpy(p, s->tls_extension->data, s->tls_extension->length); -+ p+=s->tls_extension->length; -+ } -+ - l=(p-d); - d=buf; - *(d++)=SSL3_MT_CLIENT_HELLO; -@@ -623,7 +637,7 @@ int ssl3_get_server_hello(SSL *s) - STACK_OF(SSL_CIPHER) *sk; - SSL_CIPHER *c; - unsigned char *p,*d; -- int i,al,ok; -+ int i,al,ok,pre_shared; - unsigned int j; - long n; - #ifndef OPENSSL_NO_COMP -@@ -690,7 +704,24 @@ int ssl3_get_server_hello(SSL *s) - goto f_err; - } - -- if (j != 0 && j == s->session->session_id_length -+ /* check if we want to resume the session based on external pre-shared secret */ -+ pre_shared = 0; -+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, -+ NULL, &pref_cipher, s->tls_session_secret_cb_arg)) -+ { -+ s->hit=1; -+ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j); -+ s->session->session_id_length = j; -+ memcpy(s->session->session_id, p, j); -+ pre_shared = 1; -+ } -+ } -+ -+ if ((pre_shared || j != 0) && j == s->session->session_id_length - && memcmp(p,s->session->session_id,j) == 0) - { - if(s->sid_ctx_length != s->session->sid_ctx_length -diff -uprN openssl-0.9.8d.orig/ssl/s3_srvr.c openssl-0.9.8d/ssl/s3_srvr.c ---- openssl-0.9.8d.orig/ssl/s3_srvr.c 2006-09-28 04:29:03.000000000 -0700 -+++ openssl-0.9.8d/ssl/s3_srvr.c 2006-12-10 08:20:02.000000000 -0800 -@@ -943,6 +943,75 @@ int ssl3_get_client_hello(SSL *s) - } - #endif - -+ /* Check for TLS client hello extension here */ -+ if (p < (d+n) && s->version >= TLS1_VERSION) -+ { -+ if (s->tls_extension_cb) -+ { -+ TLS_EXTENSION tls_ext; -+ unsigned short ext_total_len; -+ -+ n2s(p, ext_total_len); -+ n2s(p, tls_ext.type); -+ n2s(p, tls_ext.length); -+ -+ // sanity check in TLS extension len -+ if (tls_ext.length > (d+n) - p) -+ { -+ // just cut the lenth to packet border -+ tls_ext.length = (d+n) - p; -+ } -+ -+ tls_ext.data = p; -+ -+ // returns an alert code or 0 -+ al = s->tls_extension_cb(s, &tls_ext, s->tls_extension_cb_arg); -+ if (al != 0) -+ { -+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PEER_ERROR); -+ goto f_err; -+ } -+ } -+ } -+ -+ /* Check if we want to use external pre-shared secret for this handshake */ -+ /* for not reused session only */ -+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, -+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) -+ { -+ s->hit=1; -+ s->session->ciphers=ciphers; -+ s->session->verify_result=X509_V_OK; -+ -+ ciphers=NULL; -+ -+ /* check if some cipher was preferred by call back */ -+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); -+ if (pref_cipher == NULL) -+ { -+ al=SSL_AD_HANDSHAKE_FAILURE; -+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); -+ goto f_err; -+ } -+ -+ s->session->cipher=pref_cipher; -+ -+ if (s->cipher_list) -+ sk_SSL_CIPHER_free(s->cipher_list); -+ -+ if (s->cipher_list_by_id) -+ sk_SSL_CIPHER_free(s->cipher_list_by_id); -+ -+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); -+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); -+ } -+ } -+ - /* Given s->session->ciphers and SSL_get_ciphers, we must - * pick a cipher */ - -diff -uprN openssl-0.9.8d.orig/ssl/ssl.h openssl-0.9.8d/ssl/ssl.h ---- openssl-0.9.8d.orig/ssl/ssl.h 2006-06-14 06:52:49.000000000 -0700 -+++ openssl-0.9.8d/ssl/ssl.h 2006-12-10 08:20:02.000000000 -0800 -@@ -345,6 +345,7 @@ extern "C" { - * 'struct ssl_st *' function parameters used to prototype callbacks - * in SSL_CTX. */ - typedef struct ssl_st *ssl_crock_st; -+typedef struct tls_extension_st TLS_EXTENSION; - - /* used to hold info on the particular ciphers used */ - typedef struct ssl_cipher_st -@@ -366,6 +367,8 @@ DECLARE_STACK_OF(SSL_CIPHER) - typedef struct ssl_st SSL; - typedef struct ssl_ctx_st SSL_CTX; - -+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); -+ - /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ - typedef struct ssl_method_st - { -@@ -973,6 +976,15 @@ struct ssl_st - int first_packet; - int client_version; /* what was passed, used for - * SSLv3/TLS rollback check */ -+ -+ /* TLS externsions */ -+ TLS_EXTENSION *tls_extension; -+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg); -+ void *tls_extension_cb_arg; -+ -+ /* TLS pre-shared secret session resumption */ -+ tls_session_secret_cb_fn tls_session_secret_cb; -+ void *tls_session_secret_cb_arg; - }; - - #ifdef __cplusplus -@@ -1538,6 +1550,13 @@ void *SSL_COMP_get_compression_methods(v - int SSL_COMP_add_compression_method(int id,void *cm); - #endif - -+/* TLS extensions functions */ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); -+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg); -+ -+/* Pre-shared secret session resumption functions */ -+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); -+ - /* BEGIN ERROR CODES */ - /* The following lines are auto generated by the script mkerr.pl. Any changes - * made after this point may be overwritten when the script is next run. -@@ -1719,6 +1738,7 @@ void ERR_load_SSL_strings(void); - #define SSL_F_TLS1_ENC 210 - #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 - #define SSL_F_WRITE_PENDING 212 -+#define SSL_F_SSL_SET_HELLO_EXTENSION 213 - - /* Reason codes. */ - #define SSL_R_APP_DATA_IN_HANDSHAKE 100 -diff -uprN openssl-0.9.8d.orig/ssl/ssl_err.c openssl-0.9.8d/ssl/ssl_err.c ---- openssl-0.9.8d.orig/ssl/ssl_err.c 2006-01-08 13:52:46.000000000 -0800 -+++ openssl-0.9.8d/ssl/ssl_err.c 2006-12-10 08:20:02.000000000 -0800 -@@ -242,6 +242,7 @@ static ERR_STRING_DATA SSL_str_functs[]= - {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"}, - {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, - {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, -+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"}, - {0,NULL} - }; - -diff -uprN openssl-0.9.8d.orig/ssl/ssl_sess.c openssl-0.9.8d/ssl/ssl_sess.c ---- openssl-0.9.8d.orig/ssl/ssl_sess.c 2005-12-30 15:51:57.000000000 -0800 -+++ openssl-0.9.8d/ssl/ssl_sess.c 2006-12-10 08:20:02.000000000 -0800 -@@ -656,6 +656,15 @@ long SSL_CTX_get_timeout(const SSL_CTX * - return(s->session_timeout); - } - -+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, -+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) -+{ -+ if (s == NULL) return(0); -+ s->tls_session_secret_cb = tls_session_secret_cb; -+ s->tls_session_secret_cb_arg = arg; -+ return(1); -+} -+ - typedef struct timeout_param_st - { - SSL_CTX *ctx; -diff -uprN openssl-0.9.8d.orig/ssl/t1_ext.c openssl-0.9.8d/ssl/t1_ext.c ---- openssl-0.9.8d.orig/ssl/t1_ext.c 1969-12-31 16:00:00.000000000 -0800 -+++ openssl-0.9.8d/ssl/t1_ext.c 2006-12-10 08:20:02.000000000 -0800 -@@ -0,0 +1,48 @@ -+ -+#include -+#include "ssl_locl.h" -+ -+ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len) -+{ -+ if(s->version >= TLS1_VERSION) -+ { -+ if(s->tls_extension) -+ { -+ OPENSSL_free(s->tls_extension); -+ s->tls_extension = NULL; -+ } -+ -+ if(ext_data) -+ { -+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len); -+ if(!s->tls_extension) -+ { -+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE); -+ return 0; -+ } -+ -+ s->tls_extension->type = ext_type; -+ s->tls_extension->length = ext_len; -+ s->tls_extension->data = s->tls_extension + 1; -+ memcpy(s->tls_extension->data, ext_data, ext_len); -+ } -+ -+ return 1; -+ } -+ -+ return 0; -+} -+ -+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg) -+{ -+ if(s->version >= TLS1_VERSION) -+ { -+ s->tls_extension_cb = cb; -+ s->tls_extension_cb_arg = arg; -+ -+ return 1; -+ } -+ -+ return 0; -+} -diff -uprN openssl-0.9.8d.orig/ssl/t1_lib.c openssl-0.9.8d/ssl/t1_lib.c ---- openssl-0.9.8d.orig/ssl/t1_lib.c 2005-08-05 16:52:07.000000000 -0700 -+++ openssl-0.9.8d/ssl/t1_lib.c 2006-12-10 08:20:02.000000000 -0800 -@@ -97,6 +97,10 @@ int tls1_new(SSL *s) - - void tls1_free(SSL *s) - { -+ if(s->tls_extension) -+ { -+ OPENSSL_free(s->tls_extension); -+ } - ssl3_free(s); - } - -diff -uprN openssl-0.9.8d.orig/ssl/tls1.h openssl-0.9.8d/ssl/tls1.h ---- openssl-0.9.8d.orig/ssl/tls1.h 2006-06-14 10:52:01.000000000 -0700 -+++ openssl-0.9.8d/ssl/tls1.h 2006-12-10 08:20:02.000000000 -0800 -@@ -296,6 +296,14 @@ extern "C" { - #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ - #endif - -+/* TLS extension struct */ -+struct tls_extension_st -+{ -+ unsigned short type; -+ unsigned short length; -+ void *data; -+}; -+ - #ifdef __cplusplus - } - #endif -diff -uprN openssl-0.9.8d.orig/util/ssleay.num openssl-0.9.8d/util/ssleay.num ---- openssl-0.9.8d.orig/util/ssleay.num 2005-05-08 17:22:02.000000000 -0700 -+++ openssl-0.9.8d/util/ssleay.num 2006-12-10 08:20:02.000000000 -0800 -@@ -226,3 +226,6 @@ DTLSv1_server_method - SSL_COMP_get_compression_methods 276 EXIST:!VMS:FUNCTION:COMP - SSL_COMP_get_compress_methods 276 EXIST:VMS:FUNCTION:COMP - SSL_SESSION_get_id 277 EXIST::FUNCTION: -+SSL_set_hello_extension 278 EXIST::FUNCTION: -+SSL_set_hello_extension_cb 279 EXIST::FUNCTION: -+SSL_set_session_secret_cb 280 EXIST::FUNCTION: diff --git a/contrib/hostapd/patches/openssl-0.9.8e-tls-extensions.patch b/contrib/hostapd/patches/openssl-0.9.8e-tls-extensions.patch deleted file mode 100644 index ede053f779..0000000000 --- a/contrib/hostapd/patches/openssl-0.9.8e-tls-extensions.patch +++ /dev/null @@ -1,353 +0,0 @@ -This patch is adding support for TLS hello extensions and externally -generated pre-shared key material to OpenSSL 0.9.8e. This is -based on the patch from Alexey Kobozev -(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300). - - - -diff -uprN openssl-0.9.8e.orig/ssl/Makefile openssl-0.9.8e/ssl/Makefile ---- openssl-0.9.8e.orig/ssl/Makefile 2006-02-03 17:49:35.000000000 -0800 -+++ openssl-0.9.8e/ssl/Makefile 2007-03-22 20:23:19.000000000 -0700 -@@ -24,7 +24,7 @@ LIBSRC= \ - s2_meth.c s2_srvr.c s2_clnt.c s2_lib.c s2_enc.c s2_pkt.c \ - s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c \ - s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \ -- t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \ -+ t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c t1_ext.c \ - d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \ - d1_both.c d1_enc.c \ - ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \ -@@ -35,7 +35,7 @@ LIBOBJ= \ - s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \ - s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \ - s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \ -- t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o \ -+ t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o t1_ext.o \ - d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \ - d1_both.o d1_enc.o \ - ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \ -@@ -968,3 +968,4 @@ t1_srvr.o: ../include/openssl/ssl23.h .. - t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h - t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h - t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c -+t1_ext.o: t1_ext.c ssl_locl.h -diff -uprN openssl-0.9.8e.orig/ssl/s3_clnt.c openssl-0.9.8e/ssl/s3_clnt.c ---- openssl-0.9.8e.orig/ssl/s3_clnt.c 2006-09-28 05:23:15.000000000 -0700 -+++ openssl-0.9.8e/ssl/s3_clnt.c 2007-03-22 20:23:19.000000000 -0700 -@@ -601,6 +601,20 @@ int ssl3_client_hello(SSL *s) - #endif - *(p++)=0; /* Add the NULL method */ - -+ /* send client hello extensions if any */ -+ if (s->version >= TLS1_VERSION && s->tls_extension) -+ { -+ // set the total extensions length -+ s2n(s->tls_extension->length + 4, p); -+ -+ // put the extensions with type and length -+ s2n(s->tls_extension->type, p); -+ s2n(s->tls_extension->length, p); -+ -+ memcpy(p, s->tls_extension->data, s->tls_extension->length); -+ p+=s->tls_extension->length; -+ } -+ - l=(p-d); - d=buf; - *(d++)=SSL3_MT_CLIENT_HELLO; -@@ -623,7 +637,7 @@ int ssl3_get_server_hello(SSL *s) - STACK_OF(SSL_CIPHER) *sk; - SSL_CIPHER *c; - unsigned char *p,*d; -- int i,al,ok; -+ int i,al,ok,pre_shared; - unsigned int j; - long n; - #ifndef OPENSSL_NO_COMP -@@ -690,7 +704,24 @@ int ssl3_get_server_hello(SSL *s) - goto f_err; - } - -- if (j != 0 && j == s->session->session_id_length -+ /* check if we want to resume the session based on external pre-shared secret */ -+ pre_shared = 0; -+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, -+ NULL, &pref_cipher, s->tls_session_secret_cb_arg)) -+ { -+ s->hit=1; -+ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j); -+ s->session->session_id_length = j; -+ memcpy(s->session->session_id, p, j); -+ pre_shared = 1; -+ } -+ } -+ -+ if ((pre_shared || j != 0) && j == s->session->session_id_length - && memcmp(p,s->session->session_id,j) == 0) - { - if(s->sid_ctx_length != s->session->sid_ctx_length -diff -uprN openssl-0.9.8e.orig/ssl/s3_srvr.c openssl-0.9.8e/ssl/s3_srvr.c ---- openssl-0.9.8e.orig/ssl/s3_srvr.c 2007-02-07 12:36:40.000000000 -0800 -+++ openssl-0.9.8e/ssl/s3_srvr.c 2007-03-22 20:23:19.000000000 -0700 -@@ -945,6 +945,75 @@ int ssl3_get_client_hello(SSL *s) - } - #endif - -+ /* Check for TLS client hello extension here */ -+ if (p < (d+n) && s->version >= TLS1_VERSION) -+ { -+ if (s->tls_extension_cb) -+ { -+ TLS_EXTENSION tls_ext; -+ unsigned short ext_total_len; -+ -+ n2s(p, ext_total_len); -+ n2s(p, tls_ext.type); -+ n2s(p, tls_ext.length); -+ -+ // sanity check in TLS extension len -+ if (tls_ext.length > (d+n) - p) -+ { -+ // just cut the lenth to packet border -+ tls_ext.length = (d+n) - p; -+ } -+ -+ tls_ext.data = p; -+ -+ // returns an alert code or 0 -+ al = s->tls_extension_cb(s, &tls_ext, s->tls_extension_cb_arg); -+ if (al != 0) -+ { -+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PEER_ERROR); -+ goto f_err; -+ } -+ } -+ } -+ -+ /* Check if we want to use external pre-shared secret for this handshake */ -+ /* for not reused session only */ -+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, -+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) -+ { -+ s->hit=1; -+ s->session->ciphers=ciphers; -+ s->session->verify_result=X509_V_OK; -+ -+ ciphers=NULL; -+ -+ /* check if some cipher was preferred by call back */ -+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); -+ if (pref_cipher == NULL) -+ { -+ al=SSL_AD_HANDSHAKE_FAILURE; -+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); -+ goto f_err; -+ } -+ -+ s->session->cipher=pref_cipher; -+ -+ if (s->cipher_list) -+ sk_SSL_CIPHER_free(s->cipher_list); -+ -+ if (s->cipher_list_by_id) -+ sk_SSL_CIPHER_free(s->cipher_list_by_id); -+ -+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); -+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); -+ } -+ } -+ - /* Given s->session->ciphers and SSL_get_ciphers, we must - * pick a cipher */ - -diff -uprN openssl-0.9.8e.orig/ssl/ssl.h openssl-0.9.8e/ssl/ssl.h ---- openssl-0.9.8e.orig/ssl/ssl.h 2007-02-19 09:55:07.000000000 -0800 -+++ openssl-0.9.8e/ssl/ssl.h 2007-03-22 20:23:19.000000000 -0700 -@@ -345,6 +345,7 @@ extern "C" { - * 'struct ssl_st *' function parameters used to prototype callbacks - * in SSL_CTX. */ - typedef struct ssl_st *ssl_crock_st; -+typedef struct tls_extension_st TLS_EXTENSION; - - /* used to hold info on the particular ciphers used */ - typedef struct ssl_cipher_st -@@ -366,6 +367,8 @@ DECLARE_STACK_OF(SSL_CIPHER) - typedef struct ssl_st SSL; - typedef struct ssl_ctx_st SSL_CTX; - -+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); -+ - /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ - typedef struct ssl_method_st - { -@@ -973,6 +976,15 @@ struct ssl_st - int first_packet; - int client_version; /* what was passed, used for - * SSLv3/TLS rollback check */ -+ -+ /* TLS externsions */ -+ TLS_EXTENSION *tls_extension; -+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg); -+ void *tls_extension_cb_arg; -+ -+ /* TLS pre-shared secret session resumption */ -+ tls_session_secret_cb_fn tls_session_secret_cb; -+ void *tls_session_secret_cb_arg; - }; - - #ifdef __cplusplus -@@ -1538,6 +1550,13 @@ void *SSL_COMP_get_compression_methods(v - int SSL_COMP_add_compression_method(int id,void *cm); - #endif - -+/* TLS extensions functions */ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); -+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg); -+ -+/* Pre-shared secret session resumption functions */ -+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); -+ - /* BEGIN ERROR CODES */ - /* The following lines are auto generated by the script mkerr.pl. Any changes - * made after this point may be overwritten when the script is next run. -@@ -1719,6 +1738,7 @@ void ERR_load_SSL_strings(void); - #define SSL_F_TLS1_ENC 210 - #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 - #define SSL_F_WRITE_PENDING 212 -+#define SSL_F_SSL_SET_HELLO_EXTENSION 213 - - /* Reason codes. */ - #define SSL_R_APP_DATA_IN_HANDSHAKE 100 -diff -uprN openssl-0.9.8e.orig/ssl/ssl_err.c openssl-0.9.8e/ssl/ssl_err.c ---- openssl-0.9.8e.orig/ssl/ssl_err.c 2006-11-21 12:14:46.000000000 -0800 -+++ openssl-0.9.8e/ssl/ssl_err.c 2007-03-22 20:23:19.000000000 -0700 -@@ -242,6 +242,7 @@ static ERR_STRING_DATA SSL_str_functs[]= - {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"}, - {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, - {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, -+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"}, - {0,NULL} - }; - -diff -uprN openssl-0.9.8e.orig/ssl/ssl_sess.c openssl-0.9.8e/ssl/ssl_sess.c ---- openssl-0.9.8e.orig/ssl/ssl_sess.c 2007-02-10 02:40:24.000000000 -0800 -+++ openssl-0.9.8e/ssl/ssl_sess.c 2007-03-22 20:23:19.000000000 -0700 -@@ -656,6 +656,15 @@ long SSL_CTX_get_timeout(const SSL_CTX * - return(s->session_timeout); - } - -+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, -+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) -+{ -+ if (s == NULL) return(0); -+ s->tls_session_secret_cb = tls_session_secret_cb; -+ s->tls_session_secret_cb_arg = arg; -+ return(1); -+} -+ - typedef struct timeout_param_st - { - SSL_CTX *ctx; -diff -uprN openssl-0.9.8e.orig/ssl/t1_ext.c openssl-0.9.8e/ssl/t1_ext.c ---- openssl-0.9.8e.orig/ssl/t1_ext.c 1969-12-31 16:00:00.000000000 -0800 -+++ openssl-0.9.8e/ssl/t1_ext.c 2007-03-22 20:23:19.000000000 -0700 -@@ -0,0 +1,48 @@ -+ -+#include -+#include "ssl_locl.h" -+ -+ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len) -+{ -+ if(s->version >= TLS1_VERSION) -+ { -+ if(s->tls_extension) -+ { -+ OPENSSL_free(s->tls_extension); -+ s->tls_extension = NULL; -+ } -+ -+ if(ext_data) -+ { -+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len); -+ if(!s->tls_extension) -+ { -+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE); -+ return 0; -+ } -+ -+ s->tls_extension->type = ext_type; -+ s->tls_extension->length = ext_len; -+ s->tls_extension->data = s->tls_extension + 1; -+ memcpy(s->tls_extension->data, ext_data, ext_len); -+ } -+ -+ return 1; -+ } -+ -+ return 0; -+} -+ -+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg) -+{ -+ if(s->version >= TLS1_VERSION) -+ { -+ s->tls_extension_cb = cb; -+ s->tls_extension_cb_arg = arg; -+ -+ return 1; -+ } -+ -+ return 0; -+} -diff -uprN openssl-0.9.8e.orig/ssl/t1_lib.c openssl-0.9.8e/ssl/t1_lib.c ---- openssl-0.9.8e.orig/ssl/t1_lib.c 2007-01-21 08:07:25.000000000 -0800 -+++ openssl-0.9.8e/ssl/t1_lib.c 2007-03-22 20:23:19.000000000 -0700 -@@ -97,6 +97,10 @@ int tls1_new(SSL *s) - - void tls1_free(SSL *s) - { -+ if(s->tls_extension) -+ { -+ OPENSSL_free(s->tls_extension); -+ } - ssl3_free(s); - } - -diff -uprN openssl-0.9.8e.orig/ssl/tls1.h openssl-0.9.8e/ssl/tls1.h ---- openssl-0.9.8e.orig/ssl/tls1.h 2006-06-14 10:52:01.000000000 -0700 -+++ openssl-0.9.8e/ssl/tls1.h 2007-03-22 20:23:19.000000000 -0700 -@@ -296,6 +296,14 @@ extern "C" { - #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ - #endif - -+/* TLS extension struct */ -+struct tls_extension_st -+{ -+ unsigned short type; -+ unsigned short length; -+ void *data; -+}; -+ - #ifdef __cplusplus - } - #endif -diff -uprN openssl-0.9.8e.orig/util/ssleay.num openssl-0.9.8e/util/ssleay.num ---- openssl-0.9.8e.orig/util/ssleay.num 2006-11-30 05:04:43.000000000 -0800 -+++ openssl-0.9.8e/util/ssleay.num 2007-03-22 20:24:07.000000000 -0700 -@@ -238,3 +238,6 @@ SSL_CTX_set_info_callback - SSL_CTX_sess_get_new_cb 287 EXIST::FUNCTION: - SSL_CTX_get_client_cert_cb 288 EXIST::FUNCTION: - SSL_CTX_sess_get_remove_cb 289 EXIST::FUNCTION: -+SSL_set_hello_extension 290 EXIST::FUNCTION: -+SSL_set_hello_extension_cb 291 EXIST::FUNCTION: -+SSL_set_session_secret_cb 292 EXIST::FUNCTION: diff --git a/contrib/hostapd/patches/openssl-0.9.8g-tls-extensions.patch b/contrib/hostapd/patches/openssl-0.9.8g-tls-extensions.patch deleted file mode 100644 index 8ccbfaa29d..0000000000 --- a/contrib/hostapd/patches/openssl-0.9.8g-tls-extensions.patch +++ /dev/null @@ -1,330 +0,0 @@ -This patch adds support for TLS SessionTicket extension (RFC 5077) for -the parts used by EAP-FAST (RFC 4851). - -This is based on the patch from Alexey Kobozev -(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300). - -OpenSSL 0.9.8g does not enable TLS extension support by default, so it -will need to be enabled by adding enable-tlsext to config script -command line. - - -diff -upr openssl-0.9.8g.orig/ssl/s3_clnt.c openssl-0.9.8g/ssl/s3_clnt.c ---- openssl-0.9.8g.orig/ssl/s3_clnt.c 2007-08-31 03:28:51.000000000 +0300 -+++ openssl-0.9.8g/ssl/s3_clnt.c 2008-04-15 17:11:46.000000000 +0300 -@@ -727,6 +727,20 @@ int ssl3_get_server_hello(SSL *s) - goto f_err; - } - -+#ifndef OPENSSL_NO_TLSEXT -+ /* check if we want to resume the session based on external pre-shared secret */ -+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, -+ NULL, &pref_cipher, s->tls_session_secret_cb_arg)) -+ { -+ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j); -+ } -+ } -+#endif /* OPENSSL_NO_TLSEXT */ -+ - if (j != 0 && j == s->session->session_id_length - && memcmp(p,s->session->session_id,j) == 0) - { -diff -upr openssl-0.9.8g.orig/ssl/s3_srvr.c openssl-0.9.8g/ssl/s3_srvr.c ---- openssl-0.9.8g.orig/ssl/s3_srvr.c 2007-09-30 21:55:59.000000000 +0300 -+++ openssl-0.9.8g/ssl/s3_srvr.c 2008-04-15 17:10:37.000000000 +0300 -@@ -928,6 +928,59 @@ int ssl3_get_client_hello(SSL *s) - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); - goto err; - } -+ -+ /* Check if we want to use external pre-shared secret for this -+ * handshake for not reused session only. We need to generate -+ * server_random before calling tls_session_secret_cb in order to allow -+ * SessionTicket processing to use it in key derivation. */ -+ { -+ unsigned long Time; -+ unsigned char *pos; -+ Time=(unsigned long)time(NULL); /* Time */ -+ pos=s->s3->server_random; -+ l2n(Time,pos); -+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0) -+ { -+ al=SSL_AD_INTERNAL_ERROR; -+ goto f_err; -+ } -+ } -+ -+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, -+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) -+ { -+ s->hit=1; -+ s->session->ciphers=ciphers; -+ s->session->verify_result=X509_V_OK; -+ -+ ciphers=NULL; -+ -+ /* check if some cipher was preferred by call back */ -+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); -+ if (pref_cipher == NULL) -+ { -+ al=SSL_AD_HANDSHAKE_FAILURE; -+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); -+ goto f_err; -+ } -+ -+ s->session->cipher=pref_cipher; -+ -+ if (s->cipher_list) -+ sk_SSL_CIPHER_free(s->cipher_list); -+ -+ if (s->cipher_list_by_id) -+ sk_SSL_CIPHER_free(s->cipher_list_by_id); -+ -+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); -+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); -+ } -+ } - #endif - /* Worst case, we will use the NULL compression, but if we have other - * options, we will now look for them. We have i-1 compression -@@ -1066,16 +1119,22 @@ int ssl3_send_server_hello(SSL *s) - unsigned char *buf; - unsigned char *p,*d; - int i,sl; -- unsigned long l,Time; -+ unsigned long l; -+#ifdef OPENSSL_NO_TLSEXT -+ unsigned long Time; -+#endif - - if (s->state == SSL3_ST_SW_SRVR_HELLO_A) - { - buf=(unsigned char *)s->init_buf->data; -+#ifdef OPENSSL_NO_TLSEXT - p=s->s3->server_random; -+ /* Generate server_random if it was not needed previously */ - Time=(unsigned long)time(NULL); /* Time */ - l2n(Time,p); - if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0) - return -1; -+#endif - /* Do the message type and length last */ - d=p= &(buf[4]); - -diff -upr openssl-0.9.8g.orig/ssl/ssl.h openssl-0.9.8g/ssl/ssl.h ---- openssl-0.9.8g.orig/ssl/ssl.h 2007-10-19 10:42:38.000000000 +0300 -+++ openssl-0.9.8g/ssl/ssl.h 2008-04-15 17:10:37.000000000 +0300 -@@ -342,6 +342,7 @@ extern "C" { - * 'struct ssl_st *' function parameters used to prototype callbacks - * in SSL_CTX. */ - typedef struct ssl_st *ssl_crock_st; -+typedef struct tls_extension_st TLS_EXTENSION; - - /* used to hold info on the particular ciphers used */ - typedef struct ssl_cipher_st -@@ -363,6 +364,8 @@ DECLARE_STACK_OF(SSL_CIPHER) - typedef struct ssl_st SSL; - typedef struct ssl_ctx_st SSL_CTX; - -+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); -+ - /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ - typedef struct ssl_method_st - { -@@ -1004,6 +1007,14 @@ struct ssl_st - */ - /* RFC4507 session ticket expected to be received or sent */ - int tlsext_ticket_expected; -+ -+ /* TLS extensions */ -+ TLS_EXTENSION *tls_extension; -+ -+ /* TLS pre-shared secret session resumption */ -+ tls_session_secret_cb_fn tls_session_secret_cb; -+ void *tls_session_secret_cb_arg; -+ - SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */ - #define session_ctx initial_ctx - #else -@@ -1589,6 +1600,12 @@ void *SSL_COMP_get_compression_methods(v - int SSL_COMP_add_compression_method(int id,void *cm); - #endif - -+/* TLS extensions functions */ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); -+ -+/* Pre-shared secret session resumption functions */ -+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); -+ - /* BEGIN ERROR CODES */ - /* The following lines are auto generated by the script mkerr.pl. Any changes - * made after this point may be overwritten when the script is next run. -@@ -1778,6 +1795,7 @@ void ERR_load_SSL_strings(void); - #define SSL_F_TLS1_ENC 210 - #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 - #define SSL_F_WRITE_PENDING 212 -+#define SSL_F_SSL_SET_HELLO_EXTENSION 213 - - /* Reason codes. */ - #define SSL_R_APP_DATA_IN_HANDSHAKE 100 -diff -upr openssl-0.9.8g.orig/ssl/ssl_err.c openssl-0.9.8g/ssl/ssl_err.c ---- openssl-0.9.8g.orig/ssl/ssl_err.c 2007-10-11 17:36:59.000000000 +0300 -+++ openssl-0.9.8g/ssl/ssl_err.c 2008-04-15 17:10:37.000000000 +0300 -@@ -250,6 +250,7 @@ static ERR_STRING_DATA SSL_str_functs[]= - {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"}, - {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, - {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, -+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"}, - {0,NULL} - }; - -diff -upr openssl-0.9.8g.orig/ssl/ssl_sess.c openssl-0.9.8g/ssl/ssl_sess.c ---- openssl-0.9.8g.orig/ssl/ssl_sess.c 2007-10-19 10:36:34.000000000 +0300 -+++ openssl-0.9.8g/ssl/ssl_sess.c 2008-04-15 17:10:37.000000000 +0300 -@@ -704,6 +704,52 @@ long SSL_CTX_get_timeout(const SSL_CTX * - return(s->session_timeout); - } - -+#ifndef OPENSSL_NO_TLSEXT -+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, -+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) -+{ -+ if (s == NULL) return(0); -+ s->tls_session_secret_cb = tls_session_secret_cb; -+ s->tls_session_secret_cb_arg = arg; -+ return(1); -+} -+ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len) -+{ -+ if(s->version >= TLS1_VERSION) -+ { -+ if(s->tls_extension) -+ { -+ OPENSSL_free(s->tls_extension); -+ s->tls_extension = NULL; -+ } -+ -+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len); -+ if(!s->tls_extension) -+ { -+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE); -+ return 0; -+ } -+ -+ s->tls_extension->type = ext_type; -+ -+ if(ext_data) -+ { -+ s->tls_extension->length = ext_len; -+ s->tls_extension->data = s->tls_extension + 1; -+ memcpy(s->tls_extension->data, ext_data, ext_len); -+ } else { -+ s->tls_extension->length = 0; -+ s->tls_extension->data = NULL; -+ } -+ -+ return 1; -+ } -+ -+ return 0; -+} -+#endif /* OPENSSL_NO_TLSEXT */ -+ - typedef struct timeout_param_st - { - SSL_CTX *ctx; -diff -upr openssl-0.9.8g.orig/ssl/t1_lib.c openssl-0.9.8g/ssl/t1_lib.c ---- openssl-0.9.8g.orig/ssl/t1_lib.c 2007-10-19 10:44:10.000000000 +0300 -+++ openssl-0.9.8g/ssl/t1_lib.c 2008-04-15 17:10:37.000000000 +0300 -@@ -105,6 +105,12 @@ int tls1_new(SSL *s) - - void tls1_free(SSL *s) - { -+#ifndef OPENSSL_NO_TLSEXT -+ if(s->tls_extension) -+ { -+ OPENSSL_free(s->tls_extension); -+ } -+#endif - ssl3_free(s); - } - -@@ -174,8 +180,24 @@ unsigned char *ssl_add_clienthello_tlsex - int ticklen; - if (s->session && s->session->tlsext_tick) - ticklen = s->session->tlsext_ticklen; -+ else if (s->session && s->tls_extension && -+ s->tls_extension->type == TLSEXT_TYPE_session_ticket && -+ s->tls_extension->data) -+ { -+ ticklen = s->tls_extension->length; -+ s->session->tlsext_tick = OPENSSL_malloc(ticklen); -+ if (!s->session->tlsext_tick) -+ return NULL; -+ memcpy(s->session->tlsext_tick, s->tls_extension->data, -+ ticklen); -+ s->session->tlsext_ticklen = ticklen; -+ } - else - ticklen = 0; -+ if (ticklen == 0 && s->tls_extension && -+ s->tls_extension->type == TLSEXT_TYPE_session_ticket && -+ s->tls_extension->data == NULL) -+ goto skip_ext; - /* Check for enough room 2 for extension type, 2 for len - * rest for ticket - */ -@@ -189,6 +211,7 @@ unsigned char *ssl_add_clienthello_tlsex - ret += ticklen; - } - } -+ skip_ext: - - if ((extdatalen = ret-p-2)== 0) - return p; -@@ -543,6 +566,8 @@ int tls1_process_ticket(SSL *s, unsigned - s->tlsext_ticket_expected = 1; - return 0; /* Cache miss */ - } -+ if (s->tls_session_secret_cb) -+ return 0; - return tls_decrypt_ticket(s, p, size, session_id, len, - ret); - } -diff -upr openssl-0.9.8g.orig/ssl/tls1.h openssl-0.9.8g/ssl/tls1.h ---- openssl-0.9.8g.orig/ssl/tls1.h 2007-08-28 04:12:44.000000000 +0300 -+++ openssl-0.9.8g/ssl/tls1.h 2008-04-15 17:10:37.000000000 +0300 -@@ -365,6 +365,14 @@ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SER - #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ - #endif - -+/* TLS extension struct */ -+struct tls_extension_st -+{ -+ unsigned short type; -+ unsigned short length; -+ void *data; -+}; -+ - #ifdef __cplusplus - } - #endif -diff -upr openssl-0.9.8g.orig/util/ssleay.num openssl-0.9.8g/util/ssleay.num ---- openssl-0.9.8g.orig/util/ssleay.num 2007-08-13 01:31:16.000000000 +0300 -+++ openssl-0.9.8g/util/ssleay.num 2008-04-15 17:10:37.000000000 +0300 -@@ -241,3 +241,5 @@ SSL_CTX_sess_get_remove_cb - SSL_set_SSL_CTX 290 EXIST::FUNCTION: - SSL_get_servername 291 EXIST::FUNCTION:TLSEXT - SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT -+SSL_set_hello_extension 305 EXIST::FUNCTION:TLSEXT -+SSL_set_session_secret_cb 306 EXIST::FUNCTION:TLSEXT diff --git a/contrib/hostapd/patches/openssl-0.9.8h-tls-extensions.patch b/contrib/hostapd/patches/openssl-0.9.8h-tls-extensions.patch deleted file mode 100644 index c68f2279b7..0000000000 --- a/contrib/hostapd/patches/openssl-0.9.8h-tls-extensions.patch +++ /dev/null @@ -1,344 +0,0 @@ -This patch adds support for TLS SessionTicket extension (RFC 5077) for -the parts used by EAP-FAST (RFC 4851). - -This is based on the patch from Alexey Kobozev -(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300). - -OpenSSL 0.9.8h does not enable TLS extension support by default, so it -will need to be enabled by adding enable-tlsext to config script -command line. - - -diff -upr openssl-0.9.8h.orig/ssl/s3_clnt.c openssl-0.9.8h/ssl/s3_clnt.c ---- openssl-0.9.8h.orig/ssl/s3_clnt.c 2008-05-28 10:29:27.000000000 +0300 -+++ openssl-0.9.8h/ssl/s3_clnt.c 2008-05-29 10:44:25.000000000 +0300 -@@ -752,6 +752,20 @@ int ssl3_get_server_hello(SSL *s) - goto f_err; - } - -+#ifndef OPENSSL_NO_TLSEXT -+ /* check if we want to resume the session based on external pre-shared secret */ -+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, -+ NULL, &pref_cipher, s->tls_session_secret_cb_arg)) -+ { -+ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j); -+ } -+ } -+#endif /* OPENSSL_NO_TLSEXT */ -+ - if (j != 0 && j == s->session->session_id_length - && memcmp(p,s->session->session_id,j) == 0) - { -@@ -2693,11 +2707,8 @@ static int ssl3_check_finished(SSL *s) - { - int ok; - long n; -- /* If we have no ticket or session ID is non-zero length (a match of -- * a non-zero session length would never reach here) it cannot be a -- * resumed session. -- */ -- if (!s->session->tlsext_tick || s->session->session_id_length) -+ /* If we have no ticket it cannot be a resumed session. */ -+ if (!s->session->tlsext_tick) - return 1; - /* this function is called when we really expect a Certificate - * message, so permit appropriate message length */ -diff -upr openssl-0.9.8h.orig/ssl/s3_srvr.c openssl-0.9.8h/ssl/s3_srvr.c ---- openssl-0.9.8h.orig/ssl/s3_srvr.c 2008-04-30 19:11:32.000000000 +0300 -+++ openssl-0.9.8h/ssl/s3_srvr.c 2008-05-28 18:49:34.000000000 +0300 -@@ -959,6 +959,59 @@ int ssl3_get_client_hello(SSL *s) - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); - goto err; - } -+ -+ /* Check if we want to use external pre-shared secret for this -+ * handshake for not reused session only. We need to generate -+ * server_random before calling tls_session_secret_cb in order to allow -+ * SessionTicket processing to use it in key derivation. */ -+ { -+ unsigned long Time; -+ unsigned char *pos; -+ Time=(unsigned long)time(NULL); /* Time */ -+ pos=s->s3->server_random; -+ l2n(Time,pos); -+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0) -+ { -+ al=SSL_AD_INTERNAL_ERROR; -+ goto f_err; -+ } -+ } -+ -+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, -+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) -+ { -+ s->hit=1; -+ s->session->ciphers=ciphers; -+ s->session->verify_result=X509_V_OK; -+ -+ ciphers=NULL; -+ -+ /* check if some cipher was preferred by call back */ -+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); -+ if (pref_cipher == NULL) -+ { -+ al=SSL_AD_HANDSHAKE_FAILURE; -+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); -+ goto f_err; -+ } -+ -+ s->session->cipher=pref_cipher; -+ -+ if (s->cipher_list) -+ sk_SSL_CIPHER_free(s->cipher_list); -+ -+ if (s->cipher_list_by_id) -+ sk_SSL_CIPHER_free(s->cipher_list_by_id); -+ -+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); -+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); -+ } -+ } - #endif - /* Worst case, we will use the NULL compression, but if we have other - * options, we will now look for them. We have i-1 compression -@@ -1097,16 +1150,22 @@ int ssl3_send_server_hello(SSL *s) - unsigned char *buf; - unsigned char *p,*d; - int i,sl; -- unsigned long l,Time; -+ unsigned long l; -+#ifdef OPENSSL_NO_TLSEXT -+ unsigned long Time; -+#endif - - if (s->state == SSL3_ST_SW_SRVR_HELLO_A) - { - buf=(unsigned char *)s->init_buf->data; -+#ifdef OPENSSL_NO_TLSEXT - p=s->s3->server_random; -+ /* Generate server_random if it was not needed previously */ - Time=(unsigned long)time(NULL); /* Time */ - l2n(Time,p); - if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0) - return -1; -+#endif - /* Do the message type and length last */ - d=p= &(buf[4]); - -diff -upr openssl-0.9.8h.orig/ssl/ssl.h openssl-0.9.8h/ssl/ssl.h ---- openssl-0.9.8h.orig/ssl/ssl.h 2008-04-30 19:11:32.000000000 +0300 -+++ openssl-0.9.8h/ssl/ssl.h 2008-05-28 18:49:34.000000000 +0300 -@@ -343,6 +343,7 @@ extern "C" { - * 'struct ssl_st *' function parameters used to prototype callbacks - * in SSL_CTX. */ - typedef struct ssl_st *ssl_crock_st; -+typedef struct tls_extension_st TLS_EXTENSION; - - /* used to hold info on the particular ciphers used */ - typedef struct ssl_cipher_st -@@ -364,6 +365,8 @@ DECLARE_STACK_OF(SSL_CIPHER) - typedef struct ssl_st SSL; - typedef struct ssl_ctx_st SSL_CTX; - -+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); -+ - /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ - typedef struct ssl_method_st - { -@@ -1027,6 +1030,14 @@ struct ssl_st - - /* RFC4507 session ticket expected to be received or sent */ - int tlsext_ticket_expected; -+ -+ /* TLS extensions */ -+ TLS_EXTENSION *tls_extension; -+ -+ /* TLS pre-shared secret session resumption */ -+ tls_session_secret_cb_fn tls_session_secret_cb; -+ void *tls_session_secret_cb_arg; -+ - SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */ - #define session_ctx initial_ctx - #else -@@ -1625,6 +1636,12 @@ void *SSL_COMP_get_compression_methods(v - int SSL_COMP_add_compression_method(int id,void *cm); - #endif - -+/* TLS extensions functions */ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); -+ -+/* Pre-shared secret session resumption functions */ -+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); -+ - /* BEGIN ERROR CODES */ - /* The following lines are auto generated by the script mkerr.pl. Any changes - * made after this point may be overwritten when the script is next run. -@@ -1815,6 +1832,7 @@ void ERR_load_SSL_strings(void); - #define SSL_F_TLS1_ENC 210 - #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 - #define SSL_F_WRITE_PENDING 212 -+#define SSL_F_SSL_SET_HELLO_EXTENSION 213 - - /* Reason codes. */ - #define SSL_R_APP_DATA_IN_HANDSHAKE 100 -diff -upr openssl-0.9.8h.orig/ssl/ssl_err.c openssl-0.9.8h/ssl/ssl_err.c ---- openssl-0.9.8h.orig/ssl/ssl_err.c 2007-10-12 03:00:30.000000000 +0300 -+++ openssl-0.9.8h/ssl/ssl_err.c 2008-05-28 18:49:34.000000000 +0300 -@@ -251,6 +251,7 @@ static ERR_STRING_DATA SSL_str_functs[]= - {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"}, - {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, - {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, -+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"}, - {0,NULL} - }; - -diff -upr openssl-0.9.8h.orig/ssl/ssl_sess.c openssl-0.9.8h/ssl/ssl_sess.c ---- openssl-0.9.8h.orig/ssl/ssl_sess.c 2007-10-17 20:30:15.000000000 +0300 -+++ openssl-0.9.8h/ssl/ssl_sess.c 2008-05-28 18:49:34.000000000 +0300 -@@ -704,6 +704,52 @@ long SSL_CTX_get_timeout(const SSL_CTX * - return(s->session_timeout); - } - -+#ifndef OPENSSL_NO_TLSEXT -+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, -+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) -+{ -+ if (s == NULL) return(0); -+ s->tls_session_secret_cb = tls_session_secret_cb; -+ s->tls_session_secret_cb_arg = arg; -+ return(1); -+} -+ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len) -+{ -+ if(s->version >= TLS1_VERSION) -+ { -+ if(s->tls_extension) -+ { -+ OPENSSL_free(s->tls_extension); -+ s->tls_extension = NULL; -+ } -+ -+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len); -+ if(!s->tls_extension) -+ { -+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE); -+ return 0; -+ } -+ -+ s->tls_extension->type = ext_type; -+ -+ if(ext_data) -+ { -+ s->tls_extension->length = ext_len; -+ s->tls_extension->data = s->tls_extension + 1; -+ memcpy(s->tls_extension->data, ext_data, ext_len); -+ } else { -+ s->tls_extension->length = 0; -+ s->tls_extension->data = NULL; -+ } -+ -+ return 1; -+ } -+ -+ return 0; -+} -+#endif /* OPENSSL_NO_TLSEXT */ -+ - typedef struct timeout_param_st - { - SSL_CTX *ctx; -diff -upr openssl-0.9.8h.orig/ssl/t1_lib.c openssl-0.9.8h/ssl/t1_lib.c ---- openssl-0.9.8h.orig/ssl/t1_lib.c 2008-05-28 10:26:33.000000000 +0300 -+++ openssl-0.9.8h/ssl/t1_lib.c 2008-05-28 18:49:34.000000000 +0300 -@@ -106,6 +106,12 @@ int tls1_new(SSL *s) - - void tls1_free(SSL *s) - { -+#ifndef OPENSSL_NO_TLSEXT -+ if(s->tls_extension) -+ { -+ OPENSSL_free(s->tls_extension); -+ } -+#endif - ssl3_free(s); - } - -@@ -175,8 +181,24 @@ unsigned char *ssl_add_clienthello_tlsex - int ticklen; - if (s->session && s->session->tlsext_tick) - ticklen = s->session->tlsext_ticklen; -+ else if (s->session && s->tls_extension && -+ s->tls_extension->type == TLSEXT_TYPE_session_ticket && -+ s->tls_extension->data) -+ { -+ ticklen = s->tls_extension->length; -+ s->session->tlsext_tick = OPENSSL_malloc(ticklen); -+ if (!s->session->tlsext_tick) -+ return NULL; -+ memcpy(s->session->tlsext_tick, s->tls_extension->data, -+ ticklen); -+ s->session->tlsext_ticklen = ticklen; -+ } - else - ticklen = 0; -+ if (ticklen == 0 && s->tls_extension && -+ s->tls_extension->type == TLSEXT_TYPE_session_ticket && -+ s->tls_extension->data == NULL) -+ goto skip_ext; - /* Check for enough room 2 for extension type, 2 for len - * rest for ticket - */ -@@ -190,6 +212,7 @@ unsigned char *ssl_add_clienthello_tlsex - ret += ticklen; - } - } -+ skip_ext: - - if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) - { -@@ -774,6 +797,8 @@ int tls1_process_ticket(SSL *s, unsigned - s->tlsext_ticket_expected = 1; - return 0; /* Cache miss */ - } -+ if (s->tls_session_secret_cb) -+ return 0; - return tls_decrypt_ticket(s, p, size, session_id, len, - ret); - } -diff -upr openssl-0.9.8h.orig/ssl/tls1.h openssl-0.9.8h/ssl/tls1.h ---- openssl-0.9.8h.orig/ssl/tls1.h 2008-04-30 19:11:33.000000000 +0300 -+++ openssl-0.9.8h/ssl/tls1.h 2008-05-28 18:49:34.000000000 +0300 -@@ -398,6 +398,14 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_T - #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ - #endif - -+/* TLS extension struct */ -+struct tls_extension_st -+{ -+ unsigned short type; -+ unsigned short length; -+ void *data; -+}; -+ - #ifdef __cplusplus - } - #endif -diff -upr openssl-0.9.8h.orig/util/ssleay.num openssl-0.9.8h/util/ssleay.num ---- openssl-0.9.8h.orig/util/ssleay.num 2007-08-13 01:31:16.000000000 +0300 -+++ openssl-0.9.8h/util/ssleay.num 2008-05-28 18:49:34.000000000 +0300 -@@ -241,3 +241,5 @@ SSL_CTX_sess_get_remove_cb - SSL_set_SSL_CTX 290 EXIST::FUNCTION: - SSL_get_servername 291 EXIST::FUNCTION:TLSEXT - SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT -+SSL_set_hello_extension 305 EXIST::FUNCTION:TLSEXT -+SSL_set_session_secret_cb 306 EXIST::FUNCTION:TLSEXT diff --git a/contrib/hostapd/patches/openssl-0.9.8i-tls-extensions.patch b/contrib/hostapd/patches/openssl-0.9.8i-tls-extensions.patch deleted file mode 100644 index 90bff544eb..0000000000 --- a/contrib/hostapd/patches/openssl-0.9.8i-tls-extensions.patch +++ /dev/null @@ -1,404 +0,0 @@ -This patch adds support for TLS SessionTicket extension (RFC 5077) for -the parts used by EAP-FAST (RFC 4851). - -This is based on the patch from Alexey Kobozev -(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300). - -OpenSSL 0.9.8i does not enable TLS extension support by default, so it -will need to be enabled by adding enable-tlsext to config script -command line. - - -Index: openssl-0.9.8i/ssl/s3_clnt.c -=================================================================== ---- openssl-0.9.8i.orig/ssl/s3_clnt.c 2008-06-16 19:56:41.000000000 +0300 -+++ openssl-0.9.8i/ssl/s3_clnt.c 2008-11-23 20:39:40.000000000 +0200 -@@ -759,6 +759,21 @@ - goto f_err; - } - -+#ifndef OPENSSL_NO_TLSEXT -+ /* check if we want to resume the session based on external pre-shared secret */ -+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, -+ NULL, &pref_cipher, s->tls_session_secret_cb_arg)) -+ { -+ s->session->cipher=pref_cipher ? -+ pref_cipher : ssl_get_cipher_by_char(s,p+j); -+ } -+ } -+#endif /* OPENSSL_NO_TLSEXT */ -+ - if (j != 0 && j == s->session->session_id_length - && memcmp(p,s->session->session_id,j) == 0) - { -@@ -2701,11 +2716,8 @@ - { - int ok; - long n; -- /* If we have no ticket or session ID is non-zero length (a match of -- * a non-zero session length would never reach here) it cannot be a -- * resumed session. -- */ -- if (!s->session->tlsext_tick || s->session->session_id_length) -+ /* If we have no ticket it cannot be a resumed session. */ -+ if (!s->session->tlsext_tick) - return 1; - /* this function is called when we really expect a Certificate - * message, so permit appropriate message length */ -Index: openssl-0.9.8i/ssl/s3_srvr.c -=================================================================== ---- openssl-0.9.8i.orig/ssl/s3_srvr.c 2008-09-14 21:16:09.000000000 +0300 -+++ openssl-0.9.8i/ssl/s3_srvr.c 2008-11-23 20:37:40.000000000 +0200 -@@ -959,6 +959,59 @@ - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); - goto err; - } -+ -+ /* Check if we want to use external pre-shared secret for this -+ * handshake for not reused session only. We need to generate -+ * server_random before calling tls_session_secret_cb in order to allow -+ * SessionTicket processing to use it in key derivation. */ -+ { -+ unsigned long Time; -+ unsigned char *pos; -+ Time=(unsigned long)time(NULL); /* Time */ -+ pos=s->s3->server_random; -+ l2n(Time,pos); -+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0) -+ { -+ al=SSL_AD_INTERNAL_ERROR; -+ goto f_err; -+ } -+ } -+ -+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, -+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) -+ { -+ s->hit=1; -+ s->session->ciphers=ciphers; -+ s->session->verify_result=X509_V_OK; -+ -+ ciphers=NULL; -+ -+ /* check if some cipher was preferred by call back */ -+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); -+ if (pref_cipher == NULL) -+ { -+ al=SSL_AD_HANDSHAKE_FAILURE; -+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); -+ goto f_err; -+ } -+ -+ s->session->cipher=pref_cipher; -+ -+ if (s->cipher_list) -+ sk_SSL_CIPHER_free(s->cipher_list); -+ -+ if (s->cipher_list_by_id) -+ sk_SSL_CIPHER_free(s->cipher_list_by_id); -+ -+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); -+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); -+ } -+ } - #endif - /* Worst case, we will use the NULL compression, but if we have other - * options, we will now look for them. We have i-1 compression -@@ -1097,16 +1150,22 @@ - unsigned char *buf; - unsigned char *p,*d; - int i,sl; -- unsigned long l,Time; -+ unsigned long l; -+#ifdef OPENSSL_NO_TLSEXT -+ unsigned long Time; -+#endif - - if (s->state == SSL3_ST_SW_SRVR_HELLO_A) - { - buf=(unsigned char *)s->init_buf->data; -+#ifdef OPENSSL_NO_TLSEXT - p=s->s3->server_random; -+ /* Generate server_random if it was not needed previously */ - Time=(unsigned long)time(NULL); /* Time */ - l2n(Time,p); - if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0) - return -1; -+#endif - /* Do the message type and length last */ - d=p= &(buf[4]); - -Index: openssl-0.9.8i/ssl/ssl_err.c -=================================================================== ---- openssl-0.9.8i.orig/ssl/ssl_err.c 2008-08-13 22:44:44.000000000 +0300 -+++ openssl-0.9.8i/ssl/ssl_err.c 2008-11-23 20:33:43.000000000 +0200 -@@ -253,6 +253,7 @@ - {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"}, - {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, - {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, -+{ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT), "SSL_set_session_ticket_ext"}, - {0,NULL} - }; - -Index: openssl-0.9.8i/ssl/ssl.h -=================================================================== ---- openssl-0.9.8i.orig/ssl/ssl.h 2008-08-13 22:44:44.000000000 +0300 -+++ openssl-0.9.8i/ssl/ssl.h 2008-11-23 20:35:41.000000000 +0200 -@@ -344,6 +344,7 @@ - * 'struct ssl_st *' function parameters used to prototype callbacks - * in SSL_CTX. */ - typedef struct ssl_st *ssl_crock_st; -+typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT; - - /* used to hold info on the particular ciphers used */ - typedef struct ssl_cipher_st -@@ -362,6 +363,9 @@ - - DECLARE_STACK_OF(SSL_CIPHER) - -+typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data, int len, void *arg); -+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); -+ - /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ - typedef struct ssl_method_st - { -@@ -1034,6 +1038,18 @@ - - /* RFC4507 session ticket expected to be received or sent */ - int tlsext_ticket_expected; -+ -+ /* TLS Session Ticket extension override */ -+ TLS_SESSION_TICKET_EXT *tlsext_session_ticket; -+ -+ /* TLS Session Ticket extension callback */ -+ tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb; -+ void *tls_session_ticket_ext_cb_arg; -+ -+ /* TLS pre-shared secret session resumption */ -+ tls_session_secret_cb_fn tls_session_secret_cb; -+ void *tls_session_secret_cb_arg; -+ - SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */ - #define session_ctx initial_ctx - #else -@@ -1632,6 +1648,15 @@ - int SSL_COMP_add_compression_method(int id,void *cm); - #endif - -+/* TLS extensions functions */ -+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len); -+ -+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb, -+ void *arg); -+ -+/* Pre-shared secret session resumption functions */ -+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); -+ - /* BEGIN ERROR CODES */ - /* The following lines are auto generated by the script mkerr.pl. Any changes - * made after this point may be overwritten when the script is next run. -@@ -1824,6 +1849,7 @@ - #define SSL_F_TLS1_ENC 210 - #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 - #define SSL_F_WRITE_PENDING 212 -+#define SSL_F_SSL_SET_SESSION_TICKET_EXT 213 - - /* Reason codes. */ - #define SSL_R_APP_DATA_IN_HANDSHAKE 100 -Index: openssl-0.9.8i/ssl/ssl_sess.c -=================================================================== ---- openssl-0.9.8i.orig/ssl/ssl_sess.c 2008-06-04 21:35:27.000000000 +0300 -+++ openssl-0.9.8i/ssl/ssl_sess.c 2008-11-23 20:32:24.000000000 +0200 -@@ -707,6 +707,61 @@ - return(s->session_timeout); - } - -+#ifndef OPENSSL_NO_TLSEXT -+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, -+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) -+ { -+ if (s == NULL) return(0); -+ s->tls_session_secret_cb = tls_session_secret_cb; -+ s->tls_session_secret_cb_arg = arg; -+ return(1); -+ } -+ -+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb, -+ void *arg) -+ { -+ if (s == NULL) return(0); -+ s->tls_session_ticket_ext_cb = cb; -+ s->tls_session_ticket_ext_cb_arg = arg; -+ return(1); -+ } -+ -+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len) -+ { -+ if (s->version >= TLS1_VERSION) -+ { -+ if (s->tlsext_session_ticket) -+ { -+ OPENSSL_free(s->tlsext_session_ticket); -+ s->tlsext_session_ticket = NULL; -+ } -+ -+ s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len); -+ if (!s->tlsext_session_ticket) -+ { -+ SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE); -+ return 0; -+ } -+ -+ if (ext_data) -+ { -+ s->tlsext_session_ticket->length = ext_len; -+ s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1; -+ memcpy(s->tlsext_session_ticket->data, ext_data, ext_len); -+ } -+ else -+ { -+ s->tlsext_session_ticket->length = 0; -+ s->tlsext_session_ticket->data = NULL; -+ } -+ -+ return 1; -+ } -+ -+ return 0; -+ } -+#endif /* OPENSSL_NO_TLSEXT */ -+ - typedef struct timeout_param_st - { - SSL_CTX *ctx; -Index: openssl-0.9.8i/ssl/t1_lib.c -=================================================================== ---- openssl-0.9.8i.orig/ssl/t1_lib.c 2008-09-04 01:13:04.000000000 +0300 -+++ openssl-0.9.8i/ssl/t1_lib.c 2008-11-23 20:31:20.000000000 +0200 -@@ -106,6 +106,12 @@ - - void tls1_free(SSL *s) - { -+#ifndef OPENSSL_NO_TLSEXT -+ if (s->tlsext_session_ticket) -+ { -+ OPENSSL_free(s->tlsext_session_ticket); -+ } -+#endif - ssl3_free(s); - } - -@@ -175,8 +181,23 @@ - int ticklen; - if (s->session && s->session->tlsext_tick) - ticklen = s->session->tlsext_ticklen; -+ else if (s->session && s->tlsext_session_ticket && -+ s->tlsext_session_ticket->data) -+ { -+ ticklen = s->tlsext_session_ticket->length; -+ s->session->tlsext_tick = OPENSSL_malloc(ticklen); -+ if (!s->session->tlsext_tick) -+ return NULL; -+ memcpy(s->session->tlsext_tick, -+ s->tlsext_session_ticket->data, -+ ticklen); -+ s->session->tlsext_ticklen = ticklen; -+ } - else - ticklen = 0; -+ if (ticklen == 0 && s->tlsext_session_ticket && -+ s->tlsext_session_ticket->data == NULL) -+ goto skip_ext; - /* Check for enough room 2 for extension type, 2 for len - * rest for ticket - */ -@@ -190,6 +211,7 @@ - ret += ticklen; - } - } -+ skip_ext: - - if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) - { -@@ -407,6 +429,15 @@ - } - - } -+ else if (type == TLSEXT_TYPE_session_ticket) -+ { -+ if (s->tls_session_ticket_ext_cb && -+ !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg)) -+ { -+ *al = TLS1_AD_INTERNAL_ERROR; -+ return 0; -+ } -+ } - else if (type == TLSEXT_TYPE_status_request - && s->ctx->tlsext_status_cb) - { -@@ -553,6 +584,12 @@ - } - else if (type == TLSEXT_TYPE_session_ticket) - { -+ if (s->tls_session_ticket_ext_cb && -+ !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg)) -+ { -+ *al = TLS1_AD_INTERNAL_ERROR; -+ return 0; -+ } - if ((SSL_get_options(s) & SSL_OP_NO_TICKET) - || (size > 0)) - { -@@ -776,6 +813,15 @@ - s->tlsext_ticket_expected = 1; - return 0; /* Cache miss */ - } -+ if (s->tls_session_secret_cb) -+ { -+ /* Indicate cache miss here and instead of -+ * generating the session from ticket now, -+ * trigger abbreviated handshake based on -+ * external mechanism to calculate the master -+ * secret later. */ -+ return 0; -+ } - return tls_decrypt_ticket(s, p, size, session_id, len, - ret); - } -Index: openssl-0.9.8i/ssl/tls1.h -=================================================================== ---- openssl-0.9.8i.orig/ssl/tls1.h 2008-04-30 19:11:33.000000000 +0300 -+++ openssl-0.9.8i/ssl/tls1.h 2008-11-23 20:22:38.000000000 +0200 -@@ -398,6 +398,13 @@ - #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ - #endif - -+/* TLS extension struct */ -+struct tls_session_ticket_ext_st -+ { -+ unsigned short length; -+ void *data; -+ }; -+ - #ifdef __cplusplus - } - #endif -Index: openssl-0.9.8i/util/ssleay.num -=================================================================== ---- openssl-0.9.8i.orig/util/ssleay.num 2008-06-05 13:57:21.000000000 +0300 -+++ openssl-0.9.8i/util/ssleay.num 2008-11-23 20:22:05.000000000 +0200 -@@ -242,3 +242,5 @@ - SSL_get_servername 291 EXIST::FUNCTION:TLSEXT - SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT - SSL_CTX_set_client_cert_engine 293 EXIST::FUNCTION:ENGINE -+SSL_set_session_ticket_ext 306 EXIST::FUNCTION:TLSEXT -+SSL_set_session_secret_cb 307 EXIST::FUNCTION:TLSEXT diff --git a/contrib/hostapd/patches/openssl-0.9.9-session-ticket.patch b/contrib/hostapd/patches/openssl-0.9.9-session-ticket.patch deleted file mode 100644 index 3afa639ad8..0000000000 --- a/contrib/hostapd/patches/openssl-0.9.9-session-ticket.patch +++ /dev/null @@ -1,374 +0,0 @@ -This patch adds support for TLS SessionTicket extension (RFC 5077) for -the parts used by EAP-FAST (RFC 4851). - -This is based on the patch from Alexey Kobozev -(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300). - -NOTE: This patch (without SSL_set_hello_extension() wrapper) was -merged into the upstream OpenSSL 0.9.9 tree and as such, an external -patch for EAP-FAST support is not needed anymore. - - - -Index: openssl-SNAP-20081111/ssl/s3_clnt.c -=================================================================== ---- openssl-SNAP-20081111.orig/ssl/s3_clnt.c -+++ openssl-SNAP-20081111/ssl/s3_clnt.c -@@ -788,6 +788,23 @@ int ssl3_get_server_hello(SSL *s) - goto f_err; - } - -+#ifndef OPENSSL_NO_TLSEXT -+ /* check if we want to resume the session based on external pre-shared secret */ -+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if (s->tls_session_secret_cb(s, s->session->master_key, -+ &s->session->master_key_length, -+ NULL, &pref_cipher, -+ s->tls_session_secret_cb_arg)) -+ { -+ s->session->cipher = pref_cipher ? -+ pref_cipher : ssl_get_cipher_by_char(s, p+j); -+ } -+ } -+#endif /* OPENSSL_NO_TLSEXT */ -+ - if (j != 0 && j == s->session->session_id_length - && memcmp(p,s->session->session_id,j) == 0) - { -@@ -2927,11 +2944,8 @@ static int ssl3_check_finished(SSL *s) - { - int ok; - long n; -- /* If we have no ticket or session ID is non-zero length (a match of -- * a non-zero session length would never reach here) it cannot be a -- * resumed session. -- */ -- if (!s->session->tlsext_tick || s->session->session_id_length) -+ /* If we have no ticket it cannot be a resumed session. */ -+ if (!s->session->tlsext_tick) - return 1; - /* this function is called when we really expect a Certificate - * message, so permit appropriate message length */ -Index: openssl-SNAP-20081111/ssl/s3_srvr.c -=================================================================== ---- openssl-SNAP-20081111.orig/ssl/s3_srvr.c -+++ openssl-SNAP-20081111/ssl/s3_srvr.c -@@ -1010,6 +1010,59 @@ int ssl3_get_client_hello(SSL *s) - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); - goto err; - } -+ -+ /* Check if we want to use external pre-shared secret for this -+ * handshake for not reused session only. We need to generate -+ * server_random before calling tls_session_secret_cb in order to allow -+ * SessionTicket processing to use it in key derivation. */ -+ { -+ unsigned long Time; -+ unsigned char *pos; -+ Time=(unsigned long)time(NULL); /* Time */ -+ pos=s->s3->server_random; -+ l2n(Time,pos); -+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0) -+ { -+ al=SSL_AD_INTERNAL_ERROR; -+ goto f_err; -+ } -+ } -+ -+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, -+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) -+ { -+ s->hit=1; -+ s->session->ciphers=ciphers; -+ s->session->verify_result=X509_V_OK; -+ -+ ciphers=NULL; -+ -+ /* check if some cipher was preferred by call back */ -+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); -+ if (pref_cipher == NULL) -+ { -+ al=SSL_AD_HANDSHAKE_FAILURE; -+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); -+ goto f_err; -+ } -+ -+ s->session->cipher=pref_cipher; -+ -+ if (s->cipher_list) -+ sk_SSL_CIPHER_free(s->cipher_list); -+ -+ if (s->cipher_list_by_id) -+ sk_SSL_CIPHER_free(s->cipher_list_by_id); -+ -+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); -+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); -+ } -+ } - #endif - - /* Worst case, we will use the NULL compression, but if we have other -@@ -1134,16 +1187,22 @@ int ssl3_send_server_hello(SSL *s) - unsigned char *buf; - unsigned char *p,*d; - int i,sl; -- unsigned long l,Time; -+ unsigned long l; -+#ifdef OPENSSL_NO_TLSEXT -+ unsigned long Time; -+#endif - - if (s->state == SSL3_ST_SW_SRVR_HELLO_A) - { - buf=(unsigned char *)s->init_buf->data; -+#ifdef OPENSSL_NO_TLSEXT - p=s->s3->server_random; -+ /* Generate server_random if it was not needed previously */ - Time=(unsigned long)time(NULL); /* Time */ - l2n(Time,p); - if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0) - return -1; -+#endif - /* Do the message type and length last */ - d=p= &(buf[4]); - -Index: openssl-SNAP-20081111/ssl/ssl_err.c -=================================================================== ---- openssl-SNAP-20081111.orig/ssl/ssl_err.c -+++ openssl-SNAP-20081111/ssl/ssl_err.c -@@ -263,6 +263,7 @@ static ERR_STRING_DATA SSL_str_functs[]= - {ERR_FUNC(SSL_F_TLS1_PRF), "tls1_prf"}, - {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, - {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, -+{ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT), "SSL_set_session_ticket_ext"}, - {0,NULL} - }; - -Index: openssl-SNAP-20081111/ssl/ssl.h -=================================================================== ---- openssl-SNAP-20081111.orig/ssl/ssl.h -+++ openssl-SNAP-20081111/ssl/ssl.h -@@ -355,6 +355,7 @@ extern "C" { - * 'struct ssl_st *' function parameters used to prototype callbacks - * in SSL_CTX. */ - typedef struct ssl_st *ssl_crock_st; -+typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT; - - /* used to hold info on the particular ciphers used */ - typedef struct ssl_cipher_st -@@ -378,6 +379,8 @@ typedef struct ssl_cipher_st - - DECLARE_STACK_OF(SSL_CIPHER) - -+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); -+ - /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ - typedef struct ssl_method_st - { -@@ -1145,6 +1148,13 @@ struct ssl_st - void *tlsext_opaque_prf_input; - size_t tlsext_opaque_prf_input_len; - -+ /* TLS Session Ticket extension override */ -+ TLS_SESSION_TICKET_EXT *tlsext_session_ticket; -+ -+ /* TLS pre-shared secret session resumption */ -+ tls_session_secret_cb_fn tls_session_secret_cb; -+ void *tls_session_secret_cb_arg; -+ - SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */ - #define session_ctx initial_ctx - #else -@@ -1746,6 +1756,16 @@ void *SSL_COMP_get_compression_methods(v - int SSL_COMP_add_compression_method(int id,void *cm); - #endif - -+/* NOTE: This function will be removed; it is only here for backwards -+ * compatibility for the API during testing. */ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); -+ -+/* TLS extensions functions */ -+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len); -+ -+/* Pre-shared secret session resumption functions */ -+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); -+ - /* BEGIN ERROR CODES */ - /* The following lines are auto generated by the script mkerr.pl. Any changes - * made after this point may be overwritten when the script is next run. -@@ -1948,6 +1968,7 @@ void ERR_load_SSL_strings(void); - #define SSL_F_TLS1_PRF 284 - #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 - #define SSL_F_WRITE_PENDING 212 -+#define SSL_F_SSL_SET_SESSION_TICKET_EXT 213 - - /* Reason codes. */ - #define SSL_R_APP_DATA_IN_HANDSHAKE 100 -Index: openssl-SNAP-20081111/ssl/ssl_sess.c -=================================================================== ---- openssl-SNAP-20081111.orig/ssl/ssl_sess.c -+++ openssl-SNAP-20081111/ssl/ssl_sess.c -@@ -834,6 +834,62 @@ long SSL_CTX_get_timeout(const SSL_CTX * - return(s->session_timeout); - } - -+#ifndef OPENSSL_NO_TLSEXT -+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, -+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) -+ { -+ if (s == NULL) return(0); -+ s->tls_session_secret_cb = tls_session_secret_cb; -+ s->tls_session_secret_cb_arg = arg; -+ return(1); -+ } -+ -+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len) -+ { -+ if (s->version >= TLS1_VERSION) -+ { -+ if (s->tlsext_session_ticket) -+ { -+ OPENSSL_free(s->tlsext_session_ticket); -+ s->tlsext_session_ticket = NULL; -+ } -+ -+ s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len); -+ if (!s->tlsext_session_ticket) -+ { -+ SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE); -+ return 0; -+ } -+ -+ if (ext_data) -+ { -+ s->tlsext_session_ticket->length = ext_len; -+ s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1; -+ memcpy(s->tlsext_session_ticket->data, ext_data, ext_len); -+ } -+ else -+ { -+ s->tlsext_session_ticket->length = 0; -+ s->tlsext_session_ticket->data = NULL; -+ } -+ -+ return 1; -+ } -+ -+ return 0; -+ } -+ -+/* NOTE: This function will be removed; it is only here for backwards -+ * compatibility for the API during testing. */ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len) -+ { -+ if (ext_type != TLSEXT_TYPE_session_ticket) -+ return 0; -+ -+ return SSL_set_session_ticket_ext(s, ext_data, ext_len); -+ } -+#endif /* OPENSSL_NO_TLSEXT */ -+ - typedef struct timeout_param_st - { - SSL_CTX *ctx; -Index: openssl-SNAP-20081111/ssl/t1_lib.c -=================================================================== ---- openssl-SNAP-20081111.orig/ssl/t1_lib.c -+++ openssl-SNAP-20081111/ssl/t1_lib.c -@@ -154,6 +154,12 @@ int tls1_new(SSL *s) - - void tls1_free(SSL *s) - { -+#ifndef OPENSSL_NO_TLSEXT -+ if (s->tlsext_session_ticket) -+ { -+ OPENSSL_free(s->tlsext_session_ticket); -+ } -+#endif /* OPENSSL_NO_TLSEXT */ - ssl3_free(s); - } - -@@ -357,8 +363,23 @@ unsigned char *ssl_add_clienthello_tlsex - int ticklen; - if (s->session && s->session->tlsext_tick) - ticklen = s->session->tlsext_ticklen; -+ else if (s->session && s->tlsext_session_ticket && -+ s->tlsext_session_ticket->data) -+ { -+ ticklen = s->tlsext_session_ticket->length; -+ s->session->tlsext_tick = OPENSSL_malloc(ticklen); -+ if (!s->session->tlsext_tick) -+ return NULL; -+ memcpy(s->session->tlsext_tick, -+ s->tlsext_session_ticket->data, -+ ticklen); -+ s->session->tlsext_ticklen = ticklen; -+ } - else - ticklen = 0; -+ if (ticklen == 0 && s->tlsext_session_ticket && -+ s->tlsext_session_ticket->data == NULL) -+ goto skip_ext; - /* Check for enough room 2 for extension type, 2 for len - * rest for ticket - */ -@@ -371,6 +392,7 @@ unsigned char *ssl_add_clienthello_tlsex - ret += ticklen; - } - } -+ skip_ext: - - #ifdef TLSEXT_TYPE_opaque_prf_input - if (s->s3->client_opaque_prf_input != NULL) -@@ -1435,6 +1457,15 @@ int tls1_process_ticket(SSL *s, unsigned - s->tlsext_ticket_expected = 1; - return 0; /* Cache miss */ - } -+ if (s->tls_session_secret_cb) -+ { -+ /* Indicate cache miss here and instead of -+ * generating the session from ticket now, -+ * trigger abbreviated handshake based on -+ * external mechanism to calculate the master -+ * secret later. */ -+ return 0; -+ } - return tls_decrypt_ticket(s, p, size, session_id, len, - ret); - } -Index: openssl-SNAP-20081111/ssl/tls1.h -=================================================================== ---- openssl-SNAP-20081111.orig/ssl/tls1.h -+++ openssl-SNAP-20081111/ssl/tls1.h -@@ -512,6 +512,13 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_T - #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ - #endif - -+/* TLS Session Ticket extension struct */ -+struct tls_session_ticket_ext_st -+ { -+ unsigned short length; -+ void *data; -+ }; -+ - #ifdef __cplusplus - } - #endif -Index: openssl-SNAP-20081111/util/ssleay.num -=================================================================== ---- openssl-SNAP-20081111.orig/util/ssleay.num -+++ openssl-SNAP-20081111/util/ssleay.num -@@ -254,3 +254,5 @@ PEM_read_bio_SSL_SESSION - SSL_CTX_set_psk_server_callback 303 EXIST::FUNCTION:PSK - SSL_get_psk_identity 304 EXIST::FUNCTION:PSK - PEM_write_SSL_SESSION 305 EXIST:!WIN16:FUNCTION: -+SSL_set_session_ticket_ext 306 EXIST::FUNCTION:TLSEXT -+SSL_set_session_secret_cb 307 EXIST::FUNCTION:TLSEXT diff --git a/contrib/hostapd/src/common/defs.h b/contrib/hostapd/src/common/defs.h deleted file mode 100644 index 4930e73e75..0000000000 --- a/contrib/hostapd/src/common/defs.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - * WPA Supplicant - Common definitions - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef DEFS_H -#define DEFS_H - -#ifdef FALSE -#undef FALSE -#endif -#ifdef TRUE -#undef TRUE -#endif -typedef enum { FALSE = 0, TRUE = 1 } Boolean; - - -#define WPA_CIPHER_NONE BIT(0) -#define WPA_CIPHER_WEP40 BIT(1) -#define WPA_CIPHER_WEP104 BIT(2) -#define WPA_CIPHER_TKIP BIT(3) -#define WPA_CIPHER_CCMP BIT(4) -#ifdef CONFIG_IEEE80211W -#define WPA_CIPHER_AES_128_CMAC BIT(5) -#endif /* CONFIG_IEEE80211W */ - -#define WPA_KEY_MGMT_IEEE8021X BIT(0) -#define WPA_KEY_MGMT_PSK BIT(1) -#define WPA_KEY_MGMT_NONE BIT(2) -#define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3) -#define WPA_KEY_MGMT_WPA_NONE BIT(4) -#define WPA_KEY_MGMT_FT_IEEE8021X BIT(5) -#define WPA_KEY_MGMT_FT_PSK BIT(6) -#define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7) -#define WPA_KEY_MGMT_PSK_SHA256 BIT(8) -#define WPA_KEY_MGMT_WPS BIT(9) - -static inline int wpa_key_mgmt_wpa_ieee8021x(int akm) -{ - return akm == WPA_KEY_MGMT_IEEE8021X || - akm == WPA_KEY_MGMT_FT_IEEE8021X || - akm == WPA_KEY_MGMT_IEEE8021X_SHA256; -} - -static inline int wpa_key_mgmt_wpa_psk(int akm) -{ - return akm == WPA_KEY_MGMT_PSK || - akm == WPA_KEY_MGMT_FT_PSK || - akm == WPA_KEY_MGMT_PSK_SHA256; -} - -static inline int wpa_key_mgmt_ft(int akm) -{ - return akm == WPA_KEY_MGMT_FT_PSK || - akm == WPA_KEY_MGMT_FT_IEEE8021X; -} - -static inline int wpa_key_mgmt_sha256(int akm) -{ - return akm == WPA_KEY_MGMT_PSK_SHA256 || - akm == WPA_KEY_MGMT_IEEE8021X_SHA256; -} - - -#define WPA_PROTO_WPA BIT(0) -#define WPA_PROTO_RSN BIT(1) - -#define WPA_AUTH_ALG_OPEN BIT(0) -#define WPA_AUTH_ALG_SHARED BIT(1) -#define WPA_AUTH_ALG_LEAP BIT(2) - - -typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP, - WPA_ALG_IGTK, WPA_ALG_PMK } wpa_alg; -typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, - CIPHER_WEP104 } wpa_cipher; -typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, - KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE, - KEY_MGMT_FT_802_1X, KEY_MGMT_FT_PSK, - KEY_MGMT_802_1X_SHA256, KEY_MGMT_PSK_SHA256, - KEY_MGMT_WPS -} wpa_key_mgmt; - -/** - * enum wpa_states - wpa_supplicant state - * - * These enumeration values are used to indicate the current wpa_supplicant - * state (wpa_s->wpa_state). The current state can be retrieved with - * wpa_supplicant_get_state() function and the state can be changed by calling - * wpa_supplicant_set_state(). In WPA state machine (wpa.c and preauth.c), the - * wrapper functions wpa_sm_get_state() and wpa_sm_set_state() should be used - * to access the state variable. - */ -typedef enum { - /** - * WPA_DISCONNECTED - Disconnected state - * - * This state indicates that client is not associated, but is likely to - * start looking for an access point. This state is entered when a - * connection is lost. - */ - WPA_DISCONNECTED, - - /** - * WPA_INACTIVE - Inactive state (wpa_supplicant disabled) - * - * This state is entered if there are no enabled networks in the - * configuration. wpa_supplicant is not trying to associate with a new - * network and external interaction (e.g., ctrl_iface call to add or - * enable a network) is needed to start association. - */ - WPA_INACTIVE, - - /** - * WPA_SCANNING - Scanning for a network - * - * This state is entered when wpa_supplicant starts scanning for a - * network. - */ - WPA_SCANNING, - - /** - * WPA_ASSOCIATING - Trying to associate with a BSS/SSID - * - * This state is entered when wpa_supplicant has found a suitable BSS - * to associate with and the driver is configured to try to associate - * with this BSS in ap_scan=1 mode. When using ap_scan=2 mode, this - * state is entered when the driver is configured to try to associate - * with a network using the configured SSID and security policy. - */ - WPA_ASSOCIATING, - - /** - * WPA_ASSOCIATED - Association completed - * - * This state is entered when the driver reports that association has - * been successfully completed with an AP. If IEEE 802.1X is used - * (with or without WPA/WPA2), wpa_supplicant remains in this state - * until the IEEE 802.1X/EAPOL authentication has been completed. - */ - WPA_ASSOCIATED, - - /** - * WPA_4WAY_HANDSHAKE - WPA 4-Way Key Handshake in progress - * - * This state is entered when WPA/WPA2 4-Way Handshake is started. In - * case of WPA-PSK, this happens when receiving the first EAPOL-Key - * frame after association. In case of WPA-EAP, this state is entered - * when the IEEE 802.1X/EAPOL authentication has been completed. - */ - WPA_4WAY_HANDSHAKE, - - /** - * WPA_GROUP_HANDSHAKE - WPA Group Key Handshake in progress - * - * This state is entered when 4-Way Key Handshake has been completed - * (i.e., when the supplicant sends out message 4/4) and when Group - * Key rekeying is started by the AP (i.e., when supplicant receives - * message 1/2). - */ - WPA_GROUP_HANDSHAKE, - - /** - * WPA_COMPLETED - All authentication completed - * - * This state is entered when the full authentication process is - * completed. In case of WPA2, this happens when the 4-Way Handshake is - * successfully completed. With WPA, this state is entered after the - * Group Key Handshake; with IEEE 802.1X (non-WPA) connection is - * completed after dynamic keys are received (or if not used, after - * the EAP authentication has been completed). With static WEP keys and - * plaintext connections, this state is entered when an association - * has been completed. - * - * This state indicates that the supplicant has completed its - * processing for the association phase and that data connection is - * fully configured. - */ - WPA_COMPLETED -} wpa_states; - -#define MLME_SETPROTECTION_PROTECT_TYPE_NONE 0 -#define MLME_SETPROTECTION_PROTECT_TYPE_RX 1 -#define MLME_SETPROTECTION_PROTECT_TYPE_TX 2 -#define MLME_SETPROTECTION_PROTECT_TYPE_RX_TX 3 - -#define MLME_SETPROTECTION_KEY_TYPE_GROUP 0 -#define MLME_SETPROTECTION_KEY_TYPE_PAIRWISE 1 - -#endif /* DEFS_H */ diff --git a/contrib/hostapd/src/common/eapol_common.h b/contrib/hostapd/src/common/eapol_common.h deleted file mode 100644 index d70e62d2f6..0000000000 --- a/contrib/hostapd/src/common/eapol_common.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * EAPOL definitions shared between hostapd and wpa_supplicant - * Copyright (c) 2002-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAPOL_COMMON_H -#define EAPOL_COMMON_H - -/* IEEE Std 802.1X-2004 */ - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct ieee802_1x_hdr { - u8 version; - u8 type; - be16 length; - /* followed by length octets of data */ -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -#define EAPOL_VERSION 2 - -enum { IEEE802_1X_TYPE_EAP_PACKET = 0, - IEEE802_1X_TYPE_EAPOL_START = 1, - IEEE802_1X_TYPE_EAPOL_LOGOFF = 2, - IEEE802_1X_TYPE_EAPOL_KEY = 3, - IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT = 4 -}; - -enum { EAPOL_KEY_TYPE_RC4 = 1, EAPOL_KEY_TYPE_RSN = 2, - EAPOL_KEY_TYPE_WPA = 254 }; - -#endif /* EAPOL_COMMON_H */ diff --git a/contrib/hostapd/src/common/ieee802_11_common.c b/contrib/hostapd/src/common/ieee802_11_common.c deleted file mode 100644 index 242f933b03..0000000000 --- a/contrib/hostapd/src/common/ieee802_11_common.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * IEEE 802.11 Common routines - * Copyright (c) 2002-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "ieee802_11_defs.h" -#include "ieee802_11_common.h" - - -static int ieee802_11_parse_vendor_specific(u8 *pos, size_t elen, - struct ieee802_11_elems *elems, - int show_errors) -{ - unsigned int oui; - - /* first 3 bytes in vendor specific information element are the IEEE - * OUI of the vendor. The following byte is used a vendor specific - * sub-type. */ - if (elen < 4) { - if (show_errors) { - wpa_printf(MSG_MSGDUMP, "short vendor specific " - "information element ignored (len=%lu)", - (unsigned long) elen); - } - return -1; - } - - oui = WPA_GET_BE24(pos); - switch (oui) { - case OUI_MICROSOFT: - /* Microsoft/Wi-Fi information elements are further typed and - * subtyped */ - switch (pos[3]) { - case 1: - /* Microsoft OUI (00:50:F2) with OUI Type 1: - * real WPA information element */ - elems->wpa_ie = pos; - elems->wpa_ie_len = elen; - break; - case WMM_OUI_TYPE: - /* WMM information element */ - if (elen < 5) { - wpa_printf(MSG_MSGDUMP, "short WMM " - "information element ignored " - "(len=%lu)", - (unsigned long) elen); - return -1; - } - switch (pos[4]) { - case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT: - case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT: - /* - * Share same pointer since only one of these - * is used and they start with same data. - * Length field can be used to distinguish the - * IEs. - */ - elems->wmm = pos; - elems->wmm_len = elen; - break; - case WMM_OUI_SUBTYPE_TSPEC_ELEMENT: - elems->wmm_tspec = pos; - elems->wmm_tspec_len = elen; - break; - default: - wpa_printf(MSG_MSGDUMP, "unknown WMM " - "information element ignored " - "(subtype=%d len=%lu)", - pos[4], (unsigned long) elen); - return -1; - } - break; - case 4: - /* Wi-Fi Protected Setup (WPS) IE */ - elems->wps_ie = pos; - elems->wps_ie_len = elen; - break; - default: - wpa_printf(MSG_MSGDUMP, "Unknown Microsoft " - "information element ignored " - "(type=%d len=%lu)\n", - pos[3], (unsigned long) elen); - return -1; - } - break; - - case OUI_BROADCOM: - switch (pos[3]) { - case VENDOR_HT_CAPAB_OUI_TYPE: - elems->vendor_ht_cap = pos; - elems->vendor_ht_cap_len = elen; - break; - default: - wpa_printf(MSG_MSGDUMP, "Unknown Broadcom " - "information element ignored " - "(type=%d len=%lu)\n", - pos[3], (unsigned long) elen); - return -1; - } - break; - - default: - wpa_printf(MSG_MSGDUMP, "unknown vendor specific information " - "element ignored (vendor OUI %02x:%02x:%02x " - "len=%lu)", - pos[0], pos[1], pos[2], (unsigned long) elen); - return -1; - } - - return 0; -} - - -/** - * ieee802_11_parse_elems - Parse information elements in management frames - * @start: Pointer to the start of IEs - * @len: Length of IE buffer in octets - * @elems: Data structure for parsed elements - * @show_errors: Whether to show parsing errors in debug log - * Returns: Parsing result - */ -ParseRes ieee802_11_parse_elems(u8 *start, size_t len, - struct ieee802_11_elems *elems, - int show_errors) -{ - size_t left = len; - u8 *pos = start; - int unknown = 0; - - os_memset(elems, 0, sizeof(*elems)); - - while (left >= 2) { - u8 id, elen; - - 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; - } - - switch (id) { - case WLAN_EID_SSID: - elems->ssid = pos; - elems->ssid_len = elen; - break; - case WLAN_EID_SUPP_RATES: - elems->supp_rates = pos; - elems->supp_rates_len = elen; - break; - case WLAN_EID_FH_PARAMS: - elems->fh_params = pos; - elems->fh_params_len = elen; - break; - case WLAN_EID_DS_PARAMS: - elems->ds_params = pos; - elems->ds_params_len = elen; - break; - case WLAN_EID_CF_PARAMS: - elems->cf_params = pos; - elems->cf_params_len = elen; - break; - case WLAN_EID_TIM: - elems->tim = pos; - elems->tim_len = elen; - break; - case WLAN_EID_IBSS_PARAMS: - elems->ibss_params = pos; - elems->ibss_params_len = elen; - break; - case WLAN_EID_CHALLENGE: - elems->challenge = pos; - elems->challenge_len = elen; - break; - case WLAN_EID_ERP_INFO: - elems->erp_info = pos; - elems->erp_info_len = elen; - break; - case WLAN_EID_EXT_SUPP_RATES: - elems->ext_supp_rates = pos; - elems->ext_supp_rates_len = elen; - break; - case WLAN_EID_VENDOR_SPECIFIC: - if (ieee802_11_parse_vendor_specific(pos, elen, - elems, - show_errors)) - unknown++; - break; - case WLAN_EID_RSN: - elems->rsn_ie = pos; - elems->rsn_ie_len = elen; - break; - case WLAN_EID_PWR_CAPABILITY: - elems->power_cap = pos; - elems->power_cap_len = elen; - break; - case WLAN_EID_SUPPORTED_CHANNELS: - elems->supp_channels = pos; - elems->supp_channels_len = elen; - break; - case WLAN_EID_MOBILITY_DOMAIN: - elems->mdie = pos; - elems->mdie_len = elen; - break; - case WLAN_EID_FAST_BSS_TRANSITION: - elems->ftie = pos; - elems->ftie_len = elen; - break; - case WLAN_EID_TIMEOUT_INTERVAL: - elems->timeout_int = pos; - elems->timeout_int_len = elen; - break; - case WLAN_EID_HT_CAP: - elems->ht_capabilities = pos; - elems->ht_capabilities_len = elen; - break; - case WLAN_EID_HT_OPERATION: - elems->ht_operation = pos; - elems->ht_operation_len = elen; - break; - default: - unknown++; - if (!show_errors) - break; - wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse " - "ignored unknown element (id=%d elen=%d)", - id, elen); - break; - } - - left -= elen; - pos += elen; - } - - if (left) - return ParseFailed; - - return unknown ? ParseUnknown : ParseOK; -} diff --git a/contrib/hostapd/src/common/ieee802_11_common.h b/contrib/hostapd/src/common/ieee802_11_common.h deleted file mode 100644 index b7e497b6cc..0000000000 --- a/contrib/hostapd/src/common/ieee802_11_common.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * IEEE 802.11 Common routines - * Copyright (c) 2002-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IEEE802_11_COMMON_H -#define IEEE802_11_COMMON_H - -/* Parsed Information Elements */ -struct ieee802_11_elems { - u8 *ssid; - u8 ssid_len; - u8 *supp_rates; - u8 supp_rates_len; - u8 *fh_params; - u8 fh_params_len; - u8 *ds_params; - u8 ds_params_len; - u8 *cf_params; - u8 cf_params_len; - u8 *tim; - u8 tim_len; - u8 *ibss_params; - u8 ibss_params_len; - u8 *challenge; - u8 challenge_len; - u8 *erp_info; - u8 erp_info_len; - u8 *ext_supp_rates; - u8 ext_supp_rates_len; - u8 *wpa_ie; - u8 wpa_ie_len; - u8 *rsn_ie; - u8 rsn_ie_len; - u8 *wmm; /* WMM Information or Parameter Element */ - u8 wmm_len; /* 7 = WMM Information; 24 = WMM Parameter */ - u8 *wmm_tspec; - u8 wmm_tspec_len; - u8 *wps_ie; - u8 wps_ie_len; - u8 *power_cap; - u8 power_cap_len; - u8 *supp_channels; - u8 supp_channels_len; - u8 *mdie; - u8 mdie_len; - u8 *ftie; - u8 ftie_len; - u8 *timeout_int; - u8 timeout_int_len; - u8 *ht_capabilities; - u8 ht_capabilities_len; - u8 *ht_operation; - u8 ht_operation_len; - u8 *vendor_ht_cap; - u8 vendor_ht_cap_len; -}; - -typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes; - -ParseRes ieee802_11_parse_elems(u8 *start, size_t len, - struct ieee802_11_elems *elems, - int show_errors); - -#endif /* IEEE802_11_COMMON_H */ diff --git a/contrib/hostapd/src/common/ieee802_11_defs.h b/contrib/hostapd/src/common/ieee802_11_defs.h deleted file mode 100644 index d9e54a99ed..0000000000 --- a/contrib/hostapd/src/common/ieee802_11_defs.h +++ /dev/null @@ -1,593 +0,0 @@ -/* - * IEEE 802.11 Frame type definitions - * Copyright (c) 2002-2007, Jouni Malinen - * Copyright (c) 2007-2008 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IEEE802_11_DEFS_H -#define IEEE802_11_DEFS_H - -/* IEEE 802.11 defines */ - -#define WLAN_FC_PVER 0x0003 -#define WLAN_FC_TODS 0x0100 -#define WLAN_FC_FROMDS 0x0200 -#define WLAN_FC_MOREFRAG 0x0400 -#define WLAN_FC_RETRY 0x0800 -#define WLAN_FC_PWRMGT 0x1000 -#define WLAN_FC_MOREDATA 0x2000 -#define WLAN_FC_ISWEP 0x4000 -#define WLAN_FC_ORDER 0x8000 - -#define WLAN_FC_GET_TYPE(fc) (((fc) & 0x000c) >> 2) -#define WLAN_FC_GET_STYPE(fc) (((fc) & 0x00f0) >> 4) - -#define WLAN_GET_SEQ_FRAG(seq) ((seq) & (BIT(3) | BIT(2) | BIT(1) | BIT(0))) -#define WLAN_GET_SEQ_SEQ(seq) \ - (((seq) & (~(BIT(3) | BIT(2) | BIT(1) | BIT(0)))) >> 4) - -#define WLAN_FC_TYPE_MGMT 0 -#define WLAN_FC_TYPE_CTRL 1 -#define WLAN_FC_TYPE_DATA 2 - -/* management */ -#define WLAN_FC_STYPE_ASSOC_REQ 0 -#define WLAN_FC_STYPE_ASSOC_RESP 1 -#define WLAN_FC_STYPE_REASSOC_REQ 2 -#define WLAN_FC_STYPE_REASSOC_RESP 3 -#define WLAN_FC_STYPE_PROBE_REQ 4 -#define WLAN_FC_STYPE_PROBE_RESP 5 -#define WLAN_FC_STYPE_BEACON 8 -#define WLAN_FC_STYPE_ATIM 9 -#define WLAN_FC_STYPE_DISASSOC 10 -#define WLAN_FC_STYPE_AUTH 11 -#define WLAN_FC_STYPE_DEAUTH 12 -#define WLAN_FC_STYPE_ACTION 13 - -/* control */ -#define WLAN_FC_STYPE_PSPOLL 10 -#define WLAN_FC_STYPE_RTS 11 -#define WLAN_FC_STYPE_CTS 12 -#define WLAN_FC_STYPE_ACK 13 -#define WLAN_FC_STYPE_CFEND 14 -#define WLAN_FC_STYPE_CFENDACK 15 - -/* data */ -#define WLAN_FC_STYPE_DATA 0 -#define WLAN_FC_STYPE_DATA_CFACK 1 -#define WLAN_FC_STYPE_DATA_CFPOLL 2 -#define WLAN_FC_STYPE_DATA_CFACKPOLL 3 -#define WLAN_FC_STYPE_NULLFUNC 4 -#define WLAN_FC_STYPE_CFACK 5 -#define WLAN_FC_STYPE_CFPOLL 6 -#define WLAN_FC_STYPE_CFACKPOLL 7 -#define WLAN_FC_STYPE_QOS_DATA 8 - -/* Authentication algorithms */ -#define WLAN_AUTH_OPEN 0 -#define WLAN_AUTH_SHARED_KEY 1 -#define WLAN_AUTH_FT 2 -#define WLAN_AUTH_LEAP 128 - -#define WLAN_AUTH_CHALLENGE_LEN 128 - -#define WLAN_CAPABILITY_ESS BIT(0) -#define WLAN_CAPABILITY_IBSS BIT(1) -#define WLAN_CAPABILITY_CF_POLLABLE BIT(2) -#define WLAN_CAPABILITY_CF_POLL_REQUEST BIT(3) -#define WLAN_CAPABILITY_PRIVACY BIT(4) -#define WLAN_CAPABILITY_SHORT_PREAMBLE BIT(5) -#define WLAN_CAPABILITY_PBCC BIT(6) -#define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7) -#define WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8) -#define WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10) -#define WLAN_CAPABILITY_DSSS_OFDM BIT(13) - -/* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */ -#define WLAN_STATUS_SUCCESS 0 -#define WLAN_STATUS_UNSPECIFIED_FAILURE 1 -#define WLAN_STATUS_CAPS_UNSUPPORTED 10 -#define WLAN_STATUS_REASSOC_NO_ASSOC 11 -#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12 -#define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13 -#define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14 -#define WLAN_STATUS_CHALLENGE_FAIL 15 -#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_ER_PBCC 26 -#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 27 -/* IEEE 802.11w */ -#define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30 -#define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31 -/* IEEE 802.11i */ -#define WLAN_STATUS_INVALID_IE 40 -#define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41 -#define WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID 42 -#define WLAN_STATUS_AKMP_NOT_VALID 43 -#define WLAN_STATUS_UNSUPPORTED_RSN_IE_VERSION 44 -#define WLAN_STATUS_INVALID_RSN_IE_CAPAB 45 -#define WLAN_STATUS_CIPHER_REJECTED_PER_POLICY 46 -#define WLAN_STATUS_TS_NOT_CREATED 47 -#define WLAN_STATUS_DIRECT_LINK_NOT_ALLOWED 48 -#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 - -/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */ -#define WLAN_REASON_UNSPECIFIED 1 -#define WLAN_REASON_PREV_AUTH_NOT_VALID 2 -#define WLAN_REASON_DEAUTH_LEAVING 3 -#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4 -#define WLAN_REASON_DISASSOC_AP_BUSY 5 -#define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6 -#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_INVALID_IE 13 -#define WLAN_REASON_MICHAEL_MIC_FAILURE 14 -#define WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT 15 -#define WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT 16 -#define WLAN_REASON_IE_IN_4WAY_DIFFERS 17 -#define WLAN_REASON_GROUP_CIPHER_NOT_VALID 18 -#define WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID 19 -#define WLAN_REASON_AKMP_NOT_VALID 20 -#define WLAN_REASON_UNSUPPORTED_RSN_IE_VERSION 21 -#define WLAN_REASON_INVALID_RSN_IE_CAPAB 22 -#define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23 -#define WLAN_REASON_CIPHER_SUITE_REJECTED 24 - - -/* Information Element IDs */ -#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_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 -#define WLAN_EID_TPC_REPORT 35 -#define WLAN_EID_SUPPORTED_CHANNELS 36 -#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_IBSS_DFS 41 -/* EIDs defined by IEEE 802.11h - END */ -#define WLAN_EID_ERP_INFO 42 -#define WLAN_EID_HT_CAP 45 -#define WLAN_EID_RSN 48 -#define WLAN_EID_EXT_SUPP_RATES 50 -#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_HT_OPERATION 61 -#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62 -#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_MMIE 76 -#define WLAN_EID_VENDOR_SPECIFIC 221 - - -/* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */ -#define WLAN_ACTION_SPECTRUM_MGMT 0 -#define WLAN_ACTION_QOS 1 -#define WLAN_ACTION_DLS 2 -#define WLAN_ACTION_BLOCK_ACK 3 -#define WLAN_ACTION_PUBLIC 4 -#define WLAN_ACTION_RADIO_MEASUREMENT 5 -#define WLAN_ACTION_FT 6 -#define WLAN_ACTION_HT 7 -#define WLAN_ACTION_SA_QUERY 8 -#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */ - -/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */ -#define WLAN_SA_QUERY_REQUEST 0 -#define WLAN_SA_QUERY_RESPONSE 1 - -#define WLAN_SA_QUERY_TR_ID_LEN 2 - -/* Timeout Interval Type */ -#define WLAN_TIMEOUT_REASSOC_DEADLINE 1 -#define WLAN_TIMEOUT_KEY_LIFETIME 2 -#define WLAN_TIMEOUT_ASSOC_COMEBACK 3 - - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct ieee80211_mgmt { - le16 frame_control; - le16 duration; - u8 da[6]; - u8 sa[6]; - u8 bssid[6]; - le16 seq_ctrl; - union { - struct { - le16 auth_alg; - le16 auth_transaction; - le16 status_code; - /* possibly followed by Challenge text */ - u8 variable[0]; - } STRUCT_PACKED auth; - struct { - le16 reason_code; - } STRUCT_PACKED deauth; - struct { - le16 capab_info; - le16 listen_interval; - /* followed by SSID and Supported rates */ - u8 variable[0]; - } STRUCT_PACKED assoc_req; - struct { - le16 capab_info; - le16 status_code; - le16 aid; - /* followed by Supported rates */ - u8 variable[0]; - } STRUCT_PACKED assoc_resp, reassoc_resp; - struct { - le16 capab_info; - le16 listen_interval; - u8 current_ap[6]; - /* followed by SSID and Supported rates */ - u8 variable[0]; - } STRUCT_PACKED reassoc_req; - struct { - le16 reason_code; - } STRUCT_PACKED disassoc; - struct { - u8 timestamp[8]; - le16 beacon_int; - le16 capab_info; - /* followed by some of SSID, Supported rates, - * FH Params, DS Params, CF Params, IBSS Params, TIM */ - u8 variable[0]; - } STRUCT_PACKED beacon; - struct { - /* only variable items: SSID, Supported rates */ - u8 variable[0]; - } STRUCT_PACKED probe_req; - struct { - u8 timestamp[8]; - le16 beacon_int; - le16 capab_info; - /* followed by some of SSID, Supported rates, - * FH Params, DS Params, CF Params, IBSS Params */ - u8 variable[0]; - } STRUCT_PACKED probe_resp; - struct { - u8 category; - union { - struct { - u8 action_code; - u8 dialog_token; - u8 status_code; - u8 variable[0]; - } STRUCT_PACKED wmm_action; - struct{ - u8 action_code; - u8 element_id; - u8 length; - u8 switch_mode; - u8 new_chan; - u8 switch_count; - } STRUCT_PACKED chan_switch; - struct { - u8 action; - u8 sta_addr[ETH_ALEN]; - u8 target_ap_addr[ETH_ALEN]; - u8 variable[0]; /* FT Request */ - } STRUCT_PACKED ft_action_req; - struct { - u8 action; - u8 sta_addr[ETH_ALEN]; - u8 target_ap_addr[ETH_ALEN]; - le16 status_code; - u8 variable[0]; /* FT Request */ - } STRUCT_PACKED ft_action_resp; - struct { - u8 action; - u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; - } STRUCT_PACKED sa_query_req; - struct { - u8 action; /* */ - u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; - } STRUCT_PACKED sa_query_resp; - } u; - } STRUCT_PACKED action; - } u; -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -#define ERP_INFO_NON_ERP_PRESENT BIT(0) -#define ERP_INFO_USE_PROTECTION BIT(1) -#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2) - - -/* HT Capability element */ - -enum { - MAX_RX_AMPDU_FACTOR_8KB = 0, - MAX_RX_AMPDU_FACTOR_16KB, - MAX_RX_AMPDU_FACTOR_32KB, - MAX_RX_AMPDU_FACTOR_64KB -}; - -enum { - CALIBRATION_NOT_SUPPORTED = 0, - CALIBRATION_CANNOT_INIT, - CALIBRATION_CAN_INIT, - CALIBRATION_FULL_SUPPORT -}; - -enum { - MCS_FEEDBACK_NOT_PROVIDED = 0, - MCS_FEEDBACK_UNSOLICITED, - MCS_FEEDBACK_MRQ_RESPONSE -}; - - -struct ieee80211_ht_capability { - le16 capabilities_info; - u8 mac_ht_params_info; - u8 supported_mcs_set[16]; - le16 extended_ht_capability_info; - le32 tx_BF_capability_info; - u8 antenna_selection_info; -} STRUCT_PACKED; - - -struct ieee80211_ht_operation { - u8 control_chan; - u8 ht_param; - le16 operation_mode; - le16 stbc_param; - u8 basic_set[16]; -} STRUCT_PACKED; - -/* auxiliary bit manipulation macros FIXME: move it to common later... */ -#define SET_2BIT_U8(_ptr_, _shift_, _val_) \ - ((*(_ptr_) &= ~(3 << (_shift_))), \ - (*(_ptr_) |= (*(_ptr_) & (((u8)3) << (_shift_))) | \ - (((u8)(_val_) & 3) << _shift_))) - -#define GET_2BIT_U8(_var_, _shift_) \ - (((_var_) & (((u8)3) << (_shift_))) >> (_shift_)) - -#define SET_2BIT_LE16(_u16ptr_, _shift_, _val_) \ - ((*(_u16ptr_) &= ~(3 << (_shift_))), \ - (*(_u16ptr_) |= \ - (((*(_u16ptr_)) & (((u16)3) << ((u16)_shift_))) | \ - (((u16)(_val_) & (u16)3) << (u16)(_shift_))))) - -#define GET_2BIT_LE16(_var_, _shift_) \ - (((_var_) & (((u16)3) << (_shift_))) >> (_shift_)) - -#define SET_2BIT_LE32(_u32ptr_, _shift_, _val_) \ - ((*(_u32ptr_) &= ~(3 << (_shift_))), \ - (*(_u32ptr_) |= (((*(_u32ptr_)) & (((u32)3) << (_shift_))) | \ - (((u32)(_val_) & 3) << _shift_)))) - -#define GET_2BIT_LE32(_var_, _shift_) \ - (((_var_) & (((u32)3) << (_shift_))) >> (_shift_)) - -#define SET_3BIT_LE16(_u16ptr_, _shift_, _val_) \ - ((*(_u16ptr_) &= ~(7 << (_shift_))), \ - (*(_u16ptr_) |= (((*(_u16ptr_)) & (((u16)7) << (_shift_))) | \ - (((u16)(_val_) & 7) << _shift_)))) - -#define GET_3BIT_LE16(_var_, _shift_) \ - (((_var_) & (((u16)7) << (_shift_))) >> (_shift_)) - -#define SET_3BIT_LE32(_u32ptr_, _shift_, _val_) \ - ((*(_u32ptr_) &= ~(7 << (_shift_))), \ - (*(_u32ptr_) |= (((*(_u32ptr_)) & (((u32)7) << (_shift_))) | \ - (((u32)(_val_) & 7) << _shift_)))) - -#define GET_3BIT_LE32(_var_, _shift_) \ - (((_var_) & (((u32)7) << (_shift_))) >> (_shift_)) - - -#define HT_CAP_INFO_LDPC_CODING_CAP ((u16) BIT(0)) -#define HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET ((u16) BIT(1)) -#define HT_CAP_INFO_SMPS_MASK ((u16) (BIT(2) | BIT(3))) -#define HT_CAP_INFO_SMPS_STATIC ((u16) 0) -#define HT_CAP_INFO_SMPS_DYNAMIC ((u16) BIT(2)) -#define HT_CAP_INFO_SMPS_DISABLED ((u16) (BIT(2) | BIT(3))) -#define HT_CAP_INFO_GREEN_FIELD ((u16) BIT(4)) -#define HT_CAP_INFO_SHORT_GI20MHZ ((u16) BIT(5)) -#define HT_CAP_INFO_SHORT_GI40MHZ ((u16) BIT(6)) -#define HT_CAP_INFO_TX_STBC ((u16) BIT(7)) -#define HT_CAP_INFO_RX_STBC_MASK ((u16) (BIT(8) | BIT(9))) -#define HT_CAP_INFO_RX_STBC_1 ((u16) BIT(8)) -#define HT_CAP_INFO_RX_STBC_12 ((u16) BIT(9)) -#define HT_CAP_INFO_RX_STBC_123 ((u16) (BIT(8) | BIT(9))) -#define HT_CAP_INFO_DELAYED_BA ((u16) BIT(10)) -#define HT_CAP_INFO_MAX_AMSDU_SIZE ((u16) BIT(11)) -#define HT_CAP_INFO_DSSS_CCK40MHZ ((u16) BIT(12)) -#define HT_CAP_INFO_PSMP_SUPP ((u16) BIT(13)) -#define HT_CAP_INFO_40MHZ_INTOLERANT ((u16) BIT(14)) -#define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT ((u16) BIT(15)) - - -#define MAC_HT_PARAM_INFO_MAX_RX_AMPDU_FACTOR_OFFSET 0 -#define MAC_HT_PARAM_INFO_MAX_MPDU_DENSITY_OFFSET 2 - -#define EXT_HT_CAP_INFO_PCO ((u16) BIT(0)) -#define EXT_HT_CAP_INFO_TRANS_TIME_OFFSET 1 -#define EXT_HT_CAP_INFO_MCS_FEEDBACK_OFFSET 8 -#define EXT_HT_CAP_INFO_HTC_SUPPORTED ((u16) BIT(10)) -#define EXT_HT_CAP_INFO_RD_RESPONDER ((u16) BIT(11)) - - -#define TX_BEAMFORM_CAP_TXBF_CAP ((u32) BIT(0)) -#define TX_BEAMFORM_CAP_RX_STAGGERED_SOUNDING_CAP ((u32) BIT(1)) -#define TX_BEAMFORM_CAP_TX_STAGGERED_SOUNDING_CAP ((u32) BIT(2)) -#define TX_BEAMFORM_CAP_RX_ZLF_CAP ((u32) BIT(3)) -#define TX_BEAMFORM_CAP_TX_ZLF_CAP ((u32) BIT(4)) -#define TX_BEAMFORM_CAP_IMPLICIT_ZLF_CAP ((u32) BIT(5)) -#define TX_BEAMFORM_CAP_CALIB_OFFSET 6 -#define TX_BEAMFORM_CAP_EXPLICIT_CSI_TXBF_CAP ((u32) BIT(8)) -#define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_CAP ((u32) BIT(9)) -#define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_CAP ((u32) BIT(10)) -#define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_OFFSET 11 -#define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_FEEDBACK_OFFSET 13 -#define TX_BEAMFORM_CAP_EXPLICIT_COMPRESSED_STEERING_MATRIX_FEEDBACK_OFFSET 15 -#define TX_BEAMFORM_CAP_MINIMAL_GROUPING_OFFSET 17 -#define TX_BEAMFORM_CAP_CSI_NUM_BEAMFORMER_ANT_OFFSET 19 -#define TX_BEAMFORM_CAP_UNCOMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 21 -#define TX_BEAMFORM_CAP_COMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 23 -#define TX_BEAMFORM_CAP_SCI_MAX_OF_ROWS_BEANFORMER_SUPPORTED_OFFSET 25 - - -#define ASEL_CAPABILITY_ASEL_CAPABLE ((u8) BIT(0)) -#define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(1)) -#define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(2)) -#define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_CAP ((u8) BIT(3)) -#define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_CAP ((u8) BIT(4)) -#define ASEL_CAPABILITY_RX_AS_CAP ((u8) BIT(5)) -#define ASEL_CAPABILITY_TX_SOUND_PPDUS_CAP ((u8) BIT(6)) - - -struct ht_cap_ie { - u8 id; - u8 length; - struct ieee80211_ht_capability data; -} STRUCT_PACKED; - - -#define REC_TRANS_CHNL_WIDTH_20 0 -#define REC_TRANS_CHNL_WIDTH_ANY 1 - -#define OP_MODE_PURE 0 -#define OP_MODE_MAY_BE_LEGACY_STAS 1 -#define OP_MODE_20MHZ_HT_STA_ASSOCED 2 -#define OP_MODE_MIXED 3 - -#define HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK ((u8) BIT(0) | BIT(1)) -#define HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE ((u8) BIT(0)) -#define HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW ((u8) BIT(0) | BIT(1)) -#define HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH ((u8) BIT(2)) -#define HT_INFO_HT_PARAM_RIFS_MODE ((u8) BIT(3)) -#define HT_INFO_HT_PARAM_CTRL_ACCESS_ONLY ((u8) BIT(4)) -#define HT_INFO_HT_PARAM_SRV_INTERVAL_GRANULARITY ((u8) BIT(5)) - -#define HT_INFO_OPERATION_MODE_OP_MODE_MASK \ - ((le16) (0x0001 | 0x0002)) -#define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET 0 -#define HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT ((u8) BIT(2)) -#define HT_INFO_OPERATION_MODE_TRANSMIT_BURST_LIMIT ((u8) BIT(3)) -#define HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT ((u8) BIT(4)) - -#define HT_INFO_STBC_PARAM_DUAL_BEACON ((u16) BIT(6)) -#define HT_INFO_STBC_PARAM_DUAL_STBC_PROTECT ((u16) BIT(7)) -#define HT_INFO_STBC_PARAM_SECONDARY_BCN ((u16) BIT(8)) -#define HT_INFO_STBC_PARAM_LSIG_TXOP_PROTECT_ALLOWED ((u16) BIT(9)) -#define HT_INFO_STBC_PARAM_PCO_ACTIVE ((u16) BIT(10)) -#define HT_INFO_STBC_PARAM_PCO_PHASE ((u16) BIT(11)) - - -/* Secondary channel offset element */ -#define SECONDARY_CHANNEL_OFFSET_NONE 0 -#define SECONDARY_CHANNEL_OFFSET_ABOVE 1 -#define SECONDARY_CHANNEL_OFFSET_BELOW 3 -struct secondary_channel_offset_ie { - u8 id; - u8 length; - u8 secondary_offset_offset; -} STRUCT_PACKED; - - -/* body of Recommended Transmit Channel Width action frame */ -#define CHANNEL_WIDTH_20 0 -#define CHANNEL_WIDTH_ANY 1 -struct recommended_tx_channel_width_action { - u8 category; - u8 action; - u8 channel_width; -} STRUCT_PACKED; - -/* body of MIMO Power Save action frame */ -#define PWR_SAVE_MODE_STATIC 0 -#define PWR_SAVE_MODE_DYNAMIC 1 -struct mimo_pwr_save_action { - u8 category; - u8 action; - u8 enable; - u8 mode; -} STRUCT_PACKED; - - -#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs) - * 00:50:F2 */ - -#define WMM_OUI_TYPE 2 -#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0 -#define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1 -#define WMM_OUI_SUBTYPE_TSPEC_ELEMENT 2 -#define WMM_VERSION 1 - -#define WMM_ACTION_CODE_ADDTS_REQ 0 -#define WMM_ACTION_CODE_ADDTS_RESP 1 -#define WMM_ACTION_CODE_DELTS 2 - -#define WMM_ADDTS_STATUS_ADMISSION_ACCEPTED 0 -#define WMM_ADDTS_STATUS_INVALID_PARAMETERS 1 -/* 2 - Reserved */ -#define WMM_ADDTS_STATUS_REFUSED 3 -/* 4-255 - Reserved */ - -/* WMM TSPEC Direction Field Values */ -#define WMM_TSPEC_DIRECTION_UPLINK 0 -#define WMM_TSPEC_DIRECTION_DOWNLINK 1 -/* 2 - Reserved */ -#define WMM_TSPEC_DIRECTION_BI_DIRECTIONAL 3 - - -#define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */ - -#define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */ - -#endif /* IEEE802_11_DEFS_H */ diff --git a/contrib/hostapd/src/common/nl80211_copy.h b/contrib/hostapd/src/common/nl80211_copy.h deleted file mode 100644 index 45db17f81a..0000000000 --- a/contrib/hostapd/src/common/nl80211_copy.h +++ /dev/null @@ -1,1434 +0,0 @@ -#ifndef __LINUX_NL80211_H -#define __LINUX_NL80211_H -/* - * 802.11 netlink interface public header - * - * Copyright 2006, 2007, 2008 Johannes Berg - * Copyright 2008 Michael Wu - * Copyright 2008 Luis Carlos Cobo - * Copyright 2008 Michael Buesch - * Copyright 2008, 2009 Luis R. Rodriguez - * Copyright 2008 Jouni Malinen - * Copyright 2008 Colin McCabe - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include - -/** - * DOC: Station handling - * - * Stations are added per interface, but a special case exists with VLAN - * interfaces. When a station is bound to an AP interface, it may be moved - * into a VLAN identified by a VLAN interface index (%NL80211_ATTR_STA_VLAN). - * The station is still assumed to belong to the AP interface it was added - * to. - * - * TODO: need more info? - */ - -/** - * enum nl80211_commands - supported nl80211 commands - * - * @NL80211_CMD_UNSPEC: unspecified command to catch errors - * - * @NL80211_CMD_GET_WIPHY: request information about a wiphy or dump request - * to get a list of all present wiphys. - * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or - * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME, - * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, - * %NL80211_ATTR_WIPHY_CHANNEL_TYPE, %NL80211_ATTR_WIPHY_RETRY_SHORT, - * %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD, - * and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD. - * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request - * or rename notification. Has attributes %NL80211_ATTR_WIPHY and - * %NL80211_ATTR_WIPHY_NAME. - * @NL80211_CMD_DEL_WIPHY: Wiphy deleted. Has attributes - * %NL80211_ATTR_WIPHY and %NL80211_ATTR_WIPHY_NAME. - * - * @NL80211_CMD_GET_INTERFACE: Request an interface's configuration; - * either a dump request on a %NL80211_ATTR_WIPHY or a specific get - * on an %NL80211_ATTR_IFINDEX is supported. - * @NL80211_CMD_SET_INTERFACE: Set type of a virtual interface, requires - * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_IFTYPE. - * @NL80211_CMD_NEW_INTERFACE: Newly created virtual interface or response - * to %NL80211_CMD_GET_INTERFACE. Has %NL80211_ATTR_IFINDEX, - * %NL80211_ATTR_WIPHY and %NL80211_ATTR_IFTYPE attributes. Can also - * be sent from userspace to request creation of a new virtual interface, - * then requires attributes %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFTYPE and - * %NL80211_ATTR_IFNAME. - * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes - * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from - * userspace to request deletion of a virtual interface, then requires - * attribute %NL80211_ATTR_IFINDEX. - * - * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified - * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. - * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT, - * %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD. - * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA, - * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER, - * and %NL80211_ATTR_KEY_SEQ attributes. - * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX - * or %NL80211_ATTR_MAC. - * - * @NL80211_CMD_GET_BEACON: retrieve beacon information (returned in a - * %NL80222_CMD_NEW_BEACON message) - * @NL80211_CMD_SET_BEACON: set the beacon on an access point interface - * using the %NL80211_ATTR_BEACON_INTERVAL, %NL80211_ATTR_DTIM_PERIOD, - * %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL attributes. - * @NL80211_CMD_NEW_BEACON: add a new beacon to an access point interface, - * parameters are like for %NL80211_CMD_SET_BEACON. - * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it - * - * @NL80211_CMD_GET_STATION: Get station attributes for station identified by - * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_SET_STATION: Set station attributes for station identified by - * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_NEW_STATION: Add a station with given attributes to the - * the interface identified by %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_DEL_STATION: Remove a station identified by %NL80211_ATTR_MAC - * or, if no MAC address given, all stations, on the interface identified - * by %NL80211_ATTR_IFINDEX. - * - * @NL80211_CMD_GET_MPATH: Get mesh path attributes for mesh path to - * destination %NL80211_ATTR_MAC on the interface identified by - * %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_SET_MPATH: Set mesh path attributes for mesh path to - * destination %NL80211_ATTR_MAC on the interface identified by - * %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the - * the interface identified by %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC - * or, if no MAC address given, all mesh paths, on the interface identified - * by %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by - * %NL80211_ATTR_IFINDEX. - * - * @NL80211_CMD_GET_REG: ask the wireless core to send us its currently set - * regulatory domain. - * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command - * after being queried by the kernel. CRDA replies by sending a regulatory - * domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our - * current alpha2 if it found a match. It also provides - * NL80211_ATTR_REG_RULE_FLAGS, and a set of regulatory rules. Each - * regulatory rule is a nested set of attributes given by - * %NL80211_ATTR_REG_RULE_FREQ_[START|END] and - * %NL80211_ATTR_FREQ_RANGE_MAX_BW with an attached power rule given by - * %NL80211_ATTR_REG_RULE_POWER_MAX_ANT_GAIN and - * %NL80211_ATTR_REG_RULE_POWER_MAX_EIRP. - * @NL80211_CMD_REQ_SET_REG: ask the wireless core to set the regulatory domain - * to the the specified ISO/IEC 3166-1 alpha2 country code. The core will - * store this as a valid request and then query userspace for it. - * - * @NL80211_CMD_GET_MESH_PARAMS: Get mesh networking properties for the - * interface identified by %NL80211_ATTR_IFINDEX - * - * @NL80211_CMD_SET_MESH_PARAMS: Set mesh networking properties for the - * interface identified by %NL80211_ATTR_IFINDEX - * - * @NL80211_CMD_SET_MGMT_EXTRA_IE: Set extra IEs for management frames. The - * interface is identified with %NL80211_ATTR_IFINDEX and the management - * frame subtype with %NL80211_ATTR_MGMT_SUBTYPE. The extra IE data to be - * added to the end of the specified management frame is specified with - * %NL80211_ATTR_IE. If the command succeeds, the requested data will be - * added to all specified management frames generated by - * kernel/firmware/driver. - * Note: This command has been removed and it is only reserved at this - * point to avoid re-using existing command number. The functionality this - * command was planned for has been provided with cleaner design with the - * option to specify additional IEs in NL80211_CMD_TRIGGER_SCAN, - * NL80211_CMD_AUTHENTICATE, NL80211_CMD_ASSOCIATE, - * NL80211_CMD_DEAUTHENTICATE, and NL80211_CMD_DISASSOCIATE. - * - * @NL80211_CMD_GET_SCAN: get scan results - * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters - * @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to - * NL80211_CMD_GET_SCAN and on the "scan" multicast group) - * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, - * partial scan results may be available - * - * @NL80211_CMD_GET_SURVEY: get survey resuls, e.g. channel occupation - * or noise level - * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to - * NL80211_CMD_GET_SURVEY and on the "scan" multicast group) - * - * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain - * has been changed and provides details of the request information - * that caused the change such as who initiated the regulatory request - * (%NL80211_ATTR_REG_INITIATOR), the wiphy_idx - * (%NL80211_ATTR_REG_ALPHA2) on which the request was made from if - * the initiator was %NL80211_REGDOM_SET_BY_COUNTRY_IE or - * %NL80211_REGDOM_SET_BY_DRIVER, the type of regulatory domain - * set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is - * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on - * to (%NL80211_ATTR_REG_ALPHA2). - * @NL80211_CMD_REG_BEACON_HINT: indicates to userspace that an AP beacon - * has been found while world roaming thus enabling active scan or - * any mode of operation that initiates TX (beacons) on a channel - * where we would not have been able to do either before. As an example - * if you are world roaming (regulatory domain set to world or if your - * driver is using a custom world roaming regulatory domain) and while - * doing a passive scan on the 5 GHz band you find an AP there (if not - * on a DFS channel) you will now be able to actively scan for that AP - * or use AP mode on your card on that same channel. Note that this will - * never be used for channels 1-11 on the 2 GHz band as they are always - * enabled world wide. This beacon hint is only sent if your device had - * either disabled active scanning or beaconing on a channel. We send to - * userspace the wiphy on which we removed a restriction from - * (%NL80211_ATTR_WIPHY) and the channel on which this occurred - * before (%NL80211_ATTR_FREQ_BEFORE) and after (%NL80211_ATTR_FREQ_AFTER) - * the beacon hint was processed. - * - * @NL80211_CMD_AUTHENTICATE: authentication request and notification. - * This command is used both as a command (request to authenticate) and - * as an event on the "mlme" multicast group indicating completion of the - * authentication process. - * When used as a command, %NL80211_ATTR_IFINDEX is used to identify the - * interface. %NL80211_ATTR_MAC is used to specify PeerSTAAddress (and - * BSSID in case of station mode). %NL80211_ATTR_SSID is used to specify - * the SSID (mainly for association, but is included in authentication - * request, too, to help BSS selection. %NL80211_ATTR_WIPHY_FREQ is used - * to specify the frequence of the channel in MHz. %NL80211_ATTR_AUTH_TYPE - * is used to specify the authentication type. %NL80211_ATTR_IE is used to - * define IEs (VendorSpecificInfo, but also including RSN IE and FT IEs) - * to be added to the frame. - * When used as an event, this reports reception of an Authentication - * frame in station and IBSS modes when the local MLME processed the - * frame, i.e., it was for the local STA and was received in correct - * state. This is similar to MLME-AUTHENTICATE.confirm primitive in the - * MLME SAP interface (kernel providing MLME, userspace SME). The - * included %NL80211_ATTR_FRAME attribute contains the management frame - * (including both the header and frame body, but not FCS). This event is - * also used to indicate if the authentication attempt timed out. In that - * case the %NL80211_ATTR_FRAME attribute is replaced with a - * %NL80211_ATTR_TIMED_OUT flag (and %NL80211_ATTR_MAC to indicate which - * pending authentication timed out). - * @NL80211_CMD_ASSOCIATE: association request and notification; like - * NL80211_CMD_AUTHENTICATE but for Association and Reassociation - * (similar to MLME-ASSOCIATE.request, MLME-REASSOCIATE.request, - * MLME-ASSOCIATE.confirm or MLME-REASSOCIATE.confirm primitives). - * @NL80211_CMD_DEAUTHENTICATE: deauthentication request and notification; like - * NL80211_CMD_AUTHENTICATE but for Deauthentication frames (similar to - * MLME-DEAUTHENTICATION.request and MLME-DEAUTHENTICATE.indication - * primitives). - * @NL80211_CMD_DISASSOCIATE: disassociation request and notification; like - * NL80211_CMD_AUTHENTICATE but for Disassociation frames (similar to - * MLME-DISASSOCIATE.request and MLME-DISASSOCIATE.indication primitives). - * - * @NL80211_CMD_MICHAEL_MIC_FAILURE: notification of a locally detected Michael - * MIC (part of TKIP) failure; sent on the "mlme" multicast group; the - * event includes %NL80211_ATTR_MAC to describe the source MAC address of - * the frame with invalid MIC, %NL80211_ATTR_KEY_TYPE to show the key - * type, %NL80211_ATTR_KEY_IDX to indicate the key identifier, and - * %NL80211_ATTR_KEY_SEQ to indicate the TSC value of the frame; this - * event matches with MLME-MICHAELMICFAILURE.indication() primitive - * - * @NL80211_CMD_JOIN_IBSS: Join a new IBSS -- given at least an SSID and a - * FREQ attribute (for the initial frequency if no peer can be found) - * and optionally a MAC (as BSSID) and FREQ_FIXED attribute if those - * should be fixed rather than automatically determined. Can only be - * executed on a network interface that is UP, and fixed BSSID/FREQ - * may be rejected. Another optional parameter is the beacon interval, - * given in the %NL80211_ATTR_BEACON_INTERVAL attribute, which if not - * given defaults to 100 TU (102.4ms). - * @NL80211_CMD_LEAVE_IBSS: Leave the IBSS -- no special arguments, the IBSS is - * determined by the network interface. - * - * @NL80211_CMD_TESTMODE: testmode command, takes a wiphy (or ifindex) attribute - * to identify the device, and the TESTDATA blob attribute to pass through - * to the driver. - * - * @NL80211_CMD_CONNECT: connection request and notification; this command - * requests to connect to a specified network but without separating - * auth and assoc steps. For this, you need to specify the SSID in a - * %NL80211_ATTR_SSID attribute, and can optionally specify the association - * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_MAC, - * %NL80211_ATTR_WIPHY_FREQ and %NL80211_ATTR_CONTROL_PORT. - * It is also sent as an event, with the BSSID and response IEs when the - * connection is established or failed to be established. This can be - * determined by the STATUS_CODE attribute. - * @NL80211_CMD_ROAM: request that the card roam (currently not implemented), - * sent as an event when the card/driver roamed by itself. - * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify - * userspace that a connection was dropped by the AP or due to other - * reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and - * %NL80211_ATTR_REASON_CODE attributes are used. - * - * @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices - * associated with this wiphy must be down and will follow. - * - * @NL80211_CMD_MAX: highest used command number - * @__NL80211_CMD_AFTER_LAST: internal use - */ -enum nl80211_commands { -/* don't change the order or add anything inbetween, this is ABI! */ - NL80211_CMD_UNSPEC, - - NL80211_CMD_GET_WIPHY, /* can dump */ - NL80211_CMD_SET_WIPHY, - NL80211_CMD_NEW_WIPHY, - NL80211_CMD_DEL_WIPHY, - - NL80211_CMD_GET_INTERFACE, /* can dump */ - NL80211_CMD_SET_INTERFACE, - NL80211_CMD_NEW_INTERFACE, - NL80211_CMD_DEL_INTERFACE, - - NL80211_CMD_GET_KEY, - NL80211_CMD_SET_KEY, - NL80211_CMD_NEW_KEY, - NL80211_CMD_DEL_KEY, - - NL80211_CMD_GET_BEACON, - NL80211_CMD_SET_BEACON, - NL80211_CMD_NEW_BEACON, - NL80211_CMD_DEL_BEACON, - - NL80211_CMD_GET_STATION, - NL80211_CMD_SET_STATION, - NL80211_CMD_NEW_STATION, - NL80211_CMD_DEL_STATION, - - NL80211_CMD_GET_MPATH, - NL80211_CMD_SET_MPATH, - NL80211_CMD_NEW_MPATH, - NL80211_CMD_DEL_MPATH, - - NL80211_CMD_SET_BSS, - - NL80211_CMD_SET_REG, - NL80211_CMD_REQ_SET_REG, - - NL80211_CMD_GET_MESH_PARAMS, - NL80211_CMD_SET_MESH_PARAMS, - - NL80211_CMD_SET_MGMT_EXTRA_IE /* reserved; not used */, - - NL80211_CMD_GET_REG, - - NL80211_CMD_GET_SCAN, - NL80211_CMD_TRIGGER_SCAN, - NL80211_CMD_NEW_SCAN_RESULTS, - NL80211_CMD_SCAN_ABORTED, - - NL80211_CMD_REG_CHANGE, - - NL80211_CMD_AUTHENTICATE, - NL80211_CMD_ASSOCIATE, - NL80211_CMD_DEAUTHENTICATE, - NL80211_CMD_DISASSOCIATE, - - NL80211_CMD_MICHAEL_MIC_FAILURE, - - NL80211_CMD_REG_BEACON_HINT, - - NL80211_CMD_JOIN_IBSS, - NL80211_CMD_LEAVE_IBSS, - - NL80211_CMD_TESTMODE, - - NL80211_CMD_CONNECT, - NL80211_CMD_ROAM, - NL80211_CMD_DISCONNECT, - - NL80211_CMD_SET_WIPHY_NETNS, - - NL80211_CMD_GET_SURVEY, - NL80211_CMD_NEW_SURVEY_RESULTS, - - /* add new commands above here */ - - /* used to define NL80211_CMD_MAX below */ - __NL80211_CMD_AFTER_LAST, - NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1 -}; - -/* - * Allow user space programs to use #ifdef on new commands by defining them - * here - */ -#define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS -#define NL80211_CMD_SET_MGMT_EXTRA_IE NL80211_CMD_SET_MGMT_EXTRA_IE -#define NL80211_CMD_REG_CHANGE NL80211_CMD_REG_CHANGE -#define NL80211_CMD_AUTHENTICATE NL80211_CMD_AUTHENTICATE -#define NL80211_CMD_ASSOCIATE NL80211_CMD_ASSOCIATE -#define NL80211_CMD_DEAUTHENTICATE NL80211_CMD_DEAUTHENTICATE -#define NL80211_CMD_DISASSOCIATE NL80211_CMD_DISASSOCIATE -#define NL80211_CMD_REG_BEACON_HINT NL80211_CMD_REG_BEACON_HINT - -/** - * enum nl80211_attrs - nl80211 netlink attributes - * - * @NL80211_ATTR_UNSPEC: unspecified attribute to catch errors - * - * @NL80211_ATTR_WIPHY: index of wiphy to operate on, cf. - * /sys/class/ieee80211//index - * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming) - * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters - * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz - * @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ - * if HT20 or HT40 are allowed (i.e., 802.11n disabled if not included): - * NL80211_CHAN_NO_HT = HT not allowed (i.e., same as not including - * this attribute) - * NL80211_CHAN_HT20 = HT20 only - * NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel - * NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel - * @NL80211_ATTR_WIPHY_RETRY_SHORT: TX retry limit for frames whose length is - * less than or equal to the RTS threshold; allowed range: 1..255; - * dot11ShortRetryLimit; u8 - * @NL80211_ATTR_WIPHY_RETRY_LONG: TX retry limit for frames whose length is - * greater than the RTS threshold; allowed range: 1..255; - * dot11ShortLongLimit; u8 - * @NL80211_ATTR_WIPHY_FRAG_THRESHOLD: fragmentation threshold, i.e., maximum - * length in octets for frames; allowed range: 256..8000, disable - * fragmentation with (u32)-1; dot11FragmentationThreshold; u32 - * @NL80211_ATTR_WIPHY_RTS_THRESHOLD: RTS threshold (TX frames with length - * larger than or equal to this use RTS/CTS handshake); allowed range: - * 0..65536, disable with (u32)-1; dot11RTSThreshold; u32 - * - * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on - * @NL80211_ATTR_IFNAME: network interface name - * @NL80211_ATTR_IFTYPE: type of virtual interface, see &enum nl80211_iftype - * - * @NL80211_ATTR_MAC: MAC address (various uses) - * - * @NL80211_ATTR_KEY_DATA: (temporal) key data; for TKIP this consists of - * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC - * keys - * @NL80211_ATTR_KEY_IDX: key ID (u8, 0-3) - * @NL80211_ATTR_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11 - * section 7.3.2.25.1, e.g. 0x000FAC04) - * @NL80211_ATTR_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and - * CCMP keys, each six bytes in little endian - * - * @NL80211_ATTR_BEACON_INTERVAL: beacon interval in TU - * @NL80211_ATTR_DTIM_PERIOD: DTIM period for beaconing - * @NL80211_ATTR_BEACON_HEAD: portion of the beacon before the TIM IE - * @NL80211_ATTR_BEACON_TAIL: portion of the beacon after the TIM IE - * - * @NL80211_ATTR_STA_AID: Association ID for the station (u16) - * @NL80211_ATTR_STA_FLAGS: flags, nested element with NLA_FLAG attributes of - * &enum nl80211_sta_flags (deprecated, use %NL80211_ATTR_STA_FLAGS2) - * @NL80211_ATTR_STA_LISTEN_INTERVAL: listen interval as defined by - * IEEE 802.11 7.3.1.6 (u16). - * @NL80211_ATTR_STA_SUPPORTED_RATES: supported rates, array of supported - * rates as defined by IEEE 802.11 7.3.2.2 but without the length - * restriction (at most %NL80211_MAX_SUPP_RATES). - * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station - * to, or the AP interface the station was originally added to to. - * @NL80211_ATTR_STA_INFO: information about a station, part of station info - * given for %NL80211_CMD_GET_STATION, nested attribute containing - * info as possible, see &enum nl80211_sta_info. - * - * @NL80211_ATTR_WIPHY_BANDS: Information about an operating bands, - * consisting of a nested array. - * - * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes). - * @NL80211_ATTR_PLINK_ACTION: action to perform on the mesh peer link. - * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path. - * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path - * info given for %NL80211_CMD_GET_MPATH, nested attribute described at - * &enum nl80211_mpath_info. - * - * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of - * &enum nl80211_mntr_flags. - * - * @NL80211_ATTR_REG_ALPHA2: an ISO-3166-alpha2 country code for which the - * current regulatory domain should be set to or is already set to. - * For example, 'CR', for Costa Rica. This attribute is used by the kernel - * to query the CRDA to retrieve one regulatory domain. This attribute can - * also be used by userspace to query the kernel for the currently set - * regulatory domain. We chose an alpha2 as that is also used by the - * IEEE-802.11d country information element to identify a country. - * Users can also simply ask the wireless core to set regulatory domain - * to a specific alpha2. - * @NL80211_ATTR_REG_RULES: a nested array of regulatory domain regulatory - * rules. - * - * @NL80211_ATTR_BSS_CTS_PROT: whether CTS protection is enabled (u8, 0 or 1) - * @NL80211_ATTR_BSS_SHORT_PREAMBLE: whether short preamble is enabled - * (u8, 0 or 1) - * @NL80211_ATTR_BSS_SHORT_SLOT_TIME: whether short slot time enabled - * (u8, 0 or 1) - * @NL80211_ATTR_BSS_BASIC_RATES: basic rates, array of basic - * rates in format defined by IEEE 802.11 7.3.2.2 but without the length - * restriction (at most %NL80211_MAX_SUPP_RATES). - * - * @NL80211_ATTR_HT_CAPABILITY: HT Capability information element (from - * association request when used with NL80211_CMD_NEW_STATION) - * - * @NL80211_ATTR_SUPPORTED_IFTYPES: nested attribute containing all - * supported interface types, each a flag attribute with the number - * of the interface mode. - * - * @NL80211_ATTR_MGMT_SUBTYPE: Management frame subtype for - * %NL80211_CMD_SET_MGMT_EXTRA_IE. - * - * @NL80211_ATTR_IE: Information element(s) data (used, e.g., with - * %NL80211_CMD_SET_MGMT_EXTRA_IE). - * - * @NL80211_ATTR_MAX_NUM_SCAN_SSIDS: number of SSIDs you can scan with - * a single scan request, a wiphy attribute. - * @NL80211_ATTR_MAX_SCAN_IE_LEN: maximum length of information elements - * that can be added to a scan request - * - * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz) - * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive - * scanning and include a zero-length SSID (wildcard) for wildcard scan - * @NL80211_ATTR_BSS: scan result BSS - * - * @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain - * currently in effect. This could be any of the %NL80211_REGDOM_SET_BY_* - * @NL80211_ATTR_REG_TYPE: indicates the type of the regulatory domain currently - * set. This can be one of the nl80211_reg_type (%NL80211_REGDOM_TYPE_*) - * - * @NL80211_ATTR_SUPPORTED_COMMANDS: wiphy attribute that specifies - * an array of command numbers (i.e. a mapping index to command number) - * that the driver for the given wiphy supports. - * - * @NL80211_ATTR_FRAME: frame data (binary attribute), including frame header - * and body, but not FCS; used, e.g., with NL80211_CMD_AUTHENTICATE and - * NL80211_CMD_ASSOCIATE events - * @NL80211_ATTR_SSID: SSID (binary attribute, 0..32 octets) - * @NL80211_ATTR_AUTH_TYPE: AuthenticationType, see &enum nl80211_auth_type, - * represented as a u32 - * @NL80211_ATTR_REASON_CODE: ReasonCode for %NL80211_CMD_DEAUTHENTICATE and - * %NL80211_CMD_DISASSOCIATE, u16 - * - * @NL80211_ATTR_KEY_TYPE: Key Type, see &enum nl80211_key_type, represented as - * a u32 - * - * @NL80211_ATTR_FREQ_BEFORE: A channel which has suffered a regulatory change - * due to considerations from a beacon hint. This attribute reflects - * the state of the channel _before_ the beacon hint processing. This - * attributes consists of a nested attribute containing - * NL80211_FREQUENCY_ATTR_* - * @NL80211_ATTR_FREQ_AFTER: A channel which has suffered a regulatory change - * due to considerations from a beacon hint. This attribute reflects - * the state of the channel _after_ the beacon hint processing. This - * attributes consists of a nested attribute containing - * NL80211_FREQUENCY_ATTR_* - * - * @NL80211_ATTR_CIPHER_SUITES: a set of u32 values indicating the supported - * cipher suites - * - * @NL80211_ATTR_FREQ_FIXED: a flag indicating the IBSS should not try to look - * for other networks on different channels - * - * @NL80211_ATTR_TIMED_OUT: a flag indicating than an operation timed out; this - * is used, e.g., with %NL80211_CMD_AUTHENTICATE event - * - * @NL80211_ATTR_USE_MFP: Whether management frame protection (IEEE 802.11w) is - * used for the association (&enum nl80211_mfp, represented as a u32); - * this attribute can be used - * with %NL80211_CMD_ASSOCIATE request - * - * @NL80211_ATTR_STA_FLAGS2: Attribute containing a - * &struct nl80211_sta_flag_update. - * - * @NL80211_ATTR_CONTROL_PORT: A flag indicating whether user space controls - * IEEE 802.1X port, i.e., sets/clears %NL80211_STA_FLAG_AUTHORIZED, in - * station mode. If the flag is included in %NL80211_CMD_ASSOCIATE - * request, the driver will assume that the port is unauthorized until - * authorized by user space. Otherwise, port is marked authorized by - * default in station mode. - * - * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver. - * We recommend using nested, driver-specific attributes within this. - * - * @NL80211_ATTR_DISCONNECTED_BY_AP: A flag indicating that the DISCONNECT - * event was due to the AP disconnecting the station, and not due to - * a local disconnect request. - * @NL80211_ATTR_STATUS_CODE: StatusCode for the %NL80211_CMD_CONNECT - * event (u16) - * @NL80211_ATTR_PRIVACY: Flag attribute, used with connect(), indicating - * that protected APs should be used. - * - * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT and ASSOCIATE to - * indicate which unicast key ciphers will be used with the connection - * (an array of u32). - * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT and ASSOCIATE to indicate - * which group key cipher will be used with the connection (a u32). - * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT and ASSOCIATE to indicate - * which WPA version(s) the AP we want to associate with is using - * (a u32 with flags from &enum nl80211_wpa_versions). - * @NL80211_ATTR_AKM_SUITES: Used with CONNECT and ASSOCIATE to indicate - * which key management algorithm(s) to use (an array of u32). - * - * @NL80211_ATTR_REQ_IE: (Re)association request information elements as - * sent out by the card, for ROAM and successful CONNECT events. - * @NL80211_ATTR_RESP_IE: (Re)association response information elements as - * sent by peer, for ROAM and successful CONNECT events. - * - * @NL80211_ATTR_PREV_BSSID: previous BSSID, to be used by in ASSOCIATE - * commands to specify using a reassociate frame - * - * @NL80211_ATTR_KEY: key information in a nested attribute with - * %NL80211_KEY_* sub-attributes - * @NL80211_ATTR_KEYS: array of keys for static WEP keys for connect() - * and join_ibss(), key information is in a nested attribute each - * with %NL80211_KEY_* sub-attributes - * - * @NL80211_ATTR_PID: Process ID of a network namespace. - * - * @NL80211_ATTR_GENERATION: Used to indicate consistent snapshots for - * dumps. This number increases whenever the object list being - * dumped changes, and as such userspace can verify that it has - * obtained a complete and consistent snapshot by verifying that - * all dump messages contain the same generation number. If it - * changed then the list changed and the dump should be repeated - * completely from scratch. - * - * @NL80211_ATTR_4ADDR: Use 4-address frames on a virtual interface - * - * @NL80211_ATTR_SURVEY_INFO: survey information about a channel, part of - * the survey response for %NL80211_CMD_GET_SURVEY, nested attribute - * containing info as possible, see &enum survey_info. - * - * @NL80211_ATTR_MAX: highest attribute number currently defined - * @__NL80211_ATTR_AFTER_LAST: internal use - */ -enum nl80211_attrs { -/* don't change the order or add anything inbetween, this is ABI! */ - NL80211_ATTR_UNSPEC, - - NL80211_ATTR_WIPHY, - NL80211_ATTR_WIPHY_NAME, - - NL80211_ATTR_IFINDEX, - NL80211_ATTR_IFNAME, - NL80211_ATTR_IFTYPE, - - NL80211_ATTR_MAC, - - NL80211_ATTR_KEY_DATA, - NL80211_ATTR_KEY_IDX, - NL80211_ATTR_KEY_CIPHER, - NL80211_ATTR_KEY_SEQ, - NL80211_ATTR_KEY_DEFAULT, - - NL80211_ATTR_BEACON_INTERVAL, - NL80211_ATTR_DTIM_PERIOD, - NL80211_ATTR_BEACON_HEAD, - NL80211_ATTR_BEACON_TAIL, - - NL80211_ATTR_STA_AID, - NL80211_ATTR_STA_FLAGS, - NL80211_ATTR_STA_LISTEN_INTERVAL, - NL80211_ATTR_STA_SUPPORTED_RATES, - NL80211_ATTR_STA_VLAN, - NL80211_ATTR_STA_INFO, - - NL80211_ATTR_WIPHY_BANDS, - - NL80211_ATTR_MNTR_FLAGS, - - NL80211_ATTR_MESH_ID, - NL80211_ATTR_STA_PLINK_ACTION, - NL80211_ATTR_MPATH_NEXT_HOP, - NL80211_ATTR_MPATH_INFO, - - NL80211_ATTR_BSS_CTS_PROT, - NL80211_ATTR_BSS_SHORT_PREAMBLE, - NL80211_ATTR_BSS_SHORT_SLOT_TIME, - - NL80211_ATTR_HT_CAPABILITY, - - NL80211_ATTR_SUPPORTED_IFTYPES, - - NL80211_ATTR_REG_ALPHA2, - NL80211_ATTR_REG_RULES, - - NL80211_ATTR_MESH_PARAMS, - - NL80211_ATTR_BSS_BASIC_RATES, - - NL80211_ATTR_WIPHY_TXQ_PARAMS, - NL80211_ATTR_WIPHY_FREQ, - NL80211_ATTR_WIPHY_CHANNEL_TYPE, - - NL80211_ATTR_KEY_DEFAULT_MGMT, - - NL80211_ATTR_MGMT_SUBTYPE, - NL80211_ATTR_IE, - - NL80211_ATTR_MAX_NUM_SCAN_SSIDS, - - NL80211_ATTR_SCAN_FREQUENCIES, - NL80211_ATTR_SCAN_SSIDS, - NL80211_ATTR_GENERATION, /* replaces old SCAN_GENERATION */ - NL80211_ATTR_BSS, - - NL80211_ATTR_REG_INITIATOR, - NL80211_ATTR_REG_TYPE, - - NL80211_ATTR_SUPPORTED_COMMANDS, - - NL80211_ATTR_FRAME, - NL80211_ATTR_SSID, - NL80211_ATTR_AUTH_TYPE, - NL80211_ATTR_REASON_CODE, - - NL80211_ATTR_KEY_TYPE, - - NL80211_ATTR_MAX_SCAN_IE_LEN, - NL80211_ATTR_CIPHER_SUITES, - - NL80211_ATTR_FREQ_BEFORE, - NL80211_ATTR_FREQ_AFTER, - - NL80211_ATTR_FREQ_FIXED, - - - NL80211_ATTR_WIPHY_RETRY_SHORT, - NL80211_ATTR_WIPHY_RETRY_LONG, - NL80211_ATTR_WIPHY_FRAG_THRESHOLD, - NL80211_ATTR_WIPHY_RTS_THRESHOLD, - - NL80211_ATTR_TIMED_OUT, - - NL80211_ATTR_USE_MFP, - - NL80211_ATTR_STA_FLAGS2, - - NL80211_ATTR_CONTROL_PORT, - - NL80211_ATTR_TESTDATA, - - NL80211_ATTR_PRIVACY, - - NL80211_ATTR_DISCONNECTED_BY_AP, - NL80211_ATTR_STATUS_CODE, - - NL80211_ATTR_CIPHER_SUITES_PAIRWISE, - NL80211_ATTR_CIPHER_SUITE_GROUP, - NL80211_ATTR_WPA_VERSIONS, - NL80211_ATTR_AKM_SUITES, - - NL80211_ATTR_REQ_IE, - NL80211_ATTR_RESP_IE, - - NL80211_ATTR_PREV_BSSID, - - NL80211_ATTR_KEY, - NL80211_ATTR_KEYS, - - NL80211_ATTR_PID, - - NL80211_ATTR_4ADDR, - - NL80211_ATTR_SURVEY_INFO, - - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, - NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1 -}; - -/* source-level API compatibility */ -#define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION - -/* - * Allow user space programs to use #ifdef on new attributes by defining them - * here - */ -#define NL80211_CMD_CONNECT NL80211_CMD_CONNECT -#define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY -#define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES -#define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS -#define NL80211_ATTR_WIPHY_FREQ NL80211_ATTR_WIPHY_FREQ -#define NL80211_ATTR_WIPHY_CHANNEL_TYPE NL80211_ATTR_WIPHY_CHANNEL_TYPE -#define NL80211_ATTR_MGMT_SUBTYPE NL80211_ATTR_MGMT_SUBTYPE -#define NL80211_ATTR_IE NL80211_ATTR_IE -#define NL80211_ATTR_REG_INITIATOR NL80211_ATTR_REG_INITIATOR -#define NL80211_ATTR_REG_TYPE NL80211_ATTR_REG_TYPE -#define NL80211_ATTR_FRAME NL80211_ATTR_FRAME -#define NL80211_ATTR_SSID NL80211_ATTR_SSID -#define NL80211_ATTR_AUTH_TYPE NL80211_ATTR_AUTH_TYPE -#define NL80211_ATTR_REASON_CODE NL80211_ATTR_REASON_CODE -#define NL80211_ATTR_CIPHER_SUITES_PAIRWISE NL80211_ATTR_CIPHER_SUITES_PAIRWISE -#define NL80211_ATTR_CIPHER_SUITE_GROUP NL80211_ATTR_CIPHER_SUITE_GROUP -#define NL80211_ATTR_WPA_VERSIONS NL80211_ATTR_WPA_VERSIONS -#define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES -#define NL80211_ATTR_KEY NL80211_ATTR_KEY -#define NL80211_ATTR_KEYS NL80211_ATTR_KEYS - -#define NL80211_MAX_SUPP_RATES 32 -#define NL80211_MAX_SUPP_REG_RULES 32 -#define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0 -#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 -#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 -#define NL80211_HT_CAPABILITY_LEN 26 - -#define NL80211_MAX_NR_CIPHER_SUITES 5 -#define NL80211_MAX_NR_AKM_SUITES 2 - -/** - * enum nl80211_iftype - (virtual) interface types - * - * @NL80211_IFTYPE_UNSPECIFIED: unspecified type, driver decides - * @NL80211_IFTYPE_ADHOC: independent BSS member - * @NL80211_IFTYPE_STATION: managed BSS member - * @NL80211_IFTYPE_AP: access point - * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points - * @NL80211_IFTYPE_WDS: wireless distribution interface - * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames - * @NL80211_IFTYPE_MESH_POINT: mesh point - * @NL80211_IFTYPE_MAX: highest interface type number currently defined - * @__NL80211_IFTYPE_AFTER_LAST: internal use - * - * These values are used with the %NL80211_ATTR_IFTYPE - * to set the type of an interface. - * - */ -enum nl80211_iftype { - NL80211_IFTYPE_UNSPECIFIED, - NL80211_IFTYPE_ADHOC, - NL80211_IFTYPE_STATION, - NL80211_IFTYPE_AP, - NL80211_IFTYPE_AP_VLAN, - NL80211_IFTYPE_WDS, - NL80211_IFTYPE_MONITOR, - NL80211_IFTYPE_MESH_POINT, - - /* keep last */ - __NL80211_IFTYPE_AFTER_LAST, - NL80211_IFTYPE_MAX = __NL80211_IFTYPE_AFTER_LAST - 1 -}; - -/** - * enum nl80211_sta_flags - station flags - * - * Station flags. When a station is added to an AP interface, it is - * assumed to be already associated (and hence authenticated.) - * - * @NL80211_STA_FLAG_AUTHORIZED: station is authorized (802.1X) - * @NL80211_STA_FLAG_SHORT_PREAMBLE: station is capable of receiving frames - * with short barker preamble - * @NL80211_STA_FLAG_WME: station is WME/QoS capable - * @NL80211_STA_FLAG_MFP: station uses management frame protection - */ -enum nl80211_sta_flags { - __NL80211_STA_FLAG_INVALID, - NL80211_STA_FLAG_AUTHORIZED, - NL80211_STA_FLAG_SHORT_PREAMBLE, - NL80211_STA_FLAG_WME, - NL80211_STA_FLAG_MFP, - - /* keep last */ - __NL80211_STA_FLAG_AFTER_LAST, - NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1 -}; - -/** - * struct nl80211_sta_flag_update - station flags mask/set - * @mask: mask of station flags to set - * @set: which values to set them to - * - * Both mask and set contain bits as per &enum nl80211_sta_flags. - */ -struct nl80211_sta_flag_update { - __u32 mask; - __u32 set; -} __attribute__((packed)); - -/** - * enum nl80211_rate_info - bitrate information - * - * These attribute types are used with %NL80211_STA_INFO_TXRATE - * when getting information about the bitrate of a station. - * - * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved - * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s) - * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8) - * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate - * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval - * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined - * @__NL80211_RATE_INFO_AFTER_LAST: internal use - */ -enum nl80211_rate_info { - __NL80211_RATE_INFO_INVALID, - NL80211_RATE_INFO_BITRATE, - NL80211_RATE_INFO_MCS, - NL80211_RATE_INFO_40_MHZ_WIDTH, - NL80211_RATE_INFO_SHORT_GI, - - /* keep last */ - __NL80211_RATE_INFO_AFTER_LAST, - NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1 -}; - -/** - * enum nl80211_sta_info - station information - * - * These attribute types are used with %NL80211_ATTR_STA_INFO - * when getting information about a station. - * - * @__NL80211_STA_INFO_INVALID: attribute number 0 is reserved - * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs) - * @NL80211_STA_INFO_RX_BYTES: total received bytes (u32, from this station) - * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station) - * @__NL80211_STA_INFO_AFTER_LAST: internal - * @NL80211_STA_INFO_MAX: highest possible station info attribute - * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm) - * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute - * containing info as possible, see &enum nl80211_sta_info_txrate. - * @NL80211_STA_INFO_RX_PACKETS: total received packet (u32, from this station) - * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (u32, to this - * station) - */ -enum nl80211_sta_info { - __NL80211_STA_INFO_INVALID, - NL80211_STA_INFO_INACTIVE_TIME, - NL80211_STA_INFO_RX_BYTES, - NL80211_STA_INFO_TX_BYTES, - NL80211_STA_INFO_LLID, - NL80211_STA_INFO_PLID, - NL80211_STA_INFO_PLINK_STATE, - NL80211_STA_INFO_SIGNAL, - NL80211_STA_INFO_TX_BITRATE, - NL80211_STA_INFO_RX_PACKETS, - NL80211_STA_INFO_TX_PACKETS, - - /* keep last */ - __NL80211_STA_INFO_AFTER_LAST, - NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1 -}; - -/** - * enum nl80211_mpath_flags - nl80211 mesh path flags - * - * @NL80211_MPATH_FLAG_ACTIVE: the mesh path is active - * @NL80211_MPATH_FLAG_RESOLVING: the mesh path discovery process is running - * @NL80211_MPATH_FLAG_SN_VALID: the mesh path contains a valid SN - * @NL80211_MPATH_FLAG_FIXED: the mesh path has been manually set - * @NL80211_MPATH_FLAG_RESOLVED: the mesh path discovery process succeeded - */ -enum nl80211_mpath_flags { - NL80211_MPATH_FLAG_ACTIVE = 1<<0, - NL80211_MPATH_FLAG_RESOLVING = 1<<1, - NL80211_MPATH_FLAG_SN_VALID = 1<<2, - NL80211_MPATH_FLAG_FIXED = 1<<3, - NL80211_MPATH_FLAG_RESOLVED = 1<<4, -}; - -/** - * enum nl80211_mpath_info - mesh path information - * - * These attribute types are used with %NL80211_ATTR_MPATH_INFO when getting - * information about a mesh path. - * - * @__NL80211_MPATH_INFO_INVALID: attribute number 0 is reserved - * @NL80211_ATTR_MPATH_FRAME_QLEN: number of queued frames for this destination - * @NL80211_ATTR_MPATH_SN: destination sequence number - * @NL80211_ATTR_MPATH_METRIC: metric (cost) of this mesh path - * @NL80211_ATTR_MPATH_EXPTIME: expiration time for the path, in msec from now - * @NL80211_ATTR_MPATH_FLAGS: mesh path flags, enumerated in - * &enum nl80211_mpath_flags; - * @NL80211_ATTR_MPATH_DISCOVERY_TIMEOUT: total path discovery timeout, in msec - * @NL80211_ATTR_MPATH_DISCOVERY_RETRIES: mesh path discovery retries - */ -enum nl80211_mpath_info { - __NL80211_MPATH_INFO_INVALID, - NL80211_MPATH_INFO_FRAME_QLEN, - NL80211_MPATH_INFO_SN, - NL80211_MPATH_INFO_METRIC, - NL80211_MPATH_INFO_EXPTIME, - NL80211_MPATH_INFO_FLAGS, - NL80211_MPATH_INFO_DISCOVERY_TIMEOUT, - NL80211_MPATH_INFO_DISCOVERY_RETRIES, - - /* keep last */ - __NL80211_MPATH_INFO_AFTER_LAST, - NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1 -}; - -/** - * enum nl80211_band_attr - band attributes - * @__NL80211_BAND_ATTR_INVALID: attribute number 0 is reserved - * @NL80211_BAND_ATTR_FREQS: supported frequencies in this band, - * an array of nested frequency attributes - * @NL80211_BAND_ATTR_RATES: supported bitrates in this band, - * an array of nested bitrate attributes - * @NL80211_BAND_ATTR_HT_MCS_SET: 16-byte attribute containing the MCS set as - * defined in 802.11n - * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE - * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n - * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n - */ -enum nl80211_band_attr { - __NL80211_BAND_ATTR_INVALID, - NL80211_BAND_ATTR_FREQS, - NL80211_BAND_ATTR_RATES, - - NL80211_BAND_ATTR_HT_MCS_SET, - NL80211_BAND_ATTR_HT_CAPA, - NL80211_BAND_ATTR_HT_AMPDU_FACTOR, - NL80211_BAND_ATTR_HT_AMPDU_DENSITY, - - /* keep last */ - __NL80211_BAND_ATTR_AFTER_LAST, - NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1 -}; - -#define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA - -/** - * enum nl80211_frequency_attr - frequency attributes - * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz - * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current - * regulatory domain. - * @NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: Only passive scanning is - * permitted on this channel in current regulatory domain. - * @NL80211_FREQUENCY_ATTR_NO_IBSS: IBSS networks are not permitted - * on this channel in current regulatory domain. - * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory - * on this channel in current regulatory domain. - * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm - * (100 * dBm). - */ -enum nl80211_frequency_attr { - __NL80211_FREQUENCY_ATTR_INVALID, - NL80211_FREQUENCY_ATTR_FREQ, - NL80211_FREQUENCY_ATTR_DISABLED, - NL80211_FREQUENCY_ATTR_PASSIVE_SCAN, - NL80211_FREQUENCY_ATTR_NO_IBSS, - NL80211_FREQUENCY_ATTR_RADAR, - NL80211_FREQUENCY_ATTR_MAX_TX_POWER, - - /* keep last */ - __NL80211_FREQUENCY_ATTR_AFTER_LAST, - NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1 -}; - -#define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER - -/** - * enum nl80211_bitrate_attr - bitrate attributes - * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps - * @NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: Short preamble supported - * in 2.4 GHz band. - */ -enum nl80211_bitrate_attr { - __NL80211_BITRATE_ATTR_INVALID, - NL80211_BITRATE_ATTR_RATE, - NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE, - - /* keep last */ - __NL80211_BITRATE_ATTR_AFTER_LAST, - NL80211_BITRATE_ATTR_MAX = __NL80211_BITRATE_ATTR_AFTER_LAST - 1 -}; - -/** - * enum nl80211_initiator - Indicates the initiator of a reg domain request - * @NL80211_REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world - * regulatory domain. - * @NL80211_REGDOM_SET_BY_USER: User asked the wireless core to set the - * regulatory domain. - * @NL80211_REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the - * wireless core it thinks its knows the regulatory domain we should be in. - * @NL80211_REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an - * 802.11 country information element with regulatory information it - * thinks we should consider. - */ -enum nl80211_reg_initiator { - NL80211_REGDOM_SET_BY_CORE, - NL80211_REGDOM_SET_BY_USER, - NL80211_REGDOM_SET_BY_DRIVER, - NL80211_REGDOM_SET_BY_COUNTRY_IE, -}; - -/** - * enum nl80211_reg_type - specifies the type of regulatory domain - * @NL80211_REGDOM_TYPE_COUNTRY: the regulatory domain set is one that pertains - * to a specific country. When this is set you can count on the - * ISO / IEC 3166 alpha2 country code being valid. - * @NL80211_REGDOM_TYPE_WORLD: the regulatory set domain is the world regulatory - * domain. - * @NL80211_REGDOM_TYPE_CUSTOM_WORLD: the regulatory domain set is a custom - * driver specific world regulatory domain. These do not apply system-wide - * and are only applicable to the individual devices which have requested - * them to be applied. - * @NL80211_REGDOM_TYPE_INTERSECTION: the regulatory domain set is the product - * of an intersection between two regulatory domains -- the previously - * set regulatory domain on the system and the last accepted regulatory - * domain request to be processed. - */ -enum nl80211_reg_type { - NL80211_REGDOM_TYPE_COUNTRY, - NL80211_REGDOM_TYPE_WORLD, - NL80211_REGDOM_TYPE_CUSTOM_WORLD, - NL80211_REGDOM_TYPE_INTERSECTION, -}; - -/** - * enum nl80211_reg_rule_attr - regulatory rule attributes - * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional - * considerations for a given frequency range. These are the - * &enum nl80211_reg_rule_flags. - * @NL80211_ATTR_FREQ_RANGE_START: starting frequencry for the regulatory - * rule in KHz. This is not a center of frequency but an actual regulatory - * band edge. - * @NL80211_ATTR_FREQ_RANGE_END: ending frequency for the regulatory rule - * in KHz. This is not a center a frequency but an actual regulatory - * band edge. - * @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this - * frequency range, in KHz. - * @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain - * for a given frequency range. The value is in mBi (100 * dBi). - * If you don't have one then don't send this. - * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for - * a given frequency range. The value is in mBm (100 * dBm). - */ -enum nl80211_reg_rule_attr { - __NL80211_REG_RULE_ATTR_INVALID, - NL80211_ATTR_REG_RULE_FLAGS, - - NL80211_ATTR_FREQ_RANGE_START, - NL80211_ATTR_FREQ_RANGE_END, - NL80211_ATTR_FREQ_RANGE_MAX_BW, - - NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, - NL80211_ATTR_POWER_RULE_MAX_EIRP, - - /* keep last */ - __NL80211_REG_RULE_ATTR_AFTER_LAST, - NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 -}; - -/** - * enum nl80211_reg_rule_flags - regulatory rule flags - * - * @NL80211_RRF_NO_OFDM: OFDM modulation not allowed - * @NL80211_RRF_NO_CCK: CCK modulation not allowed - * @NL80211_RRF_NO_INDOOR: indoor operation not allowed - * @NL80211_RRF_NO_OUTDOOR: outdoor operation not allowed - * @NL80211_RRF_DFS: DFS support is required to be used - * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links - * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links - * @NL80211_RRF_PASSIVE_SCAN: passive scan is required - * @NL80211_RRF_NO_IBSS: no IBSS is allowed - */ -enum nl80211_reg_rule_flags { - NL80211_RRF_NO_OFDM = 1<<0, - NL80211_RRF_NO_CCK = 1<<1, - NL80211_RRF_NO_INDOOR = 1<<2, - NL80211_RRF_NO_OUTDOOR = 1<<3, - NL80211_RRF_DFS = 1<<4, - NL80211_RRF_PTP_ONLY = 1<<5, - NL80211_RRF_PTMP_ONLY = 1<<6, - NL80211_RRF_PASSIVE_SCAN = 1<<7, - NL80211_RRF_NO_IBSS = 1<<8, -}; - -/** - * enum nl80211_survey_info - survey information - * - * These attribute types are used with %NL80211_ATTR_SURVEY_INFO - * when getting information about a survey. - * - * @__NL80211_SURVEY_INFO_INVALID: attribute number 0 is reserved - * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel - * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm) - */ -enum nl80211_survey_info { - __NL80211_SURVEY_INFO_INVALID, - NL80211_SURVEY_INFO_FREQUENCY, - NL80211_SURVEY_INFO_NOISE, - - /* keep last */ - __NL80211_SURVEY_INFO_AFTER_LAST, - NL80211_SURVEY_INFO_MAX = __NL80211_SURVEY_INFO_AFTER_LAST - 1 -}; - -/** - * enum nl80211_mntr_flags - monitor configuration flags - * - * Monitor configuration flags. - * - * @__NL80211_MNTR_FLAG_INVALID: reserved - * - * @NL80211_MNTR_FLAG_FCSFAIL: pass frames with bad FCS - * @NL80211_MNTR_FLAG_PLCPFAIL: pass frames with bad PLCP - * @NL80211_MNTR_FLAG_CONTROL: pass control frames - * @NL80211_MNTR_FLAG_OTHER_BSS: disable BSSID filtering - * @NL80211_MNTR_FLAG_COOK_FRAMES: report frames after processing. - * overrides all other flags. - * - * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use - * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag - */ -enum nl80211_mntr_flags { - __NL80211_MNTR_FLAG_INVALID, - NL80211_MNTR_FLAG_FCSFAIL, - NL80211_MNTR_FLAG_PLCPFAIL, - NL80211_MNTR_FLAG_CONTROL, - NL80211_MNTR_FLAG_OTHER_BSS, - NL80211_MNTR_FLAG_COOK_FRAMES, - - /* keep last */ - __NL80211_MNTR_FLAG_AFTER_LAST, - NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1 -}; - -/** - * enum nl80211_meshconf_params - mesh configuration parameters - * - * Mesh configuration parameters - * - * @__NL80211_MESHCONF_INVALID: internal use - * - * @NL80211_MESHCONF_RETRY_TIMEOUT: specifies the initial retry timeout in - * millisecond units, used by the Peer Link Open message - * - * @NL80211_MESHCONF_CONFIRM_TIMEOUT: specifies the inital confirm timeout, in - * millisecond units, used by the peer link management to close a peer link - * - * @NL80211_MESHCONF_HOLDING_TIMEOUT: specifies the holding timeout, in - * millisecond units - * - * @NL80211_MESHCONF_MAX_PEER_LINKS: maximum number of peer links allowed - * on this mesh interface - * - * @NL80211_MESHCONF_MAX_RETRIES: specifies the maximum number of peer link - * open retries that can be sent to establish a new peer link instance in a - * mesh - * - * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh - * point. - * - * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically - * open peer links when we detect compatible mesh peers. - * - * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames - * containing a PREQ that an MP can send to a particular destination (path - * target) - * - * @NL80211_MESHCONF_PATH_REFRESH_TIME: how frequently to refresh mesh paths - * (in milliseconds) - * - * @NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT: minimum length of time to wait - * until giving up on a path discovery (in milliseconds) - * - * @NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT: The time (in TUs) for which mesh - * points receiving a PREQ shall consider the forwarding information from the - * root to be valid. (TU = time unit) - * - * @NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL: The minimum interval of time (in - * TUs) during which an MP can send only one action frame containing a PREQ - * reference element - * - * @NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: The interval of time (in TUs) - * that it takes for an HWMP information element to propagate across the mesh - * - * @NL80211_MESHCONF_ROOTMODE: whether root mode is enabled or not - * - * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute - * - * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use - */ -enum nl80211_meshconf_params { - __NL80211_MESHCONF_INVALID, - NL80211_MESHCONF_RETRY_TIMEOUT, - NL80211_MESHCONF_CONFIRM_TIMEOUT, - NL80211_MESHCONF_HOLDING_TIMEOUT, - NL80211_MESHCONF_MAX_PEER_LINKS, - NL80211_MESHCONF_MAX_RETRIES, - NL80211_MESHCONF_TTL, - NL80211_MESHCONF_AUTO_OPEN_PLINKS, - NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, - NL80211_MESHCONF_PATH_REFRESH_TIME, - NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, - NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, - NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, - NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, - NL80211_MESHCONF_HWMP_ROOTMODE, - - /* keep last */ - __NL80211_MESHCONF_ATTR_AFTER_LAST, - NL80211_MESHCONF_ATTR_MAX = __NL80211_MESHCONF_ATTR_AFTER_LAST - 1 -}; - -/** - * enum nl80211_txq_attr - TX queue parameter attributes - * @__NL80211_TXQ_ATTR_INVALID: Attribute number 0 is reserved - * @NL80211_TXQ_ATTR_QUEUE: TX queue identifier (NL80211_TXQ_Q_*) - * @NL80211_TXQ_ATTR_TXOP: Maximum burst time in units of 32 usecs, 0 meaning - * disabled - * @NL80211_TXQ_ATTR_CWMIN: Minimum contention window [a value of the form - * 2^n-1 in the range 1..32767] - * @NL80211_TXQ_ATTR_CWMAX: Maximum contention window [a value of the form - * 2^n-1 in the range 1..32767] - * @NL80211_TXQ_ATTR_AIFS: Arbitration interframe space [0..255] - * @__NL80211_TXQ_ATTR_AFTER_LAST: Internal - * @NL80211_TXQ_ATTR_MAX: Maximum TXQ attribute number - */ -enum nl80211_txq_attr { - __NL80211_TXQ_ATTR_INVALID, - NL80211_TXQ_ATTR_QUEUE, - NL80211_TXQ_ATTR_TXOP, - NL80211_TXQ_ATTR_CWMIN, - NL80211_TXQ_ATTR_CWMAX, - NL80211_TXQ_ATTR_AIFS, - - /* keep last */ - __NL80211_TXQ_ATTR_AFTER_LAST, - NL80211_TXQ_ATTR_MAX = __NL80211_TXQ_ATTR_AFTER_LAST - 1 -}; - -enum nl80211_txq_q { - NL80211_TXQ_Q_VO, - NL80211_TXQ_Q_VI, - NL80211_TXQ_Q_BE, - NL80211_TXQ_Q_BK -}; - -enum nl80211_channel_type { - NL80211_CHAN_NO_HT, - NL80211_CHAN_HT20, - NL80211_CHAN_HT40MINUS, - NL80211_CHAN_HT40PLUS -}; - -/** - * enum nl80211_bss - netlink attributes for a BSS - * - * @__NL80211_BSS_INVALID: invalid - * @NL80211_BSS_FREQUENCY: frequency in MHz (u32) - * @NL80211_BSS_TSF: TSF of the received probe response/beacon (u64) - * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16) - * @NL80211_BSS_CAPABILITY: capability field (CPU order, u16) - * @NL80211_BSS_INFORMATION_ELEMENTS: binary attribute containing the - * raw information elements from the probe response/beacon (bin) - * @NL80211_BSS_SIGNAL_MBM: signal strength of probe response/beacon - * in mBm (100 * dBm) (s32) - * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon - * in unspecified units, scaled to 0..100 (u8) - * @NL80211_BSS_STATUS: status, if this BSS is "used" - * @NL80211_BSS_SEEN_MS_AGO: age of this BSS entry in ms - * @__NL80211_BSS_AFTER_LAST: internal - * @NL80211_BSS_MAX: highest BSS attribute - */ -enum nl80211_bss { - __NL80211_BSS_INVALID, - NL80211_BSS_BSSID, - NL80211_BSS_FREQUENCY, - NL80211_BSS_TSF, - NL80211_BSS_BEACON_INTERVAL, - NL80211_BSS_CAPABILITY, - NL80211_BSS_INFORMATION_ELEMENTS, - NL80211_BSS_SIGNAL_MBM, - NL80211_BSS_SIGNAL_UNSPEC, - NL80211_BSS_STATUS, - NL80211_BSS_SEEN_MS_AGO, - - /* keep last */ - __NL80211_BSS_AFTER_LAST, - NL80211_BSS_MAX = __NL80211_BSS_AFTER_LAST - 1 -}; - -/** - * enum nl80211_bss_status - BSS "status" - */ -enum nl80211_bss_status { - NL80211_BSS_STATUS_AUTHENTICATED, - NL80211_BSS_STATUS_ASSOCIATED, - NL80211_BSS_STATUS_IBSS_JOINED, -}; - -/** - * enum nl80211_auth_type - AuthenticationType - * - * @NL80211_AUTHTYPE_OPEN_SYSTEM: Open System authentication - * @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only) - * @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r) - * @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP) - * @__NL80211_AUTHTYPE_NUM: internal - * @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm - * @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by - * trying multiple times); this is invalid in netlink -- leave out - * the attribute for this on CONNECT commands. - */ -enum nl80211_auth_type { - NL80211_AUTHTYPE_OPEN_SYSTEM, - NL80211_AUTHTYPE_SHARED_KEY, - NL80211_AUTHTYPE_FT, - NL80211_AUTHTYPE_NETWORK_EAP, - - /* keep last */ - __NL80211_AUTHTYPE_NUM, - NL80211_AUTHTYPE_MAX = __NL80211_AUTHTYPE_NUM - 1, - NL80211_AUTHTYPE_AUTOMATIC -}; - -/** - * enum nl80211_key_type - Key Type - * @NL80211_KEYTYPE_GROUP: Group (broadcast/multicast) key - * @NL80211_KEYTYPE_PAIRWISE: Pairwise (unicast/individual) key - * @NL80211_KEYTYPE_PEERKEY: PeerKey (DLS) - */ -enum nl80211_key_type { - NL80211_KEYTYPE_GROUP, - NL80211_KEYTYPE_PAIRWISE, - NL80211_KEYTYPE_PEERKEY, -}; - -/** - * enum nl80211_mfp - Management frame protection state - * @NL80211_MFP_NO: Management frame protection not used - * @NL80211_MFP_REQUIRED: Management frame protection required - */ -enum nl80211_mfp { - NL80211_MFP_NO, - NL80211_MFP_REQUIRED, -}; - -enum nl80211_wpa_versions { - NL80211_WPA_VERSION_1 = 1 << 0, - NL80211_WPA_VERSION_2 = 1 << 1, -}; - -/** - * enum nl80211_key_attributes - key attributes - * @__NL80211_KEY_INVALID: invalid - * @NL80211_KEY_DATA: (temporal) key data; for TKIP this consists of - * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC - * keys - * @NL80211_KEY_IDX: key ID (u8, 0-3) - * @NL80211_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11 - * section 7.3.2.25.1, e.g. 0x000FAC04) - * @NL80211_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and - * CCMP keys, each six bytes in little endian - * @NL80211_KEY_DEFAULT: flag indicating default key - * @NL80211_KEY_DEFAULT_MGMT: flag indicating default management key - * @__NL80211_KEY_AFTER_LAST: internal - * @NL80211_KEY_MAX: highest key attribute - */ -enum nl80211_key_attributes { - __NL80211_KEY_INVALID, - NL80211_KEY_DATA, - NL80211_KEY_IDX, - NL80211_KEY_CIPHER, - NL80211_KEY_SEQ, - NL80211_KEY_DEFAULT, - NL80211_KEY_DEFAULT_MGMT, - - /* keep last */ - __NL80211_KEY_AFTER_LAST, - NL80211_KEY_MAX = __NL80211_KEY_AFTER_LAST - 1 -}; - -#endif /* __LINUX_NL80211_H */ diff --git a/contrib/hostapd/src/common/privsep_commands.h b/contrib/hostapd/src/common/privsep_commands.h deleted file mode 100644 index 81b7f5432e..0000000000 --- a/contrib/hostapd/src/common/privsep_commands.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * WPA Supplicant - privilege separation commands - * Copyright (c) 2007-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef PRIVSEP_COMMANDS_H -#define PRIVSEP_COMMANDS_H - -enum privsep_cmd { - PRIVSEP_CMD_REGISTER, - PRIVSEP_CMD_UNREGISTER, - PRIVSEP_CMD_SET_WPA, - PRIVSEP_CMD_SCAN, - PRIVSEP_CMD_GET_SCAN_RESULTS, - PRIVSEP_CMD_ASSOCIATE, - PRIVSEP_CMD_GET_BSSID, - PRIVSEP_CMD_GET_SSID, - PRIVSEP_CMD_SET_KEY, - PRIVSEP_CMD_GET_CAPA, - PRIVSEP_CMD_L2_REGISTER, - PRIVSEP_CMD_L2_UNREGISTER, - PRIVSEP_CMD_L2_NOTIFY_AUTH_START, - PRIVSEP_CMD_L2_SEND, - PRIVSEP_CMD_SET_MODE, - PRIVSEP_CMD_SET_COUNTRY, -}; - -struct privsep_cmd_associate -{ - u8 bssid[ETH_ALEN]; - u8 ssid[32]; - size_t ssid_len; - int freq; - int pairwise_suite; - int group_suite; - int key_mgmt_suite; - int auth_alg; - int mode; - size_t wpa_ie_len; - /* followed by wpa_ie_len bytes of wpa_ie */ -}; - -struct privsep_cmd_set_key -{ - int alg; - u8 addr[ETH_ALEN]; - int key_idx; - int set_tx; - u8 seq[8]; - size_t seq_len; - u8 key[32]; - size_t key_len; -}; - -enum privsep_event { - PRIVSEP_EVENT_SCAN_RESULTS, - PRIVSEP_EVENT_ASSOC, - PRIVSEP_EVENT_DISASSOC, - PRIVSEP_EVENT_ASSOCINFO, - PRIVSEP_EVENT_MICHAEL_MIC_FAILURE, - PRIVSEP_EVENT_INTERFACE_STATUS, - PRIVSEP_EVENT_PMKID_CANDIDATE, - PRIVSEP_EVENT_STKSTART, - PRIVSEP_EVENT_FT_RESPONSE, - PRIVSEP_EVENT_RX_EAPOL, - PRIVSEP_EVENT_STA_RX, -}; - -#endif /* PRIVSEP_COMMANDS_H */ diff --git a/contrib/hostapd/src/common/version.h b/contrib/hostapd/src/common/version.h deleted file mode 100644 index b79c4949c4..0000000000 --- a/contrib/hostapd/src/common/version.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef VERSION_H -#define VERSION_H - -#define VERSION_STR "0.6.10" - -#endif /* VERSION_H */ diff --git a/contrib/hostapd/src/common/wireless_copy.h b/contrib/hostapd/src/common/wireless_copy.h deleted file mode 100644 index ad76466376..0000000000 --- a/contrib/hostapd/src/common/wireless_copy.h +++ /dev/null @@ -1,1099 +0,0 @@ -/* This is based on Linux Wireless Extensions header file from WIRELESS_EXT 18. - * I have just removed kernel related headers and added some typedefs etc. to - * make this easier to include into user space programs. - * Jouni Malinen, 2005-03-12. - */ - - -/* - * This file define a set of standard wireless extensions - * - * Version : 19 18.3.05 - * - * Authors : Jean Tourrilhes - HPL - - * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved. - */ - -#ifndef _LINUX_WIRELESS_H -#define _LINUX_WIRELESS_H - -/************************** DOCUMENTATION **************************/ -/* - * Initial APIs (1996 -> onward) : - * ----------------------------- - * Basically, the wireless extensions are for now a set of standard ioctl - * call + /proc/net/wireless - * - * The entry /proc/net/wireless give statistics and information on the - * driver. - * This is better than having each driver having its entry because - * its centralised and we may remove the driver module safely. - * - * Ioctl are used to configure the driver and issue commands. This is - * better than command line options of insmod because we may want to - * change dynamically (while the driver is running) some parameters. - * - * The ioctl mechanimsm are copied from standard devices ioctl. - * We have the list of command plus a structure descibing the - * data exchanged... - * Note that to add these ioctl, I was obliged to modify : - * # net/core/dev.c (two place + add include) - * # net/ipv4/af_inet.c (one place + add include) - * - * /proc/net/wireless is a copy of /proc/net/dev. - * We have a structure for data passed from the driver to /proc/net/wireless - * Too add this, I've modified : - * # net/core/dev.c (two other places) - * # include/linux/netdevice.h (one place) - * # include/linux/proc_fs.h (one place) - * - * New driver API (2002 -> onward) : - * ------------------------------- - * This file is only concerned with the user space API and common definitions. - * The new driver API is defined and documented in : - * # include/net/iw_handler.h - * - * Note as well that /proc/net/wireless implementation has now moved in : - * # net/core/wireless.c - * - * Wireless Events (2002 -> onward) : - * -------------------------------- - * Events are defined at the end of this file, and implemented in : - * # net/core/wireless.c - * - * Other comments : - * -------------- - * Do not add here things that are redundant with other mechanisms - * (drivers init, ifconfig, /proc/net/dev, ...) and with are not - * wireless specific. - * - * These wireless extensions are not magic : each driver has to provide - * support for them... - * - * IMPORTANT NOTE : As everything in the kernel, this is very much a - * work in progress. Contact me if you have ideas of improvements... - */ - -/***************************** INCLUDES *****************************/ - - /* jkm - replaced linux headers with C library headers, added typedefs */ -#if 0 -/* To minimise problems in user space, I might remove those headers - * at some point. Jean II */ -#include /* for "caddr_t" et al */ -#include /* for "struct sockaddr" et al */ -#include /* for IFNAMSIZ and co... */ -#else -#include -#include -typedef __uint32_t __u32; -typedef __int32_t __s32; -typedef __uint16_t __u16; -typedef __int16_t __s16; -typedef __uint8_t __u8; -#ifndef __user -#define __user -#endif /* __user */ -#endif - -/***************************** VERSION *****************************/ -/* - * This constant is used to know the availability of the wireless - * extensions and to know which version of wireless extensions it is - * (there is some stuff that will be added in the future...) - * I just plan to increment with each new version. - */ -#define WIRELESS_EXT 19 - -/* - * Changes : - * - * V2 to V3 - * -------- - * Alan Cox start some incompatibles changes. I've integrated a bit more. - * - Encryption renamed to Encode to avoid US regulation problems - * - Frequency changed from float to struct to avoid problems on old 386 - * - * V3 to V4 - * -------- - * - Add sensitivity - * - * V4 to V5 - * -------- - * - Missing encoding definitions in range - * - Access points stuff - * - * V5 to V6 - * -------- - * - 802.11 support (ESSID ioctls) - * - * V6 to V7 - * -------- - * - define IW_ESSID_MAX_SIZE and IW_MAX_AP - * - * V7 to V8 - * -------- - * - Changed my e-mail address - * - More 802.11 support (nickname, rate, rts, frag) - * - List index in frequencies - * - * V8 to V9 - * -------- - * - Support for 'mode of operation' (ad-hoc, managed...) - * - Support for unicast and multicast power saving - * - Change encoding to support larger tokens (>64 bits) - * - Updated iw_params (disable, flags) and use it for NWID - * - Extracted iw_point from iwreq for clarity - * - * V9 to V10 - * --------- - * - Add PM capability to range structure - * - Add PM modifier : MAX/MIN/RELATIVE - * - Add encoding option : IW_ENCODE_NOKEY - * - Add TxPower ioctls (work like TxRate) - * - * V10 to V11 - * ---------- - * - Add WE version in range (help backward/forward compatibility) - * - Add retry ioctls (work like PM) - * - * V11 to V12 - * ---------- - * - Add SIOCSIWSTATS to get /proc/net/wireless programatically - * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space - * - Add new statistics (frag, retry, beacon) - * - Add average quality (for user space calibration) - * - * V12 to V13 - * ---------- - * - Document creation of new driver API. - * - Extract union iwreq_data from struct iwreq (for new driver API). - * - Rename SIOCSIWNAME as SIOCSIWCOMMIT - * - * V13 to V14 - * ---------- - * - Wireless Events support : define struct iw_event - * - Define additional specific event numbers - * - Add "addr" and "param" fields in union iwreq_data - * - AP scanning stuff (SIOCSIWSCAN and friends) - * - * V14 to V15 - * ---------- - * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg - * - Make struct iw_freq signed (both m & e), add explicit padding - * - Add IWEVCUSTOM for driver specific event/scanning token - * - Add IW_MAX_GET_SPY for driver returning a lot of addresses - * - Add IW_TXPOW_RANGE for range of Tx Powers - * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points - * - Add IW_MODE_MONITOR for passive monitor - * - * V15 to V16 - * ---------- - * - Increase the number of bitrates in iw_range to 32 (for 802.11g) - * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a) - * - Reshuffle struct iw_range for increases, add filler - * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses - * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support - * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy" - * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index - * - * V16 to V17 - * ---------- - * - Add flags to frequency -> auto/fixed - * - Document (struct iw_quality *)->updated, add new flags (INVALID) - * - Wireless Event capability in struct iw_range - * - Add support for relative TxPower (yick !) - * - * V17 to V18 (From Jouni Malinen ) - * ---------- - * - Add support for WPA/WPA2 - * - Add extended encoding configuration (SIOCSIWENCODEEXT and - * SIOCGIWENCODEEXT) - * - Add SIOCSIWGENIE/SIOCGIWGENIE - * - Add SIOCSIWMLME - * - Add SIOCSIWPMKSA - * - Add struct iw_range bit field for supported encoding capabilities - * - Add optional scan request parameters for SIOCSIWSCAN - * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA - * related parameters (extensible up to 4096 parameter values) - * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE, - * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND - * - * V18 to V19 - * ---------- - * - Remove (struct iw_point *)->pointer from events and streams - * - Remove header includes to help user space - * - Increase IW_ENCODING_TOKEN_MAX from 32 to 64 - * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros - * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM - * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros - */ - -/**************************** CONSTANTS ****************************/ - -/* -------------------------- IOCTL LIST -------------------------- */ - -/* Wireless Identification */ -#define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */ -#define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ -/* SIOCGIWNAME is used to verify the presence of Wireless Extensions. - * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"... - * Don't put the name of your driver there, it's useless. */ - -/* Basic operations */ -#define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */ -#define SIOCGIWNWID 0x8B03 /* get network id (the cell) */ -#define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ -#define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ -#define SIOCSIWMODE 0x8B06 /* set operation mode */ -#define SIOCGIWMODE 0x8B07 /* get operation mode */ -#define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ -#define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ - -/* Informative stuff */ -#define SIOCSIWRANGE 0x8B0A /* Unused */ -#define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ -#define SIOCSIWPRIV 0x8B0C /* Unused */ -#define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ -#define SIOCSIWSTATS 0x8B0E /* Unused */ -#define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */ -/* SIOCGIWSTATS is strictly used between user space and the kernel, and - * is never passed to the driver (i.e. the driver will never see it). */ - -/* Spy support (statistics per MAC address - used for Mobile IP support) */ -#define SIOCSIWSPY 0x8B10 /* set spy addresses */ -#define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ -#define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */ -#define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */ - -/* Access Point manipulation */ -#define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ -#define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ -#define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */ -#define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */ -#define SIOCGIWSCAN 0x8B19 /* get scanning results */ - -/* 802.11 specific support */ -#define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ -#define SIOCGIWESSID 0x8B1B /* get ESSID */ -#define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ -#define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ -/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit - * within the 'iwreq' structure, so we need to use the 'data' member to - * point to a string in user space, like it is done for RANGE... */ - -/* Other parameters useful in 802.11 and some other devices */ -#define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ -#define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ -#define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ -#define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ -#define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ -#define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ -#define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ -#define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ -#define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ -#define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ - -/* Encoding stuff (scrambling, hardware security, WEP...) */ -#define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ -#define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ -/* Power saving stuff (power management, unicast and multicast) */ -#define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ -#define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ - -/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM). - * This ioctl uses struct iw_point and data buffer that includes IE id and len - * fields. More than one IE may be included in the request. Setting the generic - * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers - * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers - * are required to report the used IE as a wireless event, e.g., when - * associating with an AP. */ -#define SIOCSIWGENIE 0x8B30 /* set generic IE */ -#define SIOCGIWGENIE 0x8B31 /* get generic IE */ - -/* WPA : IEEE 802.11 MLME requests */ -#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses - * struct iw_mlme */ -/* WPA : Authentication mode parameters */ -#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */ -#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */ - -/* WPA : Extended version of encoding configuration */ -#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */ -#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */ - -/* WPA2 : PMKSA cache management */ -#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */ - -/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ - -/* These 32 ioctl are wireless device private, for 16 commands. - * Each driver is free to use them for whatever purpose it chooses, - * however the driver *must* export the description of those ioctls - * with SIOCGIWPRIV and *must* use arguments as defined below. - * If you don't follow those rules, DaveM is going to hate you (reason : - * it make mixed 32/64bit operation impossible). - */ -#define SIOCIWFIRSTPRIV 0x8BE0 -#define SIOCIWLASTPRIV 0x8BFF -/* Previously, we were using SIOCDEVPRIVATE, but we now have our - * separate range because of collisions with other tools such as - * 'mii-tool'. - * We now have 32 commands, so a bit more space ;-). - * Also, all 'odd' commands are only usable by root and don't return the - * content of ifr/iwr to user (but you are not obliged to use the set/get - * convention, just use every other two command). More details in iwpriv.c. - * And I repeat : you are not forced to use them with iwpriv, but you - * must be compliant with it. - */ - -/* ------------------------- IOCTL STUFF ------------------------- */ - -/* The first and the last (range) */ -#define SIOCIWFIRST 0x8B00 -#define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ -#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST) - -/* Even : get (world access), odd : set (root access) */ -#define IW_IS_SET(cmd) (!((cmd) & 0x1)) -#define IW_IS_GET(cmd) ((cmd) & 0x1) - -/* ----------------------- WIRELESS EVENTS ----------------------- */ -/* Those are *NOT* ioctls, do not issue request on them !!! */ -/* Most events use the same identifier as ioctl requests */ - -#define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */ -#define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */ -#define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */ -#define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */ -#define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */ -#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..) - * (scan results); This includes id and - * length fields. One IWEVGENIE may - * contain more than one IE. Scan - * results may contain one or more - * IWEVGENIE events. */ -#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure - * (struct iw_michaelmicfailure) - */ -#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request. - * The data includes id and length - * fields and may contain more than one - * IE. This event is required in - * Managed mode if the driver - * generates its own WPA/RSN IE. This - * should be sent just before - * IWEVREGISTERED event for the - * association. */ -#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association - * Response. The data includes id and - * length fields and may contain more - * than one IE. This may be sent - * between IWEVASSOCREQIE and - * IWEVREGISTERED events for the - * association. */ -#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN - * pre-authentication - * (struct iw_pmkid_cand) */ - -#define IWEVFIRST 0x8C00 -#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST) - -/* ------------------------- PRIVATE INFO ------------------------- */ -/* - * The following is used with SIOCGIWPRIV. It allow a driver to define - * the interface (name, type of data) for its private ioctl. - * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV - */ - -#define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ -#define IW_PRIV_TYPE_NONE 0x0000 -#define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ -#define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ -#define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ -#define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */ -#define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */ - -#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */ - -#define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ - -/* - * Note : if the number of args is fixed and the size < 16 octets, - * instead of passing a pointer we will put args in the iwreq struct... - */ - -/* ----------------------- OTHER CONSTANTS ----------------------- */ - -/* Maximum frequencies in the range struct */ -#define IW_MAX_FREQUENCIES 32 -/* Note : if you have something like 80 frequencies, - * don't increase this constant and don't fill the frequency list. - * The user will be able to set by channel anyway... */ - -/* Maximum bit rates in the range struct */ -#define IW_MAX_BITRATES 32 - -/* Maximum tx powers in the range struct */ -#define IW_MAX_TXPOWER 8 -/* Note : if you more than 8 TXPowers, just set the max and min or - * a few of them in the struct iw_range. */ - -/* Maximum of address that you may set with SPY */ -#define IW_MAX_SPY 8 - -/* Maximum of address that you may get in the - list of access points in range */ -#define IW_MAX_AP 64 - -/* Maximum size of the ESSID and NICKN strings */ -#define IW_ESSID_MAX_SIZE 32 - -/* Modes of operation */ -#define IW_MODE_AUTO 0 /* Let the driver decides */ -#define IW_MODE_ADHOC 1 /* Single cell network */ -#define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */ -#define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ -#define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ -#define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ -#define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */ - -/* Statistics flags (bitmask in updated) */ -#define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */ -#define IW_QUAL_LEVEL_UPDATED 0x02 -#define IW_QUAL_NOISE_UPDATED 0x04 -#define IW_QUAL_ALL_UPDATED 0x07 -#define IW_QUAL_DBM 0x08 /* Level + Noise are dBm */ -#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */ -#define IW_QUAL_LEVEL_INVALID 0x20 -#define IW_QUAL_NOISE_INVALID 0x40 -#define IW_QUAL_ALL_INVALID 0x70 - -/* Frequency flags */ -#define IW_FREQ_AUTO 0x00 /* Let the driver decides */ -#define IW_FREQ_FIXED 0x01 /* Force a specific value */ - -/* Maximum number of size of encoding token available - * they are listed in the range structure */ -#define IW_MAX_ENCODING_SIZES 8 - -/* Maximum size of the encoding token in bytes */ -#define IW_ENCODING_TOKEN_MAX 64 /* 512 bits (for now) */ - -/* Flags for encoding (along with the token) */ -#define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ -#define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ -#define IW_ENCODE_MODE 0xF000 /* Modes defined below */ -#define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ -#define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ -#define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ -#define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ -#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ -#define IW_ENCODE_TEMP 0x0400 /* Temporary key */ - -/* Power management flags available (along with the value, if any) */ -#define IW_POWER_ON 0x0000 /* No details... */ -#define IW_POWER_TYPE 0xF000 /* Type of parameter */ -#define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ -#define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ -#define IW_POWER_MODE 0x0F00 /* Power Management mode */ -#define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */ -#define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */ -#define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ -#define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ -#define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ -#define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ -#define IW_POWER_MIN 0x0001 /* Value is a minimum */ -#define IW_POWER_MAX 0x0002 /* Value is a maximum */ -#define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ - -/* Transmit Power flags available */ -#define IW_TXPOW_TYPE 0x00FF /* Type of value */ -#define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ -#define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ -#define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */ -#define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */ - -/* Retry limits and lifetime flags available */ -#define IW_RETRY_ON 0x0000 /* No details... */ -#define IW_RETRY_TYPE 0xF000 /* Type of parameter */ -#define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ -#define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ -#define IW_RETRY_MODIFIER 0x000F /* Modify a parameter */ -#define IW_RETRY_MIN 0x0001 /* Value is a minimum */ -#define IW_RETRY_MAX 0x0002 /* Value is a maximum */ -#define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ - -/* Scanning request flags */ -#define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */ -#define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */ -#define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */ -#define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */ -#define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */ -#define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */ -#define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */ -#define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */ -#define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */ -/* struct iw_scan_req scan_type */ -#define IW_SCAN_TYPE_ACTIVE 0 -#define IW_SCAN_TYPE_PASSIVE 1 -/* Maximum size of returned data */ -#define IW_SCAN_MAX_DATA 4096 /* In bytes */ - -/* Max number of char in custom event - use multiple of them if needed */ -#define IW_CUSTOM_MAX 256 /* In bytes */ - -/* Generic information element */ -#define IW_GENERIC_IE_MAX 1024 - -/* MLME requests (SIOCSIWMLME / struct iw_mlme) */ -#define IW_MLME_DEAUTH 0 -#define IW_MLME_DISASSOC 1 - -/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */ -#define IW_AUTH_INDEX 0x0FFF -#define IW_AUTH_FLAGS 0xF000 -/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095) - * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the - * parameter that is being set/get to; value will be read/written to - * struct iw_param value field) */ -#define IW_AUTH_WPA_VERSION 0 -#define IW_AUTH_CIPHER_PAIRWISE 1 -#define IW_AUTH_CIPHER_GROUP 2 -#define IW_AUTH_KEY_MGMT 3 -#define IW_AUTH_TKIP_COUNTERMEASURES 4 -#define IW_AUTH_DROP_UNENCRYPTED 5 -#define IW_AUTH_80211_AUTH_ALG 6 -#define IW_AUTH_WPA_ENABLED 7 -#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8 -#define IW_AUTH_ROAMING_CONTROL 9 -#define IW_AUTH_PRIVACY_INVOKED 10 -#define IW_AUTH_CIPHER_GROUP_MGMT 11 -#define IW_AUTH_MFP 12 - -/* IW_AUTH_WPA_VERSION values (bit field) */ -#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001 -#define IW_AUTH_WPA_VERSION_WPA 0x00000002 -#define IW_AUTH_WPA_VERSION_WPA2 0x00000004 - -/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */ -#define IW_AUTH_CIPHER_NONE 0x00000001 -#define IW_AUTH_CIPHER_WEP40 0x00000002 -#define IW_AUTH_CIPHER_TKIP 0x00000004 -#define IW_AUTH_CIPHER_CCMP 0x00000008 -#define IW_AUTH_CIPHER_WEP104 0x00000010 - -/* IW_AUTH_KEY_MGMT values (bit field) */ -#define IW_AUTH_KEY_MGMT_802_1X 1 -#define IW_AUTH_KEY_MGMT_PSK 2 - -/* IW_AUTH_80211_AUTH_ALG values (bit field) */ -#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001 -#define IW_AUTH_ALG_SHARED_KEY 0x00000002 -#define IW_AUTH_ALG_LEAP 0x00000004 - -/* IW_AUTH_ROAMING_CONTROL values */ -#define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */ -#define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming - * control */ - -/* IW_AUTH_MFP (management frame protection) values */ -#define IW_AUTH_MFP_DISABLED 0 /* MFP disabled */ -#define IW_AUTH_MFP_OPTIONAL 1 /* MFP optional */ -#define IW_AUTH_MFP_REQUIRED 2 /* MFP required */ - -/* SIOCSIWENCODEEXT definitions */ -#define IW_ENCODE_SEQ_MAX_SIZE 8 -/* struct iw_encode_ext ->alg */ -#define IW_ENCODE_ALG_NONE 0 -#define IW_ENCODE_ALG_WEP 1 -#define IW_ENCODE_ALG_TKIP 2 -#define IW_ENCODE_ALG_CCMP 3 -#define IW_ENCODE_ALG_PMK 4 -#define IW_ENCODE_ALG_AES_CMAC 5 -/* struct iw_encode_ext ->ext_flags */ -#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001 -#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002 -#define IW_ENCODE_EXT_GROUP_KEY 0x00000004 -#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008 - -/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */ -#define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */ -#define IW_MICFAILURE_GROUP 0x00000004 -#define IW_MICFAILURE_PAIRWISE 0x00000008 -#define IW_MICFAILURE_STAKEY 0x00000010 -#define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported) - */ - -/* Bit field values for enc_capa in struct iw_range */ -#define IW_ENC_CAPA_WPA 0x00000001 -#define IW_ENC_CAPA_WPA2 0x00000002 -#define IW_ENC_CAPA_CIPHER_TKIP 0x00000004 -#define IW_ENC_CAPA_CIPHER_CCMP 0x00000008 -#define IW_ENC_CAPA_4WAY_HANDSHAKE 0x00000010 - -/* Event capability macros - in (struct iw_range *)->event_capa - * Because we have more than 32 possible events, we use an array of - * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */ -#define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \ - (cmd - SIOCIWFIRSTPRIV + 0x60) : \ - (cmd - SIOCSIWCOMMIT)) -#define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5) -#define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F)) -/* Event capability constants - event autogenerated by the kernel - * This list is valid for most 802.11 devices, customise as needed... */ -#define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \ - IW_EVENT_CAPA_MASK(0x8B06) | \ - IW_EVENT_CAPA_MASK(0x8B1A)) -#define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A)) -/* "Easy" macro to set events in iw_range (less efficient) */ -#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd)) -#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; } - - -/****************************** TYPES ******************************/ - -/* --------------------------- SUBTYPES --------------------------- */ -/* - * Generic format for most parameters that fit in an int - */ -struct iw_param -{ - __s32 value; /* The value of the parameter itself */ - __u8 fixed; /* Hardware should not use auto select */ - __u8 disabled; /* Disable the feature */ - __u16 flags; /* Various specifc flags (if any) */ -}; - -/* - * For all data larger than 16 octets, we need to use a - * pointer to memory allocated in user space. - */ -struct iw_point -{ - void __user *pointer; /* Pointer to the data (in user space) */ - __u16 length; /* number of fields or size in bytes */ - __u16 flags; /* Optional params */ -}; - -/* - * A frequency - * For numbers lower than 10^9, we encode the number in 'm' and - * set 'e' to 0 - * For number greater than 10^9, we divide it by the lowest power - * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... - * The power of 10 is in 'e', the result of the division is in 'm'. - */ -struct iw_freq -{ - __s32 m; /* Mantissa */ - __s16 e; /* Exponent */ - __u8 i; /* List index (when in range struct) */ - __u8 flags; /* Flags (fixed/auto) */ -}; - -/* - * Quality of the link - */ -struct iw_quality -{ - __u8 qual; /* link quality (%retries, SNR, - %missed beacons or better...) */ - __u8 level; /* signal level (dBm) */ - __u8 noise; /* noise level (dBm) */ - __u8 updated; /* Flags to know if updated */ -}; - -/* - * Packet discarded in the wireless adapter due to - * "wireless" specific problems... - * Note : the list of counter and statistics in net_device_stats - * is already pretty exhaustive, and you should use that first. - * This is only additional stats... - */ -struct iw_discarded -{ - __u32 nwid; /* Rx : Wrong nwid/essid */ - __u32 code; /* Rx : Unable to code/decode (WEP) */ - __u32 fragment; /* Rx : Can't perform MAC reassembly */ - __u32 retries; /* Tx : Max MAC retries num reached */ - __u32 misc; /* Others cases */ -}; - -/* - * Packet/Time period missed in the wireless adapter due to - * "wireless" specific problems... - */ -struct iw_missed -{ - __u32 beacon; /* Missed beacons/superframe */ -}; - -/* - * Quality range (for spy threshold) - */ -struct iw_thrspy -{ - struct sockaddr addr; /* Source address (hw/mac) */ - struct iw_quality qual; /* Quality of the link */ - struct iw_quality low; /* Low threshold */ - struct iw_quality high; /* High threshold */ -}; - -/* - * Optional data for scan request - * - * Note: these optional parameters are controlling parameters for the - * scanning behavior, these do not apply to getting scan results - * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and - * provide a merged results with all BSSes even if the previous scan - * request limited scanning to a subset, e.g., by specifying an SSID. - * Especially, scan results are required to include an entry for the - * current BSS if the driver is in Managed mode and associated with an AP. - */ -struct iw_scan_req -{ - __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */ - __u8 essid_len; - __u8 num_channels; /* num entries in channel_list; - * 0 = scan all allowed channels */ - __u8 flags; /* reserved as padding; use zero, this may - * be used in the future for adding flags - * to request different scan behavior */ - struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or - * individual address of a specific BSS */ - - /* - * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using - * the current ESSID. This allows scan requests for specific ESSID - * without having to change the current ESSID and potentially breaking - * the current association. - */ - __u8 essid[IW_ESSID_MAX_SIZE]; - - /* - * Optional parameters for changing the default scanning behavior. - * These are based on the MLME-SCAN.request from IEEE Std 802.11. - * TU is 1.024 ms. If these are set to 0, driver is expected to use - * reasonable default values. min_channel_time defines the time that - * will be used to wait for the first reply on each channel. If no - * replies are received, next channel will be scanned after this. If - * replies are received, total time waited on the channel is defined by - * max_channel_time. - */ - __u32 min_channel_time; /* in TU */ - __u32 max_channel_time; /* in TU */ - - struct iw_freq channel_list[IW_MAX_FREQUENCIES]; -}; - -/* ------------------------- WPA SUPPORT ------------------------- */ - -/* - * Extended data structure for get/set encoding (this is used with - * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_* - * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and - * only the data contents changes (key data -> this structure, including - * key data). - * - * If the new key is the first group key, it will be set as the default - * TX key. Otherwise, default TX key index is only changed if - * IW_ENCODE_EXT_SET_TX_KEY flag is set. - * - * Key will be changed with SIOCSIWENCODEEXT in all cases except for - * special "change TX key index" operation which is indicated by setting - * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY. - * - * tx_seq/rx_seq are only used when respective - * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal - * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start - * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally - * used only by an Authenticator (AP or an IBSS station) to get the - * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and - * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for - * debugging/testing. - */ -struct iw_encode_ext -{ - __u32 ext_flags; /* IW_ENCODE_EXT_* */ - __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ - __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ - struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast - * (group) keys or unicast address for - * individual keys */ - __u16 alg; /* IW_ENCODE_ALG_* */ - __u16 key_len; - __u8 key[0]; -}; - -/* SIOCSIWMLME data */ -struct iw_mlme -{ - __u16 cmd; /* IW_MLME_* */ - __u16 reason_code; - struct sockaddr addr; -}; - -/* SIOCSIWPMKSA data */ -#define IW_PMKSA_ADD 1 -#define IW_PMKSA_REMOVE 2 -#define IW_PMKSA_FLUSH 3 - -#define IW_PMKID_LEN 16 - -struct iw_pmksa -{ - __u32 cmd; /* IW_PMKSA_* */ - struct sockaddr bssid; - __u8 pmkid[IW_PMKID_LEN]; -}; - -/* IWEVMICHAELMICFAILURE data */ -struct iw_michaelmicfailure -{ - __u32 flags; - struct sockaddr src_addr; - __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ -}; - -/* IWEVPMKIDCAND data */ -#define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */ -struct iw_pmkid_cand -{ - __u32 flags; /* IW_PMKID_CAND_* */ - __u32 index; /* the smaller the index, the higher the - * priority */ - struct sockaddr bssid; -}; - -/* ------------------------ WIRELESS STATS ------------------------ */ -/* - * Wireless statistics (used for /proc/net/wireless) - */ -struct iw_statistics -{ - __u16 status; /* Status - * - device dependent for now */ - - struct iw_quality qual; /* Quality of the link - * (instant/mean/max) */ - struct iw_discarded discard; /* Packet discarded counts */ - struct iw_missed miss; /* Packet missed counts */ -}; - -/* ------------------------ IOCTL REQUEST ------------------------ */ -/* - * This structure defines the payload of an ioctl, and is used - * below. - * - * Note that this structure should fit on the memory footprint - * of iwreq (which is the same as ifreq), which mean a max size of - * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... - * You should check this when increasing the structures defined - * above in this file... - */ -union iwreq_data -{ - /* Config - generic */ - char name[IFNAMSIZ]; - /* Name : used to verify the presence of wireless extensions. - * Name of the protocol/provider... */ - - struct iw_point essid; /* Extended network name */ - struct iw_param nwid; /* network id (or domain - the cell) */ - struct iw_freq freq; /* frequency or channel : - * 0-1000 = channel - * > 1000 = frequency in Hz */ - - struct iw_param sens; /* signal level threshold */ - struct iw_param bitrate; /* default bit rate */ - struct iw_param txpower; /* default transmit power */ - struct iw_param rts; /* RTS threshold threshold */ - struct iw_param frag; /* Fragmentation threshold */ - __u32 mode; /* Operation mode */ - struct iw_param retry; /* Retry limits & lifetime */ - - struct iw_point encoding; /* Encoding stuff : tokens */ - struct iw_param power; /* PM duration/timeout */ - struct iw_quality qual; /* Quality part of statistics */ - - struct sockaddr ap_addr; /* Access point address */ - struct sockaddr addr; /* Destination address (hw/mac) */ - - struct iw_param param; /* Other small parameters */ - struct iw_point data; /* Other large parameters */ -}; - -/* - * The structure to exchange data for ioctl. - * This structure is the same as 'struct ifreq', but (re)defined for - * convenience... - * Do I need to remind you about structure size (32 octets) ? - */ -struct iwreq -{ - union - { - char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ - } ifr_ifrn; - - /* Data part (defined just above) */ - union iwreq_data u; -}; - -/* -------------------------- IOCTL DATA -------------------------- */ -/* - * For those ioctl which want to exchange mode data that what could - * fit in the above structure... - */ - -/* - * Range of parameters - */ - -struct iw_range -{ - /* Informative stuff (to choose between different interface) */ - __u32 throughput; /* To give an idea... */ - /* In theory this value should be the maximum benchmarked - * TCP/IP throughput, because with most of these devices the - * bit rate is meaningless (overhead an co) to estimate how - * fast the connection will go and pick the fastest one. - * I suggest people to play with Netperf or any benchmark... - */ - - /* NWID (or domain id) */ - __u32 min_nwid; /* Minimal NWID we are able to set */ - __u32 max_nwid; /* Maximal NWID we are able to set */ - - /* Old Frequency (backward compat - moved lower ) */ - __u16 old_num_channels; - __u8 old_num_frequency; - - /* Wireless event capability bitmasks */ - __u32 event_capa[6]; - - /* signal level threshold range */ - __s32 sensitivity; - - /* Quality of link & SNR stuff */ - /* Quality range (link, level, noise) - * If the quality is absolute, it will be in the range [0 ; max_qual], - * if the quality is dBm, it will be in the range [max_qual ; 0]. - * Don't forget that we use 8 bit arithmetics... */ - struct iw_quality max_qual; /* Quality of the link */ - /* This should contain the average/typical values of the quality - * indicator. This should be the threshold between a "good" and - * a "bad" link (example : monitor going from green to orange). - * Currently, user space apps like quality monitors don't have any - * way to calibrate the measurement. With this, they can split - * the range between 0 and max_qual in different quality level - * (using a geometric subdivision centered on the average). - * I expect that people doing the user space apps will feedback - * us on which value we need to put in each driver... */ - struct iw_quality avg_qual; /* Quality of the link */ - - /* Rates */ - __u8 num_bitrates; /* Number of entries in the list */ - __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */ - - /* RTS threshold */ - __s32 min_rts; /* Minimal RTS threshold */ - __s32 max_rts; /* Maximal RTS threshold */ - - /* Frag threshold */ - __s32 min_frag; /* Minimal frag threshold */ - __s32 max_frag; /* Maximal frag threshold */ - - /* Power Management duration & timeout */ - __s32 min_pmp; /* Minimal PM period */ - __s32 max_pmp; /* Maximal PM period */ - __s32 min_pmt; /* Minimal PM timeout */ - __s32 max_pmt; /* Maximal PM timeout */ - __u16 pmp_flags; /* How to decode max/min PM period */ - __u16 pmt_flags; /* How to decode max/min PM timeout */ - __u16 pm_capa; /* What PM options are supported */ - - /* Encoder stuff */ - __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ - __u8 num_encoding_sizes; /* Number of entry in the list */ - __u8 max_encoding_tokens; /* Max number of tokens */ - /* For drivers that need a "login/passwd" form */ - __u8 encoding_login_index; /* token index for login token */ - - /* Transmit power */ - __u16 txpower_capa; /* What options are supported */ - __u8 num_txpower; /* Number of entries in the list */ - __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ - - /* Wireless Extension version info */ - __u8 we_version_compiled; /* Must be WIRELESS_EXT */ - __u8 we_version_source; /* Last update of source */ - - /* Retry limits and lifetime */ - __u16 retry_capa; /* What retry options are supported */ - __u16 retry_flags; /* How to decode max/min retry limit */ - __u16 r_time_flags; /* How to decode max/min retry life */ - __s32 min_retry; /* Minimal number of retries */ - __s32 max_retry; /* Maximal number of retries */ - __s32 min_r_time; /* Minimal retry lifetime */ - __s32 max_r_time; /* Maximal retry lifetime */ - - /* Frequency */ - __u16 num_channels; /* Number of channels [0; num - 1] */ - __u8 num_frequency; /* Number of entry in the list */ - struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ - /* Note : this frequency list doesn't need to fit channel numbers, - * because each entry contain its channel index */ - - __u32 enc_capa; /* IW_ENC_CAPA_* bit field */ -}; - -/* - * Private ioctl interface information - */ - -struct iw_priv_args -{ - __u32 cmd; /* Number of the ioctl to issue */ - __u16 set_args; /* Type and number of args */ - __u16 get_args; /* Type and number of args */ - char name[IFNAMSIZ]; /* Name of the extension */ -}; - -/* ----------------------- WIRELESS EVENTS ----------------------- */ -/* - * Wireless events are carried through the rtnetlink socket to user - * space. They are encapsulated in the IFLA_WIRELESS field of - * a RTM_NEWLINK message. - */ - -/* - * A Wireless Event. Contains basically the same data as the ioctl... - */ -struct iw_event -{ - __u16 len; /* Real lenght of this stuff */ - __u16 cmd; /* Wireless IOCTL */ - union iwreq_data u; /* IOCTL fixed payload */ -}; - -/* Size of the Event prefix (including padding and alignement junk) */ -#define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data)) -/* Size of the various events */ -#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ) -#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32)) -#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq)) -#define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param)) -#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr)) -#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality)) - -/* iw_point events are special. First, the payload (extra data) come at - * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second, - * we omit the pointer, so start at an offset. */ -#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \ - (char *) NULL) -#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \ - IW_EV_POINT_OFF) - -#endif /* _LINUX_WIRELESS_H */ diff --git a/contrib/hostapd/src/common/wpa_common.c b/contrib/hostapd/src/common/wpa_common.c deleted file mode 100644 index 074cb80640..0000000000 --- a/contrib/hostapd/src/common/wpa_common.c +++ /dev/null @@ -1,570 +0,0 @@ -/* - * WPA/RSN - Shared functions for supplicant and authenticator - * Copyright (c) 2002-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "md5.h" -#include "sha1.h" -#include "sha256.h" -#include "aes_wrap.h" -#include "crypto.h" -#include "ieee802_11_defs.h" -#include "defs.h" -#include "wpa_common.h" - - -/** - * wpa_eapol_key_mic - Calculate EAPOL-Key MIC - * @key: EAPOL-Key Key Confirmation Key (KCK) - * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*) - * @buf: Pointer to the beginning of the EAPOL header (version field) - * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame) - * @mic: Pointer to the buffer to which the EAPOL-Key MIC is written - * Returns: 0 on success, -1 on failure - * - * Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has - * to be cleared (all zeroes) when calling this function. - * - * Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the - * description of the Key MIC calculation. It includes packet data from the - * beginning of the EAPOL-Key header, not EAPOL header. This incorrect change - * happened during final editing of the standard and the correct behavior is - * defined in the last draft (IEEE 802.11i/D10). - */ -int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len, - u8 *mic) -{ - u8 hash[SHA1_MAC_LEN]; - - switch (ver) { - case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4: - hmac_md5(key, 16, buf, len, mic); - break; - case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES: - hmac_sha1(key, 16, buf, len, hash); - os_memcpy(mic, hash, MD5_MAC_LEN); - break; -#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) - case WPA_KEY_INFO_TYPE_AES_128_CMAC: - return omac1_aes_128(key, buf, len, mic); -#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ - default: - return -1; - } - - return 0; -} - - -/** - * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces - * @pmk: Pairwise master key - * @pmk_len: Length of PMK - * @label: Label to use in derivation - * @addr1: AA or SA - * @addr2: SA or AA - * @nonce1: ANonce or SNonce - * @nonce2: SNonce or ANonce - * @ptk: Buffer for pairwise transient key - * @ptk_len: Length of PTK - * @use_sha256: Whether to use SHA256-based KDF - * - * 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)) - * - * STK = PRF-X(SMK, "Peer key expansion", - * Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) || - * Min(INonce, PNonce) || Max(INonce, PNonce)) - */ -void 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, - u8 *ptk, size_t ptk_len, int use_sha256) -{ - u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN]; - - if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) { - os_memcpy(data, addr1, ETH_ALEN); - os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN); - } else { - os_memcpy(data, addr2, ETH_ALEN); - os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN); - } - - if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) { - os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN); - os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2, - WPA_NONCE_LEN); - } else { - os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN); - os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1, - WPA_NONCE_LEN); - } - -#ifdef CONFIG_IEEE80211W - if (use_sha256) - sha256_prf(pmk, pmk_len, label, data, sizeof(data), - ptk, ptk_len); - else -#endif /* CONFIG_IEEE80211W */ - sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk, - ptk_len); - - wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR, - MAC2STR(addr1), MAC2STR(addr2)); - wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len); - wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len); -} - - -#ifdef CONFIG_IEEE80211R -int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr, - u8 transaction_seqnum, const u8 *mdie, size_t mdie_len, - const u8 *ftie, size_t ftie_len, - const u8 *rsnie, size_t rsnie_len, - const u8 *ric, size_t ric_len, u8 *mic) -{ - u8 *buf, *pos; - size_t buf_len; - - buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len; - buf = os_malloc(buf_len); - if (buf == NULL) - return -1; - - pos = buf; - os_memcpy(pos, sta_addr, ETH_ALEN); - pos += ETH_ALEN; - os_memcpy(pos, ap_addr, ETH_ALEN); - pos += ETH_ALEN; - *pos++ = transaction_seqnum; - if (rsnie) { - os_memcpy(pos, rsnie, rsnie_len); - pos += rsnie_len; - } - if (mdie) { - os_memcpy(pos, mdie, mdie_len); - pos += mdie_len; - } - if (ftie) { - struct rsn_ftie *_ftie; - os_memcpy(pos, ftie, ftie_len); - if (ftie_len < 2 + sizeof(*_ftie)) { - os_free(buf); - return -1; - } - _ftie = (struct rsn_ftie *) (pos + 2); - os_memset(_ftie->mic, 0, sizeof(_ftie->mic)); - pos += ftie_len; - } - if (ric) { - os_memcpy(pos, ric, ric_len); - pos += ric_len; - } - - wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", buf, pos - buf); - if (omac1_aes_128(kck, buf, pos - buf, mic)) { - os_free(buf); - return -1; - } - - os_free(buf); - - return 0; -} -#endif /* CONFIG_IEEE80211R */ - - -#ifndef CONFIG_NO_WPA2 -static int rsn_selector_to_bitfield(const u8 *s) -{ - if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE) - return WPA_CIPHER_NONE; - if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP40) - return WPA_CIPHER_WEP40; - if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP) - return WPA_CIPHER_TKIP; - if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP) - return WPA_CIPHER_CCMP; - if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP104) - return WPA_CIPHER_WEP104; -#ifdef CONFIG_IEEE80211W - if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC) - return WPA_CIPHER_AES_128_CMAC; -#endif /* CONFIG_IEEE80211W */ - return 0; -} - - -static int rsn_key_mgmt_to_bitfield(const u8 *s) -{ - if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X) - return WPA_KEY_MGMT_IEEE8021X; - if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X) - return WPA_KEY_MGMT_PSK; -#ifdef CONFIG_IEEE80211R - if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X) - return WPA_KEY_MGMT_FT_IEEE8021X; - if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK) - return WPA_KEY_MGMT_FT_PSK; -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256) - return WPA_KEY_MGMT_IEEE8021X_SHA256; - if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256) - return WPA_KEY_MGMT_PSK_SHA256; -#endif /* CONFIG_IEEE80211W */ - return 0; -} -#endif /* CONFIG_NO_WPA2 */ - - -/** - * wpa_parse_wpa_ie_rsn - Parse RSN IE - * @rsn_ie: Buffer containing RSN IE - * @rsn_ie_len: RSN IE buffer length (including IE number and length octets) - * @data: Pointer to structure that will be filled in with parsed data - * Returns: 0 on success, <0 on failure - */ -int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, - struct wpa_ie_data *data) -{ -#ifndef CONFIG_NO_WPA2 - const struct rsn_ie_hdr *hdr; - const u8 *pos; - int left; - int i, count; - - os_memset(data, 0, sizeof(*data)); - data->proto = WPA_PROTO_RSN; - data->pairwise_cipher = WPA_CIPHER_CCMP; - data->group_cipher = WPA_CIPHER_CCMP; - data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; - data->capabilities = 0; - data->pmkid = NULL; - data->num_pmkid = 0; -#ifdef CONFIG_IEEE80211W - data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC; -#else /* CONFIG_IEEE80211W */ - data->mgmt_group_cipher = 0; -#endif /* CONFIG_IEEE80211W */ - - if (rsn_ie_len == 0) { - /* No RSN IE - fail silently */ - return -1; - } - - if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) { - wpa_printf(MSG_DEBUG, "%s: ie len too short %lu", - __func__, (unsigned long) rsn_ie_len); - return -1; - } - - hdr = (const struct rsn_ie_hdr *) rsn_ie; - - if (hdr->elem_id != WLAN_EID_RSN || - hdr->len != rsn_ie_len - 2 || - WPA_GET_LE16(hdr->version) != RSN_VERSION) { - wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", - __func__); - return -2; - } - - pos = (const u8 *) (hdr + 1); - left = rsn_ie_len - sizeof(*hdr); - - if (left >= RSN_SELECTOR_LEN) { - data->group_cipher = rsn_selector_to_bitfield(pos); -#ifdef CONFIG_IEEE80211W - if (data->group_cipher == WPA_CIPHER_AES_128_CMAC) { - wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as group " - "cipher", __func__); - return -1; - } -#endif /* CONFIG_IEEE80211W */ - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } else if (left > 0) { - wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", - __func__, left); - return -3; - } - - if (left >= 2) { - data->pairwise_cipher = 0; - count = WPA_GET_LE16(pos); - pos += 2; - left -= 2; - if (count == 0 || left < count * RSN_SELECTOR_LEN) { - wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " - "count %u left %u", __func__, count, left); - return -4; - } - for (i = 0; i < count; i++) { - data->pairwise_cipher |= rsn_selector_to_bitfield(pos); - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } -#ifdef CONFIG_IEEE80211W - if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) { - wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as " - "pairwise cipher", __func__); - return -1; - } -#endif /* CONFIG_IEEE80211W */ - } else if (left == 1) { - wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", - __func__); - return -5; - } - - if (left >= 2) { - data->key_mgmt = 0; - count = WPA_GET_LE16(pos); - pos += 2; - left -= 2; - if (count == 0 || left < count * RSN_SELECTOR_LEN) { - wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " - "count %u left %u", __func__, count, left); - return -6; - } - for (i = 0; i < count; i++) { - data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos); - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } - } else if (left == 1) { - wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", - __func__); - return -7; - } - - if (left >= 2) { - data->capabilities = WPA_GET_LE16(pos); - pos += 2; - left -= 2; - } - - if (left >= 2) { - data->num_pmkid = WPA_GET_LE16(pos); - pos += 2; - left -= 2; - if (left < (int) data->num_pmkid * PMKID_LEN) { - wpa_printf(MSG_DEBUG, "%s: PMKID underflow " - "(num_pmkid=%lu left=%d)", - __func__, (unsigned long) data->num_pmkid, - left); - data->num_pmkid = 0; - return -9; - } else { - data->pmkid = pos; - pos += data->num_pmkid * PMKID_LEN; - left -= data->num_pmkid * PMKID_LEN; - } - } - -#ifdef CONFIG_IEEE80211W - if (left >= 4) { - data->mgmt_group_cipher = rsn_selector_to_bitfield(pos); - if (data->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) { - wpa_printf(MSG_DEBUG, "%s: Unsupported management " - "group cipher 0x%x", __func__, - data->mgmt_group_cipher); - return -10; - } - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } -#endif /* CONFIG_IEEE80211W */ - - if (left > 0) { - wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored", - __func__, left); - } - - return 0; -#else /* CONFIG_NO_WPA2 */ - return -1; -#endif /* CONFIG_NO_WPA2 */ -} - - -#ifdef CONFIG_IEEE80211R - -/** - * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name - * - * 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) -{ - u8 buf[1 + WPA_MAX_SSID_LEN + MOBILITY_DOMAIN_ID_LEN + 1 + - FT_R0KH_ID_MAX_LEN + ETH_ALEN]; - u8 *pos, r0_key_data[48], hash[32]; - const u8 *addr[2]; - size_t len[2]; - - /* - * 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) - */ - if (ssid_len > WPA_MAX_SSID_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN) - return; - pos = buf; - *pos++ = ssid_len; - os_memcpy(pos, ssid, ssid_len); - pos += ssid_len; - os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN); - pos += MOBILITY_DOMAIN_ID_LEN; - *pos++ = r0kh_id_len; - os_memcpy(pos, r0kh_id, r0kh_id_len); - pos += r0kh_id_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); - - /* - * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt) - */ - addr[0] = (const u8 *) "FT-R0N"; - len[0] = 6; - addr[1] = r0_key_data + PMK_LEN; - len[1] = 16; - - sha256_vector(2, addr, len, hash); - os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN); -} - - -/** - * wpa_derive_pmk_r1_name - Derive PMKR1Name - * - * 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) -{ - u8 hash[32]; - const u8 *addr[4]; - size_t len[4]; - - /* - * PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name || - * R1KH-ID || S1KH-ID)) - */ - addr[0] = (const u8 *) "FT-R1N"; - len[0] = 6; - addr[1] = pmk_r0_name; - len[1] = WPA_PMK_NAME_LEN; - addr[2] = r1kh_id; - len[2] = FT_R1KH_ID_LEN; - addr[3] = s1kh_id; - len[3] = ETH_ALEN; - - sha256_vector(4, addr, len, hash); - os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN); -} - - -/** - * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0 - * - * 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) -{ - u8 buf[FT_R1KH_ID_LEN + ETH_ALEN]; - u8 *pos; - - /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || 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); - - wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name); -} - - -/** - * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1 - * - * IEEE Std 802.11r-2008 - 8.5.1.5.5 - */ -void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, - const u8 *sta_addr, const u8 *bssid, - const u8 *pmk_r1_name, - u8 *ptk, size_t ptk_len, u8 *ptk_name) -{ - u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN]; - u8 *pos, hash[32]; - const u8 *addr[6]; - size_t len[6]; - - /* - * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce || - * BSSID || STA-ADDR) - */ - pos = buf; - os_memcpy(pos, snonce, WPA_NONCE_LEN); - pos += WPA_NONCE_LEN; - os_memcpy(pos, anonce, WPA_NONCE_LEN); - pos += WPA_NONCE_LEN; - os_memcpy(pos, bssid, ETH_ALEN); - pos += ETH_ALEN; - os_memcpy(pos, sta_addr, ETH_ALEN); - pos += ETH_ALEN; - - sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, ptk, ptk_len); - - /* - * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce || - * ANonce || BSSID || STA-ADDR)) - */ - addr[0] = pmk_r1_name; - len[0] = WPA_PMK_NAME_LEN; - addr[1] = (const u8 *) "FT-PTKN"; - len[1] = 7; - addr[2] = snonce; - len[2] = WPA_NONCE_LEN; - addr[3] = anonce; - len[3] = WPA_NONCE_LEN; - addr[4] = bssid; - len[4] = ETH_ALEN; - addr[5] = sta_addr; - len[5] = ETH_ALEN; - - sha256_vector(6, addr, len, hash); - os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN); -} - -#endif /* CONFIG_IEEE80211R */ diff --git a/contrib/hostapd/src/common/wpa_common.h b/contrib/hostapd/src/common/wpa_common.h deleted file mode 100644 index 3074cd44a1..0000000000 --- a/contrib/hostapd/src/common/wpa_common.h +++ /dev/null @@ -1,335 +0,0 @@ -/* - * WPA definitions shared between hostapd and wpa_supplicant - * Copyright (c) 2002-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPA_COMMON_H -#define WPA_COMMON_H - -#define WPA_MAX_SSID_LEN 32 - -/* IEEE 802.11i */ -#define PMKID_LEN 16 -#define PMK_LEN 32 -#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 WPA_SELECTOR_LEN 4 -#define WPA_VERSION 1 -#define RSN_SELECTOR_LEN 4 -#define RSN_VERSION 1 - -#define RSN_SELECTOR(a, b, c, d) \ - ((((u32) (a)) << 24) | (((u32) (b)) << 16) | (((u32) (c)) << 8) | \ - (u32) (d)) - -#define WPA_AUTH_KEY_MGMT_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0) -#define WPA_AUTH_KEY_MGMT_UNSPEC_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 1) -#define WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 2) -#define WPA_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0) -#define WPA_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x50, 0xf2, 1) -#define WPA_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x50, 0xf2, 2) -#if 0 -#define WPA_CIPHER_SUITE_WRAP RSN_SELECTOR(0x00, 0x50, 0xf2, 3) -#endif -#define WPA_CIPHER_SUITE_CCMP RSN_SELECTOR(0x00, 0x50, 0xf2, 4) -#define WPA_CIPHER_SUITE_WEP104 RSN_SELECTOR(0x00, 0x50, 0xf2, 5) - - -#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_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) -#ifdef CONFIG_IEEE80211W -#define RSN_CIPHER_SUITE_AES_128_CMAC RSN_SELECTOR(0x00, 0x0f, 0xac, 6) -#endif /* CONFIG_IEEE80211W */ - -/* EAPOL-Key Key Data Encapsulation - * GroupKey and PeerKey require encryption, otherwise, encryption is optional. - */ -#define RSN_KEY_DATA_GROUPKEY RSN_SELECTOR(0x00, 0x0f, 0xac, 1) -#if 0 -#define RSN_KEY_DATA_STAKEY RSN_SELECTOR(0x00, 0x0f, 0xac, 2) -#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 WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1) - -#define RSN_SELECTOR_PUT(a, val) WPA_PUT_BE32((u8 *) (a), (val)) -#define RSN_SELECTOR_GET(a) WPA_GET_BE32((const u8 *) (a)) - -#define RSN_NUM_REPLAY_COUNTERS_1 0 -#define RSN_NUM_REPLAY_COUNTERS_2 1 -#define RSN_NUM_REPLAY_COUNTERS_4 2 -#define RSN_NUM_REPLAY_COUNTERS_16 3 - - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -#ifdef CONFIG_IEEE80211W -#define WPA_IGTK_LEN 16 -#endif /* CONFIG_IEEE80211W */ - - -/* IEEE 802.11, 7.3.2.25.3 RSN Capabilities */ -#define WPA_CAPABILITY_PREAUTH BIT(0) -#define WPA_CAPABILITY_NO_PAIRWISE BIT(1) -/* B2-B3: PTKSA Replay Counter */ -/* B4-B5: GTKSA Replay Counter */ -#define WPA_CAPABILITY_MFPR BIT(6) -#define WPA_CAPABILITY_MFPC BIT(7) -#define WPA_CAPABILITY_PEERKEY_ENABLED BIT(9) - - -/* IEEE 802.11r */ -#define MOBILITY_DOMAIN_ID_LEN 2 -#define FT_R0KH_ID_MAX_LEN 48 -#define FT_R1KH_ID_LEN 6 -#define WPA_PMK_NAME_LEN 16 - - -/* IEEE 802.11, 8.5.2 EAPOL-Key frames */ -#define WPA_KEY_INFO_TYPE_MASK ((u16) (BIT(0) | BIT(1) | BIT(2))) -#define WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 BIT(0) -#define WPA_KEY_INFO_TYPE_HMAC_SHA1_AES BIT(1) -#define WPA_KEY_INFO_TYPE_AES_128_CMAC 3 -#define WPA_KEY_INFO_KEY_TYPE BIT(3) /* 1 = Pairwise, 0 = Group key */ -/* bit4..5 is used in WPA, but is reserved in IEEE 802.11i/RSN */ -#define WPA_KEY_INFO_KEY_INDEX_MASK (BIT(4) | BIT(5)) -#define WPA_KEY_INFO_KEY_INDEX_SHIFT 4 -#define WPA_KEY_INFO_INSTALL BIT(6) /* pairwise */ -#define WPA_KEY_INFO_TXRX BIT(6) /* group */ -#define WPA_KEY_INFO_ACK BIT(7) -#define WPA_KEY_INFO_MIC BIT(8) -#define WPA_KEY_INFO_SECURE BIT(9) -#define WPA_KEY_INFO_ERROR BIT(10) -#define WPA_KEY_INFO_REQUEST BIT(11) -#define WPA_KEY_INFO_ENCR_KEY_DATA BIT(12) /* IEEE 802.11i/RSN only */ -#define WPA_KEY_INFO_SMK_MESSAGE BIT(13) - - -struct wpa_eapol_key { - 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[16]; - u8 key_data_length[2]; /* big endian */ - /* followed by key_data_length bytes of key_data */ -} STRUCT_PACKED; - -/** - * struct wpa_ptk - WPA Pairwise Transient Key - * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy - */ -struct wpa_ptk { - u8 kck[16]; /* EAPOL-Key Key Confirmation Key (KCK) */ - u8 kek[16]; /* EAPOL-Key Key Encryption Key (KEK) */ - u8 tk1[16]; /* Temporal Key 1 (TK1) */ - union { - u8 tk2[16]; /* Temporal Key 2 (TK2) */ - struct { - u8 tx_mic_key[8]; - u8 rx_mic_key[8]; - } auth; - } u; -} STRUCT_PACKED; - - -/* WPA IE version 1 - * 00-50-f2:1 (OUI:OUI type) - * 0x01 0x00 (version; little endian) - * (all following fields are optional:) - * Group Suite Selector (4 octets) (default: TKIP) - * Pairwise Suite Count (2 octets, little endian) (default: 1) - * Pairwise Suite List (4 * n octets) (default: TKIP) - * Authenticated Key Management Suite Count (2 octets, little endian) - * (default: 1) - * Authenticated Key Management Suite List (4 * n octets) - * (default: unspec 802.1X) - * WPA Capabilities (2 octets, little endian) (default: 0) - */ - -struct wpa_ie_hdr { - u8 elem_id; - u8 len; - u8 oui[4]; /* 24-bit OUI followed by 8-bit OUI type */ - u8 version[2]; /* little endian */ -} STRUCT_PACKED; - - -/* 1/4: PMKID - * 2/4: RSN IE - * 3/4: one or two RSN IEs + GTK IE (encrypted) - * 4/4: empty - * 1/2: GTK IE (encrypted) - * 2/2: empty - */ - -/* RSN IE version 1 - * 0x01 0x00 (version; little endian) - * (all following fields are optional:) - * Group Suite Selector (4 octets) (default: CCMP) - * Pairwise Suite Count (2 octets, little endian) (default: 1) - * Pairwise Suite List (4 * n octets) (default: CCMP) - * Authenticated Key Management Suite Count (2 octets, little endian) - * (default: 1) - * Authenticated Key Management Suite List (4 * n octets) - * (default: unspec 802.1X) - * RSN Capabilities (2 octets, little endian) (default: 0) - * PMKID Count (2 octets) (default: 0) - * PMKID List (16 * n octets) - * Management Group Cipher Suite (4 octets) (default: AES-128-CMAC) - */ - -struct rsn_ie_hdr { - u8 elem_id; /* WLAN_EID_RSN */ - u8 len; - u8 version[2]; /* little endian */ -} 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; -} STRUCT_PACKED; - -#ifdef CONFIG_IEEE80211W -struct wpa_igtk_kde { - u8 keyid[2]; - u8 pn[6]; - u8 igtk[WPA_IGTK_LEN]; -} STRUCT_PACKED; -#endif /* CONFIG_IEEE80211W */ - -#ifdef CONFIG_IEEE80211R -struct rsn_mdie { - u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN]; - u8 ft_capab; -} STRUCT_PACKED; - -#define RSN_FT_CAPAB_FT_OVER_DS BIT(0) -#define RSN_FT_CAPAB_FT_RESOURCE_REQ_SUPP BIT(1) - -struct rsn_ftie { - u8 mic_control[2]; - u8 mic[16]; - 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 - -#endif /* CONFIG_IEEE80211R */ - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len, - u8 *mic); -void 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, - u8 *ptk, size_t ptk_len, int use_sha256); - -#ifdef CONFIG_IEEE80211R -int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr, - u8 transaction_seqnum, const u8 *mdie, size_t mdie_len, - 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); -void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, - const u8 *sta_addr, const u8 *bssid, - const u8 *pmk_r1_name, - u8 *ptk, size_t ptk_len, u8 *ptk_name); -#endif /* CONFIG_IEEE80211R */ - -struct wpa_ie_data { - int proto; - int pairwise_cipher; - int group_cipher; - int key_mgmt; - int capabilities; - size_t num_pmkid; - const u8 *pmkid; - int mgmt_group_cipher; -}; - - -int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, - struct wpa_ie_data *data); - -#endif /* WPA_COMMON_H */ diff --git a/contrib/hostapd/src/common/wpa_ctrl.c b/contrib/hostapd/src/common/wpa_ctrl.c deleted file mode 100644 index 2b4e3aa5ee..0000000000 --- a/contrib/hostapd/src/common/wpa_ctrl.c +++ /dev/null @@ -1,455 +0,0 @@ -/* - * wpa_supplicant/hostapd control interface library - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#ifdef CONFIG_CTRL_IFACE - -#ifdef CONFIG_CTRL_IFACE_UNIX -#include -#endif /* CONFIG_CTRL_IFACE_UNIX */ - -#include "wpa_ctrl.h" -#include "common.h" - - -#if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP) -#define CTRL_IFACE_SOCKET -#endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */ - - -/** - * struct wpa_ctrl - Internal structure for control interface library - * - * This structure is used by the wpa_supplicant/hostapd control interface - * library to store internal data. Programs using the library should not touch - * this data directly. They can only use the pointer to the data structure as - * an identifier for the control interface connection and use this as one of - * the arguments for most of the control interface library functions. - */ -struct wpa_ctrl { -#ifdef CONFIG_CTRL_IFACE_UDP - int s; - struct sockaddr_in local; - struct sockaddr_in dest; - char *cookie; -#endif /* CONFIG_CTRL_IFACE_UDP */ -#ifdef CONFIG_CTRL_IFACE_UNIX - int s; - struct sockaddr_un local; - struct sockaddr_un dest; -#endif /* CONFIG_CTRL_IFACE_UNIX */ -#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE - HANDLE pipe; -#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ -}; - - -#ifdef CONFIG_CTRL_IFACE_UNIX - -struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) -{ - struct wpa_ctrl *ctrl; - static int counter = 0; - int ret; - size_t res; - int tries = 0; - - ctrl = os_malloc(sizeof(*ctrl)); - if (ctrl == NULL) - return NULL; - os_memset(ctrl, 0, sizeof(*ctrl)); - - ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0); - if (ctrl->s < 0) { - os_free(ctrl); - return NULL; - } - - ctrl->local.sun_family = AF_UNIX; - counter++; -try_again: - ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path), - "/tmp/wpa_ctrl_%d-%d", getpid(), counter); - if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) { - close(ctrl->s); - os_free(ctrl); - return NULL; - } - tries++; - if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, - sizeof(ctrl->local)) < 0) { - if (errno == EADDRINUSE && tries < 2) { - /* - * getpid() returns unique identifier for this instance - * of wpa_ctrl, so the existing socket file must have - * been left by unclean termination of an earlier run. - * Remove the file and try again. - */ - unlink(ctrl->local.sun_path); - goto try_again; - } - close(ctrl->s); - os_free(ctrl); - return NULL; - } - - ctrl->dest.sun_family = AF_UNIX; - res = os_strlcpy(ctrl->dest.sun_path, ctrl_path, - sizeof(ctrl->dest.sun_path)); - if (res >= sizeof(ctrl->dest.sun_path)) { - close(ctrl->s); - os_free(ctrl); - return NULL; - } - if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, - sizeof(ctrl->dest)) < 0) { - close(ctrl->s); - unlink(ctrl->local.sun_path); - os_free(ctrl); - return NULL; - } - - return ctrl; -} - - -void wpa_ctrl_close(struct wpa_ctrl *ctrl) -{ - unlink(ctrl->local.sun_path); - close(ctrl->s); - os_free(ctrl); -} - -#endif /* CONFIG_CTRL_IFACE_UNIX */ - - -#ifdef CONFIG_CTRL_IFACE_UDP - -struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) -{ - struct wpa_ctrl *ctrl; - char buf[128]; - size_t len; - - ctrl = os_malloc(sizeof(*ctrl)); - if (ctrl == NULL) - return NULL; - os_memset(ctrl, 0, sizeof(*ctrl)); - - ctrl->s = socket(PF_INET, SOCK_DGRAM, 0); - if (ctrl->s < 0) { - perror("socket"); - os_free(ctrl); - return NULL; - } - - ctrl->local.sin_family = AF_INET; - ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1); - if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, - sizeof(ctrl->local)) < 0) { - close(ctrl->s); - os_free(ctrl); - return NULL; - } - - ctrl->dest.sin_family = AF_INET; - ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1); - ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT); - if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, - sizeof(ctrl->dest)) < 0) { - perror("connect"); - close(ctrl->s); - os_free(ctrl); - return NULL; - } - - len = sizeof(buf) - 1; - if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) { - buf[len] = '\0'; - ctrl->cookie = os_strdup(buf); - } - - return ctrl; -} - - -void wpa_ctrl_close(struct wpa_ctrl *ctrl) -{ - close(ctrl->s); - os_free(ctrl->cookie); - os_free(ctrl); -} - -#endif /* CONFIG_CTRL_IFACE_UDP */ - - -#ifdef CTRL_IFACE_SOCKET -int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, - char *reply, size_t *reply_len, - void (*msg_cb)(char *msg, size_t len)) -{ - struct timeval tv; - int res; - fd_set rfds; - const char *_cmd; - char *cmd_buf = NULL; - size_t _cmd_len; - -#ifdef CONFIG_CTRL_IFACE_UDP - if (ctrl->cookie) { - char *pos; - _cmd_len = os_strlen(ctrl->cookie) + 1 + cmd_len; - cmd_buf = os_malloc(_cmd_len); - if (cmd_buf == NULL) - return -1; - _cmd = cmd_buf; - pos = cmd_buf; - os_strlcpy(pos, ctrl->cookie, _cmd_len); - pos += os_strlen(ctrl->cookie); - *pos++ = ' '; - os_memcpy(pos, cmd, cmd_len); - } else -#endif /* CONFIG_CTRL_IFACE_UDP */ - { - _cmd = cmd; - _cmd_len = cmd_len; - } - - if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) { - os_free(cmd_buf); - return -1; - } - os_free(cmd_buf); - - for (;;) { - tv.tv_sec = 2; - tv.tv_usec = 0; - FD_ZERO(&rfds); - FD_SET(ctrl->s, &rfds); - res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv); - if (FD_ISSET(ctrl->s, &rfds)) { - res = recv(ctrl->s, reply, *reply_len, 0); - if (res < 0) - return res; - if (res > 0 && reply[0] == '<') { - /* This is an unsolicited message from - * wpa_supplicant, not the reply to the - * request. Use msg_cb to report this to the - * caller. */ - if (msg_cb) { - /* Make sure the message is nul - * terminated. */ - if ((size_t) res == *reply_len) - res = (*reply_len) - 1; - reply[res] = '\0'; - msg_cb(reply, res); - } - continue; - } - *reply_len = res; - break; - } else { - return -2; - } - } - return 0; -} -#endif /* CTRL_IFACE_SOCKET */ - - -static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach) -{ - char buf[10]; - int ret; - size_t len = 10; - - ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6, - buf, &len, NULL); - if (ret < 0) - return ret; - if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0) - return 0; - return -1; -} - - -int wpa_ctrl_attach(struct wpa_ctrl *ctrl) -{ - return wpa_ctrl_attach_helper(ctrl, 1); -} - - -int wpa_ctrl_detach(struct wpa_ctrl *ctrl) -{ - return wpa_ctrl_attach_helper(ctrl, 0); -} - - -#ifdef CTRL_IFACE_SOCKET - -int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) -{ - int res; - - res = recv(ctrl->s, reply, *reply_len, 0); - if (res < 0) - return res; - *reply_len = res; - return 0; -} - - -int wpa_ctrl_pending(struct wpa_ctrl *ctrl) -{ - struct timeval tv; - fd_set rfds; - tv.tv_sec = 0; - tv.tv_usec = 0; - FD_ZERO(&rfds); - FD_SET(ctrl->s, &rfds); - select(ctrl->s + 1, &rfds, NULL, NULL, &tv); - return FD_ISSET(ctrl->s, &rfds); -} - - -int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) -{ - return ctrl->s; -} - -#endif /* CTRL_IFACE_SOCKET */ - - -#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE - -#ifndef WPA_SUPPLICANT_NAMED_PIPE -#define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant" -#endif -#define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE) - -struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) -{ - struct wpa_ctrl *ctrl; - DWORD mode; - TCHAR name[256]; - int i, ret; - - ctrl = os_malloc(sizeof(*ctrl)); - if (ctrl == NULL) - return NULL; - os_memset(ctrl, 0, sizeof(*ctrl)); - -#ifdef UNICODE - if (ctrl_path == NULL) - ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX); - else - ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"), - ctrl_path); -#else /* UNICODE */ - if (ctrl_path == NULL) - ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX); - else - ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s", - ctrl_path); -#endif /* UNICODE */ - if (ret < 0 || ret >= 256) { - os_free(ctrl); - return NULL; - } - - for (i = 0; i < 10; i++) { - ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, - NULL, OPEN_EXISTING, 0, NULL); - /* - * Current named pipe server side in wpa_supplicant is - * re-opening the pipe for new clients only after the previous - * one is taken into use. This leaves a small window for race - * conditions when two connections are being opened at almost - * the same time. Retry if that was the case. - */ - if (ctrl->pipe != INVALID_HANDLE_VALUE || - GetLastError() != ERROR_PIPE_BUSY) - break; - WaitNamedPipe(name, 1000); - } - if (ctrl->pipe == INVALID_HANDLE_VALUE) { - os_free(ctrl); - return NULL; - } - - mode = PIPE_READMODE_MESSAGE; - if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) { - CloseHandle(ctrl->pipe); - os_free(ctrl); - return NULL; - } - - return ctrl; -} - - -void wpa_ctrl_close(struct wpa_ctrl *ctrl) -{ - CloseHandle(ctrl->pipe); - os_free(ctrl); -} - - -int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, - char *reply, size_t *reply_len, - void (*msg_cb)(char *msg, size_t len)) -{ - DWORD written; - DWORD readlen = *reply_len; - - if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL)) - return -1; - - if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL)) - return -1; - *reply_len = readlen; - - return 0; -} - - -int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) -{ - DWORD len = *reply_len; - if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL)) - return -1; - *reply_len = len; - return 0; -} - - -int wpa_ctrl_pending(struct wpa_ctrl *ctrl) -{ - DWORD left; - - if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL)) - return -1; - return left ? 1 : 0; -} - - -int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) -{ - return -1; -} - -#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ - -#endif /* CONFIG_CTRL_IFACE */ diff --git a/contrib/hostapd/src/common/wpa_ctrl.h b/contrib/hostapd/src/common/wpa_ctrl.h deleted file mode 100644 index 1bfc0d6453..0000000000 --- a/contrib/hostapd/src/common/wpa_ctrl.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * wpa_supplicant/hostapd control interface library - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPA_CTRL_H -#define WPA_CTRL_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* wpa_supplicant control interface - fixed message prefixes */ - -/** Interactive request for identity/password/pin */ -#define WPA_CTRL_REQ "CTRL-REQ-" - -/** Response to identity/password/pin request */ -#define WPA_CTRL_RSP "CTRL-RSP-" - -/* Event messages with fixed prefix */ -/** Authentication completed successfully and data connection enabled */ -#define WPA_EVENT_CONNECTED "CTRL-EVENT-CONNECTED " -/** Disconnected, data connection is not available */ -#define WPA_EVENT_DISCONNECTED "CTRL-EVENT-DISCONNECTED " -/** wpa_supplicant is exiting */ -#define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING " -/** Password change was completed successfully */ -#define WPA_EVENT_PASSWORD_CHANGED "CTRL-EVENT-PASSWORD-CHANGED " -/** EAP-Request/Notification received */ -#define WPA_EVENT_EAP_NOTIFICATION "CTRL-EVENT-EAP-NOTIFICATION " -/** EAP authentication started (EAP-Request/Identity received) */ -#define WPA_EVENT_EAP_STARTED "CTRL-EVENT-EAP-STARTED " -/** EAP method selected */ -#define WPA_EVENT_EAP_METHOD "CTRL-EVENT-EAP-METHOD " -/** EAP authentication completed successfully */ -#define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS " -/** EAP authentication failed (EAP-Failure received) */ -#define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE " -/** New scan results available */ -#define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS " - -/** WPS overlap detected in PBC mode */ -#define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED " -/** Available WPS AP with active PBC found in scan results */ -#define WPS_EVENT_AP_AVAILABLE_PBC "WPS-AP-AVAILABLE-PBC " -/** Available WPS AP with recently selected PIN registrar found in scan results - */ -#define WPS_EVENT_AP_AVAILABLE_PIN "WPS-AP-AVAILABLE-PIN " -/** Available WPS AP found in scan results */ -#define WPS_EVENT_AP_AVAILABLE "WPS-AP-AVAILABLE " -/** A new credential received */ -#define WPS_EVENT_CRED_RECEIVED "WPS-CRED-RECEIVED " -/** M2D received */ -#define WPS_EVENT_M2D "WPS-M2D " -/** WPS registration failed after M2/M2D */ -#define WPS_EVENT_FAIL "WPS-FAIL " -/** WPS registration completed successfully */ -#define WPS_EVENT_SUCCESS "WPS-SUCCESS " -/** WPS enrollment attempt timed out and was terminated */ -#define WPS_EVENT_TIMEOUT "WPS-TIMEOUT " - -/* hostapd control interface - fixed message prefixes */ -#define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED " -#define WPS_EVENT_NEW_AP_SETTINGS "WPS-NEW-AP-SETTINGS " -#define WPS_EVENT_REG_SUCCESS "WPS-REG-SUCCESS " -#define WPS_EVENT_AP_SETUP_LOCKED "WPS-AP-SETUP-LOCKED " - - -/* wpa_supplicant/hostapd control interface access */ - -/** - * wpa_ctrl_open - Open a control interface to wpa_supplicant/hostapd - * @ctrl_path: Path for UNIX domain sockets; ignored if UDP sockets are used. - * Returns: Pointer to abstract control interface data or %NULL on failure - * - * This function is used to open a control interface to wpa_supplicant/hostapd. - * ctrl_path is usually /var/run/wpa_supplicant or /var/run/hostapd. This path - * is configured in wpa_supplicant/hostapd and other programs using the control - * interface need to use matching path configuration. - */ -struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path); - - -/** - * wpa_ctrl_close - Close a control interface to wpa_supplicant/hostapd - * @ctrl: Control interface data from wpa_ctrl_open() - * - * This function is used to close a control interface. - */ -void wpa_ctrl_close(struct wpa_ctrl *ctrl); - - -/** - * wpa_ctrl_request - Send a command to wpa_supplicant/hostapd - * @ctrl: Control interface data from wpa_ctrl_open() - * @cmd: Command; usually, ASCII text, e.g., "PING" - * @cmd_len: Length of the cmd in bytes - * @reply: Buffer for the response - * @reply_len: Reply buffer length - * @msg_cb: Callback function for unsolicited messages or %NULL if not used - * Returns: 0 on success, -1 on error (send or receive failed), -2 on timeout - * - * 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 - * for the reply. If unsolicited messages are received, the blocking time may - * be longer. - * - * msg_cb can be used to register a callback function that will be called for - * unsolicited messages received while waiting for the command response. These - * messages may be received if wpa_ctrl_request() is called at the same time as - * wpa_supplicant/hostapd is sending such a message. This can happen only if - * the program has used wpa_ctrl_attach() to register itself as a monitor for - * event messages. Alternatively to msg_cb, programs can register two control - * interface connections and use one of them for commands and the other one for - * receiving event messages, in other words, call wpa_ctrl_attach() only for - * the control interface connection that will be used for event messages. - */ -int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, - char *reply, size_t *reply_len, - void (*msg_cb)(char *msg, size_t len)); - - -/** - * wpa_ctrl_attach - Register as an event monitor for the control interface - * @ctrl: Control interface data from wpa_ctrl_open() - * Returns: 0 on success, -1 on failure, -2 on timeout - * - * This function registers the control interface connection as a monitor for - * wpa_supplicant/hostapd events. After a success wpa_ctrl_attach() call, the - * control interface connection starts receiving event messages that can be - * read with wpa_ctrl_recv(). - */ -int wpa_ctrl_attach(struct wpa_ctrl *ctrl); - - -/** - * wpa_ctrl_detach - Unregister event monitor from the control interface - * @ctrl: Control interface data from wpa_ctrl_open() - * Returns: 0 on success, -1 on failure, -2 on timeout - * - * This function unregisters the control interface connection as a monitor for - * wpa_supplicant/hostapd events, i.e., cancels the registration done with - * wpa_ctrl_attach(). - */ -int wpa_ctrl_detach(struct wpa_ctrl *ctrl); - - -/** - * wpa_ctrl_recv - Receive a pending control interface message - * @ctrl: Control interface data from wpa_ctrl_open() - * @reply: Buffer for the message data - * @reply_len: Length of the reply buffer - * Returns: 0 on success, -1 on failure - * - * This function will receive a pending control interface message. This - * function will block if no messages are available. The received response will - * be written to reply and reply_len is set to the actual length of the reply. - * wpa_ctrl_recv() is only used for event messages, i.e., wpa_ctrl_attach() - * must have been used to register the control interface as an event monitor. - */ -int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len); - - -/** - * wpa_ctrl_pending - Check whether there are pending event messages - * @ctrl: Control interface data from wpa_ctrl_open() - * Returns: 1 if there are pending messages, 0 if no, or -1 on error - * - * This function will check whether there are any pending control interface - * message available to be received with wpa_ctrl_recv(). wpa_ctrl_pending() is - * only used for event messages, i.e., wpa_ctrl_attach() must have been used to - * register the control interface as an event monitor. - */ -int wpa_ctrl_pending(struct wpa_ctrl *ctrl); - - -/** - * wpa_ctrl_get_fd - Get file descriptor used by the control interface - * @ctrl: Control interface data from wpa_ctrl_open() - * Returns: File descriptor used for the connection - * - * This function can be used to get the file descriptor that is used for the - * control interface connection. The returned value can be used, e.g., with - * select() while waiting for multiple events. - * - * The returned file descriptor must not be used directly for sending or - * receiving packets; instead, the library functions wpa_ctrl_request() and - * wpa_ctrl_recv() must be used for this. - */ -int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl); - -#ifdef CONFIG_CTRL_IFACE_UDP -#define WPA_CTRL_IFACE_PORT 9877 -#define WPA_GLOBAL_CTRL_IFACE_PORT 9878 -#endif /* CONFIG_CTRL_IFACE_UDP */ - - -#ifdef __cplusplus -} -#endif - -#endif /* WPA_CTRL_H */ diff --git a/contrib/hostapd/src/crypto/aes.c b/contrib/hostapd/src/crypto/aes.c deleted file mode 100644 index 8b8f2a04de..0000000000 --- a/contrib/hostapd/src/crypto/aes.c +++ /dev/null @@ -1,1127 +0,0 @@ -/* - * AES (Rijndael) cipher - * - * Modifications to public domain implementation: - * - support only 128-bit keys - * - cleanup - * - use C pre-processor to make it easier to change S table access - * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at - * cost of reduced throughput (quite small difference on Pentium 4, - * 10-25% when using -O1 or -O2 optimization) - * - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" - -#ifdef INTERNAL_AES - -#include "crypto.h" - -/* - * rijndael-alg-fst.c - * - * @version 3.0 (December 2000) - * - * Optimised ANSI C code for the Rijndael cipher (now AES) - * - * @author Vincent Rijmen - * @author Antoon Bosselaers - * @author Paulo Barreto - * - * This code is hereby placed in the public domain. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. - */ - -/* #define FULL_UNROLL */ -#define AES_SMALL_TABLES - - -/* -Te0[x] = S [x].[02, 01, 01, 03]; -Te1[x] = S [x].[03, 02, 01, 01]; -Te2[x] = S [x].[01, 03, 02, 01]; -Te3[x] = S [x].[01, 01, 03, 02]; -Te4[x] = S [x].[01, 01, 01, 01]; - -Td0[x] = Si[x].[0e, 09, 0d, 0b]; -Td1[x] = Si[x].[0b, 0e, 09, 0d]; -Td2[x] = Si[x].[0d, 0b, 0e, 09]; -Td3[x] = Si[x].[09, 0d, 0b, 0e]; -Td4[x] = Si[x].[01, 01, 01, 01]; -*/ - -static const u32 Te0[256] = { - 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, - 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, - 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, - 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, - 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, - 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, - 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, - 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, - 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, - 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, - 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, - 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, - 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, - 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, - 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, - 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, - 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, - 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, - 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, - 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, - 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, - 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, - 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, - 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, - 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, - 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, - 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, - 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, - 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, - 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, - 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, - 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, - 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, - 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, - 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, - 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, - 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, - 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, - 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, - 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, - 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, - 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, - 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, - 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, - 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, - 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, - 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, - 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, - 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, - 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, - 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, - 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, - 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, - 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, - 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, - 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, - 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, - 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, - 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, - 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, - 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, - 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, - 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, - 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, -}; -#ifndef AES_SMALL_TABLES -static const u32 Te1[256] = { - 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, - 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, - 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, - 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, - 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, - 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, - 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, - 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, - 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, - 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, - 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, - 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, - 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, - 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, - 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, - 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, - 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, - 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, - 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, - 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, - 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, - 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, - 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, - 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, - 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, - 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, - 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, - 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, - 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, - 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, - 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, - 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, - 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, - 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, - 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, - 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, - 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, - 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, - 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, - 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, - 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, - 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, - 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, - 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, - 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, - 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, - 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, - 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, - 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, - 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, - 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, - 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, - 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, - 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, - 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, - 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, - 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, - 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, - 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, - 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, - 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, - 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, - 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, - 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, -}; -static const u32 Te2[256] = { - 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, - 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, - 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, - 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, - 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, - 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, - 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, - 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, - 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, - 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, - 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, - 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, - 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, - 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, - 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, - 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, - 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, - 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, - 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, - 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, - 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, - 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, - 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, - 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, - 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, - 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, - 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, - 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, - 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, - 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, - 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, - 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, - 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, - 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, - 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, - 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, - 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, - 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, - 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, - 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, - 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, - 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, - 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, - 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, - 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, - 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, - 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, - 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, - 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, - 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, - 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, - 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, - 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, - 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, - 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, - 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, - 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, - 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, - 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, - 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, - 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, - 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, - 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, - 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, -}; -static const u32 Te3[256] = { - - 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, - 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, - 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, - 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, - 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, - 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, - 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, - 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, - 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, - 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, - 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, - 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, - 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, - 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, - 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, - 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, - 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, - 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, - 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, - 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, - 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, - 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, - 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, - 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, - 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, - 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, - 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, - 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, - 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, - 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, - 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, - 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, - 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, - 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, - 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, - 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, - 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, - 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, - 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, - 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, - 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, - 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, - 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, - 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, - 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, - 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, - 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, - 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, - 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, - 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, - 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, - 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, - 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, - 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, - 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, - 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, - 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, - 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, - 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, - 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, - 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, - 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, - 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, - 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, -}; -static const u32 Te4[256] = { - 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, - 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, - 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, - 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, - 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, - 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, - 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, - 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, - 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, - 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, - 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, - 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, - 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, - 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, - 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, - 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, - 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, - 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, - 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, - 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, - 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, - 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, - 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, - 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, - 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, - 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, - 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, - 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, - 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, - 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, - 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, - 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, - 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, - 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, - 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, - 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, - 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, - 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, - 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, - 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, - 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, - 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, - 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, - 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, - 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, - 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, - 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, - 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, - 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, - 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, - 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, - 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, - 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, - 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, - 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, - 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, - 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, - 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, - 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, - 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, - 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, - 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, - 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, - 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, -}; -#endif /* AES_SMALL_TABLES */ -static const u32 Td0[256] = { - 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, - 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, - 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, - 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, - 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, - 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, - 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, - 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, - 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, - 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, - 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, - 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, - 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, - 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, - 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, - 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, - 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, - 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, - 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, - 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, - 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, - 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, - 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, - 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, - 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, - 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, - 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, - 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, - 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, - 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, - 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, - 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, - 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, - 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, - 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, - 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, - 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, - 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, - 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, - 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, - 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, - 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, - 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, - 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, - 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, - 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, - 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, - 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, - 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, - 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, - 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, - 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, - 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, - 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, - 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, - 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, - 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, - 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, - 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, - 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, - 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, - 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, - 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, - 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, -}; -#ifndef AES_SMALL_TABLES -static const u32 Td1[256] = { - 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, - 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, - 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, - 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, - 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, - 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, - 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, - 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, - 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, - 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, - 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, - 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, - 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, - 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, - 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, - 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, - 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, - 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, - 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, - 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, - 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, - 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, - 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, - 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, - 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, - 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, - 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, - 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, - 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, - 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, - 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, - 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, - 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, - 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, - 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, - 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, - 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, - 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, - 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, - 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, - 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, - 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, - 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, - 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, - 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, - 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, - 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, - 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, - 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, - 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, - 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, - 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, - 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, - 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, - 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, - 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, - 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, - 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, - 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, - 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, - 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, - 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, - 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, - 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, -}; -static const u32 Td2[256] = { - 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, - 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, - 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, - 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, - 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, - 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, - 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, - 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, - 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, - 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, - 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, - 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, - 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, - 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, - 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, - 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, - 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, - 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, - 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, - 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, - - 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, - 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, - 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, - 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, - 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, - 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, - 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, - 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, - 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, - 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, - 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, - 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, - 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, - 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, - 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, - 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, - 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, - 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, - 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, - 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, - 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, - 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, - 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, - 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, - 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, - 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, - 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, - 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, - 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, - 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, - 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, - 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, - 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, - 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, - 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, - 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, - 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, - 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, - 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, - 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, - 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, - 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, - 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, - 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, -}; -static const u32 Td3[256] = { - 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, - 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, - 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, - 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, - 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, - 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, - 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, - 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, - 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, - 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, - 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, - 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, - 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, - 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, - 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, - 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, - 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, - 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, - 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, - 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, - 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, - 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, - 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, - 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, - 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, - 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, - 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, - 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, - 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, - 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, - 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, - 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, - 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, - 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, - 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, - 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, - 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, - 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, - 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, - 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, - 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, - 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, - 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, - 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, - 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, - 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, - 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, - 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, - 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, - 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, - 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, - 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, - 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, - 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, - 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, - 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, - 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, - 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, - 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, - 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, - 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, - 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, - 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, - 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, -}; -static const u32 Td4[256] = { - 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, - 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, - 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, - 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, - 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, - 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, - 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, - 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, - 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, - 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, - 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, - 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, - 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, - 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, - 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, - 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, - 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, - 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, - 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, - 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, - 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, - 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, - 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, - 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, - 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, - 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, - 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, - 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, - 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, - 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, - 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, - 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, - 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, - 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, - 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, - 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, - 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, - 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, - 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, - 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, - 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, - 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, - 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, - 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, - 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, - 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, - 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, - 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, - 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, - 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, - 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, - 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, - 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, - 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, - 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, - 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, - 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, - 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, - 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, - 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, - 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, - 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, - 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, - 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, -}; -static const u32 rcon[] = { - 0x01000000, 0x02000000, 0x04000000, 0x08000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000, - 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ -}; -#else /* AES_SMALL_TABLES */ -static const u8 Td4s[256] = { - 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, - 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, - 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, - 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, - 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, - 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, - 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, - 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, - 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, - 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, - 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, - 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, - 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, - 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, - 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, - 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, - 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, - 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, - 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, - 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, - 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, - 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, - 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, - 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, - 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, - 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, - 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, - 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, - 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, - 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, - 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, - 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, -}; -static const u8 rcons[] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 - /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ -}; -#endif /* AES_SMALL_TABLES */ - - -#ifndef AES_SMALL_TABLES - -#define RCON(i) rcon[(i)] - -#define TE0(i) Te0[((i) >> 24) & 0xff] -#define TE1(i) Te1[((i) >> 16) & 0xff] -#define TE2(i) Te2[((i) >> 8) & 0xff] -#define TE3(i) Te3[(i) & 0xff] -#define TE41(i) (Te4[((i) >> 24) & 0xff] & 0xff000000) -#define TE42(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000) -#define TE43(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00) -#define TE44(i) (Te4[(i) & 0xff] & 0x000000ff) -#define TE421(i) (Te4[((i) >> 16) & 0xff] & 0xff000000) -#define TE432(i) (Te4[((i) >> 8) & 0xff] & 0x00ff0000) -#define TE443(i) (Te4[(i) & 0xff] & 0x0000ff00) -#define TE414(i) (Te4[((i) >> 24) & 0xff] & 0x000000ff) -#define TE4(i) (Te4[(i)] & 0x000000ff) - -#define TD0(i) Td0[((i) >> 24) & 0xff] -#define TD1(i) Td1[((i) >> 16) & 0xff] -#define TD2(i) Td2[((i) >> 8) & 0xff] -#define TD3(i) Td3[(i) & 0xff] -#define TD41(i) (Td4[((i) >> 24) & 0xff] & 0xff000000) -#define TD42(i) (Td4[((i) >> 16) & 0xff] & 0x00ff0000) -#define TD43(i) (Td4[((i) >> 8) & 0xff] & 0x0000ff00) -#define TD44(i) (Td4[(i) & 0xff] & 0x000000ff) -#define TD0_(i) Td0[(i) & 0xff] -#define TD1_(i) Td1[(i) & 0xff] -#define TD2_(i) Td2[(i) & 0xff] -#define TD3_(i) Td3[(i) & 0xff] - -#else /* AES_SMALL_TABLES */ - -#define RCON(i) (rcons[(i)] << 24) - -static inline u32 rotr(u32 val, int bits) -{ - return (val >> bits) | (val << (32 - bits)); -} - -#define TE0(i) Te0[((i) >> 24) & 0xff] -#define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8) -#define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16) -#define TE3(i) rotr(Te0[(i) & 0xff], 24) -#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000) -#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000) -#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00) -#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff) -#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000) -#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000) -#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00) -#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff) -#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff) - -#define TD0(i) Td0[((i) >> 24) & 0xff] -#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8) -#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16) -#define TD3(i) rotr(Td0[(i) & 0xff], 24) -#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24) -#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16) -#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8) -#define TD44(i) (Td4s[(i) & 0xff]) -#define TD0_(i) Td0[(i) & 0xff] -#define TD1_(i) rotr(Td0[(i) & 0xff], 8) -#define TD2_(i) rotr(Td0[(i) & 0xff], 16) -#define TD3_(i) rotr(Td0[(i) & 0xff], 24) - -#endif /* AES_SMALL_TABLES */ - -#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) - -#ifdef _MSC_VER -#define GETU32(p) SWAP(*((u32 *)(p))) -#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } -#else -#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \ -((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) -#define PUTU32(ct, st) { \ -(ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \ -(ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } -#endif - -/** - * Expand the cipher key into the encryption key schedule. - * - * @return the number of rounds for the given cipher key size. - */ -void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[]) -{ - int i; - u32 temp; - - rk[0] = GETU32(cipherKey ); - rk[1] = GETU32(cipherKey + 4); - rk[2] = GETU32(cipherKey + 8); - rk[3] = GETU32(cipherKey + 12); - for (i = 0; i < 10; i++) { - temp = rk[3]; - rk[4] = rk[0] ^ - TE421(temp) ^ TE432(temp) ^ TE443(temp) ^ TE414(temp) ^ - RCON(i); - rk[5] = rk[1] ^ rk[4]; - rk[6] = rk[2] ^ rk[5]; - rk[7] = rk[3] ^ rk[6]; - rk += 4; - } -} - -#ifndef CONFIG_NO_AES_DECRYPT -/** - * Expand the cipher key into the decryption key schedule. - * - * @return the number of rounds for the given cipher key size. - */ -void rijndaelKeySetupDec(u32 rk[/*44*/], const u8 cipherKey[]) -{ - int Nr = 10, i, j; - u32 temp; - - /* expand the cipher key: */ - rijndaelKeySetupEnc(rk, cipherKey); - /* invert the order of the round keys: */ - for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { - temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; - temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; - temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; - temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; - } - /* apply the inverse MixColumn transform to all round keys but the - * first and the last: */ - for (i = 1; i < Nr; i++) { - rk += 4; - for (j = 0; j < 4; j++) { - rk[j] = TD0_(TE4((rk[j] >> 24) )) ^ - TD1_(TE4((rk[j] >> 16) & 0xff)) ^ - TD2_(TE4((rk[j] >> 8) & 0xff)) ^ - TD3_(TE4((rk[j] ) & 0xff)); - } - } -} -#endif /* CONFIG_NO_AES_DECRYPT */ - -#ifndef CONFIG_NO_AES_ENCRYPT -void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16]) -{ - u32 s0, s1, s2, s3, t0, t1, t2, t3; - const int Nr = 10; -#ifndef FULL_UNROLL - int r; -#endif /* ?FULL_UNROLL */ - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(pt ) ^ rk[0]; - s1 = GETU32(pt + 4) ^ rk[1]; - s2 = GETU32(pt + 8) ^ rk[2]; - s3 = GETU32(pt + 12) ^ rk[3]; - -#define ROUND(i,d,s) \ -d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \ -d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \ -d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \ -d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3] - -#ifdef FULL_UNROLL - - ROUND(1,t,s); - ROUND(2,s,t); - ROUND(3,t,s); - ROUND(4,s,t); - ROUND(5,t,s); - ROUND(6,s,t); - ROUND(7,t,s); - ROUND(8,s,t); - ROUND(9,t,s); - - rk += Nr << 2; - -#else /* !FULL_UNROLL */ - - /* Nr - 1 full rounds: */ - r = Nr >> 1; - for (;;) { - ROUND(1,t,s); - rk += 8; - if (--r == 0) - break; - ROUND(0,s,t); - } - -#endif /* ?FULL_UNROLL */ - -#undef ROUND - - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0]; - PUTU32(ct , s0); - s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1]; - PUTU32(ct + 4, s1); - s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2]; - PUTU32(ct + 8, s2); - s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3]; - PUTU32(ct + 12, s3); -} -#endif /* CONFIG_NO_AES_ENCRYPT */ - -void rijndaelDecrypt(const u32 rk[/*44*/], const u8 ct[16], u8 pt[16]) -{ - u32 s0, s1, s2, s3, t0, t1, t2, t3; - const int Nr = 10; -#ifndef FULL_UNROLL - int r; -#endif /* ?FULL_UNROLL */ - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(ct ) ^ rk[0]; - s1 = GETU32(ct + 4) ^ rk[1]; - s2 = GETU32(ct + 8) ^ rk[2]; - s3 = GETU32(ct + 12) ^ rk[3]; - -#define ROUND(i,d,s) \ -d##0 = TD0(s##0) ^ TD1(s##3) ^ TD2(s##2) ^ TD3(s##1) ^ rk[4 * i]; \ -d##1 = TD0(s##1) ^ TD1(s##0) ^ TD2(s##3) ^ TD3(s##2) ^ rk[4 * i + 1]; \ -d##2 = TD0(s##2) ^ TD1(s##1) ^ TD2(s##0) ^ TD3(s##3) ^ rk[4 * i + 2]; \ -d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3] - -#ifdef FULL_UNROLL - - ROUND(1,t,s); - ROUND(2,s,t); - ROUND(3,t,s); - ROUND(4,s,t); - ROUND(5,t,s); - ROUND(6,s,t); - ROUND(7,t,s); - ROUND(8,s,t); - ROUND(9,t,s); - - rk += Nr << 2; - -#else /* !FULL_UNROLL */ - - /* Nr - 1 full rounds: */ - r = Nr >> 1; - for (;;) { - ROUND(1,t,s); - rk += 8; - if (--r == 0) - break; - ROUND(0,s,t); - } - -#endif /* ?FULL_UNROLL */ - -#undef ROUND - - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = TD41(t0) ^ TD42(t3) ^ TD43(t2) ^ TD44(t1) ^ rk[0]; - PUTU32(pt , s0); - s1 = TD41(t1) ^ TD42(t0) ^ TD43(t3) ^ TD44(t2) ^ rk[1]; - PUTU32(pt + 4, s1); - s2 = TD41(t2) ^ TD42(t1) ^ TD43(t0) ^ TD44(t3) ^ rk[2]; - PUTU32(pt + 8, s2); - s3 = TD41(t3) ^ TD42(t2) ^ TD43(t1) ^ TD44(t0) ^ rk[3]; - PUTU32(pt + 12, s3); -} - - - -/* Generic wrapper functions for AES functions */ - -#define AES_PRIV_SIZE (4 * 44) - -#ifndef CONFIG_NO_AES_ENCRYPT -void * aes_encrypt_init(const u8 *key, size_t len) -{ - u32 *rk; - if (len != 16) - return NULL; - rk = os_malloc(AES_PRIV_SIZE); - if (rk == NULL) - return NULL; - rijndaelKeySetupEnc(rk, key); - return rk; -} - - -void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) -{ - rijndaelEncrypt(ctx, plain, crypt); -} - - -void aes_encrypt_deinit(void *ctx) -{ - os_memset(ctx, 0, AES_PRIV_SIZE); - os_free(ctx); -} -#endif /* CONFIG_NO_AES_ENCRYPT */ - - -#ifndef CONFIG_NO_AES_DECRYPT -void * aes_decrypt_init(const u8 *key, size_t len) -{ - u32 *rk; - if (len != 16) - return NULL; - rk = os_malloc(AES_PRIV_SIZE); - if (rk == NULL) - return NULL; - rijndaelKeySetupDec(rk, key); - return rk; -} - - -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) -{ - rijndaelDecrypt(ctx, crypt, plain); -} - - -void aes_decrypt_deinit(void *ctx) -{ - os_memset(ctx, 0, AES_PRIV_SIZE); - os_free(ctx); -} -#endif /* CONFIG_NO_AES_DECRYPT */ - -#endif /* INTERNAL_AES */ diff --git a/contrib/hostapd/src/crypto/aes.h b/contrib/hostapd/src/crypto/aes.h deleted file mode 100644 index 6b9f4147af..0000000000 --- a/contrib/hostapd/src/crypto/aes.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * AES functions - * Copyright (c) 2003-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef AES_H -#define AES_H - -void * aes_encrypt_init(const u8 *key, size_t len); -void 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); -void aes_decrypt_deinit(void *ctx); - -#endif /* AES_H */ diff --git a/contrib/hostapd/src/crypto/aes_wrap.c b/contrib/hostapd/src/crypto/aes_wrap.c deleted file mode 100644 index b1448b0d9a..0000000000 --- a/contrib/hostapd/src/crypto/aes_wrap.c +++ /dev/null @@ -1,533 +0,0 @@ -/* - * AES-based functions - * - * - AES Key Wrap Algorithm (128-bit KEK) (RFC3394) - * - One-Key CBC MAC (OMAC1, i.e., CMAC) hash with AES-128 - * - AES-128 CTR mode encryption - * - AES-128 EAX mode encryption/decryption - * - AES-128 CBC - * - * Copyright (c) 2003-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "aes_wrap.h" -#include "crypto.h" - -#ifndef CONFIG_NO_AES_WRAP - -/** - * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) - * @kek: 16-octet Key encryption key (KEK) - * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 - * bytes - * @plain: Plaintext key to be wrapped, n * 64 bits - * @cipher: Wrapped key, (n + 1) * 64 bits - * Returns: 0 on success, -1 on failure - */ -int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher) -{ - u8 *a, *r, b[16]; - int i, j; - void *ctx; - - a = cipher; - r = cipher + 8; - - /* 1) Initialize variables. */ - os_memset(a, 0xa6, 8); - os_memcpy(r, plain, 8 * n); - - ctx = aes_encrypt_init(kek, 16); - if (ctx == NULL) - return -1; - - /* 2) Calculate intermediate values. - * For j = 0 to 5 - * For i=1 to n - * B = AES(K, A | R[i]) - * A = MSB(64, B) ^ t where t = (n*j)+i - * R[i] = LSB(64, B) - */ - for (j = 0; j <= 5; j++) { - r = cipher + 8; - for (i = 1; i <= n; i++) { - os_memcpy(b, a, 8); - os_memcpy(b + 8, r, 8); - aes_encrypt(ctx, b, b); - os_memcpy(a, b, 8); - a[7] ^= n * j + i; - os_memcpy(r, b + 8, 8); - r += 8; - } - } - aes_encrypt_deinit(ctx); - - /* 3) Output the results. - * - * These are already in @cipher due to the location of temporary - * variables. - */ - - return 0; -} - -#endif /* CONFIG_NO_AES_WRAP */ - - -#ifndef CONFIG_NO_AES_UNWRAP - -/** - * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) - * @kek: Key encryption key (KEK) - * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 - * bytes - * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits - * @plain: Plaintext key, n * 64 bits - * Returns: 0 on success, -1 on failure (e.g., integrity verification failed) - */ -int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain) -{ - u8 a[8], *r, b[16]; - int i, j; - void *ctx; - - /* 1) Initialize variables. */ - os_memcpy(a, cipher, 8); - r = plain; - os_memcpy(r, cipher + 8, 8 * n); - - ctx = aes_decrypt_init(kek, 16); - if (ctx == NULL) - return -1; - - /* 2) Compute intermediate values. - * For j = 5 to 0 - * For i = n to 1 - * B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i - * A = MSB(64, B) - * R[i] = LSB(64, B) - */ - for (j = 5; j >= 0; j--) { - r = plain + (n - 1) * 8; - for (i = n; i >= 1; i--) { - os_memcpy(b, a, 8); - b[7] ^= n * j + i; - - os_memcpy(b + 8, r, 8); - aes_decrypt(ctx, b, b); - os_memcpy(a, b, 8); - os_memcpy(r, b + 8, 8); - r -= 8; - } - } - aes_decrypt_deinit(ctx); - - /* 3) Output results. - * - * These are already in @plain due to the location of temporary - * variables. Just verify that the IV matches with the expected value. - */ - for (i = 0; i < 8; i++) { - if (a[i] != 0xa6) - return -1; - } - - return 0; -} - -#endif /* CONFIG_NO_AES_UNWRAP */ - - -#define BLOCK_SIZE 16 - -#ifndef CONFIG_NO_AES_OMAC1 - -static void gf_mulx(u8 *pad) -{ - int i, carry; - - carry = pad[0] & 0x80; - for (i = 0; i < BLOCK_SIZE - 1; i++) - pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); - pad[BLOCK_SIZE - 1] <<= 1; - if (carry) - pad[BLOCK_SIZE - 1] ^= 0x87; -} - - -/** - * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128 - * @key: 128-bit key for the hash operation - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) - * Returns: 0 on success, -1 on failure - * - * This is a mode for using block cipher (AES in this case) for authentication. - * OMAC1 was standardized with the name CMAC by NIST in a Special Publication - * (SP) 800-38B. - */ -int omac1_aes_128_vector(const u8 *key, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac) -{ - void *ctx; - u8 cbc[BLOCK_SIZE], pad[BLOCK_SIZE]; - const u8 *pos, *end; - size_t i, e, left, total_len; - - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - os_memset(cbc, 0, BLOCK_SIZE); - - total_len = 0; - for (e = 0; e < num_elem; e++) - total_len += len[e]; - left = total_len; - - e = 0; - pos = addr[0]; - end = pos + len[0]; - - while (left >= BLOCK_SIZE) { - for (i = 0; i < BLOCK_SIZE; i++) { - cbc[i] ^= *pos++; - if (pos >= end) { - e++; - pos = addr[e]; - end = pos + len[e]; - } - } - if (left > BLOCK_SIZE) - aes_encrypt(ctx, cbc, cbc); - left -= BLOCK_SIZE; - } - - os_memset(pad, 0, BLOCK_SIZE); - aes_encrypt(ctx, pad, pad); - gf_mulx(pad); - - if (left || total_len == 0) { - for (i = 0; i < left; i++) { - cbc[i] ^= *pos++; - if (pos >= end) { - e++; - pos = addr[e]; - end = pos + len[e]; - } - } - cbc[left] ^= 0x80; - gf_mulx(pad); - } - - for (i = 0; i < BLOCK_SIZE; i++) - pad[i] ^= cbc[i]; - aes_encrypt(ctx, pad, mac); - aes_encrypt_deinit(ctx); - return 0; -} - - -/** - * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC) - * @key: 128-bit key for the hash operation - * @data: Data buffer for which a MAC is determined - * @data_len: Length of data buffer in bytes - * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) - * Returns: 0 on success, -1 on failure - * - * This is a mode for using block cipher (AES in this case) for authentication. - * OMAC1 was standardized with the name CMAC by NIST in a Special Publication - * (SP) 800-38B. - */ -int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) -{ - return omac1_aes_128_vector(key, 1, &data, &data_len, mac); -} - -#endif /* CONFIG_NO_AES_OMAC1 */ - - -#ifndef CONFIG_NO_AES_ENCRYPT_BLOCK -/** - * aes_128_encrypt_block - Perform one AES 128-bit block operation - * @key: Key for AES - * @in: Input data (16 bytes) - * @out: Output of the AES block operation (16 bytes) - * Returns: 0 on success, -1 on failure - */ -int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out) -{ - void *ctx; - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - aes_encrypt(ctx, in, out); - aes_encrypt_deinit(ctx); - return 0; -} -#endif /* CONFIG_NO_AES_ENCRYPT_BLOCK */ - - -#ifndef CONFIG_NO_AES_CTR - -/** - * aes_128_ctr_encrypt - AES-128 CTR mode encryption - * @key: Key for encryption (16 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) -{ - void *ctx; - size_t j, len, left = data_len; - int i; - u8 *pos = data; - u8 counter[BLOCK_SIZE], buf[BLOCK_SIZE]; - - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - os_memcpy(counter, nonce, BLOCK_SIZE); - - while (left > 0) { - aes_encrypt(ctx, counter, buf); - - len = (left < BLOCK_SIZE) ? left : BLOCK_SIZE; - for (j = 0; j < len; j++) - pos[j] ^= buf[j]; - pos += len; - left -= len; - - for (i = BLOCK_SIZE - 1; i >= 0; i--) { - counter[i]++; - if (counter[i]) - break; - } - } - aes_encrypt_deinit(ctx); - return 0; -} - -#endif /* CONFIG_NO_AES_CTR */ - - -#ifndef CONFIG_NO_AES_EAX - -/** - * aes_128_eax_encrypt - AES-128 EAX mode encryption - * @key: Key for encryption (16 bytes) - * @nonce: Nonce for counter mode - * @nonce_len: Nonce length in bytes - * @hdr: Header data to be authenticity protected - * @hdr_len: Length of the header data bytes - * @data: Data to encrypt in-place - * @data_len: Length of data in bytes - * @tag: 16-byte tag value - * Returns: 0 on success, -1 on failure - */ -int aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len, - const u8 *hdr, size_t hdr_len, - u8 *data, size_t data_len, u8 *tag) -{ - u8 *buf; - size_t buf_len; - u8 nonce_mac[BLOCK_SIZE], hdr_mac[BLOCK_SIZE], data_mac[BLOCK_SIZE]; - int i, ret = -1; - - if (nonce_len > data_len) - buf_len = nonce_len; - else - buf_len = data_len; - if (hdr_len > buf_len) - buf_len = hdr_len; - buf_len += 16; - - buf = os_malloc(buf_len); - if (buf == NULL) - return -1; - - os_memset(buf, 0, 15); - - buf[15] = 0; - os_memcpy(buf + 16, nonce, nonce_len); - if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) - goto fail; - - buf[15] = 1; - os_memcpy(buf + 16, hdr, hdr_len); - if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) - goto fail; - - if (aes_128_ctr_encrypt(key, nonce_mac, data, data_len)) - goto fail; - buf[15] = 2; - os_memcpy(buf + 16, data, data_len); - if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) - goto fail; - - for (i = 0; i < BLOCK_SIZE; i++) - tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i]; - - ret = 0; -fail: - os_free(buf); - - return ret; -} - - -/** - * aes_128_eax_decrypt - AES-128 EAX mode decryption - * @key: Key for decryption (16 bytes) - * @nonce: Nonce for counter mode - * @nonce_len: Nonce length in bytes - * @hdr: Header data to be authenticity protected - * @hdr_len: Length of the header data bytes - * @data: Data to encrypt in-place - * @data_len: Length of data in bytes - * @tag: 16-byte tag value - * Returns: 0 on success, -1 on failure, -2 if tag does not match - */ -int aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len, - const u8 *hdr, size_t hdr_len, - u8 *data, size_t data_len, const u8 *tag) -{ - u8 *buf; - size_t buf_len; - u8 nonce_mac[BLOCK_SIZE], hdr_mac[BLOCK_SIZE], data_mac[BLOCK_SIZE]; - int i; - - if (nonce_len > data_len) - buf_len = nonce_len; - else - buf_len = data_len; - if (hdr_len > buf_len) - buf_len = hdr_len; - buf_len += 16; - - buf = os_malloc(buf_len); - if (buf == NULL) - return -1; - - os_memset(buf, 0, 15); - - buf[15] = 0; - os_memcpy(buf + 16, nonce, nonce_len); - if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) { - os_free(buf); - return -1; - } - - buf[15] = 1; - os_memcpy(buf + 16, hdr, hdr_len); - if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) { - os_free(buf); - return -1; - } - - buf[15] = 2; - os_memcpy(buf + 16, data, data_len); - if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) { - os_free(buf); - return -1; - } - - os_free(buf); - - for (i = 0; i < BLOCK_SIZE; i++) { - if (tag[i] != (nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i])) - return -2; - } - - return aes_128_ctr_encrypt(key, nonce_mac, data, data_len); -} - -#endif /* CONFIG_NO_AES_EAX */ - - -#ifndef CONFIG_NO_AES_CBC - -/** - * aes_128_cbc_encrypt - AES-128 CBC encryption - * @key: Encryption key - * @iv: Encryption IV for CBC mode (16 bytes) - * @data: Data to encrypt in-place - * @data_len: Length of data in bytes (must be divisible by 16) - * Returns: 0 on success, -1 on failure - */ -int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) -{ - void *ctx; - u8 cbc[BLOCK_SIZE]; - u8 *pos = data; - int i, j, blocks; - - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - os_memcpy(cbc, iv, BLOCK_SIZE); - - blocks = data_len / BLOCK_SIZE; - for (i = 0; i < blocks; i++) { - for (j = 0; j < BLOCK_SIZE; j++) - cbc[j] ^= pos[j]; - aes_encrypt(ctx, cbc, cbc); - os_memcpy(pos, cbc, BLOCK_SIZE); - pos += BLOCK_SIZE; - } - aes_encrypt_deinit(ctx); - return 0; -} - - -/** - * aes_128_cbc_decrypt - AES-128 CBC decryption - * @key: Decryption key - * @iv: Decryption IV for CBC mode (16 bytes) - * @data: Data to decrypt in-place - * @data_len: Length of data in bytes (must be divisible by 16) - * Returns: 0 on success, -1 on failure - */ -int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) -{ - void *ctx; - u8 cbc[BLOCK_SIZE], tmp[BLOCK_SIZE]; - u8 *pos = data; - int i, j, blocks; - - ctx = aes_decrypt_init(key, 16); - if (ctx == NULL) - return -1; - os_memcpy(cbc, iv, BLOCK_SIZE); - - blocks = data_len / BLOCK_SIZE; - for (i = 0; i < blocks; i++) { - os_memcpy(tmp, pos, BLOCK_SIZE); - aes_decrypt(ctx, pos, pos); - for (j = 0; j < BLOCK_SIZE; j++) - pos[j] ^= cbc[j]; - os_memcpy(cbc, tmp, BLOCK_SIZE); - pos += BLOCK_SIZE; - } - aes_decrypt_deinit(ctx); - return 0; -} - -#endif /* CONFIG_NO_AES_CBC */ diff --git a/contrib/hostapd/src/crypto/aes_wrap.h b/contrib/hostapd/src/crypto/aes_wrap.h deleted file mode 100644 index 4b1c7b083b..0000000000 --- a/contrib/hostapd/src/crypto/aes_wrap.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * AES-based functions - * - * - AES Key Wrap Algorithm (128-bit KEK) (RFC3394) - * - One-Key CBC MAC (OMAC1) hash with AES-128 - * - AES-128 CTR mode encryption - * - AES-128 EAX mode encryption/decryption - * - AES-128 CBC - * - * Copyright (c) 2003-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef AES_WRAP_H -#define AES_WRAP_H - -int __must_check aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher); -int __must_check aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain); -int __must_check omac1_aes_128_vector(const u8 *key, size_t num_elem, - const u8 *addr[], const size_t *len, - u8 *mac); -int __must_check omac1_aes_128(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_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, - const u8 *nonce, size_t nonce_len, - const u8 *hdr, size_t hdr_len, - u8 *data, size_t data_len, u8 *tag); -int __must_check aes_128_eax_decrypt(const u8 *key, - const u8 *nonce, size_t nonce_len, - const u8 *hdr, size_t hdr_len, - u8 *data, size_t data_len, const u8 *tag); -int __must_check aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, - size_t data_len); -int __must_check aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, - size_t data_len); - -#endif /* AES_WRAP_H */ diff --git a/contrib/hostapd/src/crypto/crypto.h b/contrib/hostapd/src/crypto/crypto.h deleted file mode 100644 index a5129bbd05..0000000000 --- a/contrib/hostapd/src/crypto/crypto.h +++ /dev/null @@ -1,431 +0,0 @@ -/* - * WPA Supplicant / wrapper functions for crypto libraries - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file defines the cryptographic functions that need to be implemented - * for wpa_supplicant and hostapd. When TLS is not used, internal - * implementation of MD5, SHA1, and AES is used and no external libraries are - * required. When TLS is enabled (e.g., by enabling EAP-TLS or EAP-PEAP), the - * crypto library used by the TLS implementation is expected to be used for - * non-TLS needs, too, in order to save space by not implementing these - * functions twice. - * - * Wrapper code for using each crypto library is in its own file (crypto*.c) - * and one of these files is build and linked in to provide the functions - * defined here. - */ - -#ifndef CRYPTO_H -#define CRYPTO_H - -/** - * md4_vector - MD4 hash for data vector - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash - */ -void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); - -/** - * md5_vector - MD5 hash for data vector - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash - */ -void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); - -/** - * sha1_vector - SHA-1 hash for data vector - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash - */ -void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, - u8 *mac); - -/** - * fips186_2-prf - NIST FIPS Publication 186-2 change notice 1 PRF - * @seed: Seed/key for the PRF - * @seed_len: Seed length in bytes - * @x: Buffer for PRF output - * @xlen: Output length in bytes - * Returns: 0 on success, -1 on failure - * - * This function implements random number generation specified in NIST FIPS - * Publication 186-2 for EAP-SIM. This PRF uses a function that is similar to - * SHA-1, but has different message padding. - */ -int __must_check fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, - size_t xlen); - -/** - * sha256_vector - SHA256 hash for data vector - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash - */ -void sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, - u8 *mac); - -/** - * des_encrypt - Encrypt one block with DES - * @clear: 8 octets (in) - * @key: 7 octets (in) (no parity bits included) - * @cypher: 8 octets (out) - */ -void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher); - -/** - * aes_encrypt_init - Initialize AES for encryption - * @key: Encryption key - * @len: Key length in bytes (usually 16, i.e., 128 bits) - * Returns: Pointer to context data or %NULL on failure - */ -void * aes_encrypt_init(const u8 *key, size_t len); - -/** - * aes_encrypt - Encrypt one AES block - * @ctx: Context pointer from aes_encrypt_init() - * @plain: Plaintext data to be encrypted (16 bytes) - * @crypt: Buffer for the encrypted data (16 bytes) - */ -void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt); - -/** - * aes_encrypt_deinit - Deinitialize AES encryption - * @ctx: Context pointer from aes_encrypt_init() - */ -void aes_encrypt_deinit(void *ctx); - -/** - * aes_decrypt_init - Initialize AES for decryption - * @key: Decryption key - * @len: Key length in bytes (usually 16, i.e., 128 bits) - * Returns: Pointer to context data or %NULL on failure - */ -void * aes_decrypt_init(const u8 *key, size_t len); - -/** - * aes_decrypt - Decrypt one AES block - * @ctx: Context pointer from aes_encrypt_init() - * @crypt: Encrypted data (16 bytes) - * @plain: Buffer for the decrypted data (16 bytes) - */ -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain); - -/** - * aes_decrypt_deinit - Deinitialize AES decryption - * @ctx: Context pointer from aes_encrypt_init() - */ -void aes_decrypt_deinit(void *ctx); - - -enum crypto_hash_alg { - CRYPTO_HASH_ALG_MD5, CRYPTO_HASH_ALG_SHA1, - CRYPTO_HASH_ALG_HMAC_MD5, CRYPTO_HASH_ALG_HMAC_SHA1 -}; - -struct crypto_hash; - -/** - * crypto_hash_init - Initialize hash/HMAC function - * @alg: Hash algorithm - * @key: Key for keyed hash (e.g., HMAC) or %NULL if not needed - * @key_len: Length of the key in bytes - * Returns: Pointer to hash context to use with other hash functions or %NULL - * on failure - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, - size_t key_len); - -/** - * crypto_hash_update - Add data to hash calculation - * @ctx: Context pointer from crypto_hash_init() - * @data: Data buffer to add - * @len: Length of the buffer - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len); - -/** - * crypto_hash_finish - Complete hash calculation - * @ctx: Context pointer from crypto_hash_init() - * @hash: Buffer for hash value or %NULL if caller is just freeing the hash - * context - * @len: Pointer to length of the buffer or %NULL if caller is just freeing the - * hash context; on return, this is set to the actual length of the hash value - * Returns: 0 on success, -1 if buffer is too small (len set to needed length), - * or -2 on other failures (including failed crypto_hash_update() operations) - * - * This function calculates the hash value and frees the context buffer that - * was used for hash calculation. - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -int crypto_hash_finish(struct crypto_hash *ctx, u8 *hash, size_t *len); - - -enum crypto_cipher_alg { - CRYPTO_CIPHER_NULL = 0, CRYPTO_CIPHER_ALG_AES, CRYPTO_CIPHER_ALG_3DES, - CRYPTO_CIPHER_ALG_DES, CRYPTO_CIPHER_ALG_RC2, CRYPTO_CIPHER_ALG_RC4 -}; - -struct crypto_cipher; - -/** - * crypto_cipher_init - Initialize block/stream cipher function - * @alg: Cipher algorithm - * @iv: Initialization vector for block ciphers or %NULL for stream ciphers - * @key: Cipher key - * @key_len: Length of key in bytes - * Returns: Pointer to cipher context to use with other cipher functions or - * %NULL on failure - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, - const u8 *iv, const u8 *key, - size_t key_len); - -/** - * crypto_cipher_encrypt - Cipher encrypt - * @ctx: Context pointer from crypto_cipher_init() - * @plain: Plaintext to cipher - * @crypt: Resulting ciphertext - * @len: Length of the plaintext - * Returns: 0 on success, -1 on failure - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -int __must_check crypto_cipher_encrypt(struct crypto_cipher *ctx, - const u8 *plain, u8 *crypt, size_t len); - -/** - * crypto_cipher_decrypt - Cipher decrypt - * @ctx: Context pointer from crypto_cipher_init() - * @crypt: Ciphertext to decrypt - * @plain: Resulting plaintext - * @len: Length of the cipher text - * Returns: 0 on success, -1 on failure - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -int __must_check crypto_cipher_decrypt(struct crypto_cipher *ctx, - const u8 *crypt, u8 *plain, size_t len); - -/** - * crypto_cipher_decrypt - Free cipher context - * @ctx: Context pointer from crypto_cipher_init() - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -void crypto_cipher_deinit(struct crypto_cipher *ctx); - - -struct crypto_public_key; -struct crypto_private_key; - -/** - * crypto_public_key_import - Import an RSA public key - * @key: Key buffer (DER encoded RSA public key) - * @len: Key buffer length in bytes - * Returns: Pointer to the public key or %NULL on failure - * - * This function can just return %NULL if the crypto library supports X.509 - * parsing. In that case, crypto_public_key_from_cert() is used to import the - * public key from a certificate. - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len); - -/** - * crypto_private_key_import - Import an RSA private key - * @key: Key buffer (DER encoded RSA private key) - * @len: Key buffer length in bytes - * Returns: Pointer to the private key or %NULL on failure - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -struct crypto_private_key * crypto_private_key_import(const u8 *key, - size_t len); - -/** - * crypto_public_key_from_cert - Import an RSA public key from a certificate - * @buf: DER encoded X.509 certificate - * @len: Certificate buffer length in bytes - * Returns: Pointer to public key or %NULL on failure - * - * This function can just return %NULL if the crypto library does not support - * X.509 parsing. In that case, internal code will be used to parse the - * certificate and public key is imported using crypto_public_key_import(). - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, - size_t len); - -/** - * crypto_public_key_encrypt_pkcs1_v15 - Public key encryption (PKCS #1 v1.5) - * @key: Public key - * @in: Plaintext buffer - * @inlen: Length of plaintext buffer in bytes - * @out: Output buffer for encrypted data - * @outlen: Length of output buffer in bytes; set to used length on success - * Returns: 0 on success, -1 on failure - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -int __must_check crypto_public_key_encrypt_pkcs1_v15( - struct crypto_public_key *key, const u8 *in, size_t inlen, - u8 *out, size_t *outlen); - -/** - * crypto_private_key_decrypt_pkcs1_v15 - Private key decryption (PKCS #1 v1.5) - * @key: Private key - * @in: Encrypted buffer - * @inlen: Length of encrypted buffer in bytes - * @out: Output buffer for encrypted data - * @outlen: Length of output buffer in bytes; set to used length on success - * Returns: 0 on success, -1 on failure - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -int __must_check crypto_private_key_decrypt_pkcs1_v15( - struct crypto_private_key *key, const u8 *in, size_t inlen, - u8 *out, size_t *outlen); - -/** - * crypto_private_key_sign_pkcs1 - Sign with private key (PKCS #1) - * @key: Private key from crypto_private_key_import() - * @in: Plaintext buffer - * @inlen: Length of plaintext buffer in bytes - * @out: Output buffer for encrypted (signed) data - * @outlen: Length of output buffer in bytes; set to used length on success - * Returns: 0 on success, -1 on failure - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -int __must_check crypto_private_key_sign_pkcs1(struct crypto_private_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen); - -/** - * crypto_public_key_free - Free public key - * @key: Public key - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -void crypto_public_key_free(struct crypto_public_key *key); - -/** - * crypto_private_key_free - Free private key - * @key: Private key from crypto_private_key_import() - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -void crypto_private_key_free(struct crypto_private_key *key); - -/** - * crypto_public_key_decrypt_pkcs1 - Decrypt PKCS #1 signature - * @key: Public key - * @crypt: Encrypted signature data (using the private key) - * @crypt_len: Encrypted signature data length - * @plain: Buffer for plaintext (at least crypt_len bytes) - * @plain_len: Plaintext length (max buffer size on input, real len on output); - * Returns: 0 on success, -1 on failure - */ -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); - -/** - * crypto_global_init - Initialize crypto wrapper - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -int __must_check crypto_global_init(void); - -/** - * crypto_global_deinit - Deinitialize crypto wrapper - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -void crypto_global_deinit(void); - -/** - * crypto_mod_exp - Modular exponentiation of large integers - * @base: Base integer (big endian byte array) - * @base_len: Length of base integer in bytes - * @power: Power integer (big endian byte array) - * @power_len: Length of power integer in bytes - * @modulus: Modulus integer (big endian byte array) - * @modulus_len: Length of modulus integer in bytes - * @result: Buffer for the result - * @result_len: Result length (max buffer size on input, real len on output) - * Returns: 0 on success, -1 on failure - * - * This function calculates result = base ^ power mod modulus. modules_len is - * used as the maximum size of modulus buffer. It is set to the used size on - * success. - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -int __must_check crypto_mod_exp(const u8 *base, size_t base_len, - const u8 *power, size_t power_len, - const u8 *modulus, size_t modulus_len, - u8 *result, size_t *result_len); - -#endif /* CRYPTO_H */ diff --git a/contrib/hostapd/src/crypto/crypto_cryptoapi.c b/contrib/hostapd/src/crypto/crypto_cryptoapi.c deleted file mode 100644 index 45333dd2e3..0000000000 --- a/contrib/hostapd/src/crypto/crypto_cryptoapi.c +++ /dev/null @@ -1,786 +0,0 @@ -/* - * Crypto wrapper for Microsoft CryptoAPI - * Copyright (c) 2005-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include - -#include "common.h" -#include "crypto.h" - -#ifndef MS_ENH_RSA_AES_PROV -#ifdef UNICODE -#define MS_ENH_RSA_AES_PROV \ -L"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)" -#else -#define MS_ENH_RSA_AES_PROV \ -"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)" -#endif -#endif /* MS_ENH_RSA_AES_PROV */ - -#ifndef CALG_HMAC -#define CALG_HMAC (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC) -#endif - -#ifdef CONFIG_TLS_INTERNAL -#ifdef __MINGW32_VERSION -/* - * MinGW does not yet include all the needed definitions for CryptoAPI, so - * define here whatever extra is needed. - */ - -static BOOL WINAPI -(*CryptImportPublicKeyInfo)(HCRYPTPROV hCryptProv, DWORD dwCertEncodingType, - PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey) -= NULL; /* to be loaded from crypt32.dll */ - - -static int mingw_load_crypto_func(void) -{ - HINSTANCE dll; - - /* MinGW does not yet have full CryptoAPI support, so load the needed - * function here. */ - - if (CryptImportPublicKeyInfo) - return 0; - - dll = LoadLibrary("crypt32"); - if (dll == NULL) { - wpa_printf(MSG_DEBUG, "CryptoAPI: Could not load crypt32 " - "library"); - return -1; - } - - CryptImportPublicKeyInfo = GetProcAddress( - dll, "CryptImportPublicKeyInfo"); - if (CryptImportPublicKeyInfo == NULL) { - wpa_printf(MSG_DEBUG, "CryptoAPI: Could not get " - "CryptImportPublicKeyInfo() address from " - "crypt32 library"); - return -1; - } - - return 0; -} - -#else /* __MINGW32_VERSION */ - -static int mingw_load_crypto_func(void) -{ - return 0; -} - -#endif /* __MINGW32_VERSION */ -#endif /* CONFIG_TLS_INTERNAL */ - - -static void cryptoapi_report_error(const char *msg) -{ - char *s, *pos; - DWORD err = GetLastError(); - - if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, err, 0, (LPTSTR) &s, 0, NULL) == 0) { - wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d", msg, (int) err); - } - - pos = s; - while (*pos) { - if (*pos == '\n' || *pos == '\r') { - *pos = '\0'; - break; - } - pos++; - } - - wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d: (%s)", msg, (int) err, s); - LocalFree(s); -} - - -int cryptoapi_hash_vector(ALG_ID alg, size_t hash_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac) -{ - HCRYPTPROV prov; - HCRYPTHASH hash; - size_t i; - DWORD hlen; - int ret = 0; - - if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, 0)) { - cryptoapi_report_error("CryptAcquireContext"); - return -1; - } - - if (!CryptCreateHash(prov, alg, 0, 0, &hash)) { - cryptoapi_report_error("CryptCreateHash"); - CryptReleaseContext(prov, 0); - return -1; - } - - for (i = 0; i < num_elem; i++) { - if (!CryptHashData(hash, (BYTE *) addr[i], len[i], 0)) { - cryptoapi_report_error("CryptHashData"); - CryptDestroyHash(hash); - CryptReleaseContext(prov, 0); - } - } - - hlen = hash_len; - if (!CryptGetHashParam(hash, HP_HASHVAL, mac, &hlen, 0)) { - cryptoapi_report_error("CryptGetHashParam"); - ret = -1; - } - - CryptDestroyHash(hash); - CryptReleaseContext(prov, 0); - - return ret; -} - - -void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - cryptoapi_hash_vector(CALG_MD4, 16, num_elem, addr, len, mac); -} - - -void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) -{ - u8 next, tmp; - int i; - HCRYPTPROV prov; - HCRYPTKEY ckey; - DWORD dlen; - struct { - BLOBHEADER hdr; - DWORD len; - BYTE key[8]; - } key_blob; - DWORD mode = CRYPT_MODE_ECB; - - key_blob.hdr.bType = PLAINTEXTKEYBLOB; - key_blob.hdr.bVersion = CUR_BLOB_VERSION; - key_blob.hdr.reserved = 0; - key_blob.hdr.aiKeyAlg = CALG_DES; - key_blob.len = 8; - - /* Add parity bits to the key */ - next = 0; - for (i = 0; i < 7; i++) { - tmp = key[i]; - key_blob.key[i] = (tmp >> i) | next | 1; - next = tmp << (7 - i); - } - key_blob.key[i] = next | 1; - - if (!CryptAcquireContext(&prov, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: " - "%d", (int) GetLastError()); - return; - } - - if (!CryptImportKey(prov, (BYTE *) &key_blob, sizeof(key_blob), 0, 0, - &ckey)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d", - (int) GetLastError()); - CryptReleaseContext(prov, 0); - return; - } - - if (!CryptSetKeyParam(ckey, KP_MODE, (BYTE *) &mode, 0)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) " - "failed: %d", (int) GetLastError()); - CryptDestroyKey(ckey); - CryptReleaseContext(prov, 0); - return; - } - - os_memcpy(cypher, clear, 8); - dlen = 8; - if (!CryptEncrypt(ckey, 0, FALSE, 0, cypher, &dlen, 8)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d", - (int) GetLastError()); - os_memset(cypher, 0, 8); - } - - CryptDestroyKey(ckey); - CryptReleaseContext(prov, 0); -} - - -#ifdef EAP_TLS_FUNCS -void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac); -} - - -void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - cryptoapi_hash_vector(CALG_SHA, 20, num_elem, addr, len, mac); -} - - -struct aes_context { - HCRYPTPROV prov; - HCRYPTKEY ckey; -}; - - -void * aes_encrypt_init(const u8 *key, size_t len) -{ - struct aes_context *akey; - struct { - BLOBHEADER hdr; - DWORD len; - BYTE key[16]; - } key_blob; - DWORD mode = CRYPT_MODE_ECB; - - if (len != 16) - return NULL; - - key_blob.hdr.bType = PLAINTEXTKEYBLOB; - key_blob.hdr.bVersion = CUR_BLOB_VERSION; - key_blob.hdr.reserved = 0; - key_blob.hdr.aiKeyAlg = CALG_AES_128; - key_blob.len = len; - os_memcpy(key_blob.key, key, len); - - akey = os_zalloc(sizeof(*akey)); - if (akey == NULL) - return NULL; - - if (!CryptAcquireContext(&akey->prov, NULL, - MS_ENH_RSA_AES_PROV, PROV_RSA_AES, - CRYPT_VERIFYCONTEXT)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: " - "%d", (int) GetLastError()); - os_free(akey); - return NULL; - } - - if (!CryptImportKey(akey->prov, (BYTE *) &key_blob, sizeof(key_blob), - 0, 0, &akey->ckey)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d", - (int) GetLastError()); - CryptReleaseContext(akey->prov, 0); - os_free(akey); - return NULL; - } - - if (!CryptSetKeyParam(akey->ckey, KP_MODE, (BYTE *) &mode, 0)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) " - "failed: %d", (int) GetLastError()); - CryptDestroyKey(akey->ckey); - CryptReleaseContext(akey->prov, 0); - os_free(akey); - return NULL; - } - - return akey; -} - - -void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) -{ - struct aes_context *akey = ctx; - DWORD dlen; - - os_memcpy(crypt, plain, 16); - dlen = 16; - if (!CryptEncrypt(akey->ckey, 0, FALSE, 0, crypt, &dlen, 16)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d", - (int) GetLastError()); - os_memset(crypt, 0, 16); - } -} - - -void aes_encrypt_deinit(void *ctx) -{ - struct aes_context *akey = ctx; - if (akey) { - CryptDestroyKey(akey->ckey); - CryptReleaseContext(akey->prov, 0); - os_free(akey); - } -} - - -void * aes_decrypt_init(const u8 *key, size_t len) -{ - return aes_encrypt_init(key, len); -} - - -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) -{ - struct aes_context *akey = ctx; - DWORD dlen; - - os_memcpy(plain, crypt, 16); - dlen = 16; - - if (!CryptDecrypt(akey->ckey, 0, FALSE, 0, plain, &dlen)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: CryptDecrypt failed: %d", - (int) GetLastError()); - } -} - - -void aes_decrypt_deinit(void *ctx) -{ - aes_encrypt_deinit(ctx); -} - -#ifdef CONFIG_TLS_INTERNAL - -struct crypto_hash { - enum crypto_hash_alg alg; - int error; - HCRYPTPROV prov; - HCRYPTHASH hash; - HCRYPTKEY key; -}; - -struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, - size_t key_len) -{ - struct crypto_hash *ctx; - ALG_ID calg; - struct { - BLOBHEADER hdr; - DWORD len; - BYTE key[32]; - } key_blob; - - os_memset(&key_blob, 0, sizeof(key_blob)); - switch (alg) { - case CRYPTO_HASH_ALG_MD5: - calg = CALG_MD5; - break; - case CRYPTO_HASH_ALG_SHA1: - calg = CALG_SHA; - break; - case CRYPTO_HASH_ALG_HMAC_MD5: - case CRYPTO_HASH_ALG_HMAC_SHA1: - calg = CALG_HMAC; - key_blob.hdr.bType = PLAINTEXTKEYBLOB; - key_blob.hdr.bVersion = CUR_BLOB_VERSION; - key_blob.hdr.reserved = 0; - /* - * Note: RC2 is not really used, but that can be used to - * import HMAC keys of up to 16 byte long. - * CRYPT_IPSEC_HMAC_KEY flag for CryptImportKey() is needed to - * be able to import longer keys (HMAC-SHA1 uses 20-byte key). - */ - key_blob.hdr.aiKeyAlg = CALG_RC2; - key_blob.len = key_len; - if (key_len > sizeof(key_blob.key)) - return NULL; - os_memcpy(key_blob.key, key, key_len); - break; - default: - return NULL; - } - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) - return NULL; - - ctx->alg = alg; - - if (!CryptAcquireContext(&ctx->prov, NULL, NULL, PROV_RSA_FULL, 0)) { - cryptoapi_report_error("CryptAcquireContext"); - os_free(ctx); - return NULL; - } - - if (calg == CALG_HMAC) { -#ifndef CRYPT_IPSEC_HMAC_KEY -#define CRYPT_IPSEC_HMAC_KEY 0x00000100 -#endif - if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob, - sizeof(key_blob), 0, CRYPT_IPSEC_HMAC_KEY, - &ctx->key)) { - cryptoapi_report_error("CryptImportKey"); - CryptReleaseContext(ctx->prov, 0); - os_free(ctx); - return NULL; - } - } - - if (!CryptCreateHash(ctx->prov, calg, ctx->key, 0, &ctx->hash)) { - cryptoapi_report_error("CryptCreateHash"); - CryptReleaseContext(ctx->prov, 0); - os_free(ctx); - return NULL; - } - - if (calg == CALG_HMAC) { - HMAC_INFO info; - os_memset(&info, 0, sizeof(info)); - switch (alg) { - case CRYPTO_HASH_ALG_HMAC_MD5: - info.HashAlgid = CALG_MD5; - break; - case CRYPTO_HASH_ALG_HMAC_SHA1: - info.HashAlgid = CALG_SHA; - break; - default: - /* unreachable */ - break; - } - - if (!CryptSetHashParam(ctx->hash, HP_HMAC_INFO, (BYTE *) &info, - 0)) { - cryptoapi_report_error("CryptSetHashParam"); - CryptDestroyHash(ctx->hash); - CryptReleaseContext(ctx->prov, 0); - os_free(ctx); - return NULL; - } - } - - return ctx; -} - - -void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) -{ - if (ctx == NULL || ctx->error) - return; - - if (!CryptHashData(ctx->hash, (BYTE *) data, len, 0)) { - cryptoapi_report_error("CryptHashData"); - ctx->error = 1; - } -} - - -int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) -{ - int ret = 0; - DWORD hlen; - - if (ctx == NULL) - return -2; - - if (mac == NULL || len == NULL) - goto done; - - if (ctx->error) { - ret = -2; - goto done; - } - - hlen = *len; - if (!CryptGetHashParam(ctx->hash, HP_HASHVAL, mac, &hlen, 0)) { - cryptoapi_report_error("CryptGetHashParam"); - ret = -2; - } - *len = hlen; - -done: - if (ctx->alg == CRYPTO_HASH_ALG_HMAC_SHA1 || - ctx->alg == CRYPTO_HASH_ALG_HMAC_MD5) - CryptDestroyKey(ctx->key); - - os_free(ctx); - - return ret; -} - - -struct crypto_cipher { - HCRYPTPROV prov; - HCRYPTKEY key; -}; - - -struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, - const u8 *iv, const u8 *key, - size_t key_len) -{ - struct crypto_cipher *ctx; - struct { - BLOBHEADER hdr; - DWORD len; - BYTE key[32]; - } key_blob; - DWORD mode = CRYPT_MODE_CBC; - - key_blob.hdr.bType = PLAINTEXTKEYBLOB; - key_blob.hdr.bVersion = CUR_BLOB_VERSION; - key_blob.hdr.reserved = 0; - key_blob.len = key_len; - if (key_len > sizeof(key_blob.key)) - return NULL; - os_memcpy(key_blob.key, key, key_len); - - switch (alg) { - case CRYPTO_CIPHER_ALG_AES: - if (key_len == 32) - key_blob.hdr.aiKeyAlg = CALG_AES_256; - else if (key_len == 24) - key_blob.hdr.aiKeyAlg = CALG_AES_192; - else - key_blob.hdr.aiKeyAlg = CALG_AES_128; - break; - case CRYPTO_CIPHER_ALG_3DES: - key_blob.hdr.aiKeyAlg = CALG_3DES; - break; - case CRYPTO_CIPHER_ALG_DES: - key_blob.hdr.aiKeyAlg = CALG_DES; - break; - case CRYPTO_CIPHER_ALG_RC2: - key_blob.hdr.aiKeyAlg = CALG_RC2; - break; - case CRYPTO_CIPHER_ALG_RC4: - key_blob.hdr.aiKeyAlg = CALG_RC4; - break; - default: - return NULL; - } - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) - return NULL; - - if (!CryptAcquireContext(&ctx->prov, NULL, MS_ENH_RSA_AES_PROV, - PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { - cryptoapi_report_error("CryptAcquireContext"); - goto fail1; - } - - if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob, - sizeof(key_blob), 0, 0, &ctx->key)) { - cryptoapi_report_error("CryptImportKey"); - goto fail2; - } - - if (!CryptSetKeyParam(ctx->key, KP_MODE, (BYTE *) &mode, 0)) { - cryptoapi_report_error("CryptSetKeyParam(KP_MODE)"); - goto fail3; - } - - if (iv && !CryptSetKeyParam(ctx->key, KP_IV, (BYTE *) iv, 0)) { - cryptoapi_report_error("CryptSetKeyParam(KP_IV)"); - goto fail3; - } - - return ctx; - -fail3: - CryptDestroyKey(ctx->key); -fail2: - CryptReleaseContext(ctx->prov, 0); -fail1: - os_free(ctx); - return NULL; -} - - -int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, - u8 *crypt, size_t len) -{ - DWORD dlen; - - os_memcpy(crypt, plain, len); - dlen = len; - if (!CryptEncrypt(ctx->key, 0, FALSE, 0, crypt, &dlen, len)) { - cryptoapi_report_error("CryptEncrypt"); - os_memset(crypt, 0, len); - return -1; - } - - return 0; -} - - -int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, - u8 *plain, size_t len) -{ - DWORD dlen; - - os_memcpy(plain, crypt, len); - dlen = len; - if (!CryptDecrypt(ctx->key, 0, FALSE, 0, plain, &dlen)) { - cryptoapi_report_error("CryptDecrypt"); - return -1; - } - - return 0; -} - - -void crypto_cipher_deinit(struct crypto_cipher *ctx) -{ - CryptDestroyKey(ctx->key); - CryptReleaseContext(ctx->prov, 0); - os_free(ctx); -} - - -struct crypto_public_key { - HCRYPTPROV prov; - HCRYPTKEY rsa; -}; - -struct crypto_private_key { - HCRYPTPROV prov; - HCRYPTKEY rsa; -}; - - -struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) -{ - /* Use crypto_public_key_from_cert() instead. */ - return NULL; -} - - -struct crypto_private_key * crypto_private_key_import(const u8 *key, - size_t len) -{ - /* TODO */ - return NULL; -} - - -struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, - size_t len) -{ - struct crypto_public_key *pk; - PCCERT_CONTEXT cc; - - pk = os_zalloc(sizeof(*pk)); - if (pk == NULL) - return NULL; - - cc = CertCreateCertificateContext(X509_ASN_ENCODING | - PKCS_7_ASN_ENCODING, buf, len); - if (!cc) { - cryptoapi_report_error("CryptCreateCertificateContext"); - os_free(pk); - return NULL; - } - - if (!CryptAcquireContext(&pk->prov, NULL, MS_DEF_PROV, PROV_RSA_FULL, - 0)) { - cryptoapi_report_error("CryptAcquireContext"); - os_free(pk); - CertFreeCertificateContext(cc); - return NULL; - } - - if (!CryptImportPublicKeyInfo(pk->prov, X509_ASN_ENCODING | - PKCS_7_ASN_ENCODING, - &cc->pCertInfo->SubjectPublicKeyInfo, - &pk->rsa)) { - cryptoapi_report_error("CryptImportPublicKeyInfo"); - CryptReleaseContext(pk->prov, 0); - os_free(pk); - CertFreeCertificateContext(cc); - return NULL; - } - - CertFreeCertificateContext(cc); - - return pk; -} - - -int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - DWORD clen; - u8 *tmp; - size_t i; - - if (*outlen < inlen) - return -1; - tmp = malloc(*outlen); - if (tmp == NULL) - return -1; - - os_memcpy(tmp, in, inlen); - clen = inlen; - if (!CryptEncrypt(key->rsa, 0, TRUE, 0, tmp, &clen, *outlen)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: Failed to encrypt using " - "public key: %d", (int) GetLastError()); - os_free(tmp); - return -1; - } - - *outlen = clen; - - /* Reverse the output */ - for (i = 0; i < *outlen; i++) - out[i] = tmp[*outlen - 1 - i]; - - os_free(tmp); - - return 0; -} - - -int crypto_private_key_sign_pkcs1(struct crypto_private_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - /* TODO */ - return -1; -} - - -void crypto_public_key_free(struct crypto_public_key *key) -{ - if (key) { - CryptDestroyKey(key->rsa); - CryptReleaseContext(key->prov, 0); - os_free(key); - } -} - - -void crypto_private_key_free(struct crypto_private_key *key) -{ - if (key) { - CryptDestroyKey(key->rsa); - CryptReleaseContext(key->prov, 0); - os_free(key); - } -} - - -int crypto_global_init(void) -{ - return mingw_load_crypto_func(); -} - - -void crypto_global_deinit(void) -{ -} - -#endif /* CONFIG_TLS_INTERNAL */ - -#endif /* EAP_TLS_FUNCS */ diff --git a/contrib/hostapd/src/crypto/crypto_gnutls.c b/contrib/hostapd/src/crypto/crypto_gnutls.c deleted file mode 100644 index 8f8611c0fb..0000000000 --- a/contrib/hostapd/src/crypto/crypto_gnutls.c +++ /dev/null @@ -1,311 +0,0 @@ -/* - * WPA Supplicant / wrapper functions for libgcrypt - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "crypto.h" - -void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - gcry_md_hd_t hd; - unsigned char *p; - size_t i; - - if (gcry_md_open(&hd, GCRY_MD_MD4, 0) != GPG_ERR_NO_ERROR) - return; - for (i = 0; i < num_elem; i++) - gcry_md_write(hd, addr[i], len[i]); - p = gcry_md_read(hd, GCRY_MD_MD4); - if (p) - memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD4)); - gcry_md_close(hd); -} - - -void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) -{ - gcry_cipher_hd_t hd; - u8 pkey[8], next, tmp; - int i; - - /* Add parity bits to the key */ - next = 0; - for (i = 0; i < 7; i++) { - tmp = key[i]; - pkey[i] = (tmp >> i) | next | 1; - next = tmp << (7 - i); - } - pkey[i] = next | 1; - - gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); - gcry_err_code(gcry_cipher_setkey(hd, pkey, 8)); - gcry_cipher_encrypt(hd, cypher, 8, clear, 8); - gcry_cipher_close(hd); -} - - -void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - gcry_md_hd_t hd; - unsigned char *p; - size_t i; - - if (gcry_md_open(&hd, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR) - return; - for (i = 0; i < num_elem; i++) - gcry_md_write(hd, addr[i], len[i]); - p = gcry_md_read(hd, GCRY_MD_MD5); - if (p) - memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD5)); - gcry_md_close(hd); -} - - -void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - gcry_md_hd_t hd; - unsigned char *p; - size_t i; - - if (gcry_md_open(&hd, GCRY_MD_SHA1, 0) != GPG_ERR_NO_ERROR) - return; - for (i = 0; i < num_elem; i++) - gcry_md_write(hd, addr[i], len[i]); - p = gcry_md_read(hd, GCRY_MD_SHA1); - if (p) - memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_SHA1)); - gcry_md_close(hd); -} - - -#ifndef CONFIG_NO_FIPS186_2_PRF -int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) -{ - /* FIX: how to do this with libgcrypt? */ - return -1; -} -#endif /* CONFIG_NO_FIPS186_2_PRF */ - - -void * aes_encrypt_init(const u8 *key, size_t len) -{ - gcry_cipher_hd_t hd; - - if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != - GPG_ERR_NO_ERROR) { - printf("cipher open failed\n"); - return NULL; - } - if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { - printf("setkey failed\n"); - gcry_cipher_close(hd); - return NULL; - } - - return hd; -} - - -void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) -{ - gcry_cipher_hd_t hd = ctx; - gcry_cipher_encrypt(hd, crypt, 16, plain, 16); -} - - -void aes_encrypt_deinit(void *ctx) -{ - gcry_cipher_hd_t hd = ctx; - gcry_cipher_close(hd); -} - - -void * aes_decrypt_init(const u8 *key, size_t len) -{ - gcry_cipher_hd_t hd; - - if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != - GPG_ERR_NO_ERROR) - return NULL; - if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { - gcry_cipher_close(hd); - return NULL; - } - - return hd; -} - - -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) -{ - gcry_cipher_hd_t hd = ctx; - gcry_cipher_decrypt(hd, plain, 16, crypt, 16); -} - - -void aes_decrypt_deinit(void *ctx) -{ - gcry_cipher_hd_t hd = ctx; - gcry_cipher_close(hd); -} - - -int crypto_mod_exp(const u8 *base, size_t base_len, - const u8 *power, size_t power_len, - const u8 *modulus, size_t modulus_len, - u8 *result, size_t *result_len) -{ - gcry_mpi_t bn_base = NULL, bn_exp = NULL, bn_modulus = NULL, - bn_result = NULL; - int ret = -1; - - if (gcry_mpi_scan(&bn_base, GCRYMPI_FMT_USG, base, base_len, NULL) != - GPG_ERR_NO_ERROR || - gcry_mpi_scan(&bn_exp, GCRYMPI_FMT_USG, power, power_len, NULL) != - GPG_ERR_NO_ERROR || - gcry_mpi_scan(&bn_modulus, GCRYMPI_FMT_USG, modulus, modulus_len, - NULL) != GPG_ERR_NO_ERROR) - goto error; - bn_result = gcry_mpi_new(modulus_len * 8); - - gcry_mpi_powm(bn_result, bn_base, bn_exp, bn_modulus); - - if (gcry_mpi_print(GCRYMPI_FMT_USG, result, *result_len, result_len, - bn_result) != GPG_ERR_NO_ERROR) - goto error; - - ret = 0; - -error: - gcry_mpi_release(bn_base); - gcry_mpi_release(bn_exp); - gcry_mpi_release(bn_modulus); - gcry_mpi_release(bn_result); - return ret; -} - - -struct crypto_cipher { - gcry_cipher_hd_t enc; - gcry_cipher_hd_t dec; -}; - - -struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, - const u8 *iv, const u8 *key, - size_t key_len) -{ - struct crypto_cipher *ctx; - gcry_error_t res; - enum gcry_cipher_algos a; - int ivlen; - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) - return NULL; - - switch (alg) { - case CRYPTO_CIPHER_ALG_RC4: - a = GCRY_CIPHER_ARCFOUR; - res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_STREAM, - 0); - gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_STREAM, 0); - break; - case CRYPTO_CIPHER_ALG_AES: - if (key_len == 24) - a = GCRY_CIPHER_AES192; - else if (key_len == 32) - a = GCRY_CIPHER_AES256; - else - a = GCRY_CIPHER_AES; - res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); - gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); - break; - case CRYPTO_CIPHER_ALG_3DES: - a = GCRY_CIPHER_3DES; - res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); - gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); - break; - case CRYPTO_CIPHER_ALG_DES: - a = GCRY_CIPHER_DES; - res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); - gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); - break; - case CRYPTO_CIPHER_ALG_RC2: - if (key_len == 5) - a = GCRY_CIPHER_RFC2268_40; - else - a = GCRY_CIPHER_RFC2268_128; - res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); - gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); - break; - default: - os_free(ctx); - return NULL; - } - - if (res != GPG_ERR_NO_ERROR) { - os_free(ctx); - return NULL; - } - - if (gcry_cipher_setkey(ctx->enc, key, key_len) != GPG_ERR_NO_ERROR || - gcry_cipher_setkey(ctx->dec, key, key_len) != GPG_ERR_NO_ERROR) { - gcry_cipher_close(ctx->enc); - gcry_cipher_close(ctx->dec); - os_free(ctx); - return NULL; - } - - ivlen = gcry_cipher_get_algo_blklen(a); - if (gcry_cipher_setiv(ctx->enc, iv, ivlen) != GPG_ERR_NO_ERROR || - gcry_cipher_setiv(ctx->dec, iv, ivlen) != GPG_ERR_NO_ERROR) { - gcry_cipher_close(ctx->enc); - gcry_cipher_close(ctx->dec); - os_free(ctx); - return NULL; - } - - return ctx; -} - - -int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, - u8 *crypt, size_t len) -{ - if (gcry_cipher_encrypt(ctx->enc, crypt, len, plain, len) != - GPG_ERR_NO_ERROR) - return -1; - return 0; -} - - -int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, - u8 *plain, size_t len) -{ - if (gcry_cipher_decrypt(ctx->dec, plain, len, crypt, len) != - GPG_ERR_NO_ERROR) - return -1; - return 0; -} - - -void crypto_cipher_deinit(struct crypto_cipher *ctx) -{ - gcry_cipher_close(ctx->enc); - gcry_cipher_close(ctx->dec); - os_free(ctx); -} diff --git a/contrib/hostapd/src/crypto/crypto_internal.c b/contrib/hostapd/src/crypto/crypto_internal.c deleted file mode 100644 index cddfb4de8e..0000000000 --- a/contrib/hostapd/src/crypto/crypto_internal.c +++ /dev/null @@ -1,836 +0,0 @@ -/* - * WPA Supplicant / Crypto wrapper for internal crypto implementation - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto.h" -#include "md5.h" -#include "sha1.h" -#include "rc4.h" -#include "aes.h" -#include "tls/rsa.h" -#include "tls/bignum.h" -#include "tls/asn1.h" - - -#ifdef CONFIG_CRYPTO_INTERNAL - -#ifdef CONFIG_TLS_INTERNAL - -/* from des.c */ -struct des3_key_s { - u32 ek[3][32]; - u32 dk[3][32]; -}; - -void des3_key_setup(const u8 *key, struct des3_key_s *dkey); -void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt); -void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain); - - -struct MD5Context { - u32 buf[4]; - u32 bits[2]; - u8 in[64]; -}; - -struct SHA1Context { - u32 state[5]; - u32 count[2]; - unsigned char buffer[64]; -}; - - -struct crypto_hash { - enum crypto_hash_alg alg; - union { - struct MD5Context md5; - struct SHA1Context sha1; - } u; - u8 key[64]; - size_t key_len; -}; - - -struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, - size_t key_len) -{ - struct crypto_hash *ctx; - u8 k_pad[64]; - u8 tk[20]; - size_t i; - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) - return NULL; - - ctx->alg = alg; - - switch (alg) { - case CRYPTO_HASH_ALG_MD5: - MD5Init(&ctx->u.md5); - break; - case CRYPTO_HASH_ALG_SHA1: - SHA1Init(&ctx->u.sha1); - break; - case CRYPTO_HASH_ALG_HMAC_MD5: - if (key_len > sizeof(k_pad)) { - MD5Init(&ctx->u.md5); - MD5Update(&ctx->u.md5, key, key_len); - MD5Final(tk, &ctx->u.md5); - key = tk; - key_len = 16; - } - os_memcpy(ctx->key, key, key_len); - ctx->key_len = key_len; - - os_memcpy(k_pad, key, key_len); - os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); - for (i = 0; i < sizeof(k_pad); i++) - k_pad[i] ^= 0x36; - MD5Init(&ctx->u.md5); - MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); - break; - case CRYPTO_HASH_ALG_HMAC_SHA1: - if (key_len > sizeof(k_pad)) { - SHA1Init(&ctx->u.sha1); - SHA1Update(&ctx->u.sha1, key, key_len); - SHA1Final(tk, &ctx->u.sha1); - key = tk; - key_len = 20; - } - os_memcpy(ctx->key, key, key_len); - ctx->key_len = key_len; - - os_memcpy(k_pad, key, key_len); - os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); - for (i = 0; i < sizeof(k_pad); i++) - k_pad[i] ^= 0x36; - SHA1Init(&ctx->u.sha1); - SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); - break; - default: - os_free(ctx); - return NULL; - } - - return ctx; -} - - -void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) -{ - if (ctx == NULL) - return; - - switch (ctx->alg) { - case CRYPTO_HASH_ALG_MD5: - case CRYPTO_HASH_ALG_HMAC_MD5: - MD5Update(&ctx->u.md5, data, len); - break; - case CRYPTO_HASH_ALG_SHA1: - case CRYPTO_HASH_ALG_HMAC_SHA1: - SHA1Update(&ctx->u.sha1, data, len); - break; - } -} - - -int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) -{ - u8 k_pad[64]; - size_t i; - - if (ctx == NULL) - return -2; - - if (mac == NULL || len == NULL) { - os_free(ctx); - return 0; - } - - switch (ctx->alg) { - case CRYPTO_HASH_ALG_MD5: - if (*len < 16) { - *len = 16; - os_free(ctx); - return -1; - } - *len = 16; - MD5Final(mac, &ctx->u.md5); - break; - case CRYPTO_HASH_ALG_SHA1: - if (*len < 20) { - *len = 20; - os_free(ctx); - return -1; - } - *len = 20; - SHA1Final(mac, &ctx->u.sha1); - break; - case CRYPTO_HASH_ALG_HMAC_MD5: - if (*len < 16) { - *len = 16; - os_free(ctx); - return -1; - } - *len = 16; - - MD5Final(mac, &ctx->u.md5); - - os_memcpy(k_pad, ctx->key, ctx->key_len); - os_memset(k_pad + ctx->key_len, 0, - sizeof(k_pad) - ctx->key_len); - for (i = 0; i < sizeof(k_pad); i++) - k_pad[i] ^= 0x5c; - MD5Init(&ctx->u.md5); - MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); - MD5Update(&ctx->u.md5, mac, 16); - MD5Final(mac, &ctx->u.md5); - break; - case CRYPTO_HASH_ALG_HMAC_SHA1: - if (*len < 20) { - *len = 20; - os_free(ctx); - return -1; - } - *len = 20; - - SHA1Final(mac, &ctx->u.sha1); - - os_memcpy(k_pad, ctx->key, ctx->key_len); - os_memset(k_pad + ctx->key_len, 0, - sizeof(k_pad) - ctx->key_len); - for (i = 0; i < sizeof(k_pad); i++) - k_pad[i] ^= 0x5c; - SHA1Init(&ctx->u.sha1); - SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); - SHA1Update(&ctx->u.sha1, mac, 20); - SHA1Final(mac, &ctx->u.sha1); - break; - } - - os_free(ctx); - - return 0; -} - - -struct crypto_cipher { - enum crypto_cipher_alg alg; - union { - struct { - size_t used_bytes; - u8 key[16]; - size_t keylen; - } rc4; - struct { - u8 cbc[32]; - size_t block_size; - void *ctx_enc; - void *ctx_dec; - } aes; - struct { - struct des3_key_s key; - u8 cbc[8]; - } des3; - } u; -}; - - -struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, - const u8 *iv, const u8 *key, - size_t key_len) -{ - struct crypto_cipher *ctx; - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) - return NULL; - - ctx->alg = alg; - - switch (alg) { - case CRYPTO_CIPHER_ALG_RC4: - if (key_len > sizeof(ctx->u.rc4.key)) { - os_free(ctx); - return NULL; - } - ctx->u.rc4.keylen = key_len; - os_memcpy(ctx->u.rc4.key, key, key_len); - break; - case CRYPTO_CIPHER_ALG_AES: - if (key_len > sizeof(ctx->u.aes.cbc)) { - os_free(ctx); - return NULL; - } - ctx->u.aes.ctx_enc = aes_encrypt_init(key, key_len); - if (ctx->u.aes.ctx_enc == NULL) { - os_free(ctx); - return NULL; - } - ctx->u.aes.ctx_dec = aes_decrypt_init(key, key_len); - if (ctx->u.aes.ctx_dec == NULL) { - aes_encrypt_deinit(ctx->u.aes.ctx_enc); - os_free(ctx); - return NULL; - } - ctx->u.aes.block_size = key_len; - os_memcpy(ctx->u.aes.cbc, iv, ctx->u.aes.block_size); - break; - case CRYPTO_CIPHER_ALG_3DES: - if (key_len != 24) { - os_free(ctx); - return NULL; - } - des3_key_setup(key, &ctx->u.des3.key); - os_memcpy(ctx->u.des3.cbc, iv, 8); - break; - default: - os_free(ctx); - return NULL; - } - - return ctx; -} - - -int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, - u8 *crypt, size_t len) -{ - size_t i, j, blocks; - - switch (ctx->alg) { - case CRYPTO_CIPHER_ALG_RC4: - if (plain != crypt) - os_memcpy(crypt, plain, len); - rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, - ctx->u.rc4.used_bytes, crypt, len); - ctx->u.rc4.used_bytes += len; - break; - case CRYPTO_CIPHER_ALG_AES: - if (len % ctx->u.aes.block_size) - return -1; - blocks = len / ctx->u.aes.block_size; - for (i = 0; i < blocks; i++) { - for (j = 0; j < ctx->u.aes.block_size; j++) - ctx->u.aes.cbc[j] ^= plain[j]; - aes_encrypt(ctx->u.aes.ctx_enc, ctx->u.aes.cbc, - ctx->u.aes.cbc); - os_memcpy(crypt, ctx->u.aes.cbc, - ctx->u.aes.block_size); - plain += ctx->u.aes.block_size; - crypt += ctx->u.aes.block_size; - } - break; - case CRYPTO_CIPHER_ALG_3DES: - if (len % 8) - return -1; - blocks = len / 8; - for (i = 0; i < blocks; i++) { - for (j = 0; j < 8; j++) - ctx->u.des3.cbc[j] ^= plain[j]; - des3_encrypt(ctx->u.des3.cbc, &ctx->u.des3.key, - ctx->u.des3.cbc); - os_memcpy(crypt, ctx->u.des3.cbc, 8); - plain += 8; - crypt += 8; - } - break; - default: - return -1; - } - - return 0; -} - - -int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, - u8 *plain, size_t len) -{ - size_t i, j, blocks; - u8 tmp[32]; - - switch (ctx->alg) { - case CRYPTO_CIPHER_ALG_RC4: - if (plain != crypt) - os_memcpy(plain, crypt, len); - rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, - ctx->u.rc4.used_bytes, plain, len); - ctx->u.rc4.used_bytes += len; - break; - case CRYPTO_CIPHER_ALG_AES: - if (len % ctx->u.aes.block_size) - return -1; - blocks = len / ctx->u.aes.block_size; - for (i = 0; i < blocks; i++) { - os_memcpy(tmp, crypt, ctx->u.aes.block_size); - aes_decrypt(ctx->u.aes.ctx_dec, crypt, plain); - for (j = 0; j < ctx->u.aes.block_size; j++) - plain[j] ^= ctx->u.aes.cbc[j]; - os_memcpy(ctx->u.aes.cbc, tmp, ctx->u.aes.block_size); - plain += ctx->u.aes.block_size; - crypt += ctx->u.aes.block_size; - } - break; - case CRYPTO_CIPHER_ALG_3DES: - if (len % 8) - return -1; - blocks = len / 8; - for (i = 0; i < blocks; i++) { - os_memcpy(tmp, crypt, 8); - des3_decrypt(crypt, &ctx->u.des3.key, plain); - for (j = 0; j < 8; j++) - plain[j] ^= ctx->u.des3.cbc[j]; - os_memcpy(ctx->u.des3.cbc, tmp, 8); - plain += 8; - crypt += 8; - } - break; - default: - return -1; - } - - return 0; -} - - -void crypto_cipher_deinit(struct crypto_cipher *ctx) -{ - switch (ctx->alg) { - case CRYPTO_CIPHER_ALG_AES: - aes_encrypt_deinit(ctx->u.aes.ctx_enc); - aes_decrypt_deinit(ctx->u.aes.ctx_dec); - break; - case CRYPTO_CIPHER_ALG_3DES: - break; - default: - break; - } - os_free(ctx); -} - - -/* Dummy structures; these are just typecast to struct crypto_rsa_key */ -struct crypto_public_key; -struct crypto_private_key; - - -struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) -{ - return (struct crypto_public_key *) - crypto_rsa_import_public_key(key, len); -} - - -#ifdef EAP_TLS_FUNCS -static struct crypto_private_key * -crypto_pkcs8_key_import(const u8 *buf, size_t len) -{ - struct asn1_hdr hdr; - const u8 *pos, *end; - struct bignum *zero; - struct asn1_oid oid; - char obuf[80]; - - /* PKCS #8, Chapter 6 */ - - /* PrivateKeyInfo ::= SEQUENCE */ - if (asn1_get_next(buf, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 " - "header (SEQUENCE); assume PKCS #8 not used"); - return NULL; - } - pos = hdr.payload; - end = pos + hdr.length; - - /* version Version (Version ::= INTEGER) */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { - wpa_printf(MSG_DEBUG, "PKCS #8: Expected INTEGER - found " - "class %d tag 0x%x; assume PKCS #8 not used", - hdr.class, hdr.tag); - return NULL; - } - - zero = bignum_init(); - if (zero == NULL) - return NULL; - - if (bignum_set_unsigned_bin(zero, hdr.payload, hdr.length) < 0) { - wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse INTEGER"); - bignum_deinit(zero); - return NULL; - } - pos = hdr.payload + hdr.length; - - if (bignum_cmp_d(zero, 0) != 0) { - wpa_printf(MSG_DEBUG, "PKCS #8: Expected zero INTEGER in the " - "beginning of private key; not found; assume " - "PKCS #8 not used"); - bignum_deinit(zero); - return NULL; - } - bignum_deinit(zero); - - /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier - * (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */ - if (asn1_get_next(pos, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE " - "(AlgorithmIdentifier) - found class %d tag 0x%x; " - "assume PKCS #8 not used", - hdr.class, hdr.tag); - return NULL; - } - - if (asn1_get_oid(hdr.payload, hdr.length, &oid, &pos)) { - wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse OID " - "(algorithm); assume PKCS #8 not used"); - return NULL; - } - - asn1_oid_to_str(&oid, obuf, sizeof(obuf)); - wpa_printf(MSG_DEBUG, "PKCS #8: algorithm=%s", obuf); - - if (oid.len != 7 || - oid.oid[0] != 1 /* iso */ || - oid.oid[1] != 2 /* member-body */ || - oid.oid[2] != 840 /* us */ || - oid.oid[3] != 113549 /* rsadsi */ || - oid.oid[4] != 1 /* pkcs */ || - oid.oid[5] != 1 /* pkcs-1 */ || - oid.oid[6] != 1 /* rsaEncryption */) { - wpa_printf(MSG_DEBUG, "PKCS #8: Unsupported private key " - "algorithm %s", obuf); - return NULL; - } - - pos = hdr.payload + hdr.length; - - /* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_OCTETSTRING) { - wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING " - "(privateKey) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return NULL; - } - wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey"); - - return (struct crypto_private_key *) - crypto_rsa_import_private_key(hdr.payload, hdr.length); -} -#endif /* EAP_TLS_FUNCS */ - - -struct crypto_private_key * crypto_private_key_import(const u8 *key, - size_t len) -{ - struct crypto_private_key *res; - - /* First, check for possible PKCS #8 encoding */ - res = crypto_pkcs8_key_import(key, len); - if (res) - return res; - - /* Not PKCS#8, so try to import PKCS #1 encoded RSA private key */ - wpa_printf(MSG_DEBUG, "Trying to parse PKCS #1 encoded RSA private " - "key"); - return (struct crypto_private_key *) - crypto_rsa_import_private_key(key, len); -} - - -struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, - size_t len) -{ - /* No X.509 support in crypto_internal.c */ - return NULL; -} - - -static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - size_t ps_len; - u8 *pos; - - /* - * PKCS #1 v1.5, 8.1: - * - * EB = 00 || BT || PS || 00 || D - * BT = 00 or 01 for private-key operation; 02 for public-key operation - * PS = k-3-||D||; at least eight octets - * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero) - * k = length of modulus in octets (modlen) - */ - - if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) { - wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer " - "lengths (modlen=%lu outlen=%lu inlen=%lu)", - __func__, (unsigned long) modlen, - (unsigned long) *outlen, - (unsigned long) inlen); - return -1; - } - - pos = out; - *pos++ = 0x00; - *pos++ = block_type; /* BT */ - ps_len = modlen - inlen - 3; - switch (block_type) { - case 0: - os_memset(pos, 0x00, ps_len); - pos += ps_len; - break; - case 1: - os_memset(pos, 0xff, ps_len); - pos += ps_len; - break; - case 2: - if (os_get_random(pos, ps_len) < 0) { - wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get " - "random data for PS", __func__); - return -1; - } - while (ps_len--) { - if (*pos == 0x00) - *pos = 0x01; - pos++; - } - break; - default: - wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type " - "%d", __func__, block_type); - return -1; - } - *pos++ = 0x00; - os_memcpy(pos, in, inlen); /* D */ - - return 0; -} - - -static int crypto_rsa_encrypt_pkcs1(int block_type, struct crypto_rsa_key *key, - int use_private, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - size_t modlen; - - modlen = crypto_rsa_get_modulus_len(key); - - if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen, - out, outlen) < 0) - return -1; - - return crypto_rsa_exptmod(out, modlen, out, outlen, key, use_private); -} - - -int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - return crypto_rsa_encrypt_pkcs1(2, (struct crypto_rsa_key *) key, - 0, in, inlen, out, outlen); -} - - -int crypto_private_key_decrypt_pkcs1_v15(struct crypto_private_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - struct crypto_rsa_key *rkey = (struct crypto_rsa_key *) key; - int res; - u8 *pos, *end; - - res = crypto_rsa_exptmod(in, inlen, out, outlen, rkey, 1); - if (res) - return res; - - if (*outlen < 2 || out[0] != 0 || out[1] != 2) - return -1; - - /* Skip PS (pseudorandom non-zero octets) */ - pos = out + 2; - end = out + *outlen; - while (*pos && pos < end) - pos++; - if (pos == end) - return -1; - pos++; - - *outlen -= pos - out; - - /* Strip PKCS #1 header */ - os_memmove(out, pos, *outlen); - - return 0; -} - - -int crypto_private_key_sign_pkcs1(struct crypto_private_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - return crypto_rsa_encrypt_pkcs1(1, (struct crypto_rsa_key *) key, - 1, in, inlen, out, outlen); -} - - -void crypto_public_key_free(struct crypto_public_key *key) -{ - crypto_rsa_free((struct crypto_rsa_key *) key); -} - - -void crypto_private_key_free(struct crypto_private_key *key) -{ - crypto_rsa_free((struct crypto_rsa_key *) key); -} - - -int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key, - const u8 *crypt, size_t crypt_len, - u8 *plain, size_t *plain_len) -{ - size_t len; - u8 *pos; - - len = *plain_len; - if (crypto_rsa_exptmod(crypt, crypt_len, plain, &len, - (struct crypto_rsa_key *) key, 0) < 0) - return -1; - - /* - * PKCS #1 v1.5, 8.1: - * - * EB = 00 || BT || PS || 00 || D - * BT = 00 or 01 - * PS = k-3-||D|| times (00 if BT=00) or (FF if BT=01) - * k = length of modulus in octets - */ - - if (len < 3 + 8 + 16 /* min hash len */ || - plain[0] != 0x00 || (plain[1] != 0x00 && plain[1] != 0x01)) { - wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " - "structure"); - return -1; - } - - pos = plain + 3; - if (plain[1] == 0x00) { - /* BT = 00 */ - if (plain[2] != 0x00) { - wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature " - "PS (BT=00)"); - return -1; - } - while (pos + 1 < plain + len && *pos == 0x00 && pos[1] == 0x00) - pos++; - } else { - /* BT = 01 */ - if (plain[2] != 0xff) { - wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature " - "PS (BT=01)"); - return -1; - } - while (pos < plain + len && *pos == 0xff) - pos++; - } - - if (pos - plain - 2 < 8) { - /* PKCS #1 v1.5, 8.1: At least eight octets long PS */ - wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature " - "padding"); - return -1; - } - - if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) { - wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " - "structure (2)"); - return -1; - } - pos++; - len -= pos - plain; - - /* Strip PKCS #1 header */ - os_memmove(plain, pos, len); - *plain_len = len; - - return 0; -} - - -int crypto_global_init(void) -{ - return 0; -} - - -void crypto_global_deinit(void) -{ -} -#endif /* CONFIG_TLS_INTERNAL */ - - -#if defined(EAP_FAST) || defined(CONFIG_WPS) - -int crypto_mod_exp(const u8 *base, size_t base_len, - const u8 *power, size_t power_len, - const u8 *modulus, size_t modulus_len, - u8 *result, size_t *result_len) -{ - struct bignum *bn_base, *bn_exp, *bn_modulus, *bn_result; - int ret = -1; - - bn_base = bignum_init(); - bn_exp = bignum_init(); - bn_modulus = bignum_init(); - bn_result = bignum_init(); - - if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL || - bn_result == NULL) - goto error; - - if (bignum_set_unsigned_bin(bn_base, base, base_len) < 0 || - bignum_set_unsigned_bin(bn_exp, power, power_len) < 0 || - bignum_set_unsigned_bin(bn_modulus, modulus, modulus_len) < 0) - goto error; - - if (bignum_exptmod(bn_base, bn_exp, bn_modulus, bn_result) < 0) - goto error; - - ret = bignum_get_unsigned_bin(bn_result, result, result_len); - -error: - bignum_deinit(bn_base); - bignum_deinit(bn_exp); - bignum_deinit(bn_modulus); - bignum_deinit(bn_result); - return ret; -} - -#endif /* EAP_FAST || CONFIG_WPS */ - - -#endif /* CONFIG_CRYPTO_INTERNAL */ diff --git a/contrib/hostapd/src/crypto/crypto_libtomcrypt.c b/contrib/hostapd/src/crypto/crypto_libtomcrypt.c deleted file mode 100644 index e82097f10a..0000000000 --- a/contrib/hostapd/src/crypto/crypto_libtomcrypt.c +++ /dev/null @@ -1,736 +0,0 @@ -/* - * WPA Supplicant / Crypto wrapper for LibTomCrypt (for internal TLSv1) - * Copyright (c) 2005-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "rc4.h" -#include "crypto.h" - -#ifndef mp_init_multi -#define mp_init_multi ltc_init_multi -#define mp_clear_multi ltc_deinit_multi -#define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a) -#define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b) -#define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c) -#define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d) -#endif - - -void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - hash_state md; - size_t i; - - md4_init(&md); - for (i = 0; i < num_elem; i++) - md4_process(&md, addr[i], len[i]); - md4_done(&md, mac); -} - - -void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) -{ - u8 pkey[8], next, tmp; - int i; - symmetric_key skey; - - /* Add parity bits to the key */ - next = 0; - for (i = 0; i < 7; i++) { - tmp = key[i]; - pkey[i] = (tmp >> i) | next | 1; - next = tmp << (7 - i); - } - pkey[i] = next | 1; - - des_setup(pkey, 8, 0, &skey); - des_ecb_encrypt(clear, cypher, &skey); - des_done(&skey); -} - - -#ifdef EAP_TLS_FUNCS -void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - hash_state md; - size_t i; - - md5_init(&md); - for (i = 0; i < num_elem; i++) - md5_process(&md, addr[i], len[i]); - md5_done(&md, mac); -} - - -void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - hash_state md; - size_t i; - - sha1_init(&md); - for (i = 0; i < num_elem; i++) - sha1_process(&md, addr[i], len[i]); - sha1_done(&md, mac); -} - - -void * aes_encrypt_init(const u8 *key, size_t len) -{ - symmetric_key *skey; - skey = os_malloc(sizeof(*skey)); - if (skey == NULL) - return NULL; - if (aes_setup(key, len, 0, skey) != CRYPT_OK) { - os_free(skey); - return NULL; - } - return skey; -} - - -void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) -{ - symmetric_key *skey = ctx; - aes_ecb_encrypt(plain, crypt, skey); -} - - -void aes_encrypt_deinit(void *ctx) -{ - symmetric_key *skey = ctx; - aes_done(skey); - os_free(skey); -} - - -void * aes_decrypt_init(const u8 *key, size_t len) -{ - symmetric_key *skey; - skey = os_malloc(sizeof(*skey)); - if (skey == NULL) - return NULL; - if (aes_setup(key, len, 0, skey) != CRYPT_OK) { - os_free(skey); - return NULL; - } - return skey; -} - - -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) -{ - symmetric_key *skey = ctx; - aes_ecb_encrypt(plain, (u8 *) crypt, skey); -} - - -void aes_decrypt_deinit(void *ctx) -{ - symmetric_key *skey = ctx; - aes_done(skey); - os_free(skey); -} - - -#ifdef CONFIG_TLS_INTERNAL - -struct crypto_hash { - enum crypto_hash_alg alg; - int error; - union { - hash_state md; - hmac_state hmac; - } u; -}; - - -struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, - size_t key_len) -{ - struct crypto_hash *ctx; - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) - return NULL; - - ctx->alg = alg; - - switch (alg) { - case CRYPTO_HASH_ALG_MD5: - if (md5_init(&ctx->u.md) != CRYPT_OK) - goto fail; - break; - case CRYPTO_HASH_ALG_SHA1: - if (sha1_init(&ctx->u.md) != CRYPT_OK) - goto fail; - break; - case CRYPTO_HASH_ALG_HMAC_MD5: - if (hmac_init(&ctx->u.hmac, find_hash("md5"), key, key_len) != - CRYPT_OK) - goto fail; - break; - case CRYPTO_HASH_ALG_HMAC_SHA1: - if (hmac_init(&ctx->u.hmac, find_hash("sha1"), key, key_len) != - CRYPT_OK) - goto fail; - break; - default: - goto fail; - } - - return ctx; - -fail: - os_free(ctx); - return NULL; -} - -void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) -{ - if (ctx == NULL || ctx->error) - return; - - switch (ctx->alg) { - case CRYPTO_HASH_ALG_MD5: - ctx->error = md5_process(&ctx->u.md, data, len) != CRYPT_OK; - break; - case CRYPTO_HASH_ALG_SHA1: - ctx->error = sha1_process(&ctx->u.md, data, len) != CRYPT_OK; - break; - case CRYPTO_HASH_ALG_HMAC_MD5: - case CRYPTO_HASH_ALG_HMAC_SHA1: - ctx->error = hmac_process(&ctx->u.hmac, data, len) != CRYPT_OK; - break; - } -} - - -int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) -{ - int ret = 0; - unsigned long clen; - - if (ctx == NULL) - return -2; - - if (mac == NULL || len == NULL) { - os_free(ctx); - return 0; - } - - if (ctx->error) { - os_free(ctx); - return -2; - } - - switch (ctx->alg) { - case CRYPTO_HASH_ALG_MD5: - if (*len < 16) { - *len = 16; - os_free(ctx); - return -1; - } - *len = 16; - if (md5_done(&ctx->u.md, mac) != CRYPT_OK) - ret = -2; - break; - case CRYPTO_HASH_ALG_SHA1: - if (*len < 20) { - *len = 20; - os_free(ctx); - return -1; - } - *len = 20; - if (sha1_done(&ctx->u.md, mac) != CRYPT_OK) - ret = -2; - break; - case CRYPTO_HASH_ALG_HMAC_SHA1: - if (*len < 20) { - *len = 20; - os_free(ctx); - return -1; - } - /* continue */ - case CRYPTO_HASH_ALG_HMAC_MD5: - if (*len < 16) { - *len = 16; - os_free(ctx); - return -1; - } - clen = *len; - if (hmac_done(&ctx->u.hmac, mac, &clen) != CRYPT_OK) { - os_free(ctx); - return -1; - } - *len = clen; - break; - default: - ret = -2; - break; - } - - os_free(ctx); - - return ret; -} - - -struct crypto_cipher { - int rc4; - union { - symmetric_CBC cbc; - struct { - size_t used_bytes; - u8 key[16]; - size_t keylen; - } rc4; - } u; -}; - - -struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, - const u8 *iv, const u8 *key, - size_t key_len) -{ - struct crypto_cipher *ctx; - int idx, res, rc4 = 0; - - switch (alg) { - case CRYPTO_CIPHER_ALG_AES: - idx = find_cipher("aes"); - break; - case CRYPTO_CIPHER_ALG_3DES: - idx = find_cipher("3des"); - break; - case CRYPTO_CIPHER_ALG_DES: - idx = find_cipher("des"); - break; - case CRYPTO_CIPHER_ALG_RC2: - idx = find_cipher("rc2"); - break; - case CRYPTO_CIPHER_ALG_RC4: - idx = -1; - rc4 = 1; - break; - default: - return NULL; - } - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) - return NULL; - - if (rc4) { - ctx->rc4 = 1; - if (key_len > sizeof(ctx->u.rc4.key)) { - os_free(ctx); - return NULL; - } - ctx->u.rc4.keylen = key_len; - os_memcpy(ctx->u.rc4.key, key, key_len); - } else { - res = cbc_start(idx, iv, key, key_len, 0, &ctx->u.cbc); - if (res != CRYPT_OK) { - wpa_printf(MSG_DEBUG, "LibTomCrypt: Cipher start " - "failed: %s", error_to_string(res)); - os_free(ctx); - return NULL; - } - } - - return ctx; -} - -int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, - u8 *crypt, size_t len) -{ - int res; - - if (ctx->rc4) { - if (plain != crypt) - os_memcpy(crypt, plain, len); - rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, - ctx->u.rc4.used_bytes, crypt, len); - ctx->u.rc4.used_bytes += len; - return 0; - } - - res = cbc_encrypt(plain, crypt, len, &ctx->u.cbc); - if (res != CRYPT_OK) { - wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC encryption " - "failed: %s", error_to_string(res)); - return -1; - } - return 0; -} - - -int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, - u8 *plain, size_t len) -{ - int res; - - if (ctx->rc4) { - if (plain != crypt) - os_memcpy(plain, crypt, len); - rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, - ctx->u.rc4.used_bytes, plain, len); - ctx->u.rc4.used_bytes += len; - return 0; - } - - res = cbc_decrypt(crypt, plain, len, &ctx->u.cbc); - if (res != CRYPT_OK) { - wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC decryption " - "failed: %s", error_to_string(res)); - return -1; - } - - return 0; -} - - -void crypto_cipher_deinit(struct crypto_cipher *ctx) -{ - if (!ctx->rc4) - cbc_done(&ctx->u.cbc); - os_free(ctx); -} - - -struct crypto_public_key { - rsa_key rsa; -}; - -struct crypto_private_key { - rsa_key rsa; -}; - - -struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) -{ - int res; - struct crypto_public_key *pk; - - pk = os_zalloc(sizeof(*pk)); - if (pk == NULL) - return NULL; - - res = rsa_import(key, len, &pk->rsa); - if (res != CRYPT_OK) { - wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import " - "public key (res=%d '%s')", - res, error_to_string(res)); - os_free(pk); - return NULL; - } - - if (pk->rsa.type != PK_PUBLIC) { - wpa_printf(MSG_ERROR, "LibTomCrypt: Public key was not of " - "correct type"); - rsa_free(&pk->rsa); - os_free(pk); - return NULL; - } - - return pk; -} - - -struct crypto_private_key * crypto_private_key_import(const u8 *key, - size_t len) -{ - int res; - struct crypto_private_key *pk; - - pk = os_zalloc(sizeof(*pk)); - if (pk == NULL) - return NULL; - - res = rsa_import(key, len, &pk->rsa); - if (res != CRYPT_OK) { - wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import " - "private key (res=%d '%s')", - res, error_to_string(res)); - os_free(pk); - return NULL; - } - - if (pk->rsa.type != PK_PRIVATE) { - wpa_printf(MSG_ERROR, "LibTomCrypt: Private key was not of " - "correct type"); - rsa_free(&pk->rsa); - os_free(pk); - return NULL; - } - - return pk; -} - - -struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, - size_t len) -{ - /* No X.509 support in LibTomCrypt */ - return NULL; -} - - -static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - size_t ps_len; - u8 *pos; - - /* - * PKCS #1 v1.5, 8.1: - * - * EB = 00 || BT || PS || 00 || D - * BT = 00 or 01 for private-key operation; 02 for public-key operation - * PS = k-3-||D||; at least eight octets - * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero) - * k = length of modulus in octets (modlen) - */ - - if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) { - wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer " - "lengths (modlen=%lu outlen=%lu inlen=%lu)", - __func__, (unsigned long) modlen, - (unsigned long) *outlen, - (unsigned long) inlen); - return -1; - } - - pos = out; - *pos++ = 0x00; - *pos++ = block_type; /* BT */ - ps_len = modlen - inlen - 3; - switch (block_type) { - case 0: - os_memset(pos, 0x00, ps_len); - pos += ps_len; - break; - case 1: - os_memset(pos, 0xff, ps_len); - pos += ps_len; - break; - case 2: - if (os_get_random(pos, ps_len) < 0) { - wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get " - "random data for PS", __func__); - return -1; - } - while (ps_len--) { - if (*pos == 0x00) - *pos = 0x01; - pos++; - } - break; - default: - wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type " - "%d", __func__, block_type); - return -1; - } - *pos++ = 0x00; - os_memcpy(pos, in, inlen); /* D */ - - return 0; -} - - -static int crypto_rsa_encrypt_pkcs1(int block_type, rsa_key *key, int key_type, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - unsigned long len, modlen; - int res; - - modlen = mp_unsigned_bin_size(key->N); - - if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen, - out, outlen) < 0) - return -1; - - len = *outlen; - res = rsa_exptmod(out, modlen, out, &len, key_type, key); - if (res != CRYPT_OK) { - wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s", - error_to_string(res)); - return -1; - } - *outlen = len; - - return 0; -} - - -int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - return crypto_rsa_encrypt_pkcs1(2, &key->rsa, PK_PUBLIC, in, inlen, - out, outlen); -} - - -int crypto_private_key_sign_pkcs1(struct crypto_private_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - return crypto_rsa_encrypt_pkcs1(1, &key->rsa, PK_PRIVATE, in, inlen, - out, outlen); -} - - -void crypto_public_key_free(struct crypto_public_key *key) -{ - if (key) { - rsa_free(&key->rsa); - os_free(key); - } -} - - -void crypto_private_key_free(struct crypto_private_key *key) -{ - if (key) { - rsa_free(&key->rsa); - os_free(key); - } -} - - -int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key, - const u8 *crypt, size_t crypt_len, - u8 *plain, size_t *plain_len) -{ - int res; - unsigned long len; - u8 *pos; - - len = *plain_len; - res = rsa_exptmod(crypt, crypt_len, plain, &len, PK_PUBLIC, - &key->rsa); - if (res != CRYPT_OK) { - wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s", - error_to_string(res)); - return -1; - } - - /* - * PKCS #1 v1.5, 8.1: - * - * EB = 00 || BT || PS || 00 || D - * BT = 01 - * PS = k-3-||D|| times FF - * k = length of modulus in octets - */ - - if (len < 3 + 8 + 16 /* min hash len */ || - plain[0] != 0x00 || plain[1] != 0x01 || plain[2] != 0xff) { - wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " - "structure"); - return -1; - } - - pos = plain + 3; - while (pos < plain + len && *pos == 0xff) - pos++; - if (pos - plain - 2 < 8) { - /* PKCS #1 v1.5, 8.1: At least eight octets long PS */ - wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature " - "padding"); - return -1; - } - - if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) { - wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " - "structure (2)"); - return -1; - } - pos++; - len -= pos - plain; - - /* Strip PKCS #1 header */ - os_memmove(plain, pos, len); - *plain_len = len; - - return 0; -} - - -int crypto_global_init(void) -{ - ltc_mp = tfm_desc; - /* TODO: only register algorithms that are really needed */ - if (register_hash(&md4_desc) < 0 || - register_hash(&md5_desc) < 0 || - register_hash(&sha1_desc) < 0 || - register_cipher(&aes_desc) < 0 || - register_cipher(&des_desc) < 0 || - register_cipher(&des3_desc) < 0) { - wpa_printf(MSG_ERROR, "TLSv1: Failed to register " - "hash/cipher functions"); - return -1; - } - - return 0; -} - - -void crypto_global_deinit(void) -{ -} - - -#ifdef EAP_FAST - -int crypto_mod_exp(const u8 *base, size_t base_len, - const u8 *power, size_t power_len, - const u8 *modulus, size_t modulus_len, - u8 *result, size_t *result_len) -{ - void *b, *p, *m, *r; - - if (mp_init_multi(&b, &p, &m, &r, NULL) != CRYPT_OK) - return -1; - - if (mp_read_unsigned_bin(b, (u8 *) base, base_len) != CRYPT_OK || - mp_read_unsigned_bin(p, (u8 *) power, power_len) != CRYPT_OK || - mp_read_unsigned_bin(m, (u8 *) modulus, modulus_len) != CRYPT_OK) - goto fail; - - if (mp_exptmod(b, p, m, r) != CRYPT_OK) - goto fail; - - *result_len = mp_unsigned_bin_size(r); - if (mp_to_unsigned_bin(r, result) != CRYPT_OK) - goto fail; - - mp_clear_multi(b, p, m, r, NULL); - return 0; - -fail: - mp_clear_multi(b, p, m, r, NULL); - return -1; -} - -#endif /* EAP_FAST */ - -#endif /* CONFIG_TLS_INTERNAL */ - -#endif /* EAP_TLS_FUNCS */ diff --git a/contrib/hostapd/src/crypto/crypto_none.c b/contrib/hostapd/src/crypto/crypto_none.c deleted file mode 100644 index f18c2a8ded..0000000000 --- a/contrib/hostapd/src/crypto/crypto_none.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * WPA Supplicant / Empty template functions for crypto wrapper - * Copyright (c) 2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto.h" - - -void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ -} - - -void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) -{ -} diff --git a/contrib/hostapd/src/crypto/crypto_openssl.c b/contrib/hostapd/src/crypto/crypto_openssl.c deleted file mode 100644 index a4c3415c4d..0000000000 --- a/contrib/hostapd/src/crypto/crypto_openssl.c +++ /dev/null @@ -1,360 +0,0 @@ -/* - * WPA Supplicant / wrapper functions for libcrypto - * Copyright (c) 2004-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "crypto.h" - -#if OPENSSL_VERSION_NUMBER < 0x00907000 -#define DES_key_schedule des_key_schedule -#define DES_cblock des_cblock -#define DES_set_key(key, schedule) des_set_key((key), *(schedule)) -#define DES_ecb_encrypt(input, output, ks, enc) \ - des_ecb_encrypt((input), (output), *(ks), (enc)) -#endif /* openssl < 0.9.7 */ - - -void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - MD4_CTX ctx; - size_t i; - - MD4_Init(&ctx); - for (i = 0; i < num_elem; i++) - MD4_Update(&ctx, addr[i], len[i]); - MD4_Final(mac, &ctx); -} - - -void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) -{ - u8 pkey[8], next, tmp; - int i; - DES_key_schedule ks; - - /* Add parity bits to the key */ - next = 0; - for (i = 0; i < 7; i++) { - tmp = key[i]; - pkey[i] = (tmp >> i) | next | 1; - next = tmp << (7 - i); - } - pkey[i] = next | 1; - - DES_set_key(&pkey, &ks); - DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks, - DES_ENCRYPT); -} - - -void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - MD5_CTX ctx; - size_t i; - - MD5_Init(&ctx); - for (i = 0; i < num_elem; i++) - MD5_Update(&ctx, addr[i], len[i]); - MD5_Final(mac, &ctx); -} - - -void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - SHA_CTX ctx; - size_t i; - - SHA1_Init(&ctx); - for (i = 0; i < num_elem; i++) - SHA1_Update(&ctx, addr[i], len[i]); - SHA1_Final(mac, &ctx); -} - - -#ifndef CONFIG_NO_FIPS186_2_PRF -static void sha1_transform(u8 *state, const u8 data[64]) -{ - SHA_CTX context; - os_memset(&context, 0, sizeof(context)); - os_memcpy(&context.h0, state, 5 * 4); - SHA1_Transform(&context, data); - os_memcpy(state, &context.h0, 5 * 4); -} - - -int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) -{ - u8 xkey[64]; - u32 t[5], _t[5]; - int i, j, m, k; - u8 *xpos = x; - u32 carry; - - if (seed_len > sizeof(xkey)) - seed_len = sizeof(xkey); - - /* FIPS 186-2 + change notice 1 */ - - os_memcpy(xkey, seed, seed_len); - os_memset(xkey + seed_len, 0, 64 - seed_len); - t[0] = 0x67452301; - t[1] = 0xEFCDAB89; - t[2] = 0x98BADCFE; - t[3] = 0x10325476; - t[4] = 0xC3D2E1F0; - - m = xlen / 40; - for (j = 0; j < m; j++) { - /* XSEED_j = 0 */ - for (i = 0; i < 2; i++) { - /* XVAL = (XKEY + XSEED_j) mod 2^b */ - - /* w_i = G(t, XVAL) */ - os_memcpy(_t, t, 20); - sha1_transform((u8 *) _t, xkey); - _t[0] = host_to_be32(_t[0]); - _t[1] = host_to_be32(_t[1]); - _t[2] = host_to_be32(_t[2]); - _t[3] = host_to_be32(_t[3]); - _t[4] = host_to_be32(_t[4]); - os_memcpy(xpos, _t, 20); - - /* XKEY = (1 + XKEY + w_i) mod 2^b */ - carry = 1; - for (k = 19; k >= 0; k--) { - carry += xkey[k] + xpos[k]; - xkey[k] = carry & 0xff; - carry >>= 8; - } - - xpos += 20; - } - /* x_j = w_0|w_1 */ - } - - return 0; -} -#endif /* CONFIG_NO_FIPS186_2_PRF */ - - -void * aes_encrypt_init(const u8 *key, size_t len) -{ - AES_KEY *ak; - ak = os_malloc(sizeof(*ak)); - if (ak == NULL) - return NULL; - if (AES_set_encrypt_key(key, 8 * len, ak) < 0) { - os_free(ak); - return NULL; - } - return ak; -} - - -void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) -{ - AES_encrypt(plain, crypt, ctx); -} - - -void aes_encrypt_deinit(void *ctx) -{ - os_free(ctx); -} - - -void * aes_decrypt_init(const u8 *key, size_t len) -{ - AES_KEY *ak; - ak = os_malloc(sizeof(*ak)); - if (ak == NULL) - return NULL; - if (AES_set_decrypt_key(key, 8 * len, ak) < 0) { - os_free(ak); - return NULL; - } - return ak; -} - - -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) -{ - AES_decrypt(crypt, plain, ctx); -} - - -void aes_decrypt_deinit(void *ctx) -{ - os_free(ctx); -} - - -int crypto_mod_exp(const u8 *base, size_t base_len, - const u8 *power, size_t power_len, - const u8 *modulus, size_t modulus_len, - u8 *result, size_t *result_len) -{ - BIGNUM *bn_base, *bn_exp, *bn_modulus, *bn_result; - int ret = -1; - BN_CTX *ctx; - - ctx = BN_CTX_new(); - if (ctx == NULL) - return -1; - - bn_base = BN_bin2bn(base, base_len, NULL); - bn_exp = BN_bin2bn(power, power_len, NULL); - bn_modulus = BN_bin2bn(modulus, modulus_len, NULL); - bn_result = BN_new(); - - if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL || - bn_result == NULL) - goto error; - - if (BN_mod_exp(bn_result, bn_base, bn_exp, bn_modulus, ctx) != 1) - goto error; - - *result_len = BN_bn2bin(bn_result, result); - ret = 0; - -error: - BN_free(bn_base); - BN_free(bn_exp); - BN_free(bn_modulus); - BN_free(bn_result); - BN_CTX_free(ctx); - return ret; -} - - -struct crypto_cipher { - EVP_CIPHER_CTX enc; - EVP_CIPHER_CTX dec; -}; - - -struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, - const u8 *iv, const u8 *key, - size_t key_len) -{ - struct crypto_cipher *ctx; - const EVP_CIPHER *cipher; - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) - return NULL; - - switch (alg) { -#ifndef OPENSSL_NO_RC4 - case CRYPTO_CIPHER_ALG_RC4: - cipher = EVP_rc4(); - break; -#endif /* OPENSSL_NO_RC4 */ -#ifndef OPENSSL_NO_AES - case CRYPTO_CIPHER_ALG_AES: - switch (key_len) { - case 16: - cipher = EVP_aes_128_cbc(); - break; - case 24: - cipher = EVP_aes_192_cbc(); - break; - case 32: - cipher = EVP_aes_256_cbc(); - break; - default: - os_free(ctx); - return NULL; - } - break; -#endif /* OPENSSL_NO_AES */ -#ifndef OPENSSL_NO_DES - case CRYPTO_CIPHER_ALG_3DES: - cipher = EVP_des_ede3_cbc(); - break; - case CRYPTO_CIPHER_ALG_DES: - cipher = EVP_des_cbc(); - break; -#endif /* OPENSSL_NO_DES */ -#ifndef OPENSSL_NO_RC2 - case CRYPTO_CIPHER_ALG_RC2: - cipher = EVP_rc2_ecb(); - break; -#endif /* OPENSSL_NO_RC2 */ - default: - os_free(ctx); - return NULL; - } - - EVP_CIPHER_CTX_init(&ctx->enc); - EVP_CIPHER_CTX_set_padding(&ctx->enc, 0); - if (!EVP_EncryptInit_ex(&ctx->enc, cipher, NULL, NULL, NULL) || - !EVP_CIPHER_CTX_set_key_length(&ctx->enc, key_len) || - !EVP_EncryptInit_ex(&ctx->enc, cipher, NULL, key, iv)) { - EVP_CIPHER_CTX_cleanup(&ctx->enc); - os_free(ctx); - return NULL; - } - - EVP_CIPHER_CTX_init(&ctx->dec); - EVP_CIPHER_CTX_set_padding(&ctx->dec, 0); - if (!EVP_DecryptInit_ex(&ctx->dec, cipher, NULL, NULL, NULL) || - !EVP_CIPHER_CTX_set_key_length(&ctx->dec, key_len) || - !EVP_DecryptInit_ex(&ctx->dec, cipher, NULL, key, iv)) { - EVP_CIPHER_CTX_cleanup(&ctx->enc); - EVP_CIPHER_CTX_cleanup(&ctx->dec); - os_free(ctx); - return NULL; - } - - return ctx; -} - - -int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, - u8 *crypt, size_t len) -{ - int outl; - if (!EVP_EncryptUpdate(&ctx->enc, crypt, &outl, plain, len)) - return -1; - return 0; -} - - -int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, - u8 *plain, size_t len) -{ - int outl; - outl = len; - if (!EVP_DecryptUpdate(&ctx->dec, plain, &outl, crypt, len)) - return -1; - return 0; -} - - -void crypto_cipher_deinit(struct crypto_cipher *ctx) -{ - EVP_CIPHER_CTX_cleanup(&ctx->enc); - EVP_CIPHER_CTX_cleanup(&ctx->dec); - os_free(ctx); -} diff --git a/contrib/hostapd/src/crypto/des.c b/contrib/hostapd/src/crypto/des.c deleted file mode 100644 index 103e592461..0000000000 --- a/contrib/hostapd/src/crypto/des.c +++ /dev/null @@ -1,479 +0,0 @@ -/* - * DES and 3DES-EDE ciphers - * - * Modifications to LibTomCrypt implementation: - * Copyright (c) 2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto.h" - - -#ifdef INTERNAL_DES - -/* - * This implementation is based on a DES implementation included in - * LibTomCrypt. The version here is modified to fit in wpa_supplicant/hostapd - * coding style. - */ - -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com - */ - -/** - DES code submitted by Dobes Vandermeer -*/ - -#define ROLc(x, y) \ - ((((unsigned long) (x) << (unsigned long) ((y) & 31)) | \ - (((unsigned long) (x) & 0xFFFFFFFFUL) >> \ - (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL) -#define RORc(x, y) \ - (((((unsigned long) (x) & 0xFFFFFFFFUL) >> \ - (unsigned long) ((y) & 31)) | \ - ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & \ - 0xFFFFFFFFUL) - - -static const u32 bytebit[8] = -{ - 0200, 0100, 040, 020, 010, 04, 02, 01 -}; - -static const u32 bigbyte[24] = -{ - 0x800000UL, 0x400000UL, 0x200000UL, 0x100000UL, - 0x80000UL, 0x40000UL, 0x20000UL, 0x10000UL, - 0x8000UL, 0x4000UL, 0x2000UL, 0x1000UL, - 0x800UL, 0x400UL, 0x200UL, 0x100UL, - 0x80UL, 0x40UL, 0x20UL, 0x10UL, - 0x8UL, 0x4UL, 0x2UL, 0x1L -}; - -/* Use the key schedule specific in the standard (ANSI X3.92-1981) */ - -static const u8 pc1[56] = { - 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, - 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, - 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, - 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 -}; - -static const u8 totrot[16] = { - 1, 2, 4, 6, - 8, 10, 12, 14, - 15, 17, 19, 21, - 23, 25, 27, 28 -}; - -static const u8 pc2[48] = { - 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, - 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, - 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, - 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 -}; - - -static const u32 SP1[64] = -{ - 0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL, - 0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL, - 0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL, - 0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL, - 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL, - 0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL, - 0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL, - 0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL, - 0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL, - 0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL, - 0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL, - 0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL, - 0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL, - 0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL, - 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL, - 0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL -}; - -static const u32 SP2[64] = -{ - 0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL, - 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL, - 0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL, - 0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL, - 0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL, - 0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL, - 0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL, - 0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL, - 0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL, - 0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL, - 0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL, - 0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL, - 0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL, - 0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL, - 0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL, - 0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL -}; - -static const u32 SP3[64] = -{ - 0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL, - 0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL, - 0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL, - 0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL, - 0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL, - 0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL, - 0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL, - 0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL, - 0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL, - 0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL, - 0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL, - 0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL, - 0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL, - 0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL, - 0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL, - 0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL -}; - -static const u32 SP4[64] = -{ - 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, - 0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL, - 0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL, - 0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL, - 0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL, - 0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL, - 0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL, - 0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL, - 0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL, - 0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL, - 0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL, - 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, - 0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL, - 0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL, - 0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL, - 0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL -}; - -static const u32 SP5[64] = -{ - 0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL, - 0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL, - 0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL, - 0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL, - 0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL, - 0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL, - 0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL, - 0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL, - 0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL, - 0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL, - 0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL, - 0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL, - 0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL, - 0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL, - 0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL, - 0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL -}; - -static const u32 SP6[64] = -{ - 0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL, - 0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL, - 0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL, - 0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, - 0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL, - 0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL, - 0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL, - 0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL, - 0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL, - 0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL, - 0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, - 0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL, - 0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL, - 0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL, - 0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL, - 0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL -}; - -static const u32 SP7[64] = -{ - 0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL, - 0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL, - 0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL, - 0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL, - 0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL, - 0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL, - 0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL, - 0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL, - 0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL, - 0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL, - 0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL, - 0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL, - 0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL, - 0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL, - 0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL, - 0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL -}; - -static const u32 SP8[64] = -{ - 0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL, - 0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL, - 0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL, - 0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL, - 0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL, - 0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL, - 0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL, - 0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL, - 0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL, - 0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL, - 0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL, - 0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL, - 0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL, - 0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL, - 0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL, - 0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL -}; - - -static void cookey(const u32 *raw1, u32 *keyout) -{ - u32 *cook; - const u32 *raw0; - u32 dough[32]; - int i; - - cook = dough; - for (i = 0; i < 16; i++, raw1++) { - raw0 = raw1++; - *cook = (*raw0 & 0x00fc0000L) << 6; - *cook |= (*raw0 & 0x00000fc0L) << 10; - *cook |= (*raw1 & 0x00fc0000L) >> 10; - *cook++ |= (*raw1 & 0x00000fc0L) >> 6; - *cook = (*raw0 & 0x0003f000L) << 12; - *cook |= (*raw0 & 0x0000003fL) << 16; - *cook |= (*raw1 & 0x0003f000L) >> 4; - *cook++ |= (*raw1 & 0x0000003fL); - } - - os_memcpy(keyout, dough, sizeof(dough)); -} - - -static void deskey(const u8 *key, int decrypt, u32 *keyout) -{ - u32 i, j, l, m, n, kn[32]; - u8 pc1m[56], pcr[56]; - - for (j = 0; j < 56; j++) { - l = (u32) pc1[j]; - m = l & 7; - pc1m[j] = (u8) - ((key[l >> 3U] & bytebit[m]) == bytebit[m] ? 1 : 0); - } - - for (i = 0; i < 16; i++) { - if (decrypt) - m = (15 - i) << 1; - else - m = i << 1; - n = m + 1; - kn[m] = kn[n] = 0L; - for (j = 0; j < 28; j++) { - l = j + (u32) totrot[i]; - if (l < 28) - pcr[j] = pc1m[l]; - else - pcr[j] = pc1m[l - 28]; - } - for (/* j = 28 */; j < 56; j++) { - l = j + (u32) totrot[i]; - if (l < 56) - pcr[j] = pc1m[l]; - else - pcr[j] = pc1m[l - 28]; - } - for (j = 0; j < 24; j++) { - if ((int) pcr[(int) pc2[j]] != 0) - kn[m] |= bigbyte[j]; - if ((int) pcr[(int) pc2[j + 24]] != 0) - kn[n] |= bigbyte[j]; - } - } - - cookey(kn, keyout); -} - - -static void desfunc(u32 *block, const u32 *keys) -{ - u32 work, right, leftt; - int cur_round; - - leftt = block[0]; - right = block[1]; - - work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; - right ^= work; - leftt ^= (work << 4); - - work = ((leftt >> 16) ^ right) & 0x0000ffffL; - right ^= work; - leftt ^= (work << 16); - - work = ((right >> 2) ^ leftt) & 0x33333333L; - leftt ^= work; - right ^= (work << 2); - - work = ((right >> 8) ^ leftt) & 0x00ff00ffL; - leftt ^= work; - right ^= (work << 8); - - right = ROLc(right, 1); - work = (leftt ^ right) & 0xaaaaaaaaL; - - leftt ^= work; - right ^= work; - leftt = ROLc(leftt, 1); - - for (cur_round = 0; cur_round < 8; cur_round++) { - work = RORc(right, 4) ^ *keys++; - leftt ^= SP7[work & 0x3fL] - ^ SP5[(work >> 8) & 0x3fL] - ^ SP3[(work >> 16) & 0x3fL] - ^ SP1[(work >> 24) & 0x3fL]; - work = right ^ *keys++; - leftt ^= SP8[ work & 0x3fL] - ^ SP6[(work >> 8) & 0x3fL] - ^ SP4[(work >> 16) & 0x3fL] - ^ SP2[(work >> 24) & 0x3fL]; - - work = RORc(leftt, 4) ^ *keys++; - right ^= SP7[ work & 0x3fL] - ^ SP5[(work >> 8) & 0x3fL] - ^ SP3[(work >> 16) & 0x3fL] - ^ SP1[(work >> 24) & 0x3fL]; - work = leftt ^ *keys++; - right ^= SP8[ work & 0x3fL] - ^ SP6[(work >> 8) & 0x3fL] - ^ SP4[(work >> 16) & 0x3fL] - ^ SP2[(work >> 24) & 0x3fL]; - } - - right = RORc(right, 1); - work = (leftt ^ right) & 0xaaaaaaaaL; - leftt ^= work; - right ^= work; - leftt = RORc(leftt, 1); - work = ((leftt >> 8) ^ right) & 0x00ff00ffL; - right ^= work; - leftt ^= (work << 8); - /* -- */ - work = ((leftt >> 2) ^ right) & 0x33333333L; - right ^= work; - leftt ^= (work << 2); - work = ((right >> 16) ^ leftt) & 0x0000ffffL; - leftt ^= work; - right ^= (work << 16); - work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; - leftt ^= work; - right ^= (work << 4); - - block[0] = right; - block[1] = leftt; -} - - -/* wpa_supplicant/hostapd specific wrapper */ - -void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) -{ - u8 pkey[8], next, tmp; - int i; - u32 ek[32], work[2]; - - /* Add parity bits to the key */ - next = 0; - for (i = 0; i < 7; i++) { - tmp = key[i]; - pkey[i] = (tmp >> i) | next | 1; - next = tmp << (7 - i); - } - pkey[i] = next | 1; - - deskey(pkey, 0, ek); - - work[0] = WPA_GET_BE32(clear); - work[1] = WPA_GET_BE32(clear + 4); - desfunc(work, ek); - WPA_PUT_BE32(cypher, work[0]); - WPA_PUT_BE32(cypher + 4, work[1]); - - os_memset(pkey, 0, sizeof(pkey)); - os_memset(ek, 0, sizeof(ek)); -} - - -struct des3_key_s { - u32 ek[3][32]; - u32 dk[3][32]; -}; - -void des3_key_setup(const u8 *key, struct des3_key_s *dkey) -{ - deskey(key, 0, dkey->ek[0]); - deskey(key + 8, 1, dkey->ek[1]); - deskey(key + 16, 0, dkey->ek[2]); - - deskey(key, 1, dkey->dk[2]); - deskey(key + 8, 0, dkey->dk[1]); - deskey(key + 16, 1, dkey->dk[0]); -} - - -void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt) -{ - u32 work[2]; - - work[0] = WPA_GET_BE32(plain); - work[1] = WPA_GET_BE32(plain + 4); - desfunc(work, key->ek[0]); - desfunc(work, key->ek[1]); - desfunc(work, key->ek[2]); - WPA_PUT_BE32(crypt, work[0]); - WPA_PUT_BE32(crypt + 4, work[1]); -} - - -void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain) -{ - u32 work[2]; - - work[0] = WPA_GET_BE32(crypt); - work[1] = WPA_GET_BE32(crypt + 4); - desfunc(work, key->dk[0]); - desfunc(work, key->dk[1]); - desfunc(work, key->dk[2]); - WPA_PUT_BE32(plain, work[0]); - WPA_PUT_BE32(plain + 4, work[1]); -} - -#endif /* INTERNAL_DES */ diff --git a/contrib/hostapd/src/crypto/dh_groups.c b/contrib/hostapd/src/crypto/dh_groups.c deleted file mode 100644 index 5f6008a6e2..0000000000 --- a/contrib/hostapd/src/crypto/dh_groups.c +++ /dev/null @@ -1,630 +0,0 @@ -/* - * Diffie-Hellman groups - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto.h" -#include "dh_groups.h" - - -#ifdef ALL_DH_GROUPS - -/* RFC 4306, B.1. Group 1 - 768 Bit MODP - * Generator: 2 - * Prime: 2^768 - 2 ^704 - 1 + 2^64 * { [2^638 pi] + 149686 } - */ -static const u8 dh_group1_generator[1] = { 0x02 }; -static const u8 dh_group1_prime[96] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x3A, 0x36, 0x20, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -/* RFC 4306, B.2. Group 2 - 1024 Bit MODP - * Generator: 2 - * Prime: 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 } - */ -static const u8 dh_group2_generator[1] = { 0x02 }; -static const u8 dh_group2_prime[128] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -#endif /* ALL_DH_GROUPS */ - -/* RFC 3526, 2. Group 5 - 1536 Bit MODP - * Generator: 2 - * Prime: 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 } - */ -static const u8 dh_group5_generator[1] = { 0x02 }; -static const u8 dh_group5_prime[192] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -#ifdef ALL_DH_GROUPS - -/* RFC 3526, 3. Group 14 - 2048 Bit MODP - * Generator: 2 - * Prime: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 } - */ -static const u8 dh_group14_generator[1] = { 0x02 }; -static const u8 dh_group14_prime[256] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, - 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, - 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, - 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, - 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, - 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, - 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, - 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -/* RFC 3526, 4. Group 15 - 3072 Bit MODP - * Generator: 2 - * Prime: 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 } - */ -static const u8 dh_group15_generator[1] = { 0x02 }; -static const u8 dh_group15_prime[384] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, - 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, - 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, - 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, - 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, - 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, - 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, - 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, - 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, - 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, - 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, - 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, - 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, - 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, - 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, - 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, - 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, - 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, - 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, - 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, - 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, - 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, - 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, - 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -/* RFC 3526, 5. Group 16 - 4096 Bit MODP - * Generator: 2 - * Prime: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 } - */ -static const u8 dh_group16_generator[1] = { 0x02 }; -static const u8 dh_group16_prime[512] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, - 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, - 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, - 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, - 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, - 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, - 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, - 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, - 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, - 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, - 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, - 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, - 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, - 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, - 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, - 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, - 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, - 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, - 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, - 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, - 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, - 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, - 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, - 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, - 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, - 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, - 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, - 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, - 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, - 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, - 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, - 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, - 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, - 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, - 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, - 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, - 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, - 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, - 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, - 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -/* RFC 3526, 6. Group 17 - 6144 Bit MODP - * Generator: 2 - * Prime: 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 } - */ -static const u8 dh_group17_generator[1] = { 0x02 }; -static const u8 dh_group17_prime[768] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, - 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, - 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, - 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, - 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, - 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, - 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, - 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, - 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, - 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, - 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, - 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, - 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, - 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, - 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, - 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, - 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, - 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, - 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, - 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, - 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, - 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, - 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, - 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, - 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, - 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, - 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, - 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, - 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, - 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, - 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, - 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, - 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, - 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, - 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, - 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, - 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, - 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, - 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, - 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, - 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, - 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, - 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, - 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, - 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, - 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, - 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, - 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, - 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, - 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, - 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, - 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, - 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, - 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, - 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, - 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, - 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, - 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, - 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, - 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, - 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, - 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, - 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, - 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, - 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, - 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, - 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, - 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, - 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, - 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, - 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, - 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xCC, 0x40, 0x24, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -/* RFC 3526, 7. Group 18 - 8192 Bit MODP - * Generator: 2 - * Prime: 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 } - */ -static const u8 dh_group18_generator[1] = { 0x02 }; -static const u8 dh_group18_prime[1024] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, - 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, - 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, - 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, - 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, - 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, - 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, - 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, - 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, - 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, - 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, - 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, - 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, - 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, - 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, - 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, - 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, - 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, - 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, - 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, - 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, - 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, - 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, - 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, - 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, - 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, - 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, - 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, - 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, - 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, - 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, - 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, - 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, - 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, - 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, - 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, - 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, - 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, - 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, - 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, - 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, - 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, - 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, - 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, - 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, - 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, - 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, - 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, - 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, - 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, - 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, - 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, - 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, - 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, - 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, - 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, - 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, - 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, - 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, - 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, - 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, - 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, - 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, - 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, - 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, - 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, - 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, - 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, - 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, - 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, - 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, - 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xBE, 0x11, 0x59, - 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4, - 0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, - 0xD8, 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA, - 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00, - 0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, - 0x25, 0x76, 0xF6, 0x93, 0x6B, 0xA4, 0x24, 0x66, - 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68, - 0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, - 0x23, 0x8F, 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D, - 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9, - 0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, - 0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, 0xF0, 0xC7, - 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B, - 0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, - 0xFA, 0x9D, 0x4B, 0x7F, 0xA2, 0xC0, 0x87, 0xE8, - 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A, - 0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, - 0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, 0x2D, - 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36, - 0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, - 0x64, 0xF3, 0x1C, 0xC5, 0x08, 0x46, 0x85, 0x1D, - 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1, - 0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, - 0xFA, 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68, - 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92, - 0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, - 0x88, 0x9A, 0x00, 0x2E, 0xD5, 0xEE, 0x38, 0x2B, - 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47, - 0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, - 0x9E, 0x30, 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF, - 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71, - 0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -#endif /* ALL_DH_GROUPS */ - - -#define DH_GROUP(id) \ -{ id, dh_group ## id ## _generator, sizeof(dh_group ## id ## _generator), \ -dh_group ## id ## _prime, sizeof(dh_group ## id ## _prime) } - - -static struct dh_group dh_groups[] = { - DH_GROUP(5), -#ifdef ALL_DH_GROUPS - DH_GROUP(1), - DH_GROUP(2), - DH_GROUP(14), - DH_GROUP(15), - DH_GROUP(16), - DH_GROUP(17), - DH_GROUP(18) -#endif /* ALL_DH_GROUPS */ -}; - -#define NUM_DH_GROUPS (sizeof(dh_groups) / sizeof(dh_groups[0])) - - -const struct dh_group * dh_groups_get(int id) -{ - size_t i; - - for (i = 0; i < NUM_DH_GROUPS; i++) { - if (dh_groups[i].id == id) - return &dh_groups[i]; - } - return NULL; -} - - -/** - * dh_init - Initialize Diffie-Hellman handshake - * @dh: Selected Diffie-Hellman group - * @priv: Pointer for returning Diffie-Hellman private key - * Returns: Diffie-Hellman public value - */ -struct wpabuf * dh_init(const struct dh_group *dh, struct wpabuf **priv) -{ - struct wpabuf *pv; - size_t pv_len; - - if (dh == NULL) - return NULL; - - wpabuf_free(*priv); - *priv = wpabuf_alloc(dh->prime_len); - if (*priv == NULL) - return NULL; - - if (os_get_random(wpabuf_put(*priv, dh->prime_len), dh->prime_len)) { - wpabuf_free(*priv); - *priv = NULL; - return NULL; - } - - if (os_memcmp(wpabuf_head(*priv), dh->prime, dh->prime_len) > 0) { - /* Make sure private value is smaller than prime */ - *(wpabuf_mhead_u8(*priv)) = 0; - } - wpa_hexdump_buf_key(MSG_DEBUG, "DH: private value", *priv); - - pv_len = dh->prime_len; - pv = wpabuf_alloc(pv_len); - if (pv == NULL) - return NULL; - if (crypto_mod_exp(dh->generator, dh->generator_len, - wpabuf_head(*priv), wpabuf_len(*priv), - dh->prime, dh->prime_len, wpabuf_mhead(pv), - &pv_len) < 0) { - wpabuf_free(pv); - wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed"); - return NULL; - } - wpabuf_put(pv, pv_len); - wpa_hexdump_buf(MSG_DEBUG, "DH: public value", pv); - - return pv; -} - - -/** - * dh_derive_shared - Derive shared Diffie-Hellman key - * @peer_public: Diffie-Hellman public value from peer - * @own_private: Diffie-Hellman private key from dh_init() - * @dh: Selected Diffie-Hellman group - * Returns: Diffie-Hellman shared key - */ -struct wpabuf * dh_derive_shared(const struct wpabuf *peer_public, - const struct wpabuf *own_private, - const struct dh_group *dh) -{ - struct wpabuf *shared; - size_t shared_len; - - if (dh == NULL || peer_public == NULL || own_private == NULL) - return NULL; - - shared_len = dh->prime_len; - shared = wpabuf_alloc(shared_len); - if (shared == NULL) - return NULL; - if (crypto_mod_exp(wpabuf_head(peer_public), wpabuf_len(peer_public), - wpabuf_head(own_private), wpabuf_len(own_private), - dh->prime, dh->prime_len, - wpabuf_put(shared, shared_len), &shared_len) < 0) { - wpabuf_free(shared); - wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed"); - return NULL; - } - wpa_hexdump_buf_key(MSG_DEBUG, "DH: shared key", shared); - - return shared; -} diff --git a/contrib/hostapd/src/crypto/dh_groups.h b/contrib/hostapd/src/crypto/dh_groups.h deleted file mode 100644 index 5c61539b70..0000000000 --- a/contrib/hostapd/src/crypto/dh_groups.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Diffie-Hellman groups - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef DH_GROUPS_H -#define DH_GROUPS_H - -struct dh_group { - int id; - const u8 *generator; - size_t generator_len; - const u8 *prime; - size_t prime_len; -}; - -const struct dh_group * dh_groups_get(int id); -struct wpabuf * dh_init(const struct dh_group *dh, struct wpabuf **priv); -struct wpabuf * dh_derive_shared(const struct wpabuf *peer_public, - const struct wpabuf *own_private, - const struct dh_group *dh); - -#endif /* DH_GROUPS_H */ diff --git a/contrib/hostapd/src/crypto/md4.c b/contrib/hostapd/src/crypto/md4.c deleted file mode 100644 index 41c84a3a7b..0000000000 --- a/contrib/hostapd/src/crypto/md4.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * MD4 hash implementation - * Copyright (c) 2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto.h" - - -#ifdef INTERNAL_MD4 - -#define MD4_BLOCK_LENGTH 64 -#define MD4_DIGEST_LENGTH 16 - -typedef struct MD4Context { - u32 state[4]; /* state */ - u64 count; /* number of bits, mod 2^64 */ - u8 buffer[MD4_BLOCK_LENGTH]; /* input buffer */ -} MD4_CTX; - - -static void MD4Init(MD4_CTX *ctx); -static void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len); -static void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx); - - -void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - MD4_CTX ctx; - size_t i; - - MD4Init(&ctx); - for (i = 0; i < num_elem; i++) - MD4Update(&ctx, addr[i], len[i]); - MD4Final(mac, &ctx); -} - - -/* ===== start - public domain MD4 implementation ===== */ -/* $OpenBSD: md4.c,v 1.7 2005/08/08 08:05:35 espie Exp $ */ - -/* - * This code implements the MD4 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * Todd C. Miller modified the MD5 code to do MD4 based on RFC 1186. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD4Context structure, pass it to MD4Init, call MD4Update as - * needed on buffers full of bytes, and then call MD4Final, which - * will fill a supplied 16-byte array with the digest. - */ - -#define MD4_DIGEST_STRING_LENGTH (MD4_DIGEST_LENGTH * 2 + 1) - - -static void -MD4Transform(u32 state[4], const u8 block[MD4_BLOCK_LENGTH]); - -#define PUT_64BIT_LE(cp, value) do { \ - (cp)[7] = (value) >> 56; \ - (cp)[6] = (value) >> 48; \ - (cp)[5] = (value) >> 40; \ - (cp)[4] = (value) >> 32; \ - (cp)[3] = (value) >> 24; \ - (cp)[2] = (value) >> 16; \ - (cp)[1] = (value) >> 8; \ - (cp)[0] = (value); } while (0) - -#define PUT_32BIT_LE(cp, value) do { \ - (cp)[3] = (value) >> 24; \ - (cp)[2] = (value) >> 16; \ - (cp)[1] = (value) >> 8; \ - (cp)[0] = (value); } while (0) - -static u8 PADDING[MD4_BLOCK_LENGTH] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * Start MD4 accumulation. - * Set bit count to 0 and buffer to mysterious initialization constants. - */ -static void MD4Init(MD4_CTX *ctx) -{ - ctx->count = 0; - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xefcdab89; - ctx->state[2] = 0x98badcfe; - ctx->state[3] = 0x10325476; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -static void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len) -{ - size_t have, need; - - /* Check how many bytes we already have and how many more we need. */ - have = (size_t)((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1)); - need = MD4_BLOCK_LENGTH - have; - - /* Update bitcount */ - ctx->count += (u64)len << 3; - - if (len >= need) { - if (have != 0) { - os_memcpy(ctx->buffer + have, input, need); - MD4Transform(ctx->state, ctx->buffer); - input += need; - len -= need; - have = 0; - } - - /* Process data in MD4_BLOCK_LENGTH-byte chunks. */ - while (len >= MD4_BLOCK_LENGTH) { - MD4Transform(ctx->state, input); - input += MD4_BLOCK_LENGTH; - len -= MD4_BLOCK_LENGTH; - } - } - - /* Handle any remaining bytes of data. */ - if (len != 0) - os_memcpy(ctx->buffer + have, input, len); -} - -/* - * Pad pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -static void MD4Pad(MD4_CTX *ctx) -{ - u8 count[8]; - size_t padlen; - - /* Convert count to 8 bytes in little endian order. */ - PUT_64BIT_LE(count, ctx->count); - - /* Pad out to 56 mod 64. */ - padlen = MD4_BLOCK_LENGTH - - ((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1)); - if (padlen < 1 + 8) - padlen += MD4_BLOCK_LENGTH; - MD4Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */ - MD4Update(ctx, count, 8); -} - -/* - * Final wrapup--call MD4Pad, fill in digest and zero out ctx. - */ -static void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx) -{ - int i; - - MD4Pad(ctx); - if (digest != NULL) { - for (i = 0; i < 4; i++) - PUT_32BIT_LE(digest + i * 4, ctx->state[i]); - os_memset(ctx, 0, sizeof(*ctx)); - } -} - - -/* The three core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) ((x & y) | (x & z) | (y & z)) -#define F3(x, y, z) (x ^ y ^ z) - -/* This is the central step in the MD4 algorithm. */ -#define MD4STEP(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w = w<>(32-s) ) - -/* - * The core of the MD4 algorithm, this alters an existing MD4 hash to - * reflect the addition of 16 longwords of new data. MD4Update blocks - * the data and converts bytes into longwords for this routine. - */ -static void -MD4Transform(u32 state[4], const u8 block[MD4_BLOCK_LENGTH]) -{ - u32 a, b, c, d, in[MD4_BLOCK_LENGTH / 4]; - -#if BYTE_ORDER == LITTLE_ENDIAN - os_memcpy(in, block, sizeof(in)); -#else - for (a = 0; a < MD4_BLOCK_LENGTH / 4; a++) { - in[a] = (u32)( - (u32)(block[a * 4 + 0]) | - (u32)(block[a * 4 + 1]) << 8 | - (u32)(block[a * 4 + 2]) << 16 | - (u32)(block[a * 4 + 3]) << 24); - } -#endif - - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - - MD4STEP(F1, a, b, c, d, in[ 0], 3); - MD4STEP(F1, d, a, b, c, in[ 1], 7); - MD4STEP(F1, c, d, a, b, in[ 2], 11); - MD4STEP(F1, b, c, d, a, in[ 3], 19); - MD4STEP(F1, a, b, c, d, in[ 4], 3); - MD4STEP(F1, d, a, b, c, in[ 5], 7); - MD4STEP(F1, c, d, a, b, in[ 6], 11); - MD4STEP(F1, b, c, d, a, in[ 7], 19); - MD4STEP(F1, a, b, c, d, in[ 8], 3); - MD4STEP(F1, d, a, b, c, in[ 9], 7); - MD4STEP(F1, c, d, a, b, in[10], 11); - MD4STEP(F1, b, c, d, a, in[11], 19); - MD4STEP(F1, a, b, c, d, in[12], 3); - MD4STEP(F1, d, a, b, c, in[13], 7); - MD4STEP(F1, c, d, a, b, in[14], 11); - MD4STEP(F1, b, c, d, a, in[15], 19); - - MD4STEP(F2, a, b, c, d, in[ 0] + 0x5a827999, 3); - MD4STEP(F2, d, a, b, c, in[ 4] + 0x5a827999, 5); - MD4STEP(F2, c, d, a, b, in[ 8] + 0x5a827999, 9); - MD4STEP(F2, b, c, d, a, in[12] + 0x5a827999, 13); - MD4STEP(F2, a, b, c, d, in[ 1] + 0x5a827999, 3); - MD4STEP(F2, d, a, b, c, in[ 5] + 0x5a827999, 5); - MD4STEP(F2, c, d, a, b, in[ 9] + 0x5a827999, 9); - MD4STEP(F2, b, c, d, a, in[13] + 0x5a827999, 13); - MD4STEP(F2, a, b, c, d, in[ 2] + 0x5a827999, 3); - MD4STEP(F2, d, a, b, c, in[ 6] + 0x5a827999, 5); - MD4STEP(F2, c, d, a, b, in[10] + 0x5a827999, 9); - MD4STEP(F2, b, c, d, a, in[14] + 0x5a827999, 13); - MD4STEP(F2, a, b, c, d, in[ 3] + 0x5a827999, 3); - MD4STEP(F2, d, a, b, c, in[ 7] + 0x5a827999, 5); - MD4STEP(F2, c, d, a, b, in[11] + 0x5a827999, 9); - MD4STEP(F2, b, c, d, a, in[15] + 0x5a827999, 13); - - MD4STEP(F3, a, b, c, d, in[ 0] + 0x6ed9eba1, 3); - MD4STEP(F3, d, a, b, c, in[ 8] + 0x6ed9eba1, 9); - MD4STEP(F3, c, d, a, b, in[ 4] + 0x6ed9eba1, 11); - MD4STEP(F3, b, c, d, a, in[12] + 0x6ed9eba1, 15); - MD4STEP(F3, a, b, c, d, in[ 2] + 0x6ed9eba1, 3); - MD4STEP(F3, d, a, b, c, in[10] + 0x6ed9eba1, 9); - MD4STEP(F3, c, d, a, b, in[ 6] + 0x6ed9eba1, 11); - MD4STEP(F3, b, c, d, a, in[14] + 0x6ed9eba1, 15); - MD4STEP(F3, a, b, c, d, in[ 1] + 0x6ed9eba1, 3); - MD4STEP(F3, d, a, b, c, in[ 9] + 0x6ed9eba1, 9); - MD4STEP(F3, c, d, a, b, in[ 5] + 0x6ed9eba1, 11); - MD4STEP(F3, b, c, d, a, in[13] + 0x6ed9eba1, 15); - MD4STEP(F3, a, b, c, d, in[ 3] + 0x6ed9eba1, 3); - MD4STEP(F3, d, a, b, c, in[11] + 0x6ed9eba1, 9); - MD4STEP(F3, c, d, a, b, in[ 7] + 0x6ed9eba1, 11); - MD4STEP(F3, b, c, d, a, in[15] + 0x6ed9eba1, 15); - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; -} -/* ===== end - public domain MD4 implementation ===== */ - -#endif /* INTERNAL_MD4 */ diff --git a/contrib/hostapd/src/crypto/md5.c b/contrib/hostapd/src/crypto/md5.c deleted file mode 100644 index e13ce7d497..0000000000 --- a/contrib/hostapd/src/crypto/md5.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - * MD5 hash implementation and interface functions - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "md5.h" -#include "crypto.h" - - -/** - * hmac_md5_vector - HMAC-MD5 over data vector (RFC 2104) - * @key: Key for HMAC operations - * @key_len: Length of the key in bytes - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash (16 bytes) - */ -void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac) -{ - u8 k_pad[64]; /* padding - key XORd with ipad/opad */ - u8 tk[16]; - const u8 *_addr[6]; - size_t i, _len[6]; - - if (num_elem > 5) { - /* - * Fixed limit on the number of fragments to avoid having to - * allocate memory (which could fail). - */ - return; - } - - /* if key is longer than 64 bytes reset it to key = MD5(key) */ - if (key_len > 64) { - md5_vector(1, &key, &key_len, tk); - key = tk; - key_len = 16; - } - - /* the HMAC_MD5 transform looks like: - * - * MD5(K XOR opad, MD5(K XOR ipad, text)) - * - * where K is an n byte key - * ipad is the byte 0x36 repeated 64 times - * opad is the byte 0x5c repeated 64 times - * and text is the data being protected */ - - /* start out by storing key in ipad */ - os_memset(k_pad, 0, sizeof(k_pad)); - os_memcpy(k_pad, key, key_len); - - /* XOR key with ipad values */ - for (i = 0; i < 64; i++) - k_pad[i] ^= 0x36; - - /* perform inner MD5 */ - _addr[0] = k_pad; - _len[0] = 64; - for (i = 0; i < num_elem; i++) { - _addr[i + 1] = addr[i]; - _len[i + 1] = len[i]; - } - md5_vector(1 + num_elem, _addr, _len, mac); - - os_memset(k_pad, 0, sizeof(k_pad)); - os_memcpy(k_pad, key, key_len); - /* XOR key with opad values */ - for (i = 0; i < 64; i++) - k_pad[i] ^= 0x5c; - - /* perform outer MD5 */ - _addr[0] = k_pad; - _len[0] = 64; - _addr[1] = mac; - _len[1] = MD5_MAC_LEN; - md5_vector(2, _addr, _len, mac); -} - - -/** - * hmac_md5 - HMAC-MD5 over data buffer (RFC 2104) - * @key: Key for HMAC operations - * @key_len: Length of the key in bytes - * @data: Pointers to the data area - * @data_len: Length of the data area - * @mac: Buffer for the hash (16 bytes) - */ -void hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac) -{ - hmac_md5_vector(key, key_len, 1, &data, &data_len, mac); -} - - -#ifdef INTERNAL_MD5 - -struct MD5Context { - u32 buf[4]; - u32 bits[2]; - u8 in[64]; -}; - -#ifndef CONFIG_CRYPTO_INTERNAL -static void MD5Init(struct MD5Context *context); -static void MD5Update(struct MD5Context *context, unsigned char const *buf, - unsigned len); -static void MD5Final(unsigned char digest[16], struct MD5Context *context); -#endif /* CONFIG_CRYPTO_INTERNAL */ -static void MD5Transform(u32 buf[4], u32 const in[16]); - - -typedef struct MD5Context MD5_CTX; - - -/** - * md5_vector - MD5 hash for data vector - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash - */ -void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - MD5_CTX ctx; - size_t i; - - MD5Init(&ctx); - for (i = 0; i < num_elem; i++) - MD5Update(&ctx, addr[i], len[i]); - MD5Final(mac, &ctx); -} - - -/* ===== start - public domain MD5 implementation ===== */ -/* - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - */ - -#ifndef WORDS_BIGENDIAN -#define byteReverse(buf, len) /* Nothing */ -#else -/* - * Note: this code is harmless on little-endian machines. - */ -static void byteReverse(unsigned char *buf, unsigned longs) -{ - u32 t; - do { - t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | - ((unsigned) buf[1] << 8 | buf[0]); - *(u32 *) buf = t; - buf += 4; - } while (--longs); -} -#endif - -/* - * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ -void MD5Init(struct MD5Context *ctx) -{ - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - - ctx->bits[0] = 0; - ctx->bits[1] = 0; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) -{ - u32 t; - - /* Update bitcount */ - - t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((u32) len << 3)) < t) - ctx->bits[1]++; /* Carry from low to high */ - ctx->bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - - /* Handle any leading odd-sized chunks */ - - if (t) { - unsigned char *p = (unsigned char *) ctx->in + t; - - t = 64 - t; - if (len < t) { - os_memcpy(p, buf, len); - return; - } - os_memcpy(p, buf, t); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (u32 *) ctx->in); - buf += t; - len -= t; - } - /* Process data in 64-byte chunks */ - - while (len >= 64) { - os_memcpy(ctx->in, buf, 64); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (u32 *) ctx->in); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - - os_memcpy(ctx->in, buf, len); -} - -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -void MD5Final(unsigned char digest[16], struct MD5Context *ctx) -{ - unsigned count; - unsigned char *p; - - /* Compute number of bytes mod 64 */ - count = (ctx->bits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = ctx->in + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - os_memset(p, 0, count); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (u32 *) ctx->in); - - /* Now fill the next block with 56 bytes */ - os_memset(ctx->in, 0, 56); - } else { - /* Pad block to 56 bytes */ - os_memset(p, 0, count - 8); - } - byteReverse(ctx->in, 14); - - /* Append length in bits and transform */ - ((u32 *) ctx->in)[14] = ctx->bits[0]; - ((u32 *) ctx->in)[15] = ctx->bits[1]; - - MD5Transform(ctx->buf, (u32 *) ctx->in); - byteReverse((unsigned char *) ctx->buf, 4); - os_memcpy(digest, ctx->buf, 16); - os_memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ -} - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ -static void MD5Transform(u32 buf[4], u32 const in[16]) -{ - register u32 a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} -/* ===== end - public domain MD5 implementation ===== */ - -#endif /* INTERNAL_MD5 */ diff --git a/contrib/hostapd/src/crypto/md5.h b/contrib/hostapd/src/crypto/md5.h deleted file mode 100644 index e82f3969ed..0000000000 --- a/contrib/hostapd/src/crypto/md5.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * MD5 hash implementation and interface functions - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef MD5_H -#define MD5_H - -#define MD5_MAC_LEN 16 - -void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); -void hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac); - -#ifdef CONFIG_CRYPTO_INTERNAL -struct MD5Context; - -void MD5Init(struct MD5Context *context); -void MD5Update(struct MD5Context *context, unsigned char const *buf, - unsigned len); -void MD5Final(unsigned char digest[16], struct MD5Context *context); -#endif /* CONFIG_CRYPTO_INTERNAL */ - -#endif /* MD5_H */ diff --git a/contrib/hostapd/src/crypto/ms_funcs.c b/contrib/hostapd/src/crypto/ms_funcs.c deleted file mode 100644 index 7e2f0fa377..0000000000 --- a/contrib/hostapd/src/crypto/ms_funcs.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759 - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha1.h" -#include "ms_funcs.h" -#include "crypto.h" -#include "rc4.h" - - -/** - * challenge_hash - ChallengeHash() - RFC 2759, Sect. 8.2 - * @peer_challenge: 16-octet PeerChallenge (IN) - * @auth_challenge: 16-octet AuthenticatorChallenge (IN) - * @username: 0-to-256-char UserName (IN) - * @username_len: Length of username - * @challenge: 8-octet Challenge (OUT) - */ -static void challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge, - const u8 *username, size_t username_len, - u8 *challenge) -{ - u8 hash[SHA1_MAC_LEN]; - const unsigned char *addr[3]; - size_t len[3]; - - addr[0] = peer_challenge; - len[0] = 16; - addr[1] = auth_challenge; - len[1] = 16; - addr[2] = username; - len[2] = username_len; - - sha1_vector(3, addr, len, hash); - os_memcpy(challenge, hash, 8); -} - - -/** - * nt_password_hash - NtPasswordHash() - RFC 2759, Sect. 8.3 - * @password: 0-to-256-unicode-char Password (IN; ASCII) - * @password_len: Length of password - * @password_hash: 16-octet PasswordHash (OUT) - */ -void nt_password_hash(const u8 *password, size_t password_len, - u8 *password_hash) -{ - u8 buf[512], *pos; - size_t i, len; - - if (password_len > 256) - password_len = 256; - - /* Convert password into unicode */ - for (i = 0; i < password_len; i++) { - buf[2 * i] = password[i]; - buf[2 * i + 1] = 0; - } - - len = password_len * 2; - pos = buf; - md4_vector(1, (const u8 **) &pos, &len, password_hash); -} - - -/** - * hash_nt_password_hash - HashNtPasswordHash() - RFC 2759, Sect. 8.4 - * @password_hash: 16-octet PasswordHash (IN) - * @password_hash_hash: 16-octet PasswordHashHash (OUT) - */ -void hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash) -{ - size_t len = 16; - md4_vector(1, &password_hash, &len, password_hash_hash); -} - - -/** - * challenge_response - ChallengeResponse() - RFC 2759, Sect. 8.5 - * @challenge: 8-octet Challenge (IN) - * @password_hash: 16-octet PasswordHash (IN) - * @response: 24-octet Response (OUT) - */ -void 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); - zpwd[0] = password_hash[14]; - zpwd[1] = password_hash[15]; - os_memset(zpwd + 2, 0, 5); - des_encrypt(challenge, zpwd, response + 16); -} - - -/** - * generate_nt_response - GenerateNTResponse() - RFC 2759, Sect. 8.1 - * @auth_challenge: 16-octet AuthenticatorChallenge (IN) - * @peer_challenge: 16-octet PeerChallenge (IN) - * @username: 0-to-256-char UserName (IN) - * @username_len: Length of username - * @password: 0-to-256-unicode-char Password (IN; ASCII) - * @password_len: Length of password - * @response: 24-octet Response (OUT) - */ -void generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge, - const u8 *username, size_t username_len, - const u8 *password, size_t password_len, - u8 *response) -{ - u8 challenge[8]; - u8 password_hash[16]; - - challenge_hash(peer_challenge, auth_challenge, username, username_len, - challenge); - nt_password_hash(password, password_len, password_hash); - challenge_response(challenge, password_hash, response); -} - - -/** - * generate_nt_response_pwhash - GenerateNTResponse() - RFC 2759, Sect. 8.1 - * @auth_challenge: 16-octet AuthenticatorChallenge (IN) - * @peer_challenge: 16-octet PeerChallenge (IN) - * @username: 0-to-256-char UserName (IN) - * @username_len: Length of username - * @password_hash: 16-octet PasswordHash (IN) - * @response: 24-octet Response (OUT) - */ -void generate_nt_response_pwhash(const u8 *auth_challenge, - const u8 *peer_challenge, - const u8 *username, size_t username_len, - const u8 *password_hash, - u8 *response) -{ - u8 challenge[8]; - - challenge_hash(peer_challenge, auth_challenge, username, username_len, - challenge); - challenge_response(challenge, password_hash, response); -} - - -/** - * generate_authenticator_response_pwhash - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7 - * @password_hash: 16-octet PasswordHash (IN) - * @nt_response: 24-octet NT-Response (IN) - * @peer_challenge: 16-octet PeerChallenge (IN) - * @auth_challenge: 16-octet AuthenticatorChallenge (IN) - * @username: 0-to-256-char UserName (IN) - * @username_len: Length of username - * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually - * encoded as a 42-octet ASCII string (S=hexdump_of_response) - */ -void generate_authenticator_response_pwhash( - const u8 *password_hash, - const u8 *peer_challenge, const u8 *auth_challenge, - const u8 *username, size_t username_len, - const u8 *nt_response, u8 *response) -{ - static const u8 magic1[39] = { - 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, - 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, - 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 - }; - static const u8 magic2[41] = { - 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, - 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, - 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, - 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, - 0x6E - }; - - u8 password_hash_hash[16], challenge[8]; - const unsigned char *addr1[3]; - const size_t len1[3] = { 16, 24, sizeof(magic1) }; - const unsigned char *addr2[3]; - const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) }; - - addr1[0] = password_hash_hash; - addr1[1] = nt_response; - addr1[2] = magic1; - - addr2[0] = response; - addr2[1] = challenge; - addr2[2] = magic2; - - hash_nt_password_hash(password_hash, password_hash_hash); - sha1_vector(3, addr1, len1, response); - - challenge_hash(peer_challenge, auth_challenge, username, username_len, - challenge); - sha1_vector(3, addr2, len2, response); -} - - -/** - * generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7 - * @password: 0-to-256-unicode-char Password (IN; ASCII) - * @password_len: Length of password - * @nt_response: 24-octet NT-Response (IN) - * @peer_challenge: 16-octet PeerChallenge (IN) - * @auth_challenge: 16-octet AuthenticatorChallenge (IN) - * @username: 0-to-256-char UserName (IN) - * @username_len: Length of username - * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually - * encoded as a 42-octet ASCII string (S=hexdump_of_response) - */ -void generate_authenticator_response(const u8 *password, size_t password_len, - const u8 *peer_challenge, - const u8 *auth_challenge, - const u8 *username, size_t username_len, - const u8 *nt_response, u8 *response) -{ - u8 password_hash[16]; - nt_password_hash(password, password_len, password_hash); - generate_authenticator_response_pwhash(password_hash, - peer_challenge, auth_challenge, - username, username_len, - nt_response, response); -} - - -/** - * nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5 - * @challenge: 8-octet Challenge (IN) - * @password: 0-to-256-unicode-char Password (IN; ASCII) - * @password_len: Length of password - * @response: 24-octet Response (OUT) - */ -void nt_challenge_response(const u8 *challenge, const u8 *password, - size_t password_len, u8 *response) -{ - u8 password_hash[16]; - nt_password_hash(password, password_len, password_hash); - challenge_response(challenge, password_hash, response); -} - - -/** - * get_master_key - GetMasterKey() - RFC 3079, Sect. 3.4 - * @password_hash_hash: 16-octet PasswordHashHash (IN) - * @nt_response: 24-octet NTResponse (IN) - * @master_key: 16-octet MasterKey (OUT) - */ -void get_master_key(const u8 *password_hash_hash, const u8 *nt_response, - u8 *master_key) -{ - static const u8 magic1[27] = { - 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, - 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 - }; - const unsigned char *addr[3]; - const size_t len[3] = { 16, 24, sizeof(magic1) }; - u8 hash[SHA1_MAC_LEN]; - - addr[0] = password_hash_hash; - addr[1] = nt_response; - addr[2] = magic1; - - sha1_vector(3, addr, len, hash); - os_memcpy(master_key, hash, 16); -} - - -/** - * get_asymetric_start_key - GetAsymetricStartKey() - RFC 3079, Sect. 3.4 - * @master_key: 16-octet MasterKey (IN) - * @session_key: 8-to-16 octet SessionKey (OUT) - * @session_key_len: SessionKeyLength (Length of session_key) (IN) - * @is_send: IsSend (IN, BOOLEAN) - * @is_server: IsServer (IN, BOOLEAN) - */ -void get_asymetric_start_key(const u8 *master_key, u8 *session_key, - size_t session_key_len, int is_send, - int is_server) -{ - static const u8 magic2[84] = { - 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, - 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, - 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, - 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, - 0x6b, 0x65, 0x79, 0x2e - }; - static const u8 magic3[84] = { - 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, - 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, - 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, - 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, - 0x6b, 0x65, 0x79, 0x2e - }; - static const u8 shs_pad1[40] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static const u8 shs_pad2[40] = { - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 - }; - u8 digest[SHA1_MAC_LEN]; - const unsigned char *addr[4]; - const size_t len[4] = { 16, 40, 84, 40 }; - - addr[0] = master_key; - addr[1] = shs_pad1; - if (is_send) { - addr[2] = is_server ? magic3 : magic2; - } else { - addr[2] = is_server ? magic2 : magic3; - } - addr[3] = shs_pad2; - - sha1_vector(4, addr, len, digest); - - if (session_key_len > SHA1_MAC_LEN) - session_key_len = SHA1_MAC_LEN; - os_memcpy(session_key, digest, session_key_len); -} - - -#define PWBLOCK_LEN 516 - -/** - * encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10 - * @password: 0-to-256-unicode-char Password (IN; ASCII) - * @password_len: Length of password - * @password_hash: 16-octet PasswordHash (IN) - * @pw_block: 516-byte PwBlock (OUT) - * Returns: 0 on success, -1 on failure - */ -int encrypt_pw_block_with_password_hash( - const u8 *password, size_t password_len, - const u8 *password_hash, u8 *pw_block) -{ - size_t i, offset; - u8 *pos; - - if (password_len > 256) - return -1; - - os_memset(pw_block, 0, PWBLOCK_LEN); - offset = (256 - password_len) * 2; - if (os_get_random(pw_block, offset) < 0) - return -1; - for (i = 0; i < password_len; i++) - pw_block[offset + i * 2] = password[i]; - /* - * PasswordLength is 4 octets, but since the maximum password length is - * 256, only first two (in little endian byte order) can be non-zero. - */ - pos = &pw_block[2 * 256]; - WPA_PUT_LE16(pos, password_len * 2); - rc4_skip(password_hash, 16, 0, pw_block, PWBLOCK_LEN); - return 0; -} - - -/** - * new_password_encrypted_with_old_nt_password_hash - NewPasswordEncryptedWithOldNtPasswordHash() - RFC 2759, Sect. 8.9 - * @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII) - * @new_password_len: Length of new_password - * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII) - * @old_password_len: Length of old_password - * @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT) - * Returns: 0 on success, -1 on failure - */ -int 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) -{ - u8 password_hash[16]; - - nt_password_hash(old_password, old_password_len, password_hash); - if (encrypt_pw_block_with_password_hash(new_password, new_password_len, - password_hash, - encrypted_pw_block)) - return -1; - return 0; -} - - -/** - * nt_password_hash_encrypted_with_block - NtPasswordHashEncryptedWithBlock() - RFC 2759, Sect 8.13 - * @password_hash: 16-octer PasswordHash (IN) - * @block: 16-octet Block (IN) - * @cypher: 16-octer Cypher (OUT) - */ -void 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); -} - - -/** - * old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12 - * @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII) - * @new_password_len: Length of new_password - * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII) - * @old_password_len: Length of old_password - * @encrypted_password_hash: 16-octet EncryptedPasswordHash (OUT) - */ -void 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, - u8 *encrypted_password_hash) -{ - u8 old_password_hash[16], new_password_hash[16]; - - nt_password_hash(old_password, old_password_len, old_password_hash); - nt_password_hash(new_password, new_password_len, new_password_hash); - nt_password_hash_encrypted_with_block(old_password_hash, - new_password_hash, - encrypted_password_hash); -} diff --git a/contrib/hostapd/src/crypto/ms_funcs.h b/contrib/hostapd/src/crypto/ms_funcs.h deleted file mode 100644 index 6205bf68d3..0000000000 --- a/contrib/hostapd/src/crypto/ms_funcs.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759 - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef MS_FUNCS_H -#define MS_FUNCS_H - -void generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge, - const u8 *username, size_t username_len, - const u8 *password, size_t password_len, - u8 *response); -void generate_nt_response_pwhash(const u8 *auth_challenge, - const u8 *peer_challenge, - const u8 *username, size_t username_len, - const u8 *password_hash, - u8 *response); -void generate_authenticator_response(const u8 *password, size_t password_len, - const u8 *peer_challenge, - const u8 *auth_challenge, - const u8 *username, size_t username_len, - const u8 *nt_response, u8 *response); -void generate_authenticator_response_pwhash( - const u8 *password_hash, - const u8 *peer_challenge, const u8 *auth_challenge, - const u8 *username, size_t username_len, - const u8 *nt_response, u8 *response); -void 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); -void nt_password_hash(const u8 *password, size_t password_len, - u8 *password_hash); -void hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash); -void get_master_key(const u8 *password_hash_hash, const u8 *nt_response, - u8 *master_key); -void get_asymetric_start_key(const u8 *master_key, u8 *session_key, - size_t session_key_len, int is_send, - int is_server); -int __must_check encrypt_pw_block_with_password_hash( - const u8 *password, size_t password_len, - const u8 *password_hash, u8 *pw_block); -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); -void 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, - u8 *encrypted_password_hash); - -#endif /* MS_FUNCS_H */ diff --git a/contrib/hostapd/src/crypto/rc4.c b/contrib/hostapd/src/crypto/rc4.c deleted file mode 100644 index 70c790e364..0000000000 --- a/contrib/hostapd/src/crypto/rc4.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * RC4 stream cipher - * Copyright (c) 2002-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "rc4.h" - -#define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0) - -/** - * rc4 - XOR RC4 stream to given data with skip-stream-start - * @key: RC4 key - * @keylen: RC4 key length - * @skip: number of bytes to skip from the beginning of the RC4 stream - * @data: data to be XOR'ed with RC4 stream - * @data_len: buf length - * - * Generate RC4 pseudo random stream for the given key, skip beginning of the - * stream, and XOR the end result with the data buffer to perform RC4 - * encryption/decryption. - */ -void rc4_skip(const u8 *key, size_t keylen, size_t skip, - u8 *data, size_t data_len) -{ - u32 i, j, k; - u8 S[256], *pos; - size_t kpos; - - /* Setup RC4 state */ - for (i = 0; i < 256; i++) - S[i] = i; - j = 0; - kpos = 0; - for (i = 0; i < 256; i++) { - j = (j + S[i] + key[kpos]) & 0xff; - kpos++; - if (kpos >= keylen) - kpos = 0; - S_SWAP(i, j); - } - - /* Skip the start of the stream */ - i = j = 0; - for (k = 0; k < skip; k++) { - i = (i + 1) & 0xff; - j = (j + S[i]) & 0xff; - S_SWAP(i, j); - } - - /* Apply RC4 to data */ - pos = data; - for (k = 0; k < data_len; k++) { - i = (i + 1) & 0xff; - j = (j + S[i]) & 0xff; - S_SWAP(i, j); - *pos++ ^= S[(S[i] + S[j]) & 0xff]; - } -} diff --git a/contrib/hostapd/src/crypto/rc4.h b/contrib/hostapd/src/crypto/rc4.h deleted file mode 100644 index 35c7e41fba..0000000000 --- a/contrib/hostapd/src/crypto/rc4.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * RC4 stream cipher - * Copyright (c) 2002-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef RC4_H -#define RC4_H - -void rc4_skip(const u8 *key, size_t keylen, size_t skip, - u8 *data, size_t data_len); - -#endif /* RC4_H */ diff --git a/contrib/hostapd/src/crypto/sha1.c b/contrib/hostapd/src/crypto/sha1.c deleted file mode 100644 index 141e4f4ee6..0000000000 --- a/contrib/hostapd/src/crypto/sha1.c +++ /dev/null @@ -1,733 +0,0 @@ -/* - * SHA1 hash implementation and interface functions - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha1.h" -#include "md5.h" -#include "crypto.h" - - -/** - * hmac_sha1_vector - HMAC-SHA1 over data vector (RFC 2104) - * @key: Key for HMAC operations - * @key_len: Length of the key in bytes - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash (20 bytes) - */ -void hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac) -{ - unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */ - unsigned char tk[20]; - const u8 *_addr[6]; - size_t _len[6], i; - - if (num_elem > 5) { - /* - * Fixed limit on the number of fragments to avoid having to - * allocate memory (which could fail). - */ - return; - } - - /* if key is longer than 64 bytes reset it to key = SHA1(key) */ - if (key_len > 64) { - sha1_vector(1, &key, &key_len, tk); - key = tk; - key_len = 20; - } - - /* the HMAC_SHA1 transform looks like: - * - * SHA1(K XOR opad, SHA1(K XOR ipad, text)) - * - * where K is an n byte key - * ipad is the byte 0x36 repeated 64 times - * opad is the byte 0x5c repeated 64 times - * and text is the data being protected */ - - /* start out by storing key in ipad */ - os_memset(k_pad, 0, sizeof(k_pad)); - os_memcpy(k_pad, key, key_len); - /* XOR key with ipad values */ - for (i = 0; i < 64; i++) - k_pad[i] ^= 0x36; - - /* perform inner SHA1 */ - _addr[0] = k_pad; - _len[0] = 64; - for (i = 0; i < num_elem; i++) { - _addr[i + 1] = addr[i]; - _len[i + 1] = len[i]; - } - sha1_vector(1 + num_elem, _addr, _len, mac); - - os_memset(k_pad, 0, sizeof(k_pad)); - os_memcpy(k_pad, key, key_len); - /* XOR key with opad values */ - for (i = 0; i < 64; i++) - k_pad[i] ^= 0x5c; - - /* perform outer SHA1 */ - _addr[0] = k_pad; - _len[0] = 64; - _addr[1] = mac; - _len[1] = SHA1_MAC_LEN; - sha1_vector(2, _addr, _len, mac); -} - - -/** - * hmac_sha1 - HMAC-SHA1 over data buffer (RFC 2104) - * @key: Key for HMAC operations - * @key_len: Length of the key in bytes - * @data: Pointers to the data area - * @data_len: Length of the data area - * @mac: Buffer for the hash (20 bytes) - */ -void hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac) -{ - hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac); -} - - -/** - * sha1_prf - SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1) - * @key: Key for PRF - * @key_len: Length of the key in bytes - * @label: A unique label for each purpose of the PRF - * @data: Extra data to bind into the key - * @data_len: Length of the data - * @buf: Buffer for the generated pseudo-random key - * @buf_len: Number of bytes of key to generate - * - * This function is used to derive new, cryptographically separate keys from a - * given key (e.g., PMK in IEEE 802.11i). - */ -void sha1_prf(const u8 *key, size_t key_len, const char *label, - const u8 *data, size_t data_len, u8 *buf, size_t buf_len) -{ - u8 counter = 0; - size_t pos, plen; - u8 hash[SHA1_MAC_LEN]; - size_t label_len = os_strlen(label) + 1; - const unsigned char *addr[3]; - size_t len[3]; - - addr[0] = (u8 *) label; - len[0] = label_len; - addr[1] = data; - len[1] = data_len; - addr[2] = &counter; - len[2] = 1; - - pos = 0; - while (pos < buf_len) { - plen = buf_len - pos; - if (plen >= SHA1_MAC_LEN) { - hmac_sha1_vector(key, key_len, 3, addr, len, - &buf[pos]); - pos += SHA1_MAC_LEN; - } else { - hmac_sha1_vector(key, key_len, 3, addr, len, - hash); - os_memcpy(&buf[pos], hash, plen); - break; - } - counter++; - } -} - - -#ifndef CONFIG_NO_T_PRF -/** - * sha1_t_prf - EAP-FAST Pseudo-Random Function (T-PRF) - * @key: Key for PRF - * @key_len: Length of the key in bytes - * @label: A unique label for each purpose of the PRF - * @seed: Seed value to bind into the key - * @seed_len: Length of the seed - * @buf: Buffer for the generated pseudo-random key - * @buf_len: Number of bytes of key to generate - * - * This function is used to derive new, cryptographically separate keys from a - * given key for EAP-FAST. T-PRF is defined in RFC 4851, Section 5.5. - */ -void sha1_t_prf(const u8 *key, size_t key_len, const char *label, - const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len) -{ - unsigned char counter = 0; - size_t pos, plen; - u8 hash[SHA1_MAC_LEN]; - size_t label_len = os_strlen(label); - u8 output_len[2]; - const unsigned char *addr[5]; - size_t len[5]; - - addr[0] = hash; - len[0] = 0; - addr[1] = (unsigned char *) label; - len[1] = label_len + 1; - addr[2] = seed; - len[2] = seed_len; - addr[3] = output_len; - len[3] = 2; - addr[4] = &counter; - len[4] = 1; - - output_len[0] = (buf_len >> 8) & 0xff; - output_len[1] = buf_len & 0xff; - pos = 0; - while (pos < buf_len) { - counter++; - plen = buf_len - pos; - hmac_sha1_vector(key, key_len, 5, addr, len, hash); - if (plen >= SHA1_MAC_LEN) { - os_memcpy(&buf[pos], hash, SHA1_MAC_LEN); - pos += SHA1_MAC_LEN; - } else { - os_memcpy(&buf[pos], hash, plen); - break; - } - len[0] = SHA1_MAC_LEN; - } -} -#endif /* CONFIG_NO_T_PRF */ - - -#ifndef CONFIG_NO_TLS_PRF -/** - * tls_prf - Pseudo-Random Function for TLS (TLS-PRF, RFC 2246) - * @secret: Key for PRF - * @secret_len: Length of the key in bytes - * @label: A unique label for each purpose of the PRF - * @seed: Seed value to bind into the key - * @seed_len: Length of the seed - * @out: Buffer for the generated pseudo-random key - * @outlen: Number of bytes of key to generate - * Returns: 0 on success, -1 on failure. - * - * This function is used to derive new, cryptographically separate keys from a - * given key in TLS. This PRF is defined in RFC 2246, Chapter 5. - */ -int tls_prf(const u8 *secret, size_t secret_len, const char *label, - const u8 *seed, size_t seed_len, u8 *out, size_t outlen) -{ - size_t L_S1, L_S2, i; - const u8 *S1, *S2; - u8 A_MD5[MD5_MAC_LEN], A_SHA1[SHA1_MAC_LEN]; - u8 P_MD5[MD5_MAC_LEN], P_SHA1[SHA1_MAC_LEN]; - int MD5_pos, SHA1_pos; - const u8 *MD5_addr[3]; - size_t MD5_len[3]; - const unsigned char *SHA1_addr[3]; - size_t SHA1_len[3]; - - if (secret_len & 1) - return -1; - - MD5_addr[0] = A_MD5; - MD5_len[0] = MD5_MAC_LEN; - MD5_addr[1] = (unsigned char *) label; - MD5_len[1] = os_strlen(label); - MD5_addr[2] = seed; - MD5_len[2] = seed_len; - - SHA1_addr[0] = A_SHA1; - SHA1_len[0] = SHA1_MAC_LEN; - SHA1_addr[1] = (unsigned char *) label; - SHA1_len[1] = os_strlen(label); - SHA1_addr[2] = seed; - SHA1_len[2] = seed_len; - - /* RFC 2246, Chapter 5 - * A(0) = seed, A(i) = HMAC(secret, A(i-1)) - * P_hash = HMAC(secret, A(1) + seed) + HMAC(secret, A(2) + seed) + .. - * PRF = P_MD5(S1, label + seed) XOR P_SHA-1(S2, label + seed) - */ - - L_S1 = L_S2 = (secret_len + 1) / 2; - S1 = secret; - S2 = secret + L_S1; - if (secret_len & 1) { - /* The last byte of S1 will be shared with S2 */ - S2--; - } - - hmac_md5_vector(S1, L_S1, 2, &MD5_addr[1], &MD5_len[1], A_MD5); - hmac_sha1_vector(S2, L_S2, 2, &SHA1_addr[1], &SHA1_len[1], A_SHA1); - - MD5_pos = MD5_MAC_LEN; - SHA1_pos = SHA1_MAC_LEN; - for (i = 0; i < outlen; i++) { - if (MD5_pos == MD5_MAC_LEN) { - hmac_md5_vector(S1, L_S1, 3, MD5_addr, MD5_len, P_MD5); - MD5_pos = 0; - hmac_md5(S1, L_S1, A_MD5, MD5_MAC_LEN, A_MD5); - } - if (SHA1_pos == SHA1_MAC_LEN) { - hmac_sha1_vector(S2, L_S2, 3, SHA1_addr, SHA1_len, - P_SHA1); - SHA1_pos = 0; - hmac_sha1(S2, L_S2, A_SHA1, SHA1_MAC_LEN, A_SHA1); - } - - out[i] = P_MD5[MD5_pos] ^ P_SHA1[SHA1_pos]; - - MD5_pos++; - SHA1_pos++; - } - - return 0; -} -#endif /* CONFIG_NO_TLS_PRF */ - - -#ifndef CONFIG_NO_PBKDF2 - -static void pbkdf2_sha1_f(const char *passphrase, const char *ssid, - size_t ssid_len, int iterations, unsigned int count, - u8 *digest) -{ - unsigned char tmp[SHA1_MAC_LEN], tmp2[SHA1_MAC_LEN]; - int i, j; - unsigned char count_buf[4]; - const u8 *addr[2]; - size_t len[2]; - size_t passphrase_len = os_strlen(passphrase); - - addr[0] = (u8 *) ssid; - len[0] = ssid_len; - addr[1] = count_buf; - len[1] = 4; - - /* F(P, S, c, i) = U1 xor U2 xor ... Uc - * U1 = PRF(P, S || i) - * U2 = PRF(P, U1) - * Uc = PRF(P, Uc-1) - */ - - count_buf[0] = (count >> 24) & 0xff; - count_buf[1] = (count >> 16) & 0xff; - count_buf[2] = (count >> 8) & 0xff; - count_buf[3] = count & 0xff; - hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len, tmp); - os_memcpy(digest, tmp, SHA1_MAC_LEN); - - for (i = 1; i < iterations; i++) { - hmac_sha1((u8 *) passphrase, passphrase_len, tmp, SHA1_MAC_LEN, - tmp2); - os_memcpy(tmp, tmp2, SHA1_MAC_LEN); - for (j = 0; j < SHA1_MAC_LEN; j++) - digest[j] ^= tmp2[j]; - } -} - - -/** - * pbkdf2_sha1 - SHA1-based key derivation function (PBKDF2) for IEEE 802.11i - * @passphrase: ASCII passphrase - * @ssid: SSID - * @ssid_len: SSID length in bytes - * @iterations: Number of iterations to run - * @buf: Buffer for the generated key - * @buflen: Length of the buffer in bytes - * - * This function is used to derive PSK for WPA-PSK. For this protocol, - * iterations is set to 4096 and buflen to 32. This function is described in - * IEEE Std 802.11-2004, Clause H.4. The main construction is from PKCS#5 v2.0. - */ -void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, - int iterations, u8 *buf, size_t buflen) -{ - unsigned int count = 0; - unsigned char *pos = buf; - size_t left = buflen, plen; - unsigned char digest[SHA1_MAC_LEN]; - - while (left > 0) { - count++; - pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations, count, - digest); - plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left; - os_memcpy(pos, digest, plen); - pos += plen; - left -= plen; - } -} - -#endif /* CONFIG_NO_PBKDF2 */ - - -#ifdef INTERNAL_SHA1 - -struct SHA1Context { - u32 state[5]; - u32 count[2]; - unsigned char buffer[64]; -}; - -typedef struct SHA1Context SHA1_CTX; - -#ifndef CONFIG_CRYPTO_INTERNAL -static void SHA1Init(struct SHA1Context *context); -static void SHA1Update(struct SHA1Context *context, const void *data, u32 len); -static void SHA1Final(unsigned char digest[20], struct SHA1Context *context); -#endif /* CONFIG_CRYPTO_INTERNAL */ -static void SHA1Transform(u32 state[5], const unsigned char buffer[64]); - - -/** - * sha1_vector - SHA-1 hash for data vector - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash - */ -void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, - u8 *mac) -{ - SHA1_CTX ctx; - size_t i; - - SHA1Init(&ctx); - for (i = 0; i < num_elem; i++) - SHA1Update(&ctx, addr[i], len[i]); - SHA1Final(mac, &ctx); -} - - -#ifndef CONFIG_NO_FIPS186_2_PRF -int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) -{ - u8 xkey[64]; - u32 t[5], _t[5]; - int i, j, m, k; - u8 *xpos = x; - u32 carry; - - if (seed_len > sizeof(xkey)) - seed_len = sizeof(xkey); - - /* FIPS 186-2 + change notice 1 */ - - os_memcpy(xkey, seed, seed_len); - os_memset(xkey + seed_len, 0, 64 - seed_len); - t[0] = 0x67452301; - t[1] = 0xEFCDAB89; - t[2] = 0x98BADCFE; - t[3] = 0x10325476; - t[4] = 0xC3D2E1F0; - - m = xlen / 40; - for (j = 0; j < m; j++) { - /* XSEED_j = 0 */ - for (i = 0; i < 2; i++) { - /* XVAL = (XKEY + XSEED_j) mod 2^b */ - - /* w_i = G(t, XVAL) */ - os_memcpy(_t, t, 20); - SHA1Transform(_t, xkey); - _t[0] = host_to_be32(_t[0]); - _t[1] = host_to_be32(_t[1]); - _t[2] = host_to_be32(_t[2]); - _t[3] = host_to_be32(_t[3]); - _t[4] = host_to_be32(_t[4]); - os_memcpy(xpos, _t, 20); - - /* XKEY = (1 + XKEY + w_i) mod 2^b */ - carry = 1; - for (k = 19; k >= 0; k--) { - carry += xkey[k] + xpos[k]; - xkey[k] = carry & 0xff; - carry >>= 8; - } - - xpos += SHA1_MAC_LEN; - } - /* x_j = w_0|w_1 */ - } - - return 0; -} -#endif /* CONFIG_NO_FIPS186_2_PRF */ - - -/* ===== start - public domain SHA1 implementation ===== */ - -/* -SHA-1 in C -By Steve Reid -100% Public Domain - ------------------ -Modified 7/98 -By James H. Brown -Still 100% Public Domain - -Corrected a problem which generated improper hash values on 16 bit machines -Routine SHA1Update changed from - void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int -len) -to - void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned -long len) - -The 'len' parameter was declared an int which works fine on 32 bit machines. -However, on 16 bit machines an int is too small for the shifts being done -against -it. This caused the hash function to generate incorrect values if len was -greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). - -Since the file IO in main() reads 16K at a time, any file 8K or larger would -be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million -"a"s). - -I also changed the declaration of variables i & j in SHA1Update to -unsigned long from unsigned int for the same reason. - -These changes should make no difference to any 32 bit implementations since -an -int and a long are the same size in those environments. - --- -I also corrected a few compiler warnings generated by Borland C. -1. Added #include for exit() prototype -2. Removed unused variable 'j' in SHA1Final -3. Changed exit(0) to return(0) at end of main. - -ALL changes I made can be located by searching for comments containing 'JHB' ------------------ -Modified 8/98 -By Steve Reid -Still 100% public domain - -1- Removed #include and used return() instead of exit() -2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) -3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net - ------------------ -Modified 4/01 -By Saul Kravitz -Still 100% PD -Modified to run on Compaq Alpha hardware. - ------------------ -Modified 4/01 -By Jouni Malinen -Minor changes to match the coding style used in Dynamics. - -Modified September 24, 2004 -By Jouni Malinen -Fixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined. - -*/ - -/* -Test Vectors (from FIPS PUB 180-1) -"abc" - A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D -"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 -A million repetitions of "a" - 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F -*/ - -#define SHA1HANDSOFF - -#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) - -/* blk0() and blk() perform the initial expand. */ -/* I got the idea of expanding during the round function from SSLeay */ -#ifndef WORDS_BIGENDIAN -#define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \ - (rol(block->l[i], 8) & 0x00FF00FF)) -#else -#define blk0(i) block->l[i] -#endif -#define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \ - block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1)) - -/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -#define R0(v,w,x,y,z,i) \ - z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \ - w = rol(w, 30); -#define R1(v,w,x,y,z,i) \ - z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ - w = rol(w, 30); -#define R2(v,w,x,y,z,i) \ - z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30); -#define R3(v,w,x,y,z,i) \ - z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ - w = rol(w, 30); -#define R4(v,w,x,y,z,i) \ - z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ - w=rol(w, 30); - - -#ifdef VERBOSE /* SAK */ -void SHAPrintContext(SHA1_CTX *context, char *msg) -{ - printf("%s (%d,%d) %x %x %x %x %x\n", - msg, - context->count[0], context->count[1], - context->state[0], - context->state[1], - context->state[2], - context->state[3], - context->state[4]); -} -#endif - -/* Hash a single 512-bit block. This is the core of the algorithm. */ - -static void SHA1Transform(u32 state[5], const unsigned char buffer[64]) -{ - u32 a, b, c, d, e; - typedef union { - unsigned char c[64]; - u32 l[16]; - } CHAR64LONG16; - CHAR64LONG16* block; -#ifdef SHA1HANDSOFF - CHAR64LONG16 workspace; - block = &workspace; - os_memcpy(block, buffer, 64); -#else - block = (CHAR64LONG16 *) buffer; -#endif - /* Copy context->state[] to working vars */ - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - /* 4 rounds of 20 operations each. Loop unrolled. */ - R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); - R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); - /* Add the working vars back into context.state[] */ - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - /* Wipe variables */ - a = b = c = d = e = 0; -#ifdef SHA1HANDSOFF - os_memset(block, 0, 64); -#endif -} - - -/* SHA1Init - Initialize new context */ - -void SHA1Init(SHA1_CTX* context) -{ - /* SHA1 initialization constants */ - context->state[0] = 0x67452301; - context->state[1] = 0xEFCDAB89; - context->state[2] = 0x98BADCFE; - context->state[3] = 0x10325476; - context->state[4] = 0xC3D2E1F0; - context->count[0] = context->count[1] = 0; -} - - -/* Run your data through this. */ - -void SHA1Update(SHA1_CTX* context, const void *_data, u32 len) -{ - u32 i, j; - const unsigned char *data = _data; - -#ifdef VERBOSE - SHAPrintContext(context, "before"); -#endif - j = (context->count[0] >> 3) & 63; - if ((context->count[0] += len << 3) < (len << 3)) - context->count[1]++; - context->count[1] += (len >> 29); - if ((j + len) > 63) { - os_memcpy(&context->buffer[j], data, (i = 64-j)); - SHA1Transform(context->state, context->buffer); - for ( ; i + 63 < len; i += 64) { - SHA1Transform(context->state, &data[i]); - } - j = 0; - } - else i = 0; - os_memcpy(&context->buffer[j], &data[i], len - i); -#ifdef VERBOSE - SHAPrintContext(context, "after "); -#endif -} - - -/* Add padding and return the message digest. */ - -void SHA1Final(unsigned char digest[20], SHA1_CTX* context) -{ - u32 i; - unsigned char finalcount[8]; - - for (i = 0; i < 8; i++) { - finalcount[i] = (unsigned char) - ((context->count[(i >= 4 ? 0 : 1)] >> - ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ - } - SHA1Update(context, (unsigned char *) "\200", 1); - while ((context->count[0] & 504) != 448) { - SHA1Update(context, (unsigned char *) "\0", 1); - } - SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() - */ - for (i = 0; i < 20; i++) { - digest[i] = (unsigned char) - ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & - 255); - } - /* Wipe variables */ - i = 0; - os_memset(context->buffer, 0, 64); - os_memset(context->state, 0, 20); - os_memset(context->count, 0, 8); - os_memset(finalcount, 0, 8); -} - -/* ===== end - public domain SHA1 implementation ===== */ - -#endif /* INTERNAL_SHA1 */ diff --git a/contrib/hostapd/src/crypto/sha1.h b/contrib/hostapd/src/crypto/sha1.h deleted file mode 100644 index 9c365e2677..0000000000 --- a/contrib/hostapd/src/crypto/sha1.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SHA1 hash implementation and interface functions - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef SHA1_H -#define SHA1_H - -#define SHA1_MAC_LEN 20 - -void hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); -void hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac); -void sha1_prf(const u8 *key, size_t key_len, const char *label, - const u8 *data, size_t data_len, u8 *buf, size_t buf_len); -void sha1_t_prf(const u8 *key, size_t key_len, const char *label, - const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len); -int __must_check tls_prf(const u8 *secret, size_t secret_len, - const char *label, const u8 *seed, size_t seed_len, - u8 *out, size_t outlen); -void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, - int iterations, u8 *buf, size_t buflen); - -#ifdef CONFIG_CRYPTO_INTERNAL -struct SHA1Context; - -void SHA1Init(struct SHA1Context *context); -void SHA1Update(struct SHA1Context *context, const void *data, u32 len); -void SHA1Final(unsigned char digest[20], struct SHA1Context *context); -#endif /* CONFIG_CRYPTO_INTERNAL */ - -#endif /* SHA1_H */ diff --git a/contrib/hostapd/src/crypto/sha256.c b/contrib/hostapd/src/crypto/sha256.c deleted file mode 100644 index 96dac0ea71..0000000000 --- a/contrib/hostapd/src/crypto/sha256.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * SHA-256 hash implementation and interface functions - * Copyright (c) 2003-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha256.h" -#include "crypto.h" - - -/** - * hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104) - * @key: Key for HMAC operations - * @key_len: Length of the key in bytes - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash (32 bytes) - */ -void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac) -{ - unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */ - unsigned char tk[32]; - const u8 *_addr[6]; - size_t _len[6], i; - - if (num_elem > 5) { - /* - * Fixed limit on the number of fragments to avoid having to - * allocate memory (which could fail). - */ - return; - } - - /* if key is longer than 64 bytes reset it to key = SHA256(key) */ - if (key_len > 64) { - sha256_vector(1, &key, &key_len, tk); - key = tk; - key_len = 32; - } - - /* the HMAC_SHA256 transform looks like: - * - * SHA256(K XOR opad, SHA256(K XOR ipad, text)) - * - * where K is an n byte key - * ipad is the byte 0x36 repeated 64 times - * opad is the byte 0x5c repeated 64 times - * and text is the data being protected */ - - /* start out by storing key in ipad */ - os_memset(k_pad, 0, sizeof(k_pad)); - os_memcpy(k_pad, key, key_len); - /* XOR key with ipad values */ - for (i = 0; i < 64; i++) - k_pad[i] ^= 0x36; - - /* perform inner SHA256 */ - _addr[0] = k_pad; - _len[0] = 64; - for (i = 0; i < num_elem; i++) { - _addr[i + 1] = addr[i]; - _len[i + 1] = len[i]; - } - sha256_vector(1 + num_elem, _addr, _len, mac); - - os_memset(k_pad, 0, sizeof(k_pad)); - os_memcpy(k_pad, key, key_len); - /* XOR key with opad values */ - for (i = 0; i < 64; i++) - k_pad[i] ^= 0x5c; - - /* perform outer SHA256 */ - _addr[0] = k_pad; - _len[0] = 64; - _addr[1] = mac; - _len[1] = SHA256_MAC_LEN; - sha256_vector(2, _addr, _len, mac); -} - - -/** - * hmac_sha256 - HMAC-SHA256 over data buffer (RFC 2104) - * @key: Key for HMAC operations - * @key_len: Length of the key in bytes - * @data: Pointers to the data area - * @data_len: Length of the data area - * @mac: Buffer for the hash (20 bytes) - */ -void hmac_sha256(const u8 *key, size_t key_len, const u8 *data, - size_t data_len, u8 *mac) -{ - hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac); -} - - -/** - * sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2) - * @key: Key for PRF - * @key_len: Length of the key in bytes - * @label: A unique label for each purpose of the PRF - * @data: Extra data to bind into the key - * @data_len: Length of the data - * @buf: Buffer for the generated pseudo-random key - * @buf_len: Number of bytes of key to generate - * - * This function is used to derive new, cryptographically separate keys from a - * given key. - */ -void sha256_prf(const u8 *key, size_t key_len, const char *label, - const u8 *data, size_t data_len, u8 *buf, size_t buf_len) -{ - u16 counter = 1; - size_t pos, plen; - u8 hash[SHA256_MAC_LEN]; - const u8 *addr[4]; - size_t len[4]; - u8 counter_le[2], length_le[2]; - - addr[0] = counter_le; - len[0] = 2; - addr[1] = (u8 *) label; - len[1] = os_strlen(label); - addr[2] = data; - len[2] = data_len; - addr[3] = length_le; - len[3] = sizeof(length_le); - - WPA_PUT_LE16(length_le, buf_len * 8); - pos = 0; - while (pos < buf_len) { - plen = buf_len - pos; - WPA_PUT_LE16(counter_le, counter); - if (plen >= SHA256_MAC_LEN) { - hmac_sha256_vector(key, key_len, 4, addr, len, - &buf[pos]); - pos += SHA256_MAC_LEN; - } else { - hmac_sha256_vector(key, key_len, 4, addr, len, hash); - os_memcpy(&buf[pos], hash, plen); - break; - } - counter++; - } -} - - -#ifdef INTERNAL_SHA256 - -struct sha256_state { - u64 length; - u32 state[8], curlen; - u8 buf[64]; -}; - -static void sha256_init(struct sha256_state *md); -static int sha256_process(struct sha256_state *md, const unsigned char *in, - unsigned long inlen); -static int sha256_done(struct sha256_state *md, unsigned char *out); - - -/** - * sha256_vector - SHA256 hash for data vector - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash - */ -void sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, - u8 *mac) -{ - struct sha256_state ctx; - size_t i; - - sha256_init(&ctx); - for (i = 0; i < num_elem; i++) - sha256_process(&ctx, addr[i], len[i]); - sha256_done(&ctx, mac); -} - - -/* ===== start - public domain SHA256 implementation ===== */ - -/* This is based on SHA256 implementation in LibTomCrypt that was released into - * public domain by Tom St Denis. */ - -/* the K array */ -static const unsigned long K[64] = { - 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, - 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, - 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, - 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, - 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, - 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, - 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, - 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, - 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, - 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, - 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, - 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, - 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL -}; - - -/* Various logical functions */ -#define RORc(x, y) \ -( ((((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 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)) -#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) -#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) -#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) -#ifndef MIN -#define MIN(x, y) (((x) < (y)) ? (x) : (y)) -#endif - -/* compress 512-bits */ -static int sha256_compress(struct sha256_state *md, unsigned char *buf) -{ - u32 S[8], W[64], t0, t1; - u32 t; - int i; - - /* copy state into S */ - for (i = 0; i < 8; i++) { - S[i] = md->state[i]; - } - - /* copy the state into 512-bits into W[0..15] */ - for (i = 0; i < 16; i++) - W[i] = WPA_GET_BE32(buf + (4 * i)); - - /* fill W[16..63] */ - 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) \ - t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ - t1 = Sigma0(a) + Maj(a, b, c); \ - d += t0; \ - h = t0 + t1; - - 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]; - S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; - } - - /* feedback */ - for (i = 0; i < 8; i++) { - md->state[i] = md->state[i] + S[i]; - } - return 0; -} - - -/* Initialize the hash state */ -static void sha256_init(struct sha256_state *md) -{ - md->curlen = 0; - md->length = 0; - md->state[0] = 0x6A09E667UL; - md->state[1] = 0xBB67AE85UL; - md->state[2] = 0x3C6EF372UL; - md->state[3] = 0xA54FF53AUL; - md->state[4] = 0x510E527FUL; - md->state[5] = 0x9B05688CUL; - md->state[6] = 0x1F83D9ABUL; - md->state[7] = 0x5BE0CD19UL; -} - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful -*/ -static int sha256_process(struct sha256_state *md, const unsigned char *in, - unsigned long inlen) -{ - unsigned long n; -#define block_size 64 - - if (md->curlen > sizeof(md->buf)) - return -1; - - while (inlen > 0) { - if (md->curlen == 0 && inlen >= block_size) { - if (sha256_compress(md, (unsigned char *) in) < 0) - return -1; - md->length += block_size * 8; - in += block_size; - inlen -= block_size; - } else { - n = MIN(inlen, (block_size - md->curlen)); - os_memcpy(md->buf + md->curlen, in, n); - md->curlen += n; - in += n; - inlen -= n; - if (md->curlen == block_size) { - if (sha256_compress(md, md->buf) < 0) - return -1; - md->length += 8 * block_size; - md->curlen = 0; - } - } - } - - return 0; -} - - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (32 bytes) - @return CRYPT_OK if successful -*/ -static int sha256_done(struct sha256_state *md, unsigned char *out) -{ - int i; - - if (md->curlen >= sizeof(md->buf)) - return -1; - - /* increase the length of the message */ - md->length += md->curlen * 8; - - /* append the '1' bit */ - md->buf[md->curlen++] = (unsigned char) 0x80; - - /* if the length is currently above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->curlen > 56) { - while (md->curlen < 64) { - md->buf[md->curlen++] = (unsigned char) 0; - } - sha256_compress(md, md->buf); - md->curlen = 0; - } - - /* pad upto 56 bytes of zeroes */ - while (md->curlen < 56) { - md->buf[md->curlen++] = (unsigned char) 0; - } - - /* store length */ - WPA_PUT_BE64(md->buf + 56, md->length); - sha256_compress(md, md->buf); - - /* copy output */ - for (i = 0; i < 8; i++) - WPA_PUT_BE32(out + (4 * i), md->state[i]); - - return 0; -} - -/* ===== end - public domain SHA256 implementation ===== */ - -#endif /* INTERNAL_SHA256 */ diff --git a/contrib/hostapd/src/crypto/sha256.h b/contrib/hostapd/src/crypto/sha256.h deleted file mode 100644 index dc597f09b5..0000000000 --- a/contrib/hostapd/src/crypto/sha256.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * SHA256 hash implementation and interface functions - * Copyright (c) 2003-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef SHA256_H -#define SHA256_H - -#define SHA256_MAC_LEN 32 - -void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); -void hmac_sha256(const u8 *key, size_t key_len, const u8 *data, - size_t data_len, u8 *mac); -void sha256_prf(const u8 *key, size_t key_len, const char *label, - const u8 *data, size_t data_len, u8 *buf, size_t buf_len); - -#endif /* SHA256_H */ diff --git a/contrib/hostapd/src/crypto/tls.h b/contrib/hostapd/src/crypto/tls.h deleted file mode 100644 index aafb799993..0000000000 --- a/contrib/hostapd/src/crypto/tls.h +++ /dev/null @@ -1,538 +0,0 @@ -/* - * WPA Supplicant / SSL/TLS interface definition - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TLS_H -#define TLS_H - -struct tls_connection; - -struct tls_keys { - const u8 *master_key; /* TLS master secret */ - size_t master_key_len; - const u8 *client_random; - size_t client_random_len; - const u8 *server_random; - size_t server_random_len; - const u8 *inner_secret; /* TLS/IA inner secret */ - size_t inner_secret_len; -}; - -struct tls_config { - const char *opensc_engine_path; - const char *pkcs11_engine_path; - const char *pkcs11_module_path; -}; - -#define TLS_CONN_ALLOW_SIGN_RSA_MD5 BIT(0) -#define TLS_CONN_DISABLE_TIME_CHECKS BIT(1) - -/** - * struct tls_connection_params - Parameters for TLS connection - * @ca_cert: File or reference name for CA X.509 certificate in PEM or DER - * format - * @ca_cert_blob: ca_cert as inlined data or %NULL if not used - * @ca_cert_blob_len: ca_cert_blob length - * @ca_path: Path to CA certificates (OpenSSL specific) - * @subject_match: String to match in the subject of the peer certificate or - * %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 - * @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 - * @client_cert_blob_len: client_cert_blob length - * @private_key: File or reference name for client private key in PEM or DER - * format (traditional format (RSA PRIVATE KEY) or PKCS#8 (PRIVATE KEY) - * @private_key_blob: private_key as inlined data or %NULL if not used - * @private_key_blob_len: private_key_blob length - * @private_key_passwd: Passphrase for decrypted private key, %NULL if no - * passphrase is used. - * @dh_file: File name for DH/DSA data in PEM format, or %NULL if not used - * @dh_blob: dh_file as inlined data or %NULL if not used - * @dh_blob_len: dh_blob length - * @engine: 1 = use engine (e.g., a smartcard) for private key operations - * (this is OpenSSL specific for now) - * @engine_id: engine id string (this is OpenSSL specific for now) - * @ppin: pointer to the pin variable in the configuration - * (this is OpenSSL specific for now) - * @key_id: the private key's id when using engine (this is OpenSSL - * specific for now) - * @cert_id: the certificate's id when using engine - * @ca_cert_id: the CA certificate's id when using engine - * @tls_ia: Whether to enable TLS/IA (for EAP-TTLSv1) - * @flags: Parameter options (TLS_CONN_*) - * - * TLS connection parameters to be configured with tls_connection_set_params() - * and tls_global_set_params(). - * - * Certificates and private key can be configured either as a reference name - * (file path or reference to certificate store) or by providing the same data - * as a pointer to the data in memory. Only one option will be used for each - * field. - */ -struct tls_connection_params { - const char *ca_cert; - const u8 *ca_cert_blob; - size_t ca_cert_blob_len; - const char *ca_path; - const char *subject_match; - const char *altsubject_match; - const char *client_cert; - const u8 *client_cert_blob; - size_t client_cert_blob_len; - const char *private_key; - const u8 *private_key_blob; - size_t private_key_blob_len; - const char *private_key_passwd; - const char *dh_file; - const u8 *dh_blob; - size_t dh_blob_len; - int tls_ia; - - /* OpenSSL specific variables */ - int engine; - const char *engine_id; - const char *pin; - const char *key_id; - const char *cert_id; - const char *ca_cert_id; - - unsigned int flags; -}; - - -/** - * tls_init - Initialize TLS library - * @conf: Configuration data for TLS library - * Returns: Context data to be used as tls_ctx in calls to other functions, - * or %NULL on failure. - * - * Called once during program startup and once for each RSN pre-authentication - * session. In other words, there can be two concurrent TLS contexts. If global - * library initialization is needed (i.e., one that is shared between both - * authentication types), the TLS library wrapper should maintain a reference - * counter and do global initialization only when moving from 0 to 1 reference. - */ -void * tls_init(const struct tls_config *conf); - -/** - * tls_deinit - Deinitialize TLS library - * @tls_ctx: TLS context data from tls_init() - * - * Called once during program shutdown and once for each RSN pre-authentication - * session. If global library deinitialization is needed (i.e., one that is - * shared between both authentication types), the TLS library wrapper should - * maintain a reference counter and do global deinitialization only when moving - * from 1 to 0 references. - */ -void tls_deinit(void *tls_ctx); - -/** - * tls_get_errors - Process pending errors - * @tls_ctx: TLS context data from tls_init() - * Returns: Number of found error, 0 if no errors detected. - * - * Process all pending TLS errors. - */ -int tls_get_errors(void *tls_ctx); - -/** - * tls_connection_init - Initialize a new TLS connection - * @tls_ctx: TLS context data from tls_init() - * Returns: Connection context data, conn for other function calls - */ -struct tls_connection * tls_connection_init(void *tls_ctx); - -/** - * tls_connection_deinit - Free TLS connection data - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * - * Release all resources allocated for TLS connection. - */ -void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn); - -/** - * tls_connection_established - Has the TLS connection been completed? - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * Returns: 1 if TLS connection has been completed, 0 if not. - */ -int tls_connection_established(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() - * Returns: 0 on success, -1 on failure - * - * Shutdown current TLS connection without releasing all resources. New - * connection can be started by using the same conn without having to call - * tls_connection_init() or setting certificates etc. again. The new - * connection should try to use session resumption. - */ -int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn); - -enum { - TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED = -3, - TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED = -2 -}; - -/** - * tls_connection_set_params - Set TLS connection parameters - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @params: Connection parameters - * Returns: 0 on success, -1 on failure, - * TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED (-2) on possible PIN error causing - * PKCS#11 engine failure, or - * TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED (-3) on failure to verify the - * PKCS#11 engine private key. - */ -int __must_check -tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, - const struct tls_connection_params *params); - -/** - * tls_global_set_params - Set TLS parameters for all TLS connection - * @tls_ctx: TLS context data from tls_init() - * @params: Global TLS parameters - * Returns: 0 on success, -1 on failure, - * TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED (-2) on possible PIN error causing - * PKCS#11 engine failure, or - * TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED (-3) on failure to verify the - * PKCS#11 engine private key. - */ -int __must_check tls_global_set_params( - void *tls_ctx, const struct tls_connection_params *params); - -/** - * tls_global_set_verify - Set global certificate verification options - * @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 - * Returns: 0 on success, -1 on failure - */ -int __must_check tls_global_set_verify(void *tls_ctx, int check_crl); - -/** - * tls_connection_set_verify - Set certificate verification options - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @verify_peer: 1 = verify peer certificate - * Returns: 0 on success, -1 on failure - */ -int __must_check tls_connection_set_verify(void *tls_ctx, - struct tls_connection *conn, - int verify_peer); - -/** - * tls_connection_set_ia - Set TLS/IA parameters - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @tls_ia: 1 = enable TLS/IA - * Returns: 0 on success, -1 on failure - * - * This function is used to configure TLS/IA in server mode where - * tls_connection_set_params() is not used. - */ -int __must_check tls_connection_set_ia(void *tls_ctx, - struct tls_connection *conn, - int tls_ia); - -/** - * tls_connection_get_keys - Get master key and random data from TLS connection - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @keys: Structure of key/random data (filled on success) - * Returns: 0 on success, -1 on failure - */ -int __must_check tls_connection_get_keys(void *tls_ctx, - struct tls_connection *conn, - struct tls_keys *keys); - -/** - * tls_connection_prf - Use TLS-PRF to derive keying material - * @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 - * @server_random_first: seed is 0 = client_random|server_random, - * 1 = server_random|client_random - * @out: Buffer for output data from TLS-PRF - * @out_len: Length of the output buffer - * Returns: 0 on success, -1 on failure - * - * This function is optional to implement if tls_connection_get_keys() provides - * access to master secret and server/client random values. If these values are - * not exported from the TLS library, tls_connection_prf() is required so that - * further keying material can be derived from the master secret. If not - * implemented, the function will still need to be defined, but it can just - * return -1. Example implementation of this function is in tls_prf() function - * when it is called with seed set to client_random|server_random (or - * server_random|client_random). - */ -int __must_check tls_connection_prf(void *tls_ctx, - struct tls_connection *conn, - const char *label, - int server_random_first, - u8 *out, size_t out_len); - -/** - * tls_connection_handshake - Process TLS handshake (client side) - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @in_data: Input data from TLS peer - * @in_len: Input data length - * @out_len: Length of the output buffer. - * @appl_data: Pointer to application data pointer, or %NULL if dropped - * @appl_data_len: Pointer to variable that is set to appl_data length - * Returns: Pointer to output data, %NULL on failure - * - * Caller is responsible for freeing returned output data. If the final - * handshake message includes application data, this is decrypted and - * appl_data (if not %NULL) is set to point this data. Caller is responsible - * for freeing appl_data. - * - * This function is used during TLS handshake. The first call is done with - * in_data == %NULL and the library is expected to return ClientHello packet. - * This packet is then send to the server and a response from server is given - * to TLS library by calling this function again with in_data pointing to the - * TLS message from the server. - * - * If the TLS handshake fails, this function may return %NULL. However, if the - * TLS library has a TLS alert to send out, that should be returned as the - * output data. In this case, tls_connection_get_failed() must return failure - * (> 0). - * - * tls_connection_established() should return 1 once the TLS handshake has been - * completed successfully. - */ -u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len); - -/** - * tls_connection_server_handshake - Process TLS handshake (server side) - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @in_data: Input data from TLS peer - * @in_len: Input data length - * @out_len: Length of the output buffer. - * Returns: pointer to output data, %NULL on failure - * - * Caller is responsible for freeing returned output data. - */ -u8 * tls_connection_server_handshake(void *tls_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len); - -/** - * tls_connection_encrypt - Encrypt data into TLS tunnel - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @in_data: Pointer to plaintext data to be encrypted - * @in_len: Input buffer length - * @out_data: Pointer to output buffer (encrypted TLS data) - * @out_len: Maximum out_data length - * Returns: Number of bytes written to out_data, -1 on failure - * - * This function is used after TLS handshake has been completed successfully to - * send data in the encrypted tunnel. - */ -int __must_check tls_connection_encrypt(void *tls_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len); - -/** - * tls_connection_decrypt - Decrypt data from TLS tunnel - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @in_data: Pointer to input buffer (encrypted TLS data) - * @in_len: Input buffer length - * @out_data: Pointer to output buffer (decrypted data from TLS tunnel) - * @out_len: Maximum out_data length - * Returns: Number of bytes written to out_data, -1 on failure - * - * This function is used after TLS handshake has been completed successfully to - * receive data from the encrypted tunnel. - */ -int __must_check tls_connection_decrypt(void *tls_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len); - -/** - * tls_connection_resumed - Was session resumption used - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * Returns: 1 if current session used session resumption, 0 if not - */ -int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn); - -enum { - TLS_CIPHER_NONE, - TLS_CIPHER_RC4_SHA /* 0x0005 */, - TLS_CIPHER_AES128_SHA /* 0x002f */, - TLS_CIPHER_RSA_DHE_AES128_SHA /* 0x0031 */, - TLS_CIPHER_ANON_DH_AES128_SHA /* 0x0034 */ -}; - -/** - * tls_connection_set_cipher_list - Configure acceptable cipher suites - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers - * (TLS_CIPHER_*). - * Returns: 0 on success, -1 on failure - */ -int __must_check tls_connection_set_cipher_list(void *tls_ctx, - struct tls_connection *conn, - u8 *ciphers); - -/** - * tls_get_cipher - Get current cipher name - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @buf: Buffer for the cipher name - * @buflen: buf size - * Returns: 0 on success, -1 on failure - * - * Get the name of the currently used cipher. - */ -int __must_check tls_get_cipher(void *tls_ctx, struct tls_connection *conn, - char *buf, size_t buflen); - -/** - * tls_connection_enable_workaround - Enable TLS workaround options - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * Returns: 0 on success, -1 on failure - * - * This function is used to enable connection-specific workaround options for - * buffer SSL/TLS implementations. - */ -int __must_check tls_connection_enable_workaround(void *tls_ctx, - struct tls_connection *conn); - -/** - * tls_connection_client_hello_ext - Set TLS extension for ClientHello - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @ext_type: Extension type - * @data: Extension payload (%NULL to remove extension) - * @data_len: Extension payload length - * Returns: 0 on success, -1 on failure - */ -int __must_check tls_connection_client_hello_ext(void *tls_ctx, - struct tls_connection *conn, - int ext_type, const u8 *data, - size_t data_len); - -/** - * tls_connection_get_failed - Get connection failure status - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * - * Returns >0 if connection has failed, 0 if not. - */ -int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn); - -/** - * tls_connection_get_read_alerts - Get connection read alert status - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * Returns: Number of times a fatal read (remote end reported error) has - * happened during this connection. - */ -int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn); - -/** - * tls_connection_get_write_alerts - Get connection write alert status - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * Returns: Number of times a fatal write (locally detected error) has happened - * during this connection. - */ -int tls_connection_get_write_alerts(void *tls_ctx, - struct tls_connection *conn); - -/** - * tls_connection_get_keyblock_size - Get TLS key_block size - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * Returns: Size of the key_block for the negotiated cipher suite or -1 on - * failure - */ -int tls_connection_get_keyblock_size(void *tls_ctx, - struct tls_connection *conn); - -#define TLS_CAPABILITY_IA 0x0001 /* TLS Inner Application (TLS/IA) */ -/** - * tls_capabilities - Get supported TLS capabilities - * @tls_ctx: TLS context data from tls_init() - * Returns: Bit field of supported TLS capabilities (TLS_CAPABILITY_*) - */ -unsigned int tls_capabilities(void *tls_ctx); - -/** - * tls_connection_ia_send_phase_finished - Send a TLS/IA PhaseFinished message - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @final: 1 = FinalPhaseFinished, 0 = IntermediatePhaseFinished - * @out_data: Pointer to output buffer (encrypted TLS/IA data) - * @out_len: Maximum out_data length - * Returns: Number of bytes written to out_data on success, -1 on failure - * - * This function is used to send the TLS/IA end phase message, e.g., when the - * EAP server completes EAP-TTLSv1. - */ -int __must_check tls_connection_ia_send_phase_finished( - void *tls_ctx, struct tls_connection *conn, int final, - u8 *out_data, size_t out_len); - -/** - * tls_connection_ia_final_phase_finished - Has final phase been completed - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * Returns: 1 if valid FinalPhaseFinished has been received, 0 if not, or -1 - * on failure - */ -int __must_check tls_connection_ia_final_phase_finished( - void *tls_ctx, struct tls_connection *conn); - -/** - * tls_connection_ia_permute_inner_secret - Permute TLS/IA inner secret - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @key: Session key material (session_key vectors with 2-octet length), or - * %NULL if no session key was generating in the current phase - * @key_len: Length of session key material - * Returns: 0 on success, -1 on failure - */ -int __must_check tls_connection_ia_permute_inner_secret( - void *tls_ctx, struct tls_connection *conn, - const u8 *key, size_t key_len); - -typedef int (*tls_session_ticket_cb) -(void *ctx, const u8 *ticket, size_t len, const u8 *client_random, - const u8 *server_random, u8 *master_secret); - -int __must_check tls_connection_set_session_ticket_cb( - void *tls_ctx, struct tls_connection *conn, - tls_session_ticket_cb cb, void *ctx); - -#endif /* TLS_H */ diff --git a/contrib/hostapd/src/crypto/tls_gnutls.c b/contrib/hostapd/src/crypto/tls_gnutls.c deleted file mode 100644 index 2c5c5a2b64..0000000000 --- a/contrib/hostapd/src/crypto/tls_gnutls.c +++ /dev/null @@ -1,1428 +0,0 @@ -/* - * WPA Supplicant / SSL/TLS interface functions for openssl - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include -#ifdef PKCS12_FUNCS -#include -#endif /* PKCS12_FUNCS */ - -#ifdef CONFIG_GNUTLS_EXTRA -#if LIBGNUTLS_VERSION_NUMBER >= 0x010302 -#define GNUTLS_IA -#include -#if LIBGNUTLS_VERSION_NUMBER == 0x010302 -/* This function is not included in the current gnutls/extra.h even though it - * should be, so define it here as a workaround for the time being. */ -int gnutls_ia_verify_endphase(gnutls_session_t session, char *checksum); -#endif /* LIBGNUTLS_VERSION_NUMBER == 0x010302 */ -#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ -#endif /* CONFIG_GNUTLS_EXTRA */ - -#include "common.h" -#include "tls.h" - - -#ifndef TLS_RANDOM_SIZE -#define TLS_RANDOM_SIZE 32 -#endif -#ifndef TLS_MASTER_SIZE -#define TLS_MASTER_SIZE 48 -#endif - - -#if LIBGNUTLS_VERSION_NUMBER < 0x010302 -/* GnuTLS 1.3.2 added functions for using master secret. Older versions require - * use of internal structures to get the master_secret and - * {server,client}_random. - */ -#define GNUTLS_INTERNAL_STRUCTURE_HACK -#endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */ - - -#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK -/* - * It looks like gnutls does not provide access to client/server_random and - * master_key. This is somewhat unfortunate since these are needed for key - * derivation in EAP-{TLS,TTLS,PEAP,FAST}. Workaround for now is a horrible - * hack that copies the gnutls_session_int definition from gnutls_int.h so that - * we can get the needed information. - */ - -typedef u8 uint8; -typedef unsigned char opaque; -typedef struct { - uint8 suite[2]; -} cipher_suite_st; - -typedef struct { - gnutls_connection_end_t entity; - gnutls_kx_algorithm_t kx_algorithm; - gnutls_cipher_algorithm_t read_bulk_cipher_algorithm; - gnutls_mac_algorithm_t read_mac_algorithm; - gnutls_compression_method_t read_compression_algorithm; - gnutls_cipher_algorithm_t write_bulk_cipher_algorithm; - gnutls_mac_algorithm_t write_mac_algorithm; - gnutls_compression_method_t write_compression_algorithm; - cipher_suite_st current_cipher_suite; - opaque master_secret[TLS_MASTER_SIZE]; - opaque client_random[TLS_RANDOM_SIZE]; - opaque server_random[TLS_RANDOM_SIZE]; - /* followed by stuff we are not interested in */ -} security_parameters_st; - -struct gnutls_session_int { - security_parameters_st security_parameters; - /* followed by things we are not interested in */ -}; -#endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */ - -static int tls_gnutls_ref_count = 0; - -struct tls_global { - /* Data for session resumption */ - void *session_data; - size_t session_data_size; - - int server; - - int params_set; - gnutls_certificate_credentials_t xcred; -}; - -struct tls_connection { - gnutls_session session; - char *subject_match, *altsubject_match; - int read_alerts, write_alerts, failed; - - u8 *pre_shared_secret; - size_t pre_shared_secret_len; - int established; - int verify_peer; - - u8 *push_buf, *pull_buf, *pull_buf_offset; - size_t push_buf_len, pull_buf_len; - - int params_set; - gnutls_certificate_credentials_t xcred; - - int tls_ia; - int final_phase_finished; - -#ifdef GNUTLS_IA - gnutls_ia_server_credentials_t iacred_srv; - gnutls_ia_client_credentials_t iacred_cli; - - /* Session keys generated in the current phase for inner secret - * permutation before generating/verifying PhaseFinished. */ - u8 *session_keys; - size_t session_keys_len; - - u8 inner_secret[TLS_MASTER_SIZE]; -#endif /* GNUTLS_IA */ -}; - - -static void tls_log_func(int level, const char *msg) -{ - char *s, *pos; - if (level == 6 || level == 7) { - /* These levels seem to be mostly I/O debug and msg dumps */ - return; - } - - s = os_strdup(msg); - if (s == NULL) - return; - - pos = s; - while (*pos != '\0') { - if (*pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } - wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG, - "gnutls<%d> %s", level, s); - os_free(s); -} - - -extern int wpa_debug_show_keys; - -void * tls_init(const struct tls_config *conf) -{ - struct tls_global *global; - -#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK - /* Because of the horrible hack to get master_secret and client/server - * random, we need to make sure that the gnutls version is something - * that is expected to have same structure definition for the session - * data.. */ - const char *ver; - const char *ok_ver[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", "1.2.9", - "1.3.2", - NULL }; - int i; -#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ - - global = os_zalloc(sizeof(*global)); - if (global == NULL) - return NULL; - - if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) { - os_free(global); - return NULL; - } - tls_gnutls_ref_count++; - -#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK - ver = gnutls_check_version(NULL); - if (ver == NULL) { - tls_deinit(global); - return NULL; - } - wpa_printf(MSG_DEBUG, "%s - gnutls version %s", __func__, ver); - for (i = 0; ok_ver[i]; i++) { - if (strcmp(ok_ver[i], ver) == 0) - break; - } - if (ok_ver[i] == NULL) { - wpa_printf(MSG_INFO, "Untested gnutls version %s - this needs " - "to be tested and enabled in tls_gnutls.c", ver); - tls_deinit(global); - return NULL; - } -#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ - - gnutls_global_set_log_function(tls_log_func); - if (wpa_debug_show_keys) - gnutls_global_set_log_level(11); - return global; -} - - -void tls_deinit(void *ssl_ctx) -{ - struct tls_global *global = ssl_ctx; - if (global) { - if (global->params_set) - gnutls_certificate_free_credentials(global->xcred); - os_free(global->session_data); - os_free(global); - } - - tls_gnutls_ref_count--; - if (tls_gnutls_ref_count == 0) - gnutls_global_deinit(); -} - - -int tls_get_errors(void *ssl_ctx) -{ - return 0; -} - - -static ssize_t tls_pull_func(gnutls_transport_ptr ptr, void *buf, - size_t len) -{ - struct tls_connection *conn = (struct tls_connection *) ptr; - u8 *end; - if (conn->pull_buf == NULL) { - errno = EWOULDBLOCK; - return -1; - } - - end = conn->pull_buf + conn->pull_buf_len; - if ((size_t) (end - conn->pull_buf_offset) < len) - len = end - conn->pull_buf_offset; - os_memcpy(buf, conn->pull_buf_offset, len); - conn->pull_buf_offset += len; - if (conn->pull_buf_offset == end) { - wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__); - os_free(conn->pull_buf); - conn->pull_buf = conn->pull_buf_offset = NULL; - conn->pull_buf_len = 0; - } else { - wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf", - __func__, - (unsigned long) (end - conn->pull_buf_offset)); - } - return len; -} - - -static ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf, - size_t len) -{ - struct tls_connection *conn = (struct tls_connection *) ptr; - u8 *nbuf; - - nbuf = os_realloc(conn->push_buf, conn->push_buf_len + len); - if (nbuf == NULL) { - errno = ENOMEM; - return -1; - } - os_memcpy(nbuf + conn->push_buf_len, buf, len); - conn->push_buf = nbuf; - conn->push_buf_len += len; - - return len; -} - - -static int tls_gnutls_init_session(struct tls_global *global, - struct tls_connection *conn) -{ - const int cert_types[2] = { GNUTLS_CRT_X509, 0 }; - const int protos[2] = { GNUTLS_TLS1, 0 }; - int ret; - - ret = gnutls_init(&conn->session, - global->server ? GNUTLS_SERVER : GNUTLS_CLIENT); - if (ret < 0) { - wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS " - "connection: %s", gnutls_strerror(ret)); - return -1; - } - - ret = gnutls_set_default_priority(conn->session); - if (ret < 0) - goto fail; - - ret = gnutls_certificate_type_set_priority(conn->session, cert_types); - if (ret < 0) - goto fail; - - ret = gnutls_protocol_set_priority(conn->session, protos); - if (ret < 0) - goto fail; - - gnutls_transport_set_pull_function(conn->session, tls_pull_func); - gnutls_transport_set_push_function(conn->session, tls_push_func); - gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn); - - return 0; - -fail: - wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s", - gnutls_strerror(ret)); - gnutls_deinit(conn->session); - return -1; -} - - -struct tls_connection * tls_connection_init(void *ssl_ctx) -{ - struct tls_global *global = ssl_ctx; - struct tls_connection *conn; - int ret; - - conn = os_zalloc(sizeof(*conn)); - if (conn == NULL) - return NULL; - - if (tls_gnutls_init_session(global, conn)) { - os_free(conn); - return NULL; - } - - if (global->params_set) { - ret = gnutls_credentials_set(conn->session, - GNUTLS_CRD_CERTIFICATE, - global->xcred); - if (ret < 0) { - wpa_printf(MSG_INFO, "Failed to configure " - "credentials: %s", gnutls_strerror(ret)); - os_free(conn); - return NULL; - } - } - - if (gnutls_certificate_allocate_credentials(&conn->xcred)) { - os_free(conn); - return NULL; - } - - return conn; -} - - -void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return; - -#ifdef GNUTLS_IA - if (conn->iacred_srv) - gnutls_ia_free_server_credentials(conn->iacred_srv); - if (conn->iacred_cli) - gnutls_ia_free_client_credentials(conn->iacred_cli); - if (conn->session_keys) { - os_memset(conn->session_keys, 0, conn->session_keys_len); - os_free(conn->session_keys); - } -#endif /* GNUTLS_IA */ - - gnutls_certificate_free_credentials(conn->xcred); - gnutls_deinit(conn->session); - os_free(conn->pre_shared_secret); - os_free(conn->subject_match); - os_free(conn->altsubject_match); - os_free(conn->push_buf); - os_free(conn->pull_buf); - os_free(conn); -} - - -int tls_connection_established(void *ssl_ctx, struct tls_connection *conn) -{ - return conn ? conn->established : 0; -} - - -int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn) -{ - struct tls_global *global = ssl_ctx; - int ret; - - if (conn == NULL) - return -1; - - /* Shutdown previous TLS connection without notifying the peer - * because the connection was already terminated in practice - * and "close notify" shutdown alert would confuse AS. */ - gnutls_bye(conn->session, GNUTLS_SHUT_RDWR); - os_free(conn->push_buf); - conn->push_buf = NULL; - conn->push_buf_len = 0; - conn->established = 0; - conn->final_phase_finished = 0; -#ifdef GNUTLS_IA - if (conn->session_keys) { - os_memset(conn->session_keys, 0, conn->session_keys_len); - os_free(conn->session_keys); - } - conn->session_keys_len = 0; -#endif /* GNUTLS_IA */ - - gnutls_deinit(conn->session); - if (tls_gnutls_init_session(global, conn)) { - wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session " - "for session resumption use"); - return -1; - } - - ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, - conn->params_set ? conn->xcred : - global->xcred); - if (ret < 0) { - wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials " - "for session resumption: %s", gnutls_strerror(ret)); - return -1; - } - - if (global->session_data) { - ret = gnutls_session_set_data(conn->session, - global->session_data, - global->session_data_size); - if (ret < 0) { - wpa_printf(MSG_INFO, "GnuTLS: Failed to set session " - "data: %s", gnutls_strerror(ret)); - return -1; - } - } - - return 0; -} - - -#if 0 -static int tls_match_altsubject(X509 *cert, const char *match) -{ - GENERAL_NAME *gen; - char *field, *tmp; - void *ext; - int i, found = 0; - size_t len; - - ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); - - for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) { - gen = sk_GENERAL_NAME_value(ext, i); - switch (gen->type) { - case GEN_EMAIL: - field = "EMAIL"; - break; - case GEN_DNS: - field = "DNS"; - break; - case GEN_URI: - field = "URI"; - break; - default: - field = NULL; - wpa_printf(MSG_DEBUG, "TLS: altSubjectName: " - "unsupported type=%d", gen->type); - break; - } - - if (!field) - continue; - - wpa_printf(MSG_DEBUG, "TLS: altSubjectName: %s:%s", - field, gen->d.ia5->data); - len = os_strlen(field) + 1 + - strlen((char *) gen->d.ia5->data) + 1; - tmp = os_malloc(len); - if (tmp == NULL) - continue; - snprintf(tmp, len, "%s:%s", field, gen->d.ia5->data); - if (strstr(tmp, match)) - found++; - os_free(tmp); - } - - return found; -} -#endif - - -#if 0 -static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) -{ - char buf[256]; - X509 *err_cert; - int err, depth; - SSL *ssl; - struct tls_connection *conn; - char *match, *altmatch; - - err_cert = X509_STORE_CTX_get_current_cert(x509_ctx); - err = X509_STORE_CTX_get_error(x509_ctx); - depth = X509_STORE_CTX_get_error_depth(x509_ctx); - ssl = X509_STORE_CTX_get_ex_data(x509_ctx, - SSL_get_ex_data_X509_STORE_CTX_idx()); - X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); - - conn = SSL_get_app_data(ssl); - match = conn ? conn->subject_match : NULL; - altmatch = conn ? conn->altsubject_match : NULL; - - if (!preverify_ok) { - wpa_printf(MSG_WARNING, "TLS: Certificate verification failed," - " error %d (%s) depth %d for '%s'", err, - X509_verify_cert_error_string(err), depth, buf); - } else { - wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - " - "preverify_ok=%d err=%d (%s) depth=%d buf='%s'", - preverify_ok, err, - X509_verify_cert_error_string(err), depth, buf); - if (depth == 0 && match && strstr(buf, match) == NULL) { - wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not " - "match with '%s'", buf, match); - preverify_ok = 0; - } else if (depth == 0 && altmatch && - !tls_match_altsubject(err_cert, altmatch)) { - wpa_printf(MSG_WARNING, "TLS: altSubjectName match " - "'%s' not found", altmatch); - preverify_ok = 0; - } - } - - return preverify_ok; -} -#endif - - -int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, - const struct tls_connection_params *params) -{ - int ret; - - if (conn == NULL || params == NULL) - return -1; - - os_free(conn->subject_match); - conn->subject_match = NULL; - if (params->subject_match) { - conn->subject_match = os_strdup(params->subject_match); - if (conn->subject_match == NULL) - return -1; - } - - os_free(conn->altsubject_match); - conn->altsubject_match = NULL; - if (params->altsubject_match) { - conn->altsubject_match = os_strdup(params->altsubject_match); - if (conn->altsubject_match == NULL) - return -1; - } - - /* TODO: gnutls_certificate_set_verify_flags(xcred, flags); - * to force peer validation(?) */ - - if (params->ca_cert) { - conn->verify_peer = 1; - ret = gnutls_certificate_set_x509_trust_file( - conn->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' " - "in PEM format: %s", params->ca_cert, - gnutls_strerror(ret)); - ret = gnutls_certificate_set_x509_trust_file( - conn->xcred, params->ca_cert, - GNUTLS_X509_FMT_DER); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "Failed to read CA cert " - "'%s' in DER format: %s", - params->ca_cert, - gnutls_strerror(ret)); - return -1; - } - } - - if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) { - gnutls_certificate_set_verify_flags( - conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); - } - - if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) { - gnutls_certificate_set_verify_flags( - conn->xcred, - GNUTLS_VERIFY_DISABLE_TIME_CHECKS); - } - } - - if (params->client_cert && params->private_key) { - /* TODO: private_key_passwd? */ - ret = gnutls_certificate_set_x509_key_file( - conn->xcred, params->client_cert, params->private_key, - GNUTLS_X509_FMT_PEM); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "Failed to read client cert/key " - "in PEM format: %s", gnutls_strerror(ret)); - ret = gnutls_certificate_set_x509_key_file( - conn->xcred, params->client_cert, - params->private_key, GNUTLS_X509_FMT_DER); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "Failed to read client " - "cert/key in DER format: %s", - gnutls_strerror(ret)); - return ret; - } - } - } else if (params->private_key) { - int pkcs12_ok = 0; -#ifdef PKCS12_FUNCS - /* Try to load in PKCS#12 format */ -#if LIBGNUTLS_VERSION_NUMBER >= 0x010302 - ret = gnutls_certificate_set_x509_simple_pkcs12_file( - conn->xcred, params->private_key, GNUTLS_X509_FMT_DER, - params->private_key_passwd); - if (ret != 0) { - wpa_printf(MSG_DEBUG, "Failed to load private_key in " - "PKCS#12 format: %s", gnutls_strerror(ret)); - return -1; - } else - pkcs12_ok = 1; -#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ -#endif /* PKCS12_FUNCS */ - - if (!pkcs12_ok) { - wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not " - "included"); - return -1; - } - } - - conn->tls_ia = params->tls_ia; - conn->params_set = 1; - - ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, - conn->xcred); - if (ret < 0) { - wpa_printf(MSG_INFO, "Failed to configure credentials: %s", - gnutls_strerror(ret)); - } - -#ifdef GNUTLS_IA - if (conn->iacred_cli) - gnutls_ia_free_client_credentials(conn->iacred_cli); - - ret = gnutls_ia_allocate_client_credentials(&conn->iacred_cli); - if (ret) { - wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s", - gnutls_strerror(ret)); - return -1; - } - - ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA, - conn->iacred_cli); - if (ret) { - wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s", - gnutls_strerror(ret)); - gnutls_ia_free_client_credentials(conn->iacred_cli); - conn->iacred_cli = NULL; - return -1; - } -#endif /* GNUTLS_IE */ - - return ret; -} - - -int tls_global_set_params(void *tls_ctx, - const struct tls_connection_params *params) -{ - struct tls_global *global = tls_ctx; - int ret; - - /* Currently, global parameters are only set when running in server - * mode. */ - global->server = 1; - - if (global->params_set) { - gnutls_certificate_free_credentials(global->xcred); - global->params_set = 0; - } - - ret = gnutls_certificate_allocate_credentials(&global->xcred); - if (ret) { - wpa_printf(MSG_DEBUG, "Failed to allocate global credentials " - "%s", gnutls_strerror(ret)); - return -1; - } - - if (params->ca_cert) { - ret = gnutls_certificate_set_x509_trust_file( - global->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' " - "in PEM format: %s", params->ca_cert, - gnutls_strerror(ret)); - ret = gnutls_certificate_set_x509_trust_file( - global->xcred, params->ca_cert, - GNUTLS_X509_FMT_DER); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "Failed to read CA cert " - "'%s' in DER format: %s", - params->ca_cert, - gnutls_strerror(ret)); - goto fail; - } - } - - if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) { - gnutls_certificate_set_verify_flags( - global->xcred, - GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); - } - - if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) { - gnutls_certificate_set_verify_flags( - global->xcred, - GNUTLS_VERIFY_DISABLE_TIME_CHECKS); - } - } - - if (params->client_cert && params->private_key) { - /* TODO: private_key_passwd? */ - ret = gnutls_certificate_set_x509_key_file( - global->xcred, params->client_cert, - params->private_key, GNUTLS_X509_FMT_PEM); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "Failed to read client cert/key " - "in PEM format: %s", gnutls_strerror(ret)); - ret = gnutls_certificate_set_x509_key_file( - global->xcred, params->client_cert, - params->private_key, GNUTLS_X509_FMT_DER); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "Failed to read client " - "cert/key in DER format: %s", - gnutls_strerror(ret)); - goto fail; - } - } - } else if (params->private_key) { - int pkcs12_ok = 0; -#ifdef PKCS12_FUNCS - /* Try to load in PKCS#12 format */ -#if LIBGNUTLS_VERSION_NUMBER >= 0x010302 - ret = gnutls_certificate_set_x509_simple_pkcs12_file( - global->xcred, params->private_key, - GNUTLS_X509_FMT_DER, params->private_key_passwd); - if (ret != 0) { - wpa_printf(MSG_DEBUG, "Failed to load private_key in " - "PKCS#12 format: %s", gnutls_strerror(ret)); - goto fail; - } else - pkcs12_ok = 1; -#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ -#endif /* PKCS12_FUNCS */ - - if (!pkcs12_ok) { - wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not " - "included"); - goto fail; - } - } - - global->params_set = 1; - - return 0; - -fail: - gnutls_certificate_free_credentials(global->xcred); - return -1; -} - - -int tls_global_set_verify(void *ssl_ctx, int check_crl) -{ - /* TODO */ - return 0; -} - - -int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, - int verify_peer) -{ - if (conn == NULL || conn->session == NULL) - return -1; - - conn->verify_peer = verify_peer; - gnutls_certificate_server_set_request(conn->session, - verify_peer ? GNUTLS_CERT_REQUIRE - : GNUTLS_CERT_REQUEST); - - return 0; -} - - -int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, - struct tls_keys *keys) -{ -#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK - security_parameters_st *sec; -#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ - - if (conn == NULL || conn->session == NULL || keys == NULL) - return -1; - - os_memset(keys, 0, sizeof(*keys)); - -#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK - sec = &conn->session->security_parameters; - keys->master_key = sec->master_secret; - keys->master_key_len = TLS_MASTER_SIZE; - keys->client_random = sec->client_random; - keys->server_random = sec->server_random; -#else /* GNUTLS_INTERNAL_STRUCTURE_HACK */ - keys->client_random = - (u8 *) gnutls_session_get_client_random(conn->session); - keys->server_random = - (u8 *) gnutls_session_get_server_random(conn->session); - /* No access to master_secret */ -#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ - -#ifdef GNUTLS_IA - gnutls_ia_extract_inner_secret(conn->session, - (char *) conn->inner_secret); - keys->inner_secret = conn->inner_secret; - keys->inner_secret_len = TLS_MASTER_SIZE; -#endif /* GNUTLS_IA */ - - keys->client_random_len = TLS_RANDOM_SIZE; - keys->server_random_len = TLS_RANDOM_SIZE; - - return 0; -} - - -int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, - const char *label, int server_random_first, - u8 *out, size_t out_len) -{ -#if LIBGNUTLS_VERSION_NUMBER >= 0x010302 - if (conn == NULL || conn->session == NULL) - return -1; - - return gnutls_prf(conn->session, os_strlen(label), label, - server_random_first, 0, NULL, out_len, (char *) out); -#else /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ - return -1; -#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ -} - - -static int tls_connection_verify_peer(struct tls_connection *conn, - gnutls_alert_description_t *err) -{ - unsigned int status, num_certs, i; - struct os_time now; - const gnutls_datum_t *certs; - gnutls_x509_crt_t cert; - - if (gnutls_certificate_verify_peers2(conn->session, &status) < 0) { - wpa_printf(MSG_INFO, "TLS: Failed to verify peer " - "certificate chain"); - *err = GNUTLS_A_INTERNAL_ERROR; - return -1; - } - - if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) { - wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted"); - if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { - wpa_printf(MSG_INFO, "TLS: Certificate uses insecure " - "algorithm"); - *err = GNUTLS_A_INSUFFICIENT_SECURITY; - } - if (status & GNUTLS_CERT_NOT_ACTIVATED) { - wpa_printf(MSG_INFO, "TLS: Certificate not yet " - "activated"); - *err = GNUTLS_A_CERTIFICATE_EXPIRED; - } - if (status & GNUTLS_CERT_EXPIRED) { - wpa_printf(MSG_INFO, "TLS: Certificate expired"); - *err = GNUTLS_A_CERTIFICATE_EXPIRED; - } - return -1; - } - - if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { - wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a " - "known issuer"); - *err = GNUTLS_A_UNKNOWN_CA; - return -1; - } - - if (status & GNUTLS_CERT_REVOKED) { - wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked"); - *err = GNUTLS_A_CERTIFICATE_REVOKED; - return -1; - } - - os_get_time(&now); - - certs = gnutls_certificate_get_peers(conn->session, &num_certs); - if (certs == NULL) { - wpa_printf(MSG_INFO, "TLS: No peer certificate chain " - "received"); - *err = GNUTLS_A_UNKNOWN_CA; - return -1; - } - - for (i = 0; i < num_certs; i++) { - char *buf; - size_t len; - if (gnutls_x509_crt_init(&cert) < 0) { - wpa_printf(MSG_INFO, "TLS: Certificate initialization " - "failed"); - *err = GNUTLS_A_BAD_CERTIFICATE; - return -1; - } - - if (gnutls_x509_crt_import(cert, &certs[i], - GNUTLS_X509_FMT_DER) < 0) { - wpa_printf(MSG_INFO, "TLS: Could not parse peer " - "certificate %d/%d", i + 1, num_certs); - gnutls_x509_crt_deinit(cert); - *err = GNUTLS_A_BAD_CERTIFICATE; - return -1; - } - - gnutls_x509_crt_get_dn(cert, NULL, &len); - len++; - buf = os_malloc(len + 1); - if (buf) { - buf[0] = buf[len] = '\0'; - gnutls_x509_crt_get_dn(cert, buf, &len); - } - wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s", - i + 1, num_certs, buf); - - if (i == 0) { - /* TODO: validate subject_match and altsubject_match */ - } - - os_free(buf); - - if (gnutls_x509_crt_get_expiration_time(cert) < now.sec || - gnutls_x509_crt_get_activation_time(cert) > now.sec) { - wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is " - "not valid at this time", - i + 1, num_certs); - gnutls_x509_crt_deinit(cert); - *err = GNUTLS_A_CERTIFICATE_EXPIRED; - return -1; - } - - gnutls_x509_crt_deinit(cert); - } - - return 0; -} - - -u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len) -{ - struct tls_global *global = ssl_ctx; - u8 *out_data; - int ret; - - if (appl_data) - *appl_data = NULL; - - if (in_data && in_len) { - if (conn->pull_buf) { - wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " - "pull_buf", __func__, - (unsigned long) conn->pull_buf_len); - os_free(conn->pull_buf); - } - conn->pull_buf = os_malloc(in_len); - if (conn->pull_buf == NULL) - return NULL; - os_memcpy(conn->pull_buf, in_data, in_len); - conn->pull_buf_offset = conn->pull_buf; - conn->pull_buf_len = in_len; - } - - ret = gnutls_handshake(conn->session); - if (ret < 0) { - switch (ret) { - case GNUTLS_E_AGAIN: - if (global->server && conn->established && - conn->push_buf == NULL) { - /* Need to return something to trigger - * completion of EAP-TLS. */ - conn->push_buf = os_malloc(1); - } - break; - case GNUTLS_E_FATAL_ALERT_RECEIVED: - wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert", - __func__, gnutls_alert_get_name( - gnutls_alert_get(conn->session))); - conn->read_alerts++; - /* continue */ - default: - wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed " - "-> %s", __func__, gnutls_strerror(ret)); - conn->failed++; - } - } else { - size_t size; - gnutls_alert_description_t err; - - if (conn->verify_peer && - tls_connection_verify_peer(conn, &err)) { - wpa_printf(MSG_INFO, "TLS: Peer certificate chain " - "failed validation"); - conn->failed++; - gnutls_alert_send(conn->session, GNUTLS_AL_FATAL, err); - goto out; - } - -#ifdef CONFIG_GNUTLS_EXTRA - if (conn->tls_ia && !gnutls_ia_handshake_p(conn->session)) { - wpa_printf(MSG_INFO, "TLS: No TLS/IA negotiation"); - conn->failed++; - return NULL; - } -#endif /* CONFIG_GNUTLS_EXTRA */ - - if (conn->tls_ia) - wpa_printf(MSG_DEBUG, "TLS: Start TLS/IA handshake"); - else { - wpa_printf(MSG_DEBUG, "TLS: Handshake completed " - "successfully"); - } - conn->established = 1; - if (conn->push_buf == NULL) { - /* Need to return something to get final TLS ACK. */ - conn->push_buf = os_malloc(1); - } - - gnutls_session_get_data(conn->session, NULL, &size); - if (global->session_data == NULL || - global->session_data_size < size) { - os_free(global->session_data); - global->session_data = os_malloc(size); - } - if (global->session_data) { - global->session_data_size = size; - gnutls_session_get_data(conn->session, - global->session_data, - &global->session_data_size); - } - } - -out: - out_data = conn->push_buf; - *out_len = conn->push_buf_len; - conn->push_buf = NULL; - conn->push_buf_len = 0; - return out_data; -} - - -u8 * tls_connection_server_handshake(void *ssl_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len) -{ - return tls_connection_handshake(ssl_ctx, conn, in_data, in_len, - out_len, NULL, NULL); -} - - -int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - ssize_t res; - -#ifdef GNUTLS_IA - if (conn->tls_ia) - res = gnutls_ia_send(conn->session, (char *) in_data, in_len); - else -#endif /* GNUTLS_IA */ - res = gnutls_record_send(conn->session, in_data, in_len); - if (res < 0) { - wpa_printf(MSG_INFO, "%s: Encryption failed: %s", - __func__, gnutls_strerror(res)); - return -1; - } - if (conn->push_buf == NULL) - return -1; - if (conn->push_buf_len < out_len) - out_len = conn->push_buf_len; - else if (conn->push_buf_len > out_len) { - wpa_printf(MSG_INFO, "GnuTLS: Not enough buffer space for " - "encrypted message (in_len=%lu push_buf_len=%lu " - "out_len=%lu", - (unsigned long) in_len, - (unsigned long) conn->push_buf_len, - (unsigned long) out_len); - } - os_memcpy(out_data, conn->push_buf, out_len); - os_free(conn->push_buf); - conn->push_buf = NULL; - conn->push_buf_len = 0; - return out_len; -} - - -int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - ssize_t res; - - if (conn->pull_buf) { - wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " - "pull_buf", __func__, - (unsigned long) conn->pull_buf_len); - os_free(conn->pull_buf); - } - conn->pull_buf = os_malloc(in_len); - if (conn->pull_buf == NULL) - return -1; - os_memcpy(conn->pull_buf, in_data, in_len); - conn->pull_buf_offset = conn->pull_buf; - conn->pull_buf_len = in_len; - -#ifdef GNUTLS_IA - if (conn->tls_ia) { - res = gnutls_ia_recv(conn->session, (char *) out_data, - out_len); - if (out_len >= 12 && - (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED || - res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)) { - int final = res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED; - wpa_printf(MSG_DEBUG, "%s: Received %sPhaseFinished", - __func__, final ? "Final" : "Intermediate"); - - res = gnutls_ia_permute_inner_secret( - conn->session, conn->session_keys_len, - (char *) conn->session_keys); - if (conn->session_keys) { - os_memset(conn->session_keys, 0, - conn->session_keys_len); - os_free(conn->session_keys); - } - conn->session_keys = NULL; - conn->session_keys_len = 0; - if (res) { - wpa_printf(MSG_DEBUG, "%s: Failed to permute " - "inner secret: %s", - __func__, gnutls_strerror(res)); - return -1; - } - - res = gnutls_ia_verify_endphase(conn->session, - (char *) out_data); - if (res == 0) { - wpa_printf(MSG_DEBUG, "%s: Correct endphase " - "checksum", __func__); - } else { - wpa_printf(MSG_INFO, "%s: Endphase " - "verification failed: %s", - __func__, gnutls_strerror(res)); - return -1; - } - - if (final) - conn->final_phase_finished = 1; - - return 0; - } - - if (res < 0) { - wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d " - "(%s)", __func__, (int) res, - gnutls_strerror(res)); - } - return res; - } -#endif /* GNUTLS_IA */ - - res = gnutls_record_recv(conn->session, out_data, out_len); - if (res < 0) { - wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d " - "(%s)", __func__, (int) res, gnutls_strerror(res)); - } - - return res; -} - - -int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return 0; - return gnutls_session_is_resumed(conn->session); -} - - -int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, - u8 *ciphers) -{ - /* TODO */ - return -1; -} - - -int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, - char *buf, size_t buflen) -{ - /* TODO */ - buf[0] = '\0'; - return 0; -} - - -int tls_connection_enable_workaround(void *ssl_ctx, - struct tls_connection *conn) -{ - /* TODO: set SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS */ - return 0; -} - - -int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, - int ext_type, const u8 *data, - size_t data_len) -{ - /* TODO */ - return -1; -} - - -int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - return conn->failed; -} - - -int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - return conn->read_alerts; -} - - -int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - return conn->write_alerts; -} - - -int tls_connection_get_keyblock_size(void *tls_ctx, - struct tls_connection *conn) -{ - /* TODO */ - return -1; -} - - -unsigned int tls_capabilities(void *tls_ctx) -{ - unsigned int capa = 0; - -#ifdef GNUTLS_IA - capa |= TLS_CAPABILITY_IA; -#endif /* GNUTLS_IA */ - - return capa; -} - - -int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, - int tls_ia) -{ -#ifdef GNUTLS_IA - int ret; - - if (conn == NULL) - return -1; - - conn->tls_ia = tls_ia; - if (!tls_ia) - return 0; - - ret = gnutls_ia_allocate_server_credentials(&conn->iacred_srv); - if (ret) { - wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s", - gnutls_strerror(ret)); - return -1; - } - - ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA, - conn->iacred_srv); - if (ret) { - wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s", - gnutls_strerror(ret)); - gnutls_ia_free_server_credentials(conn->iacred_srv); - conn->iacred_srv = NULL; - return -1; - } - - return 0; -#else /* GNUTLS_IA */ - return -1; -#endif /* GNUTLS_IA */ -} - - -int tls_connection_ia_send_phase_finished(void *tls_ctx, - struct tls_connection *conn, - int final, - u8 *out_data, size_t out_len) -{ -#ifdef GNUTLS_IA - int ret; - - if (conn == NULL || conn->session == NULL || !conn->tls_ia) - return -1; - - ret = gnutls_ia_permute_inner_secret(conn->session, - conn->session_keys_len, - (char *) conn->session_keys); - if (conn->session_keys) { - os_memset(conn->session_keys, 0, conn->session_keys_len); - os_free(conn->session_keys); - } - conn->session_keys = NULL; - conn->session_keys_len = 0; - if (ret) { - wpa_printf(MSG_DEBUG, "%s: Failed to permute inner secret: %s", - __func__, gnutls_strerror(ret)); - return -1; - } - - ret = gnutls_ia_endphase_send(conn->session, final); - if (ret) { - wpa_printf(MSG_DEBUG, "%s: Failed to send endphase: %s", - __func__, gnutls_strerror(ret)); - return -1; - } - - if (conn->push_buf == NULL) - return -1; - if (conn->push_buf_len < out_len) - out_len = conn->push_buf_len; - os_memcpy(out_data, conn->push_buf, out_len); - os_free(conn->push_buf); - conn->push_buf = NULL; - conn->push_buf_len = 0; - return out_len; -#else /* GNUTLS_IA */ - return -1; -#endif /* GNUTLS_IA */ -} - - -int tls_connection_ia_final_phase_finished(void *tls_ctx, - struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - - return conn->final_phase_finished; -} - - -int tls_connection_ia_permute_inner_secret(void *tls_ctx, - struct tls_connection *conn, - const u8 *key, size_t key_len) -{ -#ifdef GNUTLS_IA - if (conn == NULL || !conn->tls_ia) - return -1; - - if (conn->session_keys) { - os_memset(conn->session_keys, 0, conn->session_keys_len); - os_free(conn->session_keys); - } - conn->session_keys_len = 0; - - if (key) { - conn->session_keys = os_malloc(key_len); - if (conn->session_keys == NULL) - return -1; - os_memcpy(conn->session_keys, key, key_len); - conn->session_keys_len = key_len; - } else { - conn->session_keys = NULL; - conn->session_keys_len = 0; - } - - return 0; -#else /* GNUTLS_IA */ - return -1; -#endif /* GNUTLS_IA */ -} diff --git a/contrib/hostapd/src/crypto/tls_internal.c b/contrib/hostapd/src/crypto/tls_internal.c deleted file mode 100644 index 42120c8a88..0000000000 --- a/contrib/hostapd/src/crypto/tls_internal.c +++ /dev/null @@ -1,569 +0,0 @@ -/* - * WPA Supplicant / TLS interface functions and an internal TLS implementation - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file interface functions for hostapd/wpa_supplicant to use the - * integrated TLSv1 implementation. - */ - -#include "includes.h" - -#include "common.h" -#include "tls.h" -#include "tls/tlsv1_client.h" -#include "tls/tlsv1_server.h" - - -static int tls_ref_count = 0; - -struct tls_global { - int server; - struct tlsv1_credentials *server_cred; - int check_crl; -}; - -struct tls_connection { - struct tlsv1_client *client; - struct tlsv1_server *server; -}; - - -void * tls_init(const struct tls_config *conf) -{ - struct tls_global *global; - - if (tls_ref_count == 0) { -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (tlsv1_client_global_init()) - return NULL; -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (tlsv1_server_global_init()) - return NULL; -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - } - tls_ref_count++; - - global = os_zalloc(sizeof(*global)); - if (global == NULL) - return NULL; - - return global; -} - -void tls_deinit(void *ssl_ctx) -{ - struct tls_global *global = ssl_ctx; - tls_ref_count--; - if (tls_ref_count == 0) { -#ifdef CONFIG_TLS_INTERNAL_CLIENT - tlsv1_client_global_deinit(); -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - tlsv1_cred_free(global->server_cred); - tlsv1_server_global_deinit(); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - } - os_free(global); -} - - -int tls_get_errors(void *tls_ctx) -{ - return 0; -} - - -struct tls_connection * tls_connection_init(void *tls_ctx) -{ - struct tls_connection *conn; - struct tls_global *global = tls_ctx; - - conn = os_zalloc(sizeof(*conn)); - if (conn == NULL) - return NULL; - -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (!global->server) { - conn->client = tlsv1_client_init(); - if (conn->client == NULL) { - os_free(conn); - return NULL; - } - } -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (global->server) { - conn->server = tlsv1_server_init(global->server_cred); - if (conn->server == NULL) { - os_free(conn); - return NULL; - } - } -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - - return conn; -} - - -void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return; -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) - tlsv1_client_deinit(conn->client); -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) - tlsv1_server_deinit(conn->server); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - os_free(conn); -} - - -int tls_connection_established(void *tls_ctx, struct tls_connection *conn) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) - return tlsv1_client_established(conn->client); -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) - return tlsv1_server_established(conn->server); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return 0; -} - - -int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) - return tlsv1_client_shutdown(conn->client); -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) - return tlsv1_server_shutdown(conn->server); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} - - -int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, - const struct tls_connection_params *params) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - struct tlsv1_credentials *cred; - - if (conn->client == NULL) - return -1; - - cred = tlsv1_cred_alloc(); - if (cred == NULL) - return -1; - - if (tlsv1_set_ca_cert(cred, params->ca_cert, - params->ca_cert_blob, params->ca_cert_blob_len, - params->ca_path)) { - wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA " - "certificates"); - tlsv1_cred_free(cred); - return -1; - } - - if (tlsv1_set_cert(cred, params->client_cert, - params->client_cert_blob, - params->client_cert_blob_len)) { - wpa_printf(MSG_INFO, "TLS: Failed to configure client " - "certificate"); - tlsv1_cred_free(cred); - return -1; - } - - if (tlsv1_set_private_key(cred, params->private_key, - params->private_key_passwd, - params->private_key_blob, - params->private_key_blob_len)) { - wpa_printf(MSG_INFO, "TLS: Failed to load private key"); - tlsv1_cred_free(cred); - return -1; - } - - if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob, - params->dh_blob_len)) { - wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters"); - tlsv1_cred_free(cred); - return -1; - } - - if (tlsv1_client_set_cred(conn->client, cred) < 0) { - tlsv1_cred_free(cred); - return -1; - } - - return 0; -#else /* CONFIG_TLS_INTERNAL_CLIENT */ - return -1; -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -} - - -int tls_global_set_params(void *tls_ctx, - const struct tls_connection_params *params) -{ -#ifdef CONFIG_TLS_INTERNAL_SERVER - struct tls_global *global = tls_ctx; - struct tlsv1_credentials *cred; - - /* Currently, global parameters are only set when running in server - * mode. */ - global->server = 1; - tlsv1_cred_free(global->server_cred); - global->server_cred = cred = tlsv1_cred_alloc(); - if (cred == NULL) - return -1; - - if (tlsv1_set_ca_cert(cred, params->ca_cert, params->ca_cert_blob, - params->ca_cert_blob_len, params->ca_path)) { - wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA " - "certificates"); - return -1; - } - - if (tlsv1_set_cert(cred, params->client_cert, params->client_cert_blob, - params->client_cert_blob_len)) { - wpa_printf(MSG_INFO, "TLS: Failed to configure server " - "certificate"); - return -1; - } - - if (tlsv1_set_private_key(cred, params->private_key, - params->private_key_passwd, - params->private_key_blob, - params->private_key_blob_len)) { - wpa_printf(MSG_INFO, "TLS: Failed to load private key"); - return -1; - } - - if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob, - params->dh_blob_len)) { - wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters"); - return -1; - } - - return 0; -#else /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -#endif /* CONFIG_TLS_INTERNAL_SERVER */ -} - - -int tls_global_set_verify(void *tls_ctx, int check_crl) -{ - struct tls_global *global = tls_ctx; - global->check_crl = check_crl; - return 0; -} - - -int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, - int verify_peer) -{ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) - return tlsv1_server_set_verify(conn->server, verify_peer); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} - - -int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, - int tls_ia) -{ - return -1; -} - - -int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn, - struct tls_keys *keys) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) - return tlsv1_client_get_keys(conn->client, keys); -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) - return tlsv1_server_get_keys(conn->server, keys); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} - - -int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, - const char *label, int server_random_first, - u8 *out, size_t out_len) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) { - return tlsv1_client_prf(conn->client, label, - server_random_first, - out, out_len); - } -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) { - return tlsv1_server_prf(conn->server, label, - server_random_first, - out, out_len); - } -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} - - -u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client == NULL) - return NULL; - - if (appl_data) - *appl_data = NULL; - - wpa_printf(MSG_DEBUG, "TLS: %s(in_data=%p in_len=%lu)", - __func__, in_data, (unsigned long) in_len); - return tlsv1_client_handshake(conn->client, in_data, in_len, out_len, - appl_data, appl_data_len); -#else /* CONFIG_TLS_INTERNAL_CLIENT */ - return NULL; -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -} - - -u8 * tls_connection_server_handshake(void *tls_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len) -{ -#ifdef CONFIG_TLS_INTERNAL_SERVER - u8 *out; - if (conn->server == NULL) - return NULL; - - wpa_printf(MSG_DEBUG, "TLS: %s(in_data=%p in_len=%lu)", - __func__, in_data, (unsigned long) in_len); - out = tlsv1_server_handshake(conn->server, in_data, in_len, out_len); - if (out == NULL && tlsv1_server_established(conn->server)) { - out = os_malloc(1); - *out_len = 0; - } - return out; -#else /* CONFIG_TLS_INTERNAL_SERVER */ - return NULL; -#endif /* CONFIG_TLS_INTERNAL_SERVER */ -} - - -int tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) { - return tlsv1_client_encrypt(conn->client, in_data, in_len, - out_data, out_len); - } -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) { - return tlsv1_server_encrypt(conn->server, in_data, in_len, - out_data, out_len); - } -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} - - -int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) { - return tlsv1_client_decrypt(conn->client, in_data, in_len, - out_data, out_len); - } -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) { - return tlsv1_server_decrypt(conn->server, in_data, in_len, - out_data, out_len); - } -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} - - -int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) - return tlsv1_client_resumed(conn->client); -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) - return tlsv1_server_resumed(conn->server); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} - - -int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, - u8 *ciphers) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) - return tlsv1_client_set_cipher_list(conn->client, ciphers); -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) - return tlsv1_server_set_cipher_list(conn->server, ciphers); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} - - -int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, - char *buf, size_t buflen) -{ - if (conn == NULL) - return -1; -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) - return tlsv1_client_get_cipher(conn->client, buf, buflen); -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) - return tlsv1_server_get_cipher(conn->server, buf, buflen); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} - - -int tls_connection_enable_workaround(void *tls_ctx, - struct tls_connection *conn) -{ - return -1; -} - - -int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, - int ext_type, const u8 *data, - size_t data_len) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) { - return tlsv1_client_hello_ext(conn->client, ext_type, - data, data_len); - } -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ - return -1; -} - - -int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_get_write_alerts(void *tls_ctx, - struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_get_keyblock_size(void *tls_ctx, - struct tls_connection *conn) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) - return tlsv1_client_get_keyblock_size(conn->client); -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) - return tlsv1_server_get_keyblock_size(conn->server); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} - - -unsigned int tls_capabilities(void *tls_ctx) -{ - return 0; -} - - -int tls_connection_ia_send_phase_finished(void *tls_ctx, - struct tls_connection *conn, - int final, - u8 *out_data, size_t out_len) -{ - return -1; -} - - -int tls_connection_ia_final_phase_finished(void *tls_ctx, - struct tls_connection *conn) -{ - return -1; -} - - -int tls_connection_ia_permute_inner_secret(void *tls_ctx, - struct tls_connection *conn, - const u8 *key, size_t key_len) -{ - return -1; -} - - -int tls_connection_set_session_ticket_cb(void *tls_ctx, - struct tls_connection *conn, - tls_session_ticket_cb cb, - void *ctx) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) { - tlsv1_client_set_session_ticket_cb(conn->client, cb, ctx); - return 0; - } -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) { - tlsv1_server_set_session_ticket_cb(conn->server, cb, ctx); - return 0; - } -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} diff --git a/contrib/hostapd/src/crypto/tls_none.c b/contrib/hostapd/src/crypto/tls_none.c deleted file mode 100644 index f731628b0e..0000000000 --- a/contrib/hostapd/src/crypto/tls_none.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * WPA Supplicant / SSL/TLS interface functions for no TLS case - * Copyright (c) 2004, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "tls.h" - -void * tls_init(const struct tls_config *conf) -{ - return (void *) 1; -} - -void tls_deinit(void *ssl_ctx) -{ -} - - -#ifdef EAP_TLS_NONE - -int tls_get_errors(void *tls_ctx) -{ - return 0; -} - - -struct tls_connection * tls_connection_init(void *tls_ctx) -{ - return NULL; -} - - -void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) -{ -} - - -int tls_connection_established(void *tls_ctx, struct tls_connection *conn) -{ - return -1; -} - - -int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) -{ - return -1; -} - - -int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, - const struct tls_connection_params *params) -{ - return -1; -} - - -int tls_global_set_params(void *tls_ctx, - const struct tls_connection_params *params) -{ - return -1; -} - - -int tls_global_set_verify(void *tls_ctx, int check_crl) -{ - return -1; -} - - -int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, - int verify_peer) -{ - return -1; -} - - -int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, - int tls_ia) -{ - return -1; -} - - -int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn, - struct tls_keys *keys) -{ - return -1; -} - - -int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, - const char *label, int server_random_first, - u8 *out, size_t out_len) -{ - return -1; -} - - -u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len) -{ - return NULL; -} - - -u8 * tls_connection_server_handshake(void *tls_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len) -{ - return NULL; -} - - -int tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - return -1; -} - - -int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - return -1; -} - - -int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, - u8 *ciphers) -{ - return -1; -} - - -int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, - char *buf, size_t buflen) -{ - return -1; -} - - -int tls_connection_enable_workaround(void *tls_ctx, - struct tls_connection *conn) -{ - return -1; -} - - -int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, - int ext_type, const u8 *data, - size_t data_len) -{ - return -1; -} - - -int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_get_write_alerts(void *tls_ctx, - struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_get_keyblock_size(void *tls_ctx, - struct tls_connection *conn) -{ - return -1; -} - - -unsigned int tls_capabilities(void *tls_ctx) -{ - return 0; -} - - -int tls_connection_ia_send_phase_finished(void *tls_ctx, - struct tls_connection *conn, - int final, - u8 *out_data, size_t out_len) -{ - return -1; -} - - -int tls_connection_ia_final_phase_finished(void *tls_ctx, - struct tls_connection *conn) -{ - return -1; -} - - -int tls_connection_ia_permute_inner_secret(void *tls_ctx, - struct tls_connection *conn, - const u8 *key, size_t key_len) -{ - return -1; -} - -#endif /* EAP_TLS_NONE */ diff --git a/contrib/hostapd/src/crypto/tls_openssl.c b/contrib/hostapd/src/crypto/tls_openssl.c deleted file mode 100644 index b5a1d64f53..0000000000 --- a/contrib/hostapd/src/crypto/tls_openssl.c +++ /dev/null @@ -1,2671 +0,0 @@ -/* - * WPA Supplicant / SSL/TLS interface functions for openssl - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#ifndef CONFIG_SMARTCARD -#ifndef OPENSSL_NO_ENGINE -#define OPENSSL_NO_ENGINE -#endif -#endif - -#include -#include -#include -#include -#ifndef OPENSSL_NO_ENGINE -#include -#endif /* OPENSSL_NO_ENGINE */ - -#include "common.h" -#include "tls.h" - -#if OPENSSL_VERSION_NUMBER >= 0x0090800fL -#define OPENSSL_d2i_TYPE const unsigned char ** -#else -#define OPENSSL_d2i_TYPE unsigned char ** -#endif - -#ifdef SSL_F_SSL_SET_SESSION_TICKET_EXT -#ifdef SSL_OP_NO_TICKET -/* - * Session ticket override patch was merged into OpenSSL 0.9.9 tree on - * 2008-11-15. This version uses a bit different API compared to the old patch. - */ -#define CONFIG_OPENSSL_TICKET_OVERRIDE -#endif -#endif - -static int tls_openssl_ref_count = 0; - -struct tls_connection { - SSL *ssl; - BIO *ssl_in, *ssl_out; -#ifndef OPENSSL_NO_ENGINE - ENGINE *engine; /* functional reference to the engine */ - EVP_PKEY *private_key; /* the private key if using engine */ -#endif /* OPENSSL_NO_ENGINE */ - char *subject_match, *altsubject_match; - int read_alerts, write_alerts, failed; - - tls_session_ticket_cb session_ticket_cb; - void *session_ticket_cb_ctx; - - /* SessionTicket received from OpenSSL hello_extension_cb (server) */ - u8 *session_ticket; - size_t session_ticket_len; -}; - - -#ifdef CONFIG_NO_STDOUT_DEBUG - -static void _tls_show_errors(void) -{ - unsigned long err; - - while ((err = ERR_get_error())) { - /* Just ignore the errors, since stdout is disabled */ - } -} -#define tls_show_errors(l, f, t) _tls_show_errors() - -#else /* CONFIG_NO_STDOUT_DEBUG */ - -static void tls_show_errors(int level, const char *func, const char *txt) -{ - unsigned long err; - - wpa_printf(level, "OpenSSL: %s - %s %s", - func, txt, ERR_error_string(ERR_get_error(), NULL)); - - while ((err = ERR_get_error())) { - wpa_printf(MSG_INFO, "OpenSSL: pending error: %s", - ERR_error_string(err, NULL)); - } -} - -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - -#ifdef CONFIG_NATIVE_WINDOWS - -/* Windows CryptoAPI and access to certificate stores */ -#include - -#ifdef __MINGW32_VERSION -/* - * MinGW does not yet include all the needed definitions for CryptoAPI, so - * define here whatever extra is needed. - */ -#define CERT_SYSTEM_STORE_CURRENT_USER (1 << 16) -#define CERT_STORE_READONLY_FLAG 0x00008000 -#define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000 - -#endif /* __MINGW32_VERSION */ - - -struct cryptoapi_rsa_data { - const CERT_CONTEXT *cert; - HCRYPTPROV crypt_prov; - DWORD key_spec; - BOOL free_crypt_prov; -}; - - -static void cryptoapi_error(const char *msg) -{ - wpa_printf(MSG_INFO, "CryptoAPI: %s; err=%u", - msg, (unsigned int) GetLastError()); -} - - -static int cryptoapi_rsa_pub_enc(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding) -{ - wpa_printf(MSG_DEBUG, "%s - not implemented", __func__); - return 0; -} - - -static int cryptoapi_rsa_pub_dec(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding) -{ - wpa_printf(MSG_DEBUG, "%s - not implemented", __func__); - return 0; -} - - -static int cryptoapi_rsa_priv_enc(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding) -{ - struct cryptoapi_rsa_data *priv = - (struct cryptoapi_rsa_data *) rsa->meth->app_data; - HCRYPTHASH hash; - DWORD hash_size, len, i; - unsigned char *buf = NULL; - int ret = 0; - - if (priv == NULL) { - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, - ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - if (padding != RSA_PKCS1_PADDING) { - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, - RSA_R_UNKNOWN_PADDING_TYPE); - return 0; - } - - if (flen != 16 /* MD5 */ + 20 /* SHA-1 */) { - wpa_printf(MSG_INFO, "%s - only MD5-SHA1 hash supported", - __func__); - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, - RSA_R_INVALID_MESSAGE_LENGTH); - return 0; - } - - if (!CryptCreateHash(priv->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash)) - { - cryptoapi_error("CryptCreateHash failed"); - return 0; - } - - len = sizeof(hash_size); - if (!CryptGetHashParam(hash, HP_HASHSIZE, (BYTE *) &hash_size, &len, - 0)) { - cryptoapi_error("CryptGetHashParam failed"); - goto err; - } - - if ((int) hash_size != flen) { - wpa_printf(MSG_INFO, "CryptoAPI: Invalid hash size (%u != %d)", - (unsigned) hash_size, flen); - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, - RSA_R_INVALID_MESSAGE_LENGTH); - goto err; - } - if (!CryptSetHashParam(hash, HP_HASHVAL, (BYTE * ) from, 0)) { - cryptoapi_error("CryptSetHashParam failed"); - goto err; - } - - len = RSA_size(rsa); - buf = os_malloc(len); - if (buf == NULL) { - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!CryptSignHash(hash, priv->key_spec, NULL, 0, buf, &len)) { - cryptoapi_error("CryptSignHash failed"); - goto err; - } - - for (i = 0; i < len; i++) - to[i] = buf[len - i - 1]; - ret = len; - -err: - os_free(buf); - CryptDestroyHash(hash); - - return ret; -} - - -static int cryptoapi_rsa_priv_dec(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding) -{ - wpa_printf(MSG_DEBUG, "%s - not implemented", __func__); - return 0; -} - - -static void cryptoapi_free_data(struct cryptoapi_rsa_data *priv) -{ - if (priv == NULL) - return; - if (priv->crypt_prov && priv->free_crypt_prov) - CryptReleaseContext(priv->crypt_prov, 0); - if (priv->cert) - CertFreeCertificateContext(priv->cert); - os_free(priv); -} - - -static int cryptoapi_finish(RSA *rsa) -{ - cryptoapi_free_data((struct cryptoapi_rsa_data *) rsa->meth->app_data); - os_free((void *) rsa->meth); - rsa->meth = NULL; - return 1; -} - - -static const CERT_CONTEXT * cryptoapi_find_cert(const char *name, DWORD store) -{ - HCERTSTORE cs; - const CERT_CONTEXT *ret = NULL; - - cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0, - store | CERT_STORE_OPEN_EXISTING_FLAG | - CERT_STORE_READONLY_FLAG, L"MY"); - if (cs == NULL) { - cryptoapi_error("Failed to open 'My system store'"); - return NULL; - } - - if (strncmp(name, "cert://", 7) == 0) { - unsigned short wbuf[255]; - MultiByteToWideChar(CP_ACP, 0, name + 7, -1, wbuf, 255); - ret = CertFindCertificateInStore(cs, X509_ASN_ENCODING | - PKCS_7_ASN_ENCODING, - 0, CERT_FIND_SUBJECT_STR, - wbuf, NULL); - } else if (strncmp(name, "hash://", 7) == 0) { - CRYPT_HASH_BLOB blob; - int len; - const char *hash = name + 7; - unsigned char *buf; - - len = os_strlen(hash) / 2; - buf = os_malloc(len); - if (buf && hexstr2bin(hash, buf, len) == 0) { - blob.cbData = len; - blob.pbData = buf; - ret = CertFindCertificateInStore(cs, - X509_ASN_ENCODING | - PKCS_7_ASN_ENCODING, - 0, CERT_FIND_HASH, - &blob, NULL); - } - os_free(buf); - } - - CertCloseStore(cs, 0); - - return ret; -} - - -static int tls_cryptoapi_cert(SSL *ssl, const char *name) -{ - X509 *cert = NULL; - RSA *rsa = NULL, *pub_rsa; - struct cryptoapi_rsa_data *priv; - RSA_METHOD *rsa_meth; - - if (name == NULL || - (strncmp(name, "cert://", 7) != 0 && - strncmp(name, "hash://", 7) != 0)) - return -1; - - priv = os_zalloc(sizeof(*priv)); - rsa_meth = os_zalloc(sizeof(*rsa_meth)); - if (priv == NULL || rsa_meth == NULL) { - wpa_printf(MSG_WARNING, "CryptoAPI: Failed to allocate memory " - "for CryptoAPI RSA method"); - os_free(priv); - os_free(rsa_meth); - return -1; - } - - priv->cert = cryptoapi_find_cert(name, CERT_SYSTEM_STORE_CURRENT_USER); - if (priv->cert == NULL) { - priv->cert = cryptoapi_find_cert( - name, CERT_SYSTEM_STORE_LOCAL_MACHINE); - } - if (priv->cert == NULL) { - wpa_printf(MSG_INFO, "CryptoAPI: Could not find certificate " - "'%s'", name); - goto err; - } - - cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &priv->cert->pbCertEncoded, - priv->cert->cbCertEncoded); - if (cert == NULL) { - wpa_printf(MSG_INFO, "CryptoAPI: Could not process X509 DER " - "encoding"); - goto err; - } - - if (!CryptAcquireCertificatePrivateKey(priv->cert, - CRYPT_ACQUIRE_COMPARE_KEY_FLAG, - NULL, &priv->crypt_prov, - &priv->key_spec, - &priv->free_crypt_prov)) { - cryptoapi_error("Failed to acquire a private key for the " - "certificate"); - goto err; - } - - rsa_meth->name = "Microsoft CryptoAPI RSA Method"; - rsa_meth->rsa_pub_enc = cryptoapi_rsa_pub_enc; - rsa_meth->rsa_pub_dec = cryptoapi_rsa_pub_dec; - rsa_meth->rsa_priv_enc = cryptoapi_rsa_priv_enc; - rsa_meth->rsa_priv_dec = cryptoapi_rsa_priv_dec; - rsa_meth->finish = cryptoapi_finish; - rsa_meth->flags = RSA_METHOD_FLAG_NO_CHECK; - rsa_meth->app_data = (char *) priv; - - rsa = RSA_new(); - if (rsa == NULL) { - SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, - ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!SSL_use_certificate(ssl, cert)) { - RSA_free(rsa); - rsa = NULL; - goto err; - } - pub_rsa = cert->cert_info->key->pkey->pkey.rsa; - X509_free(cert); - cert = NULL; - - rsa->n = BN_dup(pub_rsa->n); - rsa->e = BN_dup(pub_rsa->e); - if (!RSA_set_method(rsa, rsa_meth)) - goto err; - - if (!SSL_use_RSAPrivateKey(ssl, rsa)) - goto err; - RSA_free(rsa); - - return 0; - -err: - if (cert) - X509_free(cert); - if (rsa) - RSA_free(rsa); - else { - os_free(rsa_meth); - cryptoapi_free_data(priv); - } - return -1; -} - - -static int tls_cryptoapi_ca_cert(SSL_CTX *ssl_ctx, SSL *ssl, const char *name) -{ - HCERTSTORE cs; - PCCERT_CONTEXT ctx = NULL; - X509 *cert; - char buf[128]; - const char *store; -#ifdef UNICODE - WCHAR *wstore; -#endif /* UNICODE */ - - if (name == NULL || strncmp(name, "cert_store://", 13) != 0) - return -1; - - store = name + 13; -#ifdef UNICODE - wstore = os_malloc((os_strlen(store) + 1) * sizeof(WCHAR)); - if (wstore == NULL) - return -1; - wsprintf(wstore, L"%S", store); - cs = CertOpenSystemStore(0, wstore); - os_free(wstore); -#else /* UNICODE */ - cs = CertOpenSystemStore(0, store); -#endif /* UNICODE */ - if (cs == NULL) { - wpa_printf(MSG_DEBUG, "%s: failed to open system cert store " - "'%s': error=%d", __func__, store, - (int) GetLastError()); - return -1; - } - - while ((ctx = CertEnumCertificatesInStore(cs, ctx))) { - cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &ctx->pbCertEncoded, - ctx->cbCertEncoded); - if (cert == NULL) { - wpa_printf(MSG_INFO, "CryptoAPI: Could not process " - "X509 DER encoding for CA cert"); - continue; - } - - X509_NAME_oneline(X509_get_subject_name(cert), buf, - sizeof(buf)); - wpa_printf(MSG_DEBUG, "OpenSSL: Loaded CA certificate for " - "system certificate store: subject='%s'", buf); - - if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) { - tls_show_errors(MSG_WARNING, __func__, - "Failed to add ca_cert to OpenSSL " - "certificate store"); - } - - X509_free(cert); - } - - if (!CertCloseStore(cs, 0)) { - wpa_printf(MSG_DEBUG, "%s: failed to close system cert store " - "'%s': error=%d", __func__, name + 13, - (int) GetLastError()); - } - - return 0; -} - - -#else /* CONFIG_NATIVE_WINDOWS */ - -static int tls_cryptoapi_cert(SSL *ssl, const char *name) -{ - return -1; -} - -#endif /* CONFIG_NATIVE_WINDOWS */ - - -static void ssl_info_cb(const SSL *ssl, int where, int ret) -{ - const char *str; - int w; - - wpa_printf(MSG_DEBUG, "SSL: (where=0x%x ret=0x%x)", where, ret); - w = where & ~SSL_ST_MASK; - if (w & SSL_ST_CONNECT) - str = "SSL_connect"; - else if (w & SSL_ST_ACCEPT) - str = "SSL_accept"; - else - str = "undefined"; - - if (where & SSL_CB_LOOP) { - wpa_printf(MSG_DEBUG, "SSL: %s:%s", - str, SSL_state_string_long(ssl)); - } else if (where & SSL_CB_ALERT) { - wpa_printf(MSG_INFO, "SSL: SSL3 alert: %s:%s:%s", - where & SSL_CB_READ ? - "read (remote end reported an error)" : - "write (local SSL3 detected an error)", - SSL_alert_type_string_long(ret), - SSL_alert_desc_string_long(ret)); - if ((ret >> 8) == SSL3_AL_FATAL) { - struct tls_connection *conn = - SSL_get_app_data((SSL *) ssl); - if (where & SSL_CB_READ) - conn->read_alerts++; - else - conn->write_alerts++; - } - } else if (where & SSL_CB_EXIT && ret <= 0) { - wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s", - str, ret == 0 ? "failed" : "error", - SSL_state_string_long(ssl)); - } -} - - -#ifndef OPENSSL_NO_ENGINE -/** - * tls_engine_load_dynamic_generic - load any openssl engine - * @pre: an array of commands and values that load an engine initialized - * in the engine specific function - * @post: an array of commands and values that initialize an already loaded - * engine (or %NULL if not required) - * @id: the engine id of the engine to load (only required if post is not %NULL - * - * This function is a generic function that loads any openssl engine. - * - * Returns: 0 on success, -1 on failure - */ -static int tls_engine_load_dynamic_generic(const char *pre[], - const char *post[], const char *id) -{ - ENGINE *engine; - const char *dynamic_id = "dynamic"; - - engine = ENGINE_by_id(id); - if (engine) { - ENGINE_free(engine); - wpa_printf(MSG_DEBUG, "ENGINE: engine '%s' is already " - "available", id); - return 0; - } - ERR_clear_error(); - - engine = ENGINE_by_id(dynamic_id); - if (engine == NULL) { - wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]", - dynamic_id, - ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - - /* Perform the pre commands. This will load the engine. */ - while (pre && pre[0]) { - wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", pre[0], pre[1]); - if (ENGINE_ctrl_cmd_string(engine, pre[0], pre[1], 0) == 0) { - wpa_printf(MSG_INFO, "ENGINE: ctrl cmd_string failed: " - "%s %s [%s]", pre[0], pre[1], - ERR_error_string(ERR_get_error(), NULL)); - ENGINE_free(engine); - return -1; - } - pre += 2; - } - - /* - * Free the reference to the "dynamic" engine. The loaded engine can - * now be looked up using ENGINE_by_id(). - */ - ENGINE_free(engine); - - engine = ENGINE_by_id(id); - if (engine == NULL) { - wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]", - id, ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - - while (post && post[0]) { - wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", post[0], post[1]); - if (ENGINE_ctrl_cmd_string(engine, post[0], post[1], 0) == 0) { - wpa_printf(MSG_DEBUG, "ENGINE: ctrl cmd_string failed:" - " %s %s [%s]", post[0], post[1], - ERR_error_string(ERR_get_error(), NULL)); - ENGINE_remove(engine); - ENGINE_free(engine); - return -1; - } - post += 2; - } - ENGINE_free(engine); - - return 0; -} - - -/** - * tls_engine_load_dynamic_pkcs11 - load the pkcs11 engine provided by opensc - * @pkcs11_so_path: pksc11_so_path from the configuration - * @pcks11_module_path: pkcs11_module_path from the configuration - */ -static int tls_engine_load_dynamic_pkcs11(const char *pkcs11_so_path, - const char *pkcs11_module_path) -{ - char *engine_id = "pkcs11"; - const char *pre_cmd[] = { - "SO_PATH", NULL /* pkcs11_so_path */, - "ID", NULL /* engine_id */, - "LIST_ADD", "1", - /* "NO_VCHECK", "1", */ - "LOAD", NULL, - NULL, NULL - }; - const char *post_cmd[] = { - "MODULE_PATH", NULL /* pkcs11_module_path */, - NULL, NULL - }; - - if (!pkcs11_so_path || !pkcs11_module_path) - return 0; - - pre_cmd[1] = pkcs11_so_path; - pre_cmd[3] = engine_id; - post_cmd[1] = pkcs11_module_path; - - wpa_printf(MSG_DEBUG, "ENGINE: Loading pkcs11 Engine from %s", - pkcs11_so_path); - - return tls_engine_load_dynamic_generic(pre_cmd, post_cmd, engine_id); -} - - -/** - * tls_engine_load_dynamic_opensc - load the opensc engine provided by opensc - * @opensc_so_path: opensc_so_path from the configuration - */ -static int tls_engine_load_dynamic_opensc(const char *opensc_so_path) -{ - char *engine_id = "opensc"; - const char *pre_cmd[] = { - "SO_PATH", NULL /* opensc_so_path */, - "ID", NULL /* engine_id */, - "LIST_ADD", "1", - "LOAD", NULL, - NULL, NULL - }; - - if (!opensc_so_path) - return 0; - - pre_cmd[1] = opensc_so_path; - pre_cmd[3] = engine_id; - - wpa_printf(MSG_DEBUG, "ENGINE: Loading OpenSC Engine from %s", - opensc_so_path); - - return tls_engine_load_dynamic_generic(pre_cmd, NULL, engine_id); -} -#endif /* OPENSSL_NO_ENGINE */ - - -void * tls_init(const struct tls_config *conf) -{ - SSL_CTX *ssl; - - if (tls_openssl_ref_count == 0) { - SSL_load_error_strings(); - SSL_library_init(); -#ifndef OPENSSL_NO_SHA256 - EVP_add_digest(EVP_sha256()); -#endif /* OPENSSL_NO_SHA256 */ - /* TODO: if /dev/urandom is available, PRNG is seeded - * automatically. If this is not the case, random data should - * be added here. */ - -#ifdef PKCS12_FUNCS -#ifndef OPENSSL_NO_RC2 - /* - * 40-bit RC2 is commonly used in PKCS#12 files, so enable it. - * This is enabled by PKCS12_PBE_add() in OpenSSL 0.9.8 - * versions, but it looks like OpenSSL 1.0.0 does not do that - * anymore. - */ - EVP_add_cipher(EVP_rc2_40_cbc()); -#endif /* OPENSSL_NO_RC2 */ - PKCS12_PBE_add(); -#endif /* PKCS12_FUNCS */ - } - tls_openssl_ref_count++; - - ssl = SSL_CTX_new(TLSv1_method()); - if (ssl == NULL) - return NULL; - - SSL_CTX_set_info_callback(ssl, ssl_info_cb); - -#ifndef OPENSSL_NO_ENGINE - if (conf && - (conf->opensc_engine_path || conf->pkcs11_engine_path || - conf->pkcs11_module_path)) { - wpa_printf(MSG_DEBUG, "ENGINE: Loading dynamic engine"); - ERR_load_ENGINE_strings(); - ENGINE_load_dynamic(); - - if (tls_engine_load_dynamic_opensc(conf->opensc_engine_path) || - tls_engine_load_dynamic_pkcs11(conf->pkcs11_engine_path, - conf->pkcs11_module_path)) { - tls_deinit(ssl); - return NULL; - } - } -#endif /* OPENSSL_NO_ENGINE */ - - return ssl; -} - - -void tls_deinit(void *ssl_ctx) -{ - SSL_CTX *ssl = ssl_ctx; - SSL_CTX_free(ssl); - - tls_openssl_ref_count--; - if (tls_openssl_ref_count == 0) { -#ifndef OPENSSL_NO_ENGINE - ENGINE_cleanup(); -#endif /* OPENSSL_NO_ENGINE */ - CRYPTO_cleanup_all_ex_data(); - ERR_remove_state(0); - ERR_free_strings(); - EVP_cleanup(); - } -} - - -static int tls_engine_init(struct tls_connection *conn, const char *engine_id, - const char *pin, const char *key_id, - const char *cert_id, const char *ca_cert_id) -{ -#ifndef OPENSSL_NO_ENGINE - int ret = -1; - if (engine_id == NULL) { - wpa_printf(MSG_ERROR, "ENGINE: Engine ID not set"); - return -1; - } - if (pin == NULL) { - wpa_printf(MSG_ERROR, "ENGINE: Smartcard PIN not set"); - return -1; - } - if (key_id == NULL) { - wpa_printf(MSG_ERROR, "ENGINE: Key Id not set"); - return -1; - } - - ERR_clear_error(); - conn->engine = ENGINE_by_id(engine_id); - if (!conn->engine) { - wpa_printf(MSG_ERROR, "ENGINE: engine %s not available [%s]", - engine_id, ERR_error_string(ERR_get_error(), NULL)); - goto err; - } - if (ENGINE_init(conn->engine) != 1) { - wpa_printf(MSG_ERROR, "ENGINE: engine init failed " - "(engine: %s) [%s]", engine_id, - ERR_error_string(ERR_get_error(), NULL)); - goto err; - } - wpa_printf(MSG_DEBUG, "ENGINE: engine initialized"); - - if (ENGINE_ctrl_cmd_string(conn->engine, "PIN", pin, 0) == 0) { - wpa_printf(MSG_ERROR, "ENGINE: cannot set pin [%s]", - ERR_error_string(ERR_get_error(), NULL)); - goto err; - } - /* load private key first in-case PIN is required for cert */ - conn->private_key = ENGINE_load_private_key(conn->engine, - key_id, NULL, NULL); - if (!conn->private_key) { - wpa_printf(MSG_ERROR, "ENGINE: cannot load private key with id" - " '%s' [%s]", key_id, - ERR_error_string(ERR_get_error(), NULL)); - ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; - goto err; - } - - /* handle a certificate and/or CA certificate */ - if (cert_id || ca_cert_id) { - const char *cmd_name = "LOAD_CERT_CTRL"; - - /* test if the engine supports a LOAD_CERT_CTRL */ - if (!ENGINE_ctrl(conn->engine, ENGINE_CTRL_GET_CMD_FROM_NAME, - 0, (void *)cmd_name, NULL)) { - wpa_printf(MSG_ERROR, "ENGINE: engine does not support" - " loading certificates"); - ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; - goto err; - } - } - - return 0; - -err: - if (conn->engine) { - ENGINE_free(conn->engine); - conn->engine = NULL; - } - - if (conn->private_key) { - EVP_PKEY_free(conn->private_key); - conn->private_key = NULL; - } - - return ret; -#else /* OPENSSL_NO_ENGINE */ - return 0; -#endif /* OPENSSL_NO_ENGINE */ -} - - -static void tls_engine_deinit(struct tls_connection *conn) -{ -#ifndef OPENSSL_NO_ENGINE - wpa_printf(MSG_DEBUG, "ENGINE: engine deinit"); - if (conn->private_key) { - EVP_PKEY_free(conn->private_key); - conn->private_key = NULL; - } - if (conn->engine) { - ENGINE_finish(conn->engine); - conn->engine = NULL; - } -#endif /* OPENSSL_NO_ENGINE */ -} - - -int tls_get_errors(void *ssl_ctx) -{ - int count = 0; - unsigned long err; - - while ((err = ERR_get_error())) { - wpa_printf(MSG_INFO, "TLS - SSL error: %s", - ERR_error_string(err, NULL)); - count++; - } - - return count; -} - -struct tls_connection * tls_connection_init(void *ssl_ctx) -{ - SSL_CTX *ssl = ssl_ctx; - struct tls_connection *conn; - long options; - - conn = os_zalloc(sizeof(*conn)); - if (conn == NULL) - return NULL; - conn->ssl = SSL_new(ssl); - if (conn->ssl == NULL) { - tls_show_errors(MSG_INFO, __func__, - "Failed to initialize new SSL connection"); - os_free(conn); - return NULL; - } - - SSL_set_app_data(conn->ssl, conn); - options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | - SSL_OP_SINGLE_DH_USE; -#ifdef SSL_OP_NO_COMPRESSION - options |= SSL_OP_NO_COMPRESSION; -#endif /* SSL_OP_NO_COMPRESSION */ - SSL_set_options(conn->ssl, options); - - conn->ssl_in = BIO_new(BIO_s_mem()); - if (!conn->ssl_in) { - tls_show_errors(MSG_INFO, __func__, - "Failed to create a new BIO for ssl_in"); - SSL_free(conn->ssl); - os_free(conn); - return NULL; - } - - conn->ssl_out = BIO_new(BIO_s_mem()); - if (!conn->ssl_out) { - tls_show_errors(MSG_INFO, __func__, - "Failed to create a new BIO for ssl_out"); - SSL_free(conn->ssl); - BIO_free(conn->ssl_in); - os_free(conn); - return NULL; - } - - SSL_set_bio(conn->ssl, conn->ssl_in, conn->ssl_out); - - return conn; -} - - -void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return; - SSL_free(conn->ssl); - tls_engine_deinit(conn); - os_free(conn->subject_match); - os_free(conn->altsubject_match); - os_free(conn->session_ticket); - os_free(conn); -} - - -int tls_connection_established(void *ssl_ctx, struct tls_connection *conn) -{ - return conn ? SSL_is_init_finished(conn->ssl) : 0; -} - - -int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - - /* Shutdown previous TLS connection without notifying the peer - * because the connection was already terminated in practice - * and "close notify" shutdown alert would confuse AS. */ - SSL_set_quiet_shutdown(conn->ssl, 1); - SSL_shutdown(conn->ssl); - return 0; -} - - -static int tls_match_altsubject_component(X509 *cert, int type, - const char *value, size_t len) -{ - GENERAL_NAME *gen; - void *ext; - int i, found = 0; - - ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); - - for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) { - gen = sk_GENERAL_NAME_value(ext, i); - if (gen->type != type) - continue; - if (os_strlen((char *) gen->d.ia5->data) == len && - os_memcmp(value, gen->d.ia5->data, len) == 0) - found++; - } - - return found; -} - - -static int tls_match_altsubject(X509 *cert, const char *match) -{ - int type; - const char *pos, *end; - size_t len; - - pos = match; - do { - if (os_strncmp(pos, "EMAIL:", 6) == 0) { - type = GEN_EMAIL; - pos += 6; - } else if (os_strncmp(pos, "DNS:", 4) == 0) { - type = GEN_DNS; - pos += 4; - } else if (os_strncmp(pos, "URI:", 4) == 0) { - type = GEN_URI; - pos += 4; - } else { - wpa_printf(MSG_INFO, "TLS: Invalid altSubjectName " - "match '%s'", pos); - return 0; - } - end = os_strchr(pos, ';'); - while (end) { - if (os_strncmp(end + 1, "EMAIL:", 6) == 0 || - os_strncmp(end + 1, "DNS:", 4) == 0 || - os_strncmp(end + 1, "URI:", 4) == 0) - break; - end = os_strchr(end + 1, ';'); - } - if (end) - len = end - pos; - else - len = os_strlen(pos); - if (tls_match_altsubject_component(cert, type, pos, len) > 0) - return 1; - pos = end + 1; - } while (end); - - return 0; -} - - -static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) -{ - char buf[256]; - X509 *err_cert; - int err, depth; - SSL *ssl; - struct tls_connection *conn; - char *match, *altmatch; - - err_cert = X509_STORE_CTX_get_current_cert(x509_ctx); - err = X509_STORE_CTX_get_error(x509_ctx); - depth = X509_STORE_CTX_get_error_depth(x509_ctx); - ssl = X509_STORE_CTX_get_ex_data(x509_ctx, - SSL_get_ex_data_X509_STORE_CTX_idx()); - X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); - - conn = SSL_get_app_data(ssl); - match = conn ? conn->subject_match : NULL; - altmatch = conn ? conn->altsubject_match : NULL; - - if (!preverify_ok) { - wpa_printf(MSG_WARNING, "TLS: Certificate verification failed," - " error %d (%s) depth %d for '%s'", err, - X509_verify_cert_error_string(err), depth, buf); - } else { - wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - " - "preverify_ok=%d err=%d (%s) depth=%d buf='%s'", - preverify_ok, err, - X509_verify_cert_error_string(err), depth, buf); - if (depth == 0 && match && os_strstr(buf, match) == NULL) { - wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not " - "match with '%s'", buf, match); - preverify_ok = 0; - } else if (depth == 0 && altmatch && - !tls_match_altsubject(err_cert, altmatch)) { - wpa_printf(MSG_WARNING, "TLS: altSubjectName match " - "'%s' not found", altmatch); - preverify_ok = 0; - } - } - - return preverify_ok; -} - - -#ifndef OPENSSL_NO_STDIO -static int tls_load_ca_der(void *_ssl_ctx, const char *ca_cert) -{ - SSL_CTX *ssl_ctx = _ssl_ctx; - X509_LOOKUP *lookup; - int ret = 0; - - lookup = X509_STORE_add_lookup(ssl_ctx->cert_store, - X509_LOOKUP_file()); - if (lookup == NULL) { - tls_show_errors(MSG_WARNING, __func__, - "Failed add lookup for X509 store"); - return -1; - } - - if (!X509_LOOKUP_load_file(lookup, ca_cert, X509_FILETYPE_ASN1)) { - unsigned long err = ERR_peek_error(); - tls_show_errors(MSG_WARNING, __func__, - "Failed load CA in DER format"); - if (ERR_GET_LIB(err) == ERR_LIB_X509 && - ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) { - wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring " - "cert already in hash table error", - __func__); - } else - ret = -1; - } - - return ret; -} -#endif /* OPENSSL_NO_STDIO */ - - -static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn, - const char *ca_cert, const u8 *ca_cert_blob, - size_t ca_cert_blob_len, const char *ca_path) -{ - SSL_CTX *ssl_ctx = _ssl_ctx; - - /* - * Remove previously configured trusted CA certificates before adding - * new ones. - */ - X509_STORE_free(ssl_ctx->cert_store); - ssl_ctx->cert_store = X509_STORE_new(); - if (ssl_ctx->cert_store == NULL) { - wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new " - "certificate store", __func__); - return -1; - } - - if (ca_cert_blob) { - X509 *cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &ca_cert_blob, - ca_cert_blob_len); - if (cert == NULL) { - tls_show_errors(MSG_WARNING, __func__, - "Failed to parse ca_cert_blob"); - return -1; - } - - if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) { - unsigned long err = ERR_peek_error(); - tls_show_errors(MSG_WARNING, __func__, - "Failed to add ca_cert_blob to " - "certificate store"); - if (ERR_GET_LIB(err) == ERR_LIB_X509 && - ERR_GET_REASON(err) == - X509_R_CERT_ALREADY_IN_HASH_TABLE) { - wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring " - "cert already in hash table error", - __func__); - } else { - X509_free(cert); - return -1; - } - } - X509_free(cert); - wpa_printf(MSG_DEBUG, "OpenSSL: %s - added ca_cert_blob " - "to certificate store", __func__); - SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); - return 0; - } - -#ifdef CONFIG_NATIVE_WINDOWS - if (ca_cert && tls_cryptoapi_ca_cert(ssl_ctx, conn->ssl, ca_cert) == - 0) { - wpa_printf(MSG_DEBUG, "OpenSSL: Added CA certificates from " - "system certificate store"); - SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); - return 0; - } -#endif /* CONFIG_NATIVE_WINDOWS */ - - if (ca_cert || ca_path) { -#ifndef OPENSSL_NO_STDIO - if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, ca_path) != - 1) { - tls_show_errors(MSG_WARNING, __func__, - "Failed to load root certificates"); - if (ca_cert && - tls_load_ca_der(ssl_ctx, ca_cert) == 0) { - wpa_printf(MSG_DEBUG, "OpenSSL: %s - loaded " - "DER format CA certificate", - __func__); - } else - return -1; - } else { - wpa_printf(MSG_DEBUG, "TLS: Trusted root " - "certificate(s) loaded"); - tls_get_errors(ssl_ctx); - } - SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); -#else /* OPENSSL_NO_STDIO */ - wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", - __func__); - return -1; -#endif /* OPENSSL_NO_STDIO */ - } else { - /* No ca_cert configured - do not try to verify server - * certificate */ - SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL); - } - - return 0; -} - - -static int tls_global_ca_cert(SSL_CTX *ssl_ctx, const char *ca_cert) -{ - if (ca_cert) { - if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, NULL) != 1) - { - tls_show_errors(MSG_WARNING, __func__, - "Failed to load root certificates"); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLS: Trusted root " - "certificate(s) loaded"); - -#ifndef OPENSSL_NO_STDIO - /* Add the same CAs to the client certificate requests */ - SSL_CTX_set_client_CA_list(ssl_ctx, - SSL_load_client_CA_file(ca_cert)); -#endif /* OPENSSL_NO_STDIO */ - } - - return 0; -} - - -int tls_global_set_verify(void *ssl_ctx, int check_crl) -{ - int flags; - - if (check_crl) { - X509_STORE *cs = SSL_CTX_get_cert_store(ssl_ctx); - if (cs == NULL) { - tls_show_errors(MSG_INFO, __func__, "Failed to get " - "certificate store when enabling " - "check_crl"); - return -1; - } - flags = X509_V_FLAG_CRL_CHECK; - if (check_crl == 2) - flags |= X509_V_FLAG_CRL_CHECK_ALL; - X509_STORE_set_flags(cs, flags); - } - return 0; -} - - -static int tls_connection_set_subject_match(struct tls_connection *conn, - const char *subject_match, - const char *altsubject_match) -{ - os_free(conn->subject_match); - conn->subject_match = NULL; - if (subject_match) { - conn->subject_match = os_strdup(subject_match); - if (conn->subject_match == NULL) - return -1; - } - - os_free(conn->altsubject_match); - conn->altsubject_match = NULL; - if (altsubject_match) { - conn->altsubject_match = os_strdup(altsubject_match); - if (conn->altsubject_match == NULL) - return -1; - } - - return 0; -} - - -int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, - int verify_peer) -{ - static int counter = 0; - - if (conn == NULL) - return -1; - - if (verify_peer) { - SSL_set_verify(conn->ssl, SSL_VERIFY_PEER | - SSL_VERIFY_FAIL_IF_NO_PEER_CERT | - SSL_VERIFY_CLIENT_ONCE, tls_verify_cb); - } else { - SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL); - } - - SSL_set_accept_state(conn->ssl); - - /* - * Set session id context in order to avoid fatal errors when client - * tries to resume a session. However, set the context to a unique - * value in order to effectively disable session resumption for now - * since not all areas of the server code are ready for it (e.g., - * EAP-TTLS needs special handling for Phase 2 after abbreviated TLS - * handshake). - */ - counter++; - SSL_set_session_id_context(conn->ssl, - (const unsigned char *) &counter, - sizeof(counter)); - - return 0; -} - - -static int tls_connection_client_cert(struct tls_connection *conn, - const char *client_cert, - const u8 *client_cert_blob, - size_t client_cert_blob_len) -{ - if (client_cert == NULL && client_cert_blob == NULL) - return 0; - - if (client_cert_blob && - SSL_use_certificate_ASN1(conn->ssl, (u8 *) client_cert_blob, - client_cert_blob_len) == 1) { - wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_ASN1 --> " - "OK"); - return 0; - } else if (client_cert_blob) { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_certificate_ASN1 failed"); - } - - if (client_cert == NULL) - return -1; - -#ifndef OPENSSL_NO_STDIO - if (SSL_use_certificate_file(conn->ssl, client_cert, - SSL_FILETYPE_ASN1) == 1) { - wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (DER)" - " --> OK"); - return 0; - } else { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_certificate_file (DER) failed"); - } - - if (SSL_use_certificate_file(conn->ssl, client_cert, - SSL_FILETYPE_PEM) == 1) { - wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (PEM)" - " --> OK"); - return 0; - } else { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_certificate_file (PEM) failed"); - } -#else /* OPENSSL_NO_STDIO */ - wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__); -#endif /* OPENSSL_NO_STDIO */ - - return -1; -} - - -static int tls_global_client_cert(SSL_CTX *ssl_ctx, const char *client_cert) -{ -#ifndef OPENSSL_NO_STDIO - if (client_cert == NULL) - return 0; - - if (SSL_CTX_use_certificate_file(ssl_ctx, client_cert, - SSL_FILETYPE_ASN1) != 1 && - SSL_CTX_use_certificate_file(ssl_ctx, client_cert, - SSL_FILETYPE_PEM) != 1) { - tls_show_errors(MSG_INFO, __func__, - "Failed to load client certificate"); - return -1; - } - return 0; -#else /* OPENSSL_NO_STDIO */ - if (client_cert == NULL) - return 0; - wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__); - return -1; -#endif /* OPENSSL_NO_STDIO */ -} - - -static int tls_passwd_cb(char *buf, int size, int rwflag, void *password) -{ - if (password == NULL) { - return 0; - } - os_strlcpy(buf, (char *) password, size); - return os_strlen(buf); -} - - -#ifdef PKCS12_FUNCS -static int tls_parse_pkcs12(SSL_CTX *ssl_ctx, SSL *ssl, PKCS12 *p12, - const char *passwd) -{ - EVP_PKEY *pkey; - X509 *cert; - STACK_OF(X509) *certs; - int res = 0; - char buf[256]; - - pkey = NULL; - cert = NULL; - certs = NULL; - if (!PKCS12_parse(p12, passwd, &pkey, &cert, &certs)) { - tls_show_errors(MSG_DEBUG, __func__, - "Failed to parse PKCS12 file"); - PKCS12_free(p12); - return -1; - } - wpa_printf(MSG_DEBUG, "TLS: Successfully parsed PKCS12 data"); - - if (cert) { - X509_NAME_oneline(X509_get_subject_name(cert), buf, - sizeof(buf)); - wpa_printf(MSG_DEBUG, "TLS: Got certificate from PKCS12: " - "subject='%s'", buf); - if (ssl) { - if (SSL_use_certificate(ssl, cert) != 1) - res = -1; - } else { - if (SSL_CTX_use_certificate(ssl_ctx, cert) != 1) - res = -1; - } - X509_free(cert); - } - - if (pkey) { - wpa_printf(MSG_DEBUG, "TLS: Got private key from PKCS12"); - if (ssl) { - if (SSL_use_PrivateKey(ssl, pkey) != 1) - res = -1; - } else { - if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) != 1) - res = -1; - } - EVP_PKEY_free(pkey); - } - - if (certs) { - while ((cert = sk_X509_pop(certs)) != NULL) { - X509_NAME_oneline(X509_get_subject_name(cert), buf, - sizeof(buf)); - wpa_printf(MSG_DEBUG, "TLS: additional certificate" - " from PKCS12: subject='%s'", buf); - /* - * There is no SSL equivalent for the chain cert - so - * always add it to the context... - */ - if (SSL_CTX_add_extra_chain_cert(ssl_ctx, cert) != 1) { - res = -1; - break; - } - } - sk_X509_free(certs); - } - - PKCS12_free(p12); - - if (res < 0) - tls_get_errors(ssl_ctx); - - return res; -} -#endif /* PKCS12_FUNCS */ - - -static int tls_read_pkcs12(SSL_CTX *ssl_ctx, SSL *ssl, const char *private_key, - const char *passwd) -{ -#ifdef PKCS12_FUNCS - FILE *f; - PKCS12 *p12; - - f = fopen(private_key, "rb"); - if (f == NULL) - return -1; - - p12 = d2i_PKCS12_fp(f, NULL); - fclose(f); - - if (p12 == NULL) { - tls_show_errors(MSG_INFO, __func__, - "Failed to use PKCS#12 file"); - return -1; - } - - return tls_parse_pkcs12(ssl_ctx, ssl, p12, passwd); - -#else /* PKCS12_FUNCS */ - wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot read " - "p12/pfx files"); - return -1; -#endif /* PKCS12_FUNCS */ -} - - -static int tls_read_pkcs12_blob(SSL_CTX *ssl_ctx, SSL *ssl, - const u8 *blob, size_t len, const char *passwd) -{ -#ifdef PKCS12_FUNCS - PKCS12 *p12; - - p12 = d2i_PKCS12(NULL, (OPENSSL_d2i_TYPE) &blob, len); - if (p12 == NULL) { - tls_show_errors(MSG_INFO, __func__, - "Failed to use PKCS#12 blob"); - return -1; - } - - return tls_parse_pkcs12(ssl_ctx, ssl, p12, passwd); - -#else /* PKCS12_FUNCS */ - wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot parse " - "p12/pfx blobs"); - return -1; -#endif /* PKCS12_FUNCS */ -} - - -#ifndef OPENSSL_NO_ENGINE -static int tls_engine_get_cert(struct tls_connection *conn, - const char *cert_id, - X509 **cert) -{ - /* this runs after the private key is loaded so no PIN is required */ - struct { - const char *cert_id; - X509 *cert; - } params; - params.cert_id = cert_id; - params.cert = NULL; - - if (!ENGINE_ctrl_cmd(conn->engine, "LOAD_CERT_CTRL", - 0, ¶ms, NULL, 1)) { - wpa_printf(MSG_ERROR, "ENGINE: cannot load client cert with id" - " '%s' [%s]", cert_id, - ERR_error_string(ERR_get_error(), NULL)); - return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; - } - if (!params.cert) { - wpa_printf(MSG_ERROR, "ENGINE: did not properly cert with id" - " '%s'", cert_id); - return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; - } - *cert = params.cert; - return 0; -} -#endif /* OPENSSL_NO_ENGINE */ - - -static int tls_connection_engine_client_cert(struct tls_connection *conn, - const char *cert_id) -{ -#ifndef OPENSSL_NO_ENGINE - X509 *cert; - - if (tls_engine_get_cert(conn, cert_id, &cert)) - return -1; - - if (!SSL_use_certificate(conn->ssl, cert)) { - tls_show_errors(MSG_ERROR, __func__, - "SSL_use_certificate failed"); - X509_free(cert); - return -1; - } - X509_free(cert); - wpa_printf(MSG_DEBUG, "ENGINE: SSL_use_certificate --> " - "OK"); - return 0; - -#else /* OPENSSL_NO_ENGINE */ - return -1; -#endif /* OPENSSL_NO_ENGINE */ -} - - -static int tls_connection_engine_ca_cert(void *_ssl_ctx, - struct tls_connection *conn, - const char *ca_cert_id) -{ -#ifndef OPENSSL_NO_ENGINE - X509 *cert; - SSL_CTX *ssl_ctx = _ssl_ctx; - - if (tls_engine_get_cert(conn, ca_cert_id, &cert)) - return -1; - - /* start off the same as tls_connection_ca_cert */ - X509_STORE_free(ssl_ctx->cert_store); - ssl_ctx->cert_store = X509_STORE_new(); - if (ssl_ctx->cert_store == NULL) { - wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new " - "certificate store", __func__); - X509_free(cert); - return -1; - } - if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) { - unsigned long err = ERR_peek_error(); - tls_show_errors(MSG_WARNING, __func__, - "Failed to add CA certificate from engine " - "to certificate store"); - if (ERR_GET_LIB(err) == ERR_LIB_X509 && - ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) { - wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring cert" - " already in hash table error", - __func__); - } else { - X509_free(cert); - return -1; - } - } - X509_free(cert); - wpa_printf(MSG_DEBUG, "OpenSSL: %s - added CA certificate from engine " - "to certificate store", __func__); - SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); - return 0; - -#else /* OPENSSL_NO_ENGINE */ - return -1; -#endif /* OPENSSL_NO_ENGINE */ -} - - -static int tls_connection_engine_private_key(struct tls_connection *conn) -{ -#ifndef OPENSSL_NO_ENGINE - if (SSL_use_PrivateKey(conn->ssl, conn->private_key) != 1) { - tls_show_errors(MSG_ERROR, __func__, - "ENGINE: cannot use private key for TLS"); - return -1; - } - if (!SSL_check_private_key(conn->ssl)) { - tls_show_errors(MSG_INFO, __func__, - "Private key failed verification"); - return -1; - } - return 0; -#else /* OPENSSL_NO_ENGINE */ - wpa_printf(MSG_ERROR, "SSL: Configuration uses engine, but " - "engine support was not compiled in"); - return -1; -#endif /* OPENSSL_NO_ENGINE */ -} - - -static int tls_connection_private_key(void *_ssl_ctx, - struct tls_connection *conn, - const char *private_key, - const char *private_key_passwd, - const u8 *private_key_blob, - size_t private_key_blob_len) -{ - SSL_CTX *ssl_ctx = _ssl_ctx; - char *passwd; - int ok; - - if (private_key == NULL && private_key_blob == NULL) - return 0; - - if (private_key_passwd) { - passwd = os_strdup(private_key_passwd); - if (passwd == NULL) - return -1; - } else - passwd = NULL; - - SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb); - SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, passwd); - - ok = 0; - while (private_key_blob) { - if (SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA, conn->ssl, - (u8 *) private_key_blob, - private_key_blob_len) == 1) { - wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_" - "ASN1(EVP_PKEY_RSA) --> OK"); - ok = 1; - break; - } else { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA)" - " failed"); - } - - if (SSL_use_PrivateKey_ASN1(EVP_PKEY_DSA, conn->ssl, - (u8 *) private_key_blob, - private_key_blob_len) == 1) { - wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_" - "ASN1(EVP_PKEY_DSA) --> OK"); - ok = 1; - break; - } else { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_PrivateKey_ASN1(EVP_PKEY_DSA)" - " failed"); - } - - if (SSL_use_RSAPrivateKey_ASN1(conn->ssl, - (u8 *) private_key_blob, - private_key_blob_len) == 1) { - wpa_printf(MSG_DEBUG, "OpenSSL: " - "SSL_use_RSAPrivateKey_ASN1 --> OK"); - ok = 1; - break; - } else { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_RSAPrivateKey_ASN1 failed"); - } - - if (tls_read_pkcs12_blob(ssl_ctx, conn->ssl, private_key_blob, - private_key_blob_len, passwd) == 0) { - wpa_printf(MSG_DEBUG, "OpenSSL: PKCS#12 as blob --> " - "OK"); - ok = 1; - break; - } - - break; - } - - while (!ok && private_key) { -#ifndef OPENSSL_NO_STDIO - if (SSL_use_PrivateKey_file(conn->ssl, private_key, - SSL_FILETYPE_ASN1) == 1) { - wpa_printf(MSG_DEBUG, "OpenSSL: " - "SSL_use_PrivateKey_File (DER) --> OK"); - ok = 1; - break; - } else { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_PrivateKey_File (DER) " - "failed"); - } - - if (SSL_use_PrivateKey_file(conn->ssl, private_key, - SSL_FILETYPE_PEM) == 1) { - wpa_printf(MSG_DEBUG, "OpenSSL: " - "SSL_use_PrivateKey_File (PEM) --> OK"); - ok = 1; - break; - } else { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_PrivateKey_File (PEM) " - "failed"); - } -#else /* OPENSSL_NO_STDIO */ - wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", - __func__); -#endif /* OPENSSL_NO_STDIO */ - - if (tls_read_pkcs12(ssl_ctx, conn->ssl, private_key, passwd) - == 0) { - wpa_printf(MSG_DEBUG, "OpenSSL: Reading PKCS#12 file " - "--> OK"); - ok = 1; - break; - } - - if (tls_cryptoapi_cert(conn->ssl, private_key) == 0) { - wpa_printf(MSG_DEBUG, "OpenSSL: Using CryptoAPI to " - "access certificate store --> OK"); - ok = 1; - break; - } - - break; - } - - if (!ok) { - wpa_printf(MSG_INFO, "OpenSSL: Failed to load private key"); - os_free(passwd); - ERR_clear_error(); - return -1; - } - ERR_clear_error(); - SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL); - os_free(passwd); - - if (!SSL_check_private_key(conn->ssl)) { - tls_show_errors(MSG_INFO, __func__, "Private key failed " - "verification"); - return -1; - } - - wpa_printf(MSG_DEBUG, "SSL: Private key loaded successfully"); - return 0; -} - - -static int tls_global_private_key(SSL_CTX *ssl_ctx, const char *private_key, - const char *private_key_passwd) -{ - char *passwd; - - if (private_key == NULL) - return 0; - - if (private_key_passwd) { - passwd = os_strdup(private_key_passwd); - if (passwd == NULL) - return -1; - } else - passwd = NULL; - - SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb); - SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, passwd); - if ( -#ifndef OPENSSL_NO_STDIO - SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key, - SSL_FILETYPE_ASN1) != 1 && - SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key, - SSL_FILETYPE_PEM) != 1 && -#endif /* OPENSSL_NO_STDIO */ - tls_read_pkcs12(ssl_ctx, NULL, private_key, passwd)) { - tls_show_errors(MSG_INFO, __func__, - "Failed to load private key"); - os_free(passwd); - ERR_clear_error(); - return -1; - } - os_free(passwd); - ERR_clear_error(); - SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL); - - if (!SSL_CTX_check_private_key(ssl_ctx)) { - tls_show_errors(MSG_INFO, __func__, - "Private key failed verification"); - return -1; - } - - return 0; -} - - -static int tls_connection_dh(struct tls_connection *conn, const char *dh_file) -{ -#ifdef OPENSSL_NO_DH - if (dh_file == NULL) - return 0; - wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but " - "dh_file specified"); - return -1; -#else /* OPENSSL_NO_DH */ - DH *dh; - BIO *bio; - - /* TODO: add support for dh_blob */ - if (dh_file == NULL) - return 0; - if (conn == NULL) - return -1; - - bio = BIO_new_file(dh_file, "r"); - if (bio == NULL) { - wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s", - dh_file, ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); - BIO_free(bio); -#ifndef OPENSSL_NO_DSA - while (dh == NULL) { - DSA *dsa; - wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -" - " trying to parse as DSA params", dh_file, - ERR_error_string(ERR_get_error(), NULL)); - bio = BIO_new_file(dh_file, "r"); - if (bio == NULL) - break; - dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL); - BIO_free(bio); - if (!dsa) { - wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file " - "'%s': %s", dh_file, - ERR_error_string(ERR_get_error(), NULL)); - break; - } - - wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format"); - dh = DSA_dup_DH(dsa); - DSA_free(dsa); - if (dh == NULL) { - wpa_printf(MSG_INFO, "TLS: Failed to convert DSA " - "params into DH params"); - break; - } - break; - } -#endif /* !OPENSSL_NO_DSA */ - if (dh == NULL) { - wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file " - "'%s'", dh_file); - return -1; - } - - if (SSL_set_tmp_dh(conn->ssl, dh) != 1) { - wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': " - "%s", dh_file, - ERR_error_string(ERR_get_error(), NULL)); - DH_free(dh); - return -1; - } - DH_free(dh); - return 0; -#endif /* OPENSSL_NO_DH */ -} - - -static int tls_global_dh(SSL_CTX *ssl_ctx, const char *dh_file) -{ -#ifdef OPENSSL_NO_DH - if (dh_file == NULL) - return 0; - wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but " - "dh_file specified"); - return -1; -#else /* OPENSSL_NO_DH */ - DH *dh; - BIO *bio; - - /* TODO: add support for dh_blob */ - if (dh_file == NULL) - return 0; - if (ssl_ctx == NULL) - return -1; - - bio = BIO_new_file(dh_file, "r"); - if (bio == NULL) { - wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s", - dh_file, ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); - BIO_free(bio); -#ifndef OPENSSL_NO_DSA - while (dh == NULL) { - DSA *dsa; - wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -" - " trying to parse as DSA params", dh_file, - ERR_error_string(ERR_get_error(), NULL)); - bio = BIO_new_file(dh_file, "r"); - if (bio == NULL) - break; - dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL); - BIO_free(bio); - if (!dsa) { - wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file " - "'%s': %s", dh_file, - ERR_error_string(ERR_get_error(), NULL)); - break; - } - - wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format"); - dh = DSA_dup_DH(dsa); - DSA_free(dsa); - if (dh == NULL) { - wpa_printf(MSG_INFO, "TLS: Failed to convert DSA " - "params into DH params"); - break; - } - break; - } -#endif /* !OPENSSL_NO_DSA */ - if (dh == NULL) { - wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file " - "'%s'", dh_file); - return -1; - } - - if (SSL_CTX_set_tmp_dh(ssl_ctx, dh) != 1) { - wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': " - "%s", dh_file, - ERR_error_string(ERR_get_error(), NULL)); - DH_free(dh); - return -1; - } - DH_free(dh); - return 0; -#endif /* OPENSSL_NO_DH */ -} - - -int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, - struct tls_keys *keys) -{ - SSL *ssl; - - if (conn == NULL || keys == NULL) - return -1; - ssl = conn->ssl; - if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL) - return -1; - - os_memset(keys, 0, sizeof(*keys)); - keys->master_key = ssl->session->master_key; - keys->master_key_len = ssl->session->master_key_length; - keys->client_random = ssl->s3->client_random; - keys->client_random_len = SSL3_RANDOM_SIZE; - keys->server_random = ssl->s3->server_random; - keys->server_random_len = SSL3_RANDOM_SIZE; - - return 0; -} - - -int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, - const char *label, int server_random_first, - u8 *out, size_t out_len) -{ - return -1; -} - - -u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len) -{ - int res; - u8 *out_data; - - if (appl_data) - *appl_data = NULL; - - /* - * Give TLS handshake data from the server (if available) to OpenSSL - * for processing. - */ - if (in_data && - BIO_write(conn->ssl_in, in_data, in_len) < 0) { - tls_show_errors(MSG_INFO, __func__, - "Handshake failed - BIO_write"); - return NULL; - } - - /* Initiate TLS handshake or continue the existing handshake */ - res = SSL_connect(conn->ssl); - if (res != 1) { - int err = SSL_get_error(conn->ssl, res); - if (err == SSL_ERROR_WANT_READ) - wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want " - "more data"); - else if (err == SSL_ERROR_WANT_WRITE) - wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want to " - "write"); - else { - tls_show_errors(MSG_INFO, __func__, "SSL_connect"); - conn->failed++; - } - } - - /* Get the TLS handshake data to be sent to the server */ - res = BIO_ctrl_pending(conn->ssl_out); - wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res); - out_data = os_malloc(res == 0 ? 1 : res); - if (out_data == NULL) { - wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for " - "handshake output (%d bytes)", res); - if (BIO_reset(conn->ssl_out) < 0) { - tls_show_errors(MSG_INFO, __func__, - "BIO_reset failed"); - } - *out_len = 0; - return NULL; - } - res = res == 0 ? 0 : BIO_read(conn->ssl_out, out_data, res); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Handshake failed - BIO_read"); - if (BIO_reset(conn->ssl_out) < 0) { - tls_show_errors(MSG_INFO, __func__, - "BIO_reset failed"); - } - *out_len = 0; - return NULL; - } - *out_len = res; - - if (SSL_is_init_finished(conn->ssl) && appl_data) { - *appl_data = os_malloc(in_len); - if (*appl_data) { - res = SSL_read(conn->ssl, *appl_data, in_len); - if (res < 0) { - int err = SSL_get_error(conn->ssl, res); - if (err == SSL_ERROR_WANT_READ || - err == SSL_ERROR_WANT_WRITE) { - wpa_printf(MSG_DEBUG, - "SSL: No Application Data " - "included"); - } else { - tls_show_errors(MSG_INFO, __func__, - "Failed to read " - "possible " - "Application Data"); - } - os_free(*appl_data); - *appl_data = NULL; - } else { - *appl_data_len = res; - wpa_hexdump_key(MSG_MSGDUMP, "SSL: Application" - " Data in Finish message", - *appl_data, *appl_data_len); - } - } - } - - return out_data; -} - - -u8 * tls_connection_server_handshake(void *ssl_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len) -{ - int res; - u8 *out_data; - - /* - * Give TLS handshake data from the client (if available) to OpenSSL - * for processing. - */ - if (in_data && - BIO_write(conn->ssl_in, in_data, in_len) < 0) { - tls_show_errors(MSG_INFO, __func__, - "Handshake failed - BIO_write"); - return NULL; - } - - /* Initiate TLS handshake or continue the existing handshake */ - res = SSL_accept(conn->ssl); - if (res != 1) { - int err = SSL_get_error(conn->ssl, res); - if (err == SSL_ERROR_WANT_READ) - wpa_printf(MSG_DEBUG, "SSL: SSL_accept - want " - "more data"); - else if (err == SSL_ERROR_WANT_WRITE) - wpa_printf(MSG_DEBUG, "SSL: SSL_accept - want to " - "write"); - else { - tls_show_errors(MSG_INFO, __func__, "SSL_accept"); - return NULL; - } - } - - /* Get the TLS handshake data to be sent to the client */ - res = BIO_ctrl_pending(conn->ssl_out); - wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res); - out_data = os_malloc(res == 0 ? 1 : res); - if (out_data == NULL) { - wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for " - "handshake output (%d bytes)", res); - if (BIO_reset(conn->ssl_out) < 0) { - tls_show_errors(MSG_INFO, __func__, - "BIO_reset failed"); - } - *out_len = 0; - return NULL; - } - res = res == 0 ? 0 : BIO_read(conn->ssl_out, out_data, res); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Handshake failed - BIO_read"); - if (BIO_reset(conn->ssl_out) < 0) { - tls_show_errors(MSG_INFO, __func__, - "BIO_reset failed"); - } - *out_len = 0; - return NULL; - } - *out_len = res; - return out_data; -} - - -int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - int res; - - if (conn == NULL) - return -1; - - /* Give plaintext data for OpenSSL to encrypt into the TLS tunnel. */ - if ((res = BIO_reset(conn->ssl_in)) < 0 || - (res = BIO_reset(conn->ssl_out)) < 0) { - tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); - return res; - } - res = SSL_write(conn->ssl, in_data, in_len); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Encryption failed - SSL_write"); - return res; - } - - /* Read encrypted data to be sent to the server */ - res = BIO_read(conn->ssl_out, out_data, out_len); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Encryption failed - BIO_read"); - return res; - } - - return res; -} - - -int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - int res; - - /* Give encrypted data from TLS tunnel for OpenSSL to decrypt. */ - res = BIO_write(conn->ssl_in, in_data, in_len); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Decryption failed - BIO_write"); - return res; - } - if (BIO_reset(conn->ssl_out) < 0) { - tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); - return res; - } - - /* Read decrypted data for further processing */ - res = SSL_read(conn->ssl, out_data, out_len); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Decryption failed - SSL_read"); - return res; - } - - return res; -} - - -int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) -{ - return conn ? conn->ssl->hit : 0; -} - - -int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, - u8 *ciphers) -{ - char buf[100], *pos, *end; - u8 *c; - int ret; - - if (conn == NULL || conn->ssl == NULL || ciphers == NULL) - return -1; - - buf[0] = '\0'; - pos = buf; - end = pos + sizeof(buf); - - c = ciphers; - while (*c != TLS_CIPHER_NONE) { - const char *suite; - - switch (*c) { - case TLS_CIPHER_RC4_SHA: - suite = "RC4-SHA"; - break; - case TLS_CIPHER_AES128_SHA: - suite = "AES128-SHA"; - break; - case TLS_CIPHER_RSA_DHE_AES128_SHA: - suite = "DHE-RSA-AES128-SHA"; - break; - case TLS_CIPHER_ANON_DH_AES128_SHA: - suite = "ADH-AES128-SHA"; - break; - default: - wpa_printf(MSG_DEBUG, "TLS: Unsupported " - "cipher selection: %d", *c); - return -1; - } - ret = os_snprintf(pos, end - pos, ":%s", suite); - if (ret < 0 || ret >= end - pos) - break; - pos += ret; - - c++; - } - - wpa_printf(MSG_DEBUG, "OpenSSL: cipher suites: %s", buf + 1); - - if (SSL_set_cipher_list(conn->ssl, buf + 1) != 1) { - tls_show_errors(MSG_INFO, __func__, - "Cipher suite configuration failed"); - return -1; - } - - return 0; -} - - -int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, - char *buf, size_t buflen) -{ - const char *name; - if (conn == NULL || conn->ssl == NULL) - return -1; - - name = SSL_get_cipher(conn->ssl); - if (name == NULL) - return -1; - - os_strlcpy(buf, name, buflen); - return 0; -} - - -int tls_connection_enable_workaround(void *ssl_ctx, - struct tls_connection *conn) -{ - SSL_set_options(conn->ssl, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); - - return 0; -} - - -#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) -/* ClientHello TLS extensions require a patch to openssl, so this function is - * commented out unless explicitly needed for EAP-FAST in order to be able to - * build this file with unmodified openssl. */ -int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, - int ext_type, const u8 *data, - size_t data_len) -{ - if (conn == NULL || conn->ssl == NULL || ext_type != 35) - return -1; - -#ifdef CONFIG_OPENSSL_TICKET_OVERRIDE - if (SSL_set_session_ticket_ext(conn->ssl, (void *) data, - data_len) != 1) - return -1; -#else /* CONFIG_OPENSSL_TICKET_OVERRIDE */ - if (SSL_set_hello_extension(conn->ssl, ext_type, (void *) data, - data_len) != 1) - return -1; -#endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */ - - return 0; -} -#endif /* EAP_FAST || EAP_FAST_DYNAMIC */ - - -int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - return conn->failed; -} - - -int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - return conn->read_alerts; -} - - -int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - return conn->write_alerts; -} - - -int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, - const struct tls_connection_params *params) -{ - int ret; - unsigned long err; - - if (conn == NULL) - return -1; - - while ((err = ERR_get_error())) { - wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s", - __func__, ERR_error_string(err, NULL)); - } - - if (params->engine) { - wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine"); - ret = tls_engine_init(conn, params->engine_id, params->pin, - params->key_id, params->cert_id, - params->ca_cert_id); - if (ret) - return ret; - } - if (tls_connection_set_subject_match(conn, - params->subject_match, - params->altsubject_match)) - return -1; - - if (params->engine && params->ca_cert_id) { - if (tls_connection_engine_ca_cert(tls_ctx, conn, - params->ca_cert_id)) - return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED; - } else if (tls_connection_ca_cert(tls_ctx, conn, params->ca_cert, - params->ca_cert_blob, - params->ca_cert_blob_len, - params->ca_path)) - return -1; - - if (params->engine && params->cert_id) { - if (tls_connection_engine_client_cert(conn, params->cert_id)) - return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED; - } else if (tls_connection_client_cert(conn, params->client_cert, - params->client_cert_blob, - params->client_cert_blob_len)) - return -1; - - if (params->engine && params->key_id) { - wpa_printf(MSG_DEBUG, "TLS: Using private key from engine"); - if (tls_connection_engine_private_key(conn)) - return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED; - } else if (tls_connection_private_key(tls_ctx, conn, - params->private_key, - params->private_key_passwd, - params->private_key_blob, - params->private_key_blob_len)) { - wpa_printf(MSG_INFO, "TLS: Failed to load private key '%s'", - params->private_key); - return -1; - } - - if (tls_connection_dh(conn, params->dh_file)) { - wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'", - params->dh_file); - return -1; - } - - tls_get_errors(tls_ctx); - - return 0; -} - - -int tls_global_set_params(void *tls_ctx, - const struct tls_connection_params *params) -{ - SSL_CTX *ssl_ctx = tls_ctx; - unsigned long err; - - while ((err = ERR_get_error())) { - wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s", - __func__, ERR_error_string(err, NULL)); - } - - if (tls_global_ca_cert(ssl_ctx, params->ca_cert)) - return -1; - - if (tls_global_client_cert(ssl_ctx, params->client_cert)) - return -1; - - if (tls_global_private_key(ssl_ctx, params->private_key, - params->private_key_passwd)) - return -1; - - if (tls_global_dh(ssl_ctx, params->dh_file)) { - wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'", - params->dh_file); - return -1; - } - - return 0; -} - - -int tls_connection_get_keyblock_size(void *tls_ctx, - struct tls_connection *conn) -{ - const EVP_CIPHER *c; - const EVP_MD *h; - - if (conn == NULL || conn->ssl == NULL || - conn->ssl->enc_read_ctx == NULL || - conn->ssl->enc_read_ctx->cipher == NULL || - conn->ssl->read_hash == NULL) - return -1; - - c = conn->ssl->enc_read_ctx->cipher; -#if OPENSSL_VERSION_NUMBER >= 0x00909000L - h = EVP_MD_CTX_md(conn->ssl->read_hash); -#else - h = conn->ssl->read_hash; -#endif - - return 2 * (EVP_CIPHER_key_length(c) + - EVP_MD_size(h) + - EVP_CIPHER_iv_length(c)); -} - - -unsigned int tls_capabilities(void *tls_ctx) -{ - return 0; -} - - -int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, - int tls_ia) -{ - return -1; -} - - -int tls_connection_ia_send_phase_finished(void *tls_ctx, - struct tls_connection *conn, - int final, - u8 *out_data, size_t out_len) -{ - return -1; -} - - -int tls_connection_ia_final_phase_finished(void *tls_ctx, - struct tls_connection *conn) -{ - return -1; -} - - -int tls_connection_ia_permute_inner_secret(void *tls_ctx, - struct tls_connection *conn, - const u8 *key, size_t key_len) -{ - return -1; -} - - -#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) -/* Pre-shared secred requires a patch to openssl, so this function is - * commented out unless explicitly needed for EAP-FAST in order to be able to - * build this file with unmodified openssl. */ - -static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len, - STACK_OF(SSL_CIPHER) *peer_ciphers, - SSL_CIPHER **cipher, void *arg) -{ - struct tls_connection *conn = arg; - int ret; - - if (conn == NULL || conn->session_ticket_cb == NULL) - return 0; - - ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx, - conn->session_ticket, - conn->session_ticket_len, - s->s3->client_random, - s->s3->server_random, secret); - os_free(conn->session_ticket); - conn->session_ticket = NULL; - - if (ret <= 0) - return 0; - - *secret_len = SSL_MAX_MASTER_KEY_LENGTH; - return 1; -} - - -#ifdef CONFIG_OPENSSL_TICKET_OVERRIDE -static int tls_session_ticket_ext_cb(SSL *s, const unsigned char *data, - int len, void *arg) -{ - struct tls_connection *conn = arg; - - if (conn == NULL || conn->session_ticket_cb == NULL) - return 0; - - wpa_printf(MSG_DEBUG, "OpenSSL: %s: length=%d", __func__, len); - - os_free(conn->session_ticket); - conn->session_ticket = NULL; - - wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket " - "extension", data, len); - - conn->session_ticket = os_malloc(len); - if (conn->session_ticket == NULL) - return 0; - - os_memcpy(conn->session_ticket, data, len); - conn->session_ticket_len = len; - - return 1; -} -#else /* CONFIG_OPENSSL_TICKET_OVERRIDE */ -#ifdef SSL_OP_NO_TICKET -static void tls_hello_ext_cb(SSL *s, int client_server, int type, - unsigned char *data, int len, void *arg) -{ - struct tls_connection *conn = arg; - - if (conn == NULL || conn->session_ticket_cb == NULL) - return; - - wpa_printf(MSG_DEBUG, "OpenSSL: %s: type=%d length=%d", __func__, - type, len); - - if (type == TLSEXT_TYPE_session_ticket && !client_server) { - os_free(conn->session_ticket); - conn->session_ticket = NULL; - - wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket " - "extension", data, len); - conn->session_ticket = os_malloc(len); - if (conn->session_ticket == NULL) - return; - - os_memcpy(conn->session_ticket, data, len); - conn->session_ticket_len = len; - } -} -#else /* SSL_OP_NO_TICKET */ -static int tls_hello_ext_cb(SSL *s, TLS_EXTENSION *ext, void *arg) -{ - struct tls_connection *conn = arg; - - if (conn == NULL || conn->session_ticket_cb == NULL) - return 0; - - wpa_printf(MSG_DEBUG, "OpenSSL: %s: type=%d length=%d", __func__, - ext->type, ext->length); - - os_free(conn->session_ticket); - conn->session_ticket = NULL; - - if (ext->type == 35) { - wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket " - "extension", ext->data, ext->length); - conn->session_ticket = os_malloc(ext->length); - if (conn->session_ticket == NULL) - return SSL_AD_INTERNAL_ERROR; - - os_memcpy(conn->session_ticket, ext->data, ext->length); - conn->session_ticket_len = ext->length; - } - - return 0; -} -#endif /* SSL_OP_NO_TICKET */ -#endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */ -#endif /* EAP_FAST || EAP_FAST_DYNAMIC */ - - -int tls_connection_set_session_ticket_cb(void *tls_ctx, - struct tls_connection *conn, - tls_session_ticket_cb cb, - void *ctx) -{ -#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) - conn->session_ticket_cb = cb; - conn->session_ticket_cb_ctx = ctx; - - if (cb) { - if (SSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb, - conn) != 1) - return -1; -#ifdef CONFIG_OPENSSL_TICKET_OVERRIDE - SSL_set_session_ticket_ext_cb(conn->ssl, - tls_session_ticket_ext_cb, conn); -#else /* CONFIG_OPENSSL_TICKET_OVERRIDE */ -#ifdef SSL_OP_NO_TICKET - SSL_set_tlsext_debug_callback(conn->ssl, tls_hello_ext_cb); - SSL_set_tlsext_debug_arg(conn->ssl, conn); -#else /* SSL_OP_NO_TICKET */ - if (SSL_set_hello_extension_cb(conn->ssl, tls_hello_ext_cb, - conn) != 1) - return -1; -#endif /* SSL_OP_NO_TICKET */ -#endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */ - } else { - if (SSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1) - return -1; -#ifdef CONFIG_OPENSSL_TICKET_OVERRIDE - SSL_set_session_ticket_ext_cb(conn->ssl, NULL, NULL); -#else /* CONFIG_OPENSSL_TICKET_OVERRIDE */ -#ifdef SSL_OP_NO_TICKET - SSL_set_tlsext_debug_callback(conn->ssl, NULL); - SSL_set_tlsext_debug_arg(conn->ssl, conn); -#else /* SSL_OP_NO_TICKET */ - if (SSL_set_hello_extension_cb(conn->ssl, NULL, NULL) != 1) - return -1; -#endif /* SSL_OP_NO_TICKET */ -#endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */ - } - - return 0; -#else /* EAP_FAST || EAP_FAST_DYNAMIC */ - return -1; -#endif /* EAP_FAST || EAP_FAST_DYNAMIC */ -} diff --git a/contrib/hostapd/src/crypto/tls_schannel.c b/contrib/hostapd/src/crypto/tls_schannel.c deleted file mode 100644 index 87e74353dc..0000000000 --- a/contrib/hostapd/src/crypto/tls_schannel.c +++ /dev/null @@ -1,789 +0,0 @@ -/* - * WPA Supplicant / SSL/TLS interface functions for Microsoft Schannel - * Copyright (c) 2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -/* - * FIX: Go through all SSPI functions and verify what needs to be freed - * FIX: session resumption - * TODO: add support for server cert chain validation - * TODO: add support for CA cert validation - * TODO: add support for EAP-TLS (client cert/key conf) - */ - -#include "includes.h" -#include -#include -#include -#define SECURITY_WIN32 -#include -#include - -#include "common.h" -#include "tls.h" - - -struct tls_global { - HMODULE hsecurity; - PSecurityFunctionTable sspi; - HCERTSTORE my_cert_store; -}; - -struct tls_connection { - int established, start; - int failed, read_alerts, write_alerts; - - SCHANNEL_CRED schannel_cred; - CredHandle creds; - CtxtHandle context; - - u8 eap_tls_prf[128]; - int eap_tls_prf_set; -}; - - -static int schannel_load_lib(struct tls_global *global) -{ - INIT_SECURITY_INTERFACE pInitSecurityInterface; - - global->hsecurity = LoadLibrary(TEXT("Secur32.dll")); - if (global->hsecurity == NULL) { - wpa_printf(MSG_ERROR, "%s: Could not load Secur32.dll - 0x%x", - __func__, (unsigned int) GetLastError()); - return -1; - } - - pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress( - global->hsecurity, "InitSecurityInterfaceA"); - if (pInitSecurityInterface == NULL) { - wpa_printf(MSG_ERROR, "%s: Could not find " - "InitSecurityInterfaceA from Secur32.dll", - __func__); - FreeLibrary(global->hsecurity); - global->hsecurity = NULL; - return -1; - } - - global->sspi = pInitSecurityInterface(); - if (global->sspi == NULL) { - wpa_printf(MSG_ERROR, "%s: Could not read security " - "interface - 0x%x", - __func__, (unsigned int) GetLastError()); - FreeLibrary(global->hsecurity); - global->hsecurity = NULL; - return -1; - } - - return 0; -} - - -void * tls_init(const struct tls_config *conf) -{ - struct tls_global *global; - - global = os_zalloc(sizeof(*global)); - if (global == NULL) - return NULL; - if (schannel_load_lib(global)) { - os_free(global); - return NULL; - } - return global; -} - - -void tls_deinit(void *ssl_ctx) -{ - struct tls_global *global = ssl_ctx; - - if (global->my_cert_store) - CertCloseStore(global->my_cert_store, 0); - FreeLibrary(global->hsecurity); - os_free(global); -} - - -int tls_get_errors(void *ssl_ctx) -{ - return 0; -} - - -struct tls_connection * tls_connection_init(void *ssl_ctx) -{ - struct tls_connection *conn; - - conn = os_zalloc(sizeof(*conn)); - if (conn == NULL) - return NULL; - conn->start = 1; - - return conn; -} - - -void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return; - - os_free(conn); -} - - -int tls_connection_established(void *ssl_ctx, struct tls_connection *conn) -{ - return conn ? conn->established : 0; -} - - -int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn) -{ - struct tls_global *global = ssl_ctx; - if (conn == NULL) - return -1; - - conn->eap_tls_prf_set = 0; - conn->established = conn->failed = 0; - conn->read_alerts = conn->write_alerts = 0; - global->sspi->DeleteSecurityContext(&conn->context); - /* FIX: what else needs to be reseted? */ - - return 0; -} - - -int tls_global_set_params(void *tls_ctx, - const struct tls_connection_params *params) -{ - return -1; -} - - -int tls_global_set_verify(void *ssl_ctx, int check_crl) -{ - return -1; -} - - -int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, - int verify_peer) -{ - return -1; -} - - -int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, - struct tls_keys *keys) -{ - /* Schannel does not export master secret or client/server random. */ - return -1; -} - - -int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, - const char *label, int server_random_first, - u8 *out, size_t out_len) -{ - /* - * Cannot get master_key from Schannel, but EapKeyBlock can be used to - * generate session keys for EAP-TLS and EAP-PEAPv0. EAP-PEAPv2 and - * EAP-TTLS cannot use this, though, since they are using different - * labels. The only option could be to implement TLSv1 completely here - * and just use Schannel or CryptoAPI for low-level crypto - * functionality.. - */ - - if (conn == NULL || !conn->eap_tls_prf_set || server_random_first || - os_strcmp(label, "client EAP encryption") != 0 || - out_len > sizeof(conn->eap_tls_prf)) - return -1; - - os_memcpy(out, conn->eap_tls_prf, out_len); - - return 0; -} - - -static u8 * tls_conn_hs_clienthello(struct tls_global *global, - struct tls_connection *conn, - size_t *out_len) -{ - DWORD sspi_flags, sspi_flags_out; - SecBufferDesc outbuf; - SecBuffer outbufs[1]; - SECURITY_STATUS status; - TimeStamp ts_expiry; - - sspi_flags = ISC_REQ_REPLAY_DETECT | - ISC_REQ_CONFIDENTIALITY | - ISC_RET_EXTENDED_ERROR | - ISC_REQ_ALLOCATE_MEMORY | - ISC_REQ_MANUAL_CRED_VALIDATION; - - wpa_printf(MSG_DEBUG, "%s: Generating ClientHello", __func__); - - outbufs[0].pvBuffer = NULL; - outbufs[0].BufferType = SECBUFFER_TOKEN; - outbufs[0].cbBuffer = 0; - - outbuf.cBuffers = 1; - outbuf.pBuffers = outbufs; - outbuf.ulVersion = SECBUFFER_VERSION; - -#ifdef UNICODE - status = global->sspi->InitializeSecurityContextW( - &conn->creds, NULL, NULL /* server name */, sspi_flags, 0, - SECURITY_NATIVE_DREP, NULL, 0, &conn->context, - &outbuf, &sspi_flags_out, &ts_expiry); -#else /* UNICODE */ - status = global->sspi->InitializeSecurityContextA( - &conn->creds, NULL, NULL /* server name */, sspi_flags, 0, - SECURITY_NATIVE_DREP, NULL, 0, &conn->context, - &outbuf, &sspi_flags_out, &ts_expiry); -#endif /* UNICODE */ - if (status != SEC_I_CONTINUE_NEEDED) { - wpa_printf(MSG_ERROR, "%s: InitializeSecurityContextA " - "failed - 0x%x", - __func__, (unsigned int) status); - return NULL; - } - - if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) { - u8 *buf; - wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello", - outbufs[0].pvBuffer, outbufs[0].cbBuffer); - conn->start = 0; - *out_len = outbufs[0].cbBuffer; - buf = os_malloc(*out_len); - if (buf == NULL) - return NULL; - os_memcpy(buf, outbufs[0].pvBuffer, *out_len); - global->sspi->FreeContextBuffer(outbufs[0].pvBuffer); - return buf; - } - - wpa_printf(MSG_ERROR, "SChannel: Failed to generate ClientHello"); - - return NULL; -} - - -#ifndef SECPKG_ATTR_EAP_KEY_BLOCK -#define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b - -typedef struct _SecPkgContext_EapKeyBlock { - BYTE rgbKeys[128]; - BYTE rgbIVs[64]; -} SecPkgContext_EapKeyBlock, *PSecPkgContext_EapKeyBlock; -#endif /* !SECPKG_ATTR_EAP_KEY_BLOCK */ - -static int tls_get_eap(struct tls_global *global, struct tls_connection *conn) -{ - SECURITY_STATUS status; - SecPkgContext_EapKeyBlock kb; - - /* Note: Windows NT and Windows Me/98/95 do not support getting - * EapKeyBlock */ - - status = global->sspi->QueryContextAttributes( - &conn->context, SECPKG_ATTR_EAP_KEY_BLOCK, &kb); - if (status != SEC_E_OK) { - wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes(" - "SECPKG_ATTR_EAP_KEY_BLOCK) failed (%d)", - __func__, (int) status); - return -1; - } - - wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbKeys", - kb.rgbKeys, sizeof(kb.rgbKeys)); - wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbIVs", - kb.rgbIVs, sizeof(kb.rgbIVs)); - - os_memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys)); - conn->eap_tls_prf_set = 1; - return 0; -} - - -u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len) -{ - struct tls_global *global = ssl_ctx; - DWORD sspi_flags, sspi_flags_out; - SecBufferDesc inbuf, outbuf; - SecBuffer inbufs[2], outbufs[1]; - SECURITY_STATUS status; - TimeStamp ts_expiry; - u8 *out_buf = NULL; - - if (appl_data) - *appl_data = NULL; - - if (conn->start) { - return tls_conn_hs_clienthello(global, conn, out_len); - } - - wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process", - in_len); - - sspi_flags = ISC_REQ_REPLAY_DETECT | - ISC_REQ_CONFIDENTIALITY | - ISC_RET_EXTENDED_ERROR | - ISC_REQ_ALLOCATE_MEMORY | - ISC_REQ_MANUAL_CRED_VALIDATION; - - /* Input buffer for Schannel */ - inbufs[0].pvBuffer = (u8 *) in_data; - inbufs[0].cbBuffer = in_len; - inbufs[0].BufferType = SECBUFFER_TOKEN; - - /* Place for leftover data from Schannel */ - inbufs[1].pvBuffer = NULL; - inbufs[1].cbBuffer = 0; - inbufs[1].BufferType = SECBUFFER_EMPTY; - - inbuf.cBuffers = 2; - inbuf.pBuffers = inbufs; - inbuf.ulVersion = SECBUFFER_VERSION; - - /* Output buffer for Schannel */ - outbufs[0].pvBuffer = NULL; - outbufs[0].cbBuffer = 0; - outbufs[0].BufferType = SECBUFFER_TOKEN; - - outbuf.cBuffers = 1; - outbuf.pBuffers = outbufs; - outbuf.ulVersion = SECBUFFER_VERSION; - -#ifdef UNICODE - status = global->sspi->InitializeSecurityContextW( - &conn->creds, &conn->context, NULL, sspi_flags, 0, - SECURITY_NATIVE_DREP, &inbuf, 0, NULL, - &outbuf, &sspi_flags_out, &ts_expiry); -#else /* UNICODE */ - status = global->sspi->InitializeSecurityContextA( - &conn->creds, &conn->context, NULL, sspi_flags, 0, - SECURITY_NATIVE_DREP, &inbuf, 0, NULL, - &outbuf, &sspi_flags_out, &ts_expiry); -#endif /* UNICODE */ - - wpa_printf(MSG_MSGDUMP, "Schannel: InitializeSecurityContext -> " - "status=%d inlen[0]=%d intype[0]=%d inlen[1]=%d " - "intype[1]=%d outlen[0]=%d", - (int) status, (int) inbufs[0].cbBuffer, - (int) inbufs[0].BufferType, (int) inbufs[1].cbBuffer, - (int) inbufs[1].BufferType, - (int) outbufs[0].cbBuffer); - if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED || - (FAILED(status) && (sspi_flags_out & ISC_RET_EXTENDED_ERROR))) { - if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) { - wpa_hexdump(MSG_MSGDUMP, "SChannel - output", - outbufs[0].pvBuffer, outbufs[0].cbBuffer); - *out_len = outbufs[0].cbBuffer; - out_buf = os_malloc(*out_len); - if (out_buf) - os_memcpy(out_buf, outbufs[0].pvBuffer, - *out_len); - global->sspi->FreeContextBuffer(outbufs[0].pvBuffer); - outbufs[0].pvBuffer = NULL; - if (out_buf == NULL) - return NULL; - } - } - - switch (status) { - case SEC_E_INCOMPLETE_MESSAGE: - wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INCOMPLETE_MESSAGE"); - break; - case SEC_I_CONTINUE_NEEDED: - wpa_printf(MSG_DEBUG, "Schannel: SEC_I_CONTINUE_NEEDED"); - break; - case SEC_E_OK: - /* TODO: verify server certificate chain */ - wpa_printf(MSG_DEBUG, "Schannel: SEC_E_OK - Handshake " - "completed successfully"); - conn->established = 1; - tls_get_eap(global, conn); - - /* Need to return something to get final TLS ACK. */ - if (out_buf == NULL) - out_buf = os_malloc(1); - - if (inbufs[1].BufferType == SECBUFFER_EXTRA) { - wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted " - "application data", - inbufs[1].pvBuffer, inbufs[1].cbBuffer); - if (appl_data) { - *appl_data_len = outbufs[1].cbBuffer; - appl_data = os_malloc(*appl_data_len); - if (appl_data) - os_memcpy(appl_data, - outbufs[1].pvBuffer, - *appl_data_len); - } - global->sspi->FreeContextBuffer(inbufs[1].pvBuffer); - inbufs[1].pvBuffer = NULL; - } - break; - case SEC_I_INCOMPLETE_CREDENTIALS: - wpa_printf(MSG_DEBUG, - "Schannel: SEC_I_INCOMPLETE_CREDENTIALS"); - break; - case SEC_E_WRONG_PRINCIPAL: - wpa_printf(MSG_DEBUG, "Schannel: SEC_E_WRONG_PRINCIPAL"); - break; - case SEC_E_INTERNAL_ERROR: - wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INTERNAL_ERROR"); - break; - } - - if (FAILED(status)) { - wpa_printf(MSG_DEBUG, "Schannel: Handshake failed " - "(out_buf=%p)", out_buf); - conn->failed++; - global->sspi->DeleteSecurityContext(&conn->context); - return out_buf; - } - - if (inbufs[1].BufferType == SECBUFFER_EXTRA) { - /* TODO: Can this happen? What to do with this data? */ - wpa_hexdump(MSG_MSGDUMP, "SChannel - Leftover data", - inbufs[1].pvBuffer, inbufs[1].cbBuffer); - global->sspi->FreeContextBuffer(inbufs[1].pvBuffer); - inbufs[1].pvBuffer = NULL; - } - - return out_buf; -} - - -u8 * tls_connection_server_handshake(void *ssl_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len) -{ - return NULL; -} - - -int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - struct tls_global *global = ssl_ctx; - SECURITY_STATUS status; - SecBufferDesc buf; - SecBuffer bufs[4]; - SecPkgContext_StreamSizes sizes; - int i; - size_t total_len; - - status = global->sspi->QueryContextAttributes(&conn->context, - SECPKG_ATTR_STREAM_SIZES, - &sizes); - if (status != SEC_E_OK) { - wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed", - __func__); - return -1; - } - wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u", - __func__, - (unsigned int) sizes.cbHeader, - (unsigned int) sizes.cbTrailer); - - total_len = sizes.cbHeader + in_len + sizes.cbTrailer; - - if (out_len < total_len) { - wpa_printf(MSG_DEBUG, "%s: too short out_data (out_len=%lu " - "in_len=%lu total_len=%lu)", __func__, - (unsigned long) out_len, (unsigned long) in_len, - (unsigned long) total_len); - return -1; - } - - os_memset(&bufs, 0, sizeof(bufs)); - bufs[0].pvBuffer = out_data; - bufs[0].cbBuffer = sizes.cbHeader; - bufs[0].BufferType = SECBUFFER_STREAM_HEADER; - - os_memcpy(out_data + sizes.cbHeader, in_data, in_len); - bufs[1].pvBuffer = out_data + sizes.cbHeader; - bufs[1].cbBuffer = in_len; - bufs[1].BufferType = SECBUFFER_DATA; - - bufs[2].pvBuffer = out_data + sizes.cbHeader + in_len; - bufs[2].cbBuffer = sizes.cbTrailer; - bufs[2].BufferType = SECBUFFER_STREAM_TRAILER; - - buf.ulVersion = SECBUFFER_VERSION; - buf.cBuffers = 3; - buf.pBuffers = bufs; - - status = global->sspi->EncryptMessage(&conn->context, 0, &buf, 0); - - wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage -> " - "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d " - "len[2]=%d type[2]=%d", - (int) status, - (int) bufs[0].cbBuffer, (int) bufs[0].BufferType, - (int) bufs[1].cbBuffer, (int) bufs[1].BufferType, - (int) bufs[2].cbBuffer, (int) bufs[2].BufferType); - wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: " - "out_data=%p bufs %p %p %p", - out_data, bufs[0].pvBuffer, bufs[1].pvBuffer, - bufs[2].pvBuffer); - - for (i = 0; i < 3; i++) { - if (bufs[i].pvBuffer && bufs[i].BufferType != SECBUFFER_EMPTY) - { - wpa_hexdump(MSG_MSGDUMP, "SChannel: bufs", - bufs[i].pvBuffer, bufs[i].cbBuffer); - } - } - - if (status == SEC_E_OK) { - wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__); - wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Encrypted data from " - "EncryptMessage", out_data, total_len); - return total_len; - } - - wpa_printf(MSG_DEBUG, "%s: Failed - status=%d", - __func__, (int) status); - return -1; -} - - -int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - struct tls_global *global = ssl_ctx; - SECURITY_STATUS status; - SecBufferDesc buf; - SecBuffer bufs[4]; - int i; - - if (out_len < in_len) { - wpa_printf(MSG_DEBUG, "%s: out_len=%lu < in_len=%lu", __func__, - (unsigned long) out_len, (unsigned long) in_len); - return -1; - } - - wpa_hexdump(MSG_MSGDUMP, "Schannel: Encrypted data to DecryptMessage", - in_data, in_len); - os_memset(&bufs, 0, sizeof(bufs)); - os_memcpy(out_data, in_data, in_len); - bufs[0].pvBuffer = out_data; - bufs[0].cbBuffer = in_len; - bufs[0].BufferType = SECBUFFER_DATA; - - bufs[1].BufferType = SECBUFFER_EMPTY; - bufs[2].BufferType = SECBUFFER_EMPTY; - bufs[3].BufferType = SECBUFFER_EMPTY; - - buf.ulVersion = SECBUFFER_VERSION; - buf.cBuffers = 4; - buf.pBuffers = bufs; - - status = global->sspi->DecryptMessage(&conn->context, &buf, 0, - NULL); - wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage -> " - "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d " - "len[2]=%d type[2]=%d len[3]=%d type[3]=%d", - (int) status, - (int) bufs[0].cbBuffer, (int) bufs[0].BufferType, - (int) bufs[1].cbBuffer, (int) bufs[1].BufferType, - (int) bufs[2].cbBuffer, (int) bufs[2].BufferType, - (int) bufs[3].cbBuffer, (int) bufs[3].BufferType); - wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: " - "out_data=%p bufs %p %p %p %p", - out_data, bufs[0].pvBuffer, bufs[1].pvBuffer, - bufs[2].pvBuffer, bufs[3].pvBuffer); - - switch (status) { - case SEC_E_INCOMPLETE_MESSAGE: - wpa_printf(MSG_DEBUG, "%s: SEC_E_INCOMPLETE_MESSAGE", - __func__); - break; - case SEC_E_OK: - wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__); - for (i = 0; i < 4; i++) { - if (bufs[i].BufferType == SECBUFFER_DATA) - break; - } - if (i == 4) { - wpa_printf(MSG_DEBUG, "%s: No output data from " - "DecryptMessage", __func__); - return -1; - } - wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from " - "DecryptMessage", - bufs[i].pvBuffer, bufs[i].cbBuffer); - if (bufs[i].cbBuffer > out_len) { - wpa_printf(MSG_DEBUG, "%s: Too long output data", - __func__); - return -1; - } - os_memmove(out_data, bufs[i].pvBuffer, bufs[i].cbBuffer); - return bufs[i].cbBuffer; - } - - wpa_printf(MSG_DEBUG, "%s: Failed - status=%d", - __func__, (int) status); - return -1; -} - - -int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, - u8 *ciphers) -{ - return -1; -} - - -int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, - char *buf, size_t buflen) -{ - return -1; -} - - -int tls_connection_enable_workaround(void *ssl_ctx, - struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, - int ext_type, const u8 *data, - size_t data_len) -{ - return -1; -} - - -int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - return conn->failed; -} - - -int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - return conn->read_alerts; -} - - -int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - return conn->write_alerts; -} - - -int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, - const struct tls_connection_params *params) -{ - struct tls_global *global = tls_ctx; - ALG_ID algs[1]; - SECURITY_STATUS status; - TimeStamp ts_expiry; - - if (conn == NULL) - return -1; - - if (global->my_cert_store == NULL && - (global->my_cert_store = CertOpenSystemStore(0, TEXT("MY"))) == - NULL) { - wpa_printf(MSG_ERROR, "%s: CertOpenSystemStore failed - 0x%x", - __func__, (unsigned int) GetLastError()); - return -1; - } - - os_memset(&conn->schannel_cred, 0, sizeof(conn->schannel_cred)); - conn->schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; - conn->schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1; - algs[0] = CALG_RSA_KEYX; - conn->schannel_cred.cSupportedAlgs = 1; - conn->schannel_cred.palgSupportedAlgs = algs; - conn->schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; -#ifdef UNICODE - status = global->sspi->AcquireCredentialsHandleW( - NULL, UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, - &conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry); -#else /* UNICODE */ - status = global->sspi->AcquireCredentialsHandleA( - NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL, - &conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry); -#endif /* UNICODE */ - if (status != SEC_E_OK) { - wpa_printf(MSG_DEBUG, "%s: AcquireCredentialsHandleA failed - " - "0x%x", __func__, (unsigned int) status); - return -1; - } - - return 0; -} - - -unsigned int tls_capabilities(void *tls_ctx) -{ - return 0; -} - - -int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, - int tls_ia) -{ - return -1; -} - - -int tls_connection_ia_send_phase_finished(void *tls_ctx, - struct tls_connection *conn, - int final, - u8 *out_data, size_t out_len) -{ - return -1; -} - - -int tls_connection_ia_final_phase_finished(void *tls_ctx, - struct tls_connection *conn) -{ - return -1; -} - - -int tls_connection_ia_permute_inner_secret(void *tls_ctx, - struct tls_connection *conn, - const u8 *key, size_t key_len) -{ - return -1; -} diff --git a/contrib/hostapd/src/drivers/Apple80211.h b/contrib/hostapd/src/drivers/Apple80211.h deleted file mode 100644 index 2a612e7308..0000000000 --- a/contrib/hostapd/src/drivers/Apple80211.h +++ /dev/null @@ -1,156 +0,0 @@ -#ifndef APPLE80211_H -#define APPLE80211_H - -/* - * Apple80211 framework definitions - * This is an undocumented interface and the definitions here are based on - * information from MacStumbler (http://www.macstumbler.com/Apple80211.h) and - * whatever related information can be found with google and experiments ;-). - */ - -typedef struct __WirelessRef *WirelessRef; -typedef SInt32 WirelessError; -#define errWirelessNoError 0 - -typedef struct WirelessInfo { - UInt16 link_qual; - UInt16 comms_qual; - UInt16 signal; - UInt16 noise; - UInt16 port_stat; - UInt16 client_mode; - UInt16 res1; - UInt16 power; - UInt16 res2; - UInt8 bssID[6]; - UInt8 ssid[34]; -} WirelessInfo; - -typedef struct WirelessInfo2 { - /* TODO - these are probably not in correct order or complete */ - WirelessInfo info1; - UInt8 macAddress[6]; -} WirelessInfo2; - -typedef struct WirelessNetworkInfo { - UInt16 channel; - UInt16 noise; - UInt16 signal; - UInt8 bssid[6]; - UInt16 beacon_int; - UInt16 capability; - UInt16 ssid_len; - UInt8 ssid[32]; -} WirelessNetworkInfo; - -typedef int wirelessKeyType; /* TODO */ - -int WirelessIsAvailable(void); -WirelessError WirelessAttach(WirelessRef *ref, UInt32 res); -WirelessError WirelessDetach(WirelessRef ref); -WirelessError WirelessPrivate(WirelessRef ref, void *in_ptr, int in_bytes, - void *out_ptr, int out_bytes); -WirelessError WirelessSetEnabled(WirelessRef ref, UInt8 enabled); -WirelessError WirelessGetEnabled(WirelessRef ref, UInt8 *enabled); -WirelessError WirelessSetPower(WirelessRef ref, UInt8 power); -WirelessError WirelessGetPower(WirelessRef ref, UInt8 *power); -WirelessError WirelessGetInfo(WirelessRef ref, WirelessInfo *info); -WirelessError WirelessGetInfo2(WirelessRef ref, WirelessInfo2 *info); -WirelessError WirelessScan(WirelessRef ref, CFArrayRef *results, - UInt32 strip_dups); -WirelessError WirelessScanSplit(WirelessRef ref, CFArrayRef *ap_results, - CFArrayRef *ibss_results, UInt32 strip_dups); -WirelessError WirelessDirectedScan(WirelessRef ref, CFArrayRef *results, - UInt32 strip_dups, CFStringRef ssid); -WirelessError WirelessDirectedScan2(WirelessRef ref, CFDataRef ssid, - UInt32 strip_dups, CFArrayRef *results); -WirelessError WirelessJoin(WirelessRef ref, CFStringRef ssid); -WirelessError WirelessJoinWEP(WirelessRef ref, CFStringRef ssid, - CFStringRef passwd); -WirelessError WirelessJoin8021x(WirelessRef ref, CFStringRef ssid); -/* - * Set WEP key - * ref: wireless reference from WirelessAttach() - * type: ? - * key_idx: 0..3 - * key_len: 13 for WEP-104 or 0 for clearing the key - * key: Pointer to the key or %NULL if key_len = 0 - */ -WirelessError WirelessSetKey(WirelessRef ref, wirelessKeyType type, - int key_idx, int key_len, - const unsigned char *key); -/* - * Set WPA key (e.g., PMK for 4-way handshake) - * ref: wireless reference from WirelessAttach() - * type: 0..4; 1 = PMK - * key_len: 16, 32, or 0 - * key: Pointer to the key or %NULL if key_len = 0 - */ -WirelessError WirelessSetWPAKey(WirelessRef ref, wirelessKeyType type, - int key_len, const unsigned char *key); -WirelessError WirelessAssociate(WirelessRef ref, int type, CFDataRef ssid, - CFStringRef key); -WirelessError WirelessAssociate2(WirelessRef ref, CFDictionaryRef scan_res, - CFStringRef key); -WirelessError WirelessDisassociate(WirelessRef ref); - -/* - * Get a copy of scan results for the given SSID - * The returned dictionary includes following entries: - * beaconInterval: CFNumber(kCFNumberSInt32Type) - * SSID: CFData buffer of the SSID - * isWPA: CFNumber(kCFNumberSInt32Type); 0 = not used, 1 = WPA, -128 = WPA2 - * name: Name of the network (SSID string) - * BSSID: CFData buffer of the BSSID - * channel: CFNumber(kCFNumberSInt32Type) - * signal: CFNumber(kCFNumberSInt32Type) - * appleIE: CFData - * WPSNOPINRequired: CFBoolean - * noise: CFNumber(kCFNumberSInt32Type) - * capability: CFNumber(kCFNumberSInt32Type) - * uniCipher: CFArray of CFNumber(kCFNumberSInt32Type) - * appleIE_Version: CFNumber(kCFNumberSInt32Type) - * appleIE_Robust: CFBoolean - * WPSConfigured: CFBoolean - * scanWasDirected: CFBoolean - * appleIE_Product: CFNumber(kCFNumberSInt32Type) - * authModes: CFArray of CFNumber(kCFNumberSInt32Type) - * multiCipher: CFNumber(kCFNumberSInt32Type) - */ -CFDictionaryRef WirelessSafeDirectedScanCopy(WirelessRef ref, CFDataRef ssid); - -/* - * Get information about the current association - * The returned dictionary includes following entries: - * keyData: CFData buffer of the key (e.g., 32-octet PSK) - * multiCipher: CFNumber(kCFNumberSInt32Type); 0 = none, 5 = CCMP? - * channel: CFNumber(kCFNumberSInt32Type) - * isIBSS: CFBoolean - * authMode: CFNumber(kCFNumberSInt32Type); 2 = WPA-Personal; 3 = open, - * 129 = WPA2-Enterprise - * isWPA: CFNumber(kCFNumberSInt32Type); 0 = not used, 1 = WPA, -128 == WPA2 - * SSID: CFData buffer of the SSID - * cipherMode: CFNumber(kCFNumberSInt32Type); 0 = none, 4 = CCMP? - */ -CFDictionaryRef WirelessGetAssociationInfo(WirelessRef ref); - -WirelessError WirelessConfigure(WirelessRef ref); - -/* - * Get ASP information - * The returned dictionary includes following entries: - * Version: version number (e.g., 3.0) - * Channel: channel (e.g., 1) - * Vendor: vendor (e.g., 2) - */ -CFDictionaryRef WirelessGetInfoASP(void); - -/* - * Get a copy of the interface dictionary - * The returned dictionary has a key,value pairs for wireless interfaces. - * The key is the interface name and the value is the driver identifier, e.g., - * en1: com.apple.driver.AirPort.Atheros - */ -CFDictionaryRef WirelessCopyInterfaceDict(void); - -#endif /* APPLE80211_H */ diff --git a/contrib/hostapd/src/drivers/MobileApple80211.c b/contrib/hostapd/src/drivers/MobileApple80211.c deleted file mode 100644 index ce004fe4c9..0000000000 --- a/contrib/hostapd/src/drivers/MobileApple80211.c +++ /dev/null @@ -1,189 +0,0 @@ -#include "includes.h" -#include - -#include "common.h" - -#include -#include "MobileApple80211.h" - -/* - * Code for dynamically loading Apple80211 functions from Aeropuerto to avoid - * having to link with full Preferences.framework. - */ - -static void *aeropuerto = NULL; - - -int _Apple80211Initialized(void) -{ - return aeropuerto ? 1 : 0; -} - - -static int (*__Apple80211Open)(Apple80211Ref *ctx) = NULL; - -int Apple80211Open(Apple80211Ref *ctx) -{ - return __Apple80211Open(ctx); -} - - -static int (*__Apple80211Close)(Apple80211Ref ctx) = NULL; - -int Apple80211Close(Apple80211Ref ctx) -{ - return __Apple80211Close(ctx); -} - - -static int (*__Apple80211GetIfListCopy)(Apple80211Ref handle, CFArrayRef *list) - = NULL; - -int Apple80211GetIfListCopy(Apple80211Ref handle, CFArrayRef *list) -{ - return __Apple80211GetIfListCopy(handle, list); -} - - -static int (*__Apple80211BindToInterface)(Apple80211Ref handle, - CFStringRef interface) = NULL; - -int Apple80211BindToInterface(Apple80211Ref handle, - CFStringRef interface) -{ - return __Apple80211BindToInterface(handle, interface); -} - - -static int (*__Apple80211GetInterfaceNameCopy)(Apple80211Ref handle, - CFStringRef *name) = NULL; - -int Apple80211GetInterfaceNameCopy(Apple80211Ref handle, - CFStringRef *name) -{ - return __Apple80211GetInterfaceNameCopy(handle, name); -} - - -static int (*__Apple80211GetInfoCopy)(Apple80211Ref handle, - CFDictionaryRef *info) = NULL; - -int Apple80211GetInfoCopy(Apple80211Ref handle, - CFDictionaryRef *info) -{ - return __Apple80211GetInfoCopy(handle, info); -} - - -static int (*__Apple80211GetPower)(Apple80211Ref handle, char *pwr) = NULL; - -int Apple80211GetPower(Apple80211Ref handle, char *pwr) -{ - return __Apple80211GetPower(handle, pwr); -} - - -static int (*__Apple80211SetPower)(Apple80211Ref handle, char pwr) = NULL; - -int Apple80211SetPower(Apple80211Ref handle, char pwr) -{ - return __Apple80211SetPower(handle, pwr); -} - - -static int (*__Apple80211Scan)(Apple80211Ref handle, CFArrayRef *list, - CFDictionaryRef parameters) = NULL; - -int Apple80211Scan(Apple80211Ref handle, CFArrayRef *list, - CFDictionaryRef parameters) -{ - return __Apple80211Scan(handle, list, parameters); -} - - -static int (*__Apple80211Associate)(Apple80211Ref handle, CFDictionaryRef bss, - CFStringRef password) = NULL; - -int Apple80211Associate(Apple80211Ref handle, CFDictionaryRef bss, - CFStringRef password) -{ - return __Apple80211Associate(handle, bss, password); -} - - -static int (*__Apple80211AssociateAndCopyInfo)(Apple80211Ref handle, - CFDictionaryRef bss, - CFStringRef password, - CFDictionaryRef *info) = - NULL; - -int Apple80211AssociateAndCopyInfo(Apple80211Ref handle, CFDictionaryRef bss, - CFStringRef password, CFDictionaryRef *info) -{ - return __Apple80211AssociateAndCopyInfo(handle, bss, password, info); -} - - -static int (*__Apple80211CopyValue)(Apple80211Ref handle, int field, - CFDictionaryRef arg2, void *value) = NULL; - -int Apple80211CopyValue(Apple80211Ref handle, int field, CFDictionaryRef arg2, - void *value) -{ - return __Apple80211CopyValue(handle, field, arg2, value); -} - - -#define DLSYM(s) \ -do { \ - __ ## s = dlsym(aeropuerto, #s); \ - if (__ ## s == NULL) { \ - wpa_printf(MSG_ERROR, "MobileApple80211: Could not resolve " \ - "symbol '" #s "' (%s)", dlerror()); \ - err = 1; \ - } \ -} while (0) - - -__attribute__ ((constructor)) -void _Apple80211_constructor(void) -{ - const char *fname = "/System/Library/SystemConfiguration/" - "Aeropuerto.bundle/Aeropuerto"; - int err = 0; - - aeropuerto = dlopen(fname, RTLD_LAZY); - if (!aeropuerto) { - wpa_printf(MSG_ERROR, "MobileApple80211: Failed to open %s " - "for symbols", fname); - return; - } - - DLSYM(Apple80211Open); - DLSYM(Apple80211Close); - DLSYM(Apple80211GetIfListCopy); - DLSYM(Apple80211BindToInterface); - DLSYM(Apple80211GetInterfaceNameCopy); - DLSYM(Apple80211GetInfoCopy); - DLSYM(Apple80211GetPower); - DLSYM(Apple80211SetPower); - DLSYM(Apple80211Scan); - DLSYM(Apple80211Associate); - DLSYM(Apple80211AssociateAndCopyInfo); - DLSYM(Apple80211CopyValue); - - if (err) { - dlclose(aeropuerto); - aeropuerto = NULL; - } -} - - -__attribute__ ((destructor)) -void _Apple80211_destructor(void) -{ - if (aeropuerto) { - dlclose(aeropuerto); - aeropuerto = NULL; - } -} diff --git a/contrib/hostapd/src/drivers/MobileApple80211.h b/contrib/hostapd/src/drivers/MobileApple80211.h deleted file mode 100644 index 64d439d660..0000000000 --- a/contrib/hostapd/src/drivers/MobileApple80211.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef MOBILEAPPLE80211_H -#define MOBILEAPPLE80211_H - -/* - * MobileApple80211 interface for iPhone/iPod touch - * These functions are available from Aeropuerto. - */ - -struct Apple80211; -typedef struct Apple80211 *Apple80211Ref; - -int Apple80211Open(Apple80211Ref *ctx); -int Apple80211Close(Apple80211Ref ctx); -int Apple80211GetIfListCopy(Apple80211Ref handle, CFArrayRef *list); -int Apple80211BindToInterface(Apple80211Ref handle, - CFStringRef interface); -int Apple80211GetInterfaceNameCopy(Apple80211Ref handle, - CFStringRef *name); -int Apple80211GetInfoCopy(Apple80211Ref handle, - CFDictionaryRef *info); -int Apple80211GetPower(Apple80211Ref handle, char *pwr); -int Apple80211SetPower(Apple80211Ref handle, char pwr); - -/* parameters can be NULL; returns scan results in CFArrayRef *list; - * caller will need to free with CFRelease() */ -int Apple80211Scan(Apple80211Ref handle, CFArrayRef *list, - CFDictionaryRef parameters); - -int Apple80211Associate(Apple80211Ref handle, CFDictionaryRef bss, - CFStringRef password); -int Apple80211AssociateAndCopyInfo(Apple80211Ref handle, CFDictionaryRef bss, - CFStringRef password, - CFDictionaryRef *info); - -enum { - APPLE80211_VALUE_SSID = 1, - APPLE80211_VALUE_BSSID = 9 -}; - -int Apple80211CopyValue(Apple80211Ref handle, int field, CFDictionaryRef arg2, - void *value); - -#endif /* MOBILEAPPLE80211_H */ diff --git a/contrib/hostapd/src/drivers/driver.h b/contrib/hostapd/src/drivers/driver.h deleted file mode 100644 index c2975d2c12..0000000000 --- a/contrib/hostapd/src/drivers/driver.h +++ /dev/null @@ -1,1325 +0,0 @@ -/* - * WPA Supplicant - driver interface definition - * Copyright (c) 2003-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef DRIVER_H -#define DRIVER_H - -#define WPA_SUPPLICANT_DRIVER_VERSION 3 - -#include "defs.h" - -#define AUTH_ALG_OPEN_SYSTEM 0x01 -#define AUTH_ALG_SHARED_KEY 0x02 -#define AUTH_ALG_LEAP 0x04 - -#define IEEE80211_MODE_INFRA 0 -#define IEEE80211_MODE_IBSS 1 - -#define IEEE80211_CAP_ESS 0x0001 -#define IEEE80211_CAP_IBSS 0x0002 -#define IEEE80211_CAP_PRIVACY 0x0010 - -#define SSID_MAX_WPA_IE_LEN 40 -/** - * struct wpa_scan_result - Scan results (old structure) - * @bssid: BSSID - * @ssid: SSID - * @ssid_len: length of the ssid - * @wpa_ie: WPA IE - * @wpa_ie_len: length of the wpa_ie - * @rsn_ie: RSN IE - * @rsn_ie_len: length of the RSN IE - * @freq: frequency of the channel in MHz (e.g., 2412 = channel 1) - * @caps: capability information field in host byte order - * @qual: signal quality - * @noise: noise level - * @level: signal level - * @maxrate: maximum supported rate - * @mdie_present: Whether MDIE was included in Beacon/ProbeRsp frame - * @mdie: Mobility domain identifier IE (IEEE 802.11r MDIE) (starting from - * IE type field) - * @tsf: Timestamp - * - * This structure is used as a generic format for scan results from the - * driver. Each driver interface implementation is responsible for converting - * the driver or OS specific scan results into this format. - * - * This structure is the old data structure used for scan results. It is - * obsoleted by the new struct wpa_scan_res structure and the old version is - * only included for backwards compatibility with existing driver wrapper - * implementations. New implementations are encouraged to implement for struct - * wpa_scan_res. The old structure will be removed at some point. - */ -struct wpa_scan_result { - u8 bssid[ETH_ALEN]; - u8 ssid[32]; - size_t ssid_len; - u8 wpa_ie[SSID_MAX_WPA_IE_LEN]; - size_t wpa_ie_len; - u8 rsn_ie[SSID_MAX_WPA_IE_LEN]; - size_t rsn_ie_len; - int freq; - u16 caps; - int qual; - int noise; - int level; - int maxrate; - int mdie_present; - u8 mdie[5]; - u64 tsf; -}; - - -/** - * struct wpa_scan_res - Scan result for an BSS/IBSS - * @bssid: BSSID - * @freq: frequency of the channel in MHz (e.g., 2412 = channel 1) - * @beacon_int: beacon interval in TUs (host byte order) - * @caps: capability information field in host byte order - * @qual: signal quality - * @noise: noise level - * @level: signal level - * @tsf: Timestamp - * @ie_len: length of the following IE field in octets - * - * This structure is used as a generic format for scan results from the - * driver. Each driver interface implementation is responsible for converting - * the driver or OS specific scan results into this format. - * - * If the driver does not support reporting all IEs, the IE data structure is - * constructed of the IEs that are available. This field will also need to - * include SSID in IE format. All drivers are encouraged to be extended to - * report all IEs to make it easier to support future additions. - */ -struct wpa_scan_res { - u8 bssid[ETH_ALEN]; - int freq; - u16 beacon_int; - u16 caps; - int qual; - int noise; - int level; - u64 tsf; - size_t ie_len; - /* followed by ie_len octets of IEs */ -}; - -/** - * struct wpa_scan_results - Scan results - * @res: Array of pointers to allocated variable length scan result entries - * @num: Number of entries in the scan result array - */ -struct wpa_scan_results { - struct wpa_scan_res **res; - size_t num; -}; - -/** - * struct wpa_interface_info - Network interface information - * @next: Pointer to the next interface or NULL if this is the last one - * @ifname: Interface name that can be used with init() or init2() - * @desc: Human readable adapter description (e.g., vendor/model) or NULL if - * not available - * @drv_name: struct wpa_driver_ops::name (note: unlike other strings, this one - * is not an allocated copy, i.e., get_interfaces() caller will not free - * this) - */ -struct wpa_interface_info { - struct wpa_interface_info *next; - char *ifname; - char *desc; - const char *drv_name; -}; - -/** - * struct wpa_driver_associate_params - Association parameters - * Data for struct wpa_driver_ops::associate(). - */ -struct wpa_driver_associate_params { - /** - * bssid - BSSID of the selected AP - * This can be %NULL, if ap_scan=2 mode is used and the driver is - * responsible for selecting with which BSS to associate. */ - const u8 *bssid; - - /** - * ssid - The selected SSID - */ - const u8 *ssid; - size_t ssid_len; - - /** - * freq - Frequency of the channel the selected AP is using - * Frequency that the selected AP is using (in MHz as - * reported in the scan results) - */ - int freq; - - /** - * wpa_ie - WPA information element for (Re)Association Request - * 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 - * 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 - * convert into EVENT_ASSOCINFO data (see below). - * - * When using WPA2/IEEE 802.11i, wpa_ie is used for RSN IE - * instead. The driver can determine which version is used by - * looking at the first byte of the IE (0xdd for WPA, 0x30 for - * WPA2/RSN). - * - * When using WPS, wpa_ie is used for WPS IE instead of WPA/RSN IE. - */ - const u8 *wpa_ie; - /** - * wpa_ie_len - length of the wpa_ie - */ - size_t wpa_ie_len; - - /* The selected pairwise/group cipher and key management - * suites. These are usually ignored if @wpa_ie is used. */ - wpa_cipher pairwise_suite; - wpa_cipher group_suite; - wpa_key_mgmt key_mgmt_suite; - - /** - * auth_alg - Allowed authentication algorithms - * Bit field of AUTH_ALG_* - */ - int auth_alg; - - /** - * mode - Operation mode (infra/ibss) IEEE80211_MODE_* - */ - int mode; - - /** - * wep_key - WEP keys for static WEP configuration - */ - const u8 *wep_key[4]; - - /** - * wep_key_len - WEP key length for static WEP configuration - */ - size_t wep_key_len[4]; - - /** - * wep_tx_keyidx - WEP TX key index for static WEP configuration - */ - int wep_tx_keyidx; - - /** - * mgmt_frame_protection - IEEE 802.11w management frame protection - */ - enum { - NO_MGMT_FRAME_PROTECTION, - MGMT_FRAME_PROTECTION_OPTIONAL, - MGMT_FRAME_PROTECTION_REQUIRED - } 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. - */ - const char *passphrase; - - /** - * 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. - */ - const u8 *psk; -}; - -/** - * struct wpa_driver_capa - Driver capability information - */ -struct wpa_driver_capa { -#define WPA_DRIVER_CAPA_KEY_MGMT_WPA 0x00000001 -#define WPA_DRIVER_CAPA_KEY_MGMT_WPA2 0x00000002 -#define WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK 0x00000004 -#define WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK 0x00000008 -#define WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE 0x00000010 -#define WPA_DRIVER_CAPA_KEY_MGMT_FT 0x00000020 -#define WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK 0x00000040 - unsigned int key_mgmt; - -#define WPA_DRIVER_CAPA_ENC_WEP40 0x00000001 -#define WPA_DRIVER_CAPA_ENC_WEP104 0x00000002 -#define WPA_DRIVER_CAPA_ENC_TKIP 0x00000004 -#define WPA_DRIVER_CAPA_ENC_CCMP 0x00000008 - unsigned int enc; - -#define WPA_DRIVER_AUTH_OPEN 0x00000001 -#define WPA_DRIVER_AUTH_SHARED 0x00000002 -#define WPA_DRIVER_AUTH_LEAP 0x00000004 - unsigned int auth; - -/* Driver generated WPA/RSN IE */ -#define WPA_DRIVER_FLAGS_DRIVER_IE 0x00000001 -#define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC 0x00000002 -#define WPA_DRIVER_FLAGS_USER_SPACE_MLME 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 - unsigned int flags; -}; - - -#define WPA_CHAN_W_SCAN 0x00000001 -#define WPA_CHAN_W_ACTIVE_SCAN 0x00000002 -#define WPA_CHAN_W_IBSS 0x00000004 - -struct wpa_channel_data { - short chan; /* channel number (IEEE 802.11) */ - short freq; /* frequency in MHz */ - int flag; /* flag for user space use (WPA_CHAN_*) */ -}; - -#define WPA_RATE_ERP 0x00000001 -#define WPA_RATE_BASIC 0x00000002 -#define WPA_RATE_PREAMBLE2 0x00000004 -#define WPA_RATE_SUPPORTED 0x00000010 -#define WPA_RATE_OFDM 0x00000020 -#define WPA_RATE_CCK 0x00000040 -#define WPA_RATE_MANDATORY 0x00000100 - -struct wpa_rate_data { - int rate; /* rate in 100 kbps */ - int flags; /* WPA_RATE_ flags */ -}; - -typedef enum { - WPA_MODE_IEEE80211B, - WPA_MODE_IEEE80211G, - WPA_MODE_IEEE80211A, - NUM_WPA_MODES -} wpa_hw_mode; - -struct wpa_hw_modes { - wpa_hw_mode mode; - int num_channels; - struct wpa_channel_data *channels; - int num_rates; - struct wpa_rate_data *rates; -}; - - -struct ieee80211_rx_status { - int channel; - int ssi; -}; - - -/** - * struct wpa_driver_ops - Driver interface API definition - * - * This structure defines the API that each driver interface needs to implement - * for core wpa_supplicant code. All driver specific functionality is captured - * in this wrapper. - */ -struct wpa_driver_ops { - /** Name of the driver interface */ - const char *name; - /** One line description of the driver interface */ - const char *desc; - - /** - * get_bssid - Get the current BSSID - * @priv: private driver interface data - * @bssid: buffer for BSSID (ETH_ALEN = 6 bytes) - * - * Returns: 0 on success, -1 on failure - * - * Query kernel driver for the current BSSID and copy it to bssid. - * Setting bssid to 00:00:00:00:00:00 is recommended if the STA is not - * associated. - */ - int (*get_bssid)(void *priv, u8 *bssid); - - /** - * get_ssid - Get the current SSID - * @priv: private driver interface data - * @ssid: buffer for SSID (at least 32 bytes) - * - * Returns: Length of the SSID on success, -1 on failure - * - * Query kernel driver for the current SSID and copy it to ssid. - * Returning zero is recommended if the STA is not associated. - * - * Note: SSID is an array of octets, i.e., it is not nul terminated and - * can, at least in theory, contain control characters (including nul) - * and as such, should be processed as binary data, not a printable - * string. - */ - int (*get_ssid)(void *priv, u8 *ssid); - - /** - * set_wpa - Enable/disable WPA support (OBSOLETE) - * @priv: private driver interface data - * @enabled: 1 = enable, 0 = disable - * - * Returns: 0 on success, -1 on failure - * - * Note: This function is included for backwards compatibility. This is - * called only just after init and just before deinit, so these - * functions can be used to implement same functionality and the driver - * interface need not define this function. - * - * Configure the kernel driver to enable/disable WPA support. This may - * be empty function, if WPA support is always enabled. Common - * configuration items are WPA IE (clearing it when WPA support is - * disabled), Privacy flag configuration for capability field (note: - * this the value need to set in associate handler to allow plaintext - * mode to be used) when trying to associate with, roaming mode (can - * allow wpa_supplicant to control roaming if ap_scan=1 is used; - * however, drivers can also implement roaming if desired, especially - * ap_scan=2 mode is used for this). - */ - int (*set_wpa)(void *priv, int enabled); - - /** - * set_key - Configure encryption key - * @priv: private driver interface data - * @alg: encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP, - * %WPA_ALG_TKIP, %WPA_ALG_CCMP, %WPA_ALG_IGTK, %WPA_ALG_PMK); - * %WPA_ALG_NONE clears the key. - * @addr: address of the peer STA or ff:ff:ff:ff:ff:ff for - * broadcast/default keys - * @key_idx: key index (0..3), usually 0 for unicast keys; 0..4095 for - * IGTK - * @set_tx: configure this key as the default Tx key (only used when - * driver does not support separate unicast/individual key - * @seq: sequence number/packet number, seq_len octets, the next - * packet number to be used for in replay protection; configured - * for Rx keys (in most cases, this is only used with broadcast - * keys and set to zero for unicast keys) - * @seq_len: length of the seq, depends on the algorithm: - * TKIP: 6 octets, CCMP: 6 octets, IGTK: 6 octets - * @key: key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key, - * 8-byte Rx Mic Key - * @key_len: length of the key buffer in octets (WEP: 5 or 13, - * TKIP: 32, CCMP: 16, IGTK: 16) - * - * Returns: 0 on success, -1 on failure - * - * Configure the given key for the kernel driver. If the driver - * supports separate individual keys (4 default keys + 1 individual), - * addr can be used to determine whether the key is default or - * individual. If only 4 keys are supported, the default key with key - * index 0 is used as the individual key. STA must be configured to use - * it as the default Tx key (set_tx is set) and accept Rx for all the - * key indexes. In most cases, WPA uses only key indexes 1 and 2 for - * broadcast keys, so key index 0 is available for this kind of - * configuration. - * - * Please note that TKIP keys include separate TX and RX MIC keys and - * some drivers may expect them in different order than wpa_supplicant - * is using. If the TX/RX keys are swapped, all TKIP encrypted packets - * will tricker Michael MIC errors. This can be fixed by changing the - * order of MIC keys by swapping te bytes 16..23 and 24..31 of the key - * in driver_*.c set_key() implementation, see driver_ndis.c for an - * example on how this can be done. - */ - int (*set_key)(void *priv, wpa_alg alg, const u8 *addr, - int key_idx, int set_tx, const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len); - - /** - * init - Initialize driver interface - * @ctx: context to be used when calling wpa_supplicant functions, - * e.g., wpa_supplicant_event() - * @ifname: interface name, e.g., wlan0 - * - * Returns: Pointer to private data, %NULL on failure - * - * Initialize driver interface, including event processing for kernel - * driver events (e.g., associated, scan results, Michael MIC failure). - * This function can allocate a private configuration data area for - * @ctx, file descriptor, interface name, etc. information that may be - * needed in future driver operations. If this is not used, non-NULL - * value will need to be returned because %NULL is used to indicate - * failure. The returned value will be used as 'void *priv' data for - * all other driver_ops functions. - * - * The main event loop (eloop.c) of wpa_supplicant can be used to - * register callback for read sockets (eloop_register_read_sock()). - * - * See below for more information about events and - * wpa_supplicant_event() function. - */ - void * (*init)(void *ctx, const char *ifname); - - /** - * deinit - Deinitialize driver interface - * @priv: private driver interface data from init() - * - * Shut down driver interface and processing of driver events. Free - * private data buffer if one was allocated in init() handler. - */ - void (*deinit)(void *priv); - - /** - * set_param - Set driver configuration parameters - * @priv: private driver interface data from init() - * @param: driver specific configuration parameters - * - * Returns: 0 on success, -1 on failure - * - * Optional handler for notifying driver interface about configuration - * parameters (driver_param). - */ - int (*set_param)(void *priv, const char *param); - - /** - * set_countermeasures - Enable/disable TKIP countermeasures - * @priv: private driver interface data - * @enabled: 1 = countermeasures enabled, 0 = disabled - * - * Returns: 0 on success, -1 on failure - * - * Configure TKIP countermeasures. When these are enabled, the driver - * should drop all received and queued frames that are using TKIP. - */ - int (*set_countermeasures)(void *priv, int enabled); - - /** - * set_drop_unencrypted - Enable/disable unencrypted frame filtering - * @priv: private driver interface data - * @enabled: 1 = unencrypted Tx/Rx frames will be dropped, 0 = disabled - * - * Returns: 0 on success, -1 on failure - * - * Configure the driver to drop all non-EAPOL frames (both receive and - * transmit paths). Unencrypted EAPOL frames (ethertype 0x888e) must - * still be allowed for key negotiation. - */ - int (*set_drop_unencrypted)(void *priv, int enabled); - - /** - * scan - Request the driver to initiate scan - * @priv: private driver interface data - * @ssid: specific SSID to scan for (ProbeReq) or %NULL to scan for - * all SSIDs (either active scan with broadcast SSID or passive - * scan - * @ssid_len: length of the SSID - * - * Returns: 0 on success, -1 on failure - * - * Once the scan results are ready, the driver should report scan - * results event for wpa_supplicant which will eventually request the - * results with wpa_driver_get_scan_results(). - */ - int (*scan)(void *priv, const u8 *ssid, size_t ssid_len); - - /** - * get_scan_results - Fetch the latest scan results (old version) - * @priv: private driver interface data - * @results: pointer to buffer for scan results - * @max_size: maximum number of entries (buffer size) - * - * Returns: Number of scan result entries used on success, -1 on - * failure - * - * If scan results include more than max_size BSSes, max_size will be - * returned and the remaining entries will not be included in the - * buffer. - * - * This function is depracated. New driver wrapper implementations - * should implement support for get_scan_results2(). - */ - int (*get_scan_results)(void *priv, - struct wpa_scan_result *results, - size_t max_size); - - /** - * deauthenticate - Request driver to deauthenticate - * @priv: private driver interface data - * @addr: peer address (BSSID of the AP) - * @reason_code: 16-bit reason code to be sent in the deauthentication - * frame - * - * Returns: 0 on success, -1 on failure - */ - int (*deauthenticate)(void *priv, const u8 *addr, int reason_code); - - /** - * disassociate - Request driver to disassociate - * @priv: private driver interface data - * @addr: peer address (BSSID of the AP) - * @reason_code: 16-bit reason code to be sent in the disassociation - * frame - * - * Returns: 0 on success, -1 on failure - */ - int (*disassociate)(void *priv, const u8 *addr, int reason_code); - - /** - * associate - Request driver to associate - * @priv: private driver interface data - * @params: association parameters - * - * Returns: 0 on success, -1 on failure - */ - int (*associate)(void *priv, - struct wpa_driver_associate_params *params); - - /** - * set_auth_alg - Set IEEE 802.11 authentication algorithm - * @priv: private driver interface data - * @auth_alg: bit field of AUTH_ALG_* - * - * If the driver supports more than one authentication algorithm at the - * same time, it should configure all supported algorithms. If not, one - * algorithm needs to be selected arbitrarily. Open System - * authentication should be ok for most cases and it is recommended to - * be used if other options are not supported. Static WEP configuration - * may also use Shared Key authentication and LEAP requires its own - * algorithm number. For LEAP, user can make sure that only one - * algorithm is used at a time by configuring LEAP as the only - * supported EAP method. This information is also available in - * associate() params, so set_auth_alg may not be needed in case of - * most drivers. - * - * Returns: 0 on success, -1 on failure - */ - int (*set_auth_alg)(void *priv, int auth_alg); - - /** - * 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 - * - * 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. - * - * 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 - * in the driver. If the driver uses wpa_ie from wpa_supplicant, this - * 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); - - /** - * 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 - * - * Returns: 0 on success, -1 on failure - * - * This function is called when the supplicant drops a PMKSA cache - * entry for any reason. - * - * 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 - * between the driver and wpa_supplicant. If the driver uses wpa_ie - * from wpa_supplicant, this driver_ops function does not need to be - * 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); - - /** - * flush_pmkid - Flush PMKSA cache - * @priv: private driver interface data - * - * Returns: 0 on success, -1 on failure - * - * This function is called when the supplicant drops all PMKSA cache - * entries for any reason. - * - * 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 - * between the driver and wpa_supplicant. If the driver uses wpa_ie - * from wpa_supplicant, this driver_ops function does not need to be - * implemented. Likewise, if the driver does not support WPA, this - * function is not needed. - */ - int (*flush_pmkid)(void *priv); - - /** - * get_capa - Get driver capabilities - * @priv: private driver interface data - * - * Returns: 0 on success, -1 on failure - * - * Get driver/firmware/hardware capabilities. - */ - int (*get_capa)(void *priv, struct wpa_driver_capa *capa); - - /** - * poll - Poll driver for association information - * @priv: private driver interface data - * - * This is an option callback that can be used when the driver does not - * provide event mechanism for association events. This is called when - * receiving WPA EAPOL-Key messages that require association - * information. The driver interface is supposed to generate associnfo - * event before returning from this callback function. In addition, the - * driver interface should generate an association event after having - * sent out associnfo. - */ - void (*poll)(void *priv); - - /** - * get_ifname - Get interface name - * @priv: private driver interface data - * - * Returns: Pointer to the interface name. This can differ from the - * interface name used in init() call. Init() is called first. - * - * This optional function can be used to allow the driver interface to - * replace the interface name with something else, e.g., based on an - * interface mapping from a more descriptive name. - */ - const char * (*get_ifname)(void *priv); - - /** - * get_mac_addr - Get own MAC address - * @priv: private driver interface data - * - * Returns: Pointer to own MAC address or %NULL on failure - * - * This optional function can be used to get the own MAC address of the - * device from the driver interface code. This is only needed if the - * l2_packet implementation for the OS does not provide easy access to - * a MAC address. */ - const u8 * (*get_mac_addr)(void *priv); - - /** - * send_eapol - Optional function for sending EAPOL packets - * @priv: private driver interface data - * @dest: Destination MAC address - * @proto: Ethertype - * @data: EAPOL packet starting with IEEE 802.1X header - * @data_len: Size of the EAPOL packet - * - * Returns: 0 on success, -1 on failure - * - * This optional function can be used to override l2_packet operations - * with driver specific functionality. If this function pointer is set, - * l2_packet module is not used at all and the driver interface code is - * responsible for receiving and sending all EAPOL packets. The - * received EAPOL packets are sent to core code by calling - * wpa_supplicant_rx_eapol(). The driver interface is required to - * implement get_mac_addr() handler if send_eapol() is used. - */ - int (*send_eapol)(void *priv, const u8 *dest, u16 proto, - const u8 *data, size_t data_len); - - /** - * set_operstate - Sets device operating state to DORMANT or UP - * @priv: private driver interface data - * @state: 0 = dormant, 1 = up - * Returns: 0 on success, -1 on failure - * - * This is an optional function that can be used on operating systems - * that support a concept of controlling network device state from user - * space applications. This function, if set, gets called with - * state = 1 when authentication has been completed and with state = 0 - * when connection is lost. - */ - int (*set_operstate)(void *priv, int state); - - /** - * mlme_setprotection - MLME-SETPROTECTION.request primitive - * @priv: Private driver interface data - * @addr: Address of the station for which to set protection (may be - * %NULL for group keys) - * @protect_type: MLME_SETPROTECTION_PROTECT_TYPE_* - * @key_type: MLME_SETPROTECTION_KEY_TYPE_* - * Returns: 0 on success, -1 on failure - * - * This is an optional function that can be used to set the driver to - * require protection for Tx and/or Rx frames. This uses the layer - * interface defined in IEEE 802.11i-2004 clause 10.3.22.1 - * (MLME-SETPROTECTION.request). Many drivers do not use explicit - * set protection operation; instead, they set protection implicitly - * based on configured keys. - */ - int (*mlme_setprotection)(void *priv, const u8 *addr, int protect_type, - int key_type); - - /** - * get_hw_feature_data - Get hardware support data (channels and rates) - * @priv: Private driver interface data - * @num_modes: Variable for returning the number of returned modes - * flags: Variable for returning hardware feature flags - * Returns: Pointer to allocated hardware data on success or %NULL on - * failure. Caller is responsible for freeing this. - * - * This function is only needed for drivers that export MLME - * (management frame processing) to wpa_supplicant. - */ - struct wpa_hw_modes * (*get_hw_feature_data)(void *priv, - u16 *num_modes, - u16 *flags); - - /** - * set_channel - Set channel - * @priv: Private driver interface data - * @phymode: WPA_MODE_IEEE80211B, .. - * @chan: IEEE 802.11 channel number - * @freq: Frequency of the channel in MHz - * Returns: 0 on success, -1 on failure - * - * This function is only needed for drivers that export MLME - * (management frame processing) to wpa_supplicant. - */ - int (*set_channel)(void *priv, wpa_hw_mode phymode, int chan, - int freq); - - /** - * set_ssid - Set SSID - * @priv: Private driver interface data - * @ssid: SSID - * @ssid_len: SSID length - * Returns: 0 on success, -1 on failure - * - * This function is only needed for drivers that export MLME - * (management frame processing) to wpa_supplicant. - */ - int (*set_ssid)(void *priv, const u8 *ssid, size_t ssid_len); - - /** - * set_bssid - Set BSSID - * @priv: Private driver interface data - * @bssid: BSSID - * Returns: 0 on success, -1 on failure - * - * This function is only needed for drivers that export MLME - * (management frame processing) to wpa_supplicant. - */ - int (*set_bssid)(void *priv, const u8 *bssid); - - /** - * send_mlme - Send management frame from MLME - * @priv: Private driver interface data - * @data: IEEE 802.11 management frame with IEEE 802.11 header - * @data_len: Size of the management frame - * Returns: 0 on success, -1 on failure - * - * This function is only needed for drivers that export MLME - * (management frame processing) to wpa_supplicant. - */ - int (*send_mlme)(void *priv, const u8 *data, size_t data_len); - - /** - * mlme_add_sta - Add a STA entry into the driver/netstack - * @priv: Private driver interface data - * @addr: MAC address of the STA (e.g., BSSID of the AP) - * @supp_rates: Supported rate set (from (Re)AssocResp); in IEEE 802.11 - * format (one octet per rate, 1 = 0.5 Mbps) - * @supp_rates_len: Number of entries in supp_rates - * Returns: 0 on success, -1 on failure - * - * This function is only needed for drivers that export MLME - * (management frame processing) to wpa_supplicant. When the MLME code - * completes association with an AP, this function is called to - * configure the driver/netstack with a STA entry for data frame - * processing (TX rate control, encryption/decryption). - */ - int (*mlme_add_sta)(void *priv, const u8 *addr, const u8 *supp_rates, - size_t supp_rates_len); - - /** - * mlme_remove_sta - Remove a STA entry from the driver/netstack - * @priv: Private driver interface data - * @addr: MAC address of the STA (e.g., BSSID of the AP) - * Returns: 0 on success, -1 on failure - * - * This function is only needed for drivers that export MLME - * (management frame processing) to wpa_supplicant. - */ - int (*mlme_remove_sta)(void *priv, const u8 *addr); - - /** - * update_ft_ies - Update FT (IEEE 802.11r) IEs - * @priv: Private driver interface data - * @md: Mobility domain (2 octets) (also included inside ies) - * @ies: FT IEs (MDIE, FTIE, ...) or %NULL to remove IEs - * @ies_len: Length of FT IEs in bytes - * Returns: 0 on success, -1 on failure - * - * The supplicant uses this callback to let the driver know that keying - * material for FT is available and that the driver can use the - * provided IEs in the next message in FT authentication sequence. - * - * This function is only needed for driver that support IEEE 802.11r - * (Fast BSS Transition). - */ - int (*update_ft_ies)(void *priv, const u8 *md, const u8 *ies, - size_t ies_len); - - /** - * send_ft_action - Send FT Action frame (IEEE 802.11r) - * @priv: Private driver interface data - * @action: Action field value - * @target_ap: Target AP address - * @ies: FT IEs (MDIE, FTIE, ...) (FT Request action frame body) - * @ies_len: Length of FT IEs in bytes - * Returns: 0 on success, -1 on failure - * - * The supplicant uses this callback to request the driver to transmit - * an FT Action frame (action category 6) for over-the-DS fast BSS - * transition. - */ - int (*send_ft_action)(void *priv, u8 action, const u8 *target_ap, - const u8 *ies, size_t ies_len); - - /** - * get_scan_results2 - Fetch the latest scan results - * @priv: private driver interface data - * - * Returns: Allocated buffer of scan results (caller is responsible for - * freeing the data structure) on success, NULL on failure - */ - struct wpa_scan_results * (*get_scan_results2)(void *priv); - - /** - * set_probe_req_ie - Set information element(s) for Probe Request - * @priv: private driver interface data - * @ies: Information elements to append or %NULL to remove extra IEs - * @ies_len: Length of the IE buffer in octets - * Returns: 0 on success, -1 on failure - */ - int (*set_probe_req_ie)(void *priv, const u8 *ies, size_t ies_len); - - /** - * set_mode - Request driver to set the operating mode - * @priv: private driver interface data - * @mode: Operation mode (infra/ibss) IEEE80211_MODE_* - * - * This handler will be called before any key configuration and call to - * associate() handler in order to allow the operation mode to be - * configured as early as possible. This information is also available - * in associate() params and as such, some driver wrappers may not need - * to implement set_mode() handler. - * Returns: 0 on success, -1 on failure - */ - int (*set_mode)(void *priv, int mode); - - /** - * set_country - Set country - * @priv: Private driver interface data - * @alpha2: country to which to switch to - * Returns: 0 on success, -1 on failure - * - * This function is for drivers which support some form - * of setting a regulatory domain. - */ - int (*set_country)(void *priv, const char *alpha2); - - /** - * global_init - Global driver initialization - * Returns: Pointer to private data (global), %NULL on failure - * - * This optional function is called to initialize the driver wrapper - * for global data, i.e., data that applies to all interfaces. If this - * function is implemented, global_deinit() will also need to be - * implemented to free the private data. The driver will also likely - * use init2() function instead of init() to get the pointer to global - * data available to per-interface initializer. - */ - void * (*global_init)(void); - - /** - * global_deinit - Global driver deinitialization - * @priv: private driver global data from global_init() - * - * Terminate any global driver related functionality and free the - * global data structure. - */ - void (*global_deinit)(void *priv); - - /** - * init2 - Initialize driver interface (with global data) - * @ctx: context to be used when calling wpa_supplicant functions, - * e.g., wpa_supplicant_event() - * @ifname: interface name, e.g., wlan0 - * @global_priv: private driver global data from global_init() - * Returns: Pointer to private data, %NULL on failure - * - * This function can be used instead of init() if the driver wrapper - * uses global data. - */ - void * (*init2)(void *ctx, const char *ifname, void *global_priv); - - /** - * get_interfaces - Get information about available interfaces - * @global_priv: private driver global data from global_init() - * Returns: Allocated buffer of interface information (caller is - * responsible for freeing the data structure) on success, NULL on - * failure - */ - struct wpa_interface_info * (*get_interfaces)(void *global_priv); -}; - -/* Function to check whether a driver is for wired connections */ -static inline int IS_WIRED(const struct wpa_driver_ops *drv) -{ - return os_strcmp(drv->name, "wired") == 0 || - os_strcmp(drv->name, "roboswitch") == 0; -} - -/** - * enum wpa_event_type - Event type for wpa_supplicant_event() calls - */ -typedef enum wpa_event_type { - /** - * EVENT_ASSOC - Association completed - * - * This event needs to be delivered when the driver completes IEEE - * 802.11 association or reassociation successfully. - * wpa_driver_ops::get_bssid() is expected to provide the current BSSID - * after this event has been generated. In addition, optional - * EVENT_ASSOCINFO may be generated just before EVENT_ASSOC to provide - * more information about the association. If the driver interface gets - * both of these events at the same time, it can also include the - * assoc_info data in EVENT_ASSOC call. - */ - EVENT_ASSOC, - - /** - * EVENT_DISASSOC - Association lost - * - * This event should be called when association is lost either due to - * receiving deauthenticate or disassociate frame from the AP or when - * sending either of these frames to the current AP. - */ - EVENT_DISASSOC, - - /** - * EVENT_MICHAEL_MIC_FAILURE - Michael MIC (TKIP) detected - * - * This event must be delivered when a Michael MIC error is detected by - * the local driver. Additional data for event processing is - * provided with union wpa_event_data::michael_mic_failure. This - * information is used to request new encyption key and to initiate - * TKIP countermeasures if needed. - */ - EVENT_MICHAEL_MIC_FAILURE, - - /** - * EVENT_SCAN_RESULTS - Scan results available - * - * This event must be called whenever scan results are available to be - * fetched with struct wpa_driver_ops::get_scan_results(). This event - * is expected to be used some time after struct wpa_driver_ops::scan() - * is called. If the driver provides an unsolicited event when the scan - * has been completed, this event can be used to trigger - * EVENT_SCAN_RESULTS call. If such event is not available from the - * driver, the driver wrapper code is expected to use a registered - * timeout to generate EVENT_SCAN_RESULTS call after the time that the - * scan is expected to be completed. - */ - EVENT_SCAN_RESULTS, - - /** - * EVENT_ASSOCINFO - Report optional extra information for association - * - * This event can be used to report extra association information for - * EVENT_ASSOC processing. This extra information includes IEs from - * association frames and Beacon/Probe Response frames in union - * wpa_event_data::assoc_info. EVENT_ASSOCINFO must be send just before - * EVENT_ASSOC. Alternatively, the driver interface can include - * assoc_info data in the EVENT_ASSOC call if it has all the - * information available at the same point. - */ - EVENT_ASSOCINFO, - - /** - * EVENT_INTERFACE_STATUS - Report interface status changes - * - * This optional event can be used to report changes in interface - * status (interface added/removed) using union - * wpa_event_data::interface_status. This can be used to trigger - * wpa_supplicant to stop and re-start processing for the interface, - * e.g., when a cardbus card is ejected/inserted. - */ - EVENT_INTERFACE_STATUS, - - /** - * EVENT_PMKID_CANDIDATE - Report a candidate AP for pre-authentication - * - * This event can be used to inform wpa_supplicant about candidates for - * RSN (WPA2) pre-authentication. If wpa_supplicant is not responsible - * for scan request (ap_scan=2 mode), this event is required for - * pre-authentication. If wpa_supplicant is performing scan request - * (ap_scan=1), this event is optional since scan results can be used - * to add pre-authentication candidates. union - * wpa_event_data::pmkid_candidate is used to report the BSSID of the - * candidate and priority of the candidate, e.g., based on the signal - * strength, in order to try to pre-authenticate first with candidates - * that are most likely targets for re-association. - * - * EVENT_PMKID_CANDIDATE can be called whenever the driver has updates - * on the candidate list. In addition, it can be called for the current - * AP and APs that have existing PMKSA cache entries. wpa_supplicant - * will automatically skip pre-authentication in cases where a valid - * PMKSA exists. When more than one candidate exists, this event should - * be generated once for each candidate. - * - * Driver will be notified about successful pre-authentication with - * struct wpa_driver_ops::add_pmkid() calls. - */ - 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_FT_RESPONSE - Report FT (IEEE 802.11r) response IEs - * - * The driver is expected to report the received FT IEs from - * FT authentication sequence from the AP. The FT IEs are included in - * the extra information in union wpa_event_data::ft_ies. - */ - EVENT_FT_RESPONSE -} wpa_event_type; - - -/** - * union wpa_event_data - Additional data for wpa_supplicant_event() calls - */ -union wpa_event_data { - /** - * struct assoc_info - Data for EVENT_ASSOC and EVENT_ASSOCINFO events - * - * This structure is optional for EVENT_ASSOC calls and required for - * EVENT_ASSOCINFO calls. By using EVENT_ASSOC with this data, the - * driver interface does not need to generate separate EVENT_ASSOCINFO - * calls. - */ - struct assoc_info { - /** - * req_ies - (Re)Association Request IEs - * - * If the driver generates WPA/RSN IE, this event data must be - * returned for WPA handshake to have needed information. If - * wpa_supplicant-generated WPA/RSN IE is used, this - * information event is optional. - * - * This should start with the first IE (fixed fields before IEs - * are not included). - */ - u8 *req_ies; - - /** - * req_ies_len - Length of req_ies in bytes - */ - size_t req_ies_len; - - /** - * resp_ies - (Re)Association Response IEs - * - * Optional association data from the driver. This data is not - * required WPA, but may be useful for some protocols and as - * such, should be reported if this is available to the driver - * interface. - * - * This should start with the first IE (fixed fields before IEs - * are not included). - */ - u8 *resp_ies; - - /** - * resp_ies_len - Length of resp_ies in bytes - */ - size_t resp_ies_len; - - /** - * beacon_ies - Beacon or Probe Response IEs - * - * Optional Beacon/ProbeResp data: IEs included in Beacon or - * Probe Response frames from the current AP (i.e., the one - * that the client just associated with). This information is - * used to update WPA/RSN IE for the AP. If this field is not - * set, the results from previous scan will be used. If no - * data for the new AP is found, scan results will be requested - * again (without scan request). At this point, the driver is - * expected to provide WPA/RSN IE for the AP (if WPA/WPA2 is - * used). - * - * This should start with the first IE (fixed fields before IEs - * are not included). - */ - u8 *beacon_ies; - - /** - * beacon_ies_len - Length of beacon_ies */ - size_t beacon_ies_len; - } assoc_info; - - /** - * struct michael_mic_failure - Data for EVENT_MICHAEL_MIC_FAILURE - */ - struct michael_mic_failure { - int unicast; - } michael_mic_failure; - - /** - * struct interface_status - Data for EVENT_INTERFACE_STATUS - */ - struct interface_status { - char ifname[100]; - enum { - EVENT_INTERFACE_ADDED, EVENT_INTERFACE_REMOVED - } ievent; - } interface_status; - - /** - * struct pmkid_candidate - Data for EVENT_PMKID_CANDIDATE - */ - struct pmkid_candidate { - /** BSSID of the PMKID candidate */ - u8 bssid[ETH_ALEN]; - /** Smaller the index, higher the priority */ - int index; - /** Whether RSN IE includes pre-authenticate flag */ - int preauth; - } pmkid_candidate; - - /** - * struct stkstart - Data for EVENT_STKSTART - */ - struct stkstart { - u8 peer[ETH_ALEN]; - } stkstart; - - /** - * struct ft_ies - FT information elements (EVENT_FT_RESPONSE) - * - * During FT (IEEE 802.11r) authentication sequence, the driver is - * expected to use this event to report received FT IEs (MDIE, FTIE, - * RSN IE, TIE, possible resource request) to the supplicant. The FT - * IEs for the next message will be delivered through the - * struct wpa_driver_ops::update_ft_ies() callback. - */ - struct ft_ies { - const u8 *ies; - size_t ies_len; - int ft_action; - u8 target_ap[ETH_ALEN]; - } ft_ies; -}; - -/** - * wpa_supplicant_event - Report a driver event for wpa_supplicant - * @ctx: Context pointer (wpa_s); this is the ctx variable registered - * with struct wpa_driver_ops::init() - * @event: event type (defined above) - * @data: possible extra data for the event - * - * Driver wrapper code should call this function whenever an event is received - * from the driver. - */ -void wpa_supplicant_event(void *ctx, wpa_event_type event, - union wpa_event_data *data); - -/** - * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant - * @ctx: Context pointer (wpa_s); this is the ctx variable registered - * with struct wpa_driver_ops::init() - * @src_addr: Source address of the EAPOL frame - * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header) - * @len: Length of the EAPOL data - * - * This function is called for each received EAPOL frame. Most driver - * interfaces rely on more generic OS mechanism for receiving frames through - * l2_packet, but if such a mechanism is not available, the driver wrapper may - * take care of received EAPOL frames and deliver them to the core supplicant - * code by calling this function. - */ -void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len); - -void wpa_supplicant_sta_rx(void *ctx, const u8 *buf, size_t len, - struct ieee80211_rx_status *rx_status); -void wpa_supplicant_sta_free_hw_features(struct wpa_hw_modes *hw_features, - size_t num_hw_features); - -const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie); -#define WPA_IE_VENDOR_TYPE 0x0050f201 -#define WPS_IE_VENDOR_TYPE 0x0050f204 -const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, - u32 vendor_type); -struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res, - u32 vendor_type); -int wpa_scan_get_max_rate(const struct wpa_scan_res *res); -void wpa_scan_results_free(struct wpa_scan_results *res); -void wpa_scan_sort_results(struct wpa_scan_results *res); - -#endif /* DRIVER_H */ diff --git a/contrib/hostapd/src/drivers/driver_atmel.c b/contrib/hostapd/src/drivers/driver_atmel.c deleted file mode 100644 index 0a7a66ddb5..0000000000 --- a/contrib/hostapd/src/drivers/driver_atmel.c +++ /dev/null @@ -1,506 +0,0 @@ -/* - * WPA Supplicant - Driver interaction with Atmel Wireless LAN drivers - * Copyright (c) 2000-2005, ATMEL Corporation - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -/****************************************************************************** - Copyright 2000-2001 ATMEL Corporation. - - WPA Supplicant - driver interaction with Atmel Wireless lan drivers. - - This is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Atmel wireless lan drivers; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -******************************************************************************/ - -/* - * Alternatively, this software may be distributed under the terms of BSD - * license. - */ - -#include "includes.h" -#include - -#include "wireless_copy.h" -#include "common.h" -#include "driver.h" -#include "driver_wext.h" - -struct wpa_driver_atmel_data { - void *wext; /* private data for driver_wext */ - void *ctx; - char ifname[IFNAMSIZ + 1]; - int sock; -}; - - -#define ATMEL_WPA_IOCTL (SIOCIWFIRSTPRIV + 2) -#define ATMEL_WPA_IOCTL_PARAM (SIOCIWFIRSTPRIV + 3) -#define ATMEL_WPA_IOCTL_GET_PARAM (SIOCIWFIRSTPRIV + 4) - - -/* ATMEL_WPA_IOCTL ioctl() cmd: */ -enum { - SET_WPA_ENCRYPTION = 1, - SET_CIPHER_SUITES = 2, - MLME_STA_DEAUTH = 3, - MLME_STA_DISASSOC = 4 -}; - -/* ATMEL_WPA_IOCTL_PARAM ioctl() cmd: */ -enum { - ATMEL_PARAM_WPA = 1, - ATMEL_PARAM_PRIVACY_INVOKED = 2, - ATMEL_PARAM_WPA_TYPE = 3 -}; - -#define MAX_KEY_LENGTH 40 - -struct atmel_param{ - unsigned char sta_addr[6]; - int cmd; - u8 alg; - u8 key_idx; - u8 set_tx; - u8 seq[8]; - u8 seq_len; - u16 key_len; - u8 key[MAX_KEY_LENGTH]; - struct{ - int reason_code; - u8 state; - }mlme; - u8 pairwise_suite; - u8 group_suite; - u8 key_mgmt_suite; -}; - - - -static int atmel_ioctl(struct wpa_driver_atmel_data *drv, - struct atmel_param *param, - int len, int show_err) -{ - struct iwreq iwr; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) param; - iwr.u.data.length = len; - - if (ioctl(drv->sock, ATMEL_WPA_IOCTL, &iwr) < 0) { - int ret; - ret = errno; - if (show_err) - perror("ioctl[ATMEL_WPA_IOCTL]"); - return ret; - } - - return 0; -} - - -static int atmel2param(struct wpa_driver_atmel_data *drv, int param, int value) -{ - struct iwreq iwr; - int *i, ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - i = (int *) iwr.u.name; - *i++ = param; - *i++ = value; - - if (ioctl(drv->sock, ATMEL_WPA_IOCTL_PARAM, &iwr) < 0) { - perror("ioctl[ATMEL_WPA_IOCTL_PARAM]"); - ret = -1; - } - return ret; -} - - -#if 0 -static int wpa_driver_atmel_set_wpa_ie(struct wpa_driver_atmel_data *drv, - const char *wpa_ie, size_t wpa_ie_len) -{ - struct atmel_param *param; - int res; - size_t blen = ATMEL_GENERIC_ELEMENT_HDR_LEN + wpa_ie_len; - if (blen < sizeof(*param)) - blen = sizeof(*param); - - param = os_zalloc(blen); - if (param == NULL) - return -1; - - param->cmd = ATMEL_SET_GENERIC_ELEMENT; - param->u.generic_elem.len = wpa_ie_len; - os_memcpy(param->u.generic_elem.data, wpa_ie, wpa_ie_len); - res = atmel_ioctl(drv, param, blen, 1); - - os_free(param); - - return res; -} -#endif - - -static int wpa_driver_atmel_set_wpa(void *priv, int enabled) -{ - struct wpa_driver_atmel_data *drv = priv; - int ret = 0; - - printf("wpa_driver_atmel_set_wpa %s\n", drv->ifname); - - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - -#if 0 - if (!enabled && wpa_driver_atmel_set_wpa_ie(drv, NULL, 0) < 0) - ret = -1; -#endif - if (atmel2param(drv, ATMEL_PARAM_PRIVACY_INVOKED, enabled) < 0) - ret = -1; - if (atmel2param(drv, ATMEL_PARAM_WPA, enabled) < 0) - ret = -1; - - return ret; -} - - -static int wpa_driver_atmel_set_key(void *priv, wpa_alg alg, - const u8 *addr, int key_idx, - int set_tx, const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_atmel_data *drv = priv; - int ret = 0; - struct atmel_param *param; - u8 *buf; - u8 alg_type; - - size_t blen; - char *alg_name; - - switch (alg) { - case WPA_ALG_NONE: - alg_name = "none"; - alg_type = 0; - break; - case WPA_ALG_WEP: - alg_name = "WEP"; - alg_type = 1; - break; - case WPA_ALG_TKIP: - alg_name = "TKIP"; - alg_type = 2; - break; - case WPA_ALG_CCMP: - alg_name = "CCMP"; - alg_type = 3; - break; - default: - return -1; - } - - wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu " - "key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx, - (unsigned long) seq_len, (unsigned long) key_len); - - if (seq_len > 8) - return -2; - - blen = sizeof(*param) + key_len; - buf = os_zalloc(blen); - if (buf == NULL) - return -1; - - param = (struct atmel_param *) buf; - - param->cmd = SET_WPA_ENCRYPTION; - - if (addr == NULL) - os_memset(param->sta_addr, 0xff, ETH_ALEN); - else - os_memcpy(param->sta_addr, addr, ETH_ALEN); - - param->alg = alg_type; - param->key_idx = key_idx; - param->set_tx = set_tx; - os_memcpy(param->seq, seq, seq_len); - param->seq_len = seq_len; - param->key_len = key_len; - os_memcpy((u8 *)param->key, key, key_len); - - if (atmel_ioctl(drv, param, blen, 1)) { - wpa_printf(MSG_WARNING, "Failed to set encryption."); - /* TODO: show key error*/ - ret = -1; - } - os_free(buf); - - return ret; -} - - -static int wpa_driver_atmel_set_countermeasures(void *priv, - int enabled) -{ - /* FIX */ - printf("wpa_driver_atmel_set_countermeasures - not yet " - "implemented\n"); - return 0; -} - - -static int wpa_driver_atmel_set_drop_unencrypted(void *priv, - int enabled) -{ - /* FIX */ - printf("wpa_driver_atmel_set_drop_unencrypted - not yet " - "implemented\n"); - return 0; -} - - -static int wpa_driver_atmel_mlme(void *priv, const u8 *addr, int cmd, - int reason_code) -{ - struct wpa_driver_atmel_data *drv = priv; - struct atmel_param param; - int ret; - int mgmt_error = 0xaa; - - os_memset(¶m, 0, sizeof(param)); - os_memcpy(param.sta_addr, addr, ETH_ALEN); - param.cmd = cmd; - param.mlme.reason_code = reason_code; - param.mlme.state = mgmt_error; - ret = atmel_ioctl(drv, ¶m, sizeof(param), 1); - return ret; -} - - -#if 0 -static int wpa_driver_atmel_set_suites(struct wpa_driver_atmel_data *drv, - u8 pairwise_suite, u8 group_suite, - u8 key_mgmt_suite) -{ - struct atmel_param param; - int ret; - - os_memset(¶m, 0, sizeof(param)); - param.cmd = SET_CIPHER_SUITES; - param.pairwise_suite = pairwise_suite; - param.group_suite = group_suite; - param.key_mgmt_suite = key_mgmt_suite; - - ret = atmel_ioctl(drv, ¶m, sizeof(param), 1); - return ret; -} -#endif - - -static int wpa_driver_atmel_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_atmel_data *drv = priv; - printf("wpa_driver_atmel_deauthenticate\n"); - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - return wpa_driver_atmel_mlme(drv, addr, MLME_STA_DEAUTH, - reason_code); - -} - - -static int wpa_driver_atmel_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_atmel_data *drv = priv; - printf("wpa_driver_atmel_disassociate\n"); - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - return wpa_driver_atmel_mlme(drv, addr, MLME_STA_DISASSOC, - reason_code); - -} - - -#if 0 -/* Atmel driver uses specific values for each cipher suite */ -static int convertSuiteToDriver(wpa_cipher suite) -{ - u8 suite_type; - - switch(suite) { - case CIPHER_NONE: - suite_type = 0; - break; - case CIPHER_WEP40: - suite_type = 1; - break; - case CIPHER_TKIP: - suite_type = 2; - break; - case CIPHER_WEP104: - suite_type = 5; - break; - case CIPHER_CCMP: - suite_type = 3; - break; - default: - suite_type = 2; - } - - return suite_type; - -} -#endif - -static int -wpa_driver_atmel_associate(void *priv, - struct wpa_driver_associate_params *params) -{ - struct wpa_driver_atmel_data *drv = priv; - int ret = 0; -#if 0 - u8 pairwise_suite_driver; - u8 group_suite_driver; - u8 key_mgmt_suite_driver; - - pairwise_suite_driver = convertSuiteToDriver(params->pairwise_suite); - group_suite_driver = convertSuiteToDriver(params->group_suite); - key_mgmt_suite_driver = convertSuiteToDriver(params->key_mgmt_suite); - - if (wpa_driver_atmel_set_suites(drv, pairwise_suite_driver, - group_suite_driver, - key_mgmt_suite_driver) < 0){ - printf("wpa_driver_atmel_set_suites.\n"); - ret = -1; - } - if (wpa_driver_wext_set_freq(drv->wext, params->freq) < 0) { - printf("wpa_driver_atmel_set_freq.\n"); - ret = -1; - } -#endif - if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, params->ssid_len) - < 0) { - printf("FAILED : wpa_driver_atmel_set_ssid.\n"); - ret = -1; - } - if (wpa_driver_wext_set_bssid(drv->wext, params->bssid) < 0) { - printf("FAILED : wpa_driver_atmel_set_bssid.\n"); - ret = -1; - } - - return ret; -} - - -static int wpa_driver_atmel_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_atmel_data *drv = priv; - return wpa_driver_wext_get_bssid(drv->wext, bssid); -} - - -static int wpa_driver_atmel_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_atmel_data *drv = priv; - return wpa_driver_wext_get_ssid(drv->wext, ssid); -} - - -static int wpa_driver_atmel_scan(void *priv, const u8 *ssid, size_t ssid_len) -{ - struct wpa_driver_atmel_data *drv = priv; - return wpa_driver_wext_scan(drv->wext, ssid, ssid_len); -} - - -static struct wpa_scan_results * wpa_driver_atmel_get_scan_results(void *priv) -{ - struct wpa_driver_atmel_data *drv = priv; - return wpa_driver_wext_get_scan_results(drv->wext); -} - - -static int wpa_driver_atmel_set_operstate(void *priv, int state) -{ - struct wpa_driver_atmel_data *drv = priv; - return wpa_driver_wext_set_operstate(drv->wext, state); -} - - -static void * wpa_driver_atmel_init(void *ctx, const char *ifname) -{ - struct wpa_driver_atmel_data *drv; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->wext = wpa_driver_wext_init(ctx, ifname); - if (drv->wext == NULL) { - os_free(drv); - return NULL; - } - - drv->ctx = ctx; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - drv->sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->sock < 0) { - wpa_driver_wext_deinit(drv->wext); - os_free(drv); - return NULL; - } - - return drv; -} - - -static void wpa_driver_atmel_deinit(void *priv) -{ - struct wpa_driver_atmel_data *drv = priv; - wpa_driver_wext_deinit(drv->wext); - close(drv->sock); - os_free(drv); -} - - -const struct wpa_driver_ops wpa_driver_atmel_ops = { - .name = "atmel", - .desc = "ATMEL AT76C5XXx (USB, PCMCIA)", - .get_bssid = wpa_driver_atmel_get_bssid, - .get_ssid = wpa_driver_atmel_get_ssid, - .set_wpa = wpa_driver_atmel_set_wpa, - .set_key = wpa_driver_atmel_set_key, - .init = wpa_driver_atmel_init, - .deinit = wpa_driver_atmel_deinit, - .set_countermeasures = wpa_driver_atmel_set_countermeasures, - .set_drop_unencrypted = wpa_driver_atmel_set_drop_unencrypted, - .scan = wpa_driver_atmel_scan, - .get_scan_results2 = wpa_driver_atmel_get_scan_results, - .deauthenticate = wpa_driver_atmel_deauthenticate, - .disassociate = wpa_driver_atmel_disassociate, - .associate = wpa_driver_atmel_associate, - .set_operstate = wpa_driver_atmel_set_operstate, -}; diff --git a/contrib/hostapd/src/drivers/driver_broadcom.c b/contrib/hostapd/src/drivers/driver_broadcom.c deleted file mode 100644 index 3600dae110..0000000000 --- a/contrib/hostapd/src/drivers/driver_broadcom.c +++ /dev/null @@ -1,604 +0,0 @@ -/* - * WPA Supplicant - driver interaction with old Broadcom wl.o driver - * Copyright (c) 2004, Nikki Chumkov - * Copyright (c) 2004, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * Please note that the newer Broadcom driver ("hybrid Linux driver") supports - * Linux wireless extensions and does not need (or even work) with this old - * driver wrapper. Use driver_wext.c with that driver. - */ - -#include "includes.h" - -#include - -#include "common.h" - -#if 0 -#include -#include /* the L2 protocols */ -#else -#include -#include /* The L2 protocols */ -#endif -#include -#include - -/* wlioctl.h is a Broadcom header file and it is available, e.g., from Linksys - * WRT54G GPL tarball. */ -#include - -#include "driver.h" -#include "eloop.h" - -struct wpa_driver_broadcom_data { - void *ctx; - int ioctl_sock; - int event_sock; - char ifname[IFNAMSIZ + 1]; -}; - - -#ifndef WLC_DEAUTHENTICATE -#define WLC_DEAUTHENTICATE 143 -#endif -#ifndef WLC_DEAUTHENTICATE_WITH_REASON -#define WLC_DEAUTHENTICATE_WITH_REASON 201 -#endif -#ifndef WLC_SET_TKIP_COUNTERMEASURES -#define WLC_SET_TKIP_COUNTERMEASURES 202 -#endif - -#if !defined(PSK_ENABLED) /* NEW driver interface */ -#define WL_VERSION 360130 -/* wireless authentication bit vector */ -#define WPA_ENABLED 1 -#define PSK_ENABLED 2 - -#define WAUTH_WPA_ENABLED(wauth) ((wauth) & WPA_ENABLED) -#define WAUTH_PSK_ENABLED(wauth) ((wauth) & PSK_ENABLED) -#define WAUTH_ENABLED(wauth) ((wauth) & (WPA_ENABLED | PSK_ENABLED)) - -#define WSEC_PRIMARY_KEY WL_PRIMARY_KEY - -typedef wl_wsec_key_t wsec_key_t; -#endif - -typedef struct { - uint32 val; - struct ether_addr ea; - uint16 res; -} wlc_deauth_t; - - -static void wpa_driver_broadcom_scan_timeout(void *eloop_ctx, - void *timeout_ctx); - -static int broadcom_ioctl(struct wpa_driver_broadcom_data *drv, int cmd, - void *buf, int len) -{ - struct ifreq ifr; - wl_ioctl_t ioc; - int ret = 0; - - wpa_printf(MSG_MSGDUMP, "BROADCOM: wlioctl(%s,%d,len=%d,val=%p)", - drv->ifname, cmd, len, buf); - /* wpa_hexdump(MSG_MSGDUMP, "BROADCOM: wlioctl buf", buf, len); */ - - ioc.cmd = cmd; - ioc.buf = buf; - ioc.len = len; - os_strlcpy(ifr.ifr_name, drv->ifname, IFNAMSIZ); - ifr.ifr_data = (caddr_t) &ioc; - if ((ret = ioctl(drv->ioctl_sock, SIOCDEVPRIVATE, &ifr)) < 0) { - if (cmd != WLC_GET_MAGIC) - perror(ifr.ifr_name); - wpa_printf(MSG_MSGDUMP, "BROADCOM: wlioctl cmd=%d res=%d", - cmd, ret); - } - - return ret; -} - -static int wpa_driver_broadcom_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_broadcom_data *drv = priv; - if (broadcom_ioctl(drv, WLC_GET_BSSID, bssid, ETH_ALEN) == 0) - return 0; - - os_memset(bssid, 0, ETH_ALEN); - return -1; -} - -static int wpa_driver_broadcom_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_broadcom_data *drv = priv; - wlc_ssid_t s; - - if (broadcom_ioctl(drv, WLC_GET_SSID, &s, sizeof(s)) == -1) - return -1; - - os_memcpy(ssid, s.SSID, s.SSID_len); - return s.SSID_len; -} - -static int wpa_driver_broadcom_set_wpa(void *priv, int enable) -{ - struct wpa_driver_broadcom_data *drv = priv; - unsigned int wauth, wsec; - struct ether_addr ea; - - os_memset(&ea, enable ? 0xff : 0, sizeof(ea)); - if (broadcom_ioctl(drv, WLC_GET_WPA_AUTH, &wauth, sizeof(wauth)) == - -1 || - broadcom_ioctl(drv, WLC_GET_WSEC, &wsec, sizeof(wsec)) == -1) - return -1; - - if (enable) { - wauth = PSK_ENABLED; - wsec = TKIP_ENABLED; - } else { - wauth = 255; - wsec &= ~(TKIP_ENABLED | AES_ENABLED); - } - - if (broadcom_ioctl(drv, WLC_SET_WPA_AUTH, &wauth, sizeof(wauth)) == - -1 || - broadcom_ioctl(drv, WLC_SET_WSEC, &wsec, sizeof(wsec)) == -1) - return -1; - - /* FIX: magic number / error handling? */ - broadcom_ioctl(drv, 122, &ea, sizeof(ea)); - - return 0; -} - -static int wpa_driver_broadcom_set_key(void *priv, wpa_alg alg, - const u8 *addr, int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_broadcom_data *drv = priv; - int ret; - wsec_key_t wkt; - - os_memset(&wkt, 0, sizeof wkt); - wpa_printf(MSG_MSGDUMP, "BROADCOM: SET %sKEY[%d] alg=%d", - set_tx ? "PRIMARY " : "", key_idx, alg); - if (key && key_len > 0) - wpa_hexdump_key(MSG_MSGDUMP, "BROADCOM: key", key, key_len); - - switch (alg) { - case WPA_ALG_NONE: - wkt.algo = CRYPTO_ALGO_OFF; - break; - case WPA_ALG_WEP: - wkt.algo = CRYPTO_ALGO_WEP128; /* CRYPTO_ALGO_WEP1? */ - break; - case WPA_ALG_TKIP: - wkt.algo = 0; /* CRYPTO_ALGO_TKIP? */ - break; - case WPA_ALG_CCMP: - wkt.algo = 0; /* CRYPTO_ALGO_AES_CCM; - * AES_OCB_MSDU, AES_OCB_MPDU? */ - break; - default: - wkt.algo = CRYPTO_ALGO_NALG; - break; - } - - if (seq && seq_len > 0) - wpa_hexdump(MSG_MSGDUMP, "BROADCOM: SEQ", seq, seq_len); - - if (addr) - wpa_hexdump(MSG_MSGDUMP, "BROADCOM: addr", addr, ETH_ALEN); - - wkt.index = key_idx; - wkt.len = key_len; - if (key && key_len > 0) { - os_memcpy(wkt.data, key, key_len); - if (key_len == 32) { - /* hack hack hack XXX */ - os_memcpy(&wkt.data[16], &key[24], 8); - os_memcpy(&wkt.data[24], &key[16], 8); - } - } - /* wkt.algo = CRYPTO_ALGO_...; */ - wkt.flags = set_tx ? 0 : WSEC_PRIMARY_KEY; - if (addr && set_tx) - os_memcpy(&wkt.ea, addr, sizeof(wkt.ea)); - ret = broadcom_ioctl(drv, WLC_SET_KEY, &wkt, sizeof(wkt)); - if (addr && set_tx) { - /* FIX: magic number / error handling? */ - broadcom_ioctl(drv, 121, &wkt.ea, sizeof(wkt.ea)); - } - return ret; -} - - -static void wpa_driver_broadcom_event_receive(int sock, void *ctx, - void *sock_ctx) -{ - char buf[8192]; - int left; - wl_wpa_header_t *wwh; - union wpa_event_data data; - - if ((left = recv(sock, buf, sizeof buf, 0)) < 0) - return; - - wpa_hexdump(MSG_DEBUG, "RECEIVE EVENT", (u8 *) buf, left); - - if ((size_t) left < sizeof(wl_wpa_header_t)) - return; - - wwh = (wl_wpa_header_t *) buf; - - if (wwh->snap.type != WL_WPA_ETHER_TYPE) - return; - if (os_memcmp(&wwh->snap, wl_wpa_snap_template, 6) != 0) - return; - - os_memset(&data, 0, sizeof(data)); - - switch (wwh->type) { - case WLC_ASSOC_MSG: - left -= WL_WPA_HEADER_LEN; - wpa_printf(MSG_DEBUG, "BROADCOM: ASSOC MESSAGE (left: %d)", - left); - if (left > 0) { - data.assoc_info.resp_ies = os_malloc(left); - if (data.assoc_info.resp_ies == NULL) - return; - os_memcpy(data.assoc_info.resp_ies, - buf + WL_WPA_HEADER_LEN, left); - data.assoc_info.resp_ies_len = left; - wpa_hexdump(MSG_MSGDUMP, "BROADCOM: copying %d bytes " - "into resp_ies", - data.assoc_info.resp_ies, left); - } - /* data.assoc_info.req_ies = NULL; */ - /* data.assoc_info.req_ies_len = 0; */ - - wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data); - wpa_supplicant_event(ctx, EVENT_ASSOC, NULL); - break; - case WLC_DISASSOC_MSG: - wpa_printf(MSG_DEBUG, "BROADCOM: DISASSOC MESSAGE"); - wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL); - break; - case WLC_PTK_MIC_MSG: - wpa_printf(MSG_DEBUG, "BROADCOM: PTK MIC MSG MESSAGE"); - data.michael_mic_failure.unicast = 1; - wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); - break; - case WLC_GTK_MIC_MSG: - wpa_printf(MSG_DEBUG, "BROADCOM: GTK MIC MSG MESSAGE"); - data.michael_mic_failure.unicast = 0; - wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); - break; - default: - wpa_printf(MSG_DEBUG, "BROADCOM: UNKNOWN MESSAGE (%d)", - wwh->type); - break; - } - os_free(data.assoc_info.resp_ies); -} - -static void * wpa_driver_broadcom_init(void *ctx, const char *ifname) -{ - int s; - struct sockaddr_ll ll; - struct wpa_driver_broadcom_data *drv; - struct ifreq ifr; - - /* open socket to kernel */ - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - perror("socket"); - return NULL; - } - /* do it */ - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); - if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { - perror(ifr.ifr_name); - return NULL; - } - - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->ctx = ctx; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - drv->ioctl_sock = s; - - s = socket(PF_PACKET, SOCK_RAW, ntohs(ETH_P_802_2)); - if (s < 0) { - perror("socket(PF_PACKET, SOCK_RAW, ntohs(ETH_P_802_2))"); - close(drv->ioctl_sock); - os_free(drv); - return NULL; - } - - os_memset(&ll, 0, sizeof(ll)); - ll.sll_family = AF_PACKET; - ll.sll_protocol = ntohs(ETH_P_802_2); - ll.sll_ifindex = ifr.ifr_ifindex; - ll.sll_hatype = 0; - ll.sll_pkttype = PACKET_HOST; - ll.sll_halen = 0; - - if (bind(s, (struct sockaddr *) &ll, sizeof(ll)) < 0) { - perror("bind(netlink)"); - close(s); - close(drv->ioctl_sock); - os_free(drv); - return NULL; - } - - eloop_register_read_sock(s, wpa_driver_broadcom_event_receive, ctx, - NULL); - drv->event_sock = s; - - return drv; -} - -static void wpa_driver_broadcom_deinit(void *priv) -{ - struct wpa_driver_broadcom_data *drv = priv; - eloop_cancel_timeout(wpa_driver_broadcom_scan_timeout, drv, drv->ctx); - eloop_unregister_read_sock(drv->event_sock); - close(drv->event_sock); - close(drv->ioctl_sock); - os_free(drv); -} - -static int wpa_driver_broadcom_set_countermeasures(void *priv, - int enabled) -{ -#if 0 - struct wpa_driver_broadcom_data *drv = priv; - /* FIX: ? */ - return broadcom_ioctl(drv, WLC_SET_TKIP_COUNTERMEASURES, &enabled, - sizeof(enabled)); -#else - return 0; -#endif -} - -static int wpa_driver_broadcom_set_drop_unencrypted(void *priv, int enabled) -{ - struct wpa_driver_broadcom_data *drv = priv; - /* SET_EAP_RESTRICT, SET_WEP_RESTRICT */ - int restrict = (enabled ? 1 : 0); - - if (broadcom_ioctl(drv, WLC_SET_WEP_RESTRICT, - &restrict, sizeof(restrict)) < 0 || - broadcom_ioctl(drv, WLC_SET_EAP_RESTRICT, - &restrict, sizeof(restrict)) < 0) - return -1; - - return 0; -} - -static void wpa_driver_broadcom_scan_timeout(void *eloop_ctx, - void *timeout_ctx) -{ - wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); - wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); -} - -static int wpa_driver_broadcom_scan(void *priv, const u8 *ssid, - size_t ssid_len) -{ - struct wpa_driver_broadcom_data *drv = priv; - wlc_ssid_t wst = { 0, "" }; - - if (ssid && ssid_len > 0 && ssid_len <= sizeof(wst.SSID)) { - wst.SSID_len = ssid_len; - os_memcpy(wst.SSID, ssid, ssid_len); - } - - if (broadcom_ioctl(drv, WLC_SCAN, &wst, sizeof(wst)) < 0) - return -1; - - eloop_cancel_timeout(wpa_driver_broadcom_scan_timeout, drv, drv->ctx); - eloop_register_timeout(3, 0, wpa_driver_broadcom_scan_timeout, drv, - drv->ctx); - return 0; -} - - -static const int frequency_list[] = { - 2412, 2417, 2422, 2427, 2432, 2437, 2442, - 2447, 2452, 2457, 2462, 2467, 2472, 2484 -}; - -struct bss_ie_hdr { - u8 elem_id; - u8 len; - u8 oui[3]; - /* u8 oui_type; */ - /* u16 version; */ -} __attribute__ ((packed)); - -static int -wpa_driver_broadcom_get_scan_results(void *priv, - struct wpa_scan_result *results, - size_t max_size) -{ - struct wpa_driver_broadcom_data *drv = priv; - char *buf; - wl_scan_results_t *wsr; - wl_bss_info_t *wbi; - size_t ap_num; - - buf = os_malloc(WLC_IOCTL_MAXLEN); - if (buf == NULL) - return -1; - - wsr = (wl_scan_results_t *) buf; - - wsr->buflen = WLC_IOCTL_MAXLEN - sizeof(wsr); - wsr->version = 107; - wsr->count = 0; - - if (broadcom_ioctl(drv, WLC_SCAN_RESULTS, buf, WLC_IOCTL_MAXLEN) < 0) { - os_free(buf); - return -1; - } - - os_memset(results, 0, max_size * sizeof(struct wpa_scan_result)); - - for (ap_num = 0, wbi = wsr->bss_info; ap_num < wsr->count; ++ap_num) { - int left; - struct bss_ie_hdr *ie; - - os_memcpy(results[ap_num].bssid, &wbi->BSSID, ETH_ALEN); - os_memcpy(results[ap_num].ssid, wbi->SSID, wbi->SSID_len); - results[ap_num].ssid_len = wbi->SSID_len; - results[ap_num].freq = frequency_list[wbi->channel - 1]; - /* get ie's */ - wpa_hexdump(MSG_MSGDUMP, "BROADCOM: AP IEs", - (u8 *) wbi + sizeof(*wbi), wbi->ie_length); - ie = (struct bss_ie_hdr *) ((u8 *) wbi + sizeof(*wbi)); - for (left = wbi->ie_length; left > 0; - left -= (ie->len + 2), ie = (struct bss_ie_hdr *) - ((u8 *) ie + 2 + ie->len)) { - wpa_printf(MSG_MSGDUMP, "BROADCOM: IE: id:%x, len:%d", - ie->elem_id, ie->len); - if (ie->len >= 3) - wpa_printf(MSG_MSGDUMP, - "BROADCOM: oui:%02x%02x%02x", - ie->oui[0], ie->oui[1], ie->oui[2]); - if (ie->elem_id != 0xdd || - ie->len < 6 || - os_memcmp(ie->oui, WPA_OUI, 3) != 0) - continue; - os_memcpy(results[ap_num].wpa_ie, ie, ie->len + 2); - results[ap_num].wpa_ie_len = ie->len + 2; - break; - } - - wbi = (wl_bss_info_t *) ((u8 *) wbi + wbi->length); - } - - wpa_printf(MSG_MSGDUMP, "Received %d bytes of scan results (%lu " - "BSSes)", - wsr->buflen, (unsigned long) ap_num); - - os_free(buf); - return ap_num; -} - -static int wpa_driver_broadcom_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_broadcom_data *drv = priv; - wlc_deauth_t wdt; - wdt.val = reason_code; - os_memcpy(&wdt.ea, addr, sizeof wdt.ea); - wdt.res = 0x7fff; - return broadcom_ioctl(drv, WLC_DEAUTHENTICATE_WITH_REASON, &wdt, - sizeof(wdt)); -} - -static int wpa_driver_broadcom_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_broadcom_data *drv = priv; - return broadcom_ioctl(drv, WLC_DISASSOC, 0, 0); -} - -static int -wpa_driver_broadcom_associate(void *priv, - struct wpa_driver_associate_params *params) -{ - struct wpa_driver_broadcom_data *drv = priv; - wlc_ssid_t s; - int infra = 1; - int auth = 0; - int wsec = 4; - int dummy; - int wpa_auth; - - s.SSID_len = params->ssid_len; - os_memcpy(s.SSID, params->ssid, params->ssid_len); - - switch (params->pairwise_suite) { - case CIPHER_WEP40: - case CIPHER_WEP104: - wsec = 1; - break; - - case CIPHER_TKIP: - wsec = 2; - break; - - case CIPHER_CCMP: - wsec = 4; - break; - - default: - wsec = 0; - break; - } - - switch (params->key_mgmt_suite) { - case KEY_MGMT_802_1X: - wpa_auth = 1; - break; - - case KEY_MGMT_PSK: - wpa_auth = 2; - break; - - default: - wpa_auth = 255; - break; - } - - /* printf("broadcom_associate: %u %u %u\n", pairwise_suite, - * group_suite, key_mgmt_suite); - * broadcom_ioctl(ifname, WLC_GET_WSEC, &wsec, sizeof(wsec)); - * wl join uses wlc_sec_wep here, not wlc_set_wsec */ - - if (broadcom_ioctl(drv, WLC_SET_WSEC, &wsec, sizeof(wsec)) < 0 || - broadcom_ioctl(drv, WLC_SET_WPA_AUTH, &wpa_auth, - sizeof(wpa_auth)) < 0 || - broadcom_ioctl(drv, WLC_GET_WEP, &dummy, sizeof(dummy)) < 0 || - broadcom_ioctl(drv, WLC_SET_INFRA, &infra, sizeof(infra)) < 0 || - broadcom_ioctl(drv, WLC_SET_AUTH, &auth, sizeof(auth)) < 0 || - broadcom_ioctl(drv, WLC_SET_WEP, &wsec, sizeof(wsec)) < 0 || - broadcom_ioctl(drv, WLC_SET_SSID, &s, sizeof(s)) < 0) - return -1; - - return 0; -} - -const struct wpa_driver_ops wpa_driver_broadcom_ops = { - .name = "broadcom", - .desc = "Broadcom wl.o driver", - .get_bssid = wpa_driver_broadcom_get_bssid, - .get_ssid = wpa_driver_broadcom_get_ssid, - .set_wpa = wpa_driver_broadcom_set_wpa, - .set_key = wpa_driver_broadcom_set_key, - .init = wpa_driver_broadcom_init, - .deinit = wpa_driver_broadcom_deinit, - .set_countermeasures = wpa_driver_broadcom_set_countermeasures, - .set_drop_unencrypted = wpa_driver_broadcom_set_drop_unencrypted, - .scan = wpa_driver_broadcom_scan, - .get_scan_results = wpa_driver_broadcom_get_scan_results, - .deauthenticate = wpa_driver_broadcom_deauthenticate, - .disassociate = wpa_driver_broadcom_disassociate, - .associate = wpa_driver_broadcom_associate, -}; diff --git a/contrib/hostapd/src/drivers/driver_bsd.c b/contrib/hostapd/src/drivers/driver_bsd.c deleted file mode 100644 index 218d913869..0000000000 --- a/contrib/hostapd/src/drivers/driver_bsd.c +++ /dev/null @@ -1,794 +0,0 @@ -/* - * WPA Supplicant - driver interaction with BSD net80211 layer - * Copyright (c) 2004, Sam Leffler - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "driver.h" -#include "eloop.h" -#include "ieee802_11_defs.h" - -#include - -#ifdef __NetBSD__ -#include -#define COMPAT_FREEBSD_NET80211 -#else -#include -#endif - -#include -#include -#include - -struct wpa_driver_bsd_data { - int sock; /* open socket for 802.11 ioctls */ - int route; /* routing socket for events */ - char ifname[IFNAMSIZ+1]; /* interface name */ - unsigned int ifindex; /* interface index */ - void *ctx; - int prev_roaming; /* roaming state to restore on deinit */ - int prev_privacy; /* privacy state to restore on deinit */ - int prev_wpa; /* wpa state to restore on deinit */ -}; - -static int -set80211var(struct wpa_driver_bsd_data *drv, int op, const void *arg, int arg_len) -{ - struct ieee80211req ireq; - - os_memset(&ireq, 0, sizeof(ireq)); - os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ); - ireq.i_type = op; - ireq.i_len = arg_len; - ireq.i_data = (void *) arg; - - if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) { - fprintf(stderr, "ioctl[SIOCS80211, op %u, len %u]: %s\n", - op, arg_len, strerror(errno)); - return -1; - } - return 0; -} - -static int -get80211var(struct wpa_driver_bsd_data *drv, int op, void *arg, int arg_len) -{ - struct ieee80211req ireq; - - os_memset(&ireq, 0, sizeof(ireq)); - os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ); - ireq.i_type = op; - ireq.i_len = arg_len; - ireq.i_data = arg; - - if (ioctl(drv->sock, SIOCG80211, &ireq) < 0) { - fprintf(stderr, "ioctl[SIOCG80211, op %u, len %u]: %s\n", - op, arg_len, strerror(errno)); - return -1; - } - return ireq.i_len; -} - -static int -set80211param(struct wpa_driver_bsd_data *drv, int op, int arg) -{ - struct ieee80211req ireq; - - os_memset(&ireq, 0, sizeof(ireq)); - os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ); - ireq.i_type = op; - ireq.i_val = arg; - - if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) { - fprintf(stderr, "ioctl[SIOCS80211, op %u, arg 0x%x]: %s\n", - op, arg, strerror(errno)); - return -1; - } - return 0; -} - -static int -get80211param(struct wpa_driver_bsd_data *drv, int op) -{ - struct ieee80211req ireq; - - os_memset(&ireq, 0, sizeof(ireq)); - os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ); - ireq.i_type = op; - - if (ioctl(drv->sock, SIOCG80211, &ireq) < 0) { - fprintf(stderr, "ioctl[SIOCG80211, op %u]: %s\n", - op, strerror(errno)); - return -1; - } - return ireq.i_val; -} - -static int -getifflags(struct wpa_driver_bsd_data *drv, int *flags) -{ - struct ifreq ifr; - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); - if (ioctl(drv->sock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { - perror("SIOCGIFFLAGS"); - return errno; - } - *flags = ifr.ifr_flags & 0xffff; - return 0; -} - -static int -setifflags(struct wpa_driver_bsd_data *drv, int flags) -{ - struct ifreq ifr; - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); - ifr.ifr_flags = flags & 0xffff; - if (ioctl(drv->sock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) { - perror("SIOCSIFFLAGS"); - return errno; - } - return 0; -} - -static int -wpa_driver_bsd_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_bsd_data *drv = priv; - - return get80211var(drv, IEEE80211_IOC_BSSID, - bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0; -} - -#if 0 -static int -wpa_driver_bsd_set_bssid(void *priv, const char *bssid) -{ - struct wpa_driver_bsd_data *drv = priv; - - return set80211var(drv, IEEE80211_IOC_BSSID, - bssid, IEEE80211_ADDR_LEN); -} -#endif - -static int -wpa_driver_bsd_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_bsd_data *drv = priv; - - return get80211var(drv, IEEE80211_IOC_SSID, - ssid, IEEE80211_NWID_LEN); -} - -static int -wpa_driver_bsd_set_ssid(void *priv, const u8 *ssid, - size_t ssid_len) -{ - struct wpa_driver_bsd_data *drv = priv; - - return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len); -} - -static int -wpa_driver_bsd_set_wpa_ie(struct wpa_driver_bsd_data *drv, - const u8 *wpa_ie, size_t wpa_ie_len) -{ - return set80211var(drv, IEEE80211_IOC_OPTIE, wpa_ie, wpa_ie_len); -} - -static int -wpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy) -{ - struct wpa_driver_bsd_data *drv = priv; - int ret = 0; - - wpa_printf(MSG_DEBUG, "%s: wpa=%d privacy=%d", - __FUNCTION__, wpa, privacy); - - if (!wpa && wpa_driver_bsd_set_wpa_ie(drv, NULL, 0) < 0) - ret = -1; - if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0) - ret = -1; - if (set80211param(drv, IEEE80211_IOC_WPA, wpa) < 0) - ret = -1; - - return ret; -} - -static int -wpa_driver_bsd_set_wpa(void *priv, int enabled) -{ - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - - return wpa_driver_bsd_set_wpa_internal(priv, enabled ? 3 : 0, enabled); -} - -static int -wpa_driver_bsd_del_key(struct wpa_driver_bsd_data *drv, int key_idx, - const unsigned char *addr) -{ - struct ieee80211req_del_key wk; - - os_memset(&wk, 0, sizeof(wk)); - if (addr != NULL && - bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) != 0) { - struct ether_addr ea; - - os_memcpy(&ea, addr, IEEE80211_ADDR_LEN); - wpa_printf(MSG_DEBUG, "%s: addr=%s keyidx=%d", - __func__, ether_ntoa(&ea), key_idx); - os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); - wk.idk_keyix = (uint8_t) IEEE80211_KEYIX_NONE; - } else { - wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __func__, key_idx); - wk.idk_keyix = key_idx; - } - return set80211var(drv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk)); -} - -static int -wpa_driver_bsd_set_key(void *priv, wpa_alg alg, - const unsigned char *addr, int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_bsd_data *drv = priv; - struct ieee80211req_key wk; - struct ether_addr ea; - char *alg_name; - u_int8_t cipher; - - if (alg == WPA_ALG_NONE) - return wpa_driver_bsd_del_key(drv, key_idx, addr); - - switch (alg) { - case WPA_ALG_WEP: - alg_name = "WEP"; - cipher = IEEE80211_CIPHER_WEP; - break; - case WPA_ALG_TKIP: - alg_name = "TKIP"; - cipher = IEEE80211_CIPHER_TKIP; - break; - case WPA_ALG_CCMP: - alg_name = "CCMP"; - cipher = IEEE80211_CIPHER_AES_CCM; - break; - default: - wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d", - __func__, alg); - return -1; - } - - os_memcpy(&ea, addr, IEEE80211_ADDR_LEN); - wpa_printf(MSG_DEBUG, - "%s: alg=%s addr=%s key_idx=%d set_tx=%d seq_len=%zu key_len=%zu", - __func__, alg_name, ether_ntoa(&ea), key_idx, set_tx, - seq_len, key_len); - - if (seq_len > sizeof(u_int64_t)) { - wpa_printf(MSG_DEBUG, "%s: seq_len %zu too big", - __func__, seq_len); - return -2; - } - if (key_len > sizeof(wk.ik_keydata)) { - wpa_printf(MSG_DEBUG, "%s: key length %zu too big", - __func__, key_len); - return -3; - } - - os_memset(&wk, 0, sizeof(wk)); - wk.ik_type = cipher; - wk.ik_flags = IEEE80211_KEY_RECV; - if (set_tx) - wk.ik_flags |= IEEE80211_KEY_XMIT; - os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); - /* - * Deduce whether group/global or unicast key by checking - * the address (yech). Note also that we can only mark global - * keys default; doing this for a unicast key is an error. - */ - if (bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) == 0) { - wk.ik_flags |= IEEE80211_KEY_GROUP; - wk.ik_keyix = key_idx; - } else { - wk.ik_keyix = (key_idx == 0 ? IEEE80211_KEYIX_NONE : key_idx); - } - if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx) - wk.ik_flags |= IEEE80211_KEY_DEFAULT; - wk.ik_keylen = key_len; - os_memcpy(&wk.ik_keyrsc, seq, seq_len); - os_memcpy(wk.ik_keydata, key, key_len); - - return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)); -} - -static int -wpa_driver_bsd_set_countermeasures(void *priv, int enabled) -{ - struct wpa_driver_bsd_data *drv = priv; - - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - return set80211param(drv, IEEE80211_IOC_COUNTERMEASURES, enabled); -} - - -static int -wpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled) -{ - struct wpa_driver_bsd_data *drv = priv; - - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - return set80211param(drv, IEEE80211_IOC_DROPUNENCRYPTED, enabled); -} - -static int -wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, int reason_code) -{ - struct wpa_driver_bsd_data *drv = priv; - struct ieee80211req_mlme mlme; - - wpa_printf(MSG_DEBUG, "%s", __func__); - os_memset(&mlme, 0, sizeof(mlme)); - mlme.im_op = IEEE80211_MLME_DEAUTH; - mlme.im_reason = reason_code; - os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); -} - -static int -wpa_driver_bsd_disassociate(void *priv, const u8 *addr, int reason_code) -{ - struct wpa_driver_bsd_data *drv = priv; - struct ieee80211req_mlme mlme; - - wpa_printf(MSG_DEBUG, "%s", __func__); - os_memset(&mlme, 0, sizeof(mlme)); - mlme.im_op = IEEE80211_MLME_DISASSOC; - mlme.im_reason = reason_code; - os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); -} - -static int -wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params) -{ - struct wpa_driver_bsd_data *drv = priv; - struct ieee80211req_mlme mlme; - int privacy; - - wpa_printf(MSG_DEBUG, - "%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u" - , __func__ - , params->ssid_len, params->ssid - , params->wpa_ie_len - , params->pairwise_suite - , params->group_suite - , params->key_mgmt_suite - ); - - /* XXX error handling is wrong but unclear what to do... */ - if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0) - return -1; - - privacy = !(params->pairwise_suite == CIPHER_NONE && - params->group_suite == CIPHER_NONE && - params->key_mgmt_suite == KEY_MGMT_NONE && - params->wpa_ie_len == 0); - wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy); - - if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0) - return -1; - - if (params->wpa_ie_len && - set80211param(drv, IEEE80211_IOC_WPA, - params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1) < 0) - return -1; - - os_memset(&mlme, 0, sizeof(mlme)); - mlme.im_op = IEEE80211_MLME_ASSOC; - if (params->ssid != NULL) - os_memcpy(mlme.im_ssid, params->ssid, params->ssid_len); - mlme.im_ssid_len = params->ssid_len; - if (params->bssid != NULL) - os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN); - if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0) - return -1; - return 0; -} - -static int -wpa_driver_bsd_set_auth_alg(void *priv, int auth_alg) -{ - struct wpa_driver_bsd_data *drv = priv; - int authmode; - - if ((auth_alg & AUTH_ALG_OPEN_SYSTEM) && - (auth_alg & AUTH_ALG_SHARED_KEY)) - authmode = IEEE80211_AUTH_AUTO; - else if (auth_alg & AUTH_ALG_SHARED_KEY) - authmode = IEEE80211_AUTH_SHARED; - else - authmode = IEEE80211_AUTH_OPEN; - - return set80211param(drv, IEEE80211_IOC_AUTHMODE, authmode); -} - -static int -wpa_driver_bsd_scan(void *priv, const u8 *ssid, size_t ssid_len) -{ - struct wpa_driver_bsd_data *drv = priv; - int flags; - - /* NB: interface must be marked UP to do a scan */ - if (getifflags(drv, &flags) != 0 || setifflags(drv, flags | IFF_UP) != 0) - return -1; - - /* set desired ssid before scan */ - if (wpa_driver_bsd_set_ssid(drv, ssid, ssid_len) < 0) - return -1; - - /* NB: net80211 delivers a scan complete event so no need to poll */ - return set80211param(drv, IEEE80211_IOC_SCAN_REQ, 0); -} - -#include -#if __FreeBSD__ -#include -#endif -#if __NetBSD__ -#include -#endif - -static void -wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx) -{ - struct wpa_driver_bsd_data *drv = sock_ctx; - char buf[2048]; - struct if_announcemsghdr *ifan; - struct if_msghdr *ifm; - struct rt_msghdr *rtm; - union wpa_event_data event; - struct ieee80211_michael_event *mic; - int n; - - n = read(sock, buf, sizeof(buf)); - if (n < 0) { - if (errno != EINTR && errno != EAGAIN) - perror("read(PF_ROUTE)"); - return; - } - - rtm = (struct rt_msghdr *) buf; - if (rtm->rtm_version != RTM_VERSION) { - wpa_printf(MSG_DEBUG, "Routing message version %d not " - "understood\n", rtm->rtm_version); - return; - } - os_memset(&event, 0, sizeof(event)); - switch (rtm->rtm_type) { - case RTM_IFANNOUNCE: - ifan = (struct if_announcemsghdr *) rtm; - if (ifan->ifan_index != drv->ifindex) - break; - strlcpy(event.interface_status.ifname, drv->ifname, - sizeof(event.interface_status.ifname)); - switch (ifan->ifan_what) { - case IFAN_DEPARTURE: - event.interface_status.ievent = EVENT_INTERFACE_REMOVED; - default: - return; - } - wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s", - event.interface_status.ifname, - ifan->ifan_what == IFAN_DEPARTURE ? - "removed" : "added"); - wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event); - break; - case RTM_IEEE80211: - ifan = (struct if_announcemsghdr *) rtm; - if (ifan->ifan_index != drv->ifindex) - break; - switch (ifan->ifan_what) { - case RTM_IEEE80211_ASSOC: - case RTM_IEEE80211_REASSOC: - wpa_supplicant_event(ctx, EVENT_ASSOC, NULL); - break; - case RTM_IEEE80211_DISASSOC: - wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL); - break; - case RTM_IEEE80211_SCAN: - wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL); - break; - case RTM_IEEE80211_REPLAY: - /* ignore */ - break; - case RTM_IEEE80211_MICHAEL: - mic = (struct ieee80211_michael_event *) &ifan[1]; - wpa_printf(MSG_DEBUG, - "Michael MIC failure wireless event: " - "keyix=%u src_addr=" MACSTR, mic->iev_keyix, - MAC2STR(mic->iev_src)); - - os_memset(&event, 0, sizeof(event)); - event.michael_mic_failure.unicast = - !IEEE80211_IS_MULTICAST(mic->iev_dst); - wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, - &event); - break; - } - break; - case RTM_IFINFO: - ifm = (struct if_msghdr *) rtm; - if (ifm->ifm_index != drv->ifindex) - break; - if ((rtm->rtm_flags & RTF_UP) == 0) { - strlcpy(event.interface_status.ifname, drv->ifname, - sizeof(event.interface_status.ifname)); - event.interface_status.ievent = EVENT_INTERFACE_REMOVED; - wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN", - event.interface_status.ifname); - wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event); - } - break; - } -} - -/* Compare function for sorting scan results. Return >0 if @b is consider - * better. */ -static int -wpa_scan_result_compar(const void *a, const void *b) -{ - const struct wpa_scan_result *wa = a; - const struct wpa_scan_result *wb = b; - - /* WPA/WPA2 support preferred */ - if ((wb->wpa_ie_len || wb->rsn_ie_len) && - !(wa->wpa_ie_len || wa->rsn_ie_len)) - return 1; - if (!(wb->wpa_ie_len || wb->rsn_ie_len) && - (wa->wpa_ie_len || wa->rsn_ie_len)) - return -1; - - /* privacy support preferred */ - if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) && - (wb->caps & IEEE80211_CAPINFO_PRIVACY) == 0) - return 1; - if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) == 0 && - (wb->caps & IEEE80211_CAPINFO_PRIVACY)) - return -1; - - /* best/max rate preferred if signal level close enough XXX */ - if (wa->maxrate != wb->maxrate && abs(wb->level - wa->level) < 5) - return wb->maxrate - wa->maxrate; - - /* use freq for channel preference */ - - /* all things being equal, use signal level */ - return wb->level - wa->level; -} - -static int -getmaxrate(uint8_t rates[15], uint8_t nrates) -{ - int i, maxrate = -1; - - for (i = 0; i < nrates; i++) { - int rate = rates[i] & IEEE80211_RATE_VAL; - if (rate > maxrate) - rate = maxrate; - } - return maxrate; -} - -/* unalligned little endian access */ -#define LE_READ_4(p) \ - ((u_int32_t) \ - ((((const u_int8_t *)(p))[0] ) | \ - (((const u_int8_t *)(p))[1] << 8) | \ - (((const u_int8_t *)(p))[2] << 16) | \ - (((const u_int8_t *)(p))[3] << 24))) - -static int __inline -iswpaoui(const u_int8_t *frm) -{ - return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI); -} - -static int -wpa_driver_bsd_get_scan_results(void *priv, - struct wpa_scan_result *results, - size_t max_size) -{ -#define min(a,b) ((a)>(b)?(b):(a)) - struct wpa_driver_bsd_data *drv = priv; - uint8_t buf[24*1024]; - uint8_t *cp, *vp; - struct ieee80211req_scan_result *sr; - struct wpa_scan_result *wsr; - int len, ielen; - - os_memset(results, 0, max_size * sizeof(struct wpa_scan_result)); - - len = get80211var(drv, IEEE80211_IOC_SCAN_RESULTS, buf, sizeof(buf)); - if (len < 0) - return -1; - cp = buf; - wsr = results; - while (len >= sizeof(struct ieee80211req_scan_result)) { - sr = (struct ieee80211req_scan_result *) cp; - os_memcpy(wsr->bssid, sr->isr_bssid, IEEE80211_ADDR_LEN); - wsr->ssid_len = sr->isr_ssid_len; - wsr->freq = sr->isr_freq; - wsr->noise = sr->isr_noise; - wsr->qual = sr->isr_rssi; - wsr->level = 0; /* XXX? */ - wsr->caps = sr->isr_capinfo; - wsr->maxrate = getmaxrate(sr->isr_rates, sr->isr_nrates); - vp = (u_int8_t *)(sr+1); - os_memcpy(wsr->ssid, vp, sr->isr_ssid_len); - if (sr->isr_ie_len > 0) { - vp += sr->isr_ssid_len; - ielen = sr->isr_ie_len; - while (ielen > 0) { - switch (vp[0]) { - case IEEE80211_ELEMID_VENDOR: - if (!iswpaoui(vp)) - break; - wsr->wpa_ie_len = - min(2+vp[1], SSID_MAX_WPA_IE_LEN); - os_memcpy(wsr->wpa_ie, vp, - wsr->wpa_ie_len); - break; - case IEEE80211_ELEMID_RSN: - wsr->rsn_ie_len = - min(2+vp[1], SSID_MAX_WPA_IE_LEN); - os_memcpy(wsr->rsn_ie, vp, - wsr->rsn_ie_len); - break; - } - ielen -= 2+vp[1]; - vp += 2+vp[1]; - } - } - - cp += sr->isr_len, len -= sr->isr_len; - wsr++; - } - qsort(results, wsr - results, sizeof(struct wpa_scan_result), - wpa_scan_result_compar); - - wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%d BSSes)", - len, wsr - results); - - return wsr - results; -#undef min -} - -static void * -wpa_driver_bsd_init(void *ctx, const char *ifname) -{ -#define GETPARAM(drv, param, v) \ - (((v) = get80211param(drv, param)) != -1) - struct wpa_driver_bsd_data *drv; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - /* - * NB: We require the interface name be mappable to an index. - * This implies we do not support having wpa_supplicant - * wait for an interface to appear. This seems ok; that - * doesn't belong here; it's really the job of devd. - */ - drv->ifindex = if_nametoindex(ifname); - if (drv->ifindex == 0) { - wpa_printf(MSG_DEBUG, "%s: interface %s does not exist", - __func__, ifname); - goto fail1; - } - drv->sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->sock < 0) - goto fail1; - drv->route = socket(PF_ROUTE, SOCK_RAW, 0); - if (drv->route < 0) - goto fail; - eloop_register_read_sock(drv->route, - wpa_driver_bsd_event_receive, ctx, drv); - - drv->ctx = ctx; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - - if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) { - wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s", - __func__, strerror(errno)); - goto fail; - } - if (!GETPARAM(drv, IEEE80211_IOC_PRIVACY, drv->prev_privacy)) { - wpa_printf(MSG_DEBUG, "%s: failed to get privacy state: %s", - __func__, strerror(errno)); - goto fail; - } - if (!GETPARAM(drv, IEEE80211_IOC_WPA, drv->prev_wpa)) { - wpa_printf(MSG_DEBUG, "%s: failed to get wpa state: %s", - __func__, strerror(errno)); - goto fail; - } - if (set80211param(drv, IEEE80211_IOC_ROAMING, IEEE80211_ROAMING_MANUAL) < 0) { - wpa_printf(MSG_DEBUG, "%s: failed to set wpa_supplicant-based " - "roaming: %s", __func__, strerror(errno)); - goto fail; - } - - if (set80211param(drv, IEEE80211_IOC_WPA, 1+2) < 0) { - wpa_printf(MSG_DEBUG, "%s: failed to enable WPA support %s", - __func__, strerror(errno)); - goto fail; - } - - return drv; -fail: - close(drv->sock); -fail1: - os_free(drv); - return NULL; -#undef GETPARAM -} - -static void -wpa_driver_bsd_deinit(void *priv) -{ - struct wpa_driver_bsd_data *drv = priv; - int flags; - - eloop_unregister_read_sock(drv->route); - - /* NB: mark interface down */ - if (getifflags(drv, &flags) == 0) - (void) setifflags(drv, flags &~ IFF_UP); - - wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, drv->prev_privacy); - if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) < 0) - wpa_printf(MSG_DEBUG, "%s: failed to restore roaming state", - __func__); - - (void) close(drv->route); /* ioctl socket */ - (void) close(drv->sock); /* event socket */ - os_free(drv); -} - - -const struct wpa_driver_ops wpa_driver_bsd_ops = { - .name = "bsd", - .desc = "BSD 802.11 support (Atheros, etc.)", - .init = wpa_driver_bsd_init, - .deinit = wpa_driver_bsd_deinit, - .get_bssid = wpa_driver_bsd_get_bssid, - .get_ssid = wpa_driver_bsd_get_ssid, - .set_wpa = wpa_driver_bsd_set_wpa, - .set_key = wpa_driver_bsd_set_key, - .set_countermeasures = wpa_driver_bsd_set_countermeasures, - .set_drop_unencrypted = wpa_driver_bsd_set_drop_unencrypted, - .scan = wpa_driver_bsd_scan, - .get_scan_results = wpa_driver_bsd_get_scan_results, - .deauthenticate = wpa_driver_bsd_deauthenticate, - .disassociate = wpa_driver_bsd_disassociate, - .associate = wpa_driver_bsd_associate, - .set_auth_alg = wpa_driver_bsd_set_auth_alg, -}; diff --git a/contrib/hostapd/src/drivers/driver_hostap.c b/contrib/hostapd/src/drivers/driver_hostap.c deleted file mode 100644 index 84ef3bdedc..0000000000 --- a/contrib/hostapd/src/drivers/driver_hostap.c +++ /dev/null @@ -1,513 +0,0 @@ -/* - * WPA Supplicant - driver interaction with Linux Host AP driver - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "wireless_copy.h" -#include "common.h" -#include "driver.h" -#include "driver_wext.h" -#include "eloop.h" -#include "driver_hostap.h" - - -struct wpa_driver_hostap_data { - void *wext; /* private data for driver_wext */ - void *ctx; - char ifname[IFNAMSIZ + 1]; - int sock; - int current_mode; /* infra/adhoc */ -}; - - -static int hostapd_ioctl(struct wpa_driver_hostap_data *drv, - struct prism2_hostapd_param *param, - int len, int show_err) -{ - struct iwreq iwr; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) param; - iwr.u.data.length = len; - - if (ioctl(drv->sock, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) { - int ret = errno; - if (show_err) - perror("ioctl[PRISM2_IOCTL_HOSTAPD]"); - return ret; - } - - return 0; -} - - -static int wpa_driver_hostap_set_wpa_ie(struct wpa_driver_hostap_data *drv, - const u8 *wpa_ie, size_t wpa_ie_len) -{ - struct prism2_hostapd_param *param; - int res; - size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + wpa_ie_len; - if (blen < sizeof(*param)) - blen = sizeof(*param); - - param = os_zalloc(blen); - if (param == NULL) - return -1; - - param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT; - param->u.generic_elem.len = wpa_ie_len; - os_memcpy(param->u.generic_elem.data, wpa_ie, wpa_ie_len); - res = hostapd_ioctl(drv, param, blen, 1); - - os_free(param); - - return res; -} - - -static int prism2param(struct wpa_driver_hostap_data *drv, int param, - int value) -{ - struct iwreq iwr; - int *i, ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - i = (int *) iwr.u.name; - *i++ = param; - *i++ = value; - - if (ioctl(drv->sock, PRISM2_IOCTL_PRISM2_PARAM, &iwr) < 0) { - perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]"); - ret = -1; - } - return ret; -} - - -static int wpa_driver_hostap_set_wpa(void *priv, int enabled) -{ - struct wpa_driver_hostap_data *drv = priv; - int ret = 0; - - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - - if (!enabled && wpa_driver_hostap_set_wpa_ie(drv, NULL, 0) < 0) - ret = -1; - if (prism2param(drv, PRISM2_PARAM_HOST_ROAMING, enabled ? 2 : 0) < 0) - ret = -1; - if (prism2param(drv, PRISM2_PARAM_WPA, enabled) < 0) - ret = -1; - - return ret; -} - - -static void show_set_key_error(struct prism2_hostapd_param *param) -{ - switch (param->u.crypt.err) { - case HOSTAP_CRYPT_ERR_UNKNOWN_ALG: - wpa_printf(MSG_INFO, "Unknown algorithm '%s'.", - param->u.crypt.alg); - wpa_printf(MSG_INFO, "You may need to load kernel module to " - "register that algorithm."); - wpa_printf(MSG_INFO, "E.g., 'modprobe hostap_crypt_wep' for " - "WEP."); - break; - case HOSTAP_CRYPT_ERR_UNKNOWN_ADDR: - wpa_printf(MSG_INFO, "Unknown address " MACSTR ".", - MAC2STR(param->sta_addr)); - break; - case HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED: - wpa_printf(MSG_INFO, "Crypt algorithm initialization failed."); - break; - case HOSTAP_CRYPT_ERR_KEY_SET_FAILED: - wpa_printf(MSG_INFO, "Key setting failed."); - break; - case HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED: - wpa_printf(MSG_INFO, "TX key index setting failed."); - break; - case HOSTAP_CRYPT_ERR_CARD_CONF_FAILED: - wpa_printf(MSG_INFO, "Card configuration failed."); - break; - } -} - - -static int wpa_driver_hostap_set_key(void *priv, wpa_alg alg, - const u8 *addr, int key_idx, - int set_tx, const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_hostap_data *drv = priv; - struct prism2_hostapd_param *param; - u8 *buf; - size_t blen; - int ret = 0; - char *alg_name; - - switch (alg) { - case WPA_ALG_NONE: - alg_name = "none"; - break; - case WPA_ALG_WEP: - alg_name = "WEP"; - break; - case WPA_ALG_TKIP: - alg_name = "TKIP"; - break; - case WPA_ALG_CCMP: - alg_name = "CCMP"; - break; - default: - return -1; - } - - wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu " - "key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx, - (unsigned long) seq_len, (unsigned long) key_len); - - if (seq_len > 8) - return -2; - - blen = sizeof(*param) + key_len; - buf = os_zalloc(blen); - if (buf == NULL) - return -1; - - param = (struct prism2_hostapd_param *) buf; - param->cmd = PRISM2_SET_ENCRYPTION; - /* TODO: In theory, STA in client mode can use five keys; four default - * keys for receiving (with keyidx 0..3) and one individual key for - * both transmitting and receiving (keyidx 0) _unicast_ packets. Now, - * keyidx 0 is reserved for this unicast use and default keys can only - * use keyidx 1..3 (i.e., default key with keyidx 0 is not supported). - * This should be fine for more or less all cases, but for completeness - * sake, the driver could be enhanced to support the missing key. */ -#if 0 - if (addr == NULL) - os_memset(param->sta_addr, 0xff, ETH_ALEN); - else - os_memcpy(param->sta_addr, addr, ETH_ALEN); -#else - os_memset(param->sta_addr, 0xff, ETH_ALEN); -#endif - os_strlcpy((char *) param->u.crypt.alg, alg_name, - HOSTAP_CRYPT_ALG_NAME_LEN); - param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0; - param->u.crypt.idx = key_idx; - os_memcpy(param->u.crypt.seq, seq, seq_len); - param->u.crypt.key_len = key_len; - os_memcpy((u8 *) (param + 1), key, key_len); - - if (hostapd_ioctl(drv, param, blen, 1)) { - wpa_printf(MSG_WARNING, "Failed to set encryption."); - show_set_key_error(param); - ret = -1; - } - os_free(buf); - - return ret; -} - - -static int wpa_driver_hostap_set_countermeasures(void *priv, int enabled) -{ - struct wpa_driver_hostap_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - return prism2param(drv, PRISM2_PARAM_TKIP_COUNTERMEASURES, enabled); -} - - -static int wpa_driver_hostap_set_drop_unencrypted(void *priv, int enabled) -{ - struct wpa_driver_hostap_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - return prism2param(drv, PRISM2_PARAM_DROP_UNENCRYPTED, enabled); -} - - -static int wpa_driver_hostap_reset(struct wpa_driver_hostap_data *drv, - int type) -{ - struct iwreq iwr; - int *i, ret = 0; - - wpa_printf(MSG_DEBUG, "%s: type=%d", __FUNCTION__, type); - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - i = (int *) iwr.u.name; - *i++ = type; - - if (ioctl(drv->sock, PRISM2_IOCTL_RESET, &iwr) < 0) { - perror("ioctl[PRISM2_IOCTL_RESET]"); - ret = -1; - } - return ret; -} - - -static int wpa_driver_hostap_mlme(struct wpa_driver_hostap_data *drv, - const u8 *addr, int cmd, int reason_code) -{ - struct prism2_hostapd_param param; - int ret; - - /* There does not seem to be a better way of deauthenticating or - * disassociating with Prism2/2.5/3 than sending the management frame - * and then resetting the Port0 to make sure both the AP and the STA - * end up in disconnected state. */ - os_memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_MLME; - os_memcpy(param.sta_addr, addr, ETH_ALEN); - param.u.mlme.cmd = cmd; - param.u.mlme.reason_code = reason_code; - ret = hostapd_ioctl(drv, ¶m, sizeof(param), 1); - if (ret == 0) { - os_sleep(0, 100000); - ret = wpa_driver_hostap_reset(drv, 2); - } - return ret; -} - - -static int wpa_driver_hostap_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_hostap_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - return wpa_driver_hostap_mlme(drv, addr, MLME_STA_DEAUTH, - reason_code); -} - - -static int wpa_driver_hostap_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_hostap_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - return wpa_driver_hostap_mlme(drv, addr, MLME_STA_DISASSOC, - reason_code); -} - - -static int -wpa_driver_hostap_associate(void *priv, - struct wpa_driver_associate_params *params) -{ - struct wpa_driver_hostap_data *drv = priv; - int ret = 0; - int allow_unencrypted_eapol; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (params->mode != drv->current_mode) { - /* At the moment, Host AP driver requires host_roaming=2 for - * infrastructure mode and host_roaming=0 for adhoc. */ - if (prism2param(drv, PRISM2_PARAM_HOST_ROAMING, - params->mode == IEEE80211_MODE_IBSS ? 0 : 2) < - 0) { - wpa_printf(MSG_DEBUG, "%s: failed to set host_roaming", - __func__); - } - drv->current_mode = params->mode; - } - - if (prism2param(drv, PRISM2_PARAM_PRIVACY_INVOKED, - params->key_mgmt_suite != KEY_MGMT_NONE) < 0) - ret = -1; - if (wpa_driver_hostap_set_wpa_ie(drv, params->wpa_ie, - params->wpa_ie_len) < 0) - ret = -1; - if (wpa_driver_wext_set_mode(drv->wext, params->mode) < 0) - ret = -1; - if (params->freq && - wpa_driver_wext_set_freq(drv->wext, params->freq) < 0) - ret = -1; - if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, params->ssid_len) - < 0) - ret = -1; - if (wpa_driver_wext_set_bssid(drv->wext, params->bssid) < 0) - ret = -1; - - /* Allow unencrypted EAPOL messages even if pairwise keys are set when - * not using WPA. IEEE 802.1X specifies that these frames are not - * encrypted, but WPA encrypts them when pairwise keys are in use. */ - if (params->key_mgmt_suite == KEY_MGMT_802_1X || - params->key_mgmt_suite == KEY_MGMT_PSK) - allow_unencrypted_eapol = 0; - else - allow_unencrypted_eapol = 1; - - if (prism2param(drv, PRISM2_PARAM_IEEE_802_1X, - allow_unencrypted_eapol) < 0) { - wpa_printf(MSG_DEBUG, "hostap: Failed to configure " - "ieee_802_1x param"); - /* Ignore this error.. driver_hostap.c can also be used with - * other drivers that do not support this prism2_param. */ - } - - return ret; -} - - -static int wpa_driver_hostap_scan(void *priv, const u8 *ssid, size_t ssid_len) -{ - struct wpa_driver_hostap_data *drv = priv; - struct prism2_hostapd_param param; - int ret; - - if (ssid == NULL) { - /* Use standard Linux Wireless Extensions ioctl if possible - * because some drivers using hostap code in wpa_supplicant - * might not support Host AP specific scan request (with SSID - * info). */ - return wpa_driver_wext_scan(drv->wext, ssid, ssid_len); - } - - if (ssid_len > 32) - ssid_len = 32; - - os_memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_SCAN_REQ; - param.u.scan_req.ssid_len = ssid_len; - os_memcpy(param.u.scan_req.ssid, ssid, ssid_len); - ret = hostapd_ioctl(drv, ¶m, sizeof(param), 1); - - /* Not all drivers generate "scan completed" wireless event, so try to - * read results after a timeout. */ - eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv->wext, - drv->ctx); - eloop_register_timeout(3, 0, wpa_driver_wext_scan_timeout, drv->wext, - drv->ctx); - - return ret; -} - - -static int wpa_driver_hostap_set_auth_alg(void *priv, int auth_alg) -{ - struct wpa_driver_hostap_data *drv = priv; - int algs = 0; - - if (auth_alg & AUTH_ALG_OPEN_SYSTEM) - algs |= 1; - if (auth_alg & AUTH_ALG_SHARED_KEY) - algs |= 2; - if (auth_alg & AUTH_ALG_LEAP) - algs |= 4; - if (algs == 0) - algs = 1; /* at least one algorithm should be set */ - - return prism2param(drv, PRISM2_PARAM_AP_AUTH_ALGS, algs); -} - - -static int wpa_driver_hostap_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_hostap_data *drv = priv; - return wpa_driver_wext_get_bssid(drv->wext, bssid); -} - - -static int wpa_driver_hostap_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_hostap_data *drv = priv; - return wpa_driver_wext_get_ssid(drv->wext, ssid); -} - - -static struct wpa_scan_results * wpa_driver_hostap_get_scan_results(void *priv) -{ - struct wpa_driver_hostap_data *drv = priv; - return wpa_driver_wext_get_scan_results(drv->wext); -} - - -static int wpa_driver_hostap_set_operstate(void *priv, int state) -{ - struct wpa_driver_hostap_data *drv = priv; - return wpa_driver_wext_set_operstate(drv->wext, state); -} - - -static void * wpa_driver_hostap_init(void *ctx, const char *ifname) -{ - struct wpa_driver_hostap_data *drv; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->wext = wpa_driver_wext_init(ctx, ifname); - if (drv->wext == NULL) { - os_free(drv); - return NULL; - } - - drv->ctx = ctx; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - drv->sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->sock < 0) { - perror("socket"); - wpa_driver_wext_deinit(drv->wext); - os_free(drv); - return NULL; - } - - if (os_strncmp(ifname, "wlan", 4) == 0) { - /* - * Host AP driver may use both wlan# and wifi# interface in - * wireless events. - */ - char ifname2[IFNAMSIZ + 1]; - os_strlcpy(ifname2, ifname, sizeof(ifname2)); - os_memcpy(ifname2, "wifi", 4); - wpa_driver_wext_alternative_ifindex(drv->wext, ifname2); - } - - return drv; -} - - -static void wpa_driver_hostap_deinit(void *priv) -{ - struct wpa_driver_hostap_data *drv = priv; - wpa_driver_wext_deinit(drv->wext); - close(drv->sock); - os_free(drv); -} - - -const struct wpa_driver_ops wpa_driver_hostap_ops = { - .name = "hostap", - .desc = "Host AP driver (Intersil Prism2/2.5/3)", - .get_bssid = wpa_driver_hostap_get_bssid, - .get_ssid = wpa_driver_hostap_get_ssid, - .set_wpa = wpa_driver_hostap_set_wpa, - .set_key = wpa_driver_hostap_set_key, - .set_countermeasures = wpa_driver_hostap_set_countermeasures, - .set_drop_unencrypted = wpa_driver_hostap_set_drop_unencrypted, - .scan = wpa_driver_hostap_scan, - .get_scan_results2 = wpa_driver_hostap_get_scan_results, - .deauthenticate = wpa_driver_hostap_deauthenticate, - .disassociate = wpa_driver_hostap_disassociate, - .associate = wpa_driver_hostap_associate, - .set_auth_alg = wpa_driver_hostap_set_auth_alg, - .init = wpa_driver_hostap_init, - .deinit = wpa_driver_hostap_deinit, - .set_operstate = wpa_driver_hostap_set_operstate, -}; diff --git a/contrib/hostapd/src/drivers/driver_hostap.h b/contrib/hostapd/src/drivers/driver_hostap.h deleted file mode 100644 index a2508ed924..0000000000 --- a/contrib/hostapd/src/drivers/driver_hostap.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * WPA Supplicant - driver interaction with Linux Host AP driver - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef HOSTAP_DRIVER_H -#define HOSTAP_DRIVER_H - -#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0) -#define PRISM2_IOCTL_RESET (SIOCIWFIRSTPRIV + 6) -#define PRISM2_IOCTL_HOSTAPD (SIOCDEVPRIVATE + 14) - -/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes: */ -enum { - /* PRISM2_PARAM_PTYPE = 1, */ /* REMOVED 2003-10-22 */ - PRISM2_PARAM_TXRATECTRL = 2, - PRISM2_PARAM_BEACON_INT = 3, - PRISM2_PARAM_PSEUDO_IBSS = 4, - PRISM2_PARAM_ALC = 5, - /* PRISM2_PARAM_TXPOWER = 6, */ /* REMOVED 2003-10-22 */ - PRISM2_PARAM_DUMP = 7, - PRISM2_PARAM_OTHER_AP_POLICY = 8, - PRISM2_PARAM_AP_MAX_INACTIVITY = 9, - PRISM2_PARAM_AP_BRIDGE_PACKETS = 10, - PRISM2_PARAM_DTIM_PERIOD = 11, - PRISM2_PARAM_AP_NULLFUNC_ACK = 12, - PRISM2_PARAM_MAX_WDS = 13, - PRISM2_PARAM_AP_AUTOM_AP_WDS = 14, - PRISM2_PARAM_AP_AUTH_ALGS = 15, - PRISM2_PARAM_MONITOR_ALLOW_FCSERR = 16, - PRISM2_PARAM_HOST_ENCRYPT = 17, - PRISM2_PARAM_HOST_DECRYPT = 18, - PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX = 19, - PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX = 20, - PRISM2_PARAM_HOST_ROAMING = 21, - PRISM2_PARAM_BCRX_STA_KEY = 22, - PRISM2_PARAM_IEEE_802_1X = 23, - PRISM2_PARAM_ANTSEL_TX = 24, - PRISM2_PARAM_ANTSEL_RX = 25, - PRISM2_PARAM_MONITOR_TYPE = 26, - PRISM2_PARAM_WDS_TYPE = 27, - PRISM2_PARAM_HOSTSCAN = 28, - PRISM2_PARAM_AP_SCAN = 29, - PRISM2_PARAM_ENH_SEC = 30, - PRISM2_PARAM_IO_DEBUG = 31, - PRISM2_PARAM_BASIC_RATES = 32, - PRISM2_PARAM_OPER_RATES = 33, - PRISM2_PARAM_HOSTAPD = 34, - PRISM2_PARAM_HOSTAPD_STA = 35, - PRISM2_PARAM_WPA = 36, - PRISM2_PARAM_PRIVACY_INVOKED = 37, - PRISM2_PARAM_TKIP_COUNTERMEASURES = 38, - PRISM2_PARAM_DROP_UNENCRYPTED = 39, - PRISM2_PARAM_SCAN_CHANNEL_MASK = 40, -}; - -/* PRISM2_IOCTL_HOSTAPD ioctl() cmd: */ -enum { - PRISM2_HOSTAPD_FLUSH = 1, - PRISM2_HOSTAPD_ADD_STA = 2, - PRISM2_HOSTAPD_REMOVE_STA = 3, - PRISM2_HOSTAPD_GET_INFO_STA = 4, - /* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */ - PRISM2_SET_ENCRYPTION = 6, - PRISM2_GET_ENCRYPTION = 7, - PRISM2_HOSTAPD_SET_FLAGS_STA = 8, - PRISM2_HOSTAPD_GET_RID = 9, - PRISM2_HOSTAPD_SET_RID = 10, - PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR = 11, - PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12, - PRISM2_HOSTAPD_MLME = 13, - PRISM2_HOSTAPD_SCAN_REQ = 14, - PRISM2_HOSTAPD_STA_CLEAR_STATS = 15, -}; - -#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024 -#define PRISM2_HOSTAPD_RID_HDR_LEN \ -((size_t) (&((struct prism2_hostapd_param *) 0)->u.rid.data)) -#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \ -((size_t) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data)) - -/* Maximum length for algorithm names (-1 for nul termination) used in ioctl() - */ -#define HOSTAP_CRYPT_ALG_NAME_LEN 16 - - -struct prism2_hostapd_param { - u32 cmd; - u8 sta_addr[ETH_ALEN]; - union { - struct { - u16 aid; - u16 capability; - u8 tx_supp_rates; - } add_sta; - struct { - u32 inactive_sec; - } get_info_sta; - struct { - u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN]; - u32 flags; - u32 err; - u8 idx; - u8 seq[8]; /* sequence counter (set: RX, get: TX) */ - u16 key_len; - u8 key[0]; - } crypt; - struct { - u32 flags_and; - u32 flags_or; - } set_flags_sta; - struct { - u16 rid; - u16 len; - u8 data[0]; - } rid; - struct { - u8 len; - u8 data[0]; - } generic_elem; - struct { -#define MLME_STA_DEAUTH 0 -#define MLME_STA_DISASSOC 1 - u16 cmd; - u16 reason_code; - } mlme; - struct { - u8 ssid_len; - u8 ssid[32]; - } scan_req; - } u; -}; - -#define HOSTAP_CRYPT_FLAG_SET_TX_KEY 0x01 -#define HOSTAP_CRYPT_FLAG_PERMANENT 0x02 - -#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2 -#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3 -#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4 -#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5 -#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6 -#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7 - -#endif /* HOSTAP_DRIVER_H */ diff --git a/contrib/hostapd/src/drivers/driver_ipw.c b/contrib/hostapd/src/drivers/driver_ipw.c deleted file mode 100644 index 3c19cccf46..0000000000 --- a/contrib/hostapd/src/drivers/driver_ipw.c +++ /dev/null @@ -1,463 +0,0 @@ -/* - * WPA Supplicant - driver interaction with Linux ipw2100/2200 drivers - * Copyright (c) 2005 Zhu Yi - * Copyright (c) 2004 Lubomir Gelo - * Copyright (c) 2003-2004, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * Please note that ipw2100/2200 drivers change to use generic Linux wireless - * extensions if the kernel includes support for WE-18 or newer (Linux 2.6.13 - * or newer). driver_wext.c should be used in those cases. - */ - -#include "includes.h" -#include - -#include "wireless_copy.h" -#include "common.h" -#include "driver.h" -#include "driver_wext.h" - -struct wpa_driver_ipw_data { - void *wext; /* private data for driver_wext */ - void *ctx; - char ifname[IFNAMSIZ + 1]; - int sock; -}; - -/* following definitions must be kept in sync with ipw2100.c and ipw2200.c */ - -#define IPW_IOCTL_WPA_SUPPLICANT SIOCIWFIRSTPRIV+30 - -#define IPW_CMD_SET_WPA_PARAM 1 -#define IPW_CMD_SET_WPA_IE 2 -#define IPW_CMD_SET_ENCRYPTION 3 -#define IPW_CMD_MLME 4 - -#define IPW_PARAM_WPA_ENABLED 1 -#define IPW_PARAM_TKIP_COUNTERMEASURES 2 -#define IPW_PARAM_DROP_UNENCRYPTED 3 -#define IPW_PARAM_PRIVACY_INVOKED 4 -#define IPW_PARAM_AUTH_ALGS 5 -#define IPW_PARAM_IEEE_802_1X 6 - -#define IPW_MLME_STA_DEAUTH 1 -#define IPW_MLME_STA_DISASSOC 2 - -#define IPW_CRYPT_ERR_UNKNOWN_ALG 2 -#define IPW_CRYPT_ERR_UNKNOWN_ADDR 3 -#define IPW_CRYPT_ERR_CRYPT_INIT_FAILED 4 -#define IPW_CRYPT_ERR_KEY_SET_FAILED 5 -#define IPW_CRYPT_ERR_TX_KEY_SET_FAILED 6 -#define IPW_CRYPT_ERR_CARD_CONF_FAILED 7 - -#define IPW_CRYPT_ALG_NAME_LEN 16 - -struct ipw_param { - u32 cmd; - u8 sta_addr[ETH_ALEN]; - union { - struct { - u8 name; - u32 value; - } wpa_param; - struct { - u32 len; - u8 reserved[32]; - u8 data[0]; - } wpa_ie; - struct{ - u32 command; - u32 reason_code; - } mlme; - struct { - u8 alg[IPW_CRYPT_ALG_NAME_LEN]; - u8 set_tx; - u32 err; - u8 idx; - u8 seq[8]; - u16 key_len; - u8 key[0]; - } crypt; - - } u; -}; - -/* end of ipw2100.c and ipw2200.c code */ - -static int ipw_ioctl(struct wpa_driver_ipw_data *drv, - struct ipw_param *param, int len, int show_err) -{ - struct iwreq iwr; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) param; - iwr.u.data.length = len; - - if (ioctl(drv->sock, IPW_IOCTL_WPA_SUPPLICANT, &iwr) < 0) { - int ret = errno; - if (show_err) - perror("ioctl[IPW_IOCTL_WPA_SUPPLICANT]"); - return ret; - } - - return 0; -} - - -static void ipw_show_set_key_error(struct ipw_param *param) -{ - switch (param->u.crypt.err) { - case IPW_CRYPT_ERR_UNKNOWN_ALG: - wpa_printf(MSG_INFO, "Unknown algorithm '%s'.", - param->u.crypt.alg); - wpa_printf(MSG_INFO, "You may need to load kernel module to " - "register that algorithm."); - wpa_printf(MSG_INFO, "E.g., 'modprobe ieee80211_crypt_wep' for" - " WEP."); - break; - case IPW_CRYPT_ERR_UNKNOWN_ADDR: - wpa_printf(MSG_INFO, "Unknown address " MACSTR ".", - MAC2STR(param->sta_addr)); - break; - case IPW_CRYPT_ERR_CRYPT_INIT_FAILED: - wpa_printf(MSG_INFO, "Crypt algorithm initialization failed."); - break; - case IPW_CRYPT_ERR_KEY_SET_FAILED: - wpa_printf(MSG_INFO, "Key setting failed."); - break; - case IPW_CRYPT_ERR_TX_KEY_SET_FAILED: - wpa_printf(MSG_INFO, "TX key index setting failed."); - break; - case IPW_CRYPT_ERR_CARD_CONF_FAILED: - wpa_printf(MSG_INFO, "Card configuration failed."); - break; - } -} - - -static int ipw_set_wpa_ie(struct wpa_driver_ipw_data *drv, - const u8 *wpa_ie, size_t wpa_ie_len) -{ - struct ipw_param *param; - int ret; - size_t blen = sizeof(*param) + wpa_ie_len; - - param = os_zalloc(blen); - if (param == NULL) - return -1; - - param->cmd = IPW_CMD_SET_WPA_IE; - param->u.wpa_ie.len = wpa_ie_len; - os_memcpy(param->u.wpa_ie.data, wpa_ie, wpa_ie_len); - - ret = ipw_ioctl(drv, param, blen, 1); - - os_free(param); - return ret; -} - - -static int ipw_set_wpa_param(struct wpa_driver_ipw_data *drv, u8 name, - u32 value) -{ - struct ipw_param param; - - os_memset(¶m, 0, sizeof(param)); - param.cmd = IPW_CMD_SET_WPA_PARAM; - param.u.wpa_param.name = name; - param.u.wpa_param.value = value; - - return ipw_ioctl(drv, ¶m, sizeof(param), 1); -} - - -static int ipw_mlme(struct wpa_driver_ipw_data *drv, const u8 *addr, - int cmd, int reason) -{ - struct ipw_param param; - - os_memset(¶m, 0, sizeof(param)); - os_memcpy(param.sta_addr, addr, ETH_ALEN); - param.cmd = IPW_CMD_MLME; - param.u.mlme.command = cmd; - param.u.mlme.reason_code = reason; - - return ipw_ioctl(drv, ¶m, sizeof(param), 1); -} - - -static int wpa_driver_ipw_set_wpa(void *priv, int enabled) -{ - struct wpa_driver_ipw_data *drv = priv; - int ret = 0; - - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - - if (!enabled && ipw_set_wpa_ie(drv, NULL, 0) < 0) - ret = -1; - - if (ipw_set_wpa_param(drv, IPW_PARAM_WPA_ENABLED, enabled) < 0) - ret = -1; - - return ret; -} - - -static int wpa_driver_ipw_set_key(void *priv, wpa_alg alg, - const u8 *addr, int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_ipw_data *drv = priv; - struct ipw_param *param; - u8 *buf; - size_t blen; - int ret = 0; - char *alg_name; - - switch (alg) { - case WPA_ALG_NONE: - alg_name = "none"; - break; - case WPA_ALG_WEP: - alg_name = "WEP"; - break; - case WPA_ALG_TKIP: - alg_name = "TKIP"; - break; - case WPA_ALG_CCMP: - alg_name = "CCMP"; - break; - default: - return -1; - } - - wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu " - "key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx, - (unsigned long) seq_len, (unsigned long) key_len); - - if (seq_len > 8) - return -2; - - blen = sizeof(*param) + key_len; - buf = os_zalloc(blen); - if (buf == NULL) - return -1; - - param = (struct ipw_param *) buf; - param->cmd = IPW_CMD_SET_ENCRYPTION; - os_memset(param->sta_addr, 0xff, ETH_ALEN); - os_strlcpy((char *) param->u.crypt.alg, alg_name, - IPW_CRYPT_ALG_NAME_LEN); - param->u.crypt.set_tx = set_tx ? 1 : 0; - param->u.crypt.idx = key_idx; - os_memcpy(param->u.crypt.seq, seq, seq_len); - param->u.crypt.key_len = key_len; - os_memcpy((u8 *) (param + 1), key, key_len); - - if (ipw_ioctl(drv, param, blen, 1)) { - wpa_printf(MSG_WARNING, "Failed to set encryption."); - ipw_show_set_key_error(param); - ret = -1; - } - os_free(buf); - - return ret; -} - - -static int wpa_driver_ipw_set_countermeasures(void *priv, int enabled) -{ - struct wpa_driver_ipw_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - return ipw_set_wpa_param(drv, IPW_PARAM_TKIP_COUNTERMEASURES, - enabled); - -} - - -static int wpa_driver_ipw_set_drop_unencrypted(void *priv, int enabled) -{ - struct wpa_driver_ipw_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - return ipw_set_wpa_param(drv, IPW_PARAM_DROP_UNENCRYPTED, - enabled); -} - - -static int wpa_driver_ipw_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_ipw_data *drv = priv; - return ipw_mlme(drv, addr, IPW_MLME_STA_DEAUTH, reason_code); -} - - -static int wpa_driver_ipw_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_ipw_data *drv = priv; - return ipw_mlme(drv, addr, IPW_MLME_STA_DISASSOC, reason_code); -} - - -static int -wpa_driver_ipw_associate(void *priv, struct wpa_driver_associate_params *params) -{ - struct wpa_driver_ipw_data *drv = priv; - int ret = 0; - int unencrypted_eapol; - - if (ipw_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0) - ret = -1; - if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, - params->ssid_len) < 0) - ret = -1; - if (wpa_driver_wext_set_bssid(drv->wext, params->bssid) < 0) - ret = -1; - - if (params->key_mgmt_suite == KEY_MGMT_802_1X || - params->key_mgmt_suite == KEY_MGMT_PSK) - unencrypted_eapol = 0; - else - unencrypted_eapol = 1; - - if (ipw_set_wpa_param(drv, IPW_PARAM_IEEE_802_1X, - unencrypted_eapol) < 0) { - wpa_printf(MSG_DEBUG, "ipw: Failed to configure " - "ieee_802_1x param"); - } - - return ret; -} - - -static int wpa_driver_ipw_set_auth_alg(void *priv, int auth_alg) -{ - struct wpa_driver_ipw_data *drv = priv; - int algs = 0; - - if (auth_alg & AUTH_ALG_OPEN_SYSTEM) - algs |= 1; - if (auth_alg & AUTH_ALG_SHARED_KEY) - algs |= 2; - if (auth_alg & AUTH_ALG_LEAP) - algs |= 4; - if (algs == 0) - algs = 1; /* at least one algorithm should be set */ - - wpa_printf(MSG_DEBUG, "%s: auth_alg=0x%x", __FUNCTION__, algs); - return ipw_set_wpa_param(drv, IPW_PARAM_AUTH_ALGS, algs); -} - - -static int wpa_driver_ipw_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_ipw_data *drv = priv; - return wpa_driver_wext_get_bssid(drv->wext, bssid); -} - - -static int wpa_driver_ipw_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_ipw_data *drv = priv; - return wpa_driver_wext_get_ssid(drv->wext, ssid); -} - - -static int wpa_driver_ipw_scan(void *priv, const u8 *ssid, size_t ssid_len) -{ - struct wpa_driver_ipw_data *drv = priv; - return wpa_driver_wext_scan(drv->wext, ssid, ssid_len); -} - - -static struct wpa_scan_results * wpa_driver_ipw_get_scan_results(void *priv) -{ - struct wpa_driver_ipw_data *drv = priv; - return wpa_driver_wext_get_scan_results(drv->wext); -} - - -static int wpa_driver_ipw_set_operstate(void *priv, int state) -{ - struct wpa_driver_ipw_data *drv = priv; - return wpa_driver_wext_set_operstate(drv->wext, state); -} - - -static void * wpa_driver_ipw_init(void *ctx, const char *ifname) -{ - struct wpa_driver_ipw_data *drv; - int ver; - - wpa_printf(MSG_DEBUG, "%s is called", __FUNCTION__); - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->wext = wpa_driver_wext_init(ctx, ifname); - if (drv->wext == NULL) { - os_free(drv); - return NULL; - } - - ver = wpa_driver_wext_get_version(drv->wext); - if (ver >= 18) { - wpa_printf(MSG_WARNING, "Linux wireless extensions version %d " - "detected.", ver); - wpa_printf(MSG_WARNING, "ipw2x00 driver uses driver_wext " - "(-Dwext) instead of driver_ipw."); - } - - drv->ctx = ctx; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - drv->sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->sock < 0) { - wpa_driver_wext_deinit(drv->wext); - os_free(drv); - return NULL; - } - - return drv; -} - - -static void wpa_driver_ipw_deinit(void *priv) -{ - struct wpa_driver_ipw_data *drv = priv; - wpa_driver_wext_deinit(drv->wext); - close(drv->sock); - os_free(drv); -} - - -const struct wpa_driver_ops wpa_driver_ipw_ops = { - .name = "ipw", - .desc = "Intel ipw2100/2200 driver (old; use wext with Linux 2.6.13 " - "or newer)", - .get_bssid = wpa_driver_ipw_get_bssid, - .get_ssid = wpa_driver_ipw_get_ssid, - .set_wpa = wpa_driver_ipw_set_wpa, - .set_key = wpa_driver_ipw_set_key, - .set_countermeasures = wpa_driver_ipw_set_countermeasures, - .set_drop_unencrypted = wpa_driver_ipw_set_drop_unencrypted, - .scan = wpa_driver_ipw_scan, - .get_scan_results2 = wpa_driver_ipw_get_scan_results, - .deauthenticate = wpa_driver_ipw_deauthenticate, - .disassociate = wpa_driver_ipw_disassociate, - .associate = wpa_driver_ipw_associate, - .set_auth_alg = wpa_driver_ipw_set_auth_alg, - .init = wpa_driver_ipw_init, - .deinit = wpa_driver_ipw_deinit, - .set_operstate = wpa_driver_ipw_set_operstate, -}; diff --git a/contrib/hostapd/src/drivers/driver_madwifi.c b/contrib/hostapd/src/drivers/driver_madwifi.c deleted file mode 100644 index 7521037234..0000000000 --- a/contrib/hostapd/src/drivers/driver_madwifi.c +++ /dev/null @@ -1,601 +0,0 @@ -/* - * WPA Supplicant - driver interaction with MADWIFI 802.11 driver - * Copyright (c) 2004, Sam Leffler - * Copyright (c) 2004-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * Please note that madwifi supports WPA configuration via Linux wireless - * extensions and if the kernel includes support for this, driver_wext.c should - * be used instead of this driver wrapper. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "driver.h" -#include "driver_wext.h" -#include "eloop.h" -#include "ieee802_11_defs.h" -#include "wireless_copy.h" - -/* - * Avoid conflicts with wpa_supplicant definitions by undefining a definition. - */ -#undef WME_OUI_TYPE - -#include -#include -#ifdef WME_NUM_AC -/* Assume this is built against BSD branch of madwifi driver. */ -#define MADWIFI_BSD -#include -#endif /* WME_NUM_AC */ -#include -#include - - -#ifdef IEEE80211_IOCTL_SETWMMPARAMS -/* Assume this is built against madwifi-ng */ -#define MADWIFI_NG -#endif /* IEEE80211_IOCTL_SETWMMPARAMS */ - -struct wpa_driver_madwifi_data { - void *wext; /* private data for driver_wext */ - void *ctx; - char ifname[IFNAMSIZ + 1]; - int sock; -}; - -static int -set80211priv(struct wpa_driver_madwifi_data *drv, int op, void *data, int len, - int show_err) -{ - struct iwreq iwr; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - if (len < IFNAMSIZ && - op != IEEE80211_IOCTL_SET_APPIEBUF) { - /* - * Argument data fits inline; put it there. - */ - os_memcpy(iwr.u.name, data, len); - } else { - /* - * Argument data too big for inline transfer; setup a - * parameter block instead; the kernel will transfer - * the data for the driver. - */ - iwr.u.data.pointer = data; - iwr.u.data.length = len; - } - - if (ioctl(drv->sock, op, &iwr) < 0) { - if (show_err) { -#ifdef MADWIFI_NG - int first = IEEE80211_IOCTL_SETPARAM; - int last = IEEE80211_IOCTL_KICKMAC; - static const char *opnames[] = { - "ioctl[IEEE80211_IOCTL_SETPARAM]", - "ioctl[IEEE80211_IOCTL_GETPARAM]", - "ioctl[IEEE80211_IOCTL_SETMODE]", - "ioctl[IEEE80211_IOCTL_GETMODE]", - "ioctl[IEEE80211_IOCTL_SETWMMPARAMS]", - "ioctl[IEEE80211_IOCTL_GETWMMPARAMS]", - "ioctl[IEEE80211_IOCTL_SETCHANLIST]", - "ioctl[IEEE80211_IOCTL_GETCHANLIST]", - "ioctl[IEEE80211_IOCTL_CHANSWITCH]", - NULL, - "ioctl[IEEE80211_IOCTL_SET_APPIEBUF]", - "ioctl[IEEE80211_IOCTL_GETSCANRESULTS]", - NULL, - "ioctl[IEEE80211_IOCTL_GETCHANINFO]", - "ioctl[IEEE80211_IOCTL_SETOPTIE]", - "ioctl[IEEE80211_IOCTL_GETOPTIE]", - "ioctl[IEEE80211_IOCTL_SETMLME]", - NULL, - "ioctl[IEEE80211_IOCTL_SETKEY]", - NULL, - "ioctl[IEEE80211_IOCTL_DELKEY]", - NULL, - "ioctl[IEEE80211_IOCTL_ADDMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_DELMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_WDSMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_WDSDELMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_KICKMAC]", - }; -#else /* MADWIFI_NG */ - int first = IEEE80211_IOCTL_SETPARAM; - int last = IEEE80211_IOCTL_CHANLIST; - static const char *opnames[] = { - "ioctl[IEEE80211_IOCTL_SETPARAM]", - "ioctl[IEEE80211_IOCTL_GETPARAM]", - "ioctl[IEEE80211_IOCTL_SETKEY]", - "ioctl[IEEE80211_IOCTL_GETKEY]", - "ioctl[IEEE80211_IOCTL_DELKEY]", - NULL, - "ioctl[IEEE80211_IOCTL_SETMLME]", - NULL, - "ioctl[IEEE80211_IOCTL_SETOPTIE]", - "ioctl[IEEE80211_IOCTL_GETOPTIE]", - "ioctl[IEEE80211_IOCTL_ADDMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_DELMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_CHANLIST]", - }; -#endif /* MADWIFI_NG */ - int idx = op - first; - if (first <= op && op <= last && - idx < (int) (sizeof(opnames) / sizeof(opnames[0])) - && opnames[idx]) - perror(opnames[idx]); - else - perror("ioctl[unknown???]"); - } - return -1; - } - return 0; -} - -static int -set80211param(struct wpa_driver_madwifi_data *drv, int op, int arg, - int show_err) -{ - struct iwreq iwr; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.mode = op; - os_memcpy(iwr.u.name+sizeof(u32), &arg, sizeof(arg)); - - if (ioctl(drv->sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) { - if (show_err) - perror("ioctl[IEEE80211_IOCTL_SETPARAM]"); - return -1; - } - return 0; -} - -static int -wpa_driver_madwifi_set_wpa_ie(struct wpa_driver_madwifi_data *drv, - const u8 *wpa_ie, size_t wpa_ie_len) -{ - struct iwreq iwr; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - /* NB: SETOPTIE is not fixed-size so must not be inlined */ - iwr.u.data.pointer = (void *) wpa_ie; - iwr.u.data.length = wpa_ie_len; - - if (ioctl(drv->sock, IEEE80211_IOCTL_SETOPTIE, &iwr) < 0) { - perror("ioctl[IEEE80211_IOCTL_SETOPTIE]"); - return -1; - } - return 0; -} - -static int -wpa_driver_madwifi_del_key(struct wpa_driver_madwifi_data *drv, int key_idx, - const u8 *addr) -{ - struct ieee80211req_del_key wk; - - wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __FUNCTION__, key_idx); - os_memset(&wk, 0, sizeof(wk)); - wk.idk_keyix = key_idx; - if (addr != NULL) - os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); - - return set80211priv(drv, IEEE80211_IOCTL_DELKEY, &wk, sizeof(wk), 1); -} - -static int -wpa_driver_madwifi_set_key(void *priv, wpa_alg alg, - const u8 *addr, int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_madwifi_data *drv = priv; - struct ieee80211req_key wk; - char *alg_name; - u_int8_t cipher; - - if (alg == WPA_ALG_NONE) - return wpa_driver_madwifi_del_key(drv, key_idx, addr); - - switch (alg) { - case WPA_ALG_WEP: - if (addr == NULL || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", - ETH_ALEN) == 0) { - /* - * madwifi did not seem to like static WEP key - * configuration with IEEE80211_IOCTL_SETKEY, so use - * Linux wireless extensions ioctl for this. - */ - return wpa_driver_wext_set_key(drv->wext, alg, addr, - key_idx, set_tx, - seq, seq_len, - key, key_len); - } - alg_name = "WEP"; - cipher = IEEE80211_CIPHER_WEP; - break; - case WPA_ALG_TKIP: - alg_name = "TKIP"; - cipher = IEEE80211_CIPHER_TKIP; - break; - case WPA_ALG_CCMP: - alg_name = "CCMP"; - cipher = IEEE80211_CIPHER_AES_CCM; - break; - default: - wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d", - __FUNCTION__, alg); - return -1; - } - - wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu " - "key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx, - (unsigned long) seq_len, (unsigned long) key_len); - - if (seq_len > sizeof(u_int64_t)) { - wpa_printf(MSG_DEBUG, "%s: seq_len %lu too big", - __FUNCTION__, (unsigned long) seq_len); - return -2; - } - if (key_len > sizeof(wk.ik_keydata)) { - wpa_printf(MSG_DEBUG, "%s: key length %lu too big", - __FUNCTION__, (unsigned long) key_len); - return -3; - } - - os_memset(&wk, 0, sizeof(wk)); - wk.ik_type = cipher; - wk.ik_flags = IEEE80211_KEY_RECV; - if (addr == NULL || - os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) - wk.ik_flags |= IEEE80211_KEY_GROUP; - if (set_tx) { - wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT; - os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); - } else - os_memset(wk.ik_macaddr, 0, IEEE80211_ADDR_LEN); - wk.ik_keyix = key_idx; - wk.ik_keylen = key_len; -#ifdef WORDS_BIGENDIAN -#define WPA_KEY_RSC_LEN 8 - { - size_t i; - u8 tmp[WPA_KEY_RSC_LEN]; - os_memset(tmp, 0, sizeof(tmp)); - for (i = 0; i < seq_len; i++) - tmp[WPA_KEY_RSC_LEN - i - 1] = seq[i]; - os_memcpy(&wk.ik_keyrsc, tmp, WPA_KEY_RSC_LEN); - } -#else /* WORDS_BIGENDIAN */ - os_memcpy(&wk.ik_keyrsc, seq, seq_len); -#endif /* WORDS_BIGENDIAN */ - os_memcpy(wk.ik_keydata, key, key_len); - - return set80211priv(drv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk), 1); -} - -static int -wpa_driver_madwifi_set_countermeasures(void *priv, int enabled) -{ - struct wpa_driver_madwifi_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - return set80211param(drv, IEEE80211_PARAM_COUNTERMEASURES, enabled, 1); -} - - -static int -wpa_driver_madwifi_set_drop_unencrypted(void *priv, int enabled) -{ - struct wpa_driver_madwifi_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - return set80211param(drv, IEEE80211_PARAM_DROPUNENCRYPTED, enabled, 1); -} - -static int -wpa_driver_madwifi_deauthenticate(void *priv, const u8 *addr, int reason_code) -{ - struct wpa_driver_madwifi_data *drv = priv; - struct ieee80211req_mlme mlme; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - mlme.im_op = IEEE80211_MLME_DEAUTH; - mlme.im_reason = reason_code; - os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - return set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme), 1); -} - -static int -wpa_driver_madwifi_disassociate(void *priv, const u8 *addr, int reason_code) -{ - struct wpa_driver_madwifi_data *drv = priv; - struct ieee80211req_mlme mlme; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - mlme.im_op = IEEE80211_MLME_DISASSOC; - mlme.im_reason = reason_code; - os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - return set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme), 1); -} - -static int -wpa_driver_madwifi_associate(void *priv, - struct wpa_driver_associate_params *params) -{ - struct wpa_driver_madwifi_data *drv = priv; - struct ieee80211req_mlme mlme; - int ret = 0, privacy = 1; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - /* - * NB: Don't need to set the freq or cipher-related state as - * this is implied by the bssid which is used to locate - * the scanned node state which holds it. The ssid is - * needed to disambiguate an AP that broadcasts multiple - * ssid's but uses the same bssid. - */ - /* XXX error handling is wrong but unclear what to do... */ - if (wpa_driver_madwifi_set_wpa_ie(drv, params->wpa_ie, - params->wpa_ie_len) < 0) - ret = -1; - - if (params->pairwise_suite == CIPHER_NONE && - params->group_suite == CIPHER_NONE && - params->key_mgmt_suite == KEY_MGMT_NONE && - params->wpa_ie_len == 0) - privacy = 0; - - if (set80211param(drv, IEEE80211_PARAM_PRIVACY, privacy, 1) < 0) - ret = -1; - - if (params->wpa_ie_len && - set80211param(drv, IEEE80211_PARAM_WPA, - params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1, 1) < 0) - ret = -1; - - if (params->bssid == NULL) { - /* ap_scan=2 mode - driver takes care of AP selection and - * roaming */ - /* FIX: this does not seem to work; would probably need to - * change something in the driver */ - if (set80211param(drv, IEEE80211_PARAM_ROAMING, 0, 1) < 0) - ret = -1; - - if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, - params->ssid_len) < 0) - ret = -1; - } else { - if (set80211param(drv, IEEE80211_PARAM_ROAMING, 2, 1) < 0) - ret = -1; - if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, - params->ssid_len) < 0) - ret = -1; - os_memset(&mlme, 0, sizeof(mlme)); - mlme.im_op = IEEE80211_MLME_ASSOC; - os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN); - if (set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, - sizeof(mlme), 1) < 0) { - wpa_printf(MSG_DEBUG, "%s: SETMLME[ASSOC] failed", - __func__); - ret = -1; - } - } - - return ret; -} - -static int -wpa_driver_madwifi_set_auth_alg(void *priv, int auth_alg) -{ - struct wpa_driver_madwifi_data *drv = priv; - int authmode; - - if ((auth_alg & AUTH_ALG_OPEN_SYSTEM) && - (auth_alg & AUTH_ALG_SHARED_KEY)) - authmode = IEEE80211_AUTH_AUTO; - else if (auth_alg & AUTH_ALG_SHARED_KEY) - authmode = IEEE80211_AUTH_SHARED; - else - authmode = IEEE80211_AUTH_OPEN; - - return set80211param(drv, IEEE80211_PARAM_AUTHMODE, authmode, 1); -} - -static int -wpa_driver_madwifi_scan(void *priv, const u8 *ssid, size_t ssid_len) -{ - struct wpa_driver_madwifi_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - - /* set desired ssid before scan */ - /* FIX: scan should not break the current association, so using - * set_ssid may not be the best way of doing this.. */ - if (wpa_driver_wext_set_ssid(drv->wext, ssid, ssid_len) < 0) - ret = -1; - - if (ioctl(drv->sock, SIOCSIWSCAN, &iwr) < 0) { - perror("ioctl[SIOCSIWSCAN]"); - ret = -1; - } - - /* - * madwifi delivers a scan complete event so no need to poll, but - * register a backup timeout anyway to make sure that we recover even - * if the driver does not send this event for any reason. This timeout - * will only be used if the event is not delivered (event handler will - * cancel the timeout). - */ - eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv->wext, - drv->ctx); - eloop_register_timeout(30, 0, wpa_driver_wext_scan_timeout, drv->wext, - drv->ctx); - - return ret; -} - -static int wpa_driver_madwifi_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_madwifi_data *drv = priv; - return wpa_driver_wext_get_bssid(drv->wext, bssid); -} - - -static int wpa_driver_madwifi_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_madwifi_data *drv = priv; - return wpa_driver_wext_get_ssid(drv->wext, ssid); -} - - -static struct wpa_scan_results * -wpa_driver_madwifi_get_scan_results(void *priv) -{ - struct wpa_driver_madwifi_data *drv = priv; - return wpa_driver_wext_get_scan_results(drv->wext); -} - - -static int wpa_driver_madwifi_set_operstate(void *priv, int state) -{ - struct wpa_driver_madwifi_data *drv = priv; - return wpa_driver_wext_set_operstate(drv->wext, state); -} - - -static int wpa_driver_madwifi_set_probe_req_ie(void *priv, const u8 *ies, - size_t ies_len) -{ - struct ieee80211req_getset_appiebuf *probe_req_ie; - int ret; - - probe_req_ie = os_malloc(sizeof(*probe_req_ie) + ies_len); - if (probe_req_ie == NULL) - return -1; - - probe_req_ie->app_frmtype = IEEE80211_APPIE_FRAME_PROBE_REQ; - probe_req_ie->app_buflen = ies_len; - os_memcpy(probe_req_ie->app_buf, ies, ies_len); - - ret = set80211priv(priv, IEEE80211_IOCTL_SET_APPIEBUF, probe_req_ie, - sizeof(struct ieee80211req_getset_appiebuf) + - ies_len, 1); - - os_free(probe_req_ie); - - return ret; -} - - -static void * wpa_driver_madwifi_init(void *ctx, const char *ifname) -{ - struct wpa_driver_madwifi_data *drv; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->wext = wpa_driver_wext_init(ctx, ifname); - if (drv->wext == NULL) - goto fail; - - drv->ctx = ctx; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - drv->sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->sock < 0) - goto fail2; - - if (set80211param(drv, IEEE80211_PARAM_ROAMING, 2, 1) < 0) { - wpa_printf(MSG_DEBUG, "%s: failed to set wpa_supplicant-based " - "roaming", __FUNCTION__); - goto fail3; - } - - if (set80211param(drv, IEEE80211_PARAM_WPA, 3, 1) < 0) { - wpa_printf(MSG_DEBUG, "%s: failed to enable WPA support", - __FUNCTION__); - goto fail3; - } - - return drv; - -fail3: - close(drv->sock); -fail2: - wpa_driver_wext_deinit(drv->wext); -fail: - os_free(drv); - return NULL; -} - - -static void wpa_driver_madwifi_deinit(void *priv) -{ - struct wpa_driver_madwifi_data *drv = priv; - - if (wpa_driver_madwifi_set_wpa_ie(drv, NULL, 0) < 0) { - wpa_printf(MSG_DEBUG, "%s: failed to clear WPA IE", - __FUNCTION__); - } - if (set80211param(drv, IEEE80211_PARAM_ROAMING, 0, 1) < 0) { - wpa_printf(MSG_DEBUG, "%s: failed to enable driver-based " - "roaming", __FUNCTION__); - } - if (set80211param(drv, IEEE80211_PARAM_PRIVACY, 0, 1) < 0) { - wpa_printf(MSG_DEBUG, "%s: failed to disable forced Privacy " - "flag", __FUNCTION__); - } - if (set80211param(drv, IEEE80211_PARAM_WPA, 0, 1) < 0) { - wpa_printf(MSG_DEBUG, "%s: failed to disable WPA", - __FUNCTION__); - } - - wpa_driver_wext_deinit(drv->wext); - - close(drv->sock); - os_free(drv); -} - - -const struct wpa_driver_ops wpa_driver_madwifi_ops = { - .name = "madwifi", - .desc = "MADWIFI 802.11 support (Atheros, etc.)", - .get_bssid = wpa_driver_madwifi_get_bssid, - .get_ssid = wpa_driver_madwifi_get_ssid, - .set_key = wpa_driver_madwifi_set_key, - .init = wpa_driver_madwifi_init, - .deinit = wpa_driver_madwifi_deinit, - .set_countermeasures = wpa_driver_madwifi_set_countermeasures, - .set_drop_unencrypted = wpa_driver_madwifi_set_drop_unencrypted, - .scan = wpa_driver_madwifi_scan, - .get_scan_results2 = wpa_driver_madwifi_get_scan_results, - .deauthenticate = wpa_driver_madwifi_deauthenticate, - .disassociate = wpa_driver_madwifi_disassociate, - .associate = wpa_driver_madwifi_associate, - .set_auth_alg = wpa_driver_madwifi_set_auth_alg, - .set_operstate = wpa_driver_madwifi_set_operstate, - .set_probe_req_ie = wpa_driver_madwifi_set_probe_req_ie, -}; diff --git a/contrib/hostapd/src/drivers/driver_ndis.c b/contrib/hostapd/src/drivers/driver_ndis.c deleted file mode 100644 index a90e277ca0..0000000000 --- a/contrib/hostapd/src/drivers/driver_ndis.c +++ /dev/null @@ -1,3139 +0,0 @@ -/* - * WPA Supplicant - Windows/NDIS driver interface - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifdef __CYGWIN__ -/* Avoid some header file conflicts by not including standard headers for - * cygwin builds when Packet32.h is included. */ -#include "build_config.h" -int close(int fd); -#else /* __CYGWIN__ */ -#include "includes.h" -#endif /* __CYGWIN__ */ -#ifdef CONFIG_USE_NDISUIO -#include -#else /* CONFIG_USE_NDISUIO */ -#include -#endif /* CONFIG_USE_NDISUIO */ -#ifdef __MINGW32_VERSION -#include -#else /* __MINGW32_VERSION */ -#include -#endif /* __MINGW32_VERSION */ - -#ifdef _WIN32_WCE -#include -#include -#include -#endif /* _WIN32_WCE */ - -#include "common.h" -#include "driver.h" -#include "eloop.h" -#include "ieee802_11_defs.h" -#include "driver_ndis.h" - -int wpa_driver_register_event_cb(struct wpa_driver_ndis_data *drv); -#ifdef CONFIG_NDIS_EVENTS_INTEGRATED -void wpa_driver_ndis_event_pipe_cb(void *eloop_data, void *user_data); -#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ - -static void wpa_driver_ndis_deinit(void *priv); -static void wpa_driver_ndis_poll(void *drv); -static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx); -static int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv); -static int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv); -static void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv); - - -static const u8 pae_group_addr[ETH_ALEN] = -{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; - - -/* FIX: to be removed once this can be compiled with the complete NDIS - * header files */ -#ifndef OID_802_11_BSSID -#define OID_802_11_BSSID 0x0d010101 -#define OID_802_11_SSID 0x0d010102 -#define OID_802_11_INFRASTRUCTURE_MODE 0x0d010108 -#define OID_802_11_ADD_WEP 0x0D010113 -#define OID_802_11_REMOVE_WEP 0x0D010114 -#define OID_802_11_DISASSOCIATE 0x0D010115 -#define OID_802_11_BSSID_LIST 0x0d010217 -#define OID_802_11_AUTHENTICATION_MODE 0x0d010118 -#define OID_802_11_PRIVACY_FILTER 0x0d010119 -#define OID_802_11_BSSID_LIST_SCAN 0x0d01011A -#define OID_802_11_WEP_STATUS 0x0d01011B -#define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS -#define OID_802_11_ADD_KEY 0x0d01011D -#define OID_802_11_REMOVE_KEY 0x0d01011E -#define OID_802_11_ASSOCIATION_INFORMATION 0x0d01011F -#define OID_802_11_TEST 0x0d010120 -#define OID_802_11_CAPABILITY 0x0d010122 -#define OID_802_11_PMKID 0x0d010123 - -#define NDIS_802_11_LENGTH_SSID 32 -#define NDIS_802_11_LENGTH_RATES 8 -#define NDIS_802_11_LENGTH_RATES_EX 16 - -typedef UCHAR NDIS_802_11_MAC_ADDRESS[6]; - -typedef struct NDIS_802_11_SSID { - ULONG SsidLength; - UCHAR Ssid[NDIS_802_11_LENGTH_SSID]; -} NDIS_802_11_SSID; - -typedef LONG NDIS_802_11_RSSI; - -typedef enum NDIS_802_11_NETWORK_TYPE { - Ndis802_11FH, - Ndis802_11DS, - Ndis802_11OFDM5, - Ndis802_11OFDM24, - Ndis802_11NetworkTypeMax -} NDIS_802_11_NETWORK_TYPE; - -typedef struct NDIS_802_11_CONFIGURATION_FH { - ULONG Length; - ULONG HopPattern; - ULONG HopSet; - ULONG DwellTime; -} NDIS_802_11_CONFIGURATION_FH; - -typedef struct NDIS_802_11_CONFIGURATION { - ULONG Length; - ULONG BeaconPeriod; - ULONG ATIMWindow; - ULONG DSConfig; - NDIS_802_11_CONFIGURATION_FH FHConfig; -} NDIS_802_11_CONFIGURATION; - -typedef enum NDIS_802_11_NETWORK_INFRASTRUCTURE { - Ndis802_11IBSS, - Ndis802_11Infrastructure, - Ndis802_11AutoUnknown, - Ndis802_11InfrastructureMax -} NDIS_802_11_NETWORK_INFRASTRUCTURE; - -typedef enum NDIS_802_11_AUTHENTICATION_MODE { - Ndis802_11AuthModeOpen, - Ndis802_11AuthModeShared, - Ndis802_11AuthModeAutoSwitch, - Ndis802_11AuthModeWPA, - Ndis802_11AuthModeWPAPSK, - Ndis802_11AuthModeWPANone, - Ndis802_11AuthModeWPA2, - Ndis802_11AuthModeWPA2PSK, - Ndis802_11AuthModeMax -} NDIS_802_11_AUTHENTICATION_MODE; - -typedef enum NDIS_802_11_WEP_STATUS { - Ndis802_11WEPEnabled, - Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, - Ndis802_11WEPDisabled, - Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, - Ndis802_11WEPKeyAbsent, - Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, - Ndis802_11WEPNotSupported, - Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, - Ndis802_11Encryption2Enabled, - Ndis802_11Encryption2KeyAbsent, - Ndis802_11Encryption3Enabled, - Ndis802_11Encryption3KeyAbsent -} NDIS_802_11_WEP_STATUS, NDIS_802_11_ENCRYPTION_STATUS; - -typedef enum NDIS_802_11_PRIVACY_FILTER { - Ndis802_11PrivFilterAcceptAll, - Ndis802_11PrivFilter8021xWEP -} NDIS_802_11_PRIVACY_FILTER; - -typedef UCHAR NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES]; -typedef UCHAR NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; - -typedef struct NDIS_WLAN_BSSID_EX { - ULONG Length; - NDIS_802_11_MAC_ADDRESS MacAddress; /* BSSID */ - UCHAR Reserved[2]; - NDIS_802_11_SSID Ssid; - ULONG Privacy; - NDIS_802_11_RSSI Rssi; - NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; - NDIS_802_11_CONFIGURATION Configuration; - NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; - NDIS_802_11_RATES_EX SupportedRates; - ULONG IELength; - UCHAR IEs[1]; -} NDIS_WLAN_BSSID_EX; - -typedef struct NDIS_802_11_BSSID_LIST_EX { - ULONG NumberOfItems; - NDIS_WLAN_BSSID_EX Bssid[1]; -} NDIS_802_11_BSSID_LIST_EX; - -typedef struct NDIS_802_11_FIXED_IEs { - UCHAR Timestamp[8]; - USHORT BeaconInterval; - USHORT Capabilities; -} NDIS_802_11_FIXED_IEs; - -typedef struct NDIS_802_11_WEP { - ULONG Length; - ULONG KeyIndex; - ULONG KeyLength; - UCHAR KeyMaterial[1]; -} NDIS_802_11_WEP; - -typedef ULONG NDIS_802_11_KEY_INDEX; -typedef ULONGLONG NDIS_802_11_KEY_RSC; - -typedef struct NDIS_802_11_KEY { - ULONG Length; - ULONG KeyIndex; - ULONG KeyLength; - NDIS_802_11_MAC_ADDRESS BSSID; - NDIS_802_11_KEY_RSC KeyRSC; - UCHAR KeyMaterial[1]; -} NDIS_802_11_KEY; - -typedef struct NDIS_802_11_REMOVE_KEY { - ULONG Length; - ULONG KeyIndex; - NDIS_802_11_MAC_ADDRESS BSSID; -} NDIS_802_11_REMOVE_KEY; - -typedef struct NDIS_802_11_AI_REQFI { - USHORT Capabilities; - USHORT ListenInterval; - NDIS_802_11_MAC_ADDRESS CurrentAPAddress; -} NDIS_802_11_AI_REQFI; - -typedef struct NDIS_802_11_AI_RESFI { - USHORT Capabilities; - USHORT StatusCode; - USHORT AssociationId; -} NDIS_802_11_AI_RESFI; - -typedef struct NDIS_802_11_ASSOCIATION_INFORMATION { - ULONG Length; - USHORT AvailableRequestFixedIEs; - NDIS_802_11_AI_REQFI RequestFixedIEs; - ULONG RequestIELength; - ULONG OffsetRequestIEs; - USHORT AvailableResponseFixedIEs; - NDIS_802_11_AI_RESFI ResponseFixedIEs; - ULONG ResponseIELength; - ULONG OffsetResponseIEs; -} NDIS_802_11_ASSOCIATION_INFORMATION; - -typedef struct NDIS_802_11_AUTHENTICATION_ENCRYPTION { - NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported; - NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported; -} NDIS_802_11_AUTHENTICATION_ENCRYPTION; - -typedef struct NDIS_802_11_CAPABILITY { - ULONG Length; - ULONG Version; - ULONG NoOfPMKIDs; - ULONG NoOfAuthEncryptPairsSupported; - NDIS_802_11_AUTHENTICATION_ENCRYPTION - AuthenticationEncryptionSupported[1]; -} NDIS_802_11_CAPABILITY; - -typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; - -typedef struct BSSID_INFO { - NDIS_802_11_MAC_ADDRESS BSSID; - NDIS_802_11_PMKID_VALUE PMKID; -} BSSID_INFO; - -typedef struct NDIS_802_11_PMKID { - ULONG Length; - ULONG BSSIDInfoCount; - BSSID_INFO BSSIDInfo[1]; -} NDIS_802_11_PMKID; - -typedef enum NDIS_802_11_STATUS_TYPE { - Ndis802_11StatusType_Authentication, - Ndis802_11StatusType_PMKID_CandidateList = 2, - Ndis802_11StatusTypeMax -} NDIS_802_11_STATUS_TYPE; - -typedef struct NDIS_802_11_STATUS_INDICATION { - NDIS_802_11_STATUS_TYPE StatusType; -} NDIS_802_11_STATUS_INDICATION; - -typedef struct PMKID_CANDIDATE { - NDIS_802_11_MAC_ADDRESS BSSID; - ULONG Flags; -} PMKID_CANDIDATE; - -#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 - -typedef struct NDIS_802_11_PMKID_CANDIDATE_LIST { - ULONG Version; - ULONG NumCandidates; - PMKID_CANDIDATE CandidateList[1]; -} NDIS_802_11_PMKID_CANDIDATE_LIST; - -typedef struct NDIS_802_11_AUTHENTICATION_REQUEST { - ULONG Length; - NDIS_802_11_MAC_ADDRESS Bssid; - ULONG Flags; -} NDIS_802_11_AUTHENTICATION_REQUEST; - -#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01 -#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02 -#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06 -#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E - -#endif /* OID_802_11_BSSID */ - - -#ifndef OID_802_11_PMKID -/* Platform SDK for XP did not include WPA2, so add needed definitions */ - -#define OID_802_11_CAPABILITY 0x0d010122 -#define OID_802_11_PMKID 0x0d010123 - -#define Ndis802_11AuthModeWPA2 6 -#define Ndis802_11AuthModeWPA2PSK 7 - -#define Ndis802_11StatusType_PMKID_CandidateList 2 - -typedef struct NDIS_802_11_AUTHENTICATION_ENCRYPTION { - NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported; - NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported; -} NDIS_802_11_AUTHENTICATION_ENCRYPTION; - -typedef struct NDIS_802_11_CAPABILITY { - ULONG Length; - ULONG Version; - ULONG NoOfPMKIDs; - ULONG NoOfAuthEncryptPairsSupported; - NDIS_802_11_AUTHENTICATION_ENCRYPTION - AuthenticationEncryptionSupported[1]; -} NDIS_802_11_CAPABILITY; - -typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; - -typedef struct BSSID_INFO { - NDIS_802_11_MAC_ADDRESS BSSID; - NDIS_802_11_PMKID_VALUE PMKID; -} BSSID_INFO; - -typedef struct NDIS_802_11_PMKID { - ULONG Length; - ULONG BSSIDInfoCount; - BSSID_INFO BSSIDInfo[1]; -} NDIS_802_11_PMKID; - -typedef struct PMKID_CANDIDATE { - NDIS_802_11_MAC_ADDRESS BSSID; - ULONG Flags; -} PMKID_CANDIDATE; - -#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 - -typedef struct NDIS_802_11_PMKID_CANDIDATE_LIST { - ULONG Version; - ULONG NumCandidates; - PMKID_CANDIDATE CandidateList[1]; -} NDIS_802_11_PMKID_CANDIDATE_LIST; - -#endif /* OID_802_11_CAPABILITY */ - - -#ifdef CONFIG_USE_NDISUIO -#ifndef _WIN32_WCE -#ifdef __MINGW32_VERSION -typedef ULONG NDIS_OID; -#endif /* __MINGW32_VERSION */ -/* from nuiouser.h */ -#define FSCTL_NDISUIO_BASE FILE_DEVICE_NETWORK - -#define _NDISUIO_CTL_CODE(_Function, _Method, _Access) \ - CTL_CODE(FSCTL_NDISUIO_BASE, _Function, _Method, _Access) - -#define IOCTL_NDISUIO_OPEN_DEVICE \ - _NDISUIO_CTL_CODE(0x200, METHOD_BUFFERED, \ - FILE_READ_ACCESS | FILE_WRITE_ACCESS) - -#define IOCTL_NDISUIO_QUERY_OID_VALUE \ - _NDISUIO_CTL_CODE(0x201, METHOD_BUFFERED, \ - FILE_READ_ACCESS | FILE_WRITE_ACCESS) - -#define IOCTL_NDISUIO_SET_OID_VALUE \ - _NDISUIO_CTL_CODE(0x205, METHOD_BUFFERED, \ - FILE_READ_ACCESS | FILE_WRITE_ACCESS) - -#define IOCTL_NDISUIO_SET_ETHER_TYPE \ - _NDISUIO_CTL_CODE(0x202, METHOD_BUFFERED, \ - FILE_READ_ACCESS | FILE_WRITE_ACCESS) - -#define IOCTL_NDISUIO_QUERY_BINDING \ - _NDISUIO_CTL_CODE(0x203, METHOD_BUFFERED, \ - FILE_READ_ACCESS | FILE_WRITE_ACCESS) - -#define IOCTL_NDISUIO_BIND_WAIT \ - _NDISUIO_CTL_CODE(0x204, METHOD_BUFFERED, \ - FILE_READ_ACCESS | FILE_WRITE_ACCESS) - -typedef struct _NDISUIO_QUERY_OID -{ - NDIS_OID Oid; - UCHAR Data[sizeof(ULONG)]; -} NDISUIO_QUERY_OID, *PNDISUIO_QUERY_OID; - -typedef struct _NDISUIO_SET_OID -{ - NDIS_OID Oid; - UCHAR Data[sizeof(ULONG)]; -} NDISUIO_SET_OID, *PNDISUIO_SET_OID; - -typedef struct _NDISUIO_QUERY_BINDING -{ - ULONG BindingIndex; - ULONG DeviceNameOffset; - ULONG DeviceNameLength; - ULONG DeviceDescrOffset; - ULONG DeviceDescrLength; -} NDISUIO_QUERY_BINDING, *PNDISUIO_QUERY_BINDING; -#endif /* _WIN32_WCE */ -#endif /* CONFIG_USE_NDISUIO */ - - -static int ndis_get_oid(struct wpa_driver_ndis_data *drv, unsigned int oid, - char *data, size_t len) -{ -#ifdef CONFIG_USE_NDISUIO - NDISUIO_QUERY_OID *o; - size_t buflen = sizeof(*o) + len; - DWORD written; - int ret; - size_t hdrlen; - - o = os_zalloc(buflen); - if (o == NULL) - return -1; - o->Oid = oid; -#ifdef _WIN32_WCE - o->ptcDeviceName = drv->adapter_name; -#endif /* _WIN32_WCE */ - if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_QUERY_OID_VALUE, - o, sizeof(NDISUIO_QUERY_OID), o, buflen, &written, - NULL)) { - wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDISUIO_QUERY_OID_VALUE " - "failed (oid=%08x): %d", oid, (int) GetLastError()); - os_free(o); - return -1; - } - hdrlen = sizeof(NDISUIO_QUERY_OID) - sizeof(o->Data); - if (written < hdrlen) { - wpa_printf(MSG_DEBUG, "NDIS: query oid=%08x written (%d); " - "too short", oid, (unsigned int) written); - os_free(o); - return -1; - } - written -= hdrlen; - if (written > len) { - wpa_printf(MSG_DEBUG, "NDIS: query oid=%08x written (%d) > " - "len (%d)",oid, (unsigned int) written, len); - os_free(o); - return -1; - } - os_memcpy(data, o->Data, written); - ret = written; - os_free(o); - return ret; -#else /* CONFIG_USE_NDISUIO */ - char *buf; - PACKET_OID_DATA *o; - int ret; - - buf = os_zalloc(sizeof(*o) + len); - if (buf == NULL) - return -1; - o = (PACKET_OID_DATA *) buf; - o->Oid = oid; - o->Length = len; - - if (!PacketRequest(drv->adapter, FALSE, o)) { - wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed", - __func__, oid, len); - os_free(buf); - return -1; - } - if (o->Length > len) { - wpa_printf(MSG_DEBUG, "%s: oid=0x%x Length (%d) > len (%d)", - __func__, oid, (unsigned int) o->Length, len); - os_free(buf); - return -1; - } - os_memcpy(data, o->Data, o->Length); - ret = o->Length; - os_free(buf); - return ret; -#endif /* CONFIG_USE_NDISUIO */ -} - - -static int ndis_set_oid(struct wpa_driver_ndis_data *drv, unsigned int oid, - const char *data, size_t len) -{ -#ifdef CONFIG_USE_NDISUIO - NDISUIO_SET_OID *o; - size_t buflen, reallen; - DWORD written; - char txt[50]; - - os_snprintf(txt, sizeof(txt), "NDIS: Set OID %08x", oid); - wpa_hexdump_key(MSG_MSGDUMP, txt, (const u8 *) data, len); - - buflen = sizeof(*o) + len; - reallen = buflen - sizeof(o->Data); - o = os_zalloc(buflen); - if (o == NULL) - return -1; - o->Oid = oid; -#ifdef _WIN32_WCE - o->ptcDeviceName = drv->adapter_name; -#endif /* _WIN32_WCE */ - if (data) - os_memcpy(o->Data, data, len); - if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_SET_OID_VALUE, - o, reallen, NULL, 0, &written, NULL)) { - wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDISUIO_SET_OID_VALUE " - "(oid=%08x) failed: %d", oid, (int) GetLastError()); - os_free(o); - return -1; - } - os_free(o); - return 0; -#else /* CONFIG_USE_NDISUIO */ - char *buf; - PACKET_OID_DATA *o; - char txt[50]; - - os_snprintf(txt, sizeof(txt), "NDIS: Set OID %08x", oid); - wpa_hexdump_key(MSG_MSGDUMP, txt, (const u8 *) data, len); - - buf = os_zalloc(sizeof(*o) + len); - if (buf == NULL) - return -1; - o = (PACKET_OID_DATA *) buf; - o->Oid = oid; - o->Length = len; - if (data) - os_memcpy(o->Data, data, len); - - if (!PacketRequest(drv->adapter, TRUE, o)) { - wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed", - __func__, oid, len); - os_free(buf); - return -1; - } - os_free(buf); - return 0; -#endif /* CONFIG_USE_NDISUIO */ -} - - -static int ndis_set_auth_mode(struct wpa_driver_ndis_data *drv, int mode) -{ - u32 auth_mode = mode; - if (ndis_set_oid(drv, OID_802_11_AUTHENTICATION_MODE, - (char *) &auth_mode, sizeof(auth_mode)) < 0) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to set " - "OID_802_11_AUTHENTICATION_MODE (%d)", - (int) auth_mode); - return -1; - } - return 0; -} - - -static int ndis_get_auth_mode(struct wpa_driver_ndis_data *drv) -{ - u32 auth_mode; - int res; - res = ndis_get_oid(drv, OID_802_11_AUTHENTICATION_MODE, - (char *) &auth_mode, sizeof(auth_mode)); - if (res != sizeof(auth_mode)) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to get " - "OID_802_11_AUTHENTICATION_MODE"); - return -1; - } - return auth_mode; -} - - -static int ndis_set_encr_status(struct wpa_driver_ndis_data *drv, int encr) -{ - u32 encr_status = encr; - if (ndis_set_oid(drv, OID_802_11_ENCRYPTION_STATUS, - (char *) &encr_status, sizeof(encr_status)) < 0) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to set " - "OID_802_11_ENCRYPTION_STATUS (%d)", encr); - return -1; - } - return 0; -} - - -static int ndis_get_encr_status(struct wpa_driver_ndis_data *drv) -{ - u32 encr; - int res; - res = ndis_get_oid(drv, OID_802_11_ENCRYPTION_STATUS, - (char *) &encr, sizeof(encr)); - if (res != sizeof(encr)) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to get " - "OID_802_11_ENCRYPTION_STATUS"); - return -1; - } - return encr; -} - - -static int wpa_driver_ndis_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_ndis_data *drv = priv; - - if (drv->wired) { - /* - * Report PAE group address as the "BSSID" for wired - * connection. - */ - os_memcpy(bssid, pae_group_addr, ETH_ALEN); - return 0; - } - - return ndis_get_oid(drv, OID_802_11_BSSID, (char *) bssid, ETH_ALEN) < - 0 ? -1 : 0; -} - - -static int wpa_driver_ndis_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_ndis_data *drv = priv; - NDIS_802_11_SSID buf; - int res; - - res = ndis_get_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf)); - if (res < 4) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to get SSID"); - if (drv->wired) { - wpa_printf(MSG_DEBUG, "NDIS: Allow get_ssid failure " - "with a wired interface"); - return 0; - } - return -1; - } - os_memcpy(ssid, buf.Ssid, buf.SsidLength); - return buf.SsidLength; -} - - -static int wpa_driver_ndis_set_ssid(struct wpa_driver_ndis_data *drv, - const u8 *ssid, size_t ssid_len) -{ - NDIS_802_11_SSID buf; - - os_memset(&buf, 0, sizeof(buf)); - buf.SsidLength = ssid_len; - os_memcpy(buf.Ssid, ssid, ssid_len); - /* - * Make sure radio is marked enabled here so that scan request will not - * force SSID to be changed to a random one in order to enable radio at - * that point. - */ - drv->radio_enabled = 1; - return ndis_set_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf)); -} - - -/* Disconnect using OID_802_11_DISASSOCIATE. This will also turn the radio off. - */ -static int wpa_driver_ndis_radio_off(struct wpa_driver_ndis_data *drv) -{ - drv->radio_enabled = 0; - return ndis_set_oid(drv, OID_802_11_DISASSOCIATE, " ", 4); -} - - -/* Disconnect by setting SSID to random (i.e., likely not used). */ -static int wpa_driver_ndis_disconnect(struct wpa_driver_ndis_data *drv) -{ - char ssid[32]; - int i; - for (i = 0; i < 32; i++) - ssid[i] = rand() & 0xff; - return wpa_driver_ndis_set_ssid(drv, (u8 *) ssid, 32); -} - - -static int wpa_driver_ndis_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_ndis_data *drv = priv; - return wpa_driver_ndis_disconnect(drv); -} - - -static int wpa_driver_ndis_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_ndis_data *drv = priv; - return wpa_driver_ndis_disconnect(drv); -} - - -static int wpa_driver_ndis_set_wpa(void *priv, int enabled) -{ - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - return 0; -} - - -static void wpa_driver_ndis_scan_timeout(void *eloop_ctx, void *timeout_ctx) -{ - wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); - wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); -} - - -static int wpa_driver_ndis_scan(void *priv, const u8 *ssid, size_t ssid_len) -{ - struct wpa_driver_ndis_data *drv = priv; - int res; - - if (!drv->radio_enabled) { - wpa_printf(MSG_DEBUG, "NDIS: turning radio on before the first" - " scan"); - if (wpa_driver_ndis_disconnect(drv) < 0) { - wpa_printf(MSG_DEBUG, "NDIS: failed to enable radio"); - } - drv->radio_enabled = 1; - } - - res = ndis_set_oid(drv, OID_802_11_BSSID_LIST_SCAN, " ", 4); - eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx); - eloop_register_timeout(7, 0, wpa_driver_ndis_scan_timeout, drv, - drv->ctx); - return res; -} - - -static struct wpa_scan_res * wpa_driver_ndis_add_scan_ssid( - struct wpa_scan_res *r, NDIS_802_11_SSID *ssid) -{ - struct wpa_scan_res *nr; - u8 *pos; - - if (wpa_scan_get_ie(r, WLAN_EID_SSID)) - return r; /* SSID IE already present */ - - if (ssid->SsidLength == 0 || ssid->SsidLength > 32) - return r; /* No valid SSID inside scan data */ - - nr = os_realloc(r, sizeof(*r) + r->ie_len + 2 + ssid->SsidLength); - if (nr == NULL) - return r; - - pos = ((u8 *) (nr + 1)) + nr->ie_len; - *pos++ = WLAN_EID_SSID; - *pos++ = ssid->SsidLength; - os_memcpy(pos, ssid->Ssid, ssid->SsidLength); - nr->ie_len += 2 + ssid->SsidLength; - - return nr; -} - - -static struct wpa_scan_results * wpa_driver_ndis_get_scan_results(void *priv) -{ - struct wpa_driver_ndis_data *drv = priv; - NDIS_802_11_BSSID_LIST_EX *b; - size_t blen, count, i; - int len; - char *pos; - struct wpa_scan_results *results; - struct wpa_scan_res *r; - - blen = 65535; - b = os_zalloc(blen); - if (b == NULL) - return NULL; - len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen); - if (len < 0) { - wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results"); - os_free(b); - return NULL; - } - count = b->NumberOfItems; - - results = os_zalloc(sizeof(*results)); - if (results == NULL) { - os_free(b); - return NULL; - } - results->res = os_zalloc(count * sizeof(struct wpa_scan_res *)); - if (results->res == NULL) { - os_free(results); - os_free(b); - return NULL; - } - - pos = (char *) &b->Bssid[0]; - for (i = 0; i < count; i++) { - NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos; - NDIS_802_11_FIXED_IEs *fixed; - - if (bss->IELength < sizeof(NDIS_802_11_FIXED_IEs)) { - wpa_printf(MSG_DEBUG, "NDIS: too small IELength=%d", - (int) bss->IELength); - break; - } - if (((char *) bss->IEs) + bss->IELength > (char *) b + blen) { - /* - * Some NDIS drivers have been reported to include an - * entry with an invalid IELength in scan results and - * this has crashed wpa_supplicant, so validate the - * returned value before using it. - */ - wpa_printf(MSG_DEBUG, "NDIS: skipped invalid scan " - "result IE (BSSID=" MACSTR ") IELength=%d", - MAC2STR(bss->MacAddress), - (int) bss->IELength); - break; - } - - r = os_zalloc(sizeof(*r) + bss->IELength - - sizeof(NDIS_802_11_FIXED_IEs)); - if (r == NULL) - break; - - os_memcpy(r->bssid, bss->MacAddress, ETH_ALEN); - r->level = (int) bss->Rssi; - r->freq = bss->Configuration.DSConfig / 1000; - fixed = (NDIS_802_11_FIXED_IEs *) bss->IEs; - r->beacon_int = WPA_GET_LE16((u8 *) &fixed->BeaconInterval); - r->caps = WPA_GET_LE16((u8 *) &fixed->Capabilities); - r->tsf = WPA_GET_LE64(fixed->Timestamp); - os_memcpy(r + 1, bss->IEs + sizeof(NDIS_802_11_FIXED_IEs), - bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)); - r->ie_len = bss->IELength - sizeof(NDIS_802_11_FIXED_IEs); - r = wpa_driver_ndis_add_scan_ssid(r, &bss->Ssid); - - results->res[results->num++] = r; - - pos += bss->Length; - if (pos > (char *) b + blen) - break; - } - - os_free(b); - - return results; -} - - -static int wpa_driver_ndis_remove_key(struct wpa_driver_ndis_data *drv, - int key_idx, const u8 *addr, - const u8 *bssid, int pairwise) -{ - NDIS_802_11_REMOVE_KEY rkey; - NDIS_802_11_KEY_INDEX index; - int res, res2; - - os_memset(&rkey, 0, sizeof(rkey)); - - rkey.Length = sizeof(rkey); - rkey.KeyIndex = key_idx; - if (pairwise) - rkey.KeyIndex |= 1 << 30; - os_memcpy(rkey.BSSID, bssid, ETH_ALEN); - - res = ndis_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey, - sizeof(rkey)); - if (!pairwise) { - index = key_idx; - res2 = ndis_set_oid(drv, OID_802_11_REMOVE_WEP, - (char *) &index, sizeof(index)); - } else - res2 = 0; - - if (res < 0 && res2 < 0) - return -1; - return 0; -} - - -static int wpa_driver_ndis_add_wep(struct wpa_driver_ndis_data *drv, - int pairwise, int key_idx, int set_tx, - const u8 *key, size_t key_len) -{ - NDIS_802_11_WEP *wep; - size_t len; - int res; - - len = 12 + key_len; - wep = os_zalloc(len); - if (wep == NULL) - return -1; - wep->Length = len; - wep->KeyIndex = key_idx; - if (set_tx) - wep->KeyIndex |= 1 << 31; -#if 0 /* Setting bit30 does not seem to work with some NDIS drivers */ - if (pairwise) - wep->KeyIndex |= 1 << 30; -#endif - wep->KeyLength = key_len; - os_memcpy(wep->KeyMaterial, key, key_len); - - wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_WEP", - (u8 *) wep, len); - res = ndis_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len); - - os_free(wep); - - return res; -} - - -static int wpa_driver_ndis_set_key(void *priv, wpa_alg alg, const u8 *addr, - int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_ndis_data *drv = priv; - size_t len, i; - NDIS_802_11_KEY *nkey; - int res, pairwise; - u8 bssid[ETH_ALEN]; - - if (addr == NULL || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", - ETH_ALEN) == 0) { - /* Group Key */ - pairwise = 0; - if (wpa_driver_ndis_get_bssid(drv, bssid) < 0) - os_memset(bssid, 0xff, ETH_ALEN); - } else { - /* Pairwise Key */ - pairwise = 1; - os_memcpy(bssid, addr, ETH_ALEN); - } - - if (alg == WPA_ALG_NONE || key_len == 0) { - return wpa_driver_ndis_remove_key(drv, key_idx, addr, bssid, - pairwise); - } - - if (alg == WPA_ALG_WEP) { - return wpa_driver_ndis_add_wep(drv, pairwise, key_idx, set_tx, - key, key_len); - } - - len = 12 + 6 + 6 + 8 + key_len; - - nkey = os_zalloc(len); - if (nkey == NULL) - return -1; - - nkey->Length = len; - nkey->KeyIndex = key_idx; - if (set_tx) - nkey->KeyIndex |= 1 << 31; - if (pairwise) - nkey->KeyIndex |= 1 << 30; - if (seq && seq_len) - nkey->KeyIndex |= 1 << 29; - nkey->KeyLength = key_len; - os_memcpy(nkey->BSSID, bssid, ETH_ALEN); - if (seq && seq_len) { - for (i = 0; i < seq_len; i++) - nkey->KeyRSC |= (ULONGLONG) seq[i] << (i * 8); - } - if (alg == WPA_ALG_TKIP && key_len == 32) { - os_memcpy(nkey->KeyMaterial, key, 16); - os_memcpy(nkey->KeyMaterial + 16, key + 24, 8); - os_memcpy(nkey->KeyMaterial + 24, key + 16, 8); - } else { - os_memcpy(nkey->KeyMaterial, key, key_len); - } - - wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_KEY", - (u8 *) nkey, len); - res = ndis_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len); - os_free(nkey); - - return res; -} - - -static int -wpa_driver_ndis_associate(void *priv, - struct wpa_driver_associate_params *params) -{ - struct wpa_driver_ndis_data *drv = priv; - u32 auth_mode, encr, priv_mode, mode; - - drv->mode = params->mode; - - /* Note: Setting OID_802_11_INFRASTRUCTURE_MODE clears current keys, - * so static WEP keys needs to be set again after this. */ - if (params->mode == IEEE80211_MODE_IBSS) { - mode = Ndis802_11IBSS; - /* Need to make sure that BSSID polling is enabled for - * IBSS mode. */ - eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); - eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, - drv, NULL); - } else - mode = Ndis802_11Infrastructure; - if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE, - (char *) &mode, sizeof(mode)) < 0) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to set " - "OID_802_11_INFRASTRUCTURE_MODE (%d)", - (int) mode); - /* Try to continue anyway */ - } - - if (params->key_mgmt_suite == KEY_MGMT_NONE || - params->key_mgmt_suite == KEY_MGMT_802_1X_NO_WPA) { - /* Re-set WEP keys if static WEP configuration is used. */ - u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - int i; - for (i = 0; i < 4; i++) { - if (!params->wep_key[i]) - continue; - wpa_printf(MSG_DEBUG, "NDIS: Re-setting static WEP " - "key %d", i); - wpa_driver_ndis_set_key(drv, WPA_ALG_WEP, bcast, i, - i == params->wep_tx_keyidx, - NULL, 0, params->wep_key[i], - params->wep_key_len[i]); - } - } - - if (params->wpa_ie == NULL || params->wpa_ie_len == 0) { - if (params->auth_alg & AUTH_ALG_SHARED_KEY) { - if (params->auth_alg & AUTH_ALG_OPEN_SYSTEM) - auth_mode = Ndis802_11AuthModeAutoSwitch; - else - auth_mode = Ndis802_11AuthModeShared; - } else - auth_mode = Ndis802_11AuthModeOpen; - priv_mode = Ndis802_11PrivFilterAcceptAll; - } else if (params->wpa_ie[0] == WLAN_EID_RSN) { - priv_mode = Ndis802_11PrivFilter8021xWEP; - if (params->key_mgmt_suite == KEY_MGMT_PSK) - auth_mode = Ndis802_11AuthModeWPA2PSK; - else - auth_mode = Ndis802_11AuthModeWPA2; -#ifdef CONFIG_WPS - } else if (params->key_mgmt_suite == KEY_MGMT_WPS) { - auth_mode = Ndis802_11AuthModeOpen; - priv_mode = Ndis802_11PrivFilterAcceptAll; -#endif /* CONFIG_WPS */ - } else { - priv_mode = Ndis802_11PrivFilter8021xWEP; - if (params->key_mgmt_suite == KEY_MGMT_WPA_NONE) - auth_mode = Ndis802_11AuthModeWPANone; - else if (params->key_mgmt_suite == KEY_MGMT_PSK) - auth_mode = Ndis802_11AuthModeWPAPSK; - else - auth_mode = Ndis802_11AuthModeWPA; - } - - switch (params->pairwise_suite) { - case CIPHER_CCMP: - encr = Ndis802_11Encryption3Enabled; - break; - case CIPHER_TKIP: - encr = Ndis802_11Encryption2Enabled; - break; - case CIPHER_WEP40: - case CIPHER_WEP104: - encr = Ndis802_11Encryption1Enabled; - break; - case CIPHER_NONE: - if (params->group_suite == CIPHER_CCMP) - encr = Ndis802_11Encryption3Enabled; - else if (params->group_suite == CIPHER_TKIP) - encr = Ndis802_11Encryption2Enabled; - else - encr = Ndis802_11EncryptionDisabled; - break; - default: - encr = Ndis802_11EncryptionDisabled; - }; - - if (ndis_set_oid(drv, OID_802_11_PRIVACY_FILTER, - (char *) &priv_mode, sizeof(priv_mode)) < 0) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to set " - "OID_802_11_PRIVACY_FILTER (%d)", - (int) priv_mode); - /* Try to continue anyway */ - } - - ndis_set_auth_mode(drv, auth_mode); - ndis_set_encr_status(drv, encr); - - if (params->bssid) { - ndis_set_oid(drv, OID_802_11_BSSID, (char *) params->bssid, - ETH_ALEN); - drv->oid_bssid_set = 1; - } else if (drv->oid_bssid_set) { - ndis_set_oid(drv, OID_802_11_BSSID, "\xff\xff\xff\xff\xff\xff", - ETH_ALEN); - drv->oid_bssid_set = 0; - } - - return wpa_driver_ndis_set_ssid(drv, params->ssid, params->ssid_len); -} - - -static int wpa_driver_ndis_set_pmkid(struct wpa_driver_ndis_data *drv) -{ - int len, count, i, ret; - struct ndis_pmkid_entry *entry; - NDIS_802_11_PMKID *p; - - count = 0; - entry = drv->pmkid; - while (entry) { - count++; - if (count >= drv->no_of_pmkid) - break; - entry = entry->next; - } - len = 8 + count * sizeof(BSSID_INFO); - p = os_zalloc(len); - if (p == NULL) - return -1; - - p->Length = len; - p->BSSIDInfoCount = count; - entry = drv->pmkid; - for (i = 0; i < count; i++) { - os_memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN); - os_memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16); - entry = entry->next; - } - wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID", (u8 *) p, len); - ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) p, len); - os_free(p); - return ret; -} - - -static int wpa_driver_ndis_add_pmkid(void *priv, const u8 *bssid, - const u8 *pmkid) -{ - struct wpa_driver_ndis_data *drv = priv; - struct ndis_pmkid_entry *entry, *prev; - - if (drv->no_of_pmkid == 0) - return 0; - - prev = NULL; - entry = drv->pmkid; - while (entry) { - if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0) - break; - prev = entry; - entry = entry->next; - } - - if (entry) { - /* Replace existing entry for this BSSID and move it into the - * beginning of the list. */ - os_memcpy(entry->pmkid, pmkid, 16); - if (prev) { - prev->next = entry->next; - entry->next = drv->pmkid; - drv->pmkid = entry; - } - } else { - entry = os_malloc(sizeof(*entry)); - if (entry) { - os_memcpy(entry->bssid, bssid, ETH_ALEN); - os_memcpy(entry->pmkid, pmkid, 16); - entry->next = drv->pmkid; - drv->pmkid = entry; - } - } - - return wpa_driver_ndis_set_pmkid(drv); -} - - -static int wpa_driver_ndis_remove_pmkid(void *priv, const u8 *bssid, - const u8 *pmkid) -{ - struct wpa_driver_ndis_data *drv = priv; - struct ndis_pmkid_entry *entry, *prev; - - if (drv->no_of_pmkid == 0) - return 0; - - entry = drv->pmkid; - prev = NULL; - while (entry) { - if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0 && - os_memcmp(entry->pmkid, pmkid, 16) == 0) { - if (prev) - prev->next = entry->next; - else - drv->pmkid = entry->next; - os_free(entry); - break; - } - prev = entry; - entry = entry->next; - } - return wpa_driver_ndis_set_pmkid(drv); -} - - -static int wpa_driver_ndis_flush_pmkid(void *priv) -{ - struct wpa_driver_ndis_data *drv = priv; - NDIS_802_11_PMKID p; - struct ndis_pmkid_entry *pmkid, *prev; - int prev_authmode, ret; - - if (drv->no_of_pmkid == 0) - return 0; - - pmkid = drv->pmkid; - drv->pmkid = NULL; - while (pmkid) { - prev = pmkid; - pmkid = pmkid->next; - os_free(prev); - } - - /* - * Some drivers may refuse OID_802_11_PMKID if authMode is not set to - * WPA2, so change authMode temporarily, if needed. - */ - prev_authmode = ndis_get_auth_mode(drv); - if (prev_authmode != Ndis802_11AuthModeWPA2) - ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA2); - - os_memset(&p, 0, sizeof(p)); - p.Length = 8; - p.BSSIDInfoCount = 0; - wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)", - (u8 *) &p, 8); - ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8); - - if (prev_authmode != Ndis802_11AuthModeWPA2) - ndis_set_auth_mode(drv, prev_authmode); - - return ret; -} - - -static int wpa_driver_ndis_get_associnfo(struct wpa_driver_ndis_data *drv) -{ - char buf[512], *pos; - NDIS_802_11_ASSOCIATION_INFORMATION *ai; - int len; - union wpa_event_data data; - NDIS_802_11_BSSID_LIST_EX *b; - size_t blen, i; - - len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, buf, - sizeof(buf)); - if (len < 0) { - wpa_printf(MSG_DEBUG, "NDIS: failed to get association " - "information"); - return -1; - } - if (len > sizeof(buf)) { - /* Some drivers seem to be producing incorrect length for this - * data. Limit the length to the current buffer size to avoid - * crashing in hexdump. The data seems to be otherwise valid, - * so better try to use it. */ - wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association " - "information length %d", len); - len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, - buf, sizeof(buf)); - if (len < -1) { - wpa_printf(MSG_DEBUG, "NDIS: re-reading association " - "information failed"); - return -1; - } - if (len > sizeof(buf)) { - wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association" - " information length %d (re-read)", len); - len = sizeof(buf); - } - } - wpa_hexdump(MSG_MSGDUMP, "NDIS: association information", - (u8 *) buf, len); - if (len < sizeof(*ai)) { - wpa_printf(MSG_DEBUG, "NDIS: too short association " - "information"); - return -1; - } - ai = (NDIS_802_11_ASSOCIATION_INFORMATION *) buf; - wpa_printf(MSG_DEBUG, "NDIS: ReqFixed=0x%x RespFixed=0x%x off_req=%d " - "off_resp=%d len_req=%d len_resp=%d", - ai->AvailableRequestFixedIEs, ai->AvailableResponseFixedIEs, - (int) ai->OffsetRequestIEs, (int) ai->OffsetResponseIEs, - (int) ai->RequestIELength, (int) ai->ResponseIELength); - - if (ai->OffsetRequestIEs + ai->RequestIELength > (unsigned) len || - ai->OffsetResponseIEs + ai->ResponseIELength > (unsigned) len) { - wpa_printf(MSG_DEBUG, "NDIS: association information - " - "IE overflow"); - return -1; - } - - wpa_hexdump(MSG_MSGDUMP, "NDIS: Request IEs", - (u8 *) buf + ai->OffsetRequestIEs, ai->RequestIELength); - wpa_hexdump(MSG_MSGDUMP, "NDIS: Response IEs", - (u8 *) buf + ai->OffsetResponseIEs, ai->ResponseIELength); - - os_memset(&data, 0, sizeof(data)); - data.assoc_info.req_ies = (u8 *) buf + ai->OffsetRequestIEs; - data.assoc_info.req_ies_len = ai->RequestIELength; - data.assoc_info.resp_ies = (u8 *) buf + ai->OffsetResponseIEs; - data.assoc_info.resp_ies_len = ai->ResponseIELength; - - blen = 65535; - b = os_zalloc(blen); - if (b == NULL) - goto skip_scan_results; - len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen); - if (len < 0) { - wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results"); - os_free(b); - b = NULL; - goto skip_scan_results; - } - wpa_printf(MSG_DEBUG, "NDIS: %d BSSID items to process for AssocInfo", - (unsigned int) b->NumberOfItems); - - pos = (char *) &b->Bssid[0]; - for (i = 0; i < b->NumberOfItems; i++) { - NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos; - if (os_memcmp(drv->bssid, bss->MacAddress, ETH_ALEN) == 0 && - bss->IELength > sizeof(NDIS_802_11_FIXED_IEs)) { - data.assoc_info.beacon_ies = - ((u8 *) bss->IEs) + - sizeof(NDIS_802_11_FIXED_IEs); - data.assoc_info.beacon_ies_len = - bss->IELength - sizeof(NDIS_802_11_FIXED_IEs); - wpa_hexdump(MSG_MSGDUMP, "NDIS: Beacon IEs", - data.assoc_info.beacon_ies, - data.assoc_info.beacon_ies_len); - break; - } - pos += bss->Length; - if (pos > (char *) b + blen) - break; - } - -skip_scan_results: - wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data); - - os_free(b); - - return 0; -} - - -static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_driver_ndis_data *drv = eloop_ctx; - u8 bssid[ETH_ALEN]; - int poll; - - if (drv->wired) - return; - - if (wpa_driver_ndis_get_bssid(drv, bssid)) { - /* Disconnected */ - if (!is_zero_ether_addr(drv->bssid)) { - os_memset(drv->bssid, 0, ETH_ALEN); - wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); - } - } else { - /* Connected */ - if (os_memcmp(drv->bssid, bssid, ETH_ALEN) != 0) { - os_memcpy(drv->bssid, bssid, ETH_ALEN); - wpa_driver_ndis_get_associnfo(drv); - wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); - } - } - - /* When using integrated NDIS event receiver, we can skip BSSID - * polling when using infrastructure network. However, when using - * IBSS mode, many driver do not seem to generate connection event, - * so we need to enable BSSID polling to figure out when IBSS network - * has been formed. - */ - poll = drv->mode == IEEE80211_MODE_IBSS; -#ifndef CONFIG_NDIS_EVENTS_INTEGRATED -#ifndef _WIN32_WCE - poll = 1; -#endif /* _WIN32_WCE */ -#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ - - if (poll) { - eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, - drv, NULL); - } -} - - -static void wpa_driver_ndis_poll(void *priv) -{ - struct wpa_driver_ndis_data *drv = priv; - eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); - wpa_driver_ndis_poll_timeout(drv, NULL); -} - - -/* Called when driver generates Media Connect Event by calling - * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_CONNECT */ -void wpa_driver_ndis_event_connect(struct wpa_driver_ndis_data *drv) -{ - wpa_printf(MSG_DEBUG, "NDIS: Media Connect Event"); - if (wpa_driver_ndis_get_bssid(drv, drv->bssid) == 0) { - wpa_driver_ndis_get_associnfo(drv); - wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); - } -} - - -/* Called when driver generates Media Disconnect Event by calling - * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_DISCONNECT */ -void wpa_driver_ndis_event_disconnect(struct wpa_driver_ndis_data *drv) -{ - wpa_printf(MSG_DEBUG, "NDIS: Media Disconnect Event"); - os_memset(drv->bssid, 0, ETH_ALEN); - wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); -} - - -static void wpa_driver_ndis_event_auth(struct wpa_driver_ndis_data *drv, - const u8 *data, size_t data_len) -{ - NDIS_802_11_AUTHENTICATION_REQUEST *req; - int pairwise = 0, group = 0; - union wpa_event_data event; - - if (data_len < sizeof(*req)) { - wpa_printf(MSG_DEBUG, "NDIS: Too short Authentication Request " - "Event (len=%d)", data_len); - return; - } - req = (NDIS_802_11_AUTHENTICATION_REQUEST *) data; - - wpa_printf(MSG_DEBUG, "NDIS: Authentication Request Event: " - "Bssid " MACSTR " Flags 0x%x", - MAC2STR(req->Bssid), (int) req->Flags); - - if ((req->Flags & NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) == - NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) - pairwise = 1; - else if ((req->Flags & NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) == - NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) - group = 1; - - if (pairwise || group) { - os_memset(&event, 0, sizeof(event)); - event.michael_mic_failure.unicast = pairwise; - wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE, - &event); - } -} - - -static void wpa_driver_ndis_event_pmkid(struct wpa_driver_ndis_data *drv, - const u8 *data, size_t data_len) -{ - NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid; - size_t i; - union wpa_event_data event; - - if (data_len < 8) { - wpa_printf(MSG_DEBUG, "NDIS: Too short PMKID Candidate List " - "Event (len=%d)", data_len); - return; - } - pmkid = (NDIS_802_11_PMKID_CANDIDATE_LIST *) data; - wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List Event - Version %d " - "NumCandidates %d", - (int) pmkid->Version, (int) pmkid->NumCandidates); - - if (pmkid->Version != 1) { - wpa_printf(MSG_DEBUG, "NDIS: Unsupported PMKID Candidate List " - "Version %d", (int) pmkid->Version); - return; - } - - if (data_len < 8 + pmkid->NumCandidates * sizeof(PMKID_CANDIDATE)) { - wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List underflow"); - return; - } - - os_memset(&event, 0, sizeof(event)); - for (i = 0; i < pmkid->NumCandidates; i++) { - PMKID_CANDIDATE *p = &pmkid->CandidateList[i]; - wpa_printf(MSG_DEBUG, "NDIS: %d: " MACSTR " Flags 0x%x", - i, MAC2STR(p->BSSID), (int) p->Flags); - os_memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN); - event.pmkid_candidate.index = i; - event.pmkid_candidate.preauth = - p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; - wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, - &event); - } -} - - -/* Called when driver calls NdisMIndicateStatus() with - * NDIS_STATUS_MEDIA_SPECIFIC_INDICATION */ -void wpa_driver_ndis_event_media_specific(struct wpa_driver_ndis_data *drv, - const u8 *data, size_t data_len) -{ - NDIS_802_11_STATUS_INDICATION *status; - - if (data == NULL || data_len < sizeof(*status)) - return; - - wpa_hexdump(MSG_DEBUG, "NDIS: Media Specific Indication", - data, data_len); - - status = (NDIS_802_11_STATUS_INDICATION *) data; - data += sizeof(status); - data_len -= sizeof(status); - - switch (status->StatusType) { - case Ndis802_11StatusType_Authentication: - wpa_driver_ndis_event_auth(drv, data, data_len); - break; - case Ndis802_11StatusType_PMKID_CandidateList: - wpa_driver_ndis_event_pmkid(drv, data, data_len); - break; - default: - wpa_printf(MSG_DEBUG, "NDIS: Unknown StatusType %d", - (int) status->StatusType); - break; - } -} - - -/* Called when an adapter is added */ -void wpa_driver_ndis_event_adapter_arrival(struct wpa_driver_ndis_data *drv) -{ - union wpa_event_data event; - int i; - - wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Arrival"); - - for (i = 0; i < 30; i++) { - /* Re-open Packet32/NDISUIO connection */ - wpa_driver_ndis_adapter_close(drv); - if (wpa_driver_ndis_adapter_init(drv) < 0 || - wpa_driver_ndis_adapter_open(drv) < 0) { - wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialization " - "(%d) failed", i); - os_sleep(1, 0); - } else { - wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialized"); - break; - } - } - - os_memset(&event, 0, sizeof(event)); - os_strlcpy(event.interface_status.ifname, drv->ifname, - sizeof(event.interface_status.ifname)); - event.interface_status.ievent = EVENT_INTERFACE_ADDED; - wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); -} - - -/* Called when an adapter is removed */ -void wpa_driver_ndis_event_adapter_removal(struct wpa_driver_ndis_data *drv) -{ - union wpa_event_data event; - - wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Removal"); - os_memset(&event, 0, sizeof(event)); - os_strlcpy(event.interface_status.ifname, drv->ifname, - sizeof(event.interface_status.ifname)); - event.interface_status.ievent = EVENT_INTERFACE_REMOVED; - wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); -} - - -static void -wpa_driver_ndis_get_wpa_capability(struct wpa_driver_ndis_data *drv) -{ - wpa_printf(MSG_DEBUG, "NDIS: verifying driver WPA capability"); - - if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA) == 0 && - ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPA) { - wpa_printf(MSG_DEBUG, "NDIS: WPA key management supported"); - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA; - } - - if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPAPSK) == 0 && - ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPAPSK) { - wpa_printf(MSG_DEBUG, "NDIS: WPA-PSK key management " - "supported"); - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; - } - - if (ndis_set_encr_status(drv, Ndis802_11Encryption3Enabled) == 0 && - ndis_get_encr_status(drv) == Ndis802_11Encryption3KeyAbsent) { - wpa_printf(MSG_DEBUG, "NDIS: CCMP encryption supported"); - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; - } - - if (ndis_set_encr_status(drv, Ndis802_11Encryption2Enabled) == 0 && - ndis_get_encr_status(drv) == Ndis802_11Encryption2KeyAbsent) { - wpa_printf(MSG_DEBUG, "NDIS: TKIP encryption supported"); - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; - } - - if (ndis_set_encr_status(drv, Ndis802_11Encryption1Enabled) == 0 && - ndis_get_encr_status(drv) == Ndis802_11Encryption1KeyAbsent) { - wpa_printf(MSG_DEBUG, "NDIS: WEP encryption supported"); - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | - WPA_DRIVER_CAPA_ENC_WEP104; - } - - if (ndis_set_auth_mode(drv, Ndis802_11AuthModeShared) == 0 && - ndis_get_auth_mode(drv) == Ndis802_11AuthModeShared) { - drv->capa.auth |= WPA_DRIVER_AUTH_SHARED; - } - - if (ndis_set_auth_mode(drv, Ndis802_11AuthModeOpen) == 0 && - ndis_get_auth_mode(drv) == Ndis802_11AuthModeOpen) { - drv->capa.auth |= WPA_DRIVER_AUTH_OPEN; - } - - ndis_set_encr_status(drv, Ndis802_11EncryptionDisabled); - - /* Could also verify OID_802_11_ADD_KEY error reporting and - * support for OID_802_11_ASSOCIATION_INFORMATION. */ - - if (drv->capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA && - drv->capa.enc & (WPA_DRIVER_CAPA_ENC_TKIP | - WPA_DRIVER_CAPA_ENC_CCMP)) { - wpa_printf(MSG_DEBUG, "NDIS: driver supports WPA"); - drv->has_capability = 1; - } else { - wpa_printf(MSG_DEBUG, "NDIS: no WPA support found"); - } - - wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x " - "enc 0x%x auth 0x%x", - drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth); -} - - -static void wpa_driver_ndis_get_capability(struct wpa_driver_ndis_data *drv) -{ - char buf[512]; - int len; - size_t i; - NDIS_802_11_CAPABILITY *c; - - drv->capa.flags = WPA_DRIVER_FLAGS_DRIVER_IE; - - len = ndis_get_oid(drv, OID_802_11_CAPABILITY, buf, sizeof(buf)); - if (len < 0) { - wpa_driver_ndis_get_wpa_capability(drv); - return; - } - - wpa_hexdump(MSG_MSGDUMP, "OID_802_11_CAPABILITY", (u8 *) buf, len); - c = (NDIS_802_11_CAPABILITY *) buf; - if (len < sizeof(*c) || c->Version != 2) { - wpa_printf(MSG_DEBUG, "NDIS: unsupported " - "OID_802_11_CAPABILITY data"); - return; - } - wpa_printf(MSG_DEBUG, "NDIS: Driver supports OID_802_11_CAPABILITY - " - "NoOfPMKIDs %d NoOfAuthEncrPairs %d", - (int) c->NoOfPMKIDs, - (int) c->NoOfAuthEncryptPairsSupported); - drv->has_capability = 1; - drv->no_of_pmkid = c->NoOfPMKIDs; - for (i = 0; i < c->NoOfAuthEncryptPairsSupported; i++) { - NDIS_802_11_AUTHENTICATION_ENCRYPTION *ae; - ae = &c->AuthenticationEncryptionSupported[i]; - if ((char *) (ae + 1) > buf + len) { - wpa_printf(MSG_DEBUG, "NDIS: auth/encr pair list " - "overflow"); - break; - } - wpa_printf(MSG_MSGDUMP, "NDIS: %d - auth %d encr %d", - i, (int) ae->AuthModeSupported, - (int) ae->EncryptStatusSupported); - switch (ae->AuthModeSupported) { - case Ndis802_11AuthModeOpen: - drv->capa.auth |= WPA_DRIVER_AUTH_OPEN; - break; - case Ndis802_11AuthModeShared: - drv->capa.auth |= WPA_DRIVER_AUTH_SHARED; - break; - case Ndis802_11AuthModeWPA: - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA; - break; - case Ndis802_11AuthModeWPAPSK: - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; - break; - case Ndis802_11AuthModeWPA2: - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2; - break; - case Ndis802_11AuthModeWPA2PSK: - drv->capa.key_mgmt |= - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; - break; - case Ndis802_11AuthModeWPANone: - drv->capa.key_mgmt |= - WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE; - break; - default: - break; - } - switch (ae->EncryptStatusSupported) { - case Ndis802_11Encryption1Enabled: - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40; - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP104; - break; - case Ndis802_11Encryption2Enabled: - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; - break; - case Ndis802_11Encryption3Enabled: - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; - break; - default: - break; - } - } - - wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x " - "enc 0x%x auth 0x%x", - drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth); -} - - -static int wpa_driver_ndis_get_capa(void *priv, struct wpa_driver_capa *capa) -{ - struct wpa_driver_ndis_data *drv = priv; - if (!drv->has_capability) - return -1; - os_memcpy(capa, &drv->capa, sizeof(*capa)); - return 0; -} - - -static const char * wpa_driver_ndis_get_ifname(void *priv) -{ - struct wpa_driver_ndis_data *drv = priv; - return drv->ifname; -} - - -static const u8 * wpa_driver_ndis_get_mac_addr(void *priv) -{ - struct wpa_driver_ndis_data *drv = priv; - return drv->own_addr; -} - - -#ifdef _WIN32_WCE - -#define NDISUIO_MSG_SIZE (sizeof(NDISUIO_DEVICE_NOTIFICATION) + 512) - -static void ndisuio_notification_receive(void *eloop_data, void *user_ctx) -{ - struct wpa_driver_ndis_data *drv = eloop_data; - NDISUIO_DEVICE_NOTIFICATION *hdr; - u8 buf[NDISUIO_MSG_SIZE]; - DWORD len, flags; - - if (!ReadMsgQueue(drv->event_queue, buf, NDISUIO_MSG_SIZE, &len, 0, - &flags)) { - wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: " - "ReadMsgQueue failed: %d", (int) GetLastError()); - return; - } - - if (len < sizeof(NDISUIO_DEVICE_NOTIFICATION)) { - wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: " - "Too short message (len=%d)", (int) len); - return; - } - - hdr = (NDISUIO_DEVICE_NOTIFICATION *) buf; - wpa_printf(MSG_DEBUG, "NDIS: Notification received: len=%d type=0x%x", - (int) len, hdr->dwNotificationType); - - switch (hdr->dwNotificationType) { -#ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL - case NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL: - wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_ARRIVAL"); - wpa_driver_ndis_event_adapter_arrival(drv); - break; -#endif -#ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL - case NDISUIO_NOTIFICATION_ADAPTER_REMOVAL: - wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_REMOVAL"); - wpa_driver_ndis_event_adapter_removal(drv); - break; -#endif - case NDISUIO_NOTIFICATION_MEDIA_CONNECT: - wpa_printf(MSG_DEBUG, "NDIS: MEDIA_CONNECT"); - SetEvent(drv->connected_event); - wpa_driver_ndis_event_connect(drv); - break; - case NDISUIO_NOTIFICATION_MEDIA_DISCONNECT: - ResetEvent(drv->connected_event); - wpa_printf(MSG_DEBUG, "NDIS: MEDIA_DISCONNECT"); - wpa_driver_ndis_event_disconnect(drv); - break; - case NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION: - wpa_printf(MSG_DEBUG, "NDIS: MEDIA_SPECIFIC_NOTIFICATION"); -#if _WIN32_WCE == 420 || _WIN32_WCE == 0x420 - wpa_driver_ndis_event_media_specific( - drv, hdr->pvStatusBuffer, hdr->uiStatusBufferSize); -#else - wpa_driver_ndis_event_media_specific( - drv, ((const u8 *) hdr) + hdr->uiOffsetToStatusBuffer, - (size_t) hdr->uiStatusBufferSize); -#endif - break; - default: - wpa_printf(MSG_DEBUG, "NDIS: Unknown notification type 0x%x", - hdr->dwNotificationType); - break; - } -} - - -static void ndisuio_notification_deinit(struct wpa_driver_ndis_data *drv) -{ - NDISUIO_REQUEST_NOTIFICATION req; - - memset(&req, 0, sizeof(req)); - req.hMsgQueue = drv->event_queue; - req.dwNotificationTypes = 0; - - if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION, - &req, sizeof(req), NULL, 0, NULL, NULL)) { - wpa_printf(MSG_INFO, "ndisuio_notification_deinit: " - "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d", - (int) GetLastError()); - } - - if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_CANCEL_NOTIFICATION, - NULL, 0, NULL, 0, NULL, NULL)) { - wpa_printf(MSG_INFO, "ndisuio_notification_deinit: " - "IOCTL_NDISUIO_CANCEL_NOTIFICATION failed: %d", - (int) GetLastError()); - } - - if (drv->event_queue) { - eloop_unregister_event(drv->event_queue, - sizeof(drv->event_queue)); - CloseHandle(drv->event_queue); - drv->event_queue = NULL; - } - - if (drv->connected_event) { - CloseHandle(drv->connected_event); - drv->connected_event = NULL; - } -} - - -static int ndisuio_notification_init(struct wpa_driver_ndis_data *drv) -{ - MSGQUEUEOPTIONS opt; - NDISUIO_REQUEST_NOTIFICATION req; - - drv->connected_event = - CreateEvent(NULL, TRUE, FALSE, TEXT("WpaSupplicantConnected")); - if (drv->connected_event == NULL) { - wpa_printf(MSG_INFO, "ndisuio_notification_init: " - "CreateEvent failed: %d", - (int) GetLastError()); - return -1; - } - - memset(&opt, 0, sizeof(opt)); - opt.dwSize = sizeof(opt); - opt.dwMaxMessages = 5; - opt.cbMaxMessage = NDISUIO_MSG_SIZE; - opt.bReadAccess = TRUE; - - drv->event_queue = CreateMsgQueue(NULL, &opt); - if (drv->event_queue == NULL) { - wpa_printf(MSG_INFO, "ndisuio_notification_init: " - "CreateMsgQueue failed: %d", - (int) GetLastError()); - ndisuio_notification_deinit(drv); - return -1; - } - - memset(&req, 0, sizeof(req)); - req.hMsgQueue = drv->event_queue; - req.dwNotificationTypes = -#ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL - NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL | -#endif -#ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL - NDISUIO_NOTIFICATION_ADAPTER_REMOVAL | -#endif - NDISUIO_NOTIFICATION_MEDIA_CONNECT | - NDISUIO_NOTIFICATION_MEDIA_DISCONNECT | - NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION; - - if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION, - &req, sizeof(req), NULL, 0, NULL, NULL)) { - wpa_printf(MSG_INFO, "ndisuio_notification_init: " - "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d", - (int) GetLastError()); - ndisuio_notification_deinit(drv); - return -1; - } - - eloop_register_event(drv->event_queue, sizeof(drv->event_queue), - ndisuio_notification_receive, drv, NULL); - - return 0; -} -#endif /* _WIN32_WCE */ - - -static int wpa_driver_ndis_get_names(struct wpa_driver_ndis_data *drv) -{ -#ifdef CONFIG_USE_NDISUIO - NDISUIO_QUERY_BINDING *b; - size_t blen = sizeof(*b) + 1024; - int i, error, found = 0; - DWORD written; - char name[256], desc[256], *dpos; - WCHAR *pos; - size_t j, len, dlen; - - b = os_malloc(blen); - if (b == NULL) - return -1; - - for (i = 0; ; i++) { - os_memset(b, 0, blen); - b->BindingIndex = i; - if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_QUERY_BINDING, - b, sizeof(NDISUIO_QUERY_BINDING), b, blen, - &written, NULL)) { - error = (int) GetLastError(); - if (error == ERROR_NO_MORE_ITEMS) - break; - wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING " - "failed: %d", error); - break; - } - - pos = (WCHAR *) ((char *) b + b->DeviceNameOffset); - len = b->DeviceNameLength; - if (len >= sizeof(name)) - len = sizeof(name) - 1; - for (j = 0; j < len; j++) - name[j] = (char) pos[j]; - name[len] = '\0'; - - pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset); - len = b->DeviceDescrLength; - if (len >= sizeof(desc)) - len = sizeof(desc) - 1; - for (j = 0; j < len; j++) - desc[j] = (char) pos[j]; - desc[len] = '\0'; - - wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc); - - if (os_strstr(name, drv->ifname)) { - wpa_printf(MSG_DEBUG, "NDIS: Interface name match"); - found = 1; - break; - } - - if (os_strncmp(desc, drv->ifname, os_strlen(drv->ifname)) == 0) - { - wpa_printf(MSG_DEBUG, "NDIS: Interface description " - "match"); - found = 1; - break; - } - } - - if (!found) { - wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'", - drv->ifname); - os_free(b); - return -1; - } - - os_strlcpy(drv->ifname, - os_strncmp(name, "\\DEVICE\\", 8) == 0 ? name + 8 : name, - sizeof(drv->ifname)); -#ifdef _WIN32_WCE - drv->adapter_name = wpa_strdup_tchar(drv->ifname); - if (drv->adapter_name == NULL) { - wpa_printf(MSG_ERROR, "NDIS: Failed to allocate memory for " - "adapter name"); - os_free(b); - return -1; - } -#endif /* _WIN32_WCE */ - - dpos = os_strstr(desc, " - "); - if (dpos) - dlen = dpos - desc; - else - dlen = os_strlen(desc); - drv->adapter_desc = os_malloc(dlen + 1); - if (drv->adapter_desc) { - os_memcpy(drv->adapter_desc, desc, dlen); - drv->adapter_desc[dlen] = '\0'; - } - - os_free(b); - - if (drv->adapter_desc == NULL) - return -1; - - wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'", - drv->adapter_desc); - - return 0; -#else /* CONFIG_USE_NDISUIO */ - PTSTR _names; - char *names, *pos, *pos2; - ULONG len; - BOOLEAN res; -#define MAX_ADAPTERS 32 - char *name[MAX_ADAPTERS]; - char *desc[MAX_ADAPTERS]; - int num_name, num_desc, i, found_name, found_desc; - size_t dlen; - - wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s", - PacketGetVersion()); - - len = 8192; - _names = os_zalloc(len); - if (_names == NULL) - return -1; - - res = PacketGetAdapterNames(_names, &len); - if (!res && len > 8192) { - os_free(_names); - _names = os_zalloc(len); - if (_names == NULL) - return -1; - res = PacketGetAdapterNames(_names, &len); - } - - if (!res) { - wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list " - "(PacketGetAdapterNames)"); - os_free(_names); - return -1; - } - - names = (char *) _names; - if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') { - wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in " - "UNICODE"); - /* Convert to ASCII */ - pos2 = pos = names; - while (pos2 < names + len) { - if (pos2[0] == '\0' && pos2[1] == '\0' && - pos2[2] == '\0' && pos2[3] == '\0') { - pos2 += 4; - break; - } - *pos++ = pos2[0]; - pos2 += 2; - } - os_memcpy(pos + 2, names, pos - names); - pos += 2; - } else - pos = names; - - num_name = 0; - while (pos < names + len) { - name[num_name] = pos; - while (*pos && pos < names + len) - pos++; - if (pos + 1 >= names + len) { - os_free(names); - return -1; - } - pos++; - num_name++; - if (num_name >= MAX_ADAPTERS) { - wpa_printf(MSG_DEBUG, "NDIS: Too many adapters"); - os_free(names); - return -1; - } - if (*pos == '\0') { - wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found", - num_name); - pos++; - break; - } - } - - num_desc = 0; - while (pos < names + len) { - desc[num_desc] = pos; - while (*pos && pos < names + len) - pos++; - if (pos + 1 >= names + len) { - os_free(names); - return -1; - } - pos++; - num_desc++; - if (num_desc >= MAX_ADAPTERS) { - wpa_printf(MSG_DEBUG, "NDIS: Too many adapter " - "descriptions"); - os_free(names); - return -1; - } - if (*pos == '\0') { - wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions " - "found", num_name); - pos++; - break; - } - } - - /* - * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter - * descriptions. Fill in dummy descriptors to work around this. - */ - while (num_desc < num_name) - desc[num_desc++] = "dummy description"; - - if (num_name != num_desc) { - wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and " - "description counts (%d != %d)", - num_name, num_desc); - os_free(names); - return -1; - } - - found_name = found_desc = -1; - for (i = 0; i < num_name; i++) { - wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", - i, name[i], desc[i]); - if (found_name == -1 && os_strstr(name[i], drv->ifname)) - found_name = i; - if (found_desc == -1 && - os_strncmp(desc[i], drv->ifname, os_strlen(drv->ifname)) == - 0) - found_desc = i; - } - - if (found_name < 0 && found_desc >= 0) { - wpa_printf(MSG_DEBUG, "NDIS: Matched interface '%s' based on " - "description '%s'", - name[found_desc], desc[found_desc]); - found_name = found_desc; - os_strlcpy(drv->ifname, - os_strncmp(name[found_desc], "\\Device\\NPF_", 12) - == 0 ? name[found_desc] + 12 : name[found_desc], - sizeof(drv->ifname)); - } - - if (found_name < 0) { - wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'", - drv->ifname); - os_free(names); - return -1; - } - - i = found_name; - pos = os_strrchr(desc[i], '('); - if (pos) { - dlen = pos - desc[i]; - pos--; - if (pos > desc[i] && *pos == ' ') - dlen--; - } else { - dlen = os_strlen(desc[i]); - } - drv->adapter_desc = os_malloc(dlen + 1); - if (drv->adapter_desc) { - os_memcpy(drv->adapter_desc, desc[i], dlen); - drv->adapter_desc[dlen] = '\0'; - } - - os_free(names); - - if (drv->adapter_desc == NULL) - return -1; - - wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'", - drv->adapter_desc); - - return 0; -#endif /* CONFIG_USE_NDISUIO */ -} - - -#if defined(CONFIG_NATIVE_WINDOWS) || defined(__CYGWIN__) -#ifndef _WIN32_WCE -/* - * These structures are undocumented for WinXP; only WinCE version is - * documented. These would be included wzcsapi.h if it were available. Some - * changes here have been needed to make the structures match with WinXP SP2. - * It is unclear whether these work with any other version. - */ - -typedef struct { - LPWSTR wszGuid; -} INTF_KEY_ENTRY, *PINTF_KEY_ENTRY; - -typedef struct { - DWORD dwNumIntfs; - PINTF_KEY_ENTRY pIntfs; -} INTFS_KEY_TABLE, *PINTFS_KEY_TABLE; - -typedef struct { - DWORD dwDataLen; - LPBYTE pData; -} RAW_DATA, *PRAW_DATA; - -typedef struct { - LPWSTR wszGuid; - LPWSTR wszDescr; - ULONG ulMediaState; - ULONG ulMediaType; - ULONG ulPhysicalMediaType; - INT nInfraMode; - INT nAuthMode; - INT nWepStatus; -#ifndef _WIN32_WCE - u8 pad[2]; /* why is this needed? */ -#endif /* _WIN32_WCE */ - DWORD dwCtlFlags; - DWORD dwCapabilities; /* something added for WinXP SP2(?) */ - RAW_DATA rdSSID; - RAW_DATA rdBSSID; - RAW_DATA rdBSSIDList; - RAW_DATA rdStSSIDList; - RAW_DATA rdCtrlData; -#ifdef UNDER_CE - BOOL bInitialized; -#endif - DWORD nWPAMCastCipher; - /* add some extra buffer for later additions since this interface is - * far from stable */ - u8 later_additions[100]; -} INTF_ENTRY, *PINTF_ENTRY; - -#define INTF_ALL 0xffffffff -#define INTF_ALL_FLAGS 0x0000ffff -#define INTF_CTLFLAGS 0x00000010 -#define INTFCTL_ENABLED 0x8000 -#endif /* _WIN32_WCE */ - - -#ifdef _WIN32_WCE -static int wpa_driver_ndis_rebind_adapter(struct wpa_driver_ndis_data *drv) -{ - HANDLE ndis; - TCHAR multi[100]; - int len; - - len = _tcslen(drv->adapter_name); - if (len > 80) - return -1; - - ndis = CreateFile(DD_NDIS_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, - 0, NULL, OPEN_EXISTING, 0, NULL); - if (ndis == INVALID_HANDLE_VALUE) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to open file to NDIS " - "device: %d", (int) GetLastError()); - return -1; - } - - len++; - memcpy(multi, drv->adapter_name, len * sizeof(TCHAR)); - memcpy(&multi[len], TEXT("NDISUIO\0"), 9 * sizeof(TCHAR)); - len += 9; - - if (!DeviceIoControl(ndis, IOCTL_NDIS_REBIND_ADAPTER, - multi, len * sizeof(TCHAR), NULL, 0, NULL, NULL)) - { - wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDIS_REBIND_ADAPTER " - "failed: 0x%x", (int) GetLastError()); - wpa_hexdump_ascii(MSG_DEBUG, "NDIS: rebind multi_sz", - (u8 *) multi, len * sizeof(TCHAR)); - CloseHandle(ndis); - return -1; - } - - CloseHandle(ndis); - - wpa_printf(MSG_DEBUG, "NDIS: Requested NDIS rebind of NDISUIO " - "protocol"); - - return 0; -} -#endif /* _WIN32_WCE */ - - -static int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv, - int enable) -{ -#ifdef _WIN32_WCE - HKEY hk, hk2; - LONG ret; - DWORD i, hnd, len; - TCHAR keyname[256], devname[256]; - -#define WZC_DRIVER TEXT("Drivers\\BuiltIn\\ZeroConfig") - - if (enable) { - HANDLE h; - h = ActivateDeviceEx(WZC_DRIVER, NULL, 0, NULL); - if (h == INVALID_HANDLE_VALUE || h == 0) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to re-enable WZC " - "- ActivateDeviceEx failed: %d", - (int) GetLastError()); - return -1; - } - - wpa_printf(MSG_DEBUG, "NDIS: WZC re-enabled"); - return wpa_driver_ndis_rebind_adapter(drv); - } - - /* - * Unfortunately, just disabling the WZC for an interface is not enough - * to free NDISUIO for us, so need to disable and unload WZC completely - * for now when using WinCE with NDISUIO. In addition, must request - * NDISUIO protocol to be rebound to the adapter in order to free the - * NDISUIO binding that WZC hold before us. - */ - - /* Enumerate HKLM\Drivers\Active\* to find a handle to WZC. */ - ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, DEVLOAD_ACTIVE_KEY, 0, 0, &hk); - if (ret != ERROR_SUCCESS) { - wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(DEVLOAD_ACTIVE_KEY) " - "failed: %d %d", (int) ret, (int) GetLastError()); - return -1; - } - - for (i = 0; ; i++) { - len = sizeof(keyname); - ret = RegEnumKeyEx(hk, i, keyname, &len, NULL, NULL, NULL, - NULL); - if (ret != ERROR_SUCCESS) { - wpa_printf(MSG_DEBUG, "NDIS: Could not find active " - "WZC - assuming it is not running."); - RegCloseKey(hk); - return -1; - } - - ret = RegOpenKeyEx(hk, keyname, 0, 0, &hk2); - if (ret != ERROR_SUCCESS) { - wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(active dev) " - "failed: %d %d", - (int) ret, (int) GetLastError()); - continue; - } - - len = sizeof(devname); - ret = RegQueryValueEx(hk2, DEVLOAD_DEVKEY_VALNAME, NULL, NULL, - (LPBYTE) devname, &len); - if (ret != ERROR_SUCCESS) { - wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx(" - "DEVKEY_VALNAME) failed: %d %d", - (int) ret, (int) GetLastError()); - RegCloseKey(hk2); - continue; - } - - if (_tcscmp(devname, WZC_DRIVER) == 0) - break; - - RegCloseKey(hk2); - } - - RegCloseKey(hk); - - /* Found WZC - get handle to it. */ - len = sizeof(hnd); - ret = RegQueryValueEx(hk2, DEVLOAD_HANDLE_VALNAME, NULL, NULL, - (PUCHAR) &hnd, &len); - if (ret != ERROR_SUCCESS) { - wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx(HANDLE_VALNAME) " - "failed: %d %d", (int) ret, (int) GetLastError()); - RegCloseKey(hk2); - return -1; - } - - RegCloseKey(hk2); - - /* Deactivate WZC */ - if (!DeactivateDevice((HANDLE) hnd)) { - wpa_printf(MSG_DEBUG, "NDIS: DeactivateDevice failed: %d", - (int) GetLastError()); - return -1; - } - - wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily"); - drv->wzc_disabled = 1; - return wpa_driver_ndis_rebind_adapter(drv); - -#else /* _WIN32_WCE */ - - HMODULE hm; - DWORD (WINAPI *wzc_enum_interf)(LPWSTR pSrvAddr, - PINTFS_KEY_TABLE pIntfs); - DWORD (WINAPI *wzc_query_interf)(LPWSTR pSrvAddr, DWORD dwInFlags, - PINTF_ENTRY pIntf, - LPDWORD pdwOutFlags); - DWORD (WINAPI *wzc_set_interf)(LPWSTR pSrvAddr, DWORD dwInFlags, - PINTF_ENTRY pIntf, LPDWORD pdwOutFlags); - int ret = -1, j; - DWORD res; - INTFS_KEY_TABLE guids; - INTF_ENTRY intf; - char guid[128]; - WCHAR *pos; - DWORD flags, i; - - hm = LoadLibrary(TEXT("wzcsapi.dll")); - if (hm == NULL) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to load wzcsapi.dll (%u) " - "- WZC probably not running", - (unsigned int) GetLastError()); - return -1; - } - -#ifdef _WIN32_WCE - wzc_enum_interf = (void *) GetProcAddressA(hm, "WZCEnumInterfaces"); - wzc_query_interf = (void *) GetProcAddressA(hm, "WZCQueryInterface"); - wzc_set_interf = (void *) GetProcAddressA(hm, "WZCSetInterface"); -#else /* _WIN32_WCE */ - wzc_enum_interf = (void *) GetProcAddress(hm, "WZCEnumInterfaces"); - wzc_query_interf = (void *) GetProcAddress(hm, "WZCQueryInterface"); - wzc_set_interf = (void *) GetProcAddress(hm, "WZCSetInterface"); -#endif /* _WIN32_WCE */ - - if (wzc_enum_interf == NULL || wzc_query_interf == NULL || - wzc_set_interf == NULL) { - wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces, " - "WZCQueryInterface, or WZCSetInterface not found " - "in wzcsapi.dll"); - goto fail; - } - - os_memset(&guids, 0, sizeof(guids)); - res = wzc_enum_interf(NULL, &guids); - if (res != 0) { - wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces failed: %d; " - "WZC service is apparently not running", - (int) res); - goto fail; - } - - wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces: %d interfaces", - (int) guids.dwNumIntfs); - - for (i = 0; i < guids.dwNumIntfs; i++) { - pos = guids.pIntfs[i].wszGuid; - for (j = 0; j < sizeof(guid); j++) { - guid[j] = (char) *pos; - if (*pos == 0) - break; - pos++; - } - guid[sizeof(guid) - 1] = '\0'; - wpa_printf(MSG_DEBUG, "NDIS: intfs %d GUID '%s'", - (int) i, guid); - if (os_strstr(drv->ifname, guid) == NULL) - continue; - - wpa_printf(MSG_DEBUG, "NDIS: Current interface found from " - "WZC"); - break; - } - - if (i >= guids.dwNumIntfs) { - wpa_printf(MSG_DEBUG, "NDIS: Current interface not found from " - "WZC"); - goto fail; - } - - os_memset(&intf, 0, sizeof(intf)); - intf.wszGuid = guids.pIntfs[i].wszGuid; - /* Set flags to verify that the structure has not changed. */ - intf.dwCtlFlags = -1; - flags = 0; - res = wzc_query_interf(NULL, INTFCTL_ENABLED, &intf, &flags); - if (res != 0) { - wpa_printf(MSG_DEBUG, "NDIS: Could not query flags for the " - "WZC interface: %d (0x%x)", - (int) res, (int) res); - wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", - (unsigned int) GetLastError()); - goto fail; - } - - wpa_printf(MSG_DEBUG, "NDIS: WZC interface flags 0x%x dwCtlFlags 0x%x", - (int) flags, (int) intf.dwCtlFlags); - - if (intf.dwCtlFlags == -1) { - wpa_printf(MSG_DEBUG, "NDIS: Looks like wzcsapi has changed " - "again - could not disable WZC"); - wpa_hexdump(MSG_MSGDUMP, "NDIS: intf", - (u8 *) &intf, sizeof(intf)); - goto fail; - } - - if (enable) { - if (!(intf.dwCtlFlags & INTFCTL_ENABLED)) { - wpa_printf(MSG_DEBUG, "NDIS: Enabling WZC for this " - "interface"); - intf.dwCtlFlags |= INTFCTL_ENABLED; - res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf, - &flags); - if (res != 0) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to enable " - "WZC: %d (0x%x)", - (int) res, (int) res); - wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", - (unsigned int) GetLastError()); - goto fail; - } - wpa_printf(MSG_DEBUG, "NDIS: Re-enabled WZC for this " - "interface"); - drv->wzc_disabled = 0; - } - } else { - if (intf.dwCtlFlags & INTFCTL_ENABLED) { - wpa_printf(MSG_DEBUG, "NDIS: Disabling WZC for this " - "interface"); - intf.dwCtlFlags &= ~INTFCTL_ENABLED; - res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf, - &flags); - if (res != 0) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to " - "disable WZC: %d (0x%x)", - (int) res, (int) res); - wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", - (unsigned int) GetLastError()); - goto fail; - } - wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily " - "for this interface"); - drv->wzc_disabled = 1; - } else { - wpa_printf(MSG_DEBUG, "NDIS: WZC was not enabled for " - "this interface"); - } - } - - ret = 0; - -fail: - FreeLibrary(hm); - - return ret; -#endif /* _WIN32_WCE */ -} - -#else /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */ - -static int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv, - int enable) -{ - return 0; -} - -#endif /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */ - - -#ifdef CONFIG_USE_NDISUIO -/* - * l2_packet_ndis.c is sharing the same handle to NDISUIO, so we must be able - * to export this handle. This is somewhat ugly, but there is no better - * mechanism available to pass data from driver interface to l2_packet wrapper. - */ -static HANDLE driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE; - -HANDLE driver_ndis_get_ndisuio_handle(void) -{ - return driver_ndis_ndisuio_handle; -} -#endif /* CONFIG_USE_NDISUIO */ - - -static int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv) -{ -#ifdef CONFIG_USE_NDISUIO -#ifndef _WIN32_WCE -#define NDISUIO_DEVICE_NAME TEXT("\\\\.\\\\Ndisuio") - DWORD written; -#endif /* _WIN32_WCE */ - drv->ndisuio = CreateFile(NDISUIO_DEVICE_NAME, - GENERIC_READ | GENERIC_WRITE, 0, NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, - INVALID_HANDLE_VALUE); - if (drv->ndisuio == INVALID_HANDLE_VALUE) { - wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to " - "NDISUIO: %d", (int) GetLastError()); - return -1; - } - driver_ndis_ndisuio_handle = drv->ndisuio; - -#ifndef _WIN32_WCE - if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0, - NULL, 0, &written, NULL)) { - wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: " - "%d", (int) GetLastError()); - CloseHandle(drv->ndisuio); - drv->ndisuio = INVALID_HANDLE_VALUE; - return -1; - } -#endif /* _WIN32_WCE */ - - return 0; -#else /* CONFIG_USE_NDISUIO */ - return 0; -#endif /* CONFIG_USE_NDISUIO */ -} - - -static int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv) -{ -#ifdef CONFIG_USE_NDISUIO - DWORD written; -#define MAX_NDIS_DEVICE_NAME_LEN 256 - WCHAR ifname[MAX_NDIS_DEVICE_NAME_LEN]; - size_t len, i, pos; - const char *prefix = "\\DEVICE\\"; - -#ifdef _WIN32_WCE - pos = 0; -#else /* _WIN32_WCE */ - pos = 8; -#endif /* _WIN32_WCE */ - len = pos + os_strlen(drv->ifname); - if (len >= MAX_NDIS_DEVICE_NAME_LEN) - return -1; - for (i = 0; i < pos; i++) - ifname[i] = (WCHAR) prefix[i]; - for (i = pos; i < len; i++) - ifname[i] = (WCHAR) drv->ifname[i - pos]; - ifname[i] = L'\0'; - - if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_OPEN_DEVICE, - ifname, len * sizeof(WCHAR), NULL, 0, &written, - NULL)) { - wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_OPEN_DEVICE " - "failed: %d", (int) GetLastError()); - wpa_hexdump_ascii(MSG_DEBUG, "NDIS: ifname", - (const u8 *) ifname, len * sizeof(WCHAR)); - CloseHandle(drv->ndisuio); - drv->ndisuio = INVALID_HANDLE_VALUE; - return -1; - } - - wpa_printf(MSG_DEBUG, "NDIS: Opened NDISUIO device successfully"); - - return 0; -#else /* CONFIG_USE_NDISUIO */ - char ifname[128]; - os_snprintf(ifname, sizeof(ifname), "\\Device\\NPF_%s", drv->ifname); - drv->adapter = PacketOpenAdapter(ifname); - if (drv->adapter == NULL) { - wpa_printf(MSG_DEBUG, "NDIS: PacketOpenAdapter failed for " - "'%s'", ifname); - return -1; - } - return 0; -#endif /* CONFIG_USE_NDISUIO */ -} - - -static void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv) -{ -#ifdef CONFIG_USE_NDISUIO - driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE; - if (drv->ndisuio != INVALID_HANDLE_VALUE) - CloseHandle(drv->ndisuio); -#else /* CONFIG_USE_NDISUIO */ - if (drv->adapter) - PacketCloseAdapter(drv->adapter); -#endif /* CONFIG_USE_NDISUIO */ -} - - -static int ndis_add_multicast(struct wpa_driver_ndis_data *drv) -{ - if (ndis_set_oid(drv, OID_802_3_MULTICAST_LIST, - (const char *) pae_group_addr, ETH_ALEN) < 0) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to add PAE group address " - "to the multicast list"); - return -1; - } - - return 0; -} - - -static void * wpa_driver_ndis_init(void *ctx, const char *ifname) -{ - struct wpa_driver_ndis_data *drv; - u32 mode; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->ctx = ctx; - /* - * Compatibility code to strip possible prefix from the GUID. Previous - * versions include \Device\NPF_ prefix for all names, but the internal - * interface name is now only the GUI. Both Packet32 and NDISUIO - * prefixes are supported. - */ - if (os_strncmp(ifname, "\\Device\\NPF_", 12) == 0) - ifname += 12; - else if (os_strncmp(ifname, "\\DEVICE\\", 8) == 0) - ifname += 8; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - - if (wpa_driver_ndis_adapter_init(drv) < 0) { - os_free(drv); - return NULL; - } - - if (wpa_driver_ndis_get_names(drv) < 0) { - wpa_driver_ndis_adapter_close(drv); - os_free(drv); - return NULL; - } - - wpa_driver_ndis_set_wzc(drv, 0); - - if (wpa_driver_ndis_adapter_open(drv) < 0) { - wpa_driver_ndis_adapter_close(drv); - os_free(drv); - return NULL; - } - - if (ndis_get_oid(drv, OID_802_3_CURRENT_ADDRESS, - (char *) drv->own_addr, ETH_ALEN) < 0) { - wpa_printf(MSG_DEBUG, "NDIS: Get OID_802_3_CURRENT_ADDRESS " - "failed"); - wpa_driver_ndis_adapter_close(drv); - os_free(drv); - return NULL; - } - wpa_driver_ndis_get_capability(drv); - - /* Make sure that the driver does not have any obsolete PMKID entries. - */ - wpa_driver_ndis_flush_pmkid(drv); - - /* - * Disconnect to make sure that driver re-associates if it was - * connected. - */ - wpa_driver_ndis_disconnect(drv); - - eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL); - -#ifdef CONFIG_NDIS_EVENTS_INTEGRATED - drv->events = ndis_events_init(&drv->events_pipe, &drv->event_avail, - drv->ifname, drv->adapter_desc); - if (drv->events == NULL) { - wpa_driver_ndis_deinit(drv); - return NULL; - } - eloop_register_event(drv->event_avail, sizeof(drv->event_avail), - wpa_driver_ndis_event_pipe_cb, drv, NULL); -#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ - -#ifdef _WIN32_WCE - if (ndisuio_notification_init(drv) < 0) { - wpa_driver_ndis_deinit(drv); - return NULL; - } -#endif /* _WIN32_WCE */ - - /* Set mode here in case card was configured for ad-hoc mode - * previously. */ - mode = Ndis802_11Infrastructure; - if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE, - (char *) &mode, sizeof(mode)) < 0) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to set " - "OID_802_11_INFRASTRUCTURE_MODE (%d)", - (int) mode); - /* Try to continue anyway */ - - if (!drv->has_capability && drv->capa.enc == 0) { - wpa_printf(MSG_DEBUG, "NDIS: Driver did not provide " - "any wireless capabilities - assume it is " - "a wired interface"); - drv->wired = 1; - ndis_add_multicast(drv); - } - } - - return drv; -} - - -static void wpa_driver_ndis_deinit(void *priv) -{ - struct wpa_driver_ndis_data *drv = priv; - -#ifdef CONFIG_NDIS_EVENTS_INTEGRATED - if (drv->events) { - eloop_unregister_event(drv->event_avail, - sizeof(drv->event_avail)); - ndis_events_deinit(drv->events); - } -#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ - -#ifdef _WIN32_WCE - ndisuio_notification_deinit(drv); -#endif /* _WIN32_WCE */ - - eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx); - eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); - wpa_driver_ndis_flush_pmkid(drv); - wpa_driver_ndis_disconnect(drv); - if (wpa_driver_ndis_radio_off(drv) < 0) { - wpa_printf(MSG_DEBUG, "NDIS: failed to disassociate and turn " - "radio off"); - } - - wpa_driver_ndis_adapter_close(drv); - - if (drv->wzc_disabled) - wpa_driver_ndis_set_wzc(drv, 1); - -#ifdef _WIN32_WCE - os_free(drv->adapter_name); -#endif /* _WIN32_WCE */ - os_free(drv->adapter_desc); - os_free(drv); -} - - -static struct wpa_interface_info * -wpa_driver_ndis_get_interfaces(void *global_priv) -{ - struct wpa_interface_info *iface = NULL, *niface; - -#ifdef CONFIG_USE_NDISUIO - NDISUIO_QUERY_BINDING *b; - size_t blen = sizeof(*b) + 1024; - int i, error; - DWORD written; - char name[256], desc[256]; - WCHAR *pos; - size_t j, len; - HANDLE ndisuio; - - ndisuio = CreateFile(NDISUIO_DEVICE_NAME, - GENERIC_READ | GENERIC_WRITE, 0, NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, - INVALID_HANDLE_VALUE); - if (ndisuio == INVALID_HANDLE_VALUE) { - wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to " - "NDISUIO: %d", (int) GetLastError()); - return NULL; - } - -#ifndef _WIN32_WCE - if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0, - NULL, 0, &written, NULL)) { - wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: " - "%d", (int) GetLastError()); - CloseHandle(ndisuio); - return NULL; - } -#endif /* _WIN32_WCE */ - - b = os_malloc(blen); - if (b == NULL) { - CloseHandle(ndisuio); - return NULL; - } - - for (i = 0; ; i++) { - os_memset(b, 0, blen); - b->BindingIndex = i; - if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_QUERY_BINDING, - b, sizeof(NDISUIO_QUERY_BINDING), b, blen, - &written, NULL)) { - error = (int) GetLastError(); - if (error == ERROR_NO_MORE_ITEMS) - break; - wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING " - "failed: %d", error); - break; - } - - pos = (WCHAR *) ((char *) b + b->DeviceNameOffset); - len = b->DeviceNameLength; - if (len >= sizeof(name)) - len = sizeof(name) - 1; - for (j = 0; j < len; j++) - name[j] = (char) pos[j]; - name[len] = '\0'; - - pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset); - len = b->DeviceDescrLength; - if (len >= sizeof(desc)) - len = sizeof(desc) - 1; - for (j = 0; j < len; j++) - desc[j] = (char) pos[j]; - desc[len] = '\0'; - - wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc); - - niface = os_zalloc(sizeof(*niface)); - if (niface == NULL) - break; - niface->drv_name = "ndis"; - if (os_strncmp(name, "\\DEVICE\\", 8) == 0) - niface->ifname = os_strdup(name + 8); - else - niface->ifname = os_strdup(name); - if (niface->ifname == NULL) { - os_free(niface); - break; - } - niface->desc = os_strdup(desc); - niface->next = iface; - iface = niface; - } - - os_free(b); - CloseHandle(ndisuio); -#else /* CONFIG_USE_NDISUIO */ - PTSTR _names; - char *names, *pos, *pos2; - ULONG len; - BOOLEAN res; - char *name[MAX_ADAPTERS]; - char *desc[MAX_ADAPTERS]; - int num_name, num_desc, i; - - wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s", - PacketGetVersion()); - - len = 8192; - _names = os_zalloc(len); - if (_names == NULL) - return NULL; - - res = PacketGetAdapterNames(_names, &len); - if (!res && len > 8192) { - os_free(_names); - _names = os_zalloc(len); - if (_names == NULL) - return NULL; - res = PacketGetAdapterNames(_names, &len); - } - - if (!res) { - wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list " - "(PacketGetAdapterNames)"); - os_free(_names); - return NULL; - } - - names = (char *) _names; - if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') { - wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in " - "UNICODE"); - /* Convert to ASCII */ - pos2 = pos = names; - while (pos2 < names + len) { - if (pos2[0] == '\0' && pos2[1] == '\0' && - pos2[2] == '\0' && pos2[3] == '\0') { - pos2 += 4; - break; - } - *pos++ = pos2[0]; - pos2 += 2; - } - os_memcpy(pos + 2, names, pos - names); - pos += 2; - } else - pos = names; - - num_name = 0; - while (pos < names + len) { - name[num_name] = pos; - while (*pos && pos < names + len) - pos++; - if (pos + 1 >= names + len) { - os_free(names); - return NULL; - } - pos++; - num_name++; - if (num_name >= MAX_ADAPTERS) { - wpa_printf(MSG_DEBUG, "NDIS: Too many adapters"); - os_free(names); - return NULL; - } - if (*pos == '\0') { - wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found", - num_name); - pos++; - break; - } - } - - num_desc = 0; - while (pos < names + len) { - desc[num_desc] = pos; - while (*pos && pos < names + len) - pos++; - if (pos + 1 >= names + len) { - os_free(names); - return NULL; - } - pos++; - num_desc++; - if (num_desc >= MAX_ADAPTERS) { - wpa_printf(MSG_DEBUG, "NDIS: Too many adapter " - "descriptions"); - os_free(names); - return NULL; - } - if (*pos == '\0') { - wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions " - "found", num_name); - pos++; - break; - } - } - - /* - * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter - * descriptions. Fill in dummy descriptors to work around this. - */ - while (num_desc < num_name) - desc[num_desc++] = "dummy description"; - - if (num_name != num_desc) { - wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and " - "description counts (%d != %d)", - num_name, num_desc); - os_free(names); - return NULL; - } - - for (i = 0; i < num_name; i++) { - niface = os_zalloc(sizeof(*niface)); - if (niface == NULL) - break; - niface->drv_name = "ndis"; - if (os_strncmp(name[i], "\\Device\\NPF_", 12) == 0) - niface->ifname = os_strdup(name[i] + 12); - else - niface->ifname = os_strdup(name[i]); - if (niface->ifname == NULL) { - os_free(niface); - break; - } - niface->desc = os_strdup(desc[i]); - niface->next = iface; - iface = niface; - } - -#endif /* CONFIG_USE_NDISUIO */ - - return iface; -} - - -const struct wpa_driver_ops wpa_driver_ndis_ops = { - "ndis", - "Windows NDIS driver", - wpa_driver_ndis_get_bssid, - wpa_driver_ndis_get_ssid, - wpa_driver_ndis_set_wpa, - wpa_driver_ndis_set_key, - wpa_driver_ndis_init, - wpa_driver_ndis_deinit, - NULL /* set_param */, - NULL /* set_countermeasures */, - NULL /* set_drop_unencrypted */, - wpa_driver_ndis_scan, - NULL /* get_scan_results */, - wpa_driver_ndis_deauthenticate, - wpa_driver_ndis_disassociate, - wpa_driver_ndis_associate, - NULL /* set_auth_alg */, - wpa_driver_ndis_add_pmkid, - wpa_driver_ndis_remove_pmkid, - wpa_driver_ndis_flush_pmkid, - wpa_driver_ndis_get_capa, - wpa_driver_ndis_poll, - wpa_driver_ndis_get_ifname, - wpa_driver_ndis_get_mac_addr, - NULL /* send_eapol */, - NULL /* set_operstate */, - NULL /* mlme_setprotection */, - NULL /* get_hw_feature_data */, - NULL /* set_channel */, - NULL /* set_ssid */, - NULL /* set_bssid */, - NULL /* send_mlme */, - NULL /* mlme_add_sta */, - NULL /* mlme_remove_sta */, - NULL /* update_ft_ies */, - NULL /* send_ft_action */, - wpa_driver_ndis_get_scan_results, - NULL /* set_probe_req_ie */, - NULL /* set_mode */, - NULL /* set_country */, - NULL /* global_init */, - NULL /* global_deinit */, - NULL /* init2 */, - wpa_driver_ndis_get_interfaces -}; diff --git a/contrib/hostapd/src/drivers/driver_ndis.h b/contrib/hostapd/src/drivers/driver_ndis.h deleted file mode 100644 index cdce4bac85..0000000000 --- a/contrib/hostapd/src/drivers/driver_ndis.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * WPA Supplicant - Windows/NDIS driver interface - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef DRIVER_NDIS_H -#define DRIVER_NDIS_H - -#ifdef CONFIG_NDIS_EVENTS_INTEGRATED -struct ndis_events_data; -struct ndis_events_data * ndis_events_init(HANDLE *read_pipe, HANDLE *event, - const char *ifname, - const char *desc); -void ndis_events_deinit(struct ndis_events_data *events); -#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ - -struct ndis_pmkid_entry { - struct ndis_pmkid_entry *next; - u8 bssid[ETH_ALEN]; - u8 pmkid[16]; -}; - -struct wpa_driver_ndis_data { - void *ctx; - char ifname[100]; /* GUID: {7EE3EFE5-C165-472F-986D-F6FBEDFE8C8D} */ -#ifdef _WIN32_WCE - TCHAR *adapter_name; - HANDLE event_queue; /* NDISUIO notifier MsgQueue */ - HANDLE connected_event; /* WpaSupplicantConnected event */ -#endif /* _WIN32_WCE */ - u8 own_addr[ETH_ALEN]; -#ifdef CONFIG_USE_NDISUIO - HANDLE ndisuio; -#else /* CONFIG_USE_NDISUIO */ - LPADAPTER adapter; -#endif /* CONFIG_USE_NDISUIO */ - u8 bssid[ETH_ALEN]; - - int has_capability; - int no_of_pmkid; - int radio_enabled; - struct wpa_driver_capa capa; - struct ndis_pmkid_entry *pmkid; - char *adapter_desc; - int wired; - int mode; - int wzc_disabled; - int oid_bssid_set; -#ifdef CONFIG_NDIS_EVENTS_INTEGRATED - HANDLE events_pipe, event_avail; - struct ndis_events_data *events; -#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ -}; - -#endif /* DRIVER_NDIS_H */ diff --git a/contrib/hostapd/src/drivers/driver_ndis_.c b/contrib/hostapd/src/drivers/driver_ndis_.c deleted file mode 100644 index 4bee9aa543..0000000000 --- a/contrib/hostapd/src/drivers/driver_ndis_.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * WPA Supplicant - Windows/NDIS driver interface - event processing - * Copyright (c) 2004-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "driver.h" -#include "eloop.h" - -/* Keep this event processing in a separate file and without WinPcap headers to - * avoid conflicts with some of the header files. */ -struct _ADAPTER; -typedef struct _ADAPTER * LPADAPTER; -#include "driver_ndis.h" - - -void wpa_driver_ndis_event_connect(struct wpa_driver_ndis_data *drv); -void wpa_driver_ndis_event_disconnect(struct wpa_driver_ndis_data *drv); -void wpa_driver_ndis_event_media_specific(struct wpa_driver_ndis_data *drv, - const u8 *data, size_t data_len); -void wpa_driver_ndis_event_adapter_arrival(struct wpa_driver_ndis_data *drv); -void wpa_driver_ndis_event_adapter_removal(struct wpa_driver_ndis_data *drv); - - -enum event_types { EVENT_CONNECT, EVENT_DISCONNECT, - EVENT_MEDIA_SPECIFIC, EVENT_ADAPTER_ARRIVAL, - EVENT_ADAPTER_REMOVAL }; - -/* Event data: - * enum event_types (as int, i.e., 4 octets) - * data length (2 octets (big endian), optional) - * data (variable len, optional) - */ - - -static void wpa_driver_ndis_event_process(struct wpa_driver_ndis_data *drv, - u8 *buf, size_t len) -{ - u8 *pos, *data = NULL; - enum event_types type; - size_t data_len = 0; - - wpa_hexdump(MSG_MSGDUMP, "NDIS: received event data", buf, len); - if (len < sizeof(int)) - return; - type = *((int *) buf); - pos = buf + sizeof(int); - wpa_printf(MSG_DEBUG, "NDIS: event - type %d", type); - - if (buf + len - pos > 2) { - data_len = (int) *pos++ << 8; - data_len += *pos++; - if (data_len > (size_t) (buf + len - pos)) { - wpa_printf(MSG_DEBUG, "NDIS: event data overflow"); - return; - } - data = pos; - wpa_hexdump(MSG_MSGDUMP, "NDIS: event data", data, data_len); - } - - switch (type) { - case EVENT_CONNECT: - wpa_driver_ndis_event_connect(drv); - break; - case EVENT_DISCONNECT: - wpa_driver_ndis_event_disconnect(drv); - break; - case EVENT_MEDIA_SPECIFIC: - wpa_driver_ndis_event_media_specific(drv, data, data_len); - break; - case EVENT_ADAPTER_ARRIVAL: - wpa_driver_ndis_event_adapter_arrival(drv); - break; - case EVENT_ADAPTER_REMOVAL: - wpa_driver_ndis_event_adapter_removal(drv); - break; - } -} - - -void wpa_driver_ndis_event_pipe_cb(void *eloop_data, void *user_data) -{ - struct wpa_driver_ndis_data *drv = eloop_data; - u8 buf[512]; - DWORD len; - - ResetEvent(drv->event_avail); - if (ReadFile(drv->events_pipe, buf, sizeof(buf), &len, NULL)) - wpa_driver_ndis_event_process(drv, buf, len); - else { - wpa_printf(MSG_DEBUG, "%s: ReadFile() failed: %d", __func__, - (int) GetLastError()); - } -} diff --git a/contrib/hostapd/src/drivers/driver_ndiswrapper.c b/contrib/hostapd/src/drivers/driver_ndiswrapper.c deleted file mode 100644 index b5c534a74d..0000000000 --- a/contrib/hostapd/src/drivers/driver_ndiswrapper.c +++ /dev/null @@ -1,370 +0,0 @@ -/* - * WPA Supplicant - driver interaction with Linux ndiswrapper - * Copyright (c) 2004-2006, Giridhar Pemmasani - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * Please note that ndiswrapper supports WPA configuration via Linux wireless - * extensions and if the kernel includes support for this, driver_wext.c should - * be used instead of this driver wrapper. - */ - -#include "includes.h" -#include - -#include "wireless_copy.h" -#include "common.h" -#include "driver.h" -#include "driver_wext.h" - -struct wpa_driver_ndiswrapper_data { - void *wext; /* private data for driver_wext */ - void *ctx; - char ifname[IFNAMSIZ + 1]; - int sock; -}; - - -struct wpa_key -{ - wpa_alg alg; - const u8 *addr; - int key_index; - int set_tx; - const u8 *seq; - size_t seq_len; - const u8 *key; - size_t key_len; -}; - -struct wpa_assoc_info -{ - const u8 *bssid; - const u8 *ssid; - size_t ssid_len; - int freq; - const u8 *wpa_ie; - size_t wpa_ie_len; - wpa_cipher pairwise_suite; - wpa_cipher group_suite; - wpa_key_mgmt key_mgmt_suite; - int auth_alg; - int mode; -}; - -#define PRIV_RESET SIOCIWFIRSTPRIV+0 -#define WPA_SET_WPA SIOCIWFIRSTPRIV+1 -#define WPA_SET_KEY SIOCIWFIRSTPRIV+2 -#define WPA_ASSOCIATE SIOCIWFIRSTPRIV+3 -#define WPA_DISASSOCIATE SIOCIWFIRSTPRIV+4 -#define WPA_DROP_UNENCRYPTED SIOCIWFIRSTPRIV+5 -#define WPA_SET_COUNTERMEASURES SIOCIWFIRSTPRIV+6 -#define WPA_DEAUTHENTICATE SIOCIWFIRSTPRIV+7 -#define WPA_SET_AUTH_ALG SIOCIWFIRSTPRIV+8 -#define WPA_INIT SIOCIWFIRSTPRIV+9 -#define WPA_DEINIT SIOCIWFIRSTPRIV+10 -#define WPA_GET_CAPA SIOCIWFIRSTPRIV+11 - -static int get_socket(void) -{ - static const int families[] = { - AF_INET, AF_IPX, AF_AX25, AF_APPLETALK - }; - unsigned int i; - int sock; - - for (i = 0; i < sizeof(families) / sizeof(int); ++i) { - sock = socket(families[i], SOCK_DGRAM, 0); - if (sock >= 0) - return sock; - } - - return -1; -} - -static int iw_set_ext(struct wpa_driver_ndiswrapper_data *drv, int request, - struct iwreq *pwrq) -{ - os_strlcpy(pwrq->ifr_name, drv->ifname, IFNAMSIZ); - return ioctl(drv->sock, request, pwrq); -} - -static int wpa_ndiswrapper_set_wpa(void *priv, int enabled) -{ - struct wpa_driver_ndiswrapper_data *drv = priv; - struct iwreq priv_req; - int ret = 0; - - os_memset(&priv_req, 0, sizeof(priv_req)); - - priv_req.u.data.flags = enabled; - if (iw_set_ext(drv, WPA_SET_WPA, &priv_req) < 0) - ret = -1; - return ret; -} - -static int wpa_ndiswrapper_set_key(void *priv, wpa_alg alg, const u8 *addr, - int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_ndiswrapper_data *drv = priv; - struct wpa_key wpa_key; - int ret = 0; - struct iwreq priv_req; - - os_memset(&priv_req, 0, sizeof(priv_req)); - - wpa_key.alg = alg; - wpa_key.addr = addr; - wpa_key.key_index = key_idx; - wpa_key.set_tx = set_tx; - wpa_key.seq = seq; - wpa_key.seq_len = seq_len; - wpa_key.key = key; - wpa_key.key_len = key_len; - - priv_req.u.data.pointer = (void *)&wpa_key; - priv_req.u.data.length = sizeof(wpa_key); - - if (iw_set_ext(drv, WPA_SET_KEY, &priv_req) < 0) - ret = -1; - - if (alg == WPA_ALG_NONE) { - /* - * ndiswrapper did not seem to be clearing keys properly in - * some cases with WPA_SET_KEY. For example, roaming from WPA - * enabled AP to plaintext one seemed to fail since the driver - * did not associate. Try to make sure the keys are cleared so - * that plaintext APs can be used in all cases. - */ - wpa_driver_wext_set_key(drv->wext, alg, addr, key_idx, set_tx, - seq, seq_len, key, key_len); - } - - return ret; -} - -static int wpa_ndiswrapper_set_countermeasures(void *priv, int enabled) -{ - struct wpa_driver_ndiswrapper_data *drv = priv; - int ret = 0; - struct iwreq priv_req; - - os_memset(&priv_req, 0, sizeof(priv_req)); - - priv_req.u.param.value = enabled; - if (iw_set_ext(drv, WPA_SET_COUNTERMEASURES, &priv_req) < 0) - ret = -1; - - return ret; -} - -static int wpa_ndiswrapper_set_drop_unencrypted(void *priv, - int enabled) -{ - struct wpa_driver_ndiswrapper_data *drv = priv; - int ret = 0; - struct iwreq priv_req; - - os_memset(&priv_req, 0, sizeof(priv_req)); - - priv_req.u.param.value = enabled; - if (iw_set_ext(drv, WPA_DROP_UNENCRYPTED, &priv_req) < 0) - ret = -1; - return ret; -} - -static int wpa_ndiswrapper_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_ndiswrapper_data *drv = priv; - int ret = 0; - struct iwreq priv_req; - - os_memset(&priv_req, 0, sizeof(priv_req)); - - priv_req.u.param.value = reason_code; - os_memcpy(&priv_req.u.ap_addr.sa_data, addr, ETH_ALEN); - if (iw_set_ext(drv, WPA_DEAUTHENTICATE, &priv_req) < 0) - ret = -1; - return ret; -} - -static int wpa_ndiswrapper_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_ndiswrapper_data *drv = priv; - int ret = 0; - struct iwreq priv_req; - - os_memset(&priv_req, 0, sizeof(priv_req)); - - os_memcpy(&priv_req.u.ap_addr.sa_data, addr, ETH_ALEN); - if (iw_set_ext(drv, WPA_DISASSOCIATE, &priv_req) < 0) - ret = -1; - return ret; -} - -static int -wpa_ndiswrapper_associate(void *priv, - struct wpa_driver_associate_params *params) -{ - struct wpa_driver_ndiswrapper_data *drv = priv; - int ret = 0; - struct wpa_assoc_info wpa_assoc_info; - struct iwreq priv_req; - - os_memset(&priv_req, 0, sizeof(priv_req)); - os_memset(&wpa_assoc_info, 0, sizeof(wpa_assoc_info)); - - wpa_assoc_info.bssid = params->bssid; - wpa_assoc_info.ssid = params->ssid; - wpa_assoc_info.ssid_len = params->ssid_len; - wpa_assoc_info.freq = params->freq; - wpa_assoc_info.wpa_ie = params->wpa_ie; - wpa_assoc_info.wpa_ie_len = params->wpa_ie_len; - wpa_assoc_info.pairwise_suite = params->pairwise_suite; - wpa_assoc_info.group_suite = params->group_suite; - wpa_assoc_info.key_mgmt_suite = params->key_mgmt_suite; - wpa_assoc_info.auth_alg = params->auth_alg; - wpa_assoc_info.mode = params->mode; - - priv_req.u.data.pointer = (void *)&wpa_assoc_info; - priv_req.u.data.length = sizeof(wpa_assoc_info); - - if (iw_set_ext(drv, WPA_ASSOCIATE, &priv_req) < 0) - ret = -1; - return ret; -} - -static int wpa_ndiswrapper_set_auth_alg(void *priv, int auth_alg) -{ - struct wpa_driver_ndiswrapper_data *drv = priv; - int ret = 0; - struct iwreq priv_req; - - os_memset(&priv_req, 0, sizeof(priv_req)); - - priv_req.u.param.value = auth_alg; - if (iw_set_ext(drv, WPA_SET_AUTH_ALG, &priv_req) < 0) - ret = -1; - return ret; -} - -static int wpa_ndiswrapper_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_ndiswrapper_data *drv = priv; - return wpa_driver_wext_get_bssid(drv->wext, bssid); -} - - -static int wpa_ndiswrapper_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_ndiswrapper_data *drv = priv; - return wpa_driver_wext_get_ssid(drv->wext, ssid); -} - - -static int wpa_ndiswrapper_scan(void *priv, const u8 *ssid, size_t ssid_len) -{ - struct wpa_driver_ndiswrapper_data *drv = priv; - return wpa_driver_wext_scan(drv->wext, ssid, ssid_len); -} - - -static struct wpa_scan_results * wpa_ndiswrapper_get_scan_results(void *priv) -{ - struct wpa_driver_ndiswrapper_data *drv = priv; - return wpa_driver_wext_get_scan_results(drv->wext); -} - - -static int wpa_ndiswrapper_get_capa(void *priv, struct wpa_driver_capa *capa) -{ - struct wpa_driver_ndiswrapper_data *drv = priv; - int ret = 0; - struct iwreq priv_req; - - os_memset(&priv_req, 0, sizeof(priv_req)); - - priv_req.u.data.pointer = (void *) capa; - priv_req.u.data.length = sizeof(*capa); - if (iw_set_ext(drv, WPA_GET_CAPA, &priv_req) < 0) - ret = -1; - return ret; - -} - - -static int wpa_ndiswrapper_set_operstate(void *priv, int state) -{ - struct wpa_driver_ndiswrapper_data *drv = priv; - return wpa_driver_wext_set_operstate(drv->wext, state); -} - - -static void * wpa_ndiswrapper_init(void *ctx, const char *ifname) -{ - struct wpa_driver_ndiswrapper_data *drv; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->wext = wpa_driver_wext_init(ctx, ifname); - if (drv->wext == NULL) { - os_free(drv); - return NULL; - } - - drv->ctx = ctx; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - drv->sock = get_socket(); - if (drv->sock < 0) { - wpa_driver_wext_deinit(drv->wext); - os_free(drv); - return NULL; - } - - return drv; -} - - -static void wpa_ndiswrapper_deinit(void *priv) -{ - struct wpa_driver_ndiswrapper_data *drv = priv; - wpa_driver_wext_deinit(drv->wext); - close(drv->sock); - os_free(drv); -} - - -const struct wpa_driver_ops wpa_driver_ndiswrapper_ops = { - .name = "ndiswrapper", - .desc = "Linux ndiswrapper (deprecated; use wext)", - .set_wpa = wpa_ndiswrapper_set_wpa, - .set_key = wpa_ndiswrapper_set_key, - .set_countermeasures = wpa_ndiswrapper_set_countermeasures, - .set_drop_unencrypted = wpa_ndiswrapper_set_drop_unencrypted, - .deauthenticate = wpa_ndiswrapper_deauthenticate, - .disassociate = wpa_ndiswrapper_disassociate, - .associate = wpa_ndiswrapper_associate, - .set_auth_alg = wpa_ndiswrapper_set_auth_alg, - - .get_bssid = wpa_ndiswrapper_get_bssid, - .get_ssid = wpa_ndiswrapper_get_ssid, - .scan = wpa_ndiswrapper_scan, - .get_scan_results2 = wpa_ndiswrapper_get_scan_results, - .init = wpa_ndiswrapper_init, - .deinit = wpa_ndiswrapper_deinit, - .get_capa = wpa_ndiswrapper_get_capa, - .set_operstate = wpa_ndiswrapper_set_operstate, -}; diff --git a/contrib/hostapd/src/drivers/driver_nl80211.c b/contrib/hostapd/src/drivers/driver_nl80211.c deleted file mode 100644 index 9ab6d17279..0000000000 --- a/contrib/hostapd/src/drivers/driver_nl80211.c +++ /dev/null @@ -1,2766 +0,0 @@ -/* - * WPA Supplicant - driver interaction with Linux nl80211/cfg80211 - * Copyright (c) 2003-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include -#include -#include -#include -#include "nl80211_copy.h" -#ifdef CONFIG_CLIENT_MLME -#include -#include -#include "radiotap.h" -#include "radiotap_iter.h" -#endif /* CONFIG_CLIENT_MLME */ - -#include "wireless_copy.h" -#include "common.h" -#include "driver.h" -#include "eloop.h" -#include "ieee802_11_defs.h" - -#ifndef IFF_LOWER_UP -#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ -#endif -#ifndef IFF_DORMANT -#define IFF_DORMANT 0x20000 /* driver signals dormant */ -#endif - -#ifndef IF_OPER_DORMANT -#define IF_OPER_DORMANT 5 -#endif -#ifndef IF_OPER_UP -#define IF_OPER_UP 6 -#endif - - -struct wpa_driver_nl80211_data { - void *ctx; - int wext_event_sock; - int ioctl_sock; - char ifname[IFNAMSIZ + 1]; - int ifindex; - int if_removed; - u8 *assoc_req_ies; - size_t assoc_req_ies_len; - u8 *assoc_resp_ies; - size_t assoc_resp_ies_len; - struct wpa_driver_capa capa; - int has_capability; - int we_version_compiled; - - /* for set_auth_alg fallback */ - int use_crypt; - int auth_alg_fallback; - - int operstate; - - char mlmedev[IFNAMSIZ + 1]; - - int scan_complete_events; - - struct nl_handle *nl_handle; - struct nl_cache *nl_cache; - struct nl_cb *nl_cb; - struct genl_family *nl80211; - -#ifdef CONFIG_CLIENT_MLME - int monitor_sock; /* socket for monitor */ - int monitor_ifidx; -#endif /* CONFIG_CLIENT_MLME */ -}; - - -static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, - void *timeout_ctx); -static int wpa_driver_nl80211_set_mode(void *priv, int mode); -static int wpa_driver_nl80211_flush_pmkid(void *priv); -static int wpa_driver_nl80211_get_range(void *priv); -static void -wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv); - - -/* nl80211 code */ -static int ack_handler(struct nl_msg *msg, void *arg) -{ - int *err = arg; - *err = 0; - return NL_STOP; -} - -static int finish_handler(struct nl_msg *msg, void *arg) -{ - int *ret = arg; - *ret = 0; - return NL_SKIP; -} - -static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, - void *arg) -{ - int *ret = arg; - *ret = err->error; - return NL_SKIP; -} - -static int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv, - struct nl_msg *msg, - int (*valid_handler)(struct nl_msg *, void *), - void *valid_data) -{ - struct nl_cb *cb; - int err = -ENOMEM; - - cb = nl_cb_clone(drv->nl_cb); - if (!cb) - goto out; - - err = nl_send_auto_complete(drv->nl_handle, msg); - if (err < 0) - goto out; - - err = 1; - - nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); - nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); - nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); - - if (valid_handler) - nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, - valid_handler, valid_data); - - while (err > 0) - nl_recvmsgs(drv->nl_handle, cb); - out: - nl_cb_put(cb); - nlmsg_free(msg); - return err; -} - - -struct family_data { - const char *group; - int id; -}; - - -static int family_handler(struct nl_msg *msg, void *arg) -{ - struct family_data *res = arg; - struct nlattr *tb[CTRL_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct nlattr *mcgrp; - int i; - - nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - if (!tb[CTRL_ATTR_MCAST_GROUPS]) - return NL_SKIP; - - nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) { - struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1]; - nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp), - nla_len(mcgrp), NULL); - if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || - !tb2[CTRL_ATTR_MCAST_GRP_ID] || - os_strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]), - res->group, - nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0) - continue; - res->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]); - break; - }; - - return NL_SKIP; -} - - -static int nl_get_multicast_id(struct wpa_driver_nl80211_data *drv, - const char *family, const char *group) -{ - struct nl_msg *msg; - int ret = -1; - struct family_data res = { group, -ENOENT }; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - genlmsg_put(msg, 0, 0, genl_ctrl_resolve(drv->nl_handle, "nlctrl"), - 0, 0, CTRL_CMD_GETFAMILY, 0); - NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family); - - ret = send_and_recv_msgs(drv, msg, family_handler, &res); - msg = NULL; - if (ret == 0) - ret = res.id; - -nla_put_failure: - nlmsg_free(msg); - return ret; -} - - -static int wpa_driver_nl80211_send_oper_ifla( - struct wpa_driver_nl80211_data *drv, - int linkmode, int operstate) -{ - struct { - struct nlmsghdr hdr; - struct ifinfomsg ifinfo; - char opts[16]; - } req; - struct rtattr *rta; - static int nl_seq; - ssize_t ret; - - os_memset(&req, 0, sizeof(req)); - - req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); - req.hdr.nlmsg_type = RTM_SETLINK; - req.hdr.nlmsg_flags = NLM_F_REQUEST; - req.hdr.nlmsg_seq = ++nl_seq; - req.hdr.nlmsg_pid = 0; - - req.ifinfo.ifi_family = AF_UNSPEC; - req.ifinfo.ifi_type = 0; - req.ifinfo.ifi_index = drv->ifindex; - req.ifinfo.ifi_flags = 0; - req.ifinfo.ifi_change = 0; - - if (linkmode != -1) { - rta = aliasing_hide_typecast( - ((char *) &req + NLMSG_ALIGN(req.hdr.nlmsg_len)), - struct rtattr); - rta->rta_type = IFLA_LINKMODE; - rta->rta_len = RTA_LENGTH(sizeof(char)); - *((char *) RTA_DATA(rta)) = linkmode; - req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) + - RTA_LENGTH(sizeof(char)); - } - if (operstate != -1) { - rta = (struct rtattr *) - ((char *) &req + NLMSG_ALIGN(req.hdr.nlmsg_len)); - rta->rta_type = IFLA_OPERSTATE; - rta->rta_len = RTA_LENGTH(sizeof(char)); - *((char *) RTA_DATA(rta)) = operstate; - req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) + - RTA_LENGTH(sizeof(char)); - } - - wpa_printf(MSG_DEBUG, "WEXT: Operstate: linkmode=%d, operstate=%d", - linkmode, operstate); - - ret = send(drv->wext_event_sock, &req, req.hdr.nlmsg_len, 0); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "WEXT: Sending operstate IFLA failed: " - "%s (assume operstate is not supported)", - strerror(errno)); - } - - return ret < 0 ? -1 : 0; -} - - -static int wpa_driver_nl80211_set_auth_param( - struct wpa_driver_nl80211_data *drv, int idx, u32 value) -{ - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.param.flags = idx & IW_AUTH_INDEX; - iwr.u.param.value = value; - - if (ioctl(drv->ioctl_sock, SIOCSIWAUTH, &iwr) < 0) { - if (errno != EOPNOTSUPP) { - wpa_printf(MSG_DEBUG, "WEXT: SIOCSIWAUTH(param %d " - "value 0x%x) failed: %s)", - idx, value, strerror(errno)); - } - ret = errno == EOPNOTSUPP ? -2 : -1; - } - - return ret; -} - - -static int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_nl80211_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - - if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) { - perror("ioctl[SIOCGIWAP]"); - ret = -1; - } - os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN); - - return ret; -} - - -static int wpa_driver_nl80211_set_bssid(void *priv, const u8 *bssid) -{ - struct wpa_driver_nl80211_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.ap_addr.sa_family = ARPHRD_ETHER; - if (bssid) - os_memcpy(iwr.u.ap_addr.sa_data, bssid, ETH_ALEN); - else - os_memset(iwr.u.ap_addr.sa_data, 0, ETH_ALEN); - - if (ioctl(drv->ioctl_sock, SIOCSIWAP, &iwr) < 0) { - perror("ioctl[SIOCSIWAP]"); - ret = -1; - } - - return ret; -} - - -static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_nl80211_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.essid.pointer = (caddr_t) ssid; - iwr.u.essid.length = 32; - - if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) { - perror("ioctl[SIOCGIWESSID]"); - ret = -1; - } else { - ret = iwr.u.essid.length; - if (ret > 32) - ret = 32; - /* Some drivers include nul termination in the SSID, so let's - * remove it here before further processing. WE-21 changes this - * to explicitly require the length _not_ to include nul - * termination. */ - if (ret > 0 && ssid[ret - 1] == '\0' && - drv->we_version_compiled < 21) - ret--; - } - - return ret; -} - - -static int wpa_driver_nl80211_set_ssid(void *priv, const u8 *ssid, - size_t ssid_len) -{ - struct wpa_driver_nl80211_data *drv = priv; - struct iwreq iwr; - int ret = 0; - char buf[33]; - - if (ssid_len > 32) - return -1; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - /* flags: 1 = ESSID is active, 0 = not (promiscuous) */ - iwr.u.essid.flags = (ssid_len != 0); - os_memset(buf, 0, sizeof(buf)); - os_memcpy(buf, ssid, ssid_len); - iwr.u.essid.pointer = (caddr_t) buf; - if (drv->we_version_compiled < 21) { - /* For historic reasons, set SSID length to include one extra - * character, C string nul termination, even though SSID is - * really an octet string that should not be presented as a C - * string. Some Linux drivers decrement the length by one and - * can thus end up missing the last octet of the SSID if the - * length is not incremented here. WE-21 changes this to - * explicitly require the length _not_ to include nul - * termination. */ - if (ssid_len) - ssid_len++; - } - iwr.u.essid.length = ssid_len; - - if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) { - perror("ioctl[SIOCSIWESSID]"); - ret = -1; - } - - return ret; -} - - -static int wpa_driver_nl80211_set_freq(void *priv, int freq) -{ - struct wpa_driver_nl80211_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.freq.m = freq * 100000; - iwr.u.freq.e = 1; - - if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) { - perror("ioctl[SIOCSIWFREQ]"); - ret = -1; - } - - return ret; -} - - -static void -wpa_driver_nl80211_event_wireless_custom(void *ctx, char *custom) -{ - union wpa_event_data data; - - wpa_printf(MSG_MSGDUMP, "WEXT: Custom wireless event: '%s'", - custom); - - os_memset(&data, 0, sizeof(data)); - /* Host AP driver */ - if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) { - data.michael_mic_failure.unicast = - os_strstr(custom, " unicast ") != NULL; - /* TODO: parse parameters(?) */ - wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); - } else if (os_strncmp(custom, "ASSOCINFO(ReqIEs=", 17) == 0) { - char *spos; - int bytes; - - spos = custom + 17; - - bytes = strspn(spos, "0123456789abcdefABCDEF"); - if (!bytes || (bytes & 1)) - return; - bytes /= 2; - - data.assoc_info.req_ies = os_malloc(bytes); - if (data.assoc_info.req_ies == NULL) - return; - - data.assoc_info.req_ies_len = bytes; - hexstr2bin(spos, data.assoc_info.req_ies, bytes); - - spos += bytes * 2; - - data.assoc_info.resp_ies = NULL; - data.assoc_info.resp_ies_len = 0; - - if (os_strncmp(spos, " RespIEs=", 9) == 0) { - spos += 9; - - bytes = strspn(spos, "0123456789abcdefABCDEF"); - if (!bytes || (bytes & 1)) - goto done; - bytes /= 2; - - data.assoc_info.resp_ies = os_malloc(bytes); - if (data.assoc_info.resp_ies == NULL) - goto done; - - data.assoc_info.resp_ies_len = bytes; - hexstr2bin(spos, data.assoc_info.resp_ies, bytes); - } - - wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data); - - done: - os_free(data.assoc_info.resp_ies); - os_free(data.assoc_info.req_ies); -#ifdef CONFIG_PEERKEY - } else if (os_strncmp(custom, "STKSTART.request=", 17) == 0) { - if (hwaddr_aton(custom + 17, data.stkstart.peer)) { - wpa_printf(MSG_DEBUG, "WEXT: unrecognized " - "STKSTART.request '%s'", custom + 17); - return; - } - wpa_supplicant_event(ctx, EVENT_STKSTART, &data); -#endif /* CONFIG_PEERKEY */ - } -} - - -static int wpa_driver_nl80211_event_wireless_michaelmicfailure( - void *ctx, const char *ev, size_t len) -{ - const struct iw_michaelmicfailure *mic; - union wpa_event_data data; - - if (len < sizeof(*mic)) - return -1; - - mic = (const struct iw_michaelmicfailure *) ev; - - wpa_printf(MSG_DEBUG, "Michael MIC failure wireless event: " - "flags=0x%x src_addr=" MACSTR, mic->flags, - MAC2STR(mic->src_addr.sa_data)); - - os_memset(&data, 0, sizeof(data)); - data.michael_mic_failure.unicast = !(mic->flags & IW_MICFAILURE_GROUP); - wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); - - return 0; -} - - -static int wpa_driver_nl80211_event_wireless_pmkidcand( - struct wpa_driver_nl80211_data *drv, const char *ev, size_t len) -{ - const struct iw_pmkid_cand *cand; - union wpa_event_data data; - const u8 *addr; - - if (len < sizeof(*cand)) - return -1; - - cand = (const struct iw_pmkid_cand *) ev; - addr = (const u8 *) cand->bssid.sa_data; - - wpa_printf(MSG_DEBUG, "PMKID candidate wireless event: " - "flags=0x%x index=%d bssid=" MACSTR, cand->flags, - cand->index, MAC2STR(addr)); - - os_memset(&data, 0, sizeof(data)); - os_memcpy(data.pmkid_candidate.bssid, addr, ETH_ALEN); - data.pmkid_candidate.index = cand->index; - data.pmkid_candidate.preauth = cand->flags & IW_PMKID_CAND_PREAUTH; - wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data); - - return 0; -} - - -static int wpa_driver_nl80211_event_wireless_assocreqie( - struct wpa_driver_nl80211_data *drv, const char *ev, int len) -{ - if (len < 0) - return -1; - - wpa_hexdump(MSG_DEBUG, "AssocReq IE wireless event", (const u8 *) ev, - len); - os_free(drv->assoc_req_ies); - drv->assoc_req_ies = os_malloc(len); - if (drv->assoc_req_ies == NULL) { - drv->assoc_req_ies_len = 0; - return -1; - } - os_memcpy(drv->assoc_req_ies, ev, len); - drv->assoc_req_ies_len = len; - - return 0; -} - - -static int wpa_driver_nl80211_event_wireless_assocrespie( - struct wpa_driver_nl80211_data *drv, const char *ev, int len) -{ - if (len < 0) - return -1; - - wpa_hexdump(MSG_DEBUG, "AssocResp IE wireless event", (const u8 *) ev, - len); - os_free(drv->assoc_resp_ies); - drv->assoc_resp_ies = os_malloc(len); - if (drv->assoc_resp_ies == NULL) { - drv->assoc_resp_ies_len = 0; - return -1; - } - os_memcpy(drv->assoc_resp_ies, ev, len); - drv->assoc_resp_ies_len = len; - - return 0; -} - - -static void wpa_driver_nl80211_event_assoc_ies(struct wpa_driver_nl80211_data *drv) -{ - union wpa_event_data data; - - if (drv->assoc_req_ies == NULL && drv->assoc_resp_ies == NULL) - return; - - os_memset(&data, 0, sizeof(data)); - if (drv->assoc_req_ies) { - data.assoc_info.req_ies = drv->assoc_req_ies; - drv->assoc_req_ies = NULL; - data.assoc_info.req_ies_len = drv->assoc_req_ies_len; - } - if (drv->assoc_resp_ies) { - data.assoc_info.resp_ies = drv->assoc_resp_ies; - drv->assoc_resp_ies = NULL; - data.assoc_info.resp_ies_len = drv->assoc_resp_ies_len; - } - - wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data); - - os_free(data.assoc_info.req_ies); - os_free(data.assoc_info.resp_ies); -} - - -static void wpa_driver_nl80211_event_wireless(struct wpa_driver_nl80211_data *drv, - void *ctx, char *data, int len) -{ - struct iw_event iwe_buf, *iwe = &iwe_buf; - char *pos, *end, *custom, *buf; - - pos = data; - end = data + len; - - while (pos + IW_EV_LCP_LEN <= end) { - /* Event data may be unaligned, so make a local, aligned copy - * before processing. */ - os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); - wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d", - iwe->cmd, iwe->len); - if (iwe->len <= IW_EV_LCP_LEN) - return; - - custom = pos + IW_EV_POINT_LEN; - if (drv->we_version_compiled > 18 && - (iwe->cmd == IWEVMICHAELMICFAILURE || - iwe->cmd == IWEVCUSTOM || - iwe->cmd == IWEVASSOCREQIE || - iwe->cmd == IWEVASSOCRESPIE || - iwe->cmd == IWEVPMKIDCAND)) { - /* WE-19 removed the pointer from struct iw_point */ - char *dpos = (char *) &iwe_buf.u.data.length; - int dlen = dpos - (char *) &iwe_buf; - os_memcpy(dpos, pos + IW_EV_LCP_LEN, - sizeof(struct iw_event) - dlen); - } else { - os_memcpy(&iwe_buf, pos, sizeof(struct iw_event)); - custom += IW_EV_POINT_OFF; - } - - switch (iwe->cmd) { - case SIOCGIWAP: - wpa_printf(MSG_DEBUG, "Wireless event: new AP: " - MACSTR, - MAC2STR((u8 *) iwe->u.ap_addr.sa_data)); - if (is_zero_ether_addr( - (const u8 *) iwe->u.ap_addr.sa_data) || - os_memcmp(iwe->u.ap_addr.sa_data, - "\x44\x44\x44\x44\x44\x44", ETH_ALEN) == - 0) { - os_free(drv->assoc_req_ies); - drv->assoc_req_ies = NULL; - os_free(drv->assoc_resp_ies); - drv->assoc_resp_ies = NULL; - wpa_supplicant_event(ctx, EVENT_DISASSOC, - NULL); - - } else { - wpa_driver_nl80211_event_assoc_ies(drv); - wpa_supplicant_event(ctx, EVENT_ASSOC, NULL); - } - break; - case IWEVMICHAELMICFAILURE: - wpa_driver_nl80211_event_wireless_michaelmicfailure( - ctx, custom, iwe->u.data.length); - break; - case IWEVCUSTOM: - if (custom + iwe->u.data.length > end) - return; - buf = os_malloc(iwe->u.data.length + 1); - if (buf == NULL) - return; - os_memcpy(buf, custom, iwe->u.data.length); - buf[iwe->u.data.length] = '\0'; - wpa_driver_nl80211_event_wireless_custom(ctx, buf); - os_free(buf); - break; - case IWEVASSOCREQIE: - wpa_driver_nl80211_event_wireless_assocreqie( - drv, custom, iwe->u.data.length); - break; - case IWEVASSOCRESPIE: - wpa_driver_nl80211_event_wireless_assocrespie( - drv, custom, iwe->u.data.length); - break; - case IWEVPMKIDCAND: - wpa_driver_nl80211_event_wireless_pmkidcand( - drv, custom, iwe->u.data.length); - break; - } - - pos += iwe->len; - } -} - - -static void wpa_driver_nl80211_event_link(struct wpa_driver_nl80211_data *drv, - void *ctx, char *buf, size_t len, - int del) -{ - union wpa_event_data event; - - os_memset(&event, 0, sizeof(event)); - if (len > sizeof(event.interface_status.ifname)) - len = sizeof(event.interface_status.ifname) - 1; - os_memcpy(event.interface_status.ifname, buf, len); - event.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED : - EVENT_INTERFACE_ADDED; - - wpa_printf(MSG_DEBUG, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s", - del ? "DEL" : "NEW", - event.interface_status.ifname, - del ? "removed" : "added"); - - if (os_strcmp(drv->ifname, event.interface_status.ifname) == 0) { - if (del) - drv->if_removed = 1; - else - drv->if_removed = 0; - } - - wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event); -} - - -static int wpa_driver_nl80211_own_ifname(struct wpa_driver_nl80211_data *drv, - struct nlmsghdr *h) -{ - struct ifinfomsg *ifi; - int attrlen, _nlmsg_len, rta_len; - struct rtattr *attr; - - ifi = NLMSG_DATA(h); - - _nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); - - attrlen = h->nlmsg_len - _nlmsg_len; - if (attrlen < 0) - return 0; - - attr = (struct rtattr *) (((char *) ifi) + _nlmsg_len); - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_IFNAME) { - if (os_strcmp(((char *) attr) + rta_len, drv->ifname) - == 0) - return 1; - else - break; - } - attr = RTA_NEXT(attr, attrlen); - } - - return 0; -} - - -static int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv, - int ifindex, struct nlmsghdr *h) -{ - if (drv->ifindex == ifindex) - return 1; - - if (drv->if_removed && wpa_driver_nl80211_own_ifname(drv, h)) { - drv->ifindex = if_nametoindex(drv->ifname); - wpa_printf(MSG_DEBUG, "nl80211: Update ifindex for a removed " - "interface"); - wpa_driver_nl80211_finish_drv_init(drv); - return 1; - } - - return 0; -} - - -static void wpa_driver_nl80211_event_rtm_newlink(struct wpa_driver_nl80211_data *drv, - void *ctx, struct nlmsghdr *h, - size_t len) -{ - struct ifinfomsg *ifi; - int attrlen, _nlmsg_len, rta_len; - struct rtattr * attr; - - if (len < sizeof(*ifi)) - return; - - ifi = NLMSG_DATA(h); - - if (!wpa_driver_nl80211_own_ifindex(drv, ifi->ifi_index, h)) { - wpa_printf(MSG_DEBUG, "Ignore event for foreign ifindex %d", - ifi->ifi_index); - return; - } - - wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x " - "(%s%s%s%s)", - drv->operstate, ifi->ifi_flags, - (ifi->ifi_flags & IFF_UP) ? "[UP]" : "", - (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "", - (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "", - (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : ""); - /* - * Some drivers send the association event before the operup event--in - * this case, lifting operstate in wpa_driver_nl80211_set_operstate() - * fails. This will hit us when wpa_supplicant does not need to do - * IEEE 802.1X authentication - */ - if (drv->operstate == 1 && - (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP && - !(ifi->ifi_flags & IFF_RUNNING)) - wpa_driver_nl80211_send_oper_ifla(drv, -1, IF_OPER_UP); - - _nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); - - attrlen = h->nlmsg_len - _nlmsg_len; - if (attrlen < 0) - return; - - attr = (struct rtattr *) (((char *) ifi) + _nlmsg_len); - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_WIRELESS) { - wpa_driver_nl80211_event_wireless( - drv, ctx, ((char *) attr) + rta_len, - attr->rta_len - rta_len); - } else if (attr->rta_type == IFLA_IFNAME) { - wpa_driver_nl80211_event_link( - drv, ctx, - ((char *) attr) + rta_len, - attr->rta_len - rta_len, 0); - } - attr = RTA_NEXT(attr, attrlen); - } -} - - -static void wpa_driver_nl80211_event_rtm_dellink(struct wpa_driver_nl80211_data *drv, - void *ctx, struct nlmsghdr *h, - size_t len) -{ - struct ifinfomsg *ifi; - int attrlen, _nlmsg_len, rta_len; - struct rtattr * attr; - - if (len < sizeof(*ifi)) - return; - - ifi = NLMSG_DATA(h); - - _nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); - - attrlen = h->nlmsg_len - _nlmsg_len; - if (attrlen < 0) - return; - - attr = (struct rtattr *) (((char *) ifi) + _nlmsg_len); - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_IFNAME) { - wpa_driver_nl80211_event_link( - drv, ctx, - ((char *) attr) + rta_len, - attr->rta_len - rta_len, 1); - } - attr = RTA_NEXT(attr, attrlen); - } -} - - -static void wpa_driver_nl80211_event_receive_wext(int sock, void *eloop_ctx, - void *sock_ctx) -{ - char buf[8192]; - int left; - struct sockaddr_nl from; - socklen_t fromlen; - struct nlmsghdr *h; - int max_events = 10; - -try_again: - fromlen = sizeof(from); - left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, - (struct sockaddr *) &from, &fromlen); - if (left < 0) { - if (errno != EINTR && errno != EAGAIN) - perror("recvfrom(netlink)"); - return; - } - - h = (struct nlmsghdr *) buf; - while (left >= (int) sizeof(*h)) { - int len, plen; - - len = h->nlmsg_len; - plen = len - sizeof(*h); - if (len > left || plen < 0) { - wpa_printf(MSG_DEBUG, "Malformed netlink message: " - "len=%d left=%d plen=%d", - len, left, plen); - break; - } - - switch (h->nlmsg_type) { - case RTM_NEWLINK: - wpa_driver_nl80211_event_rtm_newlink(eloop_ctx, sock_ctx, - h, plen); - break; - case RTM_DELLINK: - wpa_driver_nl80211_event_rtm_dellink(eloop_ctx, sock_ctx, - h, plen); - break; - } - - len = NLMSG_ALIGN(len); - left -= len; - h = (struct nlmsghdr *) ((char *) h + len); - } - - if (left > 0) { - wpa_printf(MSG_DEBUG, "%d extra bytes in the end of netlink " - "message", left); - } - - if (--max_events > 0) { - /* - * Try to receive all events in one eloop call in order to - * limit race condition on cases where AssocInfo event, Assoc - * event, and EAPOL frames are received more or less at the - * same time. We want to process the event messages first - * before starting EAPOL processing. - */ - goto try_again; - } -} - - -static int no_seq_check(struct nl_msg *msg, void *arg) -{ - return NL_OK; -} - - -static int process_event(struct nl_msg *msg, void *arg) -{ - struct wpa_driver_nl80211_data *drv = arg; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - if (tb[NL80211_ATTR_IFINDEX]) { - int ifindex = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); - if (ifindex != drv->ifindex) { - wpa_printf(MSG_DEBUG, "nl80211: Ignored event (cmd=%d)" - " for foreign interface (ifindex %d)", - gnlh->cmd, ifindex); - return NL_SKIP; - } - } - - switch (gnlh->cmd) { - case NL80211_CMD_TRIGGER_SCAN: - wpa_printf(MSG_DEBUG, "nl80211: Scan trigger"); - break; - case NL80211_CMD_NEW_SCAN_RESULTS: - wpa_printf(MSG_DEBUG, "nl80211: New scan results available"); - drv->scan_complete_events = 1; - eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, - drv->ctx); - wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, NULL); - break; - case NL80211_CMD_SCAN_ABORTED: - wpa_printf(MSG_DEBUG, "nl80211: Scan aborted"); - /* - * Need to indicate that scan results are available in order - * not to make wpa_supplicant stop its scanning. - */ - eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, - drv->ctx); - wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, NULL); - break; - default: - wpa_printf(MSG_DEBUG, "nl0211: Ignored unknown event (cmd=%d)", - gnlh->cmd); - break; - } - - return NL_SKIP; -} - - -static void wpa_driver_nl80211_event_receive(int sock, void *eloop_ctx, - void *sock_ctx) -{ - struct nl_cb *cb; - struct wpa_driver_nl80211_data *drv = eloop_ctx; - - wpa_printf(MSG_DEBUG, "nl80211: Event message available"); - - cb = nl_cb_clone(drv->nl_cb); - if (!cb) - return; - nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); - nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, process_event, drv); - nl_recvmsgs(drv->nl_handle, cb); - nl_cb_put(cb); -} - - -static int wpa_driver_nl80211_get_ifflags_ifname(struct wpa_driver_nl80211_data *drv, - const char *ifname, int *flags) -{ - struct ifreq ifr; - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); - if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { - perror("ioctl[SIOCGIFFLAGS]"); - return -1; - } - *flags = ifr.ifr_flags & 0xffff; - return 0; -} - - -/** - * wpa_driver_nl80211_get_ifflags - Get interface flags (SIOCGIFFLAGS) - * @drv: driver_nl80211 private data - * @flags: Pointer to returned flags value - * Returns: 0 on success, -1 on failure - */ -static int wpa_driver_nl80211_get_ifflags(struct wpa_driver_nl80211_data *drv, - int *flags) -{ - return wpa_driver_nl80211_get_ifflags_ifname(drv, drv->ifname, flags); -} - - -static int wpa_driver_nl80211_set_ifflags_ifname( - struct wpa_driver_nl80211_data *drv, - const char *ifname, int flags) -{ - struct ifreq ifr; - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); - ifr.ifr_flags = flags & 0xffff; - if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { - perror("SIOCSIFFLAGS"); - return -1; - } - return 0; -} - - -/** - * wpa_driver_nl80211_set_ifflags - Set interface flags (SIOCSIFFLAGS) - * @drv: driver_nl80211 private data - * @flags: New value for flags - * Returns: 0 on success, -1 on failure - */ -static int wpa_driver_nl80211_set_ifflags(struct wpa_driver_nl80211_data *drv, - int flags) -{ - return wpa_driver_nl80211_set_ifflags_ifname(drv, drv->ifname, flags); -} - - -/** - * wpa_driver_nl80211_set_country - ask nl80211 to set the regulatory domain - * @priv: driver_nl80211 private data - * @alpha2_arg: country to which to switch to - * Returns: 0 on success, -1 on failure - * - * This asks nl80211 to set the regulatory domain for given - * country ISO / IEC alpha2. - */ -static int wpa_driver_nl80211_set_country(void *priv, const char *alpha2_arg) -{ - struct wpa_driver_nl80211_data *drv = priv; - char alpha2[3]; - struct nl_msg *msg; - - msg = nlmsg_alloc(); - if (!msg) - goto nla_put_failure; - - alpha2[0] = alpha2_arg[0]; - alpha2[1] = alpha2_arg[1]; - alpha2[2] = '\0'; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_REQ_SET_REG, 0); - - NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2); - if (send_and_recv_msgs(drv, msg, NULL, NULL)) - return -EINVAL; - return 0; -nla_put_failure: - return -EINVAL; -} - - -static int wpa_driver_nl80211_set_probe_req_ie(void *priv, const u8 *ies, - size_t ies_len) -{ - struct wpa_driver_nl80211_data *drv = priv; - struct nl_msg *msg; - int ret = -1; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_SET_MGMT_EXTRA_IE, 0); - - NLA_PUT_U8(msg, NL80211_ATTR_MGMT_SUBTYPE, 4 /* ProbeReq */); - if (ies) - NLA_PUT(msg, NL80211_ATTR_IE, ies_len, ies); - - ret = 0; - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - return ret; - -nla_put_failure: - return -ENOBUFS; -} - - -#ifdef CONFIG_CLIENT_MLME - -static int nl80211_set_vif(struct wpa_driver_nl80211_data *drv, - int drop_unencrypted, int userspace_mlme) -{ -#ifdef NL80211_CMD_SET_VIF - struct nl_msg *msg; - int ret = -1; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_SET_VIF, 0); - - if (drop_unencrypted >= 0) - NLA_PUT_U8(msg, NL80211_ATTR_VIF_DROP_UNENCRYPTED, - drop_unencrypted); - if (userspace_mlme >= 0) - NLA_PUT_U8(msg, NL80211_ATTR_VIF_USERSPACE_MLME, - userspace_mlme); - - ret = 0; - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - return ret; - -nla_put_failure: - return -ENOBUFS; -#else /* NL80211_CMD_SET_VIF */ - return -1; -#endif /* NL80211_CMD_SET_VIF */ -} - - -static int wpa_driver_nl80211_set_userspace_mlme( - struct wpa_driver_nl80211_data *drv, int enabled) -{ - return nl80211_set_vif(drv, -1, enabled); -} - - -static void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, - int ifidx) -{ - struct nl_msg *msg; - - msg = nlmsg_alloc(); - if (!msg) - goto nla_put_failure; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_DEL_INTERFACE, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx); - if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) - return; -nla_put_failure: - wpa_printf(MSG_ERROR, "nl80211: Failed to remove interface."); -} - - -static int nl80211_create_iface(struct wpa_driver_nl80211_data *drv, - const char *ifname, enum nl80211_iftype iftype) -{ - struct nl_msg *msg, *flags = NULL; - int ifidx, err; - int ret = -ENOBUFS; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_NEW_INTERFACE, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->ifname)); - NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ifname); - NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype); - - if (iftype == NL80211_IFTYPE_MONITOR) { - flags = nlmsg_alloc(); - if (!flags) - goto nla_put_failure; - - NLA_PUT_FLAG(flags, NL80211_MNTR_FLAG_COOK_FRAMES); - - err = nla_put_nested(msg, NL80211_ATTR_MNTR_FLAGS, flags); - - nlmsg_free(flags); - - if (err) - goto nla_put_failure; - } - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (ret) { - nla_put_failure: - wpa_printf(MSG_ERROR, "nl80211: Failed to create interface %d", - ret); - return ret; - } - - ifidx = if_nametoindex(ifname); - if (ifidx <= 0) - return -1; - - return ifidx; -} - - -static void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct wpa_driver_nl80211_data *drv = eloop_ctx; - int len; - unsigned char buf[3000]; - struct ieee80211_radiotap_iterator iter; - int ret; - int injected = 0, failed = 0, rxflags = 0; - struct ieee80211_rx_status rx_status; - - len = recv(sock, buf, sizeof(buf), 0); - if (len < 0) { - perror("recv"); - return; - } - - if (ieee80211_radiotap_iterator_init(&iter, (void *) buf, len)) { - wpa_printf(MSG_DEBUG, "nl80211: received invalid radiotap " - "frame"); - return; - } - - os_memset(&rx_status, 0, sizeof(rx_status)); - - while (1) { - ret = ieee80211_radiotap_iterator_next(&iter); - if (ret == -ENOENT) - break; - if (ret) { - wpa_printf(MSG_DEBUG, "nl80211: received invalid " - "radiotap frame (%d)", ret); - return; - } - switch (iter.this_arg_index) { - case IEEE80211_RADIOTAP_FLAGS: - if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS) - len -= 4; - break; - case IEEE80211_RADIOTAP_RX_FLAGS: - rxflags = 1; - break; - case IEEE80211_RADIOTAP_TX_FLAGS: - injected = 1; - failed = le_to_host16((*(u16 *) iter.this_arg)) & - IEEE80211_RADIOTAP_F_TX_FAIL; - break; - case IEEE80211_RADIOTAP_DATA_RETRIES: - break; - case IEEE80211_RADIOTAP_CHANNEL: - /* TODO convert from freq/flags to channel number - * rx_status.channel = XXX; - */ - break; - case IEEE80211_RADIOTAP_RATE: - break; - case IEEE80211_RADIOTAP_DB_ANTSIGNAL: - rx_status.ssi = *iter.this_arg; - break; - } - } - - if (rxflags && injected) - return; - - if (!injected) { - wpa_supplicant_sta_rx(drv->ctx, buf + iter.max_length, - len - iter.max_length, &rx_status); - } else if (failed) { - /* TX failure callback */ - } else { - /* TX success (ACK) callback */ - } -} - - -static int wpa_driver_nl80211_create_monitor_interface( - struct wpa_driver_nl80211_data *drv) -{ - char buf[IFNAMSIZ]; - struct sockaddr_ll ll; - int optval, flags; - socklen_t optlen; - - os_snprintf(buf, IFNAMSIZ, "mon.%s", drv->ifname); - buf[IFNAMSIZ - 1] = '\0'; - - drv->monitor_ifidx = - nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR); - - if (drv->monitor_ifidx < 0) - return -1; - - if (wpa_driver_nl80211_get_ifflags_ifname(drv, buf, &flags) != 0 || - wpa_driver_nl80211_set_ifflags_ifname(drv, buf, flags | IFF_UP) != - 0) { - wpa_printf(MSG_ERROR, "nl80211: Could not set interface '%s' " - "UP", buf); - goto error; - } - - os_memset(&ll, 0, sizeof(ll)); - ll.sll_family = AF_PACKET; - ll.sll_ifindex = drv->monitor_ifidx; - drv->monitor_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (drv->monitor_sock < 0) { - perror("socket[PF_PACKET,SOCK_RAW]"); - goto error; - } - - if (bind(drv->monitor_sock, (struct sockaddr *) &ll, - sizeof(ll)) < 0) { - perror("monitor socket bind"); - goto error; - } - - optlen = sizeof(optval); - optval = 20; - if (setsockopt - (drv->monitor_sock, SOL_SOCKET, SO_PRIORITY, &optval, optlen)) { - perror("Failed to set socket priority"); - goto error; - } - - if (eloop_register_read_sock(drv->monitor_sock, handle_monitor_read, - drv, NULL)) { - wpa_printf(MSG_ERROR, "nl80211: Could not register monitor " - "read socket"); - goto error; - } - - return 0; - - error: - nl80211_remove_iface(drv, drv->monitor_ifidx); - return -1; -} - -#endif /* CONFIG_CLIENT_MLME */ - - -/** - * wpa_driver_nl80211_init - Initialize nl80211 driver interface - * @ctx: context to be used when calling wpa_supplicant functions, - * e.g., wpa_supplicant_event() - * @ifname: interface name, e.g., wlan0 - * Returns: Pointer to private data, %NULL on failure - */ -static void * wpa_driver_nl80211_init(void *ctx, const char *ifname) -{ - int s, ret; - struct sockaddr_nl local; - struct wpa_driver_nl80211_data *drv; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->ctx = ctx; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - - drv->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); - if (drv->nl_cb == NULL) { - wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink " - "callbacks"); - goto err1; - } - - drv->nl_handle = nl_handle_alloc_cb(drv->nl_cb); - if (drv->nl_handle == NULL) { - wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink " - "callbacks"); - goto err2; - } - - if (genl_connect(drv->nl_handle)) { - wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic " - "netlink"); - goto err3; - } - - drv->nl_cache = genl_ctrl_alloc_cache(drv->nl_handle); - if (drv->nl_cache == NULL) { - wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic " - "netlink cache"); - goto err3; - } - - drv->nl80211 = genl_ctrl_search_by_name(drv->nl_cache, "nl80211"); - if (drv->nl80211 == NULL) { - wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not " - "found"); - goto err4; - } - - ret = nl_get_multicast_id(drv, "nl80211", "scan"); - if (ret >= 0) - ret = nl_socket_add_membership(drv->nl_handle, ret); - if (ret < 0) { - wpa_printf(MSG_ERROR, "nl80211: Could not add multicast " - "membership for scan events: %d (%s)", - ret, strerror(-ret)); - goto err4; - } - eloop_register_read_sock(nl_socket_get_fd(drv->nl_handle), - wpa_driver_nl80211_event_receive, drv, ctx); - - drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->ioctl_sock < 0) { - perror("socket(PF_INET,SOCK_DGRAM)"); - goto err5; - } - - s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (s < 0) { - perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)"); - goto err6; - } - - os_memset(&local, 0, sizeof(local)); - local.nl_family = AF_NETLINK; - local.nl_groups = RTMGRP_LINK; - if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) { - perror("bind(netlink)"); - close(s); - goto err6; - } - - eloop_register_read_sock(s, wpa_driver_nl80211_event_receive_wext, drv, - ctx); - drv->wext_event_sock = s; - - wpa_driver_nl80211_finish_drv_init(drv); - - return drv; - -err6: - close(drv->ioctl_sock); -err5: - genl_family_put(drv->nl80211); -err4: - nl_cache_free(drv->nl_cache); -err3: - nl_handle_destroy(drv->nl_handle); -err2: - nl_cb_put(drv->nl_cb); -err1: - os_free(drv); - return NULL; -} - - -static void -wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv) -{ - int flags; - - drv->ifindex = if_nametoindex(drv->ifname); - - if (wpa_driver_nl80211_set_mode(drv, 0) < 0) { - printf("Could not configure driver to use managed mode\n"); - } - - if (wpa_driver_nl80211_get_ifflags(drv, &flags) != 0) - printf("Could not get interface '%s' flags\n", drv->ifname); - else if (!(flags & IFF_UP)) { - if (wpa_driver_nl80211_set_ifflags(drv, flags | IFF_UP) != 0) { - printf("Could not set interface '%s' UP\n", - drv->ifname); - } - } - - /* - * Make sure that the driver does not have any obsolete PMKID entries. - */ - wpa_driver_nl80211_flush_pmkid(drv); - - wpa_driver_nl80211_get_range(drv); - - wpa_driver_nl80211_send_oper_ifla(drv, 1, IF_OPER_DORMANT); -} - - -/** - * wpa_driver_nl80211_deinit - Deinitialize nl80211 driver interface - * @priv: Pointer to private nl80211 data from wpa_driver_nl80211_init() - * - * Shut down driver interface and processing of driver events. Free - * private data buffer if one was allocated in wpa_driver_nl80211_init(). - */ -static void wpa_driver_nl80211_deinit(void *priv) -{ - struct wpa_driver_nl80211_data *drv = priv; - int flags; - -#ifdef CONFIG_CLIENT_MLME - if (drv->monitor_sock >= 0) { - eloop_unregister_read_sock(drv->monitor_sock); - close(drv->monitor_sock); - } - if (drv->monitor_ifidx > 0) - nl80211_remove_iface(drv, drv->monitor_ifidx); - if (drv->capa.flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) - wpa_driver_nl80211_set_userspace_mlme(drv, 0); -#endif /* CONFIG_CLIENT_MLME */ - - eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); - - /* - * Clear possibly configured driver parameters in order to make it - * easier to use the driver after wpa_supplicant has been terminated. - */ - (void) wpa_driver_nl80211_set_bssid(drv, - (u8 *) "\x00\x00\x00\x00\x00\x00"); - - wpa_driver_nl80211_send_oper_ifla(priv, 0, IF_OPER_UP); - - eloop_unregister_read_sock(drv->wext_event_sock); - - if (wpa_driver_nl80211_get_ifflags(drv, &flags) == 0) - (void) wpa_driver_nl80211_set_ifflags(drv, flags & ~IFF_UP); - - close(drv->wext_event_sock); - close(drv->ioctl_sock); - os_free(drv->assoc_req_ies); - os_free(drv->assoc_resp_ies); - - eloop_unregister_read_sock(nl_socket_get_fd(drv->nl_handle)); - genl_family_put(drv->nl80211); - nl_cache_free(drv->nl_cache); - nl_handle_destroy(drv->nl_handle); - nl_cb_put(drv->nl_cb); - - os_free(drv); -} - - -/** - * wpa_driver_nl80211_scan_timeout - Scan timeout to report scan completion - * @eloop_ctx: Unused - * @timeout_ctx: ctx argument given to wpa_driver_nl80211_init() - * - * This function can be used as registered timeout when starting a scan to - * generate a scan completed event if the driver does not report this. - */ -static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx) -{ - wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); - wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); -} - - -/** - * wpa_driver_nl80211_scan - Request the driver to initiate scan - * @priv: Pointer to private wext data from wpa_driver_nl80211_init() - * @ssid: Specific SSID to scan for (ProbeReq) or %NULL to scan for - * all SSIDs (either active scan with broadcast SSID or passive - * scan - * @ssid_len: Length of the SSID - * Returns: 0 on success, -1 on failure - */ -static int wpa_driver_nl80211_scan(void *priv, const u8 *ssid, size_t ssid_len) -{ - struct wpa_driver_nl80211_data *drv = priv; - int ret = 0, timeout; - struct nl_msg *msg, *ssids; - - msg = nlmsg_alloc(); - ssids = nlmsg_alloc(); - if (!msg || !ssids) { - nlmsg_free(msg); - nlmsg_free(ssids); - return -1; - } - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_TRIGGER_SCAN, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - - if (ssid && ssid_len) { - /* Request an active scan for a specific SSID */ - NLA_PUT(ssids, 1, ssid_len, ssid); - } else { - /* Request an active scan for wildcard SSID */ - NLA_PUT(ssids, 1, 0, ""); - } - nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - msg = NULL; - if (ret) { - wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d " - "(%s)", ret, strerror(-ret)); - goto nla_put_failure; - } - - /* Not all drivers generate "scan completed" wireless event, so try to - * read results after a timeout. */ - timeout = 10; - if (drv->scan_complete_events) { - /* - * The driver seems to deliver SIOCGIWSCAN events to notify - * when scan is complete, so use longer timeout to avoid race - * conditions with scanning and following association request. - */ - timeout = 30; - } - wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d " - "seconds", ret, timeout); - eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); - eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout, - drv, drv->ctx); - -nla_put_failure: - nlmsg_free(ssids); - nlmsg_free(msg); - return ret; -} - - -static int bss_info_handler(struct nl_msg *msg, void *arg) -{ - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct nlattr *bss[NL80211_BSS_MAX + 1]; - static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = { - [NL80211_BSS_BSSID] = { .type = NLA_UNSPEC }, - [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 }, - [NL80211_BSS_TSF] = { .type = NLA_U64 }, - [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 }, - [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 }, - [NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC }, - [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 }, - [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 }, - }; - struct wpa_scan_results *res = arg; - struct wpa_scan_res **tmp; - struct wpa_scan_res *r; - const u8 *ie; - size_t ie_len; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - if (!tb[NL80211_ATTR_BSS]) - return NL_SKIP; - if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], - bss_policy)) - return NL_SKIP; - if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) { - ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]); - ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]); - } else { - ie = NULL; - ie_len = 0; - } - - r = os_zalloc(sizeof(*r) + ie_len); - if (r == NULL) - return NL_SKIP; - if (bss[NL80211_BSS_BSSID]) - os_memcpy(r->bssid, nla_data(bss[NL80211_BSS_BSSID]), - ETH_ALEN); - if (bss[NL80211_BSS_FREQUENCY]) - r->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]); - if (bss[NL80211_BSS_BEACON_INTERVAL]) - r->beacon_int = nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]); - if (bss[NL80211_BSS_CAPABILITY]) - r->caps = nla_get_u16(bss[NL80211_BSS_CAPABILITY]); - if (bss[NL80211_BSS_SIGNAL_UNSPEC]) - r->qual = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]); - if (bss[NL80211_BSS_SIGNAL_MBM]) - r->level = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]); - if (bss[NL80211_BSS_TSF]) - r->tsf = nla_get_u64(bss[NL80211_BSS_TSF]); - r->ie_len = ie_len; - if (ie) - os_memcpy(r + 1, ie, ie_len); - - tmp = os_realloc(res->res, - (res->num + 1) * sizeof(struct wpa_scan_res *)); - if (tmp == NULL) { - os_free(r); - return NL_SKIP; - } - tmp[res->num++] = r; - res->res = tmp; - - return NL_SKIP; -} - - -/** - * wpa_driver_nl80211_get_scan_results - Fetch the latest scan results - * @priv: Pointer to private wext data from wpa_driver_nl80211_init() - * Returns: Scan results on success, -1 on failure - */ -static struct wpa_scan_results * -wpa_driver_nl80211_get_scan_results(void *priv) -{ - struct wpa_driver_nl80211_data *drv = priv; - struct nl_msg *msg; - struct wpa_scan_results *res; - int ret; - - res = os_zalloc(sizeof(*res)); - if (res == NULL) - return 0; - msg = nlmsg_alloc(); - if (!msg) - goto nla_put_failure; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, NLM_F_DUMP, - NL80211_CMD_GET_SCAN, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - - ret = send_and_recv_msgs(drv, msg, bss_info_handler, res); - msg = NULL; - if (ret == 0) { - wpa_printf(MSG_DEBUG, "Received scan results (%lu BSSes)", - (unsigned long) res->num); - return res; - } - wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d " - "(%s)", ret, strerror(-ret)); -nla_put_failure: - nlmsg_free(msg); - wpa_scan_results_free(res); - return NULL; -} - - -static int wpa_driver_nl80211_get_range(void *priv) -{ - struct wpa_driver_nl80211_data *drv = priv; - struct iw_range *range; - struct iwreq iwr; - int minlen; - size_t buflen; - - /* - * Use larger buffer than struct iw_range in order to allow the - * structure to grow in the future. - */ - buflen = sizeof(struct iw_range) + 500; - range = os_zalloc(buflen); - if (range == NULL) - return -1; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) range; - iwr.u.data.length = buflen; - - minlen = ((char *) &range->enc_capa) - (char *) range + - sizeof(range->enc_capa); - - if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) { - perror("ioctl[SIOCGIWRANGE]"); - os_free(range); - return -1; - } else if (iwr.u.data.length >= minlen && - range->we_version_compiled >= 18) { - wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d " - "WE(source)=%d enc_capa=0x%x", - range->we_version_compiled, - range->we_version_source, - range->enc_capa); - drv->has_capability = 1; - drv->we_version_compiled = range->we_version_compiled; - if (range->enc_capa & IW_ENC_CAPA_WPA) { - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; - } - if (range->enc_capa & IW_ENC_CAPA_WPA2) { - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; - } - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | - WPA_DRIVER_CAPA_ENC_WEP104; - if (range->enc_capa & IW_ENC_CAPA_CIPHER_TKIP) - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; - if (range->enc_capa & IW_ENC_CAPA_CIPHER_CCMP) - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; - drv->capa.auth = WPA_DRIVER_AUTH_OPEN | - WPA_DRIVER_AUTH_SHARED | - WPA_DRIVER_AUTH_LEAP; - wpa_printf(MSG_DEBUG, " capabilities: key_mgmt 0x%x enc 0x%x", - drv->capa.key_mgmt, drv->capa.enc); - } else { - wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: too old (short) data - " - "assuming WPA is not supported"); - } - - os_free(range); - return 0; -} - - -static int wpa_driver_nl80211_set_wpa(void *priv, int enabled) -{ - struct wpa_driver_nl80211_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - return wpa_driver_nl80211_set_auth_param(drv, IW_AUTH_WPA_ENABLED, - enabled); -} - - -static int wpa_driver_nl80211_set_key(void *priv, wpa_alg alg, - const u8 *addr, int key_idx, - int set_tx, const u8 *seq, - size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_nl80211_data *drv = priv; - int err; - struct nl_msg *msg; - - wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%p key_idx=%d set_tx=%d " - "seq_len=%lu key_len=%lu", - __func__, alg, addr, key_idx, set_tx, - (unsigned long) seq_len, (unsigned long) key_len); - - msg = nlmsg_alloc(); - if (msg == NULL) - return -1; - - if (alg == WPA_ALG_NONE) { - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_DEL_KEY, 0); - } else { - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_NEW_KEY, 0); - NLA_PUT(msg, NL80211_ATTR_KEY_DATA, key_len, key); - switch (alg) { - case WPA_ALG_WEP: - if (key_len == 5) - NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, - 0x000FAC01); - else - NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, - 0x000FAC05); - break; - case WPA_ALG_TKIP: - NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC02); - break; - case WPA_ALG_CCMP: - NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC04); - break; -#ifdef CONFIG_IEEE80211W - case WPA_ALG_IGTK: - NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC06); - break; -#endif /* CONFIG_IEEE80211W */ - default: - nlmsg_free(msg); - return -1; - } - } - - if (addr && os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) - { - wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr)); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - } - NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - - err = send_and_recv_msgs(drv, msg, NULL, NULL); - if (err) { - wpa_printf(MSG_DEBUG, "nl80211: set_key failed; err=%d", err); - return -1; - } - - if (set_tx && alg != WPA_ALG_NONE) { - msg = nlmsg_alloc(); - if (msg == NULL) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_KEY, 0); - NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT); - - err = send_and_recv_msgs(drv, msg, NULL, NULL); - if (err) { - wpa_printf(MSG_DEBUG, "nl80211: set default key " - "failed; err=%d", err); - return -1; - } - } - - return 0; - -nla_put_failure: - return -ENOBUFS; -} - - -static int wpa_driver_nl80211_set_countermeasures(void *priv, - int enabled) -{ - struct wpa_driver_nl80211_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - return wpa_driver_nl80211_set_auth_param(drv, - IW_AUTH_TKIP_COUNTERMEASURES, - enabled); -} - - -static int wpa_driver_nl80211_set_drop_unencrypted(void *priv, - int enabled) -{ - struct wpa_driver_nl80211_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - drv->use_crypt = enabled; - return wpa_driver_nl80211_set_auth_param(drv, IW_AUTH_DROP_UNENCRYPTED, - enabled); -} - - -static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv, - const u8 *addr, int cmd, int reason_code) -{ - struct iwreq iwr; - struct iw_mlme mlme; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - os_memset(&mlme, 0, sizeof(mlme)); - mlme.cmd = cmd; - mlme.reason_code = reason_code; - mlme.addr.sa_family = ARPHRD_ETHER; - os_memcpy(mlme.addr.sa_data, addr, ETH_ALEN); - iwr.u.data.pointer = (caddr_t) &mlme; - iwr.u.data.length = sizeof(mlme); - - if (ioctl(drv->ioctl_sock, SIOCSIWMLME, &iwr) < 0) { - perror("ioctl[SIOCSIWMLME]"); - ret = -1; - } - - return ret; -} - - -static int wpa_driver_nl80211_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_nl80211_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - return wpa_driver_nl80211_mlme(drv, addr, IW_MLME_DEAUTH, reason_code); -} - - -static int wpa_driver_nl80211_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_nl80211_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - return wpa_driver_nl80211_mlme(drv, addr, IW_MLME_DISASSOC, - reason_code); -} - - -static int wpa_driver_nl80211_set_gen_ie(void *priv, const u8 *ie, - size_t ie_len) -{ - struct wpa_driver_nl80211_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) ie; - iwr.u.data.length = ie_len; - - if (ioctl(drv->ioctl_sock, SIOCSIWGENIE, &iwr) < 0) { - perror("ioctl[SIOCSIWGENIE]"); - ret = -1; - } - - return ret; -} - - -static int wpa_driver_nl80211_cipher2wext(int cipher) -{ - switch (cipher) { - case CIPHER_NONE: - return IW_AUTH_CIPHER_NONE; - case CIPHER_WEP40: - return IW_AUTH_CIPHER_WEP40; - case CIPHER_TKIP: - return IW_AUTH_CIPHER_TKIP; - case CIPHER_CCMP: - return IW_AUTH_CIPHER_CCMP; - case CIPHER_WEP104: - return IW_AUTH_CIPHER_WEP104; - default: - return 0; - } -} - - -static int wpa_driver_nl80211_keymgmt2wext(int keymgmt) -{ - switch (keymgmt) { - case KEY_MGMT_802_1X: - case KEY_MGMT_802_1X_NO_WPA: - return IW_AUTH_KEY_MGMT_802_1X; - case KEY_MGMT_PSK: - return IW_AUTH_KEY_MGMT_PSK; - default: - return 0; - } -} - - -static int -wpa_driver_nl80211_auth_alg_fallback(struct wpa_driver_nl80211_data *drv, - struct wpa_driver_associate_params *params) -{ - struct iwreq iwr; - int ret = 0; - - wpa_printf(MSG_DEBUG, "WEXT: Driver did not support " - "SIOCSIWAUTH for AUTH_ALG, trying SIOCSIWENCODE"); - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - /* Just changing mode, not actual keys */ - iwr.u.encoding.flags = 0; - iwr.u.encoding.pointer = (caddr_t) NULL; - iwr.u.encoding.length = 0; - - /* - * Note: IW_ENCODE_{OPEN,RESTRICTED} can be interpreted to mean two - * different things. Here they are used to indicate Open System vs. - * Shared Key authentication algorithm. However, some drivers may use - * them to select between open/restricted WEP encrypted (open = allow - * both unencrypted and encrypted frames; restricted = only allow - * encrypted frames). - */ - - if (!drv->use_crypt) { - iwr.u.encoding.flags |= IW_ENCODE_DISABLED; - } else { - if (params->auth_alg & AUTH_ALG_OPEN_SYSTEM) - iwr.u.encoding.flags |= IW_ENCODE_OPEN; - if (params->auth_alg & AUTH_ALG_SHARED_KEY) - iwr.u.encoding.flags |= IW_ENCODE_RESTRICTED; - } - - if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { - perror("ioctl[SIOCSIWENCODE]"); - ret = -1; - } - - return ret; -} - - -static int wpa_driver_nl80211_associate( - void *priv, struct wpa_driver_associate_params *params) -{ - struct wpa_driver_nl80211_data *drv = priv; - int ret = 0; - int allow_unencrypted_eapol; - int value; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - /* - * If the driver did not support SIOCSIWAUTH, fallback to - * SIOCSIWENCODE here. - */ - if (drv->auth_alg_fallback && - wpa_driver_nl80211_auth_alg_fallback(drv, params) < 0) - ret = -1; - - if (!params->bssid && - wpa_driver_nl80211_set_bssid(drv, NULL) < 0) - ret = -1; - - /* TODO: should consider getting wpa version and cipher/key_mgmt suites - * from configuration, not from here, where only the selected suite is - * available */ - if (wpa_driver_nl80211_set_gen_ie(drv, params->wpa_ie, params->wpa_ie_len) - < 0) - ret = -1; - if (params->wpa_ie == NULL || params->wpa_ie_len == 0) - value = IW_AUTH_WPA_VERSION_DISABLED; - else if (params->wpa_ie[0] == WLAN_EID_RSN) - value = IW_AUTH_WPA_VERSION_WPA2; - else - value = IW_AUTH_WPA_VERSION_WPA; - if (wpa_driver_nl80211_set_auth_param(drv, - IW_AUTH_WPA_VERSION, value) < 0) - ret = -1; - value = wpa_driver_nl80211_cipher2wext(params->pairwise_suite); - if (wpa_driver_nl80211_set_auth_param(drv, - IW_AUTH_CIPHER_PAIRWISE, value) < 0) - ret = -1; - value = wpa_driver_nl80211_cipher2wext(params->group_suite); - if (wpa_driver_nl80211_set_auth_param(drv, - IW_AUTH_CIPHER_GROUP, value) < 0) - ret = -1; - value = wpa_driver_nl80211_keymgmt2wext(params->key_mgmt_suite); - if (wpa_driver_nl80211_set_auth_param(drv, - IW_AUTH_KEY_MGMT, value) < 0) - ret = -1; - value = params->key_mgmt_suite != KEY_MGMT_NONE || - params->pairwise_suite != CIPHER_NONE || - params->group_suite != CIPHER_NONE || - params->wpa_ie_len; - if (wpa_driver_nl80211_set_auth_param(drv, - IW_AUTH_PRIVACY_INVOKED, value) < 0) - ret = -1; - - /* Allow unencrypted EAPOL messages even if pairwise keys are set when - * not using WPA. IEEE 802.1X specifies that these frames are not - * encrypted, but WPA encrypts them when pairwise keys are in use. */ - if (params->key_mgmt_suite == KEY_MGMT_802_1X || - params->key_mgmt_suite == KEY_MGMT_PSK) - allow_unencrypted_eapol = 0; - else - allow_unencrypted_eapol = 1; - - if (wpa_driver_nl80211_set_auth_param(drv, - IW_AUTH_RX_UNENCRYPTED_EAPOL, - allow_unencrypted_eapol) < 0) - ret = -1; - if (params->freq && wpa_driver_nl80211_set_freq(drv, params->freq) < 0) - ret = -1; - if (wpa_driver_nl80211_set_ssid(drv, params->ssid, params->ssid_len) < 0) - ret = -1; - if (params->bssid && - wpa_driver_nl80211_set_bssid(drv, params->bssid) < 0) - ret = -1; - - return ret; -} - - -static int wpa_driver_nl80211_set_auth_alg(void *priv, int auth_alg) -{ - struct wpa_driver_nl80211_data *drv = priv; - int algs = 0, res; - - if (auth_alg & AUTH_ALG_OPEN_SYSTEM) - algs |= IW_AUTH_ALG_OPEN_SYSTEM; - if (auth_alg & AUTH_ALG_SHARED_KEY) - algs |= IW_AUTH_ALG_SHARED_KEY; - if (auth_alg & AUTH_ALG_LEAP) - algs |= IW_AUTH_ALG_LEAP; - if (algs == 0) { - /* at least one algorithm should be set */ - algs = IW_AUTH_ALG_OPEN_SYSTEM; - } - - res = wpa_driver_nl80211_set_auth_param(drv, IW_AUTH_80211_AUTH_ALG, - algs); - drv->auth_alg_fallback = res == -2; - return res; -} - - -/** - * wpa_driver_nl80211_set_mode - Set wireless mode (infra/adhoc), SIOCSIWMODE - * @priv: Pointer to private wext data from wpa_driver_nl80211_init() - * @mode: 0 = infra/BSS (associate with an AP), 1 = adhoc/IBSS - * Returns: 0 on success, -1 on failure - */ -static int wpa_driver_nl80211_set_mode(void *priv, int mode) -{ - struct wpa_driver_nl80211_data *drv = priv; - int ret = -1, flags; - struct nl_msg *msg; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_INTERFACE, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, - mode ? NL80211_IFTYPE_ADHOC : NL80211_IFTYPE_STATION); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (!ret) - return 0; - else - goto try_again; - -nla_put_failure: - wpa_printf(MSG_ERROR, "nl80211: Failed to set interface mode: %d (%s)", - ret, strerror(-ret)); - return -1; - -try_again: - /* mac80211 doesn't allow mode changes while the device is up, so - * take the device down, try to set the mode again, and bring the - * device back up. - */ - if (wpa_driver_nl80211_get_ifflags(drv, &flags) == 0) { - (void) wpa_driver_nl80211_set_ifflags(drv, flags & ~IFF_UP); - - /* Try to set the mode again while the interface is down */ - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_INTERFACE, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, - mode ? NL80211_IFTYPE_ADHOC : - NL80211_IFTYPE_STATION); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (ret) { - wpa_printf(MSG_ERROR, "Failed to set interface %s " - "mode(try_again): %d (%s)", - drv->ifname, ret, strerror(-ret)); - } - - /* Ignore return value of get_ifflags to ensure that the device - * is always up like it was before this function was called. - */ - (void) wpa_driver_nl80211_get_ifflags(drv, &flags); - (void) wpa_driver_nl80211_set_ifflags(drv, flags | IFF_UP); - } - - return ret; -} - - -static int wpa_driver_nl80211_pmksa(struct wpa_driver_nl80211_data *drv, - u32 cmd, const u8 *bssid, const u8 *pmkid) -{ - struct iwreq iwr; - struct iw_pmksa pmksa; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - os_memset(&pmksa, 0, sizeof(pmksa)); - pmksa.cmd = cmd; - pmksa.bssid.sa_family = ARPHRD_ETHER; - if (bssid) - os_memcpy(pmksa.bssid.sa_data, bssid, ETH_ALEN); - if (pmkid) - os_memcpy(pmksa.pmkid, pmkid, IW_PMKID_LEN); - iwr.u.data.pointer = (caddr_t) &pmksa; - iwr.u.data.length = sizeof(pmksa); - - if (ioctl(drv->ioctl_sock, SIOCSIWPMKSA, &iwr) < 0) { - if (errno != EOPNOTSUPP) - perror("ioctl[SIOCSIWPMKSA]"); - ret = -1; - } - - return ret; -} - - -static int wpa_driver_nl80211_add_pmkid(void *priv, const u8 *bssid, - const u8 *pmkid) -{ - struct wpa_driver_nl80211_data *drv = priv; - return wpa_driver_nl80211_pmksa(drv, IW_PMKSA_ADD, bssid, pmkid); -} - - -static int wpa_driver_nl80211_remove_pmkid(void *priv, const u8 *bssid, - const u8 *pmkid) -{ - struct wpa_driver_nl80211_data *drv = priv; - return wpa_driver_nl80211_pmksa(drv, IW_PMKSA_REMOVE, bssid, pmkid); -} - - -static int wpa_driver_nl80211_flush_pmkid(void *priv) -{ - struct wpa_driver_nl80211_data *drv = priv; - return wpa_driver_nl80211_pmksa(drv, IW_PMKSA_FLUSH, NULL, NULL); -} - - -static int wpa_driver_nl80211_get_capa(void *priv, - struct wpa_driver_capa *capa) -{ - struct wpa_driver_nl80211_data *drv = priv; - if (!drv->has_capability) - return -1; - os_memcpy(capa, &drv->capa, sizeof(*capa)); - return 0; -} - - -static int wpa_driver_nl80211_set_operstate(void *priv, int state) -{ - struct wpa_driver_nl80211_data *drv = priv; - - wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)", - __func__, drv->operstate, state, state ? "UP" : "DORMANT"); - drv->operstate = state; - return wpa_driver_nl80211_send_oper_ifla( - drv, -1, state ? IF_OPER_UP : IF_OPER_DORMANT); -} - - -#ifdef CONFIG_CLIENT_MLME -static int wpa_driver_nl80211_open_mlme(struct wpa_driver_nl80211_data *drv) -{ - if (wpa_driver_nl80211_set_userspace_mlme(drv, 1) < 0) { - wpa_printf(MSG_ERROR, "nl80211: Failed to enable userspace " - "MLME"); - return -1; - } - if (wpa_driver_nl80211_create_monitor_interface(drv)) { - wpa_printf(MSG_ERROR, "nl80211: Failed to create monitor " - "interface"); - return -1; - } - return 0; -} -#endif /* CONFIG_CLIENT_MLME */ - - -static int wpa_driver_nl80211_set_param(void *priv, const char *param) -{ -#ifdef CONFIG_CLIENT_MLME - struct wpa_driver_nl80211_data *drv = priv; - - if (param == NULL) - return 0; - - wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param); - - if (os_strstr(param, "use_mlme=1")) { - wpa_printf(MSG_DEBUG, "nl80211: Using user space MLME"); - drv->capa.flags |= WPA_DRIVER_FLAGS_USER_SPACE_MLME; - - if (wpa_driver_nl80211_open_mlme(drv)) - return -1; - } -#endif /* CONFIG_CLIENT_MLME */ - - return 0; -} - - -#ifdef CONFIG_CLIENT_MLME - -struct phy_info_arg { - u16 *num_modes; - struct wpa_hw_modes *modes; -}; - - -static int phy_info_handler(struct nl_msg *msg, void *arg) -{ - struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct phy_info_arg *phy_info = arg; - - struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1]; - - struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1]; - static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] - = { - [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 }, - [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG }, - [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG }, - [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG }, - [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG }, - }; - - struct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1]; - static struct nla_policy rate_policy[NL80211_BITRATE_ATTR_MAX + 1] = { - [NL80211_BITRATE_ATTR_RATE] = { .type = NLA_U32 }, - [NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE] = - { .type = NLA_FLAG }, - }; - - struct nlattr *nl_band; - struct nlattr *nl_freq; - struct nlattr *nl_rate; - int rem_band, rem_freq, rem_rate; - struct wpa_hw_modes *mode; - int idx, mode_is_set; - - nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - if (!tb_msg[NL80211_ATTR_WIPHY_BANDS]) - return NL_SKIP; - - nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], - rem_band) { - mode = os_realloc(phy_info->modes, - (*phy_info->num_modes + 1) * sizeof(*mode)); - if (!mode) - return NL_SKIP; - phy_info->modes = mode; - - mode_is_set = 0; - - mode = &phy_info->modes[*(phy_info->num_modes)]; - os_memset(mode, 0, sizeof(*mode)); - *(phy_info->num_modes) += 1; - - nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band), - nla_len(nl_band), NULL); - - nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], - rem_freq) { - nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, - nla_data(nl_freq), nla_len(nl_freq), - freq_policy); - if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) - continue; - mode->num_channels++; - } - - mode->channels = os_zalloc(mode->num_channels * - sizeof(struct wpa_channel_data)); - if (!mode->channels) - return NL_SKIP; - - idx = 0; - - nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], - rem_freq) { - nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, - nla_data(nl_freq), nla_len(nl_freq), - freq_policy); - if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) - continue; - - mode->channels[idx].freq = nla_get_u32( - tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); - mode->channels[idx].flag |= WPA_CHAN_W_SCAN | - WPA_CHAN_W_ACTIVE_SCAN | - WPA_CHAN_W_IBSS; - - if (!mode_is_set) { - /* crude heuristic */ - if (mode->channels[idx].freq < 4000) - mode->mode = WPA_MODE_IEEE80211B; - else - mode->mode = WPA_MODE_IEEE80211A; - mode_is_set = 1; - } - - /* crude heuristic */ - if (mode->channels[idx].freq < 4000) { - if (mode->channels[idx].freq == 2484) - mode->channels[idx].chan = 14; - else - mode->channels[idx].chan = - (mode->channels[idx].freq - - 2407) / 5; - } else - mode->channels[idx].chan = - mode->channels[idx].freq / 5 - 1000; - - if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) - mode->channels[idx].flag &= ~WPA_CHAN_W_SCAN; - if (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN]) - mode->channels[idx].flag &= - ~WPA_CHAN_W_ACTIVE_SCAN; - if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IBSS]) - mode->channels[idx].flag &= ~WPA_CHAN_W_IBSS; - idx++; - } - - nla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], - rem_rate) { - nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, - nla_data(nl_rate), nla_len(nl_rate), - rate_policy); - if (!tb_rate[NL80211_BITRATE_ATTR_RATE]) - continue; - mode->num_rates++; - } - - mode->rates = os_zalloc(mode->num_rates * - sizeof(struct wpa_rate_data)); - if (!mode->rates) - return NL_SKIP; - - idx = 0; - - nla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], - rem_rate) { - nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, - nla_data(nl_rate), nla_len(nl_rate), - rate_policy); - if (!tb_rate[NL80211_BITRATE_ATTR_RATE]) - continue; - mode->rates[idx].rate = nla_get_u32( - tb_rate[NL80211_BITRATE_ATTR_RATE]); - - /* crude heuristic */ - if (mode->mode == WPA_MODE_IEEE80211B && - mode->rates[idx].rate > 200) - mode->mode = WPA_MODE_IEEE80211G; - - if (tb_rate[NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE]) - mode->rates[idx].flags |= WPA_RATE_PREAMBLE2; - - idx++; - } - } - - return NL_SKIP; -} - - -static struct wpa_hw_modes * -wpa_driver_nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) -{ - struct wpa_driver_nl80211_data *drv = priv; - struct nl_msg *msg; - struct phy_info_arg result = { - .num_modes = num_modes, - .modes = NULL, - }; - - *num_modes = 0; - *flags = 0; - - msg = nlmsg_alloc(); - if (!msg) - return NULL; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_GET_WIPHY, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - - if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) - return result.modes; -nla_put_failure: - return NULL; -} - - -static int wpa_driver_nl80211_set_channel(void *priv, wpa_hw_mode phymode, - int chan, int freq) -{ - return wpa_driver_nl80211_set_freq(priv, freq); -} - - -static int wpa_driver_nl80211_send_mlme(void *priv, const u8 *data, - size_t data_len) -{ - struct wpa_driver_nl80211_data *drv = priv; - __u8 rtap_hdr[] = { - 0x00, 0x00, /* radiotap version */ - 0x0e, 0x00, /* radiotap length */ - 0x02, 0xc0, 0x00, 0x00, /* bmap: flags, tx and rx flags */ - 0x0c, /* F_WEP | F_FRAG (encrypt/fragment if required) */ - 0x00, /* padding */ - 0x00, 0x00, /* RX and TX flags to indicate that */ - 0x00, 0x00, /* this is the injected frame directly */ - }; - struct iovec iov[2] = { - { - .iov_base = &rtap_hdr, - .iov_len = sizeof(rtap_hdr), - }, - { - .iov_base = (void *) data, - .iov_len = data_len, - } - }; - struct msghdr msg = { - .msg_name = NULL, - .msg_namelen = 0, - .msg_iov = iov, - .msg_iovlen = 2, - .msg_control = NULL, - .msg_controllen = 0, - .msg_flags = 0, - }; - - if (sendmsg(drv->monitor_sock, &msg, 0) < 0) { - perror("send[MLME]"); - return -1; - } - - return 0; -} - - -static int wpa_driver_nl80211_mlme_add_sta(void *priv, const u8 *addr, - const u8 *supp_rates, - size_t supp_rates_len) -{ - struct wpa_driver_nl80211_data *drv = priv; - struct nl_msg *msg; - int ret = -1; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_NEW_STATION, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - /* TODO: Get proper Association ID and listen interval */ - NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, 1); - NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, supp_rates_len, - supp_rates); - NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL, 1); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - /* ignore EEXIST, this happens if a STA associates while associated */ - if (ret == -EEXIST || ret >= 0) - ret = 0; - -nla_put_failure: - return ret; -} - - -static int wpa_driver_nl80211_mlme_remove_sta(void *priv, const u8 *addr) -{ - struct wpa_driver_nl80211_data *drv = priv; - struct nl_msg *msg; - int ret = -1; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_DEL_STATION, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - - ret = 0; - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - return ret; - -nla_put_failure: - return -ENOBUFS; -} - -#endif /* CONFIG_CLIENT_MLME */ - - -const struct wpa_driver_ops wpa_driver_nl80211_ops = { - .name = "nl80211", - .desc = "Linux nl80211/cfg80211", - .get_bssid = wpa_driver_nl80211_get_bssid, - .get_ssid = wpa_driver_nl80211_get_ssid, - .set_wpa = wpa_driver_nl80211_set_wpa, - .set_key = wpa_driver_nl80211_set_key, - .set_countermeasures = wpa_driver_nl80211_set_countermeasures, - .set_drop_unencrypted = wpa_driver_nl80211_set_drop_unencrypted, - .scan = wpa_driver_nl80211_scan, - .get_scan_results2 = wpa_driver_nl80211_get_scan_results, - .deauthenticate = wpa_driver_nl80211_deauthenticate, - .disassociate = wpa_driver_nl80211_disassociate, - .set_mode = wpa_driver_nl80211_set_mode, - .associate = wpa_driver_nl80211_associate, - .set_auth_alg = wpa_driver_nl80211_set_auth_alg, - .init = wpa_driver_nl80211_init, - .deinit = wpa_driver_nl80211_deinit, - .set_param = wpa_driver_nl80211_set_param, - .add_pmkid = wpa_driver_nl80211_add_pmkid, - .remove_pmkid = wpa_driver_nl80211_remove_pmkid, - .flush_pmkid = wpa_driver_nl80211_flush_pmkid, - .get_capa = wpa_driver_nl80211_get_capa, - .set_operstate = wpa_driver_nl80211_set_operstate, - .set_country = wpa_driver_nl80211_set_country, - .set_probe_req_ie = wpa_driver_nl80211_set_probe_req_ie, -#ifdef CONFIG_CLIENT_MLME - .get_hw_feature_data = wpa_driver_nl80211_get_hw_feature_data, - .set_channel = wpa_driver_nl80211_set_channel, - .set_ssid = wpa_driver_nl80211_set_ssid, - .set_bssid = wpa_driver_nl80211_set_bssid, - .send_mlme = wpa_driver_nl80211_send_mlme, - .mlme_add_sta = wpa_driver_nl80211_mlme_add_sta, - .mlme_remove_sta = wpa_driver_nl80211_mlme_remove_sta, -#endif /* CONFIG_CLIENT_MLME */ -}; diff --git a/contrib/hostapd/src/drivers/driver_prism54.c b/contrib/hostapd/src/drivers/driver_prism54.c deleted file mode 100644 index e64e762edd..0000000000 --- a/contrib/hostapd/src/drivers/driver_prism54.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * WPA Supplicant - driver interaction with Linux Prism54.org driver - * Copyright (c) 2003-2005, Jouni Malinen - * Copyright (c) 2004, Luis R. Rodriguez - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "wireless_copy.h" -#include "common.h" -#include "driver.h" -#include "driver_wext.h" -#include "driver_hostap.h" - -struct wpa_driver_prism54_data { - void *wext; /* private data for driver_wext */ - void *ctx; - char ifname[IFNAMSIZ + 1]; - int sock; -}; - -#define PRISM54_SET_WPA SIOCIWFIRSTPRIV+12 -#define PRISM54_HOSTAPD SIOCIWFIRSTPRIV+25 -#define PRISM54_DROP_UNENCRYPTED SIOCIWFIRSTPRIV+26 - -static void show_set_key_error(struct prism2_hostapd_param *); - -static int hostapd_ioctl_prism54(struct wpa_driver_prism54_data *drv, - struct prism2_hostapd_param *param, - int len, int show_err) -{ - struct iwreq iwr; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) param; - iwr.u.data.length = len; - - if (ioctl(drv->sock, PRISM54_HOSTAPD, &iwr) < 0) { - int ret = errno; - if (show_err) - perror("ioctl[PRISM54_HOSTAPD]"); - return ret; - } - - return 0; -} - - -static int wpa_driver_prism54_set_wpa_ie(struct wpa_driver_prism54_data *drv, - const u8 *wpa_ie, - size_t wpa_ie_len) -{ - struct prism2_hostapd_param *param; - int res; - size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + wpa_ie_len; - if (blen < sizeof(*param)) - blen = sizeof(*param); - - param = os_zalloc(blen); - if (param == NULL) - return -1; - - param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT; - param->u.generic_elem.len = wpa_ie_len; - os_memcpy(param->u.generic_elem.data, wpa_ie, wpa_ie_len); - res = hostapd_ioctl_prism54(drv, param, blen, 1); - - os_free(param); - - return res; -} - - -/* This is called at wpa_supplicant daemon init time */ -static int wpa_driver_prism54_set_wpa(void *priv, int enabled) -{ - struct wpa_driver_prism54_data *drv = priv; - struct prism2_hostapd_param *param; - int res; - size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN; - if (blen < sizeof(*param)) - blen = sizeof(*param); - - param = os_zalloc(blen); - if (param == NULL) - return -1; - - param->cmd = PRISM54_SET_WPA; - param->u.generic_elem.len = 0; - res = hostapd_ioctl_prism54(drv, param, blen, 1); - - os_free(param); - - return res; -} - - -static int wpa_driver_prism54_set_key(void *priv, wpa_alg alg, - const u8 *addr, int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_prism54_data *drv = priv; - struct prism2_hostapd_param *param; - u8 *buf; - size_t blen; - int ret = 0; - char *alg_name; - - switch (alg) { - case WPA_ALG_NONE: - alg_name = "none"; - return -1; - break; - case WPA_ALG_WEP: - alg_name = "WEP"; - return -1; - break; - case WPA_ALG_TKIP: - alg_name = "TKIP"; - break; - case WPA_ALG_CCMP: - alg_name = "CCMP"; - return -1; - break; - default: - return -1; - } - - wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu " - "key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx, - (unsigned long) seq_len, (unsigned long) key_len); - - if (seq_len > 8) - return -2; - - blen = sizeof(*param) + key_len; - buf = os_zalloc(blen); - if (buf == NULL) - return -1; - - param = (struct prism2_hostapd_param *) buf; - param->cmd = PRISM2_SET_ENCRYPTION; - /* TODO: In theory, STA in client mode can use five keys; four default - * keys for receiving (with keyidx 0..3) and one individual key for - * both transmitting and receiving (keyidx 0) _unicast_ packets. Now, - * keyidx 0 is reserved for this unicast use and default keys can only - * use keyidx 1..3 (i.e., default key with keyidx 0 is not supported). - * This should be fine for more or less all cases, but for completeness - * sake, the driver could be enhanced to support the missing key. */ -#if 0 - if (addr == NULL) - os_memset(param->sta_addr, 0xff, ETH_ALEN); - else - os_memcpy(param->sta_addr, addr, ETH_ALEN); -#else - os_memset(param->sta_addr, 0xff, ETH_ALEN); -#endif - os_strlcpy((char *) param->u.crypt.alg, alg_name, - HOSTAP_CRYPT_ALG_NAME_LEN); - param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0; - param->u.crypt.idx = key_idx; - os_memcpy(param->u.crypt.seq, seq, seq_len); - param->u.crypt.key_len = key_len; - os_memcpy((u8 *) (param + 1), key, key_len); - - if (hostapd_ioctl_prism54(drv, param, blen, 1)) { - wpa_printf(MSG_WARNING, "Failed to set encryption."); - show_set_key_error(param); - ret = -1; - } - os_free(buf); - - return ret; -} - - -static int wpa_driver_prism54_set_countermeasures(void *priv, - int enabled) -{ - /* FIX */ - printf("wpa_driver_prism54_set_countermeasures - not yet " - "implemented\n"); - return 0; -} - - -static int wpa_driver_prism54_set_drop_unencrypted(void *priv, - int enabled) -{ - struct wpa_driver_prism54_data *drv = priv; - struct prism2_hostapd_param *param; - int res; - size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN; - if (blen < sizeof(*param)) - blen = sizeof(*param); - - param = os_zalloc(blen); - if (param == NULL) - return -1; - - param->cmd = PRISM54_DROP_UNENCRYPTED; - param->u.generic_elem.len = 0; - res = hostapd_ioctl_prism54(drv, param, blen, 1); - - os_free(param); - - return res; -} - - -static int wpa_driver_prism54_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - /* FIX */ - printf("wpa_driver_prism54_deauthenticate - not yet implemented\n"); - return 0; -} - - -static int wpa_driver_prism54_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - /* FIX */ - printf("wpa_driver_prism54_disassociate - not yet implemented\n"); - return 0; -} - - -static int -wpa_driver_prism54_associate(void *priv, - struct wpa_driver_associate_params *params) -{ - struct wpa_driver_prism54_data *drv = priv; - int ret = 0; - - if (wpa_driver_prism54_set_wpa_ie(drv, params->wpa_ie, - params->wpa_ie_len) < 0) - ret = -1; - if (wpa_driver_wext_set_freq(drv->wext, params->freq) < 0) - ret = -1; - if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, - params->ssid_len) < 0) - ret = -1; - if (wpa_driver_wext_set_bssid(drv->wext, params->bssid) < 0) - ret = -1; - - return ret; -} - -static void show_set_key_error(struct prism2_hostapd_param *param) -{ - switch (param->u.crypt.err) { - case HOSTAP_CRYPT_ERR_UNKNOWN_ALG: - wpa_printf(MSG_INFO, "Unknown algorithm '%s'.", - param->u.crypt.alg); - wpa_printf(MSG_INFO, "You may need to load kernel module to " - "register that algorithm."); - wpa_printf(MSG_INFO, "E.g., 'modprobe hostap_crypt_wep' for " - "WEP."); - break; - case HOSTAP_CRYPT_ERR_UNKNOWN_ADDR: - wpa_printf(MSG_INFO, "Unknown address " MACSTR ".", - MAC2STR(param->sta_addr)); - break; - case HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED: - wpa_printf(MSG_INFO, "Crypt algorithm initialization failed."); - break; - case HOSTAP_CRYPT_ERR_KEY_SET_FAILED: - wpa_printf(MSG_INFO, "Key setting failed."); - break; - case HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED: - wpa_printf(MSG_INFO, "TX key index setting failed."); - break; - case HOSTAP_CRYPT_ERR_CARD_CONF_FAILED: - wpa_printf(MSG_INFO, "Card configuration failed."); - break; - } -} - - -static int wpa_driver_prism54_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_prism54_data *drv = priv; - return wpa_driver_wext_get_bssid(drv->wext, bssid); -} - - -static int wpa_driver_prism54_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_prism54_data *drv = priv; - return wpa_driver_wext_get_ssid(drv->wext, ssid); -} - - -static int wpa_driver_prism54_scan(void *priv, const u8 *ssid, size_t ssid_len) -{ - struct wpa_driver_prism54_data *drv = priv; - return wpa_driver_wext_scan(drv->wext, ssid, ssid_len); -} - - -static struct wpa_scan_results * -wpa_driver_prism54_get_scan_results(void *priv) -{ - struct wpa_driver_prism54_data *drv = priv; - return wpa_driver_wext_get_scan_results(drv->wext); -} - - -static int wpa_driver_prism54_set_operstate(void *priv, int state) -{ - struct wpa_driver_prism54_data *drv = priv; - return wpa_driver_wext_set_operstate(drv->wext, state); -} - - -static void * wpa_driver_prism54_init(void *ctx, const char *ifname) -{ - struct wpa_driver_prism54_data *drv; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->wext = wpa_driver_wext_init(ctx, ifname); - if (drv->wext == NULL) { - os_free(drv); - return NULL; - } - - drv->ctx = ctx; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - drv->sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->sock < 0) { - wpa_driver_wext_deinit(drv->wext); - os_free(drv); - return NULL; - } - - return drv; -} - - -static void wpa_driver_prism54_deinit(void *priv) -{ - struct wpa_driver_prism54_data *drv = priv; - wpa_driver_wext_deinit(drv->wext); - close(drv->sock); - os_free(drv); -} - - -const struct wpa_driver_ops wpa_driver_prism54_ops = { - .name = "prism54", - .desc = "Prism54.org driver (Intersil Prism GT/Duette/Indigo)", - .get_bssid = wpa_driver_prism54_get_bssid, - .get_ssid = wpa_driver_prism54_get_ssid, - .set_wpa = wpa_driver_prism54_set_wpa, - .set_key = wpa_driver_prism54_set_key, - .set_countermeasures = wpa_driver_prism54_set_countermeasures, - .set_drop_unencrypted = wpa_driver_prism54_set_drop_unencrypted, - .scan = wpa_driver_prism54_scan, - .get_scan_results2 = wpa_driver_prism54_get_scan_results, - .deauthenticate = wpa_driver_prism54_deauthenticate, - .disassociate = wpa_driver_prism54_disassociate, - .associate = wpa_driver_prism54_associate, - .init = wpa_driver_prism54_init, - .deinit = wpa_driver_prism54_deinit, - .set_operstate = wpa_driver_prism54_set_operstate, -}; diff --git a/contrib/hostapd/src/drivers/driver_privsep.c b/contrib/hostapd/src/drivers/driver_privsep.c deleted file mode 100644 index fdf299dc84..0000000000 --- a/contrib/hostapd/src/drivers/driver_privsep.c +++ /dev/null @@ -1,820 +0,0 @@ -/* - * WPA Supplicant - privilege separated driver interface - * Copyright (c) 2007-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "driver.h" -#include "eloop.h" -#include "privsep_commands.h" - - -struct wpa_driver_privsep_data { - void *ctx; - u8 own_addr[ETH_ALEN]; - int priv_socket; - char *own_socket_path; - int cmd_socket; - char *own_cmd_path; - struct sockaddr_un priv_addr; - char ifname[16]; -}; - - -static int wpa_priv_reg_cmd(struct wpa_driver_privsep_data *drv, int cmd) -{ - int res; - - res = sendto(drv->priv_socket, &cmd, sizeof(cmd), 0, - (struct sockaddr *) &drv->priv_addr, - sizeof(drv->priv_addr)); - if (res < 0) - perror("sendto"); - return res < 0 ? -1 : 0; -} - - -static int wpa_priv_cmd(struct wpa_driver_privsep_data *drv, int cmd, - const void *data, size_t data_len, - void *reply, size_t *reply_len) -{ - struct msghdr msg; - struct iovec io[2]; - - io[0].iov_base = &cmd; - io[0].iov_len = sizeof(cmd); - io[1].iov_base = (u8 *) data; - io[1].iov_len = data_len; - - os_memset(&msg, 0, sizeof(msg)); - msg.msg_iov = io; - msg.msg_iovlen = data ? 2 : 1; - msg.msg_name = &drv->priv_addr; - msg.msg_namelen = sizeof(drv->priv_addr); - - if (sendmsg(drv->cmd_socket, &msg, 0) < 0) { - perror("sendmsg(cmd_socket)"); - return -1; - } - - if (reply) { - fd_set rfds; - struct timeval tv; - int res; - - FD_ZERO(&rfds); - FD_SET(drv->cmd_socket, &rfds); - tv.tv_sec = 5; - tv.tv_usec = 0; - res = select(drv->cmd_socket + 1, &rfds, NULL, NULL, &tv); - if (res < 0 && errno != EINTR) { - perror("select"); - return -1; - } - - if (FD_ISSET(drv->cmd_socket, &rfds)) { - res = recv(drv->cmd_socket, reply, *reply_len, 0); - if (res < 0) { - perror("recv"); - return -1; - } - *reply_len = res; - } else { - wpa_printf(MSG_DEBUG, "PRIVSEP: Timeout while waiting " - "for reply (cmd=%d)", cmd); - return -1; - } - } - - return 0; -} - - -static int wpa_driver_privsep_set_wpa(void *priv, int enabled) -{ - struct wpa_driver_privsep_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_WPA, &enabled, - sizeof(enabled), NULL, NULL); -} - - -static int wpa_driver_privsep_scan(void *priv, const u8 *ssid, size_t ssid_len) -{ - struct wpa_driver_privsep_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s: priv=%p", __func__, priv); - return wpa_priv_cmd(drv, PRIVSEP_CMD_SCAN, ssid, ssid_len, - NULL, NULL); -} - - -static struct wpa_scan_results * -wpa_driver_privsep_get_scan_results2(void *priv) -{ - struct wpa_driver_privsep_data *drv = priv; - int res, num; - u8 *buf, *pos, *end; - size_t reply_len = 60000; - struct wpa_scan_results *results; - struct wpa_scan_res *r; - - buf = os_malloc(reply_len); - if (buf == NULL) - return NULL; - res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SCAN_RESULTS, - NULL, 0, buf, &reply_len); - if (res < 0) { - os_free(buf); - return NULL; - } - - wpa_printf(MSG_DEBUG, "privsep: Received %lu bytes of scan results", - (unsigned long) reply_len); - if (reply_len < sizeof(int)) { - wpa_printf(MSG_DEBUG, "privsep: Invalid scan result len %lu", - (unsigned long) reply_len); - os_free(buf); - return NULL; - } - - pos = buf; - end = buf + reply_len; - os_memcpy(&num, pos, sizeof(int)); - if (num < 0 || num > 1000) { - os_free(buf); - return NULL; - } - pos += sizeof(int); - - results = os_zalloc(sizeof(*results)); - if (results == NULL) { - os_free(buf); - return NULL; - } - - results->res = os_zalloc(num * sizeof(struct wpa_scan_res *)); - if (results->res == NULL) { - os_free(results); - os_free(buf); - return NULL; - } - - while (results->num < (size_t) num && pos + sizeof(int) < end) { - int len; - os_memcpy(&len, pos, sizeof(int)); - pos += sizeof(int); - if (len < 0 || len > 10000 || pos + len > end) - break; - - r = os_malloc(len); - if (r == NULL) - break; - os_memcpy(r, pos, len); - pos += len; - if (sizeof(*r) + r->ie_len > (size_t) len) { - os_free(r); - break; - } - - results->res[results->num++] = r; - } - - os_free(buf); - return results; -} - - -static int wpa_driver_privsep_set_key(void *priv, wpa_alg alg, const u8 *addr, - int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_privsep_data *drv = priv; - struct privsep_cmd_set_key cmd; - - wpa_printf(MSG_DEBUG, "%s: priv=%p alg=%d key_idx=%d set_tx=%d", - __func__, priv, alg, key_idx, set_tx); - - os_memset(&cmd, 0, sizeof(cmd)); - cmd.alg = alg; - if (addr) - os_memcpy(cmd.addr, addr, ETH_ALEN); - else - os_memset(cmd.addr, 0xff, ETH_ALEN); - cmd.key_idx = key_idx; - cmd.set_tx = set_tx; - if (seq && seq_len > 0 && seq_len < sizeof(cmd.seq)) { - os_memcpy(cmd.seq, seq, seq_len); - cmd.seq_len = seq_len; - } - if (key && key_len > 0 && key_len < sizeof(cmd.key)) { - os_memcpy(cmd.key, key, key_len); - cmd.key_len = key_len; - } - - return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_KEY, &cmd, sizeof(cmd), - NULL, NULL); -} - - -static int wpa_driver_privsep_associate( - void *priv, struct wpa_driver_associate_params *params) -{ - struct wpa_driver_privsep_data *drv = priv; - struct privsep_cmd_associate *data; - int res; - size_t buflen; - - wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d " - "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d", - __func__, priv, params->freq, params->pairwise_suite, - params->group_suite, params->key_mgmt_suite, - params->auth_alg, params->mode); - - buflen = sizeof(*data) + params->wpa_ie_len; - data = os_zalloc(buflen); - if (data == NULL) - return -1; - - if (params->bssid) - os_memcpy(data->bssid, params->bssid, ETH_ALEN); - os_memcpy(data->ssid, params->ssid, params->ssid_len); - data->ssid_len = params->ssid_len; - data->freq = params->freq; - data->pairwise_suite = params->pairwise_suite; - data->group_suite = params->group_suite; - data->key_mgmt_suite = params->key_mgmt_suite; - data->auth_alg = params->auth_alg; - data->mode = params->mode; - data->wpa_ie_len = params->wpa_ie_len; - if (params->wpa_ie) - os_memcpy(data + 1, params->wpa_ie, params->wpa_ie_len); - /* TODO: add support for other assoc parameters */ - - res = wpa_priv_cmd(drv, PRIVSEP_CMD_ASSOCIATE, data, buflen, - NULL, NULL); - os_free(data); - - return res; -} - - -static int wpa_driver_privsep_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_privsep_data *drv = priv; - int res; - size_t len = ETH_ALEN; - - res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_BSSID, NULL, 0, bssid, &len); - if (res < 0 || len != ETH_ALEN) - return -1; - return 0; -} - - -static int wpa_driver_privsep_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_privsep_data *drv = priv; - int res, ssid_len; - u8 reply[sizeof(int) + 32]; - size_t len = sizeof(reply); - - res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SSID, NULL, 0, reply, &len); - if (res < 0 || len < sizeof(int)) - return -1; - os_memcpy(&ssid_len, reply, sizeof(int)); - if (ssid_len < 0 || ssid_len > 32 || sizeof(int) + ssid_len > len) { - wpa_printf(MSG_DEBUG, "privsep: Invalid get SSID reply"); - return -1; - } - os_memcpy(ssid, &reply[sizeof(int)], ssid_len); - return ssid_len; -} - - -static int wpa_driver_privsep_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - //struct wpa_driver_privsep_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d", - __func__, MAC2STR(addr), reason_code); - wpa_printf(MSG_DEBUG, "%s - TODO", __func__); - return 0; -} - - -static int wpa_driver_privsep_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - //struct wpa_driver_privsep_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d", - __func__, MAC2STR(addr), reason_code); - wpa_printf(MSG_DEBUG, "%s - TODO", __func__); - return 0; -} - - -static void wpa_driver_privsep_event_assoc(void *ctx, wpa_event_type event, - u8 *buf, size_t len) -{ - union wpa_event_data data; - int inc_data = 0; - u8 *pos, *end; - int ie_len; - - os_memset(&data, 0, sizeof(data)); - - pos = buf; - end = buf + len; - - if (end - pos < (int) sizeof(int)) - return; - os_memcpy(&ie_len, pos, sizeof(int)); - pos += sizeof(int); - if (ie_len < 0 || ie_len > end - pos) - return; - if (ie_len) { - data.assoc_info.req_ies = pos; - data.assoc_info.req_ies_len = ie_len; - pos += ie_len; - inc_data = 1; - } - - wpa_supplicant_event(ctx, event, inc_data ? &data : NULL); -} - - -static void wpa_driver_privsep_event_interface_status(void *ctx, u8 *buf, - size_t len) -{ - union wpa_event_data data; - int ievent; - - if (len < sizeof(int) || - len - sizeof(int) > sizeof(data.interface_status.ifname)) - return; - - os_memcpy(&ievent, buf, sizeof(int)); - - os_memset(&data, 0, sizeof(data)); - data.interface_status.ievent = ievent; - os_memcpy(data.interface_status.ifname, buf + sizeof(int), - len - sizeof(int)); - wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &data); -} - - -static void wpa_driver_privsep_event_michael_mic_failure( - void *ctx, u8 *buf, size_t len) -{ - union wpa_event_data data; - - if (len != sizeof(int)) - return; - - os_memset(&data, 0, sizeof(data)); - os_memcpy(&data.michael_mic_failure.unicast, buf, sizeof(int)); - wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); -} - - -static void wpa_driver_privsep_event_pmkid_candidate(void *ctx, u8 *buf, - size_t len) -{ - union wpa_event_data data; - - if (len != sizeof(struct pmkid_candidate)) - return; - - os_memset(&data, 0, sizeof(data)); - os_memcpy(&data.pmkid_candidate, buf, len); - wpa_supplicant_event(ctx, EVENT_PMKID_CANDIDATE, &data); -} - - -static void wpa_driver_privsep_event_stkstart(void *ctx, u8 *buf, size_t len) -{ - union wpa_event_data data; - - if (len != ETH_ALEN) - return; - - os_memset(&data, 0, sizeof(data)); - os_memcpy(data.stkstart.peer, buf, ETH_ALEN); - wpa_supplicant_event(ctx, EVENT_STKSTART, &data); -} - - -static void wpa_driver_privsep_event_ft_response(void *ctx, u8 *buf, - size_t len) -{ - union wpa_event_data data; - - if (len < sizeof(int) + ETH_ALEN) - return; - - os_memset(&data, 0, sizeof(data)); - os_memcpy(&data.ft_ies.ft_action, buf, sizeof(int)); - os_memcpy(data.ft_ies.target_ap, buf + sizeof(int), ETH_ALEN); - data.ft_ies.ies = buf + sizeof(int) + ETH_ALEN; - data.ft_ies.ies_len = len - sizeof(int) - ETH_ALEN; - wpa_supplicant_event(ctx, EVENT_FT_RESPONSE, &data); -} - - -static void wpa_driver_privsep_event_rx_eapol(void *ctx, u8 *buf, size_t len) -{ - if (len < ETH_ALEN) - return; - - wpa_supplicant_rx_eapol(ctx, buf, buf + ETH_ALEN, len - ETH_ALEN); -} - - -static void wpa_driver_privsep_event_sta_rx(void *ctx, u8 *buf, size_t len) -{ -#ifdef CONFIG_CLIENT_MLME - struct ieee80211_rx_status *rx_status; - - if (len < sizeof(*rx_status)) - return; - rx_status = (struct ieee80211_rx_status *) buf; - buf += sizeof(*rx_status); - len -= sizeof(*rx_status); - - wpa_supplicant_sta_rx(ctx, buf, len, rx_status); -#endif /* CONFIG_CLIENT_MLME */ -} - - -static void wpa_driver_privsep_receive(int sock, void *eloop_ctx, - void *sock_ctx) -{ - struct wpa_driver_privsep_data *drv = eloop_ctx; - u8 *buf, *event_buf; - size_t event_len; - int res, event; - enum privsep_event e; - struct sockaddr_un from; - socklen_t fromlen = sizeof(from); - const size_t buflen = 2000; - - buf = os_malloc(buflen); - if (buf == NULL) - return; - res = recvfrom(sock, buf, buflen, 0, - (struct sockaddr *) &from, &fromlen); - if (res < 0) { - perror("recvfrom(priv_socket)"); - os_free(buf); - return; - } - - wpa_printf(MSG_DEBUG, "privsep_driver: received %u bytes", res); - - if (res < (int) sizeof(int)) { - wpa_printf(MSG_DEBUG, "Too short event message (len=%d)", res); - return; - } - - os_memcpy(&event, buf, sizeof(int)); - event_buf = &buf[sizeof(int)]; - event_len = res - sizeof(int); - wpa_printf(MSG_DEBUG, "privsep: Event %d received (len=%lu)", - event, (unsigned long) event_len); - - e = event; - switch (e) { - case PRIVSEP_EVENT_SCAN_RESULTS: - wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, NULL); - break; - case PRIVSEP_EVENT_ASSOC: - wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOC, - event_buf, event_len); - break; - case PRIVSEP_EVENT_DISASSOC: - wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); - break; - case PRIVSEP_EVENT_ASSOCINFO: - wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOCINFO, - event_buf, event_len); - break; - case PRIVSEP_EVENT_MICHAEL_MIC_FAILURE: - wpa_driver_privsep_event_michael_mic_failure( - drv->ctx, event_buf, event_len); - break; - case PRIVSEP_EVENT_INTERFACE_STATUS: - wpa_driver_privsep_event_interface_status(drv->ctx, event_buf, - event_len); - break; - case PRIVSEP_EVENT_PMKID_CANDIDATE: - wpa_driver_privsep_event_pmkid_candidate(drv->ctx, event_buf, - event_len); - break; - case PRIVSEP_EVENT_STKSTART: - wpa_driver_privsep_event_stkstart(drv->ctx, event_buf, - event_len); - break; - case PRIVSEP_EVENT_FT_RESPONSE: - wpa_driver_privsep_event_ft_response(drv->ctx, event_buf, - event_len); - break; - case PRIVSEP_EVENT_RX_EAPOL: - wpa_driver_privsep_event_rx_eapol(drv->ctx, event_buf, - event_len); - break; - case PRIVSEP_EVENT_STA_RX: - wpa_driver_privsep_event_sta_rx(drv->ctx, event_buf, - event_len); - break; - } - - os_free(buf); -} - - -static void * wpa_driver_privsep_init(void *ctx, const char *ifname) -{ - struct wpa_driver_privsep_data *drv; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->ctx = ctx; - drv->priv_socket = -1; - drv->cmd_socket = -1; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - - return drv; -} - - -static void wpa_driver_privsep_deinit(void *priv) -{ - struct wpa_driver_privsep_data *drv = priv; - - if (drv->priv_socket >= 0) { - wpa_priv_reg_cmd(drv, PRIVSEP_CMD_UNREGISTER); - eloop_unregister_read_sock(drv->priv_socket); - close(drv->priv_socket); - } - - if (drv->own_socket_path) { - unlink(drv->own_socket_path); - os_free(drv->own_socket_path); - } - - if (drv->cmd_socket >= 0) { - eloop_unregister_read_sock(drv->cmd_socket); - close(drv->cmd_socket); - } - - if (drv->own_cmd_path) { - unlink(drv->own_cmd_path); - os_free(drv->own_cmd_path); - } - - os_free(drv); -} - - -static int wpa_driver_privsep_set_param(void *priv, const char *param) -{ - struct wpa_driver_privsep_data *drv = priv; - const char *pos; - char *own_dir, *priv_dir; - static unsigned int counter = 0; - size_t len; - struct sockaddr_un addr; - - wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param); - if (param == NULL) - pos = NULL; - else - pos = os_strstr(param, "own_dir="); - if (pos) { - char *end; - own_dir = os_strdup(pos + 8); - if (own_dir == NULL) - return -1; - end = os_strchr(own_dir, ' '); - if (end) - *end = '\0'; - } else { - own_dir = os_strdup("/tmp"); - if (own_dir == NULL) - return -1; - } - - if (param == NULL) - pos = NULL; - else - pos = os_strstr(param, "priv_dir="); - if (pos) { - char *end; - priv_dir = os_strdup(pos + 9); - if (priv_dir == NULL) { - os_free(own_dir); - return -1; - } - end = os_strchr(priv_dir, ' '); - if (end) - *end = '\0'; - } else { - priv_dir = os_strdup("/var/run/wpa_priv"); - if (priv_dir == NULL) { - os_free(own_dir); - return -1; - } - } - - len = os_strlen(own_dir) + 50; - drv->own_socket_path = os_malloc(len); - if (drv->own_socket_path == NULL) { - os_free(priv_dir); - os_free(own_dir); - return -1; - } - os_snprintf(drv->own_socket_path, len, "%s/wpa_privsep-%d-%d", - own_dir, getpid(), counter++); - - len = os_strlen(own_dir) + 50; - drv->own_cmd_path = os_malloc(len); - if (drv->own_cmd_path == NULL) { - os_free(drv->own_socket_path); - drv->own_socket_path = NULL; - os_free(priv_dir); - os_free(own_dir); - return -1; - } - os_snprintf(drv->own_cmd_path, len, "%s/wpa_privsep-%d-%d", - own_dir, getpid(), counter++); - - os_free(own_dir); - - drv->priv_addr.sun_family = AF_UNIX; - os_snprintf(drv->priv_addr.sun_path, sizeof(drv->priv_addr.sun_path), - "%s/%s", priv_dir, drv->ifname); - os_free(priv_dir); - - drv->priv_socket = socket(PF_UNIX, SOCK_DGRAM, 0); - if (drv->priv_socket < 0) { - perror("socket(PF_UNIX)"); - os_free(drv->own_socket_path); - drv->own_socket_path = NULL; - return -1; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_strlcpy(addr.sun_path, drv->own_socket_path, sizeof(addr.sun_path)); - if (bind(drv->priv_socket, (struct sockaddr *) &addr, sizeof(addr)) < - 0) { - perror("bind(PF_UNIX)"); - close(drv->priv_socket); - drv->priv_socket = -1; - unlink(drv->own_socket_path); - os_free(drv->own_socket_path); - drv->own_socket_path = NULL; - return -1; - } - - eloop_register_read_sock(drv->priv_socket, wpa_driver_privsep_receive, - drv, NULL); - - drv->cmd_socket = socket(PF_UNIX, SOCK_DGRAM, 0); - if (drv->cmd_socket < 0) { - perror("socket(PF_UNIX)"); - os_free(drv->own_cmd_path); - drv->own_cmd_path = NULL; - return -1; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_strlcpy(addr.sun_path, drv->own_cmd_path, sizeof(addr.sun_path)); - if (bind(drv->cmd_socket, (struct sockaddr *) &addr, sizeof(addr)) < 0) - { - perror("bind(PF_UNIX)"); - close(drv->cmd_socket); - drv->cmd_socket = -1; - unlink(drv->own_cmd_path); - os_free(drv->own_cmd_path); - drv->own_cmd_path = NULL; - return -1; - } - - if (wpa_priv_reg_cmd(drv, PRIVSEP_CMD_REGISTER) < 0) { - wpa_printf(MSG_ERROR, "Failed to register with wpa_priv"); - return -1; - } - - return 0; -} - - -static int wpa_driver_privsep_get_capa(void *priv, - struct wpa_driver_capa *capa) -{ - struct wpa_driver_privsep_data *drv = priv; - int res; - size_t len = sizeof(*capa); - - res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_CAPA, NULL, 0, capa, &len); - if (res < 0 || len != sizeof(*capa)) - return -1; - return 0; -} - - -static const u8 * wpa_driver_privsep_get_mac_addr(void *priv) -{ - struct wpa_driver_privsep_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __func__); - return drv->own_addr; -} - - -static int wpa_driver_privsep_set_mode(void *priv, int mode) -{ - struct wpa_driver_privsep_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s mode=%d", __func__, mode); - return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_MODE, &mode, sizeof(mode), - NULL, NULL); -} - - -static int wpa_driver_privsep_set_country(void *priv, const char *alpha2) -{ - struct wpa_driver_privsep_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s country='%s'", __func__, alpha2); - return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_COUNTRY, alpha2, - os_strlen(alpha2), NULL, NULL); -} - - -struct wpa_driver_ops wpa_driver_privsep_ops = { - "privsep", - "wpa_supplicant privilege separated driver", - wpa_driver_privsep_get_bssid, - wpa_driver_privsep_get_ssid, - wpa_driver_privsep_set_wpa, - wpa_driver_privsep_set_key, - wpa_driver_privsep_init, - wpa_driver_privsep_deinit, - wpa_driver_privsep_set_param, - NULL /* set_countermeasures */, - NULL /* set_drop_unencrypted */, - wpa_driver_privsep_scan, - NULL /* get_scan_results */, - wpa_driver_privsep_deauthenticate, - wpa_driver_privsep_disassociate, - wpa_driver_privsep_associate, - NULL /* set_auth_alg */, - NULL /* add_pmkid */, - NULL /* remove_pmkid */, - NULL /* flush_pmkid */, - wpa_driver_privsep_get_capa, - NULL /* poll */, - NULL /* get_ifname */, - wpa_driver_privsep_get_mac_addr, - NULL /* send_eapol */, - NULL /* set_operstate */, - NULL /* mlme_setprotection */, - NULL /* get_hw_feature_data */, - NULL /* set_channel */, - NULL /* set_ssid */, - NULL /* set_bssid */, - NULL /* send_mlme */, - NULL /* mlme_add_sta */, - NULL /* mlme_remove_sta */, - NULL /* update_ft_ies */, - NULL /* send_ft_action */, - wpa_driver_privsep_get_scan_results2, - NULL /* set_probe_req_ie */, - wpa_driver_privsep_set_mode, - wpa_driver_privsep_set_country, - NULL /* global_init */, - NULL /* global_deinit */, - NULL /* init2 */, - NULL /* get_interfaces */ -}; - - -struct wpa_driver_ops *wpa_supplicant_drivers[] = -{ - &wpa_driver_privsep_ops, - NULL -}; diff --git a/contrib/hostapd/src/drivers/driver_ps3.c b/contrib/hostapd/src/drivers/driver_ps3.c deleted file mode 100644 index fde3425e28..0000000000 --- a/contrib/hostapd/src/drivers/driver_ps3.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * WPA Supplicant - PS3 Linux wireless extension driver interface - * Copyright 2007, 2008 Sony Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include "wireless_copy.h" -#include "common.h" -#include "wpa_common.h" -#include "driver.h" -#include "eloop.h" -#include "driver_wext.h" -#include "ieee802_11_defs.h" - -static int wpa_driver_ps3_set_wpa_key(struct wpa_driver_wext_data *drv, - struct wpa_driver_associate_params *params) -{ - int ret, i; - struct iwreq iwr; - char *buf, *str; - - if (!params->psk && !params->passphrase) { - wpa_printf(MSG_INFO, "%s:no PSK error", __func__); - return -EINVAL; - } - - os_memset(&iwr, 0, sizeof(iwr)); - if (params->psk) { - /* includes null */ - iwr.u.data.length = PMK_LEN * 2 + 1; - buf = os_malloc(iwr.u.data.length); - if (!buf) - return -ENOMEM; - str = buf; - for (i = 0; i < PMK_LEN; i++) { - str += snprintf(str, iwr.u.data.length - (str - buf), - "%02x", params->psk[i]); - } - } else if (params->passphrase) { - /* including quotations and null */ - iwr.u.data.length = strlen(params->passphrase) + 3; - buf = os_malloc(iwr.u.data.length); - if (!buf) - return -ENOMEM; - buf[0] = '"'; - os_memcpy(buf + 1, params->passphrase, iwr.u.data.length - 3); - buf[iwr.u.data.length - 2] = '"'; - buf[iwr.u.data.length - 1] = '\0'; - } else - return -EINVAL; - iwr.u.data.pointer = (caddr_t) buf; - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - ret = ioctl(drv->ioctl_sock, SIOCIWFIRSTPRIV, &iwr); - os_free(buf); - - return ret; -} - -static int wpa_driver_ps3_set_wep_keys(struct wpa_driver_wext_data *drv, - struct wpa_driver_associate_params *params) -{ - int ret, i; - struct iwreq iwr; - - for (i = 0; i < 4; i++) { - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.encoding.flags = i + 1; - if (params->wep_key_len[i]) { - iwr.u.encoding.pointer = (caddr_t) params->wep_key[i]; - iwr.u.encoding.length = params->wep_key_len[i]; - } else - iwr.u.encoding.flags = IW_ENCODE_NOKEY | - IW_ENCODE_DISABLED; - - if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { - perror("ioctl[SIOCSIWENCODE]"); - ret = -1; - } - } - return ret; -} - -static int wpa_driver_ps3_associate(void *priv, - struct wpa_driver_associate_params *params) -{ - struct wpa_driver_wext_data *drv = priv; - int ret, value; - - wpa_printf(MSG_DEBUG, "%s: <-", __func__); - - /* clear BSSID */ - if (!params->bssid && - wpa_driver_wext_set_bssid(drv, NULL) < 0) - ret = -1; - - if (wpa_driver_wext_set_mode(drv, params->mode) < 0) - ret = -1; - - if (params->wpa_ie == NULL || params->wpa_ie_len == 0) - value = IW_AUTH_WPA_VERSION_DISABLED; - else if (params->wpa_ie[0] == WLAN_EID_RSN) - value = IW_AUTH_WPA_VERSION_WPA2; - else - value = IW_AUTH_WPA_VERSION_WPA; - if (wpa_driver_wext_set_auth_param(drv, - IW_AUTH_WPA_VERSION, value) < 0) - ret = -1; - value = wpa_driver_wext_cipher2wext(params->pairwise_suite); - if (wpa_driver_wext_set_auth_param(drv, - IW_AUTH_CIPHER_PAIRWISE, value) < 0) - ret = -1; - value = wpa_driver_wext_cipher2wext(params->group_suite); - if (wpa_driver_wext_set_auth_param(drv, - IW_AUTH_CIPHER_GROUP, value) < 0) - ret = -1; - value = wpa_driver_wext_keymgmt2wext(params->key_mgmt_suite); - if (wpa_driver_wext_set_auth_param(drv, IW_AUTH_KEY_MGMT, value) < 0) - ret = -1; - - /* set selected BSSID */ - if (params->bssid && - wpa_driver_wext_set_bssid(drv, params->bssid) < 0) - ret = -1; - - switch (params->group_suite) { - case CIPHER_NONE: - ret = 0; - break; - case CIPHER_WEP40: - case CIPHER_WEP104: - ret = wpa_driver_ps3_set_wep_keys(drv, params); - break; - case CIPHER_TKIP: - case CIPHER_CCMP: - ret = wpa_driver_ps3_set_wpa_key(drv, params); - break; - } - - /* start to associate */ - ret = wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len); - - wpa_printf(MSG_DEBUG, "%s: ->", __func__); - - return ret; -} - -static int wpa_driver_ps3_get_capa(void *priv, struct wpa_driver_capa *capa) -{ - int ret; - wpa_printf(MSG_DEBUG, "%s:<-", __func__); - - ret = wpa_driver_wext_get_capa(priv, capa); - if (ret) { - wpa_printf(MSG_INFO, "%s: base wext returns error %d", - __func__, ret); - return ret; - } - /* PS3 hypervisor does association and 4way handshake by itself */ - capa->flags |= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE; - wpa_printf(MSG_DEBUG, "%s:->", __func__); - return 0; -} - -const struct wpa_driver_ops wpa_driver_ps3_ops = { - .name = "ps3", - .desc = "PLAYSTATION3 Linux wireless extension driver", - .get_bssid = wpa_driver_wext_get_bssid, - .get_ssid = wpa_driver_wext_get_ssid, - .scan = wpa_driver_wext_scan, - .get_scan_results2 = wpa_driver_wext_get_scan_results, - .associate = wpa_driver_ps3_associate, /* PS3 */ - .init = wpa_driver_wext_init, - .deinit = wpa_driver_wext_deinit, - .get_capa = wpa_driver_ps3_get_capa, /* PS3 */ -}; diff --git a/contrib/hostapd/src/drivers/driver_ralink.c b/contrib/hostapd/src/drivers/driver_ralink.c deleted file mode 100644 index e14e70b89a..0000000000 --- a/contrib/hostapd/src/drivers/driver_ralink.c +++ /dev/null @@ -1,1505 +0,0 @@ -/* - * WPA Supplicant - driver interaction with Ralink Wireless Client - * Copyright (c) 2003-2006, Jouni Malinen - * Copyright (c) 2007, Snowpin Lee - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - */ - -#include "includes.h" -#include - -#include "wireless_copy.h" -#include "common.h" -#include "driver.h" -#include "l2_packet/l2_packet.h" -#include "eloop.h" -#include "ieee802_11_defs.h" -#include "priv_netlink.h" -#include "driver_ralink.h" - -static void wpa_driver_ralink_scan_timeout(void *eloop_ctx, void *timeout_ctx); - -#define MAX_SSID_LEN 32 - -struct wpa_driver_ralink_data { - void *ctx; - int ioctl_sock; - int event_sock; - char ifname[IFNAMSIZ + 1]; - u8 *assoc_req_ies; - size_t assoc_req_ies_len; - u8 *assoc_resp_ies; - size_t assoc_resp_ies_len; - int no_of_pmkid; - struct ndis_pmkid_entry *pmkid; - int we_version_compiled; - int ap_scan; - int scanning_done; - u8 g_driver_down; -}; - -static int ralink_set_oid(struct wpa_driver_ralink_data *drv, - unsigned short oid, char *data, int len) -{ - char *buf; - struct iwreq iwr; - - buf = os_zalloc(len); - if (buf == NULL) - return -1; - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.flags = oid; - iwr.u.data.flags |= OID_GET_SET_TOGGLE; - - if (data) - os_memcpy(buf, data, len); - - iwr.u.data.pointer = (caddr_t) buf; - iwr.u.data.length = len; - - if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) { - wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed", - __func__, oid, len); - os_free(buf); - return -1; - } - os_free(buf); - return 0; -} - -static int -ralink_get_new_driver_flag(struct wpa_driver_ralink_data *drv) -{ - struct iwreq iwr; - UCHAR enabled = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = (UCHAR*) &enabled; - iwr.u.data.flags = RT_OID_NEW_DRIVER; - - if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) { - wpa_printf(MSG_DEBUG, "%s: failed", __func__); - return 0; - } - - return (enabled == 1) ? 1 : 0; -} - -static int wpa_driver_ralink_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_ralink_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - if (drv->g_driver_down == 1) - return -1; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - - if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) { - perror("ioctl[SIOCGIWAP]"); - ret = -1; - } - os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN); - - return ret; -} - -static int wpa_driver_ralink_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_ralink_data *drv = priv; -#if 0 - struct wpa_supplicant *wpa_s = drv->ctx; - struct wpa_ssid *entry; -#endif - int ssid_len; - u8 bssid[ETH_ALEN]; - u8 ssid_str[MAX_SSID_LEN]; - struct iwreq iwr; -#if 0 - int result = 0; -#endif - int ret = 0; -#if 0 - BOOLEAN ieee8021x_mode = FALSE; - BOOLEAN ieee8021x_required_key = FALSE; -#endif - - if (drv->g_driver_down == 1) - return -1; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.essid.pointer = (caddr_t) ssid; - iwr.u.essid.length = 32; - - if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) { - perror("ioctl[SIOCGIWESSID]"); - ret = -1; - } else - ret = iwr.u.essid.length; - - if (ret <= 0) - return ret; - - ssid_len = ret; - os_memset(ssid_str, 0, MAX_SSID_LEN); - os_memcpy(ssid_str, ssid, ssid_len); - - if (drv->ap_scan == 0) { - /* Read BSSID form driver */ - if (wpa_driver_ralink_get_bssid(priv, bssid) < 0) { - wpa_printf(MSG_WARNING, "Could not read BSSID from " - "driver."); - return ret; - } - -#if 0 - entry = wpa_s->conf->ssid; - while (entry) { - if (!entry->disabled && ssid_len == entry->ssid_len && - os_memcmp(ssid_str, entry->ssid, ssid_len) == 0 && - (!entry->bssid_set || - os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)) { - /* match the config of driver */ - result = 1; - break; - } - entry = entry->next; - } - - if (result) { - wpa_printf(MSG_DEBUG, "Ready to set 802.1x mode and " - "ieee_required_keys parameters to driver"); - - /* set 802.1x mode and ieee_required_keys parameter */ - if (entry->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { - if ((entry->eapol_flags & (EAPOL_FLAG_REQUIRE_KEY_UNICAST | EAPOL_FLAG_REQUIRE_KEY_BROADCAST))) - ieee8021x_required_key = TRUE; - ieee8021x_mode = TRUE; - } - - if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X, (char *) &ieee8021x_mode, sizeof(BOOLEAN)) < 0) - { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set OID_802_11_SET_IEEE8021X(%d)", (int) ieee8021x_mode); - } - else - { - wpa_printf(MSG_DEBUG, "ieee8021x_mode is %s", ieee8021x_mode ? "TRUE" : "FALSE"); - } - - if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X_REQUIRE_KEY, (char *) &ieee8021x_required_key, sizeof(BOOLEAN)) < 0) - { - wpa_printf(MSG_DEBUG, "ERROR: Failed to set OID_802_11_SET_IEEE8021X_REQUIRE_KEY(%d)", (int) ieee8021x_required_key); - } - else - { - wpa_printf(MSG_DEBUG, "ieee8021x_required_key is %s and eapol_flag(%d)", ieee8021x_required_key ? "TRUE" : "FALSE", - entry->eapol_flags); - } - } -#endif - } - - return ret; -} - -static int wpa_driver_ralink_set_ssid(struct wpa_driver_ralink_data *drv, - const u8 *ssid, size_t ssid_len) -{ - NDIS_802_11_SSID *buf; - int ret = 0; - struct iwreq iwr; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - buf = os_zalloc(sizeof(NDIS_802_11_SSID)); - if (buf == NULL) - return -1; - os_memset(buf, 0, sizeof(*buf)); - buf->SsidLength = ssid_len; - os_memcpy(buf->Ssid, ssid, ssid_len); - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - - iwr.u.data.flags = OID_802_11_SSID; - iwr.u.data.flags |= OID_GET_SET_TOGGLE; - iwr.u.data.pointer = (caddr_t) buf; - iwr.u.data.length = sizeof(NDIS_802_11_SSID); - - if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) { - perror("ioctl[RT_PRIV_IOCTL] -- OID_802_11_SSID"); - ret = -1; - } - os_free(buf); - return ret; -} - -static void wpa_driver_ralink_event_pmkid(struct wpa_driver_ralink_data *drv, - const u8 *data, size_t data_len) -{ - NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid; - size_t i; - union wpa_event_data event; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (data_len < 8) { - wpa_printf(MSG_DEBUG, "RALINK: Too short PMKID Candidate List " - "Event (len=%lu)", (unsigned long) data_len); - return; - } - pmkid = (NDIS_802_11_PMKID_CANDIDATE_LIST *) data; - wpa_printf(MSG_DEBUG, "RALINK: PMKID Candidate List Event - Version %d" - " NumCandidates %d", - (int) pmkid->Version, (int) pmkid->NumCandidates); - - if (pmkid->Version != 1) { - wpa_printf(MSG_DEBUG, "RALINK: Unsupported PMKID Candidate " - "List Version %d", (int) pmkid->Version); - return; - } - - if (data_len < 8 + pmkid->NumCandidates * sizeof(PMKID_CANDIDATE)) { - wpa_printf(MSG_DEBUG, "RALINK: PMKID Candidate List " - "underflow"); - - return; - } - - - - os_memset(&event, 0, sizeof(event)); - for (i = 0; i < pmkid->NumCandidates; i++) { - PMKID_CANDIDATE *p = &pmkid->CandidateList[i]; - wpa_printf(MSG_DEBUG, "RALINK: %lu: " MACSTR " Flags 0x%x", - (unsigned long) i, MAC2STR(p->BSSID), - (int) p->Flags); - os_memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN); - event.pmkid_candidate.index = i; - event.pmkid_candidate.preauth = - p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; - wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, - &event); - } -} - -static int wpa_driver_ralink_set_pmkid(struct wpa_driver_ralink_data *drv) -{ - int len, count, i, ret; - struct ndis_pmkid_entry *entry; - NDIS_802_11_PMKID *p; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - count = 0; - entry = drv->pmkid; - while (entry) { - count++; - if (count >= drv->no_of_pmkid) - break; - entry = entry->next; - } - len = 8 + count * sizeof(BSSID_INFO); - p = os_zalloc(len); - if (p == NULL) - return -1; - p->Length = len; - p->BSSIDInfoCount = count; - entry = drv->pmkid; - for (i = 0; i < count; i++) { - os_memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN); - os_memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16); - entry = entry->next; - } - wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID", - (const u8 *) p, len); - ret = ralink_set_oid(drv, OID_802_11_PMKID, (char *) p, len); - os_free(p); - return ret; -} - -static int wpa_driver_ralink_add_pmkid(void *priv, const u8 *bssid, - const u8 *pmkid) -{ - struct wpa_driver_ralink_data *drv = priv; - struct ndis_pmkid_entry *entry, *prev; - - if (drv->g_driver_down == 1) - return -1; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (drv->no_of_pmkid == 0) - return 0; - - prev = NULL; - entry = drv->pmkid; - while (entry) { - if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0) - break; - prev = entry; - entry = entry->next; - } - - if (entry) { - /* Replace existing entry for this BSSID and move it into the - * beginning of the list. */ - os_memcpy(entry->pmkid, pmkid, 16); - if (prev) { - prev->next = entry->next; - entry->next = drv->pmkid; - drv->pmkid = entry; - } - } else { - entry = os_malloc(sizeof(*entry)); - if (entry) { - os_memcpy(entry->bssid, bssid, ETH_ALEN); - os_memcpy(entry->pmkid, pmkid, 16); - entry->next = drv->pmkid; - drv->pmkid = entry; - } - } - - return wpa_driver_ralink_set_pmkid(drv); -} - - -static int wpa_driver_ralink_remove_pmkid(void *priv, const u8 *bssid, - const u8 *pmkid) -{ - struct wpa_driver_ralink_data *drv = priv; - struct ndis_pmkid_entry *entry, *prev; - - if (drv->g_driver_down == 1) - return -1; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (drv->no_of_pmkid == 0) - return 0; - - entry = drv->pmkid; - prev = NULL; - drv->pmkid = NULL; - while (entry) { - if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0 && - os_memcmp(entry->pmkid, pmkid, 16) == 0) { - if (prev) - prev->next = entry->next; - else - drv->pmkid = entry->next; - os_free(entry); - break; - } - prev = entry; - entry = entry->next; - } - return wpa_driver_ralink_set_pmkid(drv); -} - - -static int wpa_driver_ralink_flush_pmkid(void *priv) -{ - struct wpa_driver_ralink_data *drv = priv; - NDIS_802_11_PMKID p; - struct ndis_pmkid_entry *pmkid, *prev; - - if (drv->g_driver_down == 1) - return -1; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (drv->no_of_pmkid == 0) - return 0; - - pmkid = drv->pmkid; - drv->pmkid = NULL; - while (pmkid) { - prev = pmkid; - pmkid = pmkid->next; - os_free(prev); - } - - os_memset(&p, 0, sizeof(p)); - p.Length = 8; - p.BSSIDInfoCount = 0; - wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)", - (const u8 *) &p, 8); - return ralink_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8); -} - -static void -wpa_driver_ralink_event_wireless_custom(struct wpa_driver_ralink_data *drv, - void *ctx, char *custom) -{ - union wpa_event_data data; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom); - - os_memset(&data, 0, sizeof(data)); - /* Host AP driver */ - if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) { - /* receive a MICFAILURE report */ - data.michael_mic_failure.unicast = - os_strstr(custom, " unicast") != NULL; - /* TODO: parse parameters(?) */ - wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); - } else if (os_strncmp(custom, "ASSOCINFO_ReqIEs=", 17) == 0) { - /* receive assoc. req. IEs */ - char *spos; - int bytes; - - spos = custom + 17; - /*get IE's length */ - /* - * bytes = strlen(spos); ==> bug, bytes may less than original - * size by using this way to get size. snowpin 20070312 - * if (!bytes) - * return; - */ - bytes = drv->assoc_req_ies_len; - - data.assoc_info.req_ies = os_malloc(bytes); - if (data.assoc_info.req_ies == NULL) - return; - - data.assoc_info.req_ies_len = bytes; - os_memcpy(data.assoc_info.req_ies, spos, bytes); - - /* skip the '\0' byte */ - spos += bytes + 1; - - data.assoc_info.resp_ies = NULL; - data.assoc_info.resp_ies_len = 0; - - if (os_strncmp(spos, " RespIEs=", 9) == 0) { - /* receive assoc. resp. IEs */ - spos += 9; - /* get IE's length */ - bytes = os_strlen(spos); - if (!bytes) - goto done; - - - data.assoc_info.resp_ies = os_malloc(bytes); - if (data.assoc_info.resp_ies == NULL) - goto done; - - data.assoc_info.resp_ies_len = bytes; - os_memcpy(data.assoc_info.resp_ies, spos, bytes); - } - - wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data); - - /* free allocated memory */ - done: - os_free(data.assoc_info.resp_ies); - os_free(data.assoc_info.req_ies); - } -} - -static void -wpa_driver_ralink_event_wireless(struct wpa_driver_ralink_data *drv, - void *ctx, char *data, int len) -{ - struct iw_event iwe_buf, *iwe = &iwe_buf; - char *pos, *end, *custom, *buf, *assoc_info_buf, *info_pos; -#if 0 - BOOLEAN ieee8021x_required_key = FALSE; -#endif - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - assoc_info_buf = info_pos = NULL; - pos = data; - end = data + len; - - while (pos + IW_EV_LCP_LEN <= end) { - /* Event data may be unaligned, so make a local, aligned copy - * before processing. */ - os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); - wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d", - iwe->cmd, iwe->len); - if (iwe->len <= IW_EV_LCP_LEN) - return; - - custom = pos + IW_EV_POINT_LEN; - - if (drv->we_version_compiled > 18 && iwe->cmd == IWEVCUSTOM) { - /* WE-19 removed the pointer from struct iw_point */ - char *dpos = (char *) &iwe_buf.u.data.length; - int dlen = dpos - (char *) &iwe_buf; - os_memcpy(dpos, pos + IW_EV_LCP_LEN, - sizeof(struct iw_event) - dlen); - } else { - os_memcpy(&iwe_buf, pos, sizeof(struct iw_event)); - custom += IW_EV_POINT_OFF; - } - - switch (iwe->cmd) { - case IWEVCUSTOM: - if (custom + iwe->u.data.length > end) - return; - buf = os_malloc(iwe->u.data.length + 1); - if (buf == NULL) - return; - os_memcpy(buf, custom, iwe->u.data.length); - buf[iwe->u.data.length] = '\0'; - - if (drv->ap_scan == 1) { - if ((iwe->u.data.flags == RT_ASSOC_EVENT_FLAG) - || (iwe->u.data.flags == - RT_REQIE_EVENT_FLAG) || - (iwe->u.data.flags == RT_RESPIE_EVENT_FLAG) - || (iwe->u.data.flags == - RT_ASSOCINFO_EVENT_FLAG)) { - if (drv->scanning_done == 0) { - os_free(buf); - return; - } - } - } - - if (iwe->u.data.flags == RT_ASSOC_EVENT_FLAG) { - wpa_printf(MSG_DEBUG, "Custom wireless event: " - "receive ASSOCIATED_EVENT !!!"); - /* determine whether the dynamic-WEP is used or - * not */ -#if 0 - if (wpa_s && wpa_s->current_ssid && - wpa_s->current_ssid->key_mgmt == - WPA_KEY_MGMT_IEEE8021X_NO_WPA) { - if ((wpa_s->current_ssid->eapol_flags & - (EAPOL_FLAG_REQUIRE_KEY_UNICAST | EAPOL_FLAG_REQUIRE_KEY_BROADCAST))) { - //wpa_printf(MSG_DEBUG, "The current ssid - (%s), eapol_flag = %d.\n", - // wpa_ssid_txt(wpa_s->current_ssid->ssid, wpa_s->current_ssid->ssid_len),wpa_s->current_ssid->eapol_flags); - ieee8021x_required_key = TRUE; - } - - if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X_REQUIRE_KEY, (char *) &ieee8021x_required_key, sizeof(BOOLEAN)) < 0) - { - wpa_printf(MSG_DEBUG, "ERROR: Failed to set OID_802_11_SET_IEEE8021X_REQUIRE_KEY(%d)", - (int) ieee8021x_required_key); - } - - wpa_printf(MSG_DEBUG, "ieee8021x_required_key is %s and eapol_flag(%d).\n", ieee8021x_required_key ? "TRUE" : "FALSE", - wpa_s->current_ssid->eapol_flags); - } -#endif - - wpa_supplicant_event(ctx, EVENT_ASSOC, NULL); - } else if (iwe->u.data.flags == RT_REQIE_EVENT_FLAG) { - wpa_printf(MSG_DEBUG, "Custom wireless event: " - "receive ReqIEs !!!"); - drv->assoc_req_ies = - os_malloc(iwe->u.data.length); - if (drv->assoc_req_ies == NULL) { - os_free(buf); - return; - } - - drv->assoc_req_ies_len = iwe->u.data.length; - os_memcpy(drv->assoc_req_ies, custom, - iwe->u.data.length); - } else if (iwe->u.data.flags == RT_RESPIE_EVENT_FLAG) { - wpa_printf(MSG_DEBUG, "Custom wireless event: " - "receive RespIEs !!!"); - drv->assoc_resp_ies = - os_malloc(iwe->u.data.length); - if (drv->assoc_resp_ies == NULL) { - os_free(drv->assoc_req_ies); - drv->assoc_req_ies = NULL; - os_free(buf); - return; - } - - drv->assoc_resp_ies_len = iwe->u.data.length; - os_memcpy(drv->assoc_resp_ies, custom, - iwe->u.data.length); - } else if (iwe->u.data.flags == - RT_ASSOCINFO_EVENT_FLAG) { - wpa_printf(MSG_DEBUG, "Custom wireless event: " - "receive ASSOCINFO_EVENT !!!"); - - assoc_info_buf = - os_zalloc(drv->assoc_req_ies_len + - drv->assoc_resp_ies_len + 1); - - if (assoc_info_buf == NULL) { - os_free(drv->assoc_req_ies); - drv->assoc_req_ies = NULL; - os_free(drv->assoc_resp_ies); - drv->assoc_resp_ies = NULL; - os_free(buf); - return; - } - - if (drv->assoc_req_ies) { - os_memcpy(assoc_info_buf, - drv->assoc_req_ies, - drv->assoc_req_ies_len); - } - info_pos = assoc_info_buf + - drv->assoc_req_ies_len; - if (drv->assoc_resp_ies) { - os_memcpy(info_pos, - drv->assoc_resp_ies, - drv->assoc_resp_ies_len); - } - assoc_info_buf[drv->assoc_req_ies_len + - drv->assoc_resp_ies_len] = '\0'; - wpa_driver_ralink_event_wireless_custom( - drv, ctx, assoc_info_buf); - os_free(drv->assoc_req_ies); - drv->assoc_req_ies = NULL; - os_free(drv->assoc_resp_ies); - drv->assoc_resp_ies = NULL; - os_free(assoc_info_buf); - } else if (iwe->u.data.flags == RT_DISASSOC_EVENT_FLAG) - { - wpa_printf(MSG_DEBUG, "Custom wireless event: " - "receive DISASSOCIATED_EVENT !!!"); - wpa_supplicant_event(ctx, EVENT_DISASSOC, - NULL); - } else if (iwe->u.data.flags == RT_PMKIDCAND_FLAG) { - wpa_printf(MSG_DEBUG, "Custom wireless event: " - "receive PMKIDCAND_EVENT !!!"); - wpa_driver_ralink_event_pmkid( - drv, (const u8 *) custom, - iwe->u.data.length); - } else if (iwe->u.data.flags == RT_INTERFACE_DOWN) { - drv->g_driver_down = 1; - eloop_terminate(); - } else if (iwe->u.data.flags == RT_REPORT_AP_INFO) { - if (drv->ap_scan != 1) { - typedef struct PACKED { - UCHAR bssid[MAC_ADDR_LEN]; - UCHAR ssid[MAX_LEN_OF_SSID]; - INT ssid_len; - UCHAR wpa_ie[40]; - INT wpa_ie_len; - UCHAR rsn_ie[40]; - INT rsn_ie_len; - INT freq; - USHORT caps; - } *PAPINFO; - - wpa_printf(MSG_DEBUG, "Custom wireless" - " event: receive " - "RT_REPORT_AP_INFO !!!"); - //printf("iwe->u.data.length = %d\n", iwe->u.data.length); - //wpa_hexdump(MSG_DEBUG, "AP_Info: ", buf, iwe->u.data.length); -#if 0 - wpa_s->num_scan_results = 1; - if (wpa_s->scan_results) - os_free(wpa_s->scan_results); - wpa_s->scan_results = os_malloc(sizeof(struct wpa_scan_result) + 1); - if (wpa_s->scan_results) { - PAPINFO pApInfo = (PAPINFO)buf; - os_memcpy(wpa_s->scan_results[0].bssid, pApInfo->bssid, ETH_ALEN); - os_memcpy(wpa_s->scan_results[0].ssid, pApInfo->ssid, pApInfo->ssid_len); - wpa_s->scan_results[0].ssid_len = pApInfo->ssid_len; - if (pApInfo->wpa_ie_len > 0) { - os_memcpy(wpa_s->scan_results[0].wpa_ie, pApInfo->wpa_ie, pApInfo->wpa_ie_len); - wpa_s->scan_results[0].wpa_ie_len = pApInfo->wpa_ie_len; - } else if (pApInfo->rsn_ie_len > 0) { - os_memcpy(wpa_s->scan_results[0].rsn_ie, pApInfo->rsn_ie, pApInfo->rsn_ie_len); - wpa_s->scan_results[0].rsn_ie_len = pApInfo->rsn_ie_len; - } - wpa_s->scan_results[0].caps = pApInfo->caps; - wpa_s->scan_results[0].freq = pApInfo->freq; - } else { - wpa_printf("wpa_s->scan_" - "results fail to " - "os_malloc!!\n"); - } -#endif - } - } else { - wpa_driver_ralink_event_wireless_custom( - drv, ctx, buf); - } - os_free(buf); - break; - } - - pos += iwe->len; - } -} - -static void -wpa_driver_ralink_event_rtm_newlink(struct wpa_driver_ralink_data *drv, - void *ctx, struct nlmsghdr *h, int len) -{ - struct ifinfomsg *ifi; - int attrlen, nlmsg_len, rta_len; - struct rtattr * attr; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (len < (int) sizeof(*ifi)) - return; - - ifi = NLMSG_DATA(h); - wpa_hexdump(MSG_DEBUG, "ifi: ", (u8 *) ifi, sizeof(struct ifinfomsg)); - - nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); - - attrlen = h->nlmsg_len - nlmsg_len; - wpa_printf(MSG_DEBUG, "attrlen=%d", attrlen); - if (attrlen < 0) - return; - - attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); - wpa_hexdump(MSG_DEBUG, "attr1: ", (u8 *) attr, sizeof(struct rtattr)); - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - wpa_hexdump(MSG_DEBUG, "attr2: ", (u8 *)attr,rta_len); - while (RTA_OK(attr, attrlen)) { - wpa_printf(MSG_DEBUG, "rta_type=%02x\n", attr->rta_type); - if (attr->rta_type == IFLA_WIRELESS) { - wpa_driver_ralink_event_wireless( - drv, ctx, - ((char *) attr) + rta_len, - attr->rta_len - rta_len); - } - attr = RTA_NEXT(attr, attrlen); - wpa_hexdump(MSG_DEBUG, "attr3: ", - (u8 *) attr, sizeof(struct rtattr)); - } -} - -static void wpa_driver_ralink_event_receive(int sock, void *ctx, - void *sock_ctx) -{ - char buf[8192]; - int left; - struct sockaddr_nl from; - socklen_t fromlen; - struct nlmsghdr *h; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - fromlen = sizeof(from); - left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, - (struct sockaddr *) &from, &fromlen); - - if (left < 0) { - if (errno != EINTR && errno != EAGAIN) - perror("recvfrom(netlink)"); - return; - } - - h = (struct nlmsghdr *) buf; - wpa_hexdump(MSG_DEBUG, "h: ", (u8 *)h, h->nlmsg_len); - - while (left >= (int) sizeof(*h)) { - int len, plen; - - len = h->nlmsg_len; - plen = len - sizeof(*h); - if (len > left || plen < 0) { - wpa_printf(MSG_DEBUG, "Malformed netlink message: " - "len=%d left=%d plen=%d", len, left, plen); - break; - } - - switch (h->nlmsg_type) { - case RTM_NEWLINK: - wpa_driver_ralink_event_rtm_newlink(ctx, sock_ctx, h, - plen); - break; - } - - len = NLMSG_ALIGN(len); - left -= len; - h = (struct nlmsghdr *) ((char *) h + len); - } - - if (left > 0) { - wpa_printf(MSG_DEBUG, "%d extra bytes in the end of netlink " - "message", left); - } - -} - -static int -ralink_get_we_version_compiled(struct wpa_driver_ralink_data *drv) -{ - struct iwreq iwr; - UINT we_version_compiled = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) &we_version_compiled; - iwr.u.data.flags = RT_OID_WE_VERSION_COMPILED; - - if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) { - wpa_printf(MSG_DEBUG, "%s: failed", __func__); - return -1; - } - - drv->we_version_compiled = we_version_compiled; - - return 0; -} - -static int -ralink_set_iface_flags(void *priv, int dev_up) -{ - struct wpa_driver_ralink_data *drv = priv; - struct ifreq ifr; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (drv->ioctl_sock < 0) - return -1; - - os_memset(&ifr, 0, sizeof(ifr)); - os_snprintf(ifr.ifr_name, IFNAMSIZ, "%s", drv->ifname); - - if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCGIFFLAGS]"); - return -1; - } - - if (dev_up) - ifr.ifr_flags |= IFF_UP; - else - ifr.ifr_flags &= ~IFF_UP; - - if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCSIFFLAGS]"); - return -1; - } - - return 0; -} - -static void * wpa_driver_ralink_init(void *ctx, const char *ifname) -{ - int s; - struct wpa_driver_ralink_data *drv; - struct ifreq ifr; - struct sockaddr_nl local; - UCHAR enable_wpa_supplicant = 0; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - /* open socket to kernel */ - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - perror("socket"); - return NULL; - } - /* do it */ - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); - - if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { - perror(ifr.ifr_name); - return NULL; - } - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - - drv->scanning_done = 1; - drv->ap_scan = 1; /* for now - let's assume ap_scan=1 is used */ - drv->ctx = ctx; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - drv->ioctl_sock = s; - drv->g_driver_down = 0; - - s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (s < 0) { - perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)"); - close(drv->ioctl_sock); - os_free(drv); - return NULL; - } - - os_memset(&local, 0, sizeof(local)); - local.nl_family = AF_NETLINK; - local.nl_groups = RTMGRP_LINK; - - if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) { - perror("bind(netlink)"); - close(s); - close(drv->ioctl_sock); - os_free(drv); - return NULL; - } - - eloop_register_read_sock(s, wpa_driver_ralink_event_receive, drv, ctx); - drv->event_sock = s; - drv->no_of_pmkid = 4; /* Number of PMKID saved supported */ - - ralink_set_iface_flags(drv, 1); /* mark up during setup */ - ralink_get_we_version_compiled(drv); - wpa_driver_ralink_flush_pmkid(drv); - - if (drv->ap_scan == 1) - enable_wpa_supplicant = 1; - else - enable_wpa_supplicant = 2; - /* trigger driver support wpa_supplicant */ - if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT, - (PCHAR) &enable_wpa_supplicant, sizeof(UCHAR)) < 0) - { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "RT_OID_WPA_SUPPLICANT_SUPPORT(%d)", - (int) enable_wpa_supplicant); - wpa_printf(MSG_ERROR, "RALINK: Driver does not support " - "wpa_supplicant"); - close(s); - close(drv->ioctl_sock); - os_free(drv); - return NULL; - } - - if (drv->ap_scan == 1) - drv->scanning_done = 0; - - return drv; -} - -static void wpa_driver_ralink_deinit(void *priv) -{ - struct wpa_driver_ralink_data *drv = priv; - UCHAR enable_wpa_supplicant; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - enable_wpa_supplicant = 0; - - if (drv->g_driver_down == 0) { - /* trigger driver disable wpa_supplicant support */ - if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT, - (char *) &enable_wpa_supplicant, - sizeof(BOOLEAN)) < 0) { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "RT_OID_WPA_SUPPLICANT_SUPPORT(%d)", - (int) enable_wpa_supplicant); - } - - wpa_driver_ralink_flush_pmkid(drv); - - sleep(1); - ralink_set_iface_flags(drv, 0); - } - - eloop_cancel_timeout(wpa_driver_ralink_scan_timeout, drv, drv->ctx); - eloop_unregister_read_sock(drv->event_sock); - close(drv->event_sock); - close(drv->ioctl_sock); - os_free(drv); -} - -static void wpa_driver_ralink_scan_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_driver_ralink_data *drv = eloop_ctx; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); - wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); - - drv->scanning_done = 1; - -} - -static int wpa_driver_ralink_scan(void *priv, const u8 *ssid, size_t ssid_len) -{ - struct wpa_driver_ralink_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - if (drv->g_driver_down == 1) - return -1; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (ssid_len > IW_ESSID_MAX_SIZE) { - wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)", - __FUNCTION__, (unsigned long) ssid_len); - return -1; - } - - /* wpa_driver_ralink_set_ssid(drv, ssid, ssid_len); */ - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - - if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) { - perror("ioctl[SIOCSIWSCAN]"); - ret = -1; - } - - /* Not all drivers generate "scan completed" wireless event, so try to - * read results after a timeout. */ - eloop_cancel_timeout(wpa_driver_ralink_scan_timeout, drv, drv->ctx); - eloop_register_timeout(4, 0, wpa_driver_ralink_scan_timeout, drv, - drv->ctx); - - drv->scanning_done = 0; - - return ret; -} - -static int -wpa_driver_ralink_get_scan_results(void *priv, - struct wpa_scan_result *results, - size_t max_size) -{ - struct wpa_driver_ralink_data *drv = priv; - UCHAR *buf = NULL; - NDIS_802_11_BSSID_LIST_EX *wsr; - NDIS_WLAN_BSSID_EX *wbi; - struct iwreq iwr; - int rv = 0; - size_t ap_num; - u8 *pos, *end; - - if (drv->g_driver_down == 1) - return -1; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (drv->we_version_compiled >= 17) { - buf = os_zalloc(8192); - iwr.u.data.length = 8192; - } else { - buf = os_zalloc(4096); - iwr.u.data.length = 4096; - } - if (buf == NULL) - return -1; - - wsr = (NDIS_802_11_BSSID_LIST_EX *) buf; - - wsr->NumberOfItems = 0; - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = (void *) buf; - iwr.u.data.flags = OID_802_11_BSSID_LIST; - - if ((rv = ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr)) < 0) { - wpa_printf(MSG_DEBUG, "ioctl fail: rv = %d", rv); - os_free(buf); - return -1; - } - - os_memset(results, 0, max_size * sizeof(struct wpa_scan_result)); - - for (ap_num = 0, wbi = wsr->Bssid; ap_num < wsr->NumberOfItems; - ++ap_num) { - os_memcpy(results[ap_num].bssid, &wbi->MacAddress, ETH_ALEN); - os_memcpy(results[ap_num].ssid, wbi->Ssid.Ssid, - wbi->Ssid.SsidLength); - results[ap_num].ssid_len = wbi->Ssid.SsidLength; - results[ap_num].freq = (wbi->Configuration.DSConfig / 1000); - - /* get ie's */ - wpa_hexdump(MSG_DEBUG, "RALINK: AP IEs", - (u8 *) wbi + sizeof(*wbi) - 1, wbi->IELength); - - pos = (u8 *) wbi + sizeof(*wbi) - 1; - end = (u8 *) wbi + sizeof(*wbi) + wbi->IELength; - - if (wbi->IELength < sizeof(NDIS_802_11_FIXED_IEs)) - break; - - pos += sizeof(NDIS_802_11_FIXED_IEs) - 2; - os_memcpy(&results[ap_num].caps, pos, 2); - pos += 2; - - while (pos + 1 < end && pos + 2 + pos[1] <= end) { - u8 ielen = 2 + pos[1]; - - if (ielen > SSID_MAX_WPA_IE_LEN) { - pos += ielen; - continue; - } - - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && - pos[1] >= 4 && - os_memcmp(pos + 2, "\x00\x50\xf2\x01", 4) == 0) { - os_memcpy(results[ap_num].wpa_ie, pos, ielen); - results[ap_num].wpa_ie_len = ielen; - } else if (pos[0] == WLAN_EID_RSN) { - os_memcpy(results[ap_num].rsn_ie, pos, ielen); - results[ap_num].rsn_ie_len = ielen; - } - pos += ielen; - } - - wbi = (NDIS_WLAN_BSSID_EX *) ((u8 *) wbi + wbi->Length); - } - - os_free(buf); - return ap_num; -} - -static int ralink_set_auth_mode(struct wpa_driver_ralink_data *drv, - NDIS_802_11_AUTHENTICATION_MODE mode) -{ - NDIS_802_11_AUTHENTICATION_MODE auth_mode = mode; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (ralink_set_oid(drv, OID_802_11_AUTHENTICATION_MODE, - (char *) &auth_mode, sizeof(auth_mode)) < 0) { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "OID_802_11_AUTHENTICATION_MODE (%d)", - (int) auth_mode); - return -1; - } - return 0; -} - -static int wpa_driver_ralink_remove_key(struct wpa_driver_ralink_data *drv, - int key_idx, const u8 *addr, - const u8 *bssid, int pairwise) -{ - NDIS_802_11_REMOVE_KEY rkey; - NDIS_802_11_KEY_INDEX _index; - int res, res2; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - os_memset(&rkey, 0, sizeof(rkey)); - - rkey.Length = sizeof(rkey); - rkey.KeyIndex = key_idx; - - if (pairwise) - rkey.KeyIndex |= 1 << 30; - - os_memcpy(rkey.BSSID, bssid, ETH_ALEN); - - res = ralink_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey, - sizeof(rkey)); - - /* AlbertY@20060210 removed it */ - if (0 /* !pairwise */) { - res2 = ralink_set_oid(drv, OID_802_11_REMOVE_WEP, - (char *) &_index, sizeof(_index)); - } else - res2 = 0; - - if (res < 0 && res2 < 0) - return res; - return 0; -} - -static int wpa_driver_ralink_add_wep(struct wpa_driver_ralink_data *drv, - int pairwise, int key_idx, int set_tx, - const u8 *key, size_t key_len) -{ - NDIS_802_11_WEP *wep; - size_t len; - int res; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - len = 12 + key_len; - wep = os_zalloc(len); - if (wep == NULL) - return -1; - - wep->Length = len; - wep->KeyIndex = key_idx; - - if (set_tx) - wep->KeyIndex |= 0x80000000; - - wep->KeyLength = key_len; - os_memcpy(wep->KeyMaterial, key, key_len); - - wpa_hexdump_key(MSG_MSGDUMP, "RALINK: OID_802_11_ADD_WEP", - (const u8 *) wep, len); - res = ralink_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len); - - os_free(wep); - - return res; -} - -static int wpa_driver_ralink_set_key(void *priv, wpa_alg alg, const u8 *addr, - int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_ralink_data *drv = priv; - size_t len, i; - NDIS_802_11_KEY *nkey; - int res, pairwise; - u8 bssid[ETH_ALEN]; - - if (drv->g_driver_down == 1) - return -1; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (addr == NULL || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", - ETH_ALEN) == 0) { - /* Group Key */ - pairwise = 0; - wpa_driver_ralink_get_bssid(drv, bssid); - } else { - /* Pairwise Key */ - pairwise = 1; - os_memcpy(bssid, addr, ETH_ALEN); - } - - if (alg == WPA_ALG_NONE || key_len == 0) { - return wpa_driver_ralink_remove_key(drv, key_idx, addr, bssid, - pairwise); - } - - if (alg == WPA_ALG_WEP) { - return wpa_driver_ralink_add_wep(drv, pairwise, key_idx, - set_tx, key, key_len); - } - - len = 12 + 6 + 6 + 8 + key_len; - - nkey = os_zalloc(len); - if (nkey == NULL) - return -1; - - nkey->Length = len; - nkey->KeyIndex = key_idx; - - if (set_tx) - nkey->KeyIndex |= 1 << 31; - - if (pairwise) - nkey->KeyIndex |= 1 << 30; - - if (seq && seq_len) - nkey->KeyIndex |= 1 << 29; - - nkey->KeyLength = key_len; - os_memcpy(nkey->BSSID, bssid, ETH_ALEN); - - if (seq && seq_len) { - for (i = 0; i < seq_len; i++) - nkey->KeyRSC |= seq[i] << (i * 8); - } - if (alg == WPA_ALG_TKIP && key_len == 32) { - os_memcpy(nkey->KeyMaterial, key, 16); - os_memcpy(nkey->KeyMaterial + 16, key + 24, 8); - os_memcpy(nkey->KeyMaterial + 24, key + 16, 8); - } else { - os_memcpy(nkey->KeyMaterial, key, key_len); - } - - wpa_printf(MSG_DEBUG, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu " - "key_len=%lu", __FUNCTION__, alg, key_idx, set_tx, - (unsigned long) seq_len, (unsigned long) key_len); - - wpa_hexdump_key(MSG_MSGDUMP, "RALINK: OID_802_11_ADD_KEY", - (const u8 *) nkey, len); - res = ralink_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len); - os_free(nkey); - - return res; -} - -static int wpa_driver_ralink_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_ralink_data *drv = priv; - - if (drv->g_driver_down == 1) - return -1; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - if (ralink_set_oid(drv, OID_802_11_DISASSOCIATE, " ", 4) < 0) { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "OID_802_11_DISASSOCIATE"); - } - - return 0; -} - -static int wpa_driver_ralink_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_ralink_data *drv = priv; - - wpa_printf(MSG_DEBUG, "g_driver_down = %d", drv->g_driver_down); - - if (drv->g_driver_down == 1) - return -1; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - if (ralink_get_new_driver_flag(drv) == 0) { - return wpa_driver_ralink_disassociate(priv, addr, reason_code); - } else { - MLME_DEAUTH_REQ_STRUCT mlme; - os_memset(&mlme, 0, sizeof(MLME_DEAUTH_REQ_STRUCT)); - mlme.Reason = reason_code; - os_memcpy(mlme.Addr, addr, MAC_ADDR_LEN); - return ralink_set_oid(drv, OID_802_11_DEAUTHENTICATION, - (char *) &mlme, - sizeof(MLME_DEAUTH_REQ_STRUCT)); - } -} - -static int -wpa_driver_ralink_associate(void *priv, - struct wpa_driver_associate_params *params) -{ - struct wpa_driver_ralink_data *drv = priv; - - NDIS_802_11_NETWORK_INFRASTRUCTURE mode; - NDIS_802_11_AUTHENTICATION_MODE auth_mode; - NDIS_802_11_WEP_STATUS encr; - BOOLEAN ieee8021xMode; - - if (drv->g_driver_down == 1) - return -1; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (params->mode == IEEE80211_MODE_IBSS) - mode = Ndis802_11IBSS; - else - mode = Ndis802_11Infrastructure; - - if (ralink_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE, - (char *) &mode, sizeof(mode)) < 0) { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "OID_802_11_INFRASTRUCTURE_MODE (%d)", - (int) mode); - /* Try to continue anyway */ - } - - if (params->wpa_ie == NULL || params->wpa_ie_len == 0) { - if (params->auth_alg & AUTH_ALG_SHARED_KEY) { - if (params->auth_alg & AUTH_ALG_OPEN_SYSTEM) - auth_mode = Ndis802_11AuthModeAutoSwitch; - else - auth_mode = Ndis802_11AuthModeShared; - } else - auth_mode = Ndis802_11AuthModeOpen; - } else if (params->wpa_ie[0] == WLAN_EID_RSN) { - if (params->key_mgmt_suite == KEY_MGMT_PSK) - auth_mode = Ndis802_11AuthModeWPA2PSK; - else - auth_mode = Ndis802_11AuthModeWPA2; - } else { - if (params->key_mgmt_suite == KEY_MGMT_WPA_NONE) - auth_mode = Ndis802_11AuthModeWPANone; - else if (params->key_mgmt_suite == KEY_MGMT_PSK) - auth_mode = Ndis802_11AuthModeWPAPSK; - else - auth_mode = Ndis802_11AuthModeWPA; - } - - switch (params->pairwise_suite) { - case CIPHER_CCMP: - encr = Ndis802_11Encryption3Enabled; - break; - case CIPHER_TKIP: - encr = Ndis802_11Encryption2Enabled; - break; - case CIPHER_WEP40: - case CIPHER_WEP104: - encr = Ndis802_11Encryption1Enabled; - break; - case CIPHER_NONE: - if (params->group_suite == CIPHER_CCMP) - encr = Ndis802_11Encryption3Enabled; - else if (params->group_suite == CIPHER_TKIP) - encr = Ndis802_11Encryption2Enabled; - else - encr = Ndis802_11EncryptionDisabled; - break; - default: - encr = Ndis802_11EncryptionDisabled; - break; - } - - ralink_set_auth_mode(drv, auth_mode); - - /* notify driver that IEEE8021x mode is enabled */ - if (params->key_mgmt_suite == KEY_MGMT_802_1X_NO_WPA) - ieee8021xMode = TRUE; - else - ieee8021xMode = FALSE; - - if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X, - (char *) &ieee8021xMode, sizeof(BOOLEAN)) < 0) { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "OID_802_11_SET_IEEE8021X(%d)", - (int) ieee8021xMode); - } - - if (ralink_set_oid(drv, OID_802_11_WEP_STATUS, - (char *) &encr, sizeof(encr)) < 0) { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "OID_802_11_WEP_STATUS(%d)", - (int) encr); - } - - if ((ieee8021xMode == FALSE) && - (encr == Ndis802_11Encryption1Enabled)) { - /* static WEP */ - int enabled = 0; - if (ralink_set_oid(drv, OID_802_11_DROP_UNENCRYPTED, - (char *) &enabled, sizeof(enabled)) < 0) { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "OID_802_11_DROP_UNENCRYPTED(%d)", - (int) encr); - } - } - - return wpa_driver_ralink_set_ssid(drv, params->ssid, params->ssid_len); -} - -static int -wpa_driver_ralink_set_countermeasures(void *priv, int enabled) -{ - struct wpa_driver_ralink_data *drv = priv; - if (drv->g_driver_down == 1) - return -1; - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - return ralink_set_oid(drv, OID_SET_COUNTERMEASURES, (char *) &enabled, - sizeof(int)); -} - -const struct wpa_driver_ops wpa_driver_ralink_ops = { - .name = "ralink", - .desc = "Ralink Wireless Client driver", - .get_bssid = wpa_driver_ralink_get_bssid, - .get_ssid = wpa_driver_ralink_get_ssid, - .set_key = wpa_driver_ralink_set_key, - .init = wpa_driver_ralink_init, - .deinit = wpa_driver_ralink_deinit, - .set_countermeasures = wpa_driver_ralink_set_countermeasures, - .scan = wpa_driver_ralink_scan, - .get_scan_results = wpa_driver_ralink_get_scan_results, - .deauthenticate = wpa_driver_ralink_deauthenticate, - .disassociate = wpa_driver_ralink_disassociate, - .associate = wpa_driver_ralink_associate, - .add_pmkid = wpa_driver_ralink_add_pmkid, - .remove_pmkid = wpa_driver_ralink_remove_pmkid, - .flush_pmkid = wpa_driver_ralink_flush_pmkid, -}; diff --git a/contrib/hostapd/src/drivers/driver_ralink.h b/contrib/hostapd/src/drivers/driver_ralink.h deleted file mode 100644 index ddf44de232..0000000000 --- a/contrib/hostapd/src/drivers/driver_ralink.h +++ /dev/null @@ -1,382 +0,0 @@ -/* - * WPA Supplicant - driver_ralink exported functions - * Copyright (c) 2003-2005, Jouni Malinen - * Copyright (c) 2007, Snowpin Lee - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -// Ralink defined OIDs -#if WIRELESS_EXT <= 11 -#ifndef SIOCDEVPRIVATE -#define SIOCDEVPRIVATE 0x8BE0 -#endif -#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE -#endif - -#define RT_PRIV_IOCTL (SIOCIWFIRSTPRIV + 0x0E) -#define RTPRIV_IOCTL_SET (SIOCIWFIRSTPRIV + 0x02) - -// IEEE 802.11 OIDs & Ralink defined OIDs ****** - -// (RaConfig Set/QueryInform) ==> -#define OID_GET_SET_TOGGLE 0x8000 - -#define OID_802_11_ADD_WEP 0x0112 -#define OID_802_11_REMOVE_WEP 0x0113 -#define OID_802_11_DISASSOCIATE 0x0114 -#define OID_802_11_PRIVACY_FILTER 0x0118 -#define OID_802_11_ASSOCIATION_INFORMATION 0x011E -#define OID_802_11_BSSID_LIST_SCAN 0x0508 -#define OID_802_11_SSID 0x0509 -#define OID_802_11_BSSID 0x050A -#define OID_802_11_WEP_STATUS 0x0510 -#define OID_802_11_AUTHENTICATION_MODE 0x0511 -#define OID_802_11_INFRASTRUCTURE_MODE 0x0512 -#define OID_802_11_TX_POWER_LEVEL 0x0517 -#define OID_802_11_REMOVE_KEY 0x0519 -#define OID_802_11_ADD_KEY 0x0520 -#define OID_802_11_DEAUTHENTICATION 0x0526 -#define OID_802_11_DROP_UNENCRYPTED 0x0527 -#define OID_802_11_BSSID_LIST 0x0609 -#define OID_802_3_CURRENT_ADDRESS 0x060A -#define OID_SET_COUNTERMEASURES 0x0616 -#define OID_802_11_SET_IEEE8021X 0x0617 // For IEEE8021x mode -#define OID_802_11_SET_IEEE8021X_REQUIRE_KEY 0x0618 // For DynamicWEP in IEEE802.1x mode -#define OID_802_11_PMKID 0x0620 -#define RT_OID_WPA_SUPPLICANT_SUPPORT 0x0621 // for trigger driver enable/disable wpa_supplicant support -#define RT_OID_WE_VERSION_COMPILED 0x0622 -#define RT_OID_NEW_DRIVER 0x0623 - -#define PACKED __attribute__ ((packed)) - -//wpa_supplicant event flags -#define RT_ASSOC_EVENT_FLAG 0x0101 -#define RT_DISASSOC_EVENT_FLAG 0x0102 -#define RT_REQIE_EVENT_FLAG 0x0103 -#define RT_RESPIE_EVENT_FLAG 0x0104 -#define RT_ASSOCINFO_EVENT_FLAG 0x0105 -#define RT_PMKIDCAND_FLAG 0x0106 -#define RT_INTERFACE_DOWN 0x0107 -#define RT_REPORT_AP_INFO 0x0108 - -// -// IEEE 802.11 Structures and definitions -// -// new types for Media Specific Indications - -#ifndef ULONG -#define CHAR char -#define INT int -#define SHORT int -#define UINT u32 -#undef ULONG -//#define ULONG u32 -#define ULONG unsigned long /* 32-bit in 32-bit CPU or 64-bit in 64-bit CPU */ -#define USHORT unsigned short -#define UCHAR unsigned char - -#define uint32 u32 -#define uint8 u8 - - -#define BOOLEAN u8 -//#define LARGE_INTEGER s64 -#define VOID void -#define LONG long -#define LONGLONG s64 -#define ULONGLONG u64 -typedef VOID *PVOID; -typedef CHAR *PCHAR; -typedef UCHAR *PUCHAR; -typedef USHORT *PUSHORT; -typedef LONG *PLONG; -typedef ULONG *PULONG; - -typedef union _LARGE_INTEGER { - struct { - ULONG LowPart; - LONG HighPart; - }vv; - struct { - ULONG LowPart; - LONG HighPart; - } u; - s64 QuadPart; -} LARGE_INTEGER; - -#endif - -#define NDIS_802_11_LENGTH_SSID 32 -#define NDIS_802_11_LENGTH_RATES 8 -#define NDIS_802_11_LENGTH_RATES_EX 16 -#define MAX_LEN_OF_SSID 32 -#define MAC_ADDR_LEN 6 - -typedef UCHAR NDIS_802_11_MAC_ADDRESS[6]; - -// mask for authentication/integrity fields -#define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS 0x0f - -#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01 -#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02 -#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06 -#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E - -// Added new types for OFDM 5G and 2.4G -typedef enum _NDIS_802_11_NETWORK_TYPE -{ - Ndis802_11FH, - Ndis802_11DS, - Ndis802_11OFDM5, - Ndis802_11OFDM24, - Ndis802_11Automode, - Ndis802_11NetworkTypeMax // not a real type, defined as an upper bound -} NDIS_802_11_NETWORK_TYPE, *PNDIS_802_11_NETWORK_TYPE; - -// -// Received Signal Strength Indication -// -typedef LONG NDIS_802_11_RSSI; // in dBm - -typedef struct _NDIS_802_11_CONFIGURATION_FH -{ - ULONG Length; // Length of structure - ULONG HopPattern; // As defined by 802.11, MSB set - ULONG HopSet; // to one if non-802.11 - ULONG DwellTime; // units are Kusec -} NDIS_802_11_CONFIGURATION_FH, *PNDIS_802_11_CONFIGURATION_FH; - -typedef struct _NDIS_802_11_CONFIGURATION -{ - ULONG Length; // Length of structure - ULONG BeaconPeriod; // units are Kusec - ULONG ATIMWindow; // units are Kusec - ULONG DSConfig; // Frequency, units are kHz - NDIS_802_11_CONFIGURATION_FH FHConfig; -} NDIS_802_11_CONFIGURATION, *PNDIS_802_11_CONFIGURATION; - -typedef ULONG NDIS_802_11_KEY_INDEX; -typedef ULONGLONG NDIS_802_11_KEY_RSC; - -// Key mapping keys require a BSSID -typedef struct _NDIS_802_11_KEY -{ - UINT Length; // Length of this structure - UINT KeyIndex; - UINT KeyLength; // length of key in bytes - NDIS_802_11_MAC_ADDRESS BSSID; - NDIS_802_11_KEY_RSC KeyRSC; - UCHAR KeyMaterial[1]; // variable length depending on above field -} NDIS_802_11_KEY, *PNDIS_802_11_KEY; - -typedef struct _NDIS_802_11_REMOVE_KEY -{ - UINT Length; // Length of this structure - UINT KeyIndex; - NDIS_802_11_MAC_ADDRESS BSSID; -} NDIS_802_11_REMOVE_KEY, *PNDIS_802_11_REMOVE_KEY; - -typedef struct PACKED _NDIS_802_11_WEP -{ - UINT Length; // Length of this structure - UINT KeyIndex; // 0 is the per-client key, 1-N are the - // global keys - UINT KeyLength; // length of key in bytes - UCHAR KeyMaterial[1];// variable length depending on above field -} NDIS_802_11_WEP, *PNDIS_802_11_WEP; - - -typedef enum _NDIS_802_11_NETWORK_INFRASTRUCTURE -{ - Ndis802_11IBSS, - Ndis802_11Infrastructure, - Ndis802_11AutoUnknown, - Ndis802_11InfrastructureMax // Not a real value, defined as upper bound -} NDIS_802_11_NETWORK_INFRASTRUCTURE, *PNDIS_802_11_NETWORK_INFRASTRUCTURE; - -// PMKID Structures -typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; - -typedef struct _BSSID_INFO -{ - NDIS_802_11_MAC_ADDRESS BSSID; - NDIS_802_11_PMKID_VALUE PMKID; -} BSSID_INFO, *PBSSID_INFO; - -typedef struct _NDIS_802_11_PMKID -{ - ULONG Length; - ULONG BSSIDInfoCount; - BSSID_INFO BSSIDInfo[1]; -} NDIS_802_11_PMKID, *PNDIS_802_11_PMKID; - -//Added new types for PMKID Candidate lists. -typedef struct _PMKID_CANDIDATE { - NDIS_802_11_MAC_ADDRESS BSSID; - ULONG Flags; -} PMKID_CANDIDATE, *PPMKID_CANDIDATE; - -typedef struct _NDIS_802_11_PMKID_CANDIDATE_LIST -{ - ULONG Version; // Version of the structure - ULONG NumCandidates; // No. of pmkid candidates - PMKID_CANDIDATE CandidateList[1]; -} NDIS_802_11_PMKID_CANDIDATE_LIST, *PNDIS_802_11_PMKID_CANDIDATE_LIST; - -//Flags for PMKID Candidate list structure -#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 - -// Add new authentication modes -typedef enum _NDIS_802_11_AUTHENTICATION_MODE -{ - Ndis802_11AuthModeOpen, - Ndis802_11AuthModeShared, - Ndis802_11AuthModeAutoSwitch, - Ndis802_11AuthModeWPA, - Ndis802_11AuthModeWPAPSK, - Ndis802_11AuthModeWPANone, - Ndis802_11AuthModeWPA2, - Ndis802_11AuthModeWPA2PSK, - Ndis802_11AuthModeMax // Not a real mode, defined as upper bound -} NDIS_802_11_AUTHENTICATION_MODE, *PNDIS_802_11_AUTHENTICATION_MODE; - -typedef UCHAR NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES]; // Set of 8 data rates -typedef UCHAR NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; // Set of 16 data rates - -typedef struct PACKED _NDIS_802_11_SSID -{ - INT SsidLength; // length of SSID field below, in bytes; - // this can be zero. - UCHAR Ssid[NDIS_802_11_LENGTH_SSID]; // SSID information field -} NDIS_802_11_SSID, *PNDIS_802_11_SSID; - - -typedef struct PACKED _NDIS_WLAN_BSSID -{ - ULONG Length; // Length of this structure - NDIS_802_11_MAC_ADDRESS MacAddress; // BSSID - UCHAR Reserved[2]; - NDIS_802_11_SSID Ssid; // SSID - ULONG Privacy; // WEP encryption requirement - NDIS_802_11_RSSI Rssi; // receive signal - // strength in dBm - NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; - NDIS_802_11_CONFIGURATION Configuration; - NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; - NDIS_802_11_RATES SupportedRates; -} NDIS_WLAN_BSSID, *PNDIS_WLAN_BSSID; - -typedef struct PACKED _NDIS_802_11_BSSID_LIST -{ - UINT NumberOfItems; // in list below, at least 1 - NDIS_WLAN_BSSID Bssid[1]; -} NDIS_802_11_BSSID_LIST, *PNDIS_802_11_BSSID_LIST; - -// Added Capabilities, IELength and IEs for each BSSID -typedef struct PACKED _NDIS_WLAN_BSSID_EX -{ - ULONG Length; // Length of this structure - NDIS_802_11_MAC_ADDRESS MacAddress; // BSSID - UCHAR Reserved[2]; - NDIS_802_11_SSID Ssid; // SSID - UINT Privacy; // WEP encryption requirement - NDIS_802_11_RSSI Rssi; // receive signal - // strength in dBm - NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; - NDIS_802_11_CONFIGURATION Configuration; - NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; - NDIS_802_11_RATES_EX SupportedRates; - ULONG IELength; - UCHAR IEs[1]; -} NDIS_WLAN_BSSID_EX, *PNDIS_WLAN_BSSID_EX; - -typedef struct PACKED _NDIS_802_11_BSSID_LIST_EX -{ - UINT NumberOfItems; // in list below, at least 1 - NDIS_WLAN_BSSID_EX Bssid[1]; -} NDIS_802_11_BSSID_LIST_EX, *PNDIS_802_11_BSSID_LIST_EX; - -typedef struct PACKED _NDIS_802_11_FIXED_IEs -{ - UCHAR Timestamp[8]; - USHORT BeaconInterval; - USHORT Capabilities; -} NDIS_802_11_FIXED_IEs, *PNDIS_802_11_FIXED_IEs; - -// Added new encryption types -// Also aliased typedef to new name -typedef enum _NDIS_802_11_WEP_STATUS -{ - Ndis802_11WEPEnabled, - Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, - Ndis802_11WEPDisabled, - Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, - Ndis802_11WEPKeyAbsent, - Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, - Ndis802_11WEPNotSupported, - Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, - Ndis802_11Encryption2Enabled, - Ndis802_11Encryption2KeyAbsent, - Ndis802_11Encryption3Enabled, - Ndis802_11Encryption3KeyAbsent -} NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS, - NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS; - -typedef enum _NDIS_802_11_RELOAD_DEFAULTS -{ - Ndis802_11ReloadWEPKeys -} NDIS_802_11_RELOAD_DEFAULTS, *PNDIS_802_11_RELOAD_DEFAULTS; - -#define NDIS_802_11_AI_REQFI_CAPABILITIES 1 -#define NDIS_802_11_AI_REQFI_LISTENINTERVAL 2 -#define NDIS_802_11_AI_REQFI_CURRENTAPADDRESS 4 - -#define NDIS_802_11_AI_RESFI_CAPABILITIES 1 -#define NDIS_802_11_AI_RESFI_STATUSCODE 2 -#define NDIS_802_11_AI_RESFI_ASSOCIATIONID 4 - -typedef struct _NDIS_802_11_AI_REQFI -{ - USHORT Capabilities; - USHORT ListenInterval; - NDIS_802_11_MAC_ADDRESS CurrentAPAddress; -} NDIS_802_11_AI_REQFI, *PNDIS_802_11_AI_REQFI; - -typedef struct _NDIS_802_11_AI_RESFI -{ - USHORT Capabilities; - USHORT StatusCode; - USHORT AssociationId; -} NDIS_802_11_AI_RESFI, *PNDIS_802_11_AI_RESFI; - -typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION -{ - ULONG Length; - USHORT AvailableRequestFixedIEs; - NDIS_802_11_AI_REQFI RequestFixedIEs; - ULONG RequestIELength; - ULONG OffsetRequestIEs; - USHORT AvailableResponseFixedIEs; - NDIS_802_11_AI_RESFI ResponseFixedIEs; - ULONG ResponseIELength; - ULONG OffsetResponseIEs; -} NDIS_802_11_ASSOCIATION_INFORMATION, *PNDIS_802_11_ASSOCIATION_INFORMATION; - -struct ndis_pmkid_entry { - struct ndis_pmkid_entry *next; - u8 bssid[ETH_ALEN]; - u8 pmkid[16]; -}; - -typedef struct _MLME_DEAUTH_REQ_STRUCT { - UCHAR Addr[MAC_ADDR_LEN]; - USHORT Reason; -} MLME_DEAUTH_REQ_STRUCT, *PMLME_DEAUTH_REQ_STRUCT; diff --git a/contrib/hostapd/src/drivers/driver_roboswitch.c b/contrib/hostapd/src/drivers/driver_roboswitch.c deleted file mode 100644 index bc11a48484..0000000000 --- a/contrib/hostapd/src/drivers/driver_roboswitch.c +++ /dev/null @@ -1,476 +0,0 @@ -/* - * WPA Supplicant - roboswitch driver interface - * Copyright (c) 2008-2009 Jouke Witteveen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include -#include -#include -#include - -#include "common.h" -#include "driver.h" -#include "l2_packet/l2_packet.h" - -#ifndef ETH_P_EAPOL -#define ETH_P_EAPOL 0x888e -#endif - -#define ROBO_PHY_ADDR 0x1e /* RoboSwitch PHY address */ - -/* MII access registers */ -#define ROBO_MII_PAGE 0x10 /* MII page register */ -#define ROBO_MII_ADDR 0x11 /* MII address register */ -#define ROBO_MII_DATA_OFFSET 0x18 /* Start of MII data registers */ - -#define ROBO_MII_PAGE_ENABLE 0x01 /* MII page op code */ -#define ROBO_MII_ADDR_WRITE 0x01 /* MII address write op code */ -#define ROBO_MII_ADDR_READ 0x02 /* MII address read op code */ -#define ROBO_MII_DATA_MAX 4 /* Consecutive MII data registers */ -#define ROBO_MII_RETRY_MAX 10 /* Read attempts before giving up */ - -/* Page numbers */ -#define ROBO_ARLCTRL_PAGE 0x04 /* ARL control page */ -#define ROBO_VLAN_PAGE 0x34 /* VLAN page */ - -/* ARL control page registers */ -#define ROBO_ARLCTRL_CONF 0x00 /* ARL configuration register */ -#define ROBO_ARLCTRL_ADDR_1 0x10 /* Multiport address 1 */ -#define ROBO_ARLCTRL_VEC_1 0x16 /* Multiport vector 1 */ -#define ROBO_ARLCTRL_ADDR_2 0x20 /* Multiport address 2 */ -#define ROBO_ARLCTRL_VEC_2 0x26 /* Multiport vector 2 */ - -/* VLAN page registers */ -#define ROBO_VLAN_ACCESS 0x08 /* VLAN table access register */ -#define ROBO_VLAN_ACCESS_5350 0x06 /* VLAN table access register (5350) */ -#define ROBO_VLAN_READ 0x0c /* VLAN read register */ -#define ROBO_VLAN_MAX 0xff /* Maximum number of VLANs */ - - -static const u8 pae_group_addr[ETH_ALEN] = -{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; - - -struct wpa_driver_roboswitch_data { - void *ctx; - struct l2_packet_data *l2; - char ifname[IFNAMSIZ + 1]; - u8 own_addr[ETH_ALEN]; - struct ifreq ifr; - int fd, is_5350; - u16 ports; -}; - - -/* Copied from the kernel-only part of mii.h. */ -static inline struct mii_ioctl_data *if_mii(struct ifreq *rq) -{ - return (struct mii_ioctl_data *) &rq->ifr_ifru; -} - - -/* - * RoboSwitch uses 16-bit Big Endian addresses. - * The ordering of the words is reversed in the MII registers. - */ -static void wpa_driver_roboswitch_addr_be16(const u8 addr[ETH_ALEN], u16 *be) -{ - int i; - for (i = 0; i < ETH_ALEN; i += 2) - be[(ETH_ALEN - i) / 2 - 1] = WPA_GET_BE16(addr + i); -} - - -static u16 wpa_driver_roboswitch_mdio_read( - struct wpa_driver_roboswitch_data *drv, u8 reg) -{ - struct mii_ioctl_data *mii = if_mii(&drv->ifr); - - mii->phy_id = ROBO_PHY_ADDR; - mii->reg_num = reg; - - if (ioctl(drv->fd, SIOCGMIIREG, &drv->ifr) < 0) { - perror("ioctl[SIOCGMIIREG]"); - return 0x00; - } - return mii->val_out; -} - - -static void wpa_driver_roboswitch_mdio_write( - struct wpa_driver_roboswitch_data *drv, u8 reg, u16 val) -{ - struct mii_ioctl_data *mii = if_mii(&drv->ifr); - - mii->phy_id = ROBO_PHY_ADDR; - mii->reg_num = reg; - mii->val_in = val; - - if (ioctl(drv->fd, SIOCSMIIREG, &drv->ifr) < 0) { - perror("ioctl[SIOCSMIIREG"); - } -} - - -static int wpa_driver_roboswitch_reg(struct wpa_driver_roboswitch_data *drv, - u8 page, u8 reg, u8 op) -{ - int i; - - /* set page number */ - wpa_driver_roboswitch_mdio_write(drv, ROBO_MII_PAGE, - (page << 8) | ROBO_MII_PAGE_ENABLE); - /* set register address */ - wpa_driver_roboswitch_mdio_write(drv, ROBO_MII_ADDR, (reg << 8) | op); - - /* check if operation completed */ - for (i = 0; i < ROBO_MII_RETRY_MAX; ++i) { - if ((wpa_driver_roboswitch_mdio_read(drv, ROBO_MII_ADDR) & 3) - == 0) - return 0; - } - /* timeout */ - return -1; -} - - -static int wpa_driver_roboswitch_read(struct wpa_driver_roboswitch_data *drv, - u8 page, u8 reg, u16 *val, int len) -{ - int i; - - if (len > ROBO_MII_DATA_MAX || - wpa_driver_roboswitch_reg(drv, page, reg, ROBO_MII_ADDR_READ) < 0) - return -1; - - for (i = 0; i < len; ++i) { - val[i] = wpa_driver_roboswitch_mdio_read( - drv, ROBO_MII_DATA_OFFSET + i); - } - - return 0; -} - - -static int wpa_driver_roboswitch_write(struct wpa_driver_roboswitch_data *drv, - u8 page, u8 reg, u16 *val, int len) -{ - int i; - - if (len > ROBO_MII_DATA_MAX) return -1; - for (i = 0; i < len; ++i) { - wpa_driver_roboswitch_mdio_write(drv, ROBO_MII_DATA_OFFSET + i, - val[i]); - } - return wpa_driver_roboswitch_reg(drv, page, reg, ROBO_MII_ADDR_WRITE); -} - - -static void wpa_driver_roboswitch_receive(void *priv, const u8 *src_addr, - const u8 *buf, size_t len) -{ - struct wpa_driver_roboswitch_data *drv = priv; - - if (len > 14 && WPA_GET_BE16(buf + 12) == ETH_P_EAPOL && - os_memcmp(buf, drv->own_addr, ETH_ALEN) == 0) { - wpa_supplicant_rx_eapol(drv->ctx, src_addr, buf + 14, - len - 14); - } -} - - -static int wpa_driver_roboswitch_get_ssid(void *priv, u8 *ssid) -{ - ssid[0] = 0; - return 0; -} - - -static int wpa_driver_roboswitch_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_roboswitch_set_param(void *priv, const char *param) -{ - struct wpa_driver_roboswitch_data *drv = priv; - char *sep; - - if (param == NULL || os_strstr(param, "multicast_only=1") == NULL) { - sep = drv->ifname + os_strlen(drv->ifname); - *sep = '.'; - drv->l2 = l2_packet_init(drv->ifname, NULL, ETH_P_ALL, - wpa_driver_roboswitch_receive, drv, - 1); - if (drv->l2 == NULL) { - wpa_printf(MSG_INFO, "%s: Unable to listen on %s", - __func__, drv->ifname); - return -1; - } - *sep = '\0'; - l2_packet_get_own_addr(drv->l2, drv->own_addr); - } else { - wpa_printf(MSG_DEBUG, "%s: Ignoring unicast frames", __func__); - drv->l2 = NULL; - } - return 0; -} - - -static const char * wpa_driver_roboswitch_get_ifname(void *priv) -{ - struct wpa_driver_roboswitch_data *drv = priv; - return drv->ifname; -} - - -static int wpa_driver_roboswitch_join(struct wpa_driver_roboswitch_data *drv, - u16 ports, const u8 *addr) -{ - u16 read1[3], read2[3], addr_be16[3]; - - wpa_driver_roboswitch_addr_be16(addr, addr_be16); - - if (wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_CONF, read1, 1) < 0) - return -1; - if (!(read1[0] & (1 << 4))) { - /* multiport addresses are not yet enabled */ - read1[0] |= 1 << 4; - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_1, addr_be16, 3); - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_1, &ports, 1); - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_2, addr_be16, 3); - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_2, &ports, 1); - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_CONF, read1, 1); - } else { - /* if both multiport addresses are the same we can add */ - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_1, read1, 3); - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_2, read2, 3); - if (os_memcmp(read1, read2, 6) != 0) - return -1; - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_1, read1, 1); - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_2, read2, 1); - if (read1[0] != read2[0]) - return -1; - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_1, addr_be16, 3); - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_1, &ports, 1); - } - return 0; -} - - -static int wpa_driver_roboswitch_leave(struct wpa_driver_roboswitch_data *drv, - u16 ports, const u8 *addr) -{ - u16 _read, addr_be16[3], addr_read[3], ports_read; - - wpa_driver_roboswitch_addr_be16(addr, addr_be16); - - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, ROBO_ARLCTRL_CONF, - &_read, 1); - /* If ARL control is disabled, there is nothing to leave. */ - if (!(_read & (1 << 4))) return -1; - - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_1, addr_read, 3); - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, ROBO_ARLCTRL_VEC_1, - &ports_read, 1); - /* check if we occupy multiport address 1 */ - if (os_memcmp(addr_read, addr_be16, 6) == 0 && ports_read == ports) { - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_2, addr_read, 3); - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_2, &ports_read, 1); - /* and multiport address 2 */ - if (os_memcmp(addr_read, addr_be16, 6) == 0 && - ports_read == ports) { - _read &= ~(1 << 4); - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_CONF, &_read, - 1); - } else { - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_1, - addr_read, 3); - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_1, - &ports_read, 1); - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_2, - addr_read, 3); - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_2, - &ports_read, 1); - } - } else { - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_2, addr_read, 3); - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_2, &ports_read, 1); - /* or multiport address 2 */ - if (os_memcmp(addr_read, addr_be16, 6) == 0 && - ports_read == ports) { - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_1, - addr_read, 3); - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_1, - &ports_read, 1); - } else return -1; - } - return 0; -} - - -static void * wpa_driver_roboswitch_init(void *ctx, const char *ifname) -{ - struct wpa_driver_roboswitch_data *drv; - char *sep; - u16 vlan = 0, _read[2]; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) return NULL; - drv->ctx = ctx; - drv->own_addr[0] = '\0'; - - /* copy ifname and take a pointer to the second to last character */ - sep = drv->ifname + - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)) - 2; - /* find the '.' seperating and */ - while (sep > drv->ifname && *sep != '.') sep--; - if (sep <= drv->ifname) { - wpa_printf(MSG_INFO, "%s: No . pair in " - "interface name %s", __func__, drv->ifname); - os_free(drv); - return NULL; - } - *sep = '\0'; - while (*++sep) { - if (*sep < '0' || *sep > '9') { - wpa_printf(MSG_INFO, "%s: Invalid vlan specification " - "in interface name %s", __func__, ifname); - os_free(drv); - return NULL; - } - vlan *= 10; - vlan += *sep - '0'; - if (vlan > ROBO_VLAN_MAX) { - wpa_printf(MSG_INFO, "%s: VLAN out of range in " - "interface name %s", __func__, ifname); - os_free(drv); - return NULL; - } - } - - drv->fd = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->fd < 0) { - wpa_printf(MSG_INFO, "%s: Unable to create socket", __func__); - os_free(drv); - return NULL; - } - - os_memset(&drv->ifr, 0, sizeof(drv->ifr)); - os_strlcpy(drv->ifr.ifr_name, drv->ifname, IFNAMSIZ); - if (ioctl(drv->fd, SIOCGMIIPHY, &drv->ifr) < 0) { - perror("ioctl[SIOCGMIIPHY]"); - os_free(drv); - return NULL; - } - if (if_mii(&drv->ifr)->phy_id != ROBO_PHY_ADDR) { - wpa_printf(MSG_INFO, "%s: Invalid phy address (not a " - "RoboSwitch?)", __func__); - os_free(drv); - return NULL; - } - - /* set and read back to see if the register can be used */ - _read[0] = ROBO_VLAN_MAX; - wpa_driver_roboswitch_write(drv, ROBO_VLAN_PAGE, ROBO_VLAN_ACCESS_5350, - _read, 1); - wpa_driver_roboswitch_read(drv, ROBO_VLAN_PAGE, ROBO_VLAN_ACCESS_5350, - _read + 1, 1); - drv->is_5350 = _read[0] == _read[1]; - - /* set the read bit */ - vlan |= 1 << 13; - wpa_driver_roboswitch_write(drv, ROBO_VLAN_PAGE, - drv->is_5350 ? ROBO_VLAN_ACCESS_5350 - : ROBO_VLAN_ACCESS, - &vlan, 1); - wpa_driver_roboswitch_read(drv, ROBO_VLAN_PAGE, ROBO_VLAN_READ, _read, - drv->is_5350 ? 2 : 1); - if (!(drv->is_5350 ? _read[1] & (1 << 4) : _read[0] & (1 << 14))) { - wpa_printf(MSG_INFO, "%s: Could not get port information for " - "VLAN %d", __func__, vlan & ~(1 << 13)); - os_free(drv); - return NULL; - } - drv->ports = _read[0] & 0x001F; - /* add the MII port */ - drv->ports |= 1 << 8; - if (wpa_driver_roboswitch_join(drv, drv->ports, pae_group_addr) < 0) { - wpa_printf(MSG_INFO, "%s: Unable to join PAE group", __func__); - os_free(drv); - return NULL; - } else { - wpa_printf(MSG_DEBUG, "%s: Added PAE group address to " - "RoboSwitch ARL", __func__); - } - - return drv; -} - - -static void wpa_driver_roboswitch_deinit(void *priv) -{ - struct wpa_driver_roboswitch_data *drv = priv; - - if (drv->l2) { - l2_packet_deinit(drv->l2); - drv->l2 = NULL; - } - if (wpa_driver_roboswitch_leave(drv, drv->ports, pae_group_addr) < 0) { - wpa_printf(MSG_DEBUG, "%s: Unable to leave PAE group", - __func__); - } - - close(drv->fd); - os_free(drv); -} - - -const struct wpa_driver_ops wpa_driver_roboswitch_ops = { - .name = "roboswitch", - .desc = "wpa_supplicant roboswitch driver", - .get_ssid = wpa_driver_roboswitch_get_ssid, - .get_bssid = wpa_driver_roboswitch_get_bssid, - .init = wpa_driver_roboswitch_init, - .deinit = wpa_driver_roboswitch_deinit, - .set_param = wpa_driver_roboswitch_set_param, - .get_ifname = wpa_driver_roboswitch_get_ifname, -}; diff --git a/contrib/hostapd/src/drivers/driver_test.c b/contrib/hostapd/src/drivers/driver_test.c deleted file mode 100644 index 2a41cf260a..0000000000 --- a/contrib/hostapd/src/drivers/driver_test.c +++ /dev/null @@ -1,1230 +0,0 @@ -/* - * WPA Supplicant - testing driver interface - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -/* Make dure we get winsock2.h for Windows build to get sockaddr_storage */ -#include "build_config.h" -#ifdef CONFIG_NATIVE_WINDOWS -#include -#endif /* CONFIG_NATIVE_WINDOWS */ - -#include "includes.h" - -#ifndef CONFIG_NATIVE_WINDOWS -#include -#include -#include -#define DRIVER_TEST_UNIX -#endif /* CONFIG_NATIVE_WINDOWS */ - -#include "common.h" -#include "driver.h" -#include "l2_packet/l2_packet.h" -#include "eloop.h" -#include "sha1.h" -#include "ieee802_11_defs.h" - - -struct wpa_driver_test_global { - int dummy; -}; - -struct wpa_driver_test_data { - struct wpa_driver_test_global *global; - void *ctx; - u8 own_addr[ETH_ALEN]; - int test_socket; -#ifdef DRIVER_TEST_UNIX - struct sockaddr_un hostapd_addr; -#endif /* DRIVER_TEST_UNIX */ - int hostapd_addr_set; - struct sockaddr_in hostapd_addr_udp; - int hostapd_addr_udp_set; - char *own_socket_path; - char *test_dir; - u8 bssid[ETH_ALEN]; - u8 ssid[32]; - size_t ssid_len; -#define MAX_SCAN_RESULTS 30 - struct wpa_scan_res *scanres[MAX_SCAN_RESULTS]; - size_t num_scanres; - int use_associnfo; - u8 assoc_wpa_ie[80]; - size_t assoc_wpa_ie_len; - int use_mlme; - int associated; - u8 *probe_req_ie; - size_t probe_req_ie_len; -}; - - -static void wpa_driver_test_poll(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_driver_test_data *drv = eloop_ctx; - -#ifdef DRIVER_TEST_UNIX - if (drv->associated && drv->hostapd_addr_set) { - struct stat st; - if (stat(drv->hostapd_addr.sun_path, &st) < 0) { - wpa_printf(MSG_DEBUG, "%s: lost connection to AP: %s", - __func__, strerror(errno)); - drv->associated = 0; - wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); - } - } -#endif /* DRIVER_TEST_UNIX */ - - eloop_register_timeout(1, 0, wpa_driver_test_poll, drv, NULL); -} - - -static int wpa_driver_test_set_wpa(void *priv, int enabled) -{ - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - return 0; -} - - -static void wpa_driver_test_scan_timeout(void *eloop_ctx, void *timeout_ctx) -{ - wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); - wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); -} - - -#ifdef DRIVER_TEST_UNIX -static void wpa_driver_scan_dir(struct wpa_driver_test_data *drv, - const char *path) -{ - struct dirent *dent; - DIR *dir; - struct sockaddr_un addr; - char cmd[512], *pos, *end; - int ret; - - dir = opendir(path); - if (dir == NULL) - return; - - end = cmd + sizeof(cmd); - pos = cmd; - ret = os_snprintf(pos, end - pos, "SCAN " MACSTR, - MAC2STR(drv->own_addr)); - if (ret >= 0 && ret < end - pos) - pos += ret; - if (drv->probe_req_ie) { - ret = os_snprintf(pos, end - pos, " "); - if (ret >= 0 && ret < end - pos) - pos += ret; - pos += wpa_snprintf_hex(pos, end - pos, drv->probe_req_ie, - drv->probe_req_ie_len); - } - end[-1] = '\0'; - - while ((dent = readdir(dir))) { - if (os_strncmp(dent->d_name, "AP-", 3) != 0) - continue; - wpa_printf(MSG_DEBUG, "%s: SCAN %s", __func__, dent->d_name); - - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", - path, dent->d_name); - - if (sendto(drv->test_socket, cmd, os_strlen(cmd), 0, - (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("sendto(test_socket)"); - } - } - closedir(dir); -} -#endif /* DRIVER_TEST_UNIX */ - - -static int wpa_driver_test_scan(void *priv, const u8 *ssid, size_t ssid_len) -{ - struct wpa_driver_test_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s: priv=%p", __func__, priv); - - drv->num_scanres = 0; - -#ifdef DRIVER_TEST_UNIX - if (drv->test_socket >= 0 && drv->test_dir) - wpa_driver_scan_dir(drv, drv->test_dir); - - if (drv->test_socket >= 0 && drv->hostapd_addr_set && - sendto(drv->test_socket, "SCAN", 4, 0, - (struct sockaddr *) &drv->hostapd_addr, - sizeof(drv->hostapd_addr)) < 0) { - perror("sendto(test_socket)"); - } -#endif /* DRIVER_TEST_UNIX */ - - if (drv->test_socket >= 0 && drv->hostapd_addr_udp_set && - sendto(drv->test_socket, "SCAN", 4, 0, - (struct sockaddr *) &drv->hostapd_addr_udp, - sizeof(drv->hostapd_addr_udp)) < 0) { - perror("sendto(test_socket)"); - } - - eloop_cancel_timeout(wpa_driver_test_scan_timeout, drv, drv->ctx); - eloop_register_timeout(1, 0, wpa_driver_test_scan_timeout, drv, - drv->ctx); - return 0; -} - - -static struct wpa_scan_results * wpa_driver_test_get_scan_results2(void *priv) -{ - struct wpa_driver_test_data *drv = priv; - struct wpa_scan_results *res; - size_t i; - - res = os_zalloc(sizeof(*res)); - if (res == NULL) - return NULL; - - res->res = os_zalloc(drv->num_scanres * sizeof(struct wpa_scan_res *)); - if (res->res == NULL) { - os_free(res); - return NULL; - } - - for (i = 0; i < drv->num_scanres; i++) { - struct wpa_scan_res *r; - if (drv->scanres[i] == NULL) - continue; - r = os_malloc(sizeof(*r) + drv->scanres[i]->ie_len); - if (r == NULL) - break; - os_memcpy(r, drv->scanres[i], - sizeof(*r) + drv->scanres[i]->ie_len); - res->res[res->num++] = r; - } - - return res; -} - - -static int wpa_driver_test_set_key(void *priv, wpa_alg alg, const u8 *addr, - int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - wpa_printf(MSG_DEBUG, "%s: priv=%p alg=%d key_idx=%d set_tx=%d", - __func__, priv, alg, key_idx, set_tx); - if (addr) { - wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr)); - } - if (seq) { - wpa_hexdump(MSG_DEBUG, " seq", seq, seq_len); - } - if (key) { - wpa_hexdump(MSG_DEBUG, " key", key, key_len); - } - return 0; -} - - -static int wpa_driver_test_associate( - void *priv, struct wpa_driver_associate_params *params) -{ - struct wpa_driver_test_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d " - "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d", - __func__, priv, params->freq, params->pairwise_suite, - params->group_suite, params->key_mgmt_suite, - params->auth_alg, params->mode); - if (params->bssid) { - wpa_printf(MSG_DEBUG, " bssid=" MACSTR, - MAC2STR(params->bssid)); - } - if (params->ssid) { - wpa_hexdump_ascii(MSG_DEBUG, " ssid", - params->ssid, params->ssid_len); - } - if (params->wpa_ie) { - wpa_hexdump(MSG_DEBUG, " wpa_ie", - params->wpa_ie, params->wpa_ie_len); - drv->assoc_wpa_ie_len = params->wpa_ie_len; - if (drv->assoc_wpa_ie_len > sizeof(drv->assoc_wpa_ie)) - drv->assoc_wpa_ie_len = sizeof(drv->assoc_wpa_ie); - os_memcpy(drv->assoc_wpa_ie, params->wpa_ie, - drv->assoc_wpa_ie_len); - } else - drv->assoc_wpa_ie_len = 0; - -#ifdef DRIVER_TEST_UNIX - if (drv->test_dir && params->bssid) { - os_memset(&drv->hostapd_addr, 0, sizeof(drv->hostapd_addr)); - drv->hostapd_addr.sun_family = AF_UNIX; - os_snprintf(drv->hostapd_addr.sun_path, - sizeof(drv->hostapd_addr.sun_path), - "%s/AP-" MACSTR, - drv->test_dir, MAC2STR(params->bssid)); - drv->hostapd_addr_set = 1; - } -#endif /* DRIVER_TEST_UNIX */ - - if (drv->test_socket >= 0 && - (drv->hostapd_addr_set || drv->hostapd_addr_udp_set)) { - char cmd[200], *pos, *end; - int ret; - end = cmd + sizeof(cmd); - pos = cmd; - ret = os_snprintf(pos, end - pos, "ASSOC " MACSTR " ", - MAC2STR(drv->own_addr)); - if (ret >= 0 && ret < end - pos) - pos += ret; - pos += wpa_snprintf_hex(pos, end - pos, params->ssid, - params->ssid_len); - ret = os_snprintf(pos, end - pos, " "); - if (ret >= 0 && ret < end - pos) - pos += ret; - pos += wpa_snprintf_hex(pos, end - pos, params->wpa_ie, - params->wpa_ie_len); - end[-1] = '\0'; -#ifdef DRIVER_TEST_UNIX - if (drv->hostapd_addr_set && - sendto(drv->test_socket, cmd, os_strlen(cmd), 0, - (struct sockaddr *) &drv->hostapd_addr, - sizeof(drv->hostapd_addr)) < 0) { - perror("sendto(test_socket)"); - return -1; - } -#endif /* DRIVER_TEST_UNIX */ - if (drv->hostapd_addr_udp_set && - sendto(drv->test_socket, cmd, os_strlen(cmd), 0, - (struct sockaddr *) &drv->hostapd_addr_udp, - sizeof(drv->hostapd_addr_udp)) < 0) { - perror("sendto(test_socket)"); - return -1; - } - - os_memcpy(drv->ssid, params->ssid, params->ssid_len); - drv->ssid_len = params->ssid_len; - } else { - drv->associated = 1; - wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); - } - - return 0; -} - - -static int wpa_driver_test_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_test_data *drv = priv; - os_memcpy(bssid, drv->bssid, ETH_ALEN); - return 0; -} - - -static int wpa_driver_test_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_test_data *drv = priv; - os_memcpy(ssid, drv->ssid, 32); - return drv->ssid_len; -} - - -static int wpa_driver_test_send_disassoc(struct wpa_driver_test_data *drv) -{ -#ifdef DRIVER_TEST_UNIX - if (drv->test_socket >= 0 && - sendto(drv->test_socket, "DISASSOC", 8, 0, - (struct sockaddr *) &drv->hostapd_addr, - sizeof(drv->hostapd_addr)) < 0) { - perror("sendto(test_socket)"); - return -1; - } -#endif /* DRIVER_TEST_UNIX */ - if (drv->test_socket >= 0 && drv->hostapd_addr_udp_set && - sendto(drv->test_socket, "DISASSOC", 8, 0, - (struct sockaddr *) &drv->hostapd_addr_udp, - sizeof(drv->hostapd_addr_udp)) < 0) { - perror("sendto(test_socket)"); - return -1; - } - return 0; -} - - -static int wpa_driver_test_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_test_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d", - __func__, MAC2STR(addr), reason_code); - os_memset(drv->bssid, 0, ETH_ALEN); - drv->associated = 0; - wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); - return wpa_driver_test_send_disassoc(drv); -} - - -static int wpa_driver_test_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_test_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d", - __func__, MAC2STR(addr), reason_code); - os_memset(drv->bssid, 0, ETH_ALEN); - drv->associated = 0; - wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); - return wpa_driver_test_send_disassoc(drv); -} - - -static void wpa_driver_test_scanresp(struct wpa_driver_test_data *drv, - struct sockaddr *from, - socklen_t fromlen, - const char *data) -{ - struct wpa_scan_res *res; - const char *pos, *pos2; - size_t len; - u8 *ie_pos, *ie_start, *ie_end; -#define MAX_IE_LEN 1000 - - wpa_printf(MSG_DEBUG, "test_driver: SCANRESP %s", data); - if (drv->num_scanres >= MAX_SCAN_RESULTS) { - wpa_printf(MSG_DEBUG, "test_driver: No room for the new scan " - "result"); - return; - } - - /* SCANRESP BSSID SSID IEs */ - - res = os_zalloc(sizeof(*res) + MAX_IE_LEN); - if (res == NULL) - return; - ie_start = ie_pos = (u8 *) (res + 1); - ie_end = ie_pos + MAX_IE_LEN; - - if (hwaddr_aton(data, res->bssid)) { - wpa_printf(MSG_DEBUG, "test_driver: invalid BSSID in scanres"); - os_free(res); - return; - } - - pos = data + 17; - while (*pos == ' ') - pos++; - pos2 = os_strchr(pos, ' '); - if (pos2 == NULL) { - wpa_printf(MSG_DEBUG, "test_driver: invalid SSID termination " - "in scanres"); - os_free(res); - return; - } - len = (pos2 - pos) / 2; - if (len > 32) - len = 32; - /* - * Generate SSID IE from the SSID field since this IE is not included - * in the main IE field. - */ - *ie_pos++ = WLAN_EID_SSID; - *ie_pos++ = len; - if (hexstr2bin(pos, ie_pos, len) < 0) { - wpa_printf(MSG_DEBUG, "test_driver: invalid SSID in scanres"); - os_free(res); - return; - } - ie_pos += len; - - pos = pos2 + 1; - pos2 = os_strchr(pos, ' '); - if (pos2 == NULL) - len = os_strlen(pos) / 2; - else - len = (pos2 - pos) / 2; - if ((int) len > ie_end - ie_pos) - len = ie_end - ie_pos; - if (hexstr2bin(pos, ie_pos, len) < 0) { - wpa_printf(MSG_DEBUG, "test_driver: invalid IEs in scanres"); - os_free(res); - return; - } - ie_pos += len; - res->ie_len = ie_pos - ie_start; - - if (pos2) { - pos = pos2 + 1; - while (*pos == ' ') - pos++; - if (os_strncmp(pos, "PRIVACY", 7) == 0) - res->caps |= IEEE80211_CAP_PRIVACY; - } - - os_free(drv->scanres[drv->num_scanres]); - drv->scanres[drv->num_scanres++] = res; -} - - -static void wpa_driver_test_assocresp(struct wpa_driver_test_data *drv, - struct sockaddr *from, - socklen_t fromlen, - const char *data) -{ - /* ASSOCRESP BSSID */ - if (hwaddr_aton(data, drv->bssid)) { - wpa_printf(MSG_DEBUG, "test_driver: invalid BSSID in " - "assocresp"); - } - if (drv->use_associnfo) { - union wpa_event_data event; - os_memset(&event, 0, sizeof(event)); - event.assoc_info.req_ies = drv->assoc_wpa_ie; - event.assoc_info.req_ies_len = drv->assoc_wpa_ie_len; - wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &event); - } - drv->associated = 1; - wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); -} - - -static void wpa_driver_test_disassoc(struct wpa_driver_test_data *drv, - struct sockaddr *from, - socklen_t fromlen) -{ - drv->associated = 0; - wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); -} - - -static void wpa_driver_test_eapol(struct wpa_driver_test_data *drv, - struct sockaddr *from, - socklen_t fromlen, - const u8 *data, size_t data_len) -{ - const u8 *src = drv->bssid; - - if (data_len > 14) { - /* Skip Ethernet header */ - src = data + ETH_ALEN; - data += 14; - data_len -= 14; - } - wpa_supplicant_rx_eapol(drv->ctx, src, data, data_len); -} - - -static void wpa_driver_test_mlme(struct wpa_driver_test_data *drv, - struct sockaddr *from, - socklen_t fromlen, - const u8 *data, size_t data_len) -{ -#ifdef CONFIG_CLIENT_MLME - struct ieee80211_rx_status rx_status; - os_memset(&rx_status, 0, sizeof(rx_status)); - wpa_supplicant_sta_rx(drv->ctx, data, data_len, &rx_status); -#endif /* CONFIG_CLIENT_MLME */ -} - - -static void wpa_driver_test_receive_unix(int sock, void *eloop_ctx, - void *sock_ctx) -{ - struct wpa_driver_test_data *drv = eloop_ctx; - char *buf; - int res; - struct sockaddr_storage from; - socklen_t fromlen = sizeof(from); - const size_t buflen = 2000; - - buf = os_malloc(buflen); - if (buf == NULL) - return; - res = recvfrom(sock, buf, buflen - 1, 0, - (struct sockaddr *) &from, &fromlen); - if (res < 0) { - perror("recvfrom(test_socket)"); - os_free(buf); - return; - } - buf[res] = '\0'; - - wpa_printf(MSG_DEBUG, "test_driver: received %u bytes", res); - - if (os_strncmp(buf, "SCANRESP ", 9) == 0) { - wpa_driver_test_scanresp(drv, (struct sockaddr *) &from, - fromlen, buf + 9); - } else if (os_strncmp(buf, "ASSOCRESP ", 10) == 0) { - wpa_driver_test_assocresp(drv, (struct sockaddr *) &from, - fromlen, buf + 10); - } else if (os_strcmp(buf, "DISASSOC") == 0) { - wpa_driver_test_disassoc(drv, (struct sockaddr *) &from, - fromlen); - } else if (os_strcmp(buf, "DEAUTH") == 0) { - wpa_driver_test_disassoc(drv, (struct sockaddr *) &from, - fromlen); - } else if (os_strncmp(buf, "EAPOL ", 6) == 0) { - wpa_driver_test_eapol(drv, (struct sockaddr *) &from, fromlen, - (const u8 *) buf + 6, res - 6); - } else if (os_strncmp(buf, "MLME ", 5) == 0) { - wpa_driver_test_mlme(drv, (struct sockaddr *) &from, fromlen, - (const u8 *) buf + 5, res - 5); - } else { - wpa_hexdump_ascii(MSG_DEBUG, "Unknown test_socket command", - (u8 *) buf, res); - } - os_free(buf); -} - - -static void * wpa_driver_test_init2(void *ctx, const char *ifname, - void *global_priv) -{ - struct wpa_driver_test_data *drv; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->global = global_priv; - drv->ctx = ctx; - drv->test_socket = -1; - - /* Set dummy BSSID and SSID for testing. */ - drv->bssid[0] = 0x02; - drv->bssid[1] = 0x00; - drv->bssid[2] = 0x00; - drv->bssid[3] = 0x00; - drv->bssid[4] = 0x00; - drv->bssid[5] = 0x01; - os_memcpy(drv->ssid, "test", 5); - drv->ssid_len = 4; - - /* Generate a MAC address to help testing with multiple STAs */ - drv->own_addr[0] = 0x02; /* locally administered */ - sha1_prf((const u8 *) ifname, os_strlen(ifname), - "wpa_supplicant test mac addr generation", - NULL, 0, drv->own_addr + 1, ETH_ALEN - 1); - eloop_register_timeout(1, 0, wpa_driver_test_poll, drv, NULL); - - return drv; -} - - -static void wpa_driver_test_close_test_socket(struct wpa_driver_test_data *drv) -{ - if (drv->test_socket >= 0) { - eloop_unregister_read_sock(drv->test_socket); - close(drv->test_socket); - drv->test_socket = -1; - } - - if (drv->own_socket_path) { - unlink(drv->own_socket_path); - os_free(drv->own_socket_path); - drv->own_socket_path = NULL; - } -} - - -static void wpa_driver_test_deinit(void *priv) -{ - struct wpa_driver_test_data *drv = priv; - int i; - wpa_driver_test_close_test_socket(drv); - eloop_cancel_timeout(wpa_driver_test_scan_timeout, drv, drv->ctx); - eloop_cancel_timeout(wpa_driver_test_poll, drv, NULL); - os_free(drv->test_dir); - for (i = 0; i < MAX_SCAN_RESULTS; i++) - os_free(drv->scanres[i]); - os_free(drv->probe_req_ie); - os_free(drv); -} - - -static int wpa_driver_test_attach(struct wpa_driver_test_data *drv, - const char *dir) -{ -#ifdef DRIVER_TEST_UNIX - static unsigned int counter = 0; - struct sockaddr_un addr; - size_t len; - - os_free(drv->own_socket_path); - if (dir) { - len = os_strlen(dir) + 30; - drv->own_socket_path = os_malloc(len); - if (drv->own_socket_path == NULL) - return -1; - os_snprintf(drv->own_socket_path, len, "%s/STA-" MACSTR, - dir, MAC2STR(drv->own_addr)); - } else { - drv->own_socket_path = os_malloc(100); - if (drv->own_socket_path == NULL) - return -1; - os_snprintf(drv->own_socket_path, 100, - "/tmp/wpa_supplicant_test-%d-%d", - getpid(), counter++); - } - - drv->test_socket = socket(PF_UNIX, SOCK_DGRAM, 0); - if (drv->test_socket < 0) { - perror("socket(PF_UNIX)"); - os_free(drv->own_socket_path); - drv->own_socket_path = NULL; - return -1; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_strlcpy(addr.sun_path, drv->own_socket_path, sizeof(addr.sun_path)); - if (bind(drv->test_socket, (struct sockaddr *) &addr, - sizeof(addr)) < 0) { - perror("bind(PF_UNIX)"); - close(drv->test_socket); - unlink(drv->own_socket_path); - os_free(drv->own_socket_path); - drv->own_socket_path = NULL; - return -1; - } - - eloop_register_read_sock(drv->test_socket, - wpa_driver_test_receive_unix, drv, NULL); - - return 0; -#else /* DRIVER_TEST_UNIX */ - return -1; -#endif /* DRIVER_TEST_UNIX */ -} - - -static int wpa_driver_test_attach_udp(struct wpa_driver_test_data *drv, - char *dst) -{ - char *pos; - - pos = os_strchr(dst, ':'); - if (pos == NULL) - return -1; - *pos++ = '\0'; - wpa_printf(MSG_DEBUG, "%s: addr=%s port=%s", __func__, dst, pos); - - drv->test_socket = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->test_socket < 0) { - perror("socket(PF_INET)"); - return -1; - } - - os_memset(&drv->hostapd_addr_udp, 0, sizeof(drv->hostapd_addr_udp)); - drv->hostapd_addr_udp.sin_family = AF_INET; -#if defined(CONFIG_NATIVE_WINDOWS) || defined(CONFIG_ANSI_C_EXTRA) - { - int a[4]; - u8 *pos; - sscanf(dst, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]); - pos = (u8 *) &drv->hostapd_addr_udp.sin_addr; - *pos++ = a[0]; - *pos++ = a[1]; - *pos++ = a[2]; - *pos++ = a[3]; - } -#else /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */ - inet_aton(dst, &drv->hostapd_addr_udp.sin_addr); -#endif /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */ - drv->hostapd_addr_udp.sin_port = htons(atoi(pos)); - - drv->hostapd_addr_udp_set = 1; - - eloop_register_read_sock(drv->test_socket, - wpa_driver_test_receive_unix, drv, NULL); - - return 0; -} - - -static int wpa_driver_test_set_param(void *priv, const char *param) -{ - struct wpa_driver_test_data *drv = priv; - const char *pos; - - wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param); - if (param == NULL) - return 0; - - wpa_driver_test_close_test_socket(drv); - -#ifdef DRIVER_TEST_UNIX - pos = os_strstr(param, "test_socket="); - if (pos) { - const char *pos2; - size_t len; - - pos += 12; - pos2 = os_strchr(pos, ' '); - if (pos2) - len = pos2 - pos; - else - len = os_strlen(pos); - if (len > sizeof(drv->hostapd_addr.sun_path)) - return -1; - os_memset(&drv->hostapd_addr, 0, sizeof(drv->hostapd_addr)); - drv->hostapd_addr.sun_family = AF_UNIX; - os_memcpy(drv->hostapd_addr.sun_path, pos, len); - drv->hostapd_addr_set = 1; - } -#endif /* DRIVER_TEST_UNIX */ - - pos = os_strstr(param, "test_dir="); - if (pos) { - char *end; - os_free(drv->test_dir); - drv->test_dir = os_strdup(pos + 9); - if (drv->test_dir == NULL) - return -1; - end = os_strchr(drv->test_dir, ' '); - if (end) - *end = '\0'; - if (wpa_driver_test_attach(drv, drv->test_dir)) - return -1; - } else { - pos = os_strstr(param, "test_udp="); - if (pos) { - char *dst, *epos; - dst = os_strdup(pos + 9); - if (dst == NULL) - return -1; - epos = os_strchr(dst, ' '); - if (epos) - *epos = '\0'; - if (wpa_driver_test_attach_udp(drv, dst)) - return -1; - os_free(dst); - } else if (wpa_driver_test_attach(drv, NULL)) - return -1; - } - - if (os_strstr(param, "use_associnfo=1")) { - wpa_printf(MSG_DEBUG, "test_driver: Use AssocInfo events"); - drv->use_associnfo = 1; - } - -#ifdef CONFIG_CLIENT_MLME - if (os_strstr(param, "use_mlme=1")) { - wpa_printf(MSG_DEBUG, "test_driver: Use internal MLME"); - drv->use_mlme = 1; - } -#endif /* CONFIG_CLIENT_MLME */ - - return 0; -} - - -static const u8 * wpa_driver_test_get_mac_addr(void *priv) -{ - struct wpa_driver_test_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __func__); - return drv->own_addr; -} - - -static int wpa_driver_test_send_eapol(void *priv, const u8 *dest, u16 proto, - const u8 *data, size_t data_len) -{ - struct wpa_driver_test_data *drv = priv; - char *msg; - size_t msg_len; - struct l2_ethhdr eth; - struct sockaddr *addr; - socklen_t alen; -#ifdef DRIVER_TEST_UNIX - struct sockaddr_un addr_un; -#endif /* DRIVER_TEST_UNIX */ - - wpa_hexdump(MSG_MSGDUMP, "test_send_eapol TX frame", data, data_len); - - os_memset(ð, 0, sizeof(eth)); - os_memcpy(eth.h_dest, dest, ETH_ALEN); - os_memcpy(eth.h_source, drv->own_addr, ETH_ALEN); - eth.h_proto = host_to_be16(proto); - - msg_len = 6 + sizeof(eth) + data_len; - msg = os_malloc(msg_len); - if (msg == NULL) - return -1; - os_memcpy(msg, "EAPOL ", 6); - os_memcpy(msg + 6, ð, sizeof(eth)); - os_memcpy(msg + 6 + sizeof(eth), data, data_len); - - if (os_memcmp(dest, drv->bssid, ETH_ALEN) == 0 || - drv->test_dir == NULL) { - if (drv->hostapd_addr_udp_set) { - addr = (struct sockaddr *) &drv->hostapd_addr_udp; - alen = sizeof(drv->hostapd_addr_udp); - } else { -#ifdef DRIVER_TEST_UNIX - addr = (struct sockaddr *) &drv->hostapd_addr; - alen = sizeof(drv->hostapd_addr); -#else /* DRIVER_TEST_UNIX */ - os_free(msg); - return -1; -#endif /* DRIVER_TEST_UNIX */ - } - } else { -#ifdef DRIVER_TEST_UNIX - struct stat st; - os_memset(&addr_un, 0, sizeof(addr_un)); - addr_un.sun_family = AF_UNIX; - os_snprintf(addr_un.sun_path, sizeof(addr_un.sun_path), - "%s/STA-" MACSTR, drv->test_dir, MAC2STR(dest)); - if (stat(addr_un.sun_path, &st) < 0) { - os_snprintf(addr_un.sun_path, sizeof(addr_un.sun_path), - "%s/AP-" MACSTR, - drv->test_dir, MAC2STR(dest)); - } - addr = (struct sockaddr *) &addr_un; - alen = sizeof(addr_un); -#else /* DRIVER_TEST_UNIX */ - os_free(msg); - return -1; -#endif /* DRIVER_TEST_UNIX */ - } - - if (sendto(drv->test_socket, msg, msg_len, 0, addr, alen) < 0) { - perror("sendmsg(test_socket)"); - os_free(msg); - return -1; - } - - os_free(msg); - return 0; -} - - -static int wpa_driver_test_get_capa(void *priv, struct wpa_driver_capa *capa) -{ - struct wpa_driver_test_data *drv = priv; - os_memset(capa, 0, sizeof(*capa)); - capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | - WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK | - WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE | - WPA_DRIVER_CAPA_KEY_MGMT_FT | - WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK; - capa->enc = WPA_DRIVER_CAPA_ENC_WEP40 | - WPA_DRIVER_CAPA_ENC_WEP104 | - WPA_DRIVER_CAPA_ENC_TKIP | - WPA_DRIVER_CAPA_ENC_CCMP; - capa->auth = WPA_DRIVER_AUTH_OPEN | - WPA_DRIVER_AUTH_SHARED | - WPA_DRIVER_AUTH_LEAP; - if (drv->use_mlme) - capa->flags |= WPA_DRIVER_FLAGS_USER_SPACE_MLME; - - return 0; -} - - -static int wpa_driver_test_mlme_setprotection(void *priv, const u8 *addr, - int protect_type, - int key_type) -{ - wpa_printf(MSG_DEBUG, "%s: protect_type=%d key_type=%d", - __func__, protect_type, key_type); - - if (addr) { - wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, - __func__, MAC2STR(addr)); - } - - return 0; -} - - -#ifdef CONFIG_CLIENT_MLME -static struct wpa_hw_modes * -wpa_driver_test_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) -{ - struct wpa_hw_modes *modes; - - *num_modes = 1; - *flags = 0; - modes = os_zalloc(*num_modes * sizeof(struct wpa_hw_modes)); - if (modes == NULL) - return NULL; - modes[0].mode = WPA_MODE_IEEE80211G; - modes[0].num_channels = 1; - modes[0].num_rates = 1; - modes[0].channels = os_zalloc(sizeof(struct wpa_channel_data)); - modes[0].rates = os_zalloc(sizeof(struct wpa_rate_data)); - if (modes[0].channels == NULL || modes[0].rates == NULL) { - wpa_supplicant_sta_free_hw_features(modes, *num_modes); - return NULL; - } - modes[0].channels[0].chan = 1; - modes[0].channels[0].freq = 2412; - modes[0].channels[0].flag = WPA_CHAN_W_SCAN | WPA_CHAN_W_ACTIVE_SCAN; - modes[0].rates[0].rate = 10; - modes[0].rates[0].flags = WPA_RATE_BASIC | WPA_RATE_SUPPORTED | - WPA_RATE_CCK | WPA_RATE_MANDATORY; - - return modes; -} - - -static int wpa_driver_test_set_channel(void *priv, wpa_hw_mode phymode, - int chan, int freq) -{ - wpa_printf(MSG_DEBUG, "%s: phymode=%d chan=%d freq=%d", - __func__, phymode, chan, freq); - return 0; -} - - -static int wpa_driver_test_send_mlme(void *priv, const u8 *data, - size_t data_len) -{ - struct wpa_driver_test_data *drv = priv; - struct msghdr msg; - struct iovec io[2]; - struct sockaddr_un addr; - const u8 *dest; - struct dirent *dent; - DIR *dir; - - wpa_hexdump(MSG_MSGDUMP, "test_send_mlme", data, data_len); - if (data_len < 10) - return -1; - dest = data + 4; - - io[0].iov_base = "MLME "; - io[0].iov_len = 5; - io[1].iov_base = (u8 *) data; - io[1].iov_len = data_len; - - os_memset(&msg, 0, sizeof(msg)); - msg.msg_iov = io; - msg.msg_iovlen = 2; - if (os_memcmp(dest, drv->bssid, ETH_ALEN) == 0 || - drv->test_dir == NULL) { - if (drv->hostapd_addr_udp_set) { - msg.msg_name = &drv->hostapd_addr_udp; - msg.msg_namelen = sizeof(drv->hostapd_addr_udp); - } else { -#ifdef DRIVER_TEST_UNIX - msg.msg_name = &drv->hostapd_addr; - msg.msg_namelen = sizeof(drv->hostapd_addr); -#endif /* DRIVER_TEST_UNIX */ - } - } else if (os_memcmp(dest, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) - { - dir = opendir(drv->test_dir); - if (dir == NULL) - return -1; - while ((dent = readdir(dir))) { -#ifdef _DIRENT_HAVE_D_TYPE - /* Skip the file if it is not a socket. - * Also accept DT_UNKNOWN (0) in case - * the C library or underlying file - * system does not support d_type. */ - if (dent->d_type != DT_SOCK && - dent->d_type != DT_UNKNOWN) - continue; -#endif /* _DIRENT_HAVE_D_TYPE */ - if (os_strcmp(dent->d_name, ".") == 0 || - os_strcmp(dent->d_name, "..") == 0) - continue; - wpa_printf(MSG_DEBUG, "%s: Send broadcast MLME to %s", - __func__, dent->d_name); - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_snprintf(addr.sun_path, sizeof(addr.sun_path), - "%s/%s", drv->test_dir, dent->d_name); - - msg.msg_name = &addr; - msg.msg_namelen = sizeof(addr); - - if (sendmsg(drv->test_socket, &msg, 0) < 0) - perror("sendmsg(test_socket)"); - } - closedir(dir); - return 0; - } else { - struct stat st; - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_snprintf(addr.sun_path, sizeof(addr.sun_path), - "%s/AP-" MACSTR, drv->test_dir, MAC2STR(dest)); - if (stat(addr.sun_path, &st) < 0) { - os_snprintf(addr.sun_path, sizeof(addr.sun_path), - "%s/STA-" MACSTR, - drv->test_dir, MAC2STR(dest)); - } - msg.msg_name = &addr; - msg.msg_namelen = sizeof(addr); - } - - if (sendmsg(drv->test_socket, &msg, 0) < 0) { - perror("sendmsg(test_socket)"); - return -1; - } - - return 0; -} - - -static int wpa_driver_test_mlme_add_sta(void *priv, const u8 *addr, - const u8 *supp_rates, - size_t supp_rates_len) -{ - wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__, MAC2STR(addr)); - return 0; -} - - -static int wpa_driver_test_mlme_remove_sta(void *priv, const u8 *addr) -{ - wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__, MAC2STR(addr)); - return 0; -} - - -static int wpa_driver_test_set_ssid(void *priv, const u8 *ssid, - size_t ssid_len) -{ - wpa_printf(MSG_DEBUG, "%s", __func__); - return 0; -} - - -static int wpa_driver_test_set_bssid(void *priv, const u8 *bssid) -{ - wpa_printf(MSG_DEBUG, "%s: bssid=" MACSTR, __func__, MAC2STR(bssid)); - return 0; -} -#endif /* CONFIG_CLIENT_MLME */ - - -static int wpa_driver_test_set_probe_req_ie(void *priv, const u8 *ies, - size_t ies_len) -{ - struct wpa_driver_test_data *drv = priv; - - os_free(drv->probe_req_ie); - if (ies) { - drv->probe_req_ie = os_malloc(ies_len); - if (drv->probe_req_ie == NULL) { - drv->probe_req_ie_len = 0; - return -1; - } - os_memcpy(drv->probe_req_ie, ies, ies_len); - drv->probe_req_ie_len = ies_len; - } else { - drv->probe_req_ie = NULL; - drv->probe_req_ie_len = 0; - } - return 0; -} - - -static void * wpa_driver_test_global_init(void) -{ - struct wpa_driver_test_global *global; - - global = os_zalloc(sizeof(*global)); - return global; -} - - -static void wpa_driver_test_global_deinit(void *priv) -{ - struct wpa_driver_test_global *global = priv; - os_free(global); -} - - -static struct wpa_interface_info * -wpa_driver_test_get_interfaces(void *global_priv) -{ - /* struct wpa_driver_test_global *global = priv; */ - struct wpa_interface_info *iface; - - iface = os_zalloc(sizeof(*iface)); - if (iface == NULL) - return iface; - iface->ifname = os_strdup("sta0"); - iface->desc = os_strdup("test interface 0"); - iface->drv_name = "test"; - iface->next = os_zalloc(sizeof(*iface)); - if (iface->next) { - iface->next->ifname = os_strdup("sta1"); - iface->next->desc = os_strdup("test interface 1"); - iface->next->drv_name = "test"; - } - - return iface; -} - - -const struct wpa_driver_ops wpa_driver_test_ops = { - "test", - "wpa_supplicant test driver", - wpa_driver_test_get_bssid, - wpa_driver_test_get_ssid, - wpa_driver_test_set_wpa, - wpa_driver_test_set_key, - NULL /* init */, - wpa_driver_test_deinit, - wpa_driver_test_set_param, - NULL /* set_countermeasures */, - NULL /* set_drop_unencrypted */, - wpa_driver_test_scan, - NULL /* get_scan_results */, - wpa_driver_test_deauthenticate, - wpa_driver_test_disassociate, - wpa_driver_test_associate, - NULL /* set_auth_alg */, - NULL /* add_pmkid */, - NULL /* remove_pmkid */, - NULL /* flush_pmkid */, - wpa_driver_test_get_capa, - NULL /* poll */, - NULL /* get_ifname */, - wpa_driver_test_get_mac_addr, - wpa_driver_test_send_eapol, - NULL /* set_operstate */, - wpa_driver_test_mlme_setprotection, -#ifdef CONFIG_CLIENT_MLME - wpa_driver_test_get_hw_feature_data, - wpa_driver_test_set_channel, - wpa_driver_test_set_ssid, - wpa_driver_test_set_bssid, - wpa_driver_test_send_mlme, - wpa_driver_test_mlme_add_sta, - wpa_driver_test_mlme_remove_sta, -#else /* CONFIG_CLIENT_MLME */ - NULL /* get_hw_feature_data */, - NULL /* set_channel */, - NULL /* set_ssid */, - NULL /* set_bssid */, - NULL /* send_mlme */, - NULL /* mlme_add_sta */, - NULL /* mlme_remove_sta */, -#endif /* CONFIG_CLIENT_MLME */ - NULL /* update_ft_ies */, - NULL /* send_ft_action */, - wpa_driver_test_get_scan_results2, - wpa_driver_test_set_probe_req_ie, - NULL /* set_mode */, - NULL /* set_country */, - wpa_driver_test_global_init, - wpa_driver_test_global_deinit, - wpa_driver_test_init2, - wpa_driver_test_get_interfaces -}; diff --git a/contrib/hostapd/src/drivers/driver_wext.c b/contrib/hostapd/src/drivers/driver_wext.c deleted file mode 100644 index e771d37ded..0000000000 --- a/contrib/hostapd/src/drivers/driver_wext.c +++ /dev/null @@ -1,2375 +0,0 @@ -/* - * WPA Supplicant - driver interaction with generic Linux Wireless Extensions - * Copyright (c) 2003-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file implements a driver interface for the Linux Wireless Extensions. - * When used with WE-18 or newer, this interface can be used as-is with number - * of drivers. In addition to this, some of the common functions in this file - * can be used by other driver interface implementations that use generic WE - * ioctls, but require private ioctls for some of the functionality. - */ - -#include "includes.h" -#include -#include - -#include "wireless_copy.h" -#include "common.h" -#include "driver.h" -#include "eloop.h" -#include "priv_netlink.h" -#include "driver_wext.h" -#include "ieee802_11_defs.h" -#include "wpa_common.h" - - -static int wpa_driver_wext_flush_pmkid(void *priv); -static int wpa_driver_wext_get_range(void *priv); -static void wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv); -static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv); - - -static int wpa_driver_wext_send_oper_ifla(struct wpa_driver_wext_data *drv, - int linkmode, int operstate) -{ - struct { - struct nlmsghdr hdr; - struct ifinfomsg ifinfo; - char opts[16]; - } req; - struct rtattr *rta; - static int nl_seq; - ssize_t ret; - - os_memset(&req, 0, sizeof(req)); - - req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); - req.hdr.nlmsg_type = RTM_SETLINK; - req.hdr.nlmsg_flags = NLM_F_REQUEST; - req.hdr.nlmsg_seq = ++nl_seq; - req.hdr.nlmsg_pid = 0; - - req.ifinfo.ifi_family = AF_UNSPEC; - req.ifinfo.ifi_type = 0; - req.ifinfo.ifi_index = drv->ifindex; - req.ifinfo.ifi_flags = 0; - req.ifinfo.ifi_change = 0; - - if (linkmode != -1) { - rta = aliasing_hide_typecast( - ((char *) &req + NLMSG_ALIGN(req.hdr.nlmsg_len)), - struct rtattr); - rta->rta_type = IFLA_LINKMODE; - rta->rta_len = RTA_LENGTH(sizeof(char)); - *((char *) RTA_DATA(rta)) = linkmode; - req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) + - RTA_LENGTH(sizeof(char)); - } - if (operstate != -1) { - rta = (struct rtattr *) - ((char *) &req + NLMSG_ALIGN(req.hdr.nlmsg_len)); - rta->rta_type = IFLA_OPERSTATE; - rta->rta_len = RTA_LENGTH(sizeof(char)); - *((char *) RTA_DATA(rta)) = operstate; - req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) + - RTA_LENGTH(sizeof(char)); - } - - wpa_printf(MSG_DEBUG, "WEXT: Operstate: linkmode=%d, operstate=%d", - linkmode, operstate); - - ret = send(drv->event_sock, &req, req.hdr.nlmsg_len, 0); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "WEXT: Sending operstate IFLA failed: " - "%s (assume operstate is not supported)", - strerror(errno)); - } - - return ret < 0 ? -1 : 0; -} - - -int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv, - int idx, u32 value) -{ - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.param.flags = idx & IW_AUTH_INDEX; - iwr.u.param.value = value; - - if (ioctl(drv->ioctl_sock, SIOCSIWAUTH, &iwr) < 0) { - if (errno != EOPNOTSUPP) { - wpa_printf(MSG_DEBUG, "WEXT: SIOCSIWAUTH(param %d " - "value 0x%x) failed: %s)", - idx, value, strerror(errno)); - } - ret = errno == EOPNOTSUPP ? -2 : -1; - } - - return ret; -} - - -/** - * wpa_driver_wext_get_bssid - Get BSSID, SIOCGIWAP - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * @bssid: Buffer for BSSID - * Returns: 0 on success, -1 on failure - */ -int wpa_driver_wext_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - - if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) { - perror("ioctl[SIOCGIWAP]"); - ret = -1; - } - os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN); - - return ret; -} - - -/** - * wpa_driver_wext_set_bssid - Set BSSID, SIOCSIWAP - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * @bssid: BSSID - * Returns: 0 on success, -1 on failure - */ -int wpa_driver_wext_set_bssid(void *priv, const u8 *bssid) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.ap_addr.sa_family = ARPHRD_ETHER; - if (bssid) - os_memcpy(iwr.u.ap_addr.sa_data, bssid, ETH_ALEN); - else - os_memset(iwr.u.ap_addr.sa_data, 0, ETH_ALEN); - - if (ioctl(drv->ioctl_sock, SIOCSIWAP, &iwr) < 0) { - perror("ioctl[SIOCSIWAP]"); - ret = -1; - } - - return ret; -} - - -/** - * wpa_driver_wext_get_ssid - Get SSID, SIOCGIWESSID - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * @ssid: Buffer for the SSID; must be at least 32 bytes long - * Returns: SSID length on success, -1 on failure - */ -int wpa_driver_wext_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.essid.pointer = (caddr_t) ssid; - iwr.u.essid.length = 32; - - if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) { - perror("ioctl[SIOCGIWESSID]"); - ret = -1; - } else { - ret = iwr.u.essid.length; - if (ret > 32) - ret = 32; - /* Some drivers include nul termination in the SSID, so let's - * remove it here before further processing. WE-21 changes this - * to explicitly require the length _not_ to include nul - * termination. */ - if (ret > 0 && ssid[ret - 1] == '\0' && - drv->we_version_compiled < 21) - ret--; - } - - return ret; -} - - -/** - * wpa_driver_wext_set_ssid - Set SSID, SIOCSIWESSID - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * @ssid: SSID - * @ssid_len: Length of SSID (0..32) - * Returns: 0 on success, -1 on failure - */ -int wpa_driver_wext_set_ssid(void *priv, const u8 *ssid, size_t ssid_len) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = 0; - char buf[33]; - - if (ssid_len > 32) - return -1; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - /* flags: 1 = ESSID is active, 0 = not (promiscuous) */ - iwr.u.essid.flags = (ssid_len != 0); - os_memset(buf, 0, sizeof(buf)); - os_memcpy(buf, ssid, ssid_len); - iwr.u.essid.pointer = (caddr_t) buf; - if (drv->we_version_compiled < 21) { - /* For historic reasons, set SSID length to include one extra - * character, C string nul termination, even though SSID is - * really an octet string that should not be presented as a C - * string. Some Linux drivers decrement the length by one and - * can thus end up missing the last octet of the SSID if the - * length is not incremented here. WE-21 changes this to - * explicitly require the length _not_ to include nul - * termination. */ - if (ssid_len) - ssid_len++; - } - iwr.u.essid.length = ssid_len; - - if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) { - perror("ioctl[SIOCSIWESSID]"); - ret = -1; - } - - return ret; -} - - -/** - * wpa_driver_wext_set_freq - Set frequency/channel, SIOCSIWFREQ - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * @freq: Frequency in MHz - * Returns: 0 on success, -1 on failure - */ -int wpa_driver_wext_set_freq(void *priv, int freq) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.freq.m = freq * 100000; - iwr.u.freq.e = 1; - - if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) { - perror("ioctl[SIOCSIWFREQ]"); - ret = -1; - } - - return ret; -} - - -static void -wpa_driver_wext_event_wireless_custom(void *ctx, char *custom) -{ - union wpa_event_data data; - - wpa_printf(MSG_MSGDUMP, "WEXT: Custom wireless event: '%s'", - custom); - - os_memset(&data, 0, sizeof(data)); - /* Host AP driver */ - if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) { - data.michael_mic_failure.unicast = - os_strstr(custom, " unicast ") != NULL; - /* TODO: parse parameters(?) */ - wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); - } else if (os_strncmp(custom, "ASSOCINFO(ReqIEs=", 17) == 0) { - char *spos; - int bytes; - - spos = custom + 17; - - bytes = strspn(spos, "0123456789abcdefABCDEF"); - if (!bytes || (bytes & 1)) - return; - bytes /= 2; - - data.assoc_info.req_ies = os_malloc(bytes); - if (data.assoc_info.req_ies == NULL) - return; - - data.assoc_info.req_ies_len = bytes; - hexstr2bin(spos, data.assoc_info.req_ies, bytes); - - spos += bytes * 2; - - data.assoc_info.resp_ies = NULL; - data.assoc_info.resp_ies_len = 0; - - if (os_strncmp(spos, " RespIEs=", 9) == 0) { - spos += 9; - - bytes = strspn(spos, "0123456789abcdefABCDEF"); - if (!bytes || (bytes & 1)) - goto done; - bytes /= 2; - - data.assoc_info.resp_ies = os_malloc(bytes); - if (data.assoc_info.resp_ies == NULL) - goto done; - - data.assoc_info.resp_ies_len = bytes; - hexstr2bin(spos, data.assoc_info.resp_ies, bytes); - } - - wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data); - - done: - os_free(data.assoc_info.resp_ies); - os_free(data.assoc_info.req_ies); -#ifdef CONFIG_PEERKEY - } else if (os_strncmp(custom, "STKSTART.request=", 17) == 0) { - if (hwaddr_aton(custom + 17, data.stkstart.peer)) { - wpa_printf(MSG_DEBUG, "WEXT: unrecognized " - "STKSTART.request '%s'", custom + 17); - return; - } - wpa_supplicant_event(ctx, EVENT_STKSTART, &data); -#endif /* CONFIG_PEERKEY */ - } -} - - -static int wpa_driver_wext_event_wireless_michaelmicfailure( - void *ctx, const char *ev, size_t len) -{ - const struct iw_michaelmicfailure *mic; - union wpa_event_data data; - - if (len < sizeof(*mic)) - return -1; - - mic = (const struct iw_michaelmicfailure *) ev; - - wpa_printf(MSG_DEBUG, "Michael MIC failure wireless event: " - "flags=0x%x src_addr=" MACSTR, mic->flags, - MAC2STR(mic->src_addr.sa_data)); - - os_memset(&data, 0, sizeof(data)); - data.michael_mic_failure.unicast = !(mic->flags & IW_MICFAILURE_GROUP); - wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); - - return 0; -} - - -static int wpa_driver_wext_event_wireless_pmkidcand( - struct wpa_driver_wext_data *drv, const char *ev, size_t len) -{ - const struct iw_pmkid_cand *cand; - union wpa_event_data data; - const u8 *addr; - - if (len < sizeof(*cand)) - return -1; - - cand = (const struct iw_pmkid_cand *) ev; - addr = (const u8 *) cand->bssid.sa_data; - - wpa_printf(MSG_DEBUG, "PMKID candidate wireless event: " - "flags=0x%x index=%d bssid=" MACSTR, cand->flags, - cand->index, MAC2STR(addr)); - - os_memset(&data, 0, sizeof(data)); - os_memcpy(data.pmkid_candidate.bssid, addr, ETH_ALEN); - data.pmkid_candidate.index = cand->index; - data.pmkid_candidate.preauth = cand->flags & IW_PMKID_CAND_PREAUTH; - wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data); - - return 0; -} - - -static int wpa_driver_wext_event_wireless_assocreqie( - struct wpa_driver_wext_data *drv, const char *ev, int len) -{ - if (len < 0) - return -1; - - wpa_hexdump(MSG_DEBUG, "AssocReq IE wireless event", (const u8 *) ev, - len); - os_free(drv->assoc_req_ies); - drv->assoc_req_ies = os_malloc(len); - if (drv->assoc_req_ies == NULL) { - drv->assoc_req_ies_len = 0; - return -1; - } - os_memcpy(drv->assoc_req_ies, ev, len); - drv->assoc_req_ies_len = len; - - return 0; -} - - -static int wpa_driver_wext_event_wireless_assocrespie( - struct wpa_driver_wext_data *drv, const char *ev, int len) -{ - if (len < 0) - return -1; - - wpa_hexdump(MSG_DEBUG, "AssocResp IE wireless event", (const u8 *) ev, - len); - os_free(drv->assoc_resp_ies); - drv->assoc_resp_ies = os_malloc(len); - if (drv->assoc_resp_ies == NULL) { - drv->assoc_resp_ies_len = 0; - return -1; - } - os_memcpy(drv->assoc_resp_ies, ev, len); - drv->assoc_resp_ies_len = len; - - return 0; -} - - -static void wpa_driver_wext_event_assoc_ies(struct wpa_driver_wext_data *drv) -{ - union wpa_event_data data; - - if (drv->assoc_req_ies == NULL && drv->assoc_resp_ies == NULL) - return; - - os_memset(&data, 0, sizeof(data)); - if (drv->assoc_req_ies) { - data.assoc_info.req_ies = drv->assoc_req_ies; - drv->assoc_req_ies = NULL; - data.assoc_info.req_ies_len = drv->assoc_req_ies_len; - } - if (drv->assoc_resp_ies) { - data.assoc_info.resp_ies = drv->assoc_resp_ies; - drv->assoc_resp_ies = NULL; - data.assoc_info.resp_ies_len = drv->assoc_resp_ies_len; - } - - wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data); - - os_free(data.assoc_info.req_ies); - os_free(data.assoc_info.resp_ies); -} - - -static void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data *drv, - void *ctx, char *data, int len) -{ - struct iw_event iwe_buf, *iwe = &iwe_buf; - char *pos, *end, *custom, *buf; - - pos = data; - end = data + len; - - while (pos + IW_EV_LCP_LEN <= end) { - /* Event data may be unaligned, so make a local, aligned copy - * before processing. */ - os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); - wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d", - iwe->cmd, iwe->len); - if (iwe->len <= IW_EV_LCP_LEN) - return; - - custom = pos + IW_EV_POINT_LEN; - if (drv->we_version_compiled > 18 && - (iwe->cmd == IWEVMICHAELMICFAILURE || - iwe->cmd == IWEVCUSTOM || - iwe->cmd == IWEVASSOCREQIE || - iwe->cmd == IWEVASSOCRESPIE || - iwe->cmd == IWEVPMKIDCAND)) { - /* WE-19 removed the pointer from struct iw_point */ - char *dpos = (char *) &iwe_buf.u.data.length; - int dlen = dpos - (char *) &iwe_buf; - os_memcpy(dpos, pos + IW_EV_LCP_LEN, - sizeof(struct iw_event) - dlen); - } else { - os_memcpy(&iwe_buf, pos, sizeof(struct iw_event)); - custom += IW_EV_POINT_OFF; - } - - switch (iwe->cmd) { - case SIOCGIWAP: - wpa_printf(MSG_DEBUG, "Wireless event: new AP: " - MACSTR, - MAC2STR((u8 *) iwe->u.ap_addr.sa_data)); - if (is_zero_ether_addr( - (const u8 *) iwe->u.ap_addr.sa_data) || - os_memcmp(iwe->u.ap_addr.sa_data, - "\x44\x44\x44\x44\x44\x44", ETH_ALEN) == - 0) { - os_free(drv->assoc_req_ies); - drv->assoc_req_ies = NULL; - os_free(drv->assoc_resp_ies); - drv->assoc_resp_ies = NULL; - wpa_supplicant_event(ctx, EVENT_DISASSOC, - NULL); - - } else { - wpa_driver_wext_event_assoc_ies(drv); - wpa_supplicant_event(ctx, EVENT_ASSOC, NULL); - } - break; - case IWEVMICHAELMICFAILURE: - if (custom + iwe->u.data.length > end) { - wpa_printf(MSG_DEBUG, "WEXT: Invalid " - "IWEVMICHAELMICFAILURE length"); - return; - } - wpa_driver_wext_event_wireless_michaelmicfailure( - ctx, custom, iwe->u.data.length); - break; - case IWEVCUSTOM: - if (custom + iwe->u.data.length > end) { - wpa_printf(MSG_DEBUG, "WEXT: Invalid " - "IWEVCUSTOM length"); - return; - } - buf = os_malloc(iwe->u.data.length + 1); - if (buf == NULL) - return; - os_memcpy(buf, custom, iwe->u.data.length); - buf[iwe->u.data.length] = '\0'; - wpa_driver_wext_event_wireless_custom(ctx, buf); - os_free(buf); - break; - case SIOCGIWSCAN: - drv->scan_complete_events = 1; - eloop_cancel_timeout(wpa_driver_wext_scan_timeout, - drv, ctx); - wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL); - break; - case IWEVASSOCREQIE: - if (custom + iwe->u.data.length > end) { - wpa_printf(MSG_DEBUG, "WEXT: Invalid " - "IWEVASSOCREQIE length"); - return; - } - wpa_driver_wext_event_wireless_assocreqie( - drv, custom, iwe->u.data.length); - break; - case IWEVASSOCRESPIE: - if (custom + iwe->u.data.length > end) { - wpa_printf(MSG_DEBUG, "WEXT: Invalid " - "IWEVASSOCRESPIE length"); - return; - } - wpa_driver_wext_event_wireless_assocrespie( - drv, custom, iwe->u.data.length); - break; - case IWEVPMKIDCAND: - if (custom + iwe->u.data.length > end) { - wpa_printf(MSG_DEBUG, "WEXT: Invalid " - "IWEVPMKIDCAND length"); - return; - } - wpa_driver_wext_event_wireless_pmkidcand( - drv, custom, iwe->u.data.length); - break; - } - - pos += iwe->len; - } -} - - -static void wpa_driver_wext_event_link(struct wpa_driver_wext_data *drv, - void *ctx, char *buf, size_t len, - int del) -{ - union wpa_event_data event; - - os_memset(&event, 0, sizeof(event)); - if (len > sizeof(event.interface_status.ifname)) - len = sizeof(event.interface_status.ifname) - 1; - os_memcpy(event.interface_status.ifname, buf, len); - event.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED : - EVENT_INTERFACE_ADDED; - - wpa_printf(MSG_DEBUG, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s", - del ? "DEL" : "NEW", - event.interface_status.ifname, - del ? "removed" : "added"); - - if (os_strcmp(drv->ifname, event.interface_status.ifname) == 0) { - if (del) - drv->if_removed = 1; - else - drv->if_removed = 0; - } - - wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event); -} - - -static int wpa_driver_wext_own_ifname(struct wpa_driver_wext_data *drv, - struct nlmsghdr *h) -{ - struct ifinfomsg *ifi; - int attrlen, nlmsg_len, rta_len; - struct rtattr *attr; - - ifi = NLMSG_DATA(h); - - nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); - - attrlen = h->nlmsg_len - nlmsg_len; - if (attrlen < 0) - return 0; - - attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_IFNAME) { - if (os_strcmp(((char *) attr) + rta_len, drv->ifname) - == 0) - return 1; - else - break; - } - attr = RTA_NEXT(attr, attrlen); - } - - return 0; -} - - -static int wpa_driver_wext_own_ifindex(struct wpa_driver_wext_data *drv, - int ifindex, struct nlmsghdr *h) -{ - if (drv->ifindex == ifindex || drv->ifindex2 == ifindex) - return 1; - - if (drv->if_removed && wpa_driver_wext_own_ifname(drv, h)) { - drv->ifindex = if_nametoindex(drv->ifname); - wpa_printf(MSG_DEBUG, "WEXT: Update ifindex for a removed " - "interface"); - wpa_driver_wext_finish_drv_init(drv); - return 1; - } - - return 0; -} - - -static void wpa_driver_wext_event_rtm_newlink(struct wpa_driver_wext_data *drv, - void *ctx, struct nlmsghdr *h, - size_t len) -{ - struct ifinfomsg *ifi; - int attrlen, nlmsg_len, rta_len; - struct rtattr * attr; - - if (len < sizeof(*ifi)) - return; - - ifi = NLMSG_DATA(h); - - if (!wpa_driver_wext_own_ifindex(drv, ifi->ifi_index, h)) { - wpa_printf(MSG_DEBUG, "Ignore event for foreign ifindex %d", - ifi->ifi_index); - return; - } - - wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x " - "(%s%s%s%s)", - drv->operstate, ifi->ifi_flags, - (ifi->ifi_flags & IFF_UP) ? "[UP]" : "", - (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "", - (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "", - (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : ""); - /* - * Some drivers send the association event before the operup event--in - * this case, lifting operstate in wpa_driver_wext_set_operstate() - * fails. This will hit us when wpa_supplicant does not need to do - * IEEE 802.1X authentication - */ - if (drv->operstate == 1 && - (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP && - !(ifi->ifi_flags & IFF_RUNNING)) - wpa_driver_wext_send_oper_ifla(drv, -1, IF_OPER_UP); - - nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); - - attrlen = h->nlmsg_len - nlmsg_len; - if (attrlen < 0) - return; - - attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_WIRELESS) { - wpa_driver_wext_event_wireless( - drv, ctx, ((char *) attr) + rta_len, - attr->rta_len - rta_len); - } else if (attr->rta_type == IFLA_IFNAME) { - wpa_driver_wext_event_link(drv, ctx, - ((char *) attr) + rta_len, - attr->rta_len - rta_len, 0); - } - attr = RTA_NEXT(attr, attrlen); - } -} - - -static void wpa_driver_wext_event_rtm_dellink(struct wpa_driver_wext_data *drv, - void *ctx, struct nlmsghdr *h, - size_t len) -{ - struct ifinfomsg *ifi; - int attrlen, nlmsg_len, rta_len; - struct rtattr * attr; - - if (len < sizeof(*ifi)) - return; - - ifi = NLMSG_DATA(h); - - nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); - - attrlen = h->nlmsg_len - nlmsg_len; - if (attrlen < 0) - return; - - attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_IFNAME) { - wpa_driver_wext_event_link(drv, ctx, - ((char *) attr) + rta_len, - attr->rta_len - rta_len, 1); - } - attr = RTA_NEXT(attr, attrlen); - } -} - - -static void wpa_driver_wext_event_receive(int sock, void *eloop_ctx, - void *sock_ctx) -{ - char buf[8192]; - int left; - struct sockaddr_nl from; - socklen_t fromlen; - struct nlmsghdr *h; - int max_events = 10; - -try_again: - fromlen = sizeof(from); - left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, - (struct sockaddr *) &from, &fromlen); - if (left < 0) { - if (errno != EINTR && errno != EAGAIN) - perror("recvfrom(netlink)"); - return; - } - - h = (struct nlmsghdr *) buf; - while (left >= (int) sizeof(*h)) { - int len, plen; - - len = h->nlmsg_len; - plen = len - sizeof(*h); - if (len > left || plen < 0) { - wpa_printf(MSG_DEBUG, "Malformed netlink message: " - "len=%d left=%d plen=%d", - len, left, plen); - break; - } - - switch (h->nlmsg_type) { - case RTM_NEWLINK: - wpa_driver_wext_event_rtm_newlink(eloop_ctx, sock_ctx, - h, plen); - break; - case RTM_DELLINK: - wpa_driver_wext_event_rtm_dellink(eloop_ctx, sock_ctx, - h, plen); - break; - } - - len = NLMSG_ALIGN(len); - left -= len; - h = (struct nlmsghdr *) ((char *) h + len); - } - - if (left > 0) { - wpa_printf(MSG_DEBUG, "%d extra bytes in the end of netlink " - "message", left); - } - - if (--max_events > 0) { - /* - * Try to receive all events in one eloop call in order to - * limit race condition on cases where AssocInfo event, Assoc - * event, and EAPOL frames are received more or less at the - * same time. We want to process the event messages first - * before starting EAPOL processing. - */ - goto try_again; - } -} - - -static int wpa_driver_wext_get_ifflags_ifname(struct wpa_driver_wext_data *drv, - const char *ifname, int *flags) -{ - struct ifreq ifr; - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); - if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { - perror("ioctl[SIOCGIFFLAGS]"); - return -1; - } - *flags = ifr.ifr_flags & 0xffff; - return 0; -} - - -/** - * wpa_driver_wext_get_ifflags - Get interface flags (SIOCGIFFLAGS) - * @drv: driver_wext private data - * @flags: Pointer to returned flags value - * Returns: 0 on success, -1 on failure - */ -int wpa_driver_wext_get_ifflags(struct wpa_driver_wext_data *drv, int *flags) -{ - return wpa_driver_wext_get_ifflags_ifname(drv, drv->ifname, flags); -} - - -static int wpa_driver_wext_set_ifflags_ifname(struct wpa_driver_wext_data *drv, - const char *ifname, int flags) -{ - struct ifreq ifr; - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); - ifr.ifr_flags = flags & 0xffff; - if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { - perror("SIOCSIFFLAGS"); - return -1; - } - return 0; -} - - -/** - * wpa_driver_wext_set_ifflags - Set interface flags (SIOCSIFFLAGS) - * @drv: driver_wext private data - * @flags: New value for flags - * Returns: 0 on success, -1 on failure - */ -int wpa_driver_wext_set_ifflags(struct wpa_driver_wext_data *drv, int flags) -{ - return wpa_driver_wext_set_ifflags_ifname(drv, drv->ifname, flags); -} - - -/** - * wpa_driver_wext_init - Initialize WE driver interface - * @ctx: context to be used when calling wpa_supplicant functions, - * e.g., wpa_supplicant_event() - * @ifname: interface name, e.g., wlan0 - * Returns: Pointer to private data, %NULL on failure - */ -void * wpa_driver_wext_init(void *ctx, const char *ifname) -{ - int s; - struct sockaddr_nl local; - struct wpa_driver_wext_data *drv; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->ctx = ctx; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - - drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->ioctl_sock < 0) { - perror("socket(PF_INET,SOCK_DGRAM)"); - os_free(drv); - return NULL; - } - - s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (s < 0) { - perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)"); - close(drv->ioctl_sock); - os_free(drv); - return NULL; - } - - os_memset(&local, 0, sizeof(local)); - local.nl_family = AF_NETLINK; - local.nl_groups = RTMGRP_LINK; - if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) { - perror("bind(netlink)"); - close(s); - close(drv->ioctl_sock); - os_free(drv); - return NULL; - } - - eloop_register_read_sock(s, wpa_driver_wext_event_receive, drv, ctx); - drv->event_sock = s; - - drv->mlme_sock = -1; - - wpa_driver_wext_finish_drv_init(drv); - - return drv; -} - - -static void wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv) -{ - int flags; - - if (wpa_driver_wext_get_ifflags(drv, &flags) != 0) - printf("Could not get interface '%s' flags\n", drv->ifname); - else if (!(flags & IFF_UP)) { - if (wpa_driver_wext_set_ifflags(drv, flags | IFF_UP) != 0) { - printf("Could not set interface '%s' UP\n", - drv->ifname); - } else { - /* - * Wait some time to allow driver to initialize before - * starting configuring the driver. This seems to be - * needed at least some drivers that load firmware etc. - * when the interface is set up. - */ - wpa_printf(MSG_DEBUG, "Interface %s set UP - waiting " - "a second for the driver to complete " - "initialization", drv->ifname); - sleep(1); - } - } - - /* - * Make sure that the driver does not have any obsolete PMKID entries. - */ - wpa_driver_wext_flush_pmkid(drv); - - if (wpa_driver_wext_set_mode(drv, 0) < 0) { - printf("Could not configure driver to use managed mode\n"); - } - - wpa_driver_wext_get_range(drv); - - /* - * Unlock the driver's BSSID and force to a random SSID to clear any - * previous association the driver might have when the supplicant - * starts up. - */ - wpa_driver_wext_disconnect(drv); - - drv->ifindex = if_nametoindex(drv->ifname); - - if (os_strncmp(drv->ifname, "wlan", 4) == 0) { - /* - * Host AP driver may use both wlan# and wifi# interface in - * wireless events. Since some of the versions included WE-18 - * support, let's add the alternative ifindex also from - * driver_wext.c for the time being. This may be removed at - * some point once it is believed that old versions of the - * driver are not in use anymore. - */ - char ifname2[IFNAMSIZ + 1]; - os_strlcpy(ifname2, drv->ifname, sizeof(ifname2)); - os_memcpy(ifname2, "wifi", 4); - wpa_driver_wext_alternative_ifindex(drv, ifname2); - } - - wpa_driver_wext_send_oper_ifla(drv, 1, IF_OPER_DORMANT); -} - - -/** - * wpa_driver_wext_deinit - Deinitialize WE driver interface - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * - * Shut down driver interface and processing of driver events. Free - * private data buffer if one was allocated in wpa_driver_wext_init(). - */ -void wpa_driver_wext_deinit(void *priv) -{ - struct wpa_driver_wext_data *drv = priv; - int flags; - - eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx); - - /* - * Clear possibly configured driver parameters in order to make it - * easier to use the driver after wpa_supplicant has been terminated. - */ - wpa_driver_wext_disconnect(drv); - - wpa_driver_wext_send_oper_ifla(priv, 0, IF_OPER_UP); - - eloop_unregister_read_sock(drv->event_sock); - if (drv->mlme_sock >= 0) - eloop_unregister_read_sock(drv->mlme_sock); - - if (wpa_driver_wext_get_ifflags(drv, &flags) == 0) - (void) wpa_driver_wext_set_ifflags(drv, flags & ~IFF_UP); - - close(drv->event_sock); - close(drv->ioctl_sock); - if (drv->mlme_sock >= 0) - close(drv->mlme_sock); - os_free(drv->assoc_req_ies); - os_free(drv->assoc_resp_ies); - os_free(drv); -} - - -/** - * wpa_driver_wext_scan_timeout - Scan timeout to report scan completion - * @eloop_ctx: Unused - * @timeout_ctx: ctx argument given to wpa_driver_wext_init() - * - * This function can be used as registered timeout when starting a scan to - * generate a scan completed event if the driver does not report this. - */ -void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx) -{ - wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); - wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); -} - - -/** - * wpa_driver_wext_scan - Request the driver to initiate scan - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * @ssid: Specific SSID to scan for (ProbeReq) or %NULL to scan for - * all SSIDs (either active scan with broadcast SSID or passive - * scan - * @ssid_len: Length of the SSID - * Returns: 0 on success, -1 on failure - */ -int wpa_driver_wext_scan(void *priv, const u8 *ssid, size_t ssid_len) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = 0, timeout; - struct iw_scan_req req; - - if (ssid_len > IW_ESSID_MAX_SIZE) { - wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)", - __FUNCTION__, (unsigned long) ssid_len); - return -1; - } - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - - if (ssid && ssid_len) { - os_memset(&req, 0, sizeof(req)); - req.essid_len = ssid_len; - req.bssid.sa_family = ARPHRD_ETHER; - os_memset(req.bssid.sa_data, 0xff, ETH_ALEN); - os_memcpy(req.essid, ssid, ssid_len); - iwr.u.data.pointer = (caddr_t) &req; - iwr.u.data.length = sizeof(req); - iwr.u.data.flags = IW_SCAN_THIS_ESSID; - } - - if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) { - perror("ioctl[SIOCSIWSCAN]"); - ret = -1; - } - - /* Not all drivers generate "scan completed" wireless event, so try to - * read results after a timeout. */ - timeout = 5; - if (drv->scan_complete_events) { - /* - * The driver seems to deliver SIOCGIWSCAN events to notify - * when scan is complete, so use longer timeout to avoid race - * conditions with scanning and following association request. - */ - timeout = 30; - } - wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d " - "seconds", ret, timeout); - eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx); - eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, drv, - drv->ctx); - - return ret; -} - - -static u8 * wpa_driver_wext_giwscan(struct wpa_driver_wext_data *drv, - size_t *len) -{ - struct iwreq iwr; - u8 *res_buf; - size_t res_buf_len; - - res_buf_len = IW_SCAN_MAX_DATA; - for (;;) { - res_buf = os_malloc(res_buf_len); - if (res_buf == NULL) - return NULL; - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = res_buf; - iwr.u.data.length = res_buf_len; - - if (ioctl(drv->ioctl_sock, SIOCGIWSCAN, &iwr) == 0) - break; - - if (errno == E2BIG && res_buf_len < 65535) { - os_free(res_buf); - res_buf = NULL; - res_buf_len *= 2; - if (res_buf_len > 65535) - res_buf_len = 65535; /* 16-bit length field */ - wpa_printf(MSG_DEBUG, "Scan results did not fit - " - "trying larger buffer (%lu bytes)", - (unsigned long) res_buf_len); - } else { - perror("ioctl[SIOCGIWSCAN]"); - os_free(res_buf); - return NULL; - } - } - - if (iwr.u.data.length > res_buf_len) { - os_free(res_buf); - return NULL; - } - *len = iwr.u.data.length; - - return res_buf; -} - - -/* - * Data structure for collecting WEXT scan results. This is needed to allow - * the various methods of reporting IEs to be combined into a single IE buffer. - */ -struct wext_scan_data { - struct wpa_scan_res res; - u8 *ie; - size_t ie_len; - u8 ssid[32]; - size_t ssid_len; - int maxrate; -}; - - -static void wext_get_scan_mode(struct iw_event *iwe, - struct wext_scan_data *res) -{ - if (iwe->u.mode == IW_MODE_ADHOC) - res->res.caps |= IEEE80211_CAP_IBSS; - else if (iwe->u.mode == IW_MODE_MASTER || iwe->u.mode == IW_MODE_INFRA) - res->res.caps |= IEEE80211_CAP_ESS; -} - - -static void wext_get_scan_ssid(struct iw_event *iwe, - struct wext_scan_data *res, char *custom, - char *end) -{ - int ssid_len = iwe->u.essid.length; - if (custom + ssid_len > end) - return; - if (iwe->u.essid.flags && - ssid_len > 0 && - ssid_len <= IW_ESSID_MAX_SIZE) { - os_memcpy(res->ssid, custom, ssid_len); - res->ssid_len = ssid_len; - } -} - - -static void wext_get_scan_freq(struct iw_event *iwe, - struct wext_scan_data *res) -{ - int divi = 1000000, i; - - if (iwe->u.freq.e == 0) { - /* - * Some drivers do not report frequency, but a channel. - * Try to map this to frequency by assuming they are using - * IEEE 802.11b/g. But don't overwrite a previously parsed - * frequency if the driver sends both frequency and channel, - * since the driver may be sending an A-band channel that we - * don't handle here. - */ - - if (res->res.freq) - return; - - if (iwe->u.freq.m >= 1 && iwe->u.freq.m <= 13) { - res->res.freq = 2407 + 5 * iwe->u.freq.m; - return; - } else if (iwe->u.freq.m == 14) { - res->res.freq = 2484; - return; - } - } - - if (iwe->u.freq.e > 6) { - wpa_printf(MSG_DEBUG, "Invalid freq in scan results (BSSID=" - MACSTR " m=%d e=%d)", - MAC2STR(res->res.bssid), iwe->u.freq.m, - iwe->u.freq.e); - return; - } - - for (i = 0; i < iwe->u.freq.e; i++) - divi /= 10; - res->res.freq = iwe->u.freq.m / divi; -} - - -static void wext_get_scan_qual(struct iw_event *iwe, - struct wext_scan_data *res) -{ - res->res.qual = iwe->u.qual.qual; - res->res.noise = iwe->u.qual.noise; - res->res.level = iwe->u.qual.level; -} - - -static void wext_get_scan_encode(struct iw_event *iwe, - struct wext_scan_data *res) -{ - if (!(iwe->u.data.flags & IW_ENCODE_DISABLED)) - res->res.caps |= IEEE80211_CAP_PRIVACY; -} - - -static void wext_get_scan_rate(struct iw_event *iwe, - struct wext_scan_data *res, char *pos, - char *end) -{ - int maxrate; - char *custom = pos + IW_EV_LCP_LEN; - struct iw_param p; - size_t clen; - - clen = iwe->len; - if (custom + clen > end) - return; - maxrate = 0; - while (((ssize_t) clen) >= (ssize_t) sizeof(struct iw_param)) { - /* Note: may be misaligned, make a local, aligned copy */ - os_memcpy(&p, custom, sizeof(struct iw_param)); - if (p.value > maxrate) - maxrate = p.value; - clen -= sizeof(struct iw_param); - custom += sizeof(struct iw_param); - } - - /* Convert the maxrate from WE-style (b/s units) to - * 802.11 rates (500000 b/s units). - */ - res->maxrate = maxrate / 500000; -} - - -static void wext_get_scan_iwevgenie(struct iw_event *iwe, - struct wext_scan_data *res, char *custom, - char *end) -{ - char *genie, *gpos, *gend; - u8 *tmp; - - if (iwe->u.data.length == 0) - return; - - gpos = genie = custom; - gend = genie + iwe->u.data.length; - if (gend > end) { - wpa_printf(MSG_INFO, "IWEVGENIE overflow"); - return; - } - - tmp = os_realloc(res->ie, res->ie_len + gend - gpos); - if (tmp == NULL) - return; - os_memcpy(tmp + res->ie_len, gpos, gend - gpos); - res->ie = tmp; - res->ie_len += gend - gpos; -} - - -static void wext_get_scan_custom(struct iw_event *iwe, - struct wext_scan_data *res, char *custom, - char *end) -{ - size_t clen; - u8 *tmp; - - clen = iwe->u.data.length; - if (custom + clen > end) - return; - - if (clen > 7 && os_strncmp(custom, "wpa_ie=", 7) == 0) { - char *spos; - int bytes; - spos = custom + 7; - bytes = custom + clen - spos; - if (bytes & 1 || bytes == 0) - return; - bytes /= 2; - tmp = os_realloc(res->ie, res->ie_len + bytes); - if (tmp == NULL) - return; - hexstr2bin(spos, tmp + res->ie_len, bytes); - res->ie = tmp; - res->ie_len += bytes; - } else if (clen > 7 && os_strncmp(custom, "rsn_ie=", 7) == 0) { - char *spos; - int bytes; - spos = custom + 7; - bytes = custom + clen - spos; - if (bytes & 1 || bytes == 0) - return; - bytes /= 2; - tmp = os_realloc(res->ie, res->ie_len + bytes); - if (tmp == NULL) - return; - hexstr2bin(spos, tmp + res->ie_len, bytes); - res->ie = tmp; - res->ie_len += bytes; - } else if (clen > 4 && os_strncmp(custom, "tsf=", 4) == 0) { - char *spos; - int bytes; - u8 bin[8]; - spos = custom + 4; - bytes = custom + clen - spos; - if (bytes != 16) { - wpa_printf(MSG_INFO, "Invalid TSF length (%d)", bytes); - return; - } - bytes /= 2; - hexstr2bin(spos, bin, bytes); - res->res.tsf += WPA_GET_BE64(bin); - } -} - - -static int wext_19_iw_point(struct wpa_driver_wext_data *drv, u16 cmd) -{ - return drv->we_version_compiled > 18 && - (cmd == SIOCGIWESSID || cmd == SIOCGIWENCODE || - cmd == IWEVGENIE || cmd == IWEVCUSTOM); -} - - -static void wpa_driver_wext_add_scan_entry(struct wpa_scan_results *res, - struct wext_scan_data *data) -{ - struct wpa_scan_res **tmp; - struct wpa_scan_res *r; - size_t extra_len; - u8 *pos, *end, *ssid_ie = NULL, *rate_ie = NULL; - - /* Figure out whether we need to fake any IEs */ - pos = data->ie; - end = pos + data->ie_len; - while (pos && pos + 1 < end) { - if (pos + 2 + pos[1] > end) - break; - if (pos[0] == WLAN_EID_SSID) - ssid_ie = pos; - else if (pos[0] == WLAN_EID_SUPP_RATES) - rate_ie = pos; - else if (pos[0] == WLAN_EID_EXT_SUPP_RATES) - rate_ie = pos; - pos += 2 + pos[1]; - } - - extra_len = 0; - if (ssid_ie == NULL) - extra_len += 2 + data->ssid_len; - if (rate_ie == NULL && data->maxrate) - extra_len += 3; - - r = os_zalloc(sizeof(*r) + extra_len + data->ie_len); - if (r == NULL) - return; - os_memcpy(r, &data->res, sizeof(*r)); - r->ie_len = extra_len + data->ie_len; - pos = (u8 *) (r + 1); - if (ssid_ie == NULL) { - /* - * Generate a fake SSID IE since the driver did not report - * a full IE list. - */ - *pos++ = WLAN_EID_SSID; - *pos++ = data->ssid_len; - os_memcpy(pos, data->ssid, data->ssid_len); - pos += data->ssid_len; - } - if (rate_ie == NULL && data->maxrate) { - /* - * Generate a fake Supported Rates IE since the driver did not - * report a full IE list. - */ - *pos++ = WLAN_EID_SUPP_RATES; - *pos++ = 1; - *pos++ = data->maxrate; - } - if (data->ie) - os_memcpy(pos, data->ie, data->ie_len); - - tmp = os_realloc(res->res, - (res->num + 1) * sizeof(struct wpa_scan_res *)); - if (tmp == NULL) { - os_free(r); - return; - } - tmp[res->num++] = r; - res->res = tmp; -} - - -/** - * wpa_driver_wext_get_scan_results - Fetch the latest scan results - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * Returns: Scan results on success, -1 on failure - */ -struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv) -{ - struct wpa_driver_wext_data *drv = priv; - size_t ap_num = 0, len; - int first; - u8 *res_buf; - struct iw_event iwe_buf, *iwe = &iwe_buf; - char *pos, *end, *custom; - struct wpa_scan_results *res; - struct wext_scan_data data; - - res_buf = wpa_driver_wext_giwscan(drv, &len); - if (res_buf == NULL) - return NULL; - - ap_num = 0; - first = 1; - - res = os_zalloc(sizeof(*res)); - if (res == NULL) { - os_free(res_buf); - return NULL; - } - - pos = (char *) res_buf; - end = (char *) res_buf + len; - os_memset(&data, 0, sizeof(data)); - - while (pos + IW_EV_LCP_LEN <= end) { - /* Event data may be unaligned, so make a local, aligned copy - * before processing. */ - os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); - if (iwe->len <= IW_EV_LCP_LEN) - break; - - custom = pos + IW_EV_POINT_LEN; - if (wext_19_iw_point(drv, iwe->cmd)) { - /* WE-19 removed the pointer from struct iw_point */ - char *dpos = (char *) &iwe_buf.u.data.length; - int dlen = dpos - (char *) &iwe_buf; - os_memcpy(dpos, pos + IW_EV_LCP_LEN, - sizeof(struct iw_event) - dlen); - } else { - os_memcpy(&iwe_buf, pos, sizeof(struct iw_event)); - custom += IW_EV_POINT_OFF; - } - - switch (iwe->cmd) { - case SIOCGIWAP: - if (!first) - wpa_driver_wext_add_scan_entry(res, &data); - first = 0; - os_free(data.ie); - os_memset(&data, 0, sizeof(data)); - os_memcpy(data.res.bssid, - iwe->u.ap_addr.sa_data, ETH_ALEN); - break; - case SIOCGIWMODE: - wext_get_scan_mode(iwe, &data); - break; - case SIOCGIWESSID: - wext_get_scan_ssid(iwe, &data, custom, end); - break; - case SIOCGIWFREQ: - wext_get_scan_freq(iwe, &data); - break; - case IWEVQUAL: - wext_get_scan_qual(iwe, &data); - break; - case SIOCGIWENCODE: - wext_get_scan_encode(iwe, &data); - break; - case SIOCGIWRATE: - wext_get_scan_rate(iwe, &data, pos, end); - break; - case IWEVGENIE: - wext_get_scan_iwevgenie(iwe, &data, custom, end); - break; - case IWEVCUSTOM: - wext_get_scan_custom(iwe, &data, custom, end); - break; - } - - pos += iwe->len; - } - os_free(res_buf); - res_buf = NULL; - if (!first) - wpa_driver_wext_add_scan_entry(res, &data); - os_free(data.ie); - - wpa_printf(MSG_DEBUG, "Received %lu bytes of scan results (%lu BSSes)", - (unsigned long) len, (unsigned long) res->num); - - return res; -} - - -static int wpa_driver_wext_get_range(void *priv) -{ - struct wpa_driver_wext_data *drv = priv; - struct iw_range *range; - struct iwreq iwr; - int minlen; - size_t buflen; - - /* - * Use larger buffer than struct iw_range in order to allow the - * structure to grow in the future. - */ - buflen = sizeof(struct iw_range) + 500; - range = os_zalloc(buflen); - if (range == NULL) - return -1; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) range; - iwr.u.data.length = buflen; - - minlen = ((char *) &range->enc_capa) - (char *) range + - sizeof(range->enc_capa); - - if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) { - perror("ioctl[SIOCGIWRANGE]"); - os_free(range); - return -1; - } else if (iwr.u.data.length >= minlen && - range->we_version_compiled >= 18) { - wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d " - "WE(source)=%d enc_capa=0x%x", - range->we_version_compiled, - range->we_version_source, - range->enc_capa); - drv->has_capability = 1; - drv->we_version_compiled = range->we_version_compiled; - if (range->enc_capa & IW_ENC_CAPA_WPA) { - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; - } - if (range->enc_capa & IW_ENC_CAPA_WPA2) { - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; - } - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | - WPA_DRIVER_CAPA_ENC_WEP104; - if (range->enc_capa & IW_ENC_CAPA_CIPHER_TKIP) - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; - if (range->enc_capa & IW_ENC_CAPA_CIPHER_CCMP) - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; - if (range->enc_capa & IW_ENC_CAPA_4WAY_HANDSHAKE) - drv->capa.flags |= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE; - drv->capa.auth = WPA_DRIVER_AUTH_OPEN | - WPA_DRIVER_AUTH_SHARED | - WPA_DRIVER_AUTH_LEAP; - - wpa_printf(MSG_DEBUG, " capabilities: key_mgmt 0x%x enc 0x%x " - "flags 0x%x", - drv->capa.key_mgmt, drv->capa.enc, drv->capa.flags); - } else { - wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: too old (short) data - " - "assuming WPA is not supported"); - } - - os_free(range); - return 0; -} - - -static int wpa_driver_wext_set_wpa(void *priv, int enabled) -{ - struct wpa_driver_wext_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - return wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, - enabled); -} - - -static int wpa_driver_wext_set_psk(struct wpa_driver_wext_data *drv, - const u8 *psk) -{ - struct iw_encode_ext *ext; - struct iwreq iwr; - int ret; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (!(drv->capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE)) - return 0; - - if (!psk) - return 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - - ext = os_zalloc(sizeof(*ext) + PMK_LEN); - if (ext == NULL) - return -1; - - iwr.u.encoding.pointer = (caddr_t) ext; - iwr.u.encoding.length = sizeof(*ext) + PMK_LEN; - ext->key_len = PMK_LEN; - os_memcpy(&ext->key, psk, ext->key_len); - ext->alg = IW_ENCODE_ALG_PMK; - - ret = ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr); - if (ret < 0) - perror("ioctl[SIOCSIWENCODEEXT] PMK"); - os_free(ext); - - return ret; -} - - -static int wpa_driver_wext_set_key_ext(void *priv, wpa_alg alg, - const u8 *addr, int key_idx, - int set_tx, const u8 *seq, - size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = 0; - struct iw_encode_ext *ext; - - if (seq_len > IW_ENCODE_SEQ_MAX_SIZE) { - wpa_printf(MSG_DEBUG, "%s: Invalid seq_len %lu", - __FUNCTION__, (unsigned long) seq_len); - return -1; - } - - ext = os_zalloc(sizeof(*ext) + key_len); - if (ext == NULL) - return -1; - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.encoding.flags = key_idx + 1; - iwr.u.encoding.flags |= IW_ENCODE_TEMP; - if (alg == WPA_ALG_NONE) - iwr.u.encoding.flags |= IW_ENCODE_DISABLED; - iwr.u.encoding.pointer = (caddr_t) ext; - iwr.u.encoding.length = sizeof(*ext) + key_len; - - if (addr == NULL || - os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) - ext->ext_flags |= IW_ENCODE_EXT_GROUP_KEY; - if (set_tx) - ext->ext_flags |= IW_ENCODE_EXT_SET_TX_KEY; - - ext->addr.sa_family = ARPHRD_ETHER; - if (addr) - os_memcpy(ext->addr.sa_data, addr, ETH_ALEN); - else - os_memset(ext->addr.sa_data, 0xff, ETH_ALEN); - if (key && key_len) { - os_memcpy(ext + 1, key, key_len); - ext->key_len = key_len; - } - switch (alg) { - case WPA_ALG_NONE: - ext->alg = IW_ENCODE_ALG_NONE; - break; - case WPA_ALG_WEP: - ext->alg = IW_ENCODE_ALG_WEP; - break; - case WPA_ALG_TKIP: - ext->alg = IW_ENCODE_ALG_TKIP; - break; - case WPA_ALG_CCMP: - ext->alg = IW_ENCODE_ALG_CCMP; - break; - case WPA_ALG_PMK: - ext->alg = IW_ENCODE_ALG_PMK; - break; -#ifdef CONFIG_IEEE80211W - case WPA_ALG_IGTK: - ext->alg = IW_ENCODE_ALG_AES_CMAC; - break; -#endif /* CONFIG_IEEE80211W */ - default: - wpa_printf(MSG_DEBUG, "%s: Unknown algorithm %d", - __FUNCTION__, alg); - os_free(ext); - return -1; - } - - if (seq && seq_len) { - ext->ext_flags |= IW_ENCODE_EXT_RX_SEQ_VALID; - os_memcpy(ext->rx_seq, seq, seq_len); - } - - if (ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr) < 0) { - ret = errno == EOPNOTSUPP ? -2 : -1; - if (errno == ENODEV) { - /* - * ndiswrapper seems to be returning incorrect error - * code.. */ - ret = -2; - } - - perror("ioctl[SIOCSIWENCODEEXT]"); - } - - os_free(ext); - return ret; -} - - -/** - * wpa_driver_wext_set_key - Configure encryption key - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * @priv: Private driver interface data - * @alg: Encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP, - * %WPA_ALG_TKIP, %WPA_ALG_CCMP); %WPA_ALG_NONE clears the key. - * @addr: Address of the peer STA or ff:ff:ff:ff:ff:ff for - * broadcast/default keys - * @key_idx: key index (0..3), usually 0 for unicast keys - * @set_tx: Configure this key as the default Tx key (only used when - * driver does not support separate unicast/individual key - * @seq: Sequence number/packet number, seq_len octets, the next - * packet number to be used for in replay protection; configured - * for Rx keys (in most cases, this is only used with broadcast - * keys and set to zero for unicast keys) - * @seq_len: Length of the seq, depends on the algorithm: - * TKIP: 6 octets, CCMP: 6 octets - * @key: Key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key, - * 8-byte Rx Mic Key - * @key_len: Length of the key buffer in octets (WEP: 5 or 13, - * TKIP: 32, CCMP: 16) - * Returns: 0 on success, -1 on failure - * - * This function uses SIOCSIWENCODEEXT by default, but tries to use - * SIOCSIWENCODE if the extended ioctl fails when configuring a WEP key. - */ -int wpa_driver_wext_set_key(void *priv, wpa_alg alg, - const u8 *addr, int key_idx, - int set_tx, const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - wpa_printf(MSG_DEBUG, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu " - "key_len=%lu", - __FUNCTION__, alg, key_idx, set_tx, - (unsigned long) seq_len, (unsigned long) key_len); - - ret = wpa_driver_wext_set_key_ext(drv, alg, addr, key_idx, set_tx, - seq, seq_len, key, key_len); - if (ret == 0) - return 0; - - if (ret == -2 && - (alg == WPA_ALG_NONE || alg == WPA_ALG_WEP)) { - wpa_printf(MSG_DEBUG, "Driver did not support " - "SIOCSIWENCODEEXT, trying SIOCSIWENCODE"); - ret = 0; - } else { - wpa_printf(MSG_DEBUG, "Driver did not support " - "SIOCSIWENCODEEXT"); - return ret; - } - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.encoding.flags = key_idx + 1; - iwr.u.encoding.flags |= IW_ENCODE_TEMP; - if (alg == WPA_ALG_NONE) - iwr.u.encoding.flags |= IW_ENCODE_DISABLED; - iwr.u.encoding.pointer = (caddr_t) key; - iwr.u.encoding.length = key_len; - - if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { - perror("ioctl[SIOCSIWENCODE]"); - ret = -1; - } - - if (set_tx && alg != WPA_ALG_NONE) { - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.encoding.flags = key_idx + 1; - iwr.u.encoding.flags |= IW_ENCODE_TEMP; - iwr.u.encoding.pointer = (caddr_t) NULL; - iwr.u.encoding.length = 0; - if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { - perror("ioctl[SIOCSIWENCODE] (set_tx)"); - ret = -1; - } - } - - return ret; -} - - -static int wpa_driver_wext_set_countermeasures(void *priv, - int enabled) -{ - struct wpa_driver_wext_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - return wpa_driver_wext_set_auth_param(drv, - IW_AUTH_TKIP_COUNTERMEASURES, - enabled); -} - - -static int wpa_driver_wext_set_drop_unencrypted(void *priv, - int enabled) -{ - struct wpa_driver_wext_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - drv->use_crypt = enabled; - return wpa_driver_wext_set_auth_param(drv, IW_AUTH_DROP_UNENCRYPTED, - enabled); -} - - -static int wpa_driver_wext_mlme(struct wpa_driver_wext_data *drv, - const u8 *addr, int cmd, int reason_code) -{ - struct iwreq iwr; - struct iw_mlme mlme; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - os_memset(&mlme, 0, sizeof(mlme)); - mlme.cmd = cmd; - mlme.reason_code = reason_code; - mlme.addr.sa_family = ARPHRD_ETHER; - os_memcpy(mlme.addr.sa_data, addr, ETH_ALEN); - iwr.u.data.pointer = (caddr_t) &mlme; - iwr.u.data.length = sizeof(mlme); - - if (ioctl(drv->ioctl_sock, SIOCSIWMLME, &iwr) < 0) { - perror("ioctl[SIOCSIWMLME]"); - ret = -1; - } - - return ret; -} - - -static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv) -{ - struct iwreq iwr; - const u8 null_bssid[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; - u8 ssid[32]; - int i; - - /* - * Only force-disconnect when the card is in infrastructure mode, - * otherwise the driver might interpret the cleared BSSID and random - * SSID as an attempt to create a new ad-hoc network. - */ - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) { - perror("ioctl[SIOCGIWMODE]"); - iwr.u.mode = IW_MODE_INFRA; - } - - if (iwr.u.mode == IW_MODE_INFRA) { - /* - * Clear the BSSID selection and set a random SSID to make sure - * the driver will not be trying to associate with something - * even if it does not understand SIOCSIWMLME commands (or - * tries to associate automatically after deauth/disassoc). - */ - wpa_driver_wext_set_bssid(drv, null_bssid); - - for (i = 0; i < 32; i++) - ssid[i] = rand() & 0xFF; - wpa_driver_wext_set_ssid(drv, ssid, 32); - } -} - - -static int wpa_driver_wext_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_wext_data *drv = priv; - int ret; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - ret = wpa_driver_wext_mlme(drv, addr, IW_MLME_DEAUTH, reason_code); - wpa_driver_wext_disconnect(drv); - return ret; -} - - -static int wpa_driver_wext_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_wext_data *drv = priv; - int ret; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - ret = wpa_driver_wext_mlme(drv, addr, IW_MLME_DISASSOC, reason_code); - wpa_driver_wext_disconnect(drv); - return ret; -} - - -static int wpa_driver_wext_set_gen_ie(void *priv, const u8 *ie, - size_t ie_len) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) ie; - iwr.u.data.length = ie_len; - - if (ioctl(drv->ioctl_sock, SIOCSIWGENIE, &iwr) < 0) { - perror("ioctl[SIOCSIWGENIE]"); - ret = -1; - } - - return ret; -} - - -int wpa_driver_wext_cipher2wext(int cipher) -{ - switch (cipher) { - case CIPHER_NONE: - return IW_AUTH_CIPHER_NONE; - case CIPHER_WEP40: - return IW_AUTH_CIPHER_WEP40; - case CIPHER_TKIP: - return IW_AUTH_CIPHER_TKIP; - case CIPHER_CCMP: - return IW_AUTH_CIPHER_CCMP; - case CIPHER_WEP104: - return IW_AUTH_CIPHER_WEP104; - default: - return 0; - } -} - - -int wpa_driver_wext_keymgmt2wext(int keymgmt) -{ - switch (keymgmt) { - case KEY_MGMT_802_1X: - case KEY_MGMT_802_1X_NO_WPA: - return IW_AUTH_KEY_MGMT_802_1X; - case KEY_MGMT_PSK: - return IW_AUTH_KEY_MGMT_PSK; - default: - return 0; - } -} - - -static int -wpa_driver_wext_auth_alg_fallback(struct wpa_driver_wext_data *drv, - struct wpa_driver_associate_params *params) -{ - struct iwreq iwr; - int ret = 0; - - wpa_printf(MSG_DEBUG, "WEXT: Driver did not support " - "SIOCSIWAUTH for AUTH_ALG, trying SIOCSIWENCODE"); - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - /* Just changing mode, not actual keys */ - iwr.u.encoding.flags = 0; - iwr.u.encoding.pointer = (caddr_t) NULL; - iwr.u.encoding.length = 0; - - /* - * Note: IW_ENCODE_{OPEN,RESTRICTED} can be interpreted to mean two - * different things. Here they are used to indicate Open System vs. - * Shared Key authentication algorithm. However, some drivers may use - * them to select between open/restricted WEP encrypted (open = allow - * both unencrypted and encrypted frames; restricted = only allow - * encrypted frames). - */ - - if (!drv->use_crypt) { - iwr.u.encoding.flags |= IW_ENCODE_DISABLED; - } else { - if (params->auth_alg & AUTH_ALG_OPEN_SYSTEM) - iwr.u.encoding.flags |= IW_ENCODE_OPEN; - if (params->auth_alg & AUTH_ALG_SHARED_KEY) - iwr.u.encoding.flags |= IW_ENCODE_RESTRICTED; - } - - if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { - perror("ioctl[SIOCSIWENCODE]"); - ret = -1; - } - - return ret; -} - - -int wpa_driver_wext_associate(void *priv, - struct wpa_driver_associate_params *params) -{ - struct wpa_driver_wext_data *drv = priv; - int ret = 0; - int allow_unencrypted_eapol; - int value; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - /* - * If the driver did not support SIOCSIWAUTH, fallback to - * SIOCSIWENCODE here. - */ - if (drv->auth_alg_fallback && - wpa_driver_wext_auth_alg_fallback(drv, params) < 0) - ret = -1; - - if (!params->bssid && - wpa_driver_wext_set_bssid(drv, NULL) < 0) - ret = -1; - - /* TODO: should consider getting wpa version and cipher/key_mgmt suites - * from configuration, not from here, where only the selected suite is - * available */ - if (wpa_driver_wext_set_gen_ie(drv, params->wpa_ie, params->wpa_ie_len) - < 0) - ret = -1; - if (params->wpa_ie == NULL || params->wpa_ie_len == 0) - value = IW_AUTH_WPA_VERSION_DISABLED; - else if (params->wpa_ie[0] == WLAN_EID_RSN) - value = IW_AUTH_WPA_VERSION_WPA2; - else - value = IW_AUTH_WPA_VERSION_WPA; - if (wpa_driver_wext_set_auth_param(drv, - IW_AUTH_WPA_VERSION, value) < 0) - ret = -1; - value = wpa_driver_wext_cipher2wext(params->pairwise_suite); - if (wpa_driver_wext_set_auth_param(drv, - IW_AUTH_CIPHER_PAIRWISE, value) < 0) - ret = -1; - value = wpa_driver_wext_cipher2wext(params->group_suite); - if (wpa_driver_wext_set_auth_param(drv, - IW_AUTH_CIPHER_GROUP, value) < 0) - ret = -1; - value = wpa_driver_wext_keymgmt2wext(params->key_mgmt_suite); - if (wpa_driver_wext_set_auth_param(drv, - IW_AUTH_KEY_MGMT, value) < 0) - ret = -1; - value = params->key_mgmt_suite != KEY_MGMT_NONE || - params->pairwise_suite != CIPHER_NONE || - params->group_suite != CIPHER_NONE || - params->wpa_ie_len; - if (wpa_driver_wext_set_auth_param(drv, - IW_AUTH_PRIVACY_INVOKED, value) < 0) - ret = -1; - - /* Allow unencrypted EAPOL messages even if pairwise keys are set when - * not using WPA. IEEE 802.1X specifies that these frames are not - * encrypted, but WPA encrypts them when pairwise keys are in use. */ - if (params->key_mgmt_suite == KEY_MGMT_802_1X || - params->key_mgmt_suite == KEY_MGMT_PSK) - allow_unencrypted_eapol = 0; - else - allow_unencrypted_eapol = 1; - - if (wpa_driver_wext_set_psk(drv, params->psk) < 0) - ret = -1; - if (wpa_driver_wext_set_auth_param(drv, - IW_AUTH_RX_UNENCRYPTED_EAPOL, - allow_unencrypted_eapol) < 0) - ret = -1; -#ifdef CONFIG_IEEE80211W - switch (params->mgmt_frame_protection) { - case NO_MGMT_FRAME_PROTECTION: - value = IW_AUTH_MFP_DISABLED; - break; - case MGMT_FRAME_PROTECTION_OPTIONAL: - value = IW_AUTH_MFP_OPTIONAL; - break; - case MGMT_FRAME_PROTECTION_REQUIRED: - value = IW_AUTH_MFP_REQUIRED; - break; - }; - if (wpa_driver_wext_set_auth_param(drv, IW_AUTH_MFP, value) < 0) - ret = -1; -#endif /* CONFIG_IEEE80211W */ - if (params->freq && wpa_driver_wext_set_freq(drv, params->freq) < 0) - ret = -1; - if (wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0) - ret = -1; - if (params->bssid && - wpa_driver_wext_set_bssid(drv, params->bssid) < 0) - ret = -1; - - return ret; -} - - -static int wpa_driver_wext_set_auth_alg(void *priv, int auth_alg) -{ - struct wpa_driver_wext_data *drv = priv; - int algs = 0, res; - - if (auth_alg & AUTH_ALG_OPEN_SYSTEM) - algs |= IW_AUTH_ALG_OPEN_SYSTEM; - if (auth_alg & AUTH_ALG_SHARED_KEY) - algs |= IW_AUTH_ALG_SHARED_KEY; - if (auth_alg & AUTH_ALG_LEAP) - algs |= IW_AUTH_ALG_LEAP; - if (algs == 0) { - /* at least one algorithm should be set */ - algs = IW_AUTH_ALG_OPEN_SYSTEM; - } - - res = wpa_driver_wext_set_auth_param(drv, IW_AUTH_80211_AUTH_ALG, - algs); - drv->auth_alg_fallback = res == -2; - return res; -} - - -/** - * wpa_driver_wext_set_mode - Set wireless mode (infra/adhoc), SIOCSIWMODE - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * @mode: 0 = infra/BSS (associate with an AP), 1 = adhoc/IBSS - * Returns: 0 on success, -1 on failure - */ -int wpa_driver_wext_set_mode(void *priv, int mode) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = -1, flags; - unsigned int new_mode = mode ? IW_MODE_ADHOC : IW_MODE_INFRA; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.mode = new_mode; - if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) == 0) { - ret = 0; - goto done; - } - - if (errno != EBUSY) { - perror("ioctl[SIOCSIWMODE]"); - goto done; - } - - /* mac80211 doesn't allow mode changes while the device is up, so if - * the device isn't in the mode we're about to change to, take device - * down, try to set the mode again, and bring it back up. - */ - if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) { - perror("ioctl[SIOCGIWMODE]"); - goto done; - } - - if (iwr.u.mode == new_mode) { - ret = 0; - goto done; - } - - if (wpa_driver_wext_get_ifflags(drv, &flags) == 0) { - (void) wpa_driver_wext_set_ifflags(drv, flags & ~IFF_UP); - - /* Try to set the mode again while the interface is down */ - iwr.u.mode = new_mode; - if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) - perror("ioctl[SIOCSIWMODE]"); - else - ret = 0; - - /* Ignore return value of get_ifflags to ensure that the device - * is always up like it was before this function was called. - */ - (void) wpa_driver_wext_get_ifflags(drv, &flags); - (void) wpa_driver_wext_set_ifflags(drv, flags | IFF_UP); - } - -done: - return ret; -} - - -static int wpa_driver_wext_pmksa(struct wpa_driver_wext_data *drv, - u32 cmd, const u8 *bssid, const u8 *pmkid) -{ - struct iwreq iwr; - struct iw_pmksa pmksa; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - os_memset(&pmksa, 0, sizeof(pmksa)); - pmksa.cmd = cmd; - pmksa.bssid.sa_family = ARPHRD_ETHER; - if (bssid) - os_memcpy(pmksa.bssid.sa_data, bssid, ETH_ALEN); - if (pmkid) - os_memcpy(pmksa.pmkid, pmkid, IW_PMKID_LEN); - iwr.u.data.pointer = (caddr_t) &pmksa; - iwr.u.data.length = sizeof(pmksa); - - if (ioctl(drv->ioctl_sock, SIOCSIWPMKSA, &iwr) < 0) { - if (errno != EOPNOTSUPP) - perror("ioctl[SIOCSIWPMKSA]"); - ret = -1; - } - - return ret; -} - - -static int wpa_driver_wext_add_pmkid(void *priv, const u8 *bssid, - const u8 *pmkid) -{ - struct wpa_driver_wext_data *drv = priv; - return wpa_driver_wext_pmksa(drv, IW_PMKSA_ADD, bssid, pmkid); -} - - -static int wpa_driver_wext_remove_pmkid(void *priv, const u8 *bssid, - const u8 *pmkid) -{ - struct wpa_driver_wext_data *drv = priv; - return wpa_driver_wext_pmksa(drv, IW_PMKSA_REMOVE, bssid, pmkid); -} - - -static int wpa_driver_wext_flush_pmkid(void *priv) -{ - struct wpa_driver_wext_data *drv = priv; - return wpa_driver_wext_pmksa(drv, IW_PMKSA_FLUSH, NULL, NULL); -} - - -int wpa_driver_wext_get_capa(void *priv, struct wpa_driver_capa *capa) -{ - struct wpa_driver_wext_data *drv = priv; - if (!drv->has_capability) - return -1; - os_memcpy(capa, &drv->capa, sizeof(*capa)); - return 0; -} - - -int wpa_driver_wext_alternative_ifindex(struct wpa_driver_wext_data *drv, - const char *ifname) -{ - if (ifname == NULL) { - drv->ifindex2 = -1; - return 0; - } - - drv->ifindex2 = if_nametoindex(ifname); - if (drv->ifindex2 <= 0) - return -1; - - wpa_printf(MSG_DEBUG, "Added alternative ifindex %d (%s) for " - "wireless events", drv->ifindex2, ifname); - - return 0; -} - - -int wpa_driver_wext_set_operstate(void *priv, int state) -{ - struct wpa_driver_wext_data *drv = priv; - - wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)", - __func__, drv->operstate, state, state ? "UP" : "DORMANT"); - drv->operstate = state; - return wpa_driver_wext_send_oper_ifla( - drv, -1, state ? IF_OPER_UP : IF_OPER_DORMANT); -} - - -int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv) -{ - return drv->we_version_compiled; -} - - -const struct wpa_driver_ops wpa_driver_wext_ops = { - .name = "wext", - .desc = "Linux wireless extensions (generic)", - .get_bssid = wpa_driver_wext_get_bssid, - .get_ssid = wpa_driver_wext_get_ssid, - .set_wpa = wpa_driver_wext_set_wpa, - .set_key = wpa_driver_wext_set_key, - .set_countermeasures = wpa_driver_wext_set_countermeasures, - .set_drop_unencrypted = wpa_driver_wext_set_drop_unencrypted, - .scan = wpa_driver_wext_scan, - .get_scan_results2 = wpa_driver_wext_get_scan_results, - .deauthenticate = wpa_driver_wext_deauthenticate, - .disassociate = wpa_driver_wext_disassociate, - .set_mode = wpa_driver_wext_set_mode, - .associate = wpa_driver_wext_associate, - .set_auth_alg = wpa_driver_wext_set_auth_alg, - .init = wpa_driver_wext_init, - .deinit = wpa_driver_wext_deinit, - .add_pmkid = wpa_driver_wext_add_pmkid, - .remove_pmkid = wpa_driver_wext_remove_pmkid, - .flush_pmkid = wpa_driver_wext_flush_pmkid, - .get_capa = wpa_driver_wext_get_capa, - .set_operstate = wpa_driver_wext_set_operstate, -}; diff --git a/contrib/hostapd/src/drivers/driver_wext.h b/contrib/hostapd/src/drivers/driver_wext.h deleted file mode 100644 index b89c2cb2fd..0000000000 --- a/contrib/hostapd/src/drivers/driver_wext.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * WPA Supplicant - driver_wext exported functions - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef DRIVER_WEXT_H -#define DRIVER_WEXT_H - -#include - -struct wpa_driver_wext_data { - void *ctx; - int event_sock; - int ioctl_sock; - int mlme_sock; - char ifname[IFNAMSIZ + 1]; - int ifindex; - int ifindex2; - int if_removed; - u8 *assoc_req_ies; - size_t assoc_req_ies_len; - u8 *assoc_resp_ies; - size_t assoc_resp_ies_len; - struct wpa_driver_capa capa; - int has_capability; - int we_version_compiled; - - /* for set_auth_alg fallback */ - int use_crypt; - int auth_alg_fallback; - - int operstate; - - char mlmedev[IFNAMSIZ + 1]; - - int scan_complete_events; -}; - -int wpa_driver_wext_get_ifflags(struct wpa_driver_wext_data *drv, int *flags); -int wpa_driver_wext_set_ifflags(struct wpa_driver_wext_data *drv, int flags); -int wpa_driver_wext_get_bssid(void *priv, u8 *bssid); -int wpa_driver_wext_set_bssid(void *priv, const u8 *bssid); -int wpa_driver_wext_get_ssid(void *priv, u8 *ssid); -int wpa_driver_wext_set_ssid(void *priv, const u8 *ssid, size_t ssid_len); -int wpa_driver_wext_set_freq(void *priv, int freq); -int wpa_driver_wext_set_mode(void *priv, int mode); -int wpa_driver_wext_set_key(void *priv, wpa_alg alg, - const u8 *addr, int key_idx, - int set_tx, const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len); -int wpa_driver_wext_scan(void *priv, const u8 *ssid, size_t ssid_len); -struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv); - -void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx); - -int wpa_driver_wext_alternative_ifindex(struct wpa_driver_wext_data *drv, - const char *ifname); - -void * wpa_driver_wext_init(void *ctx, const char *ifname); -void wpa_driver_wext_deinit(void *priv); - -int wpa_driver_wext_set_operstate(void *priv, int state); -int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv); - -int wpa_driver_wext_associate(void *priv, - struct wpa_driver_associate_params *params); -int wpa_driver_wext_get_capa(void *priv, struct wpa_driver_capa *capa); -int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv, - int idx, u32 value); -int wpa_driver_wext_cipher2wext(int cipher); -int wpa_driver_wext_keymgmt2wext(int keymgmt); - -#endif /* DRIVER_WEXT_H */ diff --git a/contrib/hostapd/src/drivers/driver_wired.c b/contrib/hostapd/src/drivers/driver_wired.c deleted file mode 100644 index 098991a1a4..0000000000 --- a/contrib/hostapd/src/drivers/driver_wired.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * WPA Supplicant - wired Ethernet driver interface - * Copyright (c) 2005-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include -#ifdef __linux__ -#include -#endif /* __linux__ */ -#if defined(__FreeBSD__) || defined(__DragonFly__) -#include -#endif /* defined(__FreeBSD__) || defined(__DragonFly__) */ - -#include "common.h" -#include "driver.h" - - -static const u8 pae_group_addr[ETH_ALEN] = -{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; - - -struct wpa_driver_wired_data { - void *ctx; - int pf_sock; - char ifname[IFNAMSIZ + 1]; - int membership, multi, iff_allmulti, iff_up; -}; - - -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_ifflags(const char *ifname, int *flags) -{ - struct ifreq ifr; - int s; - - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s < 0) { - perror("socket"); - return -1; - } - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); - if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { - perror("ioctl[SIOCGIFFLAGS]"); - 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) { - perror("socket"); - 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) { - perror("ioctl[SIOCSIFFLAGS]"); - close(s); - return -1; - } - close(s); - return 0; -} - - -static int wpa_driver_wired_multi(const char *ifname, const u8 *addr, int add) -{ - struct ifreq ifr; - int s; - - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s < 0) { - perror("socket"); - 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__) - { - 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__) */ -#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) { - perror("ioctl[SIOC{ADD/DEL}MULTI]"); - close(s); - return -1; - } - close(s); - return 0; -} - - -static int wpa_driver_wired_membership(struct wpa_driver_wired_data *drv, - const u8 *addr, int add) -{ -#ifdef __linux__ - struct packet_mreq mreq; - - if (drv->pf_sock == -1) - return -1; - - os_memset(&mreq, 0, sizeof(mreq)); - mreq.mr_ifindex = if_nametoindex(drv->ifname); - mreq.mr_type = PACKET_MR_MULTICAST; - mreq.mr_alen = ETH_ALEN; - os_memcpy(mreq.mr_address, addr, ETH_ALEN); - - if (setsockopt(drv->pf_sock, SOL_PACKET, - add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP, - &mreq, sizeof(mreq)) < 0) { - perror("setsockopt"); - return -1; - } - return 0; -#else /* __linux__ */ - return -1; -#endif /* __linux__ */ -} - - -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) - perror("socket(PF_PACKET)"); -#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 (wpa_driver_wired_membership(drv, 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__); - os_free(drv); - return NULL; - } else { - wpa_printf(MSG_DEBUG, "%s: Enabled allmulti mode", - __func__); - drv->iff_allmulti = 1; - } - - return drv; -} - - -static void wpa_driver_wired_deinit(void *priv) -{ - struct wpa_driver_wired_data *drv = priv; - int flags; - - if (drv->membership && - wpa_driver_wired_membership(drv, 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); - - os_free(drv); -} - - -const struct wpa_driver_ops wpa_driver_wired_ops = { - .name = "wired", - .desc = "wpa_supplicant wired Ethernet driver", - .get_ssid = wpa_driver_wired_get_ssid, - .get_bssid = wpa_driver_wired_get_bssid, - .init = wpa_driver_wired_init, - .deinit = wpa_driver_wired_deinit, -}; diff --git a/contrib/hostapd/src/drivers/drivers.c b/contrib/hostapd/src/drivers/drivers.c deleted file mode 100644 index d278797d7d..0000000000 --- a/contrib/hostapd/src/drivers/drivers.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * WPA Supplicant / driver interface list - * Copyright (c) 2004-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - - -#ifdef CONFIG_DRIVER_WEXT -extern struct wpa_driver_ops wpa_driver_wext_ops; /* driver_wext.c */ -#endif /* CONFIG_DRIVER_WEXT */ -#ifdef CONFIG_DRIVER_NL80211 -extern struct wpa_driver_ops wpa_driver_nl80211_ops; /* driver_nl80211.c */ -#endif /* CONFIG_DRIVER_NL80211 */ -#ifdef CONFIG_DRIVER_HOSTAP -extern struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */ -#endif /* CONFIG_DRIVER_HOSTAP */ -#ifdef CONFIG_DRIVER_PRISM54 -extern struct wpa_driver_ops wpa_driver_prism54_ops; /* driver_prism54.c */ -#endif /* CONFIG_DRIVER_PRISM54 */ -#ifdef CONFIG_DRIVER_HERMES -extern struct wpa_driver_ops wpa_driver_hermes_ops; /* driver_hermes.c */ -#endif /* CONFIG_DRIVER_HERMES */ -#ifdef CONFIG_DRIVER_MADWIFI -extern struct wpa_driver_ops wpa_driver_madwifi_ops; /* driver_madwifi.c */ -#endif /* CONFIG_DRIVER_MADWIFI */ -#ifdef CONFIG_DRIVER_ATMEL -extern struct wpa_driver_ops wpa_driver_atmel_ops; /* driver_atmel.c */ -#endif /* CONFIG_DRIVER_ATMEL */ -#ifdef CONFIG_DRIVER_NDISWRAPPER -/* driver_ndiswrapper.c */ -extern struct wpa_driver_ops wpa_driver_ndiswrapper_ops; -#endif /* CONFIG_DRIVER_NDISWRAPPER */ -#ifdef CONFIG_DRIVER_BROADCOM -extern struct wpa_driver_ops wpa_driver_broadcom_ops; /* driver_broadcom.c */ -#endif /* CONFIG_DRIVER_BROADCOM */ -#ifdef CONFIG_DRIVER_IPW -extern struct wpa_driver_ops wpa_driver_ipw_ops; /* driver_ipw.c */ -#endif /* CONFIG_DRIVER_IPW */ -#ifdef CONFIG_DRIVER_BSD -extern struct wpa_driver_ops wpa_driver_bsd_ops; /* driver_bsd.c */ -#endif /* CONFIG_DRIVER_BSD */ -#ifdef CONFIG_DRIVER_NDIS -extern struct wpa_driver_ops wpa_driver_ndis_ops; /* driver_ndis.c */ -#endif /* CONFIG_DRIVER_NDIS */ -#ifdef CONFIG_DRIVER_WIRED -extern struct wpa_driver_ops wpa_driver_wired_ops; /* driver_wired.c */ -#endif /* CONFIG_DRIVER_WIRED */ -#ifdef CONFIG_DRIVER_TEST -extern struct wpa_driver_ops wpa_driver_test_ops; /* driver_test.c */ -#endif /* CONFIG_DRIVER_TEST */ -#ifdef CONFIG_DRIVER_RALINK -extern struct wpa_driver_ops wpa_driver_ralink_ops; /* driver_ralink.c */ -#endif /* CONFIG_DRIVER_RALINK */ -#ifdef CONFIG_DRIVER_OSX -extern struct wpa_driver_ops wpa_driver_osx_ops; /* driver_osx.m */ -#endif /* CONFIG_DRIVER_OSX */ -#ifdef CONFIG_DRIVER_PS3 -extern struct wpa_driver_ops wpa_driver_ps3_ops; /* driver_ps3.c */ -#endif /* CONFIG_DRIVER_PS3 */ -#ifdef CONFIG_DRIVER_IPHONE -extern struct wpa_driver_ops wpa_driver_iphone_ops; /* driver_iphone.m */ -#endif /* CONFIG_DRIVER_IPHONE */ -#ifdef CONFIG_DRIVER_ROBOSWITCH -/* driver_roboswitch.c */ -extern struct wpa_driver_ops wpa_driver_roboswitch_ops; -#endif /* CONFIG_DRIVER_ROBOSWITCH */ - - -struct wpa_driver_ops *wpa_supplicant_drivers[] = -{ -#ifdef CONFIG_DRIVER_WEXT - &wpa_driver_wext_ops, -#endif /* CONFIG_DRIVER_WEXT */ -#ifdef CONFIG_DRIVER_NL80211 - &wpa_driver_nl80211_ops, -#endif /* CONFIG_DRIVER_NL80211 */ -#ifdef CONFIG_DRIVER_HOSTAP - &wpa_driver_hostap_ops, -#endif /* CONFIG_DRIVER_HOSTAP */ -#ifdef CONFIG_DRIVER_PRISM54 - &wpa_driver_prism54_ops, -#endif /* CONFIG_DRIVER_PRISM54 */ -#ifdef CONFIG_DRIVER_HERMES - &wpa_driver_hermes_ops, -#endif /* CONFIG_DRIVER_HERMES */ -#ifdef CONFIG_DRIVER_MADWIFI - &wpa_driver_madwifi_ops, -#endif /* CONFIG_DRIVER_MADWIFI */ -#ifdef CONFIG_DRIVER_ATMEL - &wpa_driver_atmel_ops, -#endif /* CONFIG_DRIVER_ATMEL */ -#ifdef CONFIG_DRIVER_NDISWRAPPER - &wpa_driver_ndiswrapper_ops, -#endif /* CONFIG_DRIVER_NDISWRAPPER */ -#ifdef CONFIG_DRIVER_BROADCOM - &wpa_driver_broadcom_ops, -#endif /* CONFIG_DRIVER_BROADCOM */ -#ifdef CONFIG_DRIVER_IPW - &wpa_driver_ipw_ops, -#endif /* CONFIG_DRIVER_IPW */ -#ifdef CONFIG_DRIVER_BSD - &wpa_driver_bsd_ops, -#endif /* CONFIG_DRIVER_BSD */ -#ifdef CONFIG_DRIVER_NDIS - &wpa_driver_ndis_ops, -#endif /* CONFIG_DRIVER_NDIS */ -#ifdef CONFIG_DRIVER_WIRED - &wpa_driver_wired_ops, -#endif /* CONFIG_DRIVER_WIRED */ -#ifdef CONFIG_DRIVER_TEST - &wpa_driver_test_ops, -#endif /* CONFIG_DRIVER_TEST */ -#ifdef CONFIG_DRIVER_RALINK - &wpa_driver_ralink_ops, -#endif /* CONFIG_DRIVER_RALINK */ -#ifdef CONFIG_DRIVER_OSX - &wpa_driver_osx_ops, -#endif /* CONFIG_DRIVER_OSX */ -#ifdef CONFIG_DRIVER_PS3 - &wpa_driver_ps3_ops, -#endif /* CONFIG_DRIVER_PS3 */ -#ifdef CONFIG_DRIVER_IPHONE - &wpa_driver_iphone_ops, -#endif /* CONFIG_DRIVER_IPHONE */ -#ifdef CONFIG_DRIVER_ROBOSWITCH - &wpa_driver_roboswitch_ops, -#endif /* CONFIG_DRIVER_ROBOSWITCH */ - NULL -}; diff --git a/contrib/hostapd/src/drivers/ndis_events.c b/contrib/hostapd/src/drivers/ndis_events.c deleted file mode 100644 index f6eaa7c9f7..0000000000 --- a/contrib/hostapd/src/drivers/ndis_events.c +++ /dev/null @@ -1,808 +0,0 @@ -/* - * ndis_events - Receive NdisMIndicateStatus() events using WMI - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#define _WIN32_WINNT 0x0400 - -#include "includes.h" - -#ifndef COBJMACROS -#define COBJMACROS -#endif /* COBJMACROS */ -#include - -#include "common.h" - - -static int wmi_refcnt = 0; -static int wmi_first = 1; - -struct ndis_events_data { - IWbemObjectSink sink; - IWbemObjectSinkVtbl sink_vtbl; - - IWbemServices *pSvc; - IWbemLocator *pLoc; - - HANDLE read_pipe, write_pipe, event_avail; - UINT ref; - int terminating; - char *ifname; /* {GUID..} */ - WCHAR *adapter_desc; -}; - -#define BstrAlloc(x) (x) ? SysAllocString(x) : NULL -#define BstrFree(x) if (x) SysFreeString(x) - -/* WBEM / WMI wrapper functions, to perform in-place conversion of WCHARs to - * BSTRs */ -HRESULT STDMETHODCALLTYPE call_IWbemServices_ExecQuery( - IWbemServices *pSvc, LPCWSTR strQueryLanguage, LPCWSTR strQuery, - long lFlags, IWbemContext *pCtx, IEnumWbemClassObject **ppEnum) -{ - BSTR bsQueryLanguage, bsQuery; - HRESULT hr; - - bsQueryLanguage = BstrAlloc(strQueryLanguage); - bsQuery = BstrAlloc(strQuery); - - hr = IWbemServices_ExecQuery(pSvc, bsQueryLanguage, bsQuery, lFlags, - pCtx, ppEnum); - - BstrFree(bsQueryLanguage); - BstrFree(bsQuery); - - return hr; -} - - -HRESULT STDMETHODCALLTYPE call_IWbemServices_ExecNotificationQueryAsync( - IWbemServices *pSvc, LPCWSTR strQueryLanguage, LPCWSTR strQuery, - long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler) -{ - BSTR bsQueryLanguage, bsQuery; - HRESULT hr; - - bsQueryLanguage = BstrAlloc(strQueryLanguage); - bsQuery = BstrAlloc(strQuery); - - hr = IWbemServices_ExecNotificationQueryAsync(pSvc, bsQueryLanguage, - bsQuery, lFlags, pCtx, - pResponseHandler); - - BstrFree(bsQueryLanguage); - BstrFree(bsQuery); - - return hr; -} - - -HRESULT STDMETHODCALLTYPE call_IWbemLocator_ConnectServer( - IWbemLocator *pLoc, LPCWSTR strNetworkResource, LPCWSTR strUser, - LPCWSTR strPassword, LPCWSTR strLocale, long lSecurityFlags, - LPCWSTR strAuthority, IWbemContext *pCtx, IWbemServices **ppNamespace) -{ - BSTR bsNetworkResource, bsUser, bsPassword, bsLocale, bsAuthority; - HRESULT hr; - - bsNetworkResource = BstrAlloc(strNetworkResource); - bsUser = BstrAlloc(strUser); - bsPassword = BstrAlloc(strPassword); - bsLocale = BstrAlloc(strLocale); - bsAuthority = BstrAlloc(strAuthority); - - hr = IWbemLocator_ConnectServer(pLoc, bsNetworkResource, bsUser, - bsPassword, bsLocale, lSecurityFlags, - bsAuthority, pCtx, ppNamespace); - - BstrFree(bsNetworkResource); - BstrFree(bsUser); - BstrFree(bsPassword); - BstrFree(bsLocale); - BstrFree(bsAuthority); - - return hr; -} - - -enum event_types { EVENT_CONNECT, EVENT_DISCONNECT, EVENT_MEDIA_SPECIFIC, - EVENT_ADAPTER_ARRIVAL, EVENT_ADAPTER_REMOVAL }; - -static int ndis_events_get_adapter(struct ndis_events_data *events, - const char *ifname, const char *desc); - - -static int ndis_events_constructor(struct ndis_events_data *events) -{ - events->ref = 1; - - if (!CreatePipe(&events->read_pipe, &events->write_pipe, NULL, 512)) { - wpa_printf(MSG_ERROR, "CreatePipe() failed: %d", - (int) GetLastError()); - return -1; - } - events->event_avail = CreateEvent(NULL, TRUE, FALSE, NULL); - if (events->event_avail == NULL) { - wpa_printf(MSG_ERROR, "CreateEvent() failed: %d", - (int) GetLastError()); - CloseHandle(events->read_pipe); - CloseHandle(events->write_pipe); - return -1; - } - - return 0; -} - - -static void ndis_events_destructor(struct ndis_events_data *events) -{ - CloseHandle(events->read_pipe); - CloseHandle(events->write_pipe); - CloseHandle(events->event_avail); - IWbemServices_Release(events->pSvc); - IWbemLocator_Release(events->pLoc); - if (--wmi_refcnt == 0) - CoUninitialize(); -} - - -static HRESULT STDMETHODCALLTYPE -ndis_events_query_interface(IWbemObjectSink *this, REFIID riid, void **obj) -{ - *obj = NULL; - - if (IsEqualIID(riid, &IID_IUnknown) || - IsEqualIID(riid, &IID_IWbemObjectSink)) { - *obj = this; - IWbemObjectSink_AddRef(this); - return NOERROR; - } - - return E_NOINTERFACE; -} - - -static ULONG STDMETHODCALLTYPE ndis_events_add_ref(IWbemObjectSink *this) -{ - struct ndis_events_data *events = (struct ndis_events_data *) this; - return ++events->ref; -} - - -static ULONG STDMETHODCALLTYPE ndis_events_release(IWbemObjectSink *this) -{ - struct ndis_events_data *events = (struct ndis_events_data *) this; - - if (--events->ref != 0) - return events->ref; - - ndis_events_destructor(events); - wpa_printf(MSG_DEBUG, "ndis_events: terminated"); - os_free(events->adapter_desc); - os_free(events->ifname); - os_free(events); - return 0; -} - - -static int ndis_events_send_event(struct ndis_events_data *events, - enum event_types type, - char *data, size_t data_len) -{ - char buf[512], *pos, *end; - int _type; - DWORD written; - - end = buf + sizeof(buf); - _type = (int) type; - os_memcpy(buf, &_type, sizeof(_type)); - pos = buf + sizeof(_type); - - if (data) { - if (2 + data_len > (size_t) (end - pos)) { - wpa_printf(MSG_DEBUG, "Not enough room for send_event " - "data (%d)", data_len); - return -1; - } - *pos++ = data_len >> 8; - *pos++ = data_len & 0xff; - os_memcpy(pos, data, data_len); - pos += data_len; - } - - if (WriteFile(events->write_pipe, buf, pos - buf, &written, NULL)) { - SetEvent(events->event_avail); - return 0; - } - wpa_printf(MSG_INFO, "WriteFile() failed: %d", (int) GetLastError()); - return -1; -} - - -static void ndis_events_media_connect(struct ndis_events_data *events) -{ - wpa_printf(MSG_DEBUG, "MSNdis_StatusMediaConnect"); - ndis_events_send_event(events, EVENT_CONNECT, NULL, 0); -} - - -static void ndis_events_media_disconnect(struct ndis_events_data *events) -{ - wpa_printf(MSG_DEBUG, "MSNdis_StatusMediaDisconnect"); - ndis_events_send_event(events, EVENT_DISCONNECT, NULL, 0); -} - - -static void ndis_events_media_specific(struct ndis_events_data *events, - IWbemClassObject *pObj) -{ - VARIANT vt; - HRESULT hr; - LONG lower, upper, k; - UCHAR ch; - char *data, *pos; - size_t data_len; - - wpa_printf(MSG_DEBUG, "MSNdis_StatusMediaSpecificIndication"); - - /* This is the StatusBuffer from NdisMIndicateStatus() call */ - hr = IWbemClassObject_Get(pObj, L"NdisStatusMediaSpecificIndication", - 0, &vt, NULL, NULL); - if (FAILED(hr)) { - wpa_printf(MSG_DEBUG, "Could not get " - "NdisStatusMediaSpecificIndication from " - "the object?!"); - return; - } - - SafeArrayGetLBound(V_ARRAY(&vt), 1, &lower); - SafeArrayGetUBound(V_ARRAY(&vt), 1, &upper); - data_len = upper - lower + 1; - data = os_malloc(data_len); - if (data == NULL) { - wpa_printf(MSG_DEBUG, "Failed to allocate buffer for event " - "data"); - VariantClear(&vt); - return; - } - - pos = data; - for (k = lower; k <= upper; k++) { - SafeArrayGetElement(V_ARRAY(&vt), &k, &ch); - *pos++ = ch; - } - wpa_hexdump(MSG_DEBUG, "MediaSpecificEvent", (u8 *) data, data_len); - - VariantClear(&vt); - - ndis_events_send_event(events, EVENT_MEDIA_SPECIFIC, data, data_len); - - os_free(data); -} - - -static void ndis_events_adapter_arrival(struct ndis_events_data *events) -{ - wpa_printf(MSG_DEBUG, "MSNdis_NotifyAdapterArrival"); - ndis_events_send_event(events, EVENT_ADAPTER_ARRIVAL, NULL, 0); -} - - -static void ndis_events_adapter_removal(struct ndis_events_data *events) -{ - wpa_printf(MSG_DEBUG, "MSNdis_NotifyAdapterRemoval"); - ndis_events_send_event(events, EVENT_ADAPTER_REMOVAL, NULL, 0); -} - - -static HRESULT STDMETHODCALLTYPE -ndis_events_indicate(IWbemObjectSink *this, long lObjectCount, - IWbemClassObject __RPC_FAR *__RPC_FAR *ppObjArray) -{ - struct ndis_events_data *events = (struct ndis_events_data *) this; - long i; - - if (events->terminating) { - wpa_printf(MSG_DEBUG, "ndis_events_indicate: Ignore " - "indication - terminating"); - return WBEM_NO_ERROR; - } - /* wpa_printf(MSG_DEBUG, "Notification received - %d object(s)", - lObjectCount); */ - - for (i = 0; i < lObjectCount; i++) { - IWbemClassObject *pObj = ppObjArray[i]; - HRESULT hr; - VARIANT vtClass, vt; - - hr = IWbemClassObject_Get(pObj, L"__CLASS", 0, &vtClass, NULL, - NULL); - if (FAILED(hr)) { - wpa_printf(MSG_DEBUG, "Failed to get __CLASS from " - "event."); - break; - } - /* wpa_printf(MSG_DEBUG, "CLASS: '%S'", vtClass.bstrVal); */ - - hr = IWbemClassObject_Get(pObj, L"InstanceName", 0, &vt, NULL, - NULL); - if (FAILED(hr)) { - wpa_printf(MSG_DEBUG, "Failed to get InstanceName " - "from event."); - VariantClear(&vtClass); - break; - } - - if (wcscmp(vtClass.bstrVal, - L"MSNdis_NotifyAdapterArrival") == 0) { - wpa_printf(MSG_DEBUG, "ndis_events_indicate: Try to " - "update adapter description since it may " - "have changed with new adapter instance"); - ndis_events_get_adapter(events, events->ifname, NULL); - } - - if (wcscmp(events->adapter_desc, vt.bstrVal) != 0) { - wpa_printf(MSG_DEBUG, "ndis_events_indicate: Ignore " - "indication for foreign adapter: " - "InstanceName: '%S' __CLASS: '%S'", - vt.bstrVal, vtClass.bstrVal); - VariantClear(&vtClass); - VariantClear(&vt); - continue; - } - VariantClear(&vt); - - if (wcscmp(vtClass.bstrVal, - L"MSNdis_StatusMediaSpecificIndication") == 0) { - ndis_events_media_specific(events, pObj); - } else if (wcscmp(vtClass.bstrVal, - L"MSNdis_StatusMediaConnect") == 0) { - ndis_events_media_connect(events); - } else if (wcscmp(vtClass.bstrVal, - L"MSNdis_StatusMediaDisconnect") == 0) { - ndis_events_media_disconnect(events); - } else if (wcscmp(vtClass.bstrVal, - L"MSNdis_NotifyAdapterArrival") == 0) { - ndis_events_adapter_arrival(events); - } else if (wcscmp(vtClass.bstrVal, - L"MSNdis_NotifyAdapterRemoval") == 0) { - ndis_events_adapter_removal(events); - } else { - wpa_printf(MSG_DEBUG, "Unepected event - __CLASS: " - "'%S'", vtClass.bstrVal); - } - - VariantClear(&vtClass); - } - - return WBEM_NO_ERROR; -} - - -static HRESULT STDMETHODCALLTYPE -ndis_events_set_status(IWbemObjectSink *this, long lFlags, HRESULT hResult, - BSTR strParam, IWbemClassObject __RPC_FAR *pObjParam) -{ - return WBEM_NO_ERROR; -} - - -static int notification_query(IWbemObjectSink *pDestSink, - IWbemServices *pSvc, const char *class_name) -{ - HRESULT hr; - WCHAR query[256]; - - _snwprintf(query, 256, - L"SELECT * FROM %S", class_name); - wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query); - hr = call_IWbemServices_ExecNotificationQueryAsync( - pSvc, L"WQL", query, 0, 0, pDestSink); - if (FAILED(hr)) { - wpa_printf(MSG_DEBUG, "ExecNotificationQueryAsync for %s " - "failed with hresult of 0x%x", - class_name, (int) hr); - return -1; - } - - return 0; -} - - -static int register_async_notification(IWbemObjectSink *pDestSink, - IWbemServices *pSvc) -{ - int i; - const char *class_list[] = { - "MSNdis_StatusMediaConnect", - "MSNdis_StatusMediaDisconnect", - "MSNdis_StatusMediaSpecificIndication", - "MSNdis_NotifyAdapterArrival", - "MSNdis_NotifyAdapterRemoval", - NULL - }; - - for (i = 0; class_list[i]; i++) { - if (notification_query(pDestSink, pSvc, class_list[i]) < 0) - return -1; - } - - return 0; -} - - -void ndis_events_deinit(struct ndis_events_data *events) -{ - events->terminating = 1; - IWbemServices_CancelAsyncCall(events->pSvc, &events->sink); - IWbemObjectSink_Release(&events->sink); - /* - * Rest of deinitialization is done in ndis_events_destructor() once - * all reference count drops to zero. - */ -} - - -static int ndis_events_use_desc(struct ndis_events_data *events, - const char *desc) -{ - char *tmp, *pos; - size_t len; - - if (desc == NULL) { - if (events->adapter_desc == NULL) - return -1; - /* Continue using old description */ - return 0; - } - - tmp = os_strdup(desc); - if (tmp == NULL) - return -1; - - pos = os_strstr(tmp, " (Microsoft's Packet Scheduler)"); - if (pos) - *pos = '\0'; - - len = os_strlen(tmp); - events->adapter_desc = os_malloc((len + 1) * sizeof(WCHAR)); - if (events->adapter_desc == NULL) { - os_free(tmp); - return -1; - } - _snwprintf(events->adapter_desc, len + 1, L"%S", tmp); - os_free(tmp); - return 0; -} - - -static int ndis_events_get_adapter(struct ndis_events_data *events, - const char *ifname, const char *desc) -{ - HRESULT hr; - IWbemServices *pSvc; -#define MAX_QUERY_LEN 256 - WCHAR query[MAX_QUERY_LEN]; - IEnumWbemClassObject *pEnumerator; - IWbemClassObject *pObj; - ULONG uReturned; - VARIANT vt; - int len, pos; - - /* - * Try to get adapter descriptor through WMI CIMv2 Win32_NetworkAdapter - * to have better probability of matching with InstanceName from - * MSNdis events. If this fails, use the provided description. - */ - - os_free(events->adapter_desc); - events->adapter_desc = NULL; - - hr = call_IWbemLocator_ConnectServer( - events->pLoc, L"ROOT\\CIMV2", NULL, NULL, 0, 0, 0, 0, &pSvc); - if (FAILED(hr)) { - wpa_printf(MSG_ERROR, "ndis_events: Could not connect to WMI " - "server (ROOT\\CIMV2) - error 0x%x", (int) hr); - return ndis_events_use_desc(events, desc); - } - wpa_printf(MSG_DEBUG, "ndis_events: Connected to ROOT\\CIMV2."); - - _snwprintf(query, MAX_QUERY_LEN, - L"SELECT Index FROM Win32_NetworkAdapterConfiguration " - L"WHERE SettingID='%S'", ifname); - wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query); - - hr = call_IWbemServices_ExecQuery( - pSvc, L"WQL", query, - WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, - NULL, &pEnumerator); - if (!SUCCEEDED(hr)) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface " - "GUID from Win32_NetworkAdapterConfiguration: " - "0x%x", (int) hr); - IWbemServices_Release(pSvc); - return ndis_events_use_desc(events, desc); - } - - uReturned = 0; - hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1, - &pObj, &uReturned); - if (!SUCCEEDED(hr) || uReturned == 0) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface " - "GUID from Win32_NetworkAdapterConfiguration: " - "0x%x", (int) hr); - IEnumWbemClassObject_Release(pEnumerator); - IWbemServices_Release(pSvc); - return ndis_events_use_desc(events, desc); - } - IEnumWbemClassObject_Release(pEnumerator); - - VariantInit(&vt); - hr = IWbemClassObject_Get(pObj, L"Index", 0, &vt, NULL, NULL); - if (!SUCCEEDED(hr)) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Index from " - "Win32_NetworkAdapterConfiguration: 0x%x", - (int) hr); - IWbemServices_Release(pSvc); - return ndis_events_use_desc(events, desc); - } - - _snwprintf(query, MAX_QUERY_LEN, - L"SELECT Name,PNPDeviceID FROM Win32_NetworkAdapter WHERE " - L"Index=%d", - vt.uintVal); - wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query); - VariantClear(&vt); - IWbemClassObject_Release(pObj); - - hr = call_IWbemServices_ExecQuery( - pSvc, L"WQL", query, - WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, - NULL, &pEnumerator); - if (!SUCCEEDED(hr)) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface " - "from Win32_NetworkAdapter: 0x%x", (int) hr); - IWbemServices_Release(pSvc); - return ndis_events_use_desc(events, desc); - } - - uReturned = 0; - hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1, - &pObj, &uReturned); - if (!SUCCEEDED(hr) || uReturned == 0) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface " - "from Win32_NetworkAdapter: 0x%x", (int) hr); - IEnumWbemClassObject_Release(pEnumerator); - IWbemServices_Release(pSvc); - return ndis_events_use_desc(events, desc); - } - IEnumWbemClassObject_Release(pEnumerator); - - hr = IWbemClassObject_Get(pObj, L"Name", 0, &vt, NULL, NULL); - if (!SUCCEEDED(hr)) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Name from " - "Win32_NetworkAdapter: 0x%x", (int) hr); - IWbemClassObject_Release(pObj); - IWbemServices_Release(pSvc); - return ndis_events_use_desc(events, desc); - } - - wpa_printf(MSG_DEBUG, "ndis_events: Win32_NetworkAdapter::Name='%S'", - vt.bstrVal); - events->adapter_desc = _wcsdup(vt.bstrVal); - VariantClear(&vt); - - /* - * Try to get even better candidate for matching with InstanceName - * from Win32_PnPEntity. This is needed at least for some USB cards - * that can change the InstanceName whenever being unplugged and - * plugged again. - */ - - hr = IWbemClassObject_Get(pObj, L"PNPDeviceID", 0, &vt, NULL, NULL); - if (!SUCCEEDED(hr)) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to get PNPDeviceID " - "from Win32_NetworkAdapter: 0x%x", (int) hr); - IWbemClassObject_Release(pObj); - IWbemServices_Release(pSvc); - if (events->adapter_desc == NULL) - return ndis_events_use_desc(events, desc); - return 0; /* use Win32_NetworkAdapter::Name */ - } - - wpa_printf(MSG_DEBUG, "ndis_events: Win32_NetworkAdapter::PNPDeviceID=" - "'%S'", vt.bstrVal); - - len = _snwprintf(query, MAX_QUERY_LEN, - L"SELECT Name FROM Win32_PnPEntity WHERE DeviceID='"); - if (len < 0 || len >= MAX_QUERY_LEN - 1) { - VariantClear(&vt); - IWbemClassObject_Release(pObj); - IWbemServices_Release(pSvc); - if (events->adapter_desc == NULL) - return ndis_events_use_desc(events, desc); - return 0; /* use Win32_NetworkAdapter::Name */ - } - - /* Escape \ as \\ */ - for (pos = 0; vt.bstrVal[pos] && len < MAX_QUERY_LEN - 2; pos++) { - if (vt.bstrVal[pos] == '\\') { - if (len >= MAX_QUERY_LEN - 3) - break; - query[len++] = '\\'; - } - query[len++] = vt.bstrVal[pos]; - } - query[len++] = L'\''; - query[len] = L'\0'; - VariantClear(&vt); - IWbemClassObject_Release(pObj); - wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query); - - hr = call_IWbemServices_ExecQuery( - pSvc, L"WQL", query, - WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, - NULL, &pEnumerator); - if (!SUCCEEDED(hr)) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface " - "Name from Win32_PnPEntity: 0x%x", (int) hr); - IWbemServices_Release(pSvc); - if (events->adapter_desc == NULL) - return ndis_events_use_desc(events, desc); - return 0; /* use Win32_NetworkAdapter::Name */ - } - - uReturned = 0; - hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1, - &pObj, &uReturned); - if (!SUCCEEDED(hr) || uReturned == 0) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface " - "from Win32_PnPEntity: 0x%x", (int) hr); - IEnumWbemClassObject_Release(pEnumerator); - IWbemServices_Release(pSvc); - if (events->adapter_desc == NULL) - return ndis_events_use_desc(events, desc); - return 0; /* use Win32_NetworkAdapter::Name */ - } - IEnumWbemClassObject_Release(pEnumerator); - - hr = IWbemClassObject_Get(pObj, L"Name", 0, &vt, NULL, NULL); - if (!SUCCEEDED(hr)) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Name from " - "Win32_PnPEntity: 0x%x", (int) hr); - IWbemClassObject_Release(pObj); - IWbemServices_Release(pSvc); - if (events->adapter_desc == NULL) - return ndis_events_use_desc(events, desc); - return 0; /* use Win32_NetworkAdapter::Name */ - } - - wpa_printf(MSG_DEBUG, "ndis_events: Win32_PnPEntity::Name='%S'", - vt.bstrVal); - os_free(events->adapter_desc); - events->adapter_desc = _wcsdup(vt.bstrVal); - VariantClear(&vt); - - IWbemClassObject_Release(pObj); - - IWbemServices_Release(pSvc); - - if (events->adapter_desc == NULL) - return ndis_events_use_desc(events, desc); - - return 0; -} - - -struct ndis_events_data * -ndis_events_init(HANDLE *read_pipe, HANDLE *event_avail, - const char *ifname, const char *desc) -{ - HRESULT hr; - IWbemObjectSink *pSink; - struct ndis_events_data *events; - - events = os_zalloc(sizeof(*events)); - if (events == NULL) { - wpa_printf(MSG_ERROR, "Could not allocate sink for events."); - return NULL; - } - events->ifname = os_strdup(ifname); - if (events->ifname == NULL) { - os_free(events); - return NULL; - } - - if (wmi_refcnt++ == 0) { - hr = CoInitializeEx(0, COINIT_MULTITHREADED); - if (FAILED(hr)) { - wpa_printf(MSG_ERROR, "CoInitializeEx() failed - " - "returned 0x%x", (int) hr); - os_free(events); - return NULL; - } - } - - if (wmi_first) { - /* CoInitializeSecurity() must be called once and only once - * per process, so let's use wmi_first flag to protect against - * multiple calls. */ - wmi_first = 0; - - hr = CoInitializeSecurity(NULL, -1, NULL, NULL, - RPC_C_AUTHN_LEVEL_PKT_PRIVACY, - RPC_C_IMP_LEVEL_IMPERSONATE, - NULL, EOAC_SECURE_REFS, NULL); - if (FAILED(hr)) { - wpa_printf(MSG_ERROR, "CoInitializeSecurity() failed " - "- returned 0x%x", (int) hr); - os_free(events); - return NULL; - } - } - - hr = CoCreateInstance(&CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, - &IID_IWbemLocator, - (LPVOID *) (void *) &events->pLoc); - if (FAILED(hr)) { - wpa_printf(MSG_ERROR, "CoCreateInstance() failed - returned " - "0x%x", (int) hr); - CoUninitialize(); - os_free(events); - return NULL; - } - - if (ndis_events_get_adapter(events, ifname, desc) < 0) { - CoUninitialize(); - os_free(events); - return NULL; - } - wpa_printf(MSG_DEBUG, "ndis_events: use adapter descriptor '%S'", - events->adapter_desc); - - hr = call_IWbemLocator_ConnectServer( - events->pLoc, L"ROOT\\WMI", NULL, NULL, - 0, 0, 0, 0, &events->pSvc); - if (FAILED(hr)) { - wpa_printf(MSG_ERROR, "Could not connect to server - error " - "0x%x", (int) hr); - CoUninitialize(); - os_free(events->adapter_desc); - os_free(events); - return NULL; - } - wpa_printf(MSG_DEBUG, "Connected to ROOT\\WMI."); - - ndis_events_constructor(events); - pSink = &events->sink; - pSink->lpVtbl = &events->sink_vtbl; - events->sink_vtbl.QueryInterface = ndis_events_query_interface; - events->sink_vtbl.AddRef = ndis_events_add_ref; - events->sink_vtbl.Release = ndis_events_release; - events->sink_vtbl.Indicate = ndis_events_indicate; - events->sink_vtbl.SetStatus = ndis_events_set_status; - - if (register_async_notification(pSink, events->pSvc) < 0) { - wpa_printf(MSG_DEBUG, "Failed to register async " - "notifications"); - ndis_events_destructor(events); - os_free(events->adapter_desc); - os_free(events); - return NULL; - } - - *read_pipe = events->read_pipe; - *event_avail = events->event_avail; - - return events; -} diff --git a/contrib/hostapd/src/drivers/priv_netlink.h b/contrib/hostapd/src/drivers/priv_netlink.h deleted file mode 100644 index 2a31e251a0..0000000000 --- a/contrib/hostapd/src/drivers/priv_netlink.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * wpa_supplicant - Private copy of Linux netlink/rtnetlink definitions. - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef PRIV_NETLINK_H -#define PRIV_NETLINK_H - -/* - * This should be replaced with user space header once one is available with C - * library, etc.. - */ - -#ifndef IFF_LOWER_UP -#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ -#endif -#ifndef IFF_DORMANT -#define IFF_DORMANT 0x20000 /* driver signals dormant */ -#endif - -#ifndef IFLA_IFNAME -#define IFLA_IFNAME 3 -#endif -#ifndef IFLA_WIRELESS -#define IFLA_WIRELESS 11 -#endif -#ifndef IFLA_OPERSTATE -#define IFLA_OPERSTATE 16 -#endif -#ifndef IFLA_LINKMODE -#define IFLA_LINKMODE 17 -#define IF_OPER_DORMANT 5 -#define IF_OPER_UP 6 -#endif - -#define NLM_F_REQUEST 1 - -#define NETLINK_ROUTE 0 -#define RTMGRP_LINK 1 -#define RTM_BASE 0x10 -#define RTM_NEWLINK (RTM_BASE + 0) -#define RTM_DELLINK (RTM_BASE + 1) -#define RTM_SETLINK (RTM_BASE + 3) - -#define NLMSG_ALIGNTO 4 -#define NLMSG_ALIGN(len) (((len) + NLMSG_ALIGNTO - 1) & ~(NLMSG_ALIGNTO - 1)) -#define NLMSG_LENGTH(len) ((len) + NLMSG_ALIGN(sizeof(struct nlmsghdr))) -#define NLMSG_DATA(nlh) ((void*) (((char*) nlh) + NLMSG_LENGTH(0))) - -#define RTA_ALIGNTO 4 -#define RTA_ALIGN(len) (((len) + RTA_ALIGNTO - 1) & ~(RTA_ALIGNTO - 1)) -#define RTA_OK(rta,len) \ -((len) > 0 && (rta)->rta_len >= sizeof(struct rtattr) && \ -(rta)->rta_len <= (len)) -#define RTA_NEXT(rta,attrlen) \ -((attrlen) -= RTA_ALIGN((rta)->rta_len), \ -(struct rtattr *) (((char *)(rta)) + RTA_ALIGN((rta)->rta_len))) -#define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len)) -#define RTA_DATA(rta) ((void *) (((char *) (rta)) + RTA_LENGTH(0))) - - -struct sockaddr_nl -{ - sa_family_t nl_family; - unsigned short nl_pad; - u32 nl_pid; - u32 nl_groups; -}; - -struct nlmsghdr -{ - u32 nlmsg_len; - u16 nlmsg_type; - u16 nlmsg_flags; - u32 nlmsg_seq; - u32 nlmsg_pid; -}; - -struct ifinfomsg -{ - unsigned char ifi_family; - unsigned char __ifi_pad; - unsigned short ifi_type; - int ifi_index; - unsigned ifi_flags; - unsigned ifi_change; -}; - -struct rtattr -{ - unsigned short rta_len; - unsigned short rta_type; -}; - -#endif /* PRIV_NETLINK_H */ diff --git a/contrib/hostapd/src/drivers/radiotap.c b/contrib/hostapd/src/drivers/radiotap.c deleted file mode 100644 index 804473fa4b..0000000000 --- a/contrib/hostapd/src/drivers/radiotap.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Radiotap parser - * - * Copyright 2007 Andy Green - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * - * Modified for userspace by Johannes Berg - * I only modified some things on top to ease syncing should bugs be found. - */ - -#include "includes.h" - -#include "common.h" -#include "radiotap_iter.h" - -#define le16_to_cpu le_to_host16 -#define le32_to_cpu le_to_host32 -#define __le32 uint32_t -#define ulong unsigned long -#define unlikely(cond) (cond) -#define get_unaligned(p) \ -({ \ - struct packed_dummy_struct { \ - typeof(*(p)) __val; \ - } __attribute__((packed)) *__ptr = (void *) (p); \ - \ - __ptr->__val; \ -}) - -/* function prototypes and related defs are in radiotap_iter.h */ - -/** - * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization - * @iterator: radiotap_iterator to initialize - * @radiotap_header: radiotap header to parse - * @max_length: total length we can parse into (eg, whole packet length) - * - * Returns: 0 or a negative error code if there is a problem. - * - * This function initializes an opaque iterator struct which can then - * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap - * argument which is present in the header. It knows about extended - * present headers and handles them. - * - * How to use: - * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator - * struct ieee80211_radiotap_iterator (no need to init the struct beforehand) - * checking for a good 0 return code. Then loop calling - * __ieee80211_radiotap_iterator_next()... it returns either 0, - * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem. - * The iterator's @this_arg member points to the start of the argument - * associated with the current argument index that is present, which can be - * found in the iterator's @this_arg_index member. This arg index corresponds - * to the IEEE80211_RADIOTAP_... defines. - * - * Radiotap header length: - * You can find the CPU-endian total radiotap header length in - * iterator->max_length after executing ieee80211_radiotap_iterator_init() - * successfully. - * - * Alignment Gotcha: - * You must take care when dereferencing iterator.this_arg - * for multibyte types... the pointer is not aligned. Use - * get_unaligned((type *)iterator.this_arg) to dereference - * iterator.this_arg for type "type" safely on all arches. - * - * Example code: - * See Documentation/networking/radiotap-headers.txt - */ - -int ieee80211_radiotap_iterator_init( - struct ieee80211_radiotap_iterator *iterator, - struct ieee80211_radiotap_header *radiotap_header, - int max_length) -{ - /* Linux only supports version 0 radiotap format */ - if (radiotap_header->it_version) - return -EINVAL; - - /* sanity check for allowed length and radiotap length field */ - if (max_length < le16_to_cpu(get_unaligned(&radiotap_header->it_len))) - return -EINVAL; - - iterator->rtheader = radiotap_header; - iterator->max_length = le16_to_cpu(get_unaligned( - &radiotap_header->it_len)); - iterator->arg_index = 0; - iterator->bitmap_shifter = le32_to_cpu(get_unaligned( - &radiotap_header->it_present)); - iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header); - iterator->this_arg = NULL; - - /* find payload start allowing for extended bitmap(s) */ - - if (unlikely(iterator->bitmap_shifter & (1<arg)) & - (1<arg += sizeof(u32); - - /* - * check for insanity where the present bitmaps - * keep claiming to extend up to or even beyond the - * stated radiotap header length - */ - - if (((ulong)iterator->arg - (ulong)iterator->rtheader) - > (ulong)iterator->max_length) - return -EINVAL; - } - - iterator->arg += sizeof(u32); - - /* - * no need to check again for blowing past stated radiotap - * header length, because ieee80211_radiotap_iterator_next - * checks it before it is dereferenced - */ - } - - /* we are all initialized happily */ - - return 0; -} - - -/** - * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg - * @iterator: radiotap_iterator to move to next arg (if any) - * - * Returns: 0 if there is an argument to handle, - * -ENOENT if there are no more args or -EINVAL - * if there is something else wrong. - * - * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*) - * in @this_arg_index and sets @this_arg to point to the - * payload for the field. It takes care of alignment handling and extended - * present fields. @this_arg can be changed by the caller (eg, - * incremented to move inside a compound argument like - * IEEE80211_RADIOTAP_CHANNEL). The args pointed to are in - * little-endian format whatever the endianess of your CPU. - * - * Alignment Gotcha: - * You must take care when dereferencing iterator.this_arg - * for multibyte types... the pointer is not aligned. Use - * get_unaligned((type *)iterator.this_arg) to dereference - * iterator.this_arg for type "type" safely on all arches. - */ - -int ieee80211_radiotap_iterator_next( - struct ieee80211_radiotap_iterator *iterator) -{ - - /* - * small length lookup table for all radiotap types we heard of - * starting from b0 in the bitmap, so we can walk the payload - * area of the radiotap header - * - * There is a requirement to pad args, so that args - * of a given length must begin at a boundary of that length - * -- but note that compound args are allowed (eg, 2 x u16 - * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not - * a reliable indicator of alignment requirement. - * - * upper nybble: content alignment for arg - * lower nybble: content length for arg - */ - - static const u8 rt_sizes[] = { - [IEEE80211_RADIOTAP_TSFT] = 0x88, - [IEEE80211_RADIOTAP_FLAGS] = 0x11, - [IEEE80211_RADIOTAP_RATE] = 0x11, - [IEEE80211_RADIOTAP_CHANNEL] = 0x24, - [IEEE80211_RADIOTAP_FHSS] = 0x22, - [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11, - [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11, - [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22, - [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22, - [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22, - [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11, - [IEEE80211_RADIOTAP_ANTENNA] = 0x11, - [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11, - [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11, - [IEEE80211_RADIOTAP_RX_FLAGS] = 0x22, - [IEEE80211_RADIOTAP_TX_FLAGS] = 0x22, - [IEEE80211_RADIOTAP_RTS_RETRIES] = 0x11, - [IEEE80211_RADIOTAP_DATA_RETRIES] = 0x11, - /* - * add more here as they are defined in - * include/net/ieee80211_radiotap.h - */ - }; - - /* - * for every radiotap entry we can at - * least skip (by knowing the length)... - */ - - while (iterator->arg_index < (int) sizeof(rt_sizes)) { - int hit = 0; - int pad; - - if (!(iterator->bitmap_shifter & 1)) - goto next_entry; /* arg not present */ - - /* - * arg is present, account for alignment padding - * 8-bit args can be at any alignment - * 16-bit args must start on 16-bit boundary - * 32-bit args must start on 32-bit boundary - * 64-bit args must start on 64-bit boundary - * - * note that total arg size can differ from alignment of - * elements inside arg, so we use upper nybble of length - * table to base alignment on - * - * also note: these alignments are ** relative to the - * start of the radiotap header **. There is no guarantee - * that the radiotap header itself is aligned on any - * kind of boundary. - * - * the above is why get_unaligned() is used to dereference - * multibyte elements from the radiotap area - */ - - pad = (((ulong)iterator->arg) - - ((ulong)iterator->rtheader)) & - ((rt_sizes[iterator->arg_index] >> 4) - 1); - - if (pad) - iterator->arg += - (rt_sizes[iterator->arg_index] >> 4) - pad; - - /* - * this is what we will return to user, but we need to - * move on first so next call has something fresh to test - */ - iterator->this_arg_index = iterator->arg_index; - iterator->this_arg = iterator->arg; - hit = 1; - - /* internally move on the size of this arg */ - iterator->arg += rt_sizes[iterator->arg_index] & 0x0f; - - /* - * check for insanity where we are given a bitmap that - * claims to have more arg content than the length of the - * radiotap section. We will normally end up equalling this - * max_length on the last arg, never exceeding it. - */ - - if (((ulong)iterator->arg - (ulong)iterator->rtheader) > - (ulong) iterator->max_length) - return -EINVAL; - - next_entry: - iterator->arg_index++; - if (unlikely((iterator->arg_index & 31) == 0)) { - /* completed current u32 bitmap */ - if (iterator->bitmap_shifter & 1) { - /* b31 was set, there is more */ - /* move to next u32 bitmap */ - iterator->bitmap_shifter = le32_to_cpu( - get_unaligned(iterator->next_bitmap)); - iterator->next_bitmap++; - } else - /* no more bitmaps: end */ - iterator->arg_index = sizeof(rt_sizes); - } else /* just try the next bit */ - iterator->bitmap_shifter >>= 1; - - /* if we found a valid arg earlier, return it now */ - if (hit) - return 0; - } - - /* we don't know how to handle any more args, we're done */ - return -ENOENT; -} diff --git a/contrib/hostapd/src/drivers/radiotap.h b/contrib/hostapd/src/drivers/radiotap.h deleted file mode 100644 index 508264c4cf..0000000000 --- a/contrib/hostapd/src/drivers/radiotap.h +++ /dev/null @@ -1,242 +0,0 @@ -/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */ -/* $NetBSD: ieee80211_radiotap.h,v 1.11 2005/06/22 06:16:02 dyoung Exp $ */ - -/*- - * Copyright (c) 2003, 2004 David Young. 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. - * 3. The name of David Young may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``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 DAVID - * YOUNG 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. - */ - -/* - * Modifications to fit into the linux IEEE 802.11 stack, - * Mike Kershaw (dragorn@kismetwireless.net) - */ - -#ifndef IEEE80211RADIOTAP_H -#define IEEE80211RADIOTAP_H - -#include - -/* Base version of the radiotap packet header data */ -#define PKTHDR_RADIOTAP_VERSION 0 - -/* A generic radio capture format is desirable. There is one for - * Linux, but it is neither rigidly defined (there were not even - * units given for some fields) nor easily extensible. - * - * I suggest the following extensible radio capture format. It is - * based on a bitmap indicating which fields are present. - * - * I am trying to describe precisely what the application programmer - * should expect in the following, and for that reason I tell the - * units and origin of each measurement (where it applies), or else I - * use sufficiently weaselly language ("is a monotonically nondecreasing - * function of...") that I cannot set false expectations for lawyerly - * readers. - */ - -/* The radio capture header precedes the 802.11 header. - * All data in the header is little endian on all platforms. - */ -struct ieee80211_radiotap_header { - uint8_t it_version; /* Version 0. Only increases - * for drastic changes, - * introduction of compatible - * new fields does not count. - */ - uint8_t it_pad; - uint16_t it_len; /* length of the whole - * header in bytes, including - * it_version, it_pad, - * it_len, and data fields. - */ - uint32_t it_present; /* A bitmap telling which - * fields are present. Set bit 31 - * (0x80000000) to extend the - * bitmap by another 32 bits. - * Additional extensions are made - * by setting bit 31. - */ -}; - -/* Name Data type Units - * ---- --------- ----- - * - * IEEE80211_RADIOTAP_TSFT __le64 microseconds - * - * Value in microseconds of the MAC's 64-bit 802.11 Time - * Synchronization Function timer when the first bit of the - * MPDU arrived at the MAC. For received frames, only. - * - * IEEE80211_RADIOTAP_CHANNEL 2 x uint16_t MHz, bitmap - * - * Tx/Rx frequency in MHz, followed by flags (see below). - * - * IEEE80211_RADIOTAP_FHSS uint16_t see below - * - * For frequency-hopping radios, the hop set (first byte) - * and pattern (second byte). - * - * IEEE80211_RADIOTAP_RATE u8 500kb/s - * - * Tx/Rx data rate - * - * IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from - * one milliwatt (dBm) - * - * RF signal power at the antenna, decibel difference from - * one milliwatt. - * - * IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from - * one milliwatt (dBm) - * - * RF noise power at the antenna, decibel difference from one - * milliwatt. - * - * IEEE80211_RADIOTAP_DB_ANTSIGNAL u8 decibel (dB) - * - * RF signal power at the antenna, decibel difference from an - * arbitrary, fixed reference. - * - * IEEE80211_RADIOTAP_DB_ANTNOISE u8 decibel (dB) - * - * RF noise power at the antenna, decibel difference from an - * arbitrary, fixed reference point. - * - * IEEE80211_RADIOTAP_LOCK_QUALITY uint16_t unitless - * - * Quality of Barker code lock. Unitless. Monotonically - * nondecreasing with "better" lock strength. Called "Signal - * Quality" in datasheets. (Is there a standard way to measure - * this?) - * - * IEEE80211_RADIOTAP_TX_ATTENUATION uint16_t unitless - * - * Transmit power expressed as unitless distance from max - * power set at factory calibration. 0 is max power. - * Monotonically nondecreasing with lower power levels. - * - * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t decibels (dB) - * - * Transmit power expressed as decibel distance from max power - * set at factory calibration. 0 is max power. Monotonically - * nondecreasing with lower power levels. - * - * IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from - * one milliwatt (dBm) - * - * Transmit power expressed as dBm (decibels from a 1 milliwatt - * reference). This is the absolute power level measured at - * the antenna port. - * - * IEEE80211_RADIOTAP_FLAGS u8 bitmap - * - * Properties of transmitted and received frames. See flags - * defined below. - * - * IEEE80211_RADIOTAP_ANTENNA u8 antenna index - * - * Unitless indication of the Rx/Tx antenna for this packet. - * The first antenna is antenna 0. - * - * IEEE80211_RADIOTAP_RX_FLAGS uint16_t bitmap - * - * Properties of received frames. See flags defined below. - * - * IEEE80211_RADIOTAP_TX_FLAGS uint16_t bitmap - * - * Properties of transmitted frames. See flags defined below. - * - * IEEE80211_RADIOTAP_RTS_RETRIES u8 data - * - * Number of rts retries a transmitted frame used. - * - * IEEE80211_RADIOTAP_DATA_RETRIES u8 data - * - * Number of unicast retries a transmitted frame used. - * - */ -enum ieee80211_radiotap_type { - IEEE80211_RADIOTAP_TSFT = 0, - IEEE80211_RADIOTAP_FLAGS = 1, - IEEE80211_RADIOTAP_RATE = 2, - IEEE80211_RADIOTAP_CHANNEL = 3, - IEEE80211_RADIOTAP_FHSS = 4, - IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, - IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, - IEEE80211_RADIOTAP_LOCK_QUALITY = 7, - IEEE80211_RADIOTAP_TX_ATTENUATION = 8, - IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, - IEEE80211_RADIOTAP_DBM_TX_POWER = 10, - IEEE80211_RADIOTAP_ANTENNA = 11, - IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, - IEEE80211_RADIOTAP_DB_ANTNOISE = 13, - IEEE80211_RADIOTAP_RX_FLAGS = 14, - IEEE80211_RADIOTAP_TX_FLAGS = 15, - IEEE80211_RADIOTAP_RTS_RETRIES = 16, - IEEE80211_RADIOTAP_DATA_RETRIES = 17, - IEEE80211_RADIOTAP_EXT = 31 -}; - -/* Channel flags. */ -#define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */ -#define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */ -#define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */ -#define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */ -#define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */ -#define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */ -#define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */ -#define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */ - -/* For IEEE80211_RADIOTAP_FLAGS */ -#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received - * during CFP - */ -#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received - * with short - * preamble - */ -#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received - * with WEP encryption - */ -#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received - * with fragmentation - */ -#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */ -#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between - * 802.11 header and payload - * (to 32-bit boundary) - */ -/* For IEEE80211_RADIOTAP_RX_FLAGS */ -#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */ - -/* For IEEE80211_RADIOTAP_TX_FLAGS */ -#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive - * retries */ -#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */ -#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */ - -#endif /* IEEE80211_RADIOTAP_H */ diff --git a/contrib/hostapd/src/drivers/radiotap_iter.h b/contrib/hostapd/src/drivers/radiotap_iter.h deleted file mode 100644 index 92a798a670..0000000000 --- a/contrib/hostapd/src/drivers/radiotap_iter.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __RADIOTAP_ITER_H -#define __RADIOTAP_ITER_H - -#include "radiotap.h" - -/* Radiotap header iteration - * implemented in radiotap.c - */ -/** - * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args - * @rtheader: pointer to the radiotap header we are walking through - * @max_length: length of radiotap header in cpu byte ordering - * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg - * @this_arg: pointer to current radiotap arg - * @arg_index: internal next argument index - * @arg: internal next argument pointer - * @next_bitmap: internal pointer to next present u32 - * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present - */ - -struct ieee80211_radiotap_iterator { - struct ieee80211_radiotap_header *rtheader; - int max_length; - int this_arg_index; - unsigned char *this_arg; - - int arg_index; - unsigned char *arg; - uint32_t *next_bitmap; - uint32_t bitmap_shifter; -}; - -extern int ieee80211_radiotap_iterator_init( - struct ieee80211_radiotap_iterator *iterator, - struct ieee80211_radiotap_header *radiotap_header, - int max_length); - -extern int ieee80211_radiotap_iterator_next( - struct ieee80211_radiotap_iterator *iterator); - -#endif /* __RADIOTAP_ITER_H */ diff --git a/contrib/hostapd/src/drivers/scan_helpers.c b/contrib/hostapd/src/drivers/scan_helpers.c deleted file mode 100644 index 63387701ea..0000000000 --- a/contrib/hostapd/src/drivers/scan_helpers.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * WPA Supplicant - Helper functions for scan result processing - * Copyright (c) 2007-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "drivers/driver.h" -#include "ieee802_11_defs.h" - - -const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie) -{ - const u8 *end, *pos; - - pos = (const u8 *) (res + 1); - end = pos + res->ie_len; - - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) - break; - if (pos[0] == ie) - return pos; - pos += 2 + pos[1]; - } - - return NULL; -} - - -const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, - u32 vendor_type) -{ - const u8 *end, *pos; - - pos = (const u8 *) (res + 1); - end = pos + res->ie_len; - - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) - break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - return pos; - pos += 2 + pos[1]; - } - - return NULL; -} - - -struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res, - u32 vendor_type) -{ - struct wpabuf *buf; - const u8 *end, *pos; - - buf = wpabuf_alloc(res->ie_len); - if (buf == NULL) - return NULL; - - pos = (const u8 *) (res + 1); - end = pos + res->ie_len; - - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) - break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4); - pos += 2 + pos[1]; - } - - if (wpabuf_len(buf) == 0) { - wpabuf_free(buf); - buf = NULL; - } - - return buf; -} - - -int wpa_scan_get_max_rate(const struct wpa_scan_res *res) -{ - int rate = 0; - const u8 *ie; - int i; - - ie = wpa_scan_get_ie(res, WLAN_EID_SUPP_RATES); - for (i = 0; ie && i < ie[1]; i++) { - if ((ie[i + 2] & 0x7f) > rate) - rate = ie[i + 2] & 0x7f; - } - - ie = wpa_scan_get_ie(res, WLAN_EID_EXT_SUPP_RATES); - for (i = 0; ie && i < ie[1]; i++) { - if ((ie[i + 2] & 0x7f) > rate) - rate = ie[i + 2] & 0x7f; - } - - return rate; -} - - -void wpa_scan_results_free(struct wpa_scan_results *res) -{ - size_t i; - - if (res == NULL) - return; - - for (i = 0; i < res->num; i++) - os_free(res->res[i]); - os_free(res->res); - os_free(res); -} - - -/* Compare function for sorting scan results. Return >0 if @b is considered - * better. */ -static int wpa_scan_result_compar(const void *a, const void *b) -{ - struct wpa_scan_res **_wa = (void *) a; - struct wpa_scan_res **_wb = (void *) b; - struct wpa_scan_res *wa = *_wa; - struct wpa_scan_res *wb = *_wb; - int wpa_a, wpa_b, maxrate_a, maxrate_b; - - /* WPA/WPA2 support preferred */ - wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL || - wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL; - wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL || - wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL; - - if (wpa_b && !wpa_a) - return 1; - if (!wpa_b && wpa_a) - return -1; - - /* privacy support preferred */ - if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 && - (wb->caps & IEEE80211_CAP_PRIVACY)) - return 1; - if ((wa->caps & IEEE80211_CAP_PRIVACY) && - (wb->caps & IEEE80211_CAP_PRIVACY) == 0) - return -1; - - /* best/max rate preferred if signal level close enough XXX */ - if ((wa->level && wb->level && abs(wb->level - wa->level) < 5) || - (wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) { - maxrate_a = wpa_scan_get_max_rate(wa); - maxrate_b = wpa_scan_get_max_rate(wb); - if (maxrate_a != maxrate_b) - return maxrate_b - maxrate_a; - } - - /* use freq for channel preference */ - - /* all things being equal, use signal level; if signal levels are - * identical, use quality values since some drivers may only report - * that value and leave the signal level zero */ - if (wb->level == wa->level) - return wb->qual - wa->qual; - return wb->level - wa->level; -} - - -void wpa_scan_sort_results(struct wpa_scan_results *res) -{ - qsort(res->res, res->num, sizeof(struct wpa_scan_res *), - wpa_scan_result_compar); -} diff --git a/contrib/hostapd/src/eap_common/chap.c b/contrib/hostapd/src/eap_common/chap.c deleted file mode 100644 index a088aff64e..0000000000 --- a/contrib/hostapd/src/eap_common/chap.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * CHAP-MD5 (RFC 1994) - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "md5.h" -#include "crypto.h" -#include "chap.h" - -void chap_md5(u8 id, const u8 *secret, size_t secret_len, const u8 *challenge, - size_t challenge_len, u8 *response) -{ - const u8 *addr[3]; - size_t len[3]; - - addr[0] = &id; - len[0] = 1; - addr[1] = secret; - len[1] = secret_len; - addr[2] = challenge; - len[2] = challenge_len; - md5_vector(3, addr, len, response); -} diff --git a/contrib/hostapd/src/eap_common/chap.h b/contrib/hostapd/src/eap_common/chap.h deleted file mode 100644 index 209dc8a48f..0000000000 --- a/contrib/hostapd/src/eap_common/chap.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * CHAP-MD5 (RFC 1994) - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef CHAP_H -#define CHAP_H - -#define CHAP_MD5_LEN 16 - -void chap_md5(u8 id, const u8 *secret, size_t secret_len, const u8 *challenge, - size_t challenge_len, u8 *response); - -#endif /* CHAP_H */ diff --git a/contrib/hostapd/src/eap_common/eap_common.c b/contrib/hostapd/src/eap_common/eap_common.c deleted file mode 100644 index 4afa1ddb2a..0000000000 --- a/contrib/hostapd/src/eap_common/eap_common.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * EAP common peer/server definitions - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_defs.h" -#include "eap_common.h" - -/** - * eap_hdr_validate - Validate EAP header - * @vendor: Expected EAP Vendor-Id (0 = IETF) - * @eap_type: Expected EAP type number - * @msg: EAP frame (starting with EAP header) - * @plen: Pointer to variable to contain the returned payload length - * Returns: Pointer to EAP payload (after type field), or %NULL on failure - * - * This is a helper function for EAP method implementations. This is usually - * called in the beginning of struct eap_method::process() function to verify - * that the received EAP request packet has a valid header. This function is - * able to process both legacy and expanded EAP headers and in most cases, the - * caller can just use the returned payload pointer (into *plen) for processing - * the payload regardless of whether the packet used the expanded EAP header or - * not. - */ -const u8 * eap_hdr_validate(int vendor, EapType eap_type, - const struct wpabuf *msg, size_t *plen) -{ - const struct eap_hdr *hdr; - const u8 *pos; - size_t len; - - hdr = wpabuf_head(msg); - - if (wpabuf_len(msg) < sizeof(*hdr)) { - wpa_printf(MSG_INFO, "EAP: Too short EAP frame"); - return NULL; - } - - len = be_to_host16(hdr->length); - if (len < sizeof(*hdr) + 1 || len > wpabuf_len(msg)) { - wpa_printf(MSG_INFO, "EAP: Invalid EAP length"); - return NULL; - } - - pos = (const u8 *) (hdr + 1); - - if (*pos == EAP_TYPE_EXPANDED) { - int exp_vendor; - u32 exp_type; - if (len < sizeof(*hdr) + 8) { - wpa_printf(MSG_INFO, "EAP: Invalid expanded EAP " - "length"); - return NULL; - } - pos++; - exp_vendor = WPA_GET_BE24(pos); - pos += 3; - exp_type = WPA_GET_BE32(pos); - pos += 4; - if (exp_vendor != vendor || exp_type != (u32) eap_type) { - wpa_printf(MSG_INFO, "EAP: Invalid expanded frame " - "type"); - return NULL; - } - - *plen = len - sizeof(*hdr) - 8; - return pos; - } else { - if (vendor != EAP_VENDOR_IETF || *pos != eap_type) { - wpa_printf(MSG_INFO, "EAP: Invalid frame type"); - return NULL; - } - *plen = len - sizeof(*hdr) - 1; - return pos + 1; - } -} - - -/** - * eap_msg_alloc - Allocate a buffer for an EAP message - * @vendor: Vendor-Id (0 = IETF) - * @type: EAP type - * @payload_len: Payload length in bytes (data after Type) - * @code: Message Code (EAP_CODE_*) - * @identifier: Identifier - * Returns: Pointer to the allocated message buffer or %NULL on error - * - * This function can be used to allocate a buffer for an EAP message and fill - * in the EAP header. This function is automatically using expanded EAP header - * if the selected Vendor-Id is not IETF. In other words, most EAP methods do - * not need to separately select which header type to use when using this - * function to allocate the message buffers. The returned buffer has room for - * payload_len bytes and has the EAP header and Type field already filled in. - */ -struct wpabuf * eap_msg_alloc(int vendor, EapType type, size_t payload_len, - u8 code, u8 identifier) -{ - struct wpabuf *buf; - struct eap_hdr *hdr; - size_t len; - - len = sizeof(struct eap_hdr) + (vendor == EAP_VENDOR_IETF ? 1 : 8) + - payload_len; - buf = wpabuf_alloc(len); - if (buf == NULL) - return NULL; - - hdr = wpabuf_put(buf, sizeof(*hdr)); - hdr->code = code; - hdr->identifier = identifier; - hdr->length = host_to_be16(len); - - if (vendor == EAP_VENDOR_IETF) { - wpabuf_put_u8(buf, type); - } else { - wpabuf_put_u8(buf, EAP_TYPE_EXPANDED); - wpabuf_put_be24(buf, vendor); - wpabuf_put_be32(buf, type); - } - - return buf; -} - - -/** - * eap_update_len - Update EAP header length - * @msg: EAP message from eap_msg_alloc - * - * This function updates the length field in the EAP header to match with the - * current length for the buffer. This allows eap_msg_alloc() to be used to - * allocate a larger buffer than the exact message length (e.g., if exact - * message length is not yet known). - */ -void eap_update_len(struct wpabuf *msg) -{ - struct eap_hdr *hdr; - hdr = wpabuf_mhead(msg); - if (wpabuf_len(msg) < sizeof(*hdr)) - return; - hdr->length = host_to_be16(wpabuf_len(msg)); -} - - -/** - * eap_get_id - Get EAP Identifier from wpabuf - * @msg: Buffer starting with an EAP header - * Returns: The Identifier field from the EAP header - */ -u8 eap_get_id(const struct wpabuf *msg) -{ - const struct eap_hdr *eap; - - if (wpabuf_len(msg) < sizeof(*eap)) - return 0; - - eap = wpabuf_head(msg); - return eap->identifier; -} - - -/** - * eap_get_id - Get EAP Type from wpabuf - * @msg: Buffer starting with an EAP header - * Returns: The EAP Type after the EAP header - */ -EapType eap_get_type(const struct wpabuf *msg) -{ - if (wpabuf_len(msg) < sizeof(struct eap_hdr) + 1) - return EAP_TYPE_NONE; - - return ((const u8 *) wpabuf_head(msg))[sizeof(struct eap_hdr)]; -} diff --git a/contrib/hostapd/src/eap_common/eap_common.h b/contrib/hostapd/src/eap_common/eap_common.h deleted file mode 100644 index b95e76b94f..0000000000 --- a/contrib/hostapd/src/eap_common/eap_common.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * EAP common peer/server definitions - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_COMMON_H -#define EAP_COMMON_H - -#include "wpabuf.h" - -const u8 * eap_hdr_validate(int vendor, EapType eap_type, - const struct wpabuf *msg, size_t *plen); -struct wpabuf * eap_msg_alloc(int vendor, EapType type, size_t payload_len, - u8 code, u8 identifier); -void eap_update_len(struct wpabuf *msg); -u8 eap_get_id(const struct wpabuf *msg); -EapType eap_get_type(const struct wpabuf *msg); - -#endif /* EAP_COMMON_H */ diff --git a/contrib/hostapd/src/eap_common/eap_defs.h b/contrib/hostapd/src/eap_common/eap_defs.h deleted file mode 100644 index 0efe7ab77e..0000000000 --- a/contrib/hostapd/src/eap_common/eap_defs.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * EAP server/peer: Shared EAP definitions - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_DEFS_H -#define EAP_DEFS_H - -/* RFC 3748 - Extensible Authentication Protocol (EAP) */ - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct eap_hdr { - u8 code; - u8 identifier; - be16 length; /* including code and identifier; network byte order */ - /* followed by length-4 octets of data */ -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -enum { EAP_CODE_REQUEST = 1, EAP_CODE_RESPONSE = 2, EAP_CODE_SUCCESS = 3, - EAP_CODE_FAILURE = 4 }; - -/* EAP Request and Response data begins with one octet Type. Success and - * Failure do not have additional data. */ - -/* - * EAP Method Types as allocated by IANA: - * http://www.iana.org/assignments/eap-numbers - */ -typedef enum { - EAP_TYPE_NONE = 0, - EAP_TYPE_IDENTITY = 1 /* RFC 3748 */, - EAP_TYPE_NOTIFICATION = 2 /* RFC 3748 */, - EAP_TYPE_NAK = 3 /* Response only, RFC 3748 */, - EAP_TYPE_MD5 = 4, /* RFC 3748 */ - EAP_TYPE_OTP = 5 /* RFC 3748 */, - EAP_TYPE_GTC = 6, /* RFC 3748 */ - EAP_TYPE_TLS = 13 /* RFC 2716 */, - EAP_TYPE_LEAP = 17 /* Cisco proprietary */, - EAP_TYPE_SIM = 18 /* RFC 4186 */, - EAP_TYPE_TTLS = 21 /* RFC 5281 */, - EAP_TYPE_AKA = 23 /* RFC 4187 */, - EAP_TYPE_PEAP = 25 /* draft-josefsson-pppext-eap-tls-eap-06.txt */, - EAP_TYPE_MSCHAPV2 = 26 /* draft-kamath-pppext-eap-mschapv2-00.txt */, - EAP_TYPE_TLV = 33 /* draft-josefsson-pppext-eap-tls-eap-07.txt */, - EAP_TYPE_TNC = 38 /* TNC IF-T v1.0-r3; note: tentative assignment; - * type 38 has previously been allocated for - * EAP-HTTP Digest, (funk.com) */, - EAP_TYPE_FAST = 43 /* RFC 4851 */, - EAP_TYPE_PAX = 46 /* RFC 4746 */, - EAP_TYPE_PSK = 47 /* RFC 4764 */, - EAP_TYPE_SAKE = 48 /* RFC 4763 */, - EAP_TYPE_IKEV2 = 49 /* RFC 5106 */, - EAP_TYPE_AKA_PRIME = 50 /* draft-arkko-eap-aka-kdf-10.txt */, - EAP_TYPE_GPSK = 51 /* RFC 5433 */, - EAP_TYPE_EXPANDED = 254 /* RFC 3748 */ -} EapType; - - -/* SMI Network Management Private Enterprise Code for vendor specific types */ -enum { - EAP_VENDOR_IETF = 0, - EAP_VENDOR_MICROSOFT = 0x000137 /* Microsoft */, - EAP_VENDOR_WFA = 0x00372A /* Wi-Fi Alliance */ -}; - -#define EAP_MSK_LEN 64 -#define EAP_EMSK_LEN 64 - -#endif /* EAP_DEFS_H */ diff --git a/contrib/hostapd/src/eap_common/eap_fast_common.c b/contrib/hostapd/src/eap_common/eap_fast_common.c deleted file mode 100644 index 4d3deafa0c..0000000000 --- a/contrib/hostapd/src/eap_common/eap_fast_common.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * EAP-FAST common helper functions (RFC 4851) - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha1.h" -#include "tls.h" -#include "eap_defs.h" -#include "eap_tlv_common.h" -#include "eap_fast_common.h" - - -void eap_fast_put_tlv_hdr(struct wpabuf *buf, u16 type, u16 len) -{ - struct pac_tlv_hdr hdr; - hdr.type = host_to_be16(type); - hdr.len = host_to_be16(len); - wpabuf_put_data(buf, &hdr, sizeof(hdr)); -} - - -void eap_fast_put_tlv(struct wpabuf *buf, u16 type, const void *data, - u16 len) -{ - eap_fast_put_tlv_hdr(buf, type, len); - wpabuf_put_data(buf, data, len); -} - - -void eap_fast_put_tlv_buf(struct wpabuf *buf, u16 type, - const struct wpabuf *data) -{ - eap_fast_put_tlv_hdr(buf, type, wpabuf_len(data)); - wpabuf_put_buf(buf, data); -} - - -struct wpabuf * eap_fast_tlv_eap_payload(struct wpabuf *buf) -{ - struct wpabuf *e; - - if (buf == NULL) - return NULL; - - /* Encapsulate EAP packet in EAP-Payload TLV */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Add EAP-Payload TLV"); - e = wpabuf_alloc(sizeof(struct pac_tlv_hdr) + wpabuf_len(buf)); - if (e == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to allocate memory " - "for TLV encapsulation"); - wpabuf_free(buf); - return NULL; - } - eap_fast_put_tlv_buf(e, - EAP_TLV_TYPE_MANDATORY | EAP_TLV_EAP_PAYLOAD_TLV, - buf); - wpabuf_free(buf); - return e; -} - - -void eap_fast_derive_master_secret(const u8 *pac_key, const u8 *server_random, - const u8 *client_random, u8 *master_secret) -{ -#define TLS_RANDOM_LEN 32 -#define TLS_MASTER_SECRET_LEN 48 - u8 seed[2 * TLS_RANDOM_LEN]; - - wpa_hexdump(MSG_DEBUG, "EAP-FAST: client_random", - client_random, TLS_RANDOM_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-FAST: server_random", - server_random, TLS_RANDOM_LEN); - - /* - * RFC 4851, Section 5.1: - * master_secret = T-PRF(PAC-Key, "PAC to master secret label hash", - * server_random + client_random, 48) - */ - os_memcpy(seed, server_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, client_random, TLS_RANDOM_LEN); - sha1_t_prf(pac_key, EAP_FAST_PAC_KEY_LEN, - "PAC to master secret label hash", - seed, sizeof(seed), master_secret, TLS_MASTER_SECRET_LEN); - - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: master_secret", - master_secret, TLS_MASTER_SECRET_LEN); -} - - -u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn, - const char *label, size_t len) -{ - struct tls_keys keys; - u8 *rnd = NULL, *out; - int block_size; - - block_size = tls_connection_get_keyblock_size(ssl_ctx, conn); - if (block_size < 0) - return NULL; - - out = os_malloc(block_size + len); - if (out == NULL) - return NULL; - - if (tls_connection_prf(ssl_ctx, conn, label, 1, out, block_size + len) - == 0) { - os_memmove(out, out + block_size, len); - return out; - } - - if (tls_connection_get_keys(ssl_ctx, conn, &keys)) - goto fail; - - rnd = os_malloc(keys.client_random_len + keys.server_random_len); - if (rnd == NULL) - goto fail; - - os_memcpy(rnd, keys.server_random, keys.server_random_len); - os_memcpy(rnd + keys.server_random_len, keys.client_random, - keys.client_random_len); - - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key " - "expansion", keys.master_key, keys.master_key_len); - if (tls_prf(keys.master_key, keys.master_key_len, - label, rnd, keys.client_random_len + - keys.server_random_len, out, block_size + len)) - goto fail; - os_free(rnd); - os_memmove(out, out + block_size, len); - return out; - -fail: - os_free(rnd); - os_free(out); - return NULL; -} - - -void eap_fast_derive_eap_msk(const u8 *simck, u8 *msk) -{ - /* - * RFC 4851, Section 5.4: EAP Master Session Key Generation - * MSK = T-PRF(S-IMCK[j], "Session Key Generating Function", 64) - */ - - sha1_t_prf(simck, EAP_FAST_SIMCK_LEN, - "Session Key Generating Function", (u8 *) "", 0, - msk, EAP_FAST_KEY_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (MSK)", - msk, EAP_FAST_KEY_LEN); -} - - -void eap_fast_derive_eap_emsk(const u8 *simck, u8 *emsk) -{ - /* - * RFC 4851, Section 5.4: EAP Master Session Key Genreration - * EMSK = T-PRF(S-IMCK[j], - * "Extended Session Key Generating Function", 64) - */ - - sha1_t_prf(simck, EAP_FAST_SIMCK_LEN, - "Extended Session Key Generating Function", (u8 *) "", 0, - emsk, EAP_EMSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (EMSK)", - emsk, EAP_EMSK_LEN); -} - - -int eap_fast_parse_tlv(struct eap_fast_tlv_parse *tlv, - int tlv_type, u8 *pos, int len) -{ - switch (tlv_type) { - case EAP_TLV_EAP_PAYLOAD_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: EAP-Payload TLV", - pos, len); - if (tlv->eap_payload_tlv) { - wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " - "EAP-Payload TLV in the message"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - return -2; - } - tlv->eap_payload_tlv = pos; - tlv->eap_payload_tlv_len = len; - break; - case EAP_TLV_RESULT_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Result TLV", pos, len); - if (tlv->result) { - wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " - "Result TLV in the message"); - tlv->result = EAP_TLV_RESULT_FAILURE; - return -2; - } - if (len < 2) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Result TLV"); - tlv->result = EAP_TLV_RESULT_FAILURE; - break; - } - tlv->result = WPA_GET_BE16(pos); - if (tlv->result != EAP_TLV_RESULT_SUCCESS && - tlv->result != EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Result %d", - tlv->result); - tlv->result = EAP_TLV_RESULT_FAILURE; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: Result: %s", - tlv->result == EAP_TLV_RESULT_SUCCESS ? - "Success" : "Failure"); - break; - case EAP_TLV_INTERMEDIATE_RESULT_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Intermediate Result TLV", - pos, len); - if (len < 2) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Intermediate-Result TLV"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - break; - } - if (tlv->iresult) { - wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " - "Intermediate-Result TLV in the message"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - return -2; - } - tlv->iresult = WPA_GET_BE16(pos); - if (tlv->iresult != EAP_TLV_RESULT_SUCCESS && - tlv->iresult != EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Intermediate " - "Result %d", tlv->iresult); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: Intermediate Result: %s", - tlv->iresult == EAP_TLV_RESULT_SUCCESS ? - "Success" : "Failure"); - break; - case EAP_TLV_CRYPTO_BINDING_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV", - pos, len); - if (tlv->crypto_binding) { - wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " - "Crypto-Binding TLV in the message"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - return -2; - } - tlv->crypto_binding_len = sizeof(struct eap_tlv_hdr) + len; - if (tlv->crypto_binding_len < sizeof(*tlv->crypto_binding)) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Crypto-Binding TLV"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - return -2; - } - tlv->crypto_binding = (struct eap_tlv_crypto_binding_tlv *) - (pos - sizeof(struct eap_tlv_hdr)); - break; - case EAP_TLV_REQUEST_ACTION_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Request-Action TLV", - pos, len); - if (tlv->request_action) { - wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " - "Request-Action TLV in the message"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - return -2; - } - if (len < 2) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Request-Action TLV"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - break; - } - tlv->request_action = WPA_GET_BE16(pos); - wpa_printf(MSG_DEBUG, "EAP-FAST: Request-Action: %d", - tlv->request_action); - break; - case EAP_TLV_PAC_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: PAC TLV", pos, len); - if (tlv->pac) { - wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " - "PAC TLV in the message"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - return -2; - } - tlv->pac = pos; - tlv->pac_len = len; - break; - default: - /* Unknown TLV */ - return -1; - } - - return 0; -} diff --git a/contrib/hostapd/src/eap_common/eap_fast_common.h b/contrib/hostapd/src/eap_common/eap_fast_common.h deleted file mode 100644 index c85fd37fd4..0000000000 --- a/contrib/hostapd/src/eap_common/eap_fast_common.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * EAP-FAST definitions (RFC 4851) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_FAST_H -#define EAP_FAST_H - -#define EAP_FAST_VERSION 1 -#define EAP_FAST_KEY_LEN 64 -#define EAP_FAST_SIMCK_LEN 40 -#define EAP_FAST_SKS_LEN 40 -#define EAP_FAST_CMK_LEN 20 - -#define TLS_EXT_PAC_OPAQUE 35 - -/* - * RFC 5422: Section 4.2.1 - Formats for PAC TLV Attributes / Type Field - * Note: bit 0x8000 (Mandatory) and bit 0x4000 (Reserved) are also defined - * in the general PAC TLV format (Section 4.2). - */ -#define PAC_TYPE_PAC_KEY 1 -#define PAC_TYPE_PAC_OPAQUE 2 -#define PAC_TYPE_CRED_LIFETIME 3 -#define PAC_TYPE_A_ID 4 -#define PAC_TYPE_I_ID 5 -/* - * 6 was previous assigned for SERVER_PROTECTED_DATA, but - * draft-cam-winget-eap-fast-provisioning-02.txt changed this to Reserved. - */ -#define PAC_TYPE_A_ID_INFO 7 -#define PAC_TYPE_PAC_ACKNOWLEDGEMENT 8 -#define PAC_TYPE_PAC_INFO 9 -#define PAC_TYPE_PAC_TYPE 10 - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct pac_tlv_hdr { - be16 type; - be16 len; -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -#define EAP_FAST_PAC_KEY_LEN 32 - -/* RFC 5422: 4.2.6 PAC-Type TLV */ -#define PAC_TYPE_TUNNEL_PAC 1 -/* Application Specific Short Lived PACs (only in volatile storage) */ -/* User Authorization PAC */ -#define PAC_TYPE_USER_AUTHORIZATION 3 -/* Application Specific Long Lived PACs */ -/* Machine Authentication PAC */ -#define PAC_TYPE_MACHINE_AUTHENTICATION 2 - - -/* - * RFC 5422: - * Section 3.3 - Key Derivations Used in the EAP-FAST Provisioning Exchange - */ -struct eap_fast_key_block_provisioning { - /* Extra key material after TLS key_block */ - u8 session_key_seed[EAP_FAST_SKS_LEN]; - u8 server_challenge[16]; /* MSCHAPv2 ServerChallenge */ - u8 client_challenge[16]; /* MSCHAPv2 ClientChallenge */ -}; - - -struct wpabuf; -struct tls_connection; - -struct eap_fast_tlv_parse { - u8 *eap_payload_tlv; - size_t eap_payload_tlv_len; - struct eap_tlv_crypto_binding_tlv *crypto_binding; - size_t crypto_binding_len; - int iresult; - int result; - int request_action; - u8 *pac; - size_t pac_len; -}; - -void eap_fast_put_tlv_hdr(struct wpabuf *buf, u16 type, u16 len); -void eap_fast_put_tlv(struct wpabuf *buf, u16 type, const void *data, - u16 len); -void eap_fast_put_tlv_buf(struct wpabuf *buf, u16 type, - const struct wpabuf *data); -struct wpabuf * eap_fast_tlv_eap_payload(struct wpabuf *buf); -void eap_fast_derive_master_secret(const u8 *pac_key, const u8 *server_random, - const u8 *client_random, u8 *master_secret); -u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn, - const char *label, size_t len); -void eap_fast_derive_eap_msk(const u8 *simck, u8 *msk); -void eap_fast_derive_eap_emsk(const u8 *simck, u8 *emsk); -int eap_fast_parse_tlv(struct eap_fast_tlv_parse *tlv, - int tlv_type, u8 *pos, int len); - -#endif /* EAP_FAST_H */ diff --git a/contrib/hostapd/src/eap_common/eap_gpsk_common.c b/contrib/hostapd/src/eap_common/eap_gpsk_common.c deleted file mode 100644 index 414610cf5a..0000000000 --- a/contrib/hostapd/src/eap_common/eap_gpsk_common.c +++ /dev/null @@ -1,426 +0,0 @@ -/* - * EAP server/peer: EAP-GPSK shared routines - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_defs.h" -#include "aes_wrap.h" -#include "crypto.h" -#ifdef EAP_GPSK_SHA256 -#include "sha256.h" -#endif /* EAP_GPSK_SHA256 */ -#include "eap_gpsk_common.h" - - -/** - * eap_gpsk_supported_ciphersuite - Check whether ciphersuite is supported - * @vendor: CSuite/Vendor - * @specifier: CSuite/Specifier - * Returns: 1 if ciphersuite is support, or 0 if not - */ -int eap_gpsk_supported_ciphersuite(int vendor, int specifier) -{ - if (vendor == EAP_GPSK_VENDOR_IETF && - specifier == EAP_GPSK_CIPHER_AES) - return 1; -#ifdef EAP_GPSK_SHA256 - if (vendor == EAP_GPSK_VENDOR_IETF && - specifier == EAP_GPSK_CIPHER_SHA256) - return 1; -#endif /* EAP_GPSK_SHA256 */ - return 0; -} - - -static int eap_gpsk_gkdf_cmac(const u8 *psk /* Y */, - const u8 *data /* Z */, size_t data_len, - u8 *buf, size_t len /* X */) -{ - u8 *opos; - size_t i, n, hashlen, left, clen; - u8 ibuf[2], hash[16]; - const u8 *addr[2]; - size_t vlen[2]; - - hashlen = sizeof(hash); - /* M_i = MAC_Y (i || Z); (MAC = AES-CMAC-128) */ - addr[0] = ibuf; - vlen[0] = sizeof(ibuf); - addr[1] = data; - vlen[1] = data_len; - - opos = buf; - left = len; - n = (len + hashlen - 1) / hashlen; - for (i = 1; i <= n; i++) { - WPA_PUT_BE16(ibuf, i); - if (omac1_aes_128_vector(psk, 2, addr, vlen, hash)) - return -1; - clen = left > hashlen ? hashlen : left; - os_memcpy(opos, hash, clen); - opos += clen; - left -= clen; - } - - return 0; -} - - -#ifdef EAP_GPSK_SHA256 -static int eap_gpsk_gkdf_sha256(const u8 *psk /* Y */, - const u8 *data /* Z */, size_t data_len, - u8 *buf, size_t len /* X */) -{ - u8 *opos; - size_t i, n, hashlen, left, clen; - u8 ibuf[2], hash[SHA256_MAC_LEN]; - const u8 *addr[2]; - size_t vlen[2]; - - hashlen = SHA256_MAC_LEN; - /* M_i = MAC_Y (i || Z); (MAC = HMAC-SHA256) */ - addr[0] = ibuf; - vlen[0] = sizeof(ibuf); - addr[1] = data; - vlen[1] = data_len; - - opos = buf; - left = len; - n = (len + hashlen - 1) / hashlen; - for (i = 1; i <= n; i++) { - WPA_PUT_BE16(ibuf, i); - hmac_sha256_vector(psk, 32, 2, addr, vlen, hash); - clen = left > hashlen ? hashlen : left; - os_memcpy(opos, hash, clen); - opos += clen; - left -= clen; - } - - return 0; -} -#endif /* EAP_GPSK_SHA256 */ - - -static int eap_gpsk_derive_keys_helper(u32 csuite_specifier, - u8 *kdf_out, size_t kdf_out_len, - const u8 *psk, size_t psk_len, - const u8 *seed, size_t seed_len, - u8 *msk, u8 *emsk, - u8 *sk, size_t sk_len, - u8 *pk, size_t pk_len) -{ - u8 mk[32], *pos, *data; - size_t data_len, mk_len; - int (*gkdf)(const u8 *_psk, const u8 *_data, size_t _data_len, - u8 *buf, size_t len); - - gkdf = NULL; - switch (csuite_specifier) { - case EAP_GPSK_CIPHER_AES: - gkdf = eap_gpsk_gkdf_cmac; - mk_len = 16; - break; -#ifdef EAP_GPSK_SHA256 - case EAP_GPSK_CIPHER_SHA256: - gkdf = eap_gpsk_gkdf_sha256; - mk_len = SHA256_MAC_LEN; - break; -#endif /* EAP_GPSK_SHA256 */ - default: - return -1; - } - - if (psk_len < mk_len) - return -1; - - data_len = 2 + psk_len + 6 + seed_len; - data = os_malloc(data_len); - if (data == NULL) - return -1; - pos = data; - WPA_PUT_BE16(pos, psk_len); - pos += 2; - os_memcpy(pos, psk, psk_len); - pos += psk_len; - WPA_PUT_BE32(pos, EAP_GPSK_VENDOR_IETF); /* CSuite/Vendor = IETF */ - pos += 4; - WPA_PUT_BE16(pos, csuite_specifier); /* CSuite/Specifier */ - pos += 2; - os_memcpy(pos, seed, seed_len); /* inputString */ - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: Data to MK derivation", - data, data_len); - - if (gkdf(psk, data, data_len, mk, mk_len) < 0) { - os_free(data); - return -1; - } - os_free(data); - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MK", mk, mk_len); - - if (gkdf(mk, seed, seed_len, kdf_out, kdf_out_len) < 0) - return -1; - - pos = kdf_out; - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MSK", pos, EAP_MSK_LEN); - os_memcpy(msk, pos, EAP_MSK_LEN); - pos += EAP_MSK_LEN; - - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: EMSK", pos, EAP_EMSK_LEN); - os_memcpy(emsk, pos, EAP_EMSK_LEN); - pos += EAP_EMSK_LEN; - - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: SK", pos, sk_len); - os_memcpy(sk, pos, sk_len); - pos += sk_len; - - if (pk) { - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PK", pos, pk_len); - os_memcpy(pk, pos, pk_len); - } - - return 0; -} - - -static int eap_gpsk_derive_keys_aes(const u8 *psk, size_t psk_len, - const u8 *seed, size_t seed_len, - u8 *msk, u8 *emsk, u8 *sk, size_t *sk_len, - u8 *pk, size_t *pk_len) -{ -#define EAP_GPSK_SK_LEN_AES 16 -#define EAP_GPSK_PK_LEN_AES 16 - u8 kdf_out[EAP_MSK_LEN + EAP_EMSK_LEN + EAP_GPSK_SK_LEN_AES + - EAP_GPSK_PK_LEN_AES]; - - /* - * inputString = RAND_Peer || ID_Peer || RAND_Server || ID_Server - * (= seed) - * KS = 16, PL = psk_len, CSuite_Sel = 0x00000000 0x0001 - * MK = GKDF-16 (PSK[0..15], PL || PSK || CSuite_Sel || inputString) - * MSK = GKDF-160 (MK, inputString)[0..63] - * EMSK = GKDF-160 (MK, inputString)[64..127] - * SK = GKDF-160 (MK, inputString)[128..143] - * PK = GKDF-160 (MK, inputString)[144..159] - * zero = 0x00 || 0x00 || ... || 0x00 (16 times) - * Method-ID = GKDF-16 (zero, "Method ID" || EAP_Method_Type || - * CSuite_Sel || inputString) - */ - - *sk_len = EAP_GPSK_SK_LEN_AES; - *pk_len = EAP_GPSK_PK_LEN_AES; - - return eap_gpsk_derive_keys_helper(EAP_GPSK_CIPHER_AES, - kdf_out, sizeof(kdf_out), - psk, psk_len, seed, seed_len, - msk, emsk, sk, *sk_len, - pk, *pk_len); -} - - -#ifdef EAP_GPSK_SHA256 -static int eap_gpsk_derive_keys_sha256(const u8 *psk, size_t psk_len, - const u8 *seed, size_t seed_len, - u8 *msk, u8 *emsk, - u8 *sk, size_t *sk_len) -{ -#define EAP_GPSK_SK_LEN_SHA256 SHA256_MAC_LEN -#define EAP_GPSK_PK_LEN_SHA256 SHA256_MAC_LEN - u8 kdf_out[EAP_MSK_LEN + EAP_EMSK_LEN + EAP_GPSK_SK_LEN_SHA256 + - EAP_GPSK_PK_LEN_SHA256]; - - /* - * inputString = RAND_Peer || ID_Peer || RAND_Server || ID_Server - * (= seed) - * KS = 32, PL = psk_len, CSuite_Sel = 0x00000000 0x0002 - * MK = GKDF-32 (PSK[0..31], PL || PSK || CSuite_Sel || inputString) - * MSK = GKDF-160 (MK, inputString)[0..63] - * EMSK = GKDF-160 (MK, inputString)[64..127] - * SK = GKDF-160 (MK, inputString)[128..159] - * zero = 0x00 || 0x00 || ... || 0x00 (32 times) - * Method-ID = GKDF-16 (zero, "Method ID" || EAP_Method_Type || - * CSuite_Sel || inputString) - */ - - *sk_len = EAP_GPSK_SK_LEN_SHA256; - - return eap_gpsk_derive_keys_helper(EAP_GPSK_CIPHER_SHA256, - kdf_out, sizeof(kdf_out), - psk, psk_len, seed, seed_len, - msk, emsk, sk, *sk_len, - NULL, 0); -} -#endif /* EAP_GPSK_SHA256 */ - - -/** - * eap_gpsk_derive_keys - Derive EAP-GPSK keys - * @psk: Pre-shared key - * @psk_len: Length of psk in bytes - * @vendor: CSuite/Vendor - * @specifier: CSuite/Specifier - * @rand_peer: 32-byte RAND_Peer - * @rand_server: 32-byte RAND_Server - * @id_peer: ID_Peer - * @id_peer_len: Length of ID_Peer - * @id_server: ID_Server - * @id_server_len: Length of ID_Server - * @msk: Buffer for 64-byte MSK - * @emsk: Buffer for 64-byte EMSK - * @sk: Buffer for SK (at least EAP_GPSK_MAX_SK_LEN bytes) - * @sk_len: Buffer for returning length of SK - * @pk: Buffer for PK (at least EAP_GPSK_MAX_PK_LEN bytes) - * @pk_len: Buffer for returning length of PK - * Returns: 0 on success, -1 on failure - */ -int eap_gpsk_derive_keys(const u8 *psk, size_t psk_len, int vendor, - int specifier, - const u8 *rand_peer, const u8 *rand_server, - const u8 *id_peer, size_t id_peer_len, - const u8 *id_server, size_t id_server_len, - u8 *msk, u8 *emsk, u8 *sk, size_t *sk_len, - u8 *pk, size_t *pk_len) -{ - u8 *seed, *pos; - size_t seed_len; - int ret; - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Deriving keys (%d:%d)", - vendor, specifier); - - if (vendor != EAP_GPSK_VENDOR_IETF) - return -1; - - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PSK", psk, psk_len); - - /* Seed = RAND_Peer || ID_Peer || RAND_Server || ID_Server */ - seed_len = 2 * EAP_GPSK_RAND_LEN + id_server_len + id_peer_len; - seed = os_malloc(seed_len); - if (seed == NULL) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to allocate memory " - "for key derivation"); - return -1; - } - - pos = seed; - os_memcpy(pos, rand_peer, EAP_GPSK_RAND_LEN); - pos += EAP_GPSK_RAND_LEN; - os_memcpy(pos, id_peer, id_peer_len); - pos += id_peer_len; - os_memcpy(pos, rand_server, EAP_GPSK_RAND_LEN); - pos += EAP_GPSK_RAND_LEN; - os_memcpy(pos, id_server, id_server_len); - pos += id_server_len; - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Seed", seed, seed_len); - - switch (specifier) { - case EAP_GPSK_CIPHER_AES: - ret = eap_gpsk_derive_keys_aes(psk, psk_len, seed, seed_len, - msk, emsk, sk, sk_len, - pk, pk_len); - break; -#ifdef EAP_GPSK_SHA256 - case EAP_GPSK_CIPHER_SHA256: - ret = eap_gpsk_derive_keys_sha256(psk, psk_len, seed, seed_len, - msk, emsk, sk, sk_len); - break; -#endif /* EAP_GPSK_SHA256 */ - default: - wpa_printf(MSG_DEBUG, "EAP-GPSK: Unknown cipher %d:%d used in " - "key derivation", vendor, specifier); - ret = -1; - break; - } - - os_free(seed); - - return ret; -} - - -/** - * eap_gpsk_mic_len - Get the length of the MIC - * @vendor: CSuite/Vendor - * @specifier: CSuite/Specifier - * Returns: MIC length in bytes - */ -size_t eap_gpsk_mic_len(int vendor, int specifier) -{ - if (vendor != EAP_GPSK_VENDOR_IETF) - return 0; - - switch (specifier) { - case EAP_GPSK_CIPHER_AES: - return 16; -#ifdef EAP_GPSK_SHA256 - case EAP_GPSK_CIPHER_SHA256: - return 32; -#endif /* EAP_GPSK_SHA256 */ - default: - return 0; - } -} - - -static int eap_gpsk_compute_mic_aes(const u8 *sk, size_t sk_len, - const u8 *data, size_t len, u8 *mic) -{ - if (sk_len != 16) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid SK length %lu for " - "AES-CMAC MIC", (unsigned long) sk_len); - return -1; - } - - return omac1_aes_128(sk, data, len, mic); -} - - -/** - * eap_gpsk_compute_mic - Compute EAP-GPSK MIC for an EAP packet - * @sk: Session key SK from eap_gpsk_derive_keys() - * @sk_len: SK length in bytes from eap_gpsk_derive_keys() - * @vendor: CSuite/Vendor - * @specifier: CSuite/Specifier - * @data: Input data to MIC - * @len: Input data length in bytes - * @mic: Buffer for the computed MIC, eap_gpsk_mic_len(cipher) bytes - * Returns: 0 on success, -1 on failure - */ -int eap_gpsk_compute_mic(const u8 *sk, size_t sk_len, int vendor, - int specifier, const u8 *data, size_t len, u8 *mic) -{ - int ret; - - if (vendor != EAP_GPSK_VENDOR_IETF) - return -1; - - switch (specifier) { - case EAP_GPSK_CIPHER_AES: - ret = eap_gpsk_compute_mic_aes(sk, sk_len, data, len, mic); - break; -#ifdef EAP_GPSK_SHA256 - case EAP_GPSK_CIPHER_SHA256: - hmac_sha256(sk, sk_len, data, len, mic); - ret = 0; - break; -#endif /* EAP_GPSK_SHA256 */ - default: - wpa_printf(MSG_DEBUG, "EAP-GPSK: Unknown cipher %d:%d used in " - "MIC computation", vendor, specifier); - ret = -1; - break; - } - - return ret; -} diff --git a/contrib/hostapd/src/eap_common/eap_gpsk_common.h b/contrib/hostapd/src/eap_common/eap_gpsk_common.h deleted file mode 100644 index a30ab97ffa..0000000000 --- a/contrib/hostapd/src/eap_common/eap_gpsk_common.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * EAP server/peer: EAP-GPSK shared routines - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_GPSK_COMMON_H -#define EAP_GPSK_COMMON_H - -#define EAP_GPSK_OPCODE_GPSK_1 1 -#define EAP_GPSK_OPCODE_GPSK_2 2 -#define EAP_GPSK_OPCODE_GPSK_3 3 -#define EAP_GPSK_OPCODE_GPSK_4 4 -#define EAP_GPSK_OPCODE_FAIL 5 -#define EAP_GPSK_OPCODE_PROTECTED_FAIL 6 - -/* Failure-Code in GPSK-Fail and GPSK-Protected-Fail */ -#define EAP_GPSK_FAIL_PSK_NOT_FOUND 0x00000001 -#define EAP_GPSK_FAIL_AUTHENTICATION_FAILURE 0x00000002 -#define EAP_GPSK_FAIL_AUTHORIZATION_FAILURE 0x00000003 - -#define EAP_GPSK_RAND_LEN 32 -#define EAP_GPSK_MAX_SK_LEN 32 -#define EAP_GPSK_MAX_PK_LEN 32 -#define EAP_GPSK_MAX_MIC_LEN 32 - -#define EAP_GPSK_VENDOR_IETF 0x00000000 -#define EAP_GPSK_CIPHER_RESERVED 0x000000 -#define EAP_GPSK_CIPHER_AES 0x000001 -#define EAP_GPSK_CIPHER_SHA256 0x000002 - - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct eap_gpsk_csuite { - u8 vendor[4]; - u8 specifier[2]; -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -int eap_gpsk_supported_ciphersuite(int vendor, int specifier); -int eap_gpsk_derive_keys(const u8 *psk, size_t psk_len, int vendor, - int specifier, - const u8 *rand_client, const u8 *rand_server, - const u8 *id_client, size_t id_client_len, - const u8 *id_server, size_t id_server_len, - u8 *msk, u8 *emsk, u8 *sk, size_t *sk_len, - u8 *pk, size_t *pk_len); -size_t eap_gpsk_mic_len(int vendor, int specifier); -int eap_gpsk_compute_mic(const u8 *sk, size_t sk_len, int vendor, - int specifier, const u8 *data, size_t len, u8 *mic); - -#endif /* EAP_GPSK_COMMON_H */ diff --git a/contrib/hostapd/src/eap_common/eap_ikev2_common.c b/contrib/hostapd/src/eap_common/eap_ikev2_common.c deleted file mode 100644 index e9a9c55eb3..0000000000 --- a/contrib/hostapd/src/eap_common/eap_ikev2_common.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * EAP-IKEv2 common routines - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_defs.h" -#include "eap_common.h" -#include "ikev2_common.h" -#include "eap_ikev2_common.h" - - -int eap_ikev2_derive_keymat(int prf, struct ikev2_keys *keys, - const u8 *i_nonce, size_t i_nonce_len, - const u8 *r_nonce, size_t r_nonce_len, - u8 *keymat) -{ - u8 *nonces; - size_t nlen; - - /* KEYMAT = prf+(SK_d, Ni | Nr) */ - if (keys->SK_d == NULL || i_nonce == NULL || r_nonce == NULL) - return -1; - - nlen = i_nonce_len + r_nonce_len; - nonces = os_malloc(nlen); - if (nonces == NULL) - return -1; - os_memcpy(nonces, i_nonce, i_nonce_len); - os_memcpy(nonces + i_nonce_len, r_nonce, r_nonce_len); - - if (ikev2_prf_plus(prf, keys->SK_d, keys->SK_d_len, nonces, nlen, - keymat, EAP_MSK_LEN + EAP_EMSK_LEN)) { - os_free(nonces); - return -1; - } - os_free(nonces); - - wpa_hexdump_key(MSG_DEBUG, "EAP-IKEV2: KEYMAT", - keymat, EAP_MSK_LEN + EAP_EMSK_LEN); - - return 0; -} - - -struct wpabuf * eap_ikev2_build_frag_ack(u8 id, u8 code) -{ - struct wpabuf *msg; - -#ifdef CCNS_PL - msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 1, code, id); - if (msg == NULL) { - wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory " - "for fragment ack"); - return NULL; - } - wpabuf_put_u8(msg, 0); /* Flags */ -#else /* CCNS_PL */ - msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 0, code, id); - if (msg == NULL) { - wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory " - "for fragment ack"); - return NULL; - } -#endif /* CCNS_PL */ - - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Send fragment ack"); - - return msg; -} - - -int eap_ikev2_validate_icv(int integ_alg, struct ikev2_keys *keys, - int initiator, const struct wpabuf *msg, - const u8 *pos, const u8 *end) -{ - const struct ikev2_integ_alg *integ; - size_t icv_len; - u8 icv[IKEV2_MAX_HASH_LEN]; - const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar; - - integ = ikev2_get_integ(integ_alg); - if (integ == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG " - "transform / cannot validate ICV"); - return -1; - } - icv_len = integ->hash_len; - - if (end - pos < (int) icv_len) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Not enough room in the " - "message for Integrity Checksum Data"); - return -1; - } - - if (SK_a == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: No SK_a for ICV validation"); - return -1; - } - - if (ikev2_integ_hash(integ_alg, SK_a, keys->SK_integ_len, - wpabuf_head(msg), - wpabuf_len(msg) - icv_len, icv) < 0) { - wpa_printf(MSG_INFO, "EAP-IKEV2: Could not calculate ICV"); - return -1; - } - - if (os_memcmp(icv, end - icv_len, icv_len) != 0) { - wpa_printf(MSG_INFO, "EAP-IKEV2: Invalid ICV"); - wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Calculated ICV", - icv, icv_len); - wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Received ICV", - end - icv_len, icv_len); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Valid Integrity Checksum Data in " - "the received message"); - - return icv_len; -} diff --git a/contrib/hostapd/src/eap_common/eap_ikev2_common.h b/contrib/hostapd/src/eap_common/eap_ikev2_common.h deleted file mode 100644 index a9fc2caae7..0000000000 --- a/contrib/hostapd/src/eap_common/eap_ikev2_common.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * EAP-IKEv2 definitions - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_IKEV2_COMMON_H -#define EAP_IKEV2_COMMON_H - -#ifdef CCNS_PL -/* incorrect bit order */ -#define IKEV2_FLAGS_LENGTH_INCLUDED 0x01 -#define IKEV2_FLAGS_MORE_FRAGMENTS 0x02 -#define IKEV2_FLAGS_ICV_INCLUDED 0x04 -#else /* CCNS_PL */ -#define IKEV2_FLAGS_LENGTH_INCLUDED 0x80 -#define IKEV2_FLAGS_MORE_FRAGMENTS 0x40 -#define IKEV2_FLAGS_ICV_INCLUDED 0x20 -#endif /* CCNS_PL */ - -#define IKEV2_FRAGMENT_SIZE 1400 - -struct ikev2_keys; - -int eap_ikev2_derive_keymat(int prf, struct ikev2_keys *keys, - const u8 *i_nonce, size_t i_nonce_len, - const u8 *r_nonce, size_t r_nonce_len, - u8 *keymat); -struct wpabuf * eap_ikev2_build_frag_ack(u8 id, u8 code); -int eap_ikev2_validate_icv(int integ_alg, struct ikev2_keys *keys, - int initiator, const struct wpabuf *msg, - const u8 *pos, const u8 *end); - -#endif /* EAP_IKEV2_COMMON_H */ diff --git a/contrib/hostapd/src/eap_common/eap_pax_common.c b/contrib/hostapd/src/eap_common/eap_pax_common.c deleted file mode 100644 index 80110469dc..0000000000 --- a/contrib/hostapd/src/eap_common/eap_pax_common.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * EAP server/peer: EAP-PAX shared routines - * Copyright (c) 2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha1.h" -#include "eap_pax_common.h" - - -/** - * eap_pax_kdf - PAX Key Derivation Function - * @mac_id: MAC ID (EAP_PAX_MAC_*) / currently, only HMAC_SHA1_128 is supported - * @key: Secret key (X) - * @key_len: Length of the secret key in bytes - * @identifier: Public identifier for the key (Y) - * @entropy: Exchanged entropy to seed the KDF (Z) - * @entropy_len: Length of the entropy in bytes - * @output_len: Output len in bytes (W) - * @output: Buffer for the derived key - * Returns: 0 on success, -1 failed - * - * RFC 4746, Section 2.6: PAX-KDF-W(X, Y, Z) - */ -int eap_pax_kdf(u8 mac_id, const u8 *key, size_t key_len, - const char *identifier, - const u8 *entropy, size_t entropy_len, - size_t output_len, u8 *output) -{ - u8 mac[SHA1_MAC_LEN]; - u8 counter, *pos; - const u8 *addr[3]; - size_t len[3]; - size_t num_blocks, left; - - num_blocks = (output_len + EAP_PAX_MAC_LEN - 1) / EAP_PAX_MAC_LEN; - if (identifier == NULL || num_blocks >= 255) - return -1; - - /* TODO: add support for EAP_PAX_HMAC_SHA256_128 */ - if (mac_id != EAP_PAX_MAC_HMAC_SHA1_128) - return -1; - - addr[0] = (const u8 *) identifier; - len[0] = os_strlen(identifier); - addr[1] = entropy; - len[1] = entropy_len; - addr[2] = &counter; - len[2] = 1; - - pos = output; - left = output_len; - for (counter = 1; counter <= (u8) num_blocks; counter++) { - size_t clen = left > EAP_PAX_MAC_LEN ? EAP_PAX_MAC_LEN : left; - hmac_sha1_vector(key, key_len, 3, addr, len, mac); - os_memcpy(pos, mac, clen); - pos += clen; - left -= clen; - } - - return 0; -} - - -/** - * eap_pax_mac - EAP-PAX MAC - * @mac_id: MAC ID (EAP_PAX_MAC_*) / currently, only HMAC_SHA1_128 is supported - * @key: Secret key - * @key_len: Length of the secret key in bytes - * @data1: Optional data, first block; %NULL if not used - * @data1_len: Length of data1 in bytes - * @data2: Optional data, second block; %NULL if not used - * @data2_len: Length of data2 in bytes - * @data3: Optional data, third block; %NULL if not used - * @data3_len: Length of data3 in bytes - * @mac: Buffer for the MAC value (EAP_PAX_MAC_LEN = 16 bytes) - * Returns: 0 on success, -1 on failure - * - * Wrapper function to calculate EAP-PAX MAC. - */ -int eap_pax_mac(u8 mac_id, const u8 *key, size_t key_len, - const u8 *data1, size_t data1_len, - const u8 *data2, size_t data2_len, - const u8 *data3, size_t data3_len, - u8 *mac) -{ - u8 hash[SHA1_MAC_LEN]; - const u8 *addr[3]; - size_t len[3]; - size_t count; - - /* TODO: add support for EAP_PAX_HMAC_SHA256_128 */ - if (mac_id != EAP_PAX_MAC_HMAC_SHA1_128) - return -1; - - addr[0] = data1; - len[0] = data1_len; - addr[1] = data2; - len[1] = data2_len; - addr[2] = data3; - len[2] = data3_len; - - count = (data1 ? 1 : 0) + (data2 ? 1 : 0) + (data3 ? 1 : 0); - hmac_sha1_vector(key, key_len, count, addr, len, hash); - os_memcpy(mac, hash, EAP_PAX_MAC_LEN); - - return 0; -} - - -/** - * eap_pax_initial_key_derivation - EAP-PAX initial key derivation - * @mac_id: MAC ID (EAP_PAX_MAC_*) / currently, only HMAC_SHA1_128 is supported - * @ak: Authentication Key - * @e: Entropy - * @mk: Buffer for the derived Master Key - * @ck: Buffer for the derived Confirmation Key - * @ick: Buffer for the derived Integrity Check Key - * Returns: 0 on success, -1 on failure - */ -int eap_pax_initial_key_derivation(u8 mac_id, const u8 *ak, const u8 *e, - u8 *mk, u8 *ck, u8 *ick) -{ - wpa_printf(MSG_DEBUG, "EAP-PAX: initial key derivation"); - if (eap_pax_kdf(mac_id, ak, EAP_PAX_AK_LEN, "Master Key", - e, 2 * EAP_PAX_RAND_LEN, EAP_PAX_MK_LEN, mk) || - eap_pax_kdf(mac_id, mk, EAP_PAX_MK_LEN, "Confirmation Key", - e, 2 * EAP_PAX_RAND_LEN, EAP_PAX_CK_LEN, ck) || - eap_pax_kdf(mac_id, mk, EAP_PAX_MK_LEN, "Integrity Check Key", - e, 2 * EAP_PAX_RAND_LEN, EAP_PAX_ICK_LEN, ick)) - return -1; - - wpa_hexdump_key(MSG_MSGDUMP, "EAP-PAX: AK", ak, EAP_PAX_AK_LEN); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-PAX: MK", mk, EAP_PAX_MK_LEN); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-PAX: CK", ck, EAP_PAX_CK_LEN); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-PAX: ICK", ick, EAP_PAX_ICK_LEN); - - return 0; -} diff --git a/contrib/hostapd/src/eap_common/eap_pax_common.h b/contrib/hostapd/src/eap_common/eap_pax_common.h deleted file mode 100644 index dcc171ec2c..0000000000 --- a/contrib/hostapd/src/eap_common/eap_pax_common.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * EAP server/peer: EAP-PAX shared routines - * Copyright (c) 2005-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_PAX_COMMON_H -#define EAP_PAX_COMMON_H - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct eap_pax_hdr { - u8 op_code; - u8 flags; - u8 mac_id; - u8 dh_group_id; - u8 public_key_id; - /* Followed by variable length payload and ICV */ -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -/* op_code: */ -enum { - EAP_PAX_OP_STD_1 = 0x01, - EAP_PAX_OP_STD_2 = 0x02, - EAP_PAX_OP_STD_3 = 0x03, - EAP_PAX_OP_SEC_1 = 0x11, - EAP_PAX_OP_SEC_2 = 0x12, - EAP_PAX_OP_SEC_3 = 0x13, - EAP_PAX_OP_SEC_4 = 0x14, - EAP_PAX_OP_SEC_5 = 0x15, - EAP_PAX_OP_ACK = 0x21 -}; - -/* flags: */ -#define EAP_PAX_FLAGS_MF 0x01 -#define EAP_PAX_FLAGS_CE 0x02 -#define EAP_PAX_FLAGS_AI 0x04 - -/* mac_id: */ -#define EAP_PAX_MAC_HMAC_SHA1_128 0x01 -#define EAP_PAX_HMAC_SHA256_128 0x02 - -/* dh_group_id: */ -#define EAP_PAX_DH_GROUP_NONE 0x00 -#define EAP_PAX_DH_GROUP_2048_MODP 0x01 -#define EAP_PAX_DH_GROUP_3072_MODP 0x02 -#define EAP_PAX_DH_GROUP_NIST_ECC_P_256 0x03 - -/* public_key_id: */ -#define EAP_PAX_PUBLIC_KEY_NONE 0x00 -#define EAP_PAX_PUBLIC_KEY_RSAES_OAEP 0x01 -#define EAP_PAX_PUBLIC_KEY_RSA_PKCS1_V1_5 0x02 -#define EAP_PAX_PUBLIC_KEY_EL_GAMAL_NIST_ECC 0x03 - -/* ADE type: */ -#define EAP_PAX_ADE_VENDOR_SPECIFIC 0x01 -#define EAP_PAX_ADE_CLIENT_CHANNEL_BINDING 0x02 -#define EAP_PAX_ADE_SERVER_CHANNEL_BINDING 0x03 - - -#define EAP_PAX_RAND_LEN 32 -#define EAP_PAX_MAC_LEN 16 -#define EAP_PAX_ICV_LEN 16 -#define EAP_PAX_AK_LEN 16 -#define EAP_PAX_MK_LEN 16 -#define EAP_PAX_CK_LEN 16 -#define EAP_PAX_ICK_LEN 16 - - -int eap_pax_kdf(u8 mac_id, const u8 *key, size_t key_len, - const char *identifier, - const u8 *entropy, size_t entropy_len, - size_t output_len, u8 *output); -int eap_pax_mac(u8 mac_id, const u8 *key, size_t key_len, - const u8 *data1, size_t data1_len, - const u8 *data2, size_t data2_len, - const u8 *data3, size_t data3_len, - u8 *mac); -int eap_pax_initial_key_derivation(u8 mac_id, const u8 *ak, const u8 *e, - u8 *mk, u8 *ck, u8 *ick); - -#endif /* EAP_PAX_COMMON_H */ diff --git a/contrib/hostapd/src/eap_common/eap_peap_common.c b/contrib/hostapd/src/eap_common/eap_peap_common.c deleted file mode 100644 index 14625f9639..0000000000 --- a/contrib/hostapd/src/eap_common/eap_peap_common.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * EAP-PEAP common routines - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha1.h" -#include "eap_peap_common.h" - -void peap_prfplus(int version, const u8 *key, size_t key_len, - const char *label, const u8 *seed, size_t seed_len, - u8 *buf, size_t buf_len) -{ - unsigned char counter = 0; - size_t pos, plen; - u8 hash[SHA1_MAC_LEN]; - size_t label_len = os_strlen(label); - u8 extra[2]; - const unsigned char *addr[5]; - size_t len[5]; - - addr[0] = hash; - len[0] = 0; - addr[1] = (unsigned char *) label; - len[1] = label_len; - addr[2] = seed; - len[2] = seed_len; - - if (version == 0) { - /* - * PRF+(K, S, LEN) = T1 | T2 | ... | Tn - * T1 = HMAC-SHA1(K, S | 0x01 | 0x00 | 0x00) - * T2 = HMAC-SHA1(K, T1 | S | 0x02 | 0x00 | 0x00) - * ... - * Tn = HMAC-SHA1(K, Tn-1 | S | n | 0x00 | 0x00) - */ - - extra[0] = 0; - extra[1] = 0; - - addr[3] = &counter; - len[3] = 1; - addr[4] = extra; - len[4] = 2; - } else { - /* - * PRF (K,S,LEN) = T1 | T2 | T3 | T4 | ... where: - * T1 = HMAC-SHA1(K, S | LEN | 0x01) - * T2 = HMAC-SHA1 (K, T1 | S | LEN | 0x02) - * T3 = HMAC-SHA1 (K, T2 | S | LEN | 0x03) - * T4 = HMAC-SHA1 (K, T3 | S | LEN | 0x04) - * ... - */ - - extra[0] = buf_len & 0xff; - - addr[3] = extra; - len[3] = 1; - addr[4] = &counter; - len[4] = 1; - } - - pos = 0; - while (pos < buf_len) { - counter++; - plen = buf_len - pos; - hmac_sha1_vector(key, key_len, 5, addr, len, hash); - if (plen >= SHA1_MAC_LEN) { - os_memcpy(&buf[pos], hash, SHA1_MAC_LEN); - pos += SHA1_MAC_LEN; - } else { - os_memcpy(&buf[pos], hash, plen); - break; - } - len[0] = SHA1_MAC_LEN; - } -} diff --git a/contrib/hostapd/src/eap_common/eap_peap_common.h b/contrib/hostapd/src/eap_common/eap_peap_common.h deleted file mode 100644 index f59afb07d0..0000000000 --- a/contrib/hostapd/src/eap_common/eap_peap_common.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * EAP-PEAP common routines - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_PEAP_COMMON_H -#define EAP_PEAP_COMMON_H - -void peap_prfplus(int version, const u8 *key, size_t key_len, - const char *label, const u8 *seed, size_t seed_len, - u8 *buf, size_t buf_len); - -#endif /* EAP_PEAP_COMMON_H */ diff --git a/contrib/hostapd/src/eap_common/eap_psk_common.c b/contrib/hostapd/src/eap_common/eap_psk_common.c deleted file mode 100644 index 0def3e8853..0000000000 --- a/contrib/hostapd/src/eap_common/eap_psk_common.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * EAP server/peer: EAP-PSK shared routines - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "aes_wrap.h" -#include "eap_defs.h" -#include "eap_psk_common.h" - -#define aes_block_size 16 - - -int eap_psk_key_setup(const u8 *psk, u8 *ak, u8 *kdk) -{ - os_memset(ak, 0, aes_block_size); - if (aes_128_encrypt_block(psk, ak, ak)) - return -1; - os_memcpy(kdk, ak, aes_block_size); - ak[aes_block_size - 1] ^= 0x01; - kdk[aes_block_size - 1] ^= 0x02; - if (aes_128_encrypt_block(psk, ak, ak) || - aes_128_encrypt_block(psk, kdk, kdk)) - return -1; - return 0; -} - - -int eap_psk_derive_keys(const u8 *kdk, const u8 *rand_p, u8 *tek, u8 *msk, - u8 *emsk) -{ - u8 hash[aes_block_size]; - u8 counter = 1; - int i; - - if (aes_128_encrypt_block(kdk, rand_p, hash)) - return -1; - - hash[aes_block_size - 1] ^= counter; - if (aes_128_encrypt_block(kdk, hash, tek)) - return -1; - hash[aes_block_size - 1] ^= counter; - counter++; - - for (i = 0; i < EAP_MSK_LEN / aes_block_size; i++) { - hash[aes_block_size - 1] ^= counter; - if (aes_128_encrypt_block(kdk, hash, &msk[i * aes_block_size])) - return -1; - hash[aes_block_size - 1] ^= counter; - counter++; - } - - for (i = 0; i < EAP_EMSK_LEN / aes_block_size; i++) { - hash[aes_block_size - 1] ^= counter; - if (aes_128_encrypt_block(kdk, hash, - &emsk[i * aes_block_size])) - return -1; - hash[aes_block_size - 1] ^= counter; - counter++; - } - - return 0; -} diff --git a/contrib/hostapd/src/eap_common/eap_psk_common.h b/contrib/hostapd/src/eap_common/eap_psk_common.h deleted file mode 100644 index 8adc0541ee..0000000000 --- a/contrib/hostapd/src/eap_common/eap_psk_common.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * EAP server/peer: EAP-PSK shared routines - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_PSK_COMMON_H -#define EAP_PSK_COMMON_H - - -#define EAP_PSK_RAND_LEN 16 -#define EAP_PSK_MAC_LEN 16 -#define EAP_PSK_TEK_LEN 16 -#define EAP_PSK_PSK_LEN 16 -#define EAP_PSK_AK_LEN 16 -#define EAP_PSK_KDK_LEN 16 - -#define EAP_PSK_R_FLAG_CONT 1 -#define EAP_PSK_R_FLAG_DONE_SUCCESS 2 -#define EAP_PSK_R_FLAG_DONE_FAILURE 3 -#define EAP_PSK_E_FLAG 0x20 - -#define EAP_PSK_FLAGS_GET_T(flags) (((flags) & 0xc0) >> 6) -#define EAP_PSK_FLAGS_SET_T(t) ((u8) (t) << 6) - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -/* EAP-PSK First Message (AS -> Supplicant) */ -struct eap_psk_hdr_1 { - u8 flags; - u8 rand_s[EAP_PSK_RAND_LEN]; - /* Followed by variable length ID_S */ -} STRUCT_PACKED; - -/* EAP-PSK Second Message (Supplicant -> AS) */ -struct eap_psk_hdr_2 { - u8 flags; - u8 rand_s[EAP_PSK_RAND_LEN]; - u8 rand_p[EAP_PSK_RAND_LEN]; - u8 mac_p[EAP_PSK_MAC_LEN]; - /* Followed by variable length ID_P */ -} STRUCT_PACKED; - -/* EAP-PSK Third Message (AS -> Supplicant) */ -struct eap_psk_hdr_3 { - u8 flags; - u8 rand_s[EAP_PSK_RAND_LEN]; - u8 mac_s[EAP_PSK_MAC_LEN]; - /* Followed by variable length PCHANNEL */ -} STRUCT_PACKED; - -/* EAP-PSK Fourth Message (Supplicant -> AS) */ -struct eap_psk_hdr_4 { - u8 flags; - u8 rand_s[EAP_PSK_RAND_LEN]; - /* Followed by variable length PCHANNEL */ -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -int __must_check eap_psk_key_setup(const u8 *psk, u8 *ak, u8 *kdk); -int __must_check eap_psk_derive_keys(const u8 *kdk, const u8 *rand_p, u8 *tek, - u8 *msk, u8 *emsk); - -#endif /* EAP_PSK_COMMON_H */ diff --git a/contrib/hostapd/src/eap_common/eap_sake_common.c b/contrib/hostapd/src/eap_common/eap_sake_common.c deleted file mode 100644 index eafad1d117..0000000000 --- a/contrib/hostapd/src/eap_common/eap_sake_common.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * EAP server/peer: EAP-SAKE shared routines - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha1.h" -#include "wpabuf.h" -#include "eap_defs.h" -#include "eap_sake_common.h" - - -static int eap_sake_parse_add_attr(struct eap_sake_parse_attr *attr, - const u8 *pos) -{ - size_t i; - - switch (pos[0]) { - case EAP_SAKE_AT_RAND_S: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_RAND_S"); - if (pos[1] != 2 + EAP_SAKE_RAND_LEN) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: AT_RAND_S with " - "invalid length %d", pos[1]); - return -1; - } - attr->rand_s = pos + 2; - break; - case EAP_SAKE_AT_RAND_P: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_RAND_P"); - if (pos[1] != 2 + EAP_SAKE_RAND_LEN) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: AT_RAND_P with " - "invalid length %d", pos[1]); - return -1; - } - attr->rand_p = pos + 2; - break; - case EAP_SAKE_AT_MIC_S: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_MIC_S"); - if (pos[1] != 2 + EAP_SAKE_MIC_LEN) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: AT_MIC_S with " - "invalid length %d", pos[1]); - return -1; - } - attr->mic_s = pos + 2; - break; - case EAP_SAKE_AT_MIC_P: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_MIC_P"); - if (pos[1] != 2 + EAP_SAKE_MIC_LEN) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: AT_MIC_P with " - "invalid length %d", pos[1]); - return -1; - } - attr->mic_p = pos + 2; - break; - case EAP_SAKE_AT_SERVERID: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_SERVERID"); - attr->serverid = pos + 2; - attr->serverid_len = pos[1] - 2; - break; - case EAP_SAKE_AT_PEERID: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_PEERID"); - attr->peerid = pos + 2; - attr->peerid_len = pos[1] - 2; - break; - case EAP_SAKE_AT_SPI_S: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_SPI_S"); - attr->spi_s = pos + 2; - attr->spi_s_len = pos[1] - 2; - break; - case EAP_SAKE_AT_SPI_P: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_SPI_P"); - attr->spi_p = pos + 2; - attr->spi_p_len = pos[1] - 2; - break; - case EAP_SAKE_AT_ANY_ID_REQ: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_ANY_ID_REQ"); - if (pos[1] != 4) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: Invalid AT_ANY_ID_REQ" - " length %d", pos[1]); - return -1; - } - attr->any_id_req = pos + 2; - break; - case EAP_SAKE_AT_PERM_ID_REQ: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_PERM_ID_REQ"); - if (pos[1] != 4) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: Invalid " - "AT_PERM_ID_REQ length %d", pos[1]); - return -1; - } - attr->perm_id_req = pos + 2; - break; - case EAP_SAKE_AT_ENCR_DATA: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_ENCR_DATA"); - attr->encr_data = pos + 2; - attr->encr_data_len = pos[1] - 2; - break; - case EAP_SAKE_AT_IV: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_IV"); - attr->iv = pos + 2; - attr->iv_len = pos[1] - 2; - break; - case EAP_SAKE_AT_PADDING: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_PADDING"); - for (i = 2; i < pos[1]; i++) { - if (pos[i]) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: AT_PADDING " - "with non-zero pad byte"); - return -1; - } - } - break; - case EAP_SAKE_AT_NEXT_TMPID: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_NEXT_TMPID"); - attr->next_tmpid = pos + 2; - attr->next_tmpid_len = pos[1] - 2; - break; - case EAP_SAKE_AT_MSK_LIFE: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_IV"); - if (pos[1] != 6) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: Invalid " - "AT_MSK_LIFE length %d", pos[1]); - return -1; - } - attr->msk_life = pos + 2; - break; - default: - if (pos[0] < 128) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: Unknown non-skippable" - " attribute %d", pos[0]); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-SAKE: Ignoring unknown skippable " - "attribute %d", pos[0]); - break; - } - - if (attr->iv && !attr->encr_data) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: AT_IV included without " - "AT_ENCR_DATA"); - return -1; - } - - return 0; -} - - -/** - * eap_sake_parse_attributes - Parse EAP-SAKE attributes - * @buf: Packet payload (starting with the first attribute) - * @len: Payload length - * @attr: Structure to be filled with found attributes - * Returns: 0 on success or -1 on failure - */ -int eap_sake_parse_attributes(const u8 *buf, size_t len, - struct eap_sake_parse_attr *attr) -{ - const u8 *pos = buf, *end = buf + len; - - os_memset(attr, 0, sizeof(*attr)); - while (pos < end) { - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: Too short attribute"); - return -1; - } - - if (pos[1] < 2) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: Invalid attribute " - "length (%d)", pos[1]); - return -1; - } - - if (pos + pos[1] > end) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: Attribute underflow"); - return -1; - } - - if (eap_sake_parse_add_attr(attr, pos)) - return -1; - - pos += pos[1]; - } - - return 0; -} - - -/** - * eap_sake_kdf - EAP-SAKE Key Derivation Function (KDF) - * @key: Key for KDF - * @key_len: Length of the key in bytes - * @label: A unique label for each purpose of the KDF - * @data: Extra data (start) to bind into the key - * @data_len: Length of the data - * @data2: Extra data (end) to bind into the key - * @data2_len: Length of the data2 - * @buf: Buffer for the generated pseudo-random key - * @buf_len: Number of bytes of key to generate - * - * This function is used to derive new, cryptographically separate keys from a - * given key (e.g., SMS). This is identical to the PRF used in IEEE 802.11i. - */ -static void eap_sake_kdf(const u8 *key, size_t key_len, const char *label, - const u8 *data, size_t data_len, - const u8 *data2, size_t data2_len, - u8 *buf, size_t buf_len) -{ - u8 counter = 0; - size_t pos, plen; - u8 hash[SHA1_MAC_LEN]; - size_t label_len = os_strlen(label) + 1; - const unsigned char *addr[4]; - size_t len[4]; - - addr[0] = (u8 *) label; /* Label | Y */ - len[0] = label_len; - addr[1] = data; /* Msg[start] */ - len[1] = data_len; - addr[2] = data2; /* Msg[end] */ - len[2] = data2_len; - addr[3] = &counter; /* Length */ - len[3] = 1; - - pos = 0; - while (pos < buf_len) { - plen = buf_len - pos; - if (plen >= SHA1_MAC_LEN) { - hmac_sha1_vector(key, key_len, 4, addr, len, - &buf[pos]); - pos += SHA1_MAC_LEN; - } else { - hmac_sha1_vector(key, key_len, 4, addr, len, - hash); - os_memcpy(&buf[pos], hash, plen); - break; - } - counter++; - } -} - - -/** - * eap_sake_derive_keys - Derive EAP-SAKE keys - * @root_secret_a: 16-byte Root-Secret-A - * @root_secret_b: 16-byte Root-Secret-B - * @rand_s: 16-byte RAND_S - * @rand_p: 16-byte RAND_P - * @tek: Buffer for Temporary EAK Keys (TEK-Auth[16] | TEK-Cipher[16]) - * @msk: Buffer for 64-byte MSK - * @emsk: Buffer for 64-byte EMSK - * - * This function derives EAP-SAKE keys as defined in RFC 4763, section 3.2.6. - */ -void eap_sake_derive_keys(const u8 *root_secret_a, const u8 *root_secret_b, - const u8 *rand_s, const u8 *rand_p, u8 *tek, u8 *msk, - u8 *emsk) -{ - u8 sms_a[EAP_SAKE_SMS_LEN]; - u8 sms_b[EAP_SAKE_SMS_LEN]; - u8 key_buf[EAP_MSK_LEN + EAP_EMSK_LEN]; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Deriving keys"); - - wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: Root-Secret-A", - root_secret_a, EAP_SAKE_ROOT_SECRET_LEN); - eap_sake_kdf(root_secret_a, EAP_SAKE_ROOT_SECRET_LEN, - "SAKE Master Secret A", - rand_p, EAP_SAKE_RAND_LEN, rand_s, EAP_SAKE_RAND_LEN, - sms_a, EAP_SAKE_SMS_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: SMS-A", sms_a, EAP_SAKE_SMS_LEN); - eap_sake_kdf(sms_a, EAP_SAKE_SMS_LEN, "Transient EAP Key", - rand_s, EAP_SAKE_RAND_LEN, rand_p, EAP_SAKE_RAND_LEN, - tek, EAP_SAKE_TEK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: TEK-Auth", - tek, EAP_SAKE_TEK_AUTH_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: TEK-Cipher", - tek + EAP_SAKE_TEK_AUTH_LEN, EAP_SAKE_TEK_CIPHER_LEN); - - wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: Root-Secret-B", - root_secret_b, EAP_SAKE_ROOT_SECRET_LEN); - eap_sake_kdf(root_secret_b, EAP_SAKE_ROOT_SECRET_LEN, - "SAKE Master Secret B", - rand_p, EAP_SAKE_RAND_LEN, rand_s, EAP_SAKE_RAND_LEN, - sms_b, EAP_SAKE_SMS_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: SMS-B", sms_b, EAP_SAKE_SMS_LEN); - eap_sake_kdf(sms_b, EAP_SAKE_SMS_LEN, "Master Session Key", - rand_s, EAP_SAKE_RAND_LEN, rand_p, EAP_SAKE_RAND_LEN, - key_buf, sizeof(key_buf)); - os_memcpy(msk, key_buf, EAP_MSK_LEN); - os_memcpy(emsk, key_buf + EAP_MSK_LEN, EAP_EMSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: MSK", msk, EAP_MSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: EMSK", emsk, EAP_EMSK_LEN); -} - - -/** - * eap_sake_compute_mic - Compute EAP-SAKE MIC for an EAP packet - * @tek_auth: 16-byte TEK-Auth - * @rand_s: 16-byte RAND_S - * @rand_p: 16-byte RAND_P - * @serverid: SERVERID - * @serverid_len: SERVERID length - * @peerid: PEERID - * @peerid_len: PEERID length - * @peer: MIC calculation for 0 = Server, 1 = Peer message - * @eap: EAP packet - * @eap_len: EAP packet length - * @mic_pos: MIC position in the EAP packet (must be [eap .. eap + eap_len]) - * @mic: Buffer for the computed 16-byte MIC - */ -int eap_sake_compute_mic(const u8 *tek_auth, - const u8 *rand_s, const u8 *rand_p, - const u8 *serverid, size_t serverid_len, - const u8 *peerid, size_t peerid_len, - int peer, const u8 *eap, size_t eap_len, - const u8 *mic_pos, u8 *mic) -{ - u8 _rand[2 * EAP_SAKE_RAND_LEN]; - u8 *tmp, *pos; - size_t tmplen; - - tmplen = serverid_len + 1 + peerid_len + 1 + eap_len; - tmp = os_malloc(tmplen); - if (tmp == NULL) - return -1; - pos = tmp; - if (peer) { - if (peerid) { - os_memcpy(pos, peerid, peerid_len); - pos += peerid_len; - } - *pos++ = 0x00; - if (serverid) { - os_memcpy(pos, serverid, serverid_len); - pos += serverid_len; - } - *pos++ = 0x00; - - os_memcpy(_rand, rand_s, EAP_SAKE_RAND_LEN); - os_memcpy(_rand + EAP_SAKE_RAND_LEN, rand_p, - EAP_SAKE_RAND_LEN); - } else { - if (serverid) { - os_memcpy(pos, serverid, serverid_len); - pos += serverid_len; - } - *pos++ = 0x00; - if (peerid) { - os_memcpy(pos, peerid, peerid_len); - pos += peerid_len; - } - *pos++ = 0x00; - - os_memcpy(_rand, rand_p, EAP_SAKE_RAND_LEN); - os_memcpy(_rand + EAP_SAKE_RAND_LEN, rand_s, - EAP_SAKE_RAND_LEN); - } - - os_memcpy(pos, eap, eap_len); - os_memset(pos + (mic_pos - eap), 0, EAP_SAKE_MIC_LEN); - - eap_sake_kdf(tek_auth, EAP_SAKE_TEK_AUTH_LEN, - peer ? "Peer MIC" : "Server MIC", - _rand, 2 * EAP_SAKE_RAND_LEN, tmp, tmplen, - mic, EAP_SAKE_MIC_LEN); - - os_free(tmp); - - return 0; -} - - -void eap_sake_add_attr(struct wpabuf *buf, u8 type, const u8 *data, - size_t len) -{ - wpabuf_put_u8(buf, type); - wpabuf_put_u8(buf, 2 + len); /* Length; including attr header */ - if (data) - wpabuf_put_data(buf, data, len); - else - os_memset(wpabuf_put(buf, len), 0, len); -} diff --git a/contrib/hostapd/src/eap_common/eap_sake_common.h b/contrib/hostapd/src/eap_common/eap_sake_common.h deleted file mode 100644 index 201e20729c..0000000000 --- a/contrib/hostapd/src/eap_common/eap_sake_common.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * EAP server/peer: EAP-SAKE shared routines - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_SAKE_COMMON_H -#define EAP_SAKE_COMMON_H - -#define EAP_SAKE_VERSION 2 - -#define EAP_SAKE_SUBTYPE_CHALLENGE 1 -#define EAP_SAKE_SUBTYPE_CONFIRM 2 -#define EAP_SAKE_SUBTYPE_AUTH_REJECT 3 -#define EAP_SAKE_SUBTYPE_IDENTITY 4 - -#define EAP_SAKE_AT_RAND_S 1 -#define EAP_SAKE_AT_RAND_P 2 -#define EAP_SAKE_AT_MIC_S 3 -#define EAP_SAKE_AT_MIC_P 4 -#define EAP_SAKE_AT_SERVERID 5 -#define EAP_SAKE_AT_PEERID 6 -#define EAP_SAKE_AT_SPI_S 7 -#define EAP_SAKE_AT_SPI_P 8 -#define EAP_SAKE_AT_ANY_ID_REQ 9 -#define EAP_SAKE_AT_PERM_ID_REQ 10 -#define EAP_SAKE_AT_ENCR_DATA 128 -#define EAP_SAKE_AT_IV 129 -#define EAP_SAKE_AT_PADDING 130 -#define EAP_SAKE_AT_NEXT_TMPID 131 -#define EAP_SAKE_AT_MSK_LIFE 132 - -#define EAP_SAKE_RAND_LEN 16 -#define EAP_SAKE_MIC_LEN 16 -#define EAP_SAKE_ROOT_SECRET_LEN 16 -#define EAP_SAKE_SMS_LEN 16 -#define EAP_SAKE_TEK_AUTH_LEN 16 -#define EAP_SAKE_TEK_CIPHER_LEN 16 -#define EAP_SAKE_TEK_LEN (EAP_SAKE_TEK_AUTH_LEN + EAP_SAKE_TEK_CIPHER_LEN) - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct eap_sake_hdr { - u8 version; /* EAP_SAKE_VERSION */ - u8 session_id; - u8 subtype; -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -struct eap_sake_parse_attr { - const u8 *rand_s; - const u8 *rand_p; - const u8 *mic_s; - const u8 *mic_p; - const u8 *serverid; - size_t serverid_len; - const u8 *peerid; - size_t peerid_len; - const u8 *spi_s; - size_t spi_s_len; - const u8 *spi_p; - size_t spi_p_len; - const u8 *any_id_req; - const u8 *perm_id_req; - const u8 *encr_data; - size_t encr_data_len; - const u8 *iv; - size_t iv_len; - const u8 *next_tmpid; - size_t next_tmpid_len; - const u8 *msk_life; -}; - -int eap_sake_parse_attributes(const u8 *buf, size_t len, - struct eap_sake_parse_attr *attr); -void eap_sake_derive_keys(const u8 *root_secret_a, const u8 *root_secret_b, - const u8 *rand_s, const u8 *rand_p, - u8 *tek, u8 *msk, u8 *emsk); -int eap_sake_compute_mic(const u8 *tek_auth, - const u8 *rand_s, const u8 *rand_p, - const u8 *serverid, size_t serverid_len, - const u8 *peerid, size_t peerid_len, - int peer, const u8 *eap, size_t eap_len, - const u8 *mic_pos, u8 *mic); -void eap_sake_add_attr(struct wpabuf *buf, u8 type, const u8 *data, - size_t len); - -#endif /* EAP_SAKE_COMMON_H */ diff --git a/contrib/hostapd/src/eap_common/eap_sim_common.c b/contrib/hostapd/src/eap_common/eap_sim_common.c deleted file mode 100644 index fccda02417..0000000000 --- a/contrib/hostapd/src/eap_common/eap_sim_common.c +++ /dev/null @@ -1,1214 +0,0 @@ -/* - * EAP peer/server: EAP-SIM/AKA/AKA' shared routines - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_common/eap_defs.h" -#include "sha1.h" -#include "sha256.h" -#include "crypto.h" -#include "aes_wrap.h" -#include "wpabuf.h" -#include "eap_common/eap_sim_common.h" - - -static int eap_sim_prf(const u8 *key, u8 *x, size_t xlen) -{ - return fips186_2_prf(key, EAP_SIM_MK_LEN, x, xlen); -} - - -void eap_sim_derive_mk(const u8 *identity, size_t identity_len, - const u8 *nonce_mt, u16 selected_version, - const u8 *ver_list, size_t ver_list_len, - int num_chal, const u8 *kc, u8 *mk) -{ - u8 sel_ver[2]; - const unsigned char *addr[5]; - size_t len[5]; - - addr[0] = identity; - len[0] = identity_len; - addr[1] = kc; - len[1] = num_chal * EAP_SIM_KC_LEN; - addr[2] = nonce_mt; - len[2] = EAP_SIM_NONCE_MT_LEN; - addr[3] = ver_list; - len[3] = ver_list_len; - addr[4] = sel_ver; - len[4] = 2; - - WPA_PUT_BE16(sel_ver, selected_version); - - /* MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */ - sha1_vector(5, addr, len, mk); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN); -} - - -void eap_aka_derive_mk(const u8 *identity, size_t identity_len, - const u8 *ik, const u8 *ck, u8 *mk) -{ - const u8 *addr[3]; - size_t len[3]; - - addr[0] = identity; - len[0] = identity_len; - addr[1] = ik; - len[1] = EAP_AKA_IK_LEN; - addr[2] = ck; - len[2] = EAP_AKA_CK_LEN; - - /* MK = SHA1(Identity|IK|CK) */ - sha1_vector(3, addr, len, mk); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: IK", ik, EAP_AKA_IK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: CK", ck, EAP_AKA_CK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: MK", mk, EAP_SIM_MK_LEN); -} - - -int eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk, u8 *emsk) -{ - u8 buf[EAP_SIM_K_ENCR_LEN + EAP_SIM_K_AUT_LEN + - EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN], *pos; - if (eap_sim_prf(mk, buf, sizeof(buf)) < 0) { - wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys"); - return -1; - } - pos = buf; - os_memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN); - pos += EAP_SIM_K_ENCR_LEN; - os_memcpy(k_aut, pos, EAP_SIM_K_AUT_LEN); - pos += EAP_SIM_K_AUT_LEN; - os_memcpy(msk, pos, EAP_SIM_KEYING_DATA_LEN); - pos += EAP_SIM_KEYING_DATA_LEN; - os_memcpy(emsk, pos, EAP_EMSK_LEN); - - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_encr", - k_encr, EAP_SIM_K_ENCR_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_aut", - k_aut, EAP_SIM_K_AUT_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: keying material (MSK)", - msk, EAP_SIM_KEYING_DATA_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN); - os_memset(buf, 0, sizeof(buf)); - - return 0; -} - - -int eap_sim_derive_keys_reauth(u16 _counter, - const u8 *identity, size_t identity_len, - const u8 *nonce_s, const u8 *mk, u8 *msk, - u8 *emsk) -{ - u8 xkey[SHA1_MAC_LEN]; - u8 buf[EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN + 32]; - u8 counter[2]; - const u8 *addr[4]; - size_t len[4]; - - while (identity_len > 0 && identity[identity_len - 1] == 0) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop null " - "character from the end of identity"); - identity_len--; - } - addr[0] = identity; - len[0] = identity_len; - addr[1] = counter; - len[1] = 2; - addr[2] = nonce_s; - len[2] = EAP_SIM_NONCE_S_LEN; - addr[3] = mk; - len[3] = EAP_SIM_MK_LEN; - - WPA_PUT_BE16(counter, _counter); - - wpa_printf(MSG_DEBUG, "EAP-SIM: Deriving keying data from reauth"); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity", - identity, identity_len); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: counter", counter, 2); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: NONCE_S", nonce_s, - EAP_SIM_NONCE_S_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN); - - /* XKEY' = SHA1(Identity|counter|NONCE_S|MK) */ - sha1_vector(4, addr, len, xkey); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: XKEY'", xkey, SHA1_MAC_LEN); - - if (eap_sim_prf(xkey, buf, sizeof(buf)) < 0) { - wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys"); - return -1; - } - if (msk) { - os_memcpy(msk, buf, EAP_SIM_KEYING_DATA_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: keying material (MSK)", - msk, EAP_SIM_KEYING_DATA_LEN); - } - if (emsk) { - os_memcpy(emsk, buf + EAP_SIM_KEYING_DATA_LEN, EAP_EMSK_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN); - } - os_memset(buf, 0, sizeof(buf)); - - return 0; -} - - -int eap_sim_verify_mac(const u8 *k_aut, const struct wpabuf *req, - const u8 *mac, const u8 *extra, size_t extra_len) -{ - unsigned char hmac[SHA1_MAC_LEN]; - const u8 *addr[2]; - size_t len[2]; - u8 *tmp; - - if (mac == NULL || wpabuf_len(req) < EAP_SIM_MAC_LEN || - mac < wpabuf_head_u8(req) || - mac > wpabuf_head_u8(req) + wpabuf_len(req) - EAP_SIM_MAC_LEN) - return -1; - - tmp = os_malloc(wpabuf_len(req)); - if (tmp == NULL) - return -1; - - addr[0] = tmp; - len[0] = wpabuf_len(req); - addr[1] = extra; - len[1] = extra_len; - - /* HMAC-SHA1-128 */ - os_memcpy(tmp, wpabuf_head(req), wpabuf_len(req)); - os_memset(tmp + (mac - wpabuf_head_u8(req)), 0, EAP_SIM_MAC_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - msg", - tmp, wpabuf_len(req)); - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - extra data", - extra, extra_len); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Verify MAC - K_aut", - k_aut, EAP_SIM_K_AUT_LEN); - hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac); - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC: MAC", - hmac, EAP_SIM_MAC_LEN); - os_free(tmp); - - return (os_memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1; -} - - -void eap_sim_add_mac(const u8 *k_aut, const u8 *msg, size_t msg_len, u8 *mac, - const u8 *extra, size_t extra_len) -{ - unsigned char hmac[SHA1_MAC_LEN]; - const u8 *addr[2]; - size_t len[2]; - - addr[0] = msg; - len[0] = msg_len; - addr[1] = extra; - len[1] = extra_len; - - /* HMAC-SHA1-128 */ - os_memset(mac, 0, EAP_SIM_MAC_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - msg", msg, msg_len); - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - extra data", - extra, extra_len); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Add MAC - K_aut", - k_aut, EAP_SIM_K_AUT_LEN); - hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac); - os_memcpy(mac, hmac, EAP_SIM_MAC_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC: MAC", - mac, EAP_SIM_MAC_LEN); -} - - -#ifdef EAP_AKA_PRIME -static void prf_prime(const u8 *k, const char *seed1, - const u8 *seed2, size_t seed2_len, - const u8 *seed3, size_t seed3_len, - u8 *res, size_t res_len) -{ - const u8 *addr[5]; - size_t len[5]; - u8 hash[SHA256_MAC_LEN]; - u8 iter; - - /* - * PRF'(K,S) = T1 | T2 | T3 | T4 | ... - * T1 = HMAC-SHA-256 (K, S | 0x01) - * T2 = HMAC-SHA-256 (K, T1 | S | 0x02) - * T3 = HMAC-SHA-256 (K, T2 | S | 0x03) - * T4 = HMAC-SHA-256 (K, T3 | S | 0x04) - * ... - */ - - addr[0] = hash; - len[0] = 0; - addr[1] = (const u8 *) seed1; - len[1] = os_strlen(seed1); - addr[2] = seed2; - len[2] = seed2_len; - addr[3] = seed3; - len[3] = seed3_len; - addr[4] = &iter; - len[4] = 1; - - iter = 0; - while (res_len) { - size_t hlen; - iter++; - hmac_sha256_vector(k, 32, 5, addr, len, hash); - len[0] = SHA256_MAC_LEN; - hlen = res_len > SHA256_MAC_LEN ? SHA256_MAC_LEN : res_len; - os_memcpy(res, hash, hlen); - res += hlen; - res_len -= hlen; - } -} - - -void eap_aka_prime_derive_keys(const u8 *identity, size_t identity_len, - const u8 *ik, const u8 *ck, u8 *k_encr, - u8 *k_aut, u8 *k_re, u8 *msk, u8 *emsk) -{ - u8 key[EAP_AKA_IK_LEN + EAP_AKA_CK_LEN]; - u8 keys[EAP_SIM_K_ENCR_LEN + EAP_AKA_PRIME_K_AUT_LEN + - EAP_AKA_PRIME_K_RE_LEN + EAP_MSK_LEN + EAP_EMSK_LEN]; - u8 *pos; - - /* - * MK = PRF'(IK'|CK',"EAP-AKA'"|Identity) - * K_encr = MK[0..127] - * K_aut = MK[128..383] - * K_re = MK[384..639] - * MSK = MK[640..1151] - * EMSK = MK[1152..1663] - */ - - os_memcpy(key, ik, EAP_AKA_IK_LEN); - os_memcpy(key + EAP_AKA_IK_LEN, ck, EAP_AKA_CK_LEN); - - prf_prime(key, "EAP-AKA'", identity, identity_len, NULL, 0, - keys, sizeof(keys)); - - pos = keys; - os_memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': K_encr", - k_encr, EAP_SIM_K_ENCR_LEN); - pos += EAP_SIM_K_ENCR_LEN; - - os_memcpy(k_aut, pos, EAP_AKA_PRIME_K_AUT_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': K_aut", - k_aut, EAP_AKA_PRIME_K_AUT_LEN); - pos += EAP_AKA_PRIME_K_AUT_LEN; - - os_memcpy(k_re, pos, EAP_AKA_PRIME_K_RE_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': K_re", - k_re, EAP_AKA_PRIME_K_RE_LEN); - pos += EAP_AKA_PRIME_K_RE_LEN; - - os_memcpy(msk, pos, EAP_MSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': MSK", msk, EAP_MSK_LEN); - pos += EAP_MSK_LEN; - - os_memcpy(emsk, pos, EAP_EMSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': EMSK", emsk, EAP_EMSK_LEN); -} - - -int eap_aka_prime_derive_keys_reauth(const u8 *k_re, u16 counter, - const u8 *identity, size_t identity_len, - const u8 *nonce_s, u8 *msk, u8 *emsk) -{ - u8 seed3[2 + EAP_SIM_NONCE_S_LEN]; - u8 keys[EAP_MSK_LEN + EAP_EMSK_LEN]; - u8 *pos; - - /* - * MK = PRF'(K_re,"EAP-AKA' re-auth"|Identity|counter|NONCE_S) - * MSK = MK[0..511] - * EMSK = MK[512..1023] - */ - - WPA_PUT_BE16(seed3, counter); - os_memcpy(seed3 + 2, nonce_s, EAP_SIM_NONCE_S_LEN); - - prf_prime(k_re, "EAP-AKA' re-auth", identity, identity_len, - seed3, sizeof(seed3), - keys, sizeof(keys)); - - pos = keys; - os_memcpy(msk, pos, EAP_MSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': MSK", msk, EAP_MSK_LEN); - pos += EAP_MSK_LEN; - - os_memcpy(emsk, pos, EAP_EMSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': EMSK", emsk, EAP_EMSK_LEN); - - os_memset(keys, 0, sizeof(keys)); - - return 0; -} - - -int eap_sim_verify_mac_sha256(const u8 *k_aut, const struct wpabuf *req, - const u8 *mac, const u8 *extra, size_t extra_len) -{ - unsigned char hmac[SHA256_MAC_LEN]; - const u8 *addr[2]; - size_t len[2]; - u8 *tmp; - - if (mac == NULL || wpabuf_len(req) < EAP_SIM_MAC_LEN || - mac < wpabuf_head_u8(req) || - mac > wpabuf_head_u8(req) + wpabuf_len(req) - EAP_SIM_MAC_LEN) - return -1; - - tmp = os_malloc(wpabuf_len(req)); - if (tmp == NULL) - return -1; - - addr[0] = tmp; - len[0] = wpabuf_len(req); - addr[1] = extra; - len[1] = extra_len; - - /* HMAC-SHA-256-128 */ - os_memcpy(tmp, wpabuf_head(req), wpabuf_len(req)); - os_memset(tmp + (mac - wpabuf_head_u8(req)), 0, EAP_SIM_MAC_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Verify MAC - msg", - tmp, wpabuf_len(req)); - wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Verify MAC - extra data", - extra, extra_len); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA': Verify MAC - K_aut", - k_aut, EAP_AKA_PRIME_K_AUT_LEN); - hmac_sha256_vector(k_aut, EAP_AKA_PRIME_K_AUT_LEN, 2, addr, len, hmac); - wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Verify MAC: MAC", - hmac, EAP_SIM_MAC_LEN); - os_free(tmp); - - return (os_memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1; -} - - -void eap_sim_add_mac_sha256(const u8 *k_aut, const u8 *msg, size_t msg_len, - u8 *mac, const u8 *extra, size_t extra_len) -{ - unsigned char hmac[SHA256_MAC_LEN]; - const u8 *addr[2]; - size_t len[2]; - - addr[0] = msg; - len[0] = msg_len; - addr[1] = extra; - len[1] = extra_len; - - /* HMAC-SHA-256-128 */ - os_memset(mac, 0, EAP_SIM_MAC_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Add MAC - msg", msg, msg_len); - wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Add MAC - extra data", - extra, extra_len); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA': Add MAC - K_aut", - k_aut, EAP_AKA_PRIME_K_AUT_LEN); - hmac_sha256_vector(k_aut, EAP_AKA_PRIME_K_AUT_LEN, 2, addr, len, hmac); - os_memcpy(mac, hmac, EAP_SIM_MAC_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Add MAC: MAC", - mac, EAP_SIM_MAC_LEN); -} - - -void eap_aka_prime_derive_ck_ik_prime(u8 *ck, u8 *ik, const u8 *sqn_ak, - const u8 *network_name, - size_t network_name_len) -{ - u8 key[EAP_AKA_CK_LEN + EAP_AKA_IK_LEN]; - u8 hash[SHA256_MAC_LEN]; - const u8 *addr[5]; - size_t len[5]; - u8 fc; - u8 l0[2], l1[2]; - - /* 3GPP TS 33.402 V8.0.0 - * (CK', IK') = F(CK, IK, ) - */ - /* TODO: CK', IK' generation should really be moved into the actual - * AKA procedure with network name passed in there and option to use - * AMF separation bit = 1 (3GPP TS 33.401). */ - - /* Change Request 33.402 CR 0033 to version 8.1.1 from - * 3GPP TSG-SA WG3 Meeting #53 in September 2008: - * - * CK' || IK' = HMAC-SHA-256(Key, S) - * S = FC || P0 || L0 || P1 || L1 || ... || Pn || Ln - * Key = CK || IK - * FC = 0x20 - * P0 = access network identity (3GPP TS 24.302) - * L0 = length of acceess network identity (2 octets, big endian) - * P1 = SQN xor AK (if AK is not used, AK is treaded as 000..0 - * L1 = 0x00 0x06 - */ - - fc = 0x20; - - wpa_printf(MSG_DEBUG, "EAP-AKA': Derive (CK',IK') from (CK,IK)"); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': CK", ck, EAP_AKA_CK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': IK", ik, EAP_AKA_IK_LEN); - wpa_printf(MSG_DEBUG, "EAP-AKA': FC = 0x%x", fc); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA': P0 = Access network identity", - network_name, network_name_len); - wpa_hexdump(MSG_DEBUG, "EAP-AKA': P1 = SQN xor AK", sqn_ak, 6); - - os_memcpy(key, ck, EAP_AKA_CK_LEN); - os_memcpy(key + EAP_AKA_CK_LEN, ik, EAP_AKA_IK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': Key = CK || IK", - key, sizeof(key)); - - addr[0] = &fc; - len[0] = 1; - addr[1] = network_name; - len[1] = network_name_len; - WPA_PUT_BE16(l0, network_name_len); - addr[2] = l0; - len[2] = 2; - addr[3] = sqn_ak; - len[3] = 6; - WPA_PUT_BE16(l1, 6); - addr[4] = l1; - len[4] = 2; - - hmac_sha256_vector(key, sizeof(key), 5, addr, len, hash); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': KDF output (CK' || IK')", - hash, sizeof(hash)); - - os_memcpy(ck, hash, EAP_AKA_CK_LEN); - os_memcpy(ik, hash + EAP_AKA_CK_LEN, EAP_AKA_IK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': CK'", ck, EAP_AKA_CK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': IK'", ik, EAP_AKA_IK_LEN); -} -#endif /* EAP_AKA_PRIME */ - - -int eap_sim_parse_attr(const u8 *start, const u8 *end, - struct eap_sim_attrs *attr, int aka, int encr) -{ - const u8 *pos = start, *apos; - size_t alen, plen, i, list_len; - - os_memset(attr, 0, sizeof(*attr)); - attr->id_req = NO_ID_REQ; - attr->notification = -1; - attr->counter = -1; - attr->selected_version = -1; - attr->client_error_code = -1; - - while (pos < end) { - if (pos + 2 > end) { - wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow(1)"); - return -1; - } - wpa_printf(MSG_MSGDUMP, "EAP-SIM: Attribute: Type=%d Len=%d", - pos[0], pos[1] * 4); - if (pos + pos[1] * 4 > end) { - wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow " - "(pos=%p len=%d end=%p)", - pos, pos[1] * 4, end); - return -1; - } - if (pos[1] == 0) { - wpa_printf(MSG_INFO, "EAP-SIM: Attribute underflow"); - return -1; - } - apos = pos + 2; - alen = pos[1] * 4 - 2; - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Attribute data", - apos, alen); - - switch (pos[0]) { - case EAP_SIM_AT_RAND: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RAND"); - apos += 2; - alen -= 2; - if ((!aka && (alen % GSM_RAND_LEN)) || - (aka && alen != EAP_AKA_RAND_LEN)) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RAND" - " (len %lu)", - (unsigned long) alen); - return -1; - } - attr->rand = apos; - attr->num_chal = alen / GSM_RAND_LEN; - break; - case EAP_SIM_AT_AUTN: - wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTN"); - if (!aka) { - wpa_printf(MSG_DEBUG, "EAP-SIM: " - "Unexpected AT_AUTN"); - return -1; - } - apos += 2; - alen -= 2; - if (alen != EAP_AKA_AUTN_LEN) { - wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTN" - " (len %lu)", - (unsigned long) alen); - return -1; - } - attr->autn = apos; - break; - case EAP_SIM_AT_PADDING: - if (!encr) { - wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " - "AT_PADDING"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_PADDING"); - for (i = 2; i < alen; i++) { - if (apos[i] != 0) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) " - "AT_PADDING used a non-zero" - " padding byte"); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: " - "(encr) padding bytes", - apos + 2, alen - 2); - return -1; - } - } - break; - case EAP_SIM_AT_NONCE_MT: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NONCE_MT"); - if (alen != 2 + EAP_SIM_NONCE_MT_LEN) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid " - "AT_NONCE_MT length"); - return -1; - } - attr->nonce_mt = apos + 2; - break; - case EAP_SIM_AT_PERMANENT_ID_REQ: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_PERMANENT_ID_REQ"); - attr->id_req = PERMANENT_ID; - break; - case EAP_SIM_AT_MAC: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_MAC"); - if (alen != 2 + EAP_SIM_MAC_LEN) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_MAC " - "length"); - return -1; - } - attr->mac = apos + 2; - break; - case EAP_SIM_AT_NOTIFICATION: - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid " - "AT_NOTIFICATION length %lu", - (unsigned long) alen); - return -1; - } - attr->notification = apos[0] * 256 + apos[1]; - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NOTIFICATION %d", - attr->notification); - break; - case EAP_SIM_AT_ANY_ID_REQ: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ANY_ID_REQ"); - attr->id_req = ANY_ID; - break; - case EAP_SIM_AT_IDENTITY: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IDENTITY"); - plen = WPA_GET_BE16(apos); - apos += 2; - alen -= 2; - if (plen > alen) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid " - "AT_IDENTITY (Actual Length %lu, " - "remaining length %lu)", - (unsigned long) plen, - (unsigned long) alen); - return -1; - } - - attr->identity = apos; - attr->identity_len = plen; - break; - case EAP_SIM_AT_VERSION_LIST: - if (aka) { - wpa_printf(MSG_DEBUG, "EAP-AKA: " - "Unexpected AT_VERSION_LIST"); - return -1; - } - list_len = apos[0] * 256 + apos[1]; - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_VERSION_LIST"); - if (list_len < 2 || list_len > alen - 2) { - wpa_printf(MSG_WARNING, "EAP-SIM: Invalid " - "AT_VERSION_LIST (list_len=%lu " - "attr_len=%lu)", - (unsigned long) list_len, - (unsigned long) alen); - return -1; - } - attr->version_list = apos + 2; - attr->version_list_len = list_len; - break; - case EAP_SIM_AT_SELECTED_VERSION: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION"); - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid " - "AT_SELECTED_VERSION length %lu", - (unsigned long) alen); - return -1; - } - attr->selected_version = apos[0] * 256 + apos[1]; - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION " - "%d", attr->selected_version); - break; - case EAP_SIM_AT_FULLAUTH_ID_REQ: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_FULLAUTH_ID_REQ"); - attr->id_req = FULLAUTH_ID; - break; - case EAP_SIM_AT_COUNTER: - if (!encr) { - wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " - "AT_COUNTER"); - return -1; - } - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid " - "AT_COUNTER (alen=%lu)", - (unsigned long) alen); - return -1; - } - attr->counter = apos[0] * 256 + apos[1]; - wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_COUNTER %d", - attr->counter); - break; - case EAP_SIM_AT_COUNTER_TOO_SMALL: - if (!encr) { - wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " - "AT_COUNTER_TOO_SMALL"); - return -1; - } - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid " - "AT_COUNTER_TOO_SMALL (alen=%lu)", - (unsigned long) alen); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) " - "AT_COUNTER_TOO_SMALL"); - attr->counter_too_small = 1; - break; - case EAP_SIM_AT_NONCE_S: - if (!encr) { - wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " - "AT_NONCE_S"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) " - "AT_NONCE_S"); - if (alen != 2 + EAP_SIM_NONCE_S_LEN) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid " - "AT_NONCE_S (alen=%lu)", - (unsigned long) alen); - return -1; - } - attr->nonce_s = apos + 2; - break; - case EAP_SIM_AT_CLIENT_ERROR_CODE: - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid " - "AT_CLIENT_ERROR_CODE length %lu", - (unsigned long) alen); - return -1; - } - attr->client_error_code = apos[0] * 256 + apos[1]; - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_CLIENT_ERROR_CODE " - "%d", attr->client_error_code); - break; - case EAP_SIM_AT_IV: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IV"); - if (alen != 2 + EAP_SIM_MAC_LEN) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_IV " - "length %lu", (unsigned long) alen); - return -1; - } - attr->iv = apos + 2; - break; - case EAP_SIM_AT_ENCR_DATA: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ENCR_DATA"); - attr->encr_data = apos + 2; - attr->encr_data_len = alen - 2; - if (attr->encr_data_len % 16) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid " - "AT_ENCR_DATA length %lu", - (unsigned long) - attr->encr_data_len); - return -1; - } - break; - case EAP_SIM_AT_NEXT_PSEUDONYM: - if (!encr) { - wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " - "AT_NEXT_PSEUDONYM"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) " - "AT_NEXT_PSEUDONYM"); - plen = apos[0] * 256 + apos[1]; - if (plen > alen - 2) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid" - " AT_NEXT_PSEUDONYM (actual" - " len %lu, attr len %lu)", - (unsigned long) plen, - (unsigned long) alen); - return -1; - } - attr->next_pseudonym = pos + 4; - attr->next_pseudonym_len = plen; - break; - case EAP_SIM_AT_NEXT_REAUTH_ID: - if (!encr) { - wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " - "AT_NEXT_REAUTH_ID"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) " - "AT_NEXT_REAUTH_ID"); - plen = apos[0] * 256 + apos[1]; - if (plen > alen - 2) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid" - " AT_NEXT_REAUTH_ID (actual" - " len %lu, attr len %lu)", - (unsigned long) plen, - (unsigned long) alen); - return -1; - } - attr->next_reauth_id = pos + 4; - attr->next_reauth_id_len = plen; - break; - case EAP_SIM_AT_RES: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RES"); - attr->res_len_bits = WPA_GET_BE16(apos); - apos += 2; - alen -= 2; - if (!aka || alen < EAP_AKA_MIN_RES_LEN || - alen > EAP_AKA_MAX_RES_LEN) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RES " - "(len %lu)", - (unsigned long) alen); - return -1; - } - attr->res = apos; - attr->res_len = alen; - break; - case EAP_SIM_AT_AUTS: - wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTS"); - if (!aka) { - wpa_printf(MSG_DEBUG, "EAP-SIM: " - "Unexpected AT_AUTS"); - return -1; - } - if (alen != EAP_AKA_AUTS_LEN) { - wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTS" - " (len %lu)", - (unsigned long) alen); - return -1; - } - attr->auts = apos; - break; - case EAP_SIM_AT_CHECKCODE: - wpa_printf(MSG_DEBUG, "EAP-AKA: AT_CHECKCODE"); - if (!aka) { - wpa_printf(MSG_DEBUG, "EAP-SIM: " - "Unexpected AT_CHECKCODE"); - return -1; - } - apos += 2; - alen -= 2; - if (alen != 0 && alen != EAP_AKA_CHECKCODE_LEN && - alen != EAP_AKA_PRIME_CHECKCODE_LEN) { - wpa_printf(MSG_INFO, "EAP-AKA: Invalid " - "AT_CHECKCODE (len %lu)", - (unsigned long) alen); - return -1; - } - attr->checkcode = apos; - attr->checkcode_len = alen; - break; - case EAP_SIM_AT_RESULT_IND: - if (encr) { - wpa_printf(MSG_ERROR, "EAP-SIM: Encrypted " - "AT_RESULT_IND"); - return -1; - } - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid " - "AT_RESULT_IND (alen=%lu)", - (unsigned long) alen); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RESULT_IND"); - attr->result_ind = 1; - break; -#ifdef EAP_AKA_PRIME - case EAP_SIM_AT_KDF_INPUT: - if (aka != 2) { - wpa_printf(MSG_INFO, "EAP-AKA: Unexpected " - "AT_KDF_INPUT"); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-AKA: AT_KDF_INPUT"); - plen = WPA_GET_BE16(apos); - apos += 2; - alen -= 2; - if (plen > alen) { - wpa_printf(MSG_INFO, "EAP-AKA': Invalid " - "AT_KDF_INPUT (Actual Length %lu, " - "remaining length %lu)", - (unsigned long) plen, - (unsigned long) alen); - return -1; - } - attr->kdf_input = apos; - attr->kdf_input_len = plen; - break; - case EAP_SIM_AT_KDF: - if (aka != 2) { - wpa_printf(MSG_INFO, "EAP-AKA: Unexpected " - "AT_KDF"); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-AKA: AT_KDF"); - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-AKA': Invalid " - "AT_KDF (len %lu)", - (unsigned long) alen); - return -1; - } - if (attr->kdf_count == EAP_AKA_PRIME_KDF_MAX) { - wpa_printf(MSG_DEBUG, "EAP-AKA': Too many " - "AT_KDF attributes - ignore this"); - continue; - } - attr->kdf[attr->kdf_count] = WPA_GET_BE16(apos); - attr->kdf_count++; - break; - case EAP_SIM_AT_BIDDING: - wpa_printf(MSG_DEBUG, "EAP-AKA: AT_BIDDING"); - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-AKA: Invalid " - "AT_BIDDING (len %lu)", - (unsigned long) alen); - return -1; - } - attr->bidding = apos; - break; -#endif /* EAP_AKA_PRIME */ - default: - if (pos[0] < 128) { - wpa_printf(MSG_INFO, "EAP-SIM: Unrecognized " - "non-skippable attribute %d", - pos[0]); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized skippable" - " attribute %d ignored", pos[0]); - break; - } - - pos += pos[1] * 4; - } - - wpa_printf(MSG_DEBUG, "EAP-SIM: Attributes parsed successfully " - "(aka=%d encr=%d)", aka, encr); - - return 0; -} - - -u8 * eap_sim_parse_encr(const u8 *k_encr, const u8 *encr_data, - size_t encr_data_len, const u8 *iv, - struct eap_sim_attrs *attr, int aka) -{ - u8 *decrypted; - - if (!iv) { - wpa_printf(MSG_INFO, "EAP-SIM: Encrypted data, but no IV"); - return NULL; - } - - decrypted = os_malloc(encr_data_len); - if (decrypted == NULL) - return NULL; - os_memcpy(decrypted, encr_data, encr_data_len); - - if (aes_128_cbc_decrypt(k_encr, iv, decrypted, encr_data_len)) { - os_free(decrypted); - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Decrypted AT_ENCR_DATA", - decrypted, encr_data_len); - - if (eap_sim_parse_attr(decrypted, decrypted + encr_data_len, attr, - aka, 1)) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Failed to parse " - "decrypted AT_ENCR_DATA"); - os_free(decrypted); - return NULL; - } - - return decrypted; -} - - -#define EAP_SIM_INIT_LEN 128 - -struct eap_sim_msg { - struct wpabuf *buf; - size_t mac, iv, encr; /* index from buf */ - int type; -}; - - -struct eap_sim_msg * eap_sim_msg_init(int code, int id, int type, int subtype) -{ - struct eap_sim_msg *msg; - struct eap_hdr *eap; - u8 *pos; - - msg = os_zalloc(sizeof(*msg)); - if (msg == NULL) - return NULL; - - msg->type = type; - msg->buf = wpabuf_alloc(EAP_SIM_INIT_LEN); - if (msg->buf == NULL) { - os_free(msg); - return NULL; - } - eap = wpabuf_put(msg->buf, sizeof(*eap)); - eap->code = code; - eap->identifier = id; - - pos = wpabuf_put(msg->buf, 4); - *pos++ = type; - *pos++ = subtype; - *pos++ = 0; /* Reserved */ - *pos++ = 0; /* Reserved */ - - return msg; -} - - -struct wpabuf * eap_sim_msg_finish(struct eap_sim_msg *msg, const u8 *k_aut, - const u8 *extra, size_t extra_len) -{ - struct eap_hdr *eap; - struct wpabuf *buf; - - if (msg == NULL) - return NULL; - - eap = wpabuf_mhead(msg->buf); - eap->length = host_to_be16(wpabuf_len(msg->buf)); - -#ifdef EAP_AKA_PRIME - if (k_aut && msg->mac && msg->type == EAP_TYPE_AKA_PRIME) { - eap_sim_add_mac_sha256(k_aut, (u8 *) wpabuf_head(msg->buf), - wpabuf_len(msg->buf), - (u8 *) wpabuf_mhead(msg->buf) + - msg->mac, extra, extra_len); - } else -#endif /* EAP_AKA_PRIME */ - if (k_aut && msg->mac) { - eap_sim_add_mac(k_aut, (u8 *) wpabuf_head(msg->buf), - wpabuf_len(msg->buf), - (u8 *) wpabuf_mhead(msg->buf) + msg->mac, - extra, extra_len); - } - - buf = msg->buf; - os_free(msg); - return buf; -} - - -void eap_sim_msg_free(struct eap_sim_msg *msg) -{ - if (msg) { - wpabuf_free(msg->buf); - os_free(msg); - } -} - - -u8 * eap_sim_msg_add_full(struct eap_sim_msg *msg, u8 attr, - const u8 *data, size_t len) -{ - int attr_len = 2 + len; - int pad_len; - u8 *start; - - if (msg == NULL) - return NULL; - - pad_len = (4 - attr_len % 4) % 4; - attr_len += pad_len; - if (wpabuf_resize(&msg->buf, attr_len)) - return NULL; - start = wpabuf_put(msg->buf, 0); - wpabuf_put_u8(msg->buf, attr); - wpabuf_put_u8(msg->buf, attr_len / 4); - wpabuf_put_data(msg->buf, data, len); - if (pad_len) - os_memset(wpabuf_put(msg->buf, pad_len), 0, pad_len); - return start; -} - - -u8 * eap_sim_msg_add(struct eap_sim_msg *msg, u8 attr, u16 value, - const u8 *data, size_t len) -{ - int attr_len = 4 + len; - int pad_len; - u8 *start; - - if (msg == NULL) - return NULL; - - pad_len = (4 - attr_len % 4) % 4; - attr_len += pad_len; - if (wpabuf_resize(&msg->buf, attr_len)) - return NULL; - start = wpabuf_put(msg->buf, 0); - wpabuf_put_u8(msg->buf, attr); - wpabuf_put_u8(msg->buf, attr_len / 4); - wpabuf_put_be16(msg->buf, value); - if (data) - wpabuf_put_data(msg->buf, data, len); - else - wpabuf_put(msg->buf, len); - if (pad_len) - os_memset(wpabuf_put(msg->buf, pad_len), 0, pad_len); - return start; -} - - -u8 * eap_sim_msg_add_mac(struct eap_sim_msg *msg, u8 attr) -{ - u8 *pos = eap_sim_msg_add(msg, attr, 0, NULL, EAP_SIM_MAC_LEN); - if (pos) - msg->mac = (pos - wpabuf_head_u8(msg->buf)) + 4; - return pos; -} - - -int eap_sim_msg_add_encr_start(struct eap_sim_msg *msg, u8 attr_iv, - u8 attr_encr) -{ - u8 *pos = eap_sim_msg_add(msg, attr_iv, 0, NULL, EAP_SIM_IV_LEN); - if (pos == NULL) - return -1; - msg->iv = (pos - wpabuf_head_u8(msg->buf)) + 4; - if (os_get_random(wpabuf_mhead_u8(msg->buf) + msg->iv, - EAP_SIM_IV_LEN)) { - msg->iv = 0; - return -1; - } - - pos = eap_sim_msg_add(msg, attr_encr, 0, NULL, 0); - if (pos == NULL) { - msg->iv = 0; - return -1; - } - msg->encr = pos - wpabuf_head_u8(msg->buf); - - return 0; -} - - -int eap_sim_msg_add_encr_end(struct eap_sim_msg *msg, u8 *k_encr, int attr_pad) -{ - size_t encr_len; - - if (msg == NULL || k_encr == NULL || msg->iv == 0 || msg->encr == 0) - return -1; - - encr_len = wpabuf_len(msg->buf) - msg->encr - 4; - if (encr_len % 16) { - u8 *pos; - int pad_len = 16 - (encr_len % 16); - if (pad_len < 4) { - wpa_printf(MSG_WARNING, "EAP-SIM: " - "eap_sim_msg_add_encr_end - invalid pad_len" - " %d", pad_len); - return -1; - } - wpa_printf(MSG_DEBUG, " *AT_PADDING"); - pos = eap_sim_msg_add(msg, attr_pad, 0, NULL, pad_len - 4); - if (pos == NULL) - return -1; - os_memset(pos + 4, 0, pad_len - 4); - encr_len += pad_len; - } - wpa_printf(MSG_DEBUG, " (AT_ENCR_DATA data len %lu)", - (unsigned long) encr_len); - wpabuf_mhead_u8(msg->buf)[msg->encr + 1] = encr_len / 4 + 1; - return aes_128_cbc_encrypt(k_encr, wpabuf_head_u8(msg->buf) + msg->iv, - wpabuf_mhead_u8(msg->buf) + msg->encr + 4, - encr_len); -} - - -void eap_sim_report_notification(void *msg_ctx, int notification, int aka) -{ -#ifndef CONFIG_NO_STDOUT_DEBUG - const char *type = aka ? "AKA" : "SIM"; -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - switch (notification) { - case EAP_SIM_GENERAL_FAILURE_AFTER_AUTH: - wpa_printf(MSG_WARNING, "EAP-%s: General failure " - "notification (after authentication)", type); - break; - case EAP_SIM_TEMPORARILY_DENIED: - wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: " - "User has been temporarily denied access to the " - "requested service", type); - break; - case EAP_SIM_NOT_SUBSCRIBED: - wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: " - "User has not subscribed to the requested service", - type); - break; - case EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH: - wpa_printf(MSG_WARNING, "EAP-%s: General failure " - "notification (before authentication)", type); - break; - case EAP_SIM_SUCCESS: - wpa_printf(MSG_INFO, "EAP-%s: Successful authentication " - "notification", type); - break; - default: - if (notification >= 32768) { - wpa_printf(MSG_INFO, "EAP-%s: Unrecognized " - "non-failure notification %d", - type, notification); - } else { - wpa_printf(MSG_WARNING, "EAP-%s: Unrecognized " - "failure notification %d", - type, notification); - } - } -} diff --git a/contrib/hostapd/src/eap_common/eap_sim_common.h b/contrib/hostapd/src/eap_common/eap_sim_common.h deleted file mode 100644 index a8080e27a7..0000000000 --- a/contrib/hostapd/src/eap_common/eap_sim_common.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * EAP peer/server: EAP-SIM/AKA/AKA' shared routines - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_SIM_COMMON_H -#define EAP_SIM_COMMON_H - -#define EAP_SIM_NONCE_S_LEN 16 -#define EAP_SIM_NONCE_MT_LEN 16 -#define EAP_SIM_MAC_LEN 16 -#define EAP_SIM_MK_LEN 20 -#define EAP_SIM_K_AUT_LEN 16 -#define EAP_SIM_K_ENCR_LEN 16 -#define EAP_SIM_KEYING_DATA_LEN 64 -#define EAP_SIM_IV_LEN 16 -#define EAP_SIM_KC_LEN 8 -#define EAP_SIM_SRES_LEN 4 - -#define GSM_RAND_LEN 16 - -#define EAP_SIM_VERSION 1 - -/* EAP-SIM Subtypes */ -#define EAP_SIM_SUBTYPE_START 10 -#define EAP_SIM_SUBTYPE_CHALLENGE 11 -#define EAP_SIM_SUBTYPE_NOTIFICATION 12 -#define EAP_SIM_SUBTYPE_REAUTHENTICATION 13 -#define EAP_SIM_SUBTYPE_CLIENT_ERROR 14 - -/* AT_CLIENT_ERROR_CODE error codes */ -#define EAP_SIM_UNABLE_TO_PROCESS_PACKET 0 -#define EAP_SIM_UNSUPPORTED_VERSION 1 -#define EAP_SIM_INSUFFICIENT_NUM_OF_CHAL 2 -#define EAP_SIM_RAND_NOT_FRESH 3 - -#define EAP_SIM_MAX_FAST_REAUTHS 1000 - -#define EAP_SIM_MAX_CHAL 3 - - -/* EAP-AKA Subtypes */ -#define EAP_AKA_SUBTYPE_CHALLENGE 1 -#define EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT 2 -#define EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE 4 -#define EAP_AKA_SUBTYPE_IDENTITY 5 -#define EAP_AKA_SUBTYPE_NOTIFICATION 12 -#define EAP_AKA_SUBTYPE_REAUTHENTICATION 13 -#define EAP_AKA_SUBTYPE_CLIENT_ERROR 14 - -/* AT_CLIENT_ERROR_CODE error codes */ -#define EAP_AKA_UNABLE_TO_PROCESS_PACKET 0 - -#define EAP_AKA_RAND_LEN 16 -#define EAP_AKA_AUTN_LEN 16 -#define EAP_AKA_AUTS_LEN 14 -#define EAP_AKA_RES_MAX_LEN 16 -#define EAP_AKA_IK_LEN 16 -#define EAP_AKA_CK_LEN 16 -#define EAP_AKA_MAX_FAST_REAUTHS 1000 -#define EAP_AKA_MIN_RES_LEN 4 -#define EAP_AKA_MAX_RES_LEN 16 -#define EAP_AKA_CHECKCODE_LEN 20 - -#define EAP_AKA_PRIME_K_AUT_LEN 32 -#define EAP_AKA_PRIME_CHECKCODE_LEN 32 -#define EAP_AKA_PRIME_K_RE_LEN 32 - -struct wpabuf; - -void eap_sim_derive_mk(const u8 *identity, size_t identity_len, - const u8 *nonce_mt, u16 selected_version, - const u8 *ver_list, size_t ver_list_len, - int num_chal, const u8 *kc, u8 *mk); -void eap_aka_derive_mk(const u8 *identity, size_t identity_len, - const u8 *ik, const u8 *ck, u8 *mk); -int eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk, - u8 *emsk); -int eap_sim_derive_keys_reauth(u16 _counter, - const u8 *identity, size_t identity_len, - const u8 *nonce_s, const u8 *mk, u8 *msk, - u8 *emsk); -int eap_sim_verify_mac(const u8 *k_aut, const struct wpabuf *req, - const u8 *mac, const u8 *extra, size_t extra_len); -void eap_sim_add_mac(const u8 *k_aut, const u8 *msg, size_t msg_len, u8 *mac, - const u8 *extra, size_t extra_len); - -#ifdef EAP_AKA_PRIME -void eap_aka_prime_derive_keys(const u8 *identity, size_t identity_len, - const u8 *ik, const u8 *ck, u8 *k_encr, - u8 *k_aut, u8 *k_re, u8 *msk, u8 *emsk); -int eap_aka_prime_derive_keys_reauth(const u8 *k_re, u16 counter, - const u8 *identity, size_t identity_len, - const u8 *nonce_s, u8 *msk, u8 *emsk); -int eap_sim_verify_mac_sha256(const u8 *k_aut, const struct wpabuf *req, - const u8 *mac, const u8 *extra, - size_t extra_len); -void eap_sim_add_mac_sha256(const u8 *k_aut, const u8 *msg, size_t msg_len, - u8 *mac, const u8 *extra, size_t extra_len); - -void eap_aka_prime_derive_ck_ik_prime(u8 *ck, u8 *ik, const u8 *sqn_ak, - const u8 *network_name, - size_t network_name_len); -#else /* EAP_AKA_PRIME */ -static inline void eap_aka_prime_derive_keys(const u8 *identity, - size_t identity_len, - const u8 *ik, const u8 *ck, - u8 *k_encr, u8 *k_aut, u8 *k_re, - u8 *msk, u8 *emsk) -{ -} - -static inline int eap_aka_prime_derive_keys_reauth(const u8 *k_re, u16 counter, - const u8 *identity, - size_t identity_len, - const u8 *nonce_s, u8 *msk, - u8 *emsk) -{ - return -1; -} - -static inline int eap_sim_verify_mac_sha256(const u8 *k_aut, - const struct wpabuf *req, - const u8 *mac, const u8 *extra, - size_t extra_len) -{ - return -1; -} -#endif /* EAP_AKA_PRIME */ - - -/* EAP-SIM/AKA Attributes (0..127 non-skippable) */ -#define EAP_SIM_AT_RAND 1 -#define EAP_SIM_AT_AUTN 2 /* only AKA */ -#define EAP_SIM_AT_RES 3 /* only AKA, only peer->server */ -#define EAP_SIM_AT_AUTS 4 /* only AKA, only peer->server */ -#define EAP_SIM_AT_PADDING 6 /* only encrypted */ -#define EAP_SIM_AT_NONCE_MT 7 /* only SIM, only send */ -#define EAP_SIM_AT_PERMANENT_ID_REQ 10 -#define EAP_SIM_AT_MAC 11 -#define EAP_SIM_AT_NOTIFICATION 12 -#define EAP_SIM_AT_ANY_ID_REQ 13 -#define EAP_SIM_AT_IDENTITY 14 /* only send */ -#define EAP_SIM_AT_VERSION_LIST 15 /* only SIM */ -#define EAP_SIM_AT_SELECTED_VERSION 16 /* only SIM */ -#define EAP_SIM_AT_FULLAUTH_ID_REQ 17 -#define EAP_SIM_AT_COUNTER 19 /* only encrypted */ -#define EAP_SIM_AT_COUNTER_TOO_SMALL 20 /* only encrypted */ -#define EAP_SIM_AT_NONCE_S 21 /* only encrypted */ -#define EAP_SIM_AT_CLIENT_ERROR_CODE 22 /* only send */ -#define EAP_SIM_AT_KDF_INPUT 23 /* only AKA' */ -#define EAP_SIM_AT_KDF 24 /* only AKA' */ -#define EAP_SIM_AT_IV 129 -#define EAP_SIM_AT_ENCR_DATA 130 -#define EAP_SIM_AT_NEXT_PSEUDONYM 132 /* only encrypted */ -#define EAP_SIM_AT_NEXT_REAUTH_ID 133 /* only encrypted */ -#define EAP_SIM_AT_CHECKCODE 134 /* only AKA */ -#define EAP_SIM_AT_RESULT_IND 135 -#define EAP_SIM_AT_BIDDING 136 - -/* AT_NOTIFICATION notification code values */ -#define EAP_SIM_GENERAL_FAILURE_AFTER_AUTH 0 -#define EAP_SIM_TEMPORARILY_DENIED 1026 -#define EAP_SIM_NOT_SUBSCRIBED 1031 -#define EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH 16384 -#define EAP_SIM_SUCCESS 32768 - -/* EAP-AKA' AT_KDF Key Derivation Function values */ -#define EAP_AKA_PRIME_KDF 1 - -/* AT_BIDDING flags */ -#define EAP_AKA_BIDDING_FLAG_D 0x8000 - - -enum eap_sim_id_req { - NO_ID_REQ, ANY_ID, FULLAUTH_ID, PERMANENT_ID -}; - - -struct eap_sim_attrs { - const u8 *rand, *autn, *mac, *iv, *encr_data, *version_list, *nonce_s; - const u8 *next_pseudonym, *next_reauth_id; - const u8 *nonce_mt, *identity, *res, *auts; - const u8 *checkcode; - const u8 *kdf_input; - const u8 *bidding; - size_t num_chal, version_list_len, encr_data_len; - size_t next_pseudonym_len, next_reauth_id_len, identity_len, res_len; - size_t res_len_bits; - size_t checkcode_len; - size_t kdf_input_len; - enum eap_sim_id_req id_req; - int notification, counter, selected_version, client_error_code; - int counter_too_small; - int result_ind; -#define EAP_AKA_PRIME_KDF_MAX 10 - u16 kdf[EAP_AKA_PRIME_KDF_MAX]; - size_t kdf_count; -}; - -int eap_sim_parse_attr(const u8 *start, const u8 *end, - struct eap_sim_attrs *attr, int aka, int encr); -u8 * eap_sim_parse_encr(const u8 *k_encr, const u8 *encr_data, - size_t encr_data_len, const u8 *iv, - struct eap_sim_attrs *attr, int aka); - - -struct eap_sim_msg; - -struct eap_sim_msg * eap_sim_msg_init(int code, int id, int type, int subtype); -struct wpabuf * eap_sim_msg_finish(struct eap_sim_msg *msg, const u8 *k_aut, - const u8 *extra, size_t extra_len); -void eap_sim_msg_free(struct eap_sim_msg *msg); -u8 * eap_sim_msg_add_full(struct eap_sim_msg *msg, u8 attr, - const u8 *data, size_t len); -u8 * eap_sim_msg_add(struct eap_sim_msg *msg, u8 attr, - u16 value, const u8 *data, size_t len); -u8 * eap_sim_msg_add_mac(struct eap_sim_msg *msg, u8 attr); -int eap_sim_msg_add_encr_start(struct eap_sim_msg *msg, u8 attr_iv, - u8 attr_encr); -int eap_sim_msg_add_encr_end(struct eap_sim_msg *msg, u8 *k_encr, - int attr_pad); - -void eap_sim_report_notification(void *msg_ctx, int notification, int aka); - -#endif /* EAP_SIM_COMMON_H */ diff --git a/contrib/hostapd/src/eap_common/eap_tlv_common.h b/contrib/hostapd/src/eap_common/eap_tlv_common.h deleted file mode 100644 index f86015d179..0000000000 --- a/contrib/hostapd/src/eap_common/eap_tlv_common.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * EAP-TLV definitions (draft-josefsson-pppext-eap-tls-eap-10.txt) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_TLV_COMMON_H -#define EAP_TLV_COMMON_H - -/* EAP-TLV TLVs (draft-josefsson-ppext-eap-tls-eap-10.txt) */ -#define EAP_TLV_RESULT_TLV 3 /* Acknowledged Result */ -#define EAP_TLV_NAK_TLV 4 -#define EAP_TLV_ERROR_CODE_TLV 5 -#define EAP_TLV_CONNECTION_BINDING_TLV 6 -#define EAP_TLV_VENDOR_SPECIFIC_TLV 7 -#define EAP_TLV_URI_TLV 8 -#define EAP_TLV_EAP_PAYLOAD_TLV 9 -#define EAP_TLV_INTERMEDIATE_RESULT_TLV 10 -#define EAP_TLV_PAC_TLV 11 /* RFC 5422, Section 4.2 */ -#define EAP_TLV_CRYPTO_BINDING_TLV 12 -#define EAP_TLV_CALLING_STATION_ID_TLV 13 -#define EAP_TLV_CALLED_STATION_ID_TLV 14 -#define EAP_TLV_NAS_PORT_TYPE_TLV 15 -#define EAP_TLV_SERVER_IDENTIFIER_TLV 16 -#define EAP_TLV_IDENTITY_TYPE_TLV 17 -#define EAP_TLV_SERVER_TRUSTED_ROOT_TLV 18 -#define EAP_TLV_REQUEST_ACTION_TLV 19 -#define EAP_TLV_PKCS7_TLV 20 - -#define EAP_TLV_RESULT_SUCCESS 1 -#define EAP_TLV_RESULT_FAILURE 2 - -#define EAP_TLV_TYPE_MANDATORY 0x8000 -#define EAP_TLV_TYPE_MASK 0x3fff - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct eap_tlv_hdr { - be16 tlv_type; - be16 length; -} STRUCT_PACKED; - -struct eap_tlv_nak_tlv { - be16 tlv_type; - be16 length; - be32 vendor_id; - be16 nak_type; -} STRUCT_PACKED; - -struct eap_tlv_result_tlv { - be16 tlv_type; - be16 length; - be16 status; -} STRUCT_PACKED; - -/* RFC 4851, Section 4.2.7 - Intermediate-Result TLV */ -struct eap_tlv_intermediate_result_tlv { - be16 tlv_type; - be16 length; - be16 status; - /* Followed by optional TLVs */ -} STRUCT_PACKED; - -/* RFC 4851, Section 4.2.8 - Crypto-Binding TLV */ -struct eap_tlv_crypto_binding_tlv { - be16 tlv_type; - be16 length; - u8 reserved; - u8 version; - u8 received_version; - u8 subtype; - u8 nonce[32]; - u8 compound_mac[20]; -} STRUCT_PACKED; - -struct eap_tlv_pac_ack_tlv { - be16 tlv_type; - be16 length; - be16 pac_type; - be16 pac_len; - be16 result; -} STRUCT_PACKED; - -/* RFC 4851, Section 4.2.9 - Request-Action TLV */ -struct eap_tlv_request_action_tlv { - be16 tlv_type; - be16 length; - be16 action; -} STRUCT_PACKED; - -/* RFC 5422, Section 4.2.6 - PAC-Type TLV */ -struct eap_tlv_pac_type_tlv { - be16 tlv_type; /* PAC_TYPE_PAC_TYPE */ - be16 length; - be16 pac_type; -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -#define EAP_TLV_CRYPTO_BINDING_SUBTYPE_REQUEST 0 -#define EAP_TLV_CRYPTO_BINDING_SUBTYPE_RESPONSE 1 - -#define EAP_TLV_ACTION_PROCESS_TLV 1 -#define EAP_TLV_ACTION_NEGOTIATE_EAP 2 - -#endif /* EAP_TLV_COMMON_H */ diff --git a/contrib/hostapd/src/eap_common/eap_ttls.h b/contrib/hostapd/src/eap_common/eap_ttls.h deleted file mode 100644 index 797d084786..0000000000 --- a/contrib/hostapd/src/eap_common/eap_ttls.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * EAP server/peer: EAP-TTLS (RFC 5281) - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_TTLS_H -#define EAP_TTLS_H - -struct ttls_avp { - be32 avp_code; - be32 avp_length; /* 8-bit flags, 24-bit length; - * length includes AVP header */ - /* optional 32-bit Vendor-ID */ - /* Data */ -}; - -struct ttls_avp_vendor { - be32 avp_code; - be32 avp_length; /* 8-bit flags, 24-bit length; - * length includes AVP header */ - be32 vendor_id; - /* Data */ -}; - -#define AVP_FLAGS_VENDOR 0x80 -#define AVP_FLAGS_MANDATORY 0x40 - -#define AVP_PAD(start, pos) \ -do { \ - int __pad; \ - __pad = (4 - (((pos) - (start)) & 3)) & 3; \ - os_memset((pos), 0, __pad); \ - pos += __pad; \ -} while (0) - - -/* RFC 2865 */ -#define RADIUS_ATTR_USER_NAME 1 -#define RADIUS_ATTR_USER_PASSWORD 2 -#define RADIUS_ATTR_CHAP_PASSWORD 3 -#define RADIUS_ATTR_REPLY_MESSAGE 18 -#define RADIUS_ATTR_CHAP_CHALLENGE 60 -#define RADIUS_ATTR_EAP_MESSAGE 79 - -/* RFC 2548 */ -#define RADIUS_VENDOR_ID_MICROSOFT 311 -#define RADIUS_ATTR_MS_CHAP_RESPONSE 1 -#define RADIUS_ATTR_MS_CHAP_ERROR 2 -#define RADIUS_ATTR_MS_CHAP_NT_ENC_PW 6 -#define RADIUS_ATTR_MS_CHAP_CHALLENGE 11 -#define RADIUS_ATTR_MS_CHAP2_RESPONSE 25 -#define RADIUS_ATTR_MS_CHAP2_SUCCESS 26 -#define RADIUS_ATTR_MS_CHAP2_CPW 27 - -#define EAP_TTLS_MSCHAPV2_CHALLENGE_LEN 16 -#define EAP_TTLS_MSCHAPV2_RESPONSE_LEN 50 -#define EAP_TTLS_MSCHAP_CHALLENGE_LEN 8 -#define EAP_TTLS_MSCHAP_RESPONSE_LEN 50 -#define EAP_TTLS_CHAP_CHALLENGE_LEN 16 -#define EAP_TTLS_CHAP_PASSWORD_LEN 16 - -#endif /* EAP_TTLS_H */ diff --git a/contrib/hostapd/src/eap_common/eap_wsc_common.c b/contrib/hostapd/src/eap_common/eap_wsc_common.c deleted file mode 100644 index 5d4e8cc114..0000000000 --- a/contrib/hostapd/src/eap_common/eap_wsc_common.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * EAP-WSC common routines for Wi-Fi Protected Setup - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_defs.h" -#include "eap_common.h" -#include "wps/wps.h" -#include "eap_wsc_common.h" - -struct wpabuf * eap_wsc_build_frag_ack(u8 id, u8 code) -{ - struct wpabuf *msg; - - msg = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 2, code, id); - if (msg == NULL) { - wpa_printf(MSG_ERROR, "EAP-WSC: Failed to allocate memory for " - "FRAG_ACK"); - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-WSC: Send WSC/FRAG_ACK"); - wpabuf_put_u8(msg, WSC_FRAG_ACK); /* Op-Code */ - wpabuf_put_u8(msg, 0); /* Flags */ - - return msg; -} diff --git a/contrib/hostapd/src/eap_common/eap_wsc_common.h b/contrib/hostapd/src/eap_common/eap_wsc_common.h deleted file mode 100644 index fdf61d317d..0000000000 --- a/contrib/hostapd/src/eap_common/eap_wsc_common.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * EAP-WSC definitions for Wi-Fi Protected Setup - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_WSC_COMMON_H -#define EAP_WSC_COMMON_H - -#define EAP_VENDOR_TYPE_WSC 1 - -#define WSC_FLAGS_MF 0x01 -#define WSC_FLAGS_LF 0x02 - -#define WSC_ID_REGISTRAR "WFA-SimpleConfig-Registrar-1-0" -#define WSC_ID_REGISTRAR_LEN 30 -#define WSC_ID_ENROLLEE "WFA-SimpleConfig-Enrollee-1-0" -#define WSC_ID_ENROLLEE_LEN 29 - -#define WSC_FRAGMENT_SIZE 1400 - - -struct wpabuf * eap_wsc_build_frag_ack(u8 id, u8 code); - -#endif /* EAP_WSC_COMMON_H */ diff --git a/contrib/hostapd/src/eap_common/ikev2_common.c b/contrib/hostapd/src/eap_common/ikev2_common.c deleted file mode 100644 index 818b5bdbaa..0000000000 --- a/contrib/hostapd/src/eap_common/ikev2_common.c +++ /dev/null @@ -1,796 +0,0 @@ -/* - * IKEv2 common routines for initiator and responder - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha1.h" -#include "md5.h" -#include "crypto.h" -#include "ikev2_common.h" - - -static struct ikev2_integ_alg ikev2_integ_algs[] = { - { AUTH_HMAC_SHA1_96, 20, 12 }, - { AUTH_HMAC_MD5_96, 16, 12 } -}; - -#define NUM_INTEG_ALGS (sizeof(ikev2_integ_algs) / sizeof(ikev2_integ_algs[0])) - - -static struct ikev2_prf_alg ikev2_prf_algs[] = { - { PRF_HMAC_SHA1, 20, 20 }, - { PRF_HMAC_MD5, 16, 16 } -}; - -#define NUM_PRF_ALGS (sizeof(ikev2_prf_algs) / sizeof(ikev2_prf_algs[0])) - - -static struct ikev2_encr_alg ikev2_encr_algs[] = { - { ENCR_AES_CBC, 16, 16 }, /* only 128-bit keys supported for now */ - { ENCR_3DES, 24, 8 } -}; - -#define NUM_ENCR_ALGS (sizeof(ikev2_encr_algs) / sizeof(ikev2_encr_algs[0])) - - -const struct ikev2_integ_alg * ikev2_get_integ(int id) -{ - size_t i; - - for (i = 0; i < NUM_INTEG_ALGS; i++) { - if (ikev2_integ_algs[i].id == id) - return &ikev2_integ_algs[i]; - } - - return NULL; -} - - -int ikev2_integ_hash(int alg, const u8 *key, size_t key_len, const u8 *data, - size_t data_len, u8 *hash) -{ - u8 tmphash[IKEV2_MAX_HASH_LEN]; - - switch (alg) { - case AUTH_HMAC_SHA1_96: - if (key_len != 20) - return -1; - hmac_sha1(key, key_len, data, data_len, tmphash); - os_memcpy(hash, tmphash, 12); - break; - case AUTH_HMAC_MD5_96: - if (key_len != 16) - return -1; - hmac_md5(key, key_len, data, data_len, tmphash); - os_memcpy(hash, tmphash, 12); - break; - default: - return -1; - } - - return 0; -} - - -const struct ikev2_prf_alg * ikev2_get_prf(int id) -{ - size_t i; - - for (i = 0; i < NUM_PRF_ALGS; i++) { - if (ikev2_prf_algs[i].id == id) - return &ikev2_prf_algs[i]; - } - - return NULL; -} - - -int ikev2_prf_hash(int alg, const u8 *key, size_t key_len, - size_t num_elem, const u8 *addr[], const size_t *len, - u8 *hash) -{ - switch (alg) { - case PRF_HMAC_SHA1: - hmac_sha1_vector(key, key_len, num_elem, addr, len, hash); - break; - case PRF_HMAC_MD5: - hmac_md5_vector(key, key_len, num_elem, addr, len, hash); - break; - default: - return -1; - } - - return 0; -} - - -int ikev2_prf_plus(int alg, const u8 *key, size_t key_len, - const u8 *data, size_t data_len, - u8 *out, size_t out_len) -{ - u8 hash[IKEV2_MAX_HASH_LEN]; - size_t hash_len; - u8 iter, *pos, *end; - const u8 *addr[3]; - size_t len[3]; - const struct ikev2_prf_alg *prf; - int res; - - prf = ikev2_get_prf(alg); - if (prf == NULL) - return -1; - hash_len = prf->hash_len; - - addr[0] = hash; - len[0] = hash_len; - addr[1] = data; - len[1] = data_len; - addr[2] = &iter; - len[2] = 1; - - pos = out; - end = out + out_len; - iter = 1; - while (pos < end) { - size_t clen; - if (iter == 1) - res = ikev2_prf_hash(alg, key, key_len, 2, &addr[1], - &len[1], hash); - else - res = ikev2_prf_hash(alg, key, key_len, 3, addr, len, - hash); - if (res < 0) - return -1; - clen = hash_len; - if ((int) clen > end - pos) - clen = end - pos; - os_memcpy(pos, hash, clen); - pos += clen; - iter++; - } - - return 0; -} - - -const struct ikev2_encr_alg * ikev2_get_encr(int id) -{ - size_t i; - - for (i = 0; i < NUM_ENCR_ALGS; i++) { - if (ikev2_encr_algs[i].id == id) - return &ikev2_encr_algs[i]; - } - - return NULL; -} - - -#ifdef CCNS_PL -/* from des.c */ -struct des3_key_s { - u32 ek[3][32]; - u32 dk[3][32]; -}; - -void des3_key_setup(const u8 *key, struct des3_key_s *dkey); -void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt); -void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain); -#endif /* CCNS_PL */ - - -int ikev2_encr_encrypt(int alg, const u8 *key, size_t key_len, const u8 *iv, - const u8 *plain, u8 *crypt, size_t len) -{ - struct crypto_cipher *cipher; - int encr_alg; - -#ifdef CCNS_PL - if (alg == ENCR_3DES) { - struct des3_key_s des3key; - size_t i, blocks; - u8 *pos; - - /* ECB mode is used incorrectly for 3DES!? */ - if (key_len != 24) { - wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length"); - return -1; - } - des3_key_setup(key, &des3key); - - blocks = len / 8; - pos = crypt; - for (i = 0; i < blocks; i++) { - des3_encrypt(pos, &des3key, pos); - pos += 8; - } - } else { -#endif /* CCNS_PL */ - switch (alg) { - case ENCR_3DES: - encr_alg = CRYPTO_CIPHER_ALG_3DES; - break; - case ENCR_AES_CBC: - encr_alg = CRYPTO_CIPHER_ALG_AES; - break; - default: - wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg); - return -1; - } - - cipher = crypto_cipher_init(encr_alg, iv, key, key_len); - if (cipher == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher"); - return -1; - } - - if (crypto_cipher_encrypt(cipher, plain, crypt, len) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Encryption failed"); - crypto_cipher_deinit(cipher); - return -1; - } - crypto_cipher_deinit(cipher); -#ifdef CCNS_PL - } -#endif /* CCNS_PL */ - - return 0; -} - - -int ikev2_encr_decrypt(int alg, const u8 *key, size_t key_len, const u8 *iv, - const u8 *crypt, u8 *plain, size_t len) -{ - struct crypto_cipher *cipher; - int encr_alg; - -#ifdef CCNS_PL - if (alg == ENCR_3DES) { - struct des3_key_s des3key; - size_t i, blocks; - - /* ECB mode is used incorrectly for 3DES!? */ - if (key_len != 24) { - wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length"); - return -1; - } - des3_key_setup(key, &des3key); - - if (len % 8) { - wpa_printf(MSG_INFO, "IKEV2: Invalid encrypted " - "length"); - return -1; - } - blocks = len / 8; - for (i = 0; i < blocks; i++) { - des3_decrypt(crypt, &des3key, plain); - plain += 8; - crypt += 8; - } - } else { -#endif /* CCNS_PL */ - switch (alg) { - case ENCR_3DES: - encr_alg = CRYPTO_CIPHER_ALG_3DES; - break; - case ENCR_AES_CBC: - encr_alg = CRYPTO_CIPHER_ALG_AES; - break; - default: - wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg); - return -1; - } - - cipher = crypto_cipher_init(encr_alg, iv, key, key_len); - if (cipher == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher"); - return -1; - } - - if (crypto_cipher_decrypt(cipher, crypt, plain, len) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Decryption failed"); - crypto_cipher_deinit(cipher); - return -1; - } - crypto_cipher_deinit(cipher); -#ifdef CCNS_PL - } -#endif /* CCNS_PL */ - - return 0; -} - - -int ikev2_parse_payloads(struct ikev2_payloads *payloads, - u8 next_payload, const u8 *pos, const u8 *end) -{ - const struct ikev2_payload_hdr *phdr; - - os_memset(payloads, 0, sizeof(*payloads)); - - while (next_payload != IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) { - int plen, pdatalen; - const u8 *pdata; - wpa_printf(MSG_DEBUG, "IKEV2: Processing payload %u", - next_payload); - if (end - pos < (int) sizeof(*phdr)) { - wpa_printf(MSG_INFO, "IKEV2: Too short message for " - "payload header (left=%ld)", - (long) (end - pos)); - } - phdr = (const struct ikev2_payload_hdr *) pos; - plen = WPA_GET_BE16(phdr->payload_length); - if (plen < (int) sizeof(*phdr) || pos + plen > end) { - wpa_printf(MSG_INFO, "IKEV2: Invalid payload header " - "length %d", plen); - return -1; - } - - wpa_printf(MSG_DEBUG, "IKEV2: Next Payload: %u Flags: 0x%x" - " Payload Length: %d", - phdr->next_payload, phdr->flags, plen); - - pdata = (const u8 *) (phdr + 1); - pdatalen = plen - sizeof(*phdr); - - switch (next_payload) { - case IKEV2_PAYLOAD_SA: - wpa_printf(MSG_DEBUG, "IKEV2: Payload: Security " - "Association"); - payloads->sa = pdata; - payloads->sa_len = pdatalen; - break; - case IKEV2_PAYLOAD_KEY_EXCHANGE: - wpa_printf(MSG_DEBUG, "IKEV2: Payload: Key " - "Exchange"); - payloads->ke = pdata; - payloads->ke_len = pdatalen; - break; - case IKEV2_PAYLOAD_IDi: - wpa_printf(MSG_DEBUG, "IKEV2: Payload: IDi"); - payloads->idi = pdata; - payloads->idi_len = pdatalen; - break; - case IKEV2_PAYLOAD_IDr: - wpa_printf(MSG_DEBUG, "IKEV2: Payload: IDr"); - payloads->idr = pdata; - payloads->idr_len = pdatalen; - break; - case IKEV2_PAYLOAD_CERTIFICATE: - wpa_printf(MSG_DEBUG, "IKEV2: Payload: Certificate"); - payloads->cert = pdata; - payloads->cert_len = pdatalen; - break; - case IKEV2_PAYLOAD_AUTHENTICATION: - wpa_printf(MSG_DEBUG, "IKEV2: Payload: " - "Authentication"); - payloads->auth = pdata; - payloads->auth_len = pdatalen; - break; - case IKEV2_PAYLOAD_NONCE: - wpa_printf(MSG_DEBUG, "IKEV2: Payload: Nonce"); - payloads->nonce = pdata; - payloads->nonce_len = pdatalen; - break; - case IKEV2_PAYLOAD_ENCRYPTED: - wpa_printf(MSG_DEBUG, "IKEV2: Payload: Encrypted"); - payloads->encrypted = pdata; - payloads->encrypted_len = pdatalen; - break; - case IKEV2_PAYLOAD_NOTIFICATION: - wpa_printf(MSG_DEBUG, "IKEV2: Payload: " - "Notification"); - payloads->notification = pdata; - payloads->notification_len = pdatalen; - break; - default: - if (phdr->flags & IKEV2_PAYLOAD_FLAGS_CRITICAL) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported " - "critical payload %u - reject the " - "entire message", next_payload); - return -1; - } else { - wpa_printf(MSG_DEBUG, "IKEV2: Skipped " - "unsupported payload %u", - next_payload); - } - } - - if (next_payload == IKEV2_PAYLOAD_ENCRYPTED && - pos + plen == end) { - /* - * Next Payload in the case of Encrypted Payload is - * actually the payload type for the first embedded - * payload. - */ - payloads->encr_next_payload = phdr->next_payload; - next_payload = IKEV2_PAYLOAD_NO_NEXT_PAYLOAD; - } else - next_payload = phdr->next_payload; - - pos += plen; - } - - if (pos != end) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected extra data after " - "payloads"); - return -1; - } - - return 0; -} - - -int ikev2_derive_auth_data(int prf_alg, const struct wpabuf *sign_msg, - const u8 *ID, size_t ID_len, u8 ID_type, - struct ikev2_keys *keys, int initiator, - const u8 *shared_secret, size_t shared_secret_len, - const u8 *nonce, size_t nonce_len, - const u8 *key_pad, size_t key_pad_len, - u8 *auth_data) -{ - size_t sign_len, buf_len; - u8 *sign_data, *pos, *buf, hash[IKEV2_MAX_HASH_LEN]; - const struct ikev2_prf_alg *prf; - const u8 *SK_p = initiator ? keys->SK_pi : keys->SK_pr; - - prf = ikev2_get_prf(prf_alg); - if (sign_msg == NULL || ID == NULL || SK_p == NULL || - shared_secret == NULL || nonce == NULL || prf == NULL) - return -1; - - /* prf(SK_pi/r,IDi/r') */ - buf_len = 4 + ID_len; - buf = os_zalloc(buf_len); - if (buf == NULL) - return -1; - buf[0] = ID_type; - os_memcpy(buf + 4, ID, ID_len); - if (ikev2_prf_hash(prf->id, SK_p, keys->SK_prf_len, - 1, (const u8 **) &buf, &buf_len, hash) < 0) { - os_free(buf); - return -1; - } - os_free(buf); - - /* sign_data = msg | Nr/i | prf(SK_pi/r,IDi/r') */ - sign_len = wpabuf_len(sign_msg) + nonce_len + prf->hash_len; - sign_data = os_malloc(sign_len); - if (sign_data == NULL) - return -1; - pos = sign_data; - os_memcpy(pos, wpabuf_head(sign_msg), wpabuf_len(sign_msg)); - pos += wpabuf_len(sign_msg); - os_memcpy(pos, nonce, nonce_len); - pos += nonce_len; - os_memcpy(pos, hash, prf->hash_len); - - /* AUTH = prf(prf(Shared Secret, key pad, sign_data) */ - if (ikev2_prf_hash(prf->id, shared_secret, shared_secret_len, 1, - &key_pad, &key_pad_len, hash) < 0 || - ikev2_prf_hash(prf->id, hash, prf->hash_len, 1, - (const u8 **) &sign_data, &sign_len, auth_data) < 0) - { - os_free(sign_data); - return -1; - } - os_free(sign_data); - - return 0; -} - - -u8 * ikev2_decrypt_payload(int encr_id, int integ_id, - struct ikev2_keys *keys, int initiator, - const struct ikev2_hdr *hdr, - const u8 *encrypted, size_t encrypted_len, - size_t *res_len) -{ - size_t iv_len; - const u8 *pos, *end, *iv, *integ; - u8 hash[IKEV2_MAX_HASH_LEN], *decrypted; - size_t decrypted_len, pad_len; - const struct ikev2_integ_alg *integ_alg; - const struct ikev2_encr_alg *encr_alg; - const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er; - const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar; - - if (encrypted == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No Encrypted payload in SA_AUTH"); - return NULL; - } - - encr_alg = ikev2_get_encr(encr_id); - if (encr_alg == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type"); - return NULL; - } - iv_len = encr_alg->block_size; - - integ_alg = ikev2_get_integ(integ_id); - if (integ_alg == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type"); - return NULL; - } - - if (encrypted_len < iv_len + 1 + integ_alg->hash_len) { - wpa_printf(MSG_INFO, "IKEV2: No room for IV or Integrity " - "Checksum"); - return NULL; - } - - iv = encrypted; - pos = iv + iv_len; - end = encrypted + encrypted_len; - integ = end - integ_alg->hash_len; - - if (SK_a == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No SK_a available"); - return NULL; - } - if (ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len, - (const u8 *) hdr, - integ - (const u8 *) hdr, hash) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Failed to calculate integrity " - "hash"); - return NULL; - } - if (os_memcmp(integ, hash, integ_alg->hash_len) != 0) { - wpa_printf(MSG_INFO, "IKEV2: Incorrect Integrity Checksum " - "Data"); - return NULL; - } - - if (SK_e == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No SK_e available"); - return NULL; - } - - decrypted_len = integ - pos; - decrypted = os_malloc(decrypted_len); - if (decrypted == NULL) - return NULL; - - if (ikev2_encr_decrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv, pos, - decrypted, decrypted_len) < 0) { - os_free(decrypted); - return NULL; - } - - pad_len = decrypted[decrypted_len - 1]; - if (decrypted_len < pad_len + 1) { - wpa_printf(MSG_INFO, "IKEV2: Invalid padding in encrypted " - "payload"); - os_free(decrypted); - return NULL; - } - - decrypted_len -= pad_len + 1; - - *res_len = decrypted_len; - return decrypted; -} - - -void ikev2_update_hdr(struct wpabuf *msg) -{ - struct ikev2_hdr *hdr; - - /* Update lenth field in HDR */ - hdr = wpabuf_mhead(msg); - WPA_PUT_BE32(hdr->length, wpabuf_len(msg)); -} - - -int ikev2_build_encrypted(int encr_id, int integ_id, struct ikev2_keys *keys, - int initiator, struct wpabuf *msg, - struct wpabuf *plain, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - size_t iv_len, pad_len; - u8 *icv, *iv; - const struct ikev2_integ_alg *integ_alg; - const struct ikev2_encr_alg *encr_alg; - const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er; - const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding Encrypted payload"); - - /* Encr - RFC 4306, Sect. 3.14 */ - - encr_alg = ikev2_get_encr(encr_id); - if (encr_alg == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type"); - return -1; - } - iv_len = encr_alg->block_size; - - integ_alg = ikev2_get_integ(integ_id); - if (integ_alg == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type"); - return -1; - } - - if (SK_e == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No SK_e available"); - return -1; - } - - if (SK_a == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No SK_a available"); - return -1; - } - - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - - iv = wpabuf_put(msg, iv_len); - if (os_get_random(iv, iv_len)) { - wpa_printf(MSG_INFO, "IKEV2: Could not generate IV"); - return -1; - } - - pad_len = iv_len - (wpabuf_len(plain) + 1) % iv_len; - if (pad_len == iv_len) - pad_len = 0; - wpabuf_put(plain, pad_len); - wpabuf_put_u8(plain, pad_len); - - if (ikev2_encr_encrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv, - wpabuf_head(plain), wpabuf_mhead(plain), - wpabuf_len(plain)) < 0) - return -1; - - wpabuf_put_buf(msg, plain); - - /* Need to update all headers (Length fields) prior to hash func */ - icv = wpabuf_put(msg, integ_alg->hash_len); - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - - ikev2_update_hdr(msg); - - return ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len, - wpabuf_head(msg), - wpabuf_len(msg) - integ_alg->hash_len, icv); - - return 0; -} - - -int ikev2_keys_set(struct ikev2_keys *keys) -{ - return keys->SK_d && keys->SK_ai && keys->SK_ar && keys->SK_ei && - keys->SK_er && keys->SK_pi && keys->SK_pr; -} - - -void ikev2_free_keys(struct ikev2_keys *keys) -{ - os_free(keys->SK_d); - os_free(keys->SK_ai); - os_free(keys->SK_ar); - os_free(keys->SK_ei); - os_free(keys->SK_er); - os_free(keys->SK_pi); - os_free(keys->SK_pr); - keys->SK_d = keys->SK_ai = keys->SK_ar = keys->SK_ei = keys->SK_er = - keys->SK_pi = keys->SK_pr = NULL; -} - - -int ikev2_derive_sk_keys(const struct ikev2_prf_alg *prf, - const struct ikev2_integ_alg *integ, - const struct ikev2_encr_alg *encr, - const u8 *skeyseed, const u8 *data, size_t data_len, - struct ikev2_keys *keys) -{ - u8 *keybuf, *pos; - size_t keybuf_len; - - /* - * {SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr } = - * prf+(SKEYSEED, Ni | Nr | SPIi | SPIr ) - */ - ikev2_free_keys(keys); - keys->SK_d_len = prf->key_len; - keys->SK_integ_len = integ->key_len; - keys->SK_encr_len = encr->key_len; - keys->SK_prf_len = prf->key_len; -#ifdef CCNS_PL - /* Uses encryption key length for SK_d; should be PRF length */ - keys->SK_d_len = keys->SK_encr_len; -#endif /* CCNS_PL */ - - keybuf_len = keys->SK_d_len + 2 * keys->SK_integ_len + - 2 * keys->SK_encr_len + 2 * keys->SK_prf_len; - keybuf = os_malloc(keybuf_len); - if (keybuf == NULL) - return -1; - - if (ikev2_prf_plus(prf->id, skeyseed, prf->hash_len, - data, data_len, keybuf, keybuf_len)) { - os_free(keybuf); - return -1; - } - - pos = keybuf; - - keys->SK_d = os_malloc(keys->SK_d_len); - if (keys->SK_d) { - os_memcpy(keys->SK_d, pos, keys->SK_d_len); - wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_d", - keys->SK_d, keys->SK_d_len); - } - pos += keys->SK_d_len; - - keys->SK_ai = os_malloc(keys->SK_integ_len); - if (keys->SK_ai) { - os_memcpy(keys->SK_ai, pos, keys->SK_integ_len); - wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ai", - keys->SK_ai, keys->SK_integ_len); - } - pos += keys->SK_integ_len; - - keys->SK_ar = os_malloc(keys->SK_integ_len); - if (keys->SK_ar) { - os_memcpy(keys->SK_ar, pos, keys->SK_integ_len); - wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ar", - keys->SK_ar, keys->SK_integ_len); - } - pos += keys->SK_integ_len; - - keys->SK_ei = os_malloc(keys->SK_encr_len); - if (keys->SK_ei) { - os_memcpy(keys->SK_ei, pos, keys->SK_encr_len); - wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ei", - keys->SK_ei, keys->SK_encr_len); - } - pos += keys->SK_encr_len; - - keys->SK_er = os_malloc(keys->SK_encr_len); - if (keys->SK_er) { - os_memcpy(keys->SK_er, pos, keys->SK_encr_len); - wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_er", - keys->SK_er, keys->SK_encr_len); - } - pos += keys->SK_encr_len; - - keys->SK_pi = os_malloc(keys->SK_prf_len); - if (keys->SK_pi) { - os_memcpy(keys->SK_pi, pos, keys->SK_prf_len); - wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pi", - keys->SK_pi, keys->SK_prf_len); - } - pos += keys->SK_prf_len; - - keys->SK_pr = os_malloc(keys->SK_prf_len); - if (keys->SK_pr) { - os_memcpy(keys->SK_pr, pos, keys->SK_prf_len); - wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pr", - keys->SK_pr, keys->SK_prf_len); - } - - os_free(keybuf); - - if (!ikev2_keys_set(keys)) { - ikev2_free_keys(keys); - return -1; - } - - return 0; -} diff --git a/contrib/hostapd/src/eap_common/ikev2_common.h b/contrib/hostapd/src/eap_common/ikev2_common.h deleted file mode 100644 index c96a070d5b..0000000000 --- a/contrib/hostapd/src/eap_common/ikev2_common.h +++ /dev/null @@ -1,344 +0,0 @@ -/* - * IKEv2 definitions - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IKEV2_COMMON_H -#define IKEV2_COMMON_H - -/* - * Nonce length must be at least 16 octets. It must also be at least half the - * key size of the negotiated PRF. - */ -#define IKEV2_NONCE_MIN_LEN 16 -#define IKEV2_NONCE_MAX_LEN 256 - -/* IKE Header - RFC 4306, Sect. 3.1 */ -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -#define IKEV2_SPI_LEN 8 - -struct ikev2_hdr { - u8 i_spi[IKEV2_SPI_LEN]; /* IKE_SA Initiator's SPI */ - u8 r_spi[IKEV2_SPI_LEN]; /* IKE_SA Responder's SPI */ - u8 next_payload; - u8 version; /* MjVer | MnVer */ - u8 exchange_type; - u8 flags; - u8 message_id[4]; - u8 length[4]; /* total length of HDR + payloads */ -} STRUCT_PACKED; - -struct ikev2_payload_hdr { - u8 next_payload; - u8 flags; - u8 payload_length[2]; /* this payload, including the payload header */ -} STRUCT_PACKED; - -struct ikev2_proposal { - u8 type; /* 0 (last) or 2 (more) */ - u8 reserved; - u8 proposal_length[2]; /* including all transform and attributes */ - u8 proposal_num; - u8 protocol_id; /* IKEV2_PROTOCOL_* */ - u8 spi_size; - u8 num_transforms; - /* SPI of spi_size octets */ - /* Transforms */ -} STRUCT_PACKED; - -struct ikev2_transform { - u8 type; /* 0 (last) or 3 (more) */ - u8 reserved; - u8 transform_length[2]; /* including Header and Attributes */ - u8 transform_type; - u8 reserved2; - u8 transform_id[2]; - /* Transform Attributes */ -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -/* Current IKEv2 version from RFC 4306 */ -#define IKEV2_MjVer 2 -#define IKEV2_MnVer 0 -#ifdef CCNS_PL -#define IKEV2_VERSION ((IKEV2_MjVer) | ((IKEV2_MnVer) << 4)) -#else /* CCNS_PL */ -#define IKEV2_VERSION (((IKEV2_MjVer) << 4) | (IKEV2_MnVer)) -#endif /* CCNS_PL */ - -/* IKEv2 Exchange Types */ -enum { - /* 0-33 RESERVED */ - IKE_SA_INIT = 34, - IKE_SA_AUTH = 35, - CREATE_CHILD_SA = 36, - INFORMATION = 37 - /* 38-239 RESERVED TO IANA */ - /* 240-255 Reserved for private use */ -}; - -/* IKEv2 Flags */ -#define IKEV2_HDR_INITIATOR 0x08 -#define IKEV2_HDR_VERSION 0x10 -#define IKEV2_HDR_RESPONSE 0x20 - -/* Payload Header Flags */ -#define IKEV2_PAYLOAD_FLAGS_CRITICAL 0x01 - - -/* EAP-IKEv2 Payload Types (in Next Payload Type field) - * http://www.iana.org/assignments/eap-ikev2-payloads */ -enum { - IKEV2_PAYLOAD_NO_NEXT_PAYLOAD = 0, - IKEV2_PAYLOAD_SA = 33, - IKEV2_PAYLOAD_KEY_EXCHANGE = 34, - IKEV2_PAYLOAD_IDi = 35, - IKEV2_PAYLOAD_IDr = 36, - IKEV2_PAYLOAD_CERTIFICATE = 37, - IKEV2_PAYLOAD_CERT_REQ = 38, - IKEV2_PAYLOAD_AUTHENTICATION = 39, - IKEV2_PAYLOAD_NONCE = 40, - IKEV2_PAYLOAD_NOTIFICATION = 41, - IKEV2_PAYLOAD_VENDOD_ID = 43, - IKEV2_PAYLOAD_ENCRYPTED = 46, - IKEV2_PAYLOAD_NEXT_FAST_ID = 121 -}; - - -/* IKEv2 Proposal - Protocol ID */ -enum { - IKEV2_PROTOCOL_RESERVED = 0, - IKEV2_PROTOCOL_IKE = 1, /* IKE is the only one allowed for EAP-IKEv2 */ - IKEV2_PROTOCOL_AH = 2, - IKEV2_PROTOCOL_ESP = 3 -}; - - -/* IKEv2 Transform Types */ -enum { - IKEV2_TRANSFORM_ENCR = 1, - IKEV2_TRANSFORM_PRF = 2, - IKEV2_TRANSFORM_INTEG = 3, - IKEV2_TRANSFORM_DH = 4, - IKEV2_TRANSFORM_ESN = 5 -}; - -/* IKEv2 Tranform Type 1 (Encryption Algorithm) */ -enum { - ENCR_DES_IV64 = 1, - ENCR_DES = 2, - ENCR_3DES = 3, - ENCR_RC5 = 4, - ENCR_IDEA = 5, - ENCR_CAST = 6, - ENCR_BLOWFISH = 7, - ENCR_3IDEA = 8, - ENCR_DES_IV32 = 9, - ENCR_NULL = 11, - ENCR_AES_CBC = 12, - ENCR_AES_CTR = 13 -}; - -/* IKEv2 Transform Type 2 (Pseudo-random Function) */ -enum { - PRF_HMAC_MD5 = 1, - PRF_HMAC_SHA1 = 2, - PRF_HMAC_TIGER = 3, - PRF_AES128_XCBC = 4 -}; - -/* IKEv2 Transform Type 3 (Integrity Algorithm) */ -enum { - AUTH_HMAC_MD5_96 = 1, - AUTH_HMAC_SHA1_96 = 2, - AUTH_DES_MAC = 3, - AUTH_KPDK_MD5 = 4, - AUTH_AES_XCBC_96 = 5 -}; - -/* IKEv2 Transform Type 4 (Diffie-Hellman Group) */ -enum { - DH_GROUP1_768BIT_MODP = 1, /* RFC 4306 */ - DH_GROUP2_1024BIT_MODP = 2, /* RFC 4306 */ - DH_GROUP5_1536BIT_MODP = 5, /* RFC 3526 */ - DH_GROUP5_2048BIT_MODP = 14, /* RFC 3526 */ - DH_GROUP5_3072BIT_MODP = 15, /* RFC 3526 */ - DH_GROUP5_4096BIT_MODP = 16, /* RFC 3526 */ - DH_GROUP5_6144BIT_MODP = 17, /* RFC 3526 */ - DH_GROUP5_8192BIT_MODP = 18 /* RFC 3526 */ -}; - - -/* Identification Data Types (RFC 4306, Sect. 3.5) */ -enum { - ID_IPV4_ADDR = 1, - ID_FQDN = 2, - ID_RFC822_ADDR = 3, - ID_IPV6_ADDR = 5, - ID_DER_ASN1_DN = 9, - ID_DER_ASN1_GN= 10, - ID_KEY_ID = 11 -}; - - -/* Certificate Encoding (RFC 4306, Sect. 3.6) */ -enum { - CERT_ENCODING_PKCS7_X509 = 1, - CERT_ENCODING_PGP_CERT = 2, - CERT_ENCODING_DNS_SIGNED_KEY = 3, - /* X.509 Certificate - Signature: DER encoded X.509 certificate whose - * public key is used to validate the sender's AUTH payload */ - CERT_ENCODING_X509_CERT_SIGN = 4, - CERT_ENCODING_KERBEROS_TOKEN = 6, - /* DER encoded X.509 certificate revocation list */ - CERT_ENCODING_CRL = 7, - CERT_ENCODING_ARL = 8, - CERT_ENCODING_SPKI_CERT = 9, - CERT_ENCODING_X509_CERT_ATTR = 10, - /* PKCS #1 encoded RSA key */ - CERT_ENCODING_RAW_RSA_KEY = 11, - CERT_ENCODING_HASH_AND_URL_X509_CERT = 12, - CERT_ENCODING_HASH_AND_URL_X509_BUNDLE = 13 -}; - - -/* Authentication Method (RFC 4306, Sect. 3.8) */ -enum { - AUTH_RSA_SIGN = 1, - AUTH_SHARED_KEY_MIC = 2, - AUTH_DSS_SIGN = 3 -}; - - -/* Notify Message Types (RFC 4306, Sect. 3.10.1) */ -enum { - UNSUPPORTED_CRITICAL_PAYLOAD = 1, - INVALID_IKE_SPI = 4, - INVALID_MAJOR_VERSION = 5, - INVALID_SYNTAX = 7, - INVALID_MESSAGE_ID = 9, - INVALID_SPI = 11, - NO_PROPOSAL_CHOSEN = 14, - INVALID_KE_PAYLOAD = 17, - AUTHENTICATION_FAILED = 24, - SINGLE_PAIR_REQUIRED = 34, - NO_ADDITIONAL_SAS = 35, - INTERNAL_ADDRESS_FAILURE = 36, - FAILED_CP_REQUIRED = 37, - TS_UNACCEPTABLE = 38, - INVALID_SELECTORS = 39 -}; - - -struct ikev2_keys { - u8 *SK_d, *SK_ai, *SK_ar, *SK_ei, *SK_er, *SK_pi, *SK_pr; - size_t SK_d_len, SK_integ_len, SK_encr_len, SK_prf_len; -}; - - -int ikev2_keys_set(struct ikev2_keys *keys); -void ikev2_free_keys(struct ikev2_keys *keys); - - -/* Maximum hash length for supported hash algorithms */ -#define IKEV2_MAX_HASH_LEN 20 - -struct ikev2_integ_alg { - int id; - size_t key_len; - size_t hash_len; -}; - -struct ikev2_prf_alg { - int id; - size_t key_len; - size_t hash_len; -}; - -struct ikev2_encr_alg { - int id; - size_t key_len; - size_t block_size; -}; - -const struct ikev2_integ_alg * ikev2_get_integ(int id); -int ikev2_integ_hash(int alg, const u8 *key, size_t key_len, const u8 *data, - size_t data_len, u8 *hash); -const struct ikev2_prf_alg * ikev2_get_prf(int id); -int ikev2_prf_hash(int alg, const u8 *key, size_t key_len, - size_t num_elem, const u8 *addr[], const size_t *len, - u8 *hash); -int ikev2_prf_plus(int alg, const u8 *key, size_t key_len, - const u8 *data, size_t data_len, - u8 *out, size_t out_len); -const struct ikev2_encr_alg * ikev2_get_encr(int id); -int ikev2_encr_encrypt(int alg, const u8 *key, size_t key_len, const u8 *iv, - const u8 *plain, u8 *crypt, size_t len); -int ikev2_encr_decrypt(int alg, const u8 *key, size_t key_len, const u8 *iv, - const u8 *crypt, u8 *plain, size_t len); - -int ikev2_derive_auth_data(int prf_alg, const struct wpabuf *sign_msg, - const u8 *ID, size_t ID_len, u8 ID_type, - struct ikev2_keys *keys, int initiator, - const u8 *shared_secret, size_t shared_secret_len, - const u8 *nonce, size_t nonce_len, - const u8 *key_pad, size_t key_pad_len, - u8 *auth_data); - - -struct ikev2_payloads { - const u8 *sa; - size_t sa_len; - const u8 *ke; - size_t ke_len; - const u8 *idi; - size_t idi_len; - const u8 *idr; - size_t idr_len; - const u8 *cert; - size_t cert_len; - const u8 *auth; - size_t auth_len; - const u8 *nonce; - size_t nonce_len; - const u8 *encrypted; - size_t encrypted_len; - u8 encr_next_payload; - const u8 *notification; - size_t notification_len; -}; - -int ikev2_parse_payloads(struct ikev2_payloads *payloads, - u8 next_payload, const u8 *pos, const u8 *end); - -u8 * ikev2_decrypt_payload(int encr_id, int integ_id, struct ikev2_keys *keys, - int initiator, const struct ikev2_hdr *hdr, - const u8 *encrypted, size_t encrypted_len, - size_t *res_len); -void ikev2_update_hdr(struct wpabuf *msg); -int ikev2_build_encrypted(int encr_id, int integ_id, struct ikev2_keys *keys, - int initiator, struct wpabuf *msg, - struct wpabuf *plain, u8 next_payload); -int ikev2_derive_sk_keys(const struct ikev2_prf_alg *prf, - const struct ikev2_integ_alg *integ, - const struct ikev2_encr_alg *encr, - const u8 *skeyseed, const u8 *data, size_t data_len, - struct ikev2_keys *keys); - -#endif /* IKEV2_COMMON_H */ diff --git a/contrib/hostapd/src/eap_peer/eap.c b/contrib/hostapd/src/eap_peer/eap.c deleted file mode 100644 index e8e504af54..0000000000 --- a/contrib/hostapd/src/eap_peer/eap.c +++ /dev/null @@ -1,2075 +0,0 @@ -/* - * EAP peer state machines (RFC 4137) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file implements the Peer State Machine as defined in RFC 4137. The used - * states and state transitions match mostly with the RFC. However, there are - * couple of additional transitions for working around small issues noticed - * during testing. These exceptions are explained in comments within the - * functions in this file. The method functions, m.func(), are similar to the - * ones used in RFC 4137, but some small changes have used here to optimize - * operations and to add functionality needed for fast re-authentication - * (session resumption). - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "eap_config.h" -#include "tls.h" -#include "crypto.h" -#include "pcsc_funcs.h" -#include "wpa_ctrl.h" -#include "state_machine.h" -#include "eap_common/eap_wsc_common.h" - -#define STATE_MACHINE_DATA struct eap_sm -#define STATE_MACHINE_DEBUG_PREFIX "EAP" - -#define EAP_MAX_AUTH_ROUNDS 50 - - -static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor, - EapType method); -static struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id); -static void eap_sm_processIdentity(struct eap_sm *sm, - const struct wpabuf *req); -static void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req); -static struct wpabuf * eap_sm_buildNotify(int id); -static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req); -#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) -static const char * eap_sm_method_state_txt(EapMethodState state); -static const char * eap_sm_decision_txt(EapDecision decision); -#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ - - - -static Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var) -{ - return sm->eapol_cb->get_bool(sm->eapol_ctx, var); -} - - -static void eapol_set_bool(struct eap_sm *sm, enum eapol_bool_var var, - Boolean value) -{ - sm->eapol_cb->set_bool(sm->eapol_ctx, var, value); -} - - -static unsigned int eapol_get_int(struct eap_sm *sm, enum eapol_int_var var) -{ - return sm->eapol_cb->get_int(sm->eapol_ctx, var); -} - - -static void eapol_set_int(struct eap_sm *sm, enum eapol_int_var var, - unsigned int value) -{ - sm->eapol_cb->set_int(sm->eapol_ctx, var, value); -} - - -static struct wpabuf * eapol_get_eapReqData(struct eap_sm *sm) -{ - return sm->eapol_cb->get_eapReqData(sm->eapol_ctx); -} - - -static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt) -{ - if (sm->m == NULL || sm->eap_method_priv == NULL) - return; - - wpa_printf(MSG_DEBUG, "EAP: deinitialize previously used EAP method " - "(%d, %s) at %s", sm->selectedMethod, sm->m->name, txt); - sm->m->deinit(sm, sm->eap_method_priv); - sm->eap_method_priv = NULL; - sm->m = NULL; -} - - -/** - * 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) -{ - struct eap_peer_config *config = eap_get_config(sm); - int i; - struct eap_method_type *m; - - if (config == NULL || config->eap_methods == NULL) - return 1; - - m = config->eap_methods; - for (i = 0; m[i].vendor != EAP_VENDOR_IETF || - m[i].method != EAP_TYPE_NONE; i++) { - if (m[i].vendor == vendor && m[i].method == method) - return 1; - } - return 0; -} - - -/* - * This state initializes state machine variables when the machine is - * activated (portEnabled = TRUE). This is also used when re-starting - * authentication (eapRestart == TRUE). - */ -SM_STATE(EAP, INITIALIZE) -{ - SM_ENTRY(EAP, INITIALIZE); - if (sm->fast_reauth && sm->m && sm->m->has_reauth_data && - sm->m->has_reauth_data(sm, sm->eap_method_priv) && - !sm->prev_failure) { - wpa_printf(MSG_DEBUG, "EAP: maintaining EAP method data for " - "fast reauthentication"); - sm->m->deinit_for_reauth(sm, sm->eap_method_priv); - } else { - eap_deinit_prev_method(sm, "INITIALIZE"); - } - sm->selectedMethod = EAP_TYPE_NONE; - sm->methodState = METHOD_NONE; - sm->allowNotifications = TRUE; - sm->decision = DECISION_FAIL; - eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout); - eapol_set_bool(sm, EAPOL_eapSuccess, FALSE); - eapol_set_bool(sm, EAPOL_eapFail, FALSE); - os_free(sm->eapKeyData); - sm->eapKeyData = NULL; - sm->eapKeyAvailable = FALSE; - eapol_set_bool(sm, EAPOL_eapRestart, FALSE); - sm->lastId = -1; /* new session - make sure this does not match with - * the first EAP-Packet */ - /* - * RFC 4137 does not reset eapResp and eapNoResp here. However, this - * seemed to be able to trigger cases where both were set and if EAPOL - * state machine uses eapNoResp first, it may end up not sending a real - * reply correctly. This occurred when the workaround in FAIL state set - * eapNoResp = TRUE.. Maybe that workaround needs to be fixed to do - * something else(?) - */ - eapol_set_bool(sm, EAPOL_eapResp, FALSE); - eapol_set_bool(sm, EAPOL_eapNoResp, FALSE); - sm->num_rounds = 0; - sm->prev_failure = 0; -} - - -/* - * This state is reached whenever service from the lower layer is interrupted - * or unavailable (portEnabled == FALSE). Immediate transition to INITIALIZE - * occurs when the port becomes enabled. - */ -SM_STATE(EAP, DISABLED) -{ - SM_ENTRY(EAP, DISABLED); - sm->num_rounds = 0; -} - - -/* - * The state machine spends most of its time here, waiting for something to - * happen. This state is entered unconditionally from INITIALIZE, DISCARD, and - * SEND_RESPONSE states. - */ -SM_STATE(EAP, IDLE) -{ - SM_ENTRY(EAP, IDLE); -} - - -/* - * This state is entered when an EAP packet is received (eapReq == TRUE) to - * parse the packet header. - */ -SM_STATE(EAP, RECEIVED) -{ - const struct wpabuf *eapReqData; - - SM_ENTRY(EAP, RECEIVED); - eapReqData = eapol_get_eapReqData(sm); - /* parse rxReq, rxSuccess, rxFailure, reqId, reqMethod */ - eap_sm_parseEapReq(sm, eapReqData); - sm->num_rounds++; -} - - -/* - * This state is entered when a request for a new type comes in. Either the - * correct method is started, or a Nak response is built. - */ -SM_STATE(EAP, GET_METHOD) -{ - int reinit; - EapType method; - - SM_ENTRY(EAP, GET_METHOD); - - if (sm->reqMethod == EAP_TYPE_EXPANDED) - method = sm->reqVendorMethod; - else - method = sm->reqMethod; - - if (!eap_sm_allowMethod(sm, sm->reqVendor, method)) { - wpa_printf(MSG_DEBUG, "EAP: vendor %u method %u not allowed", - sm->reqVendor, method); - goto nak; - } - - /* - * RFC 4137 does not define specific operation for fast - * re-authentication (session resumption). The design here is to allow - * the previously used method data to be maintained for - * re-authentication if the method support session resumption. - * Otherwise, the previously used method data is freed and a new method - * is allocated here. - */ - if (sm->fast_reauth && - sm->m && sm->m->vendor == sm->reqVendor && - sm->m->method == method && - sm->m->has_reauth_data && - sm->m->has_reauth_data(sm, sm->eap_method_priv)) { - wpa_printf(MSG_DEBUG, "EAP: Using previous method data" - " for fast re-authentication"); - reinit = 1; - } else { - eap_deinit_prev_method(sm, "GET_METHOD"); - reinit = 0; - } - - sm->selectedMethod = sm->reqMethod; - if (sm->m == NULL) - sm->m = eap_peer_get_eap_method(sm->reqVendor, method); - if (!sm->m) { - wpa_printf(MSG_DEBUG, "EAP: Could not find selected method: " - "vendor %d method %d", - sm->reqVendor, method); - goto nak; - } - - wpa_printf(MSG_DEBUG, "EAP: Initialize selected EAP method: " - "vendor %u method %u (%s)", - sm->reqVendor, method, sm->m->name); - if (reinit) - sm->eap_method_priv = sm->m->init_for_reauth( - sm, sm->eap_method_priv); - else - sm->eap_method_priv = sm->m->init(sm); - - if (sm->eap_method_priv == NULL) { - struct eap_peer_config *config = eap_get_config(sm); - wpa_msg(sm->msg_ctx, MSG_INFO, - "EAP: Failed to initialize EAP method: vendor %u " - "method %u (%s)", - sm->reqVendor, method, sm->m->name); - sm->m = NULL; - sm->methodState = METHOD_NONE; - sm->selectedMethod = EAP_TYPE_NONE; - if (sm->reqMethod == EAP_TYPE_TLS && config && - (config->pending_req_pin || - config->pending_req_passphrase)) { - /* - * Return without generating Nak in order to allow - * entering of PIN code or passphrase to retry the - * current EAP packet. - */ - wpa_printf(MSG_DEBUG, "EAP: Pending PIN/passphrase " - "request - skip Nak"); - return; - } - - goto nak; - } - - sm->methodState = METHOD_INIT; - wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_METHOD - "EAP vendor %u method %u (%s) selected", - sm->reqVendor, method, sm->m->name); - return; - -nak: - wpabuf_free(sm->eapRespData); - sm->eapRespData = NULL; - sm->eapRespData = eap_sm_buildNak(sm, sm->reqId); -} - - -/* - * The method processing happens here. The request from the authenticator is - * processed, and an appropriate response packet is built. - */ -SM_STATE(EAP, METHOD) -{ - struct wpabuf *eapReqData; - struct eap_method_ret ret; - - SM_ENTRY(EAP, METHOD); - if (sm->m == NULL) { - wpa_printf(MSG_WARNING, "EAP::METHOD - method not selected"); - return; - } - - eapReqData = eapol_get_eapReqData(sm); - - /* - * Get ignore, methodState, decision, allowNotifications, and - * eapRespData. RFC 4137 uses three separate method procedure (check, - * process, and buildResp) in this state. These have been combined into - * a single function call to m->process() in order to optimize EAP - * method implementation interface a bit. These procedures are only - * used from within this METHOD state, so there is no need to keep - * these as separate C functions. - * - * The RFC 4137 procedures return values as follows: - * ignore = m.check(eapReqData) - * (methodState, decision, allowNotifications) = m.process(eapReqData) - * eapRespData = m.buildResp(reqId) - */ - os_memset(&ret, 0, sizeof(ret)); - ret.ignore = sm->ignore; - ret.methodState = sm->methodState; - ret.decision = sm->decision; - ret.allowNotifications = sm->allowNotifications; - wpabuf_free(sm->eapRespData); - sm->eapRespData = NULL; - sm->eapRespData = sm->m->process(sm, sm->eap_method_priv, &ret, - eapReqData); - wpa_printf(MSG_DEBUG, "EAP: method process -> ignore=%s " - "methodState=%s decision=%s", - ret.ignore ? "TRUE" : "FALSE", - eap_sm_method_state_txt(ret.methodState), - eap_sm_decision_txt(ret.decision)); - - sm->ignore = ret.ignore; - if (sm->ignore) - return; - sm->methodState = ret.methodState; - sm->decision = ret.decision; - sm->allowNotifications = ret.allowNotifications; - - if (sm->m->isKeyAvailable && sm->m->getKey && - sm->m->isKeyAvailable(sm, sm->eap_method_priv)) { - os_free(sm->eapKeyData); - sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv, - &sm->eapKeyDataLen); - } -} - - -/* - * This state signals the lower layer that a response packet is ready to be - * sent. - */ -SM_STATE(EAP, SEND_RESPONSE) -{ - SM_ENTRY(EAP, SEND_RESPONSE); - wpabuf_free(sm->lastRespData); - if (sm->eapRespData) { - if (sm->workaround) - os_memcpy(sm->last_md5, sm->req_md5, 16); - sm->lastId = sm->reqId; - sm->lastRespData = wpabuf_dup(sm->eapRespData); - eapol_set_bool(sm, EAPOL_eapResp, TRUE); - } else - sm->lastRespData = NULL; - eapol_set_bool(sm, EAPOL_eapReq, FALSE); - eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout); -} - - -/* - * This state signals the lower layer that the request was discarded, and no - * response packet will be sent at this time. - */ -SM_STATE(EAP, DISCARD) -{ - SM_ENTRY(EAP, DISCARD); - eapol_set_bool(sm, EAPOL_eapReq, FALSE); - eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); -} - - -/* - * Handles requests for Identity method and builds a response. - */ -SM_STATE(EAP, IDENTITY) -{ - const struct wpabuf *eapReqData; - - SM_ENTRY(EAP, IDENTITY); - eapReqData = eapol_get_eapReqData(sm); - eap_sm_processIdentity(sm, eapReqData); - wpabuf_free(sm->eapRespData); - sm->eapRespData = NULL; - sm->eapRespData = eap_sm_buildIdentity(sm, sm->reqId, 0); -} - - -/* - * Handles requests for Notification method and builds a response. - */ -SM_STATE(EAP, NOTIFICATION) -{ - const struct wpabuf *eapReqData; - - SM_ENTRY(EAP, NOTIFICATION); - eapReqData = eapol_get_eapReqData(sm); - eap_sm_processNotify(sm, eapReqData); - wpabuf_free(sm->eapRespData); - sm->eapRespData = NULL; - sm->eapRespData = eap_sm_buildNotify(sm->reqId); -} - - -/* - * This state retransmits the previous response packet. - */ -SM_STATE(EAP, RETRANSMIT) -{ - SM_ENTRY(EAP, RETRANSMIT); - wpabuf_free(sm->eapRespData); - if (sm->lastRespData) - sm->eapRespData = wpabuf_dup(sm->lastRespData); - else - sm->eapRespData = NULL; -} - - -/* - * This state is entered in case of a successful completion of authentication - * and state machine waits here until port is disabled or EAP authentication is - * restarted. - */ -SM_STATE(EAP, SUCCESS) -{ - SM_ENTRY(EAP, SUCCESS); - if (sm->eapKeyData != NULL) - sm->eapKeyAvailable = TRUE; - eapol_set_bool(sm, EAPOL_eapSuccess, TRUE); - - /* - * RFC 4137 does not clear eapReq here, but this seems to be required - * to avoid processing the same request twice when state machine is - * initialized. - */ - eapol_set_bool(sm, EAPOL_eapReq, FALSE); - - /* - * RFC 4137 does not set eapNoResp here, but this seems to be required - * to get EAPOL Supplicant backend state machine into SUCCESS state. In - * addition, either eapResp or eapNoResp is required to be set after - * processing the received EAP frame. - */ - eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); - - wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS - "EAP authentication completed successfully"); -} - - -/* - * This state is entered in case of a failure and state machine waits here - * until port is disabled or EAP authentication is restarted. - */ -SM_STATE(EAP, FAILURE) -{ - SM_ENTRY(EAP, FAILURE); - eapol_set_bool(sm, EAPOL_eapFail, TRUE); - - /* - * RFC 4137 does not clear eapReq here, but this seems to be required - * to avoid processing the same request twice when state machine is - * initialized. - */ - eapol_set_bool(sm, EAPOL_eapReq, FALSE); - - /* - * RFC 4137 does not set eapNoResp here. However, either eapResp or - * eapNoResp is required to be set after processing the received EAP - * frame. - */ - eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); - - wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE - "EAP authentication failed"); - - sm->prev_failure = 1; -} - - -static int eap_success_workaround(struct eap_sm *sm, int reqId, int lastId) -{ - /* - * At least Microsoft IAS and Meetinghouse Aegis seem to be sending - * EAP-Success/Failure with lastId + 1 even though RFC 3748 and - * RFC 4137 require that reqId == lastId. In addition, it looks like - * Ringmaster v2.1.2.0 would be using lastId + 2 in EAP-Success. - * - * Accept this kind of Id if EAP workarounds are enabled. These are - * unauthenticated plaintext messages, so this should have minimal - * security implications (bit easier to fake EAP-Success/Failure). - */ - if (sm->workaround && (reqId == ((lastId + 1) & 0xff) || - reqId == ((lastId + 2) & 0xff))) { - wpa_printf(MSG_DEBUG, "EAP: Workaround for unexpected " - "identifier field in EAP Success: " - "reqId=%d lastId=%d (these are supposed to be " - "same)", reqId, lastId); - return 1; - } - wpa_printf(MSG_DEBUG, "EAP: EAP-Success Id mismatch - reqId=%d " - "lastId=%d", reqId, lastId); - return 0; -} - - -/* - * RFC 4137 - Appendix A.1: EAP Peer State Machine - State transitions - */ - -static void eap_peer_sm_step_idle(struct eap_sm *sm) -{ - /* - * The first three transitions are from RFC 4137. The last two are - * local additions to handle special cases with LEAP and PEAP server - * not sending EAP-Success in some cases. - */ - if (eapol_get_bool(sm, EAPOL_eapReq)) - SM_ENTER(EAP, RECEIVED); - else if ((eapol_get_bool(sm, EAPOL_altAccept) && - sm->decision != DECISION_FAIL) || - (eapol_get_int(sm, EAPOL_idleWhile) == 0 && - sm->decision == DECISION_UNCOND_SUCC)) - SM_ENTER(EAP, SUCCESS); - else if (eapol_get_bool(sm, EAPOL_altReject) || - (eapol_get_int(sm, EAPOL_idleWhile) == 0 && - sm->decision != DECISION_UNCOND_SUCC) || - (eapol_get_bool(sm, EAPOL_altAccept) && - sm->methodState != METHOD_CONT && - sm->decision == DECISION_FAIL)) - SM_ENTER(EAP, FAILURE); - else if (sm->selectedMethod == EAP_TYPE_LEAP && - sm->leap_done && sm->decision != DECISION_FAIL && - sm->methodState == METHOD_DONE) - SM_ENTER(EAP, SUCCESS); - else if (sm->selectedMethod == EAP_TYPE_PEAP && - sm->peap_done && sm->decision != DECISION_FAIL && - sm->methodState == METHOD_DONE) - SM_ENTER(EAP, SUCCESS); -} - - -static int eap_peer_req_is_duplicate(struct eap_sm *sm) -{ - int duplicate; - - duplicate = (sm->reqId == sm->lastId) && sm->rxReq; - if (sm->workaround && duplicate && - os_memcmp(sm->req_md5, sm->last_md5, 16) != 0) { - /* - * RFC 4137 uses (reqId == lastId) as the only verification for - * duplicate EAP requests. However, this misses cases where the - * AS is incorrectly using the same id again; and - * unfortunately, such implementations exist. Use MD5 hash as - * an extra verification for the packets being duplicate to - * workaround these issues. - */ - wpa_printf(MSG_DEBUG, "EAP: AS used the same Id again, but " - "EAP packets were not identical"); - wpa_printf(MSG_DEBUG, "EAP: workaround - assume this is not a " - "duplicate packet"); - duplicate = 0; - } - - return duplicate; -} - - -static void eap_peer_sm_step_received(struct eap_sm *sm) -{ - int duplicate = eap_peer_req_is_duplicate(sm); - - /* - * Two special cases below for LEAP are local additions to work around - * odd LEAP behavior (EAP-Success in the middle of authentication and - * then swapped roles). Other transitions are based on RFC 4137. - */ - if (sm->rxSuccess && sm->decision != DECISION_FAIL && - (sm->reqId == sm->lastId || - eap_success_workaround(sm, sm->reqId, sm->lastId))) - SM_ENTER(EAP, SUCCESS); - else if (sm->methodState != METHOD_CONT && - ((sm->rxFailure && - sm->decision != DECISION_UNCOND_SUCC) || - (sm->rxSuccess && sm->decision == DECISION_FAIL && - (sm->selectedMethod != EAP_TYPE_LEAP || - sm->methodState != METHOD_MAY_CONT))) && - (sm->reqId == sm->lastId || - eap_success_workaround(sm, sm->reqId, sm->lastId))) - SM_ENTER(EAP, FAILURE); - else if (sm->rxReq && duplicate) - SM_ENTER(EAP, RETRANSMIT); - else if (sm->rxReq && !duplicate && - sm->reqMethod == EAP_TYPE_NOTIFICATION && - sm->allowNotifications) - SM_ENTER(EAP, NOTIFICATION); - else if (sm->rxReq && !duplicate && - sm->selectedMethod == EAP_TYPE_NONE && - sm->reqMethod == EAP_TYPE_IDENTITY) - SM_ENTER(EAP, IDENTITY); - else if (sm->rxReq && !duplicate && - sm->selectedMethod == EAP_TYPE_NONE && - sm->reqMethod != EAP_TYPE_IDENTITY && - sm->reqMethod != EAP_TYPE_NOTIFICATION) - SM_ENTER(EAP, GET_METHOD); - else if (sm->rxReq && !duplicate && - sm->reqMethod == sm->selectedMethod && - sm->methodState != METHOD_DONE) - SM_ENTER(EAP, METHOD); - else if (sm->selectedMethod == EAP_TYPE_LEAP && - (sm->rxSuccess || sm->rxResp)) - SM_ENTER(EAP, METHOD); - else - SM_ENTER(EAP, DISCARD); -} - - -static void eap_peer_sm_step_local(struct eap_sm *sm) -{ - switch (sm->EAP_state) { - case EAP_INITIALIZE: - SM_ENTER(EAP, IDLE); - break; - case EAP_DISABLED: - if (eapol_get_bool(sm, EAPOL_portEnabled) && - !sm->force_disabled) - SM_ENTER(EAP, INITIALIZE); - break; - case EAP_IDLE: - eap_peer_sm_step_idle(sm); - break; - case EAP_RECEIVED: - eap_peer_sm_step_received(sm); - break; - case EAP_GET_METHOD: - if (sm->selectedMethod == sm->reqMethod) - SM_ENTER(EAP, METHOD); - else - SM_ENTER(EAP, SEND_RESPONSE); - break; - case EAP_METHOD: - if (sm->ignore) - SM_ENTER(EAP, DISCARD); - else - SM_ENTER(EAP, SEND_RESPONSE); - break; - case EAP_SEND_RESPONSE: - SM_ENTER(EAP, IDLE); - break; - case EAP_DISCARD: - SM_ENTER(EAP, IDLE); - break; - case EAP_IDENTITY: - SM_ENTER(EAP, SEND_RESPONSE); - break; - case EAP_NOTIFICATION: - SM_ENTER(EAP, SEND_RESPONSE); - break; - case EAP_RETRANSMIT: - SM_ENTER(EAP, SEND_RESPONSE); - break; - case EAP_SUCCESS: - break; - case EAP_FAILURE: - break; - } -} - - -SM_STEP(EAP) -{ - /* Global transitions */ - if (eapol_get_bool(sm, EAPOL_eapRestart) && - eapol_get_bool(sm, EAPOL_portEnabled)) - SM_ENTER_GLOBAL(EAP, INITIALIZE); - else if (!eapol_get_bool(sm, EAPOL_portEnabled) || sm->force_disabled) - SM_ENTER_GLOBAL(EAP, DISABLED); - else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) { - /* RFC 4137 does not place any limit on number of EAP messages - * in an authentication session. However, some error cases have - * ended up in a state were EAP messages were sent between the - * peer and server in a loop (e.g., TLS ACK frame in both - * direction). Since this is quite undesired outcome, limit the - * total number of EAP round-trips and abort authentication if - * this limit is exceeded. - */ - if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) { - wpa_msg(sm->msg_ctx, MSG_INFO, "EAP: more than %d " - "authentication rounds - abort", - EAP_MAX_AUTH_ROUNDS); - sm->num_rounds++; - SM_ENTER_GLOBAL(EAP, FAILURE); - } - } else { - /* Local transitions */ - eap_peer_sm_step_local(sm); - } -} - - -static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor, - EapType method) -{ - if (!eap_allowed_method(sm, vendor, method)) { - wpa_printf(MSG_DEBUG, "EAP: configuration does not allow: " - "vendor %u method %u", vendor, method); - return FALSE; - } - if (eap_peer_get_eap_method(vendor, method)) - return TRUE; - wpa_printf(MSG_DEBUG, "EAP: not included in build: " - "vendor %u method %u", vendor, method); - return FALSE; -} - - -static struct wpabuf * eap_sm_build_expanded_nak( - struct eap_sm *sm, int id, const struct eap_method *methods, - size_t count) -{ - struct wpabuf *resp; - int found = 0; - const struct eap_method *m; - - wpa_printf(MSG_DEBUG, "EAP: Building expanded EAP-Nak"); - - /* RFC 3748 - 5.3.2: Expanded Nak */ - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EXPANDED, - 8 + 8 * (count + 1), EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - wpabuf_put_be24(resp, EAP_VENDOR_IETF); - wpabuf_put_be32(resp, EAP_TYPE_NAK); - - for (m = methods; m; m = m->next) { - if (sm->reqVendor == m->vendor && - sm->reqVendorMethod == m->method) - continue; /* do not allow the current method again */ - if (eap_allowed_method(sm, m->vendor, m->method)) { - wpa_printf(MSG_DEBUG, "EAP: allowed type: " - "vendor=%u method=%u", - m->vendor, m->method); - wpabuf_put_u8(resp, EAP_TYPE_EXPANDED); - wpabuf_put_be24(resp, m->vendor); - wpabuf_put_be32(resp, m->method); - - found++; - } - } - if (!found) { - wpa_printf(MSG_DEBUG, "EAP: no more allowed methods"); - wpabuf_put_u8(resp, EAP_TYPE_EXPANDED); - wpabuf_put_be24(resp, EAP_VENDOR_IETF); - wpabuf_put_be32(resp, EAP_TYPE_NONE); - } - - eap_update_len(resp); - - return resp; -} - - -static struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id) -{ - struct wpabuf *resp; - u8 *start; - int found = 0, expanded_found = 0; - size_t count; - const struct eap_method *methods, *m; - - wpa_printf(MSG_DEBUG, "EAP: Building EAP-Nak (requested type %u " - "vendor=%u method=%u not allowed)", sm->reqMethod, - sm->reqVendor, sm->reqVendorMethod); - methods = eap_peer_get_methods(&count); - if (methods == NULL) - return NULL; - if (sm->reqMethod == EAP_TYPE_EXPANDED) - return eap_sm_build_expanded_nak(sm, id, methods, count); - - /* RFC 3748 - 5.3.1: Legacy Nak */ - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NAK, - sizeof(struct eap_hdr) + 1 + count + 1, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - start = wpabuf_put(resp, 0); - for (m = methods; m; m = m->next) { - if (m->vendor == EAP_VENDOR_IETF && m->method == sm->reqMethod) - continue; /* do not allow the current method again */ - if (eap_allowed_method(sm, m->vendor, m->method)) { - if (m->vendor != EAP_VENDOR_IETF) { - if (expanded_found) - continue; - expanded_found = 1; - wpabuf_put_u8(resp, EAP_TYPE_EXPANDED); - } else - wpabuf_put_u8(resp, m->method); - found++; - } - } - if (!found) - wpabuf_put_u8(resp, EAP_TYPE_NONE); - wpa_hexdump(MSG_DEBUG, "EAP: allowed methods", start, found); - - eap_update_len(resp); - - return resp; -} - - -static void eap_sm_processIdentity(struct eap_sm *sm, const struct wpabuf *req) -{ - const struct eap_hdr *hdr = wpabuf_head(req); - const u8 *pos = (const u8 *) (hdr + 1); - pos++; - - wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED - "EAP authentication started"); - - /* - * RFC 3748 - 5.1: Identity - * Data field may contain a displayable message in UTF-8. If this - * includes NUL-character, only the data before that should be - * displayed. Some EAP implementasitons may piggy-back additional - * options after the NUL. - */ - /* TODO: could save displayable message so that it can be shown to the - * user in case of interaction is required */ - wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Identity data", - pos, be_to_host16(hdr->length) - 5); -} - - -#ifdef PCSC_FUNCS -static int eap_sm_imsi_identity(struct eap_sm *sm, - struct eap_peer_config *conf) -{ - int aka = 0; - char imsi[100]; - size_t imsi_len; - struct eap_method_type *m = conf->eap_methods; - int i; - - imsi_len = sizeof(imsi); - if (scard_get_imsi(sm->scard_ctx, imsi, &imsi_len)) { - wpa_printf(MSG_WARNING, "Failed to get IMSI from SIM"); - return -1; - } - - wpa_hexdump_ascii(MSG_DEBUG, "IMSI", (u8 *) imsi, imsi_len); - - for (i = 0; m && (m[i].vendor != EAP_VENDOR_IETF || - m[i].method != EAP_TYPE_NONE); i++) { - if (m[i].vendor == EAP_VENDOR_IETF && - m[i].method == EAP_TYPE_AKA) { - aka = 1; - break; - } - } - - os_free(conf->identity); - conf->identity = os_malloc(1 + imsi_len); - if (conf->identity == NULL) { - wpa_printf(MSG_WARNING, "Failed to allocate buffer for " - "IMSI-based identity"); - return -1; - } - - conf->identity[0] = aka ? '0' : '1'; - os_memcpy(conf->identity + 1, imsi, imsi_len); - conf->identity_len = 1 + imsi_len; - - return 0; -} -#endif /* PCSC_FUNCS */ - - -static int eap_sm_set_scard_pin(struct eap_sm *sm, - struct eap_peer_config *conf) -{ -#ifdef PCSC_FUNCS - if (scard_set_pin(sm->scard_ctx, conf->pin)) { - /* - * Make sure the same PIN is not tried again in order to avoid - * blocking SIM. - */ - os_free(conf->pin); - conf->pin = NULL; - - wpa_printf(MSG_WARNING, "PIN validation failed"); - eap_sm_request_pin(sm); - return -1; - } - return 0; -#else /* PCSC_FUNCS */ - return -1; -#endif /* PCSC_FUNCS */ -} - -static int eap_sm_get_scard_identity(struct eap_sm *sm, - struct eap_peer_config *conf) -{ -#ifdef PCSC_FUNCS - if (eap_sm_set_scard_pin(sm, conf)) - return -1; - - return eap_sm_imsi_identity(sm, conf); -#else /* PCSC_FUNCS */ - return -1; -#endif /* PCSC_FUNCS */ -} - - -/** - * eap_sm_buildIdentity - Build EAP-Identity/Response for the current network - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @id: EAP identifier for the packet - * @encrypted: Whether the packet is for encrypted tunnel (EAP phase 2) - * Returns: Pointer to the allocated EAP-Identity/Response packet or %NULL on - * failure - * - * This function allocates and builds an EAP-Identity/Response packet for the - * current network. The caller is responsible for freeing the returned data. - */ -struct wpabuf * eap_sm_buildIdentity(struct eap_sm *sm, int id, int encrypted) -{ - struct eap_peer_config *config = eap_get_config(sm); - struct wpabuf *resp; - const u8 *identity; - size_t identity_len; - - if (config == NULL) { - wpa_printf(MSG_WARNING, "EAP: buildIdentity: configuration " - "was not available"); - return NULL; - } - - if (sm->m && sm->m->get_identity && - (identity = sm->m->get_identity(sm, sm->eap_method_priv, - &identity_len)) != NULL) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP: using method re-auth " - "identity", identity, identity_len); - } else if (!encrypted && config->anonymous_identity) { - identity = config->anonymous_identity; - identity_len = config->anonymous_identity_len; - wpa_hexdump_ascii(MSG_DEBUG, "EAP: using anonymous identity", - identity, identity_len); - } else { - identity = config->identity; - identity_len = config->identity_len; - wpa_hexdump_ascii(MSG_DEBUG, "EAP: using real identity", - identity, identity_len); - } - - if (identity == NULL) { - wpa_printf(MSG_WARNING, "EAP: buildIdentity: identity " - "configuration was not available"); - if (config->pcsc) { - if (eap_sm_get_scard_identity(sm, config) < 0) - return NULL; - identity = config->identity; - identity_len = config->identity_len; - wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from " - "IMSI", identity, identity_len); - } else { - eap_sm_request_identity(sm); - return NULL; - } - } else if (config->pcsc) { - if (eap_sm_set_scard_pin(sm, config) < 0) - return NULL; - } - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, identity_len, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - wpabuf_put_data(resp, identity, identity_len); - - return resp; -} - - -static void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req) -{ - const u8 *pos; - char *msg; - size_t i, msg_len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, req, - &msg_len); - if (pos == NULL) - return; - wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Notification data", - pos, msg_len); - - msg = os_malloc(msg_len + 1); - if (msg == NULL) - return; - for (i = 0; i < msg_len; i++) - msg[i] = isprint(pos[i]) ? (char) pos[i] : '_'; - msg[msg_len] = '\0'; - wpa_msg(sm->msg_ctx, MSG_INFO, "%s%s", - WPA_EVENT_EAP_NOTIFICATION, msg); - os_free(msg); -} - - -static struct wpabuf * eap_sm_buildNotify(int id) -{ - struct wpabuf *resp; - - wpa_printf(MSG_DEBUG, "EAP: Generating EAP-Response Notification"); - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, 0, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - return resp; -} - - -static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req) -{ - const struct eap_hdr *hdr; - size_t plen; - const u8 *pos; - - sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = FALSE; - sm->reqId = 0; - sm->reqMethod = EAP_TYPE_NONE; - sm->reqVendor = EAP_VENDOR_IETF; - sm->reqVendorMethod = EAP_TYPE_NONE; - - if (req == NULL || wpabuf_len(req) < sizeof(*hdr)) - return; - - hdr = wpabuf_head(req); - plen = be_to_host16(hdr->length); - if (plen > wpabuf_len(req)) { - wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet " - "(len=%lu plen=%lu)", - (unsigned long) wpabuf_len(req), - (unsigned long) plen); - return; - } - - sm->reqId = hdr->identifier; - - if (sm->workaround) { - const u8 *addr[1]; - addr[0] = wpabuf_head(req); - md5_vector(1, addr, &plen, sm->req_md5); - } - - switch (hdr->code) { - case EAP_CODE_REQUEST: - if (plen < sizeof(*hdr) + 1) { - wpa_printf(MSG_DEBUG, "EAP: Too short EAP-Request - " - "no Type field"); - return; - } - sm->rxReq = TRUE; - pos = (const u8 *) (hdr + 1); - sm->reqMethod = *pos++; - if (sm->reqMethod == EAP_TYPE_EXPANDED) { - if (plen < sizeof(*hdr) + 8) { - wpa_printf(MSG_DEBUG, "EAP: Ignored truncated " - "expanded EAP-Packet (plen=%lu)", - (unsigned long) plen); - return; - } - sm->reqVendor = WPA_GET_BE24(pos); - pos += 3; - sm->reqVendorMethod = WPA_GET_BE32(pos); - } - wpa_printf(MSG_DEBUG, "EAP: Received EAP-Request id=%d " - "method=%u vendor=%u vendorMethod=%u", - sm->reqId, sm->reqMethod, sm->reqVendor, - sm->reqVendorMethod); - break; - case EAP_CODE_RESPONSE: - if (sm->selectedMethod == EAP_TYPE_LEAP) { - /* - * LEAP differs from RFC 4137 by using reversed roles - * for mutual authentication and because of this, we - * need to accept EAP-Response frames if LEAP is used. - */ - if (plen < sizeof(*hdr) + 1) { - wpa_printf(MSG_DEBUG, "EAP: Too short " - "EAP-Response - no Type field"); - return; - } - sm->rxResp = TRUE; - pos = (const u8 *) (hdr + 1); - sm->reqMethod = *pos; - wpa_printf(MSG_DEBUG, "EAP: Received EAP-Response for " - "LEAP method=%d id=%d", - sm->reqMethod, sm->reqId); - break; - } - wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Response"); - break; - case EAP_CODE_SUCCESS: - wpa_printf(MSG_DEBUG, "EAP: Received EAP-Success"); - sm->rxSuccess = TRUE; - break; - case EAP_CODE_FAILURE: - wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure"); - sm->rxFailure = TRUE; - break; - default: - wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Packet with unknown " - "code %d", hdr->code); - break; - } -} - - -/** - * eap_peer_sm_init - Allocate and initialize EAP peer state machine - * @eapol_ctx: Context data to be used with eapol_cb calls - * @eapol_cb: Pointer to EAPOL callback functions - * @msg_ctx: Context data for wpa_msg() calls - * @conf: EAP configuration - * Returns: Pointer to the allocated EAP state machine or %NULL on failure - * - * This function allocates and initializes an EAP state machine. In addition, - * this initializes TLS library for the new EAP state machine. eapol_cb pointer - * will be in use until eap_peer_sm_deinit() is used to deinitialize this EAP - * state machine. Consequently, the caller must make sure that this data - * structure remains alive while the EAP state machine is active. - */ -struct eap_sm * eap_peer_sm_init(void *eapol_ctx, - struct eapol_callbacks *eapol_cb, - void *msg_ctx, struct eap_config *conf) -{ - struct eap_sm *sm; - struct tls_config tlsconf; - - sm = os_zalloc(sizeof(*sm)); - if (sm == NULL) - return NULL; - sm->eapol_ctx = eapol_ctx; - sm->eapol_cb = eapol_cb; - sm->msg_ctx = msg_ctx; - sm->ClientTimeout = 60; - sm->wps = conf->wps; - - os_memset(&tlsconf, 0, sizeof(tlsconf)); - tlsconf.opensc_engine_path = conf->opensc_engine_path; - tlsconf.pkcs11_engine_path = conf->pkcs11_engine_path; - tlsconf.pkcs11_module_path = conf->pkcs11_module_path; - sm->ssl_ctx = tls_init(&tlsconf); - if (sm->ssl_ctx == NULL) { - wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS " - "context."); - os_free(sm); - return NULL; - } - - return sm; -} - - -/** - * eap_peer_sm_deinit - Deinitialize and free an EAP peer state machine - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * This function deinitializes EAP state machine and frees all allocated - * resources. - */ -void eap_peer_sm_deinit(struct eap_sm *sm) -{ - if (sm == NULL) - return; - eap_deinit_prev_method(sm, "EAP deinit"); - eap_sm_abort(sm); - tls_deinit(sm->ssl_ctx); - os_free(sm); -} - - -/** - * eap_peer_sm_step - Step EAP peer state machine - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * Returns: 1 if EAP state was changed or 0 if not - * - * This function advances EAP state machine to a new state to match with the - * current variables. This should be called whenever variables used by the EAP - * state machine have changed. - */ -int eap_peer_sm_step(struct eap_sm *sm) -{ - int res = 0; - do { - sm->changed = FALSE; - SM_STEP_RUN(EAP); - if (sm->changed) - res = 1; - } while (sm->changed); - return res; -} - - -/** - * eap_sm_abort - Abort EAP authentication - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * Release system resources that have been allocated for the authentication - * session without fully deinitializing the EAP state machine. - */ -void eap_sm_abort(struct eap_sm *sm) -{ - wpabuf_free(sm->lastRespData); - sm->lastRespData = NULL; - wpabuf_free(sm->eapRespData); - sm->eapRespData = NULL; - os_free(sm->eapKeyData); - sm->eapKeyData = NULL; - - /* This is not clearly specified in the EAP statemachines draft, but - * it seems necessary to make sure that some of the EAPOL variables get - * cleared for the next authentication. */ - eapol_set_bool(sm, EAPOL_eapSuccess, FALSE); -} - - -#ifdef CONFIG_CTRL_IFACE -static const char * eap_sm_state_txt(int state) -{ - switch (state) { - case EAP_INITIALIZE: - return "INITIALIZE"; - case EAP_DISABLED: - return "DISABLED"; - case EAP_IDLE: - return "IDLE"; - case EAP_RECEIVED: - return "RECEIVED"; - case EAP_GET_METHOD: - return "GET_METHOD"; - case EAP_METHOD: - return "METHOD"; - case EAP_SEND_RESPONSE: - return "SEND_RESPONSE"; - case EAP_DISCARD: - return "DISCARD"; - case EAP_IDENTITY: - return "IDENTITY"; - case EAP_NOTIFICATION: - return "NOTIFICATION"; - case EAP_RETRANSMIT: - return "RETRANSMIT"; - case EAP_SUCCESS: - return "SUCCESS"; - case EAP_FAILURE: - return "FAILURE"; - default: - return "UNKNOWN"; - } -} -#endif /* CONFIG_CTRL_IFACE */ - - -#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) -static const char * eap_sm_method_state_txt(EapMethodState state) -{ - switch (state) { - case METHOD_NONE: - return "NONE"; - case METHOD_INIT: - return "INIT"; - case METHOD_CONT: - return "CONT"; - case METHOD_MAY_CONT: - return "MAY_CONT"; - case METHOD_DONE: - return "DONE"; - default: - return "UNKNOWN"; - } -} - - -static const char * eap_sm_decision_txt(EapDecision decision) -{ - switch (decision) { - case DECISION_FAIL: - return "FAIL"; - case DECISION_COND_SUCC: - return "COND_SUCC"; - case DECISION_UNCOND_SUCC: - return "UNCOND_SUCC"; - default: - return "UNKNOWN"; - } -} -#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ - - -#ifdef CONFIG_CTRL_IFACE - -/** - * eap_sm_get_status - Get EAP state machine status - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @buf: Buffer for status information - * @buflen: Maximum buffer length - * @verbose: Whether to include verbose status information - * Returns: Number of bytes written to buf. - * - * Query EAP state machine for status information. This function fills in a - * text area with current status information from the EAPOL state machine. If - * the buffer (buf) is not large enough, status information will be truncated - * to fit the buffer. - */ -int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose) -{ - int len, ret; - - if (sm == NULL) - return 0; - - len = os_snprintf(buf, buflen, - "EAP state=%s\n", - eap_sm_state_txt(sm->EAP_state)); - if (len < 0 || (size_t) len >= buflen) - return 0; - - if (sm->selectedMethod != EAP_TYPE_NONE) { - const char *name; - if (sm->m) { - name = sm->m->name; - } else { - const struct eap_method *m = - eap_peer_get_eap_method(EAP_VENDOR_IETF, - sm->selectedMethod); - if (m) - name = m->name; - else - name = "?"; - } - ret = os_snprintf(buf + len, buflen - len, - "selectedMethod=%d (EAP-%s)\n", - sm->selectedMethod, name); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - if (sm->m && sm->m->get_status) { - len += sm->m->get_status(sm, sm->eap_method_priv, - buf + len, buflen - len, - verbose); - } - } - - if (verbose) { - ret = os_snprintf(buf + len, buflen - len, - "reqMethod=%d\n" - "methodState=%s\n" - "decision=%s\n" - "ClientTimeout=%d\n", - sm->reqMethod, - eap_sm_method_state_txt(sm->methodState), - eap_sm_decision_txt(sm->decision), - sm->ClientTimeout); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - } - - return len; -} -#endif /* CONFIG_CTRL_IFACE */ - - -#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) -typedef enum { - TYPE_IDENTITY, TYPE_PASSWORD, TYPE_OTP, TYPE_PIN, TYPE_NEW_PASSWORD, - TYPE_PASSPHRASE -} eap_ctrl_req_type; - -static void eap_sm_request(struct eap_sm *sm, eap_ctrl_req_type type, - const char *msg, size_t msglen) -{ - struct eap_peer_config *config; - char *field, *txt, *tmp; - - if (sm == NULL) - return; - config = eap_get_config(sm); - if (config == NULL) - return; - - switch (type) { - case TYPE_IDENTITY: - field = "IDENTITY"; - txt = "Identity"; - config->pending_req_identity++; - break; - case TYPE_PASSWORD: - field = "PASSWORD"; - txt = "Password"; - config->pending_req_password++; - break; - case TYPE_NEW_PASSWORD: - field = "NEW_PASSWORD"; - txt = "New Password"; - config->pending_req_new_password++; - break; - case TYPE_PIN: - field = "PIN"; - txt = "PIN"; - config->pending_req_pin++; - break; - case TYPE_OTP: - field = "OTP"; - if (msg) { - tmp = os_malloc(msglen + 3); - if (tmp == NULL) - return; - tmp[0] = '['; - os_memcpy(tmp + 1, msg, msglen); - tmp[msglen + 1] = ']'; - tmp[msglen + 2] = '\0'; - txt = tmp; - os_free(config->pending_req_otp); - config->pending_req_otp = tmp; - config->pending_req_otp_len = msglen + 3; - } else { - if (config->pending_req_otp == NULL) - return; - txt = config->pending_req_otp; - } - break; - case TYPE_PASSPHRASE: - field = "PASSPHRASE"; - txt = "Private key passphrase"; - config->pending_req_passphrase++; - break; - default: - return; - } - - if (sm->eapol_cb->eap_param_needed) - sm->eapol_cb->eap_param_needed(sm->eapol_ctx, field, txt); -} -#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ -#define eap_sm_request(sm, type, msg, msglen) do { } while (0) -#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ - - -/** - * eap_sm_request_identity - Request identity from user (ctrl_iface) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * EAP methods can call this function to request identity information for the - * current network. This is normally called when the identity is not included - * in the network configuration. The request will be sent to monitor programs - * through the control interface. - */ -void eap_sm_request_identity(struct eap_sm *sm) -{ - eap_sm_request(sm, TYPE_IDENTITY, NULL, 0); -} - - -/** - * eap_sm_request_password - Request password from user (ctrl_iface) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * EAP methods can call this function to request password information for the - * current network. This is normally called when the password is not included - * in the network configuration. The request will be sent to monitor programs - * through the control interface. - */ -void eap_sm_request_password(struct eap_sm *sm) -{ - eap_sm_request(sm, TYPE_PASSWORD, NULL, 0); -} - - -/** - * eap_sm_request_new_password - Request new password from user (ctrl_iface) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * EAP methods can call this function to request new password information for - * the current network. This is normally called when the EAP method indicates - * that the current password has expired and password change is required. The - * request will be sent to monitor programs through the control interface. - */ -void eap_sm_request_new_password(struct eap_sm *sm) -{ - eap_sm_request(sm, TYPE_NEW_PASSWORD, NULL, 0); -} - - -/** - * eap_sm_request_pin - Request SIM or smart card PIN from user (ctrl_iface) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * EAP methods can call this function to request SIM or smart card PIN - * information for the current network. This is normally called when the PIN is - * not included in the network configuration. The request will be sent to - * monitor programs through the control interface. - */ -void eap_sm_request_pin(struct eap_sm *sm) -{ - eap_sm_request(sm, TYPE_PIN, NULL, 0); -} - - -/** - * eap_sm_request_otp - Request one time password from user (ctrl_iface) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @msg: Message to be displayed to the user when asking for OTP - * @msg_len: Length of the user displayable message - * - * EAP methods can call this function to request open time password (OTP) for - * the current network. The request will be sent to monitor programs through - * the control interface. - */ -void eap_sm_request_otp(struct eap_sm *sm, const char *msg, size_t msg_len) -{ - eap_sm_request(sm, TYPE_OTP, msg, msg_len); -} - - -/** - * eap_sm_request_passphrase - Request passphrase from user (ctrl_iface) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * EAP methods can call this function to request passphrase for a private key - * for the current network. This is normally called when the passphrase is not - * included in the network configuration. The request will be sent to monitor - * programs through the control interface. - */ -void eap_sm_request_passphrase(struct eap_sm *sm) -{ - eap_sm_request(sm, TYPE_PASSPHRASE, NULL, 0); -} - - -/** - * eap_sm_notify_ctrl_attached - Notification of attached monitor - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * Notify EAP state machines that a monitor was attached to the control - * interface to trigger re-sending of pending requests for user input. - */ -void eap_sm_notify_ctrl_attached(struct eap_sm *sm) -{ - struct eap_peer_config *config = eap_get_config(sm); - - if (config == NULL) - return; - - /* Re-send any pending requests for user data since a new control - * interface was added. This handles cases where the EAP authentication - * starts immediately after system startup when the user interface is - * not yet running. */ - if (config->pending_req_identity) - eap_sm_request_identity(sm); - if (config->pending_req_password) - eap_sm_request_password(sm); - if (config->pending_req_new_password) - eap_sm_request_new_password(sm); - if (config->pending_req_otp) - eap_sm_request_otp(sm, NULL, 0); - if (config->pending_req_pin) - eap_sm_request_pin(sm); - if (config->pending_req_passphrase) - eap_sm_request_passphrase(sm); -} - - -static int eap_allowed_phase2_type(int vendor, int type) -{ - if (vendor != EAP_VENDOR_IETF) - return 0; - return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS && - type != EAP_TYPE_FAST; -} - - -/** - * eap_get_phase2_type - Get EAP type for the given EAP phase 2 method name - * @name: EAP method name, e.g., MD5 - * @vendor: Buffer for returning EAP Vendor-Id - * Returns: EAP method type or %EAP_TYPE_NONE if not found - * - * This function maps EAP type names into EAP type numbers that are allowed for - * Phase 2, i.e., for tunneled authentication. Phase 2 is used, e.g., with - * EAP-PEAP, EAP-TTLS, and EAP-FAST. - */ -u32 eap_get_phase2_type(const char *name, int *vendor) -{ - int v; - u8 type = eap_peer_get_type(name, &v); - if (eap_allowed_phase2_type(v, type)) { - *vendor = v; - return type; - } - *vendor = EAP_VENDOR_IETF; - return EAP_TYPE_NONE; -} - - -/** - * eap_get_phase2_types - Get list of allowed EAP phase 2 types - * @config: Pointer to a network configuration - * @count: Pointer to a variable to be filled with number of returned EAP types - * Returns: Pointer to allocated type list or %NULL on failure - * - * This function generates an array of allowed EAP phase 2 (tunneled) types for - * the given network configuration. - */ -struct eap_method_type * eap_get_phase2_types(struct eap_peer_config *config, - size_t *count) -{ - struct eap_method_type *buf; - u32 method; - int vendor; - size_t mcount; - const struct eap_method *methods, *m; - - methods = eap_peer_get_methods(&mcount); - if (methods == NULL) - return NULL; - *count = 0; - buf = os_malloc(mcount * sizeof(struct eap_method_type)); - if (buf == NULL) - return NULL; - - for (m = methods; m; m = m->next) { - vendor = m->vendor; - method = m->method; - if (eap_allowed_phase2_type(vendor, method)) { - if (vendor == EAP_VENDOR_IETF && - method == EAP_TYPE_TLS && config && - config->private_key2 == NULL) - continue; - buf[*count].vendor = vendor; - buf[*count].method = method; - (*count)++; - } - } - - return buf; -} - - -/** - * eap_set_fast_reauth - Update fast_reauth setting - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @enabled: 1 = Fast reauthentication is enabled, 0 = Disabled - */ -void eap_set_fast_reauth(struct eap_sm *sm, int enabled) -{ - sm->fast_reauth = enabled; -} - - -/** - * eap_set_workaround - Update EAP workarounds setting - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @workaround: 1 = Enable EAP workarounds, 0 = Disable EAP workarounds - */ -void eap_set_workaround(struct eap_sm *sm, unsigned int workaround) -{ - sm->workaround = workaround; -} - - -/** - * eap_get_config - Get current network configuration - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * Returns: Pointer to the current network configuration or %NULL if not found - * - * EAP peer methods should avoid using this function if they can use other - * access functions, like eap_get_config_identity() and - * eap_get_config_password(), that do not require direct access to - * struct eap_peer_config. - */ -struct eap_peer_config * eap_get_config(struct eap_sm *sm) -{ - return sm->eapol_cb->get_config(sm->eapol_ctx); -} - - -/** - * eap_get_config_identity - Get identity from the network configuration - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @len: Buffer for the length of the identity - * Returns: Pointer to the identity or %NULL if not found - */ -const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len) -{ - struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL) - return NULL; - *len = config->identity_len; - return config->identity; -} - - -/** - * eap_get_config_password - Get password from the network configuration - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @len: Buffer for the length of the password - * Returns: Pointer to the password or %NULL if not found - */ -const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len) -{ - struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL) - return NULL; - *len = config->password_len; - return config->password; -} - - -/** - * eap_get_config_password2 - Get password from the network configuration - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @len: Buffer for the length of the password - * @hash: Buffer for returning whether the password is stored as a - * NtPasswordHash instead of plaintext password; can be %NULL if this - * information is not needed - * Returns: Pointer to the password or %NULL if not found - */ -const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash) -{ - struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL) - return NULL; - *len = config->password_len; - if (hash) - *hash = !!(config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH); - return config->password; -} - - -/** - * eap_get_config_new_password - Get new password from network configuration - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @len: Buffer for the length of the new password - * Returns: Pointer to the new password or %NULL if not found - */ -const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len) -{ - struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL) - return NULL; - *len = config->new_password_len; - return config->new_password; -} - - -/** - * eap_get_config_otp - Get one-time password from the network configuration - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @len: Buffer for the length of the one-time password - * Returns: Pointer to the one-time password or %NULL if not found - */ -const u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len) -{ - struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL) - return NULL; - *len = config->otp_len; - return config->otp; -} - - -/** - * eap_clear_config_otp - Clear used one-time password - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * This function clears a used one-time password (OTP) from the current network - * configuration. This should be called when the OTP has been used and is not - * needed anymore. - */ -void eap_clear_config_otp(struct eap_sm *sm) -{ - struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL) - return; - os_memset(config->otp, 0, config->otp_len); - os_free(config->otp); - config->otp = NULL; - config->otp_len = 0; -} - - -/** - * eap_get_config_phase1 - Get phase1 data from the network configuration - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * Returns: Pointer to the phase1 data or %NULL if not found - */ -const char * eap_get_config_phase1(struct eap_sm *sm) -{ - struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL) - return NULL; - return config->phase1; -} - - -/** - * eap_get_config_phase2 - Get phase2 data from the network configuration - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * Returns: Pointer to the phase1 data or %NULL if not found - */ -const char * eap_get_config_phase2(struct eap_sm *sm) -{ - struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL) - return NULL; - return config->phase2; -} - - -/** - * eap_key_available - Get key availability (eapKeyAvailable variable) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * Returns: 1 if EAP keying material is available, 0 if not - */ -int eap_key_available(struct eap_sm *sm) -{ - return sm ? sm->eapKeyAvailable : 0; -} - - -/** - * eap_notify_success - Notify EAP state machine about external success trigger - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * This function is called when external event, e.g., successful completion of - * WPA-PSK key handshake, is indicating that EAP state machine should move to - * success state. This is mainly used with security modes that do not use EAP - * state machine (e.g., WPA-PSK). - */ -void eap_notify_success(struct eap_sm *sm) -{ - if (sm) { - sm->decision = DECISION_COND_SUCC; - sm->EAP_state = EAP_SUCCESS; - } -} - - -/** - * eap_notify_lower_layer_success - Notification of lower layer success - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * Notify EAP state machines that a lower layer has detected a successful - * authentication. This is used to recover from dropped EAP-Success messages. - */ -void eap_notify_lower_layer_success(struct eap_sm *sm) -{ - if (sm == NULL) - return; - - if (eapol_get_bool(sm, EAPOL_eapSuccess) || - sm->decision == DECISION_FAIL || - (sm->methodState != METHOD_MAY_CONT && - sm->methodState != METHOD_DONE)) - return; - - if (sm->eapKeyData != NULL) - sm->eapKeyAvailable = TRUE; - eapol_set_bool(sm, EAPOL_eapSuccess, TRUE); - wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS - "EAP authentication completed successfully (based on lower " - "layer success)"); -} - - -/** - * eap_get_eapKeyData - Get master session key (MSK) from EAP state machine - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @len: Pointer to variable that will be set to number of bytes in the key - * Returns: Pointer to the EAP keying data or %NULL on failure - * - * Fetch EAP keying material (MSK, eapKeyData) from the EAP state machine. The - * key is available only after a successful authentication. EAP state machine - * continues to manage the key data and the caller must not change or free the - * returned data. - */ -const u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len) -{ - if (sm == NULL || sm->eapKeyData == NULL) { - *len = 0; - return NULL; - } - - *len = sm->eapKeyDataLen; - return sm->eapKeyData; -} - - -/** - * eap_get_eapKeyData - Get EAP response data - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * Returns: Pointer to the EAP response (eapRespData) or %NULL on failure - * - * Fetch EAP response (eapRespData) from the EAP state machine. This data is - * available when EAP state machine has processed an incoming EAP request. The - * EAP state machine does not maintain a reference to the response after this - * function is called and the caller is responsible for freeing the data. - */ -struct wpabuf * eap_get_eapRespData(struct eap_sm *sm) -{ - struct wpabuf *resp; - - if (sm == NULL || sm->eapRespData == NULL) - return NULL; - - resp = sm->eapRespData; - sm->eapRespData = NULL; - - return resp; -} - - -/** - * eap_sm_register_scard_ctx - Notification of smart card context - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @ctx: Context data for smart card operations - * - * Notify EAP state machines of context data for smart card operations. This - * context data will be used as a parameter for scard_*() functions. - */ -void eap_register_scard_ctx(struct eap_sm *sm, void *ctx) -{ - if (sm) - sm->scard_ctx = ctx; -} - - -/** - * eap_set_config_blob - Set or add a named configuration blob - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @blob: New value for the blob - * - * Adds a new configuration blob or replaces the current value of an existing - * blob. - */ -void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob) -{ -#ifndef CONFIG_NO_CONFIG_BLOBS - sm->eapol_cb->set_config_blob(sm->eapol_ctx, blob); -#endif /* CONFIG_NO_CONFIG_BLOBS */ -} - - -/** - * eap_get_config_blob - Get a named configuration blob - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @name: Name of the blob - * Returns: Pointer to blob data or %NULL if not found - */ -const struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm, - const char *name) -{ -#ifndef CONFIG_NO_CONFIG_BLOBS - return sm->eapol_cb->get_config_blob(sm->eapol_ctx, name); -#else /* CONFIG_NO_CONFIG_BLOBS */ - return NULL; -#endif /* CONFIG_NO_CONFIG_BLOBS */ -} - - -/** - * eap_set_force_disabled - Set force_disabled flag - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @disabled: 1 = EAP disabled, 0 = EAP enabled - * - * This function is used to force EAP state machine to be disabled when it is - * not in use (e.g., with WPA-PSK or plaintext connections). - */ -void eap_set_force_disabled(struct eap_sm *sm, int disabled) -{ - sm->force_disabled = disabled; -} - - - /** - * eap_notify_pending - Notify that EAP method is ready to re-process a request - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * An EAP method can perform a pending operation (e.g., to get a response from - * an external process). Once the response is available, this function can be - * used to request EAPOL state machine to retry delivering the previously - * received (and still unanswered) EAP request to EAP state machine. - */ -void eap_notify_pending(struct eap_sm *sm) -{ - sm->eapol_cb->notify_pending(sm->eapol_ctx); -} - - -/** - * eap_invalidate_cached_session - Mark cached session data invalid - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - */ -void eap_invalidate_cached_session(struct eap_sm *sm) -{ - if (sm) - eap_deinit_prev_method(sm, "invalidate"); -} - - -int eap_is_wps_pbc_enrollee(struct eap_peer_config *conf) -{ - if (conf->identity_len != WSC_ID_ENROLLEE_LEN || - os_memcmp(conf->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN)) - return 0; /* Not a WPS Enrollee */ - - if (conf->phase1 == NULL || os_strstr(conf->phase1, "pbc=1") == NULL) - return 0; /* Not using PBC */ - - return 1; -} - - -int eap_is_wps_pin_enrollee(struct eap_peer_config *conf) -{ - if (conf->identity_len != WSC_ID_ENROLLEE_LEN || - os_memcmp(conf->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN)) - return 0; /* Not a WPS Enrollee */ - - if (conf->phase1 == NULL || os_strstr(conf->phase1, "pin=") == NULL) - return 0; /* Not using PIN */ - - return 1; -} diff --git a/contrib/hostapd/src/eap_peer/eap.h b/contrib/hostapd/src/eap_peer/eap.h deleted file mode 100644 index d7a562812b..0000000000 --- a/contrib/hostapd/src/eap_peer/eap.h +++ /dev/null @@ -1,291 +0,0 @@ -/* - * EAP peer state machine functions (RFC 4137) - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_H -#define EAP_H - -#include "defs.h" -#include "eap_common/eap_defs.h" -#include "eap_peer/eap_methods.h" - -struct eap_sm; -struct wpa_config_blob; -struct wpabuf; - -struct eap_method_type { - int vendor; - u32 method; -}; - -#ifdef IEEE8021X_EAPOL - -/** - * enum eapol_bool_var - EAPOL boolean state variables for EAP state machine - * - * These variables are used in the interface between EAP peer state machine and - * lower layer. These are defined in RFC 4137, Sect. 4.1. Lower layer code is - * expected to maintain these variables and register a callback functions for - * EAP state machine to get and set the variables. - */ -enum eapol_bool_var { - /** - * EAPOL_eapSuccess - EAP SUCCESS state reached - * - * EAP state machine reads and writes this value. - */ - EAPOL_eapSuccess, - - /** - * EAPOL_eapRestart - Lower layer request to restart authentication - * - * Set to TRUE in lower layer, FALSE in EAP state machine. - */ - EAPOL_eapRestart, - - /** - * EAPOL_eapFail - EAP FAILURE state reached - * - * EAP state machine writes this value. - */ - EAPOL_eapFail, - - /** - * EAPOL_eapResp - Response to send - * - * Set to TRUE in EAP state machine, FALSE in lower layer. - */ - EAPOL_eapResp, - - /** - * EAPOL_eapNoResp - Request has been process; no response to send - * - * Set to TRUE in EAP state machine, FALSE in lower layer. - */ - EAPOL_eapNoResp, - - /** - * EAPOL_eapReq - EAP request available from lower layer - * - * Set to TRUE in lower layer, FALSE in EAP state machine. - */ - EAPOL_eapReq, - - /** - * EAPOL_portEnabled - Lower layer is ready for communication - * - * EAP state machines reads this value. - */ - EAPOL_portEnabled, - - /** - * EAPOL_altAccept - Alternate indication of success (RFC3748) - * - * EAP state machines reads this value. - */ - EAPOL_altAccept, - - /** - * EAPOL_altReject - Alternate indication of failure (RFC3748) - * - * EAP state machines reads this value. - */ - EAPOL_altReject -}; - -/** - * enum eapol_int_var - EAPOL integer state variables for EAP state machine - * - * These variables are used in the interface between EAP peer state machine and - * lower layer. These are defined in RFC 4137, Sect. 4.1. Lower layer code is - * expected to maintain these variables and register a callback functions for - * EAP state machine to get and set the variables. - */ -enum eapol_int_var { - /** - * EAPOL_idleWhile - Outside time for EAP peer timeout - * - * This integer variable is used to provide an outside timer that the - * external (to EAP state machine) code must decrement by one every - * second until the value reaches zero. This is used in the same way as - * EAPOL state machine timers. EAP state machine reads and writes this - * value. - */ - EAPOL_idleWhile -}; - -/** - * struct eapol_callbacks - Callback functions from EAP to lower layer - * - * This structure defines the callback functions that EAP state machine - * requires from the lower layer (usually EAPOL state machine) for updating - * state variables and requesting information. eapol_ctx from - * eap_peer_sm_init() call will be used as the ctx parameter for these - * callback functions. - */ -struct eapol_callbacks { - /** - * get_config - Get pointer to the current network configuration - * @ctx: eapol_ctx from eap_peer_sm_init() call - */ - struct eap_peer_config * (*get_config)(void *ctx); - - /** - * get_bool - Get a boolean EAPOL state variable - * @variable: EAPOL boolean variable to get - * Returns: Value of the EAPOL variable - */ - Boolean (*get_bool)(void *ctx, enum eapol_bool_var variable); - - /** - * set_bool - Set a boolean EAPOL state variable - * @ctx: eapol_ctx from eap_peer_sm_init() call - * @variable: EAPOL boolean variable to set - * @value: Value for the EAPOL variable - */ - void (*set_bool)(void *ctx, enum eapol_bool_var variable, - Boolean value); - - /** - * get_int - Get an integer EAPOL state variable - * @ctx: eapol_ctx from eap_peer_sm_init() call - * @variable: EAPOL integer variable to get - * Returns: Value of the EAPOL variable - */ - unsigned int (*get_int)(void *ctx, enum eapol_int_var variable); - - /** - * set_int - Set an integer EAPOL state variable - * @ctx: eapol_ctx from eap_peer_sm_init() call - * @variable: EAPOL integer variable to set - * @value: Value for the EAPOL variable - */ - void (*set_int)(void *ctx, enum eapol_int_var variable, - unsigned int value); - - /** - * get_eapReqData - Get EAP-Request data - * @ctx: eapol_ctx from eap_peer_sm_init() call - * @len: Pointer to variable that will be set to eapReqDataLen - * Returns: Reference to eapReqData (EAP state machine will not free - * this) or %NULL if eapReqData not available. - */ - struct wpabuf * (*get_eapReqData)(void *ctx); - - /** - * set_config_blob - Set named configuration blob - * @ctx: eapol_ctx from eap_peer_sm_init() call - * @blob: New value for the blob - * - * Adds a new configuration blob or replaces the current value of an - * existing blob. - */ - void (*set_config_blob)(void *ctx, struct wpa_config_blob *blob); - - /** - * get_config_blob - Get a named configuration blob - * @ctx: eapol_ctx from eap_peer_sm_init() call - * @name: Name of the blob - * Returns: Pointer to blob data or %NULL if not found - */ - const struct wpa_config_blob * (*get_config_blob)(void *ctx, - const char *name); - - /** - * notify_pending - Notify that a pending request can be retried - * @ctx: eapol_ctx from eap_peer_sm_init() call - * - * An EAP method can perform a pending operation (e.g., to get a - * response from an external process). Once the response is available, - * this callback function can be used to request EAPOL state machine to - * retry delivering the previously received (and still unanswered) EAP - * request to EAP state machine. - */ - void (*notify_pending)(void *ctx); - - /** - * eap_param_needed - Notify that EAP parameter is needed - * @ctx: eapol_ctx from eap_peer_sm_init() call - * @field: Field name (e.g., "IDENTITY") - * @txt: User readable text describing the required parameter - */ - void (*eap_param_needed)(void *ctx, const char *field, - const char *txt); -}; - -/** - * struct eap_config - Configuration for EAP state machine - */ -struct eap_config { - /** - * opensc_engine_path - OpenSC engine for OpenSSL engine support - * - * Usually, path to engine_opensc.so. - */ - const char *opensc_engine_path; - /** - * pkcs11_engine_path - PKCS#11 engine for OpenSSL engine support - * - * Usually, path to engine_pkcs11.so. - */ - const char *pkcs11_engine_path; - /** - * pkcs11_module_path - OpenSC PKCS#11 module for OpenSSL engine - * - * Usually, path to opensc-pkcs11.so. - */ - const char *pkcs11_module_path; - /** - * wps - WPS context data - * - * This is only used by EAP-WSC and can be left %NULL if not available. - */ - struct wps_context *wps; -}; - -struct eap_sm * eap_peer_sm_init(void *eapol_ctx, - struct eapol_callbacks *eapol_cb, - void *msg_ctx, struct eap_config *conf); -void eap_peer_sm_deinit(struct eap_sm *sm); -int eap_peer_sm_step(struct eap_sm *sm); -void eap_sm_abort(struct eap_sm *sm); -int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, - int verbose); -struct wpabuf * eap_sm_buildIdentity(struct eap_sm *sm, int id, int encrypted); -void eap_sm_request_identity(struct eap_sm *sm); -void eap_sm_request_password(struct eap_sm *sm); -void eap_sm_request_new_password(struct eap_sm *sm); -void eap_sm_request_pin(struct eap_sm *sm); -void eap_sm_request_otp(struct eap_sm *sm, const char *msg, size_t msg_len); -void eap_sm_request_passphrase(struct eap_sm *sm); -void eap_sm_notify_ctrl_attached(struct eap_sm *sm); -u32 eap_get_phase2_type(const char *name, int *vendor); -struct eap_method_type * eap_get_phase2_types(struct eap_peer_config *config, - size_t *count); -void eap_set_fast_reauth(struct eap_sm *sm, int enabled); -void eap_set_workaround(struct eap_sm *sm, unsigned int workaround); -void eap_set_force_disabled(struct eap_sm *sm, int disabled); -int eap_key_available(struct eap_sm *sm); -void eap_notify_success(struct eap_sm *sm); -void eap_notify_lower_layer_success(struct eap_sm *sm); -const u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len); -struct wpabuf * eap_get_eapRespData(struct eap_sm *sm); -void eap_register_scard_ctx(struct eap_sm *sm, void *ctx); -void eap_invalidate_cached_session(struct eap_sm *sm); - -int eap_is_wps_pbc_enrollee(struct eap_peer_config *conf); -int eap_is_wps_pin_enrollee(struct eap_peer_config *conf); - -#endif /* IEEE8021X_EAPOL */ - -#endif /* EAP_H */ diff --git a/contrib/hostapd/src/eap_peer/eap_aka.c b/contrib/hostapd/src/eap_peer/eap_aka.c deleted file mode 100644 index f237141425..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_aka.c +++ /dev/null @@ -1,1391 +0,0 @@ -/* - * EAP peer method: EAP-AKA (RFC 4187) and EAP-AKA' (draft-arkko-eap-aka-kdf) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_peer/eap_i.h" -#include "pcsc_funcs.h" -#include "eap_common/eap_sim_common.h" -#include "sha1.h" -#include "sha256.h" -#include "crypto.h" -#include "eap_peer/eap_config.h" -#ifdef CONFIG_USIM_SIMULATOR -#include "hlr_auc_gw/milenage.h" -#endif /* CONFIG_USIM_SIMULATOR */ - - -struct eap_aka_data { - u8 ik[EAP_AKA_IK_LEN], ck[EAP_AKA_CK_LEN], res[EAP_AKA_RES_MAX_LEN]; - size_t res_len; - u8 nonce_s[EAP_SIM_NONCE_S_LEN]; - u8 mk[EAP_SIM_MK_LEN]; - u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN]; - u8 k_encr[EAP_SIM_K_ENCR_LEN]; - u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */ - u8 msk[EAP_SIM_KEYING_DATA_LEN]; - u8 emsk[EAP_EMSK_LEN]; - u8 rand[EAP_AKA_RAND_LEN], autn[EAP_AKA_AUTN_LEN]; - u8 auts[EAP_AKA_AUTS_LEN]; - - int num_id_req, num_notification; - u8 *pseudonym; - size_t pseudonym_len; - u8 *reauth_id; - size_t reauth_id_len; - int reauth; - unsigned int counter, counter_too_small; - u8 *last_eap_identity; - size_t last_eap_identity_len; - enum { - CONTINUE, RESULT_SUCCESS, RESULT_FAILURE, SUCCESS, FAILURE - } state; - - struct wpabuf *id_msgs; - int prev_id; - int result_ind, use_result_ind; - u8 eap_method; - u8 *network_name; - size_t network_name_len; - u16 kdf; - int kdf_negotiation; -}; - - -#ifndef CONFIG_NO_STDOUT_DEBUG -static const char * eap_aka_state_txt(int state) -{ - switch (state) { - case CONTINUE: - return "CONTINUE"; - case RESULT_SUCCESS: - return "RESULT_SUCCESS"; - case RESULT_FAILURE: - return "RESULT_FAILURE"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "?"; - } -} -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - -static void eap_aka_state(struct eap_aka_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s", - eap_aka_state_txt(data->state), - eap_aka_state_txt(state)); - data->state = state; -} - - -static void * eap_aka_init(struct eap_sm *sm) -{ - struct eap_aka_data *data; - const char *phase1 = eap_get_config_phase1(sm); - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - data->eap_method = EAP_TYPE_AKA; - - eap_aka_state(data, CONTINUE); - data->prev_id = -1; - - data->result_ind = phase1 && os_strstr(phase1, "result_ind=1") != NULL; - - return data; -} - - -#ifdef EAP_AKA_PRIME -static void * eap_aka_prime_init(struct eap_sm *sm) -{ - struct eap_aka_data *data = eap_aka_init(sm); - if (data == NULL) - return NULL; - data->eap_method = EAP_TYPE_AKA_PRIME; - return data; -} -#endif /* EAP_AKA_PRIME */ - - -static void eap_aka_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - if (data) { - os_free(data->pseudonym); - os_free(data->reauth_id); - os_free(data->last_eap_identity); - wpabuf_free(data->id_msgs); - os_free(data->network_name); - os_free(data); - } -} - - -static int eap_aka_umts_auth(struct eap_sm *sm, struct eap_aka_data *data) -{ - struct eap_peer_config *conf; - - wpa_printf(MSG_DEBUG, "EAP-AKA: UMTS authentication algorithm"); - - conf = eap_get_config(sm); - if (conf == NULL) - return -1; - if (conf->pcsc) { - return scard_umts_auth(sm->scard_ctx, data->rand, - data->autn, data->res, &data->res_len, - data->ik, data->ck, data->auts); - } - -#ifdef CONFIG_USIM_SIMULATOR - if (conf->password) { - u8 opc[16], k[16], sqn[6]; - const char *pos; - wpa_printf(MSG_DEBUG, "EAP-AKA: Use internal Milenage " - "implementation for UMTS authentication"); - if (conf->password_len < 78) { - wpa_printf(MSG_DEBUG, "EAP-AKA: invalid Milenage " - "password"); - return -1; - } - pos = (const char *) conf->password; - if (hexstr2bin(pos, k, 16)) - return -1; - pos += 32; - if (*pos != ':') - return -1; - pos++; - - if (hexstr2bin(pos, opc, 16)) - return -1; - pos += 32; - if (*pos != ':') - return -1; - pos++; - - if (hexstr2bin(pos, sqn, 6)) - return -1; - - return milenage_check(opc, k, sqn, data->rand, data->autn, - data->ik, data->ck, - data->res, &data->res_len, data->auts); - } -#endif /* CONFIG_USIM_SIMULATOR */ - -#ifdef CONFIG_USIM_HARDCODED - wpa_printf(MSG_DEBUG, "EAP-AKA: Use hardcoded Kc and SRES values for " - "testing"); - - /* These hardcoded Kc and SRES values are used for testing. - * Could consider making them configurable. */ - os_memset(data->res, '2', EAP_AKA_RES_MAX_LEN); - data->res_len = EAP_AKA_RES_MAX_LEN; - os_memset(data->ik, '3', EAP_AKA_IK_LEN); - os_memset(data->ck, '4', EAP_AKA_CK_LEN); - { - u8 autn[EAP_AKA_AUTN_LEN]; - os_memset(autn, '1', EAP_AKA_AUTN_LEN); - if (os_memcmp(autn, data->autn, EAP_AKA_AUTN_LEN) != 0) { - wpa_printf(MSG_WARNING, "EAP-AKA: AUTN did not match " - "with expected value"); - return -1; - } - } -#if 0 - { - static int test_resync = 1; - if (test_resync) { - /* Test Resynchronization */ - test_resync = 0; - return -2; - } - } -#endif - return 0; - -#else /* CONFIG_USIM_HARDCODED */ - - wpa_printf(MSG_DEBUG, "EAP-AKA: No UMTS authentication algorith " - "enabled"); - return -1; - -#endif /* CONFIG_USIM_HARDCODED */ -} - - -#define CLEAR_PSEUDONYM 0x01 -#define CLEAR_REAUTH_ID 0x02 -#define CLEAR_EAP_ID 0x04 - -static void eap_aka_clear_identities(struct eap_aka_data *data, int id) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old%s%s%s", - id & CLEAR_PSEUDONYM ? " pseudonym" : "", - id & CLEAR_REAUTH_ID ? " reauth_id" : "", - id & CLEAR_EAP_ID ? " eap_id" : ""); - if (id & CLEAR_PSEUDONYM) { - os_free(data->pseudonym); - data->pseudonym = NULL; - data->pseudonym_len = 0; - } - if (id & CLEAR_REAUTH_ID) { - os_free(data->reauth_id); - data->reauth_id = NULL; - data->reauth_id_len = 0; - } - if (id & CLEAR_EAP_ID) { - os_free(data->last_eap_identity); - data->last_eap_identity = NULL; - data->last_eap_identity_len = 0; - } -} - - -static int eap_aka_learn_ids(struct eap_aka_data *data, - struct eap_sim_attrs *attr) -{ - if (attr->next_pseudonym) { - os_free(data->pseudonym); - data->pseudonym = os_malloc(attr->next_pseudonym_len); - if (data->pseudonym == NULL) { - wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for " - "next pseudonym"); - return -1; - } - os_memcpy(data->pseudonym, attr->next_pseudonym, - attr->next_pseudonym_len); - data->pseudonym_len = attr->next_pseudonym_len; - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-AKA: (encr) AT_NEXT_PSEUDONYM", - data->pseudonym, - data->pseudonym_len); - } - - if (attr->next_reauth_id) { - os_free(data->reauth_id); - data->reauth_id = os_malloc(attr->next_reauth_id_len); - if (data->reauth_id == NULL) { - wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for " - "next reauth_id"); - return -1; - } - os_memcpy(data->reauth_id, attr->next_reauth_id, - attr->next_reauth_id_len); - data->reauth_id_len = attr->next_reauth_id_len; - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-AKA: (encr) AT_NEXT_REAUTH_ID", - data->reauth_id, - data->reauth_id_len); - } - - return 0; -} - - -static int eap_aka_add_id_msg(struct eap_aka_data *data, - const struct wpabuf *msg) -{ - if (msg == NULL) - return -1; - - if (data->id_msgs == NULL) { - data->id_msgs = wpabuf_dup(msg); - return data->id_msgs == NULL ? -1 : 0; - } - - if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0) - return -1; - wpabuf_put_buf(data->id_msgs, msg); - - return 0; -} - - -static void eap_aka_add_checkcode(struct eap_aka_data *data, - struct eap_sim_msg *msg) -{ - const u8 *addr; - size_t len; - u8 hash[SHA256_MAC_LEN]; - - wpa_printf(MSG_DEBUG, " AT_CHECKCODE"); - - if (data->id_msgs == NULL) { - /* - * No EAP-AKA/Identity packets were exchanged - send empty - * checkcode. - */ - eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0); - return; - } - - /* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */ - addr = wpabuf_head(data->id_msgs); - len = wpabuf_len(data->id_msgs); - wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len); -#ifdef EAP_AKA_PRIME - if (data->eap_method == EAP_TYPE_AKA_PRIME) - sha256_vector(1, &addr, &len, hash); - else -#endif /* EAP_AKA_PRIME */ - sha1_vector(1, &addr, &len, hash); - - eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash, - data->eap_method == EAP_TYPE_AKA_PRIME ? - EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN); -} - - -static int eap_aka_verify_checkcode(struct eap_aka_data *data, - const u8 *checkcode, size_t checkcode_len) -{ - const u8 *addr; - size_t len; - u8 hash[SHA256_MAC_LEN]; - size_t hash_len; - - if (checkcode == NULL) - return -1; - - if (data->id_msgs == NULL) { - if (checkcode_len != 0) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from server " - "indicates that AKA/Identity messages were " - "used, but they were not"); - return -1; - } - return 0; - } - - hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ? - EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN; - - if (checkcode_len != hash_len) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from server " - "indicates that AKA/Identity message were not " - "used, but they were"); - return -1; - } - - /* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */ - addr = wpabuf_head(data->id_msgs); - len = wpabuf_len(data->id_msgs); -#ifdef EAP_AKA_PRIME - if (data->eap_method == EAP_TYPE_AKA_PRIME) - sha256_vector(1, &addr, &len, hash); - else -#endif /* EAP_AKA_PRIME */ - sha1_vector(1, &addr, &len, hash); - - if (os_memcmp(hash, checkcode, hash_len) != 0) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE"); - return -1; - } - - return 0; -} - - -static struct wpabuf * eap_aka_client_error(struct eap_aka_data *data, u8 id, - int err) -{ - struct eap_sim_msg *msg; - - eap_aka_state(data, FAILURE); - data->num_id_req = 0; - data->num_notification = 0; - - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, - EAP_AKA_SUBTYPE_CLIENT_ERROR); - eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0); - return eap_sim_msg_finish(msg, NULL, NULL, 0); -} - - -static struct wpabuf * eap_aka_authentication_reject(struct eap_aka_data *data, - u8 id) -{ - struct eap_sim_msg *msg; - - eap_aka_state(data, FAILURE); - data->num_id_req = 0; - data->num_notification = 0; - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Authentication-Reject " - "(id=%d)", id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, - EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT); - return eap_sim_msg_finish(msg, NULL, NULL, 0); -} - - -static struct wpabuf * eap_aka_synchronization_failure( - struct eap_aka_data *data, u8 id) -{ - struct eap_sim_msg *msg; - - data->num_id_req = 0; - data->num_notification = 0; - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Synchronization-Failure " - "(id=%d)", id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, - EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE); - wpa_printf(MSG_DEBUG, " AT_AUTS"); - eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts, - EAP_AKA_AUTS_LEN); - return eap_sim_msg_finish(msg, NULL, NULL, 0); -} - - -static struct wpabuf * eap_aka_response_identity(struct eap_sm *sm, - struct eap_aka_data *data, - u8 id, - enum eap_sim_id_req id_req) -{ - const u8 *identity = NULL; - size_t identity_len = 0; - struct eap_sim_msg *msg; - - data->reauth = 0; - if (id_req == ANY_ID && data->reauth_id) { - identity = data->reauth_id; - identity_len = data->reauth_id_len; - data->reauth = 1; - } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) && - data->pseudonym) { - identity = data->pseudonym; - identity_len = data->pseudonym_len; - eap_aka_clear_identities(data, CLEAR_REAUTH_ID); - } else if (id_req != NO_ID_REQ) { - identity = eap_get_config_identity(sm, &identity_len); - if (identity) { - eap_aka_clear_identities(data, CLEAR_PSEUDONYM | - CLEAR_REAUTH_ID); - } - } - if (id_req != NO_ID_REQ) - eap_aka_clear_identities(data, CLEAR_EAP_ID); - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Identity (id=%d)", id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, - EAP_AKA_SUBTYPE_IDENTITY); - - if (identity) { - wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY", - identity, identity_len); - eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len, - identity, identity_len); - } - - return eap_sim_msg_finish(msg, NULL, NULL, 0); -} - - -static struct wpabuf * eap_aka_response_challenge(struct eap_aka_data *data, - u8 id) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d)", id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, - EAP_AKA_SUBTYPE_CHALLENGE); - wpa_printf(MSG_DEBUG, " AT_RES"); - eap_sim_msg_add(msg, EAP_SIM_AT_RES, data->res_len * 8, - data->res, data->res_len); - eap_aka_add_checkcode(data, msg); - if (data->use_result_ind) { - wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); - } - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, data->k_aut, (u8 *) "", 0); -} - - -static struct wpabuf * eap_aka_response_reauth(struct eap_aka_data *data, - u8 id, int counter_too_small, - const u8 *nonce_s) -{ - struct eap_sim_msg *msg; - unsigned int counter; - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Reauthentication (id=%d)", - id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, - EAP_AKA_SUBTYPE_REAUTHENTICATION); - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); - - if (counter_too_small) { - wpa_printf(MSG_DEBUG, " *AT_COUNTER_TOO_SMALL"); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0); - counter = data->counter_too_small; - } else - counter = data->counter; - - wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); - - if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt " - "AT_ENCR_DATA"); - eap_sim_msg_free(msg); - return NULL; - } - eap_aka_add_checkcode(data, msg); - if (data->use_result_ind) { - wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); - } - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, data->k_aut, nonce_s, - EAP_SIM_NONCE_S_LEN); -} - - -static struct wpabuf * eap_aka_response_notification(struct eap_aka_data *data, - u8 id, u16 notification) -{ - struct eap_sim_msg *msg; - u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL; - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Notification (id=%d)", id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, - EAP_AKA_SUBTYPE_NOTIFICATION); - if (k_aut && data->reauth) { - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, - EAP_SIM_AT_ENCR_DATA); - wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", data->counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, - NULL, 0); - if (eap_sim_msg_add_encr_end(msg, data->k_encr, - EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt " - "AT_ENCR_DATA"); - eap_sim_msg_free(msg); - return NULL; - } - } - if (k_aut) { - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - } - return eap_sim_msg_finish(msg, k_aut, (u8 *) "", 0); -} - - -static struct wpabuf * eap_aka_process_identity(struct eap_sm *sm, - struct eap_aka_data *data, - u8 id, - const struct wpabuf *reqData, - struct eap_sim_attrs *attr) -{ - int id_error; - struct wpabuf *buf; - - wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Identity"); - - id_error = 0; - switch (attr->id_req) { - case NO_ID_REQ: - break; - case ANY_ID: - if (data->num_id_req > 0) - id_error++; - data->num_id_req++; - break; - case FULLAUTH_ID: - if (data->num_id_req > 1) - id_error++; - data->num_id_req++; - break; - case PERMANENT_ID: - if (data->num_id_req > 2) - id_error++; - data->num_id_req++; - break; - } - if (id_error) { - wpa_printf(MSG_INFO, "EAP-AKA: Too many ID requests " - "used within one authentication"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - buf = eap_aka_response_identity(sm, data, id, attr->id_req); - - if (data->prev_id != id) { - eap_aka_add_id_msg(data, reqData); - eap_aka_add_id_msg(data, buf); - data->prev_id = id; - } - - return buf; -} - - -static int eap_aka_verify_mac(struct eap_aka_data *data, - const struct wpabuf *req, - const u8 *mac, const u8 *extra, - size_t extra_len) -{ - if (data->eap_method == EAP_TYPE_AKA_PRIME) - return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra, - extra_len); - return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len); -} - - -#ifdef EAP_AKA_PRIME -static struct wpabuf * eap_aka_prime_kdf_select(struct eap_aka_data *data, - u8 id, u16 kdf) -{ - struct eap_sim_msg *msg; - - data->kdf_negotiation = 1; - data->kdf = kdf; - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d) (KDF " - "select)", id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, - EAP_AKA_SUBTYPE_CHALLENGE); - wpa_printf(MSG_DEBUG, " AT_KDF"); - eap_sim_msg_add(msg, EAP_SIM_AT_KDF, kdf, NULL, 0); - return eap_sim_msg_finish(msg, NULL, NULL, 0); -} - - -static struct wpabuf * eap_aka_prime_kdf_neg(struct eap_aka_data *data, - u8 id, struct eap_sim_attrs *attr) -{ - size_t i; - - for (i = 0; i < attr->kdf_count; i++) { - if (attr->kdf[i] == EAP_AKA_PRIME_KDF) - return eap_aka_prime_kdf_select(data, id, - EAP_AKA_PRIME_KDF); - } - - /* No matching KDF found - fail authentication as if AUTN had been - * incorrect */ - return eap_aka_authentication_reject(data, id); -} - - -static int eap_aka_prime_kdf_valid(struct eap_aka_data *data, - struct eap_sim_attrs *attr) -{ - size_t i, j; - - if (attr->kdf_count == 0) - return 0; - - /* The only allowed (and required) duplication of a KDF is the addition - * of the selected KDF into the beginning of the list. */ - - if (data->kdf_negotiation) { - if (attr->kdf[0] != data->kdf) { - wpa_printf(MSG_WARNING, "EAP-AKA': The server did not " - "accept the selected KDF"); - return 0; - } - - for (i = 1; i < attr->kdf_count; i++) { - if (attr->kdf[i] == data->kdf) - break; - } - if (i == attr->kdf_count && - attr->kdf_count < EAP_AKA_PRIME_KDF_MAX) { - wpa_printf(MSG_WARNING, "EAP-AKA': The server did not " - "duplicate the selected KDF"); - return 0; - } - - /* TODO: should check that the list is identical to the one - * used in the previous Challenge message apart from the added - * entry in the beginning. */ - } - - for (i = data->kdf ? 1 : 0; i < attr->kdf_count; i++) { - for (j = i + 1; j < attr->kdf_count; j++) { - if (attr->kdf[i] == attr->kdf[j]) { - wpa_printf(MSG_WARNING, "EAP-AKA': The server " - "included a duplicated KDF"); - return 0; - } - } - } - - return 1; -} -#endif /* EAP_AKA_PRIME */ - - -static struct wpabuf * eap_aka_process_challenge(struct eap_sm *sm, - struct eap_aka_data *data, - u8 id, - const struct wpabuf *reqData, - struct eap_sim_attrs *attr) -{ - const u8 *identity; - size_t identity_len; - int res; - struct eap_sim_attrs eattr; - - wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Challenge"); - - if (attr->checkcode && - eap_aka_verify_checkcode(data, attr->checkcode, - attr->checkcode_len)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the " - "message"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - -#ifdef EAP_AKA_PRIME - if (data->eap_method == EAP_TYPE_AKA_PRIME) { - if (!attr->kdf_input || attr->kdf_input_len == 0) { - wpa_printf(MSG_WARNING, "EAP-AKA': Challenge message " - "did not include non-empty AT_KDF_INPUT"); - /* Fail authentication as if AUTN had been incorrect */ - return eap_aka_authentication_reject(data, id); - } - os_free(data->network_name); - data->network_name = os_malloc(attr->kdf_input_len); - if (data->network_name == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA': No memory for " - "storing Network Name"); - return eap_aka_authentication_reject(data, id); - } - os_memcpy(data->network_name, attr->kdf_input, - attr->kdf_input_len); - data->network_name_len = attr->kdf_input_len; - wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA': Network Name " - "(AT_KDF_INPUT)", - data->network_name, data->network_name_len); - /* TODO: check Network Name per 3GPP.33.402 */ - - if (!eap_aka_prime_kdf_valid(data, attr)) - return eap_aka_authentication_reject(data, id); - - if (attr->kdf[0] != EAP_AKA_PRIME_KDF) - return eap_aka_prime_kdf_neg(data, id, attr); - - data->kdf = EAP_AKA_PRIME_KDF; - wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf); - } - - if (data->eap_method == EAP_TYPE_AKA && attr->bidding) { - u16 flags = WPA_GET_BE16(attr->bidding); - if ((flags & EAP_AKA_BIDDING_FLAG_D) && - eap_allowed_method(sm, EAP_VENDOR_IETF, - EAP_TYPE_AKA_PRIME)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Bidding down from " - "AKA' to AKA detected"); - /* Fail authentication as if AUTN had been incorrect */ - return eap_aka_authentication_reject(data, id); - } - } -#endif /* EAP_AKA_PRIME */ - - data->reauth = 0; - if (!attr->mac || !attr->rand || !attr->autn) { - wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " - "did not include%s%s%s", - !attr->mac ? " AT_MAC" : "", - !attr->rand ? " AT_RAND" : "", - !attr->autn ? " AT_AUTN" : ""); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - os_memcpy(data->rand, attr->rand, EAP_AKA_RAND_LEN); - os_memcpy(data->autn, attr->autn, EAP_AKA_AUTN_LEN); - - res = eap_aka_umts_auth(sm, data); - if (res == -1) { - wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication " - "failed (AUTN)"); - return eap_aka_authentication_reject(data, id); - } else if (res == -2) { - wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication " - "failed (AUTN seq# -> AUTS)"); - return eap_aka_synchronization_failure(data, id); - } else if (res) { - wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication failed"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } -#ifdef EAP_AKA_PRIME - if (data->eap_method == EAP_TYPE_AKA_PRIME) { - /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the - * needed 6-octet SQN ^ AK for CK',IK' derivation */ - u16 amf = WPA_GET_BE16(data->autn + 6); - if (!(amf & 0x8000)) { - wpa_printf(MSG_WARNING, "EAP-AKA': AMF separation bit " - "not set (AMF=0x%4x)", amf); - return eap_aka_authentication_reject(data, id); - } - eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik, - data->autn, - data->network_name, - data->network_name_len); - } -#endif /* EAP_AKA_PRIME */ - if (data->last_eap_identity) { - identity = data->last_eap_identity; - identity_len = data->last_eap_identity_len; - } else if (data->pseudonym) { - identity = data->pseudonym; - identity_len = data->pseudonym_len; - } else - identity = eap_get_config_identity(sm, &identity_len); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Selected identity for MK " - "derivation", identity, identity_len); - if (data->eap_method == EAP_TYPE_AKA_PRIME) { - eap_aka_prime_derive_keys(identity, identity_len, data->ik, - data->ck, data->k_encr, data->k_aut, - data->k_re, data->msk, data->emsk); - } else { - eap_aka_derive_mk(identity, identity_len, data->ik, data->ck, - data->mk); - eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, - data->msk, data->emsk); - } - if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " - "used invalid AT_MAC"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - /* Old reauthentication and pseudonym identities must not be used - * anymore. In other words, if no new identities are received, full - * authentication will be used on next reauthentication. */ - eap_aka_clear_identities(data, CLEAR_PSEUDONYM | CLEAR_REAUTH_ID | - CLEAR_EAP_ID); - - if (attr->encr_data) { - u8 *decrypted; - decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, - &eattr, 0); - if (decrypted == NULL) { - return eap_aka_client_error( - data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - eap_aka_learn_ids(data, &eattr); - os_free(decrypted); - } - - if (data->result_ind && attr->result_ind) - data->use_result_ind = 1; - - if (data->state != FAILURE && data->state != RESULT_FAILURE) { - eap_aka_state(data, data->use_result_ind ? - RESULT_SUCCESS : SUCCESS); - } - - data->num_id_req = 0; - data->num_notification = 0; - /* RFC 4187 specifies that counter is initialized to one after - * fullauth, but initializing it to zero makes it easier to implement - * reauth verification. */ - data->counter = 0; - return eap_aka_response_challenge(data, id); -} - - -static int eap_aka_process_notification_reauth(struct eap_aka_data *data, - struct eap_sim_attrs *attr) -{ - struct eap_sim_attrs eattr; - u8 *decrypted; - - if (attr->encr_data == NULL || attr->iv == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: Notification message after " - "reauth did not include encrypted data"); - return -1; - } - - decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, &eattr, - 0); - if (decrypted == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted " - "data from notification message"); - return -1; - } - - if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) { - wpa_printf(MSG_WARNING, "EAP-AKA: Counter in notification " - "message does not match with counter in reauth " - "message"); - os_free(decrypted); - return -1; - } - - os_free(decrypted); - return 0; -} - - -static int eap_aka_process_notification_auth(struct eap_aka_data *data, - const struct wpabuf *reqData, - struct eap_sim_attrs *attr) -{ - if (attr->mac == NULL) { - wpa_printf(MSG_INFO, "EAP-AKA: no AT_MAC in after_auth " - "Notification message"); - return -1; - } - - if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Notification message " - "used invalid AT_MAC"); - return -1; - } - - if (data->reauth && - eap_aka_process_notification_reauth(data, attr)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Invalid notification " - "message after reauth"); - return -1; - } - - return 0; -} - - -static struct wpabuf * eap_aka_process_notification( - struct eap_sm *sm, struct eap_aka_data *data, u8 id, - const struct wpabuf *reqData, struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Notification"); - if (data->num_notification > 0) { - wpa_printf(MSG_INFO, "EAP-AKA: too many notification " - "rounds (only one allowed)"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - data->num_notification++; - if (attr->notification == -1) { - wpa_printf(MSG_INFO, "EAP-AKA: no AT_NOTIFICATION in " - "Notification message"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - if ((attr->notification & 0x4000) == 0 && - eap_aka_process_notification_auth(data, reqData, attr)) { - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - eap_sim_report_notification(sm->msg_ctx, attr->notification, 1); - if (attr->notification >= 0 && attr->notification < 32768) { - eap_aka_state(data, FAILURE); - } else if (attr->notification == EAP_SIM_SUCCESS && - data->state == RESULT_SUCCESS) - eap_aka_state(data, SUCCESS); - return eap_aka_response_notification(data, id, attr->notification); -} - - -static struct wpabuf * eap_aka_process_reauthentication( - struct eap_sm *sm, struct eap_aka_data *data, u8 id, - const struct wpabuf *reqData, struct eap_sim_attrs *attr) -{ - struct eap_sim_attrs eattr; - u8 *decrypted; - - wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Reauthentication"); - - if (attr->checkcode && - eap_aka_verify_checkcode(data, attr->checkcode, - attr->checkcode_len)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the " - "message"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - if (data->reauth_id == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: Server is trying " - "reauthentication, but no reauth_id available"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - data->reauth = 1; - if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " - "did not have valid AT_MAC"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - if (attr->encr_data == NULL || attr->iv == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " - "message did not include encrypted data"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, &eattr, - 0); - if (decrypted == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted " - "data from reauthentication message"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - if (eattr.nonce_s == NULL || eattr.counter < 0) { - wpa_printf(MSG_INFO, "EAP-AKA: (encr) No%s%s in reauth packet", - !eattr.nonce_s ? " AT_NONCE_S" : "", - eattr.counter < 0 ? " AT_COUNTER" : ""); - os_free(decrypted); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) { - struct wpabuf *res; - wpa_printf(MSG_INFO, "EAP-AKA: (encr) Invalid counter " - "(%d <= %d)", eattr.counter, data->counter); - data->counter_too_small = eattr.counter; - - /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current - * reauth_id must not be used to start a new reauthentication. - * However, since it was used in the last EAP-Response-Identity - * packet, it has to saved for the following fullauth to be - * used in MK derivation. */ - os_free(data->last_eap_identity); - data->last_eap_identity = data->reauth_id; - data->last_eap_identity_len = data->reauth_id_len; - data->reauth_id = NULL; - data->reauth_id_len = 0; - - res = eap_aka_response_reauth(data, id, 1, eattr.nonce_s); - os_free(decrypted); - - return res; - } - data->counter = eattr.counter; - - os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-AKA: (encr) AT_NONCE_S", - data->nonce_s, EAP_SIM_NONCE_S_LEN); - - if (data->eap_method == EAP_TYPE_AKA_PRIME) { - eap_aka_prime_derive_keys_reauth(data->k_re, data->counter, - data->reauth_id, - data->reauth_id_len, - data->nonce_s, - data->msk, data->emsk); - } else { - eap_sim_derive_keys_reauth(data->counter, data->reauth_id, - data->reauth_id_len, - data->nonce_s, data->mk, - data->msk, data->emsk); - } - eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); - eap_aka_learn_ids(data, &eattr); - - if (data->result_ind && attr->result_ind) - data->use_result_ind = 1; - - if (data->state != FAILURE && data->state != RESULT_FAILURE) { - eap_aka_state(data, data->use_result_ind ? - RESULT_SUCCESS : SUCCESS); - } - - data->num_id_req = 0; - data->num_notification = 0; - if (data->counter > EAP_AKA_MAX_FAST_REAUTHS) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Maximum number of " - "fast reauths performed - force fullauth"); - eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); - } - os_free(decrypted); - return eap_aka_response_reauth(data, id, 0, data->nonce_s); -} - - -static struct wpabuf * eap_aka_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_aka_data *data = priv; - const struct eap_hdr *req; - u8 subtype, id; - struct wpabuf *res; - const u8 *pos; - struct eap_sim_attrs attr; - size_t len; - - wpa_hexdump_buf(MSG_DEBUG, "EAP-AKA: EAP data", reqData); - if (eap_get_config_identity(sm, &len) == NULL) { - wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured"); - eap_sm_request_identity(sm); - ret->ignore = TRUE; - return NULL; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, reqData, - &len); - if (pos == NULL || len < 1) { - ret->ignore = TRUE; - return NULL; - } - req = wpabuf_head(reqData); - id = req->identifier; - len = be_to_host16(req->length); - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - subtype = *pos++; - wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype); - pos += 2; /* Reserved */ - - if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr, - data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1, - 0)) { - res = eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - goto done; - } - - switch (subtype) { - case EAP_AKA_SUBTYPE_IDENTITY: - res = eap_aka_process_identity(sm, data, id, reqData, &attr); - break; - case EAP_AKA_SUBTYPE_CHALLENGE: - res = eap_aka_process_challenge(sm, data, id, reqData, &attr); - break; - case EAP_AKA_SUBTYPE_NOTIFICATION: - res = eap_aka_process_notification(sm, data, id, reqData, - &attr); - break; - case EAP_AKA_SUBTYPE_REAUTHENTICATION: - res = eap_aka_process_reauthentication(sm, data, id, reqData, - &attr); - break; - case EAP_AKA_SUBTYPE_CLIENT_ERROR: - wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Client-Error"); - res = eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown subtype=%d", subtype); - res = eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - break; - } - -done: - if (data->state == FAILURE) { - ret->decision = DECISION_FAIL; - ret->methodState = METHOD_DONE; - } else if (data->state == SUCCESS) { - ret->decision = data->use_result_ind ? - DECISION_UNCOND_SUCC : DECISION_COND_SUCC; - /* - * It is possible for the server to reply with AKA - * Notification, so we must allow the method to continue and - * not only accept EAP-Success at this point. - */ - ret->methodState = data->use_result_ind ? - METHOD_DONE : METHOD_MAY_CONT; - } else if (data->state == RESULT_FAILURE) - ret->methodState = METHOD_CONT; - else if (data->state == RESULT_SUCCESS) - ret->methodState = METHOD_CONT; - - if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; - } - - return res; -} - - -static Boolean eap_aka_has_reauth_data(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - return data->pseudonym || data->reauth_id; -} - - -static void eap_aka_deinit_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - eap_aka_clear_identities(data, CLEAR_EAP_ID); - data->prev_id = -1; - wpabuf_free(data->id_msgs); - data->id_msgs = NULL; - data->use_result_ind = 0; - data->kdf_negotiation = 0; -} - - -static void * eap_aka_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - data->num_id_req = 0; - data->num_notification = 0; - eap_aka_state(data, CONTINUE); - return priv; -} - - -static const u8 * eap_aka_get_identity(struct eap_sm *sm, void *priv, - size_t *len) -{ - struct eap_aka_data *data = priv; - - if (data->reauth_id) { - *len = data->reauth_id_len; - return data->reauth_id; - } - - if (data->pseudonym) { - *len = data->pseudonym_len; - return data->pseudonym; - } - - return NULL; -} - - -static Boolean eap_aka_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - return data->state == SUCCESS; -} - - -static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_aka_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_SIM_KEYING_DATA_LEN); - if (key == NULL) - return NULL; - - *len = EAP_SIM_KEYING_DATA_LEN; - os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); - - return key; -} - - -static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_aka_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_EMSK_LEN; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - - return key; -} - - -int eap_peer_aka_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA"); - if (eap == NULL) - return -1; - - eap->init = eap_aka_init; - eap->deinit = eap_aka_deinit; - eap->process = eap_aka_process; - eap->isKeyAvailable = eap_aka_isKeyAvailable; - eap->getKey = eap_aka_getKey; - eap->has_reauth_data = eap_aka_has_reauth_data; - eap->deinit_for_reauth = eap_aka_deinit_for_reauth; - eap->init_for_reauth = eap_aka_init_for_reauth; - eap->get_identity = eap_aka_get_identity; - eap->get_emsk = eap_aka_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} - - -#ifdef EAP_AKA_PRIME -int eap_peer_aka_prime_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME, - "AKA'"); - if (eap == NULL) - return -1; - - eap->init = eap_aka_prime_init; - eap->deinit = eap_aka_deinit; - eap->process = eap_aka_process; - eap->isKeyAvailable = eap_aka_isKeyAvailable; - eap->getKey = eap_aka_getKey; - eap->has_reauth_data = eap_aka_has_reauth_data; - eap->deinit_for_reauth = eap_aka_deinit_for_reauth; - eap->init_for_reauth = eap_aka_init_for_reauth; - eap->get_identity = eap_aka_get_identity; - eap->get_emsk = eap_aka_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - - return ret; -} -#endif /* EAP_AKA_PRIME */ diff --git a/contrib/hostapd/src/eap_peer/eap_config.h b/contrib/hostapd/src/eap_peer/eap_config.h deleted file mode 100644 index 94245c3d03..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_config.h +++ /dev/null @@ -1,660 +0,0 @@ -/* - * EAP peer configuration data - * Copyright (c) 2003-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_CONFIG_H -#define EAP_CONFIG_H - -/** - * struct eap_peer_config - EAP peer configuration/credentials - */ -struct eap_peer_config { - /** - * identity - EAP Identity - * - * This field is used to set the real user identity or NAI (for - * EAP-PSK/PAX/SAKE/GPSK). - */ - u8 *identity; - - /** - * identity_len - EAP Identity length - */ - size_t identity_len; - - /** - * anonymous_identity - Anonymous EAP Identity - * - * This field is used for unencrypted use with EAP types that support - * different tunnelled identity, e.g., EAP-TTLS, in order to reveal the - * real identity (identity field) only to the authentication server. - * - * If not set, the identity field will be used for both unencrypted and - * protected fields. - */ - u8 *anonymous_identity; - - /** - * anonymous_identity_len - Length of anonymous_identity - */ - size_t anonymous_identity_len; - - /** - * password - Password string for EAP - * - * This field can include either the plaintext password (default - * option) or a NtPasswordHash (16-byte MD4 hash of the unicode - * presentation of the password) if flags field has - * EAP_CONFIG_FLAGS_PASSWORD_NTHASH bit set to 1. NtPasswordHash can - * only be used with authentication mechanism that use this hash as the - * starting point for operation: MSCHAP and MSCHAPv2 (EAP-MSCHAPv2, - * EAP-TTLS/MSCHAPv2, EAP-TTLS/MSCHAP, LEAP). - * - * In addition, this field is used to configure a pre-shared key for - * EAP-PSK/PAX/SAKE/GPSK. The length of the PSK must be 16 for EAP-PSK - * and EAP-PAX and 32 for EAP-SAKE. EAP-GPSK can use a variable length - * PSK. - */ - u8 *password; - - /** - * password_len - Length of password field - */ - size_t password_len; - - /** - * ca_cert - File path to CA certificate file (PEM/DER) - * - * This file can have one or more trusted CA certificates. If ca_cert - * and ca_path are not included, server certificate will not be - * verified. This is insecure and a trusted CA certificate should - * always be configured when using EAP-TLS/TTLS/PEAP. Full path to the - * file should be used since working directory may change when - * wpa_supplicant is run in the background. - * - * Alternatively, a named configuration blob can be used by setting - * this to blob://blob_name. - * - * On Windows, trusted CA certificates can be loaded from the system - * certificate store by setting this to cert_store://name, e.g., - * ca_cert="cert_store://CA" or ca_cert="cert_store://ROOT". - * Note that when running wpa_supplicant as an application, the user - * certificate store (My user account) is used, whereas computer store - * (Computer account) is used when running wpasvc as a service. - */ - u8 *ca_cert; - - /** - * ca_path - Directory path for CA certificate files (PEM) - * - * This path may contain multiple CA certificates in OpenSSL format. - * Common use for this is to point to system trusted CA list which is - * often installed into directory like /etc/ssl/certs. If configured, - * 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; - - /** - * client_cert - File path to client certificate file (PEM/DER) - * - * This field is used with EAP method that use TLS authentication. - * Usually, this is only configured for EAP-TLS, even though this could - * in theory be used with EAP-TTLS and EAP-PEAP, too. Full path to the - * file should be used since working directory may change when - * wpa_supplicant is run in the background. - * - * Alternatively, a named configuration blob can be used by setting - * this to blob://blob_name. - */ - u8 *client_cert; - - /** - * private_key - File path to client private key file (PEM/DER/PFX) - * - * When PKCS#12/PFX file (.p12/.pfx) is used, client_cert should be - * commented out. Both the private key and certificate will be read - * from the PKCS#12 file in this case. Full path to the file should be - * used since working directory may change when wpa_supplicant is run - * in the background. - * - * Windows certificate store can be used by leaving client_cert out and - * configuring private_key in one of the following formats: - * - * cert://substring_to_match - * - * hash://certificate_thumbprint_in_hex - * - * For example: private_key="hash://63093aa9c47f56ae88334c7b65a4" - * - * Note that when running wpa_supplicant as an application, the user - * certificate store (My user account) is used, whereas computer store - * (Computer account) is used when running wpasvc as a service. - * - * Alternatively, a named configuration blob can be used by setting - * this to blob://blob_name. - */ - u8 *private_key; - - /** - * private_key_passwd - Password for private key file - * - * If left out, this will be asked through control interface. - */ - u8 *private_key_passwd; - - /** - * dh_file - File path to DH/DSA parameters file (in PEM format) - * - * This is an optional configuration file for setting parameters for an - * ephemeral DH key exchange. In most cases, the default RSA - * authentication does not use this configuration. However, it is - * possible setup RSA to use ephemeral DH key exchange. In addition, - * ciphers with DSA keys always use ephemeral DH keys. This can be used - * to achieve forward secrecy. If the file is in DSA parameters format, - * it will be automatically converted into DH params. Full path to the - * file should be used since working directory may change when - * wpa_supplicant is run in the background. - * - * Alternatively, a named configuration blob can be used by setting - * this to blob://blob_name. - */ - u8 *dh_file; - - /** - * subject_match - Constraint for server certificate subject - * - * This substring is matched against the subject of the authentication - * server certificate. If this string is set, the server sertificate is - * only accepted if it contains this string in the subject. The subject - * string is in following format: - * - * /C=US/ST=CA/L=San Francisco/CN=Test AS/emailAddress=as@n.example.com - */ - u8 *subject_match; - - /** - * altsubject_match - Constraint for server certificate alt. subject - * - * Semicolon separated string of entries to be matched against the - * alternative subject name of the authentication server certificate. - * If this string is set, the server sertificate is only accepted if it - * contains one of the entries in an alternative subject name - * extension. - * - * altSubjectName string is in following format: TYPE:VALUE - * - * Example: EMAIL:server@example.com - * Example: DNS:server.example.com;DNS:server2.example.com - * - * Following types are supported: EMAIL, DNS, URI - */ - u8 *altsubject_match; - - /** - * ca_cert2 - File path to CA certificate file (PEM/DER) (Phase 2) - * - * This file can have one or more trusted CA certificates. If ca_cert2 - * and ca_path2 are not included, server certificate will not be - * verified. This is insecure and a trusted CA certificate should - * always be configured. Full path to the file should be used since - * working directory may change when wpa_supplicant is run in the - * background. - * - * This field is like ca_cert, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. - * - * Alternatively, a named configuration blob can be used by setting - * this to blob://blob_name. - */ - u8 *ca_cert2; - - /** - * ca_path2 - Directory path for CA certificate files (PEM) (Phase 2) - * - * This path may contain multiple CA certificates in OpenSSL format. - * Common use for this is to point to system trusted CA list which is - * often installed into directory like /etc/ssl/certs. If configured, - * these certificates are added to the list of trusted CAs. ca_cert - * may also be included in that case, but it is not required. - * - * This field is like ca_path, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. - */ - u8 *ca_path2; - - /** - * client_cert2 - File path to client certificate file - * - * This field is like client_cert, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. Full path to the - * file should be used since working directory may change when - * wpa_supplicant is run in the background. - * - * Alternatively, a named configuration blob can be used by setting - * this to blob://blob_name. - */ - u8 *client_cert2; - - /** - * private_key2 - File path to client private key file - * - * This field is like private_key, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. Full path to the - * file should be used since working directory may change when - * wpa_supplicant is run in the background. - * - * Alternatively, a named configuration blob can be used by setting - * this to blob://blob_name. - */ - u8 *private_key2; - - /** - * private_key2_passwd - Password for private key file - * - * This field is like private_key_passwd, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. - */ - u8 *private_key2_passwd; - - /** - * dh_file2 - File path to DH/DSA parameters file (in PEM format) - * - * This field is like dh_file, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. Full path to the - * file should be used since working directory may change when - * wpa_supplicant is run in the background. - * - * Alternatively, a named configuration blob can be used by setting - * this to blob://blob_name. - */ - u8 *dh_file2; - - /** - * subject_match2 - Constraint for server certificate subject - * - * This field is like subject_match, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. - */ - u8 *subject_match2; - - /** - * altsubject_match2 - Constraint for server certificate alt. subject - * - * This field is like altsubject_match, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. - */ - u8 *altsubject_match2; - - /** - * eap_methods - Allowed EAP methods - * - * (vendor=EAP_VENDOR_IETF,method=EAP_TYPE_NONE) terminated list of - * allowed EAP methods or %NULL if all methods are accepted. - */ - struct eap_method_type *eap_methods; - - /** - * phase1 - Phase 1 (outer authentication) parameters - * - * String with field-value pairs, e.g., "peapver=0" or - * "peapver=1 peaplabel=1". - * - * 'peapver' can be used to force which PEAP version (0 or 1) is used. - * - * 'peaplabel=1' can be used to force new label, "client PEAP - * encryption", to be used during key derivation when PEAPv1 or newer. - * - * Most existing PEAPv1 implementation seem to be using the old label, - * "client EAP encryption", and wpa_supplicant is now using that as the - * default value. - * - * Some servers, e.g., Radiator, may require peaplabel=1 configuration - * to interoperate with PEAPv1; see eap_testing.txt for more details. - * - * 'peap_outer_success=0' can be used to terminate PEAP authentication - * on tunneled EAP-Success. This is required with some RADIUS servers - * that implement draft-josefsson-pppext-eap-tls-eap-05.txt (e.g., - * Lucent NavisRadius v4.4.0 with PEAP in "IETF Draft 5" mode). - * - * include_tls_length=1 can be used to force wpa_supplicant to include - * TLS Message Length field in all TLS messages even if they are not - * fragmented. - * - * sim_min_num_chal=3 can be used to configure EAP-SIM to require three - * challenges (by default, it accepts 2 or 3). - * - * result_ind=1 can be used to enable EAP-SIM and EAP-AKA to use - * protected result indication. - * - * fast_provisioning option can be used to enable in-line provisioning - * of EAP-FAST credentials (PAC): - * 0 = disabled, - * 1 = allow unauthenticated provisioning, - * 2 = allow authenticated provisioning, - * 3 = allow both unauthenticated and authenticated provisioning - * - * fast_max_pac_list_len=num option can be used to set the maximum - * number of PAC entries to store in a PAC list (default: 10). - * - * fast_pac_format=binary option can be used to select binary format - * for storing PAC entries in order to save some space (the default - * text format uses about 2.5 times the size of minimal binary format). - * - * crypto_binding option can be used to control PEAPv0 cryptobinding - * behavior: - * 0 = do not use cryptobinding (default) - * 1 = use cryptobinding if server supports it - * 2 = require cryptobinding - * - * EAP-WSC (WPS) uses following options: pin=Device_Password and - * uuid=Device_UUID - */ - char *phase1; - - /** - * phase2 - Phase2 (inner authentication with TLS tunnel) parameters - * - * String with field-value pairs, e.g., "auth=MSCHAPV2" for EAP-PEAP or - * "autheap=MSCHAPV2 autheap=MD5" for EAP-TTLS. - */ - char *phase2; - - /** - * pcsc - Parameters for PC/SC smartcard interface for USIM and GSM SIM - * - * This field is used to configure PC/SC smartcard interface. - * Currently, the only configuration is whether this field is %NULL (do - * not use PC/SC) or non-NULL (e.g., "") to enable PC/SC. - * - * This field is used for EAP-SIM and EAP-AKA. - */ - char *pcsc; - - /** - * pin - PIN for USIM, GSM SIM, and smartcards - * - * This field is used to configure PIN for SIM and smartcards for - * EAP-SIM and EAP-AKA. In addition, this is used with EAP-TLS if a - * smartcard is used for private key operations. - * - * If left out, this will be asked through control interface. - */ - char *pin; - - /** - * engine - Enable OpenSSL engine (e.g., for smartcard access) - * - * This is used if private key operations for EAP-TLS are performed - * using a smartcard. - */ - int engine; - - /** - * engine_id - Engine ID for OpenSSL engine - * - * "opensc" to select OpenSC engine or "pkcs11" to select PKCS#11 - * engine. - * - * This is used if private key operations for EAP-TLS are performed - * using a smartcard. - */ - char *engine_id; - - /** - * engine2 - Enable OpenSSL engine (e.g., for smartcard) (Phase 2) - * - * This is used if private key operations for EAP-TLS are performed - * using a smartcard. - * - * This field is like engine, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. - */ - int engine2; - - - /** - * pin2 - PIN for USIM, GSM SIM, and smartcards (Phase 2) - * - * This field is used to configure PIN for SIM and smartcards for - * EAP-SIM and EAP-AKA. In addition, this is used with EAP-TLS if a - * smartcard is used for private key operations. - * - * This field is like pin2, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. - * - * If left out, this will be asked through control interface. - */ - char *pin2; - - /** - * engine2_id - Engine ID for OpenSSL engine (Phase 2) - * - * "opensc" to select OpenSC engine or "pkcs11" to select PKCS#11 - * engine. - * - * This is used if private key operations for EAP-TLS are performed - * using a smartcard. - * - * This field is like engine_id, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. - */ - char *engine2_id; - - - /** - * key_id - Key ID for OpenSSL engine - * - * This is used if private key operations for EAP-TLS are performed - * using a smartcard. - */ - char *key_id; - - /** - * cert_id - Cert ID for OpenSSL engine - * - * This is used if the certificate operations for EAP-TLS are performed - * using a smartcard. - */ - char *cert_id; - - /** - * ca_cert_id - CA Cert ID for OpenSSL engine - * - * This is used if the CA certificate for EAP-TLS is on a smartcard. - */ - char *ca_cert_id; - - /** - * key2_id - Key ID for OpenSSL engine (phase2) - * - * This is used if private key operations for EAP-TLS are performed - * using a smartcard. - */ - char *key2_id; - - /** - * cert2_id - Cert ID for OpenSSL engine (phase2) - * - * This is used if the certificate operations for EAP-TLS are performed - * using a smartcard. - */ - char *cert2_id; - - /** - * ca_cert2_id - CA Cert ID for OpenSSL engine (phase2) - * - * This is used if the CA certificate for EAP-TLS is on a smartcard. - */ - char *ca_cert2_id; - - /** - * otp - One-time-password - * - * This field should not be set in configuration step. It is only used - * internally when OTP is entered through the control interface. - */ - u8 *otp; - - /** - * otp_len - Length of the otp field - */ - size_t otp_len; - - /** - * pending_req_identity - Whether there is a pending identity 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_identity; - - /** - * pending_req_password - Whether there is a pending password 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_password; - - /** - * pending_req_pin - Whether there is a pending PIN 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_pin; - - /** - * pending_req_new_password - Pending password update 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_new_password; - - /** - * pending_req_passphrase - Pending passphrase 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_passphrase; - - /** - * pending_req_otp - Whether there is a pending OTP request - * - * This field should not be set in configuration step. It is only used - * internally when control interface is used to request needed - * information. - */ - char *pending_req_otp; - - /** - * pending_req_otp_len - Length of the pending OTP request - */ - size_t pending_req_otp_len; - - /** - * pac_file - File path or blob name for the PAC entries (EAP-FAST) - * - * wpa_supplicant will need to be able to create this file and write - * updates to it when PAC is being provisioned or refreshed. Full path - * to the file should be used since working directory may change when - * wpa_supplicant is run in the background. - * Alternatively, a named configuration blob can be used by setting - * this to blob://blob_name. - */ - char *pac_file; - - /** - * mschapv2_retry - MSCHAPv2 retry in progress - * - * This field is used internally by EAP-MSCHAPv2 and should not be set - * as part of configuration. - */ - int mschapv2_retry; - - /** - * new_password - New password for password update - * - * This field is used during MSCHAPv2 password update. This is normally - * requested from the user through the control interface and not set - * from configuration. - */ - u8 *new_password; - - /** - * new_password_len - Length of new_password field - */ - size_t new_password_len; - - /** - * fragment_size - Maximum EAP fragment size in bytes (default 1398) - * - * This value limits the fragment size for EAP methods that support - * fragmentation (e.g., EAP-TLS and EAP-PEAP). This value should be set - * small enough to make the EAP messages fit in MTU of the network - * interface used for EAPOL. The default value is suitable for most - * cases. - */ - int fragment_size; - -#define EAP_CONFIG_FLAGS_PASSWORD_NTHASH BIT(0) - /** - * flags - Network configuration flags (bitfield) - * - * This variable is used for internal flags to describe further details - * for the network parameters. - * bit 0 = password is represented as a 16-byte NtPasswordHash value - * instead of plaintext password - */ - u32 flags; -}; - - -/** - * struct wpa_config_blob - Named configuration blob - * - * This data structure is used to provide storage for binary objects to store - * abstract information like certificates and private keys inlined with the - * configuration data. - */ -struct wpa_config_blob { - /** - * name - Blob name - */ - char *name; - - /** - * data - Pointer to binary data - */ - u8 *data; - - /** - * len - Length of binary data - */ - size_t len; - - /** - * next - Pointer to next blob in the configuration - */ - struct wpa_config_blob *next; -}; - -#endif /* EAP_CONFIG_H */ diff --git a/contrib/hostapd/src/eap_peer/eap_fast.c b/contrib/hostapd/src/eap_peer/eap_fast.c deleted file mode 100644 index d00867099a..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_fast.c +++ /dev/null @@ -1,1712 +0,0 @@ -/* - * EAP peer method: EAP-FAST (RFC 4851) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "eap_config.h" -#include "tls.h" -#include "eap_common/eap_tlv_common.h" -#include "sha1.h" -#include "eap_fast_pac.h" - -#ifdef EAP_FAST_DYNAMIC -#include "eap_fast_pac.c" -#endif /* EAP_FAST_DYNAMIC */ - -/* TODO: - * - test session resumption and enable it if it interoperates - * - password change (pending mschapv2 packet; replay decrypted packet) - */ - - -static void eap_fast_deinit(struct eap_sm *sm, void *priv); - - -struct eap_fast_data { - struct eap_ssl_data ssl; - - int fast_version; - - const struct eap_method *phase2_method; - void *phase2_priv; - int phase2_success; - - struct eap_method_type phase2_type; - struct eap_method_type *phase2_types; - size_t num_phase2_types; - int resuming; /* starting a resumed session */ - struct eap_fast_key_block_provisioning *key_block_p; -#define EAP_FAST_PROV_UNAUTH 1 -#define EAP_FAST_PROV_AUTH 2 - int provisioning_allowed; /* Allowed PAC provisioning modes */ - int provisioning; /* doing PAC provisioning (not the normal auth) */ - int anon_provisioning; /* doing anonymous (unauthenticated) - * provisioning */ - int session_ticket_used; - - u8 key_data[EAP_FAST_KEY_LEN]; - u8 emsk[EAP_EMSK_LEN]; - int success; - - struct eap_fast_pac *pac; - struct eap_fast_pac *current_pac; - size_t max_pac_list_len; - int use_pac_binary_format; - - u8 simck[EAP_FAST_SIMCK_LEN]; - int simck_idx; - - struct wpabuf *pending_phase2_req; -}; - - -static int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len, - const u8 *client_random, - const u8 *server_random, - u8 *master_secret) -{ - struct eap_fast_data *data = ctx; - - wpa_printf(MSG_DEBUG, "EAP-FAST: SessionTicket callback"); - - if (client_random == NULL || server_random == NULL || - master_secret == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: SessionTicket failed - fall " - "back to full TLS handshake"); - data->session_ticket_used = 0; - if (data->provisioning_allowed) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Try to provision a " - "new PAC-Key"); - data->provisioning = 1; - data->current_pac = NULL; - } - return 0; - } - - wpa_hexdump(MSG_DEBUG, "EAP-FAST: SessionTicket", ticket, len); - - if (data->current_pac == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC-Key available for " - "using SessionTicket"); - data->session_ticket_used = 0; - return 0; - } - - eap_fast_derive_master_secret(data->current_pac->pac_key, - server_random, client_random, - master_secret); - - data->session_ticket_used = 1; - - return 1; -} - - -static int eap_fast_parse_phase1(struct eap_fast_data *data, - const char *phase1) -{ - const char *pos; - - pos = os_strstr(phase1, "fast_provisioning="); - if (pos) { - data->provisioning_allowed = atoi(pos + 18); - wpa_printf(MSG_DEBUG, "EAP-FAST: Automatic PAC provisioning " - "mode: %d", data->provisioning_allowed); - } - - pos = os_strstr(phase1, "fast_max_pac_list_len="); - if (pos) { - data->max_pac_list_len = atoi(pos + 22); - if (data->max_pac_list_len == 0) - data->max_pac_list_len = 1; - wpa_printf(MSG_DEBUG, "EAP-FAST: Maximum PAC list length: %lu", - (unsigned long) data->max_pac_list_len); - } - - pos = os_strstr(phase1, "fast_pac_format=binary"); - if (pos) { - data->use_pac_binary_format = 1; - wpa_printf(MSG_DEBUG, "EAP-FAST: Using binary format for PAC " - "list"); - } - - return 0; -} - - -static void * eap_fast_init(struct eap_sm *sm) -{ - struct eap_fast_data *data; - struct eap_peer_config *config = eap_get_config(sm); - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->fast_version = EAP_FAST_VERSION; - data->max_pac_list_len = 10; - - if (config && config->phase1 && - eap_fast_parse_phase1(data, config->phase1) < 0) { - eap_fast_deinit(sm, data); - return NULL; - } - - if (eap_peer_select_phase2_methods(config, "auth=", - &data->phase2_types, - &data->num_phase2_types) < 0) { - eap_fast_deinit(sm, data); - return NULL; - } - - data->phase2_type.vendor = EAP_VENDOR_IETF; - data->phase2_type.method = EAP_TYPE_NONE; - - if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to initialize SSL."); - eap_fast_deinit(sm, data); - return NULL; - } - - if (tls_connection_set_session_ticket_cb(sm->ssl_ctx, data->ssl.conn, - eap_fast_session_ticket_cb, - data) < 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to set SessionTicket " - "callback"); - eap_fast_deinit(sm, data); - return NULL; - } - - /* - * The local RADIUS server in a Cisco AP does not seem to like empty - * fragments before data, so disable that workaround for CBC. - * TODO: consider making this configurable - */ - if (tls_connection_enable_workaround(sm->ssl_ctx, data->ssl.conn)) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to enable TLS " - "workarounds"); - } - - if (data->use_pac_binary_format && - eap_fast_load_pac_bin(sm, &data->pac, config->pac_file) < 0) { - eap_fast_deinit(sm, data); - return NULL; - } - - if (!data->use_pac_binary_format && - eap_fast_load_pac(sm, &data->pac, config->pac_file) < 0) { - eap_fast_deinit(sm, data); - return NULL; - } - eap_fast_pac_list_truncate(data->pac, data->max_pac_list_len); - - if (data->pac == NULL && !data->provisioning_allowed) { - wpa_printf(MSG_INFO, "EAP-FAST: No PAC configured and " - "provisioning disabled"); - eap_fast_deinit(sm, data); - return NULL; - } - - return data; -} - - -static void eap_fast_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - struct eap_fast_pac *pac, *prev; - - if (data == NULL) - return; - if (data->phase2_priv && data->phase2_method) - data->phase2_method->deinit(sm, data->phase2_priv); - os_free(data->phase2_types); - os_free(data->key_block_p); - eap_peer_tls_ssl_deinit(sm, &data->ssl); - - pac = data->pac; - prev = NULL; - while (pac) { - prev = pac; - pac = pac->next; - eap_fast_free_pac(prev); - } - wpabuf_free(data->pending_phase2_req); - os_free(data); -} - - -static int eap_fast_derive_msk(struct eap_fast_data *data) -{ - eap_fast_derive_eap_msk(data->simck, data->key_data); - eap_fast_derive_eap_emsk(data->simck, data->emsk); - data->success = 1; - return 0; -} - - -static void eap_fast_derive_key_auth(struct eap_sm *sm, - struct eap_fast_data *data) -{ - u8 *sks; - - /* RFC 4851, Section 5.1: - * Extra key material after TLS key_block: session_key_seed[40] - */ - - sks = eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, "key expansion", - EAP_FAST_SKS_LEN); - if (sks == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive " - "session_key_seed"); - return; - } - - /* - * RFC 4851, Section 5.2: - * S-IMCK[0] = session_key_seed - */ - wpa_hexdump_key(MSG_DEBUG, - "EAP-FAST: session_key_seed (SKS = S-IMCK[0])", - sks, EAP_FAST_SKS_LEN); - data->simck_idx = 0; - os_memcpy(data->simck, sks, EAP_FAST_SIMCK_LEN); - os_free(sks); -} - - -static void eap_fast_derive_key_provisioning(struct eap_sm *sm, - struct eap_fast_data *data) -{ - os_free(data->key_block_p); - data->key_block_p = (struct eap_fast_key_block_provisioning *) - eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, - "key expansion", - sizeof(*data->key_block_p)); - if (data->key_block_p == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive key block"); - return; - } - /* - * RFC 4851, Section 5.2: - * S-IMCK[0] = session_key_seed - */ - wpa_hexdump_key(MSG_DEBUG, - "EAP-FAST: session_key_seed (SKS = S-IMCK[0])", - data->key_block_p->session_key_seed, - sizeof(data->key_block_p->session_key_seed)); - data->simck_idx = 0; - os_memcpy(data->simck, data->key_block_p->session_key_seed, - EAP_FAST_SIMCK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: server_challenge", - data->key_block_p->server_challenge, - sizeof(data->key_block_p->server_challenge)); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: client_challenge", - data->key_block_p->client_challenge, - sizeof(data->key_block_p->client_challenge)); -} - - -static void eap_fast_derive_keys(struct eap_sm *sm, struct eap_fast_data *data) -{ - if (data->anon_provisioning) - eap_fast_derive_key_provisioning(sm, data); - else - eap_fast_derive_key_auth(sm, data); -} - - -static int eap_fast_init_phase2_method(struct eap_sm *sm, - struct eap_fast_data *data) -{ - data->phase2_method = - eap_peer_get_eap_method(data->phase2_type.vendor, - data->phase2_type.method); - if (data->phase2_method == NULL) - return -1; - - if (data->key_block_p) { - sm->auth_challenge = data->key_block_p->server_challenge; - sm->peer_challenge = data->key_block_p->client_challenge; - } - sm->init_phase2 = 1; - data->phase2_priv = data->phase2_method->init(sm); - sm->init_phase2 = 0; - sm->auth_challenge = NULL; - sm->peer_challenge = NULL; - - return data->phase2_priv == NULL ? -1 : 0; -} - - -static int eap_fast_select_phase2_method(struct eap_fast_data *data, u8 type) -{ - size_t i; - - /* TODO: TNC with anonymous provisioning; need to require both - * completed MSCHAPv2 and TNC */ - - if (data->anon_provisioning && type != EAP_TYPE_MSCHAPV2) { - wpa_printf(MSG_INFO, "EAP-FAST: Only EAP-MSCHAPv2 is allowed " - "during unauthenticated provisioning; reject phase2" - " type %d", type); - return -1; - } - -#ifdef EAP_TNC - if (type == EAP_TYPE_TNC) { - data->phase2_type.vendor = EAP_VENDOR_IETF; - data->phase2_type.method = EAP_TYPE_TNC; - wpa_printf(MSG_DEBUG, "EAP-FAST: Selected Phase 2 EAP " - "vendor %d method %d for TNC", - data->phase2_type.vendor, - data->phase2_type.method); - return 0; - } -#endif /* EAP_TNC */ - - for (i = 0; i < data->num_phase2_types; i++) { - if (data->phase2_types[i].vendor != EAP_VENDOR_IETF || - data->phase2_types[i].method != type) - continue; - - data->phase2_type.vendor = data->phase2_types[i].vendor; - data->phase2_type.method = data->phase2_types[i].method; - wpa_printf(MSG_DEBUG, "EAP-FAST: Selected Phase 2 EAP " - "vendor %d method %d", - data->phase2_type.vendor, - data->phase2_type.method); - break; - } - - if (type != data->phase2_type.method || type == EAP_TYPE_NONE) - return -1; - - return 0; -} - - -static int eap_fast_phase2_request(struct eap_sm *sm, - struct eap_fast_data *data, - struct eap_method_ret *ret, - struct eap_hdr *hdr, - struct wpabuf **resp) -{ - size_t len = be_to_host16(hdr->length); - u8 *pos; - struct eap_method_ret iret; - struct eap_peer_config *config = eap_get_config(sm); - struct wpabuf msg; - - if (len <= sizeof(struct eap_hdr)) { - wpa_printf(MSG_INFO, "EAP-FAST: too short " - "Phase 2 request (len=%lu)", (unsigned long) len); - return -1; - } - pos = (u8 *) (hdr + 1); - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 Request: type=%d", *pos); - if (*pos == EAP_TYPE_IDENTITY) { - *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1); - return 0; - } - - if (data->phase2_priv && data->phase2_method && - *pos != data->phase2_type.method) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 EAP sequence - " - "deinitialize previous method"); - data->phase2_method->deinit(sm, data->phase2_priv); - data->phase2_method = NULL; - data->phase2_priv = NULL; - data->phase2_type.vendor = EAP_VENDOR_IETF; - data->phase2_type.method = EAP_TYPE_NONE; - } - - if (data->phase2_type.vendor == EAP_VENDOR_IETF && - data->phase2_type.method == EAP_TYPE_NONE && - eap_fast_select_phase2_method(data, *pos) < 0) { - if (eap_peer_tls_phase2_nak(data->phase2_types, - data->num_phase2_types, - hdr, resp)) - return -1; - return 0; - } - - if (data->phase2_priv == NULL && - eap_fast_init_phase2_method(sm, data) < 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to initialize " - "Phase 2 EAP method %d", *pos); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return -1; - } - - os_memset(&iret, 0, sizeof(iret)); - wpabuf_set(&msg, hdr, len); - *resp = data->phase2_method->process(sm, data->phase2_priv, &iret, - &msg); - if (*resp == NULL || - (iret.methodState == METHOD_DONE && - iret.decision == DECISION_FAIL)) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - } else if ((iret.methodState == METHOD_DONE || - iret.methodState == METHOD_MAY_CONT) && - (iret.decision == DECISION_UNCOND_SUCC || - iret.decision == DECISION_COND_SUCC)) { - data->phase2_success = 1; - } - - if (*resp == NULL && config && - (config->pending_req_identity || config->pending_req_password || - config->pending_req_otp || config->pending_req_new_password)) { - wpabuf_free(data->pending_phase2_req); - data->pending_phase2_req = wpabuf_alloc_copy(hdr, len); - } else if (*resp == NULL) - return -1; - - return 0; -} - - -static struct wpabuf * eap_fast_tlv_nak(int vendor_id, int tlv_type) -{ - struct wpabuf *buf; - struct eap_tlv_nak_tlv *nak; - buf = wpabuf_alloc(sizeof(*nak)); - if (buf == NULL) - return NULL; - nak = wpabuf_put(buf, sizeof(*nak)); - nak->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | EAP_TLV_NAK_TLV); - nak->length = host_to_be16(6); - nak->vendor_id = host_to_be32(vendor_id); - nak->nak_type = host_to_be16(tlv_type); - return buf; -} - - -static struct wpabuf * eap_fast_tlv_result(int status, int intermediate) -{ - struct wpabuf *buf; - struct eap_tlv_intermediate_result_tlv *result; - buf = wpabuf_alloc(sizeof(*result)); - if (buf == NULL) - return NULL; - wpa_printf(MSG_DEBUG, "EAP-FAST: Add %sResult TLV(status=%d)", - intermediate ? "Intermediate " : "", status); - result = wpabuf_put(buf, sizeof(*result)); - result->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - (intermediate ? - EAP_TLV_INTERMEDIATE_RESULT_TLV : - EAP_TLV_RESULT_TLV)); - result->length = host_to_be16(2); - result->status = host_to_be16(status); - return buf; -} - - -static struct wpabuf * eap_fast_tlv_pac_ack(void) -{ - struct wpabuf *buf; - struct eap_tlv_result_tlv *res; - struct eap_tlv_pac_ack_tlv *ack; - - buf = wpabuf_alloc(sizeof(*res) + sizeof(*ack)); - if (buf == NULL) - return NULL; - - wpa_printf(MSG_DEBUG, "EAP-FAST: Add PAC TLV (ack)"); - ack = wpabuf_put(buf, sizeof(*ack)); - ack->tlv_type = host_to_be16(EAP_TLV_PAC_TLV | - EAP_TLV_TYPE_MANDATORY); - ack->length = host_to_be16(sizeof(*ack) - sizeof(struct eap_tlv_hdr)); - ack->pac_type = host_to_be16(PAC_TYPE_PAC_ACKNOWLEDGEMENT); - ack->pac_len = host_to_be16(2); - ack->result = host_to_be16(EAP_TLV_RESULT_SUCCESS); - - return buf; -} - - -static struct wpabuf * eap_fast_process_eap_payload_tlv( - struct eap_sm *sm, struct eap_fast_data *data, - struct eap_method_ret *ret, const struct eap_hdr *req, - u8 *eap_payload_tlv, size_t eap_payload_tlv_len) -{ - struct eap_hdr *hdr; - struct wpabuf *resp = NULL; - - if (eap_payload_tlv_len < sizeof(*hdr)) { - wpa_printf(MSG_DEBUG, "EAP-FAST: too short EAP " - "Payload TLV (len=%lu)", - (unsigned long) eap_payload_tlv_len); - return NULL; - } - - hdr = (struct eap_hdr *) eap_payload_tlv; - if (be_to_host16(hdr->length) > eap_payload_tlv_len) { - wpa_printf(MSG_DEBUG, "EAP-FAST: EAP packet overflow in " - "EAP Payload TLV"); - return NULL; - } - - if (hdr->code != EAP_CODE_REQUEST) { - wpa_printf(MSG_INFO, "EAP-FAST: Unexpected code=%d in " - "Phase 2 EAP header", hdr->code); - return NULL; - } - - if (eap_fast_phase2_request(sm, data, ret, hdr, &resp)) { - wpa_printf(MSG_INFO, "EAP-FAST: Phase2 Request processing " - "failed"); - return NULL; - } - - return eap_fast_tlv_eap_payload(resp); -} - - -static int eap_fast_validate_crypto_binding( - struct eap_tlv_crypto_binding_tlv *_bind) -{ - wpa_printf(MSG_DEBUG, "EAP-FAST: Crypto-Binding TLV: Version %d " - "Received Version %d SubType %d", - _bind->version, _bind->received_version, _bind->subtype); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: NONCE", - _bind->nonce, sizeof(_bind->nonce)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Compound MAC", - _bind->compound_mac, sizeof(_bind->compound_mac)); - - if (_bind->version != EAP_FAST_VERSION || - _bind->received_version != EAP_FAST_VERSION || - _bind->subtype != EAP_TLV_CRYPTO_BINDING_SUBTYPE_REQUEST) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid version/subtype in " - "Crypto-Binding TLV: Version %d " - "Received Version %d SubType %d", - _bind->version, _bind->received_version, - _bind->subtype); - return -1; - } - - return 0; -} - - -static void eap_fast_write_crypto_binding( - struct eap_tlv_crypto_binding_tlv *rbind, - struct eap_tlv_crypto_binding_tlv *_bind, const u8 *cmk) -{ - rbind->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - EAP_TLV_CRYPTO_BINDING_TLV); - rbind->length = host_to_be16(sizeof(*rbind) - - sizeof(struct eap_tlv_hdr)); - rbind->version = EAP_FAST_VERSION; - rbind->received_version = _bind->version; - rbind->subtype = EAP_TLV_CRYPTO_BINDING_SUBTYPE_RESPONSE; - os_memcpy(rbind->nonce, _bind->nonce, sizeof(_bind->nonce)); - inc_byte_array(rbind->nonce, sizeof(rbind->nonce)); - hmac_sha1(cmk, EAP_FAST_CMK_LEN, (u8 *) rbind, sizeof(*rbind), - rbind->compound_mac); - - wpa_printf(MSG_DEBUG, "EAP-FAST: Reply Crypto-Binding TLV: Version %d " - "Received Version %d SubType %d", - rbind->version, rbind->received_version, rbind->subtype); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: NONCE", - rbind->nonce, sizeof(rbind->nonce)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Compound MAC", - rbind->compound_mac, sizeof(rbind->compound_mac)); -} - - -static int eap_fast_get_phase2_key(struct eap_sm *sm, - struct eap_fast_data *data, - u8 *isk, size_t isk_len) -{ - u8 *key; - size_t key_len; - - os_memset(isk, 0, isk_len); - - if (data->phase2_method == NULL || data->phase2_priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 method not " - "available"); - return -1; - } - - if (data->phase2_method->isKeyAvailable == NULL || - data->phase2_method->getKey == NULL) - return 0; - - if (!data->phase2_method->isKeyAvailable(sm, data->phase2_priv) || - (key = data->phase2_method->getKey(sm, data->phase2_priv, - &key_len)) == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Could not get key material " - "from Phase 2"); - return -1; - } - - if (key_len > isk_len) - key_len = isk_len; - if (key_len == 32 && - data->phase2_method->vendor == EAP_VENDOR_IETF && - data->phase2_method->method == EAP_TYPE_MSCHAPV2) { - /* - * EAP-FAST uses reverse order for MS-MPPE keys when deriving - * MSK from EAP-MSCHAPv2. Swap the keys here to get the correct - * ISK for EAP-FAST cryptobinding. - */ - os_memcpy(isk, key + 16, 16); - os_memcpy(isk + 16, key, 16); - } else - os_memcpy(isk, key, key_len); - os_free(key); - - return 0; -} - - -static int eap_fast_get_cmk(struct eap_sm *sm, struct eap_fast_data *data, - u8 *cmk) -{ - u8 isk[32], imck[60]; - - wpa_printf(MSG_DEBUG, "EAP-FAST: Determining CMK[%d] for Compound MIC " - "calculation", data->simck_idx + 1); - - /* - * RFC 4851, Section 5.2: - * IMCK[j] = T-PRF(S-IMCK[j-1], "Inner Methods Compound Keys", - * MSK[j], 60) - * S-IMCK[j] = first 40 octets of IMCK[j] - * CMK[j] = last 20 octets of IMCK[j] - */ - - if (eap_fast_get_phase2_key(sm, data, isk, sizeof(isk)) < 0) - return -1; - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: ISK[j]", isk, sizeof(isk)); - sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN, - "Inner Methods Compound Keys", - isk, sizeof(isk), imck, sizeof(imck)); - data->simck_idx++; - os_memcpy(data->simck, imck, EAP_FAST_SIMCK_LEN); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: S-IMCK[j]", - data->simck, EAP_FAST_SIMCK_LEN); - os_memcpy(cmk, imck + EAP_FAST_SIMCK_LEN, EAP_FAST_CMK_LEN); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: CMK[j]", - cmk, EAP_FAST_CMK_LEN); - - return 0; -} - - -static u8 * eap_fast_write_pac_request(u8 *pos, u16 pac_type) -{ - struct eap_tlv_hdr *pac; - struct eap_tlv_request_action_tlv *act; - struct eap_tlv_pac_type_tlv *type; - - act = (struct eap_tlv_request_action_tlv *) pos; - act->tlv_type = host_to_be16(EAP_TLV_REQUEST_ACTION_TLV); - act->length = host_to_be16(2); - act->action = host_to_be16(EAP_TLV_ACTION_PROCESS_TLV); - - pac = (struct eap_tlv_hdr *) (act + 1); - pac->tlv_type = host_to_be16(EAP_TLV_PAC_TLV); - pac->length = host_to_be16(sizeof(*type)); - - type = (struct eap_tlv_pac_type_tlv *) (pac + 1); - type->tlv_type = host_to_be16(PAC_TYPE_PAC_TYPE); - type->length = host_to_be16(2); - type->pac_type = host_to_be16(pac_type); - - return (u8 *) (type + 1); -} - - -static struct wpabuf * eap_fast_process_crypto_binding( - struct eap_sm *sm, struct eap_fast_data *data, - struct eap_method_ret *ret, - struct eap_tlv_crypto_binding_tlv *_bind, size_t bind_len) -{ - struct wpabuf *resp; - u8 *pos; - u8 cmk[EAP_FAST_CMK_LEN], cmac[SHA1_MAC_LEN]; - int res; - size_t len; - - if (eap_fast_validate_crypto_binding(_bind) < 0) - return NULL; - - if (eap_fast_get_cmk(sm, data, cmk) < 0) - return NULL; - - /* Validate received Compound MAC */ - os_memcpy(cmac, _bind->compound_mac, sizeof(cmac)); - os_memset(_bind->compound_mac, 0, sizeof(cmac)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV for Compound " - "MAC calculation", (u8 *) _bind, bind_len); - hmac_sha1(cmk, EAP_FAST_CMK_LEN, (u8 *) _bind, bind_len, - _bind->compound_mac); - res = os_memcmp(cmac, _bind->compound_mac, sizeof(cmac)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Received Compound MAC", - cmac, sizeof(cmac)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Calculated Compound MAC", - _bind->compound_mac, sizeof(cmac)); - if (res != 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Compound MAC did not match"); - os_memcpy(_bind->compound_mac, cmac, sizeof(cmac)); - return NULL; - } - - /* - * Compound MAC was valid, so authentication succeeded. Reply with - * crypto binding to allow server to complete authentication. - */ - - len = sizeof(struct eap_tlv_crypto_binding_tlv); - resp = wpabuf_alloc(len); - if (resp == NULL) - return NULL; - - if (!data->anon_provisioning && data->phase2_success && - eap_fast_derive_msk(data) < 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to generate MSK"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - data->phase2_success = 0; - wpabuf_free(resp); - return NULL; - } - - pos = wpabuf_put(resp, sizeof(struct eap_tlv_crypto_binding_tlv)); - eap_fast_write_crypto_binding((struct eap_tlv_crypto_binding_tlv *) - pos, _bind, cmk); - - return resp; -} - - -static void eap_fast_parse_pac_tlv(struct eap_fast_pac *entry, int type, - u8 *pos, size_t len, int *pac_key_found) -{ - switch (type & 0x7fff) { - case PAC_TYPE_PAC_KEY: - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: PAC-Key", pos, len); - if (len != EAP_FAST_PAC_KEY_LEN) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid PAC-Key " - "length %lu", (unsigned long) len); - break; - } - *pac_key_found = 1; - os_memcpy(entry->pac_key, pos, len); - break; - case PAC_TYPE_PAC_OPAQUE: - wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Opaque", pos, len); - entry->pac_opaque = pos; - entry->pac_opaque_len = len; - break; - case PAC_TYPE_PAC_INFO: - wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Info", pos, len); - entry->pac_info = pos; - entry->pac_info_len = len; - break; - default: - wpa_printf(MSG_DEBUG, "EAP-FAST: Ignored unknown PAC type %d", - type); - break; - } -} - - -static int eap_fast_process_pac_tlv(struct eap_fast_pac *entry, - u8 *pac, size_t pac_len) -{ - struct pac_tlv_hdr *hdr; - u8 *pos; - size_t left, len; - int type, pac_key_found = 0; - - pos = pac; - left = pac_len; - - while (left > sizeof(*hdr)) { - hdr = (struct pac_tlv_hdr *) pos; - type = be_to_host16(hdr->type); - len = be_to_host16(hdr->len); - pos += sizeof(*hdr); - left -= sizeof(*hdr); - if (len > left) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC TLV overrun " - "(type=%d len=%lu left=%lu)", - type, (unsigned long) len, - (unsigned long) left); - return -1; - } - - eap_fast_parse_pac_tlv(entry, type, pos, len, &pac_key_found); - - pos += len; - left -= len; - } - - if (!pac_key_found || !entry->pac_opaque || !entry->pac_info) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC TLV does not include " - "all the required fields"); - return -1; - } - - return 0; -} - - -static int eap_fast_parse_pac_info(struct eap_fast_pac *entry, int type, - u8 *pos, size_t len) -{ - u16 pac_type; - u32 lifetime; - struct os_time now; - - switch (type & 0x7fff) { - case PAC_TYPE_CRED_LIFETIME: - if (len != 4) { - wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Info - " - "Invalid CRED_LIFETIME length - ignored", - pos, len); - return 0; - } - - /* - * This is not currently saved separately in PAC files since - * the server can automatically initiate PAC update when - * needed. Anyway, the information is available from PAC-Info - * dump if it is needed for something in the future. - */ - lifetime = WPA_GET_BE32(pos); - os_get_time(&now); - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Info - CRED_LIFETIME %d " - "(%d days)", - lifetime, (lifetime - (u32) now.sec) / 86400); - break; - case PAC_TYPE_A_ID: - wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: PAC-Info - A-ID", - pos, len); - entry->a_id = pos; - entry->a_id_len = len; - break; - case PAC_TYPE_I_ID: - wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: PAC-Info - I-ID", - pos, len); - entry->i_id = pos; - entry->i_id_len = len; - break; - case PAC_TYPE_A_ID_INFO: - wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: PAC-Info - A-ID-Info", - pos, len); - entry->a_id_info = pos; - entry->a_id_info_len = len; - break; - case PAC_TYPE_PAC_TYPE: - /* RFC 5422, Section 4.2.6 - PAC-Type TLV */ - if (len != 2) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid PAC-Type " - "length %lu (expected 2)", - (unsigned long) len); - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-FAST: PAC-Info - PAC-Type", - pos, len); - return -1; - } - pac_type = WPA_GET_BE16(pos); - if (pac_type != PAC_TYPE_TUNNEL_PAC && - pac_type != PAC_TYPE_USER_AUTHORIZATION && - pac_type != PAC_TYPE_MACHINE_AUTHENTICATION) { - wpa_printf(MSG_INFO, "EAP-FAST: Unsupported PAC Type " - "%d", pac_type); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Info - PAC-Type %d", - pac_type); - entry->pac_type = pac_type; - break; - default: - wpa_printf(MSG_DEBUG, "EAP-FAST: Ignored unknown PAC-Info " - "type %d", type); - break; - } - - return 0; -} - - -static int eap_fast_process_pac_info(struct eap_fast_pac *entry) -{ - struct pac_tlv_hdr *hdr; - u8 *pos; - size_t left, len; - int type; - - /* RFC 5422, Section 4.2.4 */ - - /* PAC-Type defaults to Tunnel PAC (Type 1) */ - entry->pac_type = PAC_TYPE_TUNNEL_PAC; - - pos = entry->pac_info; - left = entry->pac_info_len; - while (left > sizeof(*hdr)) { - hdr = (struct pac_tlv_hdr *) pos; - type = be_to_host16(hdr->type); - len = be_to_host16(hdr->len); - pos += sizeof(*hdr); - left -= sizeof(*hdr); - if (len > left) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Info overrun " - "(type=%d len=%lu left=%lu)", - type, (unsigned long) len, - (unsigned long) left); - return -1; - } - - if (eap_fast_parse_pac_info(entry, type, pos, len) < 0) - return -1; - - pos += len; - left -= len; - } - - if (entry->a_id == NULL || entry->a_id_info == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Info does not include " - "all the required fields"); - return -1; - } - - return 0; -} - - -static struct wpabuf * eap_fast_process_pac(struct eap_sm *sm, - struct eap_fast_data *data, - struct eap_method_ret *ret, - u8 *pac, size_t pac_len) -{ - struct eap_peer_config *config = eap_get_config(sm); - struct eap_fast_pac entry; - - os_memset(&entry, 0, sizeof(entry)); - if (eap_fast_process_pac_tlv(&entry, pac, pac_len) || - eap_fast_process_pac_info(&entry)) - return NULL; - - eap_fast_add_pac(&data->pac, &data->current_pac, &entry); - eap_fast_pac_list_truncate(data->pac, data->max_pac_list_len); - if (data->use_pac_binary_format) - eap_fast_save_pac_bin(sm, data->pac, config->pac_file); - else - eap_fast_save_pac(sm, data->pac, config->pac_file); - - if (data->provisioning) { - if (data->anon_provisioning) { - /* - * Unauthenticated provisioning does not provide keying - * material and must end with an EAP-Failure. - * Authentication will be done separately after this. - */ - data->success = 0; - ret->decision = DECISION_FAIL; - } else { - /* - * Server may or may not allow authenticated - * provisioning also for key generation. - */ - ret->decision = DECISION_COND_SUCC; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: Send PAC-Acknowledgement TLV " - "- Provisioning completed successfully"); - } else { - /* - * This is PAC refreshing, i.e., normal authentication that is - * expected to be completed with an EAP-Success. - */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Send PAC-Acknowledgement TLV " - "- PAC refreshing completed successfully"); - ret->decision = DECISION_UNCOND_SUCC; - } - ret->methodState = METHOD_DONE; - return eap_fast_tlv_pac_ack(); -} - - -static int eap_fast_parse_decrypted(struct wpabuf *decrypted, - struct eap_fast_tlv_parse *tlv, - struct wpabuf **resp) -{ - int mandatory, tlv_type, len, res; - u8 *pos, *end; - - os_memset(tlv, 0, sizeof(*tlv)); - - /* Parse TLVs from the decrypted Phase 2 data */ - pos = wpabuf_mhead(decrypted); - end = pos + wpabuf_len(decrypted); - while (pos + 4 < end) { - mandatory = pos[0] & 0x80; - tlv_type = WPA_GET_BE16(pos) & 0x3fff; - pos += 2; - len = WPA_GET_BE16(pos); - pos += 2; - if (pos + len > end) { - wpa_printf(MSG_INFO, "EAP-FAST: TLV overflow"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: Received Phase 2: " - "TLV type %d length %d%s", - tlv_type, len, mandatory ? " (mandatory)" : ""); - - res = eap_fast_parse_tlv(tlv, tlv_type, pos, len); - if (res == -2) - break; - if (res < 0) { - if (mandatory) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Nak unknown " - "mandatory TLV type %d", tlv_type); - *resp = eap_fast_tlv_nak(0, tlv_type); - break; - } else { - wpa_printf(MSG_DEBUG, "EAP-FAST: ignored " - "unknown optional TLV type %d", - tlv_type); - } - } - - pos += len; - } - - return 0; -} - - -static int eap_fast_encrypt_response(struct eap_sm *sm, - struct eap_fast_data *data, - struct wpabuf *resp, - u8 identifier, struct wpabuf **out_data) -{ - if (resp == NULL) - return 0; - - wpa_hexdump_buf(MSG_DEBUG, "EAP-FAST: Encrypting Phase 2 data", - resp); - if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_FAST, - data->fast_version, identifier, - resp, out_data)) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to encrypt a Phase 2 " - "frame"); - } - wpabuf_free(resp); - - return 0; -} - - -static struct wpabuf * eap_fast_pac_request(void) -{ - struct wpabuf *tmp; - u8 *pos, *pos2; - - tmp = wpabuf_alloc(sizeof(struct eap_tlv_hdr) + - sizeof(struct eap_tlv_request_action_tlv) + - sizeof(struct eap_tlv_pac_type_tlv)); - if (tmp == NULL) - return NULL; - - pos = wpabuf_put(tmp, 0); - pos2 = eap_fast_write_pac_request(pos, PAC_TYPE_TUNNEL_PAC); - wpabuf_put(tmp, pos2 - pos); - return tmp; -} - - -static int eap_fast_process_decrypted(struct eap_sm *sm, - struct eap_fast_data *data, - struct eap_method_ret *ret, - const struct eap_hdr *req, - struct wpabuf *decrypted, - struct wpabuf **out_data) -{ - struct wpabuf *resp = NULL, *tmp; - struct eap_fast_tlv_parse tlv; - int failed = 0; - - if (eap_fast_parse_decrypted(decrypted, &tlv, &resp) < 0) - return 0; - if (resp) - return eap_fast_encrypt_response(sm, data, resp, - req->identifier, out_data); - - if (tlv.result == EAP_TLV_RESULT_FAILURE) { - resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0); - return eap_fast_encrypt_response(sm, data, resp, - req->identifier, out_data); - } - - if (tlv.iresult == EAP_TLV_RESULT_FAILURE) { - resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 1); - return eap_fast_encrypt_response(sm, data, resp, - req->identifier, out_data); - } - - if (tlv.crypto_binding) { - tmp = eap_fast_process_crypto_binding(sm, data, ret, - tlv.crypto_binding, - tlv.crypto_binding_len); - if (tmp == NULL) - failed = 1; - else - resp = wpabuf_concat(resp, tmp); - } - - if (tlv.iresult == EAP_TLV_RESULT_SUCCESS) { - tmp = eap_fast_tlv_result(failed ? EAP_TLV_RESULT_FAILURE : - EAP_TLV_RESULT_SUCCESS, 1); - resp = wpabuf_concat(resp, tmp); - } - - if (tlv.eap_payload_tlv) { - tmp = eap_fast_process_eap_payload_tlv( - sm, data, ret, req, tlv.eap_payload_tlv, - tlv.eap_payload_tlv_len); - resp = wpabuf_concat(resp, tmp); - } - - if (tlv.pac && tlv.result != EAP_TLV_RESULT_SUCCESS) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC TLV without Result TLV " - "acknowledging success"); - failed = 1; - } else if (tlv.pac && tlv.result == EAP_TLV_RESULT_SUCCESS) { - tmp = eap_fast_process_pac(sm, data, ret, tlv.pac, - tlv.pac_len); - resp = wpabuf_concat(resp, tmp); - } - - if (data->current_pac == NULL && data->provisioning && - !data->anon_provisioning && !tlv.pac && - (tlv.iresult == EAP_TLV_RESULT_SUCCESS || - tlv.result == EAP_TLV_RESULT_SUCCESS)) { - /* - * Need to request Tunnel PAC when using authenticated - * provisioning. - */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Request Tunnel PAC"); - tmp = eap_fast_pac_request(); - resp = wpabuf_concat(resp, tmp); - } - - if (tlv.result == EAP_TLV_RESULT_SUCCESS && !failed) { - tmp = eap_fast_tlv_result(EAP_TLV_RESULT_SUCCESS, 0); - resp = wpabuf_concat(tmp, resp); - } else if (failed) { - tmp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0); - resp = wpabuf_concat(tmp, resp); - } - - if (resp && tlv.result == EAP_TLV_RESULT_SUCCESS && !failed && - tlv.crypto_binding && data->phase2_success) { - if (data->anon_provisioning) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Unauthenticated " - "provisioning completed successfully."); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - } else { - wpa_printf(MSG_DEBUG, "EAP-FAST: Authentication " - "completed successfully."); - if (data->provisioning) - ret->methodState = METHOD_MAY_CONT; - else - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - } - } - - if (resp == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: No recognized TLVs - send " - "empty response packet"); - resp = wpabuf_alloc(1); - } - - return eap_fast_encrypt_response(sm, data, resp, req->identifier, - out_data); -} - - -static int eap_fast_decrypt(struct eap_sm *sm, struct eap_fast_data *data, - struct eap_method_ret *ret, - const struct eap_hdr *req, - const struct wpabuf *in_data, - struct wpabuf **out_data) -{ - struct wpabuf *in_decrypted; - int res; - - wpa_printf(MSG_DEBUG, "EAP-FAST: Received %lu bytes encrypted data for" - " Phase 2", (unsigned long) wpabuf_len(in_data)); - - if (data->pending_phase2_req) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Pending Phase 2 request - " - "skip decryption and use old data"); - /* Clear TLS reassembly state. */ - eap_peer_tls_reset_input(&data->ssl); - - in_decrypted = data->pending_phase2_req; - data->pending_phase2_req = NULL; - goto continue_req; - } - - if (wpabuf_len(in_data) == 0) { - /* Received TLS ACK - requesting more fragments */ - return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_FAST, - data->fast_version, - req->identifier, NULL, out_data); - } - - res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted); - if (res) - return res; - -continue_req: - wpa_hexdump_buf(MSG_MSGDUMP, "EAP-FAST: Decrypted Phase 2 TLV(s)", - in_decrypted); - - if (wpabuf_len(in_decrypted) < 4) { - wpa_printf(MSG_INFO, "EAP-FAST: Too short Phase 2 " - "TLV frame (len=%lu)", - (unsigned long) wpabuf_len(in_decrypted)); - wpabuf_free(in_decrypted); - return -1; - } - - res = eap_fast_process_decrypted(sm, data, ret, req, - in_decrypted, out_data); - - wpabuf_free(in_decrypted); - - return res; -} - - -static const u8 * eap_fast_get_a_id(const u8 *buf, size_t len, size_t *id_len) -{ - const u8 *a_id; - struct pac_tlv_hdr *hdr; - - /* - * Parse authority identity (A-ID) from the EAP-FAST/Start. This - * supports both raw A-ID and one inside an A-ID TLV. - */ - a_id = buf; - *id_len = len; - if (len > sizeof(*hdr)) { - int tlen; - hdr = (struct pac_tlv_hdr *) buf; - tlen = be_to_host16(hdr->len); - if (be_to_host16(hdr->type) == PAC_TYPE_A_ID && - sizeof(*hdr) + tlen <= len) { - wpa_printf(MSG_DEBUG, "EAP-FAST: A-ID was in TLV " - "(Start)"); - a_id = (u8 *) (hdr + 1); - *id_len = tlen; - } - } - wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: A-ID", a_id, *id_len); - - return a_id; -} - - -static void eap_fast_select_pac(struct eap_fast_data *data, - const u8 *a_id, size_t a_id_len) -{ - data->current_pac = eap_fast_get_pac(data->pac, a_id, a_id_len, - PAC_TYPE_TUNNEL_PAC); - if (data->current_pac == NULL) { - /* - * Tunnel PAC was not available for this A-ID. Try to use - * Machine Authentication PAC, if one is available. - */ - data->current_pac = eap_fast_get_pac( - data->pac, a_id, a_id_len, - PAC_TYPE_MACHINE_AUTHENTICATION); - } - - if (data->current_pac) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC found for this A-ID " - "(PAC-Type %d)", data->current_pac->pac_type); - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-FAST: A-ID-Info", - data->current_pac->a_id_info, - data->current_pac->a_id_info_len); - } -} - - -static int eap_fast_use_pac_opaque(struct eap_sm *sm, - struct eap_fast_data *data, - struct eap_fast_pac *pac) -{ - u8 *tlv; - size_t tlv_len, olen; - struct eap_tlv_hdr *ehdr; - - olen = pac->pac_opaque_len; - tlv_len = sizeof(*ehdr) + olen; - tlv = os_malloc(tlv_len); - if (tlv) { - ehdr = (struct eap_tlv_hdr *) tlv; - ehdr->tlv_type = host_to_be16(PAC_TYPE_PAC_OPAQUE); - ehdr->length = host_to_be16(olen); - os_memcpy(ehdr + 1, pac->pac_opaque, olen); - } - if (tlv == NULL || - tls_connection_client_hello_ext(sm->ssl_ctx, data->ssl.conn, - TLS_EXT_PAC_OPAQUE, - tlv, tlv_len) < 0) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to add PAC-Opaque TLS " - "extension"); - os_free(tlv); - return -1; - } - os_free(tlv); - - return 0; -} - - -static int eap_fast_clear_pac_opaque_ext(struct eap_sm *sm, - struct eap_fast_data *data) -{ - if (tls_connection_client_hello_ext(sm->ssl_ctx, data->ssl.conn, - TLS_EXT_PAC_OPAQUE, NULL, 0) < 0) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to remove PAC-Opaque " - "TLS extension"); - return -1; - } - return 0; -} - - -static int eap_fast_set_provisioning_ciphers(struct eap_sm *sm, - struct eap_fast_data *data) -{ - u8 ciphers[5]; - int count = 0; - - if (data->provisioning_allowed & EAP_FAST_PROV_UNAUTH) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Enabling unauthenticated " - "provisioning TLS cipher suites"); - ciphers[count++] = TLS_CIPHER_ANON_DH_AES128_SHA; - } - - if (data->provisioning_allowed & EAP_FAST_PROV_AUTH) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Enabling authenticated " - "provisioning TLS cipher suites"); - ciphers[count++] = TLS_CIPHER_RSA_DHE_AES128_SHA; - ciphers[count++] = TLS_CIPHER_AES128_SHA; - ciphers[count++] = TLS_CIPHER_RC4_SHA; - } - - ciphers[count++] = TLS_CIPHER_NONE; - - if (tls_connection_set_cipher_list(sm->ssl_ctx, data->ssl.conn, - ciphers)) { - wpa_printf(MSG_INFO, "EAP-FAST: Could not configure TLS " - "cipher suites for provisioning"); - return -1; - } - - return 0; -} - - -static int eap_fast_process_start(struct eap_sm *sm, - struct eap_fast_data *data, u8 flags, - const u8 *pos, size_t left) -{ - const u8 *a_id; - size_t a_id_len; - - /* EAP-FAST Version negotiation (section 3.1) */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Start (server ver=%d, own ver=%d)", - flags & EAP_PEAP_VERSION_MASK, data->fast_version); - if ((flags & EAP_PEAP_VERSION_MASK) < data->fast_version) - data->fast_version = flags & EAP_PEAP_VERSION_MASK; - wpa_printf(MSG_DEBUG, "EAP-FAST: Using FAST version %d", - data->fast_version); - - a_id = eap_fast_get_a_id(pos, left, &a_id_len); - eap_fast_select_pac(data, a_id, a_id_len); - - if (data->resuming && data->current_pac) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Trying to resume session - " - "do not add PAC-Opaque to TLS ClientHello"); - if (eap_fast_clear_pac_opaque_ext(sm, data) < 0) - return -1; - } else if (data->current_pac) { - /* - * PAC found for the A-ID and we are not resuming an old - * session, so add PAC-Opaque extension to ClientHello. - */ - if (eap_fast_use_pac_opaque(sm, data, data->current_pac) < 0) - return -1; - } else { - /* No PAC found, so we must provision one. */ - if (!data->provisioning_allowed) { - wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC found and " - "provisioning disabled"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC found - " - "starting provisioning"); - if (eap_fast_set_provisioning_ciphers(sm, data) < 0 || - eap_fast_clear_pac_opaque_ext(sm, data) < 0) - return -1; - data->provisioning = 1; - } - - return 0; -} - - -static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - const struct eap_hdr *req; - size_t left; - int res; - u8 flags, id; - struct wpabuf *resp; - const u8 *pos; - struct eap_fast_data *data = priv; - - pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_FAST, ret, - reqData, &left, &flags); - if (pos == NULL) - return NULL; - - req = wpabuf_head(reqData); - id = req->identifier; - - if (flags & EAP_TLS_FLAGS_START) { - if (eap_fast_process_start(sm, data, flags, pos, left) < 0) - return NULL; - - left = 0; /* A-ID is not used in further packet processing */ - } - - resp = NULL; - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && - !data->resuming) { - /* Process tunneled (encrypted) phase 2 data. */ - struct wpabuf msg; - wpabuf_set(&msg, pos, left); - res = eap_fast_decrypt(sm, data, ret, req, &msg, &resp); - if (res < 0) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - /* - * Ack possible Alert that may have caused failure in - * decryption. - */ - res = 1; - } - } else { - /* Continue processing TLS handshake (phase 1). */ - res = eap_peer_tls_process_helper(sm, &data->ssl, - EAP_TYPE_FAST, - data->fast_version, id, pos, - left, &resp); - - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - char cipher[80]; - wpa_printf(MSG_DEBUG, - "EAP-FAST: TLS done, proceed to Phase 2"); - if (data->provisioning && - (!(data->provisioning_allowed & - EAP_FAST_PROV_AUTH) || - tls_get_cipher(sm->ssl_ctx, data->ssl.conn, - cipher, sizeof(cipher)) < 0 || - os_strstr(cipher, "ADH-") || - os_strstr(cipher, "anon"))) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Using " - "anonymous (unauthenticated) " - "provisioning"); - data->anon_provisioning = 1; - } else - data->anon_provisioning = 0; - data->resuming = 0; - eap_fast_derive_keys(sm, data); - } - - if (res == 2) { - struct wpabuf msg; - /* - * Application data included in the handshake message. - */ - wpabuf_free(data->pending_phase2_req); - data->pending_phase2_req = resp; - resp = NULL; - wpabuf_set(&msg, pos, left); - res = eap_fast_decrypt(sm, data, ret, req, &msg, - &resp); - } - } - - if (res == 1) { - wpabuf_free(resp); - return eap_peer_tls_build_ack(id, EAP_TYPE_FAST, - data->fast_version); - } - - return resp; -} - - -#if 0 /* FIX */ -static Boolean eap_fast_has_reauth_data(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - return tls_connection_established(sm->ssl_ctx, data->ssl.conn); -} - - -static void eap_fast_deinit_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - os_free(data->key_block_p); - data->key_block_p = NULL; - wpabuf_free(data->pending_phase2_req); - data->pending_phase2_req = NULL; -} - - -static void * eap_fast_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - if (eap_peer_tls_reauth_init(sm, &data->ssl)) { - os_free(data); - return NULL; - } - if (data->phase2_priv && data->phase2_method && - data->phase2_method->init_for_reauth) - data->phase2_method->init_for_reauth(sm, data->phase2_priv); - data->phase2_success = 0; - data->resuming = 1; - data->provisioning = 0; - data->anon_provisioning = 0; - data->simck_idx = 0; - return priv; -} -#endif - - -static int eap_fast_get_status(struct eap_sm *sm, void *priv, char *buf, - size_t buflen, int verbose) -{ - struct eap_fast_data *data = priv; - int len, ret; - - len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); - if (data->phase2_method) { - ret = os_snprintf(buf + len, buflen - len, - "EAP-FAST Phase2 method=%s\n", - data->phase2_method->name); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - } - return len; -} - - -static Boolean eap_fast_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - return data->success; -} - - -static u8 * eap_fast_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_fast_data *data = priv; - u8 *key; - - if (!data->success) - return NULL; - - key = os_malloc(EAP_FAST_KEY_LEN); - if (key == NULL) - return NULL; - - *len = EAP_FAST_KEY_LEN; - os_memcpy(key, data->key_data, EAP_FAST_KEY_LEN); - - return key; -} - - -static u8 * eap_fast_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_fast_data *data = priv; - u8 *key; - - if (!data->success) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_EMSK_LEN; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - - return key; -} - - -int eap_peer_fast_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_FAST, "FAST"); - if (eap == NULL) - return -1; - - eap->init = eap_fast_init; - eap->deinit = eap_fast_deinit; - eap->process = eap_fast_process; - eap->isKeyAvailable = eap_fast_isKeyAvailable; - eap->getKey = eap_fast_getKey; - eap->get_status = eap_fast_get_status; -#if 0 - eap->has_reauth_data = eap_fast_has_reauth_data; - eap->deinit_for_reauth = eap_fast_deinit_for_reauth; - eap->init_for_reauth = eap_fast_init_for_reauth; -#endif - eap->get_emsk = eap_fast_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_peer/eap_fast_pac.c b/contrib/hostapd/src/eap_peer/eap_fast_pac.c deleted file mode 100644 index 77893d6195..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_fast_pac.c +++ /dev/null @@ -1,921 +0,0 @@ -/* - * EAP peer method: EAP-FAST PAC file processing - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_config.h" -#include "eap_i.h" -#include "eap_fast_pac.h" - -/* TODO: encrypt PAC-Key in the PAC file */ - - -/* Text data format */ -static const char *pac_file_hdr = - "wpa_supplicant EAP-FAST PAC file - version 1"; - -/* - * Binary data format - * 4-octet magic value: 6A E4 92 0C - * 2-octet version (big endian) - * - * - * version=0: - * Sequence of PAC entries: - * 2-octet PAC-Type (big endian) - * 32-octet PAC-Key - * 2-octet PAC-Opaque length (big endian) - * PAC-Opaque data (length bytes) - * 2-octet PAC-Info length (big endian) - * PAC-Info data (length bytes) - */ - -#define EAP_FAST_PAC_BINARY_MAGIC 0x6ae4920c -#define EAP_FAST_PAC_BINARY_FORMAT_VERSION 0 - - -/** - * eap_fast_free_pac - Free PAC data - * @pac: Pointer to the PAC entry - * - * Note that the PAC entry must not be in a list since this function does not - * remove the list links. - */ -void eap_fast_free_pac(struct eap_fast_pac *pac) -{ - os_free(pac->pac_opaque); - os_free(pac->pac_info); - os_free(pac->a_id); - os_free(pac->i_id); - os_free(pac->a_id_info); - os_free(pac); -} - - -/** - * eap_fast_get_pac - Get a PAC entry based on A-ID - * @pac_root: Pointer to root of the PAC list - * @a_id: A-ID to search for - * @a_id_len: Length of A-ID - * @pac_type: PAC-Type to search for - * Returns: Pointer to the PAC entry, or %NULL if A-ID not found - */ -struct eap_fast_pac * eap_fast_get_pac(struct eap_fast_pac *pac_root, - const u8 *a_id, size_t a_id_len, - u16 pac_type) -{ - struct eap_fast_pac *pac = pac_root; - - while (pac) { - if (pac->pac_type == pac_type && pac->a_id_len == a_id_len && - os_memcmp(pac->a_id, a_id, a_id_len) == 0) { - return pac; - } - pac = pac->next; - } - return NULL; -} - - -static void eap_fast_remove_pac(struct eap_fast_pac **pac_root, - struct eap_fast_pac **pac_current, - const u8 *a_id, size_t a_id_len, u16 pac_type) -{ - struct eap_fast_pac *pac, *prev; - - pac = *pac_root; - prev = NULL; - - while (pac) { - if (pac->pac_type == pac_type && pac->a_id_len == a_id_len && - os_memcmp(pac->a_id, a_id, a_id_len) == 0) { - if (prev == NULL) - *pac_root = pac->next; - else - prev->next = pac->next; - if (*pac_current == pac) - *pac_current = NULL; - eap_fast_free_pac(pac); - break; - } - prev = pac; - pac = pac->next; - } -} - - -static int eap_fast_copy_buf(u8 **dst, size_t *dst_len, - const u8 *src, size_t src_len) -{ - if (src) { - *dst = os_malloc(src_len); - if (*dst == NULL) - return -1; - os_memcpy(*dst, src, src_len); - *dst_len = src_len; - } - return 0; -} - - -/** - * eap_fast_add_pac - Add a copy of a PAC entry to a list - * @pac_root: Pointer to PAC list root pointer - * @pac_current: Pointer to the current PAC pointer - * @entry: New entry to clone and add to the list - * Returns: 0 on success, -1 on failure - * - * This function makes a clone of the given PAC entry and adds this copied - * entry to the list (pac_root). If an old entry for the same A-ID is found, - * it will be removed from the PAC list and in this case, pac_current entry - * is set to %NULL if it was the removed entry. - */ -int eap_fast_add_pac(struct eap_fast_pac **pac_root, - struct eap_fast_pac **pac_current, - struct eap_fast_pac *entry) -{ - struct eap_fast_pac *pac; - - if (entry == NULL || entry->a_id == NULL) - return -1; - - /* Remove a possible old entry for the matching A-ID. */ - eap_fast_remove_pac(pac_root, pac_current, - entry->a_id, entry->a_id_len, entry->pac_type); - - /* Allocate a new entry and add it to the list of PACs. */ - pac = os_zalloc(sizeof(*pac)); - if (pac == NULL) - return -1; - - pac->pac_type = entry->pac_type; - os_memcpy(pac->pac_key, entry->pac_key, EAP_FAST_PAC_KEY_LEN); - if (eap_fast_copy_buf(&pac->pac_opaque, &pac->pac_opaque_len, - entry->pac_opaque, entry->pac_opaque_len) < 0 || - eap_fast_copy_buf(&pac->pac_info, &pac->pac_info_len, - entry->pac_info, entry->pac_info_len) < 0 || - eap_fast_copy_buf(&pac->a_id, &pac->a_id_len, - entry->a_id, entry->a_id_len) < 0 || - eap_fast_copy_buf(&pac->i_id, &pac->i_id_len, - entry->i_id, entry->i_id_len) < 0 || - eap_fast_copy_buf(&pac->a_id_info, &pac->a_id_info_len, - entry->a_id_info, entry->a_id_info_len) < 0) { - eap_fast_free_pac(pac); - return -1; - } - - pac->next = *pac_root; - *pac_root = pac; - - return 0; -} - - -struct eap_fast_read_ctx { - FILE *f; - const char *pos; - const char *end; - int line; - char *buf; - size_t buf_len; -}; - -static int eap_fast_read_line(struct eap_fast_read_ctx *rc, char **value) -{ - char *pos; - - rc->line++; - if (rc->f) { - if (fgets(rc->buf, rc->buf_len, rc->f) == NULL) - return -1; - } else { - const char *l_end; - size_t len; - if (rc->pos >= rc->end) - return -1; - l_end = rc->pos; - while (l_end < rc->end && *l_end != '\n') - l_end++; - len = l_end - rc->pos; - if (len >= rc->buf_len) - len = rc->buf_len - 1; - os_memcpy(rc->buf, rc->pos, len); - rc->buf[len] = '\0'; - rc->pos = l_end + 1; - } - - rc->buf[rc->buf_len - 1] = '\0'; - pos = rc->buf; - while (*pos != '\0') { - if (*pos == '\n' || *pos == '\r') { - *pos = '\0'; - break; - } - pos++; - } - - pos = os_strchr(rc->buf, '='); - if (pos) - *pos++ = '\0'; - *value = pos; - - return 0; -} - - -static u8 * eap_fast_parse_hex(const char *value, size_t *len) -{ - int hlen; - u8 *buf; - - if (value == NULL) - return NULL; - hlen = os_strlen(value); - if (hlen & 1) - return NULL; - *len = hlen / 2; - buf = os_malloc(*len); - if (buf == NULL) - return NULL; - if (hexstr2bin(value, buf, *len)) { - os_free(buf); - return NULL; - } - return buf; -} - - -static int eap_fast_init_pac_data(struct eap_sm *sm, const char *pac_file, - struct eap_fast_read_ctx *rc) -{ - os_memset(rc, 0, sizeof(*rc)); - - rc->buf_len = 2048; - rc->buf = os_malloc(rc->buf_len); - if (rc->buf == NULL) - return -1; - - if (os_strncmp(pac_file, "blob://", 7) == 0) { - const struct wpa_config_blob *blob; - blob = eap_get_config_blob(sm, pac_file + 7); - if (blob == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: No PAC blob '%s' - " - "assume no PAC entries have been " - "provisioned", pac_file + 7); - os_free(rc->buf); - return -1; - } - rc->pos = (char *) blob->data; - rc->end = (char *) blob->data + blob->len; - } else { - rc->f = fopen(pac_file, "rb"); - if (rc->f == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: No PAC file '%s' - " - "assume no PAC entries have been " - "provisioned", pac_file); - os_free(rc->buf); - return -1; - } - } - - return 0; -} - - -static void eap_fast_deinit_pac_data(struct eap_fast_read_ctx *rc) -{ - os_free(rc->buf); - if (rc->f) - fclose(rc->f); -} - - -static const char * eap_fast_parse_start(struct eap_fast_pac **pac) -{ - if (*pac) - return "START line without END"; - - *pac = os_zalloc(sizeof(struct eap_fast_pac)); - if (*pac == NULL) - return "No memory for PAC entry"; - (*pac)->pac_type = PAC_TYPE_TUNNEL_PAC; - return NULL; -} - - -static const char * eap_fast_parse_end(struct eap_fast_pac **pac_root, - struct eap_fast_pac **pac) -{ - if (*pac == NULL) - return "END line without START"; - if (*pac_root) { - struct eap_fast_pac *end = *pac_root; - while (end->next) - end = end->next; - end->next = *pac; - } else - *pac_root = *pac; - - *pac = NULL; - return NULL; -} - - -static const char * eap_fast_parse_pac_type(struct eap_fast_pac *pac, - char *pos) -{ - pac->pac_type = atoi(pos); - if (pac->pac_type != PAC_TYPE_TUNNEL_PAC && - pac->pac_type != PAC_TYPE_USER_AUTHORIZATION && - pac->pac_type != PAC_TYPE_MACHINE_AUTHENTICATION) - return "Unrecognized PAC-Type"; - - return NULL; -} - - -static const char * eap_fast_parse_pac_key(struct eap_fast_pac *pac, char *pos) -{ - u8 *key; - size_t key_len; - - key = eap_fast_parse_hex(pos, &key_len); - if (key == NULL || key_len != EAP_FAST_PAC_KEY_LEN) { - os_free(key); - return "Invalid PAC-Key"; - } - - os_memcpy(pac->pac_key, key, EAP_FAST_PAC_KEY_LEN); - os_free(key); - - return NULL; -} - - -static const char * eap_fast_parse_pac_opaque(struct eap_fast_pac *pac, - char *pos) -{ - os_free(pac->pac_opaque); - pac->pac_opaque = eap_fast_parse_hex(pos, &pac->pac_opaque_len); - if (pac->pac_opaque == NULL) - return "Invalid PAC-Opaque"; - return NULL; -} - - -static const char * eap_fast_parse_a_id(struct eap_fast_pac *pac, char *pos) -{ - os_free(pac->a_id); - pac->a_id = eap_fast_parse_hex(pos, &pac->a_id_len); - if (pac->a_id == NULL) - return "Invalid A-ID"; - return NULL; -} - - -static const char * eap_fast_parse_i_id(struct eap_fast_pac *pac, char *pos) -{ - os_free(pac->i_id); - pac->i_id = eap_fast_parse_hex(pos, &pac->i_id_len); - if (pac->i_id == NULL) - return "Invalid I-ID"; - return NULL; -} - - -static const char * eap_fast_parse_a_id_info(struct eap_fast_pac *pac, - char *pos) -{ - os_free(pac->a_id_info); - pac->a_id_info = eap_fast_parse_hex(pos, &pac->a_id_info_len); - if (pac->a_id_info == NULL) - return "Invalid A-ID-Info"; - return NULL; -} - - -/** - * eap_fast_load_pac - Load PAC entries (text format) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @pac_root: Pointer to root of the PAC list (to be filled) - * @pac_file: Name of the PAC file/blob to load - * Returns: 0 on success, -1 on failure - */ -int eap_fast_load_pac(struct eap_sm *sm, struct eap_fast_pac **pac_root, - const char *pac_file) -{ - struct eap_fast_read_ctx rc; - struct eap_fast_pac *pac = NULL; - int count = 0; - char *pos; - const char *err = NULL; - - if (pac_file == NULL) - return -1; - - if (eap_fast_init_pac_data(sm, pac_file, &rc) < 0) - return 0; - - if (eap_fast_read_line(&rc, &pos) < 0 || - os_strcmp(pac_file_hdr, rc.buf) != 0) - err = "Unrecognized header line"; - - while (!err && eap_fast_read_line(&rc, &pos) == 0) { - if (os_strcmp(rc.buf, "START") == 0) - err = eap_fast_parse_start(&pac); - else if (os_strcmp(rc.buf, "END") == 0) { - err = eap_fast_parse_end(pac_root, &pac); - count++; - } else if (!pac) - err = "Unexpected line outside START/END block"; - else if (os_strcmp(rc.buf, "PAC-Type") == 0) - err = eap_fast_parse_pac_type(pac, pos); - else if (os_strcmp(rc.buf, "PAC-Key") == 0) - err = eap_fast_parse_pac_key(pac, pos); - else if (os_strcmp(rc.buf, "PAC-Opaque") == 0) - err = eap_fast_parse_pac_opaque(pac, pos); - else if (os_strcmp(rc.buf, "A-ID") == 0) - err = eap_fast_parse_a_id(pac, pos); - else if (os_strcmp(rc.buf, "I-ID") == 0) - err = eap_fast_parse_i_id(pac, pos); - else if (os_strcmp(rc.buf, "A-ID-Info") == 0) - err = eap_fast_parse_a_id_info(pac, pos); - } - - if (pac) { - err = "PAC block not terminated with END"; - eap_fast_free_pac(pac); - } - - eap_fast_deinit_pac_data(&rc); - - if (err) { - wpa_printf(MSG_INFO, "EAP-FAST: %s in '%s:%d'", - err, pac_file, rc.line); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-FAST: Read %d PAC entries from '%s'", - count, pac_file); - - return 0; -} - - -static void eap_fast_write(char **buf, char **pos, size_t *buf_len, - const char *field, const u8 *data, - size_t len, int txt) -{ - size_t i, need; - int ret; - - if (data == NULL || *buf == NULL) - return; - - need = os_strlen(field) + len * 2 + 30; - if (txt) - need += os_strlen(field) + len + 20; - - if (*pos - *buf + need > *buf_len) { - char *nbuf = os_realloc(*buf, *buf_len + need); - if (nbuf == NULL) { - os_free(*buf); - *buf = NULL; - return; - } - *buf = nbuf; - *buf_len += need; - } - - ret = os_snprintf(*pos, *buf + *buf_len - *pos, "%s=", field); - if (ret < 0 || ret >= *buf + *buf_len - *pos) - return; - *pos += ret; - *pos += wpa_snprintf_hex(*pos, *buf + *buf_len - *pos, data, len); - ret = os_snprintf(*pos, *buf + *buf_len - *pos, "\n"); - if (ret < 0 || ret >= *buf + *buf_len - *pos) - return; - *pos += ret; - - if (txt) { - ret = os_snprintf(*pos, *buf + *buf_len - *pos, - "%s-txt=", field); - if (ret < 0 || ret >= *buf + *buf_len - *pos) - return; - *pos += ret; - for (i = 0; i < len; i++) { - ret = os_snprintf(*pos, *buf + *buf_len - *pos, - "%c", data[i]); - if (ret < 0 || ret >= *buf + *buf_len - *pos) - return; - *pos += ret; - } - ret = os_snprintf(*pos, *buf + *buf_len - *pos, "\n"); - if (ret < 0 || ret >= *buf + *buf_len - *pos) - return; - *pos += ret; - } -} - - -static int eap_fast_write_pac(struct eap_sm *sm, const char *pac_file, - char *buf, size_t len) -{ - if (os_strncmp(pac_file, "blob://", 7) == 0) { - struct wpa_config_blob *blob; - blob = os_zalloc(sizeof(*blob)); - if (blob == NULL) - return -1; - blob->data = (u8 *) buf; - blob->len = len; - buf = NULL; - blob->name = os_strdup(pac_file + 7); - if (blob->name == NULL) { - os_free(blob); - return -1; - } - eap_set_config_blob(sm, blob); - } else { - FILE *f; - f = fopen(pac_file, "wb"); - if (f == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to open PAC " - "file '%s' for writing", pac_file); - return -1; - } - if (fwrite(buf, 1, len, f) != len) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to write all " - "PACs into '%s'", pac_file); - fclose(f); - return -1; - } - os_free(buf); - fclose(f); - } - - return 0; -} - - -static int eap_fast_add_pac_data(struct eap_fast_pac *pac, char **buf, - char **pos, size_t *buf_len) -{ - int ret; - - ret = os_snprintf(*pos, *buf + *buf_len - *pos, - "START\nPAC-Type=%d\n", pac->pac_type); - if (ret < 0 || ret >= *buf + *buf_len - *pos) - return -1; - - *pos += ret; - eap_fast_write(buf, pos, buf_len, "PAC-Key", - pac->pac_key, EAP_FAST_PAC_KEY_LEN, 0); - eap_fast_write(buf, pos, buf_len, "PAC-Opaque", - pac->pac_opaque, pac->pac_opaque_len, 0); - eap_fast_write(buf, pos, buf_len, "PAC-Info", - pac->pac_info, pac->pac_info_len, 0); - eap_fast_write(buf, pos, buf_len, "A-ID", - pac->a_id, pac->a_id_len, 0); - eap_fast_write(buf, pos, buf_len, "I-ID", - pac->i_id, pac->i_id_len, 1); - eap_fast_write(buf, pos, buf_len, "A-ID-Info", - pac->a_id_info, pac->a_id_info_len, 1); - if (*buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: No memory for PAC " - "data"); - return -1; - } - ret = os_snprintf(*pos, *buf + *buf_len - *pos, "END\n"); - if (ret < 0 || ret >= *buf + *buf_len - *pos) - return -1; - *pos += ret; - - return 0; -} - - -/** - * eap_fast_save_pac - Save PAC entries (text format) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @pac_root: Root of the PAC list - * @pac_file: Name of the PAC file/blob - * Returns: 0 on success, -1 on failure - */ -int eap_fast_save_pac(struct eap_sm *sm, struct eap_fast_pac *pac_root, - const char *pac_file) -{ - struct eap_fast_pac *pac; - int ret, count = 0; - char *buf, *pos; - size_t buf_len; - - if (pac_file == NULL) - return -1; - - buf_len = 1024; - pos = buf = os_malloc(buf_len); - if (buf == NULL) - return -1; - - ret = os_snprintf(pos, buf + buf_len - pos, "%s\n", pac_file_hdr); - if (ret < 0 || ret >= buf + buf_len - pos) { - os_free(buf); - return -1; - } - pos += ret; - - pac = pac_root; - while (pac) { - if (eap_fast_add_pac_data(pac, &buf, &pos, &buf_len)) { - os_free(buf); - return -1; - } - count++; - pac = pac->next; - } - - if (eap_fast_write_pac(sm, pac_file, buf, pos - buf)) { - os_free(buf); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-FAST: Wrote %d PAC entries into '%s'", - count, pac_file); - - return 0; -} - - -/** - * eap_fast_pac_list_truncate - Truncate a PAC list to the given length - * @pac_root: Root of the PAC list - * @max_len: Maximum length of the list (>= 1) - * Returns: Number of PAC entries removed - */ -size_t eap_fast_pac_list_truncate(struct eap_fast_pac *pac_root, - size_t max_len) -{ - struct eap_fast_pac *pac, *prev; - size_t count; - - pac = pac_root; - prev = NULL; - count = 0; - - while (pac) { - count++; - if (count > max_len) - break; - prev = pac; - pac = pac->next; - } - - if (count <= max_len || prev == NULL) - return 0; - - count = 0; - prev->next = NULL; - - while (pac) { - prev = pac; - pac = pac->next; - eap_fast_free_pac(prev); - count++; - } - - return count; -} - - -static void eap_fast_pac_get_a_id(struct eap_fast_pac *pac) -{ - u8 *pos, *end; - u16 type, len; - - pos = pac->pac_info; - end = pos + pac->pac_info_len; - - while (pos + 4 < end) { - type = WPA_GET_BE16(pos); - pos += 2; - len = WPA_GET_BE16(pos); - pos += 2; - if (pos + len > end) - break; - - if (type == PAC_TYPE_A_ID) { - os_free(pac->a_id); - pac->a_id = os_malloc(len); - if (pac->a_id == NULL) - break; - os_memcpy(pac->a_id, pos, len); - pac->a_id_len = len; - } - - if (type == PAC_TYPE_A_ID_INFO) { - os_free(pac->a_id_info); - pac->a_id_info = os_malloc(len); - if (pac->a_id_info == NULL) - break; - os_memcpy(pac->a_id_info, pos, len); - pac->a_id_info_len = len; - } - - pos += len; - } -} - - -/** - * eap_fast_load_pac_bin - Load PAC entries (binary format) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @pac_root: Pointer to root of the PAC list (to be filled) - * @pac_file: Name of the PAC file/blob to load - * Returns: 0 on success, -1 on failure - */ -int eap_fast_load_pac_bin(struct eap_sm *sm, struct eap_fast_pac **pac_root, - const char *pac_file) -{ - const struct wpa_config_blob *blob = NULL; - u8 *buf, *end, *pos; - size_t len, count = 0; - struct eap_fast_pac *pac, *prev; - - *pac_root = NULL; - - if (pac_file == NULL) - return -1; - - if (os_strncmp(pac_file, "blob://", 7) == 0) { - blob = eap_get_config_blob(sm, pac_file + 7); - if (blob == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: No PAC blob '%s' - " - "assume no PAC entries have been " - "provisioned", pac_file + 7); - return 0; - } - buf = blob->data; - len = blob->len; - } else { - buf = (u8 *) os_readfile(pac_file, &len); - if (buf == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: No PAC file '%s' - " - "assume no PAC entries have been " - "provisioned", pac_file); - return 0; - } - } - - if (len == 0) { - if (blob == NULL) - os_free(buf); - return 0; - } - - if (len < 6 || WPA_GET_BE32(buf) != EAP_FAST_PAC_BINARY_MAGIC || - WPA_GET_BE16(buf + 4) != EAP_FAST_PAC_BINARY_FORMAT_VERSION) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid PAC file '%s' (bin)", - pac_file); - if (blob == NULL) - os_free(buf); - return -1; - } - - pac = prev = NULL; - pos = buf + 6; - end = buf + len; - while (pos < end) { - if (end - pos < 2 + 32 + 2 + 2) - goto parse_fail; - - pac = os_zalloc(sizeof(*pac)); - if (pac == NULL) - goto parse_fail; - - pac->pac_type = WPA_GET_BE16(pos); - pos += 2; - os_memcpy(pac->pac_key, pos, EAP_FAST_PAC_KEY_LEN); - pos += EAP_FAST_PAC_KEY_LEN; - pac->pac_opaque_len = WPA_GET_BE16(pos); - pos += 2; - if (pos + pac->pac_opaque_len + 2 > end) - goto parse_fail; - pac->pac_opaque = os_malloc(pac->pac_opaque_len); - if (pac->pac_opaque == NULL) - goto parse_fail; - os_memcpy(pac->pac_opaque, pos, pac->pac_opaque_len); - pos += pac->pac_opaque_len; - pac->pac_info_len = WPA_GET_BE16(pos); - pos += 2; - if (pos + pac->pac_info_len > end) - goto parse_fail; - pac->pac_info = os_malloc(pac->pac_info_len); - if (pac->pac_info == NULL) - goto parse_fail; - os_memcpy(pac->pac_info, pos, pac->pac_info_len); - pos += pac->pac_info_len; - eap_fast_pac_get_a_id(pac); - - count++; - if (prev) - prev->next = pac; - else - *pac_root = pac; - prev = pac; - } - - if (blob == NULL) - os_free(buf); - - wpa_printf(MSG_DEBUG, "EAP-FAST: Read %lu PAC entries from '%s' (bin)", - (unsigned long) count, pac_file); - - return 0; - -parse_fail: - wpa_printf(MSG_INFO, "EAP-FAST: Failed to parse PAC file '%s' (bin)", - pac_file); - if (blob == NULL) - os_free(buf); - if (pac) - eap_fast_free_pac(pac); - return -1; -} - - -/** - * eap_fast_save_pac_bin - Save PAC entries (binary format) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @pac_root: Root of the PAC list - * @pac_file: Name of the PAC file/blob - * Returns: 0 on success, -1 on failure - */ -int eap_fast_save_pac_bin(struct eap_sm *sm, struct eap_fast_pac *pac_root, - const char *pac_file) -{ - size_t len, count = 0; - struct eap_fast_pac *pac; - u8 *buf, *pos; - - len = 6; - pac = pac_root; - while (pac) { - if (pac->pac_opaque_len > 65535 || - pac->pac_info_len > 65535) - return -1; - len += 2 + EAP_FAST_PAC_KEY_LEN + 2 + pac->pac_opaque_len + - 2 + pac->pac_info_len; - pac = pac->next; - } - - buf = os_malloc(len); - if (buf == NULL) - return -1; - - pos = buf; - WPA_PUT_BE32(pos, EAP_FAST_PAC_BINARY_MAGIC); - pos += 4; - WPA_PUT_BE16(pos, EAP_FAST_PAC_BINARY_FORMAT_VERSION); - pos += 2; - - pac = pac_root; - while (pac) { - WPA_PUT_BE16(pos, pac->pac_type); - pos += 2; - os_memcpy(pos, pac->pac_key, EAP_FAST_PAC_KEY_LEN); - pos += EAP_FAST_PAC_KEY_LEN; - WPA_PUT_BE16(pos, pac->pac_opaque_len); - pos += 2; - os_memcpy(pos, pac->pac_opaque, pac->pac_opaque_len); - pos += pac->pac_opaque_len; - WPA_PUT_BE16(pos, pac->pac_info_len); - pos += 2; - os_memcpy(pos, pac->pac_info, pac->pac_info_len); - pos += pac->pac_info_len; - - pac = pac->next; - count++; - } - - if (eap_fast_write_pac(sm, pac_file, (char *) buf, len)) { - os_free(buf); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-FAST: Wrote %lu PAC entries into '%s' " - "(bin)", (unsigned long) count, pac_file); - - return 0; -} diff --git a/contrib/hostapd/src/eap_peer/eap_fast_pac.h b/contrib/hostapd/src/eap_peer/eap_fast_pac.h deleted file mode 100644 index 9483f96852..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_fast_pac.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * EAP peer method: EAP-FAST PAC file processing - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_FAST_PAC_H -#define EAP_FAST_PAC_H - -#include "eap_common/eap_fast_common.h" - -struct eap_fast_pac { - struct eap_fast_pac *next; - - u8 pac_key[EAP_FAST_PAC_KEY_LEN]; - u8 *pac_opaque; - size_t pac_opaque_len; - u8 *pac_info; - size_t pac_info_len; - u8 *a_id; - size_t a_id_len; - u8 *i_id; - size_t i_id_len; - u8 *a_id_info; - size_t a_id_info_len; - u16 pac_type; -}; - - -void eap_fast_free_pac(struct eap_fast_pac *pac); -struct eap_fast_pac * eap_fast_get_pac(struct eap_fast_pac *pac_root, - const u8 *a_id, size_t a_id_len, - u16 pac_type); -int eap_fast_add_pac(struct eap_fast_pac **pac_root, - struct eap_fast_pac **pac_current, - struct eap_fast_pac *entry); -int eap_fast_load_pac(struct eap_sm *sm, struct eap_fast_pac **pac_root, - const char *pac_file); -int eap_fast_save_pac(struct eap_sm *sm, struct eap_fast_pac *pac_root, - const char *pac_file); -size_t eap_fast_pac_list_truncate(struct eap_fast_pac *pac_root, - size_t max_len); -int eap_fast_load_pac_bin(struct eap_sm *sm, struct eap_fast_pac **pac_root, - const char *pac_file); -int eap_fast_save_pac_bin(struct eap_sm *sm, struct eap_fast_pac *pac_root, - const char *pac_file); - -#endif /* EAP_FAST_PAC_H */ diff --git a/contrib/hostapd/src/eap_peer/eap_gpsk.c b/contrib/hostapd/src/eap_peer/eap_gpsk.c deleted file mode 100644 index f6a1955baf..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_gpsk.c +++ /dev/null @@ -1,737 +0,0 @@ -/* - * EAP peer method: EAP-GPSK (RFC 5433) - * Copyright (c) 2006-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_peer/eap_i.h" -#include "eap_common/eap_gpsk_common.h" - -struct eap_gpsk_data { - enum { GPSK_1, GPSK_3, SUCCESS, FAILURE } state; - u8 rand_server[EAP_GPSK_RAND_LEN]; - u8 rand_peer[EAP_GPSK_RAND_LEN]; - u8 msk[EAP_MSK_LEN]; - u8 emsk[EAP_EMSK_LEN]; - u8 sk[EAP_GPSK_MAX_SK_LEN]; - size_t sk_len; - u8 pk[EAP_GPSK_MAX_PK_LEN]; - size_t pk_len; - u8 session_id; - int session_id_set; - u8 *id_peer; - size_t id_peer_len; - u8 *id_server; - size_t id_server_len; - int vendor; /* CSuite/Specifier */ - int specifier; /* CSuite/Specifier */ - u8 *psk; - size_t psk_len; -}; - - -static struct wpabuf * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data, - u8 identifier, - const u8 *csuite_list, - size_t csuite_list_len); -static struct wpabuf * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data, - u8 identifier); - - -#ifndef CONFIG_NO_STDOUT_DEBUG -static const char * eap_gpsk_state_txt(int state) -{ - switch (state) { - case GPSK_1: - return "GPSK-1"; - case GPSK_3: - return "GPSK-3"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "?"; - } -} -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - -static void eap_gpsk_state(struct eap_gpsk_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-GPSK: %s -> %s", - eap_gpsk_state_txt(data->state), - eap_gpsk_state_txt(state)); - data->state = state; -} - - -static void eap_gpsk_deinit(struct eap_sm *sm, void *priv); - - -static void * eap_gpsk_init(struct eap_sm *sm) -{ - struct eap_gpsk_data *data; - const u8 *identity, *password; - size_t identity_len, password_len; - - password = eap_get_config_password(sm, &password_len); - if (password == NULL) { - wpa_printf(MSG_INFO, "EAP-GPSK: No key (password) configured"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = GPSK_1; - - identity = eap_get_config_identity(sm, &identity_len); - if (identity) { - data->id_peer = os_malloc(identity_len); - if (data->id_peer == NULL) { - eap_gpsk_deinit(sm, data); - return NULL; - } - os_memcpy(data->id_peer, identity, identity_len); - data->id_peer_len = identity_len; - } - - data->psk = os_malloc(password_len); - if (data->psk == NULL) { - eap_gpsk_deinit(sm, data); - return NULL; - } - os_memcpy(data->psk, password, password_len); - data->psk_len = password_len; - - return data; -} - - -static void eap_gpsk_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_gpsk_data *data = priv; - os_free(data->id_server); - os_free(data->id_peer); - os_free(data->psk); - os_free(data); -} - - -static const u8 * eap_gpsk_process_id_server(struct eap_gpsk_data *data, - const u8 *pos, const u8 *end) -{ - u16 alen; - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet"); - return NULL; - } - alen = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < alen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server overflow"); - return NULL; - } - os_free(data->id_server); - data->id_server = os_malloc(alen); - if (data->id_server == NULL) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: No memory for ID_Server"); - return NULL; - } - os_memcpy(data->id_server, pos, alen); - data->id_server_len = alen; - wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server", - data->id_server, data->id_server_len); - pos += alen; - - return pos; -} - - -static const u8 * eap_gpsk_process_rand_server(struct eap_gpsk_data *data, - const u8 *pos, const u8 *end) -{ - if (pos == NULL) - return NULL; - - if (end - pos < EAP_GPSK_RAND_LEN) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server overflow"); - return NULL; - } - os_memcpy(data->rand_server, pos, EAP_GPSK_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server", - data->rand_server, EAP_GPSK_RAND_LEN); - pos += EAP_GPSK_RAND_LEN; - - return pos; -} - - -static int eap_gpsk_select_csuite(struct eap_sm *sm, - struct eap_gpsk_data *data, - const u8 *csuite_list, - size_t csuite_list_len) -{ - struct eap_gpsk_csuite *csuite; - int i, count; - - count = csuite_list_len / sizeof(struct eap_gpsk_csuite); - data->vendor = EAP_GPSK_VENDOR_IETF; - data->specifier = EAP_GPSK_CIPHER_RESERVED; - csuite = (struct eap_gpsk_csuite *) csuite_list; - for (i = 0; i < count; i++) { - int vendor, specifier; - vendor = WPA_GET_BE32(csuite->vendor); - specifier = WPA_GET_BE16(csuite->specifier); - wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite[%d]: %d:%d", - i, vendor, specifier); - if (data->vendor == EAP_GPSK_VENDOR_IETF && - data->specifier == EAP_GPSK_CIPHER_RESERVED && - eap_gpsk_supported_ciphersuite(vendor, specifier)) { - data->vendor = vendor; - data->specifier = specifier; - } - csuite++; - } - if (data->vendor == EAP_GPSK_VENDOR_IETF && - data->specifier == EAP_GPSK_CIPHER_RESERVED) { - wpa_msg(sm->msg_ctx, MSG_INFO, "EAP-GPSK: No supported " - "ciphersuite found"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-GPSK: Selected ciphersuite %d:%d", - data->vendor, data->specifier); - - return 0; -} - - -static const u8 * eap_gpsk_process_csuite_list(struct eap_sm *sm, - struct eap_gpsk_data *data, - const u8 **list, - size_t *list_len, - const u8 *pos, const u8 *end) -{ - if (pos == NULL) - return NULL; - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet"); - return NULL; - } - *list_len = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < (int) *list_len) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List overflow"); - return NULL; - } - if (*list_len == 0 || (*list_len % sizeof(struct eap_gpsk_csuite))) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid CSuite_List len %lu", - (unsigned long) *list_len); - return NULL; - } - *list = pos; - pos += *list_len; - - if (eap_gpsk_select_csuite(sm, data, *list, *list_len) < 0) - return NULL; - - return pos; -} - - -static struct wpabuf * eap_gpsk_process_gpsk_1(struct eap_sm *sm, - struct eap_gpsk_data *data, - struct eap_method_ret *ret, - const struct wpabuf *reqData, - const u8 *payload, - size_t payload_len) -{ - size_t csuite_list_len; - const u8 *csuite_list, *pos, *end; - struct wpabuf *resp; - - if (data->state != GPSK_1) { - ret->ignore = TRUE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-1"); - - end = payload + payload_len; - - pos = eap_gpsk_process_id_server(data, payload, end); - pos = eap_gpsk_process_rand_server(data, pos, end); - pos = eap_gpsk_process_csuite_list(sm, data, &csuite_list, - &csuite_list_len, pos, end); - if (pos == NULL) { - eap_gpsk_state(data, FAILURE); - return NULL; - } - - resp = eap_gpsk_send_gpsk_2(data, eap_get_id(reqData), - csuite_list, csuite_list_len); - if (resp == NULL) - return NULL; - - eap_gpsk_state(data, GPSK_3); - - return resp; -} - - -static struct wpabuf * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data, - u8 identifier, - const u8 *csuite_list, - size_t csuite_list_len) -{ - struct wpabuf *resp; - size_t len, miclen; - u8 *rpos, *start; - struct eap_gpsk_csuite *csuite; - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-2"); - - miclen = eap_gpsk_mic_len(data->vendor, data->specifier); - len = 1 + 2 + data->id_peer_len + 2 + data->id_server_len + - 2 * EAP_GPSK_RAND_LEN + 2 + csuite_list_len + - sizeof(struct eap_gpsk_csuite) + 2 + miclen; - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len, - EAP_CODE_RESPONSE, identifier); - if (resp == NULL) - return NULL; - - wpabuf_put_u8(resp, EAP_GPSK_OPCODE_GPSK_2); - start = wpabuf_put(resp, 0); - - wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer", - data->id_peer, data->id_peer_len); - wpabuf_put_be16(resp, data->id_peer_len); - wpabuf_put_data(resp, data->id_peer, data->id_peer_len); - - wpabuf_put_be16(resp, data->id_server_len); - wpabuf_put_data(resp, data->id_server, data->id_server_len); - - if (os_get_random(data->rand_peer, EAP_GPSK_RAND_LEN)) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to get random data " - "for RAND_Peer"); - eap_gpsk_state(data, FAILURE); - wpabuf_free(resp); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer", - data->rand_peer, EAP_GPSK_RAND_LEN); - wpabuf_put_data(resp, data->rand_peer, EAP_GPSK_RAND_LEN); - wpabuf_put_data(resp, data->rand_server, EAP_GPSK_RAND_LEN); - - wpabuf_put_be16(resp, csuite_list_len); - wpabuf_put_data(resp, csuite_list, csuite_list_len); - - csuite = wpabuf_put(resp, sizeof(*csuite)); - WPA_PUT_BE32(csuite->vendor, data->vendor); - WPA_PUT_BE16(csuite->specifier, data->specifier); - - if (eap_gpsk_derive_keys(data->psk, data->psk_len, - data->vendor, data->specifier, - data->rand_peer, data->rand_server, - data->id_peer, data->id_peer_len, - data->id_server, data->id_server_len, - data->msk, data->emsk, - data->sk, &data->sk_len, - data->pk, &data->pk_len) < 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys"); - eap_gpsk_state(data, FAILURE); - wpabuf_free(resp); - return NULL; - } - - /* No PD_Payload_1 */ - wpabuf_put_be16(resp, 0); - - rpos = wpabuf_put(resp, miclen); - if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, - data->specifier, start, rpos - start, rpos) < - 0) { - eap_gpsk_state(data, FAILURE); - wpabuf_free(resp); - return NULL; - } - - return resp; -} - - -static const u8 * eap_gpsk_validate_rand(struct eap_gpsk_data *data, - const u8 *pos, const u8 *end) -{ - if (end - pos < EAP_GPSK_RAND_LEN) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " - "RAND_Peer"); - return NULL; - } - if (os_memcmp(pos, data->rand_peer, EAP_GPSK_RAND_LEN) != 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-2 and " - "GPSK-3 did not match"); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-2", - data->rand_peer, EAP_GPSK_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-3", - pos, EAP_GPSK_RAND_LEN); - return NULL; - } - pos += EAP_GPSK_RAND_LEN; - - if (end - pos < EAP_GPSK_RAND_LEN) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " - "RAND_Server"); - return NULL; - } - if (os_memcmp(pos, data->rand_server, EAP_GPSK_RAND_LEN) != 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and " - "GPSK-3 did not match"); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1", - data->rand_server, EAP_GPSK_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-3", - pos, EAP_GPSK_RAND_LEN); - return NULL; - } - pos += EAP_GPSK_RAND_LEN; - - return pos; -} - - -static const u8 * eap_gpsk_validate_id_server(struct eap_gpsk_data *data, - const u8 *pos, const u8 *end) -{ - size_t len; - - if (pos == NULL) - return NULL; - - if (end - pos < (int) 2) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " - "length(ID_Server)"); - return NULL; - } - - len = WPA_GET_BE16(pos); - pos += 2; - - if (end - pos < (int) len) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " - "ID_Server"); - return NULL; - } - - if (len != data->id_server_len || - os_memcmp(pos, data->id_server, len) != 0) { - wpa_printf(MSG_INFO, "EAP-GPSK: ID_Server did not match with " - "the one used in GPSK-1"); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1", - data->id_server, data->id_server_len); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-3", - pos, len); - return NULL; - } - - pos += len; - - return pos; -} - - -static const u8 * eap_gpsk_validate_csuite(struct eap_gpsk_data *data, - const u8 *pos, const u8 *end) -{ - int vendor, specifier; - const struct eap_gpsk_csuite *csuite; - - if (pos == NULL) - return NULL; - - if (end - pos < (int) sizeof(*csuite)) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " - "CSuite_Sel"); - return NULL; - } - csuite = (const struct eap_gpsk_csuite *) pos; - vendor = WPA_GET_BE32(csuite->vendor); - specifier = WPA_GET_BE16(csuite->specifier); - pos += sizeof(*csuite); - if (vendor != data->vendor || specifier != data->specifier) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel (%d:%d) does not " - "match with the one sent in GPSK-2 (%d:%d)", - vendor, specifier, data->vendor, data->specifier); - return NULL; - } - - return pos; -} - - -static const u8 * eap_gpsk_validate_pd_payload_2(struct eap_gpsk_data *data, - const u8 *pos, const u8 *end) -{ - u16 alen; - - if (pos == NULL) - return NULL; - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " - "PD_Payload_2 length"); - return NULL; - } - alen = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < alen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " - "%d-octet PD_Payload_2", alen); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_2", pos, alen); - pos += alen; - - return pos; -} - - -static const u8 * eap_gpsk_validate_gpsk_3_mic(struct eap_gpsk_data *data, - const u8 *payload, - const u8 *pos, const u8 *end) -{ - size_t miclen; - u8 mic[EAP_GPSK_MAX_MIC_LEN]; - - if (pos == NULL) - return NULL; - - miclen = eap_gpsk_mic_len(data->vendor, data->specifier); - if (end - pos < (int) miclen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC " - "(left=%lu miclen=%lu)", - (unsigned long) (end - pos), - (unsigned long) miclen); - return NULL; - } - if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, - data->specifier, payload, pos - payload, mic) - < 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC"); - return NULL; - } - if (os_memcmp(mic, pos, miclen) != 0) { - wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-3"); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen); - return NULL; - } - pos += miclen; - - return pos; -} - - -static struct wpabuf * eap_gpsk_process_gpsk_3(struct eap_sm *sm, - struct eap_gpsk_data *data, - struct eap_method_ret *ret, - const struct wpabuf *reqData, - const u8 *payload, - size_t payload_len) -{ - struct wpabuf *resp; - const u8 *pos, *end; - - if (data->state != GPSK_3) { - ret->ignore = TRUE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-3"); - - end = payload + payload_len; - - pos = eap_gpsk_validate_rand(data, payload, end); - pos = eap_gpsk_validate_id_server(data, pos, end); - pos = eap_gpsk_validate_csuite(data, pos, end); - pos = eap_gpsk_validate_pd_payload_2(data, pos, end); - pos = eap_gpsk_validate_gpsk_3_mic(data, payload, pos, end); - - if (pos == NULL) { - eap_gpsk_state(data, FAILURE); - return NULL; - } - if (pos != end) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra " - "data in the end of GPSK-2", - (unsigned long) (end - pos)); - } - - resp = eap_gpsk_send_gpsk_4(data, eap_get_id(reqData)); - if (resp == NULL) - return NULL; - - eap_gpsk_state(data, SUCCESS); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - - return resp; -} - - -static struct wpabuf * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data, - u8 identifier) -{ - struct wpabuf *resp; - u8 *rpos, *start; - size_t mlen; - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-4"); - - mlen = eap_gpsk_mic_len(data->vendor, data->specifier); - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, 1 + 2 + mlen, - EAP_CODE_RESPONSE, identifier); - if (resp == NULL) - return NULL; - - wpabuf_put_u8(resp, EAP_GPSK_OPCODE_GPSK_4); - start = wpabuf_put(resp, 0); - - /* No PD_Payload_3 */ - wpabuf_put_be16(resp, 0); - - rpos = wpabuf_put(resp, mlen); - if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, - data->specifier, start, rpos - start, rpos) < - 0) { - eap_gpsk_state(data, FAILURE); - wpabuf_free(resp); - return NULL; - } - - return resp; -} - - -static struct wpabuf * eap_gpsk_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_gpsk_data *data = priv; - struct wpabuf *resp; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, reqData, &len); - if (pos == NULL || len < 1) { - ret->ignore = TRUE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode %d", *pos); - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; - - switch (*pos) { - case EAP_GPSK_OPCODE_GPSK_1: - resp = eap_gpsk_process_gpsk_1(sm, data, ret, reqData, - pos + 1, len - 1); - break; - case EAP_GPSK_OPCODE_GPSK_3: - resp = eap_gpsk_process_gpsk_3(sm, data, ret, reqData, - pos + 1, len - 1); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignoring message with " - "unknown opcode %d", *pos); - ret->ignore = TRUE; - return NULL; - } - - return resp; -} - - -static Boolean eap_gpsk_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_gpsk_data *data = priv; - return data->state == SUCCESS; -} - - -static u8 * eap_gpsk_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_gpsk_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->msk, EAP_MSK_LEN); - *len = EAP_MSK_LEN; - - return key; -} - - -static u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_gpsk_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - - return key; -} - - -int eap_peer_gpsk_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK"); - if (eap == NULL) - return -1; - - eap->init = eap_gpsk_init; - eap->deinit = eap_gpsk_deinit; - eap->process = eap_gpsk_process; - eap->isKeyAvailable = eap_gpsk_isKeyAvailable; - eap->getKey = eap_gpsk_getKey; - eap->get_emsk = eap_gpsk_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_peer/eap_gtc.c b/contrib/hostapd/src/eap_peer/eap_gtc.c deleted file mode 100644 index b2b554b447..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_gtc.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * EAP peer method: EAP-GTC (RFC 3748) - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" - - -struct eap_gtc_data { - int prefix; -}; - - -static void * eap_gtc_init(struct eap_sm *sm) -{ - struct eap_gtc_data *data; - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - if (sm->m && sm->m->vendor == EAP_VENDOR_IETF && - sm->m->method == EAP_TYPE_FAST) { - wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix " - "with challenge/response"); - data->prefix = 1; - } - return data; -} - - -static void eap_gtc_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_gtc_data *data = priv; - os_free(data); -} - - -static struct wpabuf * eap_gtc_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_gtc_data *data = priv; - struct wpabuf *resp; - const u8 *pos, *password, *identity; - size_t password_len, identity_len, len, plen; - int otp; - u8 id; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, reqData, &len); - if (pos == NULL) { - ret->ignore = TRUE; - return NULL; - } - id = eap_get_id(reqData); - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Request message", pos, len); - if (data->prefix && - (len < 10 || os_memcmp(pos, "CHALLENGE=", 10) != 0)) { - wpa_printf(MSG_DEBUG, "EAP-GTC: Challenge did not start with " - "expected prefix"); - - /* Send an empty response in order to allow tunneled - * acknowledgement of the failure. This will also cover the - * error case which seems to use EAP-MSCHAPv2 like error - * reporting with EAP-GTC inside EAP-FAST tunnel. */ - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, - 0, EAP_CODE_RESPONSE, id); - return resp; - } - - password = eap_get_config_otp(sm, &password_len); - if (password) - otp = 1; - else { - password = eap_get_config_password(sm, &password_len); - otp = 0; - } - - if (password == NULL) { - wpa_printf(MSG_INFO, "EAP-GTC: Password not configured"); - eap_sm_request_otp(sm, (const char *) pos, len); - ret->ignore = TRUE; - return NULL; - } - - ret->ignore = FALSE; - - ret->methodState = data->prefix ? METHOD_MAY_CONT : METHOD_DONE; - ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = FALSE; - - plen = password_len; - identity = eap_get_config_identity(sm, &identity_len); - if (identity == NULL) - return NULL; - if (data->prefix) - plen += 9 + identity_len + 1; - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, plen, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - if (data->prefix) { - wpabuf_put_data(resp, "RESPONSE=", 9); - wpabuf_put_data(resp, identity, identity_len); - wpabuf_put_u8(resp, '\0'); - } - wpabuf_put_data(resp, password, password_len); - wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response", - wpabuf_head_u8(resp) + sizeof(struct eap_hdr) + - 1, plen); - - if (otp) { - wpa_printf(MSG_DEBUG, "EAP-GTC: Forgetting used password"); - eap_clear_config_otp(sm); - } - - return resp; -} - - -int eap_peer_gtc_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC"); - if (eap == NULL) - return -1; - - eap->init = eap_gtc_init; - eap->deinit = eap_gtc_deinit; - eap->process = eap_gtc_process; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_peer/eap_i.h b/contrib/hostapd/src/eap_peer/eap_i.h deleted file mode 100644 index e7c826ee8f..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_i.h +++ /dev/null @@ -1,355 +0,0 @@ -/* - * EAP peer state machines internal structures (RFC 4137) - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_I_H -#define EAP_I_H - -#include "wpabuf.h" -#include "eap_peer/eap.h" -#include "eap_common/eap_common.h" - -/* RFC 4137 - EAP Peer state machine */ - -typedef enum { - DECISION_FAIL, DECISION_COND_SUCC, DECISION_UNCOND_SUCC -} EapDecision; - -typedef enum { - METHOD_NONE, METHOD_INIT, METHOD_CONT, METHOD_MAY_CONT, METHOD_DONE -} EapMethodState; - -/** - * struct eap_method_ret - EAP return values from struct eap_method::process() - * - * These structure contains OUT variables for the interface between peer state - * machine and methods (RFC 4137, Sect. 4.2). eapRespData will be returned as - * the return value of struct eap_method::process() so it is not included in - * this structure. - */ -struct eap_method_ret { - /** - * ignore - Whether method decided to drop the current packed (OUT) - */ - Boolean ignore; - - /** - * methodState - Method-specific state (IN/OUT) - */ - EapMethodState methodState; - - /** - * decision - Authentication decision (OUT) - */ - EapDecision decision; - - /** - * allowNotifications - Whether method allows notifications (OUT) - */ - Boolean allowNotifications; -}; - - -/** - * struct eap_method - EAP method interface - * This structure defines the EAP method interface. Each method will need to - * register its own EAP type, EAP name, and set of function pointers for method - * specific operations. This interface is based on section 4.4 of RFC 4137. - */ -struct eap_method { - /** - * vendor - EAP Vendor-ID (EAP_VENDOR_*) (0 = IETF) - */ - int vendor; - - /** - * method - EAP type number (EAP_TYPE_*) - */ - EapType method; - - /** - * name - Name of the method (e.g., "TLS") - */ - const char *name; - - /** - * init - Initialize an EAP method - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * Returns: Pointer to allocated private data, or %NULL on failure - * - * This function is used to initialize the EAP method explicitly - * instead of using METHOD_INIT state as specific in RFC 4137. The - * method is expected to initialize it method-specific state and return - * a pointer that will be used as the priv argument to other calls. - */ - void * (*init)(struct eap_sm *sm); - - /** - * deinit - Deinitialize an EAP method - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * - * Deinitialize the EAP method and free any allocated private data. - */ - void (*deinit)(struct eap_sm *sm, void *priv); - - /** - * process - Process an EAP request - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * @ret: Return values from EAP request validation and processing - * @reqData: EAP request to be processed (eapReqData) - * Returns: Pointer to allocated EAP response packet (eapRespData) - * - * This function is a combination of m.check(), m.process(), and - * m.buildResp() procedures defined in section 4.4 of RFC 4137 In other - * words, this function validates the incoming request, processes it, - * and build a response packet. m.check() and m.process() return values - * are returned through struct eap_method_ret *ret variable. Caller is - * responsible for freeing the returned EAP response packet. - */ - struct wpabuf * (*process)(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData); - - /** - * isKeyAvailable - Find out whether EAP method has keying material - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * Returns: %TRUE if key material (eapKeyData) is available - */ - Boolean (*isKeyAvailable)(struct eap_sm *sm, void *priv); - - /** - * getKey - Get EAP method specific keying material (eapKeyData) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * @len: Pointer to variable to store key length (eapKeyDataLen) - * Returns: Keying material (eapKeyData) or %NULL if not available - * - * This function can be used to get the keying material from the EAP - * method. The key may already be stored in the method-specific private - * data or this function may derive the key. - */ - u8 * (*getKey)(struct eap_sm *sm, void *priv, size_t *len); - - /** - * get_status - Get EAP method status - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * @buf: Buffer for status information - * @buflen: Maximum buffer length - * @verbose: Whether to include verbose status information - * Returns: Number of bytes written to buf - * - * Query EAP method for status information. This function fills in a - * text area with current status information from the EAP method. If - * the buffer (buf) is not large enough, status information will be - * truncated to fit the buffer. - */ - int (*get_status)(struct eap_sm *sm, void *priv, char *buf, - size_t buflen, int verbose); - - /** - * has_reauth_data - Whether method is ready for fast reauthentication - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * Returns: %TRUE or %FALSE based on whether fast reauthentication is - * possible - * - * This function is an optional handler that only EAP methods - * supporting fast re-authentication need to implement. - */ - Boolean (*has_reauth_data)(struct eap_sm *sm, void *priv); - - /** - * deinit_for_reauth - Release data that is not needed for fast re-auth - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * - * This function is an optional handler that only EAP methods - * supporting fast re-authentication need to implement. This is called - * when authentication has been completed and EAP state machine is - * requesting that enough state information is maintained for fast - * re-authentication - */ - void (*deinit_for_reauth)(struct eap_sm *sm, void *priv); - - /** - * init_for_reauth - Prepare for start of fast re-authentication - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * - * This function is an optional handler that only EAP methods - * supporting fast re-authentication need to implement. This is called - * when EAP authentication is started and EAP state machine is - * requesting fast re-authentication to be used. - */ - void * (*init_for_reauth)(struct eap_sm *sm, void *priv); - - /** - * get_identity - Get method specific identity for re-authentication - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * @len: Length of the returned identity - * Returns: Pointer to the method specific identity or %NULL if default - * identity is to be used - * - * This function is an optional handler that only EAP methods - * that use method specific identity need to implement. - */ - const u8 * (*get_identity)(struct eap_sm *sm, void *priv, size_t *len); - - /** - * free - Free EAP method data - * @method: Pointer to the method data registered with - * eap_peer_method_register(). - * - * This function will be called when the EAP method is being - * unregistered. If the EAP method allocated resources during - * registration (e.g., allocated struct eap_method), they should be - * freed in this function. No other method functions will be called - * after this call. If this function is not defined (i.e., function - * pointer is %NULL), a default handler is used to release the method - * data with free(method). This is suitable for most cases. - */ - void (*free)(struct eap_method *method); - -#define EAP_PEER_METHOD_INTERFACE_VERSION 1 - /** - * version - Version of the EAP peer method interface - * - * The EAP peer method implementation should set this variable to - * EAP_PEER_METHOD_INTERFACE_VERSION. This is used to verify that the - * EAP method is using supported API version when using dynamically - * loadable EAP methods. - */ - int version; - - /** - * next - Pointer to the next EAP method - * - * This variable is used internally in the EAP method registration code - * to create a linked list of registered EAP methods. - */ - struct eap_method *next; - -#ifdef CONFIG_DYNAMIC_EAP_METHODS - /** - * dl_handle - Handle for the dynamic library - * - * This variable is used internally in the EAP method registration code - * to store a handle for the dynamic library. If the method is linked - * in statically, this is %NULL. - */ - void *dl_handle; -#endif /* CONFIG_DYNAMIC_EAP_METHODS */ - - /** - * get_emsk - Get EAP method specific keying extended material (EMSK) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * @len: Pointer to a variable to store EMSK length - * Returns: EMSK or %NULL if not available - * - * This function can be used to get the extended keying material from - * the EAP method. The key may already be stored in the method-specific - * private data or this function may derive the key. - */ - u8 * (*get_emsk)(struct eap_sm *sm, void *priv, size_t *len); -}; - - -/** - * struct eap_sm - EAP state machine data - */ -struct eap_sm { - enum { - EAP_INITIALIZE, EAP_DISABLED, EAP_IDLE, EAP_RECEIVED, - EAP_GET_METHOD, EAP_METHOD, EAP_SEND_RESPONSE, EAP_DISCARD, - EAP_IDENTITY, EAP_NOTIFICATION, EAP_RETRANSMIT, EAP_SUCCESS, - EAP_FAILURE - } EAP_state; - /* Long-term local variables */ - EapType selectedMethod; - EapMethodState methodState; - int lastId; - struct wpabuf *lastRespData; - EapDecision decision; - /* Short-term local variables */ - Boolean rxReq; - Boolean rxSuccess; - Boolean rxFailure; - int reqId; - EapType reqMethod; - int reqVendor; - u32 reqVendorMethod; - Boolean ignore; - /* Constants */ - int ClientTimeout; - - /* Miscellaneous variables */ - Boolean allowNotifications; /* peer state machine <-> methods */ - struct wpabuf *eapRespData; /* peer to lower layer */ - Boolean eapKeyAvailable; /* peer to lower layer */ - u8 *eapKeyData; /* peer to lower layer */ - size_t eapKeyDataLen; /* peer to lower layer */ - const struct eap_method *m; /* selected EAP method */ - /* not defined in RFC 4137 */ - Boolean changed; - void *eapol_ctx; - struct eapol_callbacks *eapol_cb; - void *eap_method_priv; - int init_phase2; - int fast_reauth; - - Boolean rxResp /* LEAP only */; - Boolean leap_done; - Boolean peap_done; - u8 req_md5[16]; /* MD5() of the current EAP packet */ - u8 last_md5[16]; /* MD5() of the previously received EAP packet; used - * in duplicate request detection. */ - - void *msg_ctx; - void *scard_ctx; - void *ssl_ctx; - - unsigned int workaround; - - /* Optional challenges generated in Phase 1 (EAP-FAST) */ - u8 *peer_challenge, *auth_challenge; - - int num_rounds; - int force_disabled; - - struct wps_context *wps; - - int prev_failure; -}; - -const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len); -const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len); -const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash); -const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len); -const u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len); -void eap_clear_config_otp(struct eap_sm *sm); -const char * eap_get_config_phase1(struct eap_sm *sm); -const char * eap_get_config_phase2(struct eap_sm *sm); -struct eap_peer_config * eap_get_config(struct eap_sm *sm); -void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob); -const struct wpa_config_blob * -eap_get_config_blob(struct eap_sm *sm, const char *name); -void eap_notify_pending(struct eap_sm *sm); -int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method); - -#endif /* EAP_I_H */ diff --git a/contrib/hostapd/src/eap_peer/eap_ikev2.c b/contrib/hostapd/src/eap_peer/eap_ikev2.c deleted file mode 100644 index bb49a662d7..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_ikev2.c +++ /dev/null @@ -1,506 +0,0 @@ -/* - * EAP-IKEv2 peer (RFC 5106) - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "eap_common/eap_ikev2_common.h" -#include "ikev2.h" - - -struct eap_ikev2_data { - struct ikev2_responder_data ikev2; - enum { WAIT_START, PROC_MSG, WAIT_FRAG_ACK, DONE, FAIL } state; - struct wpabuf *in_buf; - struct wpabuf *out_buf; - size_t out_used; - size_t fragment_size; - int keys_ready; - u8 keymat[EAP_MSK_LEN + EAP_EMSK_LEN]; - int keymat_ok; -}; - - -static const char * eap_ikev2_state_txt(int state) -{ - switch (state) { - case WAIT_START: - return "WAIT_START"; - case PROC_MSG: - return "PROC_MSG"; - case WAIT_FRAG_ACK: - return "WAIT_FRAG_ACK"; - case DONE: - return "DONE"; - case FAIL: - return "FAIL"; - default: - return "?"; - } -} - - -static void eap_ikev2_state(struct eap_ikev2_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-IKEV2: %s -> %s", - eap_ikev2_state_txt(data->state), - eap_ikev2_state_txt(state)); - data->state = state; -} - - -static void * eap_ikev2_init(struct eap_sm *sm) -{ - struct eap_ikev2_data *data; - const u8 *identity, *password; - size_t identity_len, password_len; - - identity = eap_get_config_identity(sm, &identity_len); - if (identity == NULL) { - wpa_printf(MSG_INFO, "EAP-IKEV2: No identity available"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = WAIT_START; - data->fragment_size = IKEV2_FRAGMENT_SIZE; - data->ikev2.state = SA_INIT; - data->ikev2.peer_auth = PEER_AUTH_SECRET; - data->ikev2.key_pad = (u8 *) os_strdup("Key Pad for EAP-IKEv2"); - if (data->ikev2.key_pad == NULL) - goto failed; - data->ikev2.key_pad_len = 21; - data->ikev2.IDr = os_malloc(identity_len); - if (data->ikev2.IDr == NULL) - goto failed; - os_memcpy(data->ikev2.IDr, identity, identity_len); - data->ikev2.IDr_len = identity_len; - - password = eap_get_config_password(sm, &password_len); - if (password) { - data->ikev2.shared_secret = os_malloc(password_len); - if (data->ikev2.shared_secret == NULL) - goto failed; - os_memcpy(data->ikev2.shared_secret, password, password_len); - data->ikev2.shared_secret_len = password_len; - } - - return data; - -failed: - ikev2_responder_deinit(&data->ikev2); - os_free(data); - return NULL; -} - - -static void eap_ikev2_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_ikev2_data *data = priv; - wpabuf_free(data->in_buf); - wpabuf_free(data->out_buf); - ikev2_responder_deinit(&data->ikev2); - os_free(data); -} - - -static int eap_ikev2_peer_keymat(struct eap_ikev2_data *data) -{ - if (eap_ikev2_derive_keymat( - data->ikev2.proposal.prf, &data->ikev2.keys, - data->ikev2.i_nonce, data->ikev2.i_nonce_len, - data->ikev2.r_nonce, data->ikev2.r_nonce_len, - data->keymat) < 0) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to " - "derive key material"); - return -1; - } - data->keymat_ok = 1; - return 0; -} - - -static struct wpabuf * eap_ikev2_build_msg(struct eap_ikev2_data *data, - struct eap_method_ret *ret, u8 id) -{ - struct wpabuf *resp; - u8 flags; - size_t send_len, plen, icv_len = 0; - - ret->ignore = FALSE; - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Generating Response"); - ret->allowNotifications = TRUE; - - flags = 0; - send_len = wpabuf_len(data->out_buf) - data->out_used; - if (1 + send_len > data->fragment_size) { - send_len = data->fragment_size - 1; - flags |= IKEV2_FLAGS_MORE_FRAGMENTS; - if (data->out_used == 0) { - flags |= IKEV2_FLAGS_LENGTH_INCLUDED; - send_len -= 4; - } - } -#ifdef CCNS_PL - /* Some issues figuring out the length of the message if Message Length - * field not included?! */ - if (!(flags & IKEV2_FLAGS_LENGTH_INCLUDED)) - flags |= IKEV2_FLAGS_LENGTH_INCLUDED; -#endif /* CCNS_PL */ - - plen = 1 + send_len; - if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) - plen += 4; - if (data->keys_ready) { - const struct ikev2_integ_alg *integ; - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Add Integrity Checksum " - "Data"); - flags |= IKEV2_FLAGS_ICV_INCLUDED; - integ = ikev2_get_integ(data->ikev2.proposal.integ); - if (integ == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG " - "transform / cannot generate ICV"); - return NULL; - } - icv_len = integ->hash_len; - - plen += icv_len; - } - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, plen, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - wpabuf_put_u8(resp, flags); /* Flags */ - if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) - wpabuf_put_be32(resp, wpabuf_len(data->out_buf)); - - wpabuf_put_data(resp, wpabuf_head_u8(data->out_buf) + data->out_used, - send_len); - data->out_used += send_len; - - if (flags & IKEV2_FLAGS_ICV_INCLUDED) { - const u8 *msg = wpabuf_head(resp); - size_t len = wpabuf_len(resp); - ikev2_integ_hash(data->ikev2.proposal.integ, - data->ikev2.keys.SK_ar, - data->ikev2.keys.SK_integ_len, - msg, len, wpabuf_put(resp, icv_len)); - } - - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - - if (data->out_used == wpabuf_len(data->out_buf)) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes " - "(message sent completely)", - (unsigned long) send_len); - wpabuf_free(data->out_buf); - data->out_buf = NULL; - data->out_used = 0; - switch (data->ikev2.state) { - case SA_AUTH: - /* SA_INIT was sent out, so message have to be - * integrity protected from now on. */ - data->keys_ready = 1; - break; - case IKEV2_DONE: - ret->methodState = METHOD_DONE; - if (data->state == FAIL) - break; - ret->decision = DECISION_COND_SUCC; - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Authentication " - "completed successfully"); - if (eap_ikev2_peer_keymat(data)) - break; - eap_ikev2_state(data, DONE); - break; - case IKEV2_FAILED: - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Authentication " - "failed"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - break; - default: - break; - } - } else { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes " - "(%lu more to send)", (unsigned long) send_len, - (unsigned long) wpabuf_len(data->out_buf) - - data->out_used); - eap_ikev2_state(data, WAIT_FRAG_ACK); - } - - return resp; -} - - -static int eap_ikev2_process_icv(struct eap_ikev2_data *data, - const struct wpabuf *reqData, - u8 flags, const u8 *pos, const u8 **end) -{ - if (flags & IKEV2_FLAGS_ICV_INCLUDED) { - int icv_len = eap_ikev2_validate_icv( - data->ikev2.proposal.integ, &data->ikev2.keys, 1, - reqData, pos, *end); - if (icv_len < 0) - return -1; - /* Hide Integrity Checksum Data from further processing */ - *end -= icv_len; - } else if (data->keys_ready) { - wpa_printf(MSG_INFO, "EAP-IKEV2: The message should have " - "included integrity checksum"); - return -1; - } - - return 0; -} - - -static int eap_ikev2_process_cont(struct eap_ikev2_data *data, - const u8 *buf, size_t len) -{ - /* Process continuation of a pending message */ - if (len > wpabuf_tailroom(data->in_buf)) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment overflow"); - eap_ikev2_state(data, FAIL); - return -1; - } - - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received %lu bytes, waiting " - "for %lu bytes more", (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - - return 0; -} - - -static struct wpabuf * eap_ikev2_process_fragment(struct eap_ikev2_data *data, - struct eap_method_ret *ret, - u8 id, u8 flags, - u32 message_length, - const u8 *buf, size_t len) -{ - /* Process a fragment that is not the last one of the message */ - if (data->in_buf == NULL && !(flags & IKEV2_FLAGS_LENGTH_INCLUDED)) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: No Message Length field in " - "a fragmented packet"); - ret->ignore = TRUE; - return NULL; - } - - if (data->in_buf == NULL) { - /* First fragment of the message */ - data->in_buf = wpabuf_alloc(message_length); - if (data->in_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: No memory for " - "message"); - ret->ignore = TRUE; - return NULL; - } - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received %lu bytes in first " - "fragment, waiting for %lu bytes more", - (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - } - - return eap_ikev2_build_frag_ack(id, EAP_CODE_RESPONSE); -} - - -static struct wpabuf * eap_ikev2_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_ikev2_data *data = priv; - const u8 *start, *pos, *end; - size_t len; - u8 flags, id; - u32 message_length = 0; - struct wpabuf tmpbuf; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, reqData, &len); - if (pos == NULL) { - ret->ignore = TRUE; - return NULL; - } - - id = eap_get_id(reqData); - - start = pos; - end = start + len; - - if (len == 0) - flags = 0; /* fragment ack */ - else - flags = *pos++; - - if (eap_ikev2_process_icv(data, reqData, flags, pos, &end) < 0) { - ret->ignore = TRUE; - return NULL; - } - - if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) { - if (end - pos < 4) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Message underflow"); - ret->ignore = TRUE; - return NULL; - } - message_length = WPA_GET_BE32(pos); - pos += 4; - - if (message_length < (u32) (end - pos)) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Invalid Message " - "Length (%d; %ld remaining in this msg)", - message_length, (long) (end - pos)); - ret->ignore = TRUE; - return NULL; - } - } - - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received packet: Flags 0x%x " - "Message Length %u", flags, message_length); - - if (data->state == WAIT_FRAG_ACK) { -#ifdef CCNS_PL - if (len > 1) /* Empty Flags field included in ACK */ -#else /* CCNS_PL */ - if (len != 0) -#endif /* CCNS_PL */ - { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected payload " - "in WAIT_FRAG_ACK state"); - ret->ignore = TRUE; - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment acknowledged"); - eap_ikev2_state(data, PROC_MSG); - return eap_ikev2_build_msg(data, ret, id); - } - - if (data->in_buf && eap_ikev2_process_cont(data, pos, end - pos) < 0) { - ret->ignore = TRUE; - return NULL; - } - - if (flags & IKEV2_FLAGS_MORE_FRAGMENTS) { - return eap_ikev2_process_fragment(data, ret, id, flags, - message_length, pos, - end - pos); - } - - if (data->in_buf == NULL) { - /* Wrap unfragmented messages as wpabuf without extra copy */ - wpabuf_set(&tmpbuf, pos, end - pos); - data->in_buf = &tmpbuf; - } - - if (ikev2_responder_process(&data->ikev2, data->in_buf) < 0) { - if (data->in_buf == &tmpbuf) - data->in_buf = NULL; - eap_ikev2_state(data, FAIL); - return NULL; - } - - if (data->in_buf != &tmpbuf) - wpabuf_free(data->in_buf); - data->in_buf = NULL; - - if (data->out_buf == NULL) { - data->out_buf = ikev2_responder_build(&data->ikev2); - if (data->out_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to generate " - "IKEv2 message"); - return NULL; - } - data->out_used = 0; - } - - eap_ikev2_state(data, PROC_MSG); - return eap_ikev2_build_msg(data, ret, id); -} - - -static Boolean eap_ikev2_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_ikev2_data *data = priv; - return data->state == DONE && data->keymat_ok; -} - - -static u8 * eap_ikev2_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_ikev2_data *data = priv; - u8 *key; - - if (data->state != DONE || !data->keymat_ok) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key) { - os_memcpy(key, data->keymat, EAP_MSK_LEN); - *len = EAP_MSK_LEN; - } - - return key; -} - - -static u8 * eap_ikev2_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_ikev2_data *data = priv; - u8 *key; - - if (data->state != DONE || !data->keymat_ok) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key) { - os_memcpy(key, data->keymat + EAP_MSK_LEN, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - } - - return key; -} - - -int eap_peer_ikev2_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_IKEV2, - "IKEV2"); - if (eap == NULL) - return -1; - - eap->init = eap_ikev2_init; - eap->deinit = eap_ikev2_deinit; - eap->process = eap_ikev2_process; - eap->isKeyAvailable = eap_ikev2_isKeyAvailable; - eap->getKey = eap_ikev2_getKey; - eap->get_emsk = eap_ikev2_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_peer/eap_leap.c b/contrib/hostapd/src/eap_peer/eap_leap.c deleted file mode 100644 index 01c1f160ab..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_leap.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - * EAP peer method: LEAP - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "ms_funcs.h" -#include "crypto.h" - -#define LEAP_VERSION 1 -#define LEAP_CHALLENGE_LEN 8 -#define LEAP_RESPONSE_LEN 24 -#define LEAP_KEY_LEN 16 - - -struct eap_leap_data { - enum { - LEAP_WAIT_CHALLENGE, - LEAP_WAIT_SUCCESS, - LEAP_WAIT_RESPONSE, - LEAP_DONE - } state; - - u8 peer_challenge[LEAP_CHALLENGE_LEN]; - u8 peer_response[LEAP_RESPONSE_LEN]; - - u8 ap_challenge[LEAP_CHALLENGE_LEN]; - u8 ap_response[LEAP_RESPONSE_LEN]; -}; - - -static void * eap_leap_init(struct eap_sm *sm) -{ - struct eap_leap_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = LEAP_WAIT_CHALLENGE; - - sm->leap_done = FALSE; - return data; -} - - -static void eap_leap_deinit(struct eap_sm *sm, void *priv) -{ - os_free(priv); -} - - -static struct wpabuf * eap_leap_process_request(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_leap_data *data = priv; - struct wpabuf *resp; - const u8 *pos, *challenge, *identity, *password; - u8 challenge_len, *rpos; - size_t identity_len, password_len, len; - int pwhash; - - wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Request"); - - identity = eap_get_config_identity(sm, &identity_len); - password = eap_get_config_password2(sm, &password_len, &pwhash); - if (identity == NULL || password == NULL) - return NULL; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_LEAP, reqData, &len); - if (pos == NULL || len < 3) { - wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Request frame"); - ret->ignore = TRUE; - return NULL; - } - - if (*pos != LEAP_VERSION) { - wpa_printf(MSG_WARNING, "EAP-LEAP: Unsupported LEAP version " - "%d", *pos); - ret->ignore = TRUE; - return NULL; - } - pos++; - - pos++; /* skip unused byte */ - - challenge_len = *pos++; - if (challenge_len != LEAP_CHALLENGE_LEN || challenge_len > len - 3) { - wpa_printf(MSG_INFO, "EAP-LEAP: Invalid challenge " - "(challenge_len=%d reqDataLen=%lu)", - challenge_len, (unsigned long) wpabuf_len(reqData)); - ret->ignore = TRUE; - return NULL; - } - challenge = pos; - os_memcpy(data->peer_challenge, challenge, LEAP_CHALLENGE_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Challenge from AP", - challenge, LEAP_CHALLENGE_LEN); - - wpa_printf(MSG_DEBUG, "EAP-LEAP: Generating Challenge Response"); - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_LEAP, - 3 + LEAP_RESPONSE_LEN + identity_len, - EAP_CODE_RESPONSE, eap_get_id(reqData)); - if (resp == NULL) - return NULL; - wpabuf_put_u8(resp, LEAP_VERSION); - 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); - os_memcpy(data->peer_response, rpos, LEAP_RESPONSE_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Response", - rpos, LEAP_RESPONSE_LEN); - wpabuf_put_data(resp, identity, identity_len); - - data->state = LEAP_WAIT_SUCCESS; - - return resp; -} - - -static struct wpabuf * eap_leap_process_success(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_leap_data *data = priv; - struct wpabuf *resp; - u8 *pos; - const u8 *identity; - size_t identity_len; - - wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Success"); - - identity = eap_get_config_identity(sm, &identity_len); - if (identity == NULL) - return NULL; - - if (data->state != LEAP_WAIT_SUCCESS) { - wpa_printf(MSG_INFO, "EAP-LEAP: EAP-Success received in " - "unexpected state (%d) - ignored", data->state); - ret->ignore = TRUE; - return NULL; - } - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_LEAP, - 3 + LEAP_CHALLENGE_LEN + identity_len, - EAP_CODE_REQUEST, eap_get_id(reqData)); - if (resp == NULL) - return NULL; - wpabuf_put_u8(resp, LEAP_VERSION); - wpabuf_put_u8(resp, 0); /* unused */ - wpabuf_put_u8(resp, LEAP_CHALLENGE_LEN); - pos = wpabuf_put(resp, LEAP_CHALLENGE_LEN); - if (os_get_random(pos, LEAP_CHALLENGE_LEN)) { - wpa_printf(MSG_WARNING, "EAP-LEAP: Failed to read random data " - "for challenge"); - wpabuf_free(resp); - ret->ignore = TRUE; - return NULL; - } - os_memcpy(data->ap_challenge, pos, LEAP_CHALLENGE_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Challenge to AP/AS", pos, - LEAP_CHALLENGE_LEN); - wpabuf_put_data(resp, identity, identity_len); - - data->state = LEAP_WAIT_RESPONSE; - - return resp; -} - - -static struct wpabuf * eap_leap_process_response(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_leap_data *data = priv; - const u8 *pos, *password; - u8 response_len, pw_hash[16], pw_hash_hash[16], - expected[LEAP_RESPONSE_LEN]; - size_t password_len, len; - int pwhash; - - wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Response"); - - password = eap_get_config_password2(sm, &password_len, &pwhash); - if (password == NULL) - return NULL; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_LEAP, reqData, &len); - if (pos == NULL || len < 3) { - wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Response frame"); - ret->ignore = TRUE; - return NULL; - } - - if (*pos != LEAP_VERSION) { - wpa_printf(MSG_WARNING, "EAP-LEAP: Unsupported LEAP version " - "%d", *pos); - ret->ignore = TRUE; - return NULL; - } - pos++; - - pos++; /* skip unused byte */ - - response_len = *pos++; - if (response_len != LEAP_RESPONSE_LEN || response_len > len - 3) { - wpa_printf(MSG_INFO, "EAP-LEAP: Invalid response " - "(response_len=%d reqDataLen=%lu)", - response_len, (unsigned long) wpabuf_len(reqData)); - ret->ignore = TRUE; - return NULL; - } - - wpa_hexdump(MSG_DEBUG, "EAP-LEAP: Response from AP", - pos, LEAP_RESPONSE_LEN); - os_memcpy(data->ap_response, pos, LEAP_RESPONSE_LEN); - - if (pwhash) { - hash_nt_password_hash(password, pw_hash_hash); - } else { - nt_password_hash(password, password_len, pw_hash); - hash_nt_password_hash(pw_hash, pw_hash_hash); - } - challenge_response(data->ap_challenge, pw_hash_hash, expected); - - ret->methodState = METHOD_DONE; - ret->allowNotifications = FALSE; - - if (os_memcmp(pos, expected, LEAP_RESPONSE_LEN) != 0) { - wpa_printf(MSG_WARNING, "EAP-LEAP: AP sent an invalid " - "response - authentication failed"); - wpa_hexdump(MSG_DEBUG, "EAP-LEAP: Expected response from AP", - expected, LEAP_RESPONSE_LEN); - ret->decision = DECISION_FAIL; - return NULL; - } - - ret->decision = DECISION_UNCOND_SUCC; - - /* LEAP is somewhat odd method since it sends EAP-Success in the middle - * of the authentication. Use special variable to transit EAP state - * machine to SUCCESS state. */ - sm->leap_done = TRUE; - data->state = LEAP_DONE; - - /* No more authentication messages expected; AP will send EAPOL-Key - * frames if encryption is enabled. */ - return NULL; -} - - -static struct wpabuf * eap_leap_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - const struct eap_hdr *eap; - size_t password_len; - const u8 *password; - - password = eap_get_config_password(sm, &password_len); - if (password == NULL) { - wpa_printf(MSG_INFO, "EAP-LEAP: Password not configured"); - eap_sm_request_password(sm); - ret->ignore = TRUE; - return NULL; - } - - /* - * LEAP needs to be able to handle EAP-Success frame which does not - * include Type field. Consequently, eap_hdr_validate() cannot be used - * here. This validation will be done separately for EAP-Request and - * EAP-Response frames. - */ - eap = wpabuf_head(reqData); - if (wpabuf_len(reqData) < sizeof(*eap) || - be_to_host16(eap->length) > wpabuf_len(reqData)) { - wpa_printf(MSG_INFO, "EAP-LEAP: Invalid frame"); - ret->ignore = TRUE; - return NULL; - } - - ret->ignore = FALSE; - ret->allowNotifications = TRUE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - - sm->leap_done = FALSE; - - switch (eap->code) { - case EAP_CODE_REQUEST: - return eap_leap_process_request(sm, priv, ret, reqData); - case EAP_CODE_SUCCESS: - return eap_leap_process_success(sm, priv, ret, reqData); - case EAP_CODE_RESPONSE: - return eap_leap_process_response(sm, priv, ret, reqData); - default: - wpa_printf(MSG_INFO, "EAP-LEAP: Unexpected EAP code (%d) - " - "ignored", eap->code); - ret->ignore = TRUE; - return NULL; - } -} - - -static Boolean eap_leap_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_leap_data *data = priv; - return data->state == LEAP_DONE; -} - - -static u8 * eap_leap_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_leap_data *data = priv; - u8 *key, pw_hash_hash[16], pw_hash[16]; - const u8 *addr[5], *password; - size_t elen[5], password_len; - int pwhash; - - if (data->state != LEAP_DONE) - return NULL; - - password = eap_get_config_password2(sm, &password_len, &pwhash); - if (password == NULL) - return NULL; - - key = os_malloc(LEAP_KEY_LEN); - if (key == NULL) - return NULL; - - if (pwhash) - hash_nt_password_hash(password, pw_hash_hash); - else { - nt_password_hash(password, password_len, pw_hash); - hash_nt_password_hash(pw_hash, pw_hash_hash); - } - wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: pw_hash_hash", - pw_hash_hash, 16); - wpa_hexdump(MSG_DEBUG, "EAP-LEAP: peer_challenge", - data->peer_challenge, LEAP_CHALLENGE_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-LEAP: peer_response", - data->peer_response, LEAP_RESPONSE_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-LEAP: ap_challenge", - data->ap_challenge, LEAP_CHALLENGE_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-LEAP: ap_response", - data->ap_response, LEAP_RESPONSE_LEN); - - addr[0] = pw_hash_hash; - elen[0] = 16; - addr[1] = data->ap_challenge; - elen[1] = LEAP_CHALLENGE_LEN; - addr[2] = data->ap_response; - elen[2] = LEAP_RESPONSE_LEN; - addr[3] = data->peer_challenge; - elen[3] = LEAP_CHALLENGE_LEN; - addr[4] = data->peer_response; - elen[4] = LEAP_RESPONSE_LEN; - md5_vector(5, addr, elen, key); - wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: master key", key, LEAP_KEY_LEN); - *len = LEAP_KEY_LEN; - - return key; -} - - -int eap_peer_leap_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_LEAP, "LEAP"); - if (eap == NULL) - return -1; - - eap->init = eap_leap_init; - eap->deinit = eap_leap_deinit; - eap->process = eap_leap_process; - eap->isKeyAvailable = eap_leap_isKeyAvailable; - eap->getKey = eap_leap_getKey; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_peer/eap_md5.c b/contrib/hostapd/src/eap_peer/eap_md5.c deleted file mode 100644 index 7961143a00..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_md5.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * EAP peer method: EAP-MD5 (RFC 3748 and RFC 1994) - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "eap_common/chap.h" - - -static void * eap_md5_init(struct eap_sm *sm) -{ - /* No need for private data. However, must return non-NULL to indicate - * success. */ - return (void *) 1; -} - - -static void eap_md5_deinit(struct eap_sm *sm, void *priv) -{ -} - - -static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct wpabuf *resp; - const u8 *pos, *challenge, *password; - u8 *rpos, id; - size_t len, challenge_len, password_len; - - password = eap_get_config_password(sm, &password_len); - if (password == NULL) { - wpa_printf(MSG_INFO, "EAP-MD5: Password not configured"); - eap_sm_request_password(sm); - ret->ignore = TRUE; - return NULL; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, reqData, &len); - if (pos == NULL || len == 0) { - wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame (pos=%p len=%lu)", - pos, (unsigned long) len); - ret->ignore = TRUE; - return NULL; - } - - /* - * CHAP Challenge: - * Value-Size (1 octet) | Value(Challenge) | Name(optional) - */ - challenge_len = *pos++; - if (challenge_len == 0 || challenge_len > len - 1) { - wpa_printf(MSG_INFO, "EAP-MD5: Invalid challenge " - "(challenge_len=%lu len=%lu)", - (unsigned long) challenge_len, (unsigned long) len); - ret->ignore = TRUE; - return NULL; - } - ret->ignore = FALSE; - challenge = pos; - wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge", - challenge, challenge_len); - - wpa_printf(MSG_DEBUG, "EAP-MD5: Generating Challenge Response"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = TRUE; - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, 1 + CHAP_MD5_LEN, - EAP_CODE_RESPONSE, eap_get_id(reqData)); - if (resp == NULL) - return NULL; - - /* - * CHAP Response: - * Value-Size (1 octet) | Value(Response) | Name(optional) - */ - wpabuf_put_u8(resp, CHAP_MD5_LEN); - - id = eap_get_id(resp); - rpos = wpabuf_put(resp, CHAP_MD5_LEN); - chap_md5(id, password, password_len, challenge, challenge_len, rpos); - wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", rpos, CHAP_MD5_LEN); - - return resp; -} - - -int eap_peer_md5_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_MD5, "MD5"); - if (eap == NULL) - return -1; - - eap->init = eap_md5_init; - eap->deinit = eap_md5_deinit; - eap->process = eap_md5_process; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_peer/eap_methods.c b/contrib/hostapd/src/eap_peer/eap_methods.c deleted file mode 100644 index 2374e5e422..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_methods.c +++ /dev/null @@ -1,528 +0,0 @@ -/* - * EAP peer: Method registration - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#ifdef CONFIG_DYNAMIC_EAP_METHODS -#include -#endif /* CONFIG_DYNAMIC_EAP_METHODS */ - -#include "common.h" -#include "eap_i.h" -#include "eap_methods.h" - - -static struct eap_method *eap_methods = NULL; - - -/** - * eap_peer_get_eap_method - Get EAP method based on type number - * @vendor: EAP Vendor-Id (0 = IETF) - * @method: EAP type number - * Returns: Pointer to EAP method or %NULL if not found - */ -const struct eap_method * eap_peer_get_eap_method(int vendor, EapType method) -{ - struct eap_method *m; - for (m = eap_methods; m; m = m->next) { - if (m->vendor == vendor && m->method == method) - return m; - } - return NULL; -} - - -/** - * eap_peer_get_type - Get EAP type for the given EAP method name - * @name: EAP method name, e.g., TLS - * @vendor: Buffer for returning EAP Vendor-Id - * Returns: EAP method type or %EAP_TYPE_NONE if not found - * - * This function maps EAP type names into EAP type numbers based on the list of - * EAP methods included in the build. - */ -EapType eap_peer_get_type(const char *name, int *vendor) -{ - struct eap_method *m; - for (m = eap_methods; m; m = m->next) { - if (os_strcmp(m->name, name) == 0) { - *vendor = m->vendor; - return m->method; - } - } - *vendor = EAP_VENDOR_IETF; - return EAP_TYPE_NONE; -} - - -/** - * eap_get_name - Get EAP method name for the given EAP type - * @vendor: EAP Vendor-Id (0 = IETF) - * @type: EAP method type - * Returns: EAP method name, e.g., TLS, or %NULL if not found - * - * This function maps EAP type numbers into EAP type names based on the list of - * EAP methods included in the build. - */ -const char * eap_get_name(int vendor, EapType type) -{ - struct eap_method *m; - for (m = eap_methods; m; m = m->next) { - if (m->vendor == vendor && m->method == type) - return m->name; - } - return NULL; -} - - -/** - * eap_get_names - Get space separated list of names for supported EAP methods - * @buf: Buffer for names - * @buflen: Buffer length - * Returns: Number of characters written into buf (not including nul - * termination) - */ -size_t eap_get_names(char *buf, size_t buflen) -{ - char *pos, *end; - struct eap_method *m; - int ret; - - if (buflen == 0) - return 0; - - pos = buf; - end = pos + buflen; - - for (m = eap_methods; m; m = m->next) { - ret = os_snprintf(pos, end - pos, "%s%s", - m == eap_methods ? "" : " ", m->name); - if (ret < 0 || ret >= end - pos) - break; - pos += ret; - } - buf[buflen - 1] = '\0'; - - return pos - buf; -} - - -/** - * eap_get_names_as_string_array - Get supported EAP methods as string array - * @num: Buffer for returning the number of items in array, not including %NULL - * terminator. This parameter can be %NULL if the length is not needed. - * Returns: A %NULL-terminated array of strings, or %NULL on error. - * - * This function returns the list of names for all supported EAP methods as an - * array of strings. The caller must free the returned array items and the - * array. - */ -char ** eap_get_names_as_string_array(size_t *num) -{ - struct eap_method *m; - size_t array_len = 0; - char **array; - int i = 0, j; - - for (m = eap_methods; m; m = m->next) - array_len++; - - array = os_zalloc(sizeof(char *) * (array_len + 1)); - if (array == NULL) - return NULL; - - for (m = eap_methods; m; m = m->next) { - array[i++] = os_strdup(m->name); - if (array[i - 1] == NULL) { - for (j = 0; j < i; j++) - os_free(array[j]); - os_free(array); - return NULL; - } - } - array[i] = NULL; - - if (num) - *num = array_len; - - return array; -} - - -/** - * eap_peer_get_methods - Get a list of enabled EAP peer methods - * @count: Set to number of available methods - * Returns: List of enabled EAP peer methods - */ -const struct eap_method * eap_peer_get_methods(size_t *count) -{ - int c = 0; - struct eap_method *m; - - for (m = eap_methods; m; m = m->next) - c++; - - *count = c; - return eap_methods; -} - - -#ifdef CONFIG_DYNAMIC_EAP_METHODS -/** - * eap_peer_method_load - Load a dynamic EAP method library (shared object) - * @so: File path for the shared object file to load - * Returns: 0 on success, -1 on failure - */ -int eap_peer_method_load(const char *so) -{ - void *handle; - int (*dyn_init)(void); - int ret; - - handle = dlopen(so, RTLD_LAZY); - if (handle == NULL) { - wpa_printf(MSG_ERROR, "EAP: Failed to open dynamic EAP method " - "'%s': %s", so, dlerror()); - return -1; - } - - dyn_init = dlsym(handle, "eap_peer_method_dynamic_init"); - if (dyn_init == NULL) { - dlclose(handle); - wpa_printf(MSG_ERROR, "EAP: Invalid EAP method '%s' - no " - "eap_peer_method_dynamic_init()", so); - return -1; - } - - ret = dyn_init(); - if (ret) { - dlclose(handle); - wpa_printf(MSG_ERROR, "EAP: Failed to add EAP method '%s' - " - "ret %d", so, ret); - return ret; - } - - /* Store the handle for this shared object. It will be freed with - * dlclose() when the EAP method is unregistered. */ - eap_methods->dl_handle = handle; - - wpa_printf(MSG_DEBUG, "EAP: Loaded dynamic EAP method: '%s'", so); - - return 0; -} - - -/** - * eap_peer_method_unload - Unload a dynamic EAP method library (shared object) - * @method: Pointer to the dynamically loaded EAP method - * Returns: 0 on success, -1 on failure - * - * This function can be used to unload EAP methods that have been previously - * loaded with eap_peer_method_load(). Before unloading the method, all - * references to the method must be removed to make sure that no dereferences - * of freed memory will occur after unloading. - */ -int eap_peer_method_unload(struct eap_method *method) -{ - struct eap_method *m, *prev; - void *handle; - - m = eap_methods; - prev = NULL; - while (m) { - if (m == method) - break; - prev = m; - m = m->next; - } - - if (m == NULL || m->dl_handle == NULL) - return -1; - - if (prev) - prev->next = m->next; - else - eap_methods = m->next; - - handle = m->dl_handle; - - if (m->free) - m->free(m); - else - eap_peer_method_free(m); - - dlclose(handle); - - return 0; -} -#endif /* CONFIG_DYNAMIC_EAP_METHODS */ - - -/** - * eap_peer_method_alloc - Allocate EAP peer method structure - * @version: Version of the EAP peer method interface (set to - * EAP_PEER_METHOD_INTERFACE_VERSION) - * @vendor: EAP Vendor-ID (EAP_VENDOR_*) (0 = IETF) - * @method: EAP type number (EAP_TYPE_*) - * @name: Name of the method (e.g., "TLS") - * Returns: Allocated EAP method structure or %NULL on failure - * - * The returned structure should be freed with eap_peer_method_free() when it - * is not needed anymore. - */ -struct eap_method * eap_peer_method_alloc(int version, int vendor, - EapType method, const char *name) -{ - struct eap_method *eap; - eap = os_zalloc(sizeof(*eap)); - if (eap == NULL) - return NULL; - eap->version = version; - eap->vendor = vendor; - eap->method = method; - eap->name = name; - return eap; -} - - -/** - * eap_peer_method_free - Free EAP peer method structure - * @method: Method structure allocated with eap_peer_method_alloc() - */ -void eap_peer_method_free(struct eap_method *method) -{ - os_free(method); -} - - -/** - * eap_peer_method_register - Register an EAP peer method - * @method: EAP method to register - * Returns: 0 on success, -1 on invalid method, or -2 if a matching EAP method - * has already been registered - * - * Each EAP peer method needs to call this function to register itself as a - * supported EAP method. - */ -int eap_peer_method_register(struct eap_method *method) -{ - struct eap_method *m, *last = NULL; - - if (method == NULL || method->name == NULL || - method->version != EAP_PEER_METHOD_INTERFACE_VERSION) - return -1; - - for (m = eap_methods; m; m = m->next) { - if ((m->vendor == method->vendor && - m->method == method->method) || - os_strcmp(m->name, method->name) == 0) - return -2; - last = m; - } - - if (last) - last->next = method; - else - eap_methods = method; - - return 0; -} - - -/** - * eap_peer_register_methods - Register statically linked EAP peer methods - * Returns: 0 on success, -1 on failure - * - * This function is called at program initialization to register all EAP peer - * methods that were linked in statically. - */ -int eap_peer_register_methods(void) -{ - int ret = 0; - -#ifdef EAP_MD5 - if (ret == 0) { - int eap_peer_md5_register(void); - ret = eap_peer_md5_register(); - } -#endif /* EAP_MD5 */ - -#ifdef EAP_TLS - if (ret == 0) { - int eap_peer_tls_register(void); - ret = eap_peer_tls_register(); - } -#endif /* EAP_TLS */ - -#ifdef EAP_MSCHAPv2 - if (ret == 0) { - int eap_peer_mschapv2_register(void); - ret = eap_peer_mschapv2_register(); - } -#endif /* EAP_MSCHAPv2 */ - -#ifdef EAP_PEAP - if (ret == 0) { - int eap_peer_peap_register(void); - ret = eap_peer_peap_register(); - } -#endif /* EAP_PEAP */ - -#ifdef EAP_TTLS - if (ret == 0) { - int eap_peer_ttls_register(void); - ret = eap_peer_ttls_register(); - } -#endif /* EAP_TTLS */ - -#ifdef EAP_GTC - if (ret == 0) { - int eap_peer_gtc_register(void); - ret = eap_peer_gtc_register(); - } -#endif /* EAP_GTC */ - -#ifdef EAP_OTP - if (ret == 0) { - int eap_peer_otp_register(void); - ret = eap_peer_otp_register(); - } -#endif /* EAP_OTP */ - -#ifdef EAP_SIM - if (ret == 0) { - int eap_peer_sim_register(void); - ret = eap_peer_sim_register(); - } -#endif /* EAP_SIM */ - -#ifdef EAP_LEAP - if (ret == 0) { - int eap_peer_leap_register(void); - ret = eap_peer_leap_register(); - } -#endif /* EAP_LEAP */ - -#ifdef EAP_PSK - if (ret == 0) { - int eap_peer_psk_register(void); - ret = eap_peer_psk_register(); - } -#endif /* EAP_PSK */ - -#ifdef EAP_AKA - if (ret == 0) { - int eap_peer_aka_register(void); - ret = eap_peer_aka_register(); - } -#endif /* EAP_AKA */ - -#ifdef EAP_AKA_PRIME - if (ret == 0) { - int eap_peer_aka_prime_register(void); - ret = eap_peer_aka_prime_register(); - } -#endif /* EAP_AKA_PRIME */ - -#ifdef EAP_FAST - if (ret == 0) { - int eap_peer_fast_register(void); - ret = eap_peer_fast_register(); - } -#endif /* EAP_FAST */ - -#ifdef EAP_PAX - if (ret == 0) { - int eap_peer_pax_register(void); - ret = eap_peer_pax_register(); - } -#endif /* EAP_PAX */ - -#ifdef EAP_SAKE - if (ret == 0) { - int eap_peer_sake_register(void); - ret = eap_peer_sake_register(); - } -#endif /* EAP_SAKE */ - -#ifdef EAP_GPSK - if (ret == 0) { - int eap_peer_gpsk_register(void); - ret = eap_peer_gpsk_register(); - } -#endif /* EAP_GPSK */ - -#ifdef EAP_WSC - if (ret == 0) { - int eap_peer_wsc_register(void); - ret = eap_peer_wsc_register(); - } -#endif /* EAP_WSC */ - -#ifdef EAP_IKEV2 - if (ret == 0) { - int eap_peer_ikev2_register(void); - ret = eap_peer_ikev2_register(); - } -#endif /* EAP_IKEV2 */ - -#ifdef EAP_VENDOR_TEST - if (ret == 0) { - int eap_peer_vendor_test_register(void); - ret = eap_peer_vendor_test_register(); - } -#endif /* EAP_VENDOR_TEST */ - -#ifdef EAP_TNC - if (ret == 0) { - int eap_peer_tnc_register(void); - ret = eap_peer_tnc_register(); - } -#endif /* EAP_TNC */ - - return ret; -} - - -/** - * eap_peer_unregister_methods - Unregister EAP peer methods - * - * This function is called at program termination to unregister all EAP peer - * methods. - */ -void eap_peer_unregister_methods(void) -{ - struct eap_method *m; -#ifdef CONFIG_DYNAMIC_EAP_METHODS - void *handle; -#endif /* CONFIG_DYNAMIC_EAP_METHODS */ - - while (eap_methods) { - m = eap_methods; - eap_methods = eap_methods->next; - -#ifdef CONFIG_DYNAMIC_EAP_METHODS - handle = m->dl_handle; -#endif /* CONFIG_DYNAMIC_EAP_METHODS */ - - if (m->free) - m->free(m); - else - eap_peer_method_free(m); - -#ifdef CONFIG_DYNAMIC_EAP_METHODS - if (handle) - dlclose(handle); -#endif /* CONFIG_DYNAMIC_EAP_METHODS */ - } -} diff --git a/contrib/hostapd/src/eap_peer/eap_methods.h b/contrib/hostapd/src/eap_peer/eap_methods.h deleted file mode 100644 index 9fd9b517c7..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_methods.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * EAP peer: Method registration - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_METHODS_H -#define EAP_METHODS_H - -#include "eap_common/eap_defs.h" - -const struct eap_method * eap_peer_get_eap_method(int vendor, EapType method); -const struct eap_method * eap_peer_get_methods(size_t *count); - -struct eap_method * eap_peer_method_alloc(int version, int vendor, - EapType method, const char *name); -void eap_peer_method_free(struct eap_method *method); -int eap_peer_method_register(struct eap_method *method); - - -#ifdef IEEE8021X_EAPOL - -EapType eap_peer_get_type(const char *name, int *vendor); -const char * eap_get_name(int vendor, EapType type); -size_t eap_get_names(char *buf, size_t buflen); -char ** eap_get_names_as_string_array(size_t *num); -int eap_peer_register_methods(void); -void eap_peer_unregister_methods(void); - -#else /* IEEE8021X_EAPOL */ - -static inline EapType eap_peer_get_type(const char *name, int *vendor) -{ - *vendor = EAP_VENDOR_IETF; - return EAP_TYPE_NONE; -} - -static inline const char * eap_get_name(int vendor, EapType type) -{ - return NULL; -} - -static inline size_t eap_get_names(char *buf, size_t buflen) -{ - return 0; -} - -static inline int eap_peer_register_methods(void) -{ - return 0; -} - -static inline void eap_peer_unregister_methods(void) -{ -} - -static inline char ** eap_get_names_as_string_array(size_t *num) -{ - return NULL; -} - -#endif /* IEEE8021X_EAPOL */ - - -#ifdef CONFIG_DYNAMIC_EAP_METHODS - -int eap_peer_method_load(const char *so); -int eap_peer_method_unload(struct eap_method *method); - -#else /* CONFIG_DYNAMIC_EAP_METHODS */ - -static inline int eap_peer_method_load(const char *so) -{ - return 0; -} - -static inline int eap_peer_method_unload(struct eap_method *method) -{ - return 0; -} - -#endif /* CONFIG_DYNAMIC_EAP_METHODS */ - -#endif /* EAP_METHODS_H */ diff --git a/contrib/hostapd/src/eap_peer/eap_mschapv2.c b/contrib/hostapd/src/eap_peer/eap_mschapv2.c deleted file mode 100644 index b0c3ab7763..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_mschapv2.c +++ /dev/null @@ -1,877 +0,0 @@ -/* - * EAP peer method: EAP-MSCHAPV2 (draft-kamath-pppext-eap-mschapv2-00.txt) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file implements EAP peer part of EAP-MSCHAPV2 method (EAP type 26). - * draft-kamath-pppext-eap-mschapv2-00.txt defines the Microsoft EAP CHAP - * Extensions Protocol, Version 2, for mutual authentication and key - * derivation. This encapsulates MS-CHAP-v2 protocol which is defined in - * RFC 2759. Use of EAP-MSCHAPV2 derived keys with MPPE cipher is described in - * RFC 3079. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "eap_config.h" -#include "ms_funcs.h" -#include "wpa_ctrl.h" -#include "mschapv2.h" - - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct eap_mschapv2_hdr { - u8 op_code; /* MSCHAPV2_OP_* */ - u8 mschapv2_id; /* usually same as EAP identifier; must be changed - * for challenges, but not for success/failure */ - u8 ms_length[2]; /* Note: misaligned; length - 5 */ - /* followed by data */ -} STRUCT_PACKED; - -/* Response Data field */ -struct ms_response { - u8 peer_challenge[MSCHAPV2_CHAL_LEN]; - u8 reserved[8]; - u8 nt_response[MSCHAPV2_NT_RESPONSE_LEN]; - u8 flags; -} STRUCT_PACKED; - -/* Change-Password Data field */ -struct ms_change_password { - u8 encr_password[516]; - u8 encr_hash[16]; - u8 peer_challenge[MSCHAPV2_CHAL_LEN]; - u8 reserved[8]; - u8 nt_response[MSCHAPV2_NT_RESPONSE_LEN]; - u8 flags[2]; -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -#define MSCHAPV2_OP_CHALLENGE 1 -#define MSCHAPV2_OP_RESPONSE 2 -#define MSCHAPV2_OP_SUCCESS 3 -#define MSCHAPV2_OP_FAILURE 4 -#define MSCHAPV2_OP_CHANGE_PASSWORD 7 - -#define ERROR_RESTRICTED_LOGON_HOURS 646 -#define ERROR_ACCT_DISABLED 647 -#define ERROR_PASSWD_EXPIRED 648 -#define ERROR_NO_DIALIN_PERMISSION 649 -#define ERROR_AUTHENTICATION_FAILURE 691 -#define ERROR_CHANGING_PASSWORD 709 - -#define PASSWD_CHANGE_CHAL_LEN 16 -#define MSCHAPV2_KEY_LEN 16 - - -struct eap_mschapv2_data { - u8 auth_response[MSCHAPV2_AUTH_RESPONSE_LEN]; - int auth_response_valid; - - int prev_error; - u8 passwd_change_challenge[PASSWD_CHANGE_CHAL_LEN]; - int passwd_change_challenge_valid; - int passwd_change_version; - - /* Optional challenge values generated in EAP-FAST Phase 1 negotiation - */ - u8 *peer_challenge; - u8 *auth_challenge; - - int phase2; - u8 master_key[MSCHAPV2_MASTER_KEY_LEN]; - int master_key_valid; - int success; - - struct wpabuf *prev_challenge; -}; - - -static void eap_mschapv2_deinit(struct eap_sm *sm, void *priv); - - -static void * eap_mschapv2_init(struct eap_sm *sm) -{ - struct eap_mschapv2_data *data; - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - if (sm->peer_challenge) { - data->peer_challenge = os_malloc(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); - 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; - - return data; -} - - -static void eap_mschapv2_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_mschapv2_data *data = priv; - os_free(data->peer_challenge); - os_free(data->auth_challenge); - wpabuf_free(data->prev_challenge); - os_free(data); -} - - -static struct wpabuf * eap_mschapv2_challenge_reply( - struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id, - u8 mschapv2_id, const u8 *auth_challenge) -{ - struct wpabuf *resp; - struct eap_mschapv2_hdr *ms; - u8 *peer_challenge; - int ms_len; - struct ms_response *r; - size_t identity_len, password_len; - const u8 *identity, *password; - int pwhash; - - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Generating Challenge Response"); - - identity = eap_get_config_identity(sm, &identity_len); - password = eap_get_config_password2(sm, &password_len, &pwhash); - if (identity == NULL || password == NULL) - return NULL; - - ms_len = sizeof(*ms) + 1 + sizeof(*r) + identity_len; - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - ms = wpabuf_put(resp, sizeof(*ms)); - ms->op_code = MSCHAPV2_OP_RESPONSE; - ms->mschapv2_id = mschapv2_id; - if (data->prev_error) { - /* - * TODO: this does not seem to be enough when processing two - * or more failure messages. IAS did not increment mschapv2_id - * in its own packets, but it seemed to expect the peer to - * increment this for all packets(?). - */ - ms->mschapv2_id++; - } - WPA_PUT_BE16(ms->ms_length, ms_len); - - wpabuf_put_u8(resp, sizeof(*r)); /* Value-Size */ - - /* Response */ - r = wpabuf_put(resp, sizeof(*r)); - peer_challenge = r->peer_challenge; - if (data->peer_challenge) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge generated " - "in Phase 1"); - peer_challenge = data->peer_challenge; - os_memset(r->peer_challenge, 0, MSCHAPV2_CHAL_LEN); - } else if (os_get_random(peer_challenge, MSCHAPV2_CHAL_LEN)) { - wpabuf_free(resp); - return NULL; - } - os_memset(r->reserved, 0, 8); - if (data->auth_challenge) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge generated " - "in Phase 1"); - auth_challenge = data->auth_challenge; - } - mschapv2_derive_response(identity, identity_len, password, - password_len, pwhash, auth_challenge, - peer_challenge, r->nt_response, - data->auth_response, data->master_key); - data->auth_response_valid = 1; - data->master_key_valid = 1; - - r->flags = 0; /* reserved, must be zero */ - - wpabuf_put_data(resp, identity, identity_len); - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d " - "(response)", id, ms->mschapv2_id); - return resp; -} - - -/** - * eap_mschapv2_process - Process an EAP-MSCHAPv2 challenge message - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Pointer to private EAP method data from eap_mschapv2_init() - * @ret: Return values from EAP request validation and processing - * @req: Pointer to EAP-MSCHAPv2 header from the request - * @req_len: Length of the EAP-MSCHAPv2 data - * @id: EAP identifier used in the request - * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if - * no reply available - */ -static struct wpabuf * eap_mschapv2_challenge( - struct eap_sm *sm, struct eap_mschapv2_data *data, - struct eap_method_ret *ret, const struct eap_mschapv2_hdr *req, - size_t req_len, u8 id) -{ - size_t len, challenge_len; - const u8 *pos, *challenge; - - if (eap_get_config_identity(sm, &len) == NULL || - eap_get_config_password(sm, &len) == NULL) - return NULL; - - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received challenge"); - if (req_len < sizeof(*req) + 1) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Too short challenge data " - "(len %lu)", (unsigned long) req_len); - ret->ignore = TRUE; - return NULL; - } - pos = (const u8 *) (req + 1); - challenge_len = *pos++; - len = req_len - sizeof(*req) - 1; - if (challenge_len != MSCHAPV2_CHAL_LEN) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid challenge length " - "%lu", (unsigned long) challenge_len); - ret->ignore = TRUE; - return NULL; - } - - if (len < challenge_len) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Too short challenge" - " packet: len=%lu challenge_len=%lu", - (unsigned long) len, (unsigned long) challenge_len); - ret->ignore = TRUE; - return NULL; - } - - if (data->passwd_change_challenge_valid) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Using challenge from the " - "failure message"); - challenge = data->passwd_change_challenge; - } else - challenge = pos; - pos += challenge_len; - len -= challenge_len; - wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Authentication Servername", - pos, len); - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - return eap_mschapv2_challenge_reply(sm, data, id, req->mschapv2_id, - challenge); -} - - -static void eap_mschapv2_password_changed(struct eap_sm *sm, - struct eap_mschapv2_data *data) -{ - struct eap_peer_config *config = eap_get_config(sm); - if (config && config->new_password) { - wpa_msg(sm->msg_ctx, MSG_INFO, - WPA_EVENT_PASSWORD_CHANGED - "EAP-MSCHAPV2: Password changed successfully"); - data->prev_error = 0; - os_free(config->password); - if (config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH) { - config->password = os_malloc(16); - config->password_len = 16; - if (config->password) { - nt_password_hash(config->new_password, - config->new_password_len, - config->password); - } - os_free(config->new_password); - } else { - config->password = config->new_password; - config->password_len = config->new_password_len; - } - config->new_password = NULL; - config->new_password_len = 0; - } -} - - -/** - * eap_mschapv2_process - Process an EAP-MSCHAPv2 success message - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Pointer to private EAP method data from eap_mschapv2_init() - * @ret: Return values from EAP request validation and processing - * @req: Pointer to EAP-MSCHAPv2 header from the request - * @req_len: Length of the EAP-MSCHAPv2 data - * @id: EAP identifier used in th erequest - * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if - * no reply available - */ -static struct wpabuf * eap_mschapv2_success(struct eap_sm *sm, - struct eap_mschapv2_data *data, - struct eap_method_ret *ret, - const struct eap_mschapv2_hdr *req, - size_t req_len, u8 id) -{ - struct wpabuf *resp; - const u8 *pos; - size_t len; - - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received success"); - len = req_len - sizeof(*req); - pos = (const u8 *) (req + 1); - if (!data->auth_response_valid || - mschapv2_verify_auth_response(data->auth_response, pos, len)) { - wpa_printf(MSG_WARNING, "EAP-MSCHAPV2: Invalid authenticator " - "response in success request"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } - pos += 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN; - len -= 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN; - while (len > 0 && *pos == ' ') { - pos++; - len--; - } - wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Success message", - pos, len); - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Authentication succeeded"); - - /* Note: Only op_code of the EAP-MSCHAPV2 header is included in success - * message. */ - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, 1, - EAP_CODE_RESPONSE, id); - if (resp == NULL) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Failed to allocate " - "buffer for success response"); - ret->ignore = TRUE; - return NULL; - } - - wpabuf_put_u8(resp, MSCHAPV2_OP_SUCCESS); /* op_code */ - - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = FALSE; - data->success = 1; - - if (data->prev_error == ERROR_PASSWD_EXPIRED) - eap_mschapv2_password_changed(sm, data); - - return resp; -} - - -static int eap_mschapv2_failure_txt(struct eap_sm *sm, - struct eap_mschapv2_data *data, char *txt) -{ - char *pos, *msg = ""; - int retry = 1; - struct eap_peer_config *config = eap_get_config(sm); - - /* For example: - * E=691 R=1 C=<32 octets hex challenge> V=3 M=Authentication Failure - */ - - pos = txt; - - if (pos && os_strncmp(pos, "E=", 2) == 0) { - pos += 2; - data->prev_error = atoi(pos); - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: error %d", - data->prev_error); - pos = os_strchr(pos, ' '); - if (pos) - pos++; - } - - if (pos && os_strncmp(pos, "R=", 2) == 0) { - pos += 2; - retry = atoi(pos); - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: retry is %sallowed", - retry == 1 ? "" : "not "); - pos = os_strchr(pos, ' '); - if (pos) - pos++; - } - - if (pos && os_strncmp(pos, "C=", 2) == 0) { - int hex_len; - pos += 2; - hex_len = os_strchr(pos, ' ') - (char *) pos; - if (hex_len == PASSWD_CHANGE_CHAL_LEN * 2) { - if (hexstr2bin(pos, data->passwd_change_challenge, - PASSWD_CHANGE_CHAL_LEN)) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: invalid " - "failure challenge"); - } else { - wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: failure " - "challenge", - data->passwd_change_challenge, - PASSWD_CHANGE_CHAL_LEN); - data->passwd_change_challenge_valid = 1; - } - } else { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: invalid failure " - "challenge len %d", hex_len); - } - pos = os_strchr(pos, ' '); - if (pos) - pos++; - } else { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: required challenge field " - "was not present in failure message"); - } - - if (pos && os_strncmp(pos, "V=", 2) == 0) { - pos += 2; - data->passwd_change_version = atoi(pos); - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: password changing " - "protocol version %d", data->passwd_change_version); - pos = os_strchr(pos, ' '); - if (pos) - pos++; - } - - if (pos && os_strncmp(pos, "M=", 2) == 0) { - pos += 2; - msg = pos; - } - wpa_msg(sm->msg_ctx, MSG_WARNING, - "EAP-MSCHAPV2: failure message: '%s' (retry %sallowed, error " - "%d)", - msg, retry == 1 ? "" : "not ", data->prev_error); - if (data->prev_error == ERROR_PASSWD_EXPIRED && - data->passwd_change_version == 3 && config) { - if (config->new_password == NULL) { - wpa_msg(sm->msg_ctx, MSG_INFO, - "EAP-MSCHAPV2: Password expired - password " - "change required"); - eap_sm_request_new_password(sm); - } - } else if (retry == 1 && config) { - /* TODO: could prevent the current password from being used - * again at least for some period of time */ - if (!config->mschapv2_retry) - eap_sm_request_identity(sm); - eap_sm_request_password(sm); - config->mschapv2_retry = 1; - } else if (config) { - /* TODO: prevent retries using same username/password */ - config->mschapv2_retry = 0; - } - - return retry == 1; -} - - -static struct wpabuf * eap_mschapv2_change_password( - struct eap_sm *sm, struct eap_mschapv2_data *data, - struct eap_method_ret *ret, const struct eap_mschapv2_hdr *req, u8 id) -{ - struct wpabuf *resp; - int ms_len; - const u8 *username, *password, *new_password; - size_t username_len, password_len, new_password_len; - struct eap_mschapv2_hdr *ms; - struct ms_change_password *cp; - u8 password_hash[16], password_hash_hash[16]; - int pwhash; - - username = eap_get_config_identity(sm, &username_len); - password = eap_get_config_password2(sm, &password_len, &pwhash); - new_password = eap_get_config_new_password(sm, &new_password_len); - if (username == NULL || password == NULL || new_password == NULL) - return NULL; - - username = mschapv2_remove_domain(username, &username_len); - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = TRUE; - - ms_len = sizeof(*ms) + sizeof(*cp); - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - ms = wpabuf_put(resp, sizeof(*ms)); - ms->op_code = MSCHAPV2_OP_CHANGE_PASSWORD; - ms->mschapv2_id = req->mschapv2_id + 1; - WPA_PUT_BE16(ms->ms_length, ms_len); - cp = wpabuf_put(resp, sizeof(*cp)); - - /* Encrypted-Password */ - if (pwhash) { - if (encrypt_pw_block_with_password_hash( - new_password, new_password_len, - password, cp->encr_password)) - goto fail; - } else { - if (new_password_encrypted_with_old_nt_password_hash( - new_password, new_password_len, - password, password_len, cp->encr_password)) - goto fail; - } - - /* Encrypted-Hash */ - if (pwhash) { - u8 new_password_hash[16]; - nt_password_hash(new_password, new_password_len, - new_password_hash); - nt_password_hash_encrypted_with_block(password, - new_password_hash, - cp->encr_hash); - } else { - old_nt_password_hash_encrypted_with_new_nt_password_hash( - new_password, new_password_len, - password, password_len, cp->encr_hash); - } - - /* Peer-Challenge */ - if (os_get_random(cp->peer_challenge, MSCHAPV2_CHAL_LEN)) - goto fail; - - /* Reserved, must be zero */ - os_memset(cp->reserved, 0, 8); - - /* NT-Response */ - wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge", - data->passwd_change_challenge, PASSWD_CHANGE_CHAL_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge", - cp->peer_challenge, MSCHAPV2_CHAL_LEN); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: username", - username, username_len); - wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-MSCHAPV2: new password", - new_password, new_password_len); - generate_nt_response(data->passwd_change_challenge, cp->peer_challenge, - username, username_len, - new_password, new_password_len, - cp->nt_response); - wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: NT-Response", - cp->nt_response, MSCHAPV2_NT_RESPONSE_LEN); - - /* Authenticator response is not really needed yet, but calculate it - * here so that challenges need not be saved. */ - generate_authenticator_response(new_password, new_password_len, - cp->peer_challenge, - data->passwd_change_challenge, - username, username_len, - cp->nt_response, data->auth_response); - data->auth_response_valid = 1; - - /* Likewise, generate master_key here since we have the needed data - * available. */ - nt_password_hash(new_password, new_password_len, password_hash); - hash_nt_password_hash(password_hash, password_hash_hash); - get_master_key(password_hash_hash, cp->nt_response, data->master_key); - data->master_key_valid = 1; - - /* Flags */ - os_memset(cp->flags, 0, 2); - - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d " - "(change pw)", id, ms->mschapv2_id); - - return resp; - -fail: - wpabuf_free(resp); - return NULL; -} - - -/** - * eap_mschapv2_process - Process an EAP-MSCHAPv2 failure message - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Pointer to private EAP method data from eap_mschapv2_init() - * @ret: Return values from EAP request validation and processing - * @req: Pointer to EAP-MSCHAPv2 header from the request - * @req_len: Length of the EAP-MSCHAPv2 data - * @id: EAP identifier used in th erequest - * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if - * no reply available - */ -static struct wpabuf * eap_mschapv2_failure(struct eap_sm *sm, - struct eap_mschapv2_data *data, - struct eap_method_ret *ret, - const struct eap_mschapv2_hdr *req, - size_t req_len, u8 id) -{ - struct wpabuf *resp; - const u8 *msdata = (const u8 *) (req + 1); - char *buf; - size_t len = req_len - sizeof(*req); - int retry = 0; - - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received failure"); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Failure data", - msdata, len); - /* - * eap_mschapv2_failure_txt() expects a nul terminated string, so we - * must allocate a large enough temporary buffer to create that since - * the received message does not include nul termination. - */ - buf = os_malloc(len + 1); - if (buf) { - os_memcpy(buf, msdata, len); - buf[len] = '\0'; - retry = eap_mschapv2_failure_txt(sm, data, buf); - os_free(buf); - } - - ret->ignore = FALSE; - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; - - if (data->prev_error == ERROR_PASSWD_EXPIRED && - data->passwd_change_version == 3) { - struct eap_peer_config *config = eap_get_config(sm); - if (config && config->new_password) - return eap_mschapv2_change_password(sm, data, ret, req, - id); - if (config && config->pending_req_new_password) - return NULL; - } else if (retry && data->prev_error == ERROR_AUTHENTICATION_FAILURE) { - /* TODO: could try to retry authentication, e.g, after having - * changed the username/password. In this case, EAP MS-CHAP-v2 - * Failure Response would not be sent here. */ - return NULL; - } - - /* Note: Only op_code of the EAP-MSCHAPV2 header is included in failure - * message. */ - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, 1, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - wpabuf_put_u8(resp, MSCHAPV2_OP_FAILURE); /* op_code */ - - return resp; -} - - -static int eap_mschapv2_check_config(struct eap_sm *sm) -{ - size_t len; - - if (eap_get_config_identity(sm, &len) == NULL) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Identity not configured"); - eap_sm_request_identity(sm); - return -1; - } - - if (eap_get_config_password(sm, &len) == NULL) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Password not configured"); - eap_sm_request_password(sm); - return -1; - } - - return 0; -} - - -static int eap_mschapv2_check_mslen(struct eap_sm *sm, size_t len, - const struct eap_mschapv2_hdr *ms) -{ - size_t ms_len = WPA_GET_BE16(ms->ms_length); - - if (ms_len == len) - return 0; - - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid header: len=%lu " - "ms_len=%lu", (unsigned long) len, (unsigned long) ms_len); - if (sm->workaround) { - /* Some authentication servers use invalid ms_len, - * ignore it for interoperability. */ - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: workaround, ignore" - " invalid ms_len %lu (len %lu)", - (unsigned long) ms_len, - (unsigned long) len); - return 0; - } - - return -1; -} - - -static void eap_mschapv2_copy_challenge(struct eap_mschapv2_data *data, - const struct wpabuf *reqData) -{ - /* - * Store a copy of the challenge message, so that it can be processed - * again in case retry is allowed after a possible failure. - */ - wpabuf_free(data->prev_challenge); - data->prev_challenge = wpabuf_dup(reqData); -} - - -/** - * eap_mschapv2_process - Process an EAP-MSCHAPv2 request - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_mschapv2_init() - * @ret: Return values from EAP request validation and processing - * @reqData: EAP request to be processed (eapReqData) - * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if - * no reply available - */ -static struct wpabuf * eap_mschapv2_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_mschapv2_data *data = priv; - struct eap_peer_config *config = eap_get_config(sm); - const struct eap_mschapv2_hdr *ms; - int using_prev_challenge = 0; - const u8 *pos; - size_t len; - u8 id; - - if (eap_mschapv2_check_config(sm)) { - ret->ignore = TRUE; - return NULL; - } - - if (config->mschapv2_retry && data->prev_challenge && - data->prev_error == ERROR_AUTHENTICATION_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Replacing pending packet " - "with the previous challenge"); - - reqData = data->prev_challenge; - using_prev_challenge = 1; - config->mschapv2_retry = 0; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, reqData, - &len); - if (pos == NULL || len < sizeof(*ms) + 1) { - ret->ignore = TRUE; - return NULL; - } - - ms = (const struct eap_mschapv2_hdr *) pos; - if (eap_mschapv2_check_mslen(sm, len, ms)) { - ret->ignore = TRUE; - return NULL; - } - - id = eap_get_id(reqData); - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: RX identifier %d mschapv2_id %d", - id, ms->mschapv2_id); - - switch (ms->op_code) { - case MSCHAPV2_OP_CHALLENGE: - if (!using_prev_challenge) - eap_mschapv2_copy_challenge(data, reqData); - return eap_mschapv2_challenge(sm, data, ret, ms, len, id); - case MSCHAPV2_OP_SUCCESS: - return eap_mschapv2_success(sm, data, ret, ms, len, id); - case MSCHAPV2_OP_FAILURE: - return eap_mschapv2_failure(sm, data, ret, ms, len, id); - default: - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Unknown op %d - ignored", - ms->op_code); - ret->ignore = TRUE; - return NULL; - } -} - - -static Boolean eap_mschapv2_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_mschapv2_data *data = priv; - return data->success && data->master_key_valid; -} - - -static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_mschapv2_data *data = priv; - u8 *key; - int key_len; - - if (!data->master_key_valid || !data->success) - return NULL; - - key_len = 2 * MSCHAPV2_KEY_LEN; - - key = os_malloc(key_len); - if (key == NULL) - return NULL; - - /* 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); - - wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key", - key, key_len); - - *len = key_len; - return key; -} - - -/** - * eap_peer_mschapv2_register - Register EAP-MSCHAPv2 peer method - * Returns: 0 on success, -1 on failure - * - * This function is used to register EAP-MSCHAPv2 peer method into the EAP - * method list. - */ -int eap_peer_mschapv2_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, - "MSCHAPV2"); - if (eap == NULL) - return -1; - - eap->init = eap_mschapv2_init; - eap->deinit = eap_mschapv2_deinit; - eap->process = eap_mschapv2_process; - eap->isKeyAvailable = eap_mschapv2_isKeyAvailable; - eap->getKey = eap_mschapv2_getKey; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_peer/eap_otp.c b/contrib/hostapd/src/eap_peer/eap_otp.c deleted file mode 100644 index 556c22f9e2..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_otp.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * EAP peer method: EAP-OTP (RFC 3748) - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" - - -static void * eap_otp_init(struct eap_sm *sm) -{ - /* No need for private data. However, must return non-NULL to indicate - * success. */ - return (void *) 1; -} - - -static void eap_otp_deinit(struct eap_sm *sm, void *priv) -{ -} - - -static struct wpabuf * eap_otp_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct wpabuf *resp; - const u8 *pos, *password; - size_t password_len, len; - int otp; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_OTP, reqData, &len); - if (pos == NULL) { - ret->ignore = TRUE; - return NULL; - } - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-OTP: Request message", - pos, len); - - password = eap_get_config_otp(sm, &password_len); - if (password) - otp = 1; - else { - password = eap_get_config_password(sm, &password_len); - otp = 0; - } - - if (password == NULL) { - wpa_printf(MSG_INFO, "EAP-OTP: Password not configured"); - eap_sm_request_otp(sm, (const char *) pos, len); - ret->ignore = TRUE; - return NULL; - } - - ret->ignore = FALSE; - - ret->methodState = METHOD_DONE; - ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = FALSE; - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_OTP, password_len, - EAP_CODE_RESPONSE, eap_get_id(reqData)); - if (resp == NULL) - return NULL; - wpabuf_put_data(resp, password, password_len); - wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-OTP: Response", - password, password_len); - - if (otp) { - wpa_printf(MSG_DEBUG, "EAP-OTP: Forgetting used password"); - eap_clear_config_otp(sm); - } - - return resp; -} - - -int eap_peer_otp_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_OTP, "OTP"); - if (eap == NULL) - return -1; - - eap->init = eap_otp_init; - eap->deinit = eap_otp_deinit; - eap->process = eap_otp_process; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_peer/eap_pax.c b/contrib/hostapd/src/eap_peer/eap_pax.c deleted file mode 100644 index afd56dd49b..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_pax.c +++ /dev/null @@ -1,532 +0,0 @@ -/* - * EAP peer method: EAP-PAX (RFC 4746) - * Copyright (c) 2005-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_peer/eap_i.h" -#include "eap_common/eap_pax_common.h" -#include "sha1.h" -#include "crypto.h" - -/* - * Note: only PAX_STD subprotocol is currently supported - * - * TODO: Add support with PAX_SEC with the mandatory to implement ciphersuite - * (HMAC_SHA1_128, IANA DH Group 14 (2048 bits), RSA-PKCS1-V1_5) and - * recommended ciphersuite (HMAC_SHA256_128, IANA DH Group 15 (3072 bits), - * RSAES-OAEP). - */ - -struct eap_pax_data { - enum { PAX_INIT, PAX_STD_2_SENT, PAX_DONE } state; - u8 mac_id, dh_group_id, public_key_id; - union { - u8 e[2 * EAP_PAX_RAND_LEN]; - struct { - u8 x[EAP_PAX_RAND_LEN]; /* server rand */ - u8 y[EAP_PAX_RAND_LEN]; /* client rand */ - } r; - } rand; - char *cid; - size_t cid_len; - u8 ak[EAP_PAX_AK_LEN]; - u8 mk[EAP_PAX_MK_LEN]; - u8 ck[EAP_PAX_CK_LEN]; - u8 ick[EAP_PAX_ICK_LEN]; -}; - - -static void eap_pax_deinit(struct eap_sm *sm, void *priv); - - -static void * eap_pax_init(struct eap_sm *sm) -{ - struct eap_pax_data *data; - const u8 *identity, *password; - size_t identity_len, password_len; - - identity = eap_get_config_identity(sm, &identity_len); - password = eap_get_config_password(sm, &password_len); - if (!identity || !password) { - wpa_printf(MSG_INFO, "EAP-PAX: CID (nai) or key (password) " - "not configured"); - return NULL; - } - - if (password_len != EAP_PAX_AK_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: Invalid PSK length"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = PAX_INIT; - - data->cid = os_malloc(identity_len); - if (data->cid == NULL) { - eap_pax_deinit(sm, data); - return NULL; - } - os_memcpy(data->cid, identity, identity_len); - data->cid_len = identity_len; - - os_memcpy(data->ak, password, EAP_PAX_AK_LEN); - - return data; -} - - -static void eap_pax_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_pax_data *data = priv; - os_free(data->cid); - os_free(data); -} - - -static struct wpabuf * eap_pax_alloc_resp(const struct eap_pax_hdr *req, - u8 id, u8 op_code, size_t plen) -{ - struct wpabuf *resp; - struct eap_pax_hdr *pax; - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PAX, - sizeof(*pax) + plen, EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - pax = wpabuf_put(resp, sizeof(*pax)); - pax->op_code = op_code; - pax->flags = 0; - pax->mac_id = req->mac_id; - pax->dh_group_id = req->dh_group_id; - pax->public_key_id = req->public_key_id; - - return resp; -} - - -static struct wpabuf * eap_pax_process_std_1(struct eap_pax_data *data, - struct eap_method_ret *ret, u8 id, - const struct eap_pax_hdr *req, - size_t req_plen) -{ - struct wpabuf *resp; - const u8 *pos; - u8 *rpos; - size_t left, plen; - - wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-1 (received)"); - - if (data->state != PAX_INIT) { - wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 received in " - "unexpected state (%d) - ignored", data->state); - ret->ignore = TRUE; - return NULL; - } - - if (req->flags & EAP_PAX_FLAGS_CE) { - wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with CE flag set - " - "ignored"); - ret->ignore = TRUE; - return NULL; - } - - left = req_plen - sizeof(*req); - - if (left < 2 + EAP_PAX_RAND_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with too short " - "payload"); - ret->ignore = TRUE; - return NULL; - } - - pos = (const u8 *) (req + 1); - if (WPA_GET_BE16(pos) != EAP_PAX_RAND_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with incorrect A " - "length %d (expected %d)", - WPA_GET_BE16(pos), EAP_PAX_RAND_LEN); - ret->ignore = TRUE; - return NULL; - } - - pos += 2; - left -= 2; - os_memcpy(data->rand.r.x, pos, EAP_PAX_RAND_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: X (server rand)", - data->rand.r.x, EAP_PAX_RAND_LEN); - pos += EAP_PAX_RAND_LEN; - left -= EAP_PAX_RAND_LEN; - - if (left > 0) { - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ignored extra payload", - pos, left); - } - - if (os_get_random(data->rand.r.y, EAP_PAX_RAND_LEN)) { - wpa_printf(MSG_ERROR, "EAP-PAX: Failed to get random data"); - ret->ignore = TRUE; - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Y (client rand)", - data->rand.r.y, EAP_PAX_RAND_LEN); - - if (eap_pax_initial_key_derivation(req->mac_id, data->ak, data->rand.e, - data->mk, data->ck, data->ick) < 0) - { - ret->ignore = TRUE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-2 (sending)"); - - plen = 2 + EAP_PAX_RAND_LEN + 2 + data->cid_len + 2 + EAP_PAX_MAC_LEN + - EAP_PAX_ICV_LEN; - resp = eap_pax_alloc_resp(req, id, EAP_PAX_OP_STD_2, plen); - if (resp == NULL) - return NULL; - - wpabuf_put_be16(resp, EAP_PAX_RAND_LEN); - wpabuf_put_data(resp, data->rand.r.y, EAP_PAX_RAND_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: B = Y (client rand)", - data->rand.r.y, EAP_PAX_RAND_LEN); - - wpabuf_put_be16(resp, data->cid_len); - wpabuf_put_data(resp, data->cid, data->cid_len); - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PAX: CID", - (u8 *) data->cid, data->cid_len); - - wpabuf_put_be16(resp, EAP_PAX_MAC_LEN); - rpos = wpabuf_put(resp, EAP_PAX_MAC_LEN); - eap_pax_mac(req->mac_id, data->ck, EAP_PAX_CK_LEN, - data->rand.r.x, EAP_PAX_RAND_LEN, - data->rand.r.y, EAP_PAX_RAND_LEN, - (u8 *) data->cid, data->cid_len, rpos); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(A, B, CID)", - rpos, EAP_PAX_MAC_LEN); - - /* Optional ADE could be added here, if needed */ - - rpos = wpabuf_put(resp, EAP_PAX_ICV_LEN); - eap_pax_mac(req->mac_id, data->ick, EAP_PAX_ICK_LEN, - wpabuf_head(resp), wpabuf_len(resp) - EAP_PAX_ICV_LEN, - NULL, 0, NULL, 0, rpos); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", rpos, EAP_PAX_ICV_LEN); - - data->state = PAX_STD_2_SENT; - data->mac_id = req->mac_id; - data->dh_group_id = req->dh_group_id; - data->public_key_id = req->public_key_id; - - return resp; -} - - -static struct wpabuf * eap_pax_process_std_3(struct eap_pax_data *data, - struct eap_method_ret *ret, u8 id, - const struct eap_pax_hdr *req, - size_t req_plen) -{ - struct wpabuf *resp; - u8 *rpos, mac[EAP_PAX_MAC_LEN]; - const u8 *pos; - size_t left; - - wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-3 (received)"); - - if (data->state != PAX_STD_2_SENT) { - wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 received in " - "unexpected state (%d) - ignored", data->state); - ret->ignore = TRUE; - return NULL; - } - - if (req->flags & EAP_PAX_FLAGS_CE) { - wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with CE flag set - " - "ignored"); - ret->ignore = TRUE; - return NULL; - } - - left = req_plen - sizeof(*req); - - if (left < 2 + EAP_PAX_MAC_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with too short " - "payload"); - ret->ignore = TRUE; - return NULL; - } - - pos = (const u8 *) (req + 1); - if (WPA_GET_BE16(pos) != EAP_PAX_MAC_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with incorrect " - "MAC_CK length %d (expected %d)", - WPA_GET_BE16(pos), EAP_PAX_MAC_LEN); - ret->ignore = TRUE; - return NULL; - } - pos += 2; - left -= 2; - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(B, CID)", - pos, EAP_PAX_MAC_LEN); - eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN, - data->rand.r.y, EAP_PAX_RAND_LEN, - (u8 *) data->cid, data->cid_len, NULL, 0, mac); - if (os_memcmp(pos, mac, EAP_PAX_MAC_LEN) != 0) { - wpa_printf(MSG_INFO, "EAP-PAX: Invalid MAC_CK(B, CID) " - "received"); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: expected MAC_CK(B, CID)", - mac, EAP_PAX_MAC_LEN); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } - - pos += EAP_PAX_MAC_LEN; - left -= EAP_PAX_MAC_LEN; - - if (left > 0) { - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ignored extra payload", - pos, left); - } - - wpa_printf(MSG_DEBUG, "EAP-PAX: PAX-ACK (sending)"); - - resp = eap_pax_alloc_resp(req, id, EAP_PAX_OP_ACK, EAP_PAX_ICV_LEN); - if (resp == NULL) - return NULL; - - /* Optional ADE could be added here, if needed */ - - rpos = wpabuf_put(resp, EAP_PAX_ICV_LEN); - eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN, - wpabuf_head(resp), wpabuf_len(resp) - EAP_PAX_ICV_LEN, - NULL, 0, NULL, 0, rpos); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", rpos, EAP_PAX_ICV_LEN); - - data->state = PAX_DONE; - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = FALSE; - - return resp; -} - - -static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_pax_data *data = priv; - const struct eap_pax_hdr *req; - struct wpabuf *resp; - u8 icvbuf[EAP_PAX_ICV_LEN], id; - const u8 *icv, *pos; - size_t len; - u16 flen, mlen; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, reqData, &len); - if (pos == NULL || len < EAP_PAX_ICV_LEN) { - ret->ignore = TRUE; - return NULL; - } - id = eap_get_id(reqData); - req = (const struct eap_pax_hdr *) pos; - flen = len - EAP_PAX_ICV_LEN; - mlen = wpabuf_len(reqData) - EAP_PAX_ICV_LEN; - - wpa_printf(MSG_DEBUG, "EAP-PAX: received frame: op_code 0x%x " - "flags 0x%x mac_id 0x%x dh_group_id 0x%x " - "public_key_id 0x%x", - req->op_code, req->flags, req->mac_id, req->dh_group_id, - req->public_key_id); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: received payload", - pos, len - EAP_PAX_ICV_LEN); - - if (data->state != PAX_INIT && data->mac_id != req->mac_id) { - wpa_printf(MSG_INFO, "EAP-PAX: MAC ID changed during " - "authentication (was 0x%d, is 0x%d)", - data->mac_id, req->mac_id); - ret->ignore = TRUE; - return NULL; - } - - if (data->state != PAX_INIT && data->dh_group_id != req->dh_group_id) { - wpa_printf(MSG_INFO, "EAP-PAX: DH Group ID changed during " - "authentication (was 0x%d, is 0x%d)", - data->dh_group_id, req->dh_group_id); - ret->ignore = TRUE; - return NULL; - } - - if (data->state != PAX_INIT && - data->public_key_id != req->public_key_id) { - wpa_printf(MSG_INFO, "EAP-PAX: Public Key ID changed during " - "authentication (was 0x%d, is 0x%d)", - data->public_key_id, req->public_key_id); - ret->ignore = TRUE; - return NULL; - } - - /* TODO: add support EAP_PAX_HMAC_SHA256_128 */ - if (req->mac_id != EAP_PAX_MAC_HMAC_SHA1_128) { - wpa_printf(MSG_INFO, "EAP-PAX: Unsupported MAC ID 0x%x", - req->mac_id); - ret->ignore = TRUE; - return NULL; - } - - if (req->dh_group_id != EAP_PAX_DH_GROUP_NONE) { - wpa_printf(MSG_INFO, "EAP-PAX: Unsupported DH Group ID 0x%x", - req->dh_group_id); - ret->ignore = TRUE; - return NULL; - } - - if (req->public_key_id != EAP_PAX_PUBLIC_KEY_NONE) { - wpa_printf(MSG_INFO, "EAP-PAX: Unsupported Public Key ID 0x%x", - req->public_key_id); - ret->ignore = TRUE; - return NULL; - } - - if (req->flags & EAP_PAX_FLAGS_MF) { - /* TODO: add support for reassembling fragments */ - wpa_printf(MSG_INFO, "EAP-PAX: fragmentation not supported - " - "ignored packet"); - ret->ignore = TRUE; - return NULL; - } - - icv = pos + len - EAP_PAX_ICV_LEN; - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", icv, EAP_PAX_ICV_LEN); - if (req->op_code == EAP_PAX_OP_STD_1) { - eap_pax_mac(req->mac_id, (u8 *) "", 0, - wpabuf_head(reqData), mlen, NULL, 0, NULL, 0, - icvbuf); - } else { - eap_pax_mac(req->mac_id, data->ick, EAP_PAX_ICK_LEN, - wpabuf_head(reqData), mlen, NULL, 0, NULL, 0, - icvbuf); - } - if (os_memcmp(icv, icvbuf, EAP_PAX_ICV_LEN) != 0) { - wpa_printf(MSG_DEBUG, "EAP-PAX: invalid ICV - ignoring the " - "message"); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: expected ICV", - icvbuf, EAP_PAX_ICV_LEN); - ret->ignore = TRUE; - return NULL; - } - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - switch (req->op_code) { - case EAP_PAX_OP_STD_1: - resp = eap_pax_process_std_1(data, ret, id, req, flen); - break; - case EAP_PAX_OP_STD_3: - resp = eap_pax_process_std_3(data, ret, id, req, flen); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-PAX: ignoring message with unknown " - "op_code %d", req->op_code); - ret->ignore = TRUE; - return NULL; - } - - if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; - } - - return resp; -} - - -static Boolean eap_pax_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_pax_data *data = priv; - return data->state == PAX_DONE; -} - - -static u8 * eap_pax_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_pax_data *data = priv; - u8 *key; - - if (data->state != PAX_DONE) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_MSK_LEN; - eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN, - "Master Session Key", data->rand.e, 2 * EAP_PAX_RAND_LEN, - EAP_MSK_LEN, key); - - return key; -} - - -static u8 * eap_pax_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_pax_data *data = priv; - u8 *key; - - if (data->state != PAX_DONE) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_EMSK_LEN; - eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN, - "Extended Master Session Key", - data->rand.e, 2 * EAP_PAX_RAND_LEN, - EAP_EMSK_LEN, key); - - return key; -} - - -int eap_peer_pax_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_PAX, "PAX"); - if (eap == NULL) - return -1; - - eap->init = eap_pax_init; - eap->deinit = eap_pax_deinit; - eap->process = eap_pax_process; - eap->isKeyAvailable = eap_pax_isKeyAvailable; - eap->getKey = eap_pax_getKey; - eap->get_emsk = eap_pax_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_peer/eap_peap.c b/contrib/hostapd/src/eap_peer/eap_peap.c deleted file mode 100644 index 894fc632fd..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_peap.c +++ /dev/null @@ -1,1288 +0,0 @@ -/* - * EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/sha1.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "eap_config.h" -#include "tls.h" -#include "eap_common/eap_tlv_common.h" -#include "eap_common/eap_peap_common.h" -#include "tncc.h" - - -/* Maximum supported PEAP version - * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt - * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt - * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt - */ -#define EAP_PEAP_VERSION 1 - - -static void eap_peap_deinit(struct eap_sm *sm, void *priv); - - -struct eap_peap_data { - struct eap_ssl_data ssl; - - int peap_version, force_peap_version, force_new_label; - - const struct eap_method *phase2_method; - void *phase2_priv; - int phase2_success; - int phase2_eap_success; - int phase2_eap_started; - - struct eap_method_type phase2_type; - struct eap_method_type *phase2_types; - size_t num_phase2_types; - - int peap_outer_success; /* 0 = PEAP terminated on Phase 2 inner - * EAP-Success - * 1 = reply with tunneled EAP-Success to inner - * EAP-Success and expect AS to send outer - * (unencrypted) EAP-Success after this - * 2 = reply with PEAP/TLS ACK to inner - * EAP-Success and expect AS to send outer - * (unencrypted) EAP-Success after this */ - int resuming; /* starting a resumed session */ - int reauth; /* reauthentication */ - u8 *key_data; - - struct wpabuf *pending_phase2_req; - enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding; - int crypto_binding_used; - u8 binding_nonce[32]; - u8 ipmk[40]; - u8 cmk[20]; - int soh; /* Whether IF-TNCCS-SOH (Statement of Health; Microsoft NAP) - * is enabled. */ -}; - - -static int eap_peap_parse_phase1(struct eap_peap_data *data, - const char *phase1) -{ - const char *pos; - - pos = os_strstr(phase1, "peapver="); - if (pos) { - data->force_peap_version = atoi(pos + 8); - data->peap_version = data->force_peap_version; - wpa_printf(MSG_DEBUG, "EAP-PEAP: Forced PEAP version %d", - data->force_peap_version); - } - - if (os_strstr(phase1, "peaplabel=1")) { - data->force_new_label = 1; - wpa_printf(MSG_DEBUG, "EAP-PEAP: Force new label for key " - "derivation"); - } - - if (os_strstr(phase1, "peap_outer_success=0")) { - data->peap_outer_success = 0; - wpa_printf(MSG_DEBUG, "EAP-PEAP: terminate authentication on " - "tunneled EAP-Success"); - } else if (os_strstr(phase1, "peap_outer_success=1")) { - data->peap_outer_success = 1; - wpa_printf(MSG_DEBUG, "EAP-PEAP: send tunneled EAP-Success " - "after receiving tunneled EAP-Success"); - } else if (os_strstr(phase1, "peap_outer_success=2")) { - data->peap_outer_success = 2; - wpa_printf(MSG_DEBUG, "EAP-PEAP: send PEAP/TLS ACK after " - "receiving tunneled EAP-Success"); - } - - if (os_strstr(phase1, "crypto_binding=0")) { - data->crypto_binding = NO_BINDING; - wpa_printf(MSG_DEBUG, "EAP-PEAP: Do not use cryptobinding"); - } else if (os_strstr(phase1, "crypto_binding=1")) { - data->crypto_binding = OPTIONAL_BINDING; - wpa_printf(MSG_DEBUG, "EAP-PEAP: Optional cryptobinding"); - } else if (os_strstr(phase1, "crypto_binding=2")) { - data->crypto_binding = REQUIRE_BINDING; - wpa_printf(MSG_DEBUG, "EAP-PEAP: Require cryptobinding"); - } - -#ifdef EAP_TNC - if (os_strstr(phase1, "tnc=soh2")) { - data->soh = 2; - wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled"); - } else if (os_strstr(phase1, "tnc=soh1")) { - data->soh = 1; - wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 1 enabled"); - } else if (os_strstr(phase1, "tnc=soh")) { - data->soh = 2; - wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled"); - } -#endif /* EAP_TNC */ - - return 0; -} - - -static void * eap_peap_init(struct eap_sm *sm) -{ - struct eap_peap_data *data; - struct eap_peer_config *config = eap_get_config(sm); - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - sm->peap_done = FALSE; - data->peap_version = EAP_PEAP_VERSION; - data->force_peap_version = -1; - data->peap_outer_success = 2; - data->crypto_binding = OPTIONAL_BINDING; - - if (config && config->phase1 && - eap_peap_parse_phase1(data, config->phase1) < 0) { - eap_peap_deinit(sm, data); - return NULL; - } - - if (eap_peer_select_phase2_methods(config, "auth=", - &data->phase2_types, - &data->num_phase2_types) < 0) { - eap_peap_deinit(sm, data); - return NULL; - } - - data->phase2_type.vendor = EAP_VENDOR_IETF; - data->phase2_type.method = EAP_TYPE_NONE; - - if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) { - wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL."); - eap_peap_deinit(sm, data); - return NULL; - } - - return data; -} - - -static void eap_peap_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - if (data == NULL) - return; - if (data->phase2_priv && data->phase2_method) - data->phase2_method->deinit(sm, data->phase2_priv); - os_free(data->phase2_types); - eap_peer_tls_ssl_deinit(sm, &data->ssl); - os_free(data->key_data); - wpabuf_free(data->pending_phase2_req); - os_free(data); -} - - -/** - * eap_tlv_build_nak - Build EAP-TLV NAK message - * @id: EAP identifier for the header - * @nak_type: TLV type (EAP_TLV_*) - * Returns: Buffer to the allocated EAP-TLV NAK message or %NULL on failure - * - * This funtion builds an EAP-TLV NAK message. The caller is responsible for - * freeing the returned buffer. - */ -static struct wpabuf * eap_tlv_build_nak(int id, u16 nak_type) -{ - struct wpabuf *msg; - - msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, 10, - EAP_CODE_RESPONSE, id); - if (msg == NULL) - return NULL; - - wpabuf_put_u8(msg, 0x80); /* Mandatory */ - wpabuf_put_u8(msg, EAP_TLV_NAK_TLV); - wpabuf_put_be16(msg, 6); /* Length */ - wpabuf_put_be32(msg, 0); /* Vendor-Id */ - wpabuf_put_be16(msg, nak_type); /* NAK-Type */ - - return msg; -} - - -static int eap_peap_get_isk(struct eap_sm *sm, struct eap_peap_data *data, - u8 *isk, size_t isk_len) -{ - u8 *key; - size_t key_len; - - os_memset(isk, 0, isk_len); - if (data->phase2_method == NULL || data->phase2_priv == NULL || - data->phase2_method->isKeyAvailable == NULL || - data->phase2_method->getKey == NULL) - return 0; - - if (!data->phase2_method->isKeyAvailable(sm, data->phase2_priv) || - (key = data->phase2_method->getKey(sm, data->phase2_priv, - &key_len)) == NULL) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not get key material " - "from Phase 2"); - return -1; - } - - if (key_len > isk_len) - key_len = isk_len; - os_memcpy(isk, key, key_len); - os_free(key); - - return 0; -} - - -static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) -{ - u8 *tk; - u8 isk[32], imck[60]; - - /* - * Tunnel key (TK) is the first 60 octets of the key generated by - * phase 1 of PEAP (based on TLS). - */ - tk = data->key_data; - if (tk == NULL) - return -1; - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60); - - if (data->reauth && - tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) { - /* Fast-connect: IPMK|CMK = TK */ - os_memcpy(data->ipmk, tk, 40); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK from TK", - data->ipmk, 40); - os_memcpy(data->cmk, tk + 40, 20); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK from TK", - data->cmk, 20); - return 0; - } - - if (eap_peap_get_isk(sm, data, isk, sizeof(isk)) < 0) - return -1; - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk)); - - /* - * IPMK Seed = "Inner Methods Compound Keys" | ISK - * TempKey = First 40 octets of TK - * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60) - * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space - * in the end of the label just before ISK; is that just a typo?) - */ - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40); - peap_prfplus(data->peap_version, tk, 40, "Inner Methods Compound Keys", - isk, sizeof(isk), imck, sizeof(imck)); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)", - imck, sizeof(imck)); - - os_memcpy(data->ipmk, imck, 40); - 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); - - return 0; -} - - -static int eap_tlv_add_cryptobinding(struct eap_sm *sm, - struct eap_peap_data *data, - struct wpabuf *buf) -{ - u8 *mac; - u8 eap_type = EAP_TYPE_PEAP; - const u8 *addr[2]; - size_t len[2]; - u16 tlv_type; - - /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ - addr[0] = wpabuf_put(buf, 0); - len[0] = 60; - addr[1] = &eap_type; - len[1] = 1; - - tlv_type = EAP_TLV_CRYPTO_BINDING_TLV; - if (data->peap_version >= 2) - tlv_type |= EAP_TLV_TYPE_MANDATORY; - wpabuf_put_be16(buf, tlv_type); - wpabuf_put_be16(buf, 56); - - wpabuf_put_u8(buf, 0); /* Reserved */ - wpabuf_put_u8(buf, data->peap_version); /* Version */ - wpabuf_put_u8(buf, data->peap_version); /* RecvVersion */ - wpabuf_put_u8(buf, 1); /* SubType: 0 = Request, 1 = Response */ - wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */ - mac = wpabuf_put(buf, 20); /* Compound_MAC */ - wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK", data->cmk, 20); - wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1", - addr[0], len[0]); - wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2", - addr[1], len[1]); - hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac); - wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", mac, SHA1_MAC_LEN); - data->crypto_binding_used = 1; - - return 0; -} - - -/** - * eap_tlv_build_result - Build EAP-TLV Result message - * @id: EAP identifier for the header - * @status: Status (EAP_TLV_RESULT_SUCCESS or EAP_TLV_RESULT_FAILURE) - * Returns: Buffer to the allocated EAP-TLV Result message or %NULL on failure - * - * This funtion builds an EAP-TLV Result message. The caller is responsible for - * freeing the returned buffer. - */ -static struct wpabuf * eap_tlv_build_result(struct eap_sm *sm, - struct eap_peap_data *data, - int crypto_tlv_used, - int id, u16 status) -{ - struct wpabuf *msg; - size_t len; - - if (data->crypto_binding == NO_BINDING) - crypto_tlv_used = 0; - - len = 6; - if (crypto_tlv_used) - len += 60; /* Cryptobinding TLV */ - msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, len, - EAP_CODE_RESPONSE, id); - if (msg == NULL) - return NULL; - - wpabuf_put_u8(msg, 0x80); /* Mandatory */ - wpabuf_put_u8(msg, EAP_TLV_RESULT_TLV); - wpabuf_put_be16(msg, 2); /* Length */ - wpabuf_put_be16(msg, status); /* Status */ - - if (crypto_tlv_used && eap_tlv_add_cryptobinding(sm, data, msg)) { - wpabuf_free(msg); - return NULL; - } - - return msg; -} - - -static int eap_tlv_validate_cryptobinding(struct eap_sm *sm, - struct eap_peap_data *data, - const u8 *crypto_tlv, - size_t crypto_tlv_len) -{ - u8 buf[61], mac[SHA1_MAC_LEN]; - const u8 *pos; - - if (eap_peap_derive_cmk(sm, data) < 0) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not derive CMK"); - return -1; - } - - if (crypto_tlv_len != 4 + 56) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV " - "length %d", (int) crypto_tlv_len); - return -1; - } - - pos = crypto_tlv; - pos += 4; /* TLV header */ - if (pos[1] != data->peap_version) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version " - "mismatch (was %d; expected %d)", - pos[1], data->peap_version); - return -1; - } - - if (pos[3] != 0) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV " - "SubType %d", pos[3]); - return -1; - } - pos += 4; - os_memcpy(data->binding_nonce, pos, 32); - pos += 32; /* Nonce */ - - /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ - os_memcpy(buf, crypto_tlv, 60); - os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */ - buf[60] = EAP_TYPE_PEAP; - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Compound_MAC data", - buf, sizeof(buf)); - hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac); - - if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in " - "cryptobinding TLV"); - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received MAC", - pos, SHA1_MAC_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Expected MAC", - mac, SHA1_MAC_LEN); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received"); - - return 0; -} - - -/** - * eap_tlv_process - Process a received EAP-TLV message and generate a response - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @ret: Return values from EAP request validation and processing - * @req: EAP-TLV request to be processed. The caller must have validated that - * the buffer is large enough to contain full request (hdr->length bytes) and - * that the EAP type is EAP_TYPE_TLV. - * @resp: Buffer to return a pointer to the allocated response message. This - * field should be initialized to %NULL before the call. The value will be - * updated if a response message is generated. The caller is responsible for - * freeing the allocated message. - * @force_failure: Force negotiation to fail - * Returns: 0 on success, -1 on failure - */ -static int eap_tlv_process(struct eap_sm *sm, struct eap_peap_data *data, - struct eap_method_ret *ret, - const struct wpabuf *req, struct wpabuf **resp, - int force_failure) -{ - size_t left, tlv_len; - const u8 *pos; - const u8 *result_tlv = NULL, *crypto_tlv = NULL; - size_t result_tlv_len = 0, crypto_tlv_len = 0; - int tlv_type, mandatory; - - /* Parse TLVs */ - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, req, &left); - if (pos == NULL) - return -1; - wpa_hexdump(MSG_DEBUG, "EAP-TLV: Received TLVs", pos, left); - while (left >= 4) { - mandatory = !!(pos[0] & 0x80); - tlv_type = WPA_GET_BE16(pos) & 0x3fff; - pos += 2; - tlv_len = WPA_GET_BE16(pos); - pos += 2; - left -= 4; - if (tlv_len > left) { - wpa_printf(MSG_DEBUG, "EAP-TLV: TLV underrun " - "(tlv_len=%lu left=%lu)", - (unsigned long) tlv_len, - (unsigned long) left); - return -1; - } - switch (tlv_type) { - case EAP_TLV_RESULT_TLV: - result_tlv = pos; - result_tlv_len = tlv_len; - break; - case EAP_TLV_CRYPTO_BINDING_TLV: - crypto_tlv = pos; - crypto_tlv_len = tlv_len; - break; - default: - wpa_printf(MSG_DEBUG, "EAP-TLV: Unsupported TLV Type " - "%d%s", tlv_type, - mandatory ? " (mandatory)" : ""); - if (mandatory) { - /* NAK TLV and ignore all TLVs in this packet. - */ - *resp = eap_tlv_build_nak(eap_get_id(req), - tlv_type); - return *resp == NULL ? -1 : 0; - } - /* Ignore this TLV, but process other TLVs */ - break; - } - - pos += tlv_len; - left -= tlv_len; - } - if (left) { - wpa_printf(MSG_DEBUG, "EAP-TLV: Last TLV too short in " - "Request (left=%lu)", (unsigned long) left); - return -1; - } - - /* Process supported TLVs */ - if (crypto_tlv && data->crypto_binding != NO_BINDING) { - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV", - crypto_tlv, crypto_tlv_len); - if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4, - crypto_tlv_len + 4) < 0) { - if (result_tlv == NULL) - return -1; - force_failure = 1; - crypto_tlv = NULL; /* do not include Cryptobinding TLV - * in response, if the received - * cryptobinding was invalid. */ - } - } else if (!crypto_tlv && data->crypto_binding == REQUIRE_BINDING) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV"); - return -1; - } - - if (result_tlv) { - int status, resp_status; - wpa_hexdump(MSG_DEBUG, "EAP-TLV: Result TLV", - result_tlv, result_tlv_len); - if (result_tlv_len < 2) { - wpa_printf(MSG_INFO, "EAP-TLV: Too short Result TLV " - "(len=%lu)", - (unsigned long) result_tlv_len); - return -1; - } - status = WPA_GET_BE16(result_tlv); - if (status == EAP_TLV_RESULT_SUCCESS) { - wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success " - "- EAP-TLV/Phase2 Completed"); - if (force_failure) { - wpa_printf(MSG_INFO, "EAP-TLV: Earlier failure" - " - force failed Phase 2"); - resp_status = EAP_TLV_RESULT_FAILURE; - ret->decision = DECISION_FAIL; - } else { - resp_status = EAP_TLV_RESULT_SUCCESS; - ret->decision = DECISION_UNCOND_SUCC; - } - } else if (status == EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure"); - resp_status = EAP_TLV_RESULT_FAILURE; - ret->decision = DECISION_FAIL; - } else { - wpa_printf(MSG_INFO, "EAP-TLV: Unknown TLV Result " - "Status %d", status); - resp_status = EAP_TLV_RESULT_FAILURE; - ret->decision = DECISION_FAIL; - } - ret->methodState = METHOD_DONE; - - *resp = eap_tlv_build_result(sm, data, crypto_tlv != NULL, - eap_get_id(req), resp_status); - } - - return 0; -} - - -static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf) -{ - struct wpabuf *e; - struct eap_tlv_hdr *tlv; - - if (buf == NULL) - return NULL; - - /* Encapsulate EAP packet in EAP-Payload TLV */ - wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV"); - e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf)); - if (e == NULL) { - wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory " - "for TLV encapsulation"); - wpabuf_free(buf); - return NULL; - } - tlv = wpabuf_put(e, sizeof(*tlv)); - tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - EAP_TLV_EAP_PAYLOAD_TLV); - tlv->length = host_to_be16(wpabuf_len(buf)); - wpabuf_put_buf(e, buf); - wpabuf_free(buf); - return e; -} - - -static int eap_peap_phase2_request(struct eap_sm *sm, - struct eap_peap_data *data, - struct eap_method_ret *ret, - struct wpabuf *req, - struct wpabuf **resp) -{ - struct eap_hdr *hdr = wpabuf_mhead(req); - size_t len = be_to_host16(hdr->length); - u8 *pos; - struct eap_method_ret iret; - struct eap_peer_config *config = eap_get_config(sm); - - if (len <= sizeof(struct eap_hdr)) { - wpa_printf(MSG_INFO, "EAP-PEAP: too short " - "Phase 2 request (len=%lu)", (unsigned long) len); - return -1; - } - pos = (u8 *) (hdr + 1); - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: type=%d", *pos); - switch (*pos) { - case EAP_TYPE_IDENTITY: - *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1); - break; - case EAP_TYPE_TLV: - os_memset(&iret, 0, sizeof(iret)); - if (eap_tlv_process(sm, data, &iret, req, resp, - data->phase2_eap_started && - !data->phase2_eap_success)) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return -1; - } - if (iret.methodState == METHOD_DONE || - iret.methodState == METHOD_MAY_CONT) { - ret->methodState = iret.methodState; - ret->decision = iret.decision; - data->phase2_success = 1; - } - break; - case EAP_TYPE_EXPANDED: -#ifdef EAP_TNC - if (data->soh) { - const u8 *epos; - size_t eleft; - - epos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, - req, &eleft); - if (epos) { - struct wpabuf *buf; - wpa_printf(MSG_DEBUG, - "EAP-PEAP: SoH EAP Extensions"); - buf = tncc_process_soh_request(data->soh, - epos, eleft); - if (buf) { - *resp = eap_msg_alloc( - EAP_VENDOR_MICROSOFT, 0x21, - wpabuf_len(buf), - EAP_CODE_RESPONSE, - hdr->identifier); - if (*resp == NULL) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return -1; - } - wpabuf_put_buf(*resp, buf); - wpabuf_free(buf); - break; - } - } - } -#endif /* EAP_TNC */ - /* fall through */ - default: - if (data->phase2_type.vendor == EAP_VENDOR_IETF && - data->phase2_type.method == EAP_TYPE_NONE) { - size_t i; - for (i = 0; i < data->num_phase2_types; i++) { - if (data->phase2_types[i].vendor != - EAP_VENDOR_IETF || - data->phase2_types[i].method != *pos) - continue; - - data->phase2_type.vendor = - data->phase2_types[i].vendor; - data->phase2_type.method = - data->phase2_types[i].method; - wpa_printf(MSG_DEBUG, "EAP-PEAP: Selected " - "Phase 2 EAP vendor %d method %d", - data->phase2_type.vendor, - data->phase2_type.method); - break; - } - } - if (*pos != data->phase2_type.method || - *pos == EAP_TYPE_NONE) { - if (eap_peer_tls_phase2_nak(data->phase2_types, - data->num_phase2_types, - hdr, resp)) - return -1; - return 0; - } - - if (data->phase2_priv == NULL) { - data->phase2_method = eap_peer_get_eap_method( - data->phase2_type.vendor, - data->phase2_type.method); - if (data->phase2_method) { - sm->init_phase2 = 1; - data->phase2_priv = - data->phase2_method->init(sm); - sm->init_phase2 = 0; - } - } - if (data->phase2_priv == NULL || data->phase2_method == NULL) { - wpa_printf(MSG_INFO, "EAP-PEAP: failed to initialize " - "Phase 2 EAP method %d", *pos); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return -1; - } - data->phase2_eap_started = 1; - os_memset(&iret, 0, sizeof(iret)); - *resp = data->phase2_method->process(sm, data->phase2_priv, - &iret, req); - if ((iret.methodState == METHOD_DONE || - iret.methodState == METHOD_MAY_CONT) && - (iret.decision == DECISION_UNCOND_SUCC || - iret.decision == DECISION_COND_SUCC)) { - data->phase2_eap_success = 1; - data->phase2_success = 1; - } - break; - } - - 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); - data->pending_phase2_req = wpabuf_alloc_copy(hdr, len); - } - - return 0; -} - - -static int eap_peap_decrypt(struct eap_sm *sm, struct eap_peap_data *data, - struct eap_method_ret *ret, - const struct eap_hdr *req, - const struct wpabuf *in_data, - struct wpabuf **out_data) -{ - struct wpabuf *in_decrypted = NULL; - int res, skip_change = 0; - struct eap_hdr *hdr, *rhdr; - struct wpabuf *resp = NULL; - size_t len; - - wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for" - " Phase 2", (unsigned long) wpabuf_len(in_data)); - - if (data->pending_phase2_req) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 request - " - "skip decryption and use old data"); - /* Clear TLS reassembly state. */ - eap_peer_tls_reset_input(&data->ssl); - in_decrypted = data->pending_phase2_req; - data->pending_phase2_req = NULL; - skip_change = 1; - goto continue_req; - } - - if (wpabuf_len(in_data) == 0 && sm->workaround && - data->phase2_success) { - /* - * Cisco ACS seems to be using TLS ACK to terminate - * EAP-PEAPv0/GTC. Try to reply with TLS ACK. - */ - wpa_printf(MSG_DEBUG, "EAP-PEAP: Received TLS ACK, but " - "expected data - acknowledge with TLS ACK since " - "Phase 2 has been completed"); - ret->decision = DECISION_COND_SUCC; - ret->methodState = METHOD_DONE; - return 1; - } else if (wpabuf_len(in_data) == 0) { - /* Received TLS ACK - requesting more fragments */ - return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP, - data->peap_version, - req->identifier, NULL, out_data); - } - - res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted); - if (res) - return res; - -continue_req: - wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", - in_decrypted); - - hdr = wpabuf_mhead(in_decrypted); - if (wpabuf_len(in_decrypted) == 5 && hdr->code == EAP_CODE_REQUEST && - be_to_host16(hdr->length) == 5 && - eap_get_type(in_decrypted) == EAP_TYPE_IDENTITY) { - /* At least FreeRADIUS seems to send full EAP header with - * EAP Request Identity */ - skip_change = 1; - } - if (wpabuf_len(in_decrypted) >= 5 && hdr->code == EAP_CODE_REQUEST && - eap_get_type(in_decrypted) == EAP_TYPE_TLV) { - skip_change = 1; - } - - if (data->peap_version == 0 && !skip_change) { - struct eap_hdr *nhdr; - struct wpabuf *nmsg = wpabuf_alloc(sizeof(struct eap_hdr) + - wpabuf_len(in_decrypted)); - if (nmsg == NULL) { - wpabuf_free(in_decrypted); - return 0; - } - nhdr = wpabuf_put(nmsg, sizeof(*nhdr)); - wpabuf_put_buf(nmsg, in_decrypted); - nhdr->code = req->code; - nhdr->identifier = req->identifier; - nhdr->length = host_to_be16(sizeof(struct eap_hdr) + - wpabuf_len(in_decrypted)); - - wpabuf_free(in_decrypted); - in_decrypted = nmsg; - } - - if (data->peap_version >= 2) { - struct eap_tlv_hdr *tlv; - struct wpabuf *nmsg; - - if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) { - wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 " - "EAP TLV"); - wpabuf_free(in_decrypted); - return 0; - } - tlv = wpabuf_mhead(in_decrypted); - if ((be_to_host16(tlv->tlv_type) & 0x3fff) != - EAP_TLV_EAP_PAYLOAD_TLV) { - wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV"); - wpabuf_free(in_decrypted); - return 0; - } - if (sizeof(*tlv) + be_to_host16(tlv->length) > - wpabuf_len(in_decrypted)) { - wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV " - "length"); - wpabuf_free(in_decrypted); - return 0; - } - hdr = (struct eap_hdr *) (tlv + 1); - if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) { - wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full " - "EAP packet in EAP TLV"); - wpabuf_free(in_decrypted); - return 0; - } - - nmsg = wpabuf_alloc(be_to_host16(hdr->length)); - if (nmsg == NULL) { - wpabuf_free(in_decrypted); - return 0; - } - - wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length)); - wpabuf_free(in_decrypted); - in_decrypted = nmsg; - } - - hdr = wpabuf_mhead(in_decrypted); - if (wpabuf_len(in_decrypted) < sizeof(*hdr)) { - wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 " - "EAP frame (len=%lu)", - (unsigned long) wpabuf_len(in_decrypted)); - wpabuf_free(in_decrypted); - return 0; - } - len = be_to_host16(hdr->length); - if (len > wpabuf_len(in_decrypted)) { - wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in " - "Phase 2 EAP frame (len=%lu hdr->length=%lu)", - (unsigned long) wpabuf_len(in_decrypted), - (unsigned long) len); - wpabuf_free(in_decrypted); - return 0; - } - if (len < wpabuf_len(in_decrypted)) { - wpa_printf(MSG_INFO, "EAP-PEAP: Odd.. Phase 2 EAP header has " - "shorter length than full decrypted data " - "(%lu < %lu)", - (unsigned long) len, - (unsigned long) wpabuf_len(in_decrypted)); - } - wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d " - "identifier=%d length=%lu", hdr->code, hdr->identifier, - (unsigned long) len); - switch (hdr->code) { - case EAP_CODE_REQUEST: - if (eap_peap_phase2_request(sm, data, ret, in_decrypted, - &resp)) { - wpabuf_free(in_decrypted); - wpa_printf(MSG_INFO, "EAP-PEAP: Phase2 Request " - "processing failed"); - return 0; - } - break; - case EAP_CODE_SUCCESS: - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success"); - if (data->peap_version == 1) { - /* EAP-Success within TLS tunnel is used to indicate - * shutdown of the TLS channel. The authentication has - * been completed. */ - if (data->phase2_eap_started && - !data->phase2_eap_success) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 " - "Success used to indicate success, " - "but Phase 2 EAP was not yet " - "completed successfully"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - wpabuf_free(in_decrypted); - return 0; - } - wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - " - "EAP-Success within TLS tunnel - " - "authentication completed"); - ret->decision = DECISION_UNCOND_SUCC; - ret->methodState = METHOD_DONE; - data->phase2_success = 1; - if (data->peap_outer_success == 2) { - wpabuf_free(in_decrypted); - wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK " - "to finish authentication"); - return 1; - } else if (data->peap_outer_success == 1) { - /* Reply with EAP-Success within the TLS - * channel to complete the authentication. */ - resp = wpabuf_alloc(sizeof(struct eap_hdr)); - if (resp) { - rhdr = wpabuf_put(resp, sizeof(*rhdr)); - rhdr->code = EAP_CODE_SUCCESS; - rhdr->identifier = hdr->identifier; - rhdr->length = - host_to_be16(sizeof(*rhdr)); - } - } else { - /* No EAP-Success expected for Phase 1 (outer, - * unencrypted auth), so force EAP state - * machine to SUCCESS state. */ - sm->peap_done = TRUE; - } - } else { - /* FIX: ? */ - } - break; - case EAP_CODE_FAILURE: - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure"); - ret->decision = DECISION_FAIL; - ret->methodState = METHOD_MAY_CONT; - ret->allowNotifications = FALSE; - /* Reply with EAP-Failure within the TLS channel to complete - * failure reporting. */ - resp = wpabuf_alloc(sizeof(struct eap_hdr)); - if (resp) { - rhdr = wpabuf_put(resp, sizeof(*rhdr)); - rhdr->code = EAP_CODE_FAILURE; - rhdr->identifier = hdr->identifier; - rhdr->length = host_to_be16(sizeof(*rhdr)); - } - break; - default: - wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in " - "Phase 2 EAP header", hdr->code); - break; - } - - wpabuf_free(in_decrypted); - - if (resp) { - int skip_change2 = 0; - struct wpabuf *rmsg, buf; - - wpa_hexdump_buf_key(MSG_DEBUG, - "EAP-PEAP: Encrypting Phase 2 data", resp); - /* PEAP version changes */ - if (data->peap_version >= 2) { - resp = eap_peapv2_tlv_eap_payload(resp); - if (resp == NULL) - return -1; - } - if (wpabuf_len(resp) >= 5 && - wpabuf_head_u8(resp)[0] == EAP_CODE_RESPONSE && - eap_get_type(resp) == EAP_TYPE_TLV) - skip_change2 = 1; - rmsg = resp; - if (data->peap_version == 0 && !skip_change2) { - wpabuf_set(&buf, wpabuf_head_u8(resp) + - sizeof(struct eap_hdr), - wpabuf_len(resp) - sizeof(struct eap_hdr)); - rmsg = &buf; - } - - if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP, - data->peap_version, req->identifier, - rmsg, out_data)) { - wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt " - "a Phase 2 frame"); - } - wpabuf_free(resp); - } - - return 0; -} - - -static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - const struct eap_hdr *req; - size_t left; - int res; - u8 flags, id; - struct wpabuf *resp; - const u8 *pos; - struct eap_peap_data *data = priv; - - pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_PEAP, ret, - reqData, &left, &flags); - if (pos == NULL) - return NULL; - req = wpabuf_head(reqData); - id = req->identifier; - - if (flags & EAP_TLS_FLAGS_START) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Start (server ver=%d, own " - "ver=%d)", flags & EAP_PEAP_VERSION_MASK, - data->peap_version); - if ((flags & EAP_PEAP_VERSION_MASK) < data->peap_version) - data->peap_version = flags & EAP_PEAP_VERSION_MASK; - if (data->force_peap_version >= 0 && - data->force_peap_version != data->peap_version) { - wpa_printf(MSG_WARNING, "EAP-PEAP: Failed to select " - "forced PEAP version %d", - data->force_peap_version); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-PEAP: Using PEAP version %d", - data->peap_version); - left = 0; /* make sure that this frame is empty, even though it - * should always be, anyway */ - } - - resp = NULL; - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && - !data->resuming) { - struct wpabuf msg; - wpabuf_set(&msg, pos, left); - res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp); - } else { - res = eap_peer_tls_process_helper(sm, &data->ssl, - EAP_TYPE_PEAP, - data->peap_version, id, pos, - left, &resp); - - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - char *label; - wpa_printf(MSG_DEBUG, - "EAP-PEAP: TLS done, proceed to Phase 2"); - os_free(data->key_data); - /* draft-josefsson-ppext-eap-tls-eap-05.txt - * specifies that PEAPv1 would use "client PEAP - * encryption" as the label. However, most existing - * PEAPv1 implementations seem to be using the old - * label, "client EAP encryption", instead. Use the old - * label by default, but allow it to be configured with - * phase1 parameter peaplabel=1. */ - if (data->peap_version > 1 || data->force_new_label) - label = "client PEAP encryption"; - else - label = "client EAP encryption"; - wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in " - "key derivation", label); - data->key_data = - eap_peer_tls_derive_key(sm, &data->ssl, label, - EAP_TLS_KEY_LEN); - if (data->key_data) { - wpa_hexdump_key(MSG_DEBUG, - "EAP-PEAP: Derived key", - data->key_data, - EAP_TLS_KEY_LEN); - } else { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to " - "derive key"); - } - - if (sm->workaround && data->resuming) { - /* - * At least few RADIUS servers (Aegis v1.1.6; - * but not v1.1.4; and Cisco ACS) seem to be - * terminating PEAPv1 (Aegis) or PEAPv0 (Cisco - * ACS) session resumption with outer - * EAP-Success. This does not seem to follow - * draft-josefsson-pppext-eap-tls-eap-05.txt - * section 4.2, so only allow this if EAP - * workarounds are enabled. - */ - wpa_printf(MSG_DEBUG, "EAP-PEAP: Workaround - " - "allow outer EAP-Success to " - "terminate PEAP resumption"); - ret->decision = DECISION_COND_SUCC; - data->phase2_success = 1; - } - - data->resuming = 0; - } - - if (res == 2) { - struct wpabuf msg; - /* - * Application data included in the handshake message. - */ - wpabuf_free(data->pending_phase2_req); - data->pending_phase2_req = resp; - resp = NULL; - wpabuf_set(&msg, pos, left); - res = eap_peap_decrypt(sm, data, ret, req, &msg, - &resp); - } - } - - if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; - } - - if (res == 1) { - wpabuf_free(resp); - return eap_peer_tls_build_ack(id, EAP_TYPE_PEAP, - data->peap_version); - } - - return resp; -} - - -static Boolean eap_peap_has_reauth_data(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - return tls_connection_established(sm->ssl_ctx, data->ssl.conn) && - data->phase2_success; -} - - -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); - data->pending_phase2_req = NULL; - data->crypto_binding_used = 0; -} - - -static void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - os_free(data->key_data); - data->key_data = NULL; - if (eap_peer_tls_reauth_init(sm, &data->ssl)) { - os_free(data); - return NULL; - } - if (data->phase2_priv && data->phase2_method && - data->phase2_method->init_for_reauth) - data->phase2_method->init_for_reauth(sm, data->phase2_priv); - data->phase2_success = 0; - data->phase2_eap_success = 0; - data->phase2_eap_started = 0; - data->resuming = 1; - data->reauth = 1; - sm->peap_done = FALSE; - return priv; -} - - -static int eap_peap_get_status(struct eap_sm *sm, void *priv, char *buf, - size_t buflen, int verbose) -{ - struct eap_peap_data *data = priv; - int len, ret; - - len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); - if (data->phase2_method) { - ret = os_snprintf(buf + len, buflen - len, - "EAP-PEAPv%d Phase2 method=%s\n", - data->peap_version, - data->phase2_method->name); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - } - return len; -} - - -static Boolean eap_peap_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - return data->key_data != NULL && data->phase2_success; -} - - -static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_peap_data *data = priv; - u8 *key; - - if (data->key_data == NULL || !data->phase2_success) - return NULL; - - key = os_malloc(EAP_TLS_KEY_LEN); - if (key == NULL) - return NULL; - - *len = EAP_TLS_KEY_LEN; - - if (data->crypto_binding_used) { - u8 csk[128]; - /* - * Note: It looks like Microsoft implementation requires null - * termination for this label while the one used for deriving - * IPMK|CMK did not use null termination. - */ - peap_prfplus(data->peap_version, data->ipmk, 40, - "Session Key Generating Function", - (u8 *) "\00", 1, csk, sizeof(csk)); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk)); - os_memcpy(key, csk, EAP_TLS_KEY_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key", - key, EAP_TLS_KEY_LEN); - } else - os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); - - return key; -} - - -int eap_peer_peap_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP"); - if (eap == NULL) - return -1; - - eap->init = eap_peap_init; - eap->deinit = eap_peap_deinit; - eap->process = eap_peap_process; - eap->isKeyAvailable = eap_peap_isKeyAvailable; - eap->getKey = eap_peap_getKey; - 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; - eap->init_for_reauth = eap_peap_init_for_reauth; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_peer/eap_psk.c b/contrib/hostapd/src/eap_peer/eap_psk.c deleted file mode 100644 index 1ce6356639..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_psk.c +++ /dev/null @@ -1,482 +0,0 @@ -/* - * EAP peer method: EAP-PSK (RFC 4764) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * Note: EAP-PSK is an EAP authentication method and as such, completely - * different from WPA-PSK. This file is not needed for WPA-PSK functionality. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_peer/eap_i.h" -#include "aes_wrap.h" -#include "eap_common/eap_psk_common.h" - - -struct eap_psk_data { - enum { PSK_INIT, PSK_MAC_SENT, PSK_DONE } state; - u8 rand_p[EAP_PSK_RAND_LEN]; - u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN]; - u8 *id_s, *id_p; - size_t id_s_len, id_p_len; - u8 msk[EAP_MSK_LEN]; - u8 emsk[EAP_EMSK_LEN]; -}; - - -static void * eap_psk_init(struct eap_sm *sm) -{ - struct eap_psk_data *data; - const u8 *identity, *password; - size_t identity_len, password_len; - - password = eap_get_config_password(sm, &password_len); - if (!password || password_len != 16) { - wpa_printf(MSG_INFO, "EAP-PSK: 16-octet pre-shared key not " - "configured"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - if (eap_psk_key_setup(password, data->ak, data->kdk)) { - os_free(data); - return NULL; - } - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN); - data->state = PSK_INIT; - - identity = eap_get_config_identity(sm, &identity_len); - if (identity) { - data->id_p = os_malloc(identity_len); - if (data->id_p) - os_memcpy(data->id_p, identity, identity_len); - data->id_p_len = identity_len; - } - if (data->id_p == NULL) { - wpa_printf(MSG_INFO, "EAP-PSK: could not get own identity"); - os_free(data); - return NULL; - } - - return data; -} - - -static void eap_psk_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_psk_data *data = priv; - os_free(data->id_s); - os_free(data->id_p); - os_free(data); -} - - -static struct wpabuf * eap_psk_process_1(struct eap_psk_data *data, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - const struct eap_psk_hdr_1 *hdr1; - struct eap_psk_hdr_2 *hdr2; - struct wpabuf *resp; - u8 *buf, *pos; - size_t buflen, len; - const u8 *cpos; - - wpa_printf(MSG_DEBUG, "EAP-PSK: in INIT state"); - - cpos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, reqData, &len); - hdr1 = (const struct eap_psk_hdr_1 *) cpos; - if (cpos == NULL || len < sizeof(*hdr1)) { - wpa_printf(MSG_INFO, "EAP-PSK: Invalid first message " - "length (%lu; expected %lu or more)", - (unsigned long) len, - (unsigned long) sizeof(*hdr1)); - ret->ignore = TRUE; - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr1->flags); - if (EAP_PSK_FLAGS_GET_T(hdr1->flags) != 0) { - wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 0)", - EAP_PSK_FLAGS_GET_T(hdr1->flags)); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-PSK: 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); - 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); - - if (os_get_random(data->rand_p, EAP_PSK_RAND_LEN)) { - wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data"); - ret->ignore = TRUE; - return NULL; - } - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, - sizeof(*hdr2) + data->id_p_len, EAP_CODE_RESPONSE, - eap_get_id(reqData)); - if (resp == NULL) - return NULL; - hdr2 = wpabuf_put(resp, sizeof(*hdr2)); - hdr2->flags = EAP_PSK_FLAGS_SET_T(1); /* T=1 */ - os_memcpy(hdr2->rand_s, hdr1->rand_s, EAP_PSK_RAND_LEN); - os_memcpy(hdr2->rand_p, data->rand_p, EAP_PSK_RAND_LEN); - wpabuf_put_data(resp, data->id_p, data->id_p_len); - /* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */ - buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN; - buf = os_malloc(buflen); - if (buf == NULL) { - wpabuf_free(resp); - return NULL; - } - os_memcpy(buf, data->id_p, data->id_p_len); - pos = buf + data->id_p_len; - os_memcpy(pos, data->id_s, data->id_s_len); - pos += data->id_s_len; - os_memcpy(pos, hdr1->rand_s, EAP_PSK_RAND_LEN); - pos += EAP_PSK_RAND_LEN; - os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN); - if (omac1_aes_128(data->ak, buf, buflen, hdr2->mac_p)) { - os_free(buf); - wpabuf_free(resp); - return NULL; - } - os_free(buf); - wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_P", hdr2->rand_p, - EAP_PSK_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", hdr2->mac_p, EAP_PSK_MAC_LEN); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_P", - data->id_p, data->id_p_len); - - data->state = PSK_MAC_SENT; - - return resp; -} - - -static struct wpabuf * eap_psk_process_3(struct eap_psk_data *data, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - const struct eap_psk_hdr_3 *hdr3; - struct eap_psk_hdr_4 *hdr4; - struct wpabuf *resp; - u8 *buf, *rpchannel, nonce[16], *decrypted; - const u8 *pchannel, *tag, *msg; - u8 mac[EAP_PSK_MAC_LEN]; - size_t buflen, left, data_len, len, plen; - int failed = 0; - const u8 *pos; - - wpa_printf(MSG_DEBUG, "EAP-PSK: in MAC_SENT state"); - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, - reqData, &len); - hdr3 = (const struct eap_psk_hdr_3 *) pos; - if (pos == NULL || len < sizeof(*hdr3)) { - wpa_printf(MSG_INFO, "EAP-PSK: Invalid third message " - "length (%lu; expected %lu or more)", - (unsigned long) len, - (unsigned long) sizeof(*hdr3)); - ret->ignore = TRUE; - return NULL; - } - left = len - sizeof(*hdr3); - pchannel = (const u8 *) (hdr3 + 1); - wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr3->flags); - if (EAP_PSK_FLAGS_GET_T(hdr3->flags) != 2) { - wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 2)", - EAP_PSK_FLAGS_GET_T(hdr3->flags)); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr3->rand_s, - EAP_PSK_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_S", hdr3->mac_s, EAP_PSK_MAC_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL", pchannel, left); - - if (left < 4 + 16 + 1) { - wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in " - "third message (len=%lu, expected 21)", - (unsigned long) left); - ret->ignore = TRUE; - return NULL; - } - - /* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */ - buflen = data->id_s_len + EAP_PSK_RAND_LEN; - buf = os_malloc(buflen); - if (buf == NULL) - return NULL; - os_memcpy(buf, data->id_s, data->id_s_len); - os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN); - if (omac1_aes_128(data->ak, buf, buflen, mac)) { - os_free(buf); - return NULL; - } - os_free(buf); - if (os_memcmp(mac, hdr3->mac_s, EAP_PSK_MAC_LEN) != 0) { - wpa_printf(MSG_WARNING, "EAP-PSK: Invalid MAC_S in third " - "message"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-PSK: MAC_S verified successfully"); - - if (eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, - data->msk, data->emsk)) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN); - - os_memset(nonce, 0, 12); - os_memcpy(nonce + 12, pchannel, 4); - pchannel += 4; - left -= 4; - - tag = pchannel; - pchannel += 16; - left -= 16; - - msg = pchannel; - - wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - nonce", - nonce, sizeof(nonce)); - wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - hdr", - wpabuf_head(reqData), 5); - wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - cipher msg", msg, left); - - decrypted = os_malloc(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), - sizeof(struct eap_hdr) + 1 + - sizeof(*hdr3) - EAP_PSK_MAC_LEN, decrypted, - left, tag)) { - wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed"); - os_free(decrypted); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message", - decrypted, left); - - /* Verify R flag */ - switch (decrypted[0] >> 6) { - case EAP_PSK_R_FLAG_CONT: - wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - CONT - unsupported"); - failed = 1; - break; - case EAP_PSK_R_FLAG_DONE_SUCCESS: - wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_SUCCESS"); - break; - case EAP_PSK_R_FLAG_DONE_FAILURE: - wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_FAILURE"); - wpa_printf(MSG_INFO, "EAP-PSK: Authentication server rejected " - "authentication"); - failed = 1; - break; - } - - data_len = 1; - if ((decrypted[0] & EAP_PSK_E_FLAG) && left > 1) - data_len++; - plen = sizeof(*hdr4) + 4 + 16 + data_len; - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, plen, - EAP_CODE_RESPONSE, eap_get_id(reqData)); - if (resp == NULL) { - os_free(decrypted); - return NULL; - } - hdr4 = wpabuf_put(resp, sizeof(*hdr4)); - hdr4->flags = EAP_PSK_FLAGS_SET_T(3); /* T=3 */ - os_memcpy(hdr4->rand_s, hdr3->rand_s, EAP_PSK_RAND_LEN); - rpchannel = wpabuf_put(resp, 4 + 16 + data_len); - - /* nonce++ */ - inc_byte_array(nonce, sizeof(nonce)); - os_memcpy(rpchannel, nonce + 12, 4); - - if (decrypted[0] & EAP_PSK_E_FLAG) { - wpa_printf(MSG_DEBUG, "EAP-PSK: Unsupported E (Ext) flag"); - failed = 1; - rpchannel[4 + 16] = (EAP_PSK_R_FLAG_DONE_FAILURE << 6) | - EAP_PSK_E_FLAG; - if (left > 1) { - /* Add empty EXT_Payload with same EXT_Type */ - rpchannel[4 + 16 + 1] = decrypted[1]; - } - } else if (failed) - rpchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_FAILURE << 6; - else - rpchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS << 6; - - wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (plaintext)", - rpchannel + 4 + 16, data_len); - if (aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), - wpabuf_head(resp), - sizeof(struct eap_hdr) + 1 + sizeof(*hdr4), - rpchannel + 4 + 16, data_len, rpchannel + 4)) { - os_free(decrypted); - wpabuf_free(resp); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (PCHANNEL)", - rpchannel, 4 + 16 + data_len); - - wpa_printf(MSG_DEBUG, "EAP-PSK: Completed %ssuccessfully", - failed ? "un" : ""); - data->state = PSK_DONE; - ret->methodState = METHOD_DONE; - ret->decision = failed ? DECISION_FAIL : DECISION_UNCOND_SUCC; - - os_free(decrypted); - - return resp; -} - - -static struct wpabuf * eap_psk_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_psk_data *data = priv; - const u8 *pos; - struct wpabuf *resp = NULL; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, reqData, &len); - if (pos == NULL) { - ret->ignore = TRUE; - return NULL; - } - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - switch (data->state) { - case PSK_INIT: - resp = eap_psk_process_1(data, ret, reqData); - break; - case PSK_MAC_SENT: - resp = eap_psk_process_3(data, ret, reqData); - break; - case PSK_DONE: - wpa_printf(MSG_DEBUG, "EAP-PSK: in DONE state - ignore " - "unexpected message"); - ret->ignore = TRUE; - return NULL; - } - - if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; - } - - return resp; -} - - -static Boolean eap_psk_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_psk_data *data = priv; - return data->state == PSK_DONE; -} - - -static u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_psk_data *data = priv; - u8 *key; - - if (data->state != PSK_DONE) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_MSK_LEN; - os_memcpy(key, data->msk, EAP_MSK_LEN); - - return key; -} - - -static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_psk_data *data = priv; - u8 *key; - - if (data->state != PSK_DONE) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_EMSK_LEN; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - - return key; -} - - -int eap_peer_psk_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK"); - if (eap == NULL) - return -1; - - eap->init = eap_psk_init; - eap->deinit = eap_psk_deinit; - eap->process = eap_psk_process; - eap->isKeyAvailable = eap_psk_isKeyAvailable; - eap->getKey = eap_psk_getKey; - eap->get_emsk = eap_psk_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_peer/eap_sake.c b/contrib/hostapd/src/eap_peer/eap_sake.c deleted file mode 100644 index bb06bb2f42..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_sake.c +++ /dev/null @@ -1,499 +0,0 @@ -/* - * EAP peer method: EAP-SAKE (RFC 4763) - * Copyright (c) 2006-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_peer/eap_i.h" -#include "eap_common/eap_sake_common.h" - -struct eap_sake_data { - enum { IDENTITY, CHALLENGE, CONFIRM, SUCCESS, FAILURE } state; - u8 root_secret_a[EAP_SAKE_ROOT_SECRET_LEN]; - u8 root_secret_b[EAP_SAKE_ROOT_SECRET_LEN]; - u8 rand_s[EAP_SAKE_RAND_LEN]; - u8 rand_p[EAP_SAKE_RAND_LEN]; - struct { - u8 auth[EAP_SAKE_TEK_AUTH_LEN]; - u8 cipher[EAP_SAKE_TEK_CIPHER_LEN]; - } tek; - u8 msk[EAP_MSK_LEN]; - u8 emsk[EAP_EMSK_LEN]; - u8 session_id; - int session_id_set; - u8 *peerid; - size_t peerid_len; - u8 *serverid; - size_t serverid_len; -}; - - -static const char * eap_sake_state_txt(int state) -{ - switch (state) { - case IDENTITY: - return "IDENTITY"; - case CHALLENGE: - return "CHALLENGE"; - case CONFIRM: - return "CONFIRM"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "?"; - } -} - - -static void eap_sake_state(struct eap_sake_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-SAKE: %s -> %s", - eap_sake_state_txt(data->state), - eap_sake_state_txt(state)); - data->state = state; -} - - -static void eap_sake_deinit(struct eap_sm *sm, void *priv); - - -static void * eap_sake_init(struct eap_sm *sm) -{ - struct eap_sake_data *data; - const u8 *identity, *password; - size_t identity_len, password_len; - - password = eap_get_config_password(sm, &password_len); - if (!password || password_len != 2 * EAP_SAKE_ROOT_SECRET_LEN) { - wpa_printf(MSG_INFO, "EAP-SAKE: No key of correct length " - "configured"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = IDENTITY; - - identity = eap_get_config_identity(sm, &identity_len); - if (identity) { - data->peerid = os_malloc(identity_len); - if (data->peerid == NULL) { - eap_sake_deinit(sm, data); - return NULL; - } - os_memcpy(data->peerid, identity, identity_len); - data->peerid_len = identity_len; - } - - os_memcpy(data->root_secret_a, password, EAP_SAKE_ROOT_SECRET_LEN); - os_memcpy(data->root_secret_b, - password + EAP_SAKE_ROOT_SECRET_LEN, - EAP_SAKE_ROOT_SECRET_LEN); - - return data; -} - - -static void eap_sake_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_sake_data *data = priv; - os_free(data->serverid); - os_free(data->peerid); - os_free(data); -} - - -static struct wpabuf * eap_sake_build_msg(struct eap_sake_data *data, - int id, size_t length, u8 subtype) -{ - struct eap_sake_hdr *sake; - struct wpabuf *msg; - size_t plen; - - plen = length + sizeof(struct eap_sake_hdr); - - msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_SAKE, plen, - EAP_CODE_RESPONSE, id); - if (msg == NULL) { - wpa_printf(MSG_ERROR, "EAP-SAKE: Failed to allocate memory " - "request"); - return NULL; - } - - sake = wpabuf_put(msg, sizeof(*sake)); - sake->version = EAP_SAKE_VERSION; - sake->session_id = data->session_id; - sake->subtype = subtype; - - return msg; -} - - -static struct wpabuf * eap_sake_process_identity(struct eap_sm *sm, - struct eap_sake_data *data, - struct eap_method_ret *ret, - const struct wpabuf *reqData, - const u8 *payload, - size_t payload_len) -{ - struct eap_sake_parse_attr attr; - struct wpabuf *resp; - - if (data->state != IDENTITY) { - ret->ignore = TRUE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Received Request/Identity"); - - if (eap_sake_parse_attributes(payload, payload_len, &attr)) - return NULL; - - if (!attr.perm_id_req && !attr.any_id_req) { - wpa_printf(MSG_INFO, "EAP-SAKE: No AT_PERM_ID_REQ or " - "AT_ANY_ID_REQ in Request/Identity"); - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending Response/Identity"); - - resp = eap_sake_build_msg(data, eap_get_id(reqData), - 2 + data->peerid_len, - EAP_SAKE_SUBTYPE_IDENTITY); - if (resp == NULL) - return NULL; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_PEERID"); - eap_sake_add_attr(resp, EAP_SAKE_AT_PEERID, - data->peerid, data->peerid_len); - - eap_sake_state(data, CHALLENGE); - - return resp; -} - - -static struct wpabuf * eap_sake_process_challenge(struct eap_sm *sm, - struct eap_sake_data *data, - struct eap_method_ret *ret, - const struct wpabuf *reqData, - const u8 *payload, - size_t payload_len) -{ - struct eap_sake_parse_attr attr; - struct wpabuf *resp; - u8 *rpos; - size_t rlen; - - if (data->state != IDENTITY && data->state != CHALLENGE) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: Request/Challenge received " - "in unexpected state (%d)", data->state); - ret->ignore = TRUE; - return NULL; - } - if (data->state == IDENTITY) - eap_sake_state(data, CHALLENGE); - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Received Request/Challenge"); - - if (eap_sake_parse_attributes(payload, payload_len, &attr)) - return NULL; - - if (!attr.rand_s) { - wpa_printf(MSG_INFO, "EAP-SAKE: Request/Challenge did not " - "include AT_RAND_S"); - return NULL; - } - - os_memcpy(data->rand_s, attr.rand_s, EAP_SAKE_RAND_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-SAKE: RAND_S (server rand)", - data->rand_s, EAP_SAKE_RAND_LEN); - - if (os_get_random(data->rand_p, EAP_SAKE_RAND_LEN)) { - wpa_printf(MSG_ERROR, "EAP-SAKE: Failed to get random data"); - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, "EAP-SAKE: RAND_P (peer rand)", - data->rand_p, EAP_SAKE_RAND_LEN); - - os_free(data->serverid); - data->serverid = NULL; - data->serverid_len = 0; - if (attr.serverid) { - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-SAKE: SERVERID", - attr.serverid, attr.serverid_len); - data->serverid = os_malloc(attr.serverid_len); - if (data->serverid == NULL) - return NULL; - os_memcpy(data->serverid, attr.serverid, attr.serverid_len); - data->serverid_len = attr.serverid_len; - } - - eap_sake_derive_keys(data->root_secret_a, data->root_secret_b, - data->rand_s, data->rand_p, - (u8 *) &data->tek, data->msk, data->emsk); - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending Response/Challenge"); - - rlen = 2 + EAP_SAKE_RAND_LEN + 2 + EAP_SAKE_MIC_LEN; - if (data->peerid) - rlen += 2 + data->peerid_len; - resp = eap_sake_build_msg(data, eap_get_id(reqData), rlen, - EAP_SAKE_SUBTYPE_CHALLENGE); - if (resp == NULL) - return NULL; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_RAND_P"); - eap_sake_add_attr(resp, EAP_SAKE_AT_RAND_P, - data->rand_p, EAP_SAKE_RAND_LEN); - - if (data->peerid) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_PEERID"); - eap_sake_add_attr(resp, EAP_SAKE_AT_PEERID, - data->peerid, data->peerid_len); - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_MIC_P"); - wpabuf_put_u8(resp, EAP_SAKE_AT_MIC_P); - wpabuf_put_u8(resp, 2 + EAP_SAKE_MIC_LEN); - rpos = wpabuf_put(resp, EAP_SAKE_MIC_LEN); - if (eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p, - data->serverid, data->serverid_len, - data->peerid, data->peerid_len, 1, - wpabuf_head(resp), wpabuf_len(resp), rpos, - rpos)) { - wpa_printf(MSG_INFO, "EAP-SAKE: Failed to compute MIC"); - wpabuf_free(resp); - return NULL; - } - - eap_sake_state(data, CONFIRM); - - return resp; -} - - -static struct wpabuf * eap_sake_process_confirm(struct eap_sm *sm, - struct eap_sake_data *data, - struct eap_method_ret *ret, - const struct wpabuf *reqData, - const u8 *payload, - size_t payload_len) -{ - struct eap_sake_parse_attr attr; - u8 mic_s[EAP_SAKE_MIC_LEN]; - struct wpabuf *resp; - u8 *rpos; - - if (data->state != CONFIRM) { - ret->ignore = TRUE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Received Request/Confirm"); - - if (eap_sake_parse_attributes(payload, payload_len, &attr)) - return NULL; - - if (!attr.mic_s) { - wpa_printf(MSG_INFO, "EAP-SAKE: Request/Confirm did not " - "include AT_MIC_S"); - return NULL; - } - - eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p, - data->serverid, data->serverid_len, - data->peerid, data->peerid_len, 0, - wpabuf_head(reqData), wpabuf_len(reqData), - attr.mic_s, mic_s); - if (os_memcmp(attr.mic_s, mic_s, EAP_SAKE_MIC_LEN) != 0) { - wpa_printf(MSG_INFO, "EAP-SAKE: Incorrect AT_MIC_S"); - eap_sake_state(data, FAILURE); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; - wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending " - "Response/Auth-Reject"); - return eap_sake_build_msg(data, eap_get_id(reqData), 0, - EAP_SAKE_SUBTYPE_AUTH_REJECT); - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending Response/Confirm"); - - resp = eap_sake_build_msg(data, eap_get_id(reqData), - 2 + EAP_SAKE_MIC_LEN, - EAP_SAKE_SUBTYPE_CONFIRM); - if (resp == NULL) - return NULL; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_MIC_P"); - wpabuf_put_u8(resp, EAP_SAKE_AT_MIC_P); - wpabuf_put_u8(resp, 2 + EAP_SAKE_MIC_LEN); - rpos = wpabuf_put(resp, EAP_SAKE_MIC_LEN); - if (eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p, - data->serverid, data->serverid_len, - data->peerid, data->peerid_len, 1, - wpabuf_head(resp), wpabuf_len(resp), rpos, - rpos)) { - wpa_printf(MSG_INFO, "EAP-SAKE: Failed to compute MIC"); - wpabuf_free(resp); - return NULL; - } - - eap_sake_state(data, SUCCESS); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = FALSE; - - return resp; -} - - -static struct wpabuf * eap_sake_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_sake_data *data = priv; - const struct eap_sake_hdr *req; - struct wpabuf *resp; - const u8 *pos, *end; - size_t len; - u8 subtype, session_id; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SAKE, reqData, &len); - if (pos == NULL || len < sizeof(struct eap_sake_hdr)) { - ret->ignore = TRUE; - return NULL; - } - - req = (const struct eap_sake_hdr *) pos; - end = pos + len; - subtype = req->subtype; - session_id = req->session_id; - pos = (const u8 *) (req + 1); - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Received frame: subtype %d " - "session_id %d", subtype, session_id); - wpa_hexdump(MSG_DEBUG, "EAP-SAKE: Received attributes", - pos, end - pos); - - if (data->session_id_set && data->session_id != session_id) { - wpa_printf(MSG_INFO, "EAP-SAKE: Session ID mismatch (%d,%d)", - session_id, data->session_id); - ret->ignore = TRUE; - return NULL; - } - data->session_id = session_id; - data->session_id_set = 1; - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - switch (subtype) { - case EAP_SAKE_SUBTYPE_IDENTITY: - resp = eap_sake_process_identity(sm, data, ret, reqData, - pos, end - pos); - break; - case EAP_SAKE_SUBTYPE_CHALLENGE: - resp = eap_sake_process_challenge(sm, data, ret, reqData, - pos, end - pos); - break; - case EAP_SAKE_SUBTYPE_CONFIRM: - resp = eap_sake_process_confirm(sm, data, ret, reqData, - pos, end - pos); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Ignoring message with " - "unknown subtype %d", subtype); - ret->ignore = TRUE; - return NULL; - } - - if (ret->methodState == METHOD_DONE) - ret->allowNotifications = FALSE; - - return resp; -} - - -static Boolean eap_sake_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_sake_data *data = priv; - return data->state == SUCCESS; -} - - -static u8 * eap_sake_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_sake_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->msk, EAP_MSK_LEN); - *len = EAP_MSK_LEN; - - return key; -} - - -static u8 * eap_sake_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_sake_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - - return key; -} - - -int eap_peer_sake_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_SAKE, "SAKE"); - if (eap == NULL) - return -1; - - eap->init = eap_sake_init; - eap->deinit = eap_sake_deinit; - eap->process = eap_sake_process; - eap->isKeyAvailable = eap_sake_isKeyAvailable; - eap->getKey = eap_sake_getKey; - eap->get_emsk = eap_sake_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_peer/eap_sim.c b/contrib/hostapd/src/eap_peer/eap_sim.c deleted file mode 100644 index 5e30d1f7ed..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_sim.c +++ /dev/null @@ -1,1102 +0,0 @@ -/* - * EAP peer method: EAP-SIM (RFC 4186) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_peer/eap_i.h" -#include "eap_config.h" -#include "pcsc_funcs.h" -#include "eap_common/eap_sim_common.h" -#ifdef CONFIG_SIM_SIMULATOR -#include "hlr_auc_gw/milenage.h" -#endif /* CONFIG_SIM_SIMULATOR */ - - -struct eap_sim_data { - u8 *ver_list; - size_t ver_list_len; - int selected_version; - size_t min_num_chal, num_chal; - - u8 kc[3][EAP_SIM_KC_LEN]; - u8 sres[3][EAP_SIM_SRES_LEN]; - u8 nonce_mt[EAP_SIM_NONCE_MT_LEN], nonce_s[EAP_SIM_NONCE_S_LEN]; - u8 mk[EAP_SIM_MK_LEN]; - u8 k_aut[EAP_SIM_K_AUT_LEN]; - u8 k_encr[EAP_SIM_K_ENCR_LEN]; - u8 msk[EAP_SIM_KEYING_DATA_LEN]; - u8 emsk[EAP_EMSK_LEN]; - u8 rand[3][GSM_RAND_LEN]; - - int num_id_req, num_notification; - u8 *pseudonym; - size_t pseudonym_len; - u8 *reauth_id; - size_t reauth_id_len; - int reauth; - unsigned int counter, counter_too_small; - u8 *last_eap_identity; - size_t last_eap_identity_len; - enum { - CONTINUE, RESULT_SUCCESS, RESULT_FAILURE, SUCCESS, FAILURE - } state; - int result_ind, use_result_ind; -}; - - -#ifndef CONFIG_NO_STDOUT_DEBUG -static const char * eap_sim_state_txt(int state) -{ - switch (state) { - case CONTINUE: - return "CONTINUE"; - case RESULT_SUCCESS: - return "RESULT_SUCCESS"; - case RESULT_FAILURE: - return "RESULT_FAILURE"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "?"; - } -} -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - -static void eap_sim_state(struct eap_sim_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-SIM: %s -> %s", - eap_sim_state_txt(data->state), - eap_sim_state_txt(state)); - data->state = state; -} - - -static void * eap_sim_init(struct eap_sm *sm) -{ - struct eap_sim_data *data; - struct eap_peer_config *config = eap_get_config(sm); - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - if (os_get_random(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data " - "for NONCE_MT"); - os_free(data); - return NULL; - } - - data->min_num_chal = 2; - if (config && config->phase1) { - char *pos = os_strstr(config->phase1, "sim_min_num_chal="); - if (pos) { - data->min_num_chal = atoi(pos + 17); - if (data->min_num_chal < 2 || data->min_num_chal > 3) { - wpa_printf(MSG_WARNING, "EAP-SIM: Invalid " - "sim_min_num_chal configuration " - "(%lu, expected 2 or 3)", - (unsigned long) data->min_num_chal); - os_free(data); - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-SIM: Set minimum number of " - "challenges to %lu", - (unsigned long) data->min_num_chal); - } - - data->result_ind = os_strstr(config->phase1, "result_ind=1") != - NULL; - } - - eap_sim_state(data, CONTINUE); - - return data; -} - - -static void eap_sim_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - if (data) { - os_free(data->ver_list); - os_free(data->pseudonym); - os_free(data->reauth_id); - os_free(data->last_eap_identity); - os_free(data); - } -} - - -static int eap_sim_gsm_auth(struct eap_sm *sm, struct eap_sim_data *data) -{ - struct eap_peer_config *conf; - - wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication algorithm"); - - conf = eap_get_config(sm); - if (conf == NULL) - return -1; - if (conf->pcsc) { - if (scard_gsm_auth(sm->scard_ctx, data->rand[0], - data->sres[0], data->kc[0]) || - scard_gsm_auth(sm->scard_ctx, data->rand[1], - data->sres[1], data->kc[1]) || - (data->num_chal > 2 && - scard_gsm_auth(sm->scard_ctx, data->rand[2], - data->sres[2], data->kc[2]))) { - wpa_printf(MSG_DEBUG, "EAP-SIM: GSM SIM " - "authentication could not be completed"); - return -1; - } - return 0; - } - -#ifdef CONFIG_SIM_SIMULATOR - if (conf->password) { - u8 opc[16], k[16]; - const char *pos; - size_t i; - wpa_printf(MSG_DEBUG, "EAP-SIM: Use internal GSM-Milenage " - "implementation for authentication"); - if (conf->password_len < 65) { - wpa_printf(MSG_DEBUG, "EAP-SIM: invalid GSM-Milenage " - "password"); - return -1; - } - pos = (const char *) conf->password; - if (hexstr2bin(pos, k, 16)) - return -1; - pos += 32; - if (*pos != ':') - return -1; - pos++; - - if (hexstr2bin(pos, opc, 16)) - return -1; - - for (i = 0; i < data->num_chal; i++) { - if (gsm_milenage(opc, k, data->rand[i], - data->sres[i], data->kc[i])) { - wpa_printf(MSG_DEBUG, "EAP-SIM: " - "GSM-Milenage authentication " - "could not be completed"); - return -1; - } - wpa_hexdump(MSG_DEBUG, "EAP-SIM: RAND", - data->rand[i], GSM_RAND_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: SRES", - data->sres[i], EAP_SIM_SRES_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: Kc", - data->kc[i], EAP_SIM_KC_LEN); - } - return 0; - } -#endif /* CONFIG_SIM_SIMULATOR */ - -#ifdef CONFIG_SIM_HARDCODED - /* These hardcoded Kc and SRES values are used for testing. RAND to - * KC/SREC mapping is very bogus as far as real authentication is - * concerned, but it is quite useful for cases where the AS is rotating - * the order of pre-configured values. */ - { - size_t i; - - wpa_printf(MSG_DEBUG, "EAP-SIM: Use hardcoded Kc and SRES " - "values for testing"); - - for (i = 0; i < data->num_chal; i++) { - if (data->rand[i][0] == 0xaa) { - os_memcpy(data->kc[i], - "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7", - EAP_SIM_KC_LEN); - os_memcpy(data->sres[i], "\xd1\xd2\xd3\xd4", - EAP_SIM_SRES_LEN); - } else if (data->rand[i][0] == 0xbb) { - os_memcpy(data->kc[i], - "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7", - EAP_SIM_KC_LEN); - os_memcpy(data->sres[i], "\xe1\xe2\xe3\xe4", - EAP_SIM_SRES_LEN); - } else { - os_memcpy(data->kc[i], - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7", - EAP_SIM_KC_LEN); - os_memcpy(data->sres[i], "\xf1\xf2\xf3\xf4", - EAP_SIM_SRES_LEN); - } - } - } - - return 0; - -#else /* CONFIG_SIM_HARDCODED */ - - wpa_printf(MSG_DEBUG, "EAP-SIM: No GSM authentication algorithm " - "enabled"); - return -1; - -#endif /* CONFIG_SIM_HARDCODED */ -} - - -static int eap_sim_supported_ver(int version) -{ - return version == EAP_SIM_VERSION; -} - - -#define CLEAR_PSEUDONYM 0x01 -#define CLEAR_REAUTH_ID 0x02 -#define CLEAR_EAP_ID 0x04 - -static void eap_sim_clear_identities(struct eap_sim_data *data, int id) -{ - wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old%s%s%s", - id & CLEAR_PSEUDONYM ? " pseudonym" : "", - id & CLEAR_REAUTH_ID ? " reauth_id" : "", - id & CLEAR_EAP_ID ? " eap_id" : ""); - if (id & CLEAR_PSEUDONYM) { - os_free(data->pseudonym); - data->pseudonym = NULL; - data->pseudonym_len = 0; - } - if (id & CLEAR_REAUTH_ID) { - os_free(data->reauth_id); - data->reauth_id = NULL; - data->reauth_id_len = 0; - } - if (id & CLEAR_EAP_ID) { - os_free(data->last_eap_identity); - data->last_eap_identity = NULL; - data->last_eap_identity_len = 0; - } -} - - -static int eap_sim_learn_ids(struct eap_sim_data *data, - struct eap_sim_attrs *attr) -{ - if (attr->next_pseudonym) { - os_free(data->pseudonym); - data->pseudonym = os_malloc(attr->next_pseudonym_len); - if (data->pseudonym == NULL) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for " - "next pseudonym"); - return -1; - } - os_memcpy(data->pseudonym, attr->next_pseudonym, - attr->next_pseudonym_len); - data->pseudonym_len = attr->next_pseudonym_len; - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-SIM: (encr) AT_NEXT_PSEUDONYM", - data->pseudonym, - data->pseudonym_len); - } - - if (attr->next_reauth_id) { - os_free(data->reauth_id); - data->reauth_id = os_malloc(attr->next_reauth_id_len); - if (data->reauth_id == NULL) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for " - "next reauth_id"); - return -1; - } - os_memcpy(data->reauth_id, attr->next_reauth_id, - attr->next_reauth_id_len); - data->reauth_id_len = attr->next_reauth_id_len; - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-SIM: (encr) AT_NEXT_REAUTH_ID", - data->reauth_id, - data->reauth_id_len); - } - - return 0; -} - - -static struct wpabuf * eap_sim_client_error(struct eap_sim_data *data, u8 id, - int err) -{ - struct eap_sim_msg *msg; - - eap_sim_state(data, FAILURE); - data->num_id_req = 0; - data->num_notification = 0; - - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM, - EAP_SIM_SUBTYPE_CLIENT_ERROR); - eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0); - return eap_sim_msg_finish(msg, NULL, NULL, 0); -} - - -static struct wpabuf * eap_sim_response_start(struct eap_sm *sm, - struct eap_sim_data *data, u8 id, - enum eap_sim_id_req id_req) -{ - const u8 *identity = NULL; - size_t identity_len = 0; - struct eap_sim_msg *msg; - - data->reauth = 0; - if (id_req == ANY_ID && data->reauth_id) { - identity = data->reauth_id; - identity_len = data->reauth_id_len; - data->reauth = 1; - } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) && - data->pseudonym) { - identity = data->pseudonym; - identity_len = data->pseudonym_len; - eap_sim_clear_identities(data, CLEAR_REAUTH_ID); - } else if (id_req != NO_ID_REQ) { - identity = eap_get_config_identity(sm, &identity_len); - if (identity) { - eap_sim_clear_identities(data, CLEAR_PSEUDONYM | - CLEAR_REAUTH_ID); - } - } - if (id_req != NO_ID_REQ) - eap_sim_clear_identities(data, CLEAR_EAP_ID); - - wpa_printf(MSG_DEBUG, "Generating EAP-SIM Start (id=%d)", id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, - EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START); - if (!data->reauth) { - wpa_hexdump(MSG_DEBUG, " AT_NONCE_MT", - data->nonce_mt, EAP_SIM_NONCE_MT_LEN); - eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_MT, 0, - data->nonce_mt, EAP_SIM_NONCE_MT_LEN); - wpa_printf(MSG_DEBUG, " AT_SELECTED_VERSION %d", - data->selected_version); - eap_sim_msg_add(msg, EAP_SIM_AT_SELECTED_VERSION, - data->selected_version, NULL, 0); - } - - if (identity) { - wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY", - identity, identity_len); - eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len, - identity, identity_len); - } - - return eap_sim_msg_finish(msg, NULL, NULL, 0); -} - - -static struct wpabuf * eap_sim_response_challenge(struct eap_sim_data *data, - u8 id) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "Generating EAP-SIM Challenge (id=%d)", id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM, - EAP_SIM_SUBTYPE_CHALLENGE); - if (data->use_result_ind) { - wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); - } - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, data->k_aut, (u8 *) data->sres, - data->num_chal * EAP_SIM_SRES_LEN); -} - - -static struct wpabuf * eap_sim_response_reauth(struct eap_sim_data *data, - u8 id, int counter_too_small) -{ - struct eap_sim_msg *msg; - unsigned int counter; - - wpa_printf(MSG_DEBUG, "Generating EAP-SIM Reauthentication (id=%d)", - id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM, - EAP_SIM_SUBTYPE_REAUTHENTICATION); - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); - - if (counter_too_small) { - wpa_printf(MSG_DEBUG, " *AT_COUNTER_TOO_SMALL"); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0); - counter = data->counter_too_small; - } else - counter = data->counter; - - wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); - - if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " - "AT_ENCR_DATA"); - eap_sim_msg_free(msg); - return NULL; - } - if (data->use_result_ind) { - wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); - } - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, data->k_aut, data->nonce_s, - EAP_SIM_NONCE_S_LEN); -} - - -static struct wpabuf * eap_sim_response_notification(struct eap_sim_data *data, - u8 id, u16 notification) -{ - struct eap_sim_msg *msg; - u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL; - - wpa_printf(MSG_DEBUG, "Generating EAP-SIM Notification (id=%d)", id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, - EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION); - if (k_aut && data->reauth) { - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, - EAP_SIM_AT_ENCR_DATA); - wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", data->counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, - NULL, 0); - if (eap_sim_msg_add_encr_end(msg, data->k_encr, - EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " - "AT_ENCR_DATA"); - eap_sim_msg_free(msg); - return NULL; - } - } - if (k_aut) { - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - } - return eap_sim_msg_finish(msg, k_aut, (u8 *) "", 0); -} - - -static struct wpabuf * eap_sim_process_start(struct eap_sm *sm, - struct eap_sim_data *data, u8 id, - struct eap_sim_attrs *attr) -{ - int selected_version = -1, id_error; - size_t i; - u8 *pos; - - wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Start"); - if (attr->version_list == NULL) { - wpa_printf(MSG_INFO, "EAP-SIM: No AT_VERSION_LIST in " - "SIM/Start"); - return eap_sim_client_error(data, id, - EAP_SIM_UNSUPPORTED_VERSION); - } - - os_free(data->ver_list); - data->ver_list = os_malloc(attr->version_list_len); - if (data->ver_list == NULL) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to allocate " - "memory for version list"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - os_memcpy(data->ver_list, attr->version_list, attr->version_list_len); - data->ver_list_len = attr->version_list_len; - pos = data->ver_list; - for (i = 0; i < data->ver_list_len / 2; i++) { - int ver = pos[0] * 256 + pos[1]; - pos += 2; - if (eap_sim_supported_ver(ver)) { - selected_version = ver; - break; - } - } - if (selected_version < 0) { - wpa_printf(MSG_INFO, "EAP-SIM: Could not find a supported " - "version"); - return eap_sim_client_error(data, id, - EAP_SIM_UNSUPPORTED_VERSION); - } - wpa_printf(MSG_DEBUG, "EAP-SIM: Selected Version %d", - selected_version); - data->selected_version = selected_version; - - id_error = 0; - switch (attr->id_req) { - case NO_ID_REQ: - break; - case ANY_ID: - if (data->num_id_req > 0) - id_error++; - data->num_id_req++; - break; - case FULLAUTH_ID: - if (data->num_id_req > 1) - id_error++; - data->num_id_req++; - break; - case PERMANENT_ID: - if (data->num_id_req > 2) - id_error++; - data->num_id_req++; - break; - } - if (id_error) { - wpa_printf(MSG_INFO, "EAP-SIM: Too many ID requests " - "used within one authentication"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - return eap_sim_response_start(sm, data, id, attr->id_req); -} - - -static struct wpabuf * eap_sim_process_challenge(struct eap_sm *sm, - struct eap_sim_data *data, - u8 id, - const struct wpabuf *reqData, - struct eap_sim_attrs *attr) -{ - const u8 *identity; - size_t identity_len; - struct eap_sim_attrs eattr; - - wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Challenge"); - data->reauth = 0; - if (!attr->mac || !attr->rand) { - wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message " - "did not include%s%s", - !attr->mac ? " AT_MAC" : "", - !attr->rand ? " AT_RAND" : ""); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - wpa_printf(MSG_DEBUG, "EAP-SIM: %lu challenges", - (unsigned long) attr->num_chal); - if (attr->num_chal < data->min_num_chal) { - wpa_printf(MSG_INFO, "EAP-SIM: Insufficient number of " - "challenges (%lu)", (unsigned long) attr->num_chal); - return eap_sim_client_error(data, id, - EAP_SIM_INSUFFICIENT_NUM_OF_CHAL); - } - if (attr->num_chal > 3) { - wpa_printf(MSG_INFO, "EAP-SIM: Too many challenges " - "(%lu)", (unsigned long) attr->num_chal); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - /* Verify that RANDs are different */ - if (os_memcmp(attr->rand, attr->rand + GSM_RAND_LEN, - GSM_RAND_LEN) == 0 || - (attr->num_chal > 2 && - (os_memcmp(attr->rand, attr->rand + 2 * GSM_RAND_LEN, - GSM_RAND_LEN) == 0 || - os_memcmp(attr->rand + GSM_RAND_LEN, - attr->rand + 2 * GSM_RAND_LEN, - GSM_RAND_LEN) == 0))) { - wpa_printf(MSG_INFO, "EAP-SIM: Same RAND used multiple times"); - return eap_sim_client_error(data, id, - EAP_SIM_RAND_NOT_FRESH); - } - - os_memcpy(data->rand, attr->rand, attr->num_chal * GSM_RAND_LEN); - data->num_chal = attr->num_chal; - - if (eap_sim_gsm_auth(sm, data)) { - wpa_printf(MSG_WARNING, "EAP-SIM: GSM authentication failed"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - if (data->last_eap_identity) { - identity = data->last_eap_identity; - identity_len = data->last_eap_identity_len; - } else if (data->pseudonym) { - identity = data->pseudonym; - identity_len = data->pseudonym_len; - } else - identity = eap_get_config_identity(sm, &identity_len); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Selected identity for MK " - "derivation", identity, identity_len); - eap_sim_derive_mk(identity, identity_len, data->nonce_mt, - data->selected_version, data->ver_list, - data->ver_list_len, data->num_chal, - (const u8 *) data->kc, data->mk); - eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, - data->emsk); - if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, data->nonce_mt, - EAP_SIM_NONCE_MT_LEN)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message " - "used invalid AT_MAC"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - /* Old reauthentication and pseudonym identities must not be used - * anymore. In other words, if no new identities are received, full - * authentication will be used on next reauthentication. */ - eap_sim_clear_identities(data, CLEAR_PSEUDONYM | CLEAR_REAUTH_ID | - CLEAR_EAP_ID); - - if (attr->encr_data) { - u8 *decrypted; - decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, - &eattr, 0); - if (decrypted == NULL) { - return eap_sim_client_error( - data, id, EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - eap_sim_learn_ids(data, &eattr); - os_free(decrypted); - } - - if (data->result_ind && attr->result_ind) - data->use_result_ind = 1; - - if (data->state != FAILURE && data->state != RESULT_FAILURE) { - eap_sim_state(data, data->use_result_ind ? - RESULT_SUCCESS : SUCCESS); - } - - data->num_id_req = 0; - data->num_notification = 0; - /* RFC 4186 specifies that counter is initialized to one after - * fullauth, but initializing it to zero makes it easier to implement - * reauth verification. */ - data->counter = 0; - return eap_sim_response_challenge(data, id); -} - - -static int eap_sim_process_notification_reauth(struct eap_sim_data *data, - struct eap_sim_attrs *attr) -{ - struct eap_sim_attrs eattr; - u8 *decrypted; - - if (attr->encr_data == NULL || attr->iv == NULL) { - wpa_printf(MSG_WARNING, "EAP-SIM: Notification message after " - "reauth did not include encrypted data"); - return -1; - } - - decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, &eattr, - 0); - if (decrypted == NULL) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " - "data from notification message"); - return -1; - } - - if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) { - wpa_printf(MSG_WARNING, "EAP-SIM: Counter in notification " - "message does not match with counter in reauth " - "message"); - os_free(decrypted); - return -1; - } - - os_free(decrypted); - return 0; -} - - -static int eap_sim_process_notification_auth(struct eap_sim_data *data, - const struct wpabuf *reqData, - struct eap_sim_attrs *attr) -{ - if (attr->mac == NULL) { - wpa_printf(MSG_INFO, "EAP-SIM: no AT_MAC in after_auth " - "Notification message"); - return -1; - } - - if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0)) - { - wpa_printf(MSG_WARNING, "EAP-SIM: Notification message " - "used invalid AT_MAC"); - return -1; - } - - if (data->reauth && - eap_sim_process_notification_reauth(data, attr)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Invalid notification " - "message after reauth"); - return -1; - } - - return 0; -} - - -static struct wpabuf * eap_sim_process_notification( - struct eap_sm *sm, struct eap_sim_data *data, u8 id, - const struct wpabuf *reqData, struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Notification"); - if (data->num_notification > 0) { - wpa_printf(MSG_INFO, "EAP-SIM: too many notification " - "rounds (only one allowed)"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - data->num_notification++; - if (attr->notification == -1) { - wpa_printf(MSG_INFO, "EAP-SIM: no AT_NOTIFICATION in " - "Notification message"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - if ((attr->notification & 0x4000) == 0 && - eap_sim_process_notification_auth(data, reqData, attr)) { - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - eap_sim_report_notification(sm->msg_ctx, attr->notification, 0); - if (attr->notification >= 0 && attr->notification < 32768) { - eap_sim_state(data, FAILURE); - } else if (attr->notification == EAP_SIM_SUCCESS && - data->state == RESULT_SUCCESS) - eap_sim_state(data, SUCCESS); - return eap_sim_response_notification(data, id, attr->notification); -} - - -static struct wpabuf * eap_sim_process_reauthentication( - struct eap_sm *sm, struct eap_sim_data *data, u8 id, - const struct wpabuf *reqData, struct eap_sim_attrs *attr) -{ - struct eap_sim_attrs eattr; - u8 *decrypted; - - wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Reauthentication"); - - if (data->reauth_id == NULL) { - wpa_printf(MSG_WARNING, "EAP-SIM: Server is trying " - "reauthentication, but no reauth_id available"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - data->reauth = 1; - if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0)) - { - wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " - "did not have valid AT_MAC"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - if (attr->encr_data == NULL || attr->iv == NULL) { - wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " - "message did not include encrypted data"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, &eattr, - 0); - if (decrypted == NULL) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " - "data from reauthentication message"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - if (eattr.nonce_s == NULL || eattr.counter < 0) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) No%s%s in reauth packet", - !eattr.nonce_s ? " AT_NONCE_S" : "", - eattr.counter < 0 ? " AT_COUNTER" : ""); - os_free(decrypted); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid counter " - "(%d <= %d)", eattr.counter, data->counter); - data->counter_too_small = eattr.counter; - /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current - * reauth_id must not be used to start a new reauthentication. - * However, since it was used in the last EAP-Response-Identity - * packet, it has to saved for the following fullauth to be - * used in MK derivation. */ - os_free(data->last_eap_identity); - data->last_eap_identity = data->reauth_id; - data->last_eap_identity_len = data->reauth_id_len; - data->reauth_id = NULL; - data->reauth_id_len = 0; - os_free(decrypted); - return eap_sim_response_reauth(data, id, 1); - } - data->counter = eattr.counter; - - os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: (encr) AT_NONCE_S", - data->nonce_s, EAP_SIM_NONCE_S_LEN); - - eap_sim_derive_keys_reauth(data->counter, - data->reauth_id, data->reauth_id_len, - data->nonce_s, data->mk, data->msk, - data->emsk); - eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); - eap_sim_learn_ids(data, &eattr); - - if (data->result_ind && attr->result_ind) - data->use_result_ind = 1; - - if (data->state != FAILURE && data->state != RESULT_FAILURE) { - eap_sim_state(data, data->use_result_ind ? - RESULT_SUCCESS : SUCCESS); - } - - data->num_id_req = 0; - data->num_notification = 0; - if (data->counter > EAP_SIM_MAX_FAST_REAUTHS) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Maximum number of " - "fast reauths performed - force fullauth"); - eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); - } - os_free(decrypted); - return eap_sim_response_reauth(data, id, 0); -} - - -static struct wpabuf * eap_sim_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_sim_data *data = priv; - const struct eap_hdr *req; - u8 subtype, id; - struct wpabuf *res; - const u8 *pos; - struct eap_sim_attrs attr; - size_t len; - - wpa_hexdump_buf(MSG_DEBUG, "EAP-SIM: EAP data", reqData); - if (eap_get_config_identity(sm, &len) == NULL) { - wpa_printf(MSG_INFO, "EAP-SIM: Identity not configured"); - eap_sm_request_identity(sm); - ret->ignore = TRUE; - return NULL; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, reqData, &len); - if (pos == NULL || len < 1) { - ret->ignore = TRUE; - return NULL; - } - req = wpabuf_head(reqData); - id = req->identifier; - len = be_to_host16(req->length); - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - subtype = *pos++; - wpa_printf(MSG_DEBUG, "EAP-SIM: Subtype=%d", subtype); - pos += 2; /* Reserved */ - - if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr, 0, - 0)) { - res = eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - goto done; - } - - switch (subtype) { - case EAP_SIM_SUBTYPE_START: - res = eap_sim_process_start(sm, data, id, &attr); - break; - case EAP_SIM_SUBTYPE_CHALLENGE: - res = eap_sim_process_challenge(sm, data, id, reqData, &attr); - break; - case EAP_SIM_SUBTYPE_NOTIFICATION: - res = eap_sim_process_notification(sm, data, id, reqData, - &attr); - break; - case EAP_SIM_SUBTYPE_REAUTHENTICATION: - res = eap_sim_process_reauthentication(sm, data, id, reqData, - &attr); - break; - case EAP_SIM_SUBTYPE_CLIENT_ERROR: - wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Client-Error"); - res = eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown subtype=%d", subtype); - res = eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - break; - } - -done: - if (data->state == FAILURE) { - ret->decision = DECISION_FAIL; - ret->methodState = METHOD_DONE; - } else if (data->state == SUCCESS) { - ret->decision = data->use_result_ind ? - DECISION_UNCOND_SUCC : DECISION_COND_SUCC; - ret->methodState = data->use_result_ind ? - METHOD_DONE : METHOD_MAY_CONT; - } else if (data->state == RESULT_FAILURE) - ret->methodState = METHOD_CONT; - else if (data->state == RESULT_SUCCESS) - ret->methodState = METHOD_CONT; - - if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; - } - - return res; -} - - -static Boolean eap_sim_has_reauth_data(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - return data->pseudonym || data->reauth_id; -} - - -static void eap_sim_deinit_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - eap_sim_clear_identities(data, CLEAR_EAP_ID); - data->use_result_ind = 0; -} - - -static void * eap_sim_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - if (os_get_random(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data " - "for NONCE_MT"); - os_free(data); - return NULL; - } - data->num_id_req = 0; - data->num_notification = 0; - eap_sim_state(data, CONTINUE); - return priv; -} - - -static const u8 * eap_sim_get_identity(struct eap_sm *sm, void *priv, - size_t *len) -{ - struct eap_sim_data *data = priv; - - if (data->reauth_id) { - *len = data->reauth_id_len; - return data->reauth_id; - } - - if (data->pseudonym) { - *len = data->pseudonym_len; - return data->pseudonym; - } - - return NULL; -} - - -static Boolean eap_sim_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - return data->state == SUCCESS; -} - - -static u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_sim_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_SIM_KEYING_DATA_LEN); - if (key == NULL) - return NULL; - - *len = EAP_SIM_KEYING_DATA_LEN; - os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); - - return key; -} - - -static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_sim_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_EMSK_LEN; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - - return key; -} - - -int eap_peer_sim_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM"); - if (eap == NULL) - return -1; - - eap->init = eap_sim_init; - eap->deinit = eap_sim_deinit; - eap->process = eap_sim_process; - eap->isKeyAvailable = eap_sim_isKeyAvailable; - eap->getKey = eap_sim_getKey; - eap->has_reauth_data = eap_sim_has_reauth_data; - eap->deinit_for_reauth = eap_sim_deinit_for_reauth; - eap->init_for_reauth = eap_sim_init_for_reauth; - eap->get_identity = eap_sim_get_identity; - eap->get_emsk = eap_sim_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_peer/eap_tls.c b/contrib/hostapd/src/eap_peer/eap_tls.c deleted file mode 100644 index 31344a9136..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_tls.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * EAP peer method: EAP-TLS (RFC 2716) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "eap_config.h" -#include "tls.h" - - -static void eap_tls_deinit(struct eap_sm *sm, void *priv); - - -struct eap_tls_data { - struct eap_ssl_data ssl; - u8 *key_data; -}; - - -static void * eap_tls_init(struct eap_sm *sm) -{ - struct eap_tls_data *data; - struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL || - ((sm->init_phase2 ? config->private_key2 : config->private_key) - == NULL && - (sm->init_phase2 ? config->engine2 : config->engine) == 0)) { - wpa_printf(MSG_INFO, "EAP-TLS: Private key not configured"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) { - wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); - eap_tls_deinit(sm, data); - if (config->engine) { - wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting Smartcard " - "PIN"); - eap_sm_request_pin(sm); - sm->ignore = TRUE; - } else if (config->private_key && !config->private_key_passwd) - { - wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting private " - "key passphrase"); - eap_sm_request_passphrase(sm); - sm->ignore = TRUE; - } - return NULL; - } - - return data; -} - - -static void eap_tls_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_tls_data *data = priv; - if (data == NULL) - return; - eap_peer_tls_ssl_deinit(sm, &data->ssl); - os_free(data->key_data); - os_free(data); -} - - -static struct wpabuf * eap_tls_failure(struct eap_sm *sm, - struct eap_tls_data *data, - struct eap_method_ret *ret, int res, - struct wpabuf *resp, u8 id) -{ - wpa_printf(MSG_DEBUG, "EAP-TLS: TLS processing failed"); - - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - - if (res == -1) { - struct eap_peer_config *config = eap_get_config(sm); - if (config) { - /* - * The TLS handshake failed. So better forget the old - * PIN. It may be wrong, we cannot be sure but trying - * the wrong one again might block it on the card--so - * better ask the user again. - */ - os_free(config->pin); - config->pin = NULL; - } - } - - if (resp) { - /* - * This is likely an alert message, so send it instead of just - * ACKing the error. - */ - return resp; - } - - return eap_peer_tls_build_ack(id, EAP_TYPE_TLS, 0); -} - - -static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, - struct eap_method_ret *ret) -{ - wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); - - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - - os_free(data->key_data); - data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, - "client EAP encryption", - EAP_TLS_KEY_LEN + - EAP_EMSK_LEN); - if (data->key_data) { - wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key", - data->key_data, EAP_TLS_KEY_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived EMSK", - data->key_data + EAP_TLS_KEY_LEN, - EAP_EMSK_LEN); - } else { - wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key"); - } -} - - -static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - size_t left; - int res; - struct wpabuf *resp; - u8 flags, id; - const u8 *pos; - struct eap_tls_data *data = priv; - - pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TLS, ret, - reqData, &left, &flags); - if (pos == NULL) - return NULL; - id = eap_get_id(reqData); - - if (flags & EAP_TLS_FLAGS_START) { - wpa_printf(MSG_DEBUG, "EAP-TLS: Start"); - left = 0; /* make sure that this frame is empty, even though it - * should always be, anyway */ - } - - resp = NULL; - res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TLS, 0, id, - pos, left, &resp); - - if (res < 0) { - return eap_tls_failure(sm, data, ret, res, resp, id); - } - - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) - eap_tls_success(sm, data, ret); - - if (res == 1) { - wpabuf_free(resp); - return eap_peer_tls_build_ack(id, EAP_TYPE_TLS, 0); - } - - return resp; -} - - -static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv) -{ - struct eap_tls_data *data = priv; - return tls_connection_established(sm->ssl_ctx, data->ssl.conn); -} - - -static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv) -{ -} - - -static void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_tls_data *data = priv; - os_free(data->key_data); - data->key_data = NULL; - if (eap_peer_tls_reauth_init(sm, &data->ssl)) { - os_free(data); - return NULL; - } - return priv; -} - - -static int eap_tls_get_status(struct eap_sm *sm, void *priv, char *buf, - size_t buflen, int verbose) -{ - struct eap_tls_data *data = priv; - return eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); -} - - -static Boolean eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_tls_data *data = priv; - return data->key_data != NULL; -} - - -static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_tls_data *data = priv; - u8 *key; - - if (data->key_data == NULL) - return NULL; - - key = os_malloc(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; -} - - -static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_tls_data *data = priv; - u8 *key; - - if (data->key_data == NULL) - return NULL; - - key = os_malloc(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; -} - - -int eap_peer_tls_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS"); - if (eap == NULL) - return -1; - - eap->init = eap_tls_init; - eap->deinit = eap_tls_deinit; - eap->process = eap_tls_process; - eap->isKeyAvailable = eap_tls_isKeyAvailable; - eap->getKey = eap_tls_getKey; - eap->get_status = eap_tls_get_status; - eap->has_reauth_data = eap_tls_has_reauth_data; - eap->deinit_for_reauth = eap_tls_deinit_for_reauth; - eap->init_for_reauth = eap_tls_init_for_reauth; - eap->get_emsk = eap_tls_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_peer/eap_tls_common.c b/contrib/hostapd/src/eap_peer/eap_tls_common.c deleted file mode 100644 index 186feaada4..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_tls_common.c +++ /dev/null @@ -1,1064 +0,0 @@ -/* - * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "eap_config.h" -#include "sha1.h" -#include "tls.h" - - -static int eap_tls_check_blob(struct eap_sm *sm, const char **name, - const u8 **data, size_t *data_len) -{ - const struct wpa_config_blob *blob; - - if (*name == NULL || os_strncmp(*name, "blob://", 7) != 0) - return 0; - - blob = eap_get_config_blob(sm, *name + 7); - if (blob == NULL) { - wpa_printf(MSG_ERROR, "%s: Named configuration blob '%s' not " - "found", __func__, *name + 7); - return -1; - } - - *name = NULL; - *data = blob->data; - *data_len = blob->len; - - return 0; -} - - -static void eap_tls_params_flags(struct tls_connection_params *params, - const char *txt) -{ - if (txt == NULL) - return; - if (os_strstr(txt, "tls_allow_md5=1")) - params->flags |= TLS_CONN_ALLOW_SIGN_RSA_MD5; - if (os_strstr(txt, "tls_disable_time_checks=1")) - params->flags |= TLS_CONN_DISABLE_TIME_CHECKS; -} - - -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->engine = config->engine; - params->engine_id = config->engine_id; - params->pin = config->pin; - params->key_id = config->key_id; - params->cert_id = config->cert_id; - params->ca_cert_id = config->ca_cert_id; - eap_tls_params_flags(params, config->phase1); -} - - -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->engine = config->engine2; - params->engine_id = config->engine2_id; - params->pin = config->pin2; - params->key_id = config->key2_id; - params->cert_id = config->cert2_id; - params->ca_cert_id = config->ca_cert2_id; - eap_tls_params_flags(params, config->phase2); -} - - -static int eap_tls_params_from_conf(struct eap_sm *sm, - struct eap_ssl_data *data, - struct tls_connection_params *params, - struct eap_peer_config *config, int phase2) -{ - os_memset(params, 0, sizeof(*params)); - if (phase2) { - wpa_printf(MSG_DEBUG, "TLS: using phase2 config options"); - eap_tls_params_from_conf2(params, config); - } else { - wpa_printf(MSG_DEBUG, "TLS: using phase1 config options"); - eap_tls_params_from_conf1(params, config); - } - params->tls_ia = data->tls_ia; - - /* - * Use blob data, if available. Otherwise, leave reference to external - * file as-is. - */ - if (eap_tls_check_blob(sm, ¶ms->ca_cert, ¶ms->ca_cert_blob, - ¶ms->ca_cert_blob_len) || - eap_tls_check_blob(sm, ¶ms->client_cert, - ¶ms->client_cert_blob, - ¶ms->client_cert_blob_len) || - eap_tls_check_blob(sm, ¶ms->private_key, - ¶ms->private_key_blob, - ¶ms->private_key_blob_len) || - eap_tls_check_blob(sm, ¶ms->dh_file, ¶ms->dh_blob, - ¶ms->dh_blob_len)) { - wpa_printf(MSG_INFO, "SSL: Failed to get configuration blobs"); - return -1; - } - - return 0; -} - - -static int eap_tls_init_connection(struct eap_sm *sm, - struct eap_ssl_data *data, - struct eap_peer_config *config, - struct tls_connection_params *params) -{ - int res; - - data->conn = tls_connection_init(sm->ssl_ctx); - if (data->conn == NULL) { - wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS " - "connection"); - return -1; - } - - res = tls_connection_set_params(sm->ssl_ctx, data->conn, params); - if (res == TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED) { - /* - * At this point with the pkcs11 engine the PIN might be wrong. - * We reset the PIN in the configuration to be sure to not use - * it again and the calling function must request a new one. - */ - os_free(config->pin); - config->pin = NULL; - } else if (res == TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED) { - wpa_printf(MSG_INFO, "TLS: Failed to load private key"); - /* - * We do not know exactly but maybe the PIN was wrong, - * so ask for a new one. - */ - os_free(config->pin); - config->pin = NULL; - eap_sm_request_pin(sm); - sm->ignore = TRUE; - return -1; - } else if (res) { - wpa_printf(MSG_INFO, "TLS: Failed to set TLS connection " - "parameters"); - return -1; - } - - return 0; -} - - -/** - * eap_peer_tls_ssl_init - Initialize shared TLS functionality - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Data for TLS processing - * @config: Pointer to the network configuration - * Returns: 0 on success, -1 on failure - * - * This function is used to initialize shared TLS functionality for EAP-TLS, - * EAP-PEAP, EAP-TTLS, and EAP-FAST. - */ -int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, - struct eap_peer_config *config) -{ - struct tls_connection_params params; - - if (config == NULL) - return -1; - - data->eap = sm; - data->phase2 = sm->init_phase2; - if (eap_tls_params_from_conf(sm, data, ¶ms, config, data->phase2) < - 0) - return -1; - - if (eap_tls_init_connection(sm, data, config, ¶ms) < 0) - return -1; - - data->tls_out_limit = config->fragment_size; - if (data->phase2) { - /* Limit the fragment size in the inner TLS authentication - * since the outer authentication with EAP-PEAP does not yet - * support fragmentation */ - if (data->tls_out_limit > 100) - data->tls_out_limit -= 100; - } - - if (config->phase1 && - os_strstr(config->phase1, "include_tls_length=1")) { - wpa_printf(MSG_DEBUG, "TLS: Include TLS Message Length in " - "unfragmented packets"); - data->include_tls_length = 1; - } - - return 0; -} - - -/** - * eap_peer_tls_ssl_deinit - Deinitialize shared TLS functionality - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Data for TLS processing - * - * This function deinitializes shared TLS functionality that was initialized - * with eap_peer_tls_ssl_init(). - */ -void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) -{ - tls_connection_deinit(sm->ssl_ctx, data->conn); - eap_peer_tls_reset_input(data); - eap_peer_tls_reset_output(data); -} - - -/** - * eap_peer_tls_derive_key - Derive a key based on TLS session 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" - * @len: Length of the key material to generate (usually 64 for MSK) - * Returns: Pointer to allocated key on success or %NULL on failure - * - * This function uses TLS-PRF to generate pseudo-random data based on the TLS - * session data (client/server random and master key). Each key type may use a - * different label to bind the key usage into the generated material. - * - * The caller is responsible for freeing the returned buffer. - */ -u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, - const char *label, size_t len) -{ - struct tls_keys keys; - u8 *rnd = NULL, *out; - - out = os_malloc(len); - if (out == NULL) - return NULL; - - /* First, try to use TLS library function for PRF, if available. */ - if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) == - 0) - return out; - - /* - * TLS library did not support key generation, so get the needed TLS - * session parameters and use an internal implementation of TLS PRF to - * derive the key. - */ - if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) - goto fail; - - if (keys.client_random == NULL || keys.server_random == NULL || - keys.master_key == NULL) - goto fail; - - rnd = os_malloc(keys.client_random_len + keys.server_random_len); - if (rnd == NULL) - goto fail; - os_memcpy(rnd, keys.client_random, keys.client_random_len); - os_memcpy(rnd + keys.client_random_len, keys.server_random, - keys.server_random_len); - - if (tls_prf(keys.master_key, keys.master_key_len, - label, rnd, keys.client_random_len + - keys.server_random_len, out, len)) - goto fail; - - os_free(rnd); - return out; - -fail: - os_free(out); - os_free(rnd); - return NULL; -} - - -/** - * eap_peer_tls_reassemble_fragment - Reassemble a received fragment - * @data: Data for TLS processing - * @in_data: Next incoming TLS segment - * @in_len: Length of in_data - * Returns: 0 on success, 1 if more data is needed for the full message, or - * -1 on error - */ -static int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data, - const u8 *in_data, size_t in_len) -{ - u8 *buf; - - if (data->tls_in_len + in_len == 0) { - /* No message data received?! */ - wpa_printf(MSG_WARNING, "SSL: Invalid reassembly state: " - "tls_in_left=%lu tls_in_len=%lu in_len=%lu", - (unsigned long) data->tls_in_left, - (unsigned long) data->tls_in_len, - (unsigned long) in_len); - eap_peer_tls_reset_input(data); - return -1; - } - - if (data->tls_in_len + in_len > 65536) { - /* - * Limit length to avoid rogue servers from causing large - * memory allocations. - */ - wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size over " - "64 kB)"); - eap_peer_tls_reset_input(data); - return -1; - } - - if (in_len > data->tls_in_left) { - /* Sender is doing something odd - reject message */ - wpa_printf(MSG_INFO, "SSL: more data than TLS message length " - "indicated"); - eap_peer_tls_reset_input(data); - return -1; - } - - buf = os_realloc(data->tls_in, data->tls_in_len + in_len); - if (buf == NULL) { - wpa_printf(MSG_INFO, "SSL: Could not allocate memory for TLS " - "data"); - eap_peer_tls_reset_input(data); - return -1; - } - os_memcpy(buf + data->tls_in_len, in_data, in_len); - data->tls_in = buf; - data->tls_in_len += in_len; - data->tls_in_left -= in_len; - - if (data->tls_in_left > 0) { - wpa_printf(MSG_DEBUG, "SSL: Need %lu bytes more input " - "data", (unsigned long) data->tls_in_left); - return 1; - } - - return 0; -} - - -/** - * eap_peer_tls_data_reassemble - Reassemble TLS data - * @data: Data for TLS processing - * @in_data: Next incoming TLS segment - * @in_len: Length of in_data - * @out_len: Variable for returning length of the reassembled message - * @need_more_input: Variable for returning whether more input data is needed - * to reassemble this TLS packet - * Returns: Pointer to output data, %NULL on error or when more data is needed - * for the full message (in which case, *need_more_input is also set to 1). - * - * This function reassembles TLS fragments. Caller must not free the returned - * data buffer since an internal pointer to it is maintained. - */ -const u8 * eap_peer_tls_data_reassemble( - struct eap_ssl_data *data, const u8 *in_data, size_t in_len, - size_t *out_len, int *need_more_input) -{ - *need_more_input = 0; - - if (data->tls_in_left > in_len || data->tls_in) { - /* Message has fragments */ - int res = eap_peer_tls_reassemble_fragment(data, in_data, - in_len); - if (res) { - if (res == 1) - *need_more_input = 1; - return NULL; - } - - /* Message is now fully reassembled. */ - } else { - /* No fragments in this message, so just make a copy of it. */ - data->tls_in_left = 0; - data->tls_in = os_malloc(in_len ? in_len : 1); - if (data->tls_in == NULL) - return NULL; - os_memcpy(data->tls_in, in_data, in_len); - data->tls_in_len = in_len; - } - - *out_len = data->tls_in_len; - return data->tls_in; -} - - -/** - * eap_tls_process_input - Process incoming TLS message - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Data for TLS processing - * @in_data: Message received from the server - * @in_len: Length of in_data - * @out_data: Buffer for returning a pointer to application data (if available) - * Returns: 0 on success, 1 if more input data is needed, 2 if application data - * is available, -1 on failure - */ -static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data, - const u8 *in_data, size_t in_len, - struct wpabuf **out_data) -{ - const u8 *msg; - size_t msg_len; - int need_more_input; - u8 *appl_data; - size_t appl_data_len; - - msg = eap_peer_tls_data_reassemble(data, in_data, in_len, - &msg_len, &need_more_input); - if (msg == NULL) - return need_more_input ? 1 : -1; - - /* Full TLS message reassembled - continue handshake processing */ - if (data->tls_out) { - /* This should not happen.. */ - wpa_printf(MSG_INFO, "SSL: eap_tls_process_input - pending " - "tls_out data even though tls_out_len = 0"); - os_free(data->tls_out); - WPA_ASSERT(data->tls_out == NULL); - } - appl_data = NULL; - data->tls_out = tls_connection_handshake(sm->ssl_ctx, data->conn, - msg, msg_len, - &data->tls_out_len, - &appl_data, &appl_data_len); - - eap_peer_tls_reset_input(data); - - if (appl_data && - tls_connection_established(sm->ssl_ctx, data->conn) && - !tls_connection_get_failed(sm->ssl_ctx, data->conn)) { - wpa_hexdump_key(MSG_MSGDUMP, "SSL: Application data", - appl_data, appl_data_len); - *out_data = wpabuf_alloc_ext_data(appl_data, appl_data_len); - if (*out_data == NULL) { - os_free(appl_data); - return -1; - } - return 2; - } - - os_free(appl_data); - - return 0; -} - - -/** - * eap_tls_process_output - Process outgoing TLS message - * @data: Data for TLS processing - * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) - * @peap_version: Version number for EAP-PEAP/TTLS - * @id: EAP identifier for the response - * @ret: Return value to use on success - * @out_data: Buffer for returning the allocated output buffer - * Returns: ret (0 or 1) on success, -1 on failure - */ -static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type, - int peap_version, u8 id, int ret, - struct wpabuf **out_data) -{ - size_t len; - u8 *flags; - int more_fragments, length_included; - - len = data->tls_out_len - data->tls_out_pos; - wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total " - "%lu bytes)", - (unsigned long) len, (unsigned long) data->tls_out_len); - - /* - * Limit outgoing message to the configured maximum size. Fragment - * message if needed. - */ - if (len > data->tls_out_limit) { - more_fragments = 1; - len = data->tls_out_limit; - wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments " - "will follow", (unsigned long) len); - } else - more_fragments = 0; - - length_included = data->tls_out_pos == 0 && - (data->tls_out_len > data->tls_out_limit || - data->include_tls_length); - if (!length_included && - eap_type == EAP_TYPE_PEAP && peap_version == 0 && - !tls_connection_established(data->eap->ssl_ctx, data->conn)) { - /* - * Windows Server 2008 NPS really wants to have the TLS Message - * length included in phase 0 even for unfragmented frames or - * it will get very confused with Compound MAC calculation and - * Outer TLVs. - */ - length_included = 1; - } - - *out_data = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, - 1 + length_included * 4 + len, - EAP_CODE_RESPONSE, id); - if (*out_data == NULL) - return -1; - - flags = wpabuf_put(*out_data, 1); - *flags = peap_version; - if (more_fragments) - *flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS; - if (length_included) { - *flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED; - wpabuf_put_be32(*out_data, data->tls_out_len); - } - - wpabuf_put_data(*out_data, &data->tls_out[data->tls_out_pos], len); - data->tls_out_pos += len; - - if (!more_fragments) - eap_peer_tls_reset_output(data); - - return ret; -} - - -/** - * eap_peer_tls_process_helper - Process TLS handshake message - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Data for TLS processing - * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) - * @peap_version: Version number for EAP-PEAP/TTLS - * @id: EAP identifier for the response - * @in_data: Message received from the server - * @in_len: Length of in_data - * @out_data: Buffer for returning a pointer to the response message - * Returns: 0 on success, 1 if more input data is needed, 2 if application data - * is available, or -1 on failure - * - * This function can be used to process TLS handshake messages. It reassembles - * the received fragments and uses a TLS library to process the messages. The - * response data from the TLS library is fragmented to suitable output messages - * that the caller can send out. - * - * out_data is used to return the response message if the return value of this - * function is 0, 2, or -1. In case of failure, the message is likely a TLS - * alarm message. The caller is responsible for freeing the allocated buffer if - * *out_data is not %NULL. - * - * This function is called for each received TLS message during the TLS - * handshake after eap_peer_tls_process_init() call and possible processing of - * TLS Flags field. Once the handshake has been completed, i.e., when - * tls_connection_established() returns 1, EAP method specific decrypting of - * the tunneled data is used. - */ -int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, - EapType eap_type, int peap_version, - u8 id, const u8 *in_data, size_t in_len, - struct wpabuf **out_data) -{ - int ret = 0; - - *out_data = NULL; - - if (data->tls_out_len > 0 && in_len > 0) { - wpa_printf(MSG_DEBUG, "SSL: Received non-ACK when output " - "fragments are waiting to be sent out"); - return -1; - } - - if (data->tls_out_len == 0) { - /* - * No more data to send out - expect to receive more data from - * the AS. - */ - int res = eap_tls_process_input(sm, data, in_data, in_len, - out_data); - if (res) { - /* - * Input processing failed (res = -1) or more data is - * needed (res = 1). - */ - return res; - } - - /* - * The incoming message has been reassembled and processed. The - * response was allocated into data->tls_out buffer. - */ - } - - if (data->tls_out == NULL) { - /* - * No outgoing fragments remaining from the previous message - * and no new message generated. This indicates an error in TLS - * processing. - */ - eap_peer_tls_reset_output(data); - return -1; - } - - if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) { - /* TLS processing has failed - return error */ - wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to " - "report error"); - ret = -1; - /* TODO: clean pin if engine used? */ - } - - if (data->tls_out_len == 0) { - /* - * TLS negotiation should now be complete since all other cases - * needing more data should have been caught above based on - * the TLS Message Length field. - */ - wpa_printf(MSG_DEBUG, "SSL: No data to be sent out"); - os_free(data->tls_out); - data->tls_out = NULL; - return 1; - } - - /* Send the pending message (in fragments, if needed). */ - return eap_tls_process_output(data, eap_type, peap_version, id, ret, - out_data); -} - - -/** - * eap_peer_tls_build_ack - Build a TLS ACK frame - * @id: EAP identifier for the response - * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) - * @peap_version: Version number for EAP-PEAP/TTLS - * Returns: Pointer to the allocated ACK frame or %NULL on failure - */ -struct wpabuf * eap_peer_tls_build_ack(u8 id, EapType eap_type, - int peap_version) -{ - struct wpabuf *resp; - - resp = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, 1, EAP_CODE_RESPONSE, - id); - if (resp == NULL) - return NULL; - wpa_printf(MSG_DEBUG, "SSL: Building ACK (type=%d id=%d ver=%d)", - (int) eap_type, id, peap_version); - wpabuf_put_u8(resp, peap_version); /* Flags */ - return resp; -} - - -/** - * eap_peer_tls_reauth_init - Re-initialize shared TLS for session resumption - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Data for TLS processing - * Returns: 0 on success, -1 on failure - */ -int eap_peer_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data) -{ - eap_peer_tls_reset_input(data); - eap_peer_tls_reset_output(data); - return tls_connection_shutdown(sm->ssl_ctx, data->conn); -} - - -/** - * eap_peer_tls_status - Get TLS status - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Data for TLS processing - * @buf: Buffer for status information - * @buflen: Maximum buffer length - * @verbose: Whether to include verbose status information - * Returns: Number of bytes written to buf. - */ -int eap_peer_tls_status(struct eap_sm *sm, struct eap_ssl_data *data, - char *buf, size_t buflen, int verbose) -{ - char name[128]; - int len = 0, ret; - - if (tls_get_cipher(sm->ssl_ctx, data->conn, name, sizeof(name)) == 0) { - ret = os_snprintf(buf + len, buflen - len, - "EAP TLS cipher=%s\n", name); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - } - - return len; -} - - -/** - * eap_peer_tls_process_init - Initial validation/processing of EAP requests - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Data for TLS processing - * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) - * @ret: Return values from EAP request validation and processing - * @reqData: EAP request to be processed (eapReqData) - * @len: Buffer for returning length of the remaining payload - * @flags: Buffer for returning TLS flags - * Returns: Pointer to payload after TLS flags and length or %NULL on failure - * - * This function validates the EAP header and processes the optional TLS - * Message Length field. If this is the first fragment of a TLS message, the - * TLS reassembly code is initialized to receive the indicated number of bytes. - * - * EAP-TLS, EAP-PEAP, EAP-TTLS, and EAP-FAST methods are expected to use this - * function as the first step in processing received messages. They will need - * to process the flags (apart from Message Length Included) that are returned - * through the flags pointer and the message payload that will be returned (and - * the length is returned through the len pointer). Return values (ret) are set - * for continuation of EAP method processing. The caller is responsible for - * setting these to indicate completion (either success or failure) based on - * the authentication result. - */ -const u8 * eap_peer_tls_process_init(struct eap_sm *sm, - struct eap_ssl_data *data, - EapType eap_type, - struct eap_method_ret *ret, - const struct wpabuf *reqData, - size_t *len, u8 *flags) -{ - const u8 *pos; - size_t left; - unsigned int tls_msg_len; - - if (tls_get_errors(sm->ssl_ctx)) { - wpa_printf(MSG_INFO, "SSL: TLS errors detected"); - ret->ignore = TRUE; - return NULL; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, reqData, &left); - if (pos == NULL) { - ret->ignore = TRUE; - return NULL; - } - if (left == 0) { - wpa_printf(MSG_DEBUG, "SSL: Invalid TLS message: no Flags " - "octet included"); - if (!sm->workaround) { - ret->ignore = TRUE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "SSL: Workaround - assume no Flags " - "indicates ACK frame"); - *flags = 0; - } else { - *flags = *pos++; - left--; - } - wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - " - "Flags 0x%02x", (unsigned long) wpabuf_len(reqData), - *flags); - if (*flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { - if (left < 4) { - wpa_printf(MSG_INFO, "SSL: Short frame with TLS " - "length"); - ret->ignore = TRUE; - return NULL; - } - tls_msg_len = WPA_GET_BE32(pos); - wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d", - tls_msg_len); - if (data->tls_in_left == 0) { - data->tls_in_total = tls_msg_len; - data->tls_in_left = tls_msg_len; - os_free(data->tls_in); - data->tls_in = NULL; - data->tls_in_len = 0; - } - pos += 4; - left -= 4; - } - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - *len = left; - return pos; -} - - -/** - * eap_peer_tls_reset_input - Reset input buffers - * @data: Data for TLS processing - * - * This function frees any allocated memory for input buffers and resets input - * state. - */ -void eap_peer_tls_reset_input(struct eap_ssl_data *data) -{ - data->tls_in_left = data->tls_in_total = data->tls_in_len = 0; - os_free(data->tls_in); - data->tls_in = NULL; -} - - -/** - * eap_peer_tls_reset_output - Reset output buffers - * @data: Data for TLS processing - * - * This function frees any allocated memory for output buffers and resets - * output state. - */ -void eap_peer_tls_reset_output(struct eap_ssl_data *data) -{ - data->tls_out_len = 0; - data->tls_out_pos = 0; - os_free(data->tls_out); - data->tls_out = NULL; -} - - -/** - * eap_peer_tls_decrypt - Decrypt received phase 2 TLS message - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Data for TLS processing - * @in_data: Message received from the server - * @in_decrypted: Buffer for returning a pointer to the decrypted message - * Returns: 0 on success, 1 if more input data is needed, or -1 on failure - */ -int eap_peer_tls_decrypt(struct eap_sm *sm, struct eap_ssl_data *data, - const struct wpabuf *in_data, - struct wpabuf **in_decrypted) -{ - int res; - const u8 *msg; - size_t msg_len, buf_len; - int need_more_input; - - msg = eap_peer_tls_data_reassemble(data, wpabuf_head(in_data), - wpabuf_len(in_data), &msg_len, - &need_more_input); - if (msg == NULL) - return need_more_input ? 1 : -1; - - buf_len = wpabuf_len(in_data); - if (data->tls_in_total > buf_len) - buf_len = data->tls_in_total; - /* - * Even though we try to disable TLS compression, it is possible that - * this cannot be done with all TLS libraries. Add extra buffer space - * to handle the possibility of the decrypted data being longer than - * input data. - */ - buf_len += 500; - buf_len *= 3; - *in_decrypted = wpabuf_alloc(buf_len ? buf_len : 1); - if (*in_decrypted == NULL) { - eap_peer_tls_reset_input(data); - wpa_printf(MSG_WARNING, "SSL: Failed to allocate memory for " - "decryption"); - return -1; - } - - res = tls_connection_decrypt(sm->ssl_ctx, data->conn, msg, msg_len, - wpabuf_mhead(*in_decrypted), buf_len); - eap_peer_tls_reset_input(data); - if (res < 0) { - wpa_printf(MSG_INFO, "SSL: Failed to decrypt Phase 2 data"); - return -1; - } - wpabuf_put(*in_decrypted, res); - return 0; -} - - -/** - * eap_peer_tls_encrypt - Encrypt phase 2 TLS message - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Data for TLS processing - * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) - * @peap_version: Version number for EAP-PEAP/TTLS - * @id: EAP identifier for the response - * @in_data: Plaintext phase 2 data to encrypt or %NULL to continue fragments - * @out_data: Buffer for returning a pointer to the encrypted response message - * Returns: 0 on success, -1 on failure - */ -int eap_peer_tls_encrypt(struct eap_sm *sm, struct eap_ssl_data *data, - EapType eap_type, int peap_version, u8 id, - const struct wpabuf *in_data, - struct wpabuf **out_data) -{ - int res; - size_t len; - - if (in_data) { - eap_peer_tls_reset_output(data); - len = wpabuf_len(in_data) + 300; - data->tls_out = os_malloc(len); - if (data->tls_out == NULL) - return -1; - - res = tls_connection_encrypt(sm->ssl_ctx, data->conn, - wpabuf_head(in_data), - wpabuf_len(in_data), - data->tls_out, len); - if (res < 0) { - wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 " - "data (in_len=%lu)", - (unsigned long) wpabuf_len(in_data)); - eap_peer_tls_reset_output(data); - return -1; - } - - data->tls_out_len = res; - } - - return eap_tls_process_output(data, eap_type, peap_version, id, 0, - out_data); -} - - -/** - * eap_peer_select_phase2_methods - Select phase 2 EAP method - * @config: Pointer to the network configuration - * @prefix: 'phase2' configuration prefix, e.g., "auth=" - * @types: Buffer for returning allocated list of allowed EAP methods - * @num_types: Buffer for returning number of allocated EAP methods - * Returns: 0 on success, -1 on failure - * - * This function is used to parse EAP method list and select allowed methods - * for Phase2 authentication. - */ -int eap_peer_select_phase2_methods(struct eap_peer_config *config, - const char *prefix, - struct eap_method_type **types, - size_t *num_types) -{ - char *start, *pos, *buf; - struct eap_method_type *methods = NULL, *_methods; - u8 method; - size_t num_methods = 0, prefix_len; - - if (config == NULL || config->phase2 == NULL) - goto get_defaults; - - start = buf = os_strdup(config->phase2); - if (buf == NULL) - return -1; - - prefix_len = os_strlen(prefix); - - while (start && *start != '\0') { - int vendor; - pos = os_strstr(start, prefix); - if (pos == NULL) - break; - if (start != pos && *(pos - 1) != ' ') { - start = pos + prefix_len; - continue; - } - - start = pos + prefix_len; - pos = os_strchr(start, ' '); - if (pos) - *pos++ = '\0'; - method = eap_get_phase2_type(start, &vendor); - if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE) { - wpa_printf(MSG_ERROR, "TLS: Unsupported Phase2 EAP " - "method '%s'", start); - } else { - num_methods++; - _methods = os_realloc(methods, - num_methods * sizeof(*methods)); - if (_methods == NULL) { - os_free(methods); - os_free(buf); - return -1; - } - methods = _methods; - methods[num_methods - 1].vendor = vendor; - methods[num_methods - 1].method = method; - } - - start = pos; - } - - os_free(buf); - -get_defaults: - if (methods == NULL) - methods = eap_get_phase2_types(config, &num_methods); - - if (methods == NULL) { - wpa_printf(MSG_ERROR, "TLS: No Phase2 EAP methods available"); - return -1; - } - wpa_hexdump(MSG_DEBUG, "TLS: Phase2 EAP types", - (u8 *) methods, - num_methods * sizeof(struct eap_method_type)); - - *types = methods; - *num_types = num_methods; - - return 0; -} - - -/** - * eap_peer_tls_phase2_nak - Generate EAP-Nak for Phase 2 - * @types: Buffer for returning allocated list of allowed EAP methods - * @num_types: Buffer for returning number of allocated EAP methods - * @hdr: EAP-Request header (and the following EAP type octet) - * @resp: Buffer for returning the EAP-Nak message - * Returns: 0 on success, -1 on failure - */ -int eap_peer_tls_phase2_nak(struct eap_method_type *types, size_t num_types, - struct eap_hdr *hdr, struct wpabuf **resp) -{ - u8 *pos = (u8 *) (hdr + 1); - size_t i; - - /* TODO: add support for expanded Nak */ - wpa_printf(MSG_DEBUG, "TLS: Phase 2 Request: Nak type=%d", *pos); - wpa_hexdump(MSG_DEBUG, "TLS: Allowed Phase2 EAP types", - (u8 *) types, num_types * sizeof(struct eap_method_type)); - *resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NAK, num_types, - EAP_CODE_RESPONSE, hdr->identifier); - if (*resp == NULL) - return -1; - - for (i = 0; i < num_types; i++) { - if (types[i].vendor == EAP_VENDOR_IETF && - types[i].method < 256) - wpabuf_put_u8(*resp, types[i].method); - } - - eap_update_len(*resp); - - return 0; -} diff --git a/contrib/hostapd/src/eap_peer/eap_tls_common.h b/contrib/hostapd/src/eap_peer/eap_tls_common.h deleted file mode 100644 index 2c87427c28..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_tls_common.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_TLS_COMMON_H -#define EAP_TLS_COMMON_H - -/** - * struct eap_ssl_data - TLS data for EAP methods - */ -struct eap_ssl_data { - /** - * conn - TLS connection context data from tls_connection_init() - */ - struct tls_connection *conn; - - /** - * tls_out - TLS message to be sent out in fragments - */ - u8 *tls_out; - - /** - * tls_out_len - Total length of the outgoing TLS message - */ - size_t tls_out_len; - - /** - * tls_out_pos - The current position in the outgoing TLS message - */ - size_t tls_out_pos; - - /** - * tls_out_limit - Maximum fragment size for outgoing TLS messages - */ - size_t tls_out_limit; - - /** - * tls_in - Received TLS message buffer for re-assembly - */ - u8 *tls_in; - - /** - * tls_in_len - Number of bytes of the received TLS message in tls_in - */ - size_t tls_in_len; - - /** - * tls_in_left - Number of remaining bytes in the incoming TLS message - */ - size_t tls_in_left; - - /** - * tls_in_total - Total number of bytes in the incoming TLS message - */ - size_t tls_in_total; - - /** - * phase2 - Whether this TLS connection is used in EAP phase 2 (tunnel) - */ - int phase2; - - /** - * include_tls_length - Whether the TLS length field is included even - * if the TLS data is not fragmented - */ - int include_tls_length; - - /** - * tls_ia - Whether TLS/IA is enabled for this TLS connection - */ - int tls_ia; - - /** - * eap - Pointer to EAP state machine allocated with eap_peer_sm_init() - */ - struct eap_sm *eap; -}; - - -/* EAP TLS Flags */ -#define EAP_TLS_FLAGS_LENGTH_INCLUDED 0x80 -#define EAP_TLS_FLAGS_MORE_FRAGMENTS 0x40 -#define EAP_TLS_FLAGS_START 0x20 -#define EAP_PEAP_VERSION_MASK 0x07 - - /* could be up to 128 bytes, but only the first 64 bytes are used */ -#define EAP_TLS_KEY_LEN 64 - - -int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, - struct eap_peer_config *config); -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 u8 * eap_peer_tls_data_reassemble( - struct eap_ssl_data *data, const u8 *in_data, size_t in_len, - size_t *out_len, int *need_more_input); -int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, - EapType eap_type, int peap_version, - u8 id, const u8 *in_data, size_t in_len, - struct wpabuf **out_data); -struct wpabuf * eap_peer_tls_build_ack(u8 id, EapType eap_type, - int peap_version); -int eap_peer_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data); -int eap_peer_tls_status(struct eap_sm *sm, struct eap_ssl_data *data, - char *buf, size_t buflen, int verbose); -const u8 * eap_peer_tls_process_init(struct eap_sm *sm, - struct eap_ssl_data *data, - EapType eap_type, - struct eap_method_ret *ret, - const struct wpabuf *reqData, - size_t *len, u8 *flags); -void eap_peer_tls_reset_input(struct eap_ssl_data *data); -void eap_peer_tls_reset_output(struct eap_ssl_data *data); -int eap_peer_tls_decrypt(struct eap_sm *sm, struct eap_ssl_data *data, - const struct wpabuf *in_data, - struct wpabuf **in_decrypted); -int eap_peer_tls_encrypt(struct eap_sm *sm, struct eap_ssl_data *data, - EapType eap_type, int peap_version, u8 id, - const struct wpabuf *in_data, - struct wpabuf **out_data); -int eap_peer_select_phase2_methods(struct eap_peer_config *config, - const char *prefix, - struct eap_method_type **types, - size_t *num_types); -int eap_peer_tls_phase2_nak(struct eap_method_type *types, size_t num_types, - struct eap_hdr *hdr, struct wpabuf **resp); - -#endif /* EAP_TLS_COMMON_H */ diff --git a/contrib/hostapd/src/eap_peer/eap_tnc.c b/contrib/hostapd/src/eap_peer/eap_tnc.c deleted file mode 100644 index c560015281..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_tnc.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - * EAP peer method: EAP-TNC (Trusted Network Connect) - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "base64.h" -#include "eap_i.h" -#include "tncc.h" - - -struct eap_tnc_data { - enum { WAIT_START, PROC_MSG, WAIT_FRAG_ACK, DONE, FAIL } state; - struct tncc_data *tncc; - struct wpabuf *in_buf; - struct wpabuf *out_buf; - size_t out_used; - size_t fragment_size; -}; - - -/* EAP-TNC Flags */ -#define EAP_TNC_FLAGS_LENGTH_INCLUDED 0x80 -#define EAP_TNC_FLAGS_MORE_FRAGMENTS 0x40 -#define EAP_TNC_FLAGS_START 0x20 -#define EAP_TNC_VERSION_MASK 0x07 - -#define EAP_TNC_VERSION 1 - - -static void * eap_tnc_init(struct eap_sm *sm) -{ - struct eap_tnc_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = WAIT_START; - data->fragment_size = 1300; - data->tncc = tncc_init(); - if (data->tncc == NULL) { - os_free(data); - return NULL; - } - - return data; -} - - -static void eap_tnc_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_tnc_data *data = priv; - - wpabuf_free(data->in_buf); - wpabuf_free(data->out_buf); - tncc_deinit(data->tncc); - os_free(data); -} - - -static struct wpabuf * eap_tnc_build_frag_ack(u8 id, u8 code) -{ - struct wpabuf *msg; - - msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 0, code, id); - if (msg == NULL) { - wpa_printf(MSG_ERROR, "EAP-TNC: Failed to allocate memory " - "for fragment ack"); - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-TNC: Send fragment ack"); - - return msg; -} - - -static struct wpabuf * eap_tnc_build_msg(struct eap_tnc_data *data, - struct eap_method_ret *ret, u8 id) -{ - struct wpabuf *resp; - u8 flags; - size_t send_len, plen; - - ret->ignore = FALSE; - wpa_printf(MSG_DEBUG, "EAP-TNC: Generating Response"); - ret->allowNotifications = TRUE; - - flags = EAP_TNC_VERSION; - send_len = wpabuf_len(data->out_buf) - data->out_used; - if (1 + send_len > data->fragment_size) { - send_len = data->fragment_size - 1; - flags |= EAP_TNC_FLAGS_MORE_FRAGMENTS; - if (data->out_used == 0) { - flags |= EAP_TNC_FLAGS_LENGTH_INCLUDED; - send_len -= 4; - } - } - - plen = 1 + send_len; - if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) - plen += 4; - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, plen, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - wpabuf_put_u8(resp, flags); /* Flags */ - if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) - wpabuf_put_be32(resp, wpabuf_len(data->out_buf)); - - wpabuf_put_data(resp, wpabuf_head_u8(data->out_buf) + data->out_used, - send_len); - data->out_used += send_len; - - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - - if (data->out_used == wpabuf_len(data->out_buf)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Sending out %lu bytes " - "(message sent completely)", - (unsigned long) send_len); - wpabuf_free(data->out_buf); - data->out_buf = NULL; - data->out_used = 0; - } else { - wpa_printf(MSG_DEBUG, "EAP-TNC: Sending out %lu bytes " - "(%lu more to send)", (unsigned long) send_len, - (unsigned long) wpabuf_len(data->out_buf) - - data->out_used); - data->state = WAIT_FRAG_ACK; - } - - return resp; -} - - -static int eap_tnc_process_cont(struct eap_tnc_data *data, - const u8 *buf, size_t len) -{ - /* Process continuation of a pending message */ - if (len > wpabuf_tailroom(data->in_buf)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Fragment overflow"); - data->state = FAIL; - return -1; - } - - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-TNC: Received %lu bytes, waiting for " - "%lu bytes more", (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - - return 0; -} - - -static struct wpabuf * eap_tnc_process_fragment(struct eap_tnc_data *data, - struct eap_method_ret *ret, - u8 id, u8 flags, - u32 message_length, - const u8 *buf, size_t len) -{ - /* Process a fragment that is not the last one of the message */ - if (data->in_buf == NULL && !(flags & EAP_TNC_FLAGS_LENGTH_INCLUDED)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: No Message Length field in a " - "fragmented packet"); - ret->ignore = TRUE; - return NULL; - } - - if (data->in_buf == NULL) { - /* First fragment of the message */ - data->in_buf = wpabuf_alloc(message_length); - if (data->in_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TNC: No memory for " - "message"); - ret->ignore = TRUE; - return NULL; - } - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-TNC: Received %lu bytes in first " - "fragment, waiting for %lu bytes more", - (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - } - - return eap_tnc_build_frag_ack(id, EAP_CODE_RESPONSE); -} - - -static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_tnc_data *data = priv; - struct wpabuf *resp; - const u8 *pos, *end; - u8 *rpos, *rpos1; - size_t len, rlen; - size_t imc_len; - char *start_buf, *end_buf; - size_t start_len, end_len; - int tncs_done = 0; - u8 flags, id; - u32 message_length = 0; - struct wpabuf tmpbuf; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TNC, reqData, &len); - if (pos == NULL) { - wpa_printf(MSG_INFO, "EAP-TNC: Invalid frame (pos=%p len=%lu)", - pos, (unsigned long) len); - ret->ignore = TRUE; - return NULL; - } - - id = eap_get_id(reqData); - - end = pos + len; - - if (len == 0) - flags = 0; /* fragment ack */ - else - flags = *pos++; - - if (len > 0 && (flags & EAP_TNC_VERSION_MASK) != EAP_TNC_VERSION) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Unsupported version %d", - flags & EAP_TNC_VERSION_MASK); - ret->ignore = TRUE; - return NULL; - } - - if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) { - if (end - pos < 4) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Message underflow"); - ret->ignore = TRUE; - return NULL; - } - message_length = WPA_GET_BE32(pos); - pos += 4; - - if (message_length < (u32) (end - pos)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Invalid Message " - "Length (%d; %ld remaining in this msg)", - message_length, (long) (end - pos)); - ret->ignore = TRUE; - return NULL; - } - } - - wpa_printf(MSG_DEBUG, "EAP-TNC: Received packet: Flags 0x%x " - "Message Length %u", flags, message_length); - - if (data->state == WAIT_FRAG_ACK) { - if (len != 0) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Unexpected payload in " - "WAIT_FRAG_ACK state"); - ret->ignore = TRUE; - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-TNC: Fragment acknowledged"); - data->state = PROC_MSG; - return eap_tnc_build_msg(data, ret, id); - } - - if (data->in_buf && eap_tnc_process_cont(data, pos, end - pos) < 0) { - ret->ignore = TRUE; - return NULL; - } - - if (flags & EAP_TNC_FLAGS_MORE_FRAGMENTS) { - return eap_tnc_process_fragment(data, ret, id, flags, - message_length, pos, - end - pos); - } - - if (data->in_buf == NULL) { - /* Wrap unfragmented messages as wpabuf without extra copy */ - wpabuf_set(&tmpbuf, pos, end - pos); - data->in_buf = &tmpbuf; - } - - if (data->state == WAIT_START) { - if (!(flags & EAP_TNC_FLAGS_START)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Server did not use " - "start flag in the first message"); - ret->ignore = TRUE; - goto fail; - } - - tncc_init_connection(data->tncc); - - data->state = PROC_MSG; - } else { - enum tncc_process_res res; - - if (flags & EAP_TNC_FLAGS_START) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Server used start " - "flag again"); - ret->ignore = TRUE; - goto fail; - } - - res = tncc_process_if_tnccs(data->tncc, - wpabuf_head(data->in_buf), - wpabuf_len(data->in_buf)); - switch (res) { - case TNCCS_PROCESS_ERROR: - ret->ignore = TRUE; - goto fail; - case TNCCS_PROCESS_OK_NO_RECOMMENDATION: - case TNCCS_RECOMMENDATION_ERROR: - wpa_printf(MSG_DEBUG, "EAP-TNC: No " - "TNCCS-Recommendation received"); - break; - case TNCCS_RECOMMENDATION_ALLOW: - wpa_msg(sm->msg_ctx, MSG_INFO, - "TNC: Recommendation = allow"); - tncs_done = 1; - break; - case TNCCS_RECOMMENDATION_NONE: - wpa_msg(sm->msg_ctx, MSG_INFO, - "TNC: Recommendation = none"); - tncs_done = 1; - break; - case TNCCS_RECOMMENDATION_ISOLATE: - wpa_msg(sm->msg_ctx, MSG_INFO, - "TNC: Recommendation = isolate"); - tncs_done = 1; - break; - } - } - - if (data->in_buf != &tmpbuf) - wpabuf_free(data->in_buf); - data->in_buf = NULL; - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = TRUE; - - if (data->out_buf) { - data->state = PROC_MSG; - return eap_tnc_build_msg(data, ret, id); - } - - if (tncs_done) { - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 1, - EAP_CODE_RESPONSE, eap_get_id(reqData)); - if (resp == NULL) - return NULL; - - wpabuf_put_u8(resp, EAP_TNC_VERSION); - wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS done - reply with an " - "empty ACK message"); - return resp; - } - - imc_len = tncc_total_send_len(data->tncc); - - start_buf = tncc_if_tnccs_start(data->tncc); - if (start_buf == NULL) - return NULL; - start_len = os_strlen(start_buf); - end_buf = tncc_if_tnccs_end(); - if (end_buf == NULL) { - os_free(start_buf); - return NULL; - } - end_len = os_strlen(end_buf); - - rlen = start_len + imc_len + end_len; - resp = wpabuf_alloc(rlen); - if (resp == NULL) { - os_free(start_buf); - os_free(end_buf); - return NULL; - } - - wpabuf_put_data(resp, start_buf, start_len); - os_free(start_buf); - - rpos1 = wpabuf_put(resp, 0); - rpos = tncc_copy_send_buf(data->tncc, rpos1); - wpabuf_put(resp, rpos - rpos1); - - wpabuf_put_data(resp, end_buf, end_len); - os_free(end_buf); - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TNC: Response", - wpabuf_head(resp), wpabuf_len(resp)); - - data->out_buf = resp; - data->state = PROC_MSG; - return eap_tnc_build_msg(data, ret, id); - -fail: - if (data->in_buf == &tmpbuf) - data->in_buf = NULL; - return NULL; -} - - -int eap_peer_tnc_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_TNC, "TNC"); - if (eap == NULL) - return -1; - - eap->init = eap_tnc_init; - eap->deinit = eap_tnc_deinit; - eap->process = eap_tnc_process; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_peer/eap_ttls.c b/contrib/hostapd/src/eap_peer/eap_ttls.c deleted file mode 100644 index 0851f8bb4d..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_ttls.c +++ /dev/null @@ -1,1983 +0,0 @@ -/* - * EAP peer method: EAP-TTLS (RFC 5281) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_peer/eap_i.h" -#include "eap_peer/eap_tls_common.h" -#include "eap_peer/eap_config.h" -#include "ms_funcs.h" -#include "sha1.h" -#include "eap_common/chap.h" -#include "tls.h" -#include "mschapv2.h" -#include "eap_common/eap_ttls.h" - - -/* Maximum supported TTLS version - * 0 = RFC 5281 - * 1 = draft-funk-eap-ttls-v1-00.txt - */ -#ifndef EAP_TTLS_VERSION -#define EAP_TTLS_VERSION 0 /* TTLSv1 implementation is not yet complete */ -#endif /* EAP_TTLS_VERSION */ - - -#define MSCHAPV2_KEY_LEN 16 -#define MSCHAPV2_NT_RESPONSE_LEN 24 - - -static void eap_ttls_deinit(struct eap_sm *sm, void *priv); - - -struct eap_ttls_data { - struct eap_ssl_data ssl; - int ssl_initialized; - - int ttls_version, force_ttls_version; - - const struct eap_method *phase2_method; - void *phase2_priv; - int phase2_success; - int phase2_start; - - enum phase2_types { - EAP_TTLS_PHASE2_EAP, - EAP_TTLS_PHASE2_MSCHAPV2, - EAP_TTLS_PHASE2_MSCHAP, - EAP_TTLS_PHASE2_PAP, - EAP_TTLS_PHASE2_CHAP - } phase2_type; - struct eap_method_type phase2_eap_type; - struct eap_method_type *phase2_eap_types; - size_t num_phase2_eap_types; - - u8 auth_response[MSCHAPV2_AUTH_RESPONSE_LEN]; - int auth_response_valid; - u8 master_key[MSCHAPV2_MASTER_KEY_LEN]; /* MSCHAPv2 master key */ - u8 ident; - int resuming; /* starting a resumed session */ - int reauth; /* reauthentication */ - u8 *key_data; - - struct wpabuf *pending_phase2_req; - -#ifdef EAP_TNC - int ready_for_tnc; - int tnc_started; -#endif /* EAP_TNC */ -}; - - -static void * eap_ttls_init(struct eap_sm *sm) -{ - struct eap_ttls_data *data; - struct eap_peer_config *config = eap_get_config(sm); - char *selected; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->ttls_version = EAP_TTLS_VERSION; - data->force_ttls_version = -1; - selected = "EAP"; - data->phase2_type = EAP_TTLS_PHASE2_EAP; - -#if EAP_TTLS_VERSION > 0 - if (config && config->phase1) { - const char *pos = os_strstr(config->phase1, "ttlsver="); - if (pos) { - data->force_ttls_version = atoi(pos + 8); - data->ttls_version = data->force_ttls_version; - wpa_printf(MSG_DEBUG, "EAP-TTLS: Forced TTLS version " - "%d", data->force_ttls_version); - } - } -#endif /* EAP_TTLS_VERSION */ - - if (config && config->phase2) { - if (os_strstr(config->phase2, "autheap=")) { - selected = "EAP"; - data->phase2_type = EAP_TTLS_PHASE2_EAP; - } else if (os_strstr(config->phase2, "auth=MSCHAPV2")) { - selected = "MSCHAPV2"; - data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2; - } else if (os_strstr(config->phase2, "auth=MSCHAP")) { - selected = "MSCHAP"; - data->phase2_type = EAP_TTLS_PHASE2_MSCHAP; - } else if (os_strstr(config->phase2, "auth=PAP")) { - selected = "PAP"; - data->phase2_type = EAP_TTLS_PHASE2_PAP; - } else if (os_strstr(config->phase2, "auth=CHAP")) { - selected = "CHAP"; - data->phase2_type = EAP_TTLS_PHASE2_CHAP; - } - } - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 type: %s", selected); - - if (data->phase2_type == EAP_TTLS_PHASE2_EAP) { - if (eap_peer_select_phase2_methods(config, "autheap=", - &data->phase2_eap_types, - &data->num_phase2_eap_types) - < 0) { - eap_ttls_deinit(sm, data); - return NULL; - } - - data->phase2_eap_type.vendor = EAP_VENDOR_IETF; - data->phase2_eap_type.method = EAP_TYPE_NONE; - } - -#if EAP_TTLS_VERSION > 0 - if (!(tls_capabilities(sm->ssl_ctx) & TLS_CAPABILITY_IA) && - data->ttls_version > 0) { - if (data->force_ttls_version > 0) { - wpa_printf(MSG_INFO, "EAP-TTLS: Forced TTLSv%d and " - "TLS library does not support TLS/IA.", - data->force_ttls_version); - eap_ttls_deinit(sm, data); - return NULL; - } - data->ttls_version = 0; - } -#endif /* EAP_TTLS_VERSION */ - - return data; -} - - -static void eap_ttls_phase2_eap_deinit(struct eap_sm *sm, - struct eap_ttls_data *data) -{ - if (data->phase2_priv && data->phase2_method) { - data->phase2_method->deinit(sm, data->phase2_priv); - data->phase2_method = NULL; - data->phase2_priv = NULL; - } -} - - -static void eap_ttls_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - if (data == NULL) - return; - eap_ttls_phase2_eap_deinit(sm, data); - os_free(data->phase2_eap_types); - if (data->ssl_initialized) - eap_peer_tls_ssl_deinit(sm, &data->ssl); - os_free(data->key_data); - wpabuf_free(data->pending_phase2_req); - os_free(data); -} - - -static u8 * eap_ttls_avp_hdr(u8 *avphdr, u32 avp_code, u32 vendor_id, - int mandatory, size_t len) -{ - struct ttls_avp_vendor *avp; - u8 flags; - size_t hdrlen; - - avp = (struct ttls_avp_vendor *) avphdr; - flags = mandatory ? AVP_FLAGS_MANDATORY : 0; - if (vendor_id) { - flags |= AVP_FLAGS_VENDOR; - hdrlen = sizeof(*avp); - avp->vendor_id = host_to_be32(vendor_id); - } else { - hdrlen = sizeof(struct ttls_avp); - } - - avp->avp_code = host_to_be32(avp_code); - avp->avp_length = host_to_be32((flags << 24) | (hdrlen + len)); - - return avphdr + hdrlen; -} - - -static u8 * eap_ttls_avp_add(u8 *start, u8 *avphdr, u32 avp_code, - u32 vendor_id, int mandatory, - const u8 *data, size_t len) -{ - u8 *pos; - pos = eap_ttls_avp_hdr(avphdr, avp_code, vendor_id, mandatory, len); - os_memcpy(pos, data, len); - pos += len; - AVP_PAD(start, pos); - return pos; -} - - -static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code, - int mandatory) -{ - struct wpabuf *msg; - u8 *avp, *pos; - - msg = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(*resp) + 4); - if (msg == NULL) { - wpabuf_free(*resp); - *resp = NULL; - return -1; - } - - avp = wpabuf_mhead(msg); - pos = eap_ttls_avp_hdr(avp, avp_code, 0, mandatory, wpabuf_len(*resp)); - os_memcpy(pos, wpabuf_head(*resp), wpabuf_len(*resp)); - pos += wpabuf_len(*resp); - AVP_PAD(avp, pos); - wpabuf_free(*resp); - wpabuf_put(msg, pos - avp); - *resp = msg; - return 0; -} - - -#if EAP_TTLS_VERSION > 0 -static int eap_ttls_ia_permute_inner_secret(struct eap_sm *sm, - struct eap_ttls_data *data, - const u8 *key, size_t key_len) -{ - u8 *buf; - size_t buf_len; - int ret; - - if (key) { - buf_len = 2 + key_len; - buf = os_malloc(buf_len); - if (buf == NULL) - return -1; - WPA_PUT_BE16(buf, key_len); - os_memcpy(buf + 2, key, key_len); - } else { - buf = NULL; - buf_len = 0; - } - - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Session keys for TLS/IA inner " - "secret permutation", buf, buf_len); - ret = tls_connection_ia_permute_inner_secret(sm->ssl_ctx, - data->ssl.conn, - buf, buf_len); - os_free(buf); - - return ret; -} -#endif /* EAP_TTLS_VERSION */ - - -static int eap_ttls_v0_derive_key(struct eap_sm *sm, - struct eap_ttls_data *data) -{ - os_free(data->key_data); - data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, - "ttls keying material", - EAP_TLS_KEY_LEN); - if (!data->key_data) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to derive key"); - return -1; - } - - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key", - data->key_data, EAP_TLS_KEY_LEN); - - return 0; -} - - -#if EAP_TTLS_VERSION > 0 -static int eap_ttls_v1_derive_key(struct eap_sm *sm, - struct eap_ttls_data *data) -{ - struct tls_keys keys; - u8 *rnd; - - os_free(data->key_data); - data->key_data = NULL; - - os_memset(&keys, 0, sizeof(keys)); - if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) || - keys.client_random == NULL || keys.server_random == NULL || - keys.inner_secret == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, " - "client random, or server random to derive keying " - "material"); - return -1; - } - - rnd = os_malloc(keys.client_random_len + keys.server_random_len); - data->key_data = os_malloc(EAP_TLS_KEY_LEN); - if (rnd == NULL || data->key_data == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: No memory for key derivation"); - os_free(rnd); - os_free(data->key_data); - data->key_data = NULL; - return -1; - } - os_memcpy(rnd, keys.client_random, keys.client_random_len); - os_memcpy(rnd + keys.client_random_len, keys.server_random, - keys.server_random_len); - - if (tls_prf(keys.inner_secret, keys.inner_secret_len, - "ttls v1 keying material", rnd, keys.client_random_len + - keys.server_random_len, data->key_data, EAP_TLS_KEY_LEN)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key"); - os_free(rnd); - os_free(data->key_data); - data->key_data = NULL; - return -1; - } - - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: client/server random", - rnd, keys.client_random_len + keys.server_random_len); - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: TLS/IA inner secret", - keys.inner_secret, keys.inner_secret_len); - - os_free(rnd); - - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key", - data->key_data, EAP_TLS_KEY_LEN); - - return 0; -} -#endif /* EAP_TTLS_VERSION */ - - -static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm, - struct eap_ttls_data *data, size_t len) -{ -#if EAP_TTLS_VERSION > 0 - struct tls_keys keys; - u8 *challenge, *rnd; -#endif /* EAP_TTLS_VERSION */ - - if (data->ttls_version == 0) { - return eap_peer_tls_derive_key(sm, &data->ssl, - "ttls challenge", len); - } - -#if EAP_TTLS_VERSION > 0 - - os_memset(&keys, 0, sizeof(keys)); - if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) || - keys.client_random == NULL || keys.server_random == NULL || - keys.inner_secret == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, " - "client random, or server random to derive " - "implicit challenge"); - return NULL; - } - - rnd = os_malloc(keys.client_random_len + keys.server_random_len); - challenge = os_malloc(len); - if (rnd == NULL || challenge == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: No memory for implicit " - "challenge derivation"); - os_free(rnd); - os_free(challenge); - return NULL; - } - os_memcpy(rnd, keys.server_random, keys.server_random_len); - os_memcpy(rnd + keys.server_random_len, keys.client_random, - keys.client_random_len); - - if (tls_prf(keys.inner_secret, keys.inner_secret_len, - "inner application challenge", rnd, - keys.client_random_len + keys.server_random_len, - challenge, len)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive implicit " - "challenge"); - os_free(rnd); - os_free(challenge); - return NULL; - } - - os_free(rnd); - - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived implicit challenge", - challenge, len); - - return challenge; - -#else /* EAP_TTLS_VERSION */ - - return NULL; - -#endif /* EAP_TTLS_VERSION */ -} - - -static void eap_ttlsv1_phase2_eap_finish(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret) -{ -#if EAP_TTLS_VERSION > 0 - if (data->ttls_version > 0) { - const struct eap_method *m = data->phase2_method; - void *priv = data->phase2_priv; - - /* TTLSv1 requires TLS/IA FinalPhaseFinished */ - if (ret->decision == DECISION_UNCOND_SUCC) - ret->decision = DECISION_COND_SUCC; - ret->methodState = METHOD_CONT; - - if (ret->decision == DECISION_COND_SUCC && - m->isKeyAvailable && m->getKey && - m->isKeyAvailable(sm, priv)) { - u8 *key; - size_t key_len; - key = m->getKey(sm, priv, &key_len); - if (key) { - eap_ttls_ia_permute_inner_secret( - sm, data, key, key_len); - os_free(key); - } - } - } -#endif /* EAP_TTLS_VERSION */ -} - - -static void eap_ttls_phase2_select_eap_method(struct eap_ttls_data *data, - u8 method) -{ - size_t i; - for (i = 0; i < data->num_phase2_eap_types; i++) { - if (data->phase2_eap_types[i].vendor != EAP_VENDOR_IETF || - data->phase2_eap_types[i].method != method) - continue; - - data->phase2_eap_type.vendor = - data->phase2_eap_types[i].vendor; - data->phase2_eap_type.method = - data->phase2_eap_types[i].method; - wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected " - "Phase 2 EAP vendor %d method %d", - data->phase2_eap_type.vendor, - data->phase2_eap_type.method); - break; - } -} - - -static int eap_ttls_phase2_eap_process(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct eap_hdr *hdr, size_t len, - struct wpabuf **resp) -{ - struct wpabuf msg; - struct eap_method_ret iret; - - os_memset(&iret, 0, sizeof(iret)); - wpabuf_set(&msg, hdr, len); - *resp = data->phase2_method->process(sm, data->phase2_priv, &iret, - &msg); - if ((iret.methodState == METHOD_DONE || - iret.methodState == METHOD_MAY_CONT) && - (iret.decision == DECISION_UNCOND_SUCC || - iret.decision == DECISION_COND_SUCC || - iret.decision == DECISION_FAIL)) { - ret->methodState = iret.methodState; - ret->decision = iret.decision; - } - eap_ttlsv1_phase2_eap_finish(sm, data, ret); - - return 0; -} - - -static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct eap_hdr *hdr, size_t len, - u8 method, struct wpabuf **resp) -{ -#ifdef EAP_TNC - if (data->tnc_started && data->phase2_method && - data->phase2_priv && method == EAP_TYPE_TNC && - data->phase2_eap_type.method == EAP_TYPE_TNC) - return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len, - resp); - - if (data->ready_for_tnc && !data->tnc_started && - method == EAP_TYPE_TNC) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed " - "EAP method"); - data->tnc_started = 1; - } - - if (data->tnc_started) { - if (data->phase2_eap_type.vendor != EAP_VENDOR_IETF || - data->phase2_eap_type.method == EAP_TYPE_TNC) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Unexpected EAP " - "type %d for TNC", method); - return -1; - } - - data->phase2_eap_type.vendor = EAP_VENDOR_IETF; - data->phase2_eap_type.method = method; - wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected " - "Phase 2 EAP vendor %d method %d (TNC)", - data->phase2_eap_type.vendor, - data->phase2_eap_type.method); - - if (data->phase2_type == EAP_TTLS_PHASE2_EAP) - eap_ttls_phase2_eap_deinit(sm, data); - } -#endif /* EAP_TNC */ - - if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF && - data->phase2_eap_type.method == EAP_TYPE_NONE) - eap_ttls_phase2_select_eap_method(data, method); - - if (method != data->phase2_eap_type.method || method == EAP_TYPE_NONE) - { - if (eap_peer_tls_phase2_nak(data->phase2_eap_types, - data->num_phase2_eap_types, - hdr, resp)) - return -1; - return 0; - } - - if (data->phase2_priv == NULL) { - data->phase2_method = eap_peer_get_eap_method( - EAP_VENDOR_IETF, method); - if (data->phase2_method) { - sm->init_phase2 = 1; - data->phase2_priv = data->phase2_method->init(sm); - sm->init_phase2 = 0; - } - } - if (data->phase2_priv == NULL || data->phase2_method == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: failed to initialize " - "Phase 2 EAP method %d", method); - return -1; - } - - return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len, resp); -} - - -static int eap_ttls_phase2_request_eap(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct eap_hdr *hdr, - struct wpabuf **resp) -{ - size_t len = be_to_host16(hdr->length); - u8 *pos; - struct eap_peer_config *config = eap_get_config(sm); - - if (len <= sizeof(struct eap_hdr)) { - wpa_printf(MSG_INFO, "EAP-TTLS: too short " - "Phase 2 request (len=%lu)", (unsigned long) len); - return -1; - } - pos = (u8 *) (hdr + 1); - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP Request: type=%d", *pos); - switch (*pos) { - case EAP_TYPE_IDENTITY: - *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1); - break; - default: - if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len, - *pos, resp) < 0) - return -1; - break; - } - - if (*resp == NULL && - (config->pending_req_identity || config->pending_req_password || - config->pending_req_otp)) { - return 0; - } - - if (*resp == NULL) - return -1; - - wpa_hexdump_buf(MSG_DEBUG, "EAP-TTLS: AVP encapsulate EAP Response", - *resp); - return eap_ttls_avp_encapsulate(resp, RADIUS_ATTR_EAP_MESSAGE, 1); -} - - -static void eap_ttlsv1_permute_inner(struct eap_sm *sm, - struct eap_ttls_data *data) -{ -#if EAP_TTLS_VERSION > 0 - u8 session_key[2 * MSCHAPV2_KEY_LEN]; - - if (data->ttls_version == 0) - return; - - get_asymetric_start_key(data->master_key, session_key, - MSCHAPV2_KEY_LEN, 0, 0); - get_asymetric_start_key(data->master_key, - session_key + MSCHAPV2_KEY_LEN, - MSCHAPV2_KEY_LEN, 1, 0); - eap_ttls_ia_permute_inner_secret(sm, data, session_key, - sizeof(session_key)); -#endif /* EAP_TTLS_VERSION */ -} - - -static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct wpabuf **resp) -{ - struct wpabuf *msg; - u8 *buf, *pos, *challenge, *peer_challenge; - const u8 *identity, *password; - size_t identity_len, password_len; - int pwhash; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAPV2 Request"); - - identity = eap_get_config_identity(sm, &identity_len); - password = eap_get_config_password2(sm, &password_len, &pwhash); - if (identity == NULL || password == NULL) - return -1; - - msg = wpabuf_alloc(identity_len + 1000); - if (msg == NULL) { - wpa_printf(MSG_ERROR, - "EAP-TTLS/MSCHAPV2: Failed to allocate memory"); - return -1; - } - pos = buf = wpabuf_mhead(msg); - - /* User-Name */ - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, - identity, identity_len); - - /* MS-CHAP-Challenge */ - challenge = eap_ttls_implicit_challenge( - sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1); - if (challenge == NULL) { - wpabuf_free(msg); - wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive " - "implicit challenge"); - return -1; - } - peer_challenge = challenge + 1 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN; - - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE, - RADIUS_VENDOR_ID_MICROSOFT, 1, - challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); - - /* MS-CHAP2-Response */ - pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP2_RESPONSE, - RADIUS_VENDOR_ID_MICROSOFT, 1, - EAP_TTLS_MSCHAPV2_RESPONSE_LEN); - data->ident = challenge[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN]; - *pos++ = data->ident; - *pos++ = 0; /* Flags */ - os_memcpy(pos, peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); - pos += EAP_TTLS_MSCHAPV2_CHALLENGE_LEN; - os_memset(pos, 0, 8); /* Reserved, must be zero */ - pos += 8; - mschapv2_derive_response(identity, identity_len, password, - password_len, pwhash, challenge, - peer_challenge, pos, data->auth_response, - data->master_key); - data->auth_response_valid = 1; - - eap_ttlsv1_permute_inner(sm, data); - - pos += 24; - os_free(challenge); - AVP_PAD(buf, pos); - - wpabuf_put(msg, pos - buf); - *resp = msg; - - if (sm->workaround && data->ttls_version == 0) { - /* At least FreeRADIUS seems to be terminating - * EAP-TTLS/MSHCAPV2 without the expected MS-CHAP-v2 Success - * packet. */ - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: EAP workaround - " - "allow success without tunneled response"); - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_COND_SUCC; - } - - return 0; -} - - -static int eap_ttls_phase2_request_mschap(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct wpabuf **resp) -{ - struct wpabuf *msg; - u8 *buf, *pos, *challenge; - const u8 *identity, *password; - size_t identity_len, password_len; - int pwhash; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAP Request"); - - identity = eap_get_config_identity(sm, &identity_len); - password = eap_get_config_password2(sm, &password_len, &pwhash); - if (identity == NULL || password == NULL) - return -1; - - msg = wpabuf_alloc(identity_len + 1000); - if (msg == NULL) { - wpa_printf(MSG_ERROR, - "EAP-TTLS/MSCHAP: Failed to allocate memory"); - return -1; - } - pos = buf = wpabuf_mhead(msg); - - /* User-Name */ - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, - identity, identity_len); - - /* MS-CHAP-Challenge */ - challenge = eap_ttls_implicit_challenge( - sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1); - if (challenge == NULL) { - wpabuf_free(msg); - wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive " - "implicit challenge"); - return -1; - } - - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE, - RADIUS_VENDOR_ID_MICROSOFT, 1, - challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN); - - /* MS-CHAP-Response */ - pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_RESPONSE, - RADIUS_VENDOR_ID_MICROSOFT, 1, - EAP_TTLS_MSCHAP_RESPONSE_LEN); - data->ident = challenge[EAP_TTLS_MSCHAP_CHALLENGE_LEN]; - *pos++ = data->ident; - *pos++ = 1; /* Flags: Use NT style passwords */ - os_memset(pos, 0, 24); /* LM-Response */ - pos += 24; - if (pwhash) { - challenge_response(challenge, password, pos); /* NT-Response */ - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password hash", - password, 16); - } else { - nt_challenge_response(challenge, password, password_len, - pos); /* NT-Response */ - wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password", - password, password_len); - } - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP implicit challenge", - challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP response", pos, 24); - pos += 24; - os_free(challenge); - AVP_PAD(buf, pos); - - wpabuf_put(msg, pos - buf); - *resp = msg; - - if (data->ttls_version > 0) { - /* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success, - * so do not allow connection to be terminated yet. */ - ret->methodState = METHOD_CONT; - ret->decision = DECISION_COND_SUCC; - } else { - /* EAP-TTLS/MSCHAP does not provide tunneled success - * notification, so assume that Phase2 succeeds. */ - ret->methodState = METHOD_DONE; - ret->decision = DECISION_COND_SUCC; - } - - return 0; -} - - -static int eap_ttls_phase2_request_pap(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct wpabuf **resp) -{ - struct wpabuf *msg; - u8 *buf, *pos; - size_t pad; - const u8 *identity, *password; - size_t identity_len, password_len; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 PAP Request"); - - identity = eap_get_config_identity(sm, &identity_len); - password = eap_get_config_password(sm, &password_len); - if (identity == NULL || password == NULL) - return -1; - - msg = wpabuf_alloc(identity_len + password_len + 100); - if (msg == NULL) { - wpa_printf(MSG_ERROR, - "EAP-TTLS/PAP: Failed to allocate memory"); - return -1; - } - pos = buf = wpabuf_mhead(msg); - - /* User-Name */ - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, - identity, identity_len); - - /* User-Password; in RADIUS, this is encrypted, but EAP-TTLS encrypts - * the data, so no separate encryption is used in the AVP itself. - * However, the password is padded to obfuscate its length. */ - pad = password_len == 0 ? 16 : (16 - (password_len & 15)) & 15; - pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_USER_PASSWORD, 0, 1, - password_len + pad); - os_memcpy(pos, password, password_len); - pos += password_len; - os_memset(pos, 0, pad); - pos += pad; - AVP_PAD(buf, pos); - - wpabuf_put(msg, pos - buf); - *resp = msg; - - if (data->ttls_version > 0) { - /* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success, - * so do not allow connection to be terminated yet. */ - ret->methodState = METHOD_CONT; - ret->decision = DECISION_COND_SUCC; - } else { - /* EAP-TTLS/PAP does not provide tunneled success notification, - * so assume that Phase2 succeeds. */ - ret->methodState = METHOD_DONE; - ret->decision = DECISION_COND_SUCC; - } - - return 0; -} - - -static int eap_ttls_phase2_request_chap(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct wpabuf **resp) -{ - struct wpabuf *msg; - u8 *buf, *pos, *challenge; - const u8 *identity, *password; - size_t identity_len, password_len; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 CHAP Request"); - - identity = eap_get_config_identity(sm, &identity_len); - password = eap_get_config_password(sm, &password_len); - if (identity == NULL || password == NULL) - return -1; - - msg = wpabuf_alloc(identity_len + 1000); - if (msg == NULL) { - wpa_printf(MSG_ERROR, - "EAP-TTLS/CHAP: Failed to allocate memory"); - return -1; - } - pos = buf = wpabuf_mhead(msg); - - /* User-Name */ - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, - identity, identity_len); - - /* CHAP-Challenge */ - challenge = eap_ttls_implicit_challenge( - sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1); - if (challenge == NULL) { - wpabuf_free(msg); - wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive " - "implicit challenge"); - return -1; - } - - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_CHAP_CHALLENGE, 0, 1, - challenge, EAP_TTLS_CHAP_CHALLENGE_LEN); - - /* CHAP-Password */ - pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_CHAP_PASSWORD, 0, 1, - 1 + EAP_TTLS_CHAP_PASSWORD_LEN); - data->ident = challenge[EAP_TTLS_CHAP_CHALLENGE_LEN]; - *pos++ = data->ident; - - /* MD5(Ident + Password + Challenge) */ - chap_md5(data->ident, password, password_len, challenge, - EAP_TTLS_CHAP_CHALLENGE_LEN, pos); - - wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: CHAP username", - identity, identity_len); - wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: CHAP password", - password, password_len); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP implicit challenge", - challenge, EAP_TTLS_CHAP_CHALLENGE_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP password", - pos, EAP_TTLS_CHAP_PASSWORD_LEN); - pos += EAP_TTLS_CHAP_PASSWORD_LEN; - os_free(challenge); - AVP_PAD(buf, pos); - - wpabuf_put(msg, pos - buf); - *resp = msg; - - if (data->ttls_version > 0) { - /* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success, - * so do not allow connection to be terminated yet. */ - ret->methodState = METHOD_CONT; - ret->decision = DECISION_COND_SUCC; - } else { - /* EAP-TTLS/CHAP does not provide tunneled success - * notification, so assume that Phase2 succeeds. */ - ret->methodState = METHOD_DONE; - ret->decision = DECISION_COND_SUCC; - } - - return 0; -} - - -static int eap_ttls_phase2_request(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct eap_hdr *hdr, - struct wpabuf **resp) -{ - int res = 0; - size_t len; - enum phase2_types phase2_type = data->phase2_type; - -#ifdef EAP_TNC - if (data->tnc_started) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Processing TNC"); - phase2_type = EAP_TTLS_PHASE2_EAP; - } -#endif /* EAP_TNC */ - - if (phase2_type == EAP_TTLS_PHASE2_MSCHAPV2 || - phase2_type == EAP_TTLS_PHASE2_MSCHAP || - phase2_type == EAP_TTLS_PHASE2_PAP || - phase2_type == EAP_TTLS_PHASE2_CHAP) { - if (eap_get_config_identity(sm, &len) == NULL) { - wpa_printf(MSG_INFO, - "EAP-TTLS: Identity not configured"); - eap_sm_request_identity(sm); - if (eap_get_config_password(sm, &len) == NULL) - eap_sm_request_password(sm); - return 0; - } - - if (eap_get_config_password(sm, &len) == NULL) { - wpa_printf(MSG_INFO, - "EAP-TTLS: Password not configured"); - eap_sm_request_password(sm); - return 0; - } - } - - switch (phase2_type) { - case EAP_TTLS_PHASE2_EAP: - res = eap_ttls_phase2_request_eap(sm, data, ret, hdr, resp); - break; - case EAP_TTLS_PHASE2_MSCHAPV2: - res = eap_ttls_phase2_request_mschapv2(sm, data, ret, resp); - break; - case EAP_TTLS_PHASE2_MSCHAP: - res = eap_ttls_phase2_request_mschap(sm, data, ret, resp); - break; - case EAP_TTLS_PHASE2_PAP: - res = eap_ttls_phase2_request_pap(sm, data, ret, resp); - break; - case EAP_TTLS_PHASE2_CHAP: - res = eap_ttls_phase2_request_chap(sm, data, ret, resp); - break; - default: - wpa_printf(MSG_ERROR, "EAP-TTLS: Phase 2 - Unknown"); - res = -1; - break; - } - - if (res < 0) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - } - - return res; -} - - -#if EAP_TTLS_VERSION > 0 -static struct wpabuf * eap_ttls_build_phase_finished( - struct eap_sm *sm, struct eap_ttls_data *data, int id, int final) -{ - int len; - struct wpabuf *req; - u8 *pos; - const int max_len = 300; - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TTLS, 1 + max_len, - EAP_CODE_RESPONSE, id); - if (req == NULL) - return NULL; - - wpabuf_put_u8(req, data->ttls_version); - - pos = wpabuf_put(req, 0); - len = tls_connection_ia_send_phase_finished(sm->ssl_ctx, - data->ssl.conn, - final, pos, max_len); - if (len < 0) { - wpabuf_free(req); - return NULL; - } - wpabuf_put(req, len); - eap_update_len(req); - - return req; -} -#endif /* EAP_TTLS_VERSION */ - - -struct ttls_parse_avp { - u8 *mschapv2; - u8 *eapdata; - size_t eap_len; - int mschapv2_error; -}; - - -static int eap_ttls_parse_attr_eap(const u8 *dpos, size_t dlen, - struct ttls_parse_avp *parse) -{ - wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message"); - if (parse->eapdata == NULL) { - parse->eapdata = os_malloc(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); - if (neweap == NULL) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to allocate " - "memory for Phase 2 EAP data"); - return -1; - } - os_memcpy(neweap + parse->eap_len, dpos, dlen); - parse->eapdata = neweap; - parse->eap_len += dlen; - } - - return 0; -} - - -static int eap_ttls_parse_avp(u8 *pos, size_t left, - struct ttls_parse_avp *parse) -{ - struct ttls_avp *avp; - u32 avp_code, avp_length, vendor_id = 0; - u8 avp_flags, *dpos; - size_t dlen; - - avp = (struct ttls_avp *) pos; - avp_code = be_to_host32(avp->avp_code); - avp_length = be_to_host32(avp->avp_length); - avp_flags = (avp_length >> 24) & 0xff; - avp_length &= 0xffffff; - wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP: code=%d flags=0x%02x " - "length=%d", (int) avp_code, avp_flags, - (int) avp_length); - - if (avp_length > left) { - wpa_printf(MSG_WARNING, "EAP-TTLS: AVP overflow " - "(len=%d, left=%lu) - dropped", - (int) avp_length, (unsigned long) left); - return -1; - } - - if (avp_length < sizeof(*avp)) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid AVP length %d", - avp_length); - return -1; - } - - dpos = (u8 *) (avp + 1); - dlen = avp_length - sizeof(*avp); - if (avp_flags & AVP_FLAGS_VENDOR) { - if (dlen < 4) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Vendor AVP " - "underflow"); - return -1; - } - vendor_id = WPA_GET_BE32(dpos); - wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP vendor_id %d", - (int) vendor_id); - dpos += 4; - dlen -= 4; - } - - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP data", dpos, dlen); - - if (vendor_id == 0 && avp_code == RADIUS_ATTR_EAP_MESSAGE) { - if (eap_ttls_parse_attr_eap(dpos, dlen, parse) < 0) - return -1; - } else if (vendor_id == 0 && avp_code == RADIUS_ATTR_REPLY_MESSAGE) { - /* This is an optional message that can be displayed to - * the user. */ - wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: AVP - Reply-Message", - dpos, dlen); - } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT && - avp_code == RADIUS_ATTR_MS_CHAP2_SUCCESS) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MS-CHAP2-Success", - dpos, dlen); - if (dlen != 43) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Unexpected " - "MS-CHAP2-Success length " - "(len=%lu, expected 43)", - (unsigned long) dlen); - return -1; - } - parse->mschapv2 = dpos; - } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT && - avp_code == RADIUS_ATTR_MS_CHAP_ERROR) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MS-CHAP-Error", - dpos, dlen); - parse->mschapv2_error = 1; - } else if (avp_flags & AVP_FLAGS_MANDATORY) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Unsupported mandatory AVP " - "code %d vendor_id %d - dropped", - (int) avp_code, (int) vendor_id); - return -1; - } else { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Ignoring unsupported AVP " - "code %d vendor_id %d", - (int) avp_code, (int) vendor_id); - } - - return avp_length; -} - - -static int eap_ttls_parse_avps(struct wpabuf *in_decrypted, - struct ttls_parse_avp *parse) -{ - u8 *pos; - size_t left, pad; - int avp_length; - - pos = wpabuf_mhead(in_decrypted); - left = wpabuf_len(in_decrypted); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 AVPs", pos, left); - if (left < sizeof(struct ttls_avp)) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 AVP frame" - " len=%lu expected %lu or more - dropped", - (unsigned long) left, - (unsigned long) sizeof(struct ttls_avp)); - return -1; - } - - /* Parse AVPs */ - os_memset(parse, 0, sizeof(*parse)); - - while (left > 0) { - avp_length = eap_ttls_parse_avp(pos, left, parse); - if (avp_length < 0) - return -1; - - pad = (4 - (avp_length & 3)) & 3; - pos += avp_length + pad; - if (left < avp_length + pad) - left = 0; - else - left -= avp_length + pad; - } - - return 0; -} - - -static u8 * eap_ttls_fake_identity_request(void) -{ - struct eap_hdr *hdr; - u8 *buf; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: empty data in beginning of " - "Phase 2 - use fake EAP-Request Identity"); - buf = os_malloc(sizeof(*hdr) + 1); - if (buf == NULL) { - wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate " - "memory for fake EAP-Identity Request"); - return NULL; - } - - hdr = (struct eap_hdr *) buf; - hdr->code = EAP_CODE_REQUEST; - hdr->identifier = 0; - hdr->length = host_to_be16(sizeof(*hdr) + 1); - buf[sizeof(*hdr)] = EAP_TYPE_IDENTITY; - - return buf; -} - - -static int eap_ttls_encrypt_response(struct eap_sm *sm, - struct eap_ttls_data *data, - struct wpabuf *resp, u8 identifier, - struct wpabuf **out_data) -{ - if (resp == NULL) - return 0; - - wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS: Encrypting Phase 2 data", - resp); - if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TTLS, - data->ttls_version, identifier, - resp, out_data)) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt a Phase 2 " - "frame"); - return -1; - } - wpabuf_free(resp); - - return 0; -} - - -static int eap_ttls_process_phase2_eap(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct ttls_parse_avp *parse, - struct wpabuf **resp) -{ - struct eap_hdr *hdr; - size_t len; - - if (parse->eapdata == NULL) { - wpa_printf(MSG_WARNING, "EAP-TTLS: No EAP Message in the " - "packet - dropped"); - return -1; - } - - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP", - parse->eapdata, parse->eap_len); - hdr = (struct eap_hdr *) parse->eapdata; - - if (parse->eap_len < sizeof(*hdr)) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 EAP " - "frame (len=%lu, expected %lu or more) - dropped", - (unsigned long) parse->eap_len, - (unsigned long) sizeof(*hdr)); - return -1; - } - len = be_to_host16(hdr->length); - if (len > parse->eap_len) { - wpa_printf(MSG_INFO, "EAP-TTLS: Length mismatch in Phase 2 " - "EAP frame (EAP hdr len=%lu, EAP data len in " - "AVP=%lu)", - (unsigned long) len, - (unsigned long) parse->eap_len); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-TTLS: received Phase 2: code=%d " - "identifier=%d length=%lu", - hdr->code, hdr->identifier, (unsigned long) len); - switch (hdr->code) { - case EAP_CODE_REQUEST: - if (eap_ttls_phase2_request(sm, data, ret, hdr, resp)) { - wpa_printf(MSG_INFO, "EAP-TTLS: Phase2 Request " - "processing failed"); - return -1; - } - break; - default: - wpa_printf(MSG_INFO, "EAP-TTLS: Unexpected code=%d in " - "Phase 2 EAP header", hdr->code); - return -1; - } - - return 0; -} - - -static int eap_ttls_process_phase2_mschapv2(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct ttls_parse_avp *parse) -{ - if (parse->mschapv2_error) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Received " - "MS-CHAP-Error - failed"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - /* Reply with empty data to ACK error */ - return 1; - } - - if (parse->mschapv2 == NULL) { -#ifdef EAP_TNC - if (data->phase2_success && parse->eapdata) { - /* - * Allow EAP-TNC to be started after successfully - * completed MSCHAPV2. - */ - return 1; - } -#endif /* EAP_TNC */ - wpa_printf(MSG_WARNING, "EAP-TTLS: no MS-CHAP2-Success AVP " - "received for Phase2 MSCHAPV2"); - return -1; - } - if (parse->mschapv2[0] != data->ident) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Ident mismatch for Phase 2 " - "MSCHAPV2 (received Ident 0x%02x, expected 0x%02x)", - parse->mschapv2[0], data->ident); - return -1; - } - if (!data->auth_response_valid || - mschapv2_verify_auth_response(data->auth_response, - parse->mschapv2 + 1, 42)) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid authenticator " - "response in Phase 2 MSCHAPV2 success request"); - return -1; - } - - wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 MSCHAPV2 " - "authentication succeeded"); - if (data->ttls_version > 0) { - /* - * EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report - * success, so do not allow connection to be terminated - * yet. - */ - ret->methodState = METHOD_CONT; - ret->decision = DECISION_COND_SUCC; - } else { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - data->phase2_success = 1; - } - - /* - * Reply with empty data; authentication server will reply - * with EAP-Success after this. - */ - return 1; -} - - -#ifdef EAP_TNC -static int eap_ttls_process_tnc_start(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct ttls_parse_avp *parse, - struct wpabuf **resp) -{ - /* TNC uses inner EAP method after non-EAP TTLS phase 2. */ - if (parse->eapdata == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received " - "unexpected tunneled data (no EAP)"); - return -1; - } - - if (!data->ready_for_tnc) { - wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received " - "EAP after non-EAP, but not ready for TNC"); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed " - "non-EAP method"); - data->tnc_started = 1; - - if (eap_ttls_process_phase2_eap(sm, data, ret, parse, resp) < 0) - return -1; - - return 0; -} -#endif /* EAP_TNC */ - - -static int eap_ttls_process_decrypted(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - u8 identifier, - struct ttls_parse_avp *parse, - struct wpabuf *in_decrypted, - struct wpabuf **out_data) -{ - struct wpabuf *resp = NULL; - struct eap_peer_config *config = eap_get_config(sm); - int res; - enum phase2_types phase2_type = data->phase2_type; - -#ifdef EAP_TNC - if (data->tnc_started) - phase2_type = EAP_TTLS_PHASE2_EAP; -#endif /* EAP_TNC */ - - switch (phase2_type) { - case EAP_TTLS_PHASE2_EAP: - if (eap_ttls_process_phase2_eap(sm, data, ret, parse, &resp) < - 0) - return -1; - break; - case EAP_TTLS_PHASE2_MSCHAPV2: - res = eap_ttls_process_phase2_mschapv2(sm, data, ret, parse); -#ifdef EAP_TNC - if (res == 1 && parse->eapdata && data->phase2_success) { - /* - * TNC may be required as the next - * authentication method within the tunnel. - */ - ret->methodState = METHOD_MAY_CONT; - data->ready_for_tnc = 1; - if (eap_ttls_process_tnc_start(sm, data, ret, parse, - &resp) == 0) - break; - } -#endif /* EAP_TNC */ - return res; - case EAP_TTLS_PHASE2_MSCHAP: - case EAP_TTLS_PHASE2_PAP: - case EAP_TTLS_PHASE2_CHAP: -#ifdef EAP_TNC - if (eap_ttls_process_tnc_start(sm, data, ret, parse, &resp) < - 0) - return -1; - break; -#else /* EAP_TNC */ - /* EAP-TTLS/{MSCHAP,PAP,CHAP} should not send any TLS tunneled - * requests to the supplicant */ - wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received unexpected " - "tunneled data"); - return -1; -#endif /* EAP_TNC */ - } - - if (resp) { - if (eap_ttls_encrypt_response(sm, data, resp, identifier, - out_data) < 0) - return -1; - } 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); - data->pending_phase2_req = wpabuf_dup(in_decrypted); - } - - return 0; -} - - -#if EAP_TTLS_VERSION > 0 -static void eap_ttls_final_phase_finished(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - u8 identifier, - struct wpabuf **out_data) -{ - wpa_printf(MSG_DEBUG, "EAP-TTLS: FinalPhaseFinished received"); - wpa_printf(MSG_INFO, "EAP-TTLS: TLS/IA authentication succeeded"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - data->phase2_success = 1; - *out_data = eap_ttls_build_phase_finished(sm, data, identifier, 1); - eap_ttls_v1_derive_key(sm, data); -} -#endif /* EAP_TTLS_VERSION */ - - -static int eap_ttls_implicit_identity_request(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - u8 identifier, - struct wpabuf **out_data) -{ - int retval = 0; - struct eap_hdr *hdr; - struct wpabuf *resp; - - hdr = (struct eap_hdr *) eap_ttls_fake_identity_request(); - if (hdr == NULL) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return -1; - } - - resp = NULL; - if (eap_ttls_phase2_request(sm, data, ret, hdr, &resp)) { - wpa_printf(MSG_INFO, "EAP-TTLS: Phase2 Request " - "processing failed"); - retval = -1; - } else { - retval = eap_ttls_encrypt_response(sm, data, resp, identifier, - out_data); - } - - os_free(hdr); - - if (retval < 0) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - } - - return retval; -} - - -static int eap_ttls_phase2_start(struct eap_sm *sm, struct eap_ttls_data *data, - struct eap_method_ret *ret, u8 identifier, - struct wpabuf **out_data) -{ - data->phase2_start = 0; - - /* - * EAP-TTLS does not use Phase2 on fast re-auth; this must be done only - * if TLS part was indeed resuming a previous session. Most - * Authentication Servers terminate EAP-TTLS before reaching this - * point, but some do not. Make wpa_supplicant stop phase 2 here, if - * needed. - */ - if (data->reauth && - tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Session resumption - " - "skip phase 2"); - *out_data = eap_peer_tls_build_ack(identifier, EAP_TYPE_TTLS, - data->ttls_version); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - data->phase2_success = 1; - return 0; - } - - return eap_ttls_implicit_identity_request(sm, data, ret, identifier, - out_data); -} - - -static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data, - struct eap_method_ret *ret, u8 identifier, - const struct wpabuf *in_data, - struct wpabuf **out_data) -{ - struct wpabuf *in_decrypted = NULL; - int retval = 0; - struct ttls_parse_avp parse; - - os_memset(&parse, 0, sizeof(parse)); - - wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for" - " Phase 2", - in_data ? (unsigned long) wpabuf_len(in_data) : 0); - - if (data->pending_phase2_req) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 request - " - "skip decryption and use old data"); - /* Clear TLS reassembly state. */ - eap_peer_tls_reset_input(&data->ssl); - - in_decrypted = data->pending_phase2_req; - data->pending_phase2_req = NULL; - if (wpabuf_len(in_decrypted) == 0) { - wpabuf_free(in_decrypted); - return eap_ttls_implicit_identity_request( - sm, data, ret, identifier, out_data); - } - goto continue_req; - } - - if ((in_data == NULL || wpabuf_len(in_data) == 0) && - data->phase2_start) { - return eap_ttls_phase2_start(sm, data, ret, identifier, - out_data); - } - - if (in_data == NULL || wpabuf_len(in_data) == 0) { - /* Received TLS ACK - requesting more fragments */ - return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TTLS, - data->ttls_version, - identifier, NULL, out_data); - } - - retval = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted); - if (retval) - goto done; - -#if EAP_TTLS_VERSION > 0 - if (data->ttls_version > 0 && - (in_decrypted == NULL || wpabuf_len(in_decrypted) == 0) && - tls_connection_ia_final_phase_finished(sm->ssl_ctx, - data->ssl.conn)) { - eap_ttls_final_phase_finished(sm, data, ret, identifier, - out_data); - goto done; - } -#endif /* EAP_TTLS_VERSION */ - -continue_req: - data->phase2_start = 0; - - if (eap_ttls_parse_avps(in_decrypted, &parse) < 0) { - retval = -1; - goto done; - } - - retval = eap_ttls_process_decrypted(sm, data, ret, identifier, - &parse, in_decrypted, out_data); - -done: - wpabuf_free(in_decrypted); - os_free(parse.eapdata); - - if (retval < 0) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - } - - return retval; -} - - -static int eap_ttls_process_start(struct eap_sm *sm, - struct eap_ttls_data *data, u8 flags, - struct eap_method_ret *ret) -{ - struct eap_peer_config *config = eap_get_config(sm); - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Start (server ver=%d, own ver=%d)", - flags & EAP_PEAP_VERSION_MASK, data->ttls_version); -#if EAP_TTLS_VERSION > 0 - if ((flags & EAP_PEAP_VERSION_MASK) < data->ttls_version) - data->ttls_version = flags & EAP_PEAP_VERSION_MASK; - if (data->force_ttls_version >= 0 && - data->force_ttls_version != data->ttls_version) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to select " - "forced TTLS version %d", - data->force_ttls_version); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-TTLS: Using TTLS version %d", - data->ttls_version); - - if (data->ttls_version > 0) - data->ssl.tls_ia = 1; -#endif /* EAP_TTLS_VERSION */ - if (!data->ssl_initialized && - eap_peer_tls_ssl_init(sm, &data->ssl, config)) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL."); - return -1; - } - data->ssl_initialized = 1; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Start"); - - return 0; -} - - -static int eap_ttls_process_handshake(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - u8 identifier, - const u8 *in_data, size_t in_len, - struct wpabuf **out_data) -{ - int res; - - res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS, - data->ttls_version, identifier, - in_data, in_len, out_data); - - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS done, proceed to " - "Phase 2"); - if (data->resuming) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: fast reauth - may " - "skip Phase 2"); - ret->decision = DECISION_COND_SUCC; - ret->methodState = METHOD_MAY_CONT; - } - data->phase2_start = 1; - if (data->ttls_version == 0) - eap_ttls_v0_derive_key(sm, data); - - if (*out_data == NULL || wpabuf_len(*out_data) == 0) { - if (eap_ttls_decrypt(sm, data, ret, identifier, - NULL, out_data)) { - wpa_printf(MSG_WARNING, "EAP-TTLS: " - "failed to process early " - "start for Phase 2"); - } - res = 0; - } - data->resuming = 0; - } - - if (res == 2) { - struct wpabuf msg; - /* - * Application data included in the handshake message. - */ - wpabuf_free(data->pending_phase2_req); - data->pending_phase2_req = *out_data; - *out_data = NULL; - wpabuf_set(&msg, in_data, in_len); - res = eap_ttls_decrypt(sm, data, ret, identifier, &msg, - out_data); - } - - return res; -} - - -static void eap_ttls_check_auth_status(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret) -{ - if (data->ttls_version == 0 && ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; - if (ret->decision == DECISION_UNCOND_SUCC || - ret->decision == DECISION_COND_SUCC) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication " - "completed successfully"); - data->phase2_success = 1; -#ifdef EAP_TNC - if (!data->ready_for_tnc && !data->tnc_started) { - /* - * TNC may be required as the next - * authentication method within the tunnel. - */ - ret->methodState = METHOD_MAY_CONT; - data->ready_for_tnc = 1; - } -#endif /* EAP_TNC */ - } - } else if (data->ttls_version == 0 && - ret->methodState == METHOD_MAY_CONT && - (ret->decision == DECISION_UNCOND_SUCC || - ret->decision == DECISION_COND_SUCC)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication " - "completed successfully (MAY_CONT)"); - data->phase2_success = 1; - } -} - - -static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - size_t left; - int res; - u8 flags, id; - struct wpabuf *resp; - const u8 *pos; - struct eap_ttls_data *data = priv; - - pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TTLS, ret, - reqData, &left, &flags); - if (pos == NULL) - return NULL; - id = eap_get_id(reqData); - - if (flags & EAP_TLS_FLAGS_START) { - if (eap_ttls_process_start(sm, data, flags, ret) < 0) - return NULL; - - /* RFC 5281, Ch. 9.2: - * "This packet MAY contain additional information in the form - * of AVPs, which may provide useful hints to the client" - * For now, ignore any potential extra data. - */ - left = 0; - } else if (!data->ssl_initialized) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: First message did not " - "include Start flag"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; - return NULL; - } - - resp = NULL; - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && - !data->resuming) { - struct wpabuf msg; - wpabuf_set(&msg, pos, left); - res = eap_ttls_decrypt(sm, data, ret, id, &msg, &resp); - } else { - res = eap_ttls_process_handshake(sm, data, ret, id, - pos, left, &resp); - } - - eap_ttls_check_auth_status(sm, data, ret); - - /* 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); - return eap_peer_tls_build_ack(id, EAP_TYPE_TTLS, - data->ttls_version); - } - return resp; -} - - -static Boolean eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - return tls_connection_established(sm->ssl_ctx, data->ssl.conn) && - data->phase2_success; -} - - -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); - data->pending_phase2_req = NULL; -#ifdef EAP_TNC - data->ready_for_tnc = 0; - data->tnc_started = 0; -#endif /* EAP_TNC */ -} - - -static void * eap_ttls_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - os_free(data->key_data); - data->key_data = NULL; - if (eap_peer_tls_reauth_init(sm, &data->ssl)) { - os_free(data); - return NULL; - } - if (data->phase2_priv && data->phase2_method && - data->phase2_method->init_for_reauth) - data->phase2_method->init_for_reauth(sm, data->phase2_priv); - data->phase2_start = 0; - data->phase2_success = 0; - data->resuming = 1; - data->reauth = 1; - return priv; -} - - -static int eap_ttls_get_status(struct eap_sm *sm, void *priv, char *buf, - size_t buflen, int verbose) -{ - struct eap_ttls_data *data = priv; - int len, ret; - - len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); - ret = os_snprintf(buf + len, buflen - len, - "EAP-TTLSv%d Phase2 method=", - data->ttls_version); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - switch (data->phase2_type) { - case EAP_TTLS_PHASE2_EAP: - ret = os_snprintf(buf + len, buflen - len, "EAP-%s\n", - data->phase2_method ? - data->phase2_method->name : "?"); - break; - case EAP_TTLS_PHASE2_MSCHAPV2: - ret = os_snprintf(buf + len, buflen - len, "MSCHAPV2\n"); - break; - case EAP_TTLS_PHASE2_MSCHAP: - ret = os_snprintf(buf + len, buflen - len, "MSCHAP\n"); - break; - case EAP_TTLS_PHASE2_PAP: - ret = os_snprintf(buf + len, buflen - len, "PAP\n"); - break; - case EAP_TTLS_PHASE2_CHAP: - ret = os_snprintf(buf + len, buflen - len, "CHAP\n"); - break; - default: - ret = 0; - break; - } - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - return len; -} - - -static Boolean eap_ttls_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - return data->key_data != NULL && data->phase2_success; -} - - -static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_ttls_data *data = priv; - u8 *key; - - if (data->key_data == NULL || !data->phase2_success) - return NULL; - - key = os_malloc(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; -} - - -int eap_peer_ttls_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS"); - if (eap == NULL) - return -1; - - eap->init = eap_ttls_init; - eap->deinit = eap_ttls_deinit; - eap->process = eap_ttls_process; - eap->isKeyAvailable = eap_ttls_isKeyAvailable; - eap->getKey = eap_ttls_getKey; - eap->get_status = eap_ttls_get_status; - eap->has_reauth_data = eap_ttls_has_reauth_data; - eap->deinit_for_reauth = eap_ttls_deinit_for_reauth; - eap->init_for_reauth = eap_ttls_init_for_reauth; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_peer/eap_vendor_test.c b/contrib/hostapd/src/eap_peer/eap_vendor_test.c deleted file mode 100644 index 3e114c142a..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_vendor_test.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * EAP peer method: Test method for vendor specific (expanded) EAP type - * Copyright (c) 2005-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file implements a vendor specific test method using EAP expanded types. - * This is only for test use and must not be used for authentication since no - * security is provided. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#ifdef TEST_PENDING_REQUEST -#include "eloop.h" -#endif /* TEST_PENDING_REQUEST */ - - -#define EAP_VENDOR_ID 0xfffefd -#define EAP_VENDOR_TYPE 0xfcfbfaf9 - - -/* #define TEST_PENDING_REQUEST */ - -struct eap_vendor_test_data { - enum { INIT, CONFIRM, SUCCESS } state; - int first_try; -}; - - -static void * eap_vendor_test_init(struct eap_sm *sm) -{ - struct eap_vendor_test_data *data; - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = INIT; - data->first_try = 1; - return data; -} - - -static void eap_vendor_test_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_vendor_test_data *data = priv; - os_free(data); -} - - -#ifdef TEST_PENDING_REQUEST -static void eap_vendor_ready(void *eloop_ctx, void *timeout_ctx) -{ - struct eap_sm *sm = eloop_ctx; - wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Ready to re-process pending " - "request"); - eap_notify_pending(sm); -} -#endif /* TEST_PENDING_REQUEST */ - - -static struct wpabuf * eap_vendor_test_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_vendor_test_data *data = priv; - struct wpabuf *resp; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_ID, EAP_VENDOR_TYPE, reqData, &len); - if (pos == NULL || len < 1) { - ret->ignore = TRUE; - return NULL; - } - - if (data->state == INIT && *pos != 1) { - wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " - "%d in INIT state", *pos); - ret->ignore = TRUE; - return NULL; - } - - if (data->state == CONFIRM && *pos != 3) { - wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " - "%d in CONFIRM state", *pos); - ret->ignore = TRUE; - return NULL; - } - - if (data->state == SUCCESS) { - wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " - "in SUCCESS state"); - ret->ignore = TRUE; - return NULL; - } - - if (data->state == CONFIRM) { -#ifdef TEST_PENDING_REQUEST - if (data->first_try) { - data->first_try = 0; - wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Testing " - "pending request"); - ret->ignore = TRUE; - eloop_register_timeout(1, 0, eap_vendor_ready, sm, - NULL); - return NULL; - } -#endif /* TEST_PENDING_REQUEST */ - } - - ret->ignore = FALSE; - - wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Generating Response"); - ret->allowNotifications = TRUE; - - resp = eap_msg_alloc(EAP_VENDOR_ID, EAP_VENDOR_TYPE, 1, - EAP_CODE_RESPONSE, eap_get_id(reqData)); - if (resp == NULL) - return NULL; - - if (data->state == INIT) { - wpabuf_put_u8(resp, 2); - data->state = CONFIRM; - ret->methodState = METHOD_CONT; - ret->decision = DECISION_FAIL; - } else { - wpabuf_put_u8(resp, 4); - data->state = SUCCESS; - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - } - - return resp; -} - - -static Boolean eap_vendor_test_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_vendor_test_data *data = priv; - return data->state == SUCCESS; -} - - -static u8 * eap_vendor_test_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_vendor_test_data *data = priv; - u8 *key; - const int key_len = 64; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(key_len); - if (key == NULL) - return NULL; - - os_memset(key, 0x11, key_len / 2); - os_memset(key + key_len / 2, 0x22, key_len / 2); - *len = key_len; - - return key; -} - - -int eap_peer_vendor_test_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_ID, EAP_VENDOR_TYPE, - "VENDOR-TEST"); - if (eap == NULL) - return -1; - - eap->init = eap_vendor_test_init; - eap->deinit = eap_vendor_test_deinit; - eap->process = eap_vendor_test_process; - eap->isKeyAvailable = eap_vendor_test_isKeyAvailable; - eap->getKey = eap_vendor_test_getKey; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_peer/eap_wsc.c b/contrib/hostapd/src/eap_peer/eap_wsc.c deleted file mode 100644 index 7c8ad2fdad..0000000000 --- a/contrib/hostapd/src/eap_peer/eap_wsc.c +++ /dev/null @@ -1,453 +0,0 @@ -/* - * EAP-WSC peer for Wi-Fi Protected Setup - * Copyright (c) 2007-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "uuid.h" -#include "eap_i.h" -#include "eap_common/eap_wsc_common.h" -#include "wps/wps.h" -#include "wps/wps_defs.h" - - -struct eap_wsc_data { - enum { WAIT_START, MESG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state; - int registrar; - struct wpabuf *in_buf; - struct wpabuf *out_buf; - enum wsc_op_code in_op_code, out_op_code; - size_t out_used; - size_t fragment_size; - struct wps_data *wps; - struct wps_context *wps_ctx; -}; - - -static const char * eap_wsc_state_txt(int state) -{ - switch (state) { - case WAIT_START: - return "WAIT_START"; - case MESG: - return "MESG"; - case FRAG_ACK: - return "FRAG_ACK"; - case WAIT_FRAG_ACK: - return "WAIT_FRAG_ACK"; - case DONE: - return "DONE"; - case FAIL: - return "FAIL"; - default: - return "?"; - } -} - - -static void eap_wsc_state(struct eap_wsc_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-WSC: %s -> %s", - eap_wsc_state_txt(data->state), - eap_wsc_state_txt(state)); - data->state = state; -} - - -static void * eap_wsc_init(struct eap_sm *sm) -{ - struct eap_wsc_data *data; - const u8 *identity; - size_t identity_len; - int registrar; - struct wps_config cfg; - const char *pos; - const char *phase1; - struct wps_context *wps; - - wps = sm->wps; - if (wps == NULL) { - wpa_printf(MSG_ERROR, "EAP-WSC: WPS context not available"); - return NULL; - } - - identity = eap_get_config_identity(sm, &identity_len); - - if (identity && identity_len == WSC_ID_REGISTRAR_LEN && - os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) - registrar = 1; /* Supplicant is Registrar */ - else if (identity && identity_len == WSC_ID_ENROLLEE_LEN && - os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) - registrar = 0; /* Supplicant is Enrollee */ - else { - wpa_hexdump_ascii(MSG_INFO, "EAP-WSC: Unexpected identity", - identity, identity_len); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = registrar ? MESG : WAIT_START; - data->registrar = registrar; - data->wps_ctx = wps; - - os_memset(&cfg, 0, sizeof(cfg)); - cfg.wps = wps; - cfg.registrar = registrar; - - phase1 = eap_get_config_phase1(sm); - if (phase1 == NULL) { - wpa_printf(MSG_INFO, "EAP-WSC: phase1 configuration data not " - "set"); - os_free(data); - return NULL; - } - - pos = os_strstr(phase1, "pin="); - if (pos) { - pos += 4; - cfg.pin = (const u8 *) pos; - while (*pos != '\0' && *pos != ' ') - pos++; - cfg.pin_len = pos - (const char *) cfg.pin; - } else { - pos = os_strstr(phase1, "pbc=1"); - if (pos) - cfg.pbc = 1; - } - - if (cfg.pin == NULL && !cfg.pbc) { - wpa_printf(MSG_INFO, "EAP-WSC: PIN or PBC not set in phase1 " - "configuration data"); - os_free(data); - return NULL; - } - - data->wps = wps_init(&cfg); - if (data->wps == NULL) { - os_free(data); - return NULL; - } - data->fragment_size = WSC_FRAGMENT_SIZE; - - if (registrar && cfg.pin) { - wps_registrar_add_pin(data->wps_ctx->registrar, NULL, - cfg.pin, cfg.pin_len, 0); - } - - return data; -} - - -static void eap_wsc_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_wsc_data *data = priv; - wpabuf_free(data->in_buf); - wpabuf_free(data->out_buf); - wps_deinit(data->wps); - os_free(data->wps_ctx->network_key); - data->wps_ctx->network_key = NULL; - os_free(data); -} - - -static struct wpabuf * eap_wsc_build_msg(struct eap_wsc_data *data, - struct eap_method_ret *ret, u8 id) -{ - struct wpabuf *resp; - u8 flags; - size_t send_len, plen; - - ret->ignore = FALSE; - wpa_printf(MSG_DEBUG, "EAP-WSC: Generating Response"); - ret->allowNotifications = TRUE; - - flags = 0; - send_len = wpabuf_len(data->out_buf) - data->out_used; - if (2 + send_len > data->fragment_size) { - send_len = data->fragment_size - 2; - flags |= WSC_FLAGS_MF; - if (data->out_used == 0) { - flags |= WSC_FLAGS_LF; - send_len -= 2; - } - } - plen = 2 + send_len; - if (flags & WSC_FLAGS_LF) - plen += 2; - resp = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, plen, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - wpabuf_put_u8(resp, data->out_op_code); /* Op-Code */ - wpabuf_put_u8(resp, flags); /* Flags */ - if (flags & WSC_FLAGS_LF) - wpabuf_put_be16(resp, wpabuf_len(data->out_buf)); - - wpabuf_put_data(resp, wpabuf_head_u8(data->out_buf) + data->out_used, - send_len); - data->out_used += send_len; - - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - - if (data->out_used == wpabuf_len(data->out_buf)) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " - "(message sent completely)", - (unsigned long) send_len); - wpabuf_free(data->out_buf); - data->out_buf = NULL; - data->out_used = 0; - if ((data->state == FAIL && data->out_op_code == WSC_ACK) || - data->out_op_code == WSC_NACK || - data->out_op_code == WSC_Done) { - eap_wsc_state(data, FAIL); - ret->methodState = METHOD_DONE; - } else - eap_wsc_state(data, MESG); - } else { - wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " - "(%lu more to send)", (unsigned long) send_len, - (unsigned long) wpabuf_len(data->out_buf) - - data->out_used); - eap_wsc_state(data, WAIT_FRAG_ACK); - } - - return resp; -} - - -static int eap_wsc_process_cont(struct eap_wsc_data *data, - const u8 *buf, size_t len, u8 op_code) -{ - /* Process continuation of a pending message */ - if (op_code != data->in_op_code) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d in " - "fragment (expected %d)", - op_code, data->in_op_code); - return -1; - } - - if (len > wpabuf_tailroom(data->in_buf)) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment overflow"); - eap_wsc_state(data, FAIL); - return -1; - } - - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes, waiting " - "for %lu bytes more", (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - - return 0; -} - - -static struct wpabuf * eap_wsc_process_fragment(struct eap_wsc_data *data, - struct eap_method_ret *ret, - u8 id, u8 flags, u8 op_code, - u16 message_length, - const u8 *buf, size_t len) -{ - /* Process a fragment that is not the last one of the message */ - if (data->in_buf == NULL && !(flags & WSC_FLAGS_LF)) { - wpa_printf(MSG_DEBUG, "EAP-WSC: No Message Length field in a " - "fragmented packet"); - ret->ignore = TRUE; - return NULL; - } - - if (data->in_buf == NULL) { - /* First fragment of the message */ - data->in_buf = wpabuf_alloc(message_length); - if (data->in_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-WSC: No memory for " - "message"); - ret->ignore = TRUE; - return NULL; - } - data->in_op_code = op_code; - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes in first " - "fragment, waiting for %lu bytes more", - (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - } - - return eap_wsc_build_frag_ack(id, EAP_CODE_RESPONSE); -} - - -static struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_wsc_data *data = priv; - const u8 *start, *pos, *end; - size_t len; - u8 op_code, flags, id; - u16 message_length = 0; - enum wps_process_res res; - struct wpabuf tmpbuf; - - pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, reqData, - &len); - if (pos == NULL || len < 2) { - ret->ignore = TRUE; - return NULL; - } - - id = eap_get_id(reqData); - - start = pos; - end = start + len; - - op_code = *pos++; - flags = *pos++; - if (flags & WSC_FLAGS_LF) { - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Message underflow"); - ret->ignore = TRUE; - return NULL; - } - message_length = WPA_GET_BE16(pos); - pos += 2; - - if (message_length < end - pos) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid Message " - "Length"); - ret->ignore = TRUE; - return NULL; - } - } - - wpa_printf(MSG_DEBUG, "EAP-WSC: Received packet: Op-Code %d " - "Flags 0x%x Message Length %d", - op_code, flags, message_length); - - if (data->state == WAIT_FRAG_ACK) { - if (op_code != WSC_FRAG_ACK) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " - "in WAIT_FRAG_ACK state", op_code); - ret->ignore = TRUE; - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment acknowledged"); - eap_wsc_state(data, MESG); - return eap_wsc_build_msg(data, ret, id); - } - - if (op_code != WSC_ACK && op_code != WSC_NACK && op_code != WSC_MSG && - op_code != WSC_Done && op_code != WSC_Start) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", - op_code); - ret->ignore = TRUE; - return NULL; - } - - if (data->state == WAIT_START) { - if (op_code != WSC_Start) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " - "in WAIT_START state", op_code); - ret->ignore = TRUE; - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-WSC: Received start"); - eap_wsc_state(data, MESG); - /* Start message has empty payload, skip processing */ - goto send_msg; - } else if (op_code == WSC_Start) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", - op_code); - ret->ignore = TRUE; - return NULL; - } - - if (data->in_buf && - eap_wsc_process_cont(data, pos, end - pos, op_code) < 0) { - ret->ignore = TRUE; - return NULL; - } - - if (flags & WSC_FLAGS_MF) { - return eap_wsc_process_fragment(data, ret, id, flags, op_code, - message_length, pos, - end - pos); - } - - if (data->in_buf == NULL) { - /* Wrap unfragmented messages as wpabuf without extra copy */ - wpabuf_set(&tmpbuf, pos, end - pos); - data->in_buf = &tmpbuf; - } - - res = wps_process_msg(data->wps, op_code, data->in_buf); - switch (res) { - case WPS_DONE: - wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing completed " - "successfully - wait for EAP failure"); - eap_wsc_state(data, FAIL); - break; - case WPS_CONTINUE: - eap_wsc_state(data, MESG); - break; - case WPS_FAILURE: - case WPS_PENDING: - wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing failed"); - eap_wsc_state(data, FAIL); - break; - } - - if (data->in_buf != &tmpbuf) - wpabuf_free(data->in_buf); - data->in_buf = NULL; - -send_msg: - if (data->out_buf == NULL) { - data->out_buf = wps_get_msg(data->wps, &data->out_op_code); - if (data->out_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to receive " - "message from WPS"); - return NULL; - } - data->out_used = 0; - } - - eap_wsc_state(data, MESG); - return eap_wsc_build_msg(data, ret, id); -} - - -int eap_peer_wsc_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, - "WSC"); - if (eap == NULL) - return -1; - - eap->init = eap_wsc_init; - eap->deinit = eap_wsc_deinit; - eap->process = eap_wsc_process; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_peer/ikev2.c b/contrib/hostapd/src/eap_peer/ikev2.c deleted file mode 100644 index 9172e1f348..0000000000 --- a/contrib/hostapd/src/eap_peer/ikev2.c +++ /dev/null @@ -1,1303 +0,0 @@ -/* - * IKEv2 responder (RFC 4306) for EAP-IKEV2 - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "dh_groups.h" -#include "ikev2.h" - - -void ikev2_responder_deinit(struct ikev2_responder_data *data) -{ - ikev2_free_keys(&data->keys); - wpabuf_free(data->i_dh_public); - wpabuf_free(data->r_dh_private); - os_free(data->IDi); - os_free(data->IDr); - os_free(data->shared_secret); - wpabuf_free(data->i_sign_msg); - wpabuf_free(data->r_sign_msg); - os_free(data->key_pad); -} - - -static int ikev2_derive_keys(struct ikev2_responder_data *data) -{ - u8 *buf, *pos, *pad, skeyseed[IKEV2_MAX_HASH_LEN]; - size_t buf_len, pad_len; - struct wpabuf *shared; - const struct ikev2_integ_alg *integ; - const struct ikev2_prf_alg *prf; - const struct ikev2_encr_alg *encr; - int ret; - const u8 *addr[2]; - size_t len[2]; - - /* RFC 4306, Sect. 2.14 */ - - integ = ikev2_get_integ(data->proposal.integ); - prf = ikev2_get_prf(data->proposal.prf); - encr = ikev2_get_encr(data->proposal.encr); - if (integ == NULL || prf == NULL || encr == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported proposal"); - return -1; - } - - shared = dh_derive_shared(data->i_dh_public, data->r_dh_private, - data->dh); - if (shared == NULL) - return -1; - - /* Construct Ni | Nr | SPIi | SPIr */ - - buf_len = data->i_nonce_len + data->r_nonce_len + 2 * IKEV2_SPI_LEN; - buf = os_malloc(buf_len); - if (buf == NULL) { - wpabuf_free(shared); - return -1; - } - - pos = buf; - os_memcpy(pos, data->i_nonce, data->i_nonce_len); - pos += data->i_nonce_len; - os_memcpy(pos, data->r_nonce, data->r_nonce_len); - pos += data->r_nonce_len; - os_memcpy(pos, data->i_spi, IKEV2_SPI_LEN); - pos += IKEV2_SPI_LEN; - os_memcpy(pos, data->r_spi, IKEV2_SPI_LEN); -#ifdef CCNS_PL -#if __BYTE_ORDER == __LITTLE_ENDIAN - { - int i; - u8 *tmp = pos - IKEV2_SPI_LEN; - /* Incorrect byte re-ordering on little endian hosts.. */ - for (i = 0; i < IKEV2_SPI_LEN; i++) - *tmp++ = data->i_spi[IKEV2_SPI_LEN - 1 - i]; - for (i = 0; i < IKEV2_SPI_LEN; i++) - *tmp++ = data->r_spi[IKEV2_SPI_LEN - 1 - i]; - } -#endif -#endif /* CCNS_PL */ - - /* SKEYSEED = prf(Ni | Nr, g^ir) */ - /* Use zero-padding per RFC 4306, Sect. 2.14 */ - pad_len = data->dh->prime_len - wpabuf_len(shared); -#ifdef CCNS_PL - /* Shared secret is not zero-padded correctly */ - pad_len = 0; -#endif /* CCNS_PL */ - pad = os_zalloc(pad_len ? pad_len : 1); - if (pad == NULL) { - wpabuf_free(shared); - os_free(buf); - return -1; - } - - addr[0] = pad; - len[0] = pad_len; - addr[1] = wpabuf_head(shared); - len[1] = wpabuf_len(shared); - if (ikev2_prf_hash(prf->id, buf, data->i_nonce_len + data->r_nonce_len, - 2, addr, len, skeyseed) < 0) { - wpabuf_free(shared); - os_free(buf); - os_free(pad); - return -1; - } - os_free(pad); - wpabuf_free(shared); - - /* DH parameters are not needed anymore, so free them */ - wpabuf_free(data->i_dh_public); - data->i_dh_public = NULL; - wpabuf_free(data->r_dh_private); - data->r_dh_private = NULL; - - wpa_hexdump_key(MSG_DEBUG, "IKEV2: SKEYSEED", - skeyseed, prf->hash_len); - - ret = ikev2_derive_sk_keys(prf, integ, encr, skeyseed, buf, buf_len, - &data->keys); - os_free(buf); - return ret; -} - - -static int ikev2_parse_transform(struct ikev2_proposal_data *prop, - const u8 *pos, const u8 *end) -{ - int transform_len; - const struct ikev2_transform *t; - u16 transform_id; - const u8 *tend; - - if (end - pos < (int) sizeof(*t)) { - wpa_printf(MSG_INFO, "IKEV2: Too short transform"); - return -1; - } - - t = (const struct ikev2_transform *) pos; - transform_len = WPA_GET_BE16(t->transform_length); - if (transform_len < (int) sizeof(*t) || pos + transform_len > end) { - wpa_printf(MSG_INFO, "IKEV2: Invalid transform length %d", - transform_len); - return -1; - } - tend = pos + transform_len; - - transform_id = WPA_GET_BE16(t->transform_id); - - wpa_printf(MSG_DEBUG, "IKEV2: Transform:"); - wpa_printf(MSG_DEBUG, "IKEV2: Type: %d Transform Length: %d " - "Transform Type: %d Transform ID: %d", - t->type, transform_len, t->transform_type, transform_id); - - if (t->type != 0 && t->type != 3) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Transform type"); - return -1; - } - - pos = (const u8 *) (t + 1); - if (pos < tend) { - wpa_hexdump(MSG_DEBUG, "IKEV2: Transform Attributes", - pos, tend - pos); - } - - switch (t->transform_type) { - case IKEV2_TRANSFORM_ENCR: - if (ikev2_get_encr(transform_id)) { - if (transform_id == ENCR_AES_CBC) { - if (tend - pos != 4) { - wpa_printf(MSG_DEBUG, "IKEV2: No " - "Transform Attr for AES"); - break; - } -#ifdef CCNS_PL - if (WPA_GET_BE16(pos) != 0x001d /* ?? */) { - wpa_printf(MSG_DEBUG, "IKEV2: Not a " - "Key Size attribute for " - "AES"); - break; - } -#else /* CCNS_PL */ - if (WPA_GET_BE16(pos) != 0x800e) { - wpa_printf(MSG_DEBUG, "IKEV2: Not a " - "Key Size attribute for " - "AES"); - break; - } -#endif /* CCNS_PL */ - if (WPA_GET_BE16(pos + 2) != 128) { - wpa_printf(MSG_DEBUG, "IKEV2: " - "Unsupported AES key size " - "%d bits", - WPA_GET_BE16(pos + 2)); - break; - } - } - prop->encr = transform_id; - } - break; - case IKEV2_TRANSFORM_PRF: - if (ikev2_get_prf(transform_id)) - prop->prf = transform_id; - break; - case IKEV2_TRANSFORM_INTEG: - if (ikev2_get_integ(transform_id)) - prop->integ = transform_id; - break; - case IKEV2_TRANSFORM_DH: - if (dh_groups_get(transform_id)) - prop->dh = transform_id; - break; - } - - return transform_len; -} - - -static int ikev2_parse_proposal(struct ikev2_proposal_data *prop, - const u8 *pos, const u8 *end) -{ - const u8 *pend, *ppos; - int proposal_len, i; - const struct ikev2_proposal *p; - - if (end - pos < (int) sizeof(*p)) { - wpa_printf(MSG_INFO, "IKEV2: Too short proposal"); - return -1; - } - - /* FIX: AND processing if multiple proposals use the same # */ - - p = (const struct ikev2_proposal *) pos; - proposal_len = WPA_GET_BE16(p->proposal_length); - if (proposal_len < (int) sizeof(*p) || pos + proposal_len > end) { - wpa_printf(MSG_INFO, "IKEV2: Invalid proposal length %d", - proposal_len); - return -1; - } - wpa_printf(MSG_DEBUG, "IKEV2: SAi1 Proposal # %d", - p->proposal_num); - wpa_printf(MSG_DEBUG, "IKEV2: Type: %d Proposal Length: %d " - " Protocol ID: %d", - p->type, proposal_len, p->protocol_id); - wpa_printf(MSG_DEBUG, "IKEV2: SPI Size: %d Transforms: %d", - p->spi_size, p->num_transforms); - - if (p->type != 0 && p->type != 2) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal type"); - return -1; - } - - if (p->protocol_id != IKEV2_PROTOCOL_IKE) { - wpa_printf(MSG_DEBUG, "IKEV2: Unexpected Protocol ID " - "(only IKE allowed for EAP-IKEv2)"); - return -1; - } - - if (p->proposal_num != prop->proposal_num) { - if (p->proposal_num == prop->proposal_num + 1) - prop->proposal_num = p->proposal_num; - else { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal #"); - return -1; - } - } - - ppos = (const u8 *) (p + 1); - pend = pos + proposal_len; - if (ppos + p->spi_size > pend) { - wpa_printf(MSG_INFO, "IKEV2: Not enough room for SPI " - "in proposal"); - return -1; - } - if (p->spi_size) { - wpa_hexdump(MSG_DEBUG, "IKEV2: SPI", - ppos, p->spi_size); - ppos += p->spi_size; - } - - /* - * For initial IKE_SA negotiation, SPI Size MUST be zero; for - * subsequent negotiations, it must be 8 for IKE. We only support - * initial case for now. - */ - if (p->spi_size != 0) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected SPI Size"); - return -1; - } - - if (p->num_transforms == 0) { - wpa_printf(MSG_INFO, "IKEV2: At least one transform required"); - return -1; - } - - for (i = 0; i < (int) p->num_transforms; i++) { - int tlen = ikev2_parse_transform(prop, ppos, pend); - if (tlen < 0) - return -1; - ppos += tlen; - } - - if (ppos != pend) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected data after " - "transforms"); - return -1; - } - - return proposal_len; -} - - -static int ikev2_process_sai1(struct ikev2_responder_data *data, - const u8 *sai1, size_t sai1_len) -{ - struct ikev2_proposal_data prop; - const u8 *pos, *end; - int found = 0; - - /* Security Association Payloads: */ - - if (sai1 == NULL) { - wpa_printf(MSG_INFO, "IKEV2: SAi1 not received"); - return -1; - } - - os_memset(&prop, 0, sizeof(prop)); - prop.proposal_num = 1; - - pos = sai1; - end = sai1 + sai1_len; - - while (pos < end) { - int plen; - - prop.integ = -1; - prop.prf = -1; - prop.encr = -1; - prop.dh = -1; - plen = ikev2_parse_proposal(&prop, pos, end); - if (plen < 0) - return -1; - - if (!found && prop.integ != -1 && prop.prf != -1 && - prop.encr != -1 && prop.dh != -1) { - os_memcpy(&data->proposal, &prop, sizeof(prop)); - data->dh = dh_groups_get(prop.dh); - found = 1; - } - - pos += plen; - } - - if (pos != end) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected data after proposals"); - return -1; - } - - if (!found) { - wpa_printf(MSG_INFO, "IKEV2: No acceptable proposal found"); - return -1; - } - - wpa_printf(MSG_DEBUG, "IKEV2: Accepted proposal #%d: ENCR:%d PRF:%d " - "INTEG:%d D-H:%d", data->proposal.proposal_num, - data->proposal.encr, data->proposal.prf, - data->proposal.integ, data->proposal.dh); - - return 0; -} - - -static int ikev2_process_kei(struct ikev2_responder_data *data, - const u8 *kei, size_t kei_len) -{ - u16 group; - - /* - * Key Exchange Payload: - * DH Group # (16 bits) - * RESERVED (16 bits) - * Key Exchange Data (Diffie-Hellman public value) - */ - - if (kei == NULL) { - wpa_printf(MSG_INFO, "IKEV2: KEi not received"); - return -1; - } - - if (kei_len < 4 + 96) { - wpa_printf(MSG_INFO, "IKEV2: Too show Key Exchange Payload"); - return -1; - } - - group = WPA_GET_BE16(kei); - wpa_printf(MSG_DEBUG, "IKEV2: KEi DH Group #%u", group); - - if (group != data->proposal.dh) { - wpa_printf(MSG_DEBUG, "IKEV2: KEi DH Group #%u does not match " - "with the selected proposal (%u)", - group, data->proposal.dh); - /* Reject message with Notify payload of type - * INVALID_KE_PAYLOAD (RFC 4306, Sect. 3.4) */ - data->error_type = INVALID_KE_PAYLOAD; - data->state = NOTIFY; - return -1; - } - - if (data->dh == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported DH group"); - return -1; - } - - /* RFC 4306, Section 3.4: - * The length of DH public value MUST be equal to the lenght of the - * prime modulus. - */ - if (kei_len - 4 != data->dh->prime_len) { - wpa_printf(MSG_INFO, "IKEV2: Invalid DH public value length " - "%ld (expected %ld)", - (long) (kei_len - 4), (long) data->dh->prime_len); - return -1; - } - - wpabuf_free(data->i_dh_public); - data->i_dh_public = wpabuf_alloc(kei_len - 4); - if (data->i_dh_public == NULL) - return -1; - wpabuf_put_data(data->i_dh_public, kei + 4, kei_len - 4); - - wpa_hexdump_buf(MSG_DEBUG, "IKEV2: KEi Diffie-Hellman Public Value", - data->i_dh_public); - - return 0; -} - - -static int ikev2_process_ni(struct ikev2_responder_data *data, - const u8 *ni, size_t ni_len) -{ - if (ni == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Ni not received"); - return -1; - } - - if (ni_len < IKEV2_NONCE_MIN_LEN || ni_len > IKEV2_NONCE_MAX_LEN) { - wpa_printf(MSG_INFO, "IKEV2: Invalid Ni length %ld", - (long) ni_len); - return -1; - } - -#ifdef CCNS_PL - /* Zeros are removed incorrectly from the beginning of the nonces */ - while (ni_len > 1 && *ni == 0) { - ni_len--; - ni++; - } -#endif /* CCNS_PL */ - - data->i_nonce_len = ni_len; - os_memcpy(data->i_nonce, ni, ni_len); - wpa_hexdump(MSG_MSGDUMP, "IKEV2: Ni", - data->i_nonce, data->i_nonce_len); - - return 0; -} - - -static int ikev2_process_sa_init(struct ikev2_responder_data *data, - const struct ikev2_hdr *hdr, - struct ikev2_payloads *pl) -{ - if (ikev2_process_sai1(data, pl->sa, pl->sa_len) < 0 || - ikev2_process_kei(data, pl->ke, pl->ke_len) < 0 || - ikev2_process_ni(data, pl->nonce, pl->nonce_len) < 0) - return -1; - - os_memcpy(data->i_spi, hdr->i_spi, IKEV2_SPI_LEN); - - return 0; -} - - -static int ikev2_process_idi(struct ikev2_responder_data *data, - const u8 *idi, size_t idi_len) -{ - u8 id_type; - - if (idi == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No IDi received"); - return -1; - } - - if (idi_len < 4) { - wpa_printf(MSG_INFO, "IKEV2: Too short IDi payload"); - return -1; - } - - id_type = idi[0]; - idi += 4; - idi_len -= 4; - - wpa_printf(MSG_DEBUG, "IKEV2: IDi ID Type %d", id_type); - wpa_hexdump_ascii(MSG_DEBUG, "IKEV2: IDi", idi, idi_len); - os_free(data->IDi); - data->IDi = os_malloc(idi_len); - if (data->IDi == NULL) - return -1; - os_memcpy(data->IDi, idi, idi_len); - data->IDi_len = idi_len; - data->IDi_type = id_type; - - return 0; -} - - -static int ikev2_process_cert(struct ikev2_responder_data *data, - const u8 *cert, size_t cert_len) -{ - u8 cert_encoding; - - if (cert == NULL) { - if (data->peer_auth == PEER_AUTH_CERT) { - wpa_printf(MSG_INFO, "IKEV2: No Certificate received"); - return -1; - } - return 0; - } - - if (cert_len < 1) { - wpa_printf(MSG_INFO, "IKEV2: No Cert Encoding field"); - return -1; - } - - cert_encoding = cert[0]; - cert++; - cert_len--; - - wpa_printf(MSG_DEBUG, "IKEV2: Cert Encoding %d", cert_encoding); - wpa_hexdump(MSG_MSGDUMP, "IKEV2: Certificate Data", cert, cert_len); - - /* TODO: validate certificate */ - - return 0; -} - - -static int ikev2_process_auth_cert(struct ikev2_responder_data *data, - u8 method, const u8 *auth, size_t auth_len) -{ - if (method != AUTH_RSA_SIGN) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication " - "method %d", method); - return -1; - } - - /* TODO: validate AUTH */ - return 0; -} - - -static int ikev2_process_auth_secret(struct ikev2_responder_data *data, - u8 method, const u8 *auth, - size_t auth_len) -{ - u8 auth_data[IKEV2_MAX_HASH_LEN]; - const struct ikev2_prf_alg *prf; - - if (method != AUTH_SHARED_KEY_MIC) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication " - "method %d", method); - return -1; - } - - /* msg | Nr | prf(SK_pi,IDi') */ - if (ikev2_derive_auth_data(data->proposal.prf, data->i_sign_msg, - data->IDi, data->IDi_len, data->IDi_type, - &data->keys, 1, data->shared_secret, - data->shared_secret_len, - data->r_nonce, data->r_nonce_len, - data->key_pad, data->key_pad_len, - auth_data) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data"); - return -1; - } - - wpabuf_free(data->i_sign_msg); - data->i_sign_msg = NULL; - - prf = ikev2_get_prf(data->proposal.prf); - if (prf == NULL) - return -1; - - if (auth_len != prf->hash_len || - os_memcmp(auth, auth_data, auth_len) != 0) { - wpa_printf(MSG_INFO, "IKEV2: Invalid Authentication Data"); - wpa_hexdump(MSG_DEBUG, "IKEV2: Received Authentication Data", - auth, auth_len); - wpa_hexdump(MSG_DEBUG, "IKEV2: Expected Authentication Data", - auth_data, prf->hash_len); - data->error_type = AUTHENTICATION_FAILED; - data->state = NOTIFY; - return -1; - } - - wpa_printf(MSG_DEBUG, "IKEV2: Server authenticated successfully " - "using shared keys"); - - return 0; -} - - -static int ikev2_process_auth(struct ikev2_responder_data *data, - const u8 *auth, size_t auth_len) -{ - u8 auth_method; - - if (auth == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No Authentication Payload"); - return -1; - } - - if (auth_len < 4) { - wpa_printf(MSG_INFO, "IKEV2: Too short Authentication " - "Payload"); - return -1; - } - - auth_method = auth[0]; - auth += 4; - auth_len -= 4; - - wpa_printf(MSG_DEBUG, "IKEV2: Auth Method %d", auth_method); - wpa_hexdump(MSG_MSGDUMP, "IKEV2: Authentication Data", auth, auth_len); - - switch (data->peer_auth) { - case PEER_AUTH_CERT: - return ikev2_process_auth_cert(data, auth_method, auth, - auth_len); - case PEER_AUTH_SECRET: - return ikev2_process_auth_secret(data, auth_method, auth, - auth_len); - } - - return -1; -} - - -static int ikev2_process_sa_auth_decrypted(struct ikev2_responder_data *data, - u8 next_payload, - u8 *payload, size_t payload_len) -{ - struct ikev2_payloads pl; - - wpa_printf(MSG_DEBUG, "IKEV2: Processing decrypted payloads"); - - if (ikev2_parse_payloads(&pl, next_payload, payload, payload + - payload_len) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Failed to parse decrypted " - "payloads"); - return -1; - } - - if (ikev2_process_idi(data, pl.idi, pl.idi_len) < 0 || - ikev2_process_cert(data, pl.cert, pl.cert_len) < 0 || - ikev2_process_auth(data, pl.auth, pl.auth_len) < 0) - return -1; - - return 0; -} - - -static int ikev2_process_sa_auth(struct ikev2_responder_data *data, - const struct ikev2_hdr *hdr, - struct ikev2_payloads *pl) -{ - u8 *decrypted; - size_t decrypted_len; - int ret; - - decrypted = ikev2_decrypt_payload(data->proposal.encr, - data->proposal.integ, - &data->keys, 1, hdr, pl->encrypted, - pl->encrypted_len, &decrypted_len); - if (decrypted == NULL) - return -1; - - ret = ikev2_process_sa_auth_decrypted(data, pl->encr_next_payload, - decrypted, decrypted_len); - os_free(decrypted); - - return ret; -} - - -static int ikev2_validate_rx_state(struct ikev2_responder_data *data, - u8 exchange_type, u32 message_id) -{ - switch (data->state) { - case SA_INIT: - /* Expect to receive IKE_SA_INIT: HDR, SAi1, KEi, Ni */ - if (exchange_type != IKE_SA_INIT) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type " - "%u in SA_INIT state", exchange_type); - return -1; - } - if (message_id != 0) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u " - "in SA_INIT state", message_id); - return -1; - } - break; - case SA_AUTH: - /* Expect to receive IKE_SA_AUTH: - * HDR, SK {IDi, [CERT,] [CERTREQ,] [IDr,] - * AUTH, SAi2, TSi, TSr} - */ - if (exchange_type != IKE_SA_AUTH) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type " - "%u in SA_AUTH state", exchange_type); - return -1; - } - if (message_id != 1) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u " - "in SA_AUTH state", message_id); - return -1; - } - break; - case CHILD_SA: - if (exchange_type != CREATE_CHILD_SA) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type " - "%u in CHILD_SA state", exchange_type); - return -1; - } - if (message_id != 2) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u " - "in CHILD_SA state", message_id); - return -1; - } - break; - case NOTIFY: - case IKEV2_DONE: - case IKEV2_FAILED: - return -1; - } - - return 0; -} - - -int ikev2_responder_process(struct ikev2_responder_data *data, - const struct wpabuf *buf) -{ - const struct ikev2_hdr *hdr; - u32 length, message_id; - const u8 *pos, *end; - struct ikev2_payloads pl; - - wpa_printf(MSG_MSGDUMP, "IKEV2: Received message (len %lu)", - (unsigned long) wpabuf_len(buf)); - - if (wpabuf_len(buf) < sizeof(*hdr)) { - wpa_printf(MSG_INFO, "IKEV2: Too short frame to include HDR"); - return -1; - } - - data->error_type = 0; - hdr = (const struct ikev2_hdr *) wpabuf_head(buf); - end = wpabuf_head_u8(buf) + wpabuf_len(buf); - message_id = WPA_GET_BE32(hdr->message_id); - length = WPA_GET_BE32(hdr->length); - - wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Initiator's SPI", - hdr->i_spi, IKEV2_SPI_LEN); - wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Responder's SPI", - hdr->r_spi, IKEV2_SPI_LEN); - wpa_printf(MSG_DEBUG, "IKEV2: Next Payload: %u Version: 0x%x " - "Exchange Type: %u", - hdr->next_payload, hdr->version, hdr->exchange_type); - wpa_printf(MSG_DEBUG, "IKEV2: Message ID: %u Length: %u", - message_id, length); - - if (hdr->version != IKEV2_VERSION) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported HDR version 0x%x " - "(expected 0x%x)", hdr->version, IKEV2_VERSION); - return -1; - } - - if (length != wpabuf_len(buf)) { - wpa_printf(MSG_INFO, "IKEV2: Invalid length (HDR: %lu != " - "RX: %lu)", (unsigned long) length, - (unsigned long) wpabuf_len(buf)); - return -1; - } - - if (ikev2_validate_rx_state(data, hdr->exchange_type, message_id) < 0) - return -1; - - if ((hdr->flags & (IKEV2_HDR_INITIATOR | IKEV2_HDR_RESPONSE)) != - IKEV2_HDR_INITIATOR) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Flags value 0x%x", - hdr->flags); - return -1; - } - - if (data->state != SA_INIT) { - if (os_memcmp(data->i_spi, hdr->i_spi, IKEV2_SPI_LEN) != 0) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA " - "Initiator's SPI"); - return -1; - } - if (os_memcmp(data->r_spi, hdr->r_spi, IKEV2_SPI_LEN) != 0) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA " - "Responder's SPI"); - return -1; - } - } - - pos = (const u8 *) (hdr + 1); - if (ikev2_parse_payloads(&pl, hdr->next_payload, pos, end) < 0) - return -1; - - if (data->state == SA_INIT) { - data->last_msg = LAST_MSG_SA_INIT; - if (ikev2_process_sa_init(data, hdr, &pl) < 0) { - if (data->state == NOTIFY) - return 0; - return -1; - } - wpabuf_free(data->i_sign_msg); - data->i_sign_msg = wpabuf_dup(buf); - } - - if (data->state == SA_AUTH) { - data->last_msg = LAST_MSG_SA_AUTH; - if (ikev2_process_sa_auth(data, hdr, &pl) < 0) { - if (data->state == NOTIFY) - return 0; - return -1; - } - } - - return 0; -} - - -static void ikev2_build_hdr(struct ikev2_responder_data *data, - struct wpabuf *msg, u8 exchange_type, - u8 next_payload, u32 message_id) -{ - struct ikev2_hdr *hdr; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding HDR"); - - /* HDR - RFC 4306, Sect. 3.1 */ - hdr = wpabuf_put(msg, sizeof(*hdr)); - os_memcpy(hdr->i_spi, data->i_spi, IKEV2_SPI_LEN); - os_memcpy(hdr->r_spi, data->r_spi, IKEV2_SPI_LEN); - hdr->next_payload = next_payload; - hdr->version = IKEV2_VERSION; - hdr->exchange_type = exchange_type; - hdr->flags = IKEV2_HDR_RESPONSE; - WPA_PUT_BE32(hdr->message_id, message_id); -} - - -static int ikev2_build_sar1(struct ikev2_responder_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - struct ikev2_proposal *p; - struct ikev2_transform *t; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding SAr1 payload"); - - /* SAr1 - RFC 4306, Sect. 2.7 and 3.3 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - - p = wpabuf_put(msg, sizeof(*p)); -#ifdef CCNS_PL - /* Seems to require that the Proposal # is 1 even though RFC 4306 - * Sect 3.3.1 has following requirement "When a proposal is accepted, - * all of the proposal numbers in the SA payload MUST be the same and - * MUST match the number on the proposal sent that was accepted.". - */ - p->proposal_num = 1; -#else /* CCNS_PL */ - p->proposal_num = data->proposal.proposal_num; -#endif /* CCNS_PL */ - p->protocol_id = IKEV2_PROTOCOL_IKE; - p->num_transforms = 4; - - t = wpabuf_put(msg, sizeof(*t)); - t->type = 3; - t->transform_type = IKEV2_TRANSFORM_ENCR; - WPA_PUT_BE16(t->transform_id, data->proposal.encr); - if (data->proposal.encr == ENCR_AES_CBC) { - /* Transform Attribute: Key Len = 128 bits */ -#ifdef CCNS_PL - wpabuf_put_be16(msg, 0x001d); /* ?? */ -#else /* CCNS_PL */ - wpabuf_put_be16(msg, 0x800e); /* AF=1, AttrType=14 */ -#endif /* CCNS_PL */ - wpabuf_put_be16(msg, 128); /* 128-bit key */ - } - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) t; - WPA_PUT_BE16(t->transform_length, plen); - - t = wpabuf_put(msg, sizeof(*t)); - t->type = 3; - WPA_PUT_BE16(t->transform_length, sizeof(*t)); - t->transform_type = IKEV2_TRANSFORM_PRF; - WPA_PUT_BE16(t->transform_id, data->proposal.prf); - - t = wpabuf_put(msg, sizeof(*t)); - t->type = 3; - WPA_PUT_BE16(t->transform_length, sizeof(*t)); - t->transform_type = IKEV2_TRANSFORM_INTEG; - WPA_PUT_BE16(t->transform_id, data->proposal.integ); - - t = wpabuf_put(msg, sizeof(*t)); - WPA_PUT_BE16(t->transform_length, sizeof(*t)); - t->transform_type = IKEV2_TRANSFORM_DH; - WPA_PUT_BE16(t->transform_id, data->proposal.dh); - - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) p; - WPA_PUT_BE16(p->proposal_length, plen); - - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - - return 0; -} - - -static int ikev2_build_ker(struct ikev2_responder_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - struct wpabuf *pv; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding KEr payload"); - - pv = dh_init(data->dh, &data->r_dh_private); - if (pv == NULL) { - wpa_printf(MSG_DEBUG, "IKEV2: Failed to initialize DH"); - return -1; - } - - /* KEr - RFC 4306, Sect. 3.4 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - - wpabuf_put_be16(msg, data->proposal.dh); /* DH Group # */ - wpabuf_put(msg, 2); /* RESERVED */ - /* - * RFC 4306, Sect. 3.4: possible zero padding for public value to - * match the length of the prime. - */ - wpabuf_put(msg, data->dh->prime_len - wpabuf_len(pv)); - wpabuf_put_buf(msg, pv); - wpabuf_free(pv); - - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - return 0; -} - - -static int ikev2_build_nr(struct ikev2_responder_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding Nr payload"); - - /* Nr - RFC 4306, Sect. 3.9 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - wpabuf_put_data(msg, data->r_nonce, data->r_nonce_len); - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - return 0; -} - - -static int ikev2_build_idr(struct ikev2_responder_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding IDr payload"); - - if (data->IDr == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No IDr available"); - return -1; - } - - /* IDr - RFC 4306, Sect. 3.5 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - wpabuf_put_u8(msg, ID_KEY_ID); - wpabuf_put(msg, 3); /* RESERVED */ - wpabuf_put_data(msg, data->IDr, data->IDr_len); - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - return 0; -} - - -static int ikev2_build_auth(struct ikev2_responder_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - const struct ikev2_prf_alg *prf; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding AUTH payload"); - - prf = ikev2_get_prf(data->proposal.prf); - if (prf == NULL) - return -1; - - /* Authentication - RFC 4306, Sect. 3.8 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - wpabuf_put_u8(msg, AUTH_SHARED_KEY_MIC); - wpabuf_put(msg, 3); /* RESERVED */ - - /* msg | Ni | prf(SK_pr,IDr') */ - if (ikev2_derive_auth_data(data->proposal.prf, data->r_sign_msg, - data->IDr, data->IDr_len, ID_KEY_ID, - &data->keys, 0, data->shared_secret, - data->shared_secret_len, - data->i_nonce, data->i_nonce_len, - data->key_pad, data->key_pad_len, - wpabuf_put(msg, prf->hash_len)) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data"); - return -1; - } - wpabuf_free(data->r_sign_msg); - data->r_sign_msg = NULL; - - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - return 0; -} - - -static int ikev2_build_notification(struct ikev2_responder_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding Notification payload"); - - if (data->error_type == 0) { - wpa_printf(MSG_INFO, "IKEV2: No Notify Message Type " - "available"); - return -1; - } - - /* Notify - RFC 4306, Sect. 3.10 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; -#ifdef CCNS_PL - wpabuf_put_u8(msg, 1); /* Protocol ID: IKE_SA notification */ -#else /* CCNS_PL */ - wpabuf_put_u8(msg, 0); /* Protocol ID: no existing SA */ -#endif /* CCNS_PL */ - wpabuf_put_u8(msg, 0); /* SPI Size */ - wpabuf_put_be16(msg, data->error_type); - - switch (data->error_type) { - case INVALID_KE_PAYLOAD: - if (data->proposal.dh == -1) { - wpa_printf(MSG_INFO, "IKEV2: No DH Group selected for " - "INVALID_KE_PAYLOAD notifications"); - return -1; - } - wpabuf_put_be16(msg, data->proposal.dh); - wpa_printf(MSG_DEBUG, "IKEV2: INVALID_KE_PAYLOAD - request " - "DH Group #%d", data->proposal.dh); - break; - case AUTHENTICATION_FAILED: - /* no associated data */ - break; - default: - wpa_printf(MSG_INFO, "IKEV2: Unsupported Notify Message Type " - "%d", data->error_type); - return -1; - } - - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - return 0; -} - - -static struct wpabuf * ikev2_build_sa_init(struct ikev2_responder_data *data) -{ - struct wpabuf *msg; - - /* build IKE_SA_INIT: HDR, SAr1, KEr, Nr, [CERTREQ], [SK{IDr}] */ - - if (os_get_random(data->r_spi, IKEV2_SPI_LEN)) - return NULL; - wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Responder's SPI", - data->r_spi, IKEV2_SPI_LEN); - - data->r_nonce_len = IKEV2_NONCE_MIN_LEN; - if (os_get_random(data->r_nonce, data->r_nonce_len)) - return NULL; -#ifdef CCNS_PL - /* Zeros are removed incorrectly from the beginning of the nonces in - * key derivation; as a workaround, make sure Nr does not start with - * zero.. */ - if (data->r_nonce[0] == 0) - data->r_nonce[0] = 1; -#endif /* CCNS_PL */ - wpa_hexdump(MSG_DEBUG, "IKEV2: Nr", data->r_nonce, data->r_nonce_len); - - msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1500); - if (msg == NULL) - return NULL; - - ikev2_build_hdr(data, msg, IKE_SA_INIT, IKEV2_PAYLOAD_SA, 0); - if (ikev2_build_sar1(data, msg, IKEV2_PAYLOAD_KEY_EXCHANGE) || - ikev2_build_ker(data, msg, IKEV2_PAYLOAD_NONCE) || - ikev2_build_nr(data, msg, data->peer_auth == PEER_AUTH_SECRET ? - IKEV2_PAYLOAD_ENCRYPTED : - IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) { - wpabuf_free(msg); - return NULL; - } - - if (ikev2_derive_keys(data)) { - wpabuf_free(msg); - return NULL; - } - - if (data->peer_auth == PEER_AUTH_CERT) { - /* TODO: CERTREQ with SHA-1 hashes of Subject Public Key Info - * for trust agents */ - } - - if (data->peer_auth == PEER_AUTH_SECRET) { - struct wpabuf *plain = wpabuf_alloc(data->IDr_len + 1000); - if (plain == NULL) { - wpabuf_free(msg); - return NULL; - } - if (ikev2_build_idr(data, plain, - IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) || - ikev2_build_encrypted(data->proposal.encr, - data->proposal.integ, - &data->keys, 0, msg, plain, - IKEV2_PAYLOAD_IDr)) { - wpabuf_free(plain); - wpabuf_free(msg); - return NULL; - } - wpabuf_free(plain); - } - - ikev2_update_hdr(msg); - - wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_INIT)", msg); - - data->state = SA_AUTH; - - wpabuf_free(data->r_sign_msg); - data->r_sign_msg = wpabuf_dup(msg); - - return msg; -} - - -static struct wpabuf * ikev2_build_sa_auth(struct ikev2_responder_data *data) -{ - struct wpabuf *msg, *plain; - - /* build IKE_SA_AUTH: HDR, SK {IDr, [CERT,] AUTH} */ - - msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1000); - if (msg == NULL) - return NULL; - ikev2_build_hdr(data, msg, IKE_SA_AUTH, IKEV2_PAYLOAD_ENCRYPTED, 1); - - plain = wpabuf_alloc(data->IDr_len + 1000); - if (plain == NULL) { - wpabuf_free(msg); - return NULL; - } - - if (ikev2_build_idr(data, plain, IKEV2_PAYLOAD_AUTHENTICATION) || - ikev2_build_auth(data, plain, IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) || - ikev2_build_encrypted(data->proposal.encr, data->proposal.integ, - &data->keys, 0, msg, plain, - IKEV2_PAYLOAD_IDr)) { - wpabuf_free(plain); - wpabuf_free(msg); - return NULL; - } - wpabuf_free(plain); - - wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_AUTH)", msg); - - data->state = IKEV2_DONE; - - return msg; -} - - -static struct wpabuf * ikev2_build_notify(struct ikev2_responder_data *data) -{ - struct wpabuf *msg; - - msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + 1000); - if (msg == NULL) - return NULL; - if (data->last_msg == LAST_MSG_SA_AUTH) { - /* HDR, SK{N} */ - struct wpabuf *plain = wpabuf_alloc(100); - if (plain == NULL) { - wpabuf_free(msg); - return NULL; - } - ikev2_build_hdr(data, msg, IKE_SA_AUTH, - IKEV2_PAYLOAD_ENCRYPTED, 1); - if (ikev2_build_notification(data, plain, - IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) || - ikev2_build_encrypted(data->proposal.encr, - data->proposal.integ, - &data->keys, 0, msg, plain, - IKEV2_PAYLOAD_NOTIFICATION)) { - wpabuf_free(plain); - wpabuf_free(msg); - return NULL; - } - data->state = IKEV2_FAILED; - } else { - /* HDR, N */ - ikev2_build_hdr(data, msg, IKE_SA_INIT, - IKEV2_PAYLOAD_NOTIFICATION, 0); - if (ikev2_build_notification(data, msg, - IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) { - wpabuf_free(msg); - return NULL; - } - data->state = SA_INIT; - } - - ikev2_update_hdr(msg); - - wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (Notification)", - msg); - - return msg; -} - - -struct wpabuf * ikev2_responder_build(struct ikev2_responder_data *data) -{ - switch (data->state) { - case SA_INIT: - return ikev2_build_sa_init(data); - case SA_AUTH: - return ikev2_build_sa_auth(data); - case CHILD_SA: - return NULL; - case NOTIFY: - return ikev2_build_notify(data); - case IKEV2_DONE: - case IKEV2_FAILED: - return NULL; - } - return NULL; -} diff --git a/contrib/hostapd/src/eap_peer/ikev2.h b/contrib/hostapd/src/eap_peer/ikev2.h deleted file mode 100644 index 9ca0ca5695..0000000000 --- a/contrib/hostapd/src/eap_peer/ikev2.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * IKEv2 responder (RFC 4306) for EAP-IKEV2 - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IKEV2_H -#define IKEV2_H - -#include "eap_common/ikev2_common.h" - -struct ikev2_proposal_data { - u8 proposal_num; - int integ; - int prf; - int encr; - int dh; -}; - - -struct ikev2_responder_data { - enum { SA_INIT, SA_AUTH, CHILD_SA, NOTIFY, IKEV2_DONE, IKEV2_FAILED } - state; - u8 i_spi[IKEV2_SPI_LEN]; - u8 r_spi[IKEV2_SPI_LEN]; - u8 i_nonce[IKEV2_NONCE_MAX_LEN]; - size_t i_nonce_len; - u8 r_nonce[IKEV2_NONCE_MAX_LEN]; - size_t r_nonce_len; - struct wpabuf *i_dh_public; - struct wpabuf *r_dh_private; - struct ikev2_proposal_data proposal; - const struct dh_group *dh; - struct ikev2_keys keys; - u8 *IDi; - size_t IDi_len; - u8 IDi_type; - u8 *IDr; - size_t IDr_len; - struct wpabuf *r_sign_msg; - struct wpabuf *i_sign_msg; - u8 *shared_secret; - size_t shared_secret_len; - enum { PEER_AUTH_CERT, PEER_AUTH_SECRET } peer_auth; - u8 *key_pad; - size_t key_pad_len; - u16 error_type; - enum { LAST_MSG_SA_INIT, LAST_MSG_SA_AUTH } last_msg; -}; - - -void ikev2_responder_deinit(struct ikev2_responder_data *data); -int ikev2_responder_process(struct ikev2_responder_data *data, - const struct wpabuf *buf); -struct wpabuf * ikev2_responder_build(struct ikev2_responder_data *data); - -#endif /* IKEV2_H */ diff --git a/contrib/hostapd/src/eap_peer/mschapv2.c b/contrib/hostapd/src/eap_peer/mschapv2.c deleted file mode 100644 index 01c22d8975..0000000000 --- a/contrib/hostapd/src/eap_peer/mschapv2.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * MSCHAPV2 (RFC 2759) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "ms_funcs.h" -#include "mschapv2.h" - -const u8 * mschapv2_remove_domain(const u8 *username, size_t *len) -{ - size_t i; - - /* - * MSCHAPv2 does not include optional domain name in the - * challenge-response calculation, so remove domain prefix - * (if present). - */ - - for (i = 0; i < *len; i++) { - if (username[i] == '\\') { - *len -= i + 1; - return username + i + 1; - } - } - - return username; -} - - -void mschapv2_derive_response(const u8 *identity, size_t identity_len, - const u8 *password, size_t password_len, - int pwhash, - const u8 *auth_challenge, - const u8 *peer_challenge, - u8 *nt_response, u8 *auth_response, - u8 *master_key) -{ - const u8 *username; - size_t username_len; - u8 password_hash[16], password_hash_hash[16]; - - wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: Identity", - identity, identity_len); - username_len = identity_len; - username = mschapv2_remove_domain(identity, &username_len); - wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: Username", - username, username_len); - - wpa_hexdump(MSG_DEBUG, "MSCHAPV2: auth_challenge", - auth_challenge, MSCHAPV2_CHAL_LEN); - wpa_hexdump(MSG_DEBUG, "MSCHAPV2: peer_challenge", - peer_challenge, MSCHAPV2_CHAL_LEN); - wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: username", - username, username_len); - /* Authenticator response is not really needed yet, but calculate it - * here so that challenges need not be saved. */ - if (pwhash) { - wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: password hash", - password, password_len); - generate_nt_response_pwhash(auth_challenge, peer_challenge, - username, username_len, - password, nt_response); - generate_authenticator_response_pwhash( - password, peer_challenge, auth_challenge, - username, username_len, nt_response, auth_response); - } else { - wpa_hexdump_ascii_key(MSG_DEBUG, "MSCHAPV2: password", - password, password_len); - generate_nt_response(auth_challenge, peer_challenge, - username, username_len, - password, password_len, nt_response); - generate_authenticator_response(password, password_len, - peer_challenge, auth_challenge, - username, username_len, - nt_response, auth_response); - } - wpa_hexdump(MSG_DEBUG, "MSCHAPV2: NT Response", - nt_response, MSCHAPV2_NT_RESPONSE_LEN); - wpa_hexdump(MSG_DEBUG, "MSCHAPV2: Auth Response", - auth_response, MSCHAPV2_AUTH_RESPONSE_LEN); - - /* Generate master_key here since we have the needed data available. */ - if (pwhash) { - hash_nt_password_hash(password, password_hash_hash); - } else { - nt_password_hash(password, password_len, password_hash); - hash_nt_password_hash(password_hash, password_hash_hash); - } - get_master_key(password_hash_hash, nt_response, master_key); - wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: Master Key", - master_key, MSCHAPV2_MASTER_KEY_LEN); -} - - -int mschapv2_verify_auth_response(const u8 *auth_response, - const u8 *buf, size_t buf_len) -{ - u8 recv_response[MSCHAPV2_AUTH_RESPONSE_LEN]; - if (buf_len < 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN || - buf[0] != 'S' || buf[1] != '=' || - hexstr2bin((char *) (buf + 2), recv_response, - MSCHAPV2_AUTH_RESPONSE_LEN) || - os_memcmp(auth_response, recv_response, - MSCHAPV2_AUTH_RESPONSE_LEN) != 0) - return -1; - return 0; -} diff --git a/contrib/hostapd/src/eap_peer/mschapv2.h b/contrib/hostapd/src/eap_peer/mschapv2.h deleted file mode 100644 index c7c36f7721..0000000000 --- a/contrib/hostapd/src/eap_peer/mschapv2.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * MSCHAPV2 (RFC 2759) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef MSCHAPV2_H -#define MSCHAPV2_H - -#define MSCHAPV2_CHAL_LEN 16 -#define MSCHAPV2_NT_RESPONSE_LEN 24 -#define MSCHAPV2_AUTH_RESPONSE_LEN 20 -#define MSCHAPV2_MASTER_KEY_LEN 16 - -const u8 * mschapv2_remove_domain(const u8 *username, size_t *len); -void mschapv2_derive_response(const u8 *username, size_t username_len, - const u8 *password, size_t password_len, - int pwhash, - const u8 *auth_challenge, - const u8 *peer_challenge, - u8 *nt_response, u8 *auth_response, - u8 *master_key); -int mschapv2_verify_auth_response(const u8 *auth_response, - const u8 *buf, size_t buf_len); - -#endif /* MSCHAPV2_H */ diff --git a/contrib/hostapd/src/eap_peer/tncc.c b/contrib/hostapd/src/eap_peer/tncc.c deleted file mode 100644 index eaaa1689b5..0000000000 --- a/contrib/hostapd/src/eap_peer/tncc.c +++ /dev/null @@ -1,1369 +0,0 @@ -/* - * EAP-TNC - TNCC (IF-IMC and IF-TNCCS) - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#ifndef CONFIG_NATIVE_WINDOWS -#include -#endif /* CONFIG_NATIVE_WINDOWS */ - -#include "common.h" -#include "base64.h" -#include "tncc.h" -#include "eap_common/eap_tlv_common.h" -#include "eap_common/eap_defs.h" - - -#ifdef UNICODE -#define TSTR "%S" -#else /* UNICODE */ -#define TSTR "%s" -#endif /* UNICODE */ - - -#define TNC_CONFIG_FILE "/etc/tnc_config" -#define TNC_WINREG_PATH TEXT("SOFTWARE\\Trusted Computing Group\\TNC\\IMCs") -#define IF_TNCCS_START \ -"\n" \ -"\n" -#define IF_TNCCS_END "\n" - -/* TNC IF-IMC */ - -typedef unsigned long TNC_UInt32; -typedef unsigned char *TNC_BufferReference; - -typedef TNC_UInt32 TNC_IMCID; -typedef TNC_UInt32 TNC_ConnectionID; -typedef TNC_UInt32 TNC_ConnectionState; -typedef TNC_UInt32 TNC_RetryReason; -typedef TNC_UInt32 TNC_MessageType; -typedef TNC_MessageType *TNC_MessageTypeList; -typedef TNC_UInt32 TNC_VendorID; -typedef TNC_UInt32 TNC_MessageSubtype; -typedef TNC_UInt32 TNC_Version; -typedef TNC_UInt32 TNC_Result; - -typedef TNC_Result (*TNC_TNCC_BindFunctionPointer)( - TNC_IMCID imcID, - char *functionName, - void **pOutfunctionPointer); - -#define TNC_RESULT_SUCCESS 0 -#define TNC_RESULT_NOT_INITIALIZED 1 -#define TNC_RESULT_ALREADY_INITIALIZED 2 -#define TNC_RESULT_NO_COMMON_VERSION 3 -#define TNC_RESULT_CANT_RETRY 4 -#define TNC_RESULT_WONT_RETRY 5 -#define TNC_RESULT_INVALID_PARAMETER 6 -#define TNC_RESULT_CANT_RESPOND 7 -#define TNC_RESULT_ILLEGAL_OPERATION 8 -#define TNC_RESULT_OTHER 9 -#define TNC_RESULT_FATAL 10 - -#define TNC_CONNECTION_STATE_CREATE 0 -#define TNC_CONNECTION_STATE_HANDSHAKE 1 -#define TNC_CONNECTION_STATE_ACCESS_ALLOWED 2 -#define TNC_CONNECTION_STATE_ACCESS_ISOLATED 3 -#define TNC_CONNECTION_STATE_ACCESS_NONE 4 -#define TNC_CONNECTION_STATE_DELETE 5 - -#define TNC_IFIMC_VERSION_1 1 - -#define TNC_VENDORID_ANY ((TNC_VendorID) 0xffffff) -#define TNC_SUBTYPE_ANY ((TNC_MessageSubtype) 0xff) - -/* TNCC-TNCS Message Types */ -#define TNC_TNCCS_RECOMMENDATION 0x00000001 -#define TNC_TNCCS_ERROR 0x00000002 -#define TNC_TNCCS_PREFERREDLANGUAGE 0x00000003 -#define TNC_TNCCS_REASONSTRINGS 0x00000004 - - -/* IF-TNCCS-SOH - SSoH and SSoHR Attributes */ -enum { - SSOH_MS_MACHINE_INVENTORY = 1, - SSOH_MS_QUARANTINE_STATE = 2, - SSOH_MS_PACKET_INFO = 3, - SSOH_MS_SYSTEMGENERATED_IDS = 4, - SSOH_MS_MACHINENAME = 5, - SSOH_MS_CORRELATIONID = 6, - SSOH_MS_INSTALLED_SHVS = 7, - SSOH_MS_MACHINE_INVENTORY_EX = 8 -}; - -struct tnc_if_imc { - struct tnc_if_imc *next; - char *name; - char *path; - void *dlhandle; /* from dlopen() */ - TNC_IMCID imcID; - TNC_ConnectionID connectionID; - TNC_MessageTypeList supported_types; - size_t num_supported_types; - u8 *imc_send; - size_t imc_send_len; - - /* Functions implemented by IMCs (with TNC_IMC_ prefix) */ - TNC_Result (*Initialize)( - TNC_IMCID imcID, - TNC_Version minVersion, - TNC_Version maxVersion, - TNC_Version *pOutActualVersion); - TNC_Result (*NotifyConnectionChange)( - TNC_IMCID imcID, - TNC_ConnectionID connectionID, - TNC_ConnectionState newState); - TNC_Result (*BeginHandshake)( - TNC_IMCID imcID, - TNC_ConnectionID connectionID); - TNC_Result (*ReceiveMessage)( - TNC_IMCID imcID, - TNC_ConnectionID connectionID, - TNC_BufferReference messageBuffer, - TNC_UInt32 messageLength, - TNC_MessageType messageType); - TNC_Result (*BatchEnding)( - TNC_IMCID imcID, - TNC_ConnectionID connectionID); - TNC_Result (*Terminate)(TNC_IMCID imcID); - TNC_Result (*ProvideBindFunction)( - TNC_IMCID imcID, - TNC_TNCC_BindFunctionPointer bindFunction); -}; - -struct tncc_data { - struct tnc_if_imc *imc; - unsigned int last_batchid; -}; - -#define TNC_MAX_IMC_ID 10 -static struct tnc_if_imc *tnc_imc[TNC_MAX_IMC_ID] = { NULL }; - - -/* TNCC functions that IMCs can call */ - -TNC_Result TNC_TNCC_ReportMessageTypes( - TNC_IMCID imcID, - TNC_MessageTypeList supportedTypes, - TNC_UInt32 typeCount) -{ - TNC_UInt32 i; - struct tnc_if_imc *imc; - - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_ReportMessageTypes(imcID=%lu " - "typeCount=%lu)", - (unsigned long) imcID, (unsigned long) typeCount); - - for (i = 0; i < typeCount; i++) { - wpa_printf(MSG_DEBUG, "TNC: supportedTypes[%lu] = %lu", - i, supportedTypes[i]); - } - - if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - imc = tnc_imc[imcID]; - os_free(imc->supported_types); - imc->supported_types = - os_malloc(typeCount * sizeof(TNC_MessageTypeList)); - if (imc->supported_types == NULL) - return TNC_RESULT_FATAL; - os_memcpy(imc->supported_types, supportedTypes, - typeCount * sizeof(TNC_MessageTypeList)); - imc->num_supported_types = typeCount; - - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_TNCC_SendMessage( - TNC_IMCID imcID, - TNC_ConnectionID connectionID, - TNC_BufferReference message, - TNC_UInt32 messageLength, - TNC_MessageType messageType) -{ - struct tnc_if_imc *imc; - unsigned char *b64; - size_t b64len; - - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage(imcID=%lu " - "connectionID=%lu messageType=%lu)", - imcID, connectionID, messageType); - wpa_hexdump_ascii(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage", - message, messageLength); - - if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - b64 = base64_encode(message, messageLength, &b64len); - if (b64 == NULL) - return TNC_RESULT_FATAL; - - imc = tnc_imc[imcID]; - os_free(imc->imc_send); - imc->imc_send_len = 0; - imc->imc_send = os_zalloc(b64len + 100); - if (imc->imc_send == NULL) { - os_free(b64); - return TNC_RESULT_OTHER; - } - - imc->imc_send_len = - os_snprintf((char *) imc->imc_send, b64len + 100, - "%08X" - "%s", - (unsigned int) messageType, b64); - - os_free(b64); - - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_TNCC_RequestHandshakeRetry( - TNC_IMCID imcID, - TNC_ConnectionID connectionID, - TNC_RetryReason reason) -{ - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_RequestHandshakeRetry"); - - if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - /* - * TODO: trigger a call to eapol_sm_request_reauth(). This would - * require that the IMC continues to be loaded in memory afer - * authentication.. - */ - - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_9048_LogMessage(TNC_IMCID imcID, TNC_UInt32 severity, - const char *message) -{ - wpa_printf(MSG_DEBUG, "TNC: TNC_9048_LogMessage(imcID=%lu " - "severity==%lu message='%s')", - imcID, severity, message); - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_9048_UserMessage(TNC_IMCID imcID, TNC_ConnectionID connectionID, - const char *message) -{ - wpa_printf(MSG_DEBUG, "TNC: TNC_9048_UserMessage(imcID=%lu " - "connectionID==%lu message='%s')", - imcID, connectionID, message); - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_TNCC_BindFunction( - TNC_IMCID imcID, - char *functionName, - void **pOutfunctionPointer) -{ - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_BindFunction(imcID=%lu, " - "functionName='%s')", (unsigned long) imcID, functionName); - - if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - if (pOutfunctionPointer == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - if (os_strcmp(functionName, "TNC_TNCC_ReportMessageTypes") == 0) - *pOutfunctionPointer = TNC_TNCC_ReportMessageTypes; - else if (os_strcmp(functionName, "TNC_TNCC_SendMessage") == 0) - *pOutfunctionPointer = TNC_TNCC_SendMessage; - else if (os_strcmp(functionName, "TNC_TNCC_RequestHandshakeRetry") == - 0) - *pOutfunctionPointer = TNC_TNCC_RequestHandshakeRetry; - else if (os_strcmp(functionName, "TNC_9048_LogMessage") == 0) - *pOutfunctionPointer = TNC_9048_LogMessage; - else if (os_strcmp(functionName, "TNC_9048_UserMessage") == 0) - *pOutfunctionPointer = TNC_9048_UserMessage; - else - *pOutfunctionPointer = NULL; - - return TNC_RESULT_SUCCESS; -} - - -static void * tncc_get_sym(void *handle, char *func) -{ - void *fptr; - -#ifdef CONFIG_NATIVE_WINDOWS -#ifdef _WIN32_WCE - fptr = GetProcAddressA(handle, func); -#else /* _WIN32_WCE */ - fptr = GetProcAddress(handle, func); -#endif /* _WIN32_WCE */ -#else /* CONFIG_NATIVE_WINDOWS */ - fptr = dlsym(handle, func); -#endif /* CONFIG_NATIVE_WINDOWS */ - - return fptr; -} - - -static int tncc_imc_resolve_funcs(struct tnc_if_imc *imc) -{ - void *handle = imc->dlhandle; - - /* Mandatory IMC functions */ - imc->Initialize = tncc_get_sym(handle, "TNC_IMC_Initialize"); - if (imc->Initialize == NULL) { - wpa_printf(MSG_ERROR, "TNC: IMC does not export " - "TNC_IMC_Initialize"); - return -1; - } - - imc->BeginHandshake = tncc_get_sym(handle, "TNC_IMC_BeginHandshake"); - if (imc->BeginHandshake == NULL) { - wpa_printf(MSG_ERROR, "TNC: IMC does not export " - "TNC_IMC_BeginHandshake"); - return -1; - } - - imc->ProvideBindFunction = - tncc_get_sym(handle, "TNC_IMC_ProvideBindFunction"); - if (imc->ProvideBindFunction == NULL) { - wpa_printf(MSG_ERROR, "TNC: IMC does not export " - "TNC_IMC_ProvideBindFunction"); - return -1; - } - - /* Optional IMC functions */ - imc->NotifyConnectionChange = - tncc_get_sym(handle, "TNC_IMC_NotifyConnectionChange"); - imc->ReceiveMessage = tncc_get_sym(handle, "TNC_IMC_ReceiveMessage"); - imc->BatchEnding = tncc_get_sym(handle, "TNC_IMC_BatchEnding"); - imc->Terminate = tncc_get_sym(handle, "TNC_IMC_Terminate"); - - return 0; -} - - -static int tncc_imc_initialize(struct tnc_if_imc *imc) -{ - TNC_Result res; - TNC_Version imc_ver; - - wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_Initialize for IMC '%s'", - imc->name); - res = imc->Initialize(imc->imcID, TNC_IFIMC_VERSION_1, - TNC_IFIMC_VERSION_1, &imc_ver); - wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_Initialize: res=%lu imc_ver=%lu", - (unsigned long) res, (unsigned long) imc_ver); - - return res == TNC_RESULT_SUCCESS ? 0 : -1; -} - - -static int tncc_imc_terminate(struct tnc_if_imc *imc) -{ - TNC_Result res; - - if (imc->Terminate == NULL) - return 0; - - wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_Terminate for IMC '%s'", - imc->name); - res = imc->Terminate(imc->imcID); - wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_Terminate: %lu", - (unsigned long) res); - - return res == TNC_RESULT_SUCCESS ? 0 : -1; -} - - -static int tncc_imc_provide_bind_function(struct tnc_if_imc *imc) -{ - TNC_Result res; - - wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_ProvideBindFunction for " - "IMC '%s'", imc->name); - res = imc->ProvideBindFunction(imc->imcID, TNC_TNCC_BindFunction); - wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_ProvideBindFunction: res=%lu", - (unsigned long) res); - - return res == TNC_RESULT_SUCCESS ? 0 : -1; -} - - -static int tncc_imc_notify_connection_change(struct tnc_if_imc *imc, - TNC_ConnectionState state) -{ - TNC_Result res; - - if (imc->NotifyConnectionChange == NULL) - return 0; - - wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_NotifyConnectionChange(%d)" - " for IMC '%s'", (int) state, imc->name); - res = imc->NotifyConnectionChange(imc->imcID, imc->connectionID, - state); - wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_NotifyConnectionChange: %lu", - (unsigned long) res); - - return res == TNC_RESULT_SUCCESS ? 0 : -1; -} - - -static int tncc_imc_begin_handshake(struct tnc_if_imc *imc) -{ - TNC_Result res; - - wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_BeginHandshake for IMC " - "'%s'", imc->name); - res = imc->BeginHandshake(imc->imcID, imc->connectionID); - wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_BeginHandshake: %lu", - (unsigned long) res); - - return res == TNC_RESULT_SUCCESS ? 0 : -1; -} - - -static int tncc_load_imc(struct tnc_if_imc *imc) -{ - if (imc->path == NULL) { - wpa_printf(MSG_DEBUG, "TNC: No IMC configured"); - return -1; - } - - wpa_printf(MSG_DEBUG, "TNC: Opening IMC: %s (%s)", - imc->name, imc->path); -#ifdef CONFIG_NATIVE_WINDOWS -#ifdef UNICODE - { - TCHAR *lib = wpa_strdup_tchar(imc->path); - if (lib == NULL) - return -1; - imc->dlhandle = LoadLibrary(lib); - os_free(lib); - } -#else /* UNICODE */ - imc->dlhandle = LoadLibrary(imc->path); -#endif /* UNICODE */ - if (imc->dlhandle == NULL) { - wpa_printf(MSG_ERROR, "TNC: Failed to open IMC '%s' (%s): %d", - imc->name, imc->path, (int) GetLastError()); - return -1; - } -#else /* CONFIG_NATIVE_WINDOWS */ - imc->dlhandle = dlopen(imc->path, RTLD_LAZY); - if (imc->dlhandle == NULL) { - wpa_printf(MSG_ERROR, "TNC: Failed to open IMC '%s' (%s): %s", - imc->name, imc->path, dlerror()); - return -1; - } -#endif /* CONFIG_NATIVE_WINDOWS */ - - if (tncc_imc_resolve_funcs(imc) < 0) { - wpa_printf(MSG_ERROR, "TNC: Failed to resolve IMC functions"); - return -1; - } - - if (tncc_imc_initialize(imc) < 0 || - tncc_imc_provide_bind_function(imc) < 0) { - wpa_printf(MSG_ERROR, "TNC: Failed to initialize IMC"); - return -1; - } - - return 0; -} - - -static void tncc_unload_imc(struct tnc_if_imc *imc) -{ - tncc_imc_terminate(imc); - tnc_imc[imc->imcID] = NULL; - - if (imc->dlhandle) { -#ifdef CONFIG_NATIVE_WINDOWS - FreeLibrary(imc->dlhandle); -#else /* CONFIG_NATIVE_WINDOWS */ - dlclose(imc->dlhandle); -#endif /* CONFIG_NATIVE_WINDOWS */ - } - os_free(imc->name); - os_free(imc->path); - os_free(imc->supported_types); - os_free(imc->imc_send); -} - - -static int tncc_supported_type(struct tnc_if_imc *imc, unsigned int type) -{ - size_t i; - unsigned int vendor, subtype; - - if (imc == NULL || imc->supported_types == NULL) - return 0; - - vendor = type >> 8; - subtype = type & 0xff; - - for (i = 0; i < imc->num_supported_types; i++) { - unsigned int svendor, ssubtype; - svendor = imc->supported_types[i] >> 8; - ssubtype = imc->supported_types[i] & 0xff; - if ((vendor == svendor || svendor == TNC_VENDORID_ANY) && - (subtype == ssubtype || ssubtype == TNC_SUBTYPE_ANY)) - return 1; - } - - return 0; -} - - -static void tncc_send_to_imcs(struct tncc_data *tncc, unsigned int type, - const u8 *msg, size_t len) -{ - struct tnc_if_imc *imc; - TNC_Result res; - - wpa_hexdump_ascii(MSG_MSGDUMP, "TNC: Message to IMC(s)", msg, len); - - for (imc = tncc->imc; imc; imc = imc->next) { - if (imc->ReceiveMessage == NULL || - !tncc_supported_type(imc, type)) - continue; - - wpa_printf(MSG_DEBUG, "TNC: Call ReceiveMessage for IMC '%s'", - imc->name); - res = imc->ReceiveMessage(imc->imcID, imc->connectionID, - (TNC_BufferReference) msg, len, - type); - wpa_printf(MSG_DEBUG, "TNC: ReceiveMessage: %lu", - (unsigned long) res); - } -} - - -void tncc_init_connection(struct tncc_data *tncc) -{ - struct tnc_if_imc *imc; - - for (imc = tncc->imc; imc; imc = imc->next) { - tncc_imc_notify_connection_change( - imc, TNC_CONNECTION_STATE_CREATE); - tncc_imc_notify_connection_change( - imc, TNC_CONNECTION_STATE_HANDSHAKE); - - os_free(imc->imc_send); - imc->imc_send = NULL; - imc->imc_send_len = 0; - - tncc_imc_begin_handshake(imc); - } -} - - -size_t tncc_total_send_len(struct tncc_data *tncc) -{ - struct tnc_if_imc *imc; - - size_t len = 0; - for (imc = tncc->imc; imc; imc = imc->next) - len += imc->imc_send_len; - return len; -} - - -u8 * tncc_copy_send_buf(struct tncc_data *tncc, u8 *pos) -{ - struct tnc_if_imc *imc; - - for (imc = tncc->imc; imc; imc = imc->next) { - if (imc->imc_send == NULL) - continue; - - os_memcpy(pos, imc->imc_send, imc->imc_send_len); - pos += imc->imc_send_len; - os_free(imc->imc_send); - imc->imc_send = NULL; - imc->imc_send_len = 0; - } - - return pos; -} - - -char * tncc_if_tnccs_start(struct tncc_data *tncc) -{ - char *buf = os_malloc(1000); - if (buf == NULL) - return NULL; - tncc->last_batchid++; - os_snprintf(buf, 1000, IF_TNCCS_START, tncc->last_batchid); - return buf; -} - - -char * tncc_if_tnccs_end(void) -{ - char *buf = os_malloc(100); - if (buf == NULL) - return NULL; - os_snprintf(buf, 100, IF_TNCCS_END); - return buf; -} - - -static void tncc_notify_recommendation(struct tncc_data *tncc, - enum tncc_process_res res) -{ - TNC_ConnectionState state; - struct tnc_if_imc *imc; - - switch (res) { - case TNCCS_RECOMMENDATION_ALLOW: - state = TNC_CONNECTION_STATE_ACCESS_ALLOWED; - break; - case TNCCS_RECOMMENDATION_NONE: - state = TNC_CONNECTION_STATE_ACCESS_NONE; - break; - case TNCCS_RECOMMENDATION_ISOLATE: - state = TNC_CONNECTION_STATE_ACCESS_ISOLATED; - break; - default: - state = TNC_CONNECTION_STATE_ACCESS_NONE; - break; - } - - for (imc = tncc->imc; imc; imc = imc->next) - tncc_imc_notify_connection_change(imc, state); -} - - -static int tncc_get_type(char *start, unsigned int *type) -{ - char *pos = os_strstr(start, ""); - if (pos == NULL) - return -1; - pos += 6; - *type = strtoul(pos, NULL, 16); - return 0; -} - - -static unsigned char * tncc_get_base64(char *start, size_t *decoded_len) -{ - char *pos, *pos2; - unsigned char *decoded; - - pos = os_strstr(start, ""); - if (pos == NULL) - return NULL; - - pos += 8; - pos2 = os_strstr(pos, ""); - if (pos2 == NULL) - return NULL; - *pos2 = '\0'; - - decoded = base64_decode((unsigned char *) pos, os_strlen(pos), - decoded_len); - *pos2 = '<'; - if (decoded == NULL) { - wpa_printf(MSG_DEBUG, "TNC: Failed to decode Base64 data"); - } - - return decoded; -} - - -static enum tncc_process_res tncc_get_recommendation(char *start) -{ - char *pos, *pos2, saved; - int recom; - - pos = os_strstr(start, ""); - if (start == NULL || end == NULL || start > end) { - os_free(buf); - return TNCCS_PROCESS_ERROR; - } - - start += 13; - while (*start == ' ') - start++; - *end = '\0'; - - pos = os_strstr(start, "BatchId="); - if (pos == NULL) { - os_free(buf); - return TNCCS_PROCESS_ERROR; - } - - pos += 8; - if (*pos == '"') - pos++; - batch_id = atoi(pos); - wpa_printf(MSG_DEBUG, "TNC: Received IF-TNCCS BatchId=%u", - batch_id); - if (batch_id != tncc->last_batchid + 1) { - wpa_printf(MSG_DEBUG, "TNC: Unexpected IF-TNCCS BatchId " - "%u (expected %u)", - batch_id, tncc->last_batchid + 1); - os_free(buf); - return TNCCS_PROCESS_ERROR; - } - tncc->last_batchid = batch_id; - - while (*pos != '\0' && *pos != '>') - pos++; - if (*pos == '\0') { - os_free(buf); - return TNCCS_PROCESS_ERROR; - } - pos++; - payload = start; - - /* - * - * 01234567 - * foo== - * - */ - - while (*start) { - char *endpos; - unsigned int type; - - pos = os_strstr(start, ""); - if (pos == NULL) - break; - start = pos + 17; - end = os_strstr(start, ""); - if (end == NULL) - break; - *end = '\0'; - endpos = end; - end += 18; - - if (tncc_get_type(start, &type) < 0) { - *endpos = '<'; - start = end; - continue; - } - wpa_printf(MSG_DEBUG, "TNC: IMC-IMV-Message Type 0x%x", type); - - decoded = tncc_get_base64(start, &decoded_len); - if (decoded == NULL) { - *endpos = '<'; - start = end; - continue; - } - - tncc_send_to_imcs(tncc, type, decoded, decoded_len); - - os_free(decoded); - - start = end; - } - - /* - * - * 01234567 - * - * foo== - * - */ - - start = payload; - while (*start) { - unsigned int type; - char *xml, *xmlend, *endpos; - - pos = os_strstr(start, ""); - if (pos == NULL) - break; - start = pos + 19; - end = os_strstr(start, ""); - if (end == NULL) - break; - *end = '\0'; - endpos = end; - end += 20; - - if (tncc_get_type(start, &type) < 0) { - *endpos = '<'; - start = end; - continue; - } - wpa_printf(MSG_DEBUG, "TNC: TNCC-TNCS-Message Type 0x%x", - type); - - /* Base64 OR XML */ - decoded = NULL; - xml = NULL; - xmlend = NULL; - pos = os_strstr(start, ""); - if (pos) { - pos += 5; - pos2 = os_strstr(pos, ""); - if (pos2 == NULL) { - *endpos = '<'; - start = end; - continue; - } - xmlend = pos2; - xml = pos; - } else { - decoded = tncc_get_base64(start, &decoded_len); - if (decoded == NULL) { - *endpos = '<'; - start = end; - continue; - } - } - - if (decoded) { - wpa_hexdump_ascii(MSG_MSGDUMP, - "TNC: TNCC-TNCS-Message Base64", - decoded, decoded_len); - os_free(decoded); - } - - if (xml) { - wpa_hexdump_ascii(MSG_MSGDUMP, - "TNC: TNCC-TNCS-Message XML", - (unsigned char *) xml, - xmlend - xml); - } - - if (type == TNC_TNCCS_RECOMMENDATION && xml) { - /* - * - * - */ - *xmlend = '\0'; - res = tncc_get_recommendation(xml); - *xmlend = '<'; - recommendation_msg = 1; - } - - start = end; - } - - os_free(buf); - - if (recommendation_msg) - tncc_notify_recommendation(tncc, res); - - return res; -} - - -#ifdef CONFIG_NATIVE_WINDOWS -static int tncc_read_config_reg(struct tncc_data *tncc, HKEY hive) -{ - HKEY hk, hk2; - LONG ret; - DWORD i; - struct tnc_if_imc *imc, *last; - int j; - - last = tncc->imc; - while (last && last->next) - last = last->next; - - ret = RegOpenKeyEx(hive, TNC_WINREG_PATH, 0, KEY_ENUMERATE_SUB_KEYS, - &hk); - if (ret != ERROR_SUCCESS) - return 0; - - for (i = 0; ; i++) { - TCHAR name[255], *val; - DWORD namelen, buflen; - - namelen = 255; - ret = RegEnumKeyEx(hk, i, name, &namelen, NULL, NULL, NULL, - NULL); - - if (ret == ERROR_NO_MORE_ITEMS) - break; - - if (ret != ERROR_SUCCESS) { - wpa_printf(MSG_DEBUG, "TNC: RegEnumKeyEx failed: 0x%x", - (unsigned int) ret); - break; - } - - if (namelen >= 255) - namelen = 255 - 1; - name[namelen] = '\0'; - - wpa_printf(MSG_DEBUG, "TNC: IMC '" TSTR "'", name); - - ret = RegOpenKeyEx(hk, name, 0, KEY_QUERY_VALUE, &hk2); - if (ret != ERROR_SUCCESS) { - wpa_printf(MSG_DEBUG, "Could not open IMC key '" TSTR - "'", name); - continue; - } - - ret = RegQueryValueEx(hk2, TEXT("Path"), NULL, NULL, NULL, - &buflen); - if (ret != ERROR_SUCCESS) { - wpa_printf(MSG_DEBUG, "TNC: Could not read Path from " - "IMC key '" TSTR "'", name); - RegCloseKey(hk2); - continue; - } - - val = os_malloc(buflen); - if (val == NULL) { - RegCloseKey(hk2); - continue; - } - - ret = RegQueryValueEx(hk2, TEXT("Path"), NULL, NULL, - (LPBYTE) val, &buflen); - if (ret != ERROR_SUCCESS) { - os_free(val); - RegCloseKey(hk2); - continue; - } - - RegCloseKey(hk2); - - wpa_unicode2ascii_inplace(val); - wpa_printf(MSG_DEBUG, "TNC: IMC Path '%s'", (char *) val); - - for (j = 0; j < TNC_MAX_IMC_ID; j++) { - if (tnc_imc[j] == NULL) - break; - } - if (j >= TNC_MAX_IMC_ID) { - wpa_printf(MSG_DEBUG, "TNC: Too many IMCs"); - os_free(val); - continue; - } - - imc = os_zalloc(sizeof(*imc)); - if (imc == NULL) { - os_free(val); - break; - } - - imc->imcID = j; - - wpa_unicode2ascii_inplace(name); - imc->name = os_strdup((char *) name); - imc->path = os_strdup((char *) val); - - os_free(val); - - if (last == NULL) - tncc->imc = imc; - else - last->next = imc; - last = imc; - - tnc_imc[imc->imcID] = imc; - } - - RegCloseKey(hk); - - return 0; -} - - -static int tncc_read_config(struct tncc_data *tncc) -{ - if (tncc_read_config_reg(tncc, HKEY_LOCAL_MACHINE) < 0 || - tncc_read_config_reg(tncc, HKEY_CURRENT_USER) < 0) - return -1; - return 0; -} - -#else /* CONFIG_NATIVE_WINDOWS */ - -static struct tnc_if_imc * tncc_parse_imc(char *start, char *end, int *error) -{ - struct tnc_if_imc *imc; - char *pos, *pos2; - int i; - - for (i = 0; i < TNC_MAX_IMC_ID; i++) { - if (tnc_imc[i] == NULL) - break; - } - if (i >= TNC_MAX_IMC_ID) { - wpa_printf(MSG_DEBUG, "TNC: Too many IMCs"); - return NULL; - } - - imc = os_zalloc(sizeof(*imc)); - if (imc == NULL) { - *error = 1; - return NULL; - } - - imc->imcID = i; - - pos = start; - wpa_printf(MSG_DEBUG, "TNC: Configured IMC: %s", pos); - if (pos + 1 >= end || *pos != '"') { - wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' " - "(no starting quotation mark)", start); - os_free(imc); - return NULL; - } - - pos++; - pos2 = pos; - while (pos2 < end && *pos2 != '"') - pos2++; - if (pos2 >= end) { - wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' " - "(no ending quotation mark)", start); - os_free(imc); - return NULL; - } - *pos2 = '\0'; - wpa_printf(MSG_DEBUG, "TNC: Name: '%s'", pos); - imc->name = os_strdup(pos); - - pos = pos2 + 1; - if (pos >= end || *pos != ' ') { - wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' " - "(no space after name)", start); - os_free(imc->name); - os_free(imc); - return NULL; - } - - pos++; - wpa_printf(MSG_DEBUG, "TNC: IMC file: '%s'", pos); - imc->path = os_strdup(pos); - tnc_imc[imc->imcID] = imc; - - return imc; -} - - -static int tncc_read_config(struct tncc_data *tncc) -{ - char *config, *end, *pos, *line_end; - size_t config_len; - struct tnc_if_imc *imc, *last; - - last = NULL; - - config = os_readfile(TNC_CONFIG_FILE, &config_len); - if (config == NULL) { - wpa_printf(MSG_ERROR, "TNC: Could not open TNC configuration " - "file '%s'", TNC_CONFIG_FILE); - return -1; - } - - end = config + config_len; - for (pos = config; pos < end; pos = line_end + 1) { - line_end = pos; - while (*line_end != '\n' && *line_end != '\r' && - line_end < end) - line_end++; - *line_end = '\0'; - - if (os_strncmp(pos, "IMC ", 4) == 0) { - int error = 0; - - imc = tncc_parse_imc(pos + 4, line_end, &error); - if (error) - return -1; - if (imc) { - if (last == NULL) - tncc->imc = imc; - else - last->next = imc; - last = imc; - } - } - } - - os_free(config); - - return 0; -} - -#endif /* CONFIG_NATIVE_WINDOWS */ - - -struct tncc_data * tncc_init(void) -{ - struct tncc_data *tncc; - struct tnc_if_imc *imc; - - tncc = os_zalloc(sizeof(*tncc)); - if (tncc == NULL) - return NULL; - - /* TODO: - * move loading and Initialize() to a location that is not - * re-initialized for every EAP-TNC session (?) - */ - - if (tncc_read_config(tncc) < 0) { - wpa_printf(MSG_ERROR, "TNC: Failed to read TNC configuration"); - goto failed; - } - - for (imc = tncc->imc; imc; imc = imc->next) { - if (tncc_load_imc(imc)) { - wpa_printf(MSG_ERROR, "TNC: Failed to load IMC '%s'", - imc->name); - goto failed; - } - } - - return tncc; - -failed: - tncc_deinit(tncc); - return NULL; -} - - -void tncc_deinit(struct tncc_data *tncc) -{ - struct tnc_if_imc *imc, *prev; - - imc = tncc->imc; - while (imc) { - tncc_unload_imc(imc); - - prev = imc; - imc = imc->next; - os_free(prev); - } - - os_free(tncc); -} - - -static struct wpabuf * tncc_build_soh(int ver) -{ - struct wpabuf *buf; - u8 *tlv_len, *tlv_len2, *outer_len, *inner_len, *ssoh_len, *end; - u8 correlation_id[24]; - /* TODO: get correct name */ - char *machinename = "wpa_supplicant@w1.fi"; - - if (os_get_random(correlation_id, sizeof(correlation_id))) - return NULL; - wpa_hexdump(MSG_DEBUG, "TNC: SoH Correlation ID", - correlation_id, sizeof(correlation_id)); - - buf = wpabuf_alloc(200); - if (buf == NULL) - return NULL; - - /* Vendor-Specific TLV (Microsoft) - SoH */ - wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* TLV Type */ - tlv_len = wpabuf_put(buf, 2); /* Length */ - wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* Vendor_Id */ - wpabuf_put_be16(buf, 0x01); /* TLV Type - SoH TLV */ - tlv_len2 = wpabuf_put(buf, 2); /* Length */ - - /* SoH Header */ - wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* Outer Type */ - outer_len = wpabuf_put(buf, 2); - wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */ - wpabuf_put_be16(buf, ver); /* Inner Type */ - inner_len = wpabuf_put(buf, 2); - - if (ver == 2) { - /* SoH Mode Sub-Header */ - /* Outer Type */ - wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); - wpabuf_put_be16(buf, 4 + 24 + 1 + 1); /* Length */ - wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */ - /* Value: */ - wpabuf_put_data(buf, correlation_id, sizeof(correlation_id)); - wpabuf_put_u8(buf, 0x01); /* Intent Flag - Request */ - wpabuf_put_u8(buf, 0x00); /* Content-Type Flag */ - } - - /* SSoH TLV */ - /* System-Health-Id */ - wpabuf_put_be16(buf, 0x0002); /* Type */ - wpabuf_put_be16(buf, 4); /* Length */ - wpabuf_put_be32(buf, 79616); - /* Vendor-Specific Attribute */ - wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); - ssoh_len = wpabuf_put(buf, 2); - wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */ - - /* MS-Packet-Info */ - wpabuf_put_u8(buf, SSOH_MS_PACKET_INFO); - /* Note: IF-TNCCS-SOH v1.0 r8 claims this field to be: - * Reserved(4 bits) r(1 bit) Vers(3 bits), but Windows XP - * SP3 seems to be sending 0x11 for SSoH, i.e., r(request/response) bit - * would not be in the specified location. - * [MS-SOH] 4.0.2: Reserved(3 bits) r(1 bit) Vers(4 bits) - */ - wpabuf_put_u8(buf, 0x11); /* r=request, vers=1 */ - - /* MS-Machine-Inventory */ - /* TODO: get correct values; 0 = not applicable for OS */ - wpabuf_put_u8(buf, SSOH_MS_MACHINE_INVENTORY); - wpabuf_put_be32(buf, 0); /* osVersionMajor */ - wpabuf_put_be32(buf, 0); /* osVersionMinor */ - wpabuf_put_be32(buf, 0); /* osVersionBuild */ - wpabuf_put_be16(buf, 0); /* spVersionMajor */ - wpabuf_put_be16(buf, 0); /* spVersionMinor */ - wpabuf_put_be16(buf, 0); /* procArch */ - - /* MS-MachineName */ - wpabuf_put_u8(buf, SSOH_MS_MACHINENAME); - wpabuf_put_be16(buf, os_strlen(machinename) + 1); - wpabuf_put_data(buf, machinename, os_strlen(machinename) + 1); - - /* MS-CorrelationId */ - wpabuf_put_u8(buf, SSOH_MS_CORRELATIONID); - wpabuf_put_data(buf, correlation_id, sizeof(correlation_id)); - - /* MS-Quarantine-State */ - wpabuf_put_u8(buf, SSOH_MS_QUARANTINE_STATE); - wpabuf_put_be16(buf, 1); /* Flags: ExtState=0, f=0, qState=1 */ - wpabuf_put_be32(buf, 0xffffffff); /* ProbTime (hi) */ - wpabuf_put_be32(buf, 0xffffffff); /* ProbTime (lo) */ - wpabuf_put_be16(buf, 1); /* urlLenInBytes */ - wpabuf_put_u8(buf, 0); /* null termination for the url */ - - /* MS-Machine-Inventory-Ex */ - wpabuf_put_u8(buf, SSOH_MS_MACHINE_INVENTORY_EX); - wpabuf_put_be32(buf, 0); /* Reserved - * (note: Windows XP SP3 uses 0xdecafbad) */ - wpabuf_put_u8(buf, 1); /* ProductType: Client */ - - /* Update SSoH Length */ - end = wpabuf_put(buf, 0); - WPA_PUT_BE16(ssoh_len, end - ssoh_len - 2); - - /* TODO: SoHReportEntry TLV (zero or more) */ - - /* Update length fields */ - end = wpabuf_put(buf, 0); - WPA_PUT_BE16(tlv_len, end - tlv_len - 2); - WPA_PUT_BE16(tlv_len2, end - tlv_len2 - 2); - WPA_PUT_BE16(outer_len, end - outer_len - 2); - WPA_PUT_BE16(inner_len, end - inner_len - 2); - - return buf; -} - - -struct wpabuf * tncc_process_soh_request(int ver, const u8 *data, size_t len) -{ - const u8 *pos; - - wpa_hexdump(MSG_DEBUG, "TNC: SoH Request", data, len); - - if (len < 12) - return NULL; - - /* SoH Request */ - pos = data; - - /* TLV Type */ - if (WPA_GET_BE16(pos) != EAP_TLV_VENDOR_SPECIFIC_TLV) - return NULL; - pos += 2; - - /* Length */ - if (WPA_GET_BE16(pos) < 8) - return NULL; - pos += 2; - - /* Vendor_Id */ - if (WPA_GET_BE32(pos) != EAP_VENDOR_MICROSOFT) - return NULL; - pos += 4; - - /* TLV Type */ - if (WPA_GET_BE16(pos) != 0x02 /* SoH request TLV */) - return NULL; - - wpa_printf(MSG_DEBUG, "TNC: SoH Request TLV received"); - - return tncc_build_soh(2); -} diff --git a/contrib/hostapd/src/eap_peer/tncc.h b/contrib/hostapd/src/eap_peer/tncc.h deleted file mode 100644 index 4d42a05b9a..0000000000 --- a/contrib/hostapd/src/eap_peer/tncc.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * EAP-TNC - TNCC (IF-IMC and IF-TNCCS) - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TNCC_H -#define TNCC_H - -struct tncc_data; - -struct tncc_data * tncc_init(void); -void tncc_deinit(struct tncc_data *tncc); -void tncc_init_connection(struct tncc_data *tncc); -size_t tncc_total_send_len(struct tncc_data *tncc); -u8 * tncc_copy_send_buf(struct tncc_data *tncc, u8 *pos); -char * tncc_if_tnccs_start(struct tncc_data *tncc); -char * tncc_if_tnccs_end(void); - -enum tncc_process_res { - TNCCS_PROCESS_ERROR = -1, - TNCCS_PROCESS_OK_NO_RECOMMENDATION = 0, - TNCCS_RECOMMENDATION_ERROR, - TNCCS_RECOMMENDATION_ALLOW, - TNCCS_RECOMMENDATION_NONE, - TNCCS_RECOMMENDATION_ISOLATE -}; - -enum tncc_process_res tncc_process_if_tnccs(struct tncc_data *tncc, - const u8 *msg, size_t len); - -struct wpabuf * tncc_process_soh_request(int ver, const u8 *data, size_t len); - -#endif /* TNCC_H */ diff --git a/contrib/hostapd/src/eap_server/eap.c b/contrib/hostapd/src/eap_server/eap.c deleted file mode 100644 index 897adc3b1a..0000000000 --- a/contrib/hostapd/src/eap_server/eap.c +++ /dev/null @@ -1,1345 +0,0 @@ -/* - * hostapd / EAP Full Authenticator state machine (RFC 4137) - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This state machine is based on the full authenticator state machine defined - * in RFC 4137. However, to support backend authentication in RADIUS - * authentication server functionality, parts of backend authenticator (also - * from RFC 4137) are mixed in. This functionality is enabled by setting - * backend_auth configuration variable to TRUE. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "state_machine.h" - -#define STATE_MACHINE_DATA struct eap_sm -#define STATE_MACHINE_DEBUG_PREFIX "EAP" - -#define EAP_MAX_AUTH_ROUNDS 50 - -static void eap_user_free(struct eap_user *user); - - -/* EAP state machines are described in RFC 4137 */ - -static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount, - int eapSRTT, int eapRTTVAR, - int methodTimeout); -static void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp); -static int eap_sm_getId(const struct wpabuf *data); -static struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id); -static struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id); -static int eap_sm_nextId(struct eap_sm *sm, int id); -static void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list, - size_t len); -static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor); -static int eap_sm_Policy_getDecision(struct eap_sm *sm); -static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method); - - -static int eap_copy_buf(struct wpabuf **dst, const struct wpabuf *src) -{ - if (src == NULL) - return -1; - - wpabuf_free(*dst); - *dst = wpabuf_dup(src); - return *dst ? 0 : -1; -} - - -static int eap_copy_data(u8 **dst, size_t *dst_len, - const u8 *src, size_t src_len) -{ - if (src == NULL) - return -1; - - os_free(*dst); - *dst = os_malloc(src_len); - if (*dst) { - os_memcpy(*dst, src, src_len); - *dst_len = src_len; - return 0; - } else { - *dst_len = 0; - return -1; - } -} - -#define EAP_COPY(dst, src) \ - eap_copy_data((dst), (dst ## Len), (src), (src ## Len)) - - -/** - * eap_user_get - Fetch user information from the database - * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() - * @identity: Identity (User-Name) of the user - * @identity_len: Length of identity in bytes - * @phase2: 0 = EAP phase1 user, 1 = EAP phase2 (tunneled) user - * Returns: 0 on success, or -1 on failure - * - * This function is used to fetch user information for EAP. The user will be - * selected based on the specified identity. sm->user and - * sm->user_eap_method_index are updated for the new user when a matching user - * is found. sm->user can be used to get user information (e.g., password). - */ -int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len, - int phase2) -{ - struct eap_user *user; - - if (sm == NULL || sm->eapol_cb == NULL || - sm->eapol_cb->get_eap_user == NULL) - return -1; - - eap_user_free(sm->user); - sm->user = NULL; - - user = os_zalloc(sizeof(*user)); - if (user == NULL) - return -1; - - if (sm->eapol_cb->get_eap_user(sm->eapol_ctx, identity, - identity_len, phase2, user) != 0) { - eap_user_free(user); - return -1; - } - - sm->user = user; - sm->user_eap_method_index = 0; - - return 0; -} - - -SM_STATE(EAP, DISABLED) -{ - SM_ENTRY(EAP, DISABLED); - sm->num_rounds = 0; -} - - -SM_STATE(EAP, INITIALIZE) -{ - SM_ENTRY(EAP, INITIALIZE); - - sm->currentId = -1; - sm->eap_if.eapSuccess = FALSE; - sm->eap_if.eapFail = FALSE; - sm->eap_if.eapTimeout = FALSE; - os_free(sm->eap_if.eapKeyData); - sm->eap_if.eapKeyData = NULL; - sm->eap_if.eapKeyDataLen = 0; - sm->eap_if.eapKeyAvailable = FALSE; - sm->eap_if.eapRestart = FALSE; - - /* - * This is not defined in RFC 4137, but method state needs to be - * reseted here so that it does not remain in success state when - * re-authentication starts. - */ - if (sm->m && sm->eap_method_priv) { - sm->m->reset(sm, sm->eap_method_priv); - sm->eap_method_priv = NULL; - } - sm->m = NULL; - sm->user_eap_method_index = 0; - - if (sm->backend_auth) { - sm->currentMethod = EAP_TYPE_NONE; - /* parse rxResp, respId, respMethod */ - eap_sm_parseEapResp(sm, sm->eap_if.eapRespData); - if (sm->rxResp) { - sm->currentId = sm->respId; - } - } - sm->num_rounds = 0; - sm->method_pending = METHOD_PENDING_NONE; -} - - -SM_STATE(EAP, PICK_UP_METHOD) -{ - SM_ENTRY(EAP, PICK_UP_METHOD); - - if (eap_sm_Policy_doPickUp(sm, sm->respMethod)) { - sm->currentMethod = sm->respMethod; - if (sm->m && sm->eap_method_priv) { - sm->m->reset(sm, sm->eap_method_priv); - sm->eap_method_priv = NULL; - } - sm->m = eap_server_get_eap_method(EAP_VENDOR_IETF, - sm->currentMethod); - if (sm->m && sm->m->initPickUp) { - sm->eap_method_priv = sm->m->initPickUp(sm); - if (sm->eap_method_priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP: Failed to " - "initialize EAP method %d", - sm->currentMethod); - sm->m = NULL; - sm->currentMethod = EAP_TYPE_NONE; - } - } else { - sm->m = NULL; - sm->currentMethod = EAP_TYPE_NONE; - } - } -} - - -SM_STATE(EAP, IDLE) -{ - SM_ENTRY(EAP, IDLE); - - sm->eap_if.retransWhile = eap_sm_calculateTimeout( - sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR, - sm->methodTimeout); -} - - -SM_STATE(EAP, RETRANSMIT) -{ - SM_ENTRY(EAP, RETRANSMIT); - - sm->retransCount++; - if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) { - if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0) - sm->eap_if.eapReq = TRUE; - } -} - - -SM_STATE(EAP, RECEIVED) -{ - SM_ENTRY(EAP, RECEIVED); - - /* parse rxResp, respId, respMethod */ - eap_sm_parseEapResp(sm, sm->eap_if.eapRespData); - sm->num_rounds++; -} - - -SM_STATE(EAP, DISCARD) -{ - SM_ENTRY(EAP, DISCARD); - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapNoReq = TRUE; -} - - -SM_STATE(EAP, SEND_REQUEST) -{ - SM_ENTRY(EAP, SEND_REQUEST); - - sm->retransCount = 0; - if (sm->eap_if.eapReqData) { - if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0) - { - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = TRUE; - } else { - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = FALSE; - } - } else { - wpa_printf(MSG_INFO, "EAP: SEND_REQUEST - no eapReqData"); - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = FALSE; - sm->eap_if.eapNoReq = TRUE; - } -} - - -SM_STATE(EAP, INTEGRITY_CHECK) -{ - SM_ENTRY(EAP, INTEGRITY_CHECK); - - if (sm->m->check) { - sm->ignore = sm->m->check(sm, sm->eap_method_priv, - sm->eap_if.eapRespData); - } -} - - -SM_STATE(EAP, METHOD_REQUEST) -{ - SM_ENTRY(EAP, METHOD_REQUEST); - - if (sm->m == NULL) { - wpa_printf(MSG_DEBUG, "EAP: method not initialized"); - return; - } - - sm->currentId = eap_sm_nextId(sm, sm->currentId); - wpa_printf(MSG_DEBUG, "EAP: building EAP-Request: Identifier %d", - sm->currentId); - sm->lastId = sm->currentId; - wpabuf_free(sm->eap_if.eapReqData); - sm->eap_if.eapReqData = sm->m->buildReq(sm, sm->eap_method_priv, - sm->currentId); - if (sm->m->getTimeout) - sm->methodTimeout = sm->m->getTimeout(sm, sm->eap_method_priv); - else - sm->methodTimeout = 0; -} - - -SM_STATE(EAP, METHOD_RESPONSE) -{ - SM_ENTRY(EAP, METHOD_RESPONSE); - - sm->m->process(sm, sm->eap_method_priv, sm->eap_if.eapRespData); - if (sm->m->isDone(sm, sm->eap_method_priv)) { - eap_sm_Policy_update(sm, NULL, 0); - os_free(sm->eap_if.eapKeyData); - if (sm->m->getKey) { - sm->eap_if.eapKeyData = sm->m->getKey( - sm, sm->eap_method_priv, - &sm->eap_if.eapKeyDataLen); - } else { - sm->eap_if.eapKeyData = NULL; - sm->eap_if.eapKeyDataLen = 0; - } - sm->methodState = METHOD_END; - } else { - sm->methodState = METHOD_CONTINUE; - } -} - - -SM_STATE(EAP, PROPOSE_METHOD) -{ - int vendor; - EapType type; - - SM_ENTRY(EAP, PROPOSE_METHOD); - - type = eap_sm_Policy_getNextMethod(sm, &vendor); - if (vendor == EAP_VENDOR_IETF) - sm->currentMethod = type; - else - sm->currentMethod = EAP_TYPE_EXPANDED; - if (sm->m && sm->eap_method_priv) { - sm->m->reset(sm, sm->eap_method_priv); - sm->eap_method_priv = NULL; - } - sm->m = eap_server_get_eap_method(vendor, type); - if (sm->m) { - sm->eap_method_priv = sm->m->init(sm); - if (sm->eap_method_priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP: Failed to initialize EAP " - "method %d", sm->currentMethod); - sm->m = NULL; - sm->currentMethod = EAP_TYPE_NONE; - } - } - if (sm->currentMethod == EAP_TYPE_IDENTITY || - sm->currentMethod == EAP_TYPE_NOTIFICATION) - sm->methodState = METHOD_CONTINUE; - else - sm->methodState = METHOD_PROPOSED; -} - - -SM_STATE(EAP, NAK) -{ - const struct eap_hdr *nak; - size_t len = 0; - const u8 *pos; - const u8 *nak_list = NULL; - - SM_ENTRY(EAP, NAK); - - if (sm->eap_method_priv) { - sm->m->reset(sm, sm->eap_method_priv); - sm->eap_method_priv = NULL; - } - sm->m = NULL; - - nak = wpabuf_head(sm->eap_if.eapRespData); - if (nak && wpabuf_len(sm->eap_if.eapRespData) > sizeof(*nak)) { - len = be_to_host16(nak->length); - if (len > wpabuf_len(sm->eap_if.eapRespData)) - len = wpabuf_len(sm->eap_if.eapRespData); - pos = (const u8 *) (nak + 1); - len -= sizeof(*nak); - if (*pos == EAP_TYPE_NAK) { - pos++; - len--; - nak_list = pos; - } - } - eap_sm_Policy_update(sm, nak_list, len); -} - - -SM_STATE(EAP, SELECT_ACTION) -{ - SM_ENTRY(EAP, SELECT_ACTION); - - sm->decision = eap_sm_Policy_getDecision(sm); -} - - -SM_STATE(EAP, TIMEOUT_FAILURE) -{ - SM_ENTRY(EAP, TIMEOUT_FAILURE); - - sm->eap_if.eapTimeout = TRUE; -} - - -SM_STATE(EAP, FAILURE) -{ - SM_ENTRY(EAP, FAILURE); - - wpabuf_free(sm->eap_if.eapReqData); - sm->eap_if.eapReqData = eap_sm_buildFailure(sm, sm->currentId); - wpabuf_free(sm->lastReqData); - sm->lastReqData = NULL; - sm->eap_if.eapFail = TRUE; -} - - -SM_STATE(EAP, SUCCESS) -{ - SM_ENTRY(EAP, SUCCESS); - - wpabuf_free(sm->eap_if.eapReqData); - sm->eap_if.eapReqData = eap_sm_buildSuccess(sm, sm->currentId); - wpabuf_free(sm->lastReqData); - sm->lastReqData = NULL; - if (sm->eap_if.eapKeyData) - sm->eap_if.eapKeyAvailable = TRUE; - sm->eap_if.eapSuccess = TRUE; -} - - -SM_STATE(EAP, INITIALIZE_PASSTHROUGH) -{ - SM_ENTRY(EAP, INITIALIZE_PASSTHROUGH); - - wpabuf_free(sm->eap_if.aaaEapRespData); - sm->eap_if.aaaEapRespData = NULL; -} - - -SM_STATE(EAP, IDLE2) -{ - SM_ENTRY(EAP, IDLE2); - - sm->eap_if.retransWhile = eap_sm_calculateTimeout( - sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR, - sm->methodTimeout); -} - - -SM_STATE(EAP, RETRANSMIT2) -{ - SM_ENTRY(EAP, RETRANSMIT2); - - sm->retransCount++; - if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) { - if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0) - sm->eap_if.eapReq = TRUE; - } -} - - -SM_STATE(EAP, RECEIVED2) -{ - SM_ENTRY(EAP, RECEIVED2); - - /* parse rxResp, respId, respMethod */ - eap_sm_parseEapResp(sm, sm->eap_if.eapRespData); -} - - -SM_STATE(EAP, DISCARD2) -{ - SM_ENTRY(EAP, DISCARD2); - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapNoReq = TRUE; -} - - -SM_STATE(EAP, SEND_REQUEST2) -{ - SM_ENTRY(EAP, SEND_REQUEST2); - - sm->retransCount = 0; - if (sm->eap_if.eapReqData) { - if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0) - { - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = TRUE; - } else { - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = FALSE; - } - } else { - wpa_printf(MSG_INFO, "EAP: SEND_REQUEST2 - no eapReqData"); - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = FALSE; - sm->eap_if.eapNoReq = TRUE; - } -} - - -SM_STATE(EAP, AAA_REQUEST) -{ - SM_ENTRY(EAP, AAA_REQUEST); - - if (sm->eap_if.eapRespData == NULL) { - wpa_printf(MSG_INFO, "EAP: AAA_REQUEST - no eapRespData"); - return; - } - - /* - * if (respMethod == IDENTITY) - * aaaIdentity = eapRespData - * This is already taken care of by the EAP-Identity method which - * stores the identity into sm->identity. - */ - - eap_copy_buf(&sm->eap_if.aaaEapRespData, sm->eap_if.eapRespData); -} - - -SM_STATE(EAP, AAA_RESPONSE) -{ - SM_ENTRY(EAP, AAA_RESPONSE); - - eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData); - sm->currentId = eap_sm_getId(sm->eap_if.eapReqData); - sm->methodTimeout = sm->eap_if.aaaMethodTimeout; -} - - -SM_STATE(EAP, AAA_IDLE) -{ - SM_ENTRY(EAP, AAA_IDLE); - - sm->eap_if.aaaFail = FALSE; - sm->eap_if.aaaSuccess = FALSE; - sm->eap_if.aaaEapReq = FALSE; - sm->eap_if.aaaEapNoReq = FALSE; - sm->eap_if.aaaEapResp = TRUE; -} - - -SM_STATE(EAP, TIMEOUT_FAILURE2) -{ - SM_ENTRY(EAP, TIMEOUT_FAILURE2); - - sm->eap_if.eapTimeout = TRUE; -} - - -SM_STATE(EAP, FAILURE2) -{ - SM_ENTRY(EAP, FAILURE2); - - eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData); - sm->eap_if.eapFail = TRUE; -} - - -SM_STATE(EAP, SUCCESS2) -{ - SM_ENTRY(EAP, SUCCESS2); - - eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData); - - sm->eap_if.eapKeyAvailable = sm->eap_if.aaaEapKeyAvailable; - if (sm->eap_if.aaaEapKeyAvailable) { - EAP_COPY(&sm->eap_if.eapKeyData, sm->eap_if.aaaEapKeyData); - } else { - os_free(sm->eap_if.eapKeyData); - sm->eap_if.eapKeyData = NULL; - sm->eap_if.eapKeyDataLen = 0; - } - - sm->eap_if.eapSuccess = TRUE; - - /* - * Start reauthentication with identity request even though we know the - * previously used identity. This is needed to get reauthentication - * started properly. - */ - sm->start_reauth = TRUE; -} - - -SM_STEP(EAP) -{ - if (sm->eap_if.eapRestart && sm->eap_if.portEnabled) - SM_ENTER_GLOBAL(EAP, INITIALIZE); - else if (!sm->eap_if.portEnabled) - SM_ENTER_GLOBAL(EAP, DISABLED); - else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) { - if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) { - wpa_printf(MSG_DEBUG, "EAP: more than %d " - "authentication rounds - abort", - EAP_MAX_AUTH_ROUNDS); - sm->num_rounds++; - SM_ENTER_GLOBAL(EAP, FAILURE); - } - } else switch (sm->EAP_state) { - case EAP_INITIALIZE: - if (sm->backend_auth) { - if (!sm->rxResp) - SM_ENTER(EAP, SELECT_ACTION); - else if (sm->rxResp && - (sm->respMethod == EAP_TYPE_NAK || - (sm->respMethod == EAP_TYPE_EXPANDED && - sm->respVendor == EAP_VENDOR_IETF && - sm->respVendorMethod == EAP_TYPE_NAK))) - SM_ENTER(EAP, NAK); - else - SM_ENTER(EAP, PICK_UP_METHOD); - } else { - SM_ENTER(EAP, SELECT_ACTION); - } - break; - case EAP_PICK_UP_METHOD: - if (sm->currentMethod == EAP_TYPE_NONE) { - SM_ENTER(EAP, SELECT_ACTION); - } else { - SM_ENTER(EAP, METHOD_RESPONSE); - } - break; - case EAP_DISABLED: - if (sm->eap_if.portEnabled) - SM_ENTER(EAP, INITIALIZE); - break; - case EAP_IDLE: - if (sm->eap_if.retransWhile == 0) - SM_ENTER(EAP, RETRANSMIT); - else if (sm->eap_if.eapResp) - SM_ENTER(EAP, RECEIVED); - break; - case EAP_RETRANSMIT: - if (sm->retransCount > sm->MaxRetrans) - SM_ENTER(EAP, TIMEOUT_FAILURE); - else - SM_ENTER(EAP, IDLE); - break; - case EAP_RECEIVED: - if (sm->rxResp && (sm->respId == sm->currentId) && - (sm->respMethod == EAP_TYPE_NAK || - (sm->respMethod == EAP_TYPE_EXPANDED && - sm->respVendor == EAP_VENDOR_IETF && - sm->respVendorMethod == EAP_TYPE_NAK)) - && (sm->methodState == METHOD_PROPOSED)) - SM_ENTER(EAP, NAK); - else if (sm->rxResp && (sm->respId == sm->currentId) && - ((sm->respMethod == sm->currentMethod) || - (sm->respMethod == EAP_TYPE_EXPANDED && - sm->respVendor == EAP_VENDOR_IETF && - sm->respVendorMethod == sm->currentMethod))) - SM_ENTER(EAP, INTEGRITY_CHECK); - else { - wpa_printf(MSG_DEBUG, "EAP: RECEIVED->DISCARD: " - "rxResp=%d respId=%d currentId=%d " - "respMethod=%d currentMethod=%d", - sm->rxResp, sm->respId, sm->currentId, - sm->respMethod, sm->currentMethod); - SM_ENTER(EAP, DISCARD); - } - break; - case EAP_DISCARD: - SM_ENTER(EAP, IDLE); - break; - case EAP_SEND_REQUEST: - SM_ENTER(EAP, IDLE); - break; - case EAP_INTEGRITY_CHECK: - if (sm->ignore) - SM_ENTER(EAP, DISCARD); - else - SM_ENTER(EAP, METHOD_RESPONSE); - break; - case EAP_METHOD_REQUEST: - SM_ENTER(EAP, SEND_REQUEST); - break; - case EAP_METHOD_RESPONSE: - /* - * Note: Mechanism to allow EAP methods to wait while going - * through pending processing is an extension to RFC 4137 - * which only defines the transits to SELECT_ACTION and - * METHOD_REQUEST from this METHOD_RESPONSE state. - */ - if (sm->methodState == METHOD_END) - SM_ENTER(EAP, SELECT_ACTION); - else if (sm->method_pending == METHOD_PENDING_WAIT) { - wpa_printf(MSG_DEBUG, "EAP: Method has pending " - "processing - wait before proceeding to " - "METHOD_REQUEST state"); - } else if (sm->method_pending == METHOD_PENDING_CONT) { - wpa_printf(MSG_DEBUG, "EAP: Method has completed " - "pending processing - reprocess pending " - "EAP message"); - sm->method_pending = METHOD_PENDING_NONE; - SM_ENTER(EAP, METHOD_RESPONSE); - } else - SM_ENTER(EAP, METHOD_REQUEST); - break; - case EAP_PROPOSE_METHOD: - /* - * Note: Mechanism to allow EAP methods to wait while going - * through pending processing is an extension to RFC 4137 - * which only defines the transit to METHOD_REQUEST from this - * PROPOSE_METHOD state. - */ - if (sm->method_pending == METHOD_PENDING_WAIT) { - wpa_printf(MSG_DEBUG, "EAP: Method has pending " - "processing - wait before proceeding to " - "METHOD_REQUEST state"); - if (sm->user_eap_method_index > 0) - sm->user_eap_method_index--; - } else if (sm->method_pending == METHOD_PENDING_CONT) { - wpa_printf(MSG_DEBUG, "EAP: Method has completed " - "pending processing - reprocess pending " - "EAP message"); - sm->method_pending = METHOD_PENDING_NONE; - SM_ENTER(EAP, PROPOSE_METHOD); - } else - SM_ENTER(EAP, METHOD_REQUEST); - break; - case EAP_NAK: - SM_ENTER(EAP, SELECT_ACTION); - break; - case EAP_SELECT_ACTION: - if (sm->decision == DECISION_FAILURE) - SM_ENTER(EAP, FAILURE); - else if (sm->decision == DECISION_SUCCESS) - SM_ENTER(EAP, SUCCESS); - else if (sm->decision == DECISION_PASSTHROUGH) - SM_ENTER(EAP, INITIALIZE_PASSTHROUGH); - else - SM_ENTER(EAP, PROPOSE_METHOD); - break; - case EAP_TIMEOUT_FAILURE: - break; - case EAP_FAILURE: - break; - case EAP_SUCCESS: - break; - - case EAP_INITIALIZE_PASSTHROUGH: - if (sm->currentId == -1) - SM_ENTER(EAP, AAA_IDLE); - else - SM_ENTER(EAP, AAA_REQUEST); - break; - case EAP_IDLE2: - if (sm->eap_if.eapResp) - SM_ENTER(EAP, RECEIVED2); - else if (sm->eap_if.retransWhile == 0) - SM_ENTER(EAP, RETRANSMIT2); - break; - case EAP_RETRANSMIT2: - if (sm->retransCount > sm->MaxRetrans) - SM_ENTER(EAP, TIMEOUT_FAILURE2); - else - SM_ENTER(EAP, IDLE2); - break; - case EAP_RECEIVED2: - if (sm->rxResp && (sm->respId == sm->currentId)) - SM_ENTER(EAP, AAA_REQUEST); - else - SM_ENTER(EAP, DISCARD2); - break; - case EAP_DISCARD2: - SM_ENTER(EAP, IDLE2); - break; - case EAP_SEND_REQUEST2: - SM_ENTER(EAP, IDLE2); - break; - case EAP_AAA_REQUEST: - SM_ENTER(EAP, AAA_IDLE); - break; - case EAP_AAA_RESPONSE: - SM_ENTER(EAP, SEND_REQUEST2); - break; - case EAP_AAA_IDLE: - if (sm->eap_if.aaaFail) - SM_ENTER(EAP, FAILURE2); - else if (sm->eap_if.aaaSuccess) - SM_ENTER(EAP, SUCCESS2); - else if (sm->eap_if.aaaEapReq) - SM_ENTER(EAP, AAA_RESPONSE); - else if (sm->eap_if.aaaTimeout) - SM_ENTER(EAP, TIMEOUT_FAILURE2); - break; - case EAP_TIMEOUT_FAILURE2: - break; - case EAP_FAILURE2: - break; - case EAP_SUCCESS2: - break; - } -} - - -static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount, - int eapSRTT, int eapRTTVAR, - int methodTimeout) -{ - int rto, i; - - if (methodTimeout) { - /* - * EAP method (either internal or through AAA server, provided - * timeout hint. Use that as-is as a timeout for retransmitting - * the EAP request if no response is received. - */ - wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds " - "(from EAP method hint)", methodTimeout); - return methodTimeout; - } - - /* - * RFC 3748 recommends algorithms described in RFC 2988 for estimation - * of the retransmission timeout. This should be implemented once - * round-trip time measurements are available. For nowm a simple - * backoff mechanism is used instead if there are no EAP method - * specific hints. - * - * SRTT = smoothed round-trip time - * RTTVAR = round-trip time variation - * RTO = retransmission timeout - */ - - /* - * RFC 2988, 2.1: before RTT measurement, set RTO to 3 seconds for - * initial retransmission and then double the RTO to provide back off - * per 5.5. Limit the maximum RTO to 20 seconds per RFC 3748, 4.3 - * modified RTOmax. - */ - rto = 3; - for (i = 0; i < retransCount; i++) { - rto *= 2; - if (rto >= 20) { - rto = 20; - break; - } - } - - wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds " - "(from dynamic back off; retransCount=%d)", - rto, retransCount); - - return rto; -} - - -static void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp) -{ - const struct eap_hdr *hdr; - size_t plen; - - /* parse rxResp, respId, respMethod */ - sm->rxResp = FALSE; - sm->respId = -1; - sm->respMethod = EAP_TYPE_NONE; - sm->respVendor = EAP_VENDOR_IETF; - sm->respVendorMethod = EAP_TYPE_NONE; - - if (resp == NULL || wpabuf_len(resp) < sizeof(*hdr)) { - wpa_printf(MSG_DEBUG, "EAP: parseEapResp: invalid resp=%p " - "len=%lu", resp, - resp ? (unsigned long) wpabuf_len(resp) : 0); - return; - } - - hdr = wpabuf_head(resp); - plen = be_to_host16(hdr->length); - if (plen > wpabuf_len(resp)) { - wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet " - "(len=%lu plen=%lu)", - (unsigned long) wpabuf_len(resp), - (unsigned long) plen); - return; - } - - sm->respId = hdr->identifier; - - if (hdr->code == EAP_CODE_RESPONSE) - sm->rxResp = TRUE; - - if (plen > sizeof(*hdr)) { - u8 *pos = (u8 *) (hdr + 1); - sm->respMethod = *pos++; - if (sm->respMethod == EAP_TYPE_EXPANDED) { - if (plen < sizeof(*hdr) + 8) { - wpa_printf(MSG_DEBUG, "EAP: Ignored truncated " - "expanded EAP-Packet (plen=%lu)", - (unsigned long) plen); - return; - } - sm->respVendor = WPA_GET_BE24(pos); - pos += 3; - sm->respVendorMethod = WPA_GET_BE32(pos); - } - } - - wpa_printf(MSG_DEBUG, "EAP: parseEapResp: rxResp=%d respId=%d " - "respMethod=%u respVendor=%u respVendorMethod=%u", - sm->rxResp, sm->respId, sm->respMethod, sm->respVendor, - sm->respVendorMethod); -} - - -static int eap_sm_getId(const struct wpabuf *data) -{ - const struct eap_hdr *hdr; - - if (data == NULL || wpabuf_len(data) < sizeof(*hdr)) - return -1; - - hdr = wpabuf_head(data); - wpa_printf(MSG_DEBUG, "EAP: getId: id=%d", hdr->identifier); - return hdr->identifier; -} - - -static struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id) -{ - struct wpabuf *msg; - struct eap_hdr *resp; - wpa_printf(MSG_DEBUG, "EAP: Building EAP-Success (id=%d)", id); - - msg = wpabuf_alloc(sizeof(*resp)); - if (msg == NULL) - return NULL; - resp = wpabuf_put(msg, sizeof(*resp)); - resp->code = EAP_CODE_SUCCESS; - resp->identifier = id; - resp->length = host_to_be16(sizeof(*resp)); - - return msg; -} - - -static struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id) -{ - struct wpabuf *msg; - struct eap_hdr *resp; - wpa_printf(MSG_DEBUG, "EAP: Building EAP-Failure (id=%d)", id); - - msg = wpabuf_alloc(sizeof(*resp)); - if (msg == NULL) - return NULL; - resp = wpabuf_put(msg, sizeof(*resp)); - resp->code = EAP_CODE_FAILURE; - resp->identifier = id; - resp->length = host_to_be16(sizeof(*resp)); - - return msg; -} - - -static int eap_sm_nextId(struct eap_sm *sm, int id) -{ - if (id < 0) { - /* RFC 3748 Ch 4.1: recommended to initialize Identifier with a - * random number */ - id = rand() & 0xff; - if (id != sm->lastId) - return id; - } - return (id + 1) & 0xff; -} - - -/** - * eap_sm_process_nak - Process EAP-Response/Nak - * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() - * @nak_list: Nak list (allowed methods) from the supplicant - * @len: Length of nak_list in bytes - * - * This function is called when EAP-Response/Nak is received from the - * supplicant. This can happen for both phase 1 and phase 2 authentications. - */ -void eap_sm_process_nak(struct eap_sm *sm, const u8 *nak_list, size_t len) -{ - int i; - size_t j; - - if (sm->user == NULL) - return; - - wpa_printf(MSG_MSGDUMP, "EAP: processing NAK (current EAP method " - "index %d)", sm->user_eap_method_index); - - wpa_hexdump(MSG_MSGDUMP, "EAP: configured methods", - (u8 *) sm->user->methods, - EAP_MAX_METHODS * sizeof(sm->user->methods[0])); - wpa_hexdump(MSG_MSGDUMP, "EAP: list of methods supported by the peer", - nak_list, len); - - i = sm->user_eap_method_index; - while (i < EAP_MAX_METHODS && - (sm->user->methods[i].vendor != EAP_VENDOR_IETF || - sm->user->methods[i].method != EAP_TYPE_NONE)) { - if (sm->user->methods[i].vendor != EAP_VENDOR_IETF) - goto not_found; - for (j = 0; j < len; j++) { - if (nak_list[j] == sm->user->methods[i].method) { - break; - } - } - - if (j < len) { - /* found */ - i++; - continue; - } - - not_found: - /* not found - remove from the list */ - os_memmove(&sm->user->methods[i], &sm->user->methods[i + 1], - (EAP_MAX_METHODS - i - 1) * - sizeof(sm->user->methods[0])); - sm->user->methods[EAP_MAX_METHODS - 1].vendor = - EAP_VENDOR_IETF; - sm->user->methods[EAP_MAX_METHODS - 1].method = EAP_TYPE_NONE; - } - - wpa_hexdump(MSG_MSGDUMP, "EAP: new list of configured methods", - (u8 *) sm->user->methods, EAP_MAX_METHODS * - sizeof(sm->user->methods[0])); -} - - -static void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list, - size_t len) -{ - if (nak_list == NULL || sm == NULL || sm->user == NULL) - return; - - if (sm->user->phase2) { - wpa_printf(MSG_DEBUG, "EAP: EAP-Nak received after Phase2 user" - " info was selected - reject"); - sm->decision = DECISION_FAILURE; - return; - } - - eap_sm_process_nak(sm, nak_list, len); -} - - -static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor) -{ - EapType next; - int idx = sm->user_eap_method_index; - - /* In theory, there should be no problems with starting - * re-authentication with something else than EAP-Request/Identity and - * this does indeed work with wpa_supplicant. However, at least Funk - * Supplicant seemed to ignore re-auth if it skipped - * EAP-Request/Identity. - * Re-auth sets currentId == -1, so that can be used here to select - * whether Identity needs to be requested again. */ - if (sm->identity == NULL || sm->currentId == -1) { - *vendor = EAP_VENDOR_IETF; - next = EAP_TYPE_IDENTITY; - sm->update_user = TRUE; - } else if (sm->user && idx < EAP_MAX_METHODS && - (sm->user->methods[idx].vendor != EAP_VENDOR_IETF || - sm->user->methods[idx].method != EAP_TYPE_NONE)) { - *vendor = sm->user->methods[idx].vendor; - next = sm->user->methods[idx].method; - sm->user_eap_method_index++; - } else { - *vendor = EAP_VENDOR_IETF; - next = EAP_TYPE_NONE; - } - wpa_printf(MSG_DEBUG, "EAP: getNextMethod: vendor %d type %d", - *vendor, next); - return next; -} - - -static int eap_sm_Policy_getDecision(struct eap_sm *sm) -{ - if (!sm->eap_server && sm->identity && !sm->start_reauth) { - wpa_printf(MSG_DEBUG, "EAP: getDecision: -> PASSTHROUGH"); - return DECISION_PASSTHROUGH; - } - - if (sm->m && sm->currentMethod != EAP_TYPE_IDENTITY && - sm->m->isSuccess(sm, sm->eap_method_priv)) { - wpa_printf(MSG_DEBUG, "EAP: getDecision: method succeeded -> " - "SUCCESS"); - sm->update_user = TRUE; - return DECISION_SUCCESS; - } - - if (sm->m && sm->m->isDone(sm, sm->eap_method_priv) && - !sm->m->isSuccess(sm, sm->eap_method_priv)) { - wpa_printf(MSG_DEBUG, "EAP: getDecision: method failed -> " - "FAILURE"); - sm->update_user = TRUE; - return DECISION_FAILURE; - } - - if ((sm->user == NULL || sm->update_user) && sm->identity && - !sm->start_reauth) { - /* - * Allow Identity method to be started once to allow identity - * selection hint to be sent from the authentication server, - * but prevent a loop of Identity requests by only allowing - * this to happen once. - */ - int id_req = 0; - if (sm->user && sm->currentMethod == EAP_TYPE_IDENTITY && - sm->user->methods[0].vendor == EAP_VENDOR_IETF && - sm->user->methods[0].method == EAP_TYPE_IDENTITY) - id_req = 1; - if (eap_user_get(sm, sm->identity, sm->identity_len, 0) != 0) { - wpa_printf(MSG_DEBUG, "EAP: getDecision: user not " - "found from database -> FAILURE"); - return DECISION_FAILURE; - } - if (id_req && sm->user && - sm->user->methods[0].vendor == EAP_VENDOR_IETF && - sm->user->methods[0].method == EAP_TYPE_IDENTITY) { - wpa_printf(MSG_DEBUG, "EAP: getDecision: stop " - "identity request loop -> FAILURE"); - sm->update_user = TRUE; - return DECISION_FAILURE; - } - sm->update_user = FALSE; - } - sm->start_reauth = FALSE; - - if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && - (sm->user->methods[sm->user_eap_method_index].vendor != - EAP_VENDOR_IETF || - sm->user->methods[sm->user_eap_method_index].method != - EAP_TYPE_NONE)) { - wpa_printf(MSG_DEBUG, "EAP: getDecision: another method " - "available -> CONTINUE"); - return DECISION_CONTINUE; - } - - if (sm->identity == NULL || sm->currentId == -1) { - wpa_printf(MSG_DEBUG, "EAP: getDecision: no identity known " - "yet -> CONTINUE"); - return DECISION_CONTINUE; - } - - wpa_printf(MSG_DEBUG, "EAP: getDecision: no more methods available -> " - "FAILURE"); - return DECISION_FAILURE; -} - - -static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method) -{ - return method == EAP_TYPE_IDENTITY ? TRUE : FALSE; -} - - -/** - * eap_server_sm_step - Step EAP server state machine - * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() - * Returns: 1 if EAP state was changed or 0 if not - * - * This function advances EAP state machine to a new state to match with the - * current variables. This should be called whenever variables used by the EAP - * state machine have changed. - */ -int eap_server_sm_step(struct eap_sm *sm) -{ - int res = 0; - do { - sm->changed = FALSE; - SM_STEP_RUN(EAP); - if (sm->changed) - res = 1; - } while (sm->changed); - return res; -} - - -static void eap_user_free(struct eap_user *user) -{ - if (user == NULL) - return; - os_free(user->password); - user->password = NULL; - os_free(user); -} - - -/** - * eap_server_sm_init - Allocate and initialize EAP server state machine - * @eapol_ctx: Context data to be used with eapol_cb calls - * @eapol_cb: Pointer to EAPOL callback functions - * @conf: EAP configuration - * Returns: Pointer to the allocated EAP state machine or %NULL on failure - * - * This function allocates and initializes an EAP state machine. - */ -struct eap_sm * eap_server_sm_init(void *eapol_ctx, - struct eapol_callbacks *eapol_cb, - struct eap_config *conf) -{ - struct eap_sm *sm; - - sm = os_zalloc(sizeof(*sm)); - if (sm == NULL) - return NULL; - sm->eapol_ctx = eapol_ctx; - sm->eapol_cb = eapol_cb; - sm->MaxRetrans = 5; /* RFC 3748: max 3-5 retransmissions suggested */ - sm->ssl_ctx = conf->ssl_ctx; - sm->eap_sim_db_priv = conf->eap_sim_db_priv; - sm->backend_auth = conf->backend_auth; - sm->eap_server = conf->eap_server; - if (conf->pac_opaque_encr_key) { - sm->pac_opaque_encr_key = os_malloc(16); - if (sm->pac_opaque_encr_key) { - os_memcpy(sm->pac_opaque_encr_key, - conf->pac_opaque_encr_key, 16); - } - } - if (conf->eap_fast_a_id) { - sm->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len); - if (sm->eap_fast_a_id) { - os_memcpy(sm->eap_fast_a_id, conf->eap_fast_a_id, - conf->eap_fast_a_id_len); - sm->eap_fast_a_id_len = conf->eap_fast_a_id_len; - } - } - if (conf->eap_fast_a_id_info) - sm->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info); - sm->eap_fast_prov = conf->eap_fast_prov; - sm->pac_key_lifetime = conf->pac_key_lifetime; - sm->pac_key_refresh_time = conf->pac_key_refresh_time; - sm->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind; - sm->tnc = conf->tnc; - sm->wps = conf->wps; - if (conf->assoc_wps_ie) - sm->assoc_wps_ie = wpabuf_dup(conf->assoc_wps_ie); - - wpa_printf(MSG_DEBUG, "EAP: Server state machine created"); - - return sm; -} - - -/** - * eap_server_sm_deinit - Deinitialize and free an EAP server state machine - * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() - * - * This function deinitializes EAP state machine and frees all allocated - * resources. - */ -void eap_server_sm_deinit(struct eap_sm *sm) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAP: Server state machine removed"); - if (sm->m && sm->eap_method_priv) - sm->m->reset(sm, sm->eap_method_priv); - wpabuf_free(sm->eap_if.eapReqData); - os_free(sm->eap_if.eapKeyData); - wpabuf_free(sm->lastReqData); - wpabuf_free(sm->eap_if.eapRespData); - os_free(sm->identity); - os_free(sm->pac_opaque_encr_key); - os_free(sm->eap_fast_a_id); - os_free(sm->eap_fast_a_id_info); - wpabuf_free(sm->eap_if.aaaEapReqData); - wpabuf_free(sm->eap_if.aaaEapRespData); - os_free(sm->eap_if.aaaEapKeyData); - eap_user_free(sm->user); - wpabuf_free(sm->assoc_wps_ie); - os_free(sm); -} - - -/** - * eap_sm_notify_cached - Notify EAP state machine of cached PMK - * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() - * - * This function is called when PMKSA caching is used to skip EAP - * authentication. - */ -void eap_sm_notify_cached(struct eap_sm *sm) -{ - if (sm == NULL) - return; - - sm->EAP_state = EAP_SUCCESS; -} - - -/** - * eap_sm_pending_cb - EAP state machine callback for a pending EAP request - * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() - * - * This function is called when data for a pending EAP-Request is received. - */ -void eap_sm_pending_cb(struct eap_sm *sm) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAP: Callback for pending request received"); - if (sm->method_pending == METHOD_PENDING_WAIT) - sm->method_pending = METHOD_PENDING_CONT; -} - - -/** - * eap_sm_method_pending - Query whether EAP method is waiting for pending data - * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() - * Returns: 1 if method is waiting for pending data or 0 if not - */ -int eap_sm_method_pending(struct eap_sm *sm) -{ - if (sm == NULL) - return 0; - return sm->method_pending == METHOD_PENDING_WAIT; -} - - -/** - * eap_get_identity - Get the user identity (from EAP-Response/Identity) - * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() - * @len: Buffer for returning identity length - * Returns: Pointer to the user identity or %NULL if not available - */ -const u8 * eap_get_identity(struct eap_sm *sm, size_t *len) -{ - *len = sm->identity_len; - return sm->identity; -} - - -/** - * eap_get_interface - Get pointer to EAP-EAPOL interface data - * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() - * Returns: Pointer to the EAP-EAPOL interface data - */ -struct eap_eapol_interface * eap_get_interface(struct eap_sm *sm) -{ - return &sm->eap_if; -} diff --git a/contrib/hostapd/src/eap_server/eap.h b/contrib/hostapd/src/eap_server/eap.h deleted file mode 100644 index 6a20da4f46..0000000000 --- a/contrib/hostapd/src/eap_server/eap.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * hostapd / EAP Full Authenticator state machine (RFC 4137) - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_H -#define EAP_H - -#include "defs.h" -#include "eap_common/eap_defs.h" -#include "eap_server/eap_methods.h" -#include "wpabuf.h" - -struct eap_sm; - -#define EAP_MAX_METHODS 8 - -#define EAP_TTLS_AUTH_PAP 1 -#define EAP_TTLS_AUTH_CHAP 2 -#define EAP_TTLS_AUTH_MSCHAP 4 -#define EAP_TTLS_AUTH_MSCHAPV2 8 - -struct eap_user { - struct { - int vendor; - u32 method; - } methods[EAP_MAX_METHODS]; - u8 *password; - size_t password_len; - int password_hash; /* whether password is hashed with - * nt_password_hash() */ - int phase2; - int force_version; - int ttls_auth; /* bitfield of - * EAP_TTLS_AUTH_{PAP,CHAP,MSCHAP,MSCHAPV2} */ -}; - -struct eap_eapol_interface { - /* Lower layer to full authenticator variables */ - Boolean eapResp; /* shared with EAPOL Backend Authentication */ - struct wpabuf *eapRespData; - Boolean portEnabled; - int retransWhile; - Boolean eapRestart; /* shared with EAPOL Authenticator PAE */ - int eapSRTT; - int eapRTTVAR; - - /* Full authenticator to lower layer variables */ - Boolean eapReq; /* shared with EAPOL Backend Authentication */ - Boolean eapNoReq; /* shared with EAPOL Backend Authentication */ - Boolean eapSuccess; - Boolean eapFail; - Boolean eapTimeout; - struct wpabuf *eapReqData; - u8 *eapKeyData; - size_t eapKeyDataLen; - Boolean eapKeyAvailable; /* called keyAvailable in IEEE 802.1X-2004 */ - - /* AAA interface to full authenticator variables */ - Boolean aaaEapReq; - Boolean aaaEapNoReq; - Boolean aaaSuccess; - Boolean aaaFail; - struct wpabuf *aaaEapReqData; - u8 *aaaEapKeyData; - size_t aaaEapKeyDataLen; - Boolean aaaEapKeyAvailable; - int aaaMethodTimeout; - - /* Full authenticator to AAA interface variables */ - Boolean aaaEapResp; - struct wpabuf *aaaEapRespData; - /* aaaIdentity -> eap_get_identity() */ - Boolean aaaTimeout; -}; - -struct eapol_callbacks { - int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len, - int phase2, struct eap_user *user); - const char * (*get_eap_req_id_text)(void *ctx, size_t *len); -}; - -struct eap_config { - void *ssl_ctx; - void *eap_sim_db_priv; - Boolean backend_auth; - int eap_server; - u8 *pac_opaque_encr_key; - u8 *eap_fast_a_id; - size_t eap_fast_a_id_len; - char *eap_fast_a_id_info; - int eap_fast_prov; - int pac_key_lifetime; - int pac_key_refresh_time; - int eap_sim_aka_result_ind; - int tnc; - struct wps_context *wps; - const struct wpabuf *assoc_wps_ie; -}; - - -struct eap_sm * eap_server_sm_init(void *eapol_ctx, - struct eapol_callbacks *eapol_cb, - struct eap_config *eap_conf); -void eap_server_sm_deinit(struct eap_sm *sm); -int eap_server_sm_step(struct eap_sm *sm); -void eap_sm_notify_cached(struct eap_sm *sm); -void eap_sm_pending_cb(struct eap_sm *sm); -int eap_sm_method_pending(struct eap_sm *sm); -const u8 * eap_get_identity(struct eap_sm *sm, size_t *len); -struct eap_eapol_interface * eap_get_interface(struct eap_sm *sm); - -#endif /* EAP_H */ diff --git a/contrib/hostapd/src/eap_server/eap_aka.c b/contrib/hostapd/src/eap_server/eap_aka.c deleted file mode 100644 index aad52fd649..0000000000 --- a/contrib/hostapd/src/eap_server/eap_aka.c +++ /dev/null @@ -1,1278 +0,0 @@ -/* - * hostapd / EAP-AKA (RFC 4187) and EAP-AKA' (draft-arkko-eap-aka-kdf) - * Copyright (c) 2005-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_server/eap_i.h" -#include "eap_common/eap_sim_common.h" -#include "eap_server/eap_sim_db.h" -#include "sha1.h" -#include "sha256.h" -#include "crypto.h" - - -struct eap_aka_data { - u8 mk[EAP_SIM_MK_LEN]; - u8 nonce_s[EAP_SIM_NONCE_S_LEN]; - u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN]; - u8 k_encr[EAP_SIM_K_ENCR_LEN]; - u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */ - u8 msk[EAP_SIM_KEYING_DATA_LEN]; - u8 emsk[EAP_EMSK_LEN]; - u8 rand[EAP_AKA_RAND_LEN]; - u8 autn[EAP_AKA_AUTN_LEN]; - u8 ck[EAP_AKA_CK_LEN]; - u8 ik[EAP_AKA_IK_LEN]; - u8 res[EAP_AKA_RES_MAX_LEN]; - size_t res_len; - enum { - IDENTITY, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE - } state; - char *next_pseudonym; - char *next_reauth_id; - u16 counter; - struct eap_sim_reauth *reauth; - int auts_reported; /* whether the current AUTS has been reported to the - * eap_sim_db */ - u16 notification; - int use_result_ind; - - struct wpabuf *id_msgs; - int pending_id; - u8 eap_method; - u8 *network_name; - size_t network_name_len; - u16 kdf; -}; - - -static void eap_aka_determine_identity(struct eap_sm *sm, - struct eap_aka_data *data, - int before_identity, int after_reauth); - - -static const char * eap_aka_state_txt(int state) -{ - switch (state) { - case IDENTITY: - return "IDENTITY"; - case CHALLENGE: - return "CHALLENGE"; - case REAUTH: - return "REAUTH"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - case NOTIFICATION: - return "NOTIFICATION"; - default: - return "Unknown?!"; - } -} - - -static void eap_aka_state(struct eap_aka_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s", - eap_aka_state_txt(data->state), - eap_aka_state_txt(state)); - data->state = state; -} - - -static void * eap_aka_init(struct eap_sm *sm) -{ - struct eap_aka_data *data; - - if (sm->eap_sim_db_priv == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - data->eap_method = EAP_TYPE_AKA; - - data->state = IDENTITY; - eap_aka_determine_identity(sm, data, 1, 0); - data->pending_id = -1; - - return data; -} - - -#ifdef EAP_AKA_PRIME -static void * eap_aka_prime_init(struct eap_sm *sm) -{ - struct eap_aka_data *data; - /* TODO: make ANID configurable; see 3GPP TS 24.302 */ - char *network_name = "WLAN"; - - if (sm->eap_sim_db_priv == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - data->eap_method = EAP_TYPE_AKA_PRIME; - data->network_name = os_malloc(os_strlen(network_name)); - if (data->network_name == NULL) { - os_free(data); - return NULL; - } - - data->network_name_len = os_strlen(network_name); - os_memcpy(data->network_name, network_name, data->network_name_len); - - data->state = IDENTITY; - eap_aka_determine_identity(sm, data, 1, 0); - data->pending_id = -1; - - return data; -} -#endif /* EAP_AKA_PRIME */ - - -static void eap_aka_reset(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - os_free(data->next_pseudonym); - os_free(data->next_reauth_id); - wpabuf_free(data->id_msgs); - os_free(data->network_name); - os_free(data); -} - - -static int eap_aka_add_id_msg(struct eap_aka_data *data, - const struct wpabuf *msg) -{ - if (msg == NULL) - return -1; - - if (data->id_msgs == NULL) { - data->id_msgs = wpabuf_dup(msg); - return data->id_msgs == NULL ? -1 : 0; - } - - if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0) - return -1; - wpabuf_put_buf(data->id_msgs, msg); - - return 0; -} - - -static void eap_aka_add_checkcode(struct eap_aka_data *data, - struct eap_sim_msg *msg) -{ - const u8 *addr; - size_t len; - u8 hash[SHA256_MAC_LEN]; - - wpa_printf(MSG_DEBUG, " AT_CHECKCODE"); - - if (data->id_msgs == NULL) { - /* - * No EAP-AKA/Identity packets were exchanged - send empty - * checkcode. - */ - eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0); - return; - } - - /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */ - addr = wpabuf_head(data->id_msgs); - len = wpabuf_len(data->id_msgs); - wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len); - if (data->eap_method == EAP_TYPE_AKA_PRIME) - sha256_vector(1, &addr, &len, hash); - else - sha1_vector(1, &addr, &len, hash); - - eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash, - data->eap_method == EAP_TYPE_AKA_PRIME ? - EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN); -} - - -static int eap_aka_verify_checkcode(struct eap_aka_data *data, - const u8 *checkcode, size_t checkcode_len) -{ - const u8 *addr; - size_t len; - u8 hash[SHA256_MAC_LEN]; - size_t hash_len; - - if (checkcode == NULL) - return -1; - - if (data->id_msgs == NULL) { - if (checkcode_len != 0) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer " - "indicates that AKA/Identity messages were " - "used, but they were not"); - return -1; - } - return 0; - } - - hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ? - EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN; - - if (checkcode_len != hash_len) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer indicates " - "that AKA/Identity message were not used, but they " - "were"); - return -1; - } - - /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */ - addr = wpabuf_head(data->id_msgs); - len = wpabuf_len(data->id_msgs); - if (data->eap_method == EAP_TYPE_AKA_PRIME) - sha256_vector(1, &addr, &len, hash); - else - sha1_vector(1, &addr, &len, hash); - - if (os_memcmp(hash, checkcode, hash_len) != 0) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE"); - return -1; - } - - return 0; -} - - -static struct wpabuf * eap_aka_build_identity(struct eap_sm *sm, - struct eap_aka_data *data, u8 id) -{ - struct eap_sim_msg *msg; - struct wpabuf *buf; - - wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Identity"); - msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, - EAP_AKA_SUBTYPE_IDENTITY); - if (eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity, - sm->identity_len)) { - wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); - eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); - } else { - /* - * RFC 4187, Chap. 4.1.4 recommends that identity from EAP is - * ignored and the AKA/Identity is used to request the - * identity. - */ - wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ"); - eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0); - } - buf = eap_sim_msg_finish(msg, NULL, NULL, 0); - if (eap_aka_add_id_msg(data, buf) < 0) { - wpabuf_free(buf); - return NULL; - } - data->pending_id = id; - return buf; -} - - -static int eap_aka_build_encr(struct eap_sm *sm, struct eap_aka_data *data, - struct eap_sim_msg *msg, u16 counter, - const u8 *nonce_s) -{ - os_free(data->next_pseudonym); - data->next_pseudonym = - eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 1); - os_free(data->next_reauth_id); - if (data->counter <= EAP_AKA_MAX_FAST_REAUTHS) { - data->next_reauth_id = - eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 1); - } else { - wpa_printf(MSG_DEBUG, "EAP-AKA: Max fast re-authentication " - "count exceeded - force full authentication"); - data->next_reauth_id = NULL; - } - - if (data->next_pseudonym == NULL && data->next_reauth_id == NULL && - counter == 0 && nonce_s == NULL) - return 0; - - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); - - if (counter > 0) { - wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); - } - - if (nonce_s) { - wpa_printf(MSG_DEBUG, " *AT_NONCE_S"); - eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s, - EAP_SIM_NONCE_S_LEN); - } - - if (data->next_pseudonym) { - wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)", - data->next_pseudonym); - eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM, - os_strlen(data->next_pseudonym), - (u8 *) data->next_pseudonym, - os_strlen(data->next_pseudonym)); - } - - if (data->next_reauth_id) { - wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)", - data->next_reauth_id); - eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID, - os_strlen(data->next_reauth_id), - (u8 *) data->next_reauth_id, - os_strlen(data->next_reauth_id)); - } - - if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt " - "AT_ENCR_DATA"); - return -1; - } - - return 0; -} - - -static struct wpabuf * eap_aka_build_challenge(struct eap_sm *sm, - struct eap_aka_data *data, - u8 id) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Challenge"); - msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, - EAP_AKA_SUBTYPE_CHALLENGE); - wpa_printf(MSG_DEBUG, " AT_RAND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, data->rand, EAP_AKA_RAND_LEN); - wpa_printf(MSG_DEBUG, " AT_AUTN"); - eap_sim_msg_add(msg, EAP_SIM_AT_AUTN, 0, data->autn, EAP_AKA_AUTN_LEN); - if (data->eap_method == EAP_TYPE_AKA_PRIME) { - if (data->kdf) { - /* Add the selected KDF into the beginning */ - wpa_printf(MSG_DEBUG, " AT_KDF"); - eap_sim_msg_add(msg, EAP_SIM_AT_KDF, data->kdf, - NULL, 0); - } - wpa_printf(MSG_DEBUG, " AT_KDF"); - eap_sim_msg_add(msg, EAP_SIM_AT_KDF, EAP_AKA_PRIME_KDF, - NULL, 0); - wpa_printf(MSG_DEBUG, " AT_KDF_INPUT"); - eap_sim_msg_add(msg, EAP_SIM_AT_KDF_INPUT, - data->network_name_len, - data->network_name, data->network_name_len); - } - - if (eap_aka_build_encr(sm, data, msg, 0, NULL)) { - eap_sim_msg_free(msg); - return NULL; - } - - eap_aka_add_checkcode(data, msg); - - if (sm->eap_sim_aka_result_ind) { - wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); - } - -#ifdef EAP_AKA_PRIME - if (data->eap_method == EAP_TYPE_AKA) { - u16 flags = 0; - int i; - int aka_prime_preferred = 0; - - i = 0; - while (sm->user && i < EAP_MAX_METHODS && - (sm->user->methods[i].vendor != EAP_VENDOR_IETF || - sm->user->methods[i].method != EAP_TYPE_NONE)) { - if (sm->user->methods[i].vendor == EAP_VENDOR_IETF) { - if (sm->user->methods[i].method == - EAP_TYPE_AKA) - break; - if (sm->user->methods[i].method == - EAP_TYPE_AKA_PRIME) { - aka_prime_preferred = 1; - break; - } - } - i++; - } - - if (aka_prime_preferred) - flags |= EAP_AKA_BIDDING_FLAG_D; - eap_sim_msg_add(msg, EAP_SIM_AT_BIDDING, flags, NULL, 0); - } -#endif /* EAP_AKA_PRIME */ - - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); -} - - -static struct wpabuf * eap_aka_build_reauth(struct eap_sm *sm, - struct eap_aka_data *data, u8 id) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Re-authentication"); - - if (os_get_random(data->nonce_s, EAP_SIM_NONCE_S_LEN)) - return NULL; - wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA: NONCE_S", - data->nonce_s, EAP_SIM_NONCE_S_LEN); - - if (data->eap_method == EAP_TYPE_AKA_PRIME) { - eap_aka_prime_derive_keys_reauth(data->k_re, data->counter, - sm->identity, - sm->identity_len, - data->nonce_s, - data->msk, data->emsk); - } else { - eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, - data->msk, data->emsk); - eap_sim_derive_keys_reauth(data->counter, sm->identity, - sm->identity_len, data->nonce_s, - data->mk, data->msk, data->emsk); - } - - msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, - EAP_AKA_SUBTYPE_REAUTHENTICATION); - - if (eap_aka_build_encr(sm, data, msg, data->counter, data->nonce_s)) { - eap_sim_msg_free(msg); - return NULL; - } - - eap_aka_add_checkcode(data, msg); - - if (sm->eap_sim_aka_result_ind) { - wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); - } - - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); -} - - -static struct wpabuf * eap_aka_build_notification(struct eap_sm *sm, - struct eap_aka_data *data, - u8 id) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Notification"); - msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, - EAP_AKA_SUBTYPE_NOTIFICATION); - wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification); - eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification, - NULL, 0); - if (data->use_result_ind) { - if (data->reauth) { - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, - EAP_SIM_AT_ENCR_DATA); - wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", - data->counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, - NULL, 0); - - if (eap_sim_msg_add_encr_end(msg, data->k_encr, - EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Failed to " - "encrypt AT_ENCR_DATA"); - eap_sim_msg_free(msg); - return NULL; - } - } - - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - } - return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); -} - - -static struct wpabuf * eap_aka_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_aka_data *data = priv; - - data->auts_reported = 0; - switch (data->state) { - case IDENTITY: - return eap_aka_build_identity(sm, data, id); - case CHALLENGE: - return eap_aka_build_challenge(sm, data, id); - case REAUTH: - return eap_aka_build_reauth(sm, data, id); - case NOTIFICATION: - return eap_aka_build_notification(sm, data, id); - default: - wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in " - "buildReq", data->state); - break; - } - return NULL; -} - - -static Boolean eap_aka_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_aka_data *data = priv; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData, - &len); - if (pos == NULL || len < 3) { - wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static Boolean eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype) -{ - if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR || - subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) - return FALSE; - - switch (data->state) { - case IDENTITY: - if (subtype != EAP_AKA_SUBTYPE_IDENTITY) { - wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " - "subtype %d", subtype); - return TRUE; - } - break; - case CHALLENGE: - if (subtype != EAP_AKA_SUBTYPE_CHALLENGE && - subtype != EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) { - wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " - "subtype %d", subtype); - return TRUE; - } - break; - case REAUTH: - if (subtype != EAP_AKA_SUBTYPE_REAUTHENTICATION) { - wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " - "subtype %d", subtype); - return TRUE; - } - break; - case NOTIFICATION: - if (subtype != EAP_AKA_SUBTYPE_NOTIFICATION) { - wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " - "subtype %d", subtype); - return TRUE; - } - break; - default: - wpa_printf(MSG_INFO, "EAP-AKA: Unexpected state (%d) for " - "processing a response", data->state); - return TRUE; - } - - return FALSE; -} - - -static void eap_aka_determine_identity(struct eap_sm *sm, - struct eap_aka_data *data, - int before_identity, int after_reauth) -{ - const u8 *identity; - size_t identity_len; - int res; - - identity = NULL; - identity_len = 0; - - if (after_reauth && data->reauth) { - identity = data->reauth->identity; - identity_len = data->reauth->identity_len; - } else if (sm->identity && sm->identity_len > 0 && - sm->identity[0] == EAP_AKA_PERMANENT_PREFIX) { - identity = sm->identity; - identity_len = sm->identity_len; - } else { - identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, - sm->identity, - sm->identity_len, - &identity_len); - if (identity == NULL) { - data->reauth = eap_sim_db_get_reauth_entry( - sm->eap_sim_db_priv, sm->identity, - sm->identity_len); - if (data->reauth && - data->reauth->aka_prime != - (data->eap_method == EAP_TYPE_AKA_PRIME)) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth data " - "was for different AKA version"); - data->reauth = NULL; - } - if (data->reauth) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast " - "re-authentication"); - identity = data->reauth->identity; - identity_len = data->reauth->identity_len; - data->counter = data->reauth->counter; - if (data->eap_method == EAP_TYPE_AKA_PRIME) { - os_memcpy(data->k_encr, - data->reauth->k_encr, - EAP_SIM_K_ENCR_LEN); - os_memcpy(data->k_aut, - data->reauth->k_aut, - EAP_AKA_PRIME_K_AUT_LEN); - os_memcpy(data->k_re, - data->reauth->k_re, - EAP_AKA_PRIME_K_RE_LEN); - } else { - os_memcpy(data->mk, data->reauth->mk, - EAP_SIM_MK_LEN); - } - } - } - } - - if (identity == NULL || - eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity, - sm->identity_len) < 0) { - if (before_identity) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Permanent user name " - "not known - send AKA-Identity request"); - eap_aka_state(data, IDENTITY); - return; - } else { - wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown whether the " - "permanent user name is known; try to use " - "it"); - /* eap_sim_db_get_aka_auth() will report failure, if - * this identity is not known. */ - } - } - - wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity", - identity, identity_len); - - if (!after_reauth && data->reauth) { - eap_aka_state(data, REAUTH); - return; - } - - res = eap_sim_db_get_aka_auth(sm->eap_sim_db_priv, identity, - identity_len, data->rand, data->autn, - data->ik, data->ck, data->res, - &data->res_len, sm); - if (res == EAP_SIM_DB_PENDING) { - wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data " - "not yet available - pending request"); - sm->method_pending = METHOD_PENDING_WAIT; - return; - } - -#ifdef EAP_AKA_PRIME - if (data->eap_method == EAP_TYPE_AKA_PRIME) { - /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the - * needed 6-octet SQN ^AK for CK',IK' derivation */ - eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik, - data->autn, - data->network_name, - data->network_name_len); - } -#endif /* EAP_AKA_PRIME */ - - data->reauth = NULL; - data->counter = 0; /* reset re-auth counter since this is full auth */ - - if (res != 0) { - wpa_printf(MSG_INFO, "EAP-AKA: Failed to get AKA " - "authentication data for the peer"); - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - if (sm->method_pending == METHOD_PENDING_WAIT) { - wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data " - "available - abort pending wait"); - sm->method_pending = METHOD_PENDING_NONE; - } - - identity_len = sm->identity_len; - while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') { - wpa_printf(MSG_DEBUG, "EAP-AKA: Workaround - drop last null " - "character from identity"); - identity_len--; - } - wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity for MK derivation", - sm->identity, identity_len); - - if (data->eap_method == EAP_TYPE_AKA_PRIME) { - eap_aka_prime_derive_keys(identity, identity_len, data->ik, - data->ck, data->k_encr, data->k_aut, - data->k_re, data->msk, data->emsk); - } else { - eap_aka_derive_mk(sm->identity, identity_len, data->ik, - data->ck, data->mk); - eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, - data->msk, data->emsk); - } - - eap_aka_state(data, CHALLENGE); -} - - -static void eap_aka_process_identity(struct eap_sm *sm, - struct eap_aka_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Identity"); - - if (attr->mac || attr->iv || attr->encr_data) { - wpa_printf(MSG_WARNING, "EAP-AKA: Unexpected attribute " - "received in EAP-Response/AKA-Identity"); - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - - if (attr->identity) { - os_free(sm->identity); - sm->identity = os_malloc(attr->identity_len); - if (sm->identity) { - os_memcpy(sm->identity, attr->identity, - attr->identity_len); - sm->identity_len = attr->identity_len; - } - } - - eap_aka_determine_identity(sm, data, 0, 0); - if (eap_get_id(respData) == data->pending_id) { - data->pending_id = -1; - eap_aka_add_id_msg(data, respData); - } -} - - -static int eap_aka_verify_mac(struct eap_aka_data *data, - const struct wpabuf *req, - const u8 *mac, const u8 *extra, - size_t extra_len) -{ - if (data->eap_method == EAP_TYPE_AKA_PRIME) - return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra, - extra_len); - return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len); -} - - -static void eap_aka_process_challenge(struct eap_sm *sm, - struct eap_aka_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - const u8 *identity; - size_t identity_len; - - wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Challenge"); - -#ifdef EAP_AKA_PRIME -#if 0 - /* KDF negotiation; to be enabled only after more than one KDF is - * supported */ - if (data->eap_method == EAP_TYPE_AKA_PRIME && - attr->kdf_count == 1 && attr->mac == NULL) { - if (attr->kdf[0] != EAP_AKA_PRIME_KDF) { - wpa_printf(MSG_WARNING, "EAP-AKA': Peer selected " - "unknown KDF"); - data->notification = - EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - - data->kdf = attr->kdf[0]; - - /* Allow negotiation to continue with the selected KDF by - * sending another Challenge message */ - wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf); - return; - } -#endif -#endif /* EAP_AKA_PRIME */ - - if (attr->checkcode && - eap_aka_verify_checkcode(data, attr->checkcode, - attr->checkcode_len)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the " - "message"); - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - if (attr->mac == NULL || - eap_aka_verify_mac(data, respData, attr->mac, NULL, 0)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " - "did not include valid AT_MAC"); - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - - /* - * AT_RES is padded, so verify that there is enough room for RES and - * that the RES length in bits matches with the expected RES. - */ - if (attr->res == NULL || attr->res_len < data->res_len || - attr->res_len_bits != data->res_len * 8 || - os_memcmp(attr->res, data->res, data->res_len) != 0) { - wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not " - "include valid AT_RES (attr len=%lu, res len=%lu " - "bits, expected %lu bits)", - (unsigned long) attr->res_len, - (unsigned long) attr->res_len_bits, - (unsigned long) data->res_len * 8); - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - - wpa_printf(MSG_DEBUG, "EAP-AKA: Challenge response includes the " - "correct AT_MAC"); - if (sm->eap_sim_aka_result_ind && attr->result_ind) { - data->use_result_ind = 1; - data->notification = EAP_SIM_SUCCESS; - eap_aka_state(data, NOTIFICATION); - } else - eap_aka_state(data, SUCCESS); - - identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, sm->identity, - sm->identity_len, &identity_len); - if (identity == NULL) { - identity = sm->identity; - identity_len = sm->identity_len; - } - - if (data->next_pseudonym) { - eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, - identity_len, - data->next_pseudonym); - data->next_pseudonym = NULL; - } - if (data->next_reauth_id) { - if (data->eap_method == EAP_TYPE_AKA_PRIME) { -#ifdef EAP_AKA_PRIME - eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv, - identity, - identity_len, - data->next_reauth_id, - data->counter + 1, - data->k_encr, data->k_aut, - data->k_re); -#endif /* EAP_AKA_PRIME */ - } else { - eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, - identity_len, - data->next_reauth_id, - data->counter + 1, - data->mk); - } - data->next_reauth_id = NULL; - } -} - - -static void eap_aka_process_sync_failure(struct eap_sm *sm, - struct eap_aka_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Synchronization-Failure"); - - if (attr->auts == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: Synchronization-Failure " - "message did not include valid AT_AUTS"); - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - - /* Avoid re-reporting AUTS when processing pending EAP packet by - * maintaining a local flag stating whether this AUTS has already been - * reported. */ - if (!data->auts_reported && - eap_sim_db_resynchronize(sm->eap_sim_db_priv, sm->identity, - sm->identity_len, attr->auts, - data->rand)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Resynchronization failed"); - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - data->auts_reported = 1; - - /* Try again after resynchronization */ - eap_aka_determine_identity(sm, data, 0, 0); -} - - -static void eap_aka_process_reauth(struct eap_sm *sm, - struct eap_aka_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - struct eap_sim_attrs eattr; - u8 *decrypted = NULL; - const u8 *identity, *id2; - size_t identity_len, id2_len; - - wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Reauthentication"); - - if (attr->mac == NULL || - eap_aka_verify_mac(data, respData, attr->mac, data->nonce_s, - EAP_SIM_NONCE_S_LEN)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message " - "did not include valid AT_MAC"); - goto fail; - } - - if (attr->encr_data == NULL || attr->iv == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " - "message did not include encrypted data"); - goto fail; - } - - decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, &eattr, - 0); - if (decrypted == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted " - "data from reauthentication message"); - goto fail; - } - - if (eattr.counter != data->counter) { - wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message " - "used incorrect counter %u, expected %u", - eattr.counter, data->counter); - goto fail; - } - os_free(decrypted); - decrypted = NULL; - - wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response includes " - "the correct AT_MAC"); - - if (eattr.counter_too_small) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response " - "included AT_COUNTER_TOO_SMALL - starting full " - "authentication"); - eap_aka_determine_identity(sm, data, 0, 1); - return; - } - - if (sm->eap_sim_aka_result_ind && attr->result_ind) { - data->use_result_ind = 1; - data->notification = EAP_SIM_SUCCESS; - eap_aka_state(data, NOTIFICATION); - } else - eap_aka_state(data, SUCCESS); - - if (data->reauth) { - identity = data->reauth->identity; - identity_len = data->reauth->identity_len; - } else { - identity = sm->identity; - identity_len = sm->identity_len; - } - - id2 = eap_sim_db_get_permanent(sm->eap_sim_db_priv, identity, - identity_len, &id2_len); - if (id2) { - identity = id2; - identity_len = id2_len; - } - - if (data->next_pseudonym) { - eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, - identity_len, data->next_pseudonym); - data->next_pseudonym = NULL; - } - if (data->next_reauth_id) { - if (data->eap_method == EAP_TYPE_AKA_PRIME) { -#ifdef EAP_AKA_PRIME - eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv, - identity, - identity_len, - data->next_reauth_id, - data->counter + 1, - data->k_encr, data->k_aut, - data->k_re); -#endif /* EAP_AKA_PRIME */ - } else { - eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, - identity_len, - data->next_reauth_id, - data->counter + 1, - data->mk); - } - data->next_reauth_id = NULL; - } else { - eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); - data->reauth = NULL; - } - - return; - -fail: - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); - data->reauth = NULL; - os_free(decrypted); -} - - -static void eap_aka_process_client_error(struct eap_sm *sm, - struct eap_aka_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: Client reported error %d", - attr->client_error_code); - if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) - eap_aka_state(data, SUCCESS); - else - eap_aka_state(data, FAILURE); -} - - -static void eap_aka_process_authentication_reject( - struct eap_sm *sm, struct eap_aka_data *data, - struct wpabuf *respData, struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: Client rejected authentication"); - eap_aka_state(data, FAILURE); -} - - -static void eap_aka_process_notification(struct eap_sm *sm, - struct eap_aka_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: Client replied to notification"); - if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) - eap_aka_state(data, SUCCESS); - else - eap_aka_state(data, FAILURE); -} - - -static void eap_aka_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_aka_data *data = priv; - const u8 *pos, *end; - u8 subtype; - size_t len; - struct eap_sim_attrs attr; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData, - &len); - if (pos == NULL || len < 3) - return; - - end = pos + len; - subtype = *pos; - pos += 3; - - if (eap_aka_subtype_ok(data, subtype)) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized or unexpected " - "EAP-AKA Subtype in EAP Response"); - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - - if (eap_sim_parse_attr(pos, end, &attr, - data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1, - 0)) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Failed to parse attributes"); - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - - if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR) { - eap_aka_process_client_error(sm, data, respData, &attr); - return; - } - - if (subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) { - eap_aka_process_authentication_reject(sm, data, respData, - &attr); - return; - } - - switch (data->state) { - case IDENTITY: - eap_aka_process_identity(sm, data, respData, &attr); - break; - case CHALLENGE: - if (subtype == EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) { - eap_aka_process_sync_failure(sm, data, respData, - &attr); - } else { - eap_aka_process_challenge(sm, data, respData, &attr); - } - break; - case REAUTH: - eap_aka_process_reauth(sm, data, respData, &attr); - break; - case NOTIFICATION: - eap_aka_process_notification(sm, data, respData, &attr); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in " - "process", data->state); - break; - } -} - - -static Boolean eap_aka_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_aka_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_SIM_KEYING_DATA_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); - *len = EAP_SIM_KEYING_DATA_LEN; - return key; -} - - -static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_aka_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - return key; -} - - -static Boolean eap_aka_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_aka_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA"); - if (eap == NULL) - return -1; - - eap->init = eap_aka_init; - eap->reset = eap_aka_reset; - eap->buildReq = eap_aka_buildReq; - eap->check = eap_aka_check; - eap->process = eap_aka_process; - eap->isDone = eap_aka_isDone; - eap->getKey = eap_aka_getKey; - eap->isSuccess = eap_aka_isSuccess; - eap->get_emsk = eap_aka_get_emsk; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} - - -#ifdef EAP_AKA_PRIME -int eap_server_aka_prime_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME, - "AKA'"); - if (eap == NULL) - return -1; - - eap->init = eap_aka_prime_init; - eap->reset = eap_aka_reset; - eap->buildReq = eap_aka_buildReq; - eap->check = eap_aka_check; - eap->process = eap_aka_process; - eap->isDone = eap_aka_isDone; - eap->getKey = eap_aka_getKey; - eap->isSuccess = eap_aka_isSuccess; - eap->get_emsk = eap_aka_get_emsk; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - - return ret; -} -#endif /* EAP_AKA_PRIME */ diff --git a/contrib/hostapd/src/eap_server/eap_fast.c b/contrib/hostapd/src/eap_server/eap_fast.c deleted file mode 100644 index c06f396ffd..0000000000 --- a/contrib/hostapd/src/eap_server/eap_fast.c +++ /dev/null @@ -1,1641 +0,0 @@ -/* - * EAP-FAST server (RFC 4851) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "aes_wrap.h" -#include "sha1.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "tls.h" -#include "eap_common/eap_tlv_common.h" -#include "eap_common/eap_fast_common.h" - - -static void eap_fast_reset(struct eap_sm *sm, void *priv); - - -/* Private PAC-Opaque TLV types */ -#define PAC_OPAQUE_TYPE_PAD 0 -#define PAC_OPAQUE_TYPE_KEY 1 -#define PAC_OPAQUE_TYPE_LIFETIME 2 -#define PAC_OPAQUE_TYPE_IDENTITY 3 - -struct eap_fast_data { - struct eap_ssl_data ssl; - enum { - START, PHASE1, PHASE2_START, PHASE2_ID, PHASE2_METHOD, - CRYPTO_BINDING, REQUEST_PAC, SUCCESS, FAILURE - } state; - - int fast_version; - const struct eap_method *phase2_method; - void *phase2_priv; - int force_version; - int peer_version; - - u8 crypto_binding_nonce[32]; - int final_result; - - struct eap_fast_key_block_provisioning *key_block_p; - - u8 simck[EAP_FAST_SIMCK_LEN]; - u8 cmk[EAP_FAST_CMK_LEN]; - int simck_idx; - - u8 pac_opaque_encr[16]; - u8 *srv_id; - size_t srv_id_len; - char *srv_id_info; - - int anon_provisioning; - int send_new_pac; /* server triggered re-keying of Tunnel PAC */ - struct wpabuf *pending_phase2_resp; - u8 *identity; /* from PAC-Opaque */ - size_t identity_len; - int eap_seq; - int tnc_started; - - int pac_key_lifetime; - int pac_key_refresh_time; -}; - - -static int eap_fast_process_phase2_start(struct eap_sm *sm, - struct eap_fast_data *data); - - -static const char * eap_fast_state_txt(int state) -{ - switch (state) { - case START: - return "START"; - case PHASE1: - return "PHASE1"; - case PHASE2_START: - return "PHASE2_START"; - case PHASE2_ID: - return "PHASE2_ID"; - case PHASE2_METHOD: - return "PHASE2_METHOD"; - case CRYPTO_BINDING: - return "CRYPTO_BINDING"; - case REQUEST_PAC: - return "REQUEST_PAC"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "Unknown?!"; - } -} - - -static void eap_fast_state(struct eap_fast_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-FAST: %s -> %s", - eap_fast_state_txt(data->state), - eap_fast_state_txt(state)); - data->state = state; -} - - -static EapType eap_fast_req_failure(struct eap_sm *sm, - struct eap_fast_data *data) -{ - /* TODO: send Result TLV(FAILURE) */ - eap_fast_state(data, FAILURE); - return EAP_TYPE_NONE; -} - - -static int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len, - const u8 *client_random, - const u8 *server_random, - u8 *master_secret) -{ - struct eap_fast_data *data = ctx; - const u8 *pac_opaque; - size_t pac_opaque_len; - u8 *buf, *pos, *end, *pac_key = NULL; - os_time_t lifetime = 0; - struct os_time now; - u8 *identity = NULL; - size_t identity_len = 0; - - wpa_printf(MSG_DEBUG, "EAP-FAST: SessionTicket callback"); - wpa_hexdump(MSG_DEBUG, "EAP-FAST: SessionTicket (PAC-Opaque)", - ticket, len); - - if (len < 4 || WPA_GET_BE16(ticket) != PAC_TYPE_PAC_OPAQUE) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Ignore invalid " - "SessionTicket"); - return 0; - } - - pac_opaque_len = WPA_GET_BE16(ticket + 2); - pac_opaque = ticket + 4; - if (pac_opaque_len < 8 || pac_opaque_len % 8 || - pac_opaque_len > len - 4) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Ignore invalid PAC-Opaque " - "(len=%lu left=%lu)", - (unsigned long) pac_opaque_len, - (unsigned long) len); - return 0; - } - wpa_hexdump(MSG_DEBUG, "EAP-FAST: Received PAC-Opaque", - pac_opaque, pac_opaque_len); - - buf = os_malloc(pac_opaque_len - 8); - if (buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to allocate memory " - "for decrypting PAC-Opaque"); - return 0; - } - - if (aes_unwrap(data->pac_opaque_encr, (pac_opaque_len - 8) / 8, - pac_opaque, buf) < 0) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to decrypt " - "PAC-Opaque"); - os_free(buf); - /* - * This may have been caused by server changing the PAC-Opaque - * encryption key, so just ignore this PAC-Opaque instead of - * failing the authentication completely. Provisioning can now - * be used to provision a new PAC. - */ - return 0; - } - - end = buf + pac_opaque_len - 8; - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Decrypted PAC-Opaque", - buf, end - buf); - - pos = buf; - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) - break; - - switch (*pos) { - case PAC_OPAQUE_TYPE_PAD: - pos = end; - break; - case PAC_OPAQUE_TYPE_KEY: - if (pos[1] != EAP_FAST_PAC_KEY_LEN) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid " - "PAC-Key length %d", pos[1]); - os_free(buf); - return -1; - } - pac_key = pos + 2; - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: PAC-Key from " - "decrypted PAC-Opaque", - pac_key, EAP_FAST_PAC_KEY_LEN); - break; - case PAC_OPAQUE_TYPE_LIFETIME: - if (pos[1] != 4) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid " - "PAC-Key lifetime length %d", - pos[1]); - os_free(buf); - return -1; - } - lifetime = WPA_GET_BE32(pos + 2); - break; - case PAC_OPAQUE_TYPE_IDENTITY: - identity = pos + 2; - identity_len = pos[1]; - break; - } - - pos += 2 + pos[1]; - } - - if (pac_key == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC-Key included in " - "PAC-Opaque"); - os_free(buf); - return -1; - } - - if (identity) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: Identity from " - "PAC-Opaque", identity, identity_len); - os_free(data->identity); - data->identity = os_malloc(identity_len); - if (data->identity) { - os_memcpy(data->identity, identity, identity_len); - data->identity_len = identity_len; - } - } - - if (os_get_time(&now) < 0 || lifetime <= 0 || now.sec > lifetime) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Key not valid anymore " - "(lifetime=%ld now=%ld)", lifetime, now.sec); - data->send_new_pac = 2; - /* - * Allow PAC to be used to allow a PAC update with some level - * of server authentication (i.e., do not fall back to full TLS - * handshake since we cannot be sure that the peer would be - * able to validate server certificate now). However, reject - * the authentication since the PAC was not valid anymore. Peer - * can connect again with the newly provisioned PAC after this. - */ - } else if (lifetime - now.sec < data->pac_key_refresh_time) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Key soft timeout; send " - "an update if authentication succeeds"); - data->send_new_pac = 1; - } - - eap_fast_derive_master_secret(pac_key, server_random, client_random, - master_secret); - - os_free(buf); - - return 1; -} - - -static void eap_fast_derive_key_auth(struct eap_sm *sm, - struct eap_fast_data *data) -{ - u8 *sks; - - /* RFC 4851, Section 5.1: - * Extra key material after TLS key_block: session_key_seed[40] - */ - - sks = eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, "key expansion", - EAP_FAST_SKS_LEN); - if (sks == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive " - "session_key_seed"); - return; - } - - /* - * RFC 4851, Section 5.2: - * S-IMCK[0] = session_key_seed - */ - wpa_hexdump_key(MSG_DEBUG, - "EAP-FAST: session_key_seed (SKS = S-IMCK[0])", - sks, EAP_FAST_SKS_LEN); - data->simck_idx = 0; - os_memcpy(data->simck, sks, EAP_FAST_SIMCK_LEN); - os_free(sks); -} - - -static void eap_fast_derive_key_provisioning(struct eap_sm *sm, - struct eap_fast_data *data) -{ - os_free(data->key_block_p); - data->key_block_p = (struct eap_fast_key_block_provisioning *) - eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, - "key expansion", - sizeof(*data->key_block_p)); - if (data->key_block_p == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive key block"); - return; - } - /* - * RFC 4851, Section 5.2: - * S-IMCK[0] = session_key_seed - */ - wpa_hexdump_key(MSG_DEBUG, - "EAP-FAST: session_key_seed (SKS = S-IMCK[0])", - data->key_block_p->session_key_seed, - sizeof(data->key_block_p->session_key_seed)); - data->simck_idx = 0; - os_memcpy(data->simck, data->key_block_p->session_key_seed, - EAP_FAST_SIMCK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: server_challenge", - data->key_block_p->server_challenge, - sizeof(data->key_block_p->server_challenge)); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: client_challenge", - data->key_block_p->client_challenge, - sizeof(data->key_block_p->client_challenge)); -} - - -static int eap_fast_get_phase2_key(struct eap_sm *sm, - struct eap_fast_data *data, - u8 *isk, size_t isk_len) -{ - u8 *key; - size_t key_len; - - os_memset(isk, 0, isk_len); - - if (data->phase2_method == NULL || data->phase2_priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 method not " - "available"); - return -1; - } - - if (data->phase2_method->getKey == NULL) - return 0; - - if ((key = data->phase2_method->getKey(sm, data->phase2_priv, - &key_len)) == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Could not get key material " - "from Phase 2"); - return -1; - } - - if (key_len > isk_len) - key_len = isk_len; - if (key_len == 32 && - data->phase2_method->vendor == EAP_VENDOR_IETF && - data->phase2_method->method == EAP_TYPE_MSCHAPV2) { - /* - * EAP-FAST uses reverse order for MS-MPPE keys when deriving - * MSK from EAP-MSCHAPv2. Swap the keys here to get the correct - * ISK for EAP-FAST cryptobinding. - */ - os_memcpy(isk, key + 16, 16); - os_memcpy(isk + 16, key, 16); - } else - os_memcpy(isk, key, key_len); - os_free(key); - - return 0; -} - - -static int eap_fast_update_icmk(struct eap_sm *sm, struct eap_fast_data *data) -{ - u8 isk[32], imck[60]; - - wpa_printf(MSG_DEBUG, "EAP-FAST: Deriving ICMK[%d] (S-IMCK and CMK)", - data->simck_idx + 1); - - /* - * RFC 4851, Section 5.2: - * IMCK[j] = T-PRF(S-IMCK[j-1], "Inner Methods Compound Keys", - * MSK[j], 60) - * S-IMCK[j] = first 40 octets of IMCK[j] - * CMK[j] = last 20 octets of IMCK[j] - */ - - if (eap_fast_get_phase2_key(sm, data, isk, sizeof(isk)) < 0) - return -1; - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: ISK[j]", isk, sizeof(isk)); - sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN, - "Inner Methods Compound Keys", - isk, sizeof(isk), imck, sizeof(imck)); - data->simck_idx++; - os_memcpy(data->simck, imck, EAP_FAST_SIMCK_LEN); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: S-IMCK[j]", - data->simck, EAP_FAST_SIMCK_LEN); - os_memcpy(data->cmk, imck + EAP_FAST_SIMCK_LEN, EAP_FAST_CMK_LEN); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: CMK[j]", - data->cmk, EAP_FAST_CMK_LEN); - - return 0; -} - - -static void * eap_fast_init(struct eap_sm *sm) -{ - struct eap_fast_data *data; - u8 ciphers[5] = { - TLS_CIPHER_ANON_DH_AES128_SHA, - TLS_CIPHER_AES128_SHA, - TLS_CIPHER_RSA_DHE_AES128_SHA, - TLS_CIPHER_RC4_SHA, - TLS_CIPHER_NONE - }; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->fast_version = EAP_FAST_VERSION; - data->force_version = -1; - if (sm->user && sm->user->force_version >= 0) { - data->force_version = sm->user->force_version; - wpa_printf(MSG_DEBUG, "EAP-FAST: forcing version %d", - data->force_version); - data->fast_version = data->force_version; - } - data->state = START; - - if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to initialize SSL."); - eap_fast_reset(sm, data); - return NULL; - } - - if (tls_connection_set_cipher_list(sm->ssl_ctx, data->ssl.conn, - ciphers) < 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to set TLS cipher " - "suites"); - eap_fast_reset(sm, data); - return NULL; - } - - if (tls_connection_set_session_ticket_cb(sm->ssl_ctx, data->ssl.conn, - eap_fast_session_ticket_cb, - data) < 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to set SessionTicket " - "callback"); - eap_fast_reset(sm, data); - return NULL; - } - - if (sm->pac_opaque_encr_key == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: No PAC-Opaque encryption key " - "configured"); - eap_fast_reset(sm, data); - return NULL; - } - os_memcpy(data->pac_opaque_encr, sm->pac_opaque_encr_key, - sizeof(data->pac_opaque_encr)); - - if (sm->eap_fast_a_id == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: No A-ID configured"); - eap_fast_reset(sm, data); - return NULL; - } - data->srv_id = os_malloc(sm->eap_fast_a_id_len); - if (data->srv_id == NULL) { - eap_fast_reset(sm, data); - return NULL; - } - os_memcpy(data->srv_id, sm->eap_fast_a_id, sm->eap_fast_a_id_len); - data->srv_id_len = sm->eap_fast_a_id_len; - - if (sm->eap_fast_a_id_info == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: No A-ID-Info configured"); - eap_fast_reset(sm, data); - return NULL; - } - data->srv_id_info = os_strdup(sm->eap_fast_a_id_info); - if (data->srv_id_info == NULL) { - eap_fast_reset(sm, data); - return NULL; - } - - /* PAC-Key lifetime in seconds (hard limit) */ - data->pac_key_lifetime = sm->pac_key_lifetime; - - /* - * PAC-Key refresh time in seconds (soft limit on remaining hard - * limit). The server will generate a new PAC-Key when this number of - * seconds (or fewer) of the lifetime remains. - */ - data->pac_key_refresh_time = sm->pac_key_refresh_time; - - return data; -} - - -static void eap_fast_reset(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - if (data == NULL) - return; - if (data->phase2_priv && data->phase2_method) - data->phase2_method->reset(sm, data->phase2_priv); - eap_server_tls_ssl_deinit(sm, &data->ssl); - os_free(data->srv_id); - os_free(data->srv_id_info); - os_free(data->key_block_p); - wpabuf_free(data->pending_phase2_resp); - os_free(data->identity); - os_free(data); -} - - -static struct wpabuf * eap_fast_build_start(struct eap_sm *sm, - struct eap_fast_data *data, u8 id) -{ - struct wpabuf *req; - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_FAST, - 1 + sizeof(struct pac_tlv_hdr) + data->srv_id_len, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-FAST: Failed to allocate memory for" - " request"); - eap_fast_state(data, FAILURE); - return NULL; - } - - wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->fast_version); - - /* RFC 4851, 4.1.1. Authority ID Data */ - eap_fast_put_tlv(req, PAC_TYPE_A_ID, data->srv_id, data->srv_id_len); - - eap_fast_state(data, PHASE1); - - return req; -} - - -static int eap_fast_phase1_done(struct eap_sm *sm, struct eap_fast_data *data) -{ - char cipher[64]; - - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase1 done, starting Phase2"); - - if (tls_get_cipher(sm->ssl_ctx, data->ssl.conn, cipher, sizeof(cipher)) - < 0) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to get cipher " - "information"); - eap_fast_state(data, FAILURE); - return -1; - } - data->anon_provisioning = os_strstr(cipher, "ADH") != NULL; - - if (data->anon_provisioning) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Anonymous provisioning"); - eap_fast_derive_key_provisioning(sm, data); - } else - eap_fast_derive_key_auth(sm, data); - - eap_fast_state(data, PHASE2_START); - - return 0; -} - - -static struct wpabuf * eap_fast_build_phase2_req(struct eap_sm *sm, - struct eap_fast_data *data, - u8 id) -{ - struct wpabuf *req; - - if (data->phase2_priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 method not " - "initialized"); - return NULL; - } - req = data->phase2_method->buildReq(sm, data->phase2_priv, id); - if (req == NULL) - return NULL; - - wpa_hexdump_buf_key(MSG_MSGDUMP, "EAP-FAST: Phase 2 EAP-Request", req); - return eap_fast_tlv_eap_payload(req); -} - - -static struct wpabuf * eap_fast_build_crypto_binding( - struct eap_sm *sm, struct eap_fast_data *data) -{ - struct wpabuf *buf; - struct eap_tlv_result_tlv *result; - struct eap_tlv_crypto_binding_tlv *binding; - - buf = wpabuf_alloc(2 * sizeof(*result) + sizeof(*binding)); - if (buf == NULL) - return NULL; - - if (data->send_new_pac || data->anon_provisioning || - data->phase2_method) - data->final_result = 0; - else - data->final_result = 1; - - if (!data->final_result || data->eap_seq > 1) { - /* Intermediate-Result */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Add Intermediate-Result TLV " - "(status=SUCCESS)"); - result = wpabuf_put(buf, sizeof(*result)); - result->tlv_type = host_to_be16( - EAP_TLV_TYPE_MANDATORY | - EAP_TLV_INTERMEDIATE_RESULT_TLV); - result->length = host_to_be16(2); - result->status = host_to_be16(EAP_TLV_RESULT_SUCCESS); - } - - if (data->final_result) { - /* Result TLV */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Add Result TLV " - "(status=SUCCESS)"); - result = wpabuf_put(buf, sizeof(*result)); - result->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - EAP_TLV_RESULT_TLV); - result->length = host_to_be16(2); - result->status = host_to_be16(EAP_TLV_RESULT_SUCCESS); - } - - /* Crypto-Binding TLV */ - binding = wpabuf_put(buf, sizeof(*binding)); - binding->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - EAP_TLV_CRYPTO_BINDING_TLV); - binding->length = host_to_be16(sizeof(*binding) - - sizeof(struct eap_tlv_hdr)); - binding->version = EAP_FAST_VERSION; - binding->received_version = data->peer_version; - binding->subtype = EAP_TLV_CRYPTO_BINDING_SUBTYPE_REQUEST; - if (os_get_random(binding->nonce, sizeof(binding->nonce)) < 0) { - wpabuf_free(buf); - return NULL; - } - - /* - * RFC 4851, Section 4.2.8: - * The nonce in a request MUST have its least significant bit set to 0. - */ - binding->nonce[sizeof(binding->nonce) - 1] &= ~0x01; - - os_memcpy(data->crypto_binding_nonce, binding->nonce, - sizeof(binding->nonce)); - - /* - * RFC 4851, Section 5.3: - * CMK = CMK[j] - * Compound-MAC = HMAC-SHA1( CMK, Crypto-Binding TLV ) - */ - - hmac_sha1(data->cmk, EAP_FAST_CMK_LEN, - (u8 *) binding, sizeof(*binding), - binding->compound_mac); - - wpa_printf(MSG_DEBUG, "EAP-FAST: Add Crypto-Binding TLV: Version %d " - "Received Version %d SubType %d", - binding->version, binding->received_version, - binding->subtype); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: NONCE", - binding->nonce, sizeof(binding->nonce)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Compound MAC", - binding->compound_mac, sizeof(binding->compound_mac)); - - return buf; -} - - -static struct wpabuf * eap_fast_build_pac(struct eap_sm *sm, - struct eap_fast_data *data) -{ - u8 pac_key[EAP_FAST_PAC_KEY_LEN]; - u8 *pac_buf, *pac_opaque; - struct wpabuf *buf; - u8 *pos; - size_t buf_len, srv_id_info_len, pac_len; - struct eap_tlv_hdr *pac_tlv; - struct pac_tlv_hdr *pac_info; - struct eap_tlv_result_tlv *result; - struct os_time now; - - if (os_get_random(pac_key, EAP_FAST_PAC_KEY_LEN) < 0 || - os_get_time(&now) < 0) - return NULL; - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Generated PAC-Key", - pac_key, EAP_FAST_PAC_KEY_LEN); - - pac_len = (2 + EAP_FAST_PAC_KEY_LEN) + (2 + 4) + - (2 + sm->identity_len) + 8; - pac_buf = os_malloc(pac_len); - if (pac_buf == NULL) - return NULL; - - srv_id_info_len = os_strlen(data->srv_id_info); - - pos = pac_buf; - *pos++ = PAC_OPAQUE_TYPE_KEY; - *pos++ = EAP_FAST_PAC_KEY_LEN; - os_memcpy(pos, pac_key, EAP_FAST_PAC_KEY_LEN); - pos += EAP_FAST_PAC_KEY_LEN; - - *pos++ = PAC_OPAQUE_TYPE_LIFETIME; - *pos++ = 4; - WPA_PUT_BE32(pos, now.sec + data->pac_key_lifetime); - pos += 4; - - if (sm->identity) { - *pos++ = PAC_OPAQUE_TYPE_IDENTITY; - *pos++ = sm->identity_len; - os_memcpy(pos, sm->identity, sm->identity_len); - pos += sm->identity_len; - } - - pac_len = pos - pac_buf; - while (pac_len % 8) { - *pos++ = PAC_OPAQUE_TYPE_PAD; - pac_len++; - } - - pac_opaque = os_malloc(pac_len + 8); - if (pac_opaque == NULL) { - os_free(pac_buf); - return NULL; - } - if (aes_wrap(data->pac_opaque_encr, pac_len / 8, pac_buf, - pac_opaque) < 0) { - os_free(pac_buf); - os_free(pac_opaque); - return NULL; - } - os_free(pac_buf); - - pac_len += 8; - wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Opaque", - pac_opaque, pac_len); - - buf_len = sizeof(*pac_tlv) + - sizeof(struct pac_tlv_hdr) + EAP_FAST_PAC_KEY_LEN + - sizeof(struct pac_tlv_hdr) + pac_len + - data->srv_id_len + srv_id_info_len + 100 + sizeof(*result); - buf = wpabuf_alloc(buf_len); - if (buf == NULL) { - os_free(pac_opaque); - return NULL; - } - - /* Result TLV */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Add Result TLV (status=SUCCESS)"); - result = wpabuf_put(buf, sizeof(*result)); - WPA_PUT_BE16((u8 *) &result->tlv_type, - EAP_TLV_TYPE_MANDATORY | EAP_TLV_RESULT_TLV); - WPA_PUT_BE16((u8 *) &result->length, 2); - WPA_PUT_BE16((u8 *) &result->status, EAP_TLV_RESULT_SUCCESS); - - /* PAC TLV */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Add PAC TLV"); - pac_tlv = wpabuf_put(buf, sizeof(*pac_tlv)); - pac_tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - EAP_TLV_PAC_TLV); - - /* PAC-Key */ - eap_fast_put_tlv(buf, PAC_TYPE_PAC_KEY, pac_key, EAP_FAST_PAC_KEY_LEN); - - /* PAC-Opaque */ - eap_fast_put_tlv(buf, PAC_TYPE_PAC_OPAQUE, pac_opaque, pac_len); - os_free(pac_opaque); - - /* PAC-Info */ - pac_info = wpabuf_put(buf, sizeof(*pac_info)); - pac_info->type = host_to_be16(PAC_TYPE_PAC_INFO); - - /* PAC-Lifetime (inside PAC-Info) */ - eap_fast_put_tlv_hdr(buf, PAC_TYPE_CRED_LIFETIME, 4); - wpabuf_put_be32(buf, now.sec + data->pac_key_lifetime); - - /* A-ID (inside PAC-Info) */ - eap_fast_put_tlv(buf, PAC_TYPE_A_ID, data->srv_id, data->srv_id_len); - - /* Note: headers may be misaligned after A-ID */ - - /* A-ID-Info (inside PAC-Info) */ - eap_fast_put_tlv(buf, PAC_TYPE_A_ID_INFO, data->srv_id_info, - srv_id_info_len); - - /* PAC-Type (inside PAC-Info) */ - eap_fast_put_tlv_hdr(buf, PAC_TYPE_PAC_TYPE, 2); - wpabuf_put_be16(buf, PAC_TYPE_TUNNEL_PAC); - - /* Update PAC-Info and PAC TLV Length fields */ - pos = wpabuf_put(buf, 0); - pac_info->len = host_to_be16(pos - (u8 *) (pac_info + 1)); - pac_tlv->length = host_to_be16(pos - (u8 *) (pac_tlv + 1)); - - return buf; -} - - -static int eap_fast_encrypt_phase2(struct eap_sm *sm, - struct eap_fast_data *data, - struct wpabuf *plain, int piggyback) -{ - struct wpabuf *encr; - - wpa_hexdump_buf_key(MSG_DEBUG, "EAP-FAST: Encrypting Phase 2 TLVs", - plain); - encr = eap_server_tls_encrypt(sm, &data->ssl, wpabuf_mhead(plain), - wpabuf_len(plain)); - wpabuf_free(plain); - - if (data->ssl.out_buf && piggyback) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Piggyback Phase 2 data " - "(len=%d) with last Phase 1 Message (len=%d " - "used=%d)", - (int) wpabuf_len(encr), - (int) wpabuf_len(data->ssl.out_buf), - (int) data->ssl.out_used); - if (wpabuf_resize(&data->ssl.out_buf, wpabuf_len(encr)) < 0) { - wpa_printf(MSG_WARNING, "EAP-FAST: Failed to resize " - "output buffer"); - wpabuf_free(encr); - return -1; - } - wpabuf_put_buf(data->ssl.out_buf, encr); - wpabuf_free(encr); - } else { - wpabuf_free(data->ssl.out_buf); - data->ssl.out_used = 0; - data->ssl.out_buf = encr; - } - - return 0; -} - - -static struct wpabuf * eap_fast_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_fast_data *data = priv; - struct wpabuf *req = NULL; - int piggyback = 0; - - if (data->ssl.state == FRAG_ACK) { - return eap_server_tls_build_ack(id, EAP_TYPE_FAST, - data->fast_version); - } - - if (data->ssl.state == WAIT_FRAG_ACK) { - return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_FAST, - data->fast_version, id); - } - - switch (data->state) { - case START: - return eap_fast_build_start(sm, data, id); - case PHASE1: - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - if (eap_fast_phase1_done(sm, data) < 0) - return NULL; - if (data->state == PHASE2_START) { - /* - * Try to generate Phase 2 data to piggyback - * with the end of Phase 1 to avoid extra - * roundtrip. - */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Try to start " - "Phase 2"); - if (eap_fast_process_phase2_start(sm, data)) - break; - req = eap_fast_build_phase2_req(sm, data, id); - piggyback = 1; - } - } - break; - case PHASE2_ID: - case PHASE2_METHOD: - req = eap_fast_build_phase2_req(sm, data, id); - break; - case CRYPTO_BINDING: - req = eap_fast_build_crypto_binding(sm, data); - if (data->phase2_method) { - /* - * Include the start of the next EAP method in the - * sequence in the same message with Crypto-Binding to - * save a round-trip. - */ - struct wpabuf *eap; - eap = eap_fast_build_phase2_req(sm, data, id); - req = wpabuf_concat(req, eap); - eap_fast_state(data, PHASE2_METHOD); - } - break; - case REQUEST_PAC: - req = eap_fast_build_pac(sm, data); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-FAST: %s - unexpected state %d", - __func__, data->state); - return NULL; - } - - if (req && - eap_fast_encrypt_phase2(sm, data, req, piggyback) < 0) - return NULL; - - return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_FAST, - data->fast_version, id); -} - - -static Boolean eap_fast_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_FAST, respData, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static int eap_fast_phase2_init(struct eap_sm *sm, struct eap_fast_data *data, - EapType eap_type) -{ - if (data->phase2_priv && data->phase2_method) { - data->phase2_method->reset(sm, data->phase2_priv); - data->phase2_method = NULL; - data->phase2_priv = NULL; - } - data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF, - eap_type); - if (!data->phase2_method) - return -1; - - if (data->key_block_p) { - sm->auth_challenge = data->key_block_p->server_challenge; - sm->peer_challenge = data->key_block_p->client_challenge; - } - sm->init_phase2 = 1; - data->phase2_priv = data->phase2_method->init(sm); - sm->init_phase2 = 0; - sm->auth_challenge = NULL; - sm->peer_challenge = NULL; - - return data->phase2_priv == NULL ? -1 : 0; -} - - -static void eap_fast_process_phase2_response(struct eap_sm *sm, - struct eap_fast_data *data, - u8 *in_data, size_t in_len) -{ - u8 next_type = EAP_TYPE_NONE; - struct eap_hdr *hdr; - u8 *pos; - size_t left; - struct wpabuf buf; - const struct eap_method *m = data->phase2_method; - void *priv = data->phase2_priv; - - if (priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: %s - Phase2 not " - "initialized?!", __func__); - return; - } - - hdr = (struct eap_hdr *) in_data; - pos = (u8 *) (hdr + 1); - - if (in_len > sizeof(*hdr) && *pos == EAP_TYPE_NAK) { - left = in_len - sizeof(*hdr); - wpa_hexdump(MSG_DEBUG, "EAP-FAST: Phase2 type Nak'ed; " - "allowed types", pos + 1, left - 1); -#ifdef EAP_TNC - if (m && m->vendor == EAP_VENDOR_IETF && - m->method == EAP_TYPE_TNC) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Peer Nak'ed required " - "TNC negotiation"); - next_type = eap_fast_req_failure(sm, data); - eap_fast_phase2_init(sm, data, next_type); - return; - } -#endif /* EAP_TNC */ - eap_sm_process_nak(sm, pos + 1, left - 1); - if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && - sm->user->methods[sm->user_eap_method_index].method != - EAP_TYPE_NONE) { - next_type = sm->user->methods[ - sm->user_eap_method_index++].method; - wpa_printf(MSG_DEBUG, "EAP-FAST: try EAP type %d", - next_type); - } else { - next_type = eap_fast_req_failure(sm, data); - } - eap_fast_phase2_init(sm, data, next_type); - return; - } - - wpabuf_set(&buf, in_data, in_len); - - if (m->check(sm, priv, &buf)) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase2 check() asked to " - "ignore the packet"); - next_type = eap_fast_req_failure(sm, data); - return; - } - - m->process(sm, priv, &buf); - - if (!m->isDone(sm, priv)) - return; - - if (!m->isSuccess(sm, priv)) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase2 method failed"); - next_type = eap_fast_req_failure(sm, data); - eap_fast_phase2_init(sm, data, next_type); - return; - } - - switch (data->state) { - case PHASE2_ID: - if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: Phase2 " - "Identity not found in the user " - "database", - sm->identity, sm->identity_len); - next_type = eap_fast_req_failure(sm, data); - break; - } - - eap_fast_state(data, PHASE2_METHOD); - if (data->anon_provisioning) { - /* - * Only EAP-MSCHAPv2 is allowed for anonymous - * provisioning. - */ - next_type = EAP_TYPE_MSCHAPV2; - sm->user_eap_method_index = 0; - } else { - next_type = sm->user->methods[0].method; - sm->user_eap_method_index = 1; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: try EAP type %d", next_type); - break; - case PHASE2_METHOD: - case CRYPTO_BINDING: - eap_fast_update_icmk(sm, data); - eap_fast_state(data, CRYPTO_BINDING); - data->eap_seq++; - next_type = EAP_TYPE_NONE; -#ifdef EAP_TNC - if (sm->tnc && !data->tnc_started) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Initialize TNC"); - next_type = EAP_TYPE_TNC; - data->tnc_started = 1; - } -#endif /* EAP_TNC */ - break; - case FAILURE: - break; - default: - wpa_printf(MSG_DEBUG, "EAP-FAST: %s - unexpected state %d", - __func__, data->state); - break; - } - - eap_fast_phase2_init(sm, data, next_type); -} - - -static void eap_fast_process_phase2_eap(struct eap_sm *sm, - struct eap_fast_data *data, - u8 *in_data, size_t in_len) -{ - struct eap_hdr *hdr; - size_t len; - - hdr = (struct eap_hdr *) in_data; - if (in_len < (int) sizeof(*hdr)) { - wpa_printf(MSG_INFO, "EAP-FAST: Too short Phase 2 " - "EAP frame (len=%lu)", (unsigned long) in_len); - eap_fast_req_failure(sm, data); - return; - } - len = be_to_host16(hdr->length); - if (len > in_len) { - wpa_printf(MSG_INFO, "EAP-FAST: Length mismatch in " - "Phase 2 EAP frame (len=%lu hdr->length=%lu)", - (unsigned long) in_len, (unsigned long) len); - eap_fast_req_failure(sm, data); - return; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: Received Phase 2: code=%d " - "identifier=%d length=%lu", hdr->code, hdr->identifier, - (unsigned long) len); - switch (hdr->code) { - case EAP_CODE_RESPONSE: - eap_fast_process_phase2_response(sm, data, (u8 *) hdr, len); - break; - default: - wpa_printf(MSG_INFO, "EAP-FAST: Unexpected code=%d in " - "Phase 2 EAP header", hdr->code); - break; - } -} - - -static int eap_fast_parse_tlvs(u8 *data, size_t data_len, - struct eap_fast_tlv_parse *tlv) -{ - int mandatory, tlv_type, len, res; - u8 *pos, *end; - - os_memset(tlv, 0, sizeof(*tlv)); - - pos = data; - end = data + data_len; - while (pos + 4 < end) { - mandatory = pos[0] & 0x80; - tlv_type = WPA_GET_BE16(pos) & 0x3fff; - pos += 2; - len = WPA_GET_BE16(pos); - pos += 2; - if (pos + len > end) { - wpa_printf(MSG_INFO, "EAP-FAST: TLV overflow"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: Received Phase 2: " - "TLV type %d length %d%s", - tlv_type, len, mandatory ? " (mandatory)" : ""); - - res = eap_fast_parse_tlv(tlv, tlv_type, pos, len); - if (res == -2) - break; - if (res < 0) { - if (mandatory) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Nak unknown " - "mandatory TLV type %d", tlv_type); - /* TODO: generate Nak TLV */ - break; - } else { - wpa_printf(MSG_DEBUG, "EAP-FAST: Ignored " - "unknown optional TLV type %d", - tlv_type); - } - } - - pos += len; - } - - return 0; -} - - -static int eap_fast_validate_crypto_binding( - struct eap_fast_data *data, struct eap_tlv_crypto_binding_tlv *b, - size_t bind_len) -{ - u8 cmac[SHA1_MAC_LEN]; - - wpa_printf(MSG_DEBUG, "EAP-FAST: Reply Crypto-Binding TLV: " - "Version %d Received Version %d SubType %d", - b->version, b->received_version, b->subtype); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: NONCE", - b->nonce, sizeof(b->nonce)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Compound MAC", - b->compound_mac, sizeof(b->compound_mac)); - - if (b->version != EAP_FAST_VERSION || - b->received_version != EAP_FAST_VERSION) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Unexpected version " - "in Crypto-Binding: version %d " - "received_version %d", b->version, - b->received_version); - return -1; - } - - if (b->subtype != EAP_TLV_CRYPTO_BINDING_SUBTYPE_RESPONSE) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Unexpected subtype in " - "Crypto-Binding: %d", b->subtype); - return -1; - } - - if (os_memcmp(data->crypto_binding_nonce, b->nonce, 31) != 0 || - (data->crypto_binding_nonce[31] | 1) != b->nonce[31]) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid nonce in " - "Crypto-Binding"); - return -1; - } - - os_memcpy(cmac, b->compound_mac, sizeof(cmac)); - os_memset(b->compound_mac, 0, sizeof(cmac)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV for " - "Compound MAC calculation", - (u8 *) b, bind_len); - hmac_sha1(data->cmk, EAP_FAST_CMK_LEN, (u8 *) b, bind_len, - b->compound_mac); - if (os_memcmp(cmac, b->compound_mac, sizeof(cmac)) != 0) { - wpa_hexdump(MSG_MSGDUMP, - "EAP-FAST: Calculated Compound MAC", - b->compound_mac, sizeof(cmac)); - wpa_printf(MSG_INFO, "EAP-FAST: Compound MAC did not " - "match"); - return -1; - } - - return 0; -} - - -static int eap_fast_pac_type(u8 *pac, size_t len, u16 type) -{ - struct eap_tlv_pac_type_tlv *tlv; - - if (pac == NULL || len != sizeof(*tlv)) - return 0; - - tlv = (struct eap_tlv_pac_type_tlv *) pac; - - return be_to_host16(tlv->tlv_type) == PAC_TYPE_PAC_TYPE && - be_to_host16(tlv->length) == 2 && - be_to_host16(tlv->pac_type) == type; -} - - -static void eap_fast_process_phase2_tlvs(struct eap_sm *sm, - struct eap_fast_data *data, - u8 *in_data, size_t in_len) -{ - struct eap_fast_tlv_parse tlv; - int check_crypto_binding = data->state == CRYPTO_BINDING; - - if (eap_fast_parse_tlvs(in_data, in_len, &tlv) < 0) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to parse received " - "Phase 2 TLVs"); - return; - } - - if (tlv.result == EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Result TLV indicated " - "failure"); - eap_fast_state(data, FAILURE); - return; - } - - if (data->state == REQUEST_PAC) { - u16 type, len, res; - if (tlv.pac == NULL || tlv.pac_len < 6) { - wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC " - "Acknowledgement received"); - eap_fast_state(data, FAILURE); - return; - } - - type = WPA_GET_BE16(tlv.pac); - len = WPA_GET_BE16(tlv.pac + 2); - res = WPA_GET_BE16(tlv.pac + 4); - - if (type != PAC_TYPE_PAC_ACKNOWLEDGEMENT || len != 2 || - res != EAP_TLV_RESULT_SUCCESS) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC TLV did not " - "contain acknowledgement"); - eap_fast_state(data, FAILURE); - return; - } - - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Acknowledgement received " - "- PAC provisioning succeeded"); - eap_fast_state(data, (data->anon_provisioning || - data->send_new_pac == 2) ? - FAILURE : SUCCESS); - return; - } - - if (check_crypto_binding) { - if (tlv.crypto_binding == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: No Crypto-Binding " - "TLV received"); - eap_fast_state(data, FAILURE); - return; - } - - if (data->final_result && - tlv.result != EAP_TLV_RESULT_SUCCESS) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Crypto-Binding TLV " - "without Success Result"); - eap_fast_state(data, FAILURE); - return; - } - - if (!data->final_result && - tlv.iresult != EAP_TLV_RESULT_SUCCESS) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Crypto-Binding TLV " - "without intermediate Success Result"); - eap_fast_state(data, FAILURE); - return; - } - - if (eap_fast_validate_crypto_binding(data, tlv.crypto_binding, - tlv.crypto_binding_len)) { - eap_fast_state(data, FAILURE); - return; - } - - wpa_printf(MSG_DEBUG, "EAP-FAST: Valid Crypto-Binding TLV " - "received"); - if (data->final_result) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Authentication " - "completed successfully"); - } - - if (data->anon_provisioning && - sm->eap_fast_prov != ANON_PROV && - sm->eap_fast_prov != BOTH_PROV) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Client is trying to " - "use unauthenticated provisioning which is " - "disabled"); - eap_fast_state(data, FAILURE); - return; - } - - if (sm->eap_fast_prov != AUTH_PROV && - sm->eap_fast_prov != BOTH_PROV && - tlv.request_action == EAP_TLV_ACTION_PROCESS_TLV && - eap_fast_pac_type(tlv.pac, tlv.pac_len, - PAC_TYPE_TUNNEL_PAC)) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Client is trying to " - "use authenticated provisioning which is " - "disabled"); - eap_fast_state(data, FAILURE); - return; - } - - if (data->anon_provisioning || - (tlv.request_action == EAP_TLV_ACTION_PROCESS_TLV && - eap_fast_pac_type(tlv.pac, tlv.pac_len, - PAC_TYPE_TUNNEL_PAC))) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Requested a new " - "Tunnel PAC"); - eap_fast_state(data, REQUEST_PAC); - } else if (data->send_new_pac) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Server triggered " - "re-keying of Tunnel PAC"); - eap_fast_state(data, REQUEST_PAC); - } else if (data->final_result) - eap_fast_state(data, SUCCESS); - } - - if (tlv.eap_payload_tlv) { - eap_fast_process_phase2_eap(sm, data, tlv.eap_payload_tlv, - tlv.eap_payload_tlv_len); - } -} - - -static void eap_fast_process_phase2(struct eap_sm *sm, - struct eap_fast_data *data, - struct wpabuf *in_buf) -{ - u8 *in_decrypted; - int len_decrypted; - size_t buf_len; - u8 *in_data; - size_t in_len; - - in_data = wpabuf_mhead(in_buf); - in_len = wpabuf_len(in_buf); - - wpa_printf(MSG_DEBUG, "EAP-FAST: Received %lu bytes encrypted data for" - " Phase 2", (unsigned long) in_len); - - if (data->pending_phase2_resp) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - " - "skip decryption and use old data"); - eap_fast_process_phase2_tlvs( - sm, data, wpabuf_mhead(data->pending_phase2_resp), - wpabuf_len(data->pending_phase2_resp)); - wpabuf_free(data->pending_phase2_resp); - data->pending_phase2_resp = NULL; - return; - } - - buf_len = in_len; - /* - * Even though we try to disable TLS compression, it is possible that - * this cannot be done with all TLS libraries. Add extra buffer space - * to handle the possibility of the decrypted data being longer than - * input data. - */ - buf_len += 500; - buf_len *= 3; - in_decrypted = os_malloc(buf_len); - if (in_decrypted == NULL) { - wpa_printf(MSG_WARNING, "EAP-FAST: Failed to allocate memory " - "for decryption"); - return; - } - - len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, - in_data, in_len, - in_decrypted, buf_len); - if (len_decrypted < 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to decrypt Phase 2 " - "data"); - os_free(in_decrypted); - eap_fast_state(data, FAILURE); - return; - } - - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Decrypted Phase 2 TLVs", - in_decrypted, len_decrypted); - - eap_fast_process_phase2_tlvs(sm, data, in_decrypted, len_decrypted); - - if (sm->method_pending == METHOD_PENDING_WAIT) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase2 method is in " - "pending wait state - save decrypted response"); - wpabuf_free(data->pending_phase2_resp); - data->pending_phase2_resp = wpabuf_alloc_copy(in_decrypted, - len_decrypted); - } - - os_free(in_decrypted); -} - - -static int eap_fast_process_version(struct eap_sm *sm, void *priv, - int peer_version) -{ - struct eap_fast_data *data = priv; - - data->peer_version = peer_version; - - if (data->force_version >= 0 && peer_version != data->force_version) { - wpa_printf(MSG_INFO, "EAP-FAST: peer did not select the forced" - " version (forced=%d peer=%d) - reject", - data->force_version, peer_version); - return -1; - } - - if (peer_version < data->fast_version) { - wpa_printf(MSG_DEBUG, "EAP-FAST: peer ver=%d, own ver=%d; " - "use version %d", - peer_version, data->fast_version, peer_version); - data->fast_version = peer_version; - } - - return 0; -} - - -static int eap_fast_process_phase1(struct eap_sm *sm, - struct eap_fast_data *data) -{ - if (eap_server_tls_phase1(sm, &data->ssl) < 0) { - wpa_printf(MSG_INFO, "EAP-FAST: TLS processing failed"); - eap_fast_state(data, FAILURE); - return -1; - } - - if (!tls_connection_established(sm->ssl_ctx, data->ssl.conn) || - wpabuf_len(data->ssl.out_buf) > 0) - return 1; - - /* - * Phase 1 was completed with the received message (e.g., when using - * abbreviated handshake), so Phase 2 can be started immediately - * without having to send through an empty message to the peer. - */ - - return eap_fast_phase1_done(sm, data); -} - - -static int eap_fast_process_phase2_start(struct eap_sm *sm, - struct eap_fast_data *data) -{ - u8 next_type; - - if (data->identity) { - os_free(sm->identity); - sm->identity = data->identity; - data->identity = NULL; - sm->identity_len = data->identity_len; - data->identity_len = 0; - sm->require_identity_match = 1; - if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: " - "Phase2 Identity not found " - "in the user database", - sm->identity, sm->identity_len); - next_type = eap_fast_req_failure(sm, data); - } else { - wpa_printf(MSG_DEBUG, "EAP-FAST: Identity already " - "known - skip Phase 2 Identity Request"); - next_type = sm->user->methods[0].method; - sm->user_eap_method_index = 1; - } - - eap_fast_state(data, PHASE2_METHOD); - } else { - eap_fast_state(data, PHASE2_ID); - next_type = EAP_TYPE_IDENTITY; - } - - return eap_fast_phase2_init(sm, data, next_type); -} - - -static void eap_fast_process_msg(struct eap_sm *sm, void *priv, - const struct wpabuf *respData) -{ - struct eap_fast_data *data = priv; - - switch (data->state) { - case PHASE1: - if (eap_fast_process_phase1(sm, data)) - break; - - /* fall through to PHASE2_START */ - case PHASE2_START: - eap_fast_process_phase2_start(sm, data); - break; - case PHASE2_ID: - case PHASE2_METHOD: - case CRYPTO_BINDING: - case REQUEST_PAC: - eap_fast_process_phase2(sm, data, data->ssl.in_buf); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-FAST: Unexpected state %d in %s", - data->state, __func__); - break; - } -} - - -static void eap_fast_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_fast_data *data = priv; - if (eap_server_tls_process(sm, &data->ssl, respData, data, - EAP_TYPE_FAST, eap_fast_process_version, - eap_fast_process_msg) < 0) - eap_fast_state(data, FAILURE); -} - - -static Boolean eap_fast_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_fast_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_fast_data *data = priv; - u8 *eapKeyData; - - if (data->state != SUCCESS) - return NULL; - - eapKeyData = os_malloc(EAP_FAST_KEY_LEN); - if (eapKeyData == NULL) - return NULL; - - eap_fast_derive_eap_msk(data->simck, eapKeyData); - *len = EAP_FAST_KEY_LEN; - - return eapKeyData; -} - - -static u8 * eap_fast_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_fast_data *data = priv; - u8 *eapKeyData; - - if (data->state != SUCCESS) - return NULL; - - eapKeyData = os_malloc(EAP_EMSK_LEN); - if (eapKeyData == NULL) - return NULL; - - eap_fast_derive_eap_emsk(data->simck, eapKeyData); - *len = EAP_EMSK_LEN; - - return eapKeyData; -} - - -static Boolean eap_fast_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_fast_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_FAST, "FAST"); - if (eap == NULL) - return -1; - - eap->init = eap_fast_init; - eap->reset = eap_fast_reset; - eap->buildReq = eap_fast_buildReq; - eap->check = eap_fast_check; - eap->process = eap_fast_process; - eap->isDone = eap_fast_isDone; - eap->getKey = eap_fast_getKey; - eap->get_emsk = eap_fast_get_emsk; - eap->isSuccess = eap_fast_isSuccess; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_server/eap_gpsk.c b/contrib/hostapd/src/eap_server/eap_gpsk.c deleted file mode 100644 index d0c7559d75..0000000000 --- a/contrib/hostapd/src/eap_server/eap_gpsk.c +++ /dev/null @@ -1,633 +0,0 @@ -/* - * hostapd / EAP-GPSK (RFC 5433) server - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_server/eap_i.h" -#include "eap_common/eap_gpsk_common.h" - - -struct eap_gpsk_data { - enum { GPSK_1, GPSK_3, SUCCESS, FAILURE } state; - u8 rand_server[EAP_GPSK_RAND_LEN]; - u8 rand_peer[EAP_GPSK_RAND_LEN]; - u8 msk[EAP_MSK_LEN]; - u8 emsk[EAP_EMSK_LEN]; - u8 sk[EAP_GPSK_MAX_SK_LEN]; - size_t sk_len; - u8 pk[EAP_GPSK_MAX_PK_LEN]; - size_t pk_len; - u8 *id_peer; - size_t id_peer_len; - u8 *id_server; - size_t id_server_len; -#define MAX_NUM_CSUITES 2 - struct eap_gpsk_csuite csuite_list[MAX_NUM_CSUITES]; - size_t csuite_count; - int vendor; /* CSuite/Vendor */ - int specifier; /* CSuite/Specifier */ -}; - - -static const char * eap_gpsk_state_txt(int state) -{ - switch (state) { - case GPSK_1: - return "GPSK-1"; - case GPSK_3: - return "GPSK-3"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "?"; - } -} - - -static void eap_gpsk_state(struct eap_gpsk_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-GPSK: %s -> %s", - eap_gpsk_state_txt(data->state), - eap_gpsk_state_txt(state)); - data->state = state; -} - - -static void * eap_gpsk_init(struct eap_sm *sm) -{ - struct eap_gpsk_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = GPSK_1; - - /* TODO: add support for configuring ID_Server */ - data->id_server = (u8 *) os_strdup("hostapd"); - if (data->id_server) - data->id_server_len = os_strlen((char *) data->id_server); - - data->csuite_count = 0; - if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF, - EAP_GPSK_CIPHER_AES)) { - WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor, - EAP_GPSK_VENDOR_IETF); - WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier, - EAP_GPSK_CIPHER_AES); - data->csuite_count++; - } - if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF, - EAP_GPSK_CIPHER_SHA256)) { - WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor, - EAP_GPSK_VENDOR_IETF); - WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier, - EAP_GPSK_CIPHER_SHA256); - data->csuite_count++; - } - - return data; -} - - -static void eap_gpsk_reset(struct eap_sm *sm, void *priv) -{ - struct eap_gpsk_data *data = priv; - os_free(data->id_server); - os_free(data->id_peer); - os_free(data); -} - - -static struct wpabuf * eap_gpsk_build_gpsk_1(struct eap_sm *sm, - struct eap_gpsk_data *data, u8 id) -{ - size_t len; - struct wpabuf *req; - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-1"); - - if (os_get_random(data->rand_server, EAP_GPSK_RAND_LEN)) { - wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to get random data"); - eap_gpsk_state(data, FAILURE); - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, "EAP-GPSK: RAND_Server", - data->rand_server, EAP_GPSK_RAND_LEN); - - len = 1 + 2 + data->id_server_len + EAP_GPSK_RAND_LEN + 2 + - data->csuite_count * sizeof(struct eap_gpsk_csuite); - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to allocate memory " - "for request/GPSK-1"); - eap_gpsk_state(data, FAILURE); - return NULL; - } - - wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_1); - wpabuf_put_be16(req, data->id_server_len); - wpabuf_put_data(req, data->id_server, data->id_server_len); - wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN); - wpabuf_put_be16(req, - data->csuite_count * sizeof(struct eap_gpsk_csuite)); - wpabuf_put_data(req, data->csuite_list, - data->csuite_count * sizeof(struct eap_gpsk_csuite)); - - return req; -} - - -static struct wpabuf * eap_gpsk_build_gpsk_3(struct eap_sm *sm, - struct eap_gpsk_data *data, u8 id) -{ - u8 *pos, *start; - size_t len, miclen; - struct eap_gpsk_csuite *csuite; - struct wpabuf *req; - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-3"); - - miclen = eap_gpsk_mic_len(data->vendor, data->specifier); - len = 1 + 2 * EAP_GPSK_RAND_LEN + 2 + data->id_server_len + - sizeof(struct eap_gpsk_csuite) + 2 + miclen; - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to allocate memory " - "for request/GPSK-3"); - eap_gpsk_state(data, FAILURE); - return NULL; - } - - wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_3); - start = wpabuf_put(req, 0); - - wpabuf_put_data(req, data->rand_peer, EAP_GPSK_RAND_LEN); - wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN); - wpabuf_put_be16(req, data->id_server_len); - wpabuf_put_data(req, data->id_server, data->id_server_len); - csuite = wpabuf_put(req, sizeof(*csuite)); - WPA_PUT_BE32(csuite->vendor, data->vendor); - WPA_PUT_BE16(csuite->specifier, data->specifier); - - /* no PD_Payload_2 */ - wpabuf_put_be16(req, 0); - - pos = wpabuf_put(req, miclen); - if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, - data->specifier, start, pos - start, pos) < 0) - { - os_free(req); - eap_gpsk_state(data, FAILURE); - return NULL; - } - - return req; -} - - -static struct wpabuf * eap_gpsk_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_gpsk_data *data = priv; - - switch (data->state) { - case GPSK_1: - return eap_gpsk_build_gpsk_1(sm, data, id); - case GPSK_3: - return eap_gpsk_build_gpsk_3(sm, data, id); - default: - wpa_printf(MSG_DEBUG, "EAP-GPSK: Unknown state %d in buildReq", - data->state); - break; - } - return NULL; -} - - -static Boolean eap_gpsk_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_gpsk_data *data = priv; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-GPSK: Invalid frame"); - return TRUE; - } - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode=%d", *pos); - - if (data->state == GPSK_1 && *pos == EAP_GPSK_OPCODE_GPSK_2) - return FALSE; - - if (data->state == GPSK_3 && *pos == EAP_GPSK_OPCODE_GPSK_4) - return FALSE; - - wpa_printf(MSG_INFO, "EAP-GPSK: Unexpected opcode=%d in state=%d", - *pos, data->state); - - return TRUE; -} - - -static void eap_gpsk_process_gpsk_2(struct eap_sm *sm, - struct eap_gpsk_data *data, - const u8 *payload, size_t payloadlen) -{ - const u8 *pos, *end; - u16 alen; - const struct eap_gpsk_csuite *csuite; - size_t i, miclen; - u8 mic[EAP_GPSK_MAX_MIC_LEN]; - - if (data->state != GPSK_1) - return; - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-2"); - - pos = payload; - end = payload + payloadlen; - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "ID_Peer length"); - eap_gpsk_state(data, FAILURE); - return; - } - alen = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < alen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "ID_Peer"); - eap_gpsk_state(data, FAILURE); - return; - } - os_free(data->id_peer); - data->id_peer = os_malloc(alen); - if (data->id_peer == NULL) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Not enough memory to store " - "%d-octet ID_Peer", alen); - return; - } - os_memcpy(data->id_peer, pos, alen); - data->id_peer_len = alen; - wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer", - data->id_peer, data->id_peer_len); - pos += alen; - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "ID_Server length"); - eap_gpsk_state(data, FAILURE); - return; - } - alen = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < alen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "ID_Server"); - eap_gpsk_state(data, FAILURE); - return; - } - if (alen != data->id_server_len || - os_memcmp(pos, data->id_server, alen) != 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1 and " - "GPSK-2 did not match"); - eap_gpsk_state(data, FAILURE); - return; - } - pos += alen; - - if (end - pos < EAP_GPSK_RAND_LEN) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "RAND_Peer"); - eap_gpsk_state(data, FAILURE); - return; - } - os_memcpy(data->rand_peer, pos, EAP_GPSK_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer", - data->rand_peer, EAP_GPSK_RAND_LEN); - pos += EAP_GPSK_RAND_LEN; - - if (end - pos < EAP_GPSK_RAND_LEN) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "RAND_Server"); - eap_gpsk_state(data, FAILURE); - return; - } - if (os_memcmp(data->rand_server, pos, EAP_GPSK_RAND_LEN) != 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and " - "GPSK-2 did not match"); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1", - data->rand_server, EAP_GPSK_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-2", - pos, EAP_GPSK_RAND_LEN); - eap_gpsk_state(data, FAILURE); - return; - } - pos += EAP_GPSK_RAND_LEN; - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "CSuite_List length"); - eap_gpsk_state(data, FAILURE); - return; - } - alen = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < alen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "CSuite_List"); - eap_gpsk_state(data, FAILURE); - return; - } - if (alen != data->csuite_count * sizeof(struct eap_gpsk_csuite) || - os_memcmp(pos, data->csuite_list, alen) != 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List in GPSK-1 and " - "GPSK-2 did not match"); - eap_gpsk_state(data, FAILURE); - return; - } - pos += alen; - - if (end - pos < (int) sizeof(*csuite)) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "CSuite_Sel"); - eap_gpsk_state(data, FAILURE); - return; - } - csuite = (const struct eap_gpsk_csuite *) pos; - for (i = 0; i < data->csuite_count; i++) { - if (os_memcmp(csuite, &data->csuite_list[i], sizeof(*csuite)) - == 0) - break; - } - if (i == data->csuite_count) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Peer selected unsupported " - "ciphersuite %d:%d", - WPA_GET_BE32(csuite->vendor), - WPA_GET_BE16(csuite->specifier)); - eap_gpsk_state(data, FAILURE); - return; - } - data->vendor = WPA_GET_BE32(csuite->vendor); - data->specifier = WPA_GET_BE16(csuite->specifier); - wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel %d:%d", - data->vendor, data->specifier); - pos += sizeof(*csuite); - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "PD_Payload_1 length"); - eap_gpsk_state(data, FAILURE); - return; - } - alen = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < alen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "PD_Payload_1"); - eap_gpsk_state(data, FAILURE); - return; - } - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen); - pos += alen; - - if (sm->user == NULL || sm->user->password == NULL) { - wpa_printf(MSG_INFO, "EAP-GPSK: No PSK/password configured " - "for the user"); - eap_gpsk_state(data, FAILURE); - return; - } - - if (eap_gpsk_derive_keys(sm->user->password, sm->user->password_len, - data->vendor, data->specifier, - data->rand_peer, data->rand_server, - data->id_peer, data->id_peer_len, - data->id_server, data->id_server_len, - data->msk, data->emsk, - data->sk, &data->sk_len, - data->pk, &data->pk_len) < 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys"); - eap_gpsk_state(data, FAILURE); - return; - } - - miclen = eap_gpsk_mic_len(data->vendor, data->specifier); - if (end - pos < (int) miclen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC " - "(left=%lu miclen=%lu)", - (unsigned long) (end - pos), - (unsigned long) miclen); - eap_gpsk_state(data, FAILURE); - return; - } - if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, - data->specifier, payload, pos - payload, mic) - < 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC"); - eap_gpsk_state(data, FAILURE); - return; - } - if (os_memcmp(mic, pos, miclen) != 0) { - wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-2"); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen); - eap_gpsk_state(data, FAILURE); - return; - } - pos += miclen; - - if (pos != end) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra " - "data in the end of GPSK-2", - (unsigned long) (end - pos)); - } - - eap_gpsk_state(data, GPSK_3); -} - - -static void eap_gpsk_process_gpsk_4(struct eap_sm *sm, - struct eap_gpsk_data *data, - const u8 *payload, size_t payloadlen) -{ - const u8 *pos, *end; - u16 alen; - size_t miclen; - u8 mic[EAP_GPSK_MAX_MIC_LEN]; - - if (data->state != GPSK_3) - return; - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-4"); - - pos = payload; - end = payload + payloadlen; - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "PD_Payload_1 length"); - eap_gpsk_state(data, FAILURE); - return; - } - alen = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < alen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "PD_Payload_1"); - eap_gpsk_state(data, FAILURE); - return; - } - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen); - pos += alen; - - miclen = eap_gpsk_mic_len(data->vendor, data->specifier); - if (end - pos < (int) miclen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC " - "(left=%lu miclen=%lu)", - (unsigned long) (end - pos), - (unsigned long) miclen); - eap_gpsk_state(data, FAILURE); - return; - } - if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, - data->specifier, payload, pos - payload, mic) - < 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC"); - eap_gpsk_state(data, FAILURE); - return; - } - if (os_memcmp(mic, pos, miclen) != 0) { - wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-4"); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen); - eap_gpsk_state(data, FAILURE); - return; - } - pos += miclen; - - if (pos != end) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra " - "data in the end of GPSK-4", - (unsigned long) (end - pos)); - } - - eap_gpsk_state(data, SUCCESS); -} - - -static void eap_gpsk_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_gpsk_data *data = priv; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len); - if (pos == NULL || len < 1) - return; - - switch (*pos) { - case EAP_GPSK_OPCODE_GPSK_2: - eap_gpsk_process_gpsk_2(sm, data, pos + 1, len - 1); - break; - case EAP_GPSK_OPCODE_GPSK_4: - eap_gpsk_process_gpsk_4(sm, data, pos + 1, len - 1); - break; - } -} - - -static Boolean eap_gpsk_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_gpsk_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_gpsk_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_gpsk_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->msk, EAP_MSK_LEN); - *len = EAP_MSK_LEN; - - return key; -} - - -static u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_gpsk_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - - return key; -} - - -static Boolean eap_gpsk_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_gpsk_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_gpsk_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK"); - if (eap == NULL) - return -1; - - eap->init = eap_gpsk_init; - eap->reset = eap_gpsk_reset; - eap->buildReq = eap_gpsk_buildReq; - eap->check = eap_gpsk_check; - eap->process = eap_gpsk_process; - eap->isDone = eap_gpsk_isDone; - eap->getKey = eap_gpsk_getKey; - eap->isSuccess = eap_gpsk_isSuccess; - eap->get_emsk = eap_gpsk_get_emsk; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_server/eap_gtc.c b/contrib/hostapd/src/eap_server/eap_gtc.c deleted file mode 100644 index 97e328b83f..0000000000 --- a/contrib/hostapd/src/eap_server/eap_gtc.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * hostapd / EAP-GTC (RFC 3748) - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" - - -struct eap_gtc_data { - enum { CONTINUE, SUCCESS, FAILURE } state; - int prefix; -}; - - -static void * eap_gtc_init(struct eap_sm *sm) -{ - struct eap_gtc_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = CONTINUE; - -#ifdef EAP_FAST - if (sm->m && sm->m->vendor == EAP_VENDOR_IETF && - sm->m->method == EAP_TYPE_FAST) { - wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix " - "with challenge/response"); - data->prefix = 1; - } -#endif /* EAP_FAST */ - - return data; -} - - -static void eap_gtc_reset(struct eap_sm *sm, void *priv) -{ - struct eap_gtc_data *data = priv; - os_free(data); -} - - -static struct wpabuf * eap_gtc_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_gtc_data *data = priv; - struct wpabuf *req; - char *msg; - size_t msg_len; - - msg = data->prefix ? "CHALLENGE=Password" : "Password"; - - msg_len = os_strlen(msg); - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, msg_len, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-GTC: Failed to allocate memory for " - "request"); - data->state = FAILURE; - return NULL; - } - - wpabuf_put_data(req, msg, msg_len); - - data->state = CONTINUE; - - return req; -} - - -static Boolean eap_gtc_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, respData, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-GTC: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static void eap_gtc_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_gtc_data *data = priv; - const u8 *pos; - size_t rlen; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, respData, &rlen); - if (pos == NULL || rlen < 1) - return; /* Should not happen - frame already validated */ - - wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response", pos, rlen); - -#ifdef EAP_FAST - if (data->prefix) { - const u8 *pos2, *end; - /* "RESPONSE=\0" */ - if (rlen < 10) { - wpa_printf(MSG_DEBUG, "EAP-GTC: Too short response " - "for EAP-FAST prefix"); - data->state = FAILURE; - return; - } - - end = pos + rlen; - pos += 9; - pos2 = pos; - while (pos2 < end && *pos2) - pos2++; - if (pos2 == end) { - wpa_printf(MSG_DEBUG, "EAP-GTC: No password in " - "response to EAP-FAST prefix"); - data->state = FAILURE; - return; - } - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Response user", - pos, pos2 - pos); - if (sm->identity && sm->require_identity_match && - (pos2 - pos != (int) sm->identity_len || - os_memcmp(pos, sm->identity, sm->identity_len))) { - wpa_printf(MSG_DEBUG, "EAP-GTC: Phase 2 Identity did " - "not match with required Identity"); - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Expected " - "identity", - sm->identity, sm->identity_len); - data->state = FAILURE; - return; - } else { - os_free(sm->identity); - sm->identity_len = pos2 - pos; - sm->identity = os_malloc(sm->identity_len); - if (sm->identity == NULL) { - data->state = FAILURE; - return; - } - os_memcpy(sm->identity, pos, sm->identity_len); - } - - if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-GTC: Phase2 " - "Identity not found in the user " - "database", - sm->identity, sm->identity_len); - data->state = FAILURE; - return; - } - - pos = pos2 + 1; - rlen = end - pos; - wpa_hexdump_ascii_key(MSG_MSGDUMP, - "EAP-GTC: Response password", - pos, rlen); - } -#endif /* EAP_FAST */ - - if (sm->user == NULL || sm->user->password == NULL || - sm->user->password_hash) { - wpa_printf(MSG_INFO, "EAP-GTC: Plaintext password not " - "configured"); - data->state = FAILURE; - return; - } - - if (rlen != sm->user->password_len || - os_memcmp(pos, sm->user->password, rlen) != 0) { - wpa_printf(MSG_DEBUG, "EAP-GTC: Done - Failure"); - data->state = FAILURE; - } else { - wpa_printf(MSG_DEBUG, "EAP-GTC: Done - Success"); - data->state = SUCCESS; - } -} - - -static Boolean eap_gtc_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_gtc_data *data = priv; - return data->state != CONTINUE; -} - - -static Boolean eap_gtc_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_gtc_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_gtc_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC"); - if (eap == NULL) - return -1; - - eap->init = eap_gtc_init; - eap->reset = eap_gtc_reset; - eap->buildReq = eap_gtc_buildReq; - eap->check = eap_gtc_check; - eap->process = eap_gtc_process; - eap->isDone = eap_gtc_isDone; - eap->isSuccess = eap_gtc_isSuccess; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_server/eap_i.h b/contrib/hostapd/src/eap_server/eap_i.h deleted file mode 100644 index d52b86f955..0000000000 --- a/contrib/hostapd/src/eap_server/eap_i.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - * hostapd / EAP Authenticator state machine internal structures (RFC 4137) - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_I_H -#define EAP_I_H - -#include "wpabuf.h" -#include "eap_server/eap.h" -#include "eap_common/eap_common.h" - -/* RFC 4137 - EAP Standalone Authenticator */ - -/** - * struct eap_method - EAP method interface - * This structure defines the EAP method interface. Each method will need to - * register its own EAP type, EAP name, and set of function pointers for method - * specific operations. This interface is based on section 5.4 of RFC 4137. - */ -struct eap_method { - int vendor; - EapType method; - const char *name; - - void * (*init)(struct eap_sm *sm); - void * (*initPickUp)(struct eap_sm *sm); - void (*reset)(struct eap_sm *sm, void *priv); - - struct wpabuf * (*buildReq)(struct eap_sm *sm, void *priv, u8 id); - int (*getTimeout)(struct eap_sm *sm, void *priv); - Boolean (*check)(struct eap_sm *sm, void *priv, - struct wpabuf *respData); - void (*process)(struct eap_sm *sm, void *priv, - struct wpabuf *respData); - Boolean (*isDone)(struct eap_sm *sm, void *priv); - u8 * (*getKey)(struct eap_sm *sm, void *priv, size_t *len); - /* isSuccess is not specified in draft-ietf-eap-statemachine-05.txt, - * but it is useful in implementing Policy.getDecision() */ - Boolean (*isSuccess)(struct eap_sm *sm, void *priv); - - /** - * free - Free EAP method data - * @method: Pointer to the method data registered with - * eap_server_method_register(). - * - * This function will be called when the EAP method is being - * unregistered. If the EAP method allocated resources during - * registration (e.g., allocated struct eap_method), they should be - * freed in this function. No other method functions will be called - * after this call. If this function is not defined (i.e., function - * pointer is %NULL), a default handler is used to release the method - * data with free(method). This is suitable for most cases. - */ - void (*free)(struct eap_method *method); - -#define EAP_SERVER_METHOD_INTERFACE_VERSION 1 - /** - * version - Version of the EAP server method interface - * - * The EAP server method implementation should set this variable to - * EAP_SERVER_METHOD_INTERFACE_VERSION. This is used to verify that the - * EAP method is using supported API version when using dynamically - * loadable EAP methods. - */ - int version; - - /** - * next - Pointer to the next EAP method - * - * This variable is used internally in the EAP method registration code - * to create a linked list of registered EAP methods. - */ - struct eap_method *next; - - /** - * get_emsk - Get EAP method specific keying extended material (EMSK) - * @sm: Pointer to EAP state machine allocated with eap_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * @len: Pointer to a variable to store EMSK length - * Returns: EMSK or %NULL if not available - * - * This function can be used to get the extended keying material from - * the EAP method. The key may already be stored in the method-specific - * private data or this function may derive the key. - */ - u8 * (*get_emsk)(struct eap_sm *sm, void *priv, size_t *len); -}; - -/** - * struct eap_sm - EAP server state machine data - */ -struct eap_sm { - enum { - EAP_DISABLED, EAP_INITIALIZE, EAP_IDLE, EAP_RECEIVED, - EAP_INTEGRITY_CHECK, EAP_METHOD_RESPONSE, EAP_METHOD_REQUEST, - EAP_PROPOSE_METHOD, EAP_SELECT_ACTION, EAP_SEND_REQUEST, - EAP_DISCARD, EAP_NAK, EAP_RETRANSMIT, EAP_SUCCESS, EAP_FAILURE, - EAP_TIMEOUT_FAILURE, EAP_PICK_UP_METHOD, - EAP_INITIALIZE_PASSTHROUGH, EAP_IDLE2, EAP_RETRANSMIT2, - EAP_RECEIVED2, EAP_DISCARD2, EAP_SEND_REQUEST2, - EAP_AAA_REQUEST, EAP_AAA_RESPONSE, EAP_AAA_IDLE, - EAP_TIMEOUT_FAILURE2, EAP_FAILURE2, EAP_SUCCESS2 - } EAP_state; - - /* Constants */ - int MaxRetrans; - - struct eap_eapol_interface eap_if; - - /* Full authenticator state machine local variables */ - - /* Long-term (maintained betwen packets) */ - EapType currentMethod; - int currentId; - enum { - METHOD_PROPOSED, METHOD_CONTINUE, METHOD_END - } methodState; - int retransCount; - struct wpabuf *lastReqData; - int methodTimeout; - - /* Short-term (not maintained between packets) */ - Boolean rxResp; - int respId; - EapType respMethod; - int respVendor; - u32 respVendorMethod; - Boolean ignore; - enum { - DECISION_SUCCESS, DECISION_FAILURE, DECISION_CONTINUE, - DECISION_PASSTHROUGH - } decision; - - /* Miscellaneous variables */ - const struct eap_method *m; /* selected EAP method */ - /* not defined in RFC 4137 */ - Boolean changed; - void *eapol_ctx, *msg_ctx; - struct eapol_callbacks *eapol_cb; - void *eap_method_priv; - u8 *identity; - size_t identity_len; - /* Whether Phase 2 method should validate identity match */ - int require_identity_match; - int lastId; /* Identifier used in the last EAP-Packet */ - struct eap_user *user; - int user_eap_method_index; - int init_phase2; - void *ssl_ctx; - void *eap_sim_db_priv; - Boolean backend_auth; - Boolean update_user; - int eap_server; - - int num_rounds; - enum { - METHOD_PENDING_NONE, METHOD_PENDING_WAIT, METHOD_PENDING_CONT - } method_pending; - - u8 *auth_challenge; - u8 *peer_challenge; - - u8 *pac_opaque_encr_key; - u8 *eap_fast_a_id; - size_t eap_fast_a_id_len; - char *eap_fast_a_id_info; - enum { - NO_PROV, ANON_PROV, AUTH_PROV, BOTH_PROV - } eap_fast_prov; - int pac_key_lifetime; - int pac_key_refresh_time; - int eap_sim_aka_result_ind; - int tnc; - struct wps_context *wps; - struct wpabuf *assoc_wps_ie; - - Boolean start_reauth; -}; - -int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len, - int phase2); -void eap_sm_process_nak(struct eap_sm *sm, const u8 *nak_list, size_t len); - -#endif /* EAP_I_H */ diff --git a/contrib/hostapd/src/eap_server/eap_identity.c b/contrib/hostapd/src/eap_server/eap_identity.c deleted file mode 100644 index cd8da2a632..0000000000 --- a/contrib/hostapd/src/eap_server/eap_identity.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * hostapd / EAP-Identity - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" - - -struct eap_identity_data { - enum { CONTINUE, SUCCESS, FAILURE } state; - int pick_up; -}; - - -static void * eap_identity_init(struct eap_sm *sm) -{ - struct eap_identity_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = CONTINUE; - - return data; -} - - -static void * eap_identity_initPickUp(struct eap_sm *sm) -{ - struct eap_identity_data *data; - data = eap_identity_init(sm); - if (data) { - data->pick_up = 1; - } - return data; -} - - -static void eap_identity_reset(struct eap_sm *sm, void *priv) -{ - struct eap_identity_data *data = priv; - os_free(data); -} - - -static struct wpabuf * eap_identity_buildReq(struct eap_sm *sm, void *priv, - u8 id) -{ - struct eap_identity_data *data = priv; - struct wpabuf *req; - const char *req_data; - size_t req_data_len; - - if (sm->eapol_cb->get_eap_req_id_text) { - req_data = sm->eapol_cb->get_eap_req_id_text(sm->eapol_ctx, - &req_data_len); - } else { - req_data = NULL; - req_data_len = 0; - } - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, req_data_len, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-Identity: Failed to allocate " - "memory for request"); - data->state = FAILURE; - return NULL; - } - - wpabuf_put_data(req, req_data, req_data_len); - - return req; -} - - -static Boolean eap_identity_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, - respData, &len); - if (pos == NULL) { - wpa_printf(MSG_INFO, "EAP-Identity: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static void eap_identity_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_identity_data *data = priv; - const u8 *pos; - size_t len; - - if (data->pick_up) { - if (eap_identity_check(sm, data, respData)) { - wpa_printf(MSG_DEBUG, "EAP-Identity: failed to pick " - "up already started negotiation"); - data->state = FAILURE; - return; - } - data->pick_up = 0; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, - respData, &len); - if (pos == NULL) - return; /* Should not happen - frame already validated */ - - wpa_hexdump_ascii(MSG_DEBUG, "EAP-Identity: Peer identity", pos, len); - if (sm->identity) - sm->update_user = TRUE; - os_free(sm->identity); - sm->identity = os_malloc(len ? len : 1); - if (sm->identity == NULL) { - data->state = FAILURE; - } else { - os_memcpy(sm->identity, pos, len); - sm->identity_len = len; - data->state = SUCCESS; - } -} - - -static Boolean eap_identity_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_identity_data *data = priv; - return data->state != CONTINUE; -} - - -static Boolean eap_identity_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_identity_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_identity_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, - "Identity"); - if (eap == NULL) - return -1; - - eap->init = eap_identity_init; - eap->initPickUp = eap_identity_initPickUp; - eap->reset = eap_identity_reset; - eap->buildReq = eap_identity_buildReq; - eap->check = eap_identity_check; - eap->process = eap_identity_process; - eap->isDone = eap_identity_isDone; - eap->isSuccess = eap_identity_isSuccess; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_server/eap_ikev2.c b/contrib/hostapd/src/eap_server/eap_ikev2.c deleted file mode 100644 index 06074ee28f..0000000000 --- a/contrib/hostapd/src/eap_server/eap_ikev2.c +++ /dev/null @@ -1,538 +0,0 @@ -/* - * EAP-IKEv2 server (RFC 5106) - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "eap_common/eap_ikev2_common.h" -#include "ikev2.h" - - -struct eap_ikev2_data { - struct ikev2_initiator_data ikev2; - enum { MSG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state; - struct wpabuf *in_buf; - struct wpabuf *out_buf; - size_t out_used; - size_t fragment_size; - int keys_ready; - u8 keymat[EAP_MSK_LEN + EAP_EMSK_LEN]; - int keymat_ok; -}; - - -static const u8 * eap_ikev2_get_shared_secret(void *ctx, const u8 *IDr, - size_t IDr_len, - size_t *secret_len) -{ - struct eap_sm *sm = ctx; - - if (IDr == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: No IDr received - default " - "to user identity from EAP-Identity"); - IDr = sm->identity; - IDr_len = sm->identity_len; - } - - if (eap_user_get(sm, IDr, IDr_len, 0) < 0 || sm->user == NULL || - sm->user->password == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: No user entry found"); - return NULL; - } - - *secret_len = sm->user->password_len; - return sm->user->password; -} - - -static const char * eap_ikev2_state_txt(int state) -{ - switch (state) { - case MSG: - return "MSG"; - case FRAG_ACK: - return "FRAG_ACK"; - case WAIT_FRAG_ACK: - return "WAIT_FRAG_ACK"; - case DONE: - return "DONE"; - case FAIL: - return "FAIL"; - default: - return "?"; - } -} - - -static void eap_ikev2_state(struct eap_ikev2_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-IKEV2: %s -> %s", - eap_ikev2_state_txt(data->state), - eap_ikev2_state_txt(state)); - data->state = state; -} - - -static void * eap_ikev2_init(struct eap_sm *sm) -{ - struct eap_ikev2_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = MSG; - data->fragment_size = IKEV2_FRAGMENT_SIZE; - data->ikev2.state = SA_INIT; - data->ikev2.peer_auth = PEER_AUTH_SECRET; - data->ikev2.key_pad = (u8 *) os_strdup("Key Pad for EAP-IKEv2"); - if (data->ikev2.key_pad == NULL) - goto failed; - data->ikev2.key_pad_len = 21; - - /* TODO: make proposals configurable */ - data->ikev2.proposal.proposal_num = 1; - data->ikev2.proposal.integ = AUTH_HMAC_SHA1_96; - data->ikev2.proposal.prf = PRF_HMAC_SHA1; - data->ikev2.proposal.encr = ENCR_AES_CBC; - data->ikev2.proposal.dh = DH_GROUP2_1024BIT_MODP; - - data->ikev2.IDi = (u8 *) os_strdup("hostapd"); - data->ikev2.IDi_len = 7; - - data->ikev2.get_shared_secret = eap_ikev2_get_shared_secret; - data->ikev2.cb_ctx = sm; - - return data; - -failed: - ikev2_initiator_deinit(&data->ikev2); - os_free(data); - return NULL; -} - - -static void eap_ikev2_reset(struct eap_sm *sm, void *priv) -{ - struct eap_ikev2_data *data = priv; - wpabuf_free(data->in_buf); - wpabuf_free(data->out_buf); - ikev2_initiator_deinit(&data->ikev2); - os_free(data); -} - - -static struct wpabuf * eap_ikev2_build_msg(struct eap_ikev2_data *data, u8 id) -{ - struct wpabuf *req; - u8 flags; - size_t send_len, plen, icv_len = 0; - - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Generating Request"); - - flags = 0; - send_len = wpabuf_len(data->out_buf) - data->out_used; - if (1 + send_len > data->fragment_size) { - send_len = data->fragment_size - 1; - flags |= IKEV2_FLAGS_MORE_FRAGMENTS; - if (data->out_used == 0) { - flags |= IKEV2_FLAGS_LENGTH_INCLUDED; - send_len -= 4; - } - } - - plen = 1 + send_len; - if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) - plen += 4; - if (data->keys_ready) { - const struct ikev2_integ_alg *integ; - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Add Integrity Checksum " - "Data"); - flags |= IKEV2_FLAGS_ICV_INCLUDED; - integ = ikev2_get_integ(data->ikev2.proposal.integ); - if (integ == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG " - "transform / cannot generate ICV"); - return NULL; - } - icv_len = integ->hash_len; - - plen += icv_len; - } - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, plen, - EAP_CODE_REQUEST, id); - if (req == NULL) - return NULL; - - wpabuf_put_u8(req, flags); /* Flags */ - if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) - wpabuf_put_be32(req, wpabuf_len(data->out_buf)); - - wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used, - send_len); - data->out_used += send_len; - - if (flags & IKEV2_FLAGS_ICV_INCLUDED) { - const u8 *msg = wpabuf_head(req); - size_t len = wpabuf_len(req); - ikev2_integ_hash(data->ikev2.proposal.integ, - data->ikev2.keys.SK_ai, - data->ikev2.keys.SK_integ_len, - msg, len, wpabuf_put(req, icv_len)); - } - - if (data->out_used == wpabuf_len(data->out_buf)) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes " - "(message sent completely)", - (unsigned long) send_len); - wpabuf_free(data->out_buf); - data->out_buf = NULL; - data->out_used = 0; - } else { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes " - "(%lu more to send)", (unsigned long) send_len, - (unsigned long) wpabuf_len(data->out_buf) - - data->out_used); - eap_ikev2_state(data, WAIT_FRAG_ACK); - } - - return req; -} - - -static struct wpabuf * eap_ikev2_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_ikev2_data *data = priv; - - switch (data->state) { - case MSG: - if (data->out_buf == NULL) { - data->out_buf = ikev2_initiator_build(&data->ikev2); - if (data->out_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to " - "generate IKEv2 message"); - return NULL; - } - data->out_used = 0; - } - /* pass through */ - case WAIT_FRAG_ACK: - return eap_ikev2_build_msg(data, id); - case FRAG_ACK: - return eap_ikev2_build_frag_ack(id, EAP_CODE_REQUEST); - default: - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected state %d in " - "buildReq", data->state); - return NULL; - } -} - - -static Boolean eap_ikev2_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, respData, - &len); - if (pos == NULL) { - wpa_printf(MSG_INFO, "EAP-IKEV2: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static int eap_ikev2_process_icv(struct eap_ikev2_data *data, - const struct wpabuf *respData, - u8 flags, const u8 *pos, const u8 **end) -{ - if (flags & IKEV2_FLAGS_ICV_INCLUDED) { - int icv_len = eap_ikev2_validate_icv( - data->ikev2.proposal.integ, &data->ikev2.keys, 0, - respData, pos, *end); - if (icv_len < 0) - return -1; - /* Hide Integrity Checksum Data from further processing */ - *end -= icv_len; - } else if (data->keys_ready) { - wpa_printf(MSG_INFO, "EAP-IKEV2: The message should have " - "included integrity checksum"); - return -1; - } - - return 0; -} - - -static int eap_ikev2_process_cont(struct eap_ikev2_data *data, - const u8 *buf, size_t len) -{ - /* Process continuation of a pending message */ - if (len > wpabuf_tailroom(data->in_buf)) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment overflow"); - eap_ikev2_state(data, FAIL); - return -1; - } - - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received %lu bytes, waiting for %lu " - "bytes more", (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - - return 0; -} - - -static int eap_ikev2_process_fragment(struct eap_ikev2_data *data, - u8 flags, u32 message_length, - const u8 *buf, size_t len) -{ - /* Process a fragment that is not the last one of the message */ - if (data->in_buf == NULL && !(flags & IKEV2_FLAGS_LENGTH_INCLUDED)) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: No Message Length field in " - "a fragmented packet"); - return -1; - } - - if (data->in_buf == NULL) { - /* First fragment of the message */ - data->in_buf = wpabuf_alloc(message_length); - if (data->in_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: No memory for " - "message"); - return -1; - } - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received %lu bytes in first " - "fragment, waiting for %lu bytes more", - (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - } - - return 0; -} - - -static int eap_ikev2_server_keymat(struct eap_ikev2_data *data) -{ - if (eap_ikev2_derive_keymat( - data->ikev2.proposal.prf, &data->ikev2.keys, - data->ikev2.i_nonce, data->ikev2.i_nonce_len, - data->ikev2.r_nonce, data->ikev2.r_nonce_len, - data->keymat) < 0) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to derive " - "key material"); - return -1; - } - data->keymat_ok = 1; - return 0; -} - - -static void eap_ikev2_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_ikev2_data *data = priv; - const u8 *start, *pos, *end; - size_t len; - u8 flags; - u32 message_length = 0; - struct wpabuf tmpbuf; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, respData, - &len); - if (pos == NULL) - return; /* Should not happen; message already verified */ - - start = pos; - end = start + len; - - if (len == 0) { - /* fragment ack */ - flags = 0; - } else - flags = *pos++; - - if (eap_ikev2_process_icv(data, respData, flags, pos, &end) < 0) { - eap_ikev2_state(data, FAIL); - return; - } - - if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) { - if (end - pos < 4) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Message underflow"); - eap_ikev2_state(data, FAIL); - return; - } - message_length = WPA_GET_BE32(pos); - pos += 4; - - if (message_length < (u32) (end - pos)) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Invalid Message " - "Length (%d; %ld remaining in this msg)", - message_length, (long) (end - pos)); - eap_ikev2_state(data, FAIL); - return; - } - } - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received packet: Flags 0x%x " - "Message Length %u", flags, message_length); - - if (data->state == WAIT_FRAG_ACK) { - if (len != 0) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected payload " - "in WAIT_FRAG_ACK state"); - eap_ikev2_state(data, FAIL); - return; - } - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment acknowledged"); - eap_ikev2_state(data, MSG); - return; - } - - if (data->in_buf && eap_ikev2_process_cont(data, pos, end - pos) < 0) { - eap_ikev2_state(data, FAIL); - return; - } - - if (flags & IKEV2_FLAGS_MORE_FRAGMENTS) { - if (eap_ikev2_process_fragment(data, flags, message_length, - pos, end - pos) < 0) - eap_ikev2_state(data, FAIL); - else - eap_ikev2_state(data, FRAG_ACK); - return; - } else if (data->state == FRAG_ACK) { - wpa_printf(MSG_DEBUG, "EAP-TNC: All fragments received"); - data->state = MSG; - } - - if (data->in_buf == NULL) { - /* Wrap unfragmented messages as wpabuf without extra copy */ - wpabuf_set(&tmpbuf, pos, end - pos); - data->in_buf = &tmpbuf; - } - - if (ikev2_initiator_process(&data->ikev2, data->in_buf) < 0) { - if (data->in_buf == &tmpbuf) - data->in_buf = NULL; - eap_ikev2_state(data, FAIL); - return; - } - - switch (data->ikev2.state) { - case SA_AUTH: - /* SA_INIT was sent out, so message have to be - * integrity protected from now on. */ - data->keys_ready = 1; - break; - case IKEV2_DONE: - if (data->state == FAIL) - break; - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Authentication completed " - "successfully"); - if (eap_ikev2_server_keymat(data)) - break; - eap_ikev2_state(data, DONE); - break; - default: - break; - } - - if (data->in_buf != &tmpbuf) - wpabuf_free(data->in_buf); - data->in_buf = NULL; -} - - -static Boolean eap_ikev2_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_ikev2_data *data = priv; - return data->state == DONE || data->state == FAIL; -} - - -static Boolean eap_ikev2_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_ikev2_data *data = priv; - return data->state == DONE && data->ikev2.state == IKEV2_DONE && - data->keymat_ok; -} - - -static u8 * eap_ikev2_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_ikev2_data *data = priv; - u8 *key; - - if (data->state != DONE || !data->keymat_ok) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key) { - os_memcpy(key, data->keymat, EAP_MSK_LEN); - *len = EAP_MSK_LEN; - } - - return key; -} - - -static u8 * eap_ikev2_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_ikev2_data *data = priv; - u8 *key; - - if (data->state != DONE || !data->keymat_ok) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key) { - os_memcpy(key, data->keymat + EAP_MSK_LEN, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - } - - return key; -} - - -int eap_server_ikev2_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_IKEV2, - "IKEV2"); - if (eap == NULL) - return -1; - - eap->init = eap_ikev2_init; - eap->reset = eap_ikev2_reset; - eap->buildReq = eap_ikev2_buildReq; - eap->check = eap_ikev2_check; - eap->process = eap_ikev2_process; - eap->isDone = eap_ikev2_isDone; - eap->getKey = eap_ikev2_getKey; - eap->isSuccess = eap_ikev2_isSuccess; - eap->get_emsk = eap_ikev2_get_emsk; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_server/eap_md5.c b/contrib/hostapd/src/eap_server/eap_md5.c deleted file mode 100644 index dee2dc5a01..0000000000 --- a/contrib/hostapd/src/eap_server/eap_md5.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * hostapd / EAP-MD5 server - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "eap_common/chap.h" - - -#define CHALLENGE_LEN 16 - -struct eap_md5_data { - u8 challenge[CHALLENGE_LEN]; - enum { CONTINUE, SUCCESS, FAILURE } state; -}; - - -static void * eap_md5_init(struct eap_sm *sm) -{ - struct eap_md5_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = CONTINUE; - - return data; -} - - -static void eap_md5_reset(struct eap_sm *sm, void *priv) -{ - struct eap_md5_data *data = priv; - os_free(data); -} - - -static struct wpabuf * eap_md5_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_md5_data *data = priv; - struct wpabuf *req; - - if (os_get_random(data->challenge, CHALLENGE_LEN)) { - wpa_printf(MSG_ERROR, "EAP-MD5: Failed to get random data"); - data->state = FAILURE; - return NULL; - } - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, 1 + CHALLENGE_LEN, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-MD5: Failed to allocate memory for " - "request"); - data->state = FAILURE; - return NULL; - } - - wpabuf_put_u8(req, CHALLENGE_LEN); - wpabuf_put_data(req, data->challenge, CHALLENGE_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge", data->challenge, - CHALLENGE_LEN); - - data->state = CONTINUE; - - return req; -} - - -static Boolean eap_md5_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, respData, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame"); - return TRUE; - } - if (*pos != CHAP_MD5_LEN || 1 + CHAP_MD5_LEN > len) { - wpa_printf(MSG_INFO, "EAP-MD5: Invalid response " - "(response_len=%d payload_len=%lu", - *pos, (unsigned long) len); - return TRUE; - } - - return FALSE; -} - - -static void eap_md5_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_md5_data *data = priv; - const u8 *pos; - size_t plen; - u8 hash[CHAP_MD5_LEN], id; - - if (sm->user == NULL || sm->user->password == NULL || - sm->user->password_hash) { - wpa_printf(MSG_INFO, "EAP-MD5: Plaintext password not " - "configured"); - data->state = FAILURE; - return; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, respData, &plen); - if (pos == NULL || *pos != CHAP_MD5_LEN || plen < 1 + CHAP_MD5_LEN) - return; /* Should not happen - frame already validated */ - - pos++; /* Skip response len */ - wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", pos, CHAP_MD5_LEN); - - id = eap_get_id(respData); - chap_md5(id, sm->user->password, sm->user->password_len, - data->challenge, CHALLENGE_LEN, hash); - - if (os_memcmp(hash, pos, CHAP_MD5_LEN) == 0) { - wpa_printf(MSG_DEBUG, "EAP-MD5: Done - Success"); - data->state = SUCCESS; - } else { - wpa_printf(MSG_DEBUG, "EAP-MD5: Done - Failure"); - data->state = FAILURE; - } -} - - -static Boolean eap_md5_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_md5_data *data = priv; - return data->state != CONTINUE; -} - - -static Boolean eap_md5_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_md5_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_md5_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_MD5, "MD5"); - if (eap == NULL) - return -1; - - eap->init = eap_md5_init; - eap->reset = eap_md5_reset; - eap->buildReq = eap_md5_buildReq; - eap->check = eap_md5_check; - eap->process = eap_md5_process; - eap->isDone = eap_md5_isDone; - eap->isSuccess = eap_md5_isSuccess; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_server/eap_methods.c b/contrib/hostapd/src/eap_server/eap_methods.c deleted file mode 100644 index 4092d675b3..0000000000 --- a/contrib/hostapd/src/eap_server/eap_methods.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * hostapd / EAP method registration - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "eap_methods.h" - - -static struct eap_method *eap_methods; - - -/** - * eap_server_get_eap_method - Get EAP method based on type number - * @vendor: EAP Vendor-Id (0 = IETF) - * @method: EAP type number - * Returns: Pointer to EAP method or %NULL if not found - */ -const struct eap_method * eap_server_get_eap_method(int vendor, EapType method) -{ - struct eap_method *m; - for (m = eap_methods; m; m = m->next) { - if (m->vendor == vendor && m->method == method) - return m; - } - return NULL; -} - - -/** - * eap_server_get_type - Get EAP type for the given EAP method name - * @name: EAP method name, e.g., TLS - * @vendor: Buffer for returning EAP Vendor-Id - * Returns: EAP method type or %EAP_TYPE_NONE if not found - * - * This function maps EAP type names into EAP type numbers based on the list of - * EAP methods included in the build. - */ -EapType eap_server_get_type(const char *name, int *vendor) -{ - struct eap_method *m; - for (m = eap_methods; m; m = m->next) { - if (os_strcmp(m->name, name) == 0) { - *vendor = m->vendor; - return m->method; - } - } - *vendor = EAP_VENDOR_IETF; - return EAP_TYPE_NONE; -} - - -/** - * eap_server_method_alloc - Allocate EAP server method structure - * @version: Version of the EAP server method interface (set to - * EAP_SERVER_METHOD_INTERFACE_VERSION) - * @vendor: EAP Vendor-ID (EAP_VENDOR_*) (0 = IETF) - * @method: EAP type number (EAP_TYPE_*) - * @name: Name of the method (e.g., "TLS") - * Returns: Allocated EAP method structure or %NULL on failure - * - * The returned structure should be freed with eap_server_method_free() when it - * is not needed anymore. - */ -struct eap_method * eap_server_method_alloc(int version, int vendor, - EapType method, const char *name) -{ - struct eap_method *eap; - eap = os_zalloc(sizeof(*eap)); - if (eap == NULL) - return NULL; - eap->version = version; - eap->vendor = vendor; - eap->method = method; - eap->name = name; - return eap; -} - - -/** - * eap_server_method_free - Free EAP server method structure - * @method: Method structure allocated with eap_server_method_alloc() - */ -void eap_server_method_free(struct eap_method *method) -{ - os_free(method); -} - - -/** - * eap_server_method_register - Register an EAP server method - * @method: EAP method to register - * Returns: 0 on success, -1 on invalid method, or -2 if a matching EAP method - * has already been registered - * - * Each EAP server method needs to call this function to register itself as a - * supported EAP method. - */ -int eap_server_method_register(struct eap_method *method) -{ - struct eap_method *m, *last = NULL; - - if (method == NULL || method->name == NULL || - method->version != EAP_SERVER_METHOD_INTERFACE_VERSION) - return -1; - - for (m = eap_methods; m; m = m->next) { - if ((m->vendor == method->vendor && - m->method == method->method) || - os_strcmp(m->name, method->name) == 0) - return -2; - last = m; - } - - if (last) - last->next = method; - else - eap_methods = method; - - return 0; -} - - -/** - * eap_server_register_methods - Register statically linked EAP server methods - * Returns: 0 on success, -1 on failure - * - * This function is called at program initialization to register all EAP server - * methods that were linked in statically. - */ -int eap_server_register_methods(void) -{ - int ret = 0; - - if (ret == 0) { - int eap_server_identity_register(void); - ret = eap_server_identity_register(); - } - -#ifdef EAP_MD5 - if (ret == 0) { - int eap_server_md5_register(void); - ret = eap_server_md5_register(); - } -#endif /* EAP_MD5 */ - -#ifdef EAP_TLS - if (ret == 0) { - int eap_server_tls_register(void); - ret = eap_server_tls_register(); - } -#endif /* EAP_TLS */ - -#ifdef EAP_MSCHAPv2 - if (ret == 0) { - int eap_server_mschapv2_register(void); - ret = eap_server_mschapv2_register(); - } -#endif /* EAP_MSCHAPv2 */ - -#ifdef EAP_PEAP - if (ret == 0) { - int eap_server_peap_register(void); - ret = eap_server_peap_register(); - } -#endif /* EAP_PEAP */ - -#ifdef EAP_TLV - if (ret == 0) { - int eap_server_tlv_register(void); - ret = eap_server_tlv_register(); - } -#endif /* EAP_TLV */ - -#ifdef EAP_GTC - if (ret == 0) { - int eap_server_gtc_register(void); - ret = eap_server_gtc_register(); - } -#endif /* EAP_GTC */ - -#ifdef EAP_TTLS - if (ret == 0) { - int eap_server_ttls_register(void); - ret = eap_server_ttls_register(); - } -#endif /* EAP_TTLS */ - -#ifdef EAP_SIM - if (ret == 0) { - int eap_server_sim_register(void); - ret = eap_server_sim_register(); - } -#endif /* EAP_SIM */ - -#ifdef EAP_AKA - if (ret == 0) { - int eap_server_aka_register(void); - ret = eap_server_aka_register(); - } -#endif /* EAP_AKA */ - -#ifdef EAP_AKA_PRIME - if (ret == 0) { - int eap_server_aka_prime_register(void); - ret = eap_server_aka_prime_register(); - } -#endif /* EAP_AKA_PRIME */ - -#ifdef EAP_PAX - if (ret == 0) { - int eap_server_pax_register(void); - ret = eap_server_pax_register(); - } -#endif /* EAP_PAX */ - -#ifdef EAP_PSK - if (ret == 0) { - int eap_server_psk_register(void); - ret = eap_server_psk_register(); - } -#endif /* EAP_PSK */ - -#ifdef EAP_SAKE - if (ret == 0) { - int eap_server_sake_register(void); - ret = eap_server_sake_register(); - } -#endif /* EAP_SAKE */ - -#ifdef EAP_GPSK - if (ret == 0) { - int eap_server_gpsk_register(void); - ret = eap_server_gpsk_register(); - } -#endif /* EAP_GPSK */ - -#ifdef EAP_VENDOR_TEST - if (ret == 0) { - int eap_server_vendor_test_register(void); - ret = eap_server_vendor_test_register(); - } -#endif /* EAP_VENDOR_TEST */ - -#ifdef EAP_FAST - if (ret == 0) { - int eap_server_fast_register(void); - ret = eap_server_fast_register(); - } -#endif /* EAP_FAST */ - -#ifdef EAP_WSC - if (ret == 0) { - int eap_server_wsc_register(void); - ret = eap_server_wsc_register(); - } -#endif /* EAP_WSC */ - -#ifdef EAP_IKEV2 - if (ret == 0) { - int eap_server_ikev2_register(void); - ret = eap_server_ikev2_register(); - } -#endif /* EAP_IKEV2 */ - -#ifdef EAP_TNC - if (ret == 0) { - int eap_server_tnc_register(void); - ret = eap_server_tnc_register(); - } -#endif /* EAP_TNC */ - - return ret; -} - - -/** - * eap_server_unregister_methods - Unregister EAP server methods - * - * This function is called at program termination to unregister all EAP server - * methods. - */ -void eap_server_unregister_methods(void) -{ - struct eap_method *m; - - while (eap_methods) { - m = eap_methods; - eap_methods = eap_methods->next; - - if (m->free) - m->free(m); - else - eap_server_method_free(m); - } -} diff --git a/contrib/hostapd/src/eap_server/eap_methods.h b/contrib/hostapd/src/eap_server/eap_methods.h deleted file mode 100644 index 0fd53909ff..0000000000 --- a/contrib/hostapd/src/eap_server/eap_methods.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * hostapd / EAP method registration - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_METHODS_H -#define EAP_METHODS_H - -const struct eap_method * eap_server_get_eap_method(int vendor, - EapType method); -struct eap_method * eap_server_method_alloc(int version, int vendor, - EapType method, const char *name); -void eap_server_method_free(struct eap_method *method); -int eap_server_method_register(struct eap_method *method); - -EapType eap_server_get_type(const char *name, int *vendor); -int eap_server_register_methods(void); -void eap_server_unregister_methods(void); - -#endif /* EAP_METHODS_H */ diff --git a/contrib/hostapd/src/eap_server/eap_mschapv2.c b/contrib/hostapd/src/eap_server/eap_mschapv2.c deleted file mode 100644 index 20e7adee6f..0000000000 --- a/contrib/hostapd/src/eap_server/eap_mschapv2.c +++ /dev/null @@ -1,568 +0,0 @@ -/* - * hostapd / EAP-MSCHAPv2 (draft-kamath-pppext-eap-mschapv2-00.txt) server - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "ms_funcs.h" - - -struct eap_mschapv2_hdr { - u8 op_code; /* MSCHAPV2_OP_* */ - u8 mschapv2_id; /* must be changed for challenges, but not for - * success/failure */ - u8 ms_length[2]; /* Note: misaligned; length - 5 */ - /* followed by data */ -} STRUCT_PACKED; - -#define MSCHAPV2_OP_CHALLENGE 1 -#define MSCHAPV2_OP_RESPONSE 2 -#define MSCHAPV2_OP_SUCCESS 3 -#define MSCHAPV2_OP_FAILURE 4 -#define MSCHAPV2_OP_CHANGE_PASSWORD 7 - -#define MSCHAPV2_RESP_LEN 49 - -#define ERROR_RESTRICTED_LOGON_HOURS 646 -#define ERROR_ACCT_DISABLED 647 -#define ERROR_PASSWD_EXPIRED 648 -#define ERROR_NO_DIALIN_PERMISSION 649 -#define ERROR_AUTHENTICATION_FAILURE 691 -#define ERROR_CHANGING_PASSWORD 709 - -#define PASSWD_CHANGE_CHAL_LEN 16 -#define MSCHAPV2_KEY_LEN 16 - - -#define CHALLENGE_LEN 16 - -struct eap_mschapv2_data { - u8 auth_challenge[CHALLENGE_LEN]; - int auth_challenge_from_tls; - u8 *peer_challenge; - u8 auth_response[20]; - enum { CHALLENGE, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE } state; - u8 resp_mschapv2_id; - u8 master_key[16]; - int master_key_valid; -}; - - -static void * eap_mschapv2_init(struct eap_sm *sm) -{ - struct eap_mschapv2_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = CHALLENGE; - - if (sm->auth_challenge) { - os_memcpy(data->auth_challenge, sm->auth_challenge, - CHALLENGE_LEN); - data->auth_challenge_from_tls = 1; - } - - if (sm->peer_challenge) { - data->peer_challenge = os_malloc(CHALLENGE_LEN); - if (data->peer_challenge == NULL) { - os_free(data); - return NULL; - } - os_memcpy(data->peer_challenge, sm->peer_challenge, - CHALLENGE_LEN); - } - - return data; -} - - -static void eap_mschapv2_reset(struct eap_sm *sm, void *priv) -{ - struct eap_mschapv2_data *data = priv; - if (data == NULL) - return; - - os_free(data->peer_challenge); - os_free(data); -} - - -static struct wpabuf * eap_mschapv2_build_challenge( - struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id) -{ - struct wpabuf *req; - struct eap_mschapv2_hdr *ms; - char *name = "hostapd"; /* TODO: make this configurable */ - size_t ms_len; - - if (!data->auth_challenge_from_tls && - os_get_random(data->auth_challenge, CHALLENGE_LEN)) { - wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to get random " - "data"); - data->state = FAILURE; - return NULL; - } - - ms_len = sizeof(*ms) + 1 + CHALLENGE_LEN + os_strlen(name); - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory" - " for request"); - data->state = FAILURE; - return NULL; - } - - ms = wpabuf_put(req, sizeof(*ms)); - ms->op_code = MSCHAPV2_OP_CHALLENGE; - ms->mschapv2_id = id; - WPA_PUT_BE16(ms->ms_length, ms_len); - - wpabuf_put_u8(req, CHALLENGE_LEN); - if (!data->auth_challenge_from_tls) - wpabuf_put_data(req, data->auth_challenge, CHALLENGE_LEN); - else - wpabuf_put(req, CHALLENGE_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Challenge", - data->auth_challenge, CHALLENGE_LEN); - wpabuf_put_data(req, name, os_strlen(name)); - - return req; -} - - -static struct wpabuf * eap_mschapv2_build_success_req( - struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id) -{ - struct wpabuf *req; - struct eap_mschapv2_hdr *ms; - u8 *msg; - char *message = "OK"; - size_t ms_len; - - ms_len = sizeof(*ms) + 2 + 2 * sizeof(data->auth_response) + 1 + 2 + - os_strlen(message); - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory" - " for request"); - data->state = FAILURE; - return NULL; - } - - ms = wpabuf_put(req, sizeof(*ms)); - ms->op_code = MSCHAPV2_OP_SUCCESS; - ms->mschapv2_id = data->resp_mschapv2_id; - WPA_PUT_BE16(ms->ms_length, ms_len); - msg = (u8 *) (ms + 1); - - wpabuf_put_u8(req, 'S'); - wpabuf_put_u8(req, '='); - wpa_snprintf_hex_uppercase( - wpabuf_put(req, sizeof(data->auth_response) * 2), - sizeof(data->auth_response) * 2 + 1, - data->auth_response, sizeof(data->auth_response)); - wpabuf_put_u8(req, ' '); - wpabuf_put_u8(req, 'M'); - wpabuf_put_u8(req, '='); - wpabuf_put_data(req, message, os_strlen(message)); - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Success Request Message", - msg, ms_len - sizeof(*ms)); - - return req; -} - - -static struct wpabuf * eap_mschapv2_build_failure_req( - struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id) -{ - struct wpabuf *req; - struct eap_mschapv2_hdr *ms; - char *message = "E=691 R=0 C=00000000000000000000000000000000 V=3 " - "M=FAILED"; - size_t ms_len; - - ms_len = sizeof(*ms) + os_strlen(message); - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory" - " for request"); - data->state = FAILURE; - return NULL; - } - - ms = wpabuf_put(req, sizeof(*ms)); - ms->op_code = MSCHAPV2_OP_FAILURE; - ms->mschapv2_id = data->resp_mschapv2_id; - WPA_PUT_BE16(ms->ms_length, ms_len); - - wpabuf_put_data(req, message, os_strlen(message)); - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Failure Request Message", - (u8 *) message, os_strlen(message)); - - return req; -} - - -static struct wpabuf * eap_mschapv2_buildReq(struct eap_sm *sm, void *priv, - u8 id) -{ - struct eap_mschapv2_data *data = priv; - - switch (data->state) { - case CHALLENGE: - return eap_mschapv2_build_challenge(sm, data, id); - case SUCCESS_REQ: - return eap_mschapv2_build_success_req(sm, data, id); - case FAILURE_REQ: - return eap_mschapv2_build_failure_req(sm, data, id); - default: - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Unknown state %d in " - "buildReq", data->state); - break; - } - return NULL; -} - - -static Boolean eap_mschapv2_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_mschapv2_data *data = priv; - struct eap_mschapv2_hdr *resp; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData, - &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid frame"); - return TRUE; - } - - resp = (struct eap_mschapv2_hdr *) pos; - if (data->state == CHALLENGE && - resp->op_code != MSCHAPV2_OP_RESPONSE) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Response - " - "ignore op %d", resp->op_code); - return TRUE; - } - - if (data->state == SUCCESS_REQ && - resp->op_code != MSCHAPV2_OP_SUCCESS && - resp->op_code != MSCHAPV2_OP_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Success or " - "Failure - ignore op %d", resp->op_code); - return TRUE; - } - - if (data->state == FAILURE_REQ && - resp->op_code != MSCHAPV2_OP_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Failure " - "- ignore op %d", resp->op_code); - return TRUE; - } - - return FALSE; -} - - -static void eap_mschapv2_process_response(struct eap_sm *sm, - struct eap_mschapv2_data *data, - struct wpabuf *respData) -{ - struct eap_mschapv2_hdr *resp; - const u8 *pos, *end, *peer_challenge, *nt_response, *name; - u8 flags; - size_t len, name_len, i; - u8 expected[24]; - const u8 *username, *user; - size_t username_len, user_len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData, - &len); - if (pos == NULL || len < 1) - return; /* Should not happen - frame already validated */ - - end = pos + len; - resp = (struct eap_mschapv2_hdr *) pos; - pos = (u8 *) (resp + 1); - - if (len < sizeof(*resp) + 1 + 49 || - resp->op_code != MSCHAPV2_OP_RESPONSE || - pos[0] != 49) { - wpa_hexdump_buf(MSG_DEBUG, "EAP-MSCHAPV2: Invalid response", - respData); - data->state = FAILURE; - return; - } - data->resp_mschapv2_id = resp->mschapv2_id; - pos++; - peer_challenge = pos; - pos += 16 + 8; - nt_response = pos; - pos += 24; - flags = *pos++; - name = pos; - name_len = end - name; - - if (data->peer_challenge) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Using pre-configured " - "Peer-Challenge"); - peer_challenge = data->peer_challenge; - } - wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Peer-Challenge", - peer_challenge, 16); - wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: NT-Response", nt_response, 24); - wpa_printf(MSG_MSGDUMP, "EAP-MSCHAPV2: Flags 0x%x", flags); - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Name", name, name_len); - - /* MSCHAPv2 does not include optional domain name in the - * challenge-response calculation, so remove domain prefix - * (if present). */ - username = sm->identity; - username_len = sm->identity_len; - for (i = 0; i < username_len; i++) { - if (username[i] == '\\') { - username_len -= i + 1; - username += i + 1; - break; - } - } - - user = name; - user_len = name_len; - for (i = 0; i < user_len; i++) { - if (user[i] == '\\') { - user_len -= i + 1; - user += i + 1; - break; - } - } - - if (username_len != user_len || - os_memcmp(username, user, username_len) != 0) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Mismatch in user names"); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Expected user " - "name", username, username_len); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Received user " - "name", user, user_len); - data->state = FAILURE; - return; - } - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: User name", - username, username_len); - - if (sm->user->password_hash) { - generate_nt_response_pwhash(data->auth_challenge, - peer_challenge, - username, username_len, - sm->user->password, - expected); - } else { - generate_nt_response(data->auth_challenge, peer_challenge, - username, username_len, - sm->user->password, - sm->user->password_len, - expected); - } - - if (os_memcmp(nt_response, expected, 24) == 0) { - const u8 *pw_hash; - u8 pw_hash_buf[16], pw_hash_hash[16]; - - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Correct NT-Response"); - data->state = SUCCESS_REQ; - - /* Authenticator response is not really needed yet, but - * calculate it here so that peer_challenge and username need - * not be saved. */ - if (sm->user->password_hash) { - pw_hash = sm->user->password; - } else { - nt_password_hash(sm->user->password, - sm->user->password_len, - pw_hash_buf); - pw_hash = pw_hash_buf; - } - generate_authenticator_response_pwhash( - pw_hash, peer_challenge, data->auth_challenge, - username, username_len, nt_response, - data->auth_response); - - hash_nt_password_hash(pw_hash, pw_hash_hash); - get_master_key(pw_hash_hash, nt_response, data->master_key); - data->master_key_valid = 1; - wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived Master Key", - data->master_key, MSCHAPV2_KEY_LEN); - } else { - wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Expected NT-Response", - expected, 24); - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Invalid NT-Response"); - data->state = FAILURE_REQ; - } -} - - -static void eap_mschapv2_process_success_resp(struct eap_sm *sm, - struct eap_mschapv2_data *data, - struct wpabuf *respData) -{ - struct eap_mschapv2_hdr *resp; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData, - &len); - if (pos == NULL || len < 1) - return; /* Should not happen - frame already validated */ - - resp = (struct eap_mschapv2_hdr *) pos; - - if (resp->op_code == MSCHAPV2_OP_SUCCESS) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received Success Response" - " - authentication completed successfully"); - data->state = SUCCESS; - } else { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Did not receive Success " - "Response - peer rejected authentication"); - data->state = FAILURE; - } -} - - -static void eap_mschapv2_process_failure_resp(struct eap_sm *sm, - struct eap_mschapv2_data *data, - struct wpabuf *respData) -{ - struct eap_mschapv2_hdr *resp; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData, - &len); - if (pos == NULL || len < 1) - return; /* Should not happen - frame already validated */ - - resp = (struct eap_mschapv2_hdr *) pos; - - if (resp->op_code == MSCHAPV2_OP_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received Failure Response" - " - authentication failed"); - } else { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Did not receive Failure " - "Response - authentication failed"); - } - - data->state = FAILURE; -} - - -static void eap_mschapv2_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_mschapv2_data *data = priv; - - if (sm->user == NULL || sm->user->password == NULL) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Password not configured"); - data->state = FAILURE; - return; - } - - switch (data->state) { - case CHALLENGE: - eap_mschapv2_process_response(sm, data, respData); - break; - case SUCCESS_REQ: - eap_mschapv2_process_success_resp(sm, data, respData); - break; - case FAILURE_REQ: - eap_mschapv2_process_failure_resp(sm, data, respData); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Unknown state %d in " - "process", data->state); - break; - } -} - - -static Boolean eap_mschapv2_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_mschapv2_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_mschapv2_data *data = priv; - u8 *key; - - if (data->state != SUCCESS || !data->master_key_valid) - return NULL; - - *len = 2 * MSCHAPV2_KEY_LEN; - key = os_malloc(*len); - if (key == NULL) - return NULL; - /* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key */ - get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 0, 1); - get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN, - MSCHAPV2_KEY_LEN, 1, 1); - wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key", key, *len); - - return key; -} - - -static Boolean eap_mschapv2_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_mschapv2_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_mschapv2_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, - "MSCHAPV2"); - if (eap == NULL) - return -1; - - eap->init = eap_mschapv2_init; - eap->reset = eap_mschapv2_reset; - eap->buildReq = eap_mschapv2_buildReq; - eap->check = eap_mschapv2_check; - eap->process = eap_mschapv2_process; - eap->isDone = eap_mschapv2_isDone; - eap->getKey = eap_mschapv2_getKey; - eap->isSuccess = eap_mschapv2_isSuccess; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_server/eap_pax.c b/contrib/hostapd/src/eap_server/eap_pax.c deleted file mode 100644 index 1dc023b699..0000000000 --- a/contrib/hostapd/src/eap_server/eap_pax.c +++ /dev/null @@ -1,569 +0,0 @@ -/* - * hostapd / EAP-PAX (RFC 4746) server - * Copyright (c) 2005-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_server/eap_i.h" -#include "eap_common/eap_pax_common.h" - -/* - * Note: only PAX_STD subprotocol is currently supported - * - * TODO: Add support with PAX_SEC with the mandatory to implement ciphersuite - * (HMAC_SHA1_128, IANA DH Group 14 (2048 bits), RSA-PKCS1-V1_5) and - * recommended ciphersuite (HMAC_SHA256_128, IANA DH Group 15 (3072 bits), - * RSAES-OAEP). - */ - -struct eap_pax_data { - enum { PAX_STD_1, PAX_STD_3, SUCCESS, FAILURE } state; - u8 mac_id; - union { - u8 e[2 * EAP_PAX_RAND_LEN]; - struct { - u8 x[EAP_PAX_RAND_LEN]; /* server rand */ - u8 y[EAP_PAX_RAND_LEN]; /* client rand */ - } r; - } rand; - u8 ak[EAP_PAX_AK_LEN]; - u8 mk[EAP_PAX_MK_LEN]; - u8 ck[EAP_PAX_CK_LEN]; - u8 ick[EAP_PAX_ICK_LEN]; - int keys_set; - char *cid; - size_t cid_len; -}; - - -static void * eap_pax_init(struct eap_sm *sm) -{ - struct eap_pax_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = PAX_STD_1; - /* - * TODO: make this configurable once EAP_PAX_HMAC_SHA256_128 is - * supported - */ - data->mac_id = EAP_PAX_MAC_HMAC_SHA1_128; - - return data; -} - - -static void eap_pax_reset(struct eap_sm *sm, void *priv) -{ - struct eap_pax_data *data = priv; - os_free(data->cid); - os_free(data); -} - - -static struct wpabuf * eap_pax_build_std_1(struct eap_sm *sm, - struct eap_pax_data *data, u8 id) -{ - struct wpabuf *req; - struct eap_pax_hdr *pax; - u8 *pos; - - wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-1 (sending)"); - - if (os_get_random(data->rand.r.x, EAP_PAX_RAND_LEN)) { - wpa_printf(MSG_ERROR, "EAP-PAX: Failed to get random data"); - data->state = FAILURE; - return NULL; - } - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PAX, - sizeof(*pax) + 2 + EAP_PAX_RAND_LEN + - EAP_PAX_ICV_LEN, EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-PAX: Failed to allocate memory " - "request"); - data->state = FAILURE; - return NULL; - } - - pax = wpabuf_put(req, sizeof(*pax)); - pax->op_code = EAP_PAX_OP_STD_1; - pax->flags = 0; - pax->mac_id = data->mac_id; - pax->dh_group_id = EAP_PAX_DH_GROUP_NONE; - pax->public_key_id = EAP_PAX_PUBLIC_KEY_NONE; - - wpabuf_put_be16(req, EAP_PAX_RAND_LEN); - wpabuf_put_data(req, data->rand.r.x, EAP_PAX_RAND_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: A = X (server rand)", - data->rand.r.x, EAP_PAX_RAND_LEN); - - pos = wpabuf_put(req, EAP_PAX_MAC_LEN); - eap_pax_mac(data->mac_id, (u8 *) "", 0, - wpabuf_mhead(req), wpabuf_len(req) - EAP_PAX_ICV_LEN, - NULL, 0, NULL, 0, pos); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN); - - return req; -} - - -static struct wpabuf * eap_pax_build_std_3(struct eap_sm *sm, - struct eap_pax_data *data, u8 id) -{ - struct wpabuf *req; - struct eap_pax_hdr *pax; - u8 *pos; - - wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-3 (sending)"); - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PAX, - sizeof(*pax) + 2 + EAP_PAX_MAC_LEN + - EAP_PAX_ICV_LEN, EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-PAX: Failed to allocate memory " - "request"); - data->state = FAILURE; - return NULL; - } - - pax = wpabuf_put(req, sizeof(*pax)); - pax->op_code = EAP_PAX_OP_STD_3; - pax->flags = 0; - pax->mac_id = data->mac_id; - pax->dh_group_id = EAP_PAX_DH_GROUP_NONE; - pax->public_key_id = EAP_PAX_PUBLIC_KEY_NONE; - - wpabuf_put_be16(req, EAP_PAX_MAC_LEN); - pos = wpabuf_put(req, EAP_PAX_MAC_LEN); - eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN, - data->rand.r.y, EAP_PAX_RAND_LEN, - (u8 *) data->cid, data->cid_len, NULL, 0, pos); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(B, CID)", - pos, EAP_PAX_MAC_LEN); - pos += EAP_PAX_MAC_LEN; - - /* Optional ADE could be added here, if needed */ - - pos = wpabuf_put(req, EAP_PAX_MAC_LEN); - eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN, - wpabuf_mhead(req), wpabuf_len(req) - EAP_PAX_ICV_LEN, - NULL, 0, NULL, 0, pos); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN); - - return req; -} - - -static struct wpabuf * eap_pax_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_pax_data *data = priv; - - switch (data->state) { - case PAX_STD_1: - return eap_pax_build_std_1(sm, data, id); - case PAX_STD_3: - return eap_pax_build_std_3(sm, data, id); - default: - wpa_printf(MSG_DEBUG, "EAP-PAX: Unknown state %d in buildReq", - data->state); - break; - } - return NULL; -} - - -static Boolean eap_pax_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_pax_data *data = priv; - struct eap_pax_hdr *resp; - const u8 *pos; - size_t len, mlen; - u8 icvbuf[EAP_PAX_ICV_LEN], *icv; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len); - if (pos == NULL || len < sizeof(*resp)) { - wpa_printf(MSG_INFO, "EAP-PAX: Invalid frame"); - return TRUE; - } - - mlen = sizeof(struct eap_hdr) + 1 + len; - resp = (struct eap_pax_hdr *) pos; - - wpa_printf(MSG_DEBUG, "EAP-PAX: received frame: op_code 0x%x " - "flags 0x%x mac_id 0x%x dh_group_id 0x%x " - "public_key_id 0x%x", - resp->op_code, resp->flags, resp->mac_id, resp->dh_group_id, - resp->public_key_id); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: received payload", - (u8 *) (resp + 1), len - sizeof(*resp) - EAP_PAX_ICV_LEN); - - if (data->state == PAX_STD_1 && - resp->op_code != EAP_PAX_OP_STD_2) { - wpa_printf(MSG_DEBUG, "EAP-PAX: Expected PAX_STD-2 - " - "ignore op %d", resp->op_code); - return TRUE; - } - - if (data->state == PAX_STD_3 && - resp->op_code != EAP_PAX_OP_ACK) { - wpa_printf(MSG_DEBUG, "EAP-PAX: Expected PAX-ACK - " - "ignore op %d", resp->op_code); - return TRUE; - } - - if (resp->op_code != EAP_PAX_OP_STD_2 && - resp->op_code != EAP_PAX_OP_ACK) { - wpa_printf(MSG_DEBUG, "EAP-PAX: Unknown op_code 0x%x", - resp->op_code); - } - - if (data->mac_id != resp->mac_id) { - wpa_printf(MSG_DEBUG, "EAP-PAX: Expected MAC ID 0x%x, " - "received 0x%x", data->mac_id, resp->mac_id); - return TRUE; - } - - if (resp->dh_group_id != EAP_PAX_DH_GROUP_NONE) { - wpa_printf(MSG_INFO, "EAP-PAX: Expected DH Group ID 0x%x, " - "received 0x%x", EAP_PAX_DH_GROUP_NONE, - resp->dh_group_id); - return TRUE; - } - - if (resp->public_key_id != EAP_PAX_PUBLIC_KEY_NONE) { - wpa_printf(MSG_INFO, "EAP-PAX: Expected Public Key ID 0x%x, " - "received 0x%x", EAP_PAX_PUBLIC_KEY_NONE, - resp->public_key_id); - return TRUE; - } - - if (resp->flags & EAP_PAX_FLAGS_MF) { - /* TODO: add support for reassembling fragments */ - wpa_printf(MSG_INFO, "EAP-PAX: fragmentation not supported"); - return TRUE; - } - - if (resp->flags & EAP_PAX_FLAGS_CE) { - wpa_printf(MSG_INFO, "EAP-PAX: Unexpected CE flag"); - return TRUE; - } - - if (data->keys_set) { - if (len - sizeof(*resp) < EAP_PAX_ICV_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: No ICV in the packet"); - return TRUE; - } - icv = wpabuf_mhead_u8(respData) + mlen - EAP_PAX_ICV_LEN; - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", icv, EAP_PAX_ICV_LEN); - eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN, - wpabuf_mhead(respData), - wpabuf_len(respData) - EAP_PAX_ICV_LEN, - NULL, 0, NULL, 0, icvbuf); - if (os_memcmp(icvbuf, icv, EAP_PAX_ICV_LEN) != 0) { - wpa_printf(MSG_INFO, "EAP-PAX: Invalid ICV"); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected ICV", - icvbuf, EAP_PAX_ICV_LEN); - return TRUE; - } - } - - return FALSE; -} - - -static void eap_pax_process_std_2(struct eap_sm *sm, - struct eap_pax_data *data, - struct wpabuf *respData) -{ - struct eap_pax_hdr *resp; - u8 mac[EAP_PAX_MAC_LEN], icvbuf[EAP_PAX_ICV_LEN]; - const u8 *pos; - size_t len, left; - int i; - - if (data->state != PAX_STD_1) - return; - - wpa_printf(MSG_DEBUG, "EAP-PAX: Received PAX_STD-2"); - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len); - if (pos == NULL || len < sizeof(*resp) + EAP_PAX_ICV_LEN) - return; - - resp = (struct eap_pax_hdr *) pos; - pos = (u8 *) (resp + 1); - left = len - sizeof(*resp); - - if (left < 2 + EAP_PAX_RAND_LEN || - WPA_GET_BE16(pos) != EAP_PAX_RAND_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (B)"); - return; - } - pos += 2; - left -= 2; - os_memcpy(data->rand.r.y, pos, EAP_PAX_RAND_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Y (client rand)", - data->rand.r.y, EAP_PAX_RAND_LEN); - pos += EAP_PAX_RAND_LEN; - left -= EAP_PAX_RAND_LEN; - - if (left < 2 || (size_t) 2 + WPA_GET_BE16(pos) > left) { - wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (CID)"); - return; - } - data->cid_len = WPA_GET_BE16(pos); - os_free(data->cid); - data->cid = os_malloc(data->cid_len); - if (data->cid == NULL) { - wpa_printf(MSG_INFO, "EAP-PAX: Failed to allocate memory for " - "CID"); - return; - } - os_memcpy(data->cid, pos + 2, data->cid_len); - pos += 2 + data->cid_len; - left -= 2 + data->cid_len; - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PAX: CID", - (u8 *) data->cid, data->cid_len); - - if (left < 2 + EAP_PAX_MAC_LEN || - WPA_GET_BE16(pos) != EAP_PAX_MAC_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (MAC_CK)"); - return; - } - pos += 2; - left -= 2; - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(A, B, CID)", - pos, EAP_PAX_MAC_LEN); - - if (eap_user_get(sm, (u8 *) data->cid, data->cid_len, 0) < 0) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-PAX: unknown CID", - (u8 *) data->cid, data->cid_len); - data->state = FAILURE; - return; - } - - for (i = 0; - i < EAP_MAX_METHODS && - (sm->user->methods[i].vendor != EAP_VENDOR_IETF || - sm->user->methods[i].method != EAP_TYPE_NONE); - i++) { - if (sm->user->methods[i].vendor == EAP_VENDOR_IETF && - sm->user->methods[i].method == EAP_TYPE_PAX) - break; - } - - if (i >= EAP_MAX_METHODS || - sm->user->methods[i].vendor != EAP_VENDOR_IETF || - sm->user->methods[i].method != EAP_TYPE_PAX) { - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-PAX: EAP-PAX not enabled for CID", - (u8 *) data->cid, data->cid_len); - data->state = FAILURE; - return; - } - - if (sm->user->password == NULL || - sm->user->password_len != EAP_PAX_AK_LEN) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-PAX: invalid password in " - "user database for CID", - (u8 *) data->cid, data->cid_len); - data->state = FAILURE; - return; - } - os_memcpy(data->ak, sm->user->password, EAP_PAX_AK_LEN); - - if (eap_pax_initial_key_derivation(data->mac_id, data->ak, - data->rand.e, data->mk, data->ck, - data->ick) < 0) { - wpa_printf(MSG_INFO, "EAP-PAX: Failed to complete initial " - "key derivation"); - data->state = FAILURE; - return; - } - data->keys_set = 1; - - eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN, - data->rand.r.x, EAP_PAX_RAND_LEN, - data->rand.r.y, EAP_PAX_RAND_LEN, - (u8 *) data->cid, data->cid_len, mac); - if (os_memcmp(mac, pos, EAP_PAX_MAC_LEN) != 0) { - wpa_printf(MSG_INFO, "EAP-PAX: Invalid MAC_CK(A, B, CID) in " - "PAX_STD-2"); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected MAC_CK(A, B, CID)", - mac, EAP_PAX_MAC_LEN); - data->state = FAILURE; - return; - } - - pos += EAP_PAX_MAC_LEN; - left -= EAP_PAX_MAC_LEN; - - if (left < EAP_PAX_ICV_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: Too short ICV (%lu) in " - "PAX_STD-2", (unsigned long) left); - return; - } - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN); - eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN, - wpabuf_head(respData), - wpabuf_len(respData) - EAP_PAX_ICV_LEN, NULL, 0, NULL, 0, - icvbuf); - if (os_memcmp(icvbuf, pos, EAP_PAX_ICV_LEN) != 0) { - wpa_printf(MSG_INFO, "EAP-PAX: Invalid ICV in PAX_STD-2"); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected ICV", - icvbuf, EAP_PAX_ICV_LEN); - return; - } - pos += EAP_PAX_ICV_LEN; - left -= EAP_PAX_ICV_LEN; - - if (left > 0) { - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ignored extra payload", - pos, left); - } - - data->state = PAX_STD_3; -} - - -static void eap_pax_process_ack(struct eap_sm *sm, - struct eap_pax_data *data, - struct wpabuf *respData) -{ - if (data->state != PAX_STD_3) - return; - - wpa_printf(MSG_DEBUG, "EAP-PAX: Received PAX-ACK - authentication " - "completed successfully"); - data->state = SUCCESS; -} - - -static void eap_pax_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_pax_data *data = priv; - struct eap_pax_hdr *resp; - const u8 *pos; - size_t len; - - if (sm->user == NULL || sm->user->password == NULL) { - wpa_printf(MSG_INFO, "EAP-PAX: Plaintext password not " - "configured"); - data->state = FAILURE; - return; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len); - if (pos == NULL || len < sizeof(*resp)) - return; - - resp = (struct eap_pax_hdr *) pos; - - switch (resp->op_code) { - case EAP_PAX_OP_STD_2: - eap_pax_process_std_2(sm, data, respData); - break; - case EAP_PAX_OP_ACK: - eap_pax_process_ack(sm, data, respData); - break; - } -} - - -static Boolean eap_pax_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_pax_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_pax_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_pax_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_MSK_LEN; - eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN, - "Master Session Key", data->rand.e, 2 * EAP_PAX_RAND_LEN, - EAP_MSK_LEN, key); - - return key; -} - - -static u8 * eap_pax_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_pax_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_EMSK_LEN; - eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN, - "Extended Master Session Key", - data->rand.e, 2 * EAP_PAX_RAND_LEN, - EAP_EMSK_LEN, key); - - return key; -} - - -static Boolean eap_pax_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_pax_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_pax_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_PAX, "PAX"); - if (eap == NULL) - return -1; - - eap->init = eap_pax_init; - eap->reset = eap_pax_reset; - eap->buildReq = eap_pax_buildReq; - eap->check = eap_pax_check; - eap->process = eap_pax_process; - eap->isDone = eap_pax_isDone; - eap->getKey = eap_pax_getKey; - eap->isSuccess = eap_pax_isSuccess; - eap->get_emsk = eap_pax_get_emsk; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_server/eap_peap.c b/contrib/hostapd/src/eap_server/eap_peap.c deleted file mode 100644 index 4b2d5a5c83..0000000000 --- a/contrib/hostapd/src/eap_server/eap_peap.c +++ /dev/null @@ -1,1421 +0,0 @@ -/* - * hostapd / EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha1.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "eap_common/eap_tlv_common.h" -#include "eap_common/eap_peap_common.h" -#include "tls.h" -#include "tncs.h" - - -/* Maximum supported PEAP version - * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt - * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt - * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt - */ -#define EAP_PEAP_VERSION 1 - - -static void eap_peap_reset(struct eap_sm *sm, void *priv); - - -struct eap_peap_data { - struct eap_ssl_data ssl; - enum { - START, PHASE1, PHASE1_ID2, PHASE2_START, PHASE2_ID, - PHASE2_METHOD, PHASE2_SOH, - PHASE2_TLV, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE - } state; - - int peap_version; - int recv_version; - const struct eap_method *phase2_method; - void *phase2_priv; - int force_version; - struct wpabuf *pending_phase2_resp; - enum { TLV_REQ_NONE, TLV_REQ_SUCCESS, TLV_REQ_FAILURE } tlv_request; - int crypto_binding_sent; - int crypto_binding_used; - enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding; - u8 binding_nonce[32]; - u8 ipmk[40]; - u8 cmk[20]; - u8 *phase2_key; - size_t phase2_key_len; - struct wpabuf *soh_response; -}; - - -static const char * eap_peap_state_txt(int state) -{ - switch (state) { - case START: - return "START"; - case PHASE1: - return "PHASE1"; - case PHASE1_ID2: - return "PHASE1_ID2"; - case PHASE2_START: - return "PHASE2_START"; - case PHASE2_ID: - return "PHASE2_ID"; - case PHASE2_METHOD: - return "PHASE2_METHOD"; - case PHASE2_SOH: - return "PHASE2_SOH"; - case PHASE2_TLV: - return "PHASE2_TLV"; - case SUCCESS_REQ: - return "SUCCESS_REQ"; - case FAILURE_REQ: - return "FAILURE_REQ"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "Unknown?!"; - } -} - - -static void eap_peap_state(struct eap_peap_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-PEAP: %s -> %s", - eap_peap_state_txt(data->state), - eap_peap_state_txt(state)); - data->state = state; -} - - -static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf) -{ - struct wpabuf *e; - struct eap_tlv_hdr *tlv; - - if (buf == NULL) - return NULL; - - /* Encapsulate EAP packet in EAP-Payload TLV */ - wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV"); - e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf)); - if (e == NULL) { - wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory " - "for TLV encapsulation"); - wpabuf_free(buf); - return NULL; - } - tlv = wpabuf_put(e, sizeof(*tlv)); - tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - EAP_TLV_EAP_PAYLOAD_TLV); - tlv->length = host_to_be16(wpabuf_len(buf)); - wpabuf_put_buf(e, buf); - wpabuf_free(buf); - return e; -} - - -static void eap_peap_req_success(struct eap_sm *sm, - struct eap_peap_data *data) -{ - if (data->state == FAILURE || data->state == FAILURE_REQ) { - eap_peap_state(data, FAILURE); - return; - } - - if (data->peap_version == 0) { - data->tlv_request = TLV_REQ_SUCCESS; - eap_peap_state(data, PHASE2_TLV); - } else { - eap_peap_state(data, SUCCESS_REQ); - } -} - - -static void eap_peap_req_failure(struct eap_sm *sm, - struct eap_peap_data *data) -{ - if (data->state == FAILURE || data->state == FAILURE_REQ || - data->state == SUCCESS_REQ || data->tlv_request != TLV_REQ_NONE) { - eap_peap_state(data, FAILURE); - return; - } - - if (data->peap_version == 0) { - data->tlv_request = TLV_REQ_FAILURE; - eap_peap_state(data, PHASE2_TLV); - } else { - eap_peap_state(data, FAILURE_REQ); - } -} - - -static void * eap_peap_init(struct eap_sm *sm) -{ - struct eap_peap_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->peap_version = EAP_PEAP_VERSION; - data->force_version = -1; - if (sm->user && sm->user->force_version >= 0) { - data->force_version = sm->user->force_version; - wpa_printf(MSG_DEBUG, "EAP-PEAP: forcing version %d", - data->force_version); - data->peap_version = data->force_version; - } - data->state = START; - data->crypto_binding = OPTIONAL_BINDING; - - if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) { - wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL."); - eap_peap_reset(sm, data); - return NULL; - } - - return data; -} - - -static void eap_peap_reset(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - if (data == NULL) - return; - if (data->phase2_priv && data->phase2_method) - data->phase2_method->reset(sm, data->phase2_priv); - eap_server_tls_ssl_deinit(sm, &data->ssl); - wpabuf_free(data->pending_phase2_resp); - os_free(data->phase2_key); - wpabuf_free(data->soh_response); - os_free(data); -} - - -static struct wpabuf * eap_peap_build_start(struct eap_sm *sm, - struct eap_peap_data *data, u8 id) -{ - struct wpabuf *req; - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PEAP, 1, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to allocate memory for" - " request"); - eap_peap_state(data, FAILURE); - return NULL; - } - - wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->peap_version); - - eap_peap_state(data, PHASE1); - - return req; -} - - -static struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm, - struct eap_peap_data *data, - u8 id) -{ - struct wpabuf *buf, *encr_req; - const u8 *req; - size_t req_len; - - if (data->phase2_method == NULL || data->phase2_priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 method not ready"); - return NULL; - } - buf = data->phase2_method->buildReq(sm, data->phase2_priv, id); - if (data->peap_version >= 2 && buf) - buf = eap_peapv2_tlv_eap_payload(buf); - if (buf == NULL) - return NULL; - - req = wpabuf_head(buf); - req_len = wpabuf_len(buf); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data", - req, req_len); - - if (data->peap_version == 0 && - data->phase2_method->method != EAP_TYPE_TLV) { - req += sizeof(struct eap_hdr); - req_len -= sizeof(struct eap_hdr); - } - - encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len); - wpabuf_free(buf); - - return encr_req; -} - - -#ifdef EAP_TNC -static struct wpabuf * eap_peap_build_phase2_soh(struct eap_sm *sm, - struct eap_peap_data *data, - u8 id) -{ - struct wpabuf *buf1, *buf, *encr_req; - const u8 *req; - size_t req_len; - - buf1 = tncs_build_soh_request(); - if (buf1 == NULL) - return NULL; - - buf = eap_msg_alloc(EAP_VENDOR_MICROSOFT, 0x21, wpabuf_len(buf1), - EAP_CODE_REQUEST, id); - if (buf == NULL) { - wpabuf_free(buf1); - return NULL; - } - wpabuf_put_buf(buf, buf1); - wpabuf_free(buf1); - - req = wpabuf_head(buf); - req_len = wpabuf_len(buf); - - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 SOH data", - req, req_len); - - req += sizeof(struct eap_hdr); - req_len -= sizeof(struct eap_hdr); - - encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len); - wpabuf_free(buf); - - return encr_req; -} -#endif /* EAP_TNC */ - - -static void eap_peap_get_isk(struct eap_peap_data *data, - u8 *isk, size_t isk_len) -{ - size_t key_len; - - os_memset(isk, 0, isk_len); - if (data->phase2_key == NULL) - return; - - key_len = data->phase2_key_len; - if (key_len > isk_len) - key_len = isk_len; - os_memcpy(isk, data->phase2_key, key_len); -} - - -static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) -{ - u8 *tk; - u8 isk[32], imck[60]; - - /* - * Tunnel key (TK) is the first 60 octets of the key generated by - * phase 1 of PEAP (based on TLS). - */ - tk = eap_server_tls_derive_key(sm, &data->ssl, "client EAP encryption", - EAP_TLS_KEY_LEN); - if (tk == NULL) - return -1; - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60); - - eap_peap_get_isk(data, isk, sizeof(isk)); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk)); - - /* - * IPMK Seed = "Inner Methods Compound Keys" | ISK - * TempKey = First 40 octets of TK - * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60) - * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space - * in the end of the label just before ISK; is that just a typo?) - */ - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40); - peap_prfplus(data->peap_version, tk, 40, "Inner Methods Compound Keys", - isk, sizeof(isk), imck, sizeof(imck)); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)", - imck, sizeof(imck)); - - os_free(tk); - - /* TODO: fast-connect: IPMK|CMK = TK */ - os_memcpy(data->ipmk, imck, 40); - 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); - - return 0; -} - - -static struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm, - struct eap_peap_data *data, - u8 id) -{ - struct wpabuf *buf, *encr_req; - size_t len; - - len = 6; /* Result TLV */ - if (data->crypto_binding != NO_BINDING) - len += 60; /* Cryptobinding TLV */ -#ifdef EAP_TNC - if (data->soh_response) - len += wpabuf_len(data->soh_response); -#endif /* EAP_TNC */ - - buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, len, - EAP_CODE_REQUEST, id); - if (buf == NULL) - return NULL; - - wpabuf_put_u8(buf, 0x80); /* Mandatory */ - wpabuf_put_u8(buf, EAP_TLV_RESULT_TLV); - /* Length */ - wpabuf_put_be16(buf, 2); - /* Status */ - wpabuf_put_be16(buf, data->tlv_request == TLV_REQ_SUCCESS ? - EAP_TLV_RESULT_SUCCESS : EAP_TLV_RESULT_FAILURE); - - if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS && - data->crypto_binding != NO_BINDING) { - u8 *mac; - u8 eap_type = EAP_TYPE_PEAP; - const u8 *addr[2]; - size_t len[2]; - u16 tlv_type; - -#ifdef EAP_TNC - if (data->soh_response) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Adding MS-SOH " - "Response TLV"); - wpabuf_put_buf(buf, data->soh_response); - wpabuf_free(data->soh_response); - data->soh_response = NULL; - } -#endif /* EAP_TNC */ - - if (eap_peap_derive_cmk(sm, data) < 0 || - os_get_random(data->binding_nonce, 32)) { - wpabuf_free(buf); - return NULL; - } - - /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ - addr[0] = wpabuf_put(buf, 0); - len[0] = 60; - addr[1] = &eap_type; - len[1] = 1; - - tlv_type = EAP_TLV_CRYPTO_BINDING_TLV; - if (data->peap_version >= 2) - tlv_type |= EAP_TLV_TYPE_MANDATORY; - wpabuf_put_be16(buf, tlv_type); - wpabuf_put_be16(buf, 56); - - wpabuf_put_u8(buf, 0); /* Reserved */ - wpabuf_put_u8(buf, data->peap_version); /* Version */ - wpabuf_put_u8(buf, data->recv_version); /* RecvVersion */ - wpabuf_put_u8(buf, 0); /* SubType: 0 = Request, 1 = Response */ - wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */ - mac = wpabuf_put(buf, 20); /* Compound_MAC */ - wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK", - data->cmk, 20); - wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1", - addr[0], len[0]); - wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2", - addr[1], len[1]); - hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac); - wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", - mac, SHA1_MAC_LEN); - data->crypto_binding_sent = 1; - } - - wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 TLV data", - buf); - - encr_req = eap_server_tls_encrypt(sm, &data->ssl, wpabuf_head(buf), - wpabuf_len(buf)); - wpabuf_free(buf); - - return encr_req; -} - - -static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm, - struct eap_peap_data *data, - u8 id, int success) -{ - struct wpabuf *encr_req; - size_t req_len; - struct eap_hdr *hdr; - - req_len = sizeof(*hdr); - hdr = os_zalloc(req_len); - if (hdr == NULL) - return NULL; - - hdr->code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE; - hdr->identifier = id; - hdr->length = host_to_be16(req_len); - - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data", - (u8 *) hdr, req_len); - - encr_req = eap_server_tls_encrypt(sm, &data->ssl, (u8 *) hdr, req_len); - os_free(hdr); - - return encr_req; -} - - -static struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_peap_data *data = priv; - - if (data->ssl.state == FRAG_ACK) { - return eap_server_tls_build_ack(id, EAP_TYPE_PEAP, - data->peap_version); - } - - if (data->ssl.state == WAIT_FRAG_ACK) { - return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP, - data->peap_version, id); - } - - switch (data->state) { - case START: - return eap_peap_build_start(sm, data, id); - case PHASE1: - case PHASE1_ID2: - if (data->peap_version < 2 && - tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase1 done, " - "starting Phase2"); - eap_peap_state(data, PHASE2_START); - } - break; - case PHASE2_ID: - case PHASE2_METHOD: - wpabuf_free(data->ssl.out_buf); - data->ssl.out_used = 0; - data->ssl.out_buf = eap_peap_build_phase2_req(sm, data, id); - break; -#ifdef EAP_TNC - case PHASE2_SOH: - wpabuf_free(data->ssl.out_buf); - data->ssl.out_used = 0; - data->ssl.out_buf = eap_peap_build_phase2_soh(sm, data, id); - break; -#endif /* EAP_TNC */ - case PHASE2_TLV: - wpabuf_free(data->ssl.out_buf); - data->ssl.out_used = 0; - data->ssl.out_buf = eap_peap_build_phase2_tlv(sm, data, id); - break; - case SUCCESS_REQ: - wpabuf_free(data->ssl.out_buf); - data->ssl.out_used = 0; - data->ssl.out_buf = eap_peap_build_phase2_term(sm, data, id, - 1); - break; - case FAILURE_REQ: - wpabuf_free(data->ssl.out_buf); - data->ssl.out_used = 0; - data->ssl.out_buf = eap_peap_build_phase2_term(sm, data, id, - 0); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d", - __func__, data->state); - return NULL; - } - - return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP, - data->peap_version, id); -} - - -static Boolean eap_peap_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-PEAP: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data, - EapType eap_type) -{ - if (data->phase2_priv && data->phase2_method) { - data->phase2_method->reset(sm, data->phase2_priv); - data->phase2_method = NULL; - data->phase2_priv = NULL; - } - data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF, - eap_type); - if (!data->phase2_method) - return -1; - - sm->init_phase2 = 1; - data->phase2_priv = data->phase2_method->init(sm); - sm->init_phase2 = 0; - return 0; -} - - -static int eap_tlv_validate_cryptobinding(struct eap_sm *sm, - struct eap_peap_data *data, - const u8 *crypto_tlv, - size_t crypto_tlv_len) -{ - u8 buf[61], mac[SHA1_MAC_LEN]; - const u8 *pos; - - if (crypto_tlv_len != 4 + 56) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV " - "length %d", (int) crypto_tlv_len); - return -1; - } - - pos = crypto_tlv; - pos += 4; /* TLV header */ - if (pos[1] != data->peap_version) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version " - "mismatch (was %d; expected %d)", - pos[1], data->peap_version); - return -1; - } - - if (pos[3] != 1) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV " - "SubType %d", pos[3]); - return -1; - } - pos += 4; - pos += 32; /* Nonce */ - - /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ - os_memcpy(buf, crypto_tlv, 60); - os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */ - buf[60] = EAP_TYPE_PEAP; - hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac); - - if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in " - "cryptobinding TLV"); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK", data->cmk, 20); - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding seed data", - buf, 61); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received"); - - return 0; -} - - -static void eap_peap_process_phase2_tlv(struct eap_sm *sm, - struct eap_peap_data *data, - struct wpabuf *in_data) -{ - const u8 *pos; - size_t left; - const u8 *result_tlv = NULL, *crypto_tlv = NULL; - size_t result_tlv_len = 0, crypto_tlv_len = 0; - int tlv_type, mandatory, tlv_len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, in_data, &left); - if (pos == NULL) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid EAP-TLV header"); - return; - } - - /* Parse TLVs */ - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs", pos, left); - while (left >= 4) { - mandatory = !!(pos[0] & 0x80); - tlv_type = pos[0] & 0x3f; - tlv_type = (tlv_type << 8) | pos[1]; - tlv_len = ((int) pos[2] << 8) | pos[3]; - pos += 4; - left -= 4; - if ((size_t) tlv_len > left) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun " - "(tlv_len=%d left=%lu)", tlv_len, - (unsigned long) left); - eap_peap_state(data, FAILURE); - return; - } - switch (tlv_type) { - case EAP_TLV_RESULT_TLV: - result_tlv = pos; - result_tlv_len = tlv_len; - break; - case EAP_TLV_CRYPTO_BINDING_TLV: - crypto_tlv = pos; - crypto_tlv_len = tlv_len; - break; - default: - wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type " - "%d%s", tlv_type, - mandatory ? " (mandatory)" : ""); - if (mandatory) { - eap_peap_state(data, FAILURE); - return; - } - /* Ignore this TLV, but process other TLVs */ - break; - } - - pos += tlv_len; - left -= tlv_len; - } - if (left) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in " - "Request (left=%lu)", (unsigned long) left); - eap_peap_state(data, FAILURE); - return; - } - - /* Process supported TLVs */ - if (crypto_tlv && data->crypto_binding_sent) { - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV", - crypto_tlv, crypto_tlv_len); - if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4, - crypto_tlv_len + 4) < 0) { - eap_peap_state(data, FAILURE); - return; - } - data->crypto_binding_used = 1; - } else if (!crypto_tlv && data->crypto_binding_sent && - data->crypto_binding == REQUIRE_BINDING) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV"); - eap_peap_state(data, FAILURE); - return; - } - - if (result_tlv) { - int status; - const char *requested; - - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Result TLV", - result_tlv, result_tlv_len); - if (result_tlv_len < 2) { - wpa_printf(MSG_INFO, "EAP-PEAP: Too short Result TLV " - "(len=%lu)", - (unsigned long) result_tlv_len); - eap_peap_state(data, FAILURE); - return; - } - requested = data->tlv_request == TLV_REQ_SUCCESS ? "Success" : - "Failure"; - status = WPA_GET_BE16(result_tlv); - if (status == EAP_TLV_RESULT_SUCCESS) { - wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Success " - "- requested %s", requested); - if (data->tlv_request == TLV_REQ_SUCCESS) - eap_peap_state(data, SUCCESS); - else - eap_peap_state(data, FAILURE); - - } else if (status == EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Failure " - "- requested %s", requested); - eap_peap_state(data, FAILURE); - } else { - wpa_printf(MSG_INFO, "EAP-PEAP: Unknown TLV Result " - "Status %d", status); - eap_peap_state(data, FAILURE); - } - } -} - - -#ifdef EAP_TNC -static void eap_peap_process_phase2_soh(struct eap_sm *sm, - struct eap_peap_data *data, - struct wpabuf *in_data) -{ - const u8 *pos, *vpos; - size_t left; - const u8 *soh_tlv = NULL; - size_t soh_tlv_len = 0; - int tlv_type, mandatory, tlv_len, vtlv_len; - u8 next_type; - u32 vendor_id; - - pos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, in_data, &left); - if (pos == NULL) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Not a valid SoH EAP " - "Extensions Method header - skip TNC"); - goto auth_method; - } - - /* Parse TLVs */ - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs (SoH)", pos, left); - while (left >= 4) { - mandatory = !!(pos[0] & 0x80); - tlv_type = pos[0] & 0x3f; - tlv_type = (tlv_type << 8) | pos[1]; - tlv_len = ((int) pos[2] << 8) | pos[3]; - pos += 4; - left -= 4; - if ((size_t) tlv_len > left) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun " - "(tlv_len=%d left=%lu)", tlv_len, - (unsigned long) left); - eap_peap_state(data, FAILURE); - return; - } - switch (tlv_type) { - case EAP_TLV_VENDOR_SPECIFIC_TLV: - if (tlv_len < 4) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Too short " - "vendor specific TLV (len=%d)", - (int) tlv_len); - eap_peap_state(data, FAILURE); - return; - } - - vendor_id = WPA_GET_BE32(pos); - if (vendor_id != EAP_VENDOR_MICROSOFT) { - if (mandatory) { - eap_peap_state(data, FAILURE); - return; - } - break; - } - - vpos = pos + 4; - mandatory = !!(vpos[0] & 0x80); - tlv_type = vpos[0] & 0x3f; - tlv_type = (tlv_type << 8) | vpos[1]; - vtlv_len = ((int) vpos[2] << 8) | vpos[3]; - vpos += 4; - if (vpos + vtlv_len > pos + left) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Vendor TLV " - "underrun"); - eap_peap_state(data, FAILURE); - return; - } - - if (tlv_type == 1) { - soh_tlv = vpos; - soh_tlv_len = vtlv_len; - break; - } - - wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported MS-TLV " - "Type %d%s", tlv_type, - mandatory ? " (mandatory)" : ""); - if (mandatory) { - eap_peap_state(data, FAILURE); - return; - } - /* Ignore this TLV, but process other TLVs */ - break; - default: - wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type " - "%d%s", tlv_type, - mandatory ? " (mandatory)" : ""); - if (mandatory) { - eap_peap_state(data, FAILURE); - return; - } - /* Ignore this TLV, but process other TLVs */ - break; - } - - pos += tlv_len; - left -= tlv_len; - } - if (left) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in " - "Request (left=%lu)", (unsigned long) left); - eap_peap_state(data, FAILURE); - return; - } - - /* Process supported TLVs */ - if (soh_tlv) { - int failure = 0; - wpabuf_free(data->soh_response); - data->soh_response = tncs_process_soh(soh_tlv, soh_tlv_len, - &failure); - if (failure) { - eap_peap_state(data, FAILURE); - return; - } - } else { - wpa_printf(MSG_DEBUG, "EAP-PEAP: No SoH TLV received"); - eap_peap_state(data, FAILURE); - return; - } - -auth_method: - eap_peap_state(data, PHASE2_METHOD); - next_type = sm->user->methods[0].method; - sm->user_eap_method_index = 1; - wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type); - eap_peap_phase2_init(sm, data, next_type); -} -#endif /* EAP_TNC */ - - -static void eap_peap_process_phase2_response(struct eap_sm *sm, - struct eap_peap_data *data, - struct wpabuf *in_data) -{ - u8 next_type = EAP_TYPE_NONE; - const struct eap_hdr *hdr; - const u8 *pos; - size_t left; - - if (data->state == PHASE2_TLV) { - eap_peap_process_phase2_tlv(sm, data, in_data); - return; - } - -#ifdef EAP_TNC - if (data->state == PHASE2_SOH) { - eap_peap_process_phase2_soh(sm, data, in_data); - return; - } -#endif /* EAP_TNC */ - - if (data->phase2_priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - Phase2 not " - "initialized?!", __func__); - return; - } - - hdr = wpabuf_head(in_data); - pos = (const u8 *) (hdr + 1); - - if (wpabuf_len(in_data) > sizeof(*hdr) && *pos == EAP_TYPE_NAK) { - left = wpabuf_len(in_data) - sizeof(*hdr); - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 type Nak'ed; " - "allowed types", pos + 1, left - 1); - eap_sm_process_nak(sm, pos + 1, left - 1); - if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && - sm->user->methods[sm->user_eap_method_index].method != - EAP_TYPE_NONE) { - next_type = sm->user->methods[ - sm->user_eap_method_index++].method; - wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", - next_type); - } else { - eap_peap_req_failure(sm, data); - next_type = EAP_TYPE_NONE; - } - eap_peap_phase2_init(sm, data, next_type); - return; - } - - if (data->phase2_method->check(sm, data->phase2_priv, in_data)) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 check() asked to " - "ignore the packet"); - return; - } - - data->phase2_method->process(sm, data->phase2_priv, in_data); - - if (sm->method_pending == METHOD_PENDING_WAIT) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method is in " - "pending wait state - save decrypted response"); - wpabuf_free(data->pending_phase2_resp); - data->pending_phase2_resp = wpabuf_dup(in_data); - } - - if (!data->phase2_method->isDone(sm, data->phase2_priv)) - return; - - if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method failed"); - eap_peap_req_failure(sm, data); - next_type = EAP_TYPE_NONE; - eap_peap_phase2_init(sm, data, next_type); - return; - } - - os_free(data->phase2_key); - if (data->phase2_method->getKey) { - data->phase2_key = data->phase2_method->getKey( - sm, data->phase2_priv, &data->phase2_key_len); - if (data->phase2_key == NULL) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 getKey " - "failed"); - eap_peap_req_failure(sm, data); - eap_peap_phase2_init(sm, data, EAP_TYPE_NONE); - return; - } - } - - switch (data->state) { - case PHASE1_ID2: - case PHASE2_ID: - case PHASE2_SOH: - if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP_PEAP: Phase2 " - "Identity not found in the user " - "database", - sm->identity, sm->identity_len); - eap_peap_req_failure(sm, data); - next_type = EAP_TYPE_NONE; - break; - } - -#ifdef EAP_TNC - if (data->state != PHASE2_SOH && sm->tnc && - data->peap_version == 0) { - eap_peap_state(data, PHASE2_SOH); - wpa_printf(MSG_DEBUG, "EAP-PEAP: Try to initialize " - "TNC (NAP SOH)"); - next_type = EAP_TYPE_NONE; - break; - } -#endif /* EAP_TNC */ - - eap_peap_state(data, PHASE2_METHOD); - next_type = sm->user->methods[0].method; - sm->user_eap_method_index = 1; - wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type); - break; - case PHASE2_METHOD: - eap_peap_req_success(sm, data); - next_type = EAP_TYPE_NONE; - break; - case FAILURE: - break; - default: - wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d", - __func__, data->state); - break; - } - - eap_peap_phase2_init(sm, data, next_type); -} - - -static void eap_peap_process_phase2(struct eap_sm *sm, - struct eap_peap_data *data, - const struct wpabuf *respData, - struct wpabuf *in_buf) -{ - struct wpabuf *in_decrypted; - int len_decrypted; - const struct eap_hdr *hdr; - size_t buf_len, len; - u8 *in_data; - size_t in_len; - - in_data = wpabuf_mhead(in_buf); - in_len = wpabuf_len(in_buf); - - wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for" - " Phase 2", (unsigned long) in_len); - - if (data->pending_phase2_resp) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - " - "skip decryption and use old data"); - eap_peap_process_phase2_response(sm, data, - data->pending_phase2_resp); - wpabuf_free(data->pending_phase2_resp); - data->pending_phase2_resp = NULL; - return; - } - - buf_len = in_len; - /* - * Even though we try to disable TLS compression, it is possible that - * this cannot be done with all TLS libraries. Add extra buffer space - * to handle the possibility of the decrypted data being longer than - * input data. - */ - buf_len += 500; - buf_len *= 3; - in_decrypted = wpabuf_alloc(buf_len); - if (in_decrypted == NULL) { - wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory " - "for decryption"); - return; - } - - len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, - in_data, in_len, - wpabuf_mhead(in_decrypted), - buf_len); - if (len_decrypted < 0) { - wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 " - "data"); - wpabuf_free(in_decrypted); - eap_peap_state(data, FAILURE); - return; - } - wpabuf_put(in_decrypted, len_decrypted); - - wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", - in_decrypted); - - hdr = wpabuf_head(in_decrypted); - - if (data->peap_version == 0 && data->state != PHASE2_TLV) { - const struct eap_hdr *resp; - struct eap_hdr *nhdr; - struct wpabuf *nbuf = - wpabuf_alloc(sizeof(struct eap_hdr) + - wpabuf_len(in_decrypted)); - if (nbuf == NULL) { - wpabuf_free(in_decrypted); - return; - } - - resp = wpabuf_head(respData); - nhdr = wpabuf_put(nbuf, sizeof(*nhdr)); - nhdr->code = resp->code; - nhdr->identifier = resp->identifier; - nhdr->length = host_to_be16(sizeof(struct eap_hdr) + - wpabuf_len(in_decrypted)); - wpabuf_put_buf(nbuf, in_decrypted); - wpabuf_free(in_decrypted); - - in_decrypted = nbuf; - } else if (data->peap_version >= 2) { - struct eap_tlv_hdr *tlv; - struct wpabuf *nmsg; - - if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) { - wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 " - "EAP TLV"); - wpabuf_free(in_decrypted); - return; - } - tlv = wpabuf_mhead(in_decrypted); - if ((be_to_host16(tlv->tlv_type) & EAP_TLV_TYPE_MASK) != - EAP_TLV_EAP_PAYLOAD_TLV) { - wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV"); - wpabuf_free(in_decrypted); - return; - } - if (sizeof(*tlv) + be_to_host16(tlv->length) > - wpabuf_len(in_decrypted)) { - wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV " - "length"); - wpabuf_free(in_decrypted); - return; - } - hdr = (struct eap_hdr *) (tlv + 1); - if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) { - wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full " - "EAP packet in EAP TLV"); - wpabuf_free(in_decrypted); - return; - } - - nmsg = wpabuf_alloc(be_to_host16(hdr->length)); - if (nmsg == NULL) { - wpabuf_free(in_decrypted); - return; - } - - wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length)); - wpabuf_free(in_decrypted); - in_decrypted = nmsg; - } - - hdr = wpabuf_head(in_decrypted); - if (wpabuf_len(in_decrypted) < (int) sizeof(*hdr)) { - wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 " - "EAP frame (len=%lu)", - (unsigned long) wpabuf_len(in_decrypted)); - wpabuf_free(in_decrypted); - eap_peap_req_failure(sm, data); - return; - } - len = be_to_host16(hdr->length); - if (len > wpabuf_len(in_decrypted)) { - wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in " - "Phase 2 EAP frame (len=%lu hdr->length=%lu)", - (unsigned long) wpabuf_len(in_decrypted), - (unsigned long) len); - wpabuf_free(in_decrypted); - eap_peap_req_failure(sm, data); - return; - } - wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d " - "identifier=%d length=%lu", hdr->code, hdr->identifier, - (unsigned long) len); - switch (hdr->code) { - case EAP_CODE_RESPONSE: - eap_peap_process_phase2_response(sm, data, in_decrypted); - break; - case EAP_CODE_SUCCESS: - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success"); - if (data->state == SUCCESS_REQ) { - eap_peap_state(data, SUCCESS); - } - break; - case EAP_CODE_FAILURE: - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure"); - eap_peap_state(data, FAILURE); - break; - default: - wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in " - "Phase 2 EAP header", hdr->code); - break; - } - - os_free(in_decrypted); -} - - -static int eap_peapv2_start_phase2(struct eap_sm *sm, - struct eap_peap_data *data) -{ - struct wpabuf *buf, *buf2; - int res; - - wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 " - "payload in the same message"); - eap_peap_state(data, PHASE1_ID2); - if (eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY)) - return -1; - - /* TODO: which Id to use here? */ - buf = data->phase2_method->buildReq(sm, data->phase2_priv, 6); - if (buf == NULL) - return -1; - - buf2 = eap_peapv2_tlv_eap_payload(buf); - if (buf2 == NULL) - return -1; - - wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Identity Request", buf2); - - buf = wpabuf_alloc(data->ssl.tls_out_limit); - if (buf == NULL) { - wpabuf_free(buf2); - return -1; - } - - res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn, - wpabuf_head(buf2), wpabuf_len(buf2), - wpabuf_put(buf, 0), - data->ssl.tls_out_limit); - wpabuf_free(buf2); - - if (res < 0) { - wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 " - "data"); - wpabuf_free(buf); - return -1; - } - - wpabuf_put(buf, res); - wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request", - buf); - - /* Append TLS data into the pending buffer after the Server Finished */ - if (wpabuf_resize(&data->ssl.out_buf, wpabuf_len(buf)) < 0) { - wpabuf_free(buf); - return -1; - } - wpabuf_put_buf(data->ssl.out_buf, buf); - wpabuf_free(buf); - - return 0; -} - - -static int eap_peap_process_version(struct eap_sm *sm, void *priv, - int peer_version) -{ - struct eap_peap_data *data = priv; - - data->recv_version = peer_version; - if (data->force_version >= 0 && peer_version != data->force_version) { - wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced" - " version (forced=%d peer=%d) - reject", - data->force_version, peer_version); - return -1; - } - if (peer_version < data->peap_version) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; " - "use version %d", - peer_version, data->peap_version, peer_version); - data->peap_version = peer_version; - } - - return 0; -} - - -static void eap_peap_process_msg(struct eap_sm *sm, void *priv, - const struct wpabuf *respData) -{ - struct eap_peap_data *data = priv; - - switch (data->state) { - case PHASE1: - if (eap_server_tls_phase1(sm, &data->ssl) < 0) { - eap_peap_state(data, FAILURE); - break; - } - - if (data->peap_version >= 2 && - tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - if (eap_peapv2_start_phase2(sm, data)) { - eap_peap_state(data, FAILURE); - break; - } - } - break; - case PHASE2_START: - eap_peap_state(data, PHASE2_ID); - eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY); - break; - case PHASE1_ID2: - case PHASE2_ID: - case PHASE2_METHOD: - case PHASE2_SOH: - case PHASE2_TLV: - eap_peap_process_phase2(sm, data, respData, data->ssl.in_buf); - break; - case SUCCESS_REQ: - eap_peap_state(data, SUCCESS); - break; - case FAILURE_REQ: - eap_peap_state(data, FAILURE); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected state %d in %s", - data->state, __func__); - break; - } -} - - -static void eap_peap_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_peap_data *data = priv; - if (eap_server_tls_process(sm, &data->ssl, respData, data, - EAP_TYPE_PEAP, eap_peap_process_version, - eap_peap_process_msg) < 0) - eap_peap_state(data, FAILURE); -} - - -static Boolean eap_peap_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_peap_data *data = priv; - u8 *eapKeyData; - - if (data->state != SUCCESS) - return NULL; - - if (data->crypto_binding_used) { - u8 csk[128]; - /* - * Note: It looks like Microsoft implementation requires null - * termination for this label while the one used for deriving - * IPMK|CMK did not use null termination. - */ - peap_prfplus(data->peap_version, data->ipmk, 40, - "Session Key Generating Function", - (u8 *) "\00", 1, csk, sizeof(csk)); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk)); - eapKeyData = os_malloc(EAP_TLS_KEY_LEN); - if (eapKeyData) { - os_memcpy(eapKeyData, csk, EAP_TLS_KEY_LEN); - *len = EAP_TLS_KEY_LEN; - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key", - eapKeyData, EAP_TLS_KEY_LEN); - } else { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive " - "key"); - } - - return eapKeyData; - } - - /* TODO: PEAPv1 - different label in some cases */ - eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, - "client EAP encryption", - EAP_TLS_KEY_LEN); - if (eapKeyData) { - *len = EAP_TLS_KEY_LEN; - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key", - eapKeyData, EAP_TLS_KEY_LEN); - } else { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive key"); - } - - return eapKeyData; -} - - -static Boolean eap_peap_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_peap_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP"); - if (eap == NULL) - return -1; - - eap->init = eap_peap_init; - eap->reset = eap_peap_reset; - eap->buildReq = eap_peap_buildReq; - eap->check = eap_peap_check; - eap->process = eap_peap_process; - eap->isDone = eap_peap_isDone; - eap->getKey = eap_peap_getKey; - eap->isSuccess = eap_peap_isSuccess; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_server/eap_psk.c b/contrib/hostapd/src/eap_server/eap_psk.c deleted file mode 100644 index c68d4c34d4..0000000000 --- a/contrib/hostapd/src/eap_server/eap_psk.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * hostapd / EAP-PSK (RFC 4764) server - * Copyright (c) 2005-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * Note: EAP-PSK is an EAP authentication method and as such, completely - * different from WPA-PSK. This file is not needed for WPA-PSK functionality. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_server/eap_i.h" -#include "aes_wrap.h" -#include "eap_common/eap_psk_common.h" - - -struct eap_psk_data { - enum { PSK_1, PSK_3, SUCCESS, FAILURE } state; - u8 rand_s[EAP_PSK_RAND_LEN]; - u8 rand_p[EAP_PSK_RAND_LEN]; - u8 *id_p, *id_s; - size_t id_p_len, id_s_len; - u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN]; - u8 msk[EAP_MSK_LEN]; - u8 emsk[EAP_EMSK_LEN]; -}; - - -static void * eap_psk_init(struct eap_sm *sm) -{ - struct eap_psk_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = PSK_1; - data->id_s = (u8 *) "hostapd"; - data->id_s_len = 7; - - return data; -} - - -static void eap_psk_reset(struct eap_sm *sm, void *priv) -{ - struct eap_psk_data *data = priv; - os_free(data->id_p); - os_free(data); -} - - -static struct wpabuf * eap_psk_build_1(struct eap_sm *sm, - struct eap_psk_data *data, u8 id) -{ - struct wpabuf *req; - struct eap_psk_hdr_1 *psk; - - wpa_printf(MSG_DEBUG, "EAP-PSK: PSK-1 (sending)"); - - if (os_get_random(data->rand_s, EAP_PSK_RAND_LEN)) { - wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data"); - data->state = FAILURE; - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: RAND_S (server rand)", - data->rand_s, EAP_PSK_RAND_LEN); - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, - sizeof(*psk) + data->id_s_len, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory " - "request"); - data->state = FAILURE; - return NULL; - } - - psk = wpabuf_put(req, sizeof(*psk)); - psk->flags = EAP_PSK_FLAGS_SET_T(0); /* T=0 */ - os_memcpy(psk->rand_s, data->rand_s, EAP_PSK_RAND_LEN); - wpabuf_put_data(req, data->id_s, data->id_s_len); - - return req; -} - - -static struct wpabuf * eap_psk_build_3(struct eap_sm *sm, - struct eap_psk_data *data, u8 id) -{ - struct wpabuf *req; - struct eap_psk_hdr_3 *psk; - u8 *buf, *pchannel, nonce[16]; - size_t buflen; - - wpa_printf(MSG_DEBUG, "EAP-PSK: PSK-3 (sending)"); - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, - sizeof(*psk) + 4 + 16 + 1, EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory " - "request"); - data->state = FAILURE; - return NULL; - } - - psk = wpabuf_put(req, sizeof(*psk)); - psk->flags = EAP_PSK_FLAGS_SET_T(2); /* T=2 */ - os_memcpy(psk->rand_s, data->rand_s, EAP_PSK_RAND_LEN); - - /* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */ - buflen = data->id_s_len + EAP_PSK_RAND_LEN; - buf = os_malloc(buflen); - if (buf == NULL) - goto fail; - - os_memcpy(buf, data->id_s, data->id_s_len); - os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN); - if (omac1_aes_128(data->ak, buf, buflen, psk->mac_s)) - goto fail; - os_free(buf); - - if (eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, data->msk, - data->emsk)) - goto fail; - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN); - - os_memset(nonce, 0, sizeof(nonce)); - pchannel = wpabuf_put(req, 4 + 16 + 1); - os_memcpy(pchannel, nonce + 12, 4); - os_memset(pchannel + 4, 0, 16); /* Tag */ - pchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS << 6; - wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL (plaintext)", - pchannel, 4 + 16 + 1); - if (aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), - wpabuf_head(req), 22, - pchannel + 4 + 16, 1, pchannel + 4)) - goto fail; - wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL (encrypted)", - pchannel, 4 + 16 + 1); - - return req; - -fail: - wpabuf_free(req); - data->state = FAILURE; - return NULL; -} - - -static struct wpabuf * eap_psk_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_psk_data *data = priv; - - switch (data->state) { - case PSK_1: - return eap_psk_build_1(sm, data, id); - case PSK_3: - return eap_psk_build_3(sm, data, id); - default: - wpa_printf(MSG_DEBUG, "EAP-PSK: Unknown state %d in buildReq", - data->state); - break; - } - return NULL; -} - - -static Boolean eap_psk_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_psk_data *data = priv; - size_t len; - u8 t; - const u8 *pos; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); - return TRUE; - } - t = EAP_PSK_FLAGS_GET_T(*pos); - - wpa_printf(MSG_DEBUG, "EAP-PSK: received frame: T=%d", t); - - if (data->state == PSK_1 && t != 1) { - wpa_printf(MSG_DEBUG, "EAP-PSK: Expected PSK-2 - " - "ignore T=%d", t); - return TRUE; - } - - if (data->state == PSK_3 && t != 3) { - wpa_printf(MSG_DEBUG, "EAP-PSK: Expected PSK-4 - " - "ignore T=%d", t); - return TRUE; - } - - if ((t == 1 && len < sizeof(struct eap_psk_hdr_2)) || - (t == 3 && len < sizeof(struct eap_psk_hdr_4))) { - wpa_printf(MSG_DEBUG, "EAP-PSK: Too short frame"); - return TRUE; - } - - return FALSE; -} - - -static void eap_psk_process_2(struct eap_sm *sm, - struct eap_psk_data *data, - struct wpabuf *respData) -{ - const struct eap_psk_hdr_2 *resp; - u8 *pos, mac[EAP_PSK_MAC_LEN], *buf; - size_t left, buflen; - int i; - const u8 *cpos; - - if (data->state != PSK_1) - return; - - wpa_printf(MSG_DEBUG, "EAP-PSK: Received PSK-2"); - - cpos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, - &left); - if (cpos == NULL || left < sizeof(*resp)) { - wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); - return; - } - resp = (const struct eap_psk_hdr_2 *) cpos; - cpos = (const u8 *) (resp + 1); - left -= sizeof(*resp); - - os_free(data->id_p); - data->id_p = os_malloc(left); - if (data->id_p == NULL) { - wpa_printf(MSG_INFO, "EAP-PSK: Failed to allocate memory for " - "ID_P"); - return; - } - os_memcpy(data->id_p, cpos, left); - data->id_p_len = left; - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PSK: ID_P", - data->id_p, data->id_p_len); - - if (eap_user_get(sm, data->id_p, data->id_p_len, 0) < 0) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: unknown ID_P", - data->id_p, data->id_p_len); - data->state = FAILURE; - return; - } - - for (i = 0; - i < EAP_MAX_METHODS && - (sm->user->methods[i].vendor != EAP_VENDOR_IETF || - sm->user->methods[i].method != EAP_TYPE_NONE); - i++) { - if (sm->user->methods[i].vendor == EAP_VENDOR_IETF && - sm->user->methods[i].method == EAP_TYPE_PSK) - break; - } - - if (i >= EAP_MAX_METHODS || - sm->user->methods[i].vendor != EAP_VENDOR_IETF || - sm->user->methods[i].method != EAP_TYPE_PSK) { - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-PSK: EAP-PSK not enabled for ID_P", - data->id_p, data->id_p_len); - data->state = FAILURE; - return; - } - - if (sm->user->password == NULL || - sm->user->password_len != EAP_PSK_PSK_LEN) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: invalid password in " - "user database for ID_P", - data->id_p, data->id_p_len); - data->state = FAILURE; - return; - } - if (eap_psk_key_setup(sm->user->password, data->ak, data->kdk)) { - data->state = FAILURE; - return; - } - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN); - - wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: RAND_P (client rand)", - resp->rand_p, EAP_PSK_RAND_LEN); - os_memcpy(data->rand_p, resp->rand_p, EAP_PSK_RAND_LEN); - - /* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */ - buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN; - buf = os_malloc(buflen); - if (buf == NULL) { - data->state = FAILURE; - return; - } - os_memcpy(buf, data->id_p, data->id_p_len); - pos = buf + data->id_p_len; - os_memcpy(pos, data->id_s, data->id_s_len); - pos += data->id_s_len; - os_memcpy(pos, data->rand_s, EAP_PSK_RAND_LEN); - pos += EAP_PSK_RAND_LEN; - os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN); - if (omac1_aes_128(data->ak, buf, buflen, mac)) { - os_free(buf); - data->state = FAILURE; - return; - } - os_free(buf); - wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", resp->mac_p, EAP_PSK_MAC_LEN); - if (os_memcmp(mac, resp->mac_p, EAP_PSK_MAC_LEN) != 0) { - wpa_printf(MSG_INFO, "EAP-PSK: Invalid MAC_P"); - wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: Expected MAC_P", - mac, EAP_PSK_MAC_LEN); - data->state = FAILURE; - return; - } - - data->state = PSK_3; -} - - -static void eap_psk_process_4(struct eap_sm *sm, - struct eap_psk_data *data, - struct wpabuf *respData) -{ - const struct eap_psk_hdr_4 *resp; - u8 *decrypted, nonce[16]; - size_t left; - const u8 *pos, *tag; - - if (data->state != PSK_3) - return; - - wpa_printf(MSG_DEBUG, "EAP-PSK: Received PSK-4"); - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &left); - if (pos == NULL || left < sizeof(*resp)) { - wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); - return; - } - resp = (const struct eap_psk_hdr_4 *) pos; - pos = (const u8 *) (resp + 1); - left -= sizeof(*resp); - - wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: Encrypted PCHANNEL", pos, left); - - if (left < 4 + 16 + 1) { - wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in " - "PSK-4 (len=%lu, expected 21)", - (unsigned long) left); - return; - } - - if (pos[0] == 0 && pos[1] == 0 && pos[2] == 0 && pos[3] == 0) { - wpa_printf(MSG_DEBUG, "EAP-PSK: Nonce did not increase"); - return; - } - - os_memset(nonce, 0, 12); - os_memcpy(nonce + 12, pos, 4); - pos += 4; - left -= 4; - tag = pos; - pos += 16; - left -= 16; - - decrypted = os_malloc(left); - if (decrypted == NULL) - return; - os_memcpy(decrypted, pos, left); - - if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce), - wpabuf_head(respData), 22, decrypted, left, - tag)) { - wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed"); - os_free(decrypted); - data->state = FAILURE; - return; - } - wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message", - decrypted, left); - - /* Verify R flag */ - switch (decrypted[0] >> 6) { - case EAP_PSK_R_FLAG_CONT: - wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - CONT - unsupported"); - data->state = FAILURE; - break; - case EAP_PSK_R_FLAG_DONE_SUCCESS: - wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_SUCCESS"); - data->state = SUCCESS; - break; - case EAP_PSK_R_FLAG_DONE_FAILURE: - wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_FAILURE"); - data->state = FAILURE; - break; - } - os_free(decrypted); -} - - -static void eap_psk_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_psk_data *data = priv; - const u8 *pos; - size_t len; - - if (sm->user == NULL || sm->user->password == NULL) { - wpa_printf(MSG_INFO, "EAP-PSK: Plaintext password not " - "configured"); - data->state = FAILURE; - return; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &len); - if (pos == NULL || len < 1) - return; - - switch (EAP_PSK_FLAGS_GET_T(*pos)) { - case 1: - eap_psk_process_2(sm, data, respData); - break; - case 3: - eap_psk_process_4(sm, data, respData); - break; - } -} - - -static Boolean eap_psk_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_psk_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_psk_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->msk, EAP_MSK_LEN); - *len = EAP_MSK_LEN; - - return key; -} - - -static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_psk_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - - return key; -} - - -static Boolean eap_psk_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_psk_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_psk_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK"); - if (eap == NULL) - return -1; - - eap->init = eap_psk_init; - eap->reset = eap_psk_reset; - eap->buildReq = eap_psk_buildReq; - eap->check = eap_psk_check; - eap->process = eap_psk_process; - eap->isDone = eap_psk_isDone; - eap->getKey = eap_psk_getKey; - eap->isSuccess = eap_psk_isSuccess; - eap->get_emsk = eap_psk_get_emsk; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_server/eap_sake.c b/contrib/hostapd/src/eap_server/eap_sake.c deleted file mode 100644 index ce4848f85e..0000000000 --- a/contrib/hostapd/src/eap_server/eap_sake.c +++ /dev/null @@ -1,542 +0,0 @@ -/* - * hostapd / EAP-SAKE (RFC 4763) server - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_server/eap_i.h" -#include "eap_common/eap_sake_common.h" - - -struct eap_sake_data { - enum { IDENTITY, CHALLENGE, CONFIRM, SUCCESS, FAILURE } state; - u8 rand_s[EAP_SAKE_RAND_LEN]; - u8 rand_p[EAP_SAKE_RAND_LEN]; - struct { - u8 auth[EAP_SAKE_TEK_AUTH_LEN]; - u8 cipher[EAP_SAKE_TEK_CIPHER_LEN]; - } tek; - u8 msk[EAP_MSK_LEN]; - u8 emsk[EAP_EMSK_LEN]; - u8 session_id; - u8 *peerid; - size_t peerid_len; - u8 *serverid; - size_t serverid_len; -}; - - -static const char * eap_sake_state_txt(int state) -{ - switch (state) { - case IDENTITY: - return "IDENTITY"; - case CHALLENGE: - return "CHALLENGE"; - case CONFIRM: - return "CONFIRM"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "?"; - } -} - - -static void eap_sake_state(struct eap_sake_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-SAKE: %s -> %s", - eap_sake_state_txt(data->state), - eap_sake_state_txt(state)); - data->state = state; -} - - -static void * eap_sake_init(struct eap_sm *sm) -{ - struct eap_sake_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = CHALLENGE; - - if (os_get_random(&data->session_id, 1)) { - wpa_printf(MSG_ERROR, "EAP-SAKE: Failed to get random data"); - os_free(data); - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-SAKE: Initialized Session ID %d", - data->session_id); - - /* TODO: add support for configuring SERVERID */ - data->serverid = (u8 *) os_strdup("hostapd"); - if (data->serverid) - data->serverid_len = os_strlen((char *) data->serverid); - - return data; -} - - -static void eap_sake_reset(struct eap_sm *sm, void *priv) -{ - struct eap_sake_data *data = priv; - os_free(data->serverid); - os_free(data->peerid); - os_free(data); -} - - -static struct wpabuf * eap_sake_build_msg(struct eap_sake_data *data, - u8 id, size_t length, u8 subtype) -{ - struct eap_sake_hdr *sake; - struct wpabuf *msg; - size_t plen; - - plen = sizeof(struct eap_sake_hdr) + length; - - msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_SAKE, plen, - EAP_CODE_REQUEST, id); - if (msg == NULL) { - wpa_printf(MSG_ERROR, "EAP-SAKE: Failed to allocate memory " - "request"); - return NULL; - } - - sake = wpabuf_put(msg, sizeof(*sake)); - sake->version = EAP_SAKE_VERSION; - sake->session_id = data->session_id; - sake->subtype = subtype; - - return msg; -} - - -static struct wpabuf * eap_sake_build_identity(struct eap_sm *sm, - struct eap_sake_data *data, - u8 id) -{ - struct wpabuf *msg; - size_t plen; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Request/Identity"); - - plen = 4; - if (data->serverid) - plen += 2 + data->serverid_len; - msg = eap_sake_build_msg(data, id, plen, EAP_SAKE_SUBTYPE_IDENTITY); - if (msg == NULL) { - data->state = FAILURE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_PERM_ID_REQ"); - eap_sake_add_attr(msg, EAP_SAKE_AT_PERM_ID_REQ, NULL, 2); - - if (data->serverid) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_SERVERID"); - eap_sake_add_attr(msg, EAP_SAKE_AT_SERVERID, - data->serverid, data->serverid_len); - } - - return msg; -} - - -static struct wpabuf * eap_sake_build_challenge(struct eap_sm *sm, - struct eap_sake_data *data, - u8 id) -{ - struct wpabuf *msg; - size_t plen; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Request/Challenge"); - - if (os_get_random(data->rand_s, EAP_SAKE_RAND_LEN)) { - wpa_printf(MSG_ERROR, "EAP-SAKE: Failed to get random data"); - data->state = FAILURE; - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, "EAP-SAKE: RAND_S (server rand)", - data->rand_s, EAP_SAKE_RAND_LEN); - - plen = 2 + EAP_SAKE_RAND_LEN; - if (data->serverid) - plen += 2 + data->serverid_len; - msg = eap_sake_build_msg(data, id, plen, EAP_SAKE_SUBTYPE_CHALLENGE); - if (msg == NULL) { - data->state = FAILURE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_RAND_S"); - eap_sake_add_attr(msg, EAP_SAKE_AT_RAND_S, - data->rand_s, EAP_SAKE_RAND_LEN); - - if (data->serverid) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_SERVERID"); - eap_sake_add_attr(msg, EAP_SAKE_AT_SERVERID, - data->serverid, data->serverid_len); - } - - return msg; -} - - -static struct wpabuf * eap_sake_build_confirm(struct eap_sm *sm, - struct eap_sake_data *data, - u8 id) -{ - struct wpabuf *msg; - u8 *mic; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Request/Confirm"); - - msg = eap_sake_build_msg(data, id, 2 + EAP_SAKE_MIC_LEN, - EAP_SAKE_SUBTYPE_CONFIRM); - if (msg == NULL) { - data->state = FAILURE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_MIC_S"); - wpabuf_put_u8(msg, EAP_SAKE_AT_MIC_S); - wpabuf_put_u8(msg, 2 + EAP_SAKE_MIC_LEN); - mic = wpabuf_put(msg, EAP_SAKE_MIC_LEN); - if (eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p, - data->serverid, data->serverid_len, - data->peerid, data->peerid_len, 0, - wpabuf_head(msg), wpabuf_len(msg), mic, mic)) - { - wpa_printf(MSG_INFO, "EAP-SAKE: Failed to compute MIC"); - data->state = FAILURE; - os_free(msg); - return NULL; - } - - return msg; -} - - -static struct wpabuf * eap_sake_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_sake_data *data = priv; - - switch (data->state) { - case IDENTITY: - return eap_sake_build_identity(sm, data, id); - case CHALLENGE: - return eap_sake_build_challenge(sm, data, id); - case CONFIRM: - return eap_sake_build_confirm(sm, data, id); - default: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Unknown state %d in buildReq", - data->state); - break; - } - return NULL; -} - - -static Boolean eap_sake_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_sake_data *data = priv; - struct eap_sake_hdr *resp; - size_t len; - u8 version, session_id, subtype; - const u8 *pos; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SAKE, respData, &len); - if (pos == NULL || len < sizeof(struct eap_sake_hdr)) { - wpa_printf(MSG_INFO, "EAP-SAKE: Invalid frame"); - return TRUE; - } - - resp = (struct eap_sake_hdr *) pos; - version = resp->version; - session_id = resp->session_id; - subtype = resp->subtype; - - if (version != EAP_SAKE_VERSION) { - wpa_printf(MSG_INFO, "EAP-SAKE: Unknown version %d", version); - return TRUE; - } - - if (session_id != data->session_id) { - wpa_printf(MSG_INFO, "EAP-SAKE: Session ID mismatch (%d,%d)", - session_id, data->session_id); - return TRUE; - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Received frame: subtype=%d", subtype); - - if (data->state == IDENTITY && subtype == EAP_SAKE_SUBTYPE_IDENTITY) - return FALSE; - - if (data->state == CHALLENGE && subtype == EAP_SAKE_SUBTYPE_CHALLENGE) - return FALSE; - - if (data->state == CONFIRM && subtype == EAP_SAKE_SUBTYPE_CONFIRM) - return FALSE; - - if (subtype == EAP_SAKE_SUBTYPE_AUTH_REJECT) - return FALSE; - - wpa_printf(MSG_INFO, "EAP-SAKE: Unexpected subtype=%d in state=%d", - subtype, data->state); - - return TRUE; -} - - -static void eap_sake_process_identity(struct eap_sm *sm, - struct eap_sake_data *data, - const struct wpabuf *respData, - const u8 *payload, size_t payloadlen) -{ - if (data->state != IDENTITY) - return; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Received Response/Identity"); - /* TODO: update identity and select new user data */ - eap_sake_state(data, CHALLENGE); -} - - -static void eap_sake_process_challenge(struct eap_sm *sm, - struct eap_sake_data *data, - const struct wpabuf *respData, - const u8 *payload, size_t payloadlen) -{ - struct eap_sake_parse_attr attr; - u8 mic_p[EAP_SAKE_MIC_LEN]; - - if (data->state != CHALLENGE) - return; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Received Response/Challenge"); - - if (eap_sake_parse_attributes(payload, payloadlen, &attr)) - return; - - if (!attr.rand_p || !attr.mic_p) { - wpa_printf(MSG_INFO, "EAP-SAKE: Response/Challenge did not " - "include AT_RAND_P or AT_MIC_P"); - return; - } - - os_memcpy(data->rand_p, attr.rand_p, EAP_SAKE_RAND_LEN); - - os_free(data->peerid); - data->peerid = NULL; - data->peerid_len = 0; - if (attr.peerid) { - data->peerid = os_malloc(attr.peerid_len); - if (data->peerid == NULL) - return; - os_memcpy(data->peerid, attr.peerid, attr.peerid_len); - data->peerid_len = attr.peerid_len; - } - - if (sm->user == NULL || sm->user->password == NULL || - sm->user->password_len != 2 * EAP_SAKE_ROOT_SECRET_LEN) { - wpa_printf(MSG_INFO, "EAP-SAKE: Plaintext password with " - "%d-byte key not configured", - 2 * EAP_SAKE_ROOT_SECRET_LEN); - data->state = FAILURE; - return; - } - eap_sake_derive_keys(sm->user->password, - sm->user->password + EAP_SAKE_ROOT_SECRET_LEN, - data->rand_s, data->rand_p, - (u8 *) &data->tek, data->msk, data->emsk); - - eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p, - data->serverid, data->serverid_len, - data->peerid, data->peerid_len, 1, - wpabuf_head(respData), wpabuf_len(respData), - attr.mic_p, mic_p); - if (os_memcmp(attr.mic_p, mic_p, EAP_SAKE_MIC_LEN) != 0) { - wpa_printf(MSG_INFO, "EAP-SAKE: Incorrect AT_MIC_P"); - eap_sake_state(data, FAILURE); - return; - } - - eap_sake_state(data, CONFIRM); -} - - -static void eap_sake_process_confirm(struct eap_sm *sm, - struct eap_sake_data *data, - const struct wpabuf *respData, - const u8 *payload, size_t payloadlen) -{ - struct eap_sake_parse_attr attr; - u8 mic_p[EAP_SAKE_MIC_LEN]; - - if (data->state != CONFIRM) - return; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Received Response/Confirm"); - - if (eap_sake_parse_attributes(payload, payloadlen, &attr)) - return; - - if (!attr.mic_p) { - wpa_printf(MSG_INFO, "EAP-SAKE: Response/Confirm did not " - "include AT_MIC_P"); - return; - } - - eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p, - data->serverid, data->serverid_len, - data->peerid, data->peerid_len, 1, - wpabuf_head(respData), wpabuf_len(respData), - attr.mic_p, mic_p); - if (os_memcmp(attr.mic_p, mic_p, EAP_SAKE_MIC_LEN) != 0) { - wpa_printf(MSG_INFO, "EAP-SAKE: Incorrect AT_MIC_P"); - eap_sake_state(data, FAILURE); - } else - eap_sake_state(data, SUCCESS); -} - - -static void eap_sake_process_auth_reject(struct eap_sm *sm, - struct eap_sake_data *data, - const struct wpabuf *respData, - const u8 *payload, size_t payloadlen) -{ - wpa_printf(MSG_DEBUG, "EAP-SAKE: Received Response/Auth-Reject"); - eap_sake_state(data, FAILURE); -} - - -static void eap_sake_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_sake_data *data = priv; - struct eap_sake_hdr *resp; - u8 subtype; - size_t len; - const u8 *pos, *end; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SAKE, respData, &len); - if (pos == NULL || len < sizeof(struct eap_sake_hdr)) - return; - - resp = (struct eap_sake_hdr *) pos; - end = pos + len; - subtype = resp->subtype; - pos = (u8 *) (resp + 1); - - wpa_hexdump(MSG_DEBUG, "EAP-SAKE: Received attributes", - pos, end - pos); - - switch (subtype) { - case EAP_SAKE_SUBTYPE_IDENTITY: - eap_sake_process_identity(sm, data, respData, pos, end - pos); - break; - case EAP_SAKE_SUBTYPE_CHALLENGE: - eap_sake_process_challenge(sm, data, respData, pos, end - pos); - break; - case EAP_SAKE_SUBTYPE_CONFIRM: - eap_sake_process_confirm(sm, data, respData, pos, end - pos); - break; - case EAP_SAKE_SUBTYPE_AUTH_REJECT: - eap_sake_process_auth_reject(sm, data, respData, pos, - end - pos); - break; - } -} - - -static Boolean eap_sake_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_sake_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_sake_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_sake_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->msk, EAP_MSK_LEN); - *len = EAP_MSK_LEN; - - return key; -} - - -static u8 * eap_sake_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_sake_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - - return key; -} - - -static Boolean eap_sake_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_sake_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_sake_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_SAKE, "SAKE"); - if (eap == NULL) - return -1; - - eap->init = eap_sake_init; - eap->reset = eap_sake_reset; - eap->buildReq = eap_sake_buildReq; - eap->check = eap_sake_check; - eap->process = eap_sake_process; - eap->isDone = eap_sake_isDone; - eap->getKey = eap_sake_getKey; - eap->isSuccess = eap_sake_isSuccess; - eap->get_emsk = eap_sake_get_emsk; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_server/eap_sim.c b/contrib/hostapd/src/eap_server/eap_sim.c deleted file mode 100644 index 436c65591f..0000000000 --- a/contrib/hostapd/src/eap_server/eap_sim.c +++ /dev/null @@ -1,797 +0,0 @@ -/* - * hostapd / EAP-SIM (RFC 4186) - * Copyright (c) 2005-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_server/eap_i.h" -#include "eap_common/eap_sim_common.h" -#include "eap_server/eap_sim_db.h" - - -struct eap_sim_data { - u8 mk[EAP_SIM_MK_LEN]; - u8 nonce_mt[EAP_SIM_NONCE_MT_LEN]; - u8 nonce_s[EAP_SIM_NONCE_S_LEN]; - u8 k_aut[EAP_SIM_K_AUT_LEN]; - u8 k_encr[EAP_SIM_K_ENCR_LEN]; - u8 msk[EAP_SIM_KEYING_DATA_LEN]; - u8 emsk[EAP_EMSK_LEN]; - u8 kc[EAP_SIM_MAX_CHAL][EAP_SIM_KC_LEN]; - u8 sres[EAP_SIM_MAX_CHAL][EAP_SIM_SRES_LEN]; - u8 rand[EAP_SIM_MAX_CHAL][GSM_RAND_LEN]; - int num_chal; - enum { - START, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE - } state; - char *next_pseudonym; - char *next_reauth_id; - u16 counter; - struct eap_sim_reauth *reauth; - u16 notification; - int use_result_ind; -}; - - -static const char * eap_sim_state_txt(int state) -{ - switch (state) { - case START: - return "START"; - case CHALLENGE: - return "CHALLENGE"; - case REAUTH: - return "REAUTH"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - case NOTIFICATION: - return "NOTIFICATION"; - default: - return "Unknown?!"; - } -} - - -static void eap_sim_state(struct eap_sim_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-SIM: %s -> %s", - eap_sim_state_txt(data->state), - eap_sim_state_txt(state)); - data->state = state; -} - - -static void * eap_sim_init(struct eap_sm *sm) -{ - struct eap_sim_data *data; - - if (sm->eap_sim_db_priv == NULL) { - wpa_printf(MSG_WARNING, "EAP-SIM: eap_sim_db not configured"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = START; - - return data; -} - - -static void eap_sim_reset(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - os_free(data->next_pseudonym); - os_free(data->next_reauth_id); - os_free(data); -} - - -static struct wpabuf * eap_sim_build_start(struct eap_sm *sm, - struct eap_sim_data *data, u8 id) -{ - struct eap_sim_msg *msg; - u8 ver[2]; - - wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Start"); - msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, - EAP_SIM_SUBTYPE_START); - if (eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity, - sm->identity_len)) { - wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); - eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); - } else { - /* - * RFC 4186, Chap. 4.2.4 recommends that identity from EAP is - * ignored and the SIM/Start is used to request the identity. - */ - wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ"); - eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0); - } - wpa_printf(MSG_DEBUG, " AT_VERSION_LIST"); - ver[0] = 0; - ver[1] = EAP_SIM_VERSION; - eap_sim_msg_add(msg, EAP_SIM_AT_VERSION_LIST, sizeof(ver), - ver, sizeof(ver)); - return eap_sim_msg_finish(msg, NULL, NULL, 0); -} - - -static int eap_sim_build_encr(struct eap_sm *sm, struct eap_sim_data *data, - struct eap_sim_msg *msg, u16 counter, - const u8 *nonce_s) -{ - os_free(data->next_pseudonym); - data->next_pseudonym = - eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 0); - os_free(data->next_reauth_id); - if (data->counter <= EAP_SIM_MAX_FAST_REAUTHS) { - data->next_reauth_id = - eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 0); - } else { - wpa_printf(MSG_DEBUG, "EAP-SIM: Max fast re-authentication " - "count exceeded - force full authentication"); - data->next_reauth_id = NULL; - } - - if (data->next_pseudonym == NULL && data->next_reauth_id == NULL && - counter == 0 && nonce_s == NULL) - return 0; - - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); - - if (counter > 0) { - wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); - } - - if (nonce_s) { - wpa_printf(MSG_DEBUG, " *AT_NONCE_S"); - eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s, - EAP_SIM_NONCE_S_LEN); - } - - if (data->next_pseudonym) { - wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)", - data->next_pseudonym); - eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM, - os_strlen(data->next_pseudonym), - (u8 *) data->next_pseudonym, - os_strlen(data->next_pseudonym)); - } - - if (data->next_reauth_id) { - wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)", - data->next_reauth_id); - eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID, - os_strlen(data->next_reauth_id), - (u8 *) data->next_reauth_id, - os_strlen(data->next_reauth_id)); - } - - if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " - "AT_ENCR_DATA"); - return -1; - } - - return 0; -} - - -static struct wpabuf * eap_sim_build_challenge(struct eap_sm *sm, - struct eap_sim_data *data, - u8 id) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Challenge"); - msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, - EAP_SIM_SUBTYPE_CHALLENGE); - wpa_printf(MSG_DEBUG, " AT_RAND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, (u8 *) data->rand, - data->num_chal * GSM_RAND_LEN); - - if (eap_sim_build_encr(sm, data, msg, 0, NULL)) { - eap_sim_msg_free(msg); - return NULL; - } - - if (sm->eap_sim_aka_result_ind) { - wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); - } - - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, data->k_aut, data->nonce_mt, - EAP_SIM_NONCE_MT_LEN); -} - - -static struct wpabuf * eap_sim_build_reauth(struct eap_sm *sm, - struct eap_sim_data *data, u8 id) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Re-authentication"); - - if (os_get_random(data->nonce_s, EAP_SIM_NONCE_S_LEN)) - return NULL; - wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: NONCE_S", - data->nonce_s, EAP_SIM_NONCE_S_LEN); - - eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, - data->emsk); - eap_sim_derive_keys_reauth(data->counter, sm->identity, - sm->identity_len, data->nonce_s, data->mk, - data->msk, data->emsk); - - msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, - EAP_SIM_SUBTYPE_REAUTHENTICATION); - - if (eap_sim_build_encr(sm, data, msg, data->counter, data->nonce_s)) { - eap_sim_msg_free(msg); - return NULL; - } - - if (sm->eap_sim_aka_result_ind) { - wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); - } - - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); -} - - -static struct wpabuf * eap_sim_build_notification(struct eap_sm *sm, - struct eap_sim_data *data, - u8 id) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Notification"); - msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, - EAP_SIM_SUBTYPE_NOTIFICATION); - wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification); - eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification, - NULL, 0); - if (data->use_result_ind) { - if (data->reauth) { - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, - EAP_SIM_AT_ENCR_DATA); - wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", - data->counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, - NULL, 0); - - if (eap_sim_msg_add_encr_end(msg, data->k_encr, - EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to " - "encrypt AT_ENCR_DATA"); - eap_sim_msg_free(msg); - return NULL; - } - } - - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - } - return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); -} - - -static struct wpabuf * eap_sim_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_sim_data *data = priv; - - switch (data->state) { - case START: - return eap_sim_build_start(sm, data, id); - case CHALLENGE: - return eap_sim_build_challenge(sm, data, id); - case REAUTH: - return eap_sim_build_reauth(sm, data, id); - case NOTIFICATION: - return eap_sim_build_notification(sm, data, id); - default: - wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in " - "buildReq", data->state); - break; - } - return NULL; -} - - -static Boolean eap_sim_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_sim_data *data = priv; - const u8 *pos; - size_t len; - u8 subtype; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len); - if (pos == NULL || len < 3) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid frame"); - return TRUE; - } - subtype = *pos; - - if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) - return FALSE; - - switch (data->state) { - case START: - if (subtype != EAP_SIM_SUBTYPE_START) { - wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " - "subtype %d", subtype); - return TRUE; - } - break; - case CHALLENGE: - if (subtype != EAP_SIM_SUBTYPE_CHALLENGE) { - wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " - "subtype %d", subtype); - return TRUE; - } - break; - case REAUTH: - if (subtype != EAP_SIM_SUBTYPE_REAUTHENTICATION) { - wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " - "subtype %d", subtype); - return TRUE; - } - break; - case NOTIFICATION: - if (subtype != EAP_SIM_SUBTYPE_NOTIFICATION) { - wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " - "subtype %d", subtype); - return TRUE; - } - break; - default: - wpa_printf(MSG_INFO, "EAP-SIM: Unexpected state (%d) for " - "processing a response", data->state); - return TRUE; - } - - return FALSE; -} - - -static int eap_sim_supported_ver(struct eap_sim_data *data, int version) -{ - return version == EAP_SIM_VERSION; -} - - -static void eap_sim_process_start(struct eap_sm *sm, - struct eap_sim_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - const u8 *identity; - size_t identity_len; - u8 ver_list[2]; - - wpa_printf(MSG_DEBUG, "EAP-SIM: Receive start response"); - - if (attr->identity) { - os_free(sm->identity); - sm->identity = os_malloc(attr->identity_len); - if (sm->identity) { - os_memcpy(sm->identity, attr->identity, - attr->identity_len); - sm->identity_len = attr->identity_len; - } - } - - identity = NULL; - identity_len = 0; - - if (sm->identity && sm->identity_len > 0 && - sm->identity[0] == EAP_SIM_PERMANENT_PREFIX) { - identity = sm->identity; - identity_len = sm->identity_len; - } else { - identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, - sm->identity, - sm->identity_len, - &identity_len); - if (identity == NULL) { - data->reauth = eap_sim_db_get_reauth_entry( - sm->eap_sim_db_priv, sm->identity, - sm->identity_len); - if (data->reauth) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Using fast " - "re-authentication"); - identity = data->reauth->identity; - identity_len = data->reauth->identity_len; - data->counter = data->reauth->counter; - os_memcpy(data->mk, data->reauth->mk, - EAP_SIM_MK_LEN); - } - } - } - - if (identity == NULL) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Could not get proper permanent" - " user name"); - eap_sim_state(data, FAILURE); - return; - } - - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity", - identity, identity_len); - - if (data->reauth) { - eap_sim_state(data, REAUTH); - return; - } - - if (attr->nonce_mt == NULL || attr->selected_version < 0) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Start/Response missing " - "required attributes"); - eap_sim_state(data, FAILURE); - return; - } - - if (!eap_sim_supported_ver(data, attr->selected_version)) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Peer selected unsupported " - "version %d", attr->selected_version); - eap_sim_state(data, FAILURE); - return; - } - - data->counter = 0; /* reset re-auth counter since this is full auth */ - data->reauth = NULL; - - data->num_chal = eap_sim_db_get_gsm_triplets( - sm->eap_sim_db_priv, identity, identity_len, - EAP_SIM_MAX_CHAL, - (u8 *) data->rand, (u8 *) data->kc, (u8 *) data->sres, sm); - if (data->num_chal == EAP_SIM_DB_PENDING) { - wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication triplets " - "not yet available - pending request"); - sm->method_pending = METHOD_PENDING_WAIT; - return; - } - if (data->num_chal < 2) { - wpa_printf(MSG_INFO, "EAP-SIM: Failed to get GSM " - "authentication triplets for the peer"); - eap_sim_state(data, FAILURE); - return; - } - - identity_len = sm->identity_len; - while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') { - wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop last null " - "character from identity"); - identity_len--; - } - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity for MK derivation", - sm->identity, identity_len); - - os_memcpy(data->nonce_mt, attr->nonce_mt, EAP_SIM_NONCE_MT_LEN); - WPA_PUT_BE16(ver_list, EAP_SIM_VERSION); - eap_sim_derive_mk(sm->identity, identity_len, attr->nonce_mt, - attr->selected_version, ver_list, sizeof(ver_list), - data->num_chal, (const u8 *) data->kc, data->mk); - eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, - data->emsk); - - eap_sim_state(data, CHALLENGE); -} - - -static void eap_sim_process_challenge(struct eap_sm *sm, - struct eap_sim_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - const u8 *identity; - size_t identity_len; - - if (attr->mac == NULL || - eap_sim_verify_mac(data->k_aut, respData, attr->mac, - (u8 *) data->sres, - data->num_chal * EAP_SIM_SRES_LEN)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message " - "did not include valid AT_MAC"); - eap_sim_state(data, FAILURE); - return; - } - - wpa_printf(MSG_DEBUG, "EAP-SIM: Challenge response includes the " - "correct AT_MAC"); - if (sm->eap_sim_aka_result_ind && attr->result_ind) { - data->use_result_ind = 1; - data->notification = EAP_SIM_SUCCESS; - eap_sim_state(data, NOTIFICATION); - } else - eap_sim_state(data, SUCCESS); - - identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, sm->identity, - sm->identity_len, &identity_len); - if (identity == NULL) { - identity = sm->identity; - identity_len = sm->identity_len; - } - - if (data->next_pseudonym) { - eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, - identity_len, - data->next_pseudonym); - data->next_pseudonym = NULL; - } - if (data->next_reauth_id) { - eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, - identity_len, - data->next_reauth_id, data->counter + 1, - data->mk); - data->next_reauth_id = NULL; - } -} - - -static void eap_sim_process_reauth(struct eap_sm *sm, - struct eap_sim_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - struct eap_sim_attrs eattr; - u8 *decrypted = NULL; - const u8 *identity, *id2; - size_t identity_len, id2_len; - - if (attr->mac == NULL || - eap_sim_verify_mac(data->k_aut, respData, attr->mac, data->nonce_s, - EAP_SIM_NONCE_S_LEN)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message " - "did not include valid AT_MAC"); - goto fail; - } - - if (attr->encr_data == NULL || attr->iv == NULL) { - wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " - "message did not include encrypted data"); - goto fail; - } - - decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, &eattr, - 0); - if (decrypted == NULL) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " - "data from reauthentication message"); - goto fail; - } - - if (eattr.counter != data->counter) { - wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message " - "used incorrect counter %u, expected %u", - eattr.counter, data->counter); - goto fail; - } - os_free(decrypted); - decrypted = NULL; - - wpa_printf(MSG_DEBUG, "EAP-SIM: Re-authentication response includes " - "the correct AT_MAC"); - if (sm->eap_sim_aka_result_ind && attr->result_ind) { - data->use_result_ind = 1; - data->notification = EAP_SIM_SUCCESS; - eap_sim_state(data, NOTIFICATION); - } else - eap_sim_state(data, SUCCESS); - - if (data->reauth) { - identity = data->reauth->identity; - identity_len = data->reauth->identity_len; - } else { - identity = sm->identity; - identity_len = sm->identity_len; - } - - id2 = eap_sim_db_get_permanent(sm->eap_sim_db_priv, identity, - identity_len, &id2_len); - if (id2) { - identity = id2; - identity_len = id2_len; - } - - if (data->next_pseudonym) { - eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, - identity_len, data->next_pseudonym); - data->next_pseudonym = NULL; - } - if (data->next_reauth_id) { - eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, - identity_len, data->next_reauth_id, - data->counter + 1, data->mk); - data->next_reauth_id = NULL; - } else { - eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); - data->reauth = NULL; - } - - return; - -fail: - eap_sim_state(data, FAILURE); - eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); - data->reauth = NULL; - os_free(decrypted); -} - - -static void eap_sim_process_client_error(struct eap_sm *sm, - struct eap_sim_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-SIM: Client reported error %d", - attr->client_error_code); - if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) - eap_sim_state(data, SUCCESS); - else - eap_sim_state(data, FAILURE); -} - - -static void eap_sim_process_notification(struct eap_sm *sm, - struct eap_sim_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-SIM: Client replied to notification"); - if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) - eap_sim_state(data, SUCCESS); - else - eap_sim_state(data, FAILURE); -} - - -static void eap_sim_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_sim_data *data = priv; - const u8 *pos, *end; - u8 subtype; - size_t len; - struct eap_sim_attrs attr; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len); - if (pos == NULL || len < 3) - return; - - end = pos + len; - subtype = *pos; - pos += 3; - - if (eap_sim_parse_attr(pos, end, &attr, 0, 0)) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to parse attributes"); - eap_sim_state(data, FAILURE); - return; - } - - if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) { - eap_sim_process_client_error(sm, data, respData, &attr); - return; - } - - switch (data->state) { - case START: - eap_sim_process_start(sm, data, respData, &attr); - break; - case CHALLENGE: - eap_sim_process_challenge(sm, data, respData, &attr); - break; - case REAUTH: - eap_sim_process_reauth(sm, data, respData, &attr); - break; - case NOTIFICATION: - eap_sim_process_notification(sm, data, respData, &attr); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in " - "process", data->state); - break; - } -} - - -static Boolean eap_sim_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_sim_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_SIM_KEYING_DATA_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); - *len = EAP_SIM_KEYING_DATA_LEN; - return key; -} - - -static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_sim_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - return key; -} - - -static Boolean eap_sim_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_sim_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM"); - if (eap == NULL) - return -1; - - eap->init = eap_sim_init; - eap->reset = eap_sim_reset; - eap->buildReq = eap_sim_buildReq; - eap->check = eap_sim_check; - eap->process = eap_sim_process; - eap->isDone = eap_sim_isDone; - eap->getKey = eap_sim_getKey; - eap->isSuccess = eap_sim_isSuccess; - eap->get_emsk = eap_sim_get_emsk; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_server/eap_sim_db.c b/contrib/hostapd/src/eap_server/eap_sim_db.c deleted file mode 100644 index ed0bd3cd13..0000000000 --- a/contrib/hostapd/src/eap_server/eap_sim_db.c +++ /dev/null @@ -1,1337 +0,0 @@ -/* - * hostapd / EAP-SIM database/authenticator gateway - * Copyright (c) 2005-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This is an example implementation of the EAP-SIM/AKA database/authentication - * gateway interface that is using an external program as an SS7 gateway to - * GSM/UMTS authentication center (HLR/AuC). hlr_auc_gw is an example - * implementation of such a gateway program. This eap_sim_db.c takes care of - * EAP-SIM/AKA pseudonyms and re-auth identities. It can be used with different - * gateway implementations for HLR/AuC access. Alternatively, it can also be - * completely replaced if the in-memory database of pseudonyms/re-auth - * identities is not suitable for some cases. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "eap_common/eap_sim_common.h" -#include "eap_server/eap_sim_db.h" -#include "eloop.h" - -struct eap_sim_pseudonym { - struct eap_sim_pseudonym *next; - u8 *identity; - size_t identity_len; - char *pseudonym; -}; - -struct eap_sim_db_pending { - struct eap_sim_db_pending *next; - u8 imsi[20]; - size_t imsi_len; - enum { PENDING, SUCCESS, FAILURE } state; - void *cb_session_ctx; - struct os_time timestamp; - int aka; - union { - struct { - u8 kc[EAP_SIM_MAX_CHAL][EAP_SIM_KC_LEN]; - u8 sres[EAP_SIM_MAX_CHAL][EAP_SIM_SRES_LEN]; - u8 rand[EAP_SIM_MAX_CHAL][GSM_RAND_LEN]; - int num_chal; - } sim; - struct { - u8 rand[EAP_AKA_RAND_LEN]; - u8 autn[EAP_AKA_AUTN_LEN]; - u8 ik[EAP_AKA_IK_LEN]; - u8 ck[EAP_AKA_CK_LEN]; - u8 res[EAP_AKA_RES_MAX_LEN]; - size_t res_len; - } aka; - } u; -}; - -struct eap_sim_db_data { - int sock; - char *fname; - char *local_sock; - void (*get_complete_cb)(void *ctx, void *session_ctx); - void *ctx; - struct eap_sim_pseudonym *pseudonyms; - struct eap_sim_reauth *reauths; - struct eap_sim_db_pending *pending; -}; - - -static struct eap_sim_db_pending * -eap_sim_db_get_pending(struct eap_sim_db_data *data, const u8 *imsi, - size_t imsi_len, int aka) -{ - struct eap_sim_db_pending *entry, *prev = NULL; - - entry = data->pending; - while (entry) { - if (entry->aka == aka && entry->imsi_len == imsi_len && - os_memcmp(entry->imsi, imsi, imsi_len) == 0) { - if (prev) - prev->next = entry->next; - else - data->pending = entry->next; - break; - } - prev = entry; - entry = entry->next; - } - return entry; -} - - -static void eap_sim_db_add_pending(struct eap_sim_db_data *data, - struct eap_sim_db_pending *entry) -{ - entry->next = data->pending; - data->pending = entry; -} - - -static void eap_sim_db_sim_resp_auth(struct eap_sim_db_data *data, - const char *imsi, char *buf) -{ - char *start, *end, *pos; - struct eap_sim_db_pending *entry; - int num_chal; - - /* - * SIM-RESP-AUTH Kc(i):SRES(i):RAND(i) ... - * SIM-RESP-AUTH FAILURE - * (IMSI = ASCII string, Kc/SRES/RAND = hex string) - */ - - entry = eap_sim_db_get_pending(data, (u8 *) imsi, os_strlen(imsi), 0); - if (entry == NULL) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: No pending entry for the " - "received message found"); - return; - } - - start = buf; - if (os_strncmp(start, "FAILURE", 7) == 0) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: External server reported " - "failure"); - entry->state = FAILURE; - eap_sim_db_add_pending(data, entry); - data->get_complete_cb(data->ctx, entry->cb_session_ctx); - return; - } - - num_chal = 0; - while (num_chal < EAP_SIM_MAX_CHAL) { - end = os_strchr(start, ' '); - if (end) - *end = '\0'; - - pos = os_strchr(start, ':'); - if (pos == NULL) - goto parse_fail; - *pos = '\0'; - if (hexstr2bin(start, entry->u.sim.kc[num_chal], - EAP_SIM_KC_LEN)) - goto parse_fail; - - start = pos + 1; - pos = os_strchr(start, ':'); - if (pos == NULL) - goto parse_fail; - *pos = '\0'; - if (hexstr2bin(start, entry->u.sim.sres[num_chal], - EAP_SIM_SRES_LEN)) - goto parse_fail; - - start = pos + 1; - if (hexstr2bin(start, entry->u.sim.rand[num_chal], - GSM_RAND_LEN)) - goto parse_fail; - - num_chal++; - if (end == NULL) - break; - else - start = end + 1; - } - entry->u.sim.num_chal = num_chal; - - entry->state = SUCCESS; - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Authentication data parsed " - "successfully - callback"); - eap_sim_db_add_pending(data, entry); - data->get_complete_cb(data->ctx, entry->cb_session_ctx); - return; - -parse_fail: - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string"); - os_free(entry); -} - - -static void eap_sim_db_aka_resp_auth(struct eap_sim_db_data *data, - const char *imsi, char *buf) -{ - char *start, *end; - struct eap_sim_db_pending *entry; - - /* - * AKA-RESP-AUTH - * AKA-RESP-AUTH FAILURE - * (IMSI = ASCII string, RAND/AUTN/IK/CK/RES = hex string) - */ - - entry = eap_sim_db_get_pending(data, (u8 *) imsi, os_strlen(imsi), 1); - if (entry == NULL) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: No pending entry for the " - "received message found"); - return; - } - - start = buf; - if (os_strncmp(start, "FAILURE", 7) == 0) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: External server reported " - "failure"); - entry->state = FAILURE; - eap_sim_db_add_pending(data, entry); - data->get_complete_cb(data->ctx, entry->cb_session_ctx); - return; - } - - end = os_strchr(start, ' '); - if (end == NULL) - goto parse_fail; - *end = '\0'; - if (hexstr2bin(start, entry->u.aka.rand, EAP_AKA_RAND_LEN)) - goto parse_fail; - - start = end + 1; - end = os_strchr(start, ' '); - if (end == NULL) - goto parse_fail; - *end = '\0'; - if (hexstr2bin(start, entry->u.aka.autn, EAP_AKA_AUTN_LEN)) - goto parse_fail; - - start = end + 1; - end = os_strchr(start, ' '); - if (end == NULL) - goto parse_fail; - *end = '\0'; - if (hexstr2bin(start, entry->u.aka.ik, EAP_AKA_IK_LEN)) - goto parse_fail; - - start = end + 1; - end = os_strchr(start, ' '); - if (end == NULL) - goto parse_fail; - *end = '\0'; - if (hexstr2bin(start, entry->u.aka.ck, EAP_AKA_CK_LEN)) - goto parse_fail; - - start = end + 1; - end = os_strchr(start, ' '); - if (end) - *end = '\0'; - else { - end = start; - while (*end) - end++; - } - entry->u.aka.res_len = (end - start) / 2; - if (entry->u.aka.res_len > EAP_AKA_RES_MAX_LEN) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Too long RES"); - entry->u.aka.res_len = 0; - goto parse_fail; - } - if (hexstr2bin(start, entry->u.aka.res, entry->u.aka.res_len)) - goto parse_fail; - - entry->state = SUCCESS; - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Authentication data parsed " - "successfully - callback"); - eap_sim_db_add_pending(data, entry); - data->get_complete_cb(data->ctx, entry->cb_session_ctx); - return; - -parse_fail: - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string"); - os_free(entry); -} - - -static void eap_sim_db_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct eap_sim_db_data *data = eloop_ctx; - char buf[1000], *pos, *cmd, *imsi; - int res; - - res = recv(sock, buf, sizeof(buf), 0); - if (res < 0) - return; - wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-SIM DB: Received from an " - "external source", (u8 *) buf, res); - if (res == 0) - return; - if (res >= (int) sizeof(buf)) - res = sizeof(buf) - 1; - buf[res] = '\0'; - - if (data->get_complete_cb == NULL) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: No get_complete_cb " - "registered"); - return; - } - - /* ... */ - - cmd = buf; - pos = os_strchr(cmd, ' '); - if (pos == NULL) - goto parse_fail; - *pos = '\0'; - imsi = pos + 1; - pos = os_strchr(imsi, ' '); - if (pos == NULL) - goto parse_fail; - *pos = '\0'; - wpa_printf(MSG_DEBUG, "EAP-SIM DB: External response=%s for IMSI %s", - cmd, imsi); - - if (os_strcmp(cmd, "SIM-RESP-AUTH") == 0) - eap_sim_db_sim_resp_auth(data, imsi, pos + 1); - else if (os_strcmp(cmd, "AKA-RESP-AUTH") == 0) - eap_sim_db_aka_resp_auth(data, imsi, pos + 1); - else - wpa_printf(MSG_INFO, "EAP-SIM DB: Unknown external response " - "'%s'", cmd); - return; - -parse_fail: - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string"); -} - - -static int eap_sim_db_open_socket(struct eap_sim_db_data *data) -{ - struct sockaddr_un addr; - static int counter = 0; - - if (os_strncmp(data->fname, "unix:", 5) != 0) - return -1; - - data->sock = socket(PF_UNIX, SOCK_DGRAM, 0); - if (data->sock < 0) { - perror("socket(eap_sim_db)"); - return -1; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_snprintf(addr.sun_path, sizeof(addr.sun_path), - "/tmp/eap_sim_db_%d-%d", getpid(), counter++); - data->local_sock = os_strdup(addr.sun_path); - if (bind(data->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind(eap_sim_db)"); - close(data->sock); - data->sock = -1; - return -1; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_strlcpy(addr.sun_path, data->fname + 5, sizeof(addr.sun_path)); - if (connect(data->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("connect(eap_sim_db)"); - wpa_hexdump_ascii(MSG_INFO, "HLR/AuC GW socket", - (u8 *) addr.sun_path, - os_strlen(addr.sun_path)); - close(data->sock); - data->sock = -1; - return -1; - } - - eloop_register_read_sock(data->sock, eap_sim_db_receive, data, NULL); - - return 0; -} - - -static void eap_sim_db_close_socket(struct eap_sim_db_data *data) -{ - if (data->sock >= 0) { - eloop_unregister_read_sock(data->sock); - close(data->sock); - data->sock = -1; - } - if (data->local_sock) { - unlink(data->local_sock); - os_free(data->local_sock); - data->local_sock = NULL; - } -} - - -/** - * eap_sim_db_init - Initialize EAP-SIM DB / authentication gateway interface - * @config: Configuration data (e.g., file name) - * @get_complete_cb: Callback function for reporting availability of triplets - * @ctx: Context pointer for get_complete_cb - * Returns: Pointer to a private data structure or %NULL on failure - */ -void * eap_sim_db_init(const char *config, - void (*get_complete_cb)(void *ctx, void *session_ctx), - void *ctx) -{ - struct eap_sim_db_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - data->sock = -1; - data->get_complete_cb = get_complete_cb; - data->ctx = ctx; - data->fname = os_strdup(config); - if (data->fname == NULL) - goto fail; - - if (os_strncmp(data->fname, "unix:", 5) == 0) { - if (eap_sim_db_open_socket(data)) - goto fail; - } - - return data; - -fail: - eap_sim_db_close_socket(data); - os_free(data->fname); - os_free(data); - return NULL; -} - - -static void eap_sim_db_free_pseudonym(struct eap_sim_pseudonym *p) -{ - os_free(p->identity); - os_free(p->pseudonym); - os_free(p); -} - - -static void eap_sim_db_free_reauth(struct eap_sim_reauth *r) -{ - os_free(r->identity); - os_free(r->reauth_id); - os_free(r); -} - - -/** - * eap_sim_db_deinit - Deinitialize EAP-SIM DB/authentication gw interface - * @priv: Private data pointer from eap_sim_db_init() - */ -void eap_sim_db_deinit(void *priv) -{ - struct eap_sim_db_data *data = priv; - struct eap_sim_pseudonym *p, *prev; - struct eap_sim_reauth *r, *prevr; - struct eap_sim_db_pending *pending, *prev_pending; - - eap_sim_db_close_socket(data); - os_free(data->fname); - - p = data->pseudonyms; - while (p) { - prev = p; - p = p->next; - eap_sim_db_free_pseudonym(prev); - } - - r = data->reauths; - while (r) { - prevr = r; - r = r->next; - eap_sim_db_free_reauth(prevr); - } - - pending = data->pending; - while (pending) { - prev_pending = pending; - pending = pending->next; - os_free(prev_pending); - } - - os_free(data); -} - - -static int eap_sim_db_send(struct eap_sim_db_data *data, const char *msg, - size_t len) -{ - int _errno = 0; - - if (send(data->sock, msg, len, 0) < 0) { - _errno = errno; - perror("send[EAP-SIM DB UNIX]"); - } - - if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL || - _errno == ECONNREFUSED) { - /* Try to reconnect */ - eap_sim_db_close_socket(data); - if (eap_sim_db_open_socket(data) < 0) - return -1; - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Reconnected to the " - "external server"); - if (send(data->sock, msg, len, 0) < 0) { - perror("send[EAP-SIM DB UNIX]"); - return -1; - } - } - - return 0; -} - - -static void eap_sim_db_expire_pending(struct eap_sim_db_data *data) -{ - /* TODO: add limit for maximum length for pending list; remove latest - * (i.e., last) entry from the list if the limit is reached; could also - * use timeout to expire pending entries */ -} - - -/** - * eap_sim_db_get_gsm_triplets - Get GSM triplets - * @priv: Private data pointer from eap_sim_db_init() - * @identity: User name identity - * @identity_len: Length of identity in bytes - * @max_chal: Maximum number of triplets - * @_rand: Buffer for RAND values - * @kc: Buffer for Kc values - * @sres: Buffer for SRES values - * @cb_session_ctx: Session callback context for get_complete_cb() - * Returns: Number of triplets received (has to be less than or equal to - * max_chal), -1 (EAP_SIM_DB_FAILURE) on error (e.g., user not found), or - * -2 (EAP_SIM_DB_PENDING) if results are not yet available. In this case, the - * callback function registered with eap_sim_db_init() will be called once the - * results become available. - * - * In most cases, the user name is '1' | IMSI, i.e., 1 followed by the IMSI in - * ASCII format. - * - * When using an external server for GSM triplets, this function can always - * start a request and return EAP_SIM_DB_PENDING immediately if authentication - * triplets are not available. Once the triplets are received, callback - * function registered with eap_sim_db_init() is called to notify EAP state - * machine to reprocess the message. This eap_sim_db_get_gsm_triplets() - * function will then be called again and the newly received triplets will then - * be given to the caller. - */ -int eap_sim_db_get_gsm_triplets(void *priv, const u8 *identity, - size_t identity_len, int max_chal, - u8 *_rand, u8 *kc, u8 *sres, - void *cb_session_ctx) -{ - struct eap_sim_db_data *data = priv; - struct eap_sim_db_pending *entry; - int len, ret; - size_t i; - char msg[40]; - - if (identity_len < 2 || identity[0] != EAP_SIM_PERMANENT_PREFIX) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity", - identity, identity_len); - return EAP_SIM_DB_FAILURE; - } - identity++; - identity_len--; - for (i = 0; i < identity_len; i++) { - if (identity[i] == '@') { - identity_len = i; - break; - } - } - if (identity_len + 1 > sizeof(entry->imsi)) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity", - identity, identity_len); - return EAP_SIM_DB_FAILURE; - } - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: Get GSM triplets for IMSI", - identity, identity_len); - - entry = eap_sim_db_get_pending(data, identity, identity_len, 0); - if (entry) { - int num_chal; - if (entry->state == FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> " - "failure"); - os_free(entry); - return EAP_SIM_DB_FAILURE; - } - - if (entry->state == PENDING) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> " - "still pending"); - eap_sim_db_add_pending(data, entry); - return EAP_SIM_DB_PENDING; - } - - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> " - "%d challenges", entry->u.sim.num_chal); - num_chal = entry->u.sim.num_chal; - if (num_chal > max_chal) - num_chal = max_chal; - os_memcpy(_rand, entry->u.sim.rand, num_chal * GSM_RAND_LEN); - os_memcpy(sres, entry->u.sim.sres, - num_chal * EAP_SIM_SRES_LEN); - os_memcpy(kc, entry->u.sim.kc, num_chal * EAP_SIM_KC_LEN); - os_free(entry); - return num_chal; - } - - if (data->sock < 0) { - if (eap_sim_db_open_socket(data) < 0) - return EAP_SIM_DB_FAILURE; - } - - len = os_snprintf(msg, sizeof(msg), "SIM-REQ-AUTH "); - if (len < 0 || len + identity_len >= sizeof(msg)) - return EAP_SIM_DB_FAILURE; - os_memcpy(msg + len, identity, identity_len); - len += identity_len; - ret = os_snprintf(msg + len, sizeof(msg) - len, " %d", max_chal); - if (ret < 0 || (size_t) ret >= sizeof(msg) - len) - return EAP_SIM_DB_FAILURE; - len += ret; - - wpa_hexdump(MSG_DEBUG, "EAP-SIM DB: requesting SIM authentication " - "data for IMSI", identity, identity_len); - if (eap_sim_db_send(data, msg, len) < 0) - return EAP_SIM_DB_FAILURE; - - entry = os_zalloc(sizeof(*entry)); - if (entry == NULL) - return EAP_SIM_DB_FAILURE; - - os_get_time(&entry->timestamp); - os_memcpy(entry->imsi, identity, identity_len); - entry->imsi_len = identity_len; - entry->cb_session_ctx = cb_session_ctx; - entry->state = PENDING; - eap_sim_db_add_pending(data, entry); - eap_sim_db_expire_pending(data); - - return EAP_SIM_DB_PENDING; -} - - -static struct eap_sim_pseudonym * -eap_sim_db_get_pseudonym(struct eap_sim_db_data *data, const u8 *identity, - size_t identity_len) -{ - char *pseudonym; - size_t len; - struct eap_sim_pseudonym *p; - - if (identity_len == 0 || - (identity[0] != EAP_SIM_PSEUDONYM_PREFIX && - identity[0] != EAP_AKA_PSEUDONYM_PREFIX)) - return NULL; - - /* Remove possible realm from identity */ - len = 0; - while (len < identity_len) { - if (identity[len] == '@') - break; - len++; - } - - pseudonym = os_malloc(len + 1); - if (pseudonym == NULL) - return NULL; - os_memcpy(pseudonym, identity, len); - pseudonym[len] = '\0'; - - p = data->pseudonyms; - while (p) { - if (os_strcmp(p->pseudonym, pseudonym) == 0) - break; - p = p->next; - } - - os_free(pseudonym); - - return p; -} - - -static struct eap_sim_pseudonym * -eap_sim_db_get_pseudonym_id(struct eap_sim_db_data *data, const u8 *identity, - size_t identity_len) -{ - struct eap_sim_pseudonym *p; - - if (identity_len == 0 || - (identity[0] != EAP_SIM_PERMANENT_PREFIX && - identity[0] != EAP_AKA_PERMANENT_PREFIX)) - return NULL; - - p = data->pseudonyms; - while (p) { - if (identity_len == p->identity_len && - os_memcmp(p->identity, identity, identity_len) == 0) - break; - p = p->next; - } - - return p; -} - - -static struct eap_sim_reauth * -eap_sim_db_get_reauth(struct eap_sim_db_data *data, const u8 *identity, - size_t identity_len) -{ - char *reauth_id; - size_t len; - struct eap_sim_reauth *r; - - if (identity_len == 0 || - (identity[0] != EAP_SIM_REAUTH_ID_PREFIX && - identity[0] != EAP_AKA_REAUTH_ID_PREFIX)) - return NULL; - - /* Remove possible realm from identity */ - len = 0; - while (len < identity_len) { - if (identity[len] == '@') - break; - len++; - } - - reauth_id = os_malloc(len + 1); - if (reauth_id == NULL) - return NULL; - os_memcpy(reauth_id, identity, len); - reauth_id[len] = '\0'; - - r = data->reauths; - while (r) { - if (os_strcmp(r->reauth_id, reauth_id) == 0) - break; - r = r->next; - } - - os_free(reauth_id); - - return r; -} - - -static struct eap_sim_reauth * -eap_sim_db_get_reauth_id(struct eap_sim_db_data *data, const u8 *identity, - size_t identity_len) -{ - struct eap_sim_pseudonym *p; - struct eap_sim_reauth *r; - - if (identity_len == 0) - return NULL; - - p = eap_sim_db_get_pseudonym(data, identity, identity_len); - if (p == NULL) - p = eap_sim_db_get_pseudonym_id(data, identity, identity_len); - if (p) { - identity = p->identity; - identity_len = p->identity_len; - } - - r = data->reauths; - while (r) { - if (identity_len == r->identity_len && - os_memcmp(r->identity, identity, identity_len) == 0) - break; - r = r->next; - } - - return r; -} - - -/** - * eap_sim_db_identity_known - Verify whether the given identity is known - * @priv: Private data pointer from eap_sim_db_init() - * @identity: User name identity - * @identity_len: Length of identity in bytes - * Returns: 0 if the user is found or -1 on failure - * - * In most cases, the user name is ['0','1'] | IMSI, i.e., 1 followed by the - * IMSI in ASCII format, ['2','3'] | pseudonym, or ['4','5'] | reauth_id. - */ -int eap_sim_db_identity_known(void *priv, const u8 *identity, - size_t identity_len) -{ - struct eap_sim_db_data *data = priv; - - if (identity == NULL || identity_len < 2) - return -1; - - if (identity[0] == EAP_SIM_PSEUDONYM_PREFIX || - identity[0] == EAP_AKA_PSEUDONYM_PREFIX) { - struct eap_sim_pseudonym *p = - eap_sim_db_get_pseudonym(data, identity, identity_len); - return p ? 0 : -1; - } - - if (identity[0] == EAP_SIM_REAUTH_ID_PREFIX || - identity[0] == EAP_AKA_REAUTH_ID_PREFIX) { - struct eap_sim_reauth *r = - eap_sim_db_get_reauth(data, identity, identity_len); - return r ? 0 : -1; - } - - if (identity[0] != EAP_SIM_PERMANENT_PREFIX && - identity[0] != EAP_AKA_PERMANENT_PREFIX) { - /* Unknown identity prefix */ - return -1; - } - - /* TODO: Should consider asking HLR/AuC gateway whether this permanent - * identity is known. If it is, EAP-SIM/AKA can skip identity request. - * In case of EAP-AKA, this would reduce number of needed round-trips. - * Ideally, this would be done with one wait, i.e., just request - * authentication data and store it for the next use. This would then - * need to use similar pending-request functionality as the normal - * request for authentication data at later phase. - */ - return -1; -} - - -static char * eap_sim_db_get_next(struct eap_sim_db_data *data, char prefix) -{ - char *id, *pos, *end; - u8 buf[10]; - - if (os_get_random(buf, sizeof(buf))) - return NULL; - id = os_malloc(sizeof(buf) * 2 + 2); - if (id == NULL) - return NULL; - - pos = id; - end = id + sizeof(buf) * 2 + 2; - *pos++ = prefix; - pos += wpa_snprintf_hex(pos, end - pos, buf, sizeof(buf)); - - return id; -} - - -/** - * eap_sim_db_get_next_pseudonym - EAP-SIM DB: Get next pseudonym - * @priv: Private data pointer from eap_sim_db_init() - * @aka: Using EAP-AKA instead of EAP-SIM - * Returns: Next pseudonym (allocated string) or %NULL on failure - * - * This function is used to generate a pseudonym for EAP-SIM. The returned - * pseudonym is not added to database at this point; it will need to be added - * with eap_sim_db_add_pseudonym() once the authentication has been completed - * successfully. Caller is responsible for freeing the returned buffer. - */ -char * eap_sim_db_get_next_pseudonym(void *priv, int aka) -{ - struct eap_sim_db_data *data = priv; - return eap_sim_db_get_next(data, aka ? EAP_AKA_PSEUDONYM_PREFIX : - EAP_SIM_PSEUDONYM_PREFIX); -} - - -/** - * eap_sim_db_get_next_reauth_id - EAP-SIM DB: Get next reauth_id - * @priv: Private data pointer from eap_sim_db_init() - * @aka: Using EAP-AKA instead of EAP-SIM - * Returns: Next reauth_id (allocated string) or %NULL on failure - * - * This function is used to generate a fast re-authentication identity for - * EAP-SIM. The returned reauth_id is not added to database at this point; it - * will need to be added with eap_sim_db_add_reauth() once the authentication - * has been completed successfully. Caller is responsible for freeing the - * returned buffer. - */ -char * eap_sim_db_get_next_reauth_id(void *priv, int aka) -{ - struct eap_sim_db_data *data = priv; - return eap_sim_db_get_next(data, aka ? EAP_AKA_REAUTH_ID_PREFIX : - EAP_SIM_REAUTH_ID_PREFIX); -} - - -/** - * eap_sim_db_add_pseudonym - EAP-SIM DB: Add new pseudonym - * @priv: Private data pointer from eap_sim_db_init() - * @identity: Identity of the user (may be permanent identity or pseudonym) - * @identity_len: Length of identity - * @pseudonym: Pseudonym for this user. This needs to be an allocated buffer, - * e.g., return value from eap_sim_db_get_next_pseudonym(). Caller must not - * free it. - * Returns: 0 on success, -1 on failure - * - * This function adds a new pseudonym for EAP-SIM user. EAP-SIM DB is - * responsible of freeing pseudonym buffer once it is not needed anymore. - */ -int eap_sim_db_add_pseudonym(void *priv, const u8 *identity, - size_t identity_len, char *pseudonym) -{ - struct eap_sim_db_data *data = priv; - struct eap_sim_pseudonym *p; - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: Add pseudonym for identity", - identity, identity_len); - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pseudonym: %s", pseudonym); - - /* TODO: could store last two pseudonyms */ - p = eap_sim_db_get_pseudonym(data, identity, identity_len); - if (p == NULL) - p = eap_sim_db_get_pseudonym_id(data, identity, identity_len); - - if (p) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Replacing previous " - "pseudonym: %s", p->pseudonym); - os_free(p->pseudonym); - p->pseudonym = pseudonym; - return 0; - } - - p = os_zalloc(sizeof(*p)); - if (p == NULL) { - os_free(pseudonym); - return -1; - } - - p->next = data->pseudonyms; - p->identity = os_malloc(identity_len); - if (p->identity == NULL) { - os_free(p); - os_free(pseudonym); - return -1; - } - os_memcpy(p->identity, identity, identity_len); - p->identity_len = identity_len; - p->pseudonym = pseudonym; - data->pseudonyms = p; - - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added new pseudonym entry"); - return 0; -} - - -static struct eap_sim_reauth * -eap_sim_db_add_reauth_data(struct eap_sim_db_data *data, const u8 *identity, - size_t identity_len, char *reauth_id, u16 counter) -{ - struct eap_sim_reauth *r; - - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: Add reauth_id for identity", - identity, identity_len); - wpa_printf(MSG_DEBUG, "EAP-SIM DB: reauth_id: %s", reauth_id); - - r = eap_sim_db_get_reauth(data, identity, identity_len); - if (r == NULL) - r = eap_sim_db_get_reauth_id(data, identity, identity_len); - - if (r) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Replacing previous " - "reauth_id: %s", r->reauth_id); - os_free(r->reauth_id); - r->reauth_id = reauth_id; - } else { - r = os_zalloc(sizeof(*r)); - if (r == NULL) { - os_free(reauth_id); - return NULL; - } - - r->next = data->reauths; - r->identity = os_malloc(identity_len); - if (r->identity == NULL) { - os_free(r); - os_free(reauth_id); - return NULL; - } - os_memcpy(r->identity, identity, identity_len); - r->identity_len = identity_len; - r->reauth_id = reauth_id; - data->reauths = r; - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added new reauth entry"); - } - - r->counter = counter; - - return r; -} - - -/** - * eap_sim_db_add_reauth - EAP-SIM DB: Add new re-authentication entry - * @priv: Private data pointer from eap_sim_db_init() - * @identity: Identity of the user (may be permanent identity or pseudonym) - * @identity_len: Length of identity - * @reauth_id: reauth_id for this user. This needs to be an allocated buffer, - * e.g., return value from eap_sim_db_get_next_reauth_id(). Caller must not - * free it. - * @counter: AT_COUNTER value for fast re-authentication - * @mk: 16-byte MK from the previous full authentication or %NULL - * Returns: 0 on success, -1 on failure - * - * This function adds a new re-authentication entry for an EAP-SIM user. - * EAP-SIM DB is responsible of freeing reauth_id buffer once it is not needed - * anymore. - */ -int eap_sim_db_add_reauth(void *priv, const u8 *identity, - size_t identity_len, char *reauth_id, u16 counter, - const u8 *mk) -{ - struct eap_sim_db_data *data = priv; - struct eap_sim_reauth *r; - - r = eap_sim_db_add_reauth_data(data, identity, identity_len, reauth_id, - counter); - if (r == NULL) - return -1; - - os_memcpy(r->mk, mk, EAP_SIM_MK_LEN); - r->aka_prime = 0; - - return 0; -} - - -#ifdef EAP_AKA_PRIME -/** - * eap_sim_db_add_reauth_prime - EAP-AKA' DB: Add new re-authentication entry - * @priv: Private data pointer from eap_sim_db_init() - * @identity: Identity of the user (may be permanent identity or pseudonym) - * @identity_len: Length of identity - * @reauth_id: reauth_id for this user. This needs to be an allocated buffer, - * e.g., return value from eap_sim_db_get_next_reauth_id(). Caller must not - * free it. - * @counter: AT_COUNTER value for fast re-authentication - * @k_encr: K_encr from the previous full authentication - * @k_aut: K_aut from the previous full authentication - * @k_re: 32-byte K_re from the previous full authentication - * Returns: 0 on success, -1 on failure - * - * This function adds a new re-authentication entry for an EAP-AKA' user. - * EAP-SIM DB is responsible of freeing reauth_id buffer once it is not needed - * anymore. - */ -int eap_sim_db_add_reauth_prime(void *priv, const u8 *identity, - size_t identity_len, char *reauth_id, - u16 counter, const u8 *k_encr, const u8 *k_aut, - const u8 *k_re) -{ - struct eap_sim_db_data *data = priv; - struct eap_sim_reauth *r; - - r = eap_sim_db_add_reauth_data(data, identity, identity_len, reauth_id, - counter); - if (r == NULL) - return -1; - - r->aka_prime = 1; - os_memcpy(r->k_encr, k_encr, EAP_SIM_K_ENCR_LEN); - os_memcpy(r->k_aut, k_aut, EAP_AKA_PRIME_K_AUT_LEN); - os_memcpy(r->k_re, k_re, EAP_AKA_PRIME_K_RE_LEN); - - return 0; -} -#endif /* EAP_AKA_PRIME */ - - -/** - * eap_sim_db_get_permanent - EAP-SIM DB: Get permanent identity - * @priv: Private data pointer from eap_sim_db_init() - * @identity: Identity of the user (may be permanent identity or pseudonym) - * @identity_len: Length of identity - * @len: Buffer for length of the returned permanent identity - * Returns: Pointer to the permanent identity, or %NULL if not found - */ -const u8 * eap_sim_db_get_permanent(void *priv, const u8 *identity, - size_t identity_len, size_t *len) -{ - struct eap_sim_db_data *data = priv; - struct eap_sim_pseudonym *p; - - if (identity == NULL) - return NULL; - - p = eap_sim_db_get_pseudonym(data, identity, identity_len); - if (p == NULL) - p = eap_sim_db_get_pseudonym_id(data, identity, identity_len); - if (p == NULL) - return NULL; - - *len = p->identity_len; - return p->identity; -} - - -/** - * eap_sim_db_get_reauth_entry - EAP-SIM DB: Get re-authentication entry - * @priv: Private data pointer from eap_sim_db_init() - * @identity: Identity of the user (may be permanent identity, pseudonym, or - * reauth_id) - * @identity_len: Length of identity - * Returns: Pointer to the re-auth entry, or %NULL if not found - */ -struct eap_sim_reauth * -eap_sim_db_get_reauth_entry(void *priv, const u8 *identity, - size_t identity_len) -{ - struct eap_sim_db_data *data = priv; - struct eap_sim_reauth *r; - - if (identity == NULL) - return NULL; - r = eap_sim_db_get_reauth(data, identity, identity_len); - if (r == NULL) - r = eap_sim_db_get_reauth_id(data, identity, identity_len); - return r; -} - - -/** - * eap_sim_db_remove_reauth - EAP-SIM DB: Remove re-authentication entry - * @priv: Private data pointer from eap_sim_db_init() - * @reauth: Pointer to re-authentication entry from - * eap_sim_db_get_reauth_entry() - */ -void eap_sim_db_remove_reauth(void *priv, struct eap_sim_reauth *reauth) -{ - struct eap_sim_db_data *data = priv; - struct eap_sim_reauth *r, *prev = NULL; - r = data->reauths; - while (r) { - if (r == reauth) { - if (prev) - prev->next = r->next; - else - data->reauths = r->next; - eap_sim_db_free_reauth(r); - return; - } - prev = r; - r = r->next; - } -} - - -/** - * eap_sim_db_get_aka_auth - Get AKA authentication values - * @priv: Private data pointer from eap_sim_db_init() - * @identity: User name identity - * @identity_len: Length of identity in bytes - * @_rand: Buffer for RAND value - * @autn: Buffer for AUTN value - * @ik: Buffer for IK value - * @ck: Buffer for CK value - * @res: Buffer for RES value - * @res_len: Buffer for RES length - * @cb_session_ctx: Session callback context for get_complete_cb() - * Returns: 0 on success, -1 (EAP_SIM_DB_FAILURE) on error (e.g., user not - * found), or -2 (EAP_SIM_DB_PENDING) if results are not yet available. In this - * case, the callback function registered with eap_sim_db_init() will be - * called once the results become available. - * - * In most cases, the user name is '0' | IMSI, i.e., 0 followed by the IMSI in - * ASCII format. - * - * When using an external server for AKA authentication, this function can - * always start a request and return EAP_SIM_DB_PENDING immediately if - * authentication triplets are not available. Once the authentication data are - * received, callback function registered with eap_sim_db_init() is called to - * notify EAP state machine to reprocess the message. This - * eap_sim_db_get_aka_auth() function will then be called again and the newly - * received triplets will then be given to the caller. - */ -int eap_sim_db_get_aka_auth(void *priv, const u8 *identity, - size_t identity_len, u8 *_rand, u8 *autn, u8 *ik, - u8 *ck, u8 *res, size_t *res_len, - void *cb_session_ctx) -{ - struct eap_sim_db_data *data = priv; - struct eap_sim_db_pending *entry; - int len; - size_t i; - char msg[40]; - - if (identity_len < 2 || identity == NULL || - identity[0] != EAP_AKA_PERMANENT_PREFIX) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity", - identity, identity_len); - return EAP_SIM_DB_FAILURE; - } - identity++; - identity_len--; - for (i = 0; i < identity_len; i++) { - if (identity[i] == '@') { - identity_len = i; - break; - } - } - if (identity_len + 1 > sizeof(entry->imsi)) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity", - identity, identity_len); - return EAP_SIM_DB_FAILURE; - } - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: Get AKA auth for IMSI", - identity, identity_len); - - entry = eap_sim_db_get_pending(data, identity, identity_len, 1); - if (entry) { - if (entry->state == FAILURE) { - os_free(entry); - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failure"); - return EAP_SIM_DB_FAILURE; - } - - if (entry->state == PENDING) { - eap_sim_db_add_pending(data, entry); - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending"); - return EAP_SIM_DB_PENDING; - } - - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Returning successfully " - "received authentication data"); - os_memcpy(_rand, entry->u.aka.rand, EAP_AKA_RAND_LEN); - os_memcpy(autn, entry->u.aka.autn, EAP_AKA_AUTN_LEN); - os_memcpy(ik, entry->u.aka.ik, EAP_AKA_IK_LEN); - os_memcpy(ck, entry->u.aka.ck, EAP_AKA_CK_LEN); - os_memcpy(res, entry->u.aka.res, EAP_AKA_RES_MAX_LEN); - *res_len = entry->u.aka.res_len; - os_free(entry); - return 0; - } - - if (data->sock < 0) { - if (eap_sim_db_open_socket(data) < 0) - return EAP_SIM_DB_FAILURE; - } - - len = os_snprintf(msg, sizeof(msg), "AKA-REQ-AUTH "); - if (len < 0 || len + identity_len >= sizeof(msg)) - return EAP_SIM_DB_FAILURE; - os_memcpy(msg + len, identity, identity_len); - len += identity_len; - - wpa_hexdump(MSG_DEBUG, "EAP-SIM DB: requesting AKA authentication " - "data for IMSI", identity, identity_len); - if (eap_sim_db_send(data, msg, len) < 0) - return EAP_SIM_DB_FAILURE; - - entry = os_zalloc(sizeof(*entry)); - if (entry == NULL) - return EAP_SIM_DB_FAILURE; - - os_get_time(&entry->timestamp); - entry->aka = 1; - os_memcpy(entry->imsi, identity, identity_len); - entry->imsi_len = identity_len; - entry->cb_session_ctx = cb_session_ctx; - entry->state = PENDING; - eap_sim_db_add_pending(data, entry); - eap_sim_db_expire_pending(data); - - return EAP_SIM_DB_PENDING; -} - - -/** - * eap_sim_db_resynchronize - Resynchronize AKA AUTN - * @priv: Private data pointer from eap_sim_db_init() - * @identity: User name identity - * @identity_len: Length of identity in bytes - * @auts: AUTS value from the peer - * @_rand: RAND value used in the rejected message - * Returns: 0 on success, -1 on failure - * - * This function is called when the peer reports synchronization failure in the - * AUTN value by sending AUTS. The AUTS and RAND values should be sent to - * HLR/AuC to allow it to resynchronize with the peer. After this, - * eap_sim_db_get_aka_auth() will be called again to to fetch updated - * RAND/AUTN values for the next challenge. - */ -int eap_sim_db_resynchronize(void *priv, const u8 *identity, - size_t identity_len, const u8 *auts, - const u8 *_rand) -{ - struct eap_sim_db_data *data = priv; - size_t i; - - if (identity_len < 2 || identity == NULL || - identity[0] != EAP_AKA_PERMANENT_PREFIX) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity", - identity, identity_len); - return -1; - } - identity++; - identity_len--; - for (i = 0; i < identity_len; i++) { - if (identity[i] == '@') { - identity_len = i; - break; - } - } - if (identity_len > 20) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity", - identity, identity_len); - return -1; - } - - if (data->sock >= 0) { - char msg[100]; - int len, ret; - - len = os_snprintf(msg, sizeof(msg), "AKA-AUTS "); - if (len < 0 || len + identity_len >= sizeof(msg)) - return -1; - os_memcpy(msg + len, identity, identity_len); - len += identity_len; - - ret = os_snprintf(msg + len, sizeof(msg) - len, " "); - if (ret < 0 || (size_t) ret >= sizeof(msg) - len) - return -1; - len += ret; - len += wpa_snprintf_hex(msg + len, sizeof(msg) - len, - auts, EAP_AKA_AUTS_LEN); - ret = os_snprintf(msg + len, sizeof(msg) - len, " "); - if (ret < 0 || (size_t) ret >= sizeof(msg) - len) - return -1; - len += ret; - len += wpa_snprintf_hex(msg + len, sizeof(msg) - len, - _rand, EAP_AKA_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-SIM DB: reporting AKA AUTS for " - "IMSI", identity, identity_len); - if (eap_sim_db_send(data, msg, len) < 0) - return -1; - } - - return 0; -} diff --git a/contrib/hostapd/src/eap_server/eap_sim_db.h b/contrib/hostapd/src/eap_server/eap_sim_db.h deleted file mode 100644 index 66221817b2..0000000000 --- a/contrib/hostapd/src/eap_server/eap_sim_db.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * hostapd / EAP-SIM database/authenticator gateway - * Copyright (c) 2005-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_SIM_DB_H -#define EAP_SIM_DB_H - -#ifdef EAP_SIM - -#include "eap_common/eap_sim_common.h" - -/* Identity prefixes */ -#define EAP_SIM_PERMANENT_PREFIX '1' -#define EAP_SIM_PSEUDONYM_PREFIX '3' -#define EAP_SIM_REAUTH_ID_PREFIX '5' -#define EAP_AKA_PERMANENT_PREFIX '0' -#define EAP_AKA_PSEUDONYM_PREFIX '2' -#define EAP_AKA_REAUTH_ID_PREFIX '4' - -void * eap_sim_db_init(const char *config, - void (*get_complete_cb)(void *ctx, void *session_ctx), - void *ctx); - -void eap_sim_db_deinit(void *priv); - -int eap_sim_db_get_gsm_triplets(void *priv, const u8 *identity, - size_t identity_len, int max_chal, - u8 *_rand, u8 *kc, u8 *sres, - void *cb_session_ctx); - -#define EAP_SIM_DB_FAILURE -1 -#define EAP_SIM_DB_PENDING -2 - -int eap_sim_db_identity_known(void *priv, const u8 *identity, - size_t identity_len); - -char * eap_sim_db_get_next_pseudonym(void *priv, int aka); - -char * eap_sim_db_get_next_reauth_id(void *priv, int aka); - -int eap_sim_db_add_pseudonym(void *priv, const u8 *identity, - size_t identity_len, char *pseudonym); - -int eap_sim_db_add_reauth(void *priv, const u8 *identity, - size_t identity_len, char *reauth_id, u16 counter, - const u8 *mk); -int eap_sim_db_add_reauth_prime(void *priv, const u8 *identity, - size_t identity_len, char *reauth_id, - u16 counter, const u8 *k_encr, const u8 *k_aut, - const u8 *k_re); - -const u8 * eap_sim_db_get_permanent(void *priv, const u8 *identity, - size_t identity_len, size_t *len); - -struct eap_sim_reauth { - struct eap_sim_reauth *next; - u8 *identity; - size_t identity_len; - char *reauth_id; - u16 counter; - int aka_prime; - u8 mk[EAP_SIM_MK_LEN]; - u8 k_encr[EAP_SIM_K_ENCR_LEN]; - u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN]; - u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; -}; - -struct eap_sim_reauth * -eap_sim_db_get_reauth_entry(void *priv, const u8 *identity, - size_t identity_len); - -void eap_sim_db_remove_reauth(void *priv, struct eap_sim_reauth *reauth); - -int eap_sim_db_get_aka_auth(void *priv, const u8 *identity, - size_t identity_len, u8 *_rand, u8 *autn, u8 *ik, - u8 *ck, u8 *res, size_t *res_len, - void *cb_session_ctx); - -int eap_sim_db_resynchronize(void *priv, const u8 *identity, - size_t identity_len, const u8 *auts, - const u8 *_rand); - -#else /* EAP_SIM */ -static inline void * -eap_sim_db_init(const char *config, - void (*get_complete_cb)(void *ctx, void *session_ctx), - void *ctx) -{ - return (void *) 1; -} - -static inline void eap_sim_db_deinit(void *priv) -{ -} -#endif /* EAP_SIM */ - -#endif /* EAP_SIM_DB_H */ diff --git a/contrib/hostapd/src/eap_server/eap_tls.c b/contrib/hostapd/src/eap_server/eap_tls.c deleted file mode 100644 index 5747940f78..0000000000 --- a/contrib/hostapd/src/eap_server/eap_tls.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * hostapd / EAP-TLS (RFC 2716) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "tls.h" - - -static void eap_tls_reset(struct eap_sm *sm, void *priv); - - -struct eap_tls_data { - struct eap_ssl_data ssl; - enum { START, CONTINUE, SUCCESS, FAILURE } state; - int established; -}; - - -static const char * eap_tls_state_txt(int state) -{ - switch (state) { - case START: - return "START"; - case CONTINUE: - return "CONTINUE"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "Unknown?!"; - } -} - - -static void eap_tls_state(struct eap_tls_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-TLS: %s -> %s", - eap_tls_state_txt(data->state), - eap_tls_state_txt(state)); - data->state = state; -} - - -static void * eap_tls_init(struct eap_sm *sm) -{ - struct eap_tls_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = START; - - if (eap_server_tls_ssl_init(sm, &data->ssl, 1)) { - wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); - eap_tls_reset(sm, data); - return NULL; - } - - return data; -} - - -static void eap_tls_reset(struct eap_sm *sm, void *priv) -{ - struct eap_tls_data *data = priv; - if (data == NULL) - return; - eap_server_tls_ssl_deinit(sm, &data->ssl); - os_free(data); -} - - -static struct wpabuf * eap_tls_build_start(struct eap_sm *sm, - struct eap_tls_data *data, u8 id) -{ - struct wpabuf *req; - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLS, 1, EAP_CODE_REQUEST, - id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-TLS: Failed to allocate memory for " - "request"); - eap_tls_state(data, FAILURE); - return NULL; - } - - wpabuf_put_u8(req, EAP_TLS_FLAGS_START); - - eap_tls_state(data, CONTINUE); - - return req; -} - - -static struct wpabuf * eap_tls_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_tls_data *data = priv; - struct wpabuf *res; - - if (data->ssl.state == FRAG_ACK) { - return eap_server_tls_build_ack(id, EAP_TYPE_TLS, 0); - } - - if (data->ssl.state == WAIT_FRAG_ACK) { - res = eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TLS, 0, - id); - goto check_established; - } - - switch (data->state) { - case START: - return eap_tls_build_start(sm, data, id); - case CONTINUE: - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) - data->established = 1; - break; - default: - wpa_printf(MSG_DEBUG, "EAP-TLS: %s - unexpected state %d", - __func__, data->state); - return NULL; - } - - res = eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TLS, 0, id); - -check_established: - if (data->established && data->ssl.state != WAIT_FRAG_ACK) { - /* TLS handshake has been completed and there are no more - * fragments waiting to be sent out. */ - wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); - eap_tls_state(data, SUCCESS); - } - - return res; -} - - -static Boolean eap_tls_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLS, respData, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-TLS: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static void eap_tls_process_msg(struct eap_sm *sm, void *priv, - const struct wpabuf *respData) -{ - struct eap_tls_data *data = priv; - if (data->state == SUCCESS && wpabuf_len(data->ssl.in_buf) == 0) { - wpa_printf(MSG_DEBUG, "EAP-TLS: Client acknowledged final TLS " - "handshake message"); - return; - } - if (eap_server_tls_phase1(sm, &data->ssl) < 0) - eap_tls_state(data, FAILURE); -} - - -static void eap_tls_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_tls_data *data = priv; - if (eap_server_tls_process(sm, &data->ssl, respData, data, - EAP_TYPE_TLS, NULL, eap_tls_process_msg) < - 0) - eap_tls_state(data, FAILURE); -} - - -static Boolean eap_tls_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_tls_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_tls_data *data = priv; - u8 *eapKeyData; - - if (data->state != SUCCESS) - return NULL; - - eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, - "client EAP encryption", - EAP_TLS_KEY_LEN); - if (eapKeyData) { - *len = EAP_TLS_KEY_LEN; - wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived key", - eapKeyData, EAP_TLS_KEY_LEN); - } else { - wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive key"); - } - - return eapKeyData; -} - - -static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_tls_data *data = priv; - u8 *eapKeyData, *emsk; - - if (data->state != SUCCESS) - return NULL; - - eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, - "client EAP encryption", - EAP_TLS_KEY_LEN + EAP_EMSK_LEN); - if (eapKeyData) { - emsk = os_malloc(EAP_EMSK_LEN); - if (emsk) - os_memcpy(emsk, eapKeyData + EAP_TLS_KEY_LEN, - EAP_EMSK_LEN); - os_free(eapKeyData); - } else - emsk = NULL; - - if (emsk) { - *len = EAP_EMSK_LEN; - wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived EMSK", - emsk, EAP_EMSK_LEN); - } else { - wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive EMSK"); - } - - return emsk; -} - - -static Boolean eap_tls_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_tls_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_tls_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS"); - if (eap == NULL) - return -1; - - eap->init = eap_tls_init; - eap->reset = eap_tls_reset; - eap->buildReq = eap_tls_buildReq; - eap->check = eap_tls_check; - eap->process = eap_tls_process; - eap->isDone = eap_tls_isDone; - eap->getKey = eap_tls_getKey; - eap->isSuccess = eap_tls_isSuccess; - eap->get_emsk = eap_tls_get_emsk; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_server/eap_tls_common.c b/contrib/hostapd/src/eap_server/eap_tls_common.c deleted file mode 100644 index bda1184c02..0000000000 --- a/contrib/hostapd/src/eap_server/eap_tls_common.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - * hostapd / EAP-TLS/PEAP/TTLS/FAST common functions - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "sha1.h" -#include "tls.h" - - -int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, - int verify_peer) -{ - data->eap = sm; - data->phase2 = sm->init_phase2; - - data->conn = tls_connection_init(sm->ssl_ctx); - if (data->conn == NULL) { - wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS " - "connection"); - return -1; - } - - if (tls_connection_set_verify(sm->ssl_ctx, data->conn, verify_peer)) { - wpa_printf(MSG_INFO, "SSL: Failed to configure verification " - "of TLS peer certificate"); - tls_connection_deinit(sm->ssl_ctx, data->conn); - data->conn = NULL; - return -1; - } - - /* TODO: make this configurable */ - data->tls_out_limit = 1398; - if (data->phase2) { - /* Limit the fragment size in the inner TLS authentication - * since the outer authentication with EAP-PEAP does not yet - * support fragmentation */ - if (data->tls_out_limit > 100) - data->tls_out_limit -= 100; - } - return 0; -} - - -void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) -{ - tls_connection_deinit(sm->ssl_ctx, data->conn); - os_free(data->in_buf); - os_free(data->out_buf); -} - - -u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, - char *label, size_t len) -{ - struct tls_keys keys; - u8 *rnd = NULL, *out; - - out = os_malloc(len); - if (out == NULL) - return NULL; - - if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) == - 0) - return out; - - if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) - goto fail; - - if (keys.client_random == NULL || keys.server_random == NULL || - keys.master_key == NULL) - goto fail; - - rnd = os_malloc(keys.client_random_len + keys.server_random_len); - if (rnd == NULL) - goto fail; - os_memcpy(rnd, keys.client_random, keys.client_random_len); - os_memcpy(rnd + keys.client_random_len, keys.server_random, - keys.server_random_len); - - if (tls_prf(keys.master_key, keys.master_key_len, - label, rnd, keys.client_random_len + - keys.server_random_len, out, len)) - goto fail; - - os_free(rnd); - return out; - -fail: - os_free(out); - os_free(rnd); - return NULL; -} - - -struct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data, - int eap_type, int version, u8 id) -{ - struct wpabuf *req; - u8 flags; - size_t send_len, plen; - - wpa_printf(MSG_DEBUG, "SSL: Generating Request"); - if (data->out_buf == NULL) { - wpa_printf(MSG_ERROR, "SSL: out_buf NULL in %s", __func__); - return NULL; - } - - flags = version; - send_len = wpabuf_len(data->out_buf) - data->out_used; - if (1 + send_len > data->tls_out_limit) { - send_len = data->tls_out_limit - 1; - flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS; - if (data->out_used == 0) { - flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED; - send_len -= 4; - } - } - - plen = 1 + send_len; - if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) - plen += 4; - - req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, plen, - EAP_CODE_REQUEST, id); - if (req == NULL) - return NULL; - - wpabuf_put_u8(req, flags); /* Flags */ - if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) - wpabuf_put_be32(req, wpabuf_len(data->out_buf)); - - wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used, - send_len); - data->out_used += send_len; - - if (data->out_used == wpabuf_len(data->out_buf)) { - wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes " - "(message sent completely)", - (unsigned long) send_len); - wpabuf_free(data->out_buf); - data->out_buf = NULL; - data->out_used = 0; - data->state = MSG; - } else { - wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes " - "(%lu more to send)", (unsigned long) send_len, - (unsigned long) wpabuf_len(data->out_buf) - - data->out_used); - data->state = WAIT_FRAG_ACK; - } - - return req; -} - - -struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version) -{ - struct wpabuf *req; - - req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, 1, EAP_CODE_REQUEST, - id); - if (req == NULL) - return NULL; - wpa_printf(MSG_DEBUG, "SSL: Building ACK"); - wpabuf_put_u8(req, version); /* Flags */ - return req; -} - - -static int eap_server_tls_process_cont(struct eap_ssl_data *data, - const u8 *buf, size_t len) -{ - /* Process continuation of a pending message */ - if (len > wpabuf_tailroom(data->in_buf)) { - wpa_printf(MSG_DEBUG, "SSL: Fragment overflow"); - return -1; - } - - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes, waiting for %lu " - "bytes more", (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - - return 0; -} - - -static int eap_server_tls_process_fragment(struct eap_ssl_data *data, - u8 flags, u32 message_length, - const u8 *buf, size_t len) -{ - /* Process a fragment that is not the last one of the message */ - if (data->in_buf == NULL && !(flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)) { - wpa_printf(MSG_DEBUG, "SSL: No Message Length field in a " - "fragmented packet"); - return -1; - } - - if (data->in_buf == NULL) { - /* First fragment of the message */ - - /* Limit length to avoid rogue peers from causing large - * memory allocations. */ - if (message_length > 65536) { - wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size" - " over 64 kB)"); - return -1; - } - - data->in_buf = wpabuf_alloc(message_length); - if (data->in_buf == NULL) { - wpa_printf(MSG_DEBUG, "SSL: No memory for message"); - return -1; - } - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes in first " - "fragment, waiting for %lu bytes more", - (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - } - - return 0; -} - - -int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data) -{ - u8 *next; - size_t next_len; - - next = tls_connection_server_handshake( - sm->ssl_ctx, data->conn, - wpabuf_mhead(data->in_buf), - wpabuf_len(data->in_buf), - &next_len); - if (next == NULL) { - wpa_printf(MSG_INFO, "SSL: TLS processing failed"); - return -1; - } - if (data->out_buf) { - /* This should not happen.. */ - wpa_printf(MSG_INFO, "SSL: pending tls_out data when " - "processing new message"); - os_free(data->out_buf); - WPA_ASSERT(data->out_buf == NULL); - } - data->out_buf = wpabuf_alloc_ext_data(next, next_len); - if (data->out_buf == NULL) { - os_free(next); - return -1; - } - return 0; -} - - -static int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags, - const u8 **pos, size_t *left) -{ - unsigned int tls_msg_len = 0; - const u8 *end = *pos + *left; - - if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { - if (*left < 4) { - wpa_printf(MSG_INFO, "SSL: Short frame with TLS " - "length"); - return -1; - } - tls_msg_len = WPA_GET_BE32(*pos); - wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d", - tls_msg_len); - *pos += 4; - *left -= 4; - } - - wpa_printf(MSG_DEBUG, "SSL: Received packet: Flags 0x%x " - "Message Length %u", flags, tls_msg_len); - - if (data->state == WAIT_FRAG_ACK) { - if (*left != 0) { - wpa_printf(MSG_DEBUG, "SSL: Unexpected payload in " - "WAIT_FRAG_ACK state"); - return -1; - } - wpa_printf(MSG_DEBUG, "SSL: Fragment acknowledged"); - return 1; - } - - if (data->in_buf && - eap_server_tls_process_cont(data, *pos, end - *pos) < 0) - return -1; - - if (flags & EAP_TLS_FLAGS_MORE_FRAGMENTS) { - if (eap_server_tls_process_fragment(data, flags, tls_msg_len, - *pos, end - *pos) < 0) - return -1; - - data->state = FRAG_ACK; - return 1; - } - - if (data->state == FRAG_ACK) { - wpa_printf(MSG_DEBUG, "SSL: All fragments received"); - data->state = MSG; - } - - if (data->in_buf == NULL) { - /* Wrap unfragmented messages as wpabuf without extra copy */ - wpabuf_set(&data->tmpbuf, *pos, end - *pos); - data->in_buf = &data->tmpbuf; - } - - return 0; -} - - -static void eap_server_tls_free_in_buf(struct eap_ssl_data *data) -{ - if (data->in_buf != &data->tmpbuf) - wpabuf_free(data->in_buf); - data->in_buf = NULL; -} - - -struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm, - struct eap_ssl_data *data, - const u8 *plain, size_t plain_len) -{ - int res; - struct wpabuf *buf; - size_t buf_len; - - /* reserve some extra room for encryption overhead */ - buf_len = plain_len + 300; - buf = wpabuf_alloc(buf_len); - if (buf == NULL) - return NULL; - res = tls_connection_encrypt(sm->ssl_ctx, data->conn, - plain, plain_len, wpabuf_put(buf, 0), - buf_len); - if (res < 0) { - wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data"); - wpabuf_free(buf); - return NULL; - } - - wpabuf_put(buf, res); - - return buf; -} - - -int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data, - struct wpabuf *respData, void *priv, int eap_type, - int (*proc_version)(struct eap_sm *sm, void *priv, - int peer_version), - void (*proc_msg)(struct eap_sm *sm, void *priv, - const struct wpabuf *respData)) -{ - const u8 *pos; - u8 flags; - size_t left; - int ret, res = 0; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, respData, &left); - if (pos == NULL || left < 1) - return 0; /* Should not happen - frame already validated */ - flags = *pos++; - left--; - wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - Flags 0x%02x", - (unsigned long) wpabuf_len(respData), flags); - - if (proc_version && - proc_version(sm, priv, flags & EAP_TLS_VERSION_MASK) < 0) - return -1; - - ret = eap_server_tls_reassemble(data, flags, &pos, &left); - if (ret < 0) { - res = -1; - goto done; - } else if (ret == 1) - return 0; - - if (proc_msg) - proc_msg(sm, priv, respData); - - if (tls_connection_get_write_alerts(sm->ssl_ctx, data->conn) > 1) { - wpa_printf(MSG_INFO, "SSL: Locally detected fatal error in " - "TLS processing"); - res = -1; - } - -done: - eap_server_tls_free_in_buf(data); - - return res; -} diff --git a/contrib/hostapd/src/eap_server/eap_tls_common.h b/contrib/hostapd/src/eap_server/eap_tls_common.h deleted file mode 100644 index ce8dd252bc..0000000000 --- a/contrib/hostapd/src/eap_server/eap_tls_common.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * hostapd / EAP-TLS/PEAP/TTLS/FAST common functions - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_TLS_COMMON_H -#define EAP_TLS_COMMON_H - -struct eap_ssl_data { - struct tls_connection *conn; - - size_t tls_out_limit; - - int phase2; - - struct eap_sm *eap; - - enum { MSG, FRAG_ACK, WAIT_FRAG_ACK } state; - struct wpabuf *in_buf; - struct wpabuf *out_buf; - size_t out_used; - struct wpabuf tmpbuf; -}; - - -/* EAP TLS Flags */ -#define EAP_TLS_FLAGS_LENGTH_INCLUDED 0x80 -#define EAP_TLS_FLAGS_MORE_FRAGMENTS 0x40 -#define EAP_TLS_FLAGS_START 0x20 -#define EAP_TLS_VERSION_MASK 0x07 - - /* could be up to 128 bytes, but only the first 64 bytes are used */ -#define EAP_TLS_KEY_LEN 64 - - -int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, - int verify_peer); -void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data); -u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, - char *label, size_t len); -struct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data, - int eap_type, int version, u8 id); -struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version); -int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data); -struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm, - struct eap_ssl_data *data, - const u8 *plain, size_t plain_len); -int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data, - struct wpabuf *respData, void *priv, int eap_type, - int (*proc_version)(struct eap_sm *sm, void *priv, - int peer_version), - void (*proc_msg)(struct eap_sm *sm, void *priv, - const struct wpabuf *respData)); - -#endif /* EAP_TLS_COMMON_H */ diff --git a/contrib/hostapd/src/eap_server/eap_tnc.c b/contrib/hostapd/src/eap_server/eap_tnc.c deleted file mode 100644 index 4cb3ecfb05..0000000000 --- a/contrib/hostapd/src/eap_server/eap_tnc.c +++ /dev/null @@ -1,536 +0,0 @@ -/* - * EAP server method: EAP-TNC (Trusted Network Connect) - * Copyright (c) 2007-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "base64.h" -#include "eap_i.h" -#include "tncs.h" - - -struct eap_tnc_data { - enum { START, CONTINUE, RECOMMENDATION, FRAG_ACK, WAIT_FRAG_ACK, DONE, - FAIL } state; - enum { ALLOW, ISOLATE, NO_ACCESS, NO_RECOMMENDATION } recommendation; - struct tncs_data *tncs; - struct wpabuf *in_buf; - struct wpabuf *out_buf; - size_t out_used; - size_t fragment_size; -}; - - -/* EAP-TNC Flags */ -#define EAP_TNC_FLAGS_LENGTH_INCLUDED 0x80 -#define EAP_TNC_FLAGS_MORE_FRAGMENTS 0x40 -#define EAP_TNC_FLAGS_START 0x20 -#define EAP_TNC_VERSION_MASK 0x07 - -#define EAP_TNC_VERSION 1 - - -static void * eap_tnc_init(struct eap_sm *sm) -{ - struct eap_tnc_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = START; - data->tncs = tncs_init(); - if (data->tncs == NULL) { - os_free(data); - return NULL; - } - - data->fragment_size = 1300; - - return data; -} - - -static void eap_tnc_reset(struct eap_sm *sm, void *priv) -{ - struct eap_tnc_data *data = priv; - wpabuf_free(data->in_buf); - wpabuf_free(data->out_buf); - tncs_deinit(data->tncs); - os_free(data); -} - - -static struct wpabuf * eap_tnc_build_start(struct eap_sm *sm, - struct eap_tnc_data *data, u8 id) -{ - struct wpabuf *req; - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 1, EAP_CODE_REQUEST, - id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-TNC: Failed to allocate memory for " - "request"); - data->state = FAIL; - return NULL; - } - - wpabuf_put_u8(req, EAP_TNC_FLAGS_START | EAP_TNC_VERSION); - - data->state = CONTINUE; - - return req; -} - - -static struct wpabuf * eap_tnc_build(struct eap_sm *sm, - struct eap_tnc_data *data) -{ - struct wpabuf *req; - u8 *rpos, *rpos1; - size_t rlen; - char *start_buf, *end_buf; - size_t start_len, end_len; - size_t imv_len; - - imv_len = tncs_total_send_len(data->tncs); - - start_buf = tncs_if_tnccs_start(data->tncs); - if (start_buf == NULL) - return NULL; - start_len = os_strlen(start_buf); - end_buf = tncs_if_tnccs_end(); - if (end_buf == NULL) { - os_free(start_buf); - return NULL; - } - end_len = os_strlen(end_buf); - - rlen = start_len + imv_len + end_len; - req = wpabuf_alloc(rlen); - if (req == NULL) { - os_free(start_buf); - os_free(end_buf); - return NULL; - } - - wpabuf_put_data(req, start_buf, start_len); - os_free(start_buf); - - rpos1 = wpabuf_put(req, 0); - rpos = tncs_copy_send_buf(data->tncs, rpos1); - wpabuf_put(req, rpos - rpos1); - - wpabuf_put_data(req, end_buf, end_len); - os_free(end_buf); - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TNC: Request", - wpabuf_head(req), wpabuf_len(req)); - - return req; -} - - -static struct wpabuf * eap_tnc_build_recommendation(struct eap_sm *sm, - struct eap_tnc_data *data) -{ - switch (data->recommendation) { - case ALLOW: - data->state = DONE; - break; - case ISOLATE: - data->state = FAIL; - /* TODO: support assignment to a different VLAN */ - break; - case NO_ACCESS: - data->state = FAIL; - break; - case NO_RECOMMENDATION: - data->state = DONE; - break; - default: - wpa_printf(MSG_DEBUG, "EAP-TNC: Unknown recommendation"); - return NULL; - } - - return eap_tnc_build(sm, data); -} - - -static struct wpabuf * eap_tnc_build_frag_ack(u8 id, u8 code) -{ - struct wpabuf *msg; - - msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 0, code, id); - if (msg == NULL) { - wpa_printf(MSG_ERROR, "EAP-TNC: Failed to allocate memory " - "for fragment ack"); - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-TNC: Send fragment ack"); - - return msg; -} - - -static struct wpabuf * eap_tnc_build_msg(struct eap_tnc_data *data, u8 id) -{ - struct wpabuf *req; - u8 flags; - size_t send_len, plen; - - wpa_printf(MSG_DEBUG, "EAP-TNC: Generating Request"); - - flags = EAP_TNC_VERSION; - send_len = wpabuf_len(data->out_buf) - data->out_used; - if (1 + send_len > data->fragment_size) { - send_len = data->fragment_size - 1; - flags |= EAP_TNC_FLAGS_MORE_FRAGMENTS; - if (data->out_used == 0) { - flags |= EAP_TNC_FLAGS_LENGTH_INCLUDED; - send_len -= 4; - } - } - - plen = 1 + send_len; - if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) - plen += 4; - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, plen, - EAP_CODE_REQUEST, id); - if (req == NULL) - return NULL; - - wpabuf_put_u8(req, flags); /* Flags */ - if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) - wpabuf_put_be32(req, wpabuf_len(data->out_buf)); - - wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used, - send_len); - data->out_used += send_len; - - if (data->out_used == wpabuf_len(data->out_buf)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Sending out %lu bytes " - "(message sent completely)", - (unsigned long) send_len); - wpabuf_free(data->out_buf); - data->out_buf = NULL; - data->out_used = 0; - } else { - wpa_printf(MSG_DEBUG, "EAP-TNC: Sending out %lu bytes " - "(%lu more to send)", (unsigned long) send_len, - (unsigned long) wpabuf_len(data->out_buf) - - data->out_used); - data->state = WAIT_FRAG_ACK; - } - - return req; -} - - -static struct wpabuf * eap_tnc_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_tnc_data *data = priv; - - switch (data->state) { - case START: - tncs_init_connection(data->tncs); - return eap_tnc_build_start(sm, data, id); - case CONTINUE: - if (data->out_buf == NULL) { - data->out_buf = eap_tnc_build(sm, data); - if (data->out_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Failed to " - "generate message"); - return NULL; - } - data->out_used = 0; - } - return eap_tnc_build_msg(data, id); - case RECOMMENDATION: - if (data->out_buf == NULL) { - data->out_buf = eap_tnc_build_recommendation(sm, data); - if (data->out_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Failed to " - "generate recommendation message"); - return NULL; - } - data->out_used = 0; - } - return eap_tnc_build_msg(data, id); - case WAIT_FRAG_ACK: - return eap_tnc_build_msg(data, id); - case FRAG_ACK: - return eap_tnc_build_frag_ack(id, EAP_CODE_REQUEST); - case DONE: - case FAIL: - return NULL; - } - - return NULL; -} - - -static Boolean eap_tnc_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_tnc_data *data = priv; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TNC, respData, - &len); - if (pos == NULL) { - wpa_printf(MSG_INFO, "EAP-TNC: Invalid frame"); - return TRUE; - } - - if (len == 0 && data->state != WAIT_FRAG_ACK) { - wpa_printf(MSG_INFO, "EAP-TNC: Invalid frame (empty)"); - return TRUE; - } - - if (len == 0) - return FALSE; /* Fragment ACK does not include flags */ - - if ((*pos & EAP_TNC_VERSION_MASK) != EAP_TNC_VERSION) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Unsupported version %d", - *pos & EAP_TNC_VERSION_MASK); - return TRUE; - } - - if (*pos & EAP_TNC_FLAGS_START) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Peer used Start flag"); - return TRUE; - } - - return FALSE; -} - - -static void tncs_process(struct eap_tnc_data *data, struct wpabuf *inbuf) -{ - enum tncs_process_res res; - - res = tncs_process_if_tnccs(data->tncs, wpabuf_head(inbuf), - wpabuf_len(inbuf)); - switch (res) { - case TNCCS_RECOMMENDATION_ALLOW: - wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS allowed access"); - data->state = RECOMMENDATION; - data->recommendation = ALLOW; - break; - case TNCCS_RECOMMENDATION_NO_RECOMMENDATION: - wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS has no recommendation"); - data->state = RECOMMENDATION; - data->recommendation = NO_RECOMMENDATION; - break; - case TNCCS_RECOMMENDATION_ISOLATE: - wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS requested isolation"); - data->state = RECOMMENDATION; - data->recommendation = ISOLATE; - break; - case TNCCS_RECOMMENDATION_NO_ACCESS: - wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS rejected access"); - data->state = RECOMMENDATION; - data->recommendation = NO_ACCESS; - break; - case TNCCS_PROCESS_ERROR: - wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS processing error"); - data->state = FAIL; - break; - default: - break; - } -} - - -static int eap_tnc_process_cont(struct eap_tnc_data *data, - const u8 *buf, size_t len) -{ - /* Process continuation of a pending message */ - if (len > wpabuf_tailroom(data->in_buf)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Fragment overflow"); - data->state = FAIL; - return -1; - } - - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-TNC: Received %lu bytes, waiting for %lu " - "bytes more", (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - - return 0; -} - - -static int eap_tnc_process_fragment(struct eap_tnc_data *data, - u8 flags, u32 message_length, - const u8 *buf, size_t len) -{ - /* Process a fragment that is not the last one of the message */ - if (data->in_buf == NULL && !(flags & EAP_TNC_FLAGS_LENGTH_INCLUDED)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: No Message Length field in a " - "fragmented packet"); - return -1; - } - - if (data->in_buf == NULL) { - /* First fragment of the message */ - data->in_buf = wpabuf_alloc(message_length); - if (data->in_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TNC: No memory for " - "message"); - return -1; - } - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-TNC: Received %lu bytes in first " - "fragment, waiting for %lu bytes more", - (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - } - - return 0; -} - - -static void eap_tnc_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_tnc_data *data = priv; - const u8 *pos, *end; - size_t len; - u8 flags; - u32 message_length = 0; - struct wpabuf tmpbuf; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TNC, respData, &len); - if (pos == NULL) - return; /* Should not happen; message already verified */ - - end = pos + len; - - if (len == 1 && (data->state == DONE || data->state == FAIL)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Peer acknowledged the last " - "message"); - return; - } - - if (len == 0) { - /* fragment ack */ - flags = 0; - } else - flags = *pos++; - - if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) { - if (end - pos < 4) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Message underflow"); - data->state = FAIL; - return; - } - message_length = WPA_GET_BE32(pos); - pos += 4; - - if (message_length < (u32) (end - pos)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Invalid Message " - "Length (%d; %ld remaining in this msg)", - message_length, (long) (end - pos)); - data->state = FAIL; - return; - } - } - wpa_printf(MSG_DEBUG, "EAP-TNC: Received packet: Flags 0x%x " - "Message Length %u", flags, message_length); - - if (data->state == WAIT_FRAG_ACK) { - if (len != 0) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Unexpected payload " - "in WAIT_FRAG_ACK state"); - data->state = FAIL; - return; - } - wpa_printf(MSG_DEBUG, "EAP-TNC: Fragment acknowledged"); - data->state = CONTINUE; - return; - } - - if (data->in_buf && eap_tnc_process_cont(data, pos, end - pos) < 0) { - data->state = FAIL; - return; - } - - if (flags & EAP_TNC_FLAGS_MORE_FRAGMENTS) { - if (eap_tnc_process_fragment(data, flags, message_length, - pos, end - pos) < 0) - data->state = FAIL; - else - data->state = FRAG_ACK; - return; - } else if (data->state == FRAG_ACK) { - wpa_printf(MSG_DEBUG, "EAP-TNC: All fragments received"); - data->state = CONTINUE; - } - - if (data->in_buf == NULL) { - /* Wrap unfragmented messages as wpabuf without extra copy */ - wpabuf_set(&tmpbuf, pos, end - pos); - data->in_buf = &tmpbuf; - } - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TNC: Received payload", - wpabuf_head(data->in_buf), wpabuf_len(data->in_buf)); - tncs_process(data, data->in_buf); - - if (data->in_buf != &tmpbuf) - wpabuf_free(data->in_buf); - data->in_buf = NULL; -} - - -static Boolean eap_tnc_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_tnc_data *data = priv; - return data->state == DONE || data->state == FAIL; -} - - -static Boolean eap_tnc_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_tnc_data *data = priv; - return data->state == DONE; -} - - -int eap_server_tnc_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_TNC, "TNC"); - if (eap == NULL) - return -1; - - eap->init = eap_tnc_init; - eap->reset = eap_tnc_reset; - eap->buildReq = eap_tnc_buildReq; - eap->check = eap_tnc_check; - eap->process = eap_tnc_process; - eap->isDone = eap_tnc_isDone; - eap->isSuccess = eap_tnc_isSuccess; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_server/eap_ttls.c b/contrib/hostapd/src/eap_server/eap_ttls.c deleted file mode 100644 index 21e4b21b15..0000000000 --- a/contrib/hostapd/src/eap_server/eap_ttls.c +++ /dev/null @@ -1,1477 +0,0 @@ -/* - * hostapd / EAP-TTLS (RFC 5281) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_server/eap_i.h" -#include "eap_server/eap_tls_common.h" -#include "ms_funcs.h" -#include "sha1.h" -#include "eap_common/chap.h" -#include "tls.h" -#include "eap_common/eap_ttls.h" - - -/* Maximum supported TTLS version - * 0 = RFC 5281 - * 1 = draft-funk-eap-ttls-v1-00.txt - */ -#ifndef EAP_TTLS_VERSION -#define EAP_TTLS_VERSION 0 /* TTLSv1 implementation is not yet complete */ -#endif /* EAP_TTLS_VERSION */ - - -#define MSCHAPV2_KEY_LEN 16 - - -static void eap_ttls_reset(struct eap_sm *sm, void *priv); - - -struct eap_ttls_data { - struct eap_ssl_data ssl; - enum { - START, PHASE1, PHASE2_START, PHASE2_METHOD, - PHASE2_MSCHAPV2_RESP, PHASE_FINISHED, SUCCESS, FAILURE - } state; - - int ttls_version; - int force_version; - const struct eap_method *phase2_method; - void *phase2_priv; - int mschapv2_resp_ok; - u8 mschapv2_auth_response[20]; - u8 mschapv2_ident; - int tls_ia_configured; - struct wpabuf *pending_phase2_eap_resp; - int tnc_started; -}; - - -static const char * eap_ttls_state_txt(int state) -{ - switch (state) { - case START: - return "START"; - case PHASE1: - return "PHASE1"; - case PHASE2_START: - return "PHASE2_START"; - case PHASE2_METHOD: - return "PHASE2_METHOD"; - case PHASE2_MSCHAPV2_RESP: - return "PHASE2_MSCHAPV2_RESP"; - case PHASE_FINISHED: - return "PHASE_FINISHED"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "Unknown?!"; - } -} - - -static void eap_ttls_state(struct eap_ttls_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-TTLS: %s -> %s", - eap_ttls_state_txt(data->state), - eap_ttls_state_txt(state)); - data->state = state; -} - - -static u8 * eap_ttls_avp_hdr(u8 *avphdr, u32 avp_code, u32 vendor_id, - int mandatory, size_t len) -{ - struct ttls_avp_vendor *avp; - u8 flags; - size_t hdrlen; - - avp = (struct ttls_avp_vendor *) avphdr; - flags = mandatory ? AVP_FLAGS_MANDATORY : 0; - if (vendor_id) { - flags |= AVP_FLAGS_VENDOR; - hdrlen = sizeof(*avp); - avp->vendor_id = host_to_be32(vendor_id); - } else { - hdrlen = sizeof(struct ttls_avp); - } - - avp->avp_code = host_to_be32(avp_code); - avp->avp_length = host_to_be32((flags << 24) | (hdrlen + len)); - - return avphdr + hdrlen; -} - - -static struct wpabuf * eap_ttls_avp_encapsulate(struct wpabuf *resp, - u32 avp_code, int mandatory) -{ - struct wpabuf *avp; - u8 *pos; - - avp = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(resp) + 4); - if (avp == NULL) { - wpabuf_free(resp); - return NULL; - } - - pos = eap_ttls_avp_hdr(wpabuf_mhead(avp), avp_code, 0, mandatory, - wpabuf_len(resp)); - os_memcpy(pos, wpabuf_head(resp), wpabuf_len(resp)); - pos += wpabuf_len(resp); - AVP_PAD((const u8 *) wpabuf_head(avp), pos); - wpabuf_free(resp); - wpabuf_put(avp, pos - (u8 *) wpabuf_head(avp)); - return avp; -} - - -struct eap_ttls_avp { - /* Note: eap is allocated memory; caller is responsible for freeing - * it. All the other pointers are pointing to the packet data, i.e., - * they must not be freed separately. */ - u8 *eap; - size_t eap_len; - u8 *user_name; - size_t user_name_len; - u8 *user_password; - size_t user_password_len; - u8 *chap_challenge; - size_t chap_challenge_len; - u8 *chap_password; - size_t chap_password_len; - u8 *mschap_challenge; - size_t mschap_challenge_len; - u8 *mschap_response; - size_t mschap_response_len; - u8 *mschap2_response; - size_t mschap2_response_len; -}; - - -static int eap_ttls_avp_parse(u8 *buf, size_t len, struct eap_ttls_avp *parse) -{ - struct ttls_avp *avp; - u8 *pos; - int left; - - pos = buf; - left = len; - os_memset(parse, 0, sizeof(*parse)); - - while (left > 0) { - u32 avp_code, avp_length, vendor_id = 0; - u8 avp_flags, *dpos; - size_t pad, dlen; - avp = (struct ttls_avp *) pos; - avp_code = be_to_host32(avp->avp_code); - avp_length = be_to_host32(avp->avp_length); - avp_flags = (avp_length >> 24) & 0xff; - avp_length &= 0xffffff; - wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP: code=%d flags=0x%02x " - "length=%d", (int) avp_code, avp_flags, - (int) avp_length); - if ((int) avp_length > left) { - wpa_printf(MSG_WARNING, "EAP-TTLS: AVP overflow " - "(len=%d, left=%d) - dropped", - (int) avp_length, left); - goto fail; - } - if (avp_length < sizeof(*avp)) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid AVP length " - "%d", avp_length); - goto fail; - } - dpos = (u8 *) (avp + 1); - dlen = avp_length - sizeof(*avp); - if (avp_flags & AVP_FLAGS_VENDOR) { - if (dlen < 4) { - wpa_printf(MSG_WARNING, "EAP-TTLS: vendor AVP " - "underflow"); - goto fail; - } - vendor_id = be_to_host32(* (be32 *) dpos); - wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP vendor_id %d", - (int) vendor_id); - dpos += 4; - dlen -= 4; - } - - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP data", dpos, dlen); - - if (vendor_id == 0 && avp_code == RADIUS_ATTR_EAP_MESSAGE) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message"); - if (parse->eap == NULL) { - parse->eap = os_malloc(dlen); - if (parse->eap == NULL) { - wpa_printf(MSG_WARNING, "EAP-TTLS: " - "failed to allocate memory " - "for Phase 2 EAP data"); - goto fail; - } - os_memcpy(parse->eap, dpos, dlen); - parse->eap_len = dlen; - } else { - u8 *neweap = os_realloc(parse->eap, - parse->eap_len + dlen); - if (neweap == NULL) { - wpa_printf(MSG_WARNING, "EAP-TTLS: " - "failed to allocate memory " - "for Phase 2 EAP data"); - goto fail; - } - os_memcpy(neweap + parse->eap_len, dpos, dlen); - parse->eap = neweap; - parse->eap_len += dlen; - } - } else if (vendor_id == 0 && - avp_code == RADIUS_ATTR_USER_NAME) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: User-Name", - dpos, dlen); - parse->user_name = dpos; - parse->user_name_len = dlen; - } else if (vendor_id == 0 && - avp_code == RADIUS_ATTR_USER_PASSWORD) { - u8 *password = dpos; - size_t password_len = dlen; - while (password_len > 0 && - password[password_len - 1] == '\0') { - password_len--; - } - wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: " - "User-Password (PAP)", - password, password_len); - parse->user_password = password; - parse->user_password_len = password_len; - } else if (vendor_id == 0 && - avp_code == RADIUS_ATTR_CHAP_CHALLENGE) { - wpa_hexdump(MSG_DEBUG, - "EAP-TTLS: CHAP-Challenge (CHAP)", - dpos, dlen); - parse->chap_challenge = dpos; - parse->chap_challenge_len = dlen; - } else if (vendor_id == 0 && - avp_code == RADIUS_ATTR_CHAP_PASSWORD) { - wpa_hexdump(MSG_DEBUG, - "EAP-TTLS: CHAP-Password (CHAP)", - dpos, dlen); - parse->chap_password = dpos; - parse->chap_password_len = dlen; - } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT && - avp_code == RADIUS_ATTR_MS_CHAP_CHALLENGE) { - wpa_hexdump(MSG_DEBUG, - "EAP-TTLS: MS-CHAP-Challenge", - dpos, dlen); - parse->mschap_challenge = dpos; - parse->mschap_challenge_len = dlen; - } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT && - avp_code == RADIUS_ATTR_MS_CHAP_RESPONSE) { - wpa_hexdump(MSG_DEBUG, - "EAP-TTLS: MS-CHAP-Response (MSCHAP)", - dpos, dlen); - parse->mschap_response = dpos; - parse->mschap_response_len = dlen; - } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT && - avp_code == RADIUS_ATTR_MS_CHAP2_RESPONSE) { - wpa_hexdump(MSG_DEBUG, - "EAP-TTLS: MS-CHAP2-Response (MSCHAPV2)", - dpos, dlen); - parse->mschap2_response = dpos; - parse->mschap2_response_len = dlen; - } else if (avp_flags & AVP_FLAGS_MANDATORY) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Unsupported " - "mandatory AVP code %d vendor_id %d - " - "dropped", (int) avp_code, (int) vendor_id); - goto fail; - } else { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Ignoring unsupported " - "AVP code %d vendor_id %d", - (int) avp_code, (int) vendor_id); - } - - pad = (4 - (avp_length & 3)) & 3; - pos += avp_length + pad; - left -= avp_length + pad; - } - - return 0; - -fail: - os_free(parse->eap); - parse->eap = NULL; - return -1; -} - - -static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm, - struct eap_ttls_data *data, size_t len) -{ - struct tls_keys keys; - u8 *challenge, *rnd; - - if (data->ttls_version == 0) { - return eap_server_tls_derive_key(sm, &data->ssl, - "ttls challenge", len); - } - - os_memset(&keys, 0, sizeof(keys)); - if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) || - keys.client_random == NULL || keys.server_random == NULL || - keys.inner_secret == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, " - "client random, or server random to derive " - "implicit challenge"); - return NULL; - } - - rnd = os_malloc(keys.client_random_len + keys.server_random_len); - challenge = os_malloc(len); - if (rnd == NULL || challenge == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: No memory for implicit " - "challenge derivation"); - os_free(rnd); - os_free(challenge); - return NULL; - } - os_memcpy(rnd, keys.server_random, keys.server_random_len); - os_memcpy(rnd + keys.server_random_len, keys.client_random, - keys.client_random_len); - - if (tls_prf(keys.inner_secret, keys.inner_secret_len, - "inner application challenge", rnd, - keys.client_random_len + keys.server_random_len, - challenge, len)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive implicit " - "challenge"); - os_free(rnd); - os_free(challenge); - return NULL; - } - - os_free(rnd); - - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived implicit challenge", - challenge, len); - - return challenge; -} - - -static void * eap_ttls_init(struct eap_sm *sm) -{ - struct eap_ttls_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->ttls_version = EAP_TTLS_VERSION; - data->force_version = -1; - if (sm->user && sm->user->force_version >= 0) { - data->force_version = sm->user->force_version; - wpa_printf(MSG_DEBUG, "EAP-TTLS: forcing version %d", - data->force_version); - data->ttls_version = data->force_version; - } - data->state = START; - - if (!(tls_capabilities(sm->ssl_ctx) & TLS_CAPABILITY_IA) && - data->ttls_version > 0) { - if (data->force_version > 0) { - wpa_printf(MSG_INFO, "EAP-TTLS: Forced TTLSv%d and " - "TLS library does not support TLS/IA.", - data->force_version); - eap_ttls_reset(sm, data); - return NULL; - } - data->ttls_version = 0; - } - - if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL."); - eap_ttls_reset(sm, data); - return NULL; - } - - return data; -} - - -static void eap_ttls_reset(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - if (data == NULL) - return; - if (data->phase2_priv && data->phase2_method) - data->phase2_method->reset(sm, data->phase2_priv); - eap_server_tls_ssl_deinit(sm, &data->ssl); - wpabuf_free(data->pending_phase2_eap_resp); - os_free(data); -} - - -static struct wpabuf * eap_ttls_build_start(struct eap_sm *sm, - struct eap_ttls_data *data, u8 id) -{ - struct wpabuf *req; - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TTLS, 1, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to allocate memory for" - " request"); - eap_ttls_state(data, FAILURE); - return NULL; - } - - wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->ttls_version); - - eap_ttls_state(data, PHASE1); - - return req; -} - - -static struct wpabuf * eap_ttls_build_phase2_eap_req( - struct eap_sm *sm, struct eap_ttls_data *data, u8 id) -{ - struct wpabuf *buf, *encr_req; - u8 *req; - size_t req_len; - - - buf = data->phase2_method->buildReq(sm, data->phase2_priv, id); - if (buf == NULL) - return NULL; - - wpa_hexdump_buf_key(MSG_DEBUG, - "EAP-TTLS/EAP: Encapsulate Phase 2 data", buf); - - buf = eap_ttls_avp_encapsulate(buf, RADIUS_ATTR_EAP_MESSAGE, 1); - if (buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Failed to encapsulate " - "packet"); - return NULL; - } - - req = wpabuf_mhead(buf); - req_len = wpabuf_len(buf); - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated Phase " - "2 data", req, req_len); - - encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len); - wpabuf_free(buf); - - return encr_req; -} - - -static struct wpabuf * eap_ttls_build_phase2_mschapv2( - struct eap_sm *sm, struct eap_ttls_data *data) -{ - struct wpabuf *encr_req; - u8 *req, *pos, *end; - int ret; - size_t req_len; - - pos = req = os_malloc(100); - if (req == NULL) - return NULL; - end = req + 100; - - if (data->mschapv2_resp_ok) { - pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP2_SUCCESS, - RADIUS_VENDOR_ID_MICROSOFT, 1, 43); - *pos++ = data->mschapv2_ident; - ret = os_snprintf((char *) pos, end - pos, "S="); - if (ret >= 0 && ret < end - pos) - pos += ret; - pos += wpa_snprintf_hex_uppercase( - (char *) pos, end - pos, data->mschapv2_auth_response, - sizeof(data->mschapv2_auth_response)); - } else { - pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_ERROR, - RADIUS_VENDOR_ID_MICROSOFT, 1, 6); - os_memcpy(pos, "Failed", 6); - pos += 6; - AVP_PAD(req, pos); - } - - req_len = pos - req; - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 " - "data", req, req_len); - - encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len); - os_free(req); - - return encr_req; -} - - -static struct wpabuf * eap_ttls_build_phase_finished( - struct eap_sm *sm, struct eap_ttls_data *data, int final) -{ - int len; - struct wpabuf *req; - const int max_len = 300; - - req = wpabuf_alloc(max_len); - if (req == NULL) - return NULL; - - len = tls_connection_ia_send_phase_finished(sm->ssl_ctx, - data->ssl.conn, final, - wpabuf_mhead(req), - max_len); - if (len < 0) { - wpabuf_free(req); - return NULL; - } - wpabuf_put(req, len); - - return req; -} - - -static struct wpabuf * eap_ttls_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_ttls_data *data = priv; - - if (data->ssl.state == FRAG_ACK) { - return eap_server_tls_build_ack(id, EAP_TYPE_TTLS, - data->ttls_version); - } - - if (data->ssl.state == WAIT_FRAG_ACK) { - return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TTLS, - data->ttls_version, id); - } - - switch (data->state) { - case START: - return eap_ttls_build_start(sm, data, id); - case PHASE1: - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase1 done, " - "starting Phase2"); - eap_ttls_state(data, PHASE2_START); - } - break; - case PHASE2_METHOD: - wpabuf_free(data->ssl.out_buf); - data->ssl.out_used = 0; - data->ssl.out_buf = eap_ttls_build_phase2_eap_req(sm, data, - id); - break; - case PHASE2_MSCHAPV2_RESP: - wpabuf_free(data->ssl.out_buf); - data->ssl.out_used = 0; - data->ssl.out_buf = eap_ttls_build_phase2_mschapv2(sm, data); - break; - case PHASE_FINISHED: - wpabuf_free(data->ssl.out_buf); - data->ssl.out_used = 0; - data->ssl.out_buf = eap_ttls_build_phase_finished(sm, data, 1); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d", - __func__, data->state); - return NULL; - } - - return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TTLS, - data->ttls_version, id); -} - - -static Boolean eap_ttls_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TTLS, respData, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-TTLS: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static int eap_ttls_ia_permute_inner_secret(struct eap_sm *sm, - struct eap_ttls_data *data, - const u8 *key, size_t key_len) -{ - u8 *buf; - size_t buf_len; - int ret; - - if (key) { - buf_len = 2 + key_len; - buf = os_malloc(buf_len); - if (buf == NULL) - return -1; - WPA_PUT_BE16(buf, key_len); - os_memcpy(buf + 2, key, key_len); - } else { - buf = NULL; - buf_len = 0; - } - - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Session keys for TLS/IA inner " - "secret permutation", buf, buf_len); - ret = tls_connection_ia_permute_inner_secret(sm->ssl_ctx, - data->ssl.conn, - buf, buf_len); - os_free(buf); - - return ret; -} - - -static void eap_ttls_process_phase2_pap(struct eap_sm *sm, - struct eap_ttls_data *data, - const u8 *user_password, - size_t user_password_len) -{ - if (!sm->user || !sm->user->password || sm->user->password_hash || - !(sm->user->ttls_auth & EAP_TTLS_AUTH_PAP)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: No plaintext user " - "password configured"); - eap_ttls_state(data, FAILURE); - return; - } - - if (sm->user->password_len != user_password_len || - os_memcmp(sm->user->password, user_password, user_password_len) != - 0) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: Invalid user password"); - eap_ttls_state(data, FAILURE); - return; - } - - wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: Correct user password"); - eap_ttls_state(data, data->ttls_version > 0 ? PHASE_FINISHED : - SUCCESS); -} - - -static void eap_ttls_process_phase2_chap(struct eap_sm *sm, - struct eap_ttls_data *data, - const u8 *challenge, - size_t challenge_len, - const u8 *password, - size_t password_len) -{ - u8 *chal, hash[CHAP_MD5_LEN]; - - if (challenge == NULL || password == NULL || - challenge_len != EAP_TTLS_CHAP_CHALLENGE_LEN || - password_len != 1 + EAP_TTLS_CHAP_PASSWORD_LEN) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Invalid CHAP attributes " - "(challenge len %lu password len %lu)", - (unsigned long) challenge_len, - (unsigned long) password_len); - eap_ttls_state(data, FAILURE); - return; - } - - if (!sm->user || !sm->user->password || sm->user->password_hash || - !(sm->user->ttls_auth & EAP_TTLS_AUTH_CHAP)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: No plaintext user " - "password configured"); - eap_ttls_state(data, FAILURE); - return; - } - - chal = eap_ttls_implicit_challenge(sm, data, - EAP_TTLS_CHAP_CHALLENGE_LEN + 1); - if (chal == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Failed to generate " - "challenge from TLS data"); - eap_ttls_state(data, FAILURE); - return; - } - - if (os_memcmp(challenge, chal, EAP_TTLS_CHAP_CHALLENGE_LEN) != 0 || - password[0] != chal[EAP_TTLS_CHAP_CHALLENGE_LEN]) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Challenge mismatch"); - os_free(chal); - eap_ttls_state(data, FAILURE); - return; - } - os_free(chal); - - /* MD5(Ident + Password + Challenge) */ - chap_md5(password[0], sm->user->password, sm->user->password_len, - challenge, challenge_len, hash); - - if (os_memcmp(hash, password + 1, EAP_TTLS_CHAP_PASSWORD_LEN) == 0) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Correct user password"); - eap_ttls_state(data, data->ttls_version > 0 ? PHASE_FINISHED : - SUCCESS); - } else { - wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Invalid user password"); - eap_ttls_state(data, FAILURE); - } -} - - -static void eap_ttls_process_phase2_mschap(struct eap_sm *sm, - struct eap_ttls_data *data, - u8 *challenge, size_t challenge_len, - u8 *response, size_t response_len) -{ - u8 *chal, nt_response[24]; - - if (challenge == NULL || response == NULL || - challenge_len != EAP_TTLS_MSCHAP_CHALLENGE_LEN || - response_len != EAP_TTLS_MSCHAP_RESPONSE_LEN) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Invalid MS-CHAP " - "attributes (challenge len %lu response len %lu)", - (unsigned long) challenge_len, - (unsigned long) response_len); - eap_ttls_state(data, FAILURE); - return; - } - - if (!sm->user || !sm->user->password || - !(sm->user->ttls_auth & EAP_TTLS_AUTH_MSCHAP)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: No user password " - "configured"); - eap_ttls_state(data, FAILURE); - return; - } - - chal = eap_ttls_implicit_challenge(sm, data, - EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1); - if (chal == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Failed to generate " - "challenge from TLS data"); - eap_ttls_state(data, FAILURE); - return; - } - - if (os_memcmp(challenge, chal, EAP_TTLS_MSCHAP_CHALLENGE_LEN) != 0 || - response[0] != chal[EAP_TTLS_MSCHAP_CHALLENGE_LEN]) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Challenge mismatch"); - os_free(chal); - eap_ttls_state(data, FAILURE); - return; - } - os_free(chal); - - if (sm->user->password_hash) - challenge_response(challenge, sm->user->password, nt_response); - else - nt_challenge_response(challenge, sm->user->password, - sm->user->password_len, nt_response); - - if (os_memcmp(nt_response, response + 2 + 24, 24) == 0) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Correct response"); - eap_ttls_state(data, data->ttls_version > 0 ? PHASE_FINISHED : - SUCCESS); - } else { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Invalid NT-Response"); - wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAP: Received", - response + 2 + 24, 24); - wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAP: Expected", - nt_response, 24); - eap_ttls_state(data, FAILURE); - } -} - - -static void eap_ttls_process_phase2_mschapv2(struct eap_sm *sm, - struct eap_ttls_data *data, - u8 *challenge, - size_t challenge_len, - u8 *response, size_t response_len) -{ - u8 *chal, *username, nt_response[24], *rx_resp, *peer_challenge, - *auth_challenge; - size_t username_len, i; - - if (challenge == NULL || response == NULL || - challenge_len != EAP_TTLS_MSCHAPV2_CHALLENGE_LEN || - response_len != EAP_TTLS_MSCHAPV2_RESPONSE_LEN) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Invalid MS-CHAP2 " - "attributes (challenge len %lu response len %lu)", - (unsigned long) challenge_len, - (unsigned long) response_len); - eap_ttls_state(data, FAILURE); - return; - } - - if (!sm->user || !sm->user->password || - !(sm->user->ttls_auth & EAP_TTLS_AUTH_MSCHAPV2)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: No user password " - "configured"); - eap_ttls_state(data, FAILURE); - return; - } - - /* MSCHAPv2 does not include optional domain name in the - * challenge-response calculation, so remove domain prefix - * (if present). */ - username = sm->identity; - username_len = sm->identity_len; - for (i = 0; i < username_len; i++) { - if (username[i] == '\\') { - username_len -= i + 1; - username += i + 1; - break; - } - } - - chal = eap_ttls_implicit_challenge( - sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1); - if (chal == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Failed to generate " - "challenge from TLS data"); - eap_ttls_state(data, FAILURE); - return; - } - - if (os_memcmp(challenge, chal, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) != 0 || - response[0] != chal[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN]) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Challenge mismatch"); - os_free(chal); - eap_ttls_state(data, FAILURE); - return; - } - os_free(chal); - - auth_challenge = challenge; - peer_challenge = response + 2; - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: User", - username, username_len); - wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: auth_challenge", - auth_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: peer_challenge", - peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); - - if (sm->user->password_hash) { - generate_nt_response_pwhash(auth_challenge, peer_challenge, - username, username_len, - sm->user->password, - nt_response); - } else { - generate_nt_response(auth_challenge, peer_challenge, - username, username_len, - sm->user->password, - sm->user->password_len, - nt_response); - } - - rx_resp = response + 2 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 8; - if (os_memcmp(nt_response, rx_resp, 24) == 0) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Correct " - "NT-Response"); - data->mschapv2_resp_ok = 1; - if (data->ttls_version > 0) { - const u8 *pw_hash; - u8 pw_hash_buf[16], pw_hash_hash[16], master_key[16]; - u8 session_key[2 * MSCHAPV2_KEY_LEN]; - - if (sm->user->password_hash) - pw_hash = sm->user->password; - else { - nt_password_hash(sm->user->password, - sm->user->password_len, - pw_hash_buf); - pw_hash = pw_hash_buf; - } - hash_nt_password_hash(pw_hash, pw_hash_hash); - get_master_key(pw_hash_hash, nt_response, master_key); - get_asymetric_start_key(master_key, session_key, - MSCHAPV2_KEY_LEN, 0, 0); - get_asymetric_start_key(master_key, - session_key + MSCHAPV2_KEY_LEN, - MSCHAPV2_KEY_LEN, 1, 0); - eap_ttls_ia_permute_inner_secret(sm, data, - session_key, - sizeof(session_key)); - } - - if (sm->user->password_hash) { - generate_authenticator_response_pwhash( - sm->user->password, - peer_challenge, auth_challenge, - username, username_len, nt_response, - data->mschapv2_auth_response); - } else { - generate_authenticator_response( - sm->user->password, sm->user->password_len, - peer_challenge, auth_challenge, - username, username_len, nt_response, - data->mschapv2_auth_response); - } - } else { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Invalid " - "NT-Response"); - wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: Received", - rx_resp, 24); - wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: Expected", - nt_response, 24); - data->mschapv2_resp_ok = 0; - } - eap_ttls_state(data, PHASE2_MSCHAPV2_RESP); - data->mschapv2_ident = response[0]; -} - - -static int eap_ttls_phase2_eap_init(struct eap_sm *sm, - struct eap_ttls_data *data, - EapType eap_type) -{ - if (data->phase2_priv && data->phase2_method) { - data->phase2_method->reset(sm, data->phase2_priv); - data->phase2_method = NULL; - data->phase2_priv = NULL; - } - data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF, - eap_type); - if (!data->phase2_method) - return -1; - - sm->init_phase2 = 1; - data->phase2_priv = data->phase2_method->init(sm); - sm->init_phase2 = 0; - return data->phase2_priv == NULL ? -1 : 0; -} - - -static void eap_ttls_process_phase2_eap_response(struct eap_sm *sm, - struct eap_ttls_data *data, - u8 *in_data, size_t in_len) -{ - u8 next_type = EAP_TYPE_NONE; - struct eap_hdr *hdr; - u8 *pos; - size_t left; - struct wpabuf buf; - const struct eap_method *m = data->phase2_method; - void *priv = data->phase2_priv; - - if (priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: %s - Phase2 not " - "initialized?!", __func__); - return; - } - - hdr = (struct eap_hdr *) in_data; - pos = (u8 *) (hdr + 1); - - if (in_len > sizeof(*hdr) && *pos == EAP_TYPE_NAK) { - left = in_len - sizeof(*hdr); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 type Nak'ed; " - "allowed types", pos + 1, left - 1); - eap_sm_process_nak(sm, pos + 1, left - 1); - if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && - sm->user->methods[sm->user_eap_method_index].method != - EAP_TYPE_NONE) { - next_type = sm->user->methods[ - sm->user_eap_method_index++].method; - wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d", - next_type); - if (eap_ttls_phase2_eap_init(sm, data, next_type)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to " - "initialize EAP type %d", - next_type); - eap_ttls_state(data, FAILURE); - return; - } - } else { - eap_ttls_state(data, FAILURE); - } - return; - } - - wpabuf_set(&buf, in_data, in_len); - - if (m->check(sm, priv, &buf)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 check() asked to " - "ignore the packet"); - return; - } - - m->process(sm, priv, &buf); - - if (sm->method_pending == METHOD_PENDING_WAIT) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 method is in " - "pending wait state - save decrypted response"); - wpabuf_free(data->pending_phase2_eap_resp); - data->pending_phase2_eap_resp = wpabuf_dup(&buf); - } - - if (!m->isDone(sm, priv)) - return; - - if (!m->isSuccess(sm, priv)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 method failed"); - eap_ttls_state(data, FAILURE); - return; - } - - switch (data->state) { - case PHASE2_START: - if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP_TTLS: Phase2 " - "Identity not found in the user " - "database", - sm->identity, sm->identity_len); - eap_ttls_state(data, FAILURE); - break; - } - - eap_ttls_state(data, PHASE2_METHOD); - next_type = sm->user->methods[0].method; - sm->user_eap_method_index = 1; - wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d", next_type); - if (eap_ttls_phase2_eap_init(sm, data, next_type)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to initialize " - "EAP type %d", next_type); - eap_ttls_state(data, FAILURE); - } - break; - case PHASE2_METHOD: - if (data->ttls_version > 0) { - if (m->getKey) { - u8 *key; - size_t key_len; - key = m->getKey(sm, priv, &key_len); - eap_ttls_ia_permute_inner_secret(sm, data, - key, key_len); - } - eap_ttls_state(data, PHASE_FINISHED); - } else - eap_ttls_state(data, SUCCESS); - break; - case FAILURE: - break; - default: - wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d", - __func__, data->state); - break; - } -} - - -static void eap_ttls_process_phase2_eap(struct eap_sm *sm, - struct eap_ttls_data *data, - const u8 *eap, size_t eap_len) -{ - struct eap_hdr *hdr; - size_t len; - - if (data->state == PHASE2_START) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: initializing Phase 2"); - if (eap_ttls_phase2_eap_init(sm, data, EAP_TYPE_IDENTITY) < 0) - { - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: failed to " - "initialize EAP-Identity"); - return; - } - } - - if (eap_len < sizeof(*hdr)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: too short Phase 2 EAP " - "packet (len=%lu)", (unsigned long) eap_len); - return; - } - - hdr = (struct eap_hdr *) eap; - len = be_to_host16(hdr->length); - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: received Phase 2 EAP: code=%d " - "identifier=%d length=%lu", hdr->code, hdr->identifier, - (unsigned long) len); - if (len > eap_len) { - wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Length mismatch in Phase 2" - " EAP frame (hdr len=%lu, data len in AVP=%lu)", - (unsigned long) len, (unsigned long) eap_len); - return; - } - - switch (hdr->code) { - case EAP_CODE_RESPONSE: - eap_ttls_process_phase2_eap_response(sm, data, (u8 *) hdr, - len); - break; - default: - wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Unexpected code=%d in " - "Phase 2 EAP header", hdr->code); - break; - } -} - - -static void eap_ttls_process_phase2(struct eap_sm *sm, - struct eap_ttls_data *data, - struct wpabuf *in_buf) -{ - u8 *in_decrypted; - int len_decrypted; - struct eap_ttls_avp parse; - size_t buf_len; - u8 *in_data; - size_t in_len; - - in_data = wpabuf_mhead(in_buf); - in_len = wpabuf_len(in_buf); - - wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for" - " Phase 2", (unsigned long) in_len); - - if (data->pending_phase2_eap_resp) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 EAP response " - "- skip decryption and use old data"); - eap_ttls_process_phase2_eap( - sm, data, wpabuf_head(data->pending_phase2_eap_resp), - wpabuf_len(data->pending_phase2_eap_resp)); - wpabuf_free(data->pending_phase2_eap_resp); - data->pending_phase2_eap_resp = NULL; - return; - } - - buf_len = in_len; - /* - * Even though we try to disable TLS compression, it is possible that - * this cannot be done with all TLS libraries. Add extra buffer space - * to handle the possibility of the decrypted data being longer than - * input data. - */ - buf_len += 500; - buf_len *= 3; - in_decrypted = os_malloc(buf_len); - if (in_decrypted == NULL) { - wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate memory " - "for decryption"); - return; - } - - len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, - in_data, in_len, - in_decrypted, buf_len); - if (len_decrypted < 0) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 " - "data"); - os_free(in_decrypted); - eap_ttls_state(data, FAILURE); - return; - } - - if (data->state == PHASE_FINISHED) { - if (len_decrypted == 0 && - tls_connection_ia_final_phase_finished(sm->ssl_ctx, - data->ssl.conn)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: FinalPhaseFinished " - "received"); - eap_ttls_state(data, SUCCESS); - } else { - wpa_printf(MSG_INFO, "EAP-TTLS: Did not receive valid " - "FinalPhaseFinished"); - eap_ttls_state(data, FAILURE); - } - - os_free(in_decrypted); - return; - } - - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP", - in_decrypted, len_decrypted); - - if (eap_ttls_avp_parse(in_decrypted, len_decrypted, &parse) < 0) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to parse AVPs"); - os_free(in_decrypted); - eap_ttls_state(data, FAILURE); - return; - } - - if (parse.user_name) { - os_free(sm->identity); - sm->identity = os_malloc(parse.user_name_len); - if (sm->identity) { - os_memcpy(sm->identity, parse.user_name, - parse.user_name_len); - sm->identity_len = parse.user_name_len; - } - if (eap_user_get(sm, parse.user_name, parse.user_name_len, 1) - != 0) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 Identity not " - "found in the user database"); - eap_ttls_state(data, FAILURE); - goto done; - } - } - -#ifdef EAP_TNC - if (data->tnc_started && parse.eap == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: TNC started but no EAP " - "response from peer"); - eap_ttls_state(data, FAILURE); - goto done; - } -#endif /* EAP_TNC */ - - if (parse.eap) { - eap_ttls_process_phase2_eap(sm, data, parse.eap, - parse.eap_len); - } else if (parse.user_password) { - eap_ttls_process_phase2_pap(sm, data, parse.user_password, - parse.user_password_len); - } else if (parse.chap_password) { - eap_ttls_process_phase2_chap(sm, data, - parse.chap_challenge, - parse.chap_challenge_len, - parse.chap_password, - parse.chap_password_len); - } else if (parse.mschap_response) { - eap_ttls_process_phase2_mschap(sm, data, - parse.mschap_challenge, - parse.mschap_challenge_len, - parse.mschap_response, - parse.mschap_response_len); - } else if (parse.mschap2_response) { - eap_ttls_process_phase2_mschapv2(sm, data, - parse.mschap_challenge, - parse.mschap_challenge_len, - parse.mschap2_response, - parse.mschap2_response_len); - } - -done: - os_free(in_decrypted); - os_free(parse.eap); -} - - -static void eap_ttls_start_tnc(struct eap_sm *sm, struct eap_ttls_data *data) -{ -#ifdef EAP_TNC - if (!sm->tnc || data->state != SUCCESS || data->tnc_started) - return; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Initialize TNC"); - if (eap_ttls_phase2_eap_init(sm, data, EAP_TYPE_TNC)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to initialize TNC"); - eap_ttls_state(data, FAILURE); - return; - } - - data->tnc_started = 1; - eap_ttls_state(data, PHASE2_METHOD); -#endif /* EAP_TNC */ -} - - -static int eap_ttls_process_version(struct eap_sm *sm, void *priv, - int peer_version) -{ - struct eap_ttls_data *data = priv; - if (peer_version < data->ttls_version) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: peer ver=%d, own ver=%d; " - "use version %d", - peer_version, data->ttls_version, peer_version); - data->ttls_version = peer_version; - } - - if (data->ttls_version > 0 && !data->tls_ia_configured) { - if (tls_connection_set_ia(sm->ssl_ctx, data->ssl.conn, 1)) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to enable " - "TLS/IA"); - return -1; - } - data->tls_ia_configured = 1; - } - - return 0; -} - - -static void eap_ttls_process_msg(struct eap_sm *sm, void *priv, - const struct wpabuf *respData) -{ - struct eap_ttls_data *data = priv; - - switch (data->state) { - case PHASE1: - if (eap_server_tls_phase1(sm, &data->ssl) < 0) - eap_ttls_state(data, FAILURE); - break; - case PHASE2_START: - case PHASE2_METHOD: - case PHASE_FINISHED: - eap_ttls_process_phase2(sm, data, data->ssl.in_buf); - eap_ttls_start_tnc(sm, data); - break; - case PHASE2_MSCHAPV2_RESP: - if (data->mschapv2_resp_ok && wpabuf_len(data->ssl.in_buf) == - 0) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer " - "acknowledged response"); - eap_ttls_state(data, data->ttls_version > 0 ? - PHASE_FINISHED : SUCCESS); - } else if (!data->mschapv2_resp_ok) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer " - "acknowledged error"); - eap_ttls_state(data, FAILURE); - } else { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Unexpected " - "frame from peer (payload len %lu, " - "expected empty frame)", - (unsigned long) - wpabuf_len(data->ssl.in_buf)); - eap_ttls_state(data, FAILURE); - } - eap_ttls_start_tnc(sm, data); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-TTLS: Unexpected state %d in %s", - data->state, __func__); - break; - } -} - - -static void eap_ttls_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_ttls_data *data = priv; - if (eap_server_tls_process(sm, &data->ssl, respData, data, - EAP_TYPE_TTLS, eap_ttls_process_version, - eap_ttls_process_msg) < 0) - eap_ttls_state(data, FAILURE); -} - - -static Boolean eap_ttls_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_ttls_v1_derive_key(struct eap_sm *sm, - struct eap_ttls_data *data) -{ - struct tls_keys keys; - u8 *rnd, *key; - - os_memset(&keys, 0, sizeof(keys)); - if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) || - keys.client_random == NULL || keys.server_random == NULL || - keys.inner_secret == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, " - "client random, or server random to derive keying " - "material"); - return NULL; - } - - rnd = os_malloc(keys.client_random_len + keys.server_random_len); - key = os_malloc(EAP_TLS_KEY_LEN); - if (rnd == NULL || key == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: No memory for key derivation"); - os_free(rnd); - os_free(key); - return NULL; - } - os_memcpy(rnd, keys.client_random, keys.client_random_len); - os_memcpy(rnd + keys.client_random_len, keys.server_random, - keys.server_random_len); - - if (tls_prf(keys.inner_secret, keys.inner_secret_len, - "ttls v1 keying material", rnd, keys.client_random_len + - keys.server_random_len, key, EAP_TLS_KEY_LEN)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key"); - os_free(rnd); - os_free(key); - return NULL; - } - - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: client/server random", - rnd, keys.client_random_len + keys.server_random_len); - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: TLS/IA inner secret", - keys.inner_secret, keys.inner_secret_len); - - os_free(rnd); - - return key; -} - - -static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_ttls_data *data = priv; - u8 *eapKeyData; - - if (data->state != SUCCESS) - return NULL; - - if (data->ttls_version == 0) { - eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, - "ttls keying material", - EAP_TLS_KEY_LEN); - } else { - eapKeyData = eap_ttls_v1_derive_key(sm, data); - } - - if (eapKeyData) { - *len = EAP_TLS_KEY_LEN; - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key", - eapKeyData, EAP_TLS_KEY_LEN); - } else { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key"); - } - - return eapKeyData; -} - - -static Boolean eap_ttls_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_ttls_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS"); - if (eap == NULL) - return -1; - - eap->init = eap_ttls_init; - eap->reset = eap_ttls_reset; - eap->buildReq = eap_ttls_buildReq; - eap->check = eap_ttls_check; - eap->process = eap_ttls_process; - eap->isDone = eap_ttls_isDone; - eap->getKey = eap_ttls_getKey; - eap->isSuccess = eap_ttls_isSuccess; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_server/eap_vendor_test.c b/contrib/hostapd/src/eap_server/eap_vendor_test.c deleted file mode 100644 index 0dd0aca911..0000000000 --- a/contrib/hostapd/src/eap_server/eap_vendor_test.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * hostapd / Test method for vendor specific (expanded) EAP type - * Copyright (c) 2005-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" - - -#define EAP_VENDOR_ID 0xfffefd -#define EAP_VENDOR_TYPE 0xfcfbfaf9 - - -struct eap_vendor_test_data { - enum { INIT, CONFIRM, SUCCESS, FAILURE } state; -}; - - -static const char * eap_vendor_test_state_txt(int state) -{ - switch (state) { - case INIT: - return "INIT"; - case CONFIRM: - return "CONFIRM"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "?"; - } -} - - -static void eap_vendor_test_state(struct eap_vendor_test_data *data, - int state) -{ - wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: %s -> %s", - eap_vendor_test_state_txt(data->state), - eap_vendor_test_state_txt(state)); - data->state = state; -} - - -static void * eap_vendor_test_init(struct eap_sm *sm) -{ - struct eap_vendor_test_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = INIT; - - return data; -} - - -static void eap_vendor_test_reset(struct eap_sm *sm, void *priv) -{ - struct eap_vendor_test_data *data = priv; - os_free(data); -} - - -static struct wpabuf * eap_vendor_test_buildReq(struct eap_sm *sm, void *priv, - u8 id) -{ - struct eap_vendor_test_data *data = priv; - struct wpabuf *req; - - req = eap_msg_alloc(EAP_VENDOR_ID, EAP_VENDOR_TYPE, 1, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-VENDOR-TEST: Failed to allocate " - "memory for request"); - return NULL; - } - - wpabuf_put_u8(req, data->state == INIT ? 1 : 3); - - return req; -} - - -static Boolean eap_vendor_test_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_ID, EAP_VENDOR_TYPE, respData, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-VENDOR-TEST: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static void eap_vendor_test_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_vendor_test_data *data = priv; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_ID, EAP_VENDOR_TYPE, respData, &len); - if (pos == NULL || len < 1) - return; - - if (data->state == INIT) { - if (*pos == 2) - eap_vendor_test_state(data, CONFIRM); - else - eap_vendor_test_state(data, FAILURE); - } else if (data->state == CONFIRM) { - if (*pos == 4) - eap_vendor_test_state(data, SUCCESS); - else - eap_vendor_test_state(data, FAILURE); - } else - eap_vendor_test_state(data, FAILURE); -} - - -static Boolean eap_vendor_test_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_vendor_test_data *data = priv; - return data->state == SUCCESS; -} - - -static u8 * eap_vendor_test_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_vendor_test_data *data = priv; - u8 *key; - const int key_len = 64; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(key_len); - if (key == NULL) - return NULL; - - os_memset(key, 0x11, key_len / 2); - os_memset(key + key_len / 2, 0x22, key_len / 2); - *len = key_len; - - return key; -} - - -static Boolean eap_vendor_test_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_vendor_test_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_vendor_test_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_ID, EAP_VENDOR_TYPE, - "VENDOR-TEST"); - if (eap == NULL) - return -1; - - eap->init = eap_vendor_test_init; - eap->reset = eap_vendor_test_reset; - eap->buildReq = eap_vendor_test_buildReq; - eap->check = eap_vendor_test_check; - eap->process = eap_vendor_test_process; - eap->isDone = eap_vendor_test_isDone; - eap->getKey = eap_vendor_test_getKey; - eap->isSuccess = eap_vendor_test_isSuccess; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_server/eap_wsc.c b/contrib/hostapd/src/eap_server/eap_wsc.c deleted file mode 100644 index 3c17577889..0000000000 --- a/contrib/hostapd/src/eap_server/eap_wsc.c +++ /dev/null @@ -1,498 +0,0 @@ -/* - * EAP-WSC server for Wi-Fi Protected Setup - * Copyright (c) 2007-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eloop.h" -#include "eap_i.h" -#include "eap_common/eap_wsc_common.h" -#include "wps/wps.h" - - -struct eap_wsc_data { - enum { START, MSG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state; - int registrar; - struct wpabuf *in_buf; - struct wpabuf *out_buf; - enum wsc_op_code in_op_code, out_op_code; - size_t out_used; - size_t fragment_size; - struct wps_data *wps; - int ext_reg_timeout; -}; - - -static const char * eap_wsc_state_txt(int state) -{ - switch (state) { - case START: - return "START"; - case MSG: - return "MSG"; - case FRAG_ACK: - return "FRAG_ACK"; - case WAIT_FRAG_ACK: - return "WAIT_FRAG_ACK"; - case DONE: - return "DONE"; - case FAIL: - return "FAIL"; - default: - return "?"; - } -} - - -static void eap_wsc_state(struct eap_wsc_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-WSC: %s -> %s", - eap_wsc_state_txt(data->state), - eap_wsc_state_txt(state)); - data->state = state; -} - - -static void eap_wsc_ext_reg_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct eap_sm *sm = eloop_ctx; - struct eap_wsc_data *data = timeout_ctx; - - if (sm->method_pending != METHOD_PENDING_WAIT) - return; - - wpa_printf(MSG_DEBUG, "EAP-WSC: Timeout while waiting for an External " - "Registrar"); - data->ext_reg_timeout = 1; - eap_sm_pending_cb(sm); -} - - -static void * eap_wsc_init(struct eap_sm *sm) -{ - struct eap_wsc_data *data; - int registrar; - struct wps_config cfg; - - if (sm->identity && sm->identity_len == WSC_ID_REGISTRAR_LEN && - os_memcmp(sm->identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == - 0) - registrar = 0; /* Supplicant is Registrar */ - else if (sm->identity && sm->identity_len == WSC_ID_ENROLLEE_LEN && - os_memcmp(sm->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) - == 0) - registrar = 1; /* Supplicant is Enrollee */ - else { - wpa_hexdump_ascii(MSG_INFO, "EAP-WSC: Unexpected identity", - sm->identity, sm->identity_len); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = registrar ? START : MSG; - data->registrar = registrar; - - os_memset(&cfg, 0, sizeof(cfg)); - cfg.wps = sm->wps; - cfg.registrar = registrar; - if (registrar) { - if (sm->wps == NULL || sm->wps->registrar == NULL) { - wpa_printf(MSG_INFO, "EAP-WSC: WPS Registrar not " - "initialized"); - os_free(data); - return NULL; - } - } else { - if (sm->user == NULL || sm->user->password == NULL) { - wpa_printf(MSG_INFO, "EAP-WSC: No AP PIN (password) " - "configured for Enrollee functionality"); - os_free(data); - return NULL; - } - cfg.pin = sm->user->password; - cfg.pin_len = sm->user->password_len; - } - cfg.assoc_wps_ie = sm->assoc_wps_ie; - data->wps = wps_init(&cfg); - if (data->wps == NULL) { - os_free(data); - return NULL; - } - data->fragment_size = WSC_FRAGMENT_SIZE; - - return data; -} - - -static void eap_wsc_reset(struct eap_sm *sm, void *priv) -{ - struct eap_wsc_data *data = priv; - eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data); - wpabuf_free(data->in_buf); - wpabuf_free(data->out_buf); - wps_deinit(data->wps); - os_free(data); -} - - -static struct wpabuf * eap_wsc_build_start(struct eap_sm *sm, - struct eap_wsc_data *data, u8 id) -{ - struct wpabuf *req; - - req = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 2, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-WSC: Failed to allocate memory for " - "request"); - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-WSC: Send WSC/Start"); - wpabuf_put_u8(req, WSC_Start); /* Op-Code */ - wpabuf_put_u8(req, 0); /* Flags */ - - return req; -} - - -static struct wpabuf * eap_wsc_build_msg(struct eap_wsc_data *data, u8 id) -{ - struct wpabuf *req; - u8 flags; - size_t send_len, plen; - - flags = 0; - send_len = wpabuf_len(data->out_buf) - data->out_used; - if (2 + send_len > data->fragment_size) { - send_len = data->fragment_size - 2; - flags |= WSC_FLAGS_MF; - if (data->out_used == 0) { - flags |= WSC_FLAGS_LF; - send_len -= 2; - } - } - plen = 2 + send_len; - if (flags & WSC_FLAGS_LF) - plen += 2; - req = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, plen, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-WSC: Failed to allocate memory for " - "request"); - return NULL; - } - - wpabuf_put_u8(req, data->out_op_code); /* Op-Code */ - wpabuf_put_u8(req, flags); /* Flags */ - if (flags & WSC_FLAGS_LF) - wpabuf_put_be16(req, wpabuf_len(data->out_buf)); - - wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used, - send_len); - data->out_used += send_len; - - if (data->out_used == wpabuf_len(data->out_buf)) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " - "(message sent completely)", - (unsigned long) send_len); - wpabuf_free(data->out_buf); - data->out_buf = NULL; - data->out_used = 0; - eap_wsc_state(data, MSG); - } else { - wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " - "(%lu more to send)", (unsigned long) send_len, - (unsigned long) wpabuf_len(data->out_buf) - - data->out_used); - eap_wsc_state(data, WAIT_FRAG_ACK); - } - - return req; -} - - -static struct wpabuf * eap_wsc_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_wsc_data *data = priv; - - switch (data->state) { - case START: - return eap_wsc_build_start(sm, data, id); - case MSG: - if (data->out_buf == NULL) { - data->out_buf = wps_get_msg(data->wps, - &data->out_op_code); - if (data->out_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to " - "receive message from WPS"); - return NULL; - } - data->out_used = 0; - } - /* pass through */ - case WAIT_FRAG_ACK: - return eap_wsc_build_msg(data, id); - case FRAG_ACK: - return eap_wsc_build_frag_ack(id, EAP_CODE_REQUEST); - default: - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected state %d in " - "buildReq", data->state); - return NULL; - } -} - - -static Boolean eap_wsc_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, - respData, &len); - if (pos == NULL || len < 2) { - wpa_printf(MSG_INFO, "EAP-WSC: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static int eap_wsc_process_cont(struct eap_wsc_data *data, - const u8 *buf, size_t len, u8 op_code) -{ - /* Process continuation of a pending message */ - if (op_code != data->in_op_code) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d in " - "fragment (expected %d)", - op_code, data->in_op_code); - eap_wsc_state(data, FAIL); - return -1; - } - - if (len > wpabuf_tailroom(data->in_buf)) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment overflow"); - eap_wsc_state(data, FAIL); - return -1; - } - - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes, waiting for %lu " - "bytes more", (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - - return 0; -} - - -static int eap_wsc_process_fragment(struct eap_wsc_data *data, - u8 flags, u8 op_code, u16 message_length, - const u8 *buf, size_t len) -{ - /* Process a fragment that is not the last one of the message */ - if (data->in_buf == NULL && !(flags & WSC_FLAGS_LF)) { - wpa_printf(MSG_DEBUG, "EAP-WSC: No Message Length " - "field in a fragmented packet"); - return -1; - } - - if (data->in_buf == NULL) { - /* First fragment of the message */ - data->in_buf = wpabuf_alloc(message_length); - if (data->in_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-WSC: No memory for " - "message"); - return -1; - } - data->in_op_code = op_code; - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes in " - "first fragment, waiting for %lu bytes more", - (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - } - - return 0; -} - - -static void eap_wsc_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_wsc_data *data = priv; - const u8 *start, *pos, *end; - size_t len; - u8 op_code, flags; - u16 message_length = 0; - enum wps_process_res res; - struct wpabuf tmpbuf; - - eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data); - if (data->ext_reg_timeout) { - eap_wsc_state(data, FAIL); - return; - } - - pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, - respData, &len); - if (pos == NULL || len < 2) - return; /* Should not happen; message already verified */ - - start = pos; - end = start + len; - - op_code = *pos++; - flags = *pos++; - if (flags & WSC_FLAGS_LF) { - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Message underflow"); - return; - } - message_length = WPA_GET_BE16(pos); - pos += 2; - - if (message_length < end - pos) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid Message " - "Length"); - return; - } - } - - wpa_printf(MSG_DEBUG, "EAP-WSC: Received packet: Op-Code %d " - "Flags 0x%x Message Length %d", - op_code, flags, message_length); - - if (data->state == WAIT_FRAG_ACK) { - if (op_code != WSC_FRAG_ACK) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " - "in WAIT_FRAG_ACK state", op_code); - eap_wsc_state(data, FAIL); - return; - } - wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment acknowledged"); - eap_wsc_state(data, MSG); - return; - } - - if (op_code != WSC_ACK && op_code != WSC_NACK && op_code != WSC_MSG && - op_code != WSC_Done) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", - op_code); - eap_wsc_state(data, FAIL); - return; - } - - if (data->in_buf && - eap_wsc_process_cont(data, pos, end - pos, op_code) < 0) { - eap_wsc_state(data, FAIL); - return; - } - - if (flags & WSC_FLAGS_MF) { - if (eap_wsc_process_fragment(data, flags, op_code, - message_length, pos, end - pos) < - 0) - eap_wsc_state(data, FAIL); - else - eap_wsc_state(data, FRAG_ACK); - return; - } - - if (data->in_buf == NULL) { - /* Wrap unfragmented messages as wpabuf without extra copy */ - wpabuf_set(&tmpbuf, pos, end - pos); - data->in_buf = &tmpbuf; - } - - res = wps_process_msg(data->wps, op_code, data->in_buf); - switch (res) { - case WPS_DONE: - wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing completed " - "successfully - report EAP failure"); - eap_wsc_state(data, FAIL); - break; - case WPS_CONTINUE: - eap_wsc_state(data, MSG); - break; - case WPS_FAILURE: - wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing failed"); - eap_wsc_state(data, FAIL); - break; - case WPS_PENDING: - eap_wsc_state(data, MSG); - sm->method_pending = METHOD_PENDING_WAIT; - eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data); - eloop_register_timeout(5, 0, eap_wsc_ext_reg_timeout, - sm, data); - break; - } - - if (data->in_buf != &tmpbuf) - wpabuf_free(data->in_buf); - data->in_buf = NULL; -} - - -static Boolean eap_wsc_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_wsc_data *data = priv; - return data->state == FAIL; -} - - -static Boolean eap_wsc_isSuccess(struct eap_sm *sm, void *priv) -{ - /* EAP-WSC will always result in EAP-Failure */ - return FALSE; -} - - -static int eap_wsc_getTimeout(struct eap_sm *sm, void *priv) -{ - /* Recommended retransmit times: retransmit timeout 5 seconds, - * per-message timeout 15 seconds, i.e., 3 tries. */ - sm->MaxRetrans = 2; /* total 3 attempts */ - return 5; -} - - -int eap_server_wsc_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, - "WSC"); - if (eap == NULL) - return -1; - - eap->init = eap_wsc_init; - eap->reset = eap_wsc_reset; - eap->buildReq = eap_wsc_buildReq; - eap->check = eap_wsc_check; - eap->process = eap_wsc_process; - eap->isDone = eap_wsc_isDone; - eap->isSuccess = eap_wsc_isSuccess; - eap->getTimeout = eap_wsc_getTimeout; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/src/eap_server/ikev2.c b/contrib/hostapd/src/eap_server/ikev2.c deleted file mode 100644 index 46767c5014..0000000000 --- a/contrib/hostapd/src/eap_server/ikev2.c +++ /dev/null @@ -1,1205 +0,0 @@ -/* - * IKEv2 initiator (RFC 4306) for EAP-IKEV2 - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "dh_groups.h" -#include "ikev2.h" - - -static int ikev2_process_idr(struct ikev2_initiator_data *data, - const u8 *idr, size_t idr_len); - - -void ikev2_initiator_deinit(struct ikev2_initiator_data *data) -{ - ikev2_free_keys(&data->keys); - wpabuf_free(data->r_dh_public); - wpabuf_free(data->i_dh_private); - os_free(data->IDi); - os_free(data->IDr); - os_free(data->shared_secret); - wpabuf_free(data->i_sign_msg); - wpabuf_free(data->r_sign_msg); - os_free(data->key_pad); -} - - -static int ikev2_derive_keys(struct ikev2_initiator_data *data) -{ - u8 *buf, *pos, *pad, skeyseed[IKEV2_MAX_HASH_LEN]; - size_t buf_len, pad_len; - struct wpabuf *shared; - const struct ikev2_integ_alg *integ; - const struct ikev2_prf_alg *prf; - const struct ikev2_encr_alg *encr; - int ret; - const u8 *addr[2]; - size_t len[2]; - - /* RFC 4306, Sect. 2.14 */ - - integ = ikev2_get_integ(data->proposal.integ); - prf = ikev2_get_prf(data->proposal.prf); - encr = ikev2_get_encr(data->proposal.encr); - if (integ == NULL || prf == NULL || encr == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported proposal"); - return -1; - } - - shared = dh_derive_shared(data->r_dh_public, data->i_dh_private, - data->dh); - if (shared == NULL) - return -1; - - /* Construct Ni | Nr | SPIi | SPIr */ - - buf_len = data->i_nonce_len + data->r_nonce_len + 2 * IKEV2_SPI_LEN; - buf = os_malloc(buf_len); - if (buf == NULL) { - wpabuf_free(shared); - return -1; - } - - pos = buf; - os_memcpy(pos, data->i_nonce, data->i_nonce_len); - pos += data->i_nonce_len; - os_memcpy(pos, data->r_nonce, data->r_nonce_len); - pos += data->r_nonce_len; - os_memcpy(pos, data->i_spi, IKEV2_SPI_LEN); - pos += IKEV2_SPI_LEN; - os_memcpy(pos, data->r_spi, IKEV2_SPI_LEN); - - /* SKEYSEED = prf(Ni | Nr, g^ir) */ - - /* Use zero-padding per RFC 4306, Sect. 2.14 */ - pad_len = data->dh->prime_len - wpabuf_len(shared); - pad = os_zalloc(pad_len ? pad_len : 1); - if (pad == NULL) { - wpabuf_free(shared); - os_free(buf); - return -1; - } - addr[0] = pad; - len[0] = pad_len; - addr[1] = wpabuf_head(shared); - len[1] = wpabuf_len(shared); - if (ikev2_prf_hash(prf->id, buf, data->i_nonce_len + data->r_nonce_len, - 2, addr, len, skeyseed) < 0) { - wpabuf_free(shared); - os_free(buf); - os_free(pad); - return -1; - } - os_free(pad); - wpabuf_free(shared); - - /* DH parameters are not needed anymore, so free them */ - wpabuf_free(data->r_dh_public); - data->r_dh_public = NULL; - wpabuf_free(data->i_dh_private); - data->i_dh_private = NULL; - - wpa_hexdump_key(MSG_DEBUG, "IKEV2: SKEYSEED", - skeyseed, prf->hash_len); - - ret = ikev2_derive_sk_keys(prf, integ, encr, skeyseed, buf, buf_len, - &data->keys); - os_free(buf); - return ret; -} - - -static int ikev2_parse_transform(struct ikev2_initiator_data *data, - struct ikev2_proposal_data *prop, - const u8 *pos, const u8 *end) -{ - int transform_len; - const struct ikev2_transform *t; - u16 transform_id; - const u8 *tend; - - if (end - pos < (int) sizeof(*t)) { - wpa_printf(MSG_INFO, "IKEV2: Too short transform"); - return -1; - } - - t = (const struct ikev2_transform *) pos; - transform_len = WPA_GET_BE16(t->transform_length); - if (transform_len < (int) sizeof(*t) || pos + transform_len > end) { - wpa_printf(MSG_INFO, "IKEV2: Invalid transform length %d", - transform_len); - return -1; - } - tend = pos + transform_len; - - transform_id = WPA_GET_BE16(t->transform_id); - - wpa_printf(MSG_DEBUG, "IKEV2: Transform:"); - wpa_printf(MSG_DEBUG, "IKEV2: Type: %d Transform Length: %d " - "Transform Type: %d Transform ID: %d", - t->type, transform_len, t->transform_type, transform_id); - - if (t->type != 0 && t->type != 3) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Transform type"); - return -1; - } - - pos = (const u8 *) (t + 1); - if (pos < tend) { - wpa_hexdump(MSG_DEBUG, "IKEV2: Transform Attributes", - pos, tend - pos); - } - - switch (t->transform_type) { - case IKEV2_TRANSFORM_ENCR: - if (ikev2_get_encr(transform_id) && - transform_id == data->proposal.encr) { - if (transform_id == ENCR_AES_CBC) { - if (tend - pos != 4) { - wpa_printf(MSG_DEBUG, "IKEV2: No " - "Transform Attr for AES"); - break; - } - if (WPA_GET_BE16(pos) != 0x800e) { - wpa_printf(MSG_DEBUG, "IKEV2: Not a " - "Key Size attribute for " - "AES"); - break; - } - if (WPA_GET_BE16(pos + 2) != 128) { - wpa_printf(MSG_DEBUG, "IKEV2: " - "Unsupported AES key size " - "%d bits", - WPA_GET_BE16(pos + 2)); - break; - } - } - prop->encr = transform_id; - } - break; - case IKEV2_TRANSFORM_PRF: - if (ikev2_get_prf(transform_id) && - transform_id == data->proposal.prf) - prop->prf = transform_id; - break; - case IKEV2_TRANSFORM_INTEG: - if (ikev2_get_integ(transform_id) && - transform_id == data->proposal.integ) - prop->integ = transform_id; - break; - case IKEV2_TRANSFORM_DH: - if (dh_groups_get(transform_id) && - transform_id == data->proposal.dh) - prop->dh = transform_id; - break; - } - - return transform_len; -} - - -static int ikev2_parse_proposal(struct ikev2_initiator_data *data, - struct ikev2_proposal_data *prop, - const u8 *pos, const u8 *end) -{ - const u8 *pend, *ppos; - int proposal_len, i; - const struct ikev2_proposal *p; - - if (end - pos < (int) sizeof(*p)) { - wpa_printf(MSG_INFO, "IKEV2: Too short proposal"); - return -1; - } - - p = (const struct ikev2_proposal *) pos; - proposal_len = WPA_GET_BE16(p->proposal_length); - if (proposal_len < (int) sizeof(*p) || pos + proposal_len > end) { - wpa_printf(MSG_INFO, "IKEV2: Invalid proposal length %d", - proposal_len); - return -1; - } - wpa_printf(MSG_DEBUG, "IKEV2: SAi1 Proposal # %d", - p->proposal_num); - wpa_printf(MSG_DEBUG, "IKEV2: Type: %d Proposal Length: %d " - " Protocol ID: %d", - p->type, proposal_len, p->protocol_id); - wpa_printf(MSG_DEBUG, "IKEV2: SPI Size: %d Transforms: %d", - p->spi_size, p->num_transforms); - - if (p->type != 0 && p->type != 2) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal type"); - return -1; - } - - if (p->protocol_id != IKEV2_PROTOCOL_IKE) { - wpa_printf(MSG_DEBUG, "IKEV2: Unexpected Protocol ID " - "(only IKE allowed for EAP-IKEv2)"); - return -1; - } - - if (p->proposal_num != prop->proposal_num) { - if (p->proposal_num == prop->proposal_num + 1) - prop->proposal_num = p->proposal_num; - else { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal #"); - return -1; - } - } - - ppos = (const u8 *) (p + 1); - pend = pos + proposal_len; - if (ppos + p->spi_size > pend) { - wpa_printf(MSG_INFO, "IKEV2: Not enough room for SPI " - "in proposal"); - return -1; - } - if (p->spi_size) { - wpa_hexdump(MSG_DEBUG, "IKEV2: SPI", - ppos, p->spi_size); - ppos += p->spi_size; - } - - /* - * For initial IKE_SA negotiation, SPI Size MUST be zero; for - * subsequent negotiations, it must be 8 for IKE. We only support - * initial case for now. - */ - if (p->spi_size != 0) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected SPI Size"); - return -1; - } - - if (p->num_transforms == 0) { - wpa_printf(MSG_INFO, "IKEV2: At least one transform required"); - return -1; - } - - for (i = 0; i < (int) p->num_transforms; i++) { - int tlen = ikev2_parse_transform(data, prop, ppos, pend); - if (tlen < 0) - return -1; - ppos += tlen; - } - - if (ppos != pend) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected data after " - "transforms"); - return -1; - } - - return proposal_len; -} - - -static int ikev2_process_sar1(struct ikev2_initiator_data *data, - const u8 *sar1, size_t sar1_len) -{ - struct ikev2_proposal_data prop; - const u8 *pos, *end; - int found = 0; - - /* Security Association Payloads: */ - - if (sar1 == NULL) { - wpa_printf(MSG_INFO, "IKEV2: SAr1 not received"); - return -1; - } - - os_memset(&prop, 0, sizeof(prop)); - prop.proposal_num = 1; - - pos = sar1; - end = sar1 + sar1_len; - - while (pos < end) { - int plen; - - prop.integ = -1; - prop.prf = -1; - prop.encr = -1; - prop.dh = -1; - plen = ikev2_parse_proposal(data, &prop, pos, end); - if (plen < 0) - return -1; - - if (!found && prop.integ != -1 && prop.prf != -1 && - prop.encr != -1 && prop.dh != -1) { - found = 1; - } - - pos += plen; - - /* Only one proposal expected in SAr */ - break; - } - - if (pos != end) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected data after proposal"); - return -1; - } - - if (!found) { - wpa_printf(MSG_INFO, "IKEV2: No acceptable proposal found"); - return -1; - } - - wpa_printf(MSG_DEBUG, "IKEV2: Accepted proposal #%d: ENCR:%d PRF:%d " - "INTEG:%d D-H:%d", data->proposal.proposal_num, - data->proposal.encr, data->proposal.prf, - data->proposal.integ, data->proposal.dh); - - return 0; -} - - -static int ikev2_process_ker(struct ikev2_initiator_data *data, - const u8 *ker, size_t ker_len) -{ - u16 group; - - /* - * Key Exchange Payload: - * DH Group # (16 bits) - * RESERVED (16 bits) - * Key Exchange Data (Diffie-Hellman public value) - */ - - if (ker == NULL) { - wpa_printf(MSG_INFO, "IKEV2: KEr not received"); - return -1; - } - - if (ker_len < 4 + 96) { - wpa_printf(MSG_INFO, "IKEV2: Too show Key Exchange Payload"); - return -1; - } - - group = WPA_GET_BE16(ker); - wpa_printf(MSG_DEBUG, "IKEV2: KEr DH Group #%u", group); - - if (group != data->proposal.dh) { - wpa_printf(MSG_DEBUG, "IKEV2: KEr DH Group #%u does not match " - "with the selected proposal (%u)", - group, data->proposal.dh); - return -1; - } - - if (data->dh == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported DH group"); - return -1; - } - - /* RFC 4306, Section 3.4: - * The length of DH public value MUST be equal to the lenght of the - * prime modulus. - */ - if (ker_len - 4 != data->dh->prime_len) { - wpa_printf(MSG_INFO, "IKEV2: Invalid DH public value length " - "%ld (expected %ld)", - (long) (ker_len - 4), (long) data->dh->prime_len); - return -1; - } - - wpabuf_free(data->r_dh_public); - data->r_dh_public = wpabuf_alloc_copy(ker + 4, ker_len - 4); - if (data->r_dh_public == NULL) - return -1; - - wpa_hexdump_buf(MSG_DEBUG, "IKEV2: KEr Diffie-Hellman Public Value", - data->r_dh_public); - - return 0; -} - - -static int ikev2_process_nr(struct ikev2_initiator_data *data, - const u8 *nr, size_t nr_len) -{ - if (nr == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Nr not received"); - return -1; - } - - if (nr_len < IKEV2_NONCE_MIN_LEN || nr_len > IKEV2_NONCE_MAX_LEN) { - wpa_printf(MSG_INFO, "IKEV2: Invalid Nr length %ld", - (long) nr_len); - return -1; - } - - data->r_nonce_len = nr_len; - os_memcpy(data->r_nonce, nr, nr_len); - wpa_hexdump(MSG_MSGDUMP, "IKEV2: Nr", - data->r_nonce, data->r_nonce_len); - - return 0; -} - - -static int ikev2_process_sa_init_encr(struct ikev2_initiator_data *data, - const struct ikev2_hdr *hdr, - const u8 *encrypted, - size_t encrypted_len, u8 next_payload) -{ - u8 *decrypted; - size_t decrypted_len; - struct ikev2_payloads pl; - int ret = 0; - - decrypted = ikev2_decrypt_payload(data->proposal.encr, - data->proposal.integ, &data->keys, 0, - hdr, encrypted, encrypted_len, - &decrypted_len); - if (decrypted == NULL) - return -1; - - wpa_printf(MSG_DEBUG, "IKEV2: Processing decrypted payloads"); - - if (ikev2_parse_payloads(&pl, next_payload, decrypted, - decrypted + decrypted_len) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Failed to parse decrypted " - "payloads"); - return -1; - } - - if (pl.idr) - ret = ikev2_process_idr(data, pl.idr, pl.idr_len); - - os_free(decrypted); - - return ret; -} - - -static int ikev2_process_sa_init(struct ikev2_initiator_data *data, - const struct ikev2_hdr *hdr, - struct ikev2_payloads *pl) -{ - if (ikev2_process_sar1(data, pl->sa, pl->sa_len) < 0 || - ikev2_process_ker(data, pl->ke, pl->ke_len) < 0 || - ikev2_process_nr(data, pl->nonce, pl->nonce_len) < 0) - return -1; - - os_memcpy(data->r_spi, hdr->r_spi, IKEV2_SPI_LEN); - - if (ikev2_derive_keys(data) < 0) - return -1; - - if (pl->encrypted) { - wpa_printf(MSG_DEBUG, "IKEV2: Encrypted payload in SA_INIT - " - "try to get IDr from it"); - if (ikev2_process_sa_init_encr(data, hdr, pl->encrypted, - pl->encrypted_len, - pl->encr_next_payload) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Failed to process " - "encrypted payload"); - return -1; - } - } - - data->state = SA_AUTH; - - return 0; -} - - -static int ikev2_process_idr(struct ikev2_initiator_data *data, - const u8 *idr, size_t idr_len) -{ - u8 id_type; - - if (idr == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No IDr received"); - return -1; - } - - if (idr_len < 4) { - wpa_printf(MSG_INFO, "IKEV2: Too short IDr payload"); - return -1; - } - - id_type = idr[0]; - idr += 4; - idr_len -= 4; - - wpa_printf(MSG_DEBUG, "IKEV2: IDr ID Type %d", id_type); - wpa_hexdump_ascii(MSG_DEBUG, "IKEV2: IDr", idr, idr_len); - if (data->IDr) { - if (id_type != data->IDr_type || idr_len != data->IDr_len || - os_memcmp(idr, data->IDr, idr_len) != 0) { - wpa_printf(MSG_INFO, "IKEV2: IDr differs from the one " - "received earlier"); - wpa_printf(MSG_DEBUG, "IKEV2: Previous IDr ID Type %d", - id_type); - wpa_hexdump_ascii(MSG_DEBUG, "Previous IKEV2: IDr", - data->IDr, data->IDr_len); - return -1; - } - os_free(data->IDr); - } - data->IDr = os_malloc(idr_len); - if (data->IDr == NULL) - return -1; - os_memcpy(data->IDr, idr, idr_len); - data->IDr_len = idr_len; - data->IDr_type = id_type; - - return 0; -} - - -static int ikev2_process_cert(struct ikev2_initiator_data *data, - const u8 *cert, size_t cert_len) -{ - u8 cert_encoding; - - if (cert == NULL) { - if (data->peer_auth == PEER_AUTH_CERT) { - wpa_printf(MSG_INFO, "IKEV2: No Certificate received"); - return -1; - } - return 0; - } - - if (cert_len < 1) { - wpa_printf(MSG_INFO, "IKEV2: No Cert Encoding field"); - return -1; - } - - cert_encoding = cert[0]; - cert++; - cert_len--; - - wpa_printf(MSG_DEBUG, "IKEV2: Cert Encoding %d", cert_encoding); - wpa_hexdump(MSG_MSGDUMP, "IKEV2: Certificate Data", cert, cert_len); - - /* TODO: validate certificate */ - - return 0; -} - - -static int ikev2_process_auth_cert(struct ikev2_initiator_data *data, - u8 method, const u8 *auth, size_t auth_len) -{ - if (method != AUTH_RSA_SIGN) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication " - "method %d", method); - return -1; - } - - /* TODO: validate AUTH */ - return 0; -} - - -static int ikev2_process_auth_secret(struct ikev2_initiator_data *data, - u8 method, const u8 *auth, - size_t auth_len) -{ - u8 auth_data[IKEV2_MAX_HASH_LEN]; - const struct ikev2_prf_alg *prf; - - if (method != AUTH_SHARED_KEY_MIC) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication " - "method %d", method); - return -1; - } - - /* msg | Ni | prf(SK_pr,IDr') */ - if (ikev2_derive_auth_data(data->proposal.prf, data->r_sign_msg, - data->IDr, data->IDr_len, data->IDr_type, - &data->keys, 0, data->shared_secret, - data->shared_secret_len, - data->i_nonce, data->i_nonce_len, - data->key_pad, data->key_pad_len, - auth_data) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data"); - return -1; - } - - wpabuf_free(data->r_sign_msg); - data->r_sign_msg = NULL; - - prf = ikev2_get_prf(data->proposal.prf); - if (prf == NULL) - return -1; - - if (auth_len != prf->hash_len || - os_memcmp(auth, auth_data, auth_len) != 0) { - wpa_printf(MSG_INFO, "IKEV2: Invalid Authentication Data"); - wpa_hexdump(MSG_DEBUG, "IKEV2: Received Authentication Data", - auth, auth_len); - wpa_hexdump(MSG_DEBUG, "IKEV2: Expected Authentication Data", - auth_data, prf->hash_len); - return -1; - } - - wpa_printf(MSG_DEBUG, "IKEV2: Peer authenticated successfully " - "using shared keys"); - - return 0; -} - - -static int ikev2_process_auth(struct ikev2_initiator_data *data, - const u8 *auth, size_t auth_len) -{ - u8 auth_method; - - if (auth == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No Authentication Payload"); - return -1; - } - - if (auth_len < 4) { - wpa_printf(MSG_INFO, "IKEV2: Too short Authentication " - "Payload"); - return -1; - } - - auth_method = auth[0]; - auth += 4; - auth_len -= 4; - - wpa_printf(MSG_DEBUG, "IKEV2: Auth Method %d", auth_method); - wpa_hexdump(MSG_MSGDUMP, "IKEV2: Authentication Data", auth, auth_len); - - switch (data->peer_auth) { - case PEER_AUTH_CERT: - return ikev2_process_auth_cert(data, auth_method, auth, - auth_len); - case PEER_AUTH_SECRET: - return ikev2_process_auth_secret(data, auth_method, auth, - auth_len); - } - - return -1; -} - - -static int ikev2_process_sa_auth_decrypted(struct ikev2_initiator_data *data, - u8 next_payload, - u8 *payload, size_t payload_len) -{ - struct ikev2_payloads pl; - - wpa_printf(MSG_DEBUG, "IKEV2: Processing decrypted payloads"); - - if (ikev2_parse_payloads(&pl, next_payload, payload, payload + - payload_len) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Failed to parse decrypted " - "payloads"); - return -1; - } - - if (ikev2_process_idr(data, pl.idr, pl.idr_len) < 0 || - ikev2_process_cert(data, pl.cert, pl.cert_len) < 0 || - ikev2_process_auth(data, pl.auth, pl.auth_len) < 0) - return -1; - - return 0; -} - - -static int ikev2_process_sa_auth(struct ikev2_initiator_data *data, - const struct ikev2_hdr *hdr, - struct ikev2_payloads *pl) -{ - u8 *decrypted; - size_t decrypted_len; - int ret; - - decrypted = ikev2_decrypt_payload(data->proposal.encr, - data->proposal.integ, - &data->keys, 0, hdr, pl->encrypted, - pl->encrypted_len, &decrypted_len); - if (decrypted == NULL) - return -1; - - ret = ikev2_process_sa_auth_decrypted(data, pl->encr_next_payload, - decrypted, decrypted_len); - os_free(decrypted); - - if (ret == 0 && !data->unknown_user) { - wpa_printf(MSG_DEBUG, "IKEV2: Authentication completed"); - data->state = IKEV2_DONE; - } - - return ret; -} - - -static int ikev2_validate_rx_state(struct ikev2_initiator_data *data, - u8 exchange_type, u32 message_id) -{ - switch (data->state) { - case SA_INIT: - /* Expect to receive IKE_SA_INIT: HDR, SAr, KEr, Nr, [CERTREQ], - * [SK{IDr}] */ - if (exchange_type != IKE_SA_INIT) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type " - "%u in SA_INIT state", exchange_type); - return -1; - } - if (message_id != 0) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u " - "in SA_INIT state", message_id); - return -1; - } - break; - case SA_AUTH: - /* Expect to receive IKE_SA_AUTH: - * HDR, SK {IDr, [CERT,] [CERTREQ,] [NFID,] AUTH} - */ - if (exchange_type != IKE_SA_AUTH) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type " - "%u in SA_AUTH state", exchange_type); - return -1; - } - if (message_id != 1) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u " - "in SA_AUTH state", message_id); - return -1; - } - break; - case CHILD_SA: - if (exchange_type != CREATE_CHILD_SA) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type " - "%u in CHILD_SA state", exchange_type); - return -1; - } - if (message_id != 2) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u " - "in CHILD_SA state", message_id); - return -1; - } - break; - case IKEV2_DONE: - return -1; - } - - return 0; -} - - -int ikev2_initiator_process(struct ikev2_initiator_data *data, - const struct wpabuf *buf) -{ - const struct ikev2_hdr *hdr; - u32 length, message_id; - const u8 *pos, *end; - struct ikev2_payloads pl; - - wpa_printf(MSG_MSGDUMP, "IKEV2: Received message (len %lu)", - (unsigned long) wpabuf_len(buf)); - - if (wpabuf_len(buf) < sizeof(*hdr)) { - wpa_printf(MSG_INFO, "IKEV2: Too short frame to include HDR"); - return -1; - } - - hdr = (const struct ikev2_hdr *) wpabuf_head(buf); - end = wpabuf_head_u8(buf) + wpabuf_len(buf); - message_id = WPA_GET_BE32(hdr->message_id); - length = WPA_GET_BE32(hdr->length); - - wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Initiator's SPI", - hdr->i_spi, IKEV2_SPI_LEN); - wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Initiator's SPI", - hdr->r_spi, IKEV2_SPI_LEN); - wpa_printf(MSG_DEBUG, "IKEV2: Next Payload: %u Version: 0x%x " - "Exchange Type: %u", - hdr->next_payload, hdr->version, hdr->exchange_type); - wpa_printf(MSG_DEBUG, "IKEV2: Message ID: %u Length: %u", - message_id, length); - - if (hdr->version != IKEV2_VERSION) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported HDR version 0x%x " - "(expected 0x%x)", hdr->version, IKEV2_VERSION); - return -1; - } - - if (length != wpabuf_len(buf)) { - wpa_printf(MSG_INFO, "IKEV2: Invalid length (HDR: %lu != " - "RX: %lu)", (unsigned long) length, - (unsigned long) wpabuf_len(buf)); - return -1; - } - - if (ikev2_validate_rx_state(data, hdr->exchange_type, message_id) < 0) - return -1; - - if ((hdr->flags & (IKEV2_HDR_INITIATOR | IKEV2_HDR_RESPONSE)) != - IKEV2_HDR_RESPONSE) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Flags value 0x%x", - hdr->flags); - return -1; - } - - if (data->state != SA_INIT) { - if (os_memcmp(data->i_spi, hdr->i_spi, IKEV2_SPI_LEN) != 0) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA " - "Initiator's SPI"); - return -1; - } - if (os_memcmp(data->r_spi, hdr->r_spi, IKEV2_SPI_LEN) != 0) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA " - "Responder's SPI"); - return -1; - } - } - - pos = (const u8 *) (hdr + 1); - if (ikev2_parse_payloads(&pl, hdr->next_payload, pos, end) < 0) - return -1; - - switch (data->state) { - case SA_INIT: - if (ikev2_process_sa_init(data, hdr, &pl) < 0) - return -1; - wpabuf_free(data->r_sign_msg); - data->r_sign_msg = wpabuf_dup(buf); - break; - case SA_AUTH: - if (ikev2_process_sa_auth(data, hdr, &pl) < 0) - return -1; - break; - case CHILD_SA: - case IKEV2_DONE: - break; - } - - return 0; -} - - -static void ikev2_build_hdr(struct ikev2_initiator_data *data, - struct wpabuf *msg, u8 exchange_type, - u8 next_payload, u32 message_id) -{ - struct ikev2_hdr *hdr; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding HDR"); - - /* HDR - RFC 4306, Sect. 3.1 */ - hdr = wpabuf_put(msg, sizeof(*hdr)); - os_memcpy(hdr->i_spi, data->i_spi, IKEV2_SPI_LEN); - os_memcpy(hdr->r_spi, data->r_spi, IKEV2_SPI_LEN); - hdr->next_payload = next_payload; - hdr->version = IKEV2_VERSION; - hdr->exchange_type = exchange_type; - hdr->flags = IKEV2_HDR_INITIATOR; - WPA_PUT_BE32(hdr->message_id, message_id); -} - - -static int ikev2_build_sai(struct ikev2_initiator_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - struct ikev2_proposal *p; - struct ikev2_transform *t; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding SAi payload"); - - /* SAi1 - RFC 4306, Sect. 2.7 and 3.3 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - - /* TODO: support for multiple proposals */ - p = wpabuf_put(msg, sizeof(*p)); - p->proposal_num = data->proposal.proposal_num; - p->protocol_id = IKEV2_PROTOCOL_IKE; - p->num_transforms = 4; - - t = wpabuf_put(msg, sizeof(*t)); - t->type = 3; - t->transform_type = IKEV2_TRANSFORM_ENCR; - WPA_PUT_BE16(t->transform_id, data->proposal.encr); - if (data->proposal.encr == ENCR_AES_CBC) { - /* Transform Attribute: Key Len = 128 bits */ - wpabuf_put_be16(msg, 0x800e); /* AF=1, AttrType=14 */ - wpabuf_put_be16(msg, 128); /* 128-bit key */ - } - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) t; - WPA_PUT_BE16(t->transform_length, plen); - - t = wpabuf_put(msg, sizeof(*t)); - t->type = 3; - WPA_PUT_BE16(t->transform_length, sizeof(*t)); - t->transform_type = IKEV2_TRANSFORM_PRF; - WPA_PUT_BE16(t->transform_id, data->proposal.prf); - - t = wpabuf_put(msg, sizeof(*t)); - t->type = 3; - WPA_PUT_BE16(t->transform_length, sizeof(*t)); - t->transform_type = IKEV2_TRANSFORM_INTEG; - WPA_PUT_BE16(t->transform_id, data->proposal.integ); - - t = wpabuf_put(msg, sizeof(*t)); - WPA_PUT_BE16(t->transform_length, sizeof(*t)); - t->transform_type = IKEV2_TRANSFORM_DH; - WPA_PUT_BE16(t->transform_id, data->proposal.dh); - - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) p; - WPA_PUT_BE16(p->proposal_length, plen); - - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - - return 0; -} - - -static int ikev2_build_kei(struct ikev2_initiator_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - struct wpabuf *pv; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding KEi payload"); - - data->dh = dh_groups_get(data->proposal.dh); - pv = dh_init(data->dh, &data->i_dh_private); - if (pv == NULL) { - wpa_printf(MSG_DEBUG, "IKEV2: Failed to initialize DH"); - return -1; - } - - /* KEi - RFC 4306, Sect. 3.4 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - - wpabuf_put_be16(msg, data->proposal.dh); /* DH Group # */ - wpabuf_put(msg, 2); /* RESERVED */ - /* - * RFC 4306, Sect. 3.4: possible zero padding for public value to - * match the length of the prime. - */ - wpabuf_put(msg, data->dh->prime_len - wpabuf_len(pv)); - wpabuf_put_buf(msg, pv); - os_free(pv); - - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - return 0; -} - - -static int ikev2_build_ni(struct ikev2_initiator_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding Ni payload"); - - /* Ni - RFC 4306, Sect. 3.9 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - wpabuf_put_data(msg, data->i_nonce, data->i_nonce_len); - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - return 0; -} - - -static int ikev2_build_idi(struct ikev2_initiator_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding IDi payload"); - - if (data->IDi == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No IDi available"); - return -1; - } - - /* IDi - RFC 4306, Sect. 3.5 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - wpabuf_put_u8(msg, ID_KEY_ID); - wpabuf_put(msg, 3); /* RESERVED */ - wpabuf_put_data(msg, data->IDi, data->IDi_len); - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - return 0; -} - - -static int ikev2_build_auth(struct ikev2_initiator_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - const struct ikev2_prf_alg *prf; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding AUTH payload"); - - prf = ikev2_get_prf(data->proposal.prf); - if (prf == NULL) - return -1; - - /* Authentication - RFC 4306, Sect. 3.8 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - wpabuf_put_u8(msg, AUTH_SHARED_KEY_MIC); - wpabuf_put(msg, 3); /* RESERVED */ - - /* msg | Nr | prf(SK_pi,IDi') */ - if (ikev2_derive_auth_data(data->proposal.prf, data->i_sign_msg, - data->IDi, data->IDi_len, ID_KEY_ID, - &data->keys, 1, data->shared_secret, - data->shared_secret_len, - data->r_nonce, data->r_nonce_len, - data->key_pad, data->key_pad_len, - wpabuf_put(msg, prf->hash_len)) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data"); - return -1; - } - wpabuf_free(data->i_sign_msg); - data->i_sign_msg = NULL; - - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - return 0; -} - - -static struct wpabuf * ikev2_build_sa_init(struct ikev2_initiator_data *data) -{ - struct wpabuf *msg; - - /* build IKE_SA_INIT: HDR, SAi, KEi, Ni */ - - if (os_get_random(data->i_spi, IKEV2_SPI_LEN)) - return NULL; - wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Initiator's SPI", - data->i_spi, IKEV2_SPI_LEN); - - data->i_nonce_len = IKEV2_NONCE_MIN_LEN; - if (os_get_random(data->i_nonce, data->i_nonce_len)) - return NULL; - wpa_hexdump(MSG_DEBUG, "IKEV2: Ni", data->i_nonce, data->i_nonce_len); - - msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + 1000); - if (msg == NULL) - return NULL; - - ikev2_build_hdr(data, msg, IKE_SA_INIT, IKEV2_PAYLOAD_SA, 0); - if (ikev2_build_sai(data, msg, IKEV2_PAYLOAD_KEY_EXCHANGE) || - ikev2_build_kei(data, msg, IKEV2_PAYLOAD_NONCE) || - ikev2_build_ni(data, msg, IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) { - wpabuf_free(msg); - return NULL; - } - - ikev2_update_hdr(msg); - - wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_INIT)", msg); - - wpabuf_free(data->i_sign_msg); - data->i_sign_msg = wpabuf_dup(msg); - - return msg; -} - - -static struct wpabuf * ikev2_build_sa_auth(struct ikev2_initiator_data *data) -{ - struct wpabuf *msg, *plain; - const u8 *secret; - size_t secret_len; - - secret = data->get_shared_secret(data->cb_ctx, data->IDr, - data->IDr_len, &secret_len); - if (secret == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Could not get shared secret - " - "use fake value"); - /* RFC 5106, Sect. 7: - * Use a random key to fake AUTH generation in order to prevent - * probing of user identities. - */ - data->unknown_user = 1; - os_free(data->shared_secret); - data->shared_secret = os_malloc(16); - if (data->shared_secret == NULL) - return NULL; - data->shared_secret_len = 16; - if (os_get_random(data->shared_secret, 16)) - return NULL; - } else { - os_free(data->shared_secret); - data->shared_secret = os_malloc(secret_len); - if (data->shared_secret == NULL) - return NULL; - os_memcpy(data->shared_secret, secret, secret_len); - data->shared_secret_len = secret_len; - } - - /* build IKE_SA_AUTH: HDR, SK {IDi, [CERT,] [CERTREQ,] AUTH} */ - - msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1000); - if (msg == NULL) - return NULL; - ikev2_build_hdr(data, msg, IKE_SA_AUTH, IKEV2_PAYLOAD_ENCRYPTED, 1); - - plain = wpabuf_alloc(data->IDr_len + 1000); - if (plain == NULL) { - wpabuf_free(msg); - return NULL; - } - - if (ikev2_build_idi(data, plain, IKEV2_PAYLOAD_AUTHENTICATION) || - ikev2_build_auth(data, plain, IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) || - ikev2_build_encrypted(data->proposal.encr, data->proposal.integ, - &data->keys, 1, msg, plain, - IKEV2_PAYLOAD_IDi)) { - wpabuf_free(plain); - wpabuf_free(msg); - return NULL; - } - wpabuf_free(plain); - - wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_AUTH)", msg); - - return msg; -} - - -struct wpabuf * ikev2_initiator_build(struct ikev2_initiator_data *data) -{ - switch (data->state) { - case SA_INIT: - return ikev2_build_sa_init(data); - case SA_AUTH: - return ikev2_build_sa_auth(data); - case CHILD_SA: - return NULL; - case IKEV2_DONE: - return NULL; - } - return NULL; -} diff --git a/contrib/hostapd/src/eap_server/ikev2.h b/contrib/hostapd/src/eap_server/ikev2.h deleted file mode 100644 index 8349fbe62d..0000000000 --- a/contrib/hostapd/src/eap_server/ikev2.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * IKEv2 initiator (RFC 4306) for EAP-IKEV2 - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IKEV2_H -#define IKEV2_H - -#include "eap_common/ikev2_common.h" - -struct ikev2_proposal_data { - u8 proposal_num; - int integ; - int prf; - int encr; - int dh; -}; - - -struct ikev2_initiator_data { - enum { SA_INIT, SA_AUTH, CHILD_SA, IKEV2_DONE } state; - u8 i_spi[IKEV2_SPI_LEN]; - u8 r_spi[IKEV2_SPI_LEN]; - u8 i_nonce[IKEV2_NONCE_MAX_LEN]; - size_t i_nonce_len; - u8 r_nonce[IKEV2_NONCE_MAX_LEN]; - size_t r_nonce_len; - struct wpabuf *r_dh_public; - struct wpabuf *i_dh_private; - struct ikev2_proposal_data proposal; - const struct dh_group *dh; - struct ikev2_keys keys; - u8 *IDi; - size_t IDi_len; - u8 *IDr; - size_t IDr_len; - u8 IDr_type; - struct wpabuf *r_sign_msg; - struct wpabuf *i_sign_msg; - u8 *shared_secret; - size_t shared_secret_len; - enum { PEER_AUTH_CERT, PEER_AUTH_SECRET } peer_auth; - u8 *key_pad; - size_t key_pad_len; - - const u8 * (*get_shared_secret)(void *ctx, const u8 *IDr, - size_t IDr_len, size_t *secret_len); - void *cb_ctx; - int unknown_user; -}; - - -void ikev2_initiator_deinit(struct ikev2_initiator_data *data); -int ikev2_initiator_process(struct ikev2_initiator_data *data, - const struct wpabuf *buf); -struct wpabuf * ikev2_initiator_build(struct ikev2_initiator_data *data); - -#endif /* IKEV2_H */ diff --git a/contrib/hostapd/src/eap_server/tncs.c b/contrib/hostapd/src/eap_server/tncs.c deleted file mode 100644 index 21d83b3bd9..0000000000 --- a/contrib/hostapd/src/eap_server/tncs.c +++ /dev/null @@ -1,1272 +0,0 @@ -/* - * EAP-TNC - TNCS (IF-IMV, IF-TNCCS, and IF-TNCCS-SOH) - * Copyright (c) 2007-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "base64.h" -#include "tncs.h" -#include "eap_common/eap_tlv_common.h" -#include "eap_common/eap_defs.h" - - -/* TODO: TNCS must be thread-safe; review the code and add locking etc. if - * needed.. */ - -#define TNC_CONFIG_FILE "/etc/tnc_config" -#define IF_TNCCS_START \ -"\n" \ -"\n" -#define IF_TNCCS_END "\n" - -/* TNC IF-IMV */ - -typedef unsigned long TNC_UInt32; -typedef unsigned char *TNC_BufferReference; - -typedef TNC_UInt32 TNC_IMVID; -typedef TNC_UInt32 TNC_ConnectionID; -typedef TNC_UInt32 TNC_ConnectionState; -typedef TNC_UInt32 TNC_RetryReason; -typedef TNC_UInt32 TNC_IMV_Action_Recommendation; -typedef TNC_UInt32 TNC_IMV_Evaluation_Result; -typedef TNC_UInt32 TNC_MessageType; -typedef TNC_MessageType *TNC_MessageTypeList; -typedef TNC_UInt32 TNC_VendorID; -typedef TNC_UInt32 TNC_Subtype; -typedef TNC_UInt32 TNC_Version; -typedef TNC_UInt32 TNC_Result; -typedef TNC_UInt32 TNC_AttributeID; - -typedef TNC_Result (*TNC_TNCS_BindFunctionPointer)( - TNC_IMVID imvID, - char *functionName, - void **pOutfunctionPointer); - -#define TNC_RESULT_SUCCESS 0 -#define TNC_RESULT_NOT_INITIALIZED 1 -#define TNC_RESULT_ALREADY_INITIALIZED 2 -#define TNC_RESULT_NO_COMMON_VERSION 3 -#define TNC_RESULT_CANT_RETRY 4 -#define TNC_RESULT_WONT_RETRY 5 -#define TNC_RESULT_INVALID_PARAMETER 6 -#define TNC_RESULT_CANT_RESPOND 7 -#define TNC_RESULT_ILLEGAL_OPERATION 8 -#define TNC_RESULT_OTHER 9 -#define TNC_RESULT_FATAL 10 - -#define TNC_CONNECTION_STATE_CREATE 0 -#define TNC_CONNECTION_STATE_HANDSHAKE 1 -#define TNC_CONNECTION_STATE_ACCESS_ALLOWED 2 -#define TNC_CONNECTION_STATE_ACCESS_ISOLATED 3 -#define TNC_CONNECTION_STATE_ACCESS_NONE 4 -#define TNC_CONNECTION_STATE_DELETE 5 - -#define TNC_IFIMV_VERSION_1 1 - -#define TNC_VENDORID_ANY ((TNC_VendorID) 0xffffff) -#define TNC_SUBTYPE_ANY ((TNC_Subtype) 0xff) - -/* TNCC-TNCS Message Types */ -#define TNC_TNCCS_RECOMMENDATION 0x00000001 -#define TNC_TNCCS_ERROR 0x00000002 -#define TNC_TNCCS_PREFERREDLANGUAGE 0x00000003 -#define TNC_TNCCS_REASONSTRINGS 0x00000004 - -/* Possible TNC_IMV_Action_Recommendation values: */ -enum IMV_Action_Recommendation { - TNC_IMV_ACTION_RECOMMENDATION_ALLOW, - TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS, - TNC_IMV_ACTION_RECOMMENDATION_ISOLATE, - TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION -}; - -/* Possible TNC_IMV_Evaluation_Result values: */ -enum IMV_Evaluation_Result { - TNC_IMV_EVALUATION_RESULT_COMPLIANT, - TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR, - TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR, - TNC_IMV_EVALUATION_RESULT_ERROR, - TNC_IMV_EVALUATION_RESULT_DONT_KNOW -}; - -struct tnc_if_imv { - struct tnc_if_imv *next; - char *name; - char *path; - void *dlhandle; /* from dlopen() */ - TNC_IMVID imvID; - TNC_MessageTypeList supported_types; - size_t num_supported_types; - - /* Functions implemented by IMVs (with TNC_IMV_ prefix) */ - TNC_Result (*Initialize)( - TNC_IMVID imvID, - TNC_Version minVersion, - TNC_Version maxVersion, - TNC_Version *pOutActualVersion); - TNC_Result (*NotifyConnectionChange)( - TNC_IMVID imvID, - TNC_ConnectionID connectionID, - TNC_ConnectionState newState); - TNC_Result (*ReceiveMessage)( - TNC_IMVID imvID, - TNC_ConnectionID connectionID, - TNC_BufferReference message, - TNC_UInt32 messageLength, - TNC_MessageType messageType); - TNC_Result (*SolicitRecommendation)( - TNC_IMVID imvID, - TNC_ConnectionID connectionID); - TNC_Result (*BatchEnding)( - TNC_IMVID imvID, - TNC_ConnectionID connectionID); - TNC_Result (*Terminate)(TNC_IMVID imvID); - TNC_Result (*ProvideBindFunction)( - TNC_IMVID imvID, - TNC_TNCS_BindFunctionPointer bindFunction); -}; - - -#define TNC_MAX_IMV_ID 10 - -struct tncs_data { - struct tncs_data *next; - struct tnc_if_imv *imv; /* local copy of tncs_global_data->imv */ - TNC_ConnectionID connectionID; - unsigned int last_batchid; - enum IMV_Action_Recommendation recommendation; - int done; - - struct conn_imv { - u8 *imv_send; - size_t imv_send_len; - enum IMV_Action_Recommendation recommendation; - int recommendation_set; - } imv_data[TNC_MAX_IMV_ID]; - - char *tncs_message; -}; - - -struct tncs_global { - struct tnc_if_imv *imv; - TNC_ConnectionID next_conn_id; - struct tncs_data *connections; -}; - -static struct tncs_global *tncs_global_data = NULL; - - -static struct tnc_if_imv * tncs_get_imv(TNC_IMVID imvID) -{ - struct tnc_if_imv *imv; - - if (imvID >= TNC_MAX_IMV_ID || tncs_global_data == NULL) - return NULL; - imv = tncs_global_data->imv; - while (imv) { - if (imv->imvID == imvID) - return imv; - imv = imv->next; - } - return NULL; -} - - -static struct tncs_data * tncs_get_conn(TNC_ConnectionID connectionID) -{ - struct tncs_data *tncs; - - if (tncs_global_data == NULL) - return NULL; - - tncs = tncs_global_data->connections; - while (tncs) { - if (tncs->connectionID == connectionID) - return tncs; - tncs = tncs->next; - } - - wpa_printf(MSG_DEBUG, "TNC: Connection ID %lu not found", - (unsigned long) connectionID); - - return NULL; -} - - -/* TNCS functions that IMVs can call */ -TNC_Result TNC_TNCS_ReportMessageTypes( - TNC_IMVID imvID, - TNC_MessageTypeList supportedTypes, - TNC_UInt32 typeCount) -{ - TNC_UInt32 i; - struct tnc_if_imv *imv; - - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_ReportMessageTypes(imvID=%lu " - "typeCount=%lu)", - (unsigned long) imvID, (unsigned long) typeCount); - - for (i = 0; i < typeCount; i++) { - wpa_printf(MSG_DEBUG, "TNC: supportedTypes[%lu] = %lu", - i, supportedTypes[i]); - } - - imv = tncs_get_imv(imvID); - if (imv == NULL) - return TNC_RESULT_INVALID_PARAMETER; - os_free(imv->supported_types); - imv->supported_types = - os_malloc(typeCount * sizeof(TNC_MessageTypeList)); - if (imv->supported_types == NULL) - return TNC_RESULT_FATAL; - os_memcpy(imv->supported_types, supportedTypes, - typeCount * sizeof(TNC_MessageTypeList)); - imv->num_supported_types = typeCount; - - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_TNCS_SendMessage( - TNC_IMVID imvID, - TNC_ConnectionID connectionID, - TNC_BufferReference message, - TNC_UInt32 messageLength, - TNC_MessageType messageType) -{ - struct tncs_data *tncs; - unsigned char *b64; - size_t b64len; - - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_SendMessage(imvID=%lu " - "connectionID=%lu messageType=%lu)", - imvID, connectionID, messageType); - wpa_hexdump_ascii(MSG_DEBUG, "TNC: TNC_TNCS_SendMessage", - message, messageLength); - - if (tncs_get_imv(imvID) == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - tncs = tncs_get_conn(connectionID); - if (tncs == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - b64 = base64_encode(message, messageLength, &b64len); - if (b64 == NULL) - return TNC_RESULT_FATAL; - - os_free(tncs->imv_data[imvID].imv_send); - tncs->imv_data[imvID].imv_send_len = 0; - tncs->imv_data[imvID].imv_send = os_zalloc(b64len + 100); - if (tncs->imv_data[imvID].imv_send == NULL) { - os_free(b64); - return TNC_RESULT_OTHER; - } - - tncs->imv_data[imvID].imv_send_len = - os_snprintf((char *) tncs->imv_data[imvID].imv_send, - b64len + 100, - "%08X" - "%s", - (unsigned int) messageType, b64); - - os_free(b64); - - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_TNCS_RequestHandshakeRetry( - TNC_IMVID imvID, - TNC_ConnectionID connectionID, - TNC_RetryReason reason) -{ - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_RequestHandshakeRetry"); - /* TODO */ - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_TNCS_ProvideRecommendation( - TNC_IMVID imvID, - TNC_ConnectionID connectionID, - TNC_IMV_Action_Recommendation recommendation, - TNC_IMV_Evaluation_Result evaluation) -{ - struct tncs_data *tncs; - - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_ProvideRecommendation(imvID=%lu " - "connectionID=%lu recommendation=%lu evaluation=%lu)", - (unsigned long) imvID, (unsigned long) connectionID, - (unsigned long) recommendation, (unsigned long) evaluation); - - if (tncs_get_imv(imvID) == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - tncs = tncs_get_conn(connectionID); - if (tncs == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - tncs->imv_data[imvID].recommendation = recommendation; - tncs->imv_data[imvID].recommendation_set = 1; - - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_TNCS_GetAttribute( - TNC_IMVID imvID, - TNC_ConnectionID connectionID, - TNC_AttributeID attribureID, - TNC_UInt32 bufferLength, - TNC_BufferReference buffer, - TNC_UInt32 *pOutValueLength) -{ - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_GetAttribute"); - /* TODO */ - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_TNCS_SetAttribute( - TNC_IMVID imvID, - TNC_ConnectionID connectionID, - TNC_AttributeID attribureID, - TNC_UInt32 bufferLength, - TNC_BufferReference buffer) -{ - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_SetAttribute"); - /* TODO */ - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_TNCS_BindFunction( - TNC_IMVID imvID, - char *functionName, - void **pOutFunctionPointer) -{ - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_BindFunction(imcID=%lu, " - "functionName='%s')", (unsigned long) imvID, functionName); - - if (tncs_get_imv(imvID) == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - if (pOutFunctionPointer == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - if (os_strcmp(functionName, "TNC_TNCS_ReportMessageTypes") == 0) - *pOutFunctionPointer = TNC_TNCS_ReportMessageTypes; - else if (os_strcmp(functionName, "TNC_TNCS_SendMessage") == 0) - *pOutFunctionPointer = TNC_TNCS_SendMessage; - else if (os_strcmp(functionName, "TNC_TNCS_RequestHandshakeRetry") == - 0) - *pOutFunctionPointer = TNC_TNCS_RequestHandshakeRetry; - else if (os_strcmp(functionName, "TNC_TNCS_ProvideRecommendation") == - 0) - *pOutFunctionPointer = TNC_TNCS_ProvideRecommendation; - else if (os_strcmp(functionName, "TNC_TNCS_GetAttribute") == 0) - *pOutFunctionPointer = TNC_TNCS_GetAttribute; - else if (os_strcmp(functionName, "TNC_TNCS_SetAttribute") == 0) - *pOutFunctionPointer = TNC_TNCS_SetAttribute; - else - *pOutFunctionPointer = NULL; - - return TNC_RESULT_SUCCESS; -} - - -static void * tncs_get_sym(void *handle, char *func) -{ - void *fptr; - - fptr = dlsym(handle, func); - - return fptr; -} - - -static int tncs_imv_resolve_funcs(struct tnc_if_imv *imv) -{ - void *handle = imv->dlhandle; - - /* Mandatory IMV functions */ - imv->Initialize = tncs_get_sym(handle, "TNC_IMV_Initialize"); - if (imv->Initialize == NULL) { - wpa_printf(MSG_ERROR, "TNC: IMV does not export " - "TNC_IMV_Initialize"); - return -1; - } - - imv->SolicitRecommendation = tncs_get_sym( - handle, "TNC_IMV_SolicitRecommendation"); - if (imv->SolicitRecommendation == NULL) { - wpa_printf(MSG_ERROR, "TNC: IMV does not export " - "TNC_IMV_SolicitRecommendation"); - return -1; - } - - imv->ProvideBindFunction = - tncs_get_sym(handle, "TNC_IMV_ProvideBindFunction"); - if (imv->ProvideBindFunction == NULL) { - wpa_printf(MSG_ERROR, "TNC: IMV does not export " - "TNC_IMV_ProvideBindFunction"); - return -1; - } - - /* Optional IMV functions */ - imv->NotifyConnectionChange = - tncs_get_sym(handle, "TNC_IMV_NotifyConnectionChange"); - imv->ReceiveMessage = tncs_get_sym(handle, "TNC_IMV_ReceiveMessage"); - imv->BatchEnding = tncs_get_sym(handle, "TNC_IMV_BatchEnding"); - imv->Terminate = tncs_get_sym(handle, "TNC_IMV_Terminate"); - - return 0; -} - - -static int tncs_imv_initialize(struct tnc_if_imv *imv) -{ - TNC_Result res; - TNC_Version imv_ver; - - wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMV_Initialize for IMV '%s'", - imv->name); - res = imv->Initialize(imv->imvID, TNC_IFIMV_VERSION_1, - TNC_IFIMV_VERSION_1, &imv_ver); - wpa_printf(MSG_DEBUG, "TNC: TNC_IMV_Initialize: res=%lu imv_ver=%lu", - (unsigned long) res, (unsigned long) imv_ver); - - return res == TNC_RESULT_SUCCESS ? 0 : -1; -} - - -static int tncs_imv_terminate(struct tnc_if_imv *imv) -{ - TNC_Result res; - - if (imv->Terminate == NULL) - return 0; - - wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMV_Terminate for IMV '%s'", - imv->name); - res = imv->Terminate(imv->imvID); - wpa_printf(MSG_DEBUG, "TNC: TNC_IMV_Terminate: %lu", - (unsigned long) res); - - return res == TNC_RESULT_SUCCESS ? 0 : -1; -} - - -static int tncs_imv_provide_bind_function(struct tnc_if_imv *imv) -{ - TNC_Result res; - - wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMV_ProvideBindFunction for " - "IMV '%s'", imv->name); - res = imv->ProvideBindFunction(imv->imvID, TNC_TNCS_BindFunction); - wpa_printf(MSG_DEBUG, "TNC: TNC_IMV_ProvideBindFunction: res=%lu", - (unsigned long) res); - - return res == TNC_RESULT_SUCCESS ? 0 : -1; -} - - -static int tncs_imv_notify_connection_change(struct tnc_if_imv *imv, - TNC_ConnectionID conn, - TNC_ConnectionState state) -{ - TNC_Result res; - - if (imv->NotifyConnectionChange == NULL) - return 0; - - wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMV_NotifyConnectionChange(%d)" - " for IMV '%s'", (int) state, imv->name); - res = imv->NotifyConnectionChange(imv->imvID, conn, state); - wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_NotifyConnectionChange: %lu", - (unsigned long) res); - - return res == TNC_RESULT_SUCCESS ? 0 : -1; -} - - -static int tncs_load_imv(struct tnc_if_imv *imv) -{ - if (imv->path == NULL) { - wpa_printf(MSG_DEBUG, "TNC: No IMV configured"); - return -1; - } - - wpa_printf(MSG_DEBUG, "TNC: Opening IMV: %s (%s)", - imv->name, imv->path); - imv->dlhandle = dlopen(imv->path, RTLD_LAZY); - if (imv->dlhandle == NULL) { - wpa_printf(MSG_ERROR, "TNC: Failed to open IMV '%s' (%s): %s", - imv->name, imv->path, dlerror()); - return -1; - } - - if (tncs_imv_resolve_funcs(imv) < 0) { - wpa_printf(MSG_ERROR, "TNC: Failed to resolve IMV functions"); - return -1; - } - - if (tncs_imv_initialize(imv) < 0 || - tncs_imv_provide_bind_function(imv) < 0) { - wpa_printf(MSG_ERROR, "TNC: Failed to initialize IMV"); - return -1; - } - - return 0; -} - - -static void tncs_free_imv(struct tnc_if_imv *imv) -{ - os_free(imv->name); - os_free(imv->path); - os_free(imv->supported_types); -} - -static void tncs_unload_imv(struct tnc_if_imv *imv) -{ - tncs_imv_terminate(imv); - - if (imv->dlhandle) - dlclose(imv->dlhandle); - - tncs_free_imv(imv); -} - - -static int tncs_supported_type(struct tnc_if_imv *imv, unsigned int type) -{ - size_t i; - unsigned int vendor, subtype; - - if (imv == NULL || imv->supported_types == NULL) - return 0; - - vendor = type >> 8; - subtype = type & 0xff; - - for (i = 0; i < imv->num_supported_types; i++) { - unsigned int svendor, ssubtype; - svendor = imv->supported_types[i] >> 8; - ssubtype = imv->supported_types[i] & 0xff; - if ((vendor == svendor || svendor == TNC_VENDORID_ANY) && - (subtype == ssubtype || ssubtype == TNC_SUBTYPE_ANY)) - return 1; - } - - return 0; -} - - -static void tncs_send_to_imvs(struct tncs_data *tncs, unsigned int type, - const u8 *msg, size_t len) -{ - struct tnc_if_imv *imv; - TNC_Result res; - - wpa_hexdump_ascii(MSG_MSGDUMP, "TNC: Message to IMV(s)", msg, len); - - for (imv = tncs->imv; imv; imv = imv->next) { - if (imv->ReceiveMessage == NULL || - !tncs_supported_type(imv, type)) - continue; - - wpa_printf(MSG_DEBUG, "TNC: Call ReceiveMessage for IMV '%s'", - imv->name); - res = imv->ReceiveMessage(imv->imvID, tncs->connectionID, - (TNC_BufferReference) msg, len, - type); - wpa_printf(MSG_DEBUG, "TNC: ReceiveMessage: %lu", - (unsigned long) res); - } -} - - -static void tncs_batch_ending(struct tncs_data *tncs) -{ - struct tnc_if_imv *imv; - TNC_Result res; - - for (imv = tncs->imv; imv; imv = imv->next) { - if (imv->BatchEnding == NULL) - continue; - - wpa_printf(MSG_DEBUG, "TNC: Call BatchEnding for IMV '%s'", - imv->name); - res = imv->BatchEnding(imv->imvID, tncs->connectionID); - wpa_printf(MSG_DEBUG, "TNC: BatchEnding: %lu", - (unsigned long) res); - } -} - - -static void tncs_solicit_recommendation(struct tncs_data *tncs) -{ - struct tnc_if_imv *imv; - TNC_Result res; - - for (imv = tncs->imv; imv; imv = imv->next) { - if (tncs->imv_data[imv->imvID].recommendation_set) - continue; - - wpa_printf(MSG_DEBUG, "TNC: Call SolicitRecommendation for " - "IMV '%s'", imv->name); - res = imv->SolicitRecommendation(imv->imvID, - tncs->connectionID); - wpa_printf(MSG_DEBUG, "TNC: SolicitRecommendation: %lu", - (unsigned long) res); - } -} - - -void tncs_init_connection(struct tncs_data *tncs) -{ - struct tnc_if_imv *imv; - int i; - - for (imv = tncs->imv; imv; imv = imv->next) { - tncs_imv_notify_connection_change( - imv, tncs->connectionID, TNC_CONNECTION_STATE_CREATE); - tncs_imv_notify_connection_change( - imv, tncs->connectionID, - TNC_CONNECTION_STATE_HANDSHAKE); - } - - for (i = 0; i < TNC_MAX_IMV_ID; i++) { - os_free(tncs->imv_data[i].imv_send); - tncs->imv_data[i].imv_send = NULL; - tncs->imv_data[i].imv_send_len = 0; - } -} - - -size_t tncs_total_send_len(struct tncs_data *tncs) -{ - int i; - size_t len = 0; - - for (i = 0; i < TNC_MAX_IMV_ID; i++) - len += tncs->imv_data[i].imv_send_len; - if (tncs->tncs_message) - len += os_strlen(tncs->tncs_message); - return len; -} - - -u8 * tncs_copy_send_buf(struct tncs_data *tncs, u8 *pos) -{ - int i; - - for (i = 0; i < TNC_MAX_IMV_ID; i++) { - if (tncs->imv_data[i].imv_send == NULL) - continue; - - os_memcpy(pos, tncs->imv_data[i].imv_send, - tncs->imv_data[i].imv_send_len); - pos += tncs->imv_data[i].imv_send_len; - os_free(tncs->imv_data[i].imv_send); - tncs->imv_data[i].imv_send = NULL; - tncs->imv_data[i].imv_send_len = 0; - } - - if (tncs->tncs_message) { - size_t len = os_strlen(tncs->tncs_message); - os_memcpy(pos, tncs->tncs_message, len); - pos += len; - os_free(tncs->tncs_message); - tncs->tncs_message = NULL; - } - - return pos; -} - - -char * tncs_if_tnccs_start(struct tncs_data *tncs) -{ - char *buf = os_malloc(1000); - if (buf == NULL) - return NULL; - tncs->last_batchid++; - os_snprintf(buf, 1000, IF_TNCCS_START, tncs->last_batchid); - return buf; -} - - -char * tncs_if_tnccs_end(void) -{ - char *buf = os_malloc(100); - if (buf == NULL) - return NULL; - os_snprintf(buf, 100, IF_TNCCS_END); - return buf; -} - - -static int tncs_get_type(char *start, unsigned int *type) -{ - char *pos = os_strstr(start, ""); - if (pos == NULL) - return -1; - pos += 6; - *type = strtoul(pos, NULL, 16); - return 0; -} - - -static unsigned char * tncs_get_base64(char *start, size_t *decoded_len) -{ - char *pos, *pos2; - unsigned char *decoded; - - pos = os_strstr(start, ""); - if (pos == NULL) - return NULL; - - pos += 8; - pos2 = os_strstr(pos, ""); - if (pos2 == NULL) - return NULL; - *pos2 = '\0'; - - decoded = base64_decode((unsigned char *) pos, os_strlen(pos), - decoded_len); - *pos2 = '<'; - if (decoded == NULL) { - wpa_printf(MSG_DEBUG, "TNC: Failed to decode Base64 data"); - } - - return decoded; -} - - -static enum tncs_process_res tncs_derive_recommendation(struct tncs_data *tncs) -{ - enum IMV_Action_Recommendation rec; - struct tnc_if_imv *imv; - TNC_ConnectionState state; - char *txt; - - wpa_printf(MSG_DEBUG, "TNC: No more messages from IMVs"); - - if (tncs->done) - return TNCCS_PROCESS_OK_NO_RECOMMENDATION; - - tncs_solicit_recommendation(tncs); - - /* Select the most restrictive recommendation */ - rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION; - for (imv = tncs->imv; imv; imv = imv->next) { - TNC_IMV_Action_Recommendation irec; - irec = tncs->imv_data[imv->imvID].recommendation; - if (irec == TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS) - rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS; - if (irec == TNC_IMV_ACTION_RECOMMENDATION_ISOLATE && - rec != TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS) - rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE; - if (irec == TNC_IMV_ACTION_RECOMMENDATION_ALLOW && - rec == TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION) - rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW; - } - - wpa_printf(MSG_DEBUG, "TNC: Recommendation: %d", rec); - tncs->recommendation = rec; - tncs->done = 1; - - txt = NULL; - switch (rec) { - case TNC_IMV_ACTION_RECOMMENDATION_ALLOW: - case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION: - txt = "allow"; - state = TNC_CONNECTION_STATE_ACCESS_ALLOWED; - break; - case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE: - txt = "isolate"; - state = TNC_CONNECTION_STATE_ACCESS_ISOLATED; - break; - case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS: - txt = "none"; - state = TNC_CONNECTION_STATE_ACCESS_NONE; - break; - default: - state = TNC_CONNECTION_STATE_ACCESS_ALLOWED; - break; - } - - if (txt) { - os_free(tncs->tncs_message); - tncs->tncs_message = os_zalloc(200); - if (tncs->tncs_message) { - os_snprintf(tncs->tncs_message, 199, - "%08X" - "" - "" - "", - TNC_TNCCS_RECOMMENDATION, txt); - } - } - - for (imv = tncs->imv; imv; imv = imv->next) { - tncs_imv_notify_connection_change(imv, tncs->connectionID, - state); - } - - switch (rec) { - case TNC_IMV_ACTION_RECOMMENDATION_ALLOW: - return TNCCS_RECOMMENDATION_ALLOW; - case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS: - return TNCCS_RECOMMENDATION_NO_ACCESS; - case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE: - return TNCCS_RECOMMENDATION_ISOLATE; - case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION: - return TNCCS_RECOMMENDATION_NO_RECOMMENDATION; - default: - return TNCCS_PROCESS_ERROR; - } -} - - -enum tncs_process_res tncs_process_if_tnccs(struct tncs_data *tncs, - const u8 *msg, size_t len) -{ - char *buf, *start, *end, *pos, *pos2, *payload; - unsigned int batch_id; - unsigned char *decoded; - size_t decoded_len; - - buf = os_malloc(len + 1); - if (buf == NULL) - return TNCCS_PROCESS_ERROR; - - os_memcpy(buf, msg, len); - buf[len] = '\0'; - start = os_strstr(buf, ""); - if (start == NULL || end == NULL || start > end) { - os_free(buf); - return TNCCS_PROCESS_ERROR; - } - - start += 13; - while (*start == ' ') - start++; - *end = '\0'; - - pos = os_strstr(start, "BatchId="); - if (pos == NULL) { - os_free(buf); - return TNCCS_PROCESS_ERROR; - } - - pos += 8; - if (*pos == '"') - pos++; - batch_id = atoi(pos); - wpa_printf(MSG_DEBUG, "TNC: Received IF-TNCCS BatchId=%u", - batch_id); - if (batch_id != tncs->last_batchid + 1) { - wpa_printf(MSG_DEBUG, "TNC: Unexpected IF-TNCCS BatchId " - "%u (expected %u)", - batch_id, tncs->last_batchid + 1); - os_free(buf); - return TNCCS_PROCESS_ERROR; - } - tncs->last_batchid = batch_id; - - while (*pos != '\0' && *pos != '>') - pos++; - if (*pos == '\0') { - os_free(buf); - return TNCCS_PROCESS_ERROR; - } - pos++; - payload = start; - - /* - * - * 01234567 - * foo== - * - */ - - while (*start) { - char *endpos; - unsigned int type; - - pos = os_strstr(start, ""); - if (pos == NULL) - break; - start = pos + 17; - end = os_strstr(start, ""); - if (end == NULL) - break; - *end = '\0'; - endpos = end; - end += 18; - - if (tncs_get_type(start, &type) < 0) { - *endpos = '<'; - start = end; - continue; - } - wpa_printf(MSG_DEBUG, "TNC: IMC-IMV-Message Type 0x%x", type); - - decoded = tncs_get_base64(start, &decoded_len); - if (decoded == NULL) { - *endpos = '<'; - start = end; - continue; - } - - tncs_send_to_imvs(tncs, type, decoded, decoded_len); - - os_free(decoded); - - start = end; - } - - /* - * - * 01234567 - * - * foo== - * - */ - - start = payload; - while (*start) { - unsigned int type; - char *xml, *xmlend, *endpos; - - pos = os_strstr(start, ""); - if (pos == NULL) - break; - start = pos + 19; - end = os_strstr(start, ""); - if (end == NULL) - break; - *end = '\0'; - endpos = end; - end += 20; - - if (tncs_get_type(start, &type) < 0) { - *endpos = '<'; - start = end; - continue; - } - wpa_printf(MSG_DEBUG, "TNC: TNCC-TNCS-Message Type 0x%x", - type); - - /* Base64 OR XML */ - decoded = NULL; - xml = NULL; - xmlend = NULL; - pos = os_strstr(start, ""); - if (pos) { - pos += 5; - pos2 = os_strstr(pos, ""); - if (pos2 == NULL) { - *endpos = '<'; - start = end; - continue; - } - xmlend = pos2; - xml = pos; - } else { - decoded = tncs_get_base64(start, &decoded_len); - if (decoded == NULL) { - *endpos = '<'; - start = end; - continue; - } - } - - if (decoded) { - wpa_hexdump_ascii(MSG_MSGDUMP, - "TNC: TNCC-TNCS-Message Base64", - decoded, decoded_len); - os_free(decoded); - } - - if (xml) { - wpa_hexdump_ascii(MSG_MSGDUMP, - "TNC: TNCC-TNCS-Message XML", - (unsigned char *) xml, - xmlend - xml); - } - - start = end; - } - - os_free(buf); - - tncs_batch_ending(tncs); - - if (tncs_total_send_len(tncs) == 0) - return tncs_derive_recommendation(tncs); - - return TNCCS_PROCESS_OK_NO_RECOMMENDATION; -} - - -static struct tnc_if_imv * tncs_parse_imv(int id, char *start, char *end, - int *error) -{ - struct tnc_if_imv *imv; - char *pos, *pos2; - - if (id >= TNC_MAX_IMV_ID) { - wpa_printf(MSG_DEBUG, "TNC: Too many IMVs"); - return NULL; - } - - imv = os_zalloc(sizeof(*imv)); - if (imv == NULL) { - *error = 1; - return NULL; - } - - imv->imvID = id; - - pos = start; - wpa_printf(MSG_DEBUG, "TNC: Configured IMV: %s", pos); - if (pos + 1 >= end || *pos != '"') { - wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMV line '%s' " - "(no starting quotation mark)", start); - os_free(imv); - return NULL; - } - - pos++; - pos2 = pos; - while (pos2 < end && *pos2 != '"') - pos2++; - if (pos2 >= end) { - wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMV line '%s' " - "(no ending quotation mark)", start); - os_free(imv); - return NULL; - } - *pos2 = '\0'; - wpa_printf(MSG_DEBUG, "TNC: Name: '%s'", pos); - imv->name = os_strdup(pos); - - pos = pos2 + 1; - if (pos >= end || *pos != ' ') { - wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMV line '%s' " - "(no space after name)", start); - os_free(imv); - return NULL; - } - - pos++; - wpa_printf(MSG_DEBUG, "TNC: IMV file: '%s'", pos); - imv->path = os_strdup(pos); - - return imv; -} - - -static int tncs_read_config(struct tncs_global *global) -{ - char *config, *end, *pos, *line_end; - size_t config_len; - struct tnc_if_imv *imv, *last; - int id = 0; - - last = NULL; - - config = os_readfile(TNC_CONFIG_FILE, &config_len); - if (config == NULL) { - wpa_printf(MSG_ERROR, "TNC: Could not open TNC configuration " - "file '%s'", TNC_CONFIG_FILE); - return -1; - } - - end = config + config_len; - for (pos = config; pos < end; pos = line_end + 1) { - line_end = pos; - while (*line_end != '\n' && *line_end != '\r' && - line_end < end) - line_end++; - *line_end = '\0'; - - if (os_strncmp(pos, "IMV ", 4) == 0) { - int error = 0; - - imv = tncs_parse_imv(id++, pos + 4, line_end, &error); - if (error) - return -1; - if (imv) { - if (last == NULL) - global->imv = imv; - else - last->next = imv; - last = imv; - } - } - } - - os_free(config); - - return 0; -} - - -struct tncs_data * tncs_init(void) -{ - struct tncs_data *tncs; - - if (tncs_global_data == NULL) - return NULL; - - tncs = os_zalloc(sizeof(*tncs)); - if (tncs == NULL) - return NULL; - tncs->imv = tncs_global_data->imv; - tncs->connectionID = tncs_global_data->next_conn_id++; - tncs->next = tncs_global_data->connections; - tncs_global_data->connections = tncs; - - return tncs; -} - - -void tncs_deinit(struct tncs_data *tncs) -{ - int i; - struct tncs_data *prev, *conn; - - if (tncs == NULL) - return; - - for (i = 0; i < TNC_MAX_IMV_ID; i++) - os_free(tncs->imv_data[i].imv_send); - - prev = NULL; - conn = tncs_global_data->connections; - while (conn) { - if (conn == tncs) { - if (prev) - prev->next = tncs->next; - else - tncs_global_data->connections = tncs->next; - break; - } - prev = conn; - conn = conn->next; - } - - os_free(tncs->tncs_message); - os_free(tncs); -} - - -int tncs_global_init(void) -{ - struct tnc_if_imv *imv; - - tncs_global_data = os_zalloc(sizeof(*tncs_global_data)); - if (tncs_global_data == NULL) - return -1; - - if (tncs_read_config(tncs_global_data) < 0) { - wpa_printf(MSG_ERROR, "TNC: Failed to read TNC configuration"); - goto failed; - } - - for (imv = tncs_global_data->imv; imv; imv = imv->next) { - if (tncs_load_imv(imv)) { - wpa_printf(MSG_ERROR, "TNC: Failed to load IMV '%s'", - imv->name); - goto failed; - } - } - - return 0; - -failed: - tncs_global_deinit(); - return -1; -} - - -void tncs_global_deinit(void) -{ - struct tnc_if_imv *imv, *prev; - - if (tncs_global_data == NULL) - return; - - imv = tncs_global_data->imv; - while (imv) { - tncs_unload_imv(imv); - - prev = imv; - imv = imv->next; - os_free(prev); - } - - os_free(tncs_global_data); -} - - -struct wpabuf * tncs_build_soh_request(void) -{ - struct wpabuf *buf; - - /* - * Build a SoH Request TLV (to be used inside SoH EAP Extensions - * Method) - */ - - buf = wpabuf_alloc(8 + 4); - if (buf == NULL) - return NULL; - - /* Vendor-Specific TLV (Microsoft) - SoH Request */ - wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* TLV Type */ - wpabuf_put_be16(buf, 8); /* Length */ - - wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* Vendor_Id */ - - wpabuf_put_be16(buf, 0x02); /* TLV Type - SoH Request TLV */ - wpabuf_put_be16(buf, 0); /* Length */ - - return buf; -} - - -struct wpabuf * tncs_process_soh(const u8 *soh_tlv, size_t soh_tlv_len, - int *failure) -{ - wpa_hexdump(MSG_DEBUG, "TNC: SoH TLV", soh_tlv, soh_tlv_len); - *failure = 0; - - /* TODO: return MS-SoH Response TLV */ - - return NULL; -} diff --git a/contrib/hostapd/src/eap_server/tncs.h b/contrib/hostapd/src/eap_server/tncs.h deleted file mode 100644 index 18a3a1fa3c..0000000000 --- a/contrib/hostapd/src/eap_server/tncs.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * EAP-TNC - TNCS (IF-IMV, IF-TNCCS, and IF-TNCCS-SOH) - * Copyright (c) 2007-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TNCS_H -#define TNCS_H - -struct tncs_data; - -struct tncs_data * tncs_init(void); -void tncs_deinit(struct tncs_data *tncs); -void tncs_init_connection(struct tncs_data *tncs); -size_t tncs_total_send_len(struct tncs_data *tncs); -u8 * tncs_copy_send_buf(struct tncs_data *tncs, u8 *pos); -char * tncs_if_tnccs_start(struct tncs_data *tncs); -char * tncs_if_tnccs_end(void); - -enum tncs_process_res { - TNCCS_PROCESS_ERROR = -1, - TNCCS_PROCESS_OK_NO_RECOMMENDATION = 0, - TNCCS_RECOMMENDATION_ERROR, - TNCCS_RECOMMENDATION_ALLOW, - TNCCS_RECOMMENDATION_NONE, - TNCCS_RECOMMENDATION_ISOLATE, - TNCCS_RECOMMENDATION_NO_ACCESS, - TNCCS_RECOMMENDATION_NO_RECOMMENDATION -}; - -enum tncs_process_res tncs_process_if_tnccs(struct tncs_data *tncs, - const u8 *msg, size_t len); - -int tncs_global_init(void); -void tncs_global_deinit(void); - -struct wpabuf * tncs_build_soh_request(void); -struct wpabuf * tncs_process_soh(const u8 *soh_tlv, size_t soh_tlv_len, - int *failure); - -#endif /* TNCS_H */ diff --git a/contrib/hostapd/src/eapol_supp/eapol_supp_sm.c b/contrib/hostapd/src/eapol_supp/eapol_supp_sm.c deleted file mode 100644 index d163049cce..0000000000 --- a/contrib/hostapd/src/eapol_supp/eapol_supp_sm.c +++ /dev/null @@ -1,1876 +0,0 @@ -/* - * EAPOL supplicant state machines - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eapol_supp_sm.h" -#include "eap_peer/eap.h" -#include "eloop.h" -#include "eapol_common.h" -#include "md5.h" -#include "rc4.h" -#include "state_machine.h" -#include "wpabuf.h" - -#define STATE_MACHINE_DATA struct eapol_sm -#define STATE_MACHINE_DEBUG_PREFIX "EAPOL" - - -/* IEEE 802.1X-2004 - Supplicant - EAPOL state machines */ - -/** - * struct eapol_sm - Internal data for EAPOL state machines - */ -struct eapol_sm { - /* Timers */ - unsigned int authWhile; - unsigned int heldWhile; - unsigned int startWhen; - unsigned int idleWhile; /* for EAP state machine */ - int timer_tick_enabled; - - /* Global variables */ - Boolean eapFail; - Boolean eapolEap; - Boolean eapSuccess; - Boolean initialize; - Boolean keyDone; - Boolean keyRun; - PortControl portControl; - Boolean portEnabled; - PortStatus suppPortStatus; /* dot1xSuppControlledPortStatus */ - Boolean portValid; - Boolean suppAbort; - Boolean suppFail; - Boolean suppStart; - Boolean suppSuccess; - Boolean suppTimeout; - - /* Supplicant PAE state machine */ - enum { - SUPP_PAE_UNKNOWN = 0, - SUPP_PAE_DISCONNECTED = 1, - SUPP_PAE_LOGOFF = 2, - SUPP_PAE_CONNECTING = 3, - SUPP_PAE_AUTHENTICATING = 4, - SUPP_PAE_AUTHENTICATED = 5, - /* unused(6) */ - SUPP_PAE_HELD = 7, - SUPP_PAE_RESTART = 8, - SUPP_PAE_S_FORCE_AUTH = 9, - SUPP_PAE_S_FORCE_UNAUTH = 10 - } SUPP_PAE_state; /* dot1xSuppPaeState */ - /* Variables */ - Boolean userLogoff; - Boolean logoffSent; - unsigned int startCount; - Boolean eapRestart; - PortControl sPortMode; - /* Constants */ - unsigned int heldPeriod; /* dot1xSuppHeldPeriod */ - unsigned int startPeriod; /* dot1xSuppStartPeriod */ - unsigned int maxStart; /* dot1xSuppMaxStart */ - - /* Key Receive state machine */ - enum { - KEY_RX_UNKNOWN = 0, - KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE - } KEY_RX_state; - /* Variables */ - Boolean rxKey; - - /* Supplicant Backend state machine */ - enum { - SUPP_BE_UNKNOWN = 0, - SUPP_BE_INITIALIZE = 1, - SUPP_BE_IDLE = 2, - SUPP_BE_REQUEST = 3, - SUPP_BE_RECEIVE = 4, - SUPP_BE_RESPONSE = 5, - SUPP_BE_FAIL = 6, - SUPP_BE_TIMEOUT = 7, - SUPP_BE_SUCCESS = 8 - } SUPP_BE_state; /* dot1xSuppBackendPaeState */ - /* Variables */ - Boolean eapNoResp; - Boolean eapReq; - Boolean eapResp; - /* Constants */ - unsigned int authPeriod; /* dot1xSuppAuthPeriod */ - - /* Statistics */ - unsigned int dot1xSuppEapolFramesRx; - unsigned int dot1xSuppEapolFramesTx; - unsigned int dot1xSuppEapolStartFramesTx; - unsigned int dot1xSuppEapolLogoffFramesTx; - unsigned int dot1xSuppEapolRespFramesTx; - unsigned int dot1xSuppEapolReqIdFramesRx; - unsigned int dot1xSuppEapolReqFramesRx; - unsigned int dot1xSuppInvalidEapolFramesRx; - unsigned int dot1xSuppEapLengthErrorFramesRx; - unsigned int dot1xSuppLastEapolFrameVersion; - unsigned char dot1xSuppLastEapolFrameSource[6]; - - /* Miscellaneous variables (not defined in IEEE 802.1X-2004) */ - Boolean changed; - struct eap_sm *eap; - struct eap_peer_config *config; - Boolean initial_req; - u8 *last_rx_key; - size_t last_rx_key_len; - struct wpabuf *eapReqData; /* for EAP */ - Boolean altAccept; /* for EAP */ - Boolean altReject; /* for EAP */ - Boolean replay_counter_valid; - u8 last_replay_counter[16]; - struct eapol_config conf; - struct eapol_ctx *ctx; - enum { EAPOL_CB_IN_PROGRESS = 0, EAPOL_CB_SUCCESS, EAPOL_CB_FAILURE } - cb_status; - Boolean cached_pmk; - - Boolean unicast_key_received, broadcast_key_received; -}; - - -#define IEEE8021X_REPLAY_COUNTER_LEN 8 -#define IEEE8021X_KEY_SIGN_LEN 16 -#define IEEE8021X_KEY_IV_LEN 16 - -#define IEEE8021X_KEY_INDEX_FLAG 0x80 -#define IEEE8021X_KEY_INDEX_MASK 0x03 - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct ieee802_1x_eapol_key { - u8 type; - /* Note: key_length is unaligned */ - u8 key_length[2]; - /* does not repeat within the life of the keying material used to - * encrypt the Key field; 64-bit NTP timestamp MAY be used here */ - u8 replay_counter[IEEE8021X_REPLAY_COUNTER_LEN]; - u8 key_iv[IEEE8021X_KEY_IV_LEN]; /* cryptographically random number */ - u8 key_index; /* key flag in the most significant bit: - * 0 = broadcast (default key), - * 1 = unicast (key mapping key); key index is in the - * 7 least significant bits */ - /* HMAC-MD5 message integrity check computed with MS-MPPE-Send-Key as - * the key */ - u8 key_signature[IEEE8021X_KEY_SIGN_LEN]; - - /* followed by key: if packet body length = 44 + key length, then the - * key field (of key_length bytes) contains the key in encrypted form; - * if packet body length = 44, key field is absent and key_length - * represents the number of least significant octets from - * MS-MPPE-Send-Key attribute to be used as the keying material; - * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */ -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -static void eapol_sm_txLogoff(struct eapol_sm *sm); -static void eapol_sm_txStart(struct eapol_sm *sm); -static void eapol_sm_processKey(struct eapol_sm *sm); -static void eapol_sm_getSuppRsp(struct eapol_sm *sm); -static void eapol_sm_txSuppRsp(struct eapol_sm *sm); -static void eapol_sm_abortSupp(struct eapol_sm *sm); -static void eapol_sm_abort_cached(struct eapol_sm *sm); -static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx); - - -/* Port Timers state machine - implemented as a function that will be called - * once a second as a registered event loop timeout */ -static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx) -{ - struct eapol_sm *sm = timeout_ctx; - - if (sm->authWhile > 0) { - sm->authWhile--; - if (sm->authWhile == 0) - wpa_printf(MSG_DEBUG, "EAPOL: authWhile --> 0"); - } - if (sm->heldWhile > 0) { - sm->heldWhile--; - if (sm->heldWhile == 0) - wpa_printf(MSG_DEBUG, "EAPOL: heldWhile --> 0"); - } - if (sm->startWhen > 0) { - sm->startWhen--; - if (sm->startWhen == 0) - wpa_printf(MSG_DEBUG, "EAPOL: startWhen --> 0"); - } - if (sm->idleWhile > 0) { - sm->idleWhile--; - if (sm->idleWhile == 0) - wpa_printf(MSG_DEBUG, "EAPOL: idleWhile --> 0"); - } - - if (sm->authWhile | sm->heldWhile | sm->startWhen | sm->idleWhile) { - eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, - sm); - } else { - wpa_printf(MSG_DEBUG, "EAPOL: disable timer tick"); - sm->timer_tick_enabled = 0; - } - eapol_sm_step(sm); -} - - -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); -} - - -SM_STATE(SUPP_PAE, LOGOFF) -{ - SM_ENTRY(SUPP_PAE, LOGOFF); - eapol_sm_txLogoff(sm); - sm->logoffSent = TRUE; - sm->suppPortStatus = Unauthorized; -} - - -SM_STATE(SUPP_PAE, DISCONNECTED) -{ - SM_ENTRY(SUPP_PAE, DISCONNECTED); - sm->sPortMode = Auto; - sm->startCount = 0; - sm->logoffSent = FALSE; - sm->suppPortStatus = Unauthorized; - sm->suppAbort = TRUE; - - sm->unicast_key_received = FALSE; - sm->broadcast_key_received = FALSE; -} - - -SM_STATE(SUPP_PAE, CONNECTING) -{ - int send_start = sm->SUPP_PAE_state == SUPP_PAE_CONNECTING; - SM_ENTRY(SUPP_PAE, CONNECTING); - if (send_start) { - sm->startWhen = sm->startPeriod; - sm->startCount++; - } else { - /* - * Do not send EAPOL-Start immediately since in most cases, - * Authenticator is going to start authentication immediately - * after association and an extra EAPOL-Start is just going to - * delay authentication. Use a short timeout to send the first - * EAPOL-Start if Authenticator does not start authentication. - */ -#ifdef CONFIG_WPS - /* Reduce latency on starting WPS negotiation. */ - sm->startWhen = 1; -#else /* CONFIG_WPS */ - sm->startWhen = 3; -#endif /* CONFIG_WPS */ - } - eapol_enable_timer_tick(sm); - sm->eapolEap = FALSE; - if (send_start) - eapol_sm_txStart(sm); -} - - -SM_STATE(SUPP_PAE, AUTHENTICATING) -{ - SM_ENTRY(SUPP_PAE, AUTHENTICATING); - sm->startCount = 0; - sm->suppSuccess = FALSE; - sm->suppFail = FALSE; - sm->suppTimeout = FALSE; - sm->keyRun = FALSE; - sm->keyDone = FALSE; - sm->suppStart = TRUE; -} - - -SM_STATE(SUPP_PAE, HELD) -{ - SM_ENTRY(SUPP_PAE, HELD); - sm->heldWhile = sm->heldPeriod; - eapol_enable_timer_tick(sm); - sm->suppPortStatus = Unauthorized; - sm->cb_status = EAPOL_CB_FAILURE; -} - - -SM_STATE(SUPP_PAE, AUTHENTICATED) -{ - SM_ENTRY(SUPP_PAE, AUTHENTICATED); - sm->suppPortStatus = Authorized; - sm->cb_status = EAPOL_CB_SUCCESS; -} - - -SM_STATE(SUPP_PAE, RESTART) -{ - SM_ENTRY(SUPP_PAE, RESTART); - sm->eapRestart = TRUE; -} - - -SM_STATE(SUPP_PAE, S_FORCE_AUTH) -{ - SM_ENTRY(SUPP_PAE, S_FORCE_AUTH); - sm->suppPortStatus = Authorized; - sm->sPortMode = ForceAuthorized; -} - - -SM_STATE(SUPP_PAE, S_FORCE_UNAUTH) -{ - SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH); - sm->suppPortStatus = Unauthorized; - sm->sPortMode = ForceUnauthorized; - eapol_sm_txLogoff(sm); -} - - -SM_STEP(SUPP_PAE) -{ - if ((sm->userLogoff && !sm->logoffSent) && - !(sm->initialize || !sm->portEnabled)) - SM_ENTER_GLOBAL(SUPP_PAE, LOGOFF); - else if (((sm->portControl == Auto) && - (sm->sPortMode != sm->portControl)) || - sm->initialize || !sm->portEnabled) - SM_ENTER_GLOBAL(SUPP_PAE, DISCONNECTED); - else if ((sm->portControl == ForceAuthorized) && - (sm->sPortMode != sm->portControl) && - !(sm->initialize || !sm->portEnabled)) - SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_AUTH); - else if ((sm->portControl == ForceUnauthorized) && - (sm->sPortMode != sm->portControl) && - !(sm->initialize || !sm->portEnabled)) - SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_UNAUTH); - else switch (sm->SUPP_PAE_state) { - case SUPP_PAE_UNKNOWN: - break; - case SUPP_PAE_LOGOFF: - if (!sm->userLogoff) - SM_ENTER(SUPP_PAE, DISCONNECTED); - break; - case SUPP_PAE_DISCONNECTED: - SM_ENTER(SUPP_PAE, CONNECTING); - break; - case SUPP_PAE_CONNECTING: - if (sm->startWhen == 0 && sm->startCount < sm->maxStart) - SM_ENTER(SUPP_PAE, CONNECTING); - else if (sm->startWhen == 0 && - sm->startCount >= sm->maxStart && - sm->portValid) - SM_ENTER(SUPP_PAE, AUTHENTICATED); - else if (sm->eapSuccess || sm->eapFail) - SM_ENTER(SUPP_PAE, AUTHENTICATING); - else if (sm->eapolEap) - SM_ENTER(SUPP_PAE, RESTART); - else if (sm->startWhen == 0 && - sm->startCount >= sm->maxStart && - !sm->portValid) - SM_ENTER(SUPP_PAE, HELD); - break; - case SUPP_PAE_AUTHENTICATING: - if (sm->eapSuccess && !sm->portValid && - sm->conf.accept_802_1x_keys && - sm->conf.required_keys == 0) { - wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for " - "plaintext connection; no EAPOL-Key frames " - "required"); - sm->portValid = TRUE; - if (sm->ctx->eapol_done_cb) - sm->ctx->eapol_done_cb(sm->ctx->ctx); - } - if (sm->eapSuccess && sm->portValid) - SM_ENTER(SUPP_PAE, AUTHENTICATED); - else if (sm->eapFail || (sm->keyDone && !sm->portValid)) - SM_ENTER(SUPP_PAE, HELD); - else if (sm->suppTimeout) - SM_ENTER(SUPP_PAE, CONNECTING); - break; - case SUPP_PAE_HELD: - if (sm->heldWhile == 0) - SM_ENTER(SUPP_PAE, CONNECTING); - else if (sm->eapolEap) - SM_ENTER(SUPP_PAE, RESTART); - break; - case SUPP_PAE_AUTHENTICATED: - if (sm->eapolEap && sm->portValid) - SM_ENTER(SUPP_PAE, RESTART); - else if (!sm->portValid) - SM_ENTER(SUPP_PAE, DISCONNECTED); - break; - case SUPP_PAE_RESTART: - if (!sm->eapRestart) - SM_ENTER(SUPP_PAE, AUTHENTICATING); - break; - case SUPP_PAE_S_FORCE_AUTH: - break; - case SUPP_PAE_S_FORCE_UNAUTH: - break; - } -} - - -SM_STATE(KEY_RX, NO_KEY_RECEIVE) -{ - SM_ENTRY(KEY_RX, NO_KEY_RECEIVE); -} - - -SM_STATE(KEY_RX, KEY_RECEIVE) -{ - SM_ENTRY(KEY_RX, KEY_RECEIVE); - eapol_sm_processKey(sm); - sm->rxKey = FALSE; -} - - -SM_STEP(KEY_RX) -{ - if (sm->initialize || !sm->portEnabled) - SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE); - switch (sm->KEY_RX_state) { - case KEY_RX_UNKNOWN: - break; - case KEY_RX_NO_KEY_RECEIVE: - if (sm->rxKey) - SM_ENTER(KEY_RX, KEY_RECEIVE); - break; - case KEY_RX_KEY_RECEIVE: - if (sm->rxKey) - SM_ENTER(KEY_RX, KEY_RECEIVE); - break; - } -} - - -SM_STATE(SUPP_BE, REQUEST) -{ - SM_ENTRY(SUPP_BE, REQUEST); - sm->authWhile = 0; - sm->eapReq = TRUE; - eapol_sm_getSuppRsp(sm); -} - - -SM_STATE(SUPP_BE, RESPONSE) -{ - SM_ENTRY(SUPP_BE, RESPONSE); - eapol_sm_txSuppRsp(sm); - sm->eapResp = FALSE; -} - - -SM_STATE(SUPP_BE, SUCCESS) -{ - SM_ENTRY(SUPP_BE, SUCCESS); - sm->keyRun = TRUE; - sm->suppSuccess = TRUE; - - if (eap_key_available(sm->eap)) { - /* New key received - clear IEEE 802.1X EAPOL-Key replay - * counter */ - sm->replay_counter_valid = FALSE; - } -} - - -SM_STATE(SUPP_BE, FAIL) -{ - SM_ENTRY(SUPP_BE, FAIL); - sm->suppFail = TRUE; -} - - -SM_STATE(SUPP_BE, TIMEOUT) -{ - SM_ENTRY(SUPP_BE, TIMEOUT); - sm->suppTimeout = TRUE; -} - - -SM_STATE(SUPP_BE, IDLE) -{ - SM_ENTRY(SUPP_BE, IDLE); - sm->suppStart = FALSE; - sm->initial_req = TRUE; -} - - -SM_STATE(SUPP_BE, INITIALIZE) -{ - SM_ENTRY(SUPP_BE, INITIALIZE); - eapol_sm_abortSupp(sm); - sm->suppAbort = FALSE; -} - - -SM_STATE(SUPP_BE, RECEIVE) -{ - SM_ENTRY(SUPP_BE, RECEIVE); - sm->authWhile = sm->authPeriod; - eapol_enable_timer_tick(sm); - sm->eapolEap = FALSE; - sm->eapNoResp = FALSE; - sm->initial_req = FALSE; -} - - -SM_STEP(SUPP_BE) -{ - if (sm->initialize || sm->suppAbort) - SM_ENTER_GLOBAL(SUPP_BE, INITIALIZE); - else switch (sm->SUPP_BE_state) { - case SUPP_BE_UNKNOWN: - break; - case SUPP_BE_REQUEST: - /* - * IEEE Std 802.1X-2004 has transitions from REQUEST to FAIL - * and SUCCESS based on eapFail and eapSuccess, respectively. - * However, IEEE Std 802.1X-2004 is also specifying that - * eapNoResp should be set in conjuction with eapSuccess and - * eapFail which would mean that more than one of the - * transitions here would be activated at the same time. - * Skipping RESPONSE and/or RECEIVE states in these cases can - * cause problems and the direct transitions to do not seem - * correct. Because of this, the conditions for these - * transitions are verified only after eapNoResp. They are - * unlikely to be used since eapNoResp should always be set if - * either of eapSuccess or eapFail is set. - */ - if (sm->eapResp && sm->eapNoResp) { - wpa_printf(MSG_DEBUG, "EAPOL: SUPP_BE REQUEST: both " - "eapResp and eapNoResp set?!"); - } - if (sm->eapResp) - SM_ENTER(SUPP_BE, RESPONSE); - else if (sm->eapNoResp) - SM_ENTER(SUPP_BE, RECEIVE); - else if (sm->eapFail) - SM_ENTER(SUPP_BE, FAIL); - else if (sm->eapSuccess) - SM_ENTER(SUPP_BE, SUCCESS); - break; - case SUPP_BE_RESPONSE: - SM_ENTER(SUPP_BE, RECEIVE); - break; - case SUPP_BE_SUCCESS: - SM_ENTER(SUPP_BE, IDLE); - break; - case SUPP_BE_FAIL: - SM_ENTER(SUPP_BE, IDLE); - break; - case SUPP_BE_TIMEOUT: - SM_ENTER(SUPP_BE, IDLE); - break; - case SUPP_BE_IDLE: - if (sm->eapFail && sm->suppStart) - SM_ENTER(SUPP_BE, FAIL); - else if (sm->eapolEap && sm->suppStart) - SM_ENTER(SUPP_BE, REQUEST); - else if (sm->eapSuccess && sm->suppStart) - SM_ENTER(SUPP_BE, SUCCESS); - break; - case SUPP_BE_INITIALIZE: - SM_ENTER(SUPP_BE, IDLE); - break; - case SUPP_BE_RECEIVE: - if (sm->eapolEap) - SM_ENTER(SUPP_BE, REQUEST); - else if (sm->eapFail) - SM_ENTER(SUPP_BE, FAIL); - else if (sm->authWhile == 0) - SM_ENTER(SUPP_BE, TIMEOUT); - else if (sm->eapSuccess) - SM_ENTER(SUPP_BE, SUCCESS); - break; - } -} - - -static void eapol_sm_txLogoff(struct eapol_sm *sm) -{ - wpa_printf(MSG_DEBUG, "EAPOL: txLogoff"); - sm->ctx->eapol_send(sm->ctx->eapol_send_ctx, - IEEE802_1X_TYPE_EAPOL_LOGOFF, (u8 *) "", 0); - sm->dot1xSuppEapolLogoffFramesTx++; - sm->dot1xSuppEapolFramesTx++; -} - - -static void eapol_sm_txStart(struct eapol_sm *sm) -{ - wpa_printf(MSG_DEBUG, "EAPOL: txStart"); - sm->ctx->eapol_send(sm->ctx->eapol_send_ctx, - IEEE802_1X_TYPE_EAPOL_START, (u8 *) "", 0); - sm->dot1xSuppEapolStartFramesTx++; - sm->dot1xSuppEapolFramesTx++; -} - - -#define IEEE8021X_ENCR_KEY_LEN 32 -#define IEEE8021X_SIGN_KEY_LEN 32 - -struct eap_key_data { - u8 encr_key[IEEE8021X_ENCR_KEY_LEN]; - u8 sign_key[IEEE8021X_SIGN_KEY_LEN]; -}; - - -static void eapol_sm_processKey(struct eapol_sm *sm) -{ - struct ieee802_1x_hdr *hdr; - struct ieee802_1x_eapol_key *key; - struct eap_key_data keydata; - u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32]; - u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN]; - int key_len, res, sign_key_len, encr_key_len; - u16 rx_key_length; - - wpa_printf(MSG_DEBUG, "EAPOL: processKey"); - if (sm->last_rx_key == NULL) - return; - - if (!sm->conf.accept_802_1x_keys) { - wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key" - " even though this was not accepted - " - "ignoring this packet"); - return; - } - - hdr = (struct ieee802_1x_hdr *) sm->last_rx_key; - key = (struct ieee802_1x_eapol_key *) (hdr + 1); - if (sizeof(*hdr) + be_to_host16(hdr->length) > sm->last_rx_key_len) { - wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame"); - return; - } - rx_key_length = WPA_GET_BE16(key->key_length); - wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d " - "EAPOL-Key: type=%d key_length=%d key_index=0x%x", - hdr->version, hdr->type, be_to_host16(hdr->length), - key->type, rx_key_length, key->key_index); - - eapol_sm_notify_lower_layer_success(sm, 1); - sign_key_len = IEEE8021X_SIGN_KEY_LEN; - encr_key_len = IEEE8021X_ENCR_KEY_LEN; - res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata)); - if (res < 0) { - wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for " - "decrypting EAPOL-Key keys"); - return; - } - if (res == 16) { - /* LEAP derives only 16 bytes of keying material. */ - res = eapol_sm_get_key(sm, (u8 *) &keydata, 16); - if (res) { - wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP " - "master key for decrypting EAPOL-Key keys"); - return; - } - sign_key_len = 16; - encr_key_len = 16; - os_memcpy(keydata.sign_key, keydata.encr_key, 16); - } else if (res) { - wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key " - "data for decrypting EAPOL-Key keys (res=%d)", res); - return; - } - - /* The key replay_counter must increase when same master key */ - if (sm->replay_counter_valid && - os_memcmp(sm->last_replay_counter, key->replay_counter, - IEEE8021X_REPLAY_COUNTER_LEN) >= 0) { - wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did " - "not increase - ignoring key"); - wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter", - sm->last_replay_counter, - IEEE8021X_REPLAY_COUNTER_LEN); - wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter", - key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN); - return; - } - - /* Verify key signature (HMAC-MD5) */ - os_memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN); - os_memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN); - hmac_md5(keydata.sign_key, sign_key_len, - sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length), - key->key_signature); - if (os_memcmp(orig_key_sign, key->key_signature, - IEEE8021X_KEY_SIGN_LEN) != 0) { - wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in " - "EAPOL-Key packet"); - os_memcpy(key->key_signature, orig_key_sign, - IEEE8021X_KEY_SIGN_LEN); - return; - } - wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified"); - - key_len = be_to_host16(hdr->length) - sizeof(*key); - if (key_len > 32 || rx_key_length > 32) { - wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d", - key_len ? key_len : rx_key_length); - return; - } - if (key_len == rx_key_length) { - os_memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN); - os_memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key, - encr_key_len); - os_memcpy(datakey, key + 1, key_len); - rc4_skip(ekey, IEEE8021X_KEY_IV_LEN + encr_key_len, 0, - datakey, key_len); - wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key", - datakey, key_len); - } else if (key_len == 0) { - /* - * IEEE 802.1X-2004 specifies that least significant Key Length - * octets from MS-MPPE-Send-Key are used as the key if the key - * data is not present. This seems to be meaning the beginning - * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in - * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator. - * Anyway, taking the beginning of the keying material from EAP - * seems to interoperate with Authenticators. - */ - key_len = rx_key_length; - os_memcpy(datakey, keydata.encr_key, key_len); - wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying " - "material data encryption key", - datakey, key_len); - } else { - wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d " - "(key_length=%d)", key_len, rx_key_length); - return; - } - - sm->replay_counter_valid = TRUE; - os_memcpy(sm->last_replay_counter, key->replay_counter, - IEEE8021X_REPLAY_COUNTER_LEN); - - wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d " - "len %d", - key->key_index & IEEE8021X_KEY_INDEX_FLAG ? - "unicast" : "broadcast", - key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len); - - if (sm->ctx->set_wep_key && - sm->ctx->set_wep_key(sm->ctx->ctx, - key->key_index & IEEE8021X_KEY_INDEX_FLAG, - key->key_index & IEEE8021X_KEY_INDEX_MASK, - datakey, key_len) < 0) { - wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the " - " driver."); - } else { - if (key->key_index & IEEE8021X_KEY_INDEX_FLAG) - sm->unicast_key_received = TRUE; - else - sm->broadcast_key_received = TRUE; - - if ((sm->unicast_key_received || - !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) && - (sm->broadcast_key_received || - !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST))) - { - wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key " - "frames received"); - sm->portValid = TRUE; - if (sm->ctx->eapol_done_cb) - sm->ctx->eapol_done_cb(sm->ctx->ctx); - } - } -} - - -static void eapol_sm_getSuppRsp(struct eapol_sm *sm) -{ - wpa_printf(MSG_DEBUG, "EAPOL: getSuppRsp"); - /* EAP layer processing; no special code is needed, since Supplicant - * Backend state machine is waiting for eapNoResp or eapResp to be set - * and these are only set in the EAP state machine when the processing - * has finished. */ -} - - -static void eapol_sm_txSuppRsp(struct eapol_sm *sm) -{ - struct wpabuf *resp; - - wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp"); - resp = eap_get_eapRespData(sm->eap); - if (resp == NULL) { - wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP response data " - "not available"); - return; - } - - /* Send EAP-Packet from the EAP layer to the Authenticator */ - sm->ctx->eapol_send(sm->ctx->eapol_send_ctx, - IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(resp), - wpabuf_len(resp)); - - /* eapRespData is not used anymore, so free it here */ - wpabuf_free(resp); - - if (sm->initial_req) - sm->dot1xSuppEapolReqIdFramesRx++; - else - sm->dot1xSuppEapolReqFramesRx++; - sm->dot1xSuppEapolRespFramesTx++; - sm->dot1xSuppEapolFramesTx++; -} - - -static void eapol_sm_abortSupp(struct eapol_sm *sm) -{ - /* release system resources that may have been allocated for the - * authentication session */ - os_free(sm->last_rx_key); - sm->last_rx_key = NULL; - wpabuf_free(sm->eapReqData); - sm->eapReqData = NULL; - eap_sm_abort(sm->eap); -} - - -static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx) -{ - eapol_sm_step(timeout_ctx); -} - - -/** - * eapol_sm_step - EAPOL state machine step function - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * - * This function is called to notify the state machine about changed external - * variables. It will step through the EAPOL state machines in loop to process - * all triggered state changes. - */ -void eapol_sm_step(struct eapol_sm *sm) -{ - int i; - - /* In theory, it should be ok to run this in loop until !changed. - * However, it is better to use a limit on number of iterations to - * allow events (e.g., SIGTERM) to stop the program cleanly if the - * state machine were to generate a busy loop. */ - for (i = 0; i < 100; i++) { - sm->changed = FALSE; - SM_STEP_RUN(SUPP_PAE); - SM_STEP_RUN(KEY_RX); - SM_STEP_RUN(SUPP_BE); - if (eap_peer_sm_step(sm->eap)) - sm->changed = TRUE; - if (!sm->changed) - break; - } - - if (sm->changed) { - /* restart EAPOL state machine step from timeout call in order - * to allow other events to be processed. */ - eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm); - eloop_register_timeout(0, 0, eapol_sm_step_timeout, NULL, sm); - } - - if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) { - int success = sm->cb_status == EAPOL_CB_SUCCESS ? 1 : 0; - sm->cb_status = EAPOL_CB_IN_PROGRESS; - sm->ctx->cb(sm, success, sm->ctx->cb_ctx); - } -} - - -#ifdef CONFIG_CTRL_IFACE -static const char *eapol_supp_pae_state(int state) -{ - switch (state) { - case SUPP_PAE_LOGOFF: - return "LOGOFF"; - case SUPP_PAE_DISCONNECTED: - return "DISCONNECTED"; - case SUPP_PAE_CONNECTING: - return "CONNECTING"; - case SUPP_PAE_AUTHENTICATING: - return "AUTHENTICATING"; - case SUPP_PAE_HELD: - return "HELD"; - case SUPP_PAE_AUTHENTICATED: - return "AUTHENTICATED"; - case SUPP_PAE_RESTART: - return "RESTART"; - default: - return "UNKNOWN"; - } -} - - -static const char *eapol_supp_be_state(int state) -{ - switch (state) { - case SUPP_BE_REQUEST: - return "REQUEST"; - case SUPP_BE_RESPONSE: - return "RESPONSE"; - case SUPP_BE_SUCCESS: - return "SUCCESS"; - case SUPP_BE_FAIL: - return "FAIL"; - case SUPP_BE_TIMEOUT: - return "TIMEOUT"; - case SUPP_BE_IDLE: - return "IDLE"; - case SUPP_BE_INITIALIZE: - return "INITIALIZE"; - case SUPP_BE_RECEIVE: - return "RECEIVE"; - default: - return "UNKNOWN"; - } -} - - -static const char * eapol_port_status(PortStatus status) -{ - if (status == Authorized) - return "Authorized"; - else - return "Unauthorized"; -} -#endif /* CONFIG_CTRL_IFACE */ - - -#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) -static const char * eapol_port_control(PortControl ctrl) -{ - switch (ctrl) { - case Auto: - return "Auto"; - case ForceUnauthorized: - return "ForceUnauthorized"; - case ForceAuthorized: - return "ForceAuthorized"; - default: - return "Unknown"; - } -} -#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ - - -/** - * eapol_sm_configure - Set EAPOL variables - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @heldPeriod: dot1xSuppHeldPeriod - * @authPeriod: dot1xSuppAuthPeriod - * @startPeriod: dot1xSuppStartPeriod - * @maxStart: dot1xSuppMaxStart - * - * Set configurable EAPOL state machine variables. Each variable can be set to - * the given value or ignored if set to -1 (to set only some of the variables). - */ -void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod, - int startPeriod, int maxStart) -{ - if (sm == NULL) - return; - if (heldPeriod >= 0) - sm->heldPeriod = heldPeriod; - if (authPeriod >= 0) - sm->authPeriod = authPeriod; - if (startPeriod >= 0) - sm->startPeriod = startPeriod; - if (maxStart >= 0) - sm->maxStart = maxStart; -} - - -#ifdef CONFIG_CTRL_IFACE -/** - * eapol_sm_get_status - Get EAPOL state machine status - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @buf: Buffer for status information - * @buflen: Maximum buffer length - * @verbose: Whether to include verbose status information - * Returns: Number of bytes written to buf. - * - * Query EAPOL state machine for status information. This function fills in a - * text area with current status information from the EAPOL state machine. If - * the buffer (buf) is not large enough, status information will be truncated - * to fit the buffer. - */ -int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen, - int verbose) -{ - int len, ret; - if (sm == NULL) - return 0; - - len = os_snprintf(buf, buflen, - "Supplicant PAE state=%s\n" - "suppPortStatus=%s\n", - eapol_supp_pae_state(sm->SUPP_PAE_state), - eapol_port_status(sm->suppPortStatus)); - if (len < 0 || (size_t) len >= buflen) - return 0; - - if (verbose) { - ret = os_snprintf(buf + len, buflen - len, - "heldPeriod=%u\n" - "authPeriod=%u\n" - "startPeriod=%u\n" - "maxStart=%u\n" - "portControl=%s\n" - "Supplicant Backend state=%s\n", - sm->heldPeriod, - sm->authPeriod, - sm->startPeriod, - sm->maxStart, - eapol_port_control(sm->portControl), - eapol_supp_be_state(sm->SUPP_BE_state)); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - } - - len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose); - - return len; -} - - -/** - * eapol_sm_get_mib - Get EAPOL state machine MIBs - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @buf: Buffer for MIB information - * @buflen: Maximum buffer length - * Returns: Number of bytes written to buf. - * - * Query EAPOL state machine for MIB information. This function fills in a - * text area with current MIB information from the EAPOL state machine. If - * the buffer (buf) is not large enough, MIB information will be truncated to - * fit the buffer. - */ -int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen) -{ - size_t len; - int ret; - - if (sm == NULL) - return 0; - ret = os_snprintf(buf, buflen, - "dot1xSuppPaeState=%d\n" - "dot1xSuppHeldPeriod=%u\n" - "dot1xSuppAuthPeriod=%u\n" - "dot1xSuppStartPeriod=%u\n" - "dot1xSuppMaxStart=%u\n" - "dot1xSuppSuppControlledPortStatus=%s\n" - "dot1xSuppBackendPaeState=%d\n", - sm->SUPP_PAE_state, - sm->heldPeriod, - sm->authPeriod, - sm->startPeriod, - sm->maxStart, - sm->suppPortStatus == Authorized ? - "Authorized" : "Unauthorized", - sm->SUPP_BE_state); - - if (ret < 0 || (size_t) ret >= buflen) - return 0; - len = ret; - - ret = os_snprintf(buf + len, buflen - len, - "dot1xSuppEapolFramesRx=%u\n" - "dot1xSuppEapolFramesTx=%u\n" - "dot1xSuppEapolStartFramesTx=%u\n" - "dot1xSuppEapolLogoffFramesTx=%u\n" - "dot1xSuppEapolRespFramesTx=%u\n" - "dot1xSuppEapolReqIdFramesRx=%u\n" - "dot1xSuppEapolReqFramesRx=%u\n" - "dot1xSuppInvalidEapolFramesRx=%u\n" - "dot1xSuppEapLengthErrorFramesRx=%u\n" - "dot1xSuppLastEapolFrameVersion=%u\n" - "dot1xSuppLastEapolFrameSource=" MACSTR "\n", - sm->dot1xSuppEapolFramesRx, - sm->dot1xSuppEapolFramesTx, - sm->dot1xSuppEapolStartFramesTx, - sm->dot1xSuppEapolLogoffFramesTx, - sm->dot1xSuppEapolRespFramesTx, - sm->dot1xSuppEapolReqIdFramesRx, - sm->dot1xSuppEapolReqFramesRx, - sm->dot1xSuppInvalidEapolFramesRx, - sm->dot1xSuppEapLengthErrorFramesRx, - sm->dot1xSuppLastEapolFrameVersion, - MAC2STR(sm->dot1xSuppLastEapolFrameSource)); - - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - return len; -} -#endif /* CONFIG_CTRL_IFACE */ - - -/** - * eapol_sm_rx_eapol - Process received EAPOL frames - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @src: Source MAC address of the EAPOL packet - * @buf: Pointer to the beginning of the EAPOL data (EAPOL header) - * @len: Length of the EAPOL frame - * Returns: 1 = EAPOL frame processed, 0 = not for EAPOL state machine, - * -1 failure - */ -int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf, - size_t len) -{ - const struct ieee802_1x_hdr *hdr; - const struct ieee802_1x_eapol_key *key; - int data_len; - int res = 1; - size_t plen; - - if (sm == NULL) - return 0; - sm->dot1xSuppEapolFramesRx++; - if (len < sizeof(*hdr)) { - sm->dot1xSuppInvalidEapolFramesRx++; - return 0; - } - hdr = (const struct ieee802_1x_hdr *) buf; - sm->dot1xSuppLastEapolFrameVersion = hdr->version; - os_memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN); - if (hdr->version < EAPOL_VERSION) { - /* TODO: backwards compatibility */ - } - plen = be_to_host16(hdr->length); - if (plen > len - sizeof(*hdr)) { - sm->dot1xSuppEapLengthErrorFramesRx++; - return 0; - } -#ifdef CONFIG_WPS - if (sm->conf.workaround && - plen < len - sizeof(*hdr) && - hdr->type == IEEE802_1X_TYPE_EAP_PACKET && - len - sizeof(*hdr) > sizeof(struct eap_hdr)) { - const struct eap_hdr *ehdr = - (const struct eap_hdr *) (hdr + 1); - u16 elen; - - elen = be_to_host16(ehdr->length); - if (elen > plen && elen <= len - sizeof(*hdr)) { - /* - * Buffalo WHR-G125 Ver.1.47 seems to send EAP-WPS - * packets with too short EAPOL header length field - * (14 octets). This is fixed in firmware Ver.1.49. - * As a workaround, fix the EAPOL header based on the - * correct length in the EAP packet. - */ - wpa_printf(MSG_DEBUG, "EAPOL: Workaround - fix EAPOL " - "payload length based on EAP header: " - "%d -> %d", (int) plen, elen); - plen = elen; - } - } -#endif /* CONFIG_WPS */ - data_len = plen + sizeof(*hdr); - - switch (hdr->type) { - case IEEE802_1X_TYPE_EAP_PACKET: - if (sm->cached_pmk) { - /* Trying to use PMKSA caching, but Authenticator did - * not seem to have a matching entry. Need to restart - * EAPOL state machines. - */ - eapol_sm_abort_cached(sm); - } - wpabuf_free(sm->eapReqData); - sm->eapReqData = wpabuf_alloc_copy(hdr + 1, plen); - if (sm->eapReqData) { - wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet " - "frame"); - sm->eapolEap = TRUE; - eapol_sm_step(sm); - } - break; - case IEEE802_1X_TYPE_EAPOL_KEY: - if (plen < sizeof(*key)) { - wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key " - "frame received"); - break; - } - key = (const struct ieee802_1x_eapol_key *) (hdr + 1); - if (key->type == EAPOL_KEY_TYPE_WPA || - key->type == EAPOL_KEY_TYPE_RSN) { - /* WPA Supplicant takes care of this frame. */ - wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key " - "frame in EAPOL state machines"); - res = 0; - break; - } - if (key->type != EAPOL_KEY_TYPE_RC4) { - wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown " - "EAPOL-Key type %d", key->type); - break; - } - os_free(sm->last_rx_key); - sm->last_rx_key = os_malloc(data_len); - if (sm->last_rx_key) { - wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key " - "frame"); - os_memcpy(sm->last_rx_key, buf, data_len); - sm->last_rx_key_len = data_len; - sm->rxKey = TRUE; - eapol_sm_step(sm); - } - break; - default: - wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d", - hdr->type); - sm->dot1xSuppInvalidEapolFramesRx++; - break; - } - - return res; -} - - -/** - * eapol_sm_notify_tx_eapol_key - Notification about transmitted EAPOL packet - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * - * Notify EAPOL state machine about transmitted EAPOL packet from an external - * component, e.g., WPA. This will update the statistics. - */ -void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm) -{ - if (sm) - sm->dot1xSuppEapolFramesTx++; -} - - -/** - * eapol_sm_notify_portEnabled - Notification about portEnabled change - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @enabled: New portEnabled value - * - * Notify EAPOL state machine about new portEnabled value. - */ -void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAPOL: External notification - " - "portEnabled=%d", enabled); - sm->portEnabled = enabled; - eapol_sm_step(sm); -} - - -/** - * eapol_sm_notify_portValid - Notification about portValid change - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @valid: New portValid value - * - * Notify EAPOL state machine about new portValid value. - */ -void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAPOL: External notification - " - "portValid=%d", valid); - sm->portValid = valid; - eapol_sm_step(sm); -} - - -/** - * eapol_sm_notify_eap_success - Notification of external EAP success trigger - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @success: %TRUE = set success, %FALSE = clear success - * - * Notify the EAPOL state machine that external event has forced EAP state to - * success (success = %TRUE). This can be cleared by setting success = %FALSE. - * - * This function is called to update EAP state when WPA-PSK key handshake has - * been completed successfully since WPA-PSK does not use EAP state machine. - */ -void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAPOL: External notification - " - "EAP success=%d", success); - sm->eapSuccess = success; - sm->altAccept = success; - if (success) - eap_notify_success(sm->eap); - eapol_sm_step(sm); -} - - -/** - * eapol_sm_notify_eap_fail - Notification of external EAP failure trigger - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @fail: %TRUE = set failure, %FALSE = clear failure - * - * Notify EAPOL state machine that external event has forced EAP state to - * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE. - */ -void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAPOL: External notification - " - "EAP fail=%d", fail); - sm->eapFail = fail; - sm->altReject = fail; - eapol_sm_step(sm); -} - - -/** - * eapol_sm_notify_config - Notification of EAPOL configuration change - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @config: Pointer to current network EAP configuration - * @conf: Pointer to EAPOL configuration data - * - * Notify EAPOL state machine that configuration has changed. config will be - * stored as a backpointer to network configuration. This can be %NULL to clear - * the stored pointed. conf will be copied to local EAPOL/EAP configuration - * data. If conf is %NULL, this part of the configuration change will be - * skipped. - */ -void eapol_sm_notify_config(struct eapol_sm *sm, - struct eap_peer_config *config, - const struct eapol_config *conf) -{ - if (sm == NULL) - return; - - sm->config = config; - - if (conf == NULL) - return; - - sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys; - sm->conf.required_keys = conf->required_keys; - sm->conf.fast_reauth = conf->fast_reauth; - sm->conf.workaround = conf->workaround; - if (sm->eap) { - eap_set_fast_reauth(sm->eap, conf->fast_reauth); - eap_set_workaround(sm->eap, conf->workaround); - eap_set_force_disabled(sm->eap, conf->eap_disabled); - } -} - - -/** - * eapol_sm_get_key - Get master session key (MSK) from EAP - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @key: Pointer for key buffer - * @len: Number of bytes to copy to key - * Returns: 0 on success (len of key available), maximum available key len - * (>0) if key is available but it is shorter than len, or -1 on failure. - * - * Fetch EAP keying material (MSK, eapKeyData) from EAP state machine. The key - * is available only after a successful authentication. - */ -int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len) -{ - const u8 *eap_key; - size_t eap_len; - - if (sm == NULL || !eap_key_available(sm->eap)) { - wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available"); - return -1; - } - eap_key = eap_get_eapKeyData(sm->eap, &eap_len); - if (eap_key == NULL) { - wpa_printf(MSG_DEBUG, "EAPOL: Failed to get eapKeyData"); - return -1; - } - if (len > eap_len) { - wpa_printf(MSG_DEBUG, "EAPOL: Requested key length (%lu) not " - "available (len=%lu)", - (unsigned long) len, (unsigned long) eap_len); - return eap_len; - } - os_memcpy(key, eap_key, len); - wpa_printf(MSG_DEBUG, "EAPOL: Successfully fetched key (len=%lu)", - (unsigned long) len); - return 0; -} - - -/** - * eapol_sm_notify_logoff - Notification of logon/logoff commands - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @logoff: Whether command was logoff - * - * Notify EAPOL state machines that user requested logon/logoff. - */ -void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff) -{ - if (sm) { - sm->userLogoff = logoff; - eapol_sm_step(sm); - } -} - - -/** - * eapol_sm_notify_pmkid_attempt - Notification of successful PMKSA caching - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * - * Notify EAPOL state machines that PMKSA caching was successful. This is used - * to move EAPOL and EAP state machines into authenticated/successful state. - */ -void eapol_sm_notify_cached(struct eapol_sm *sm) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL"); - sm->SUPP_PAE_state = SUPP_PAE_AUTHENTICATED; - sm->suppPortStatus = Authorized; - sm->portValid = TRUE; - eap_notify_success(sm->eap); - eapol_sm_step(sm); -} - - -/** - * eapol_sm_notify_pmkid_attempt - Notification of PMKSA caching - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @attempt: Whether PMKSA caching is tried - * - * Notify EAPOL state machines whether PMKSA caching is used. - */ -void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm, int attempt) -{ - if (sm == NULL) - return; - if (attempt) { - wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA"); - sm->cached_pmk = TRUE; - } else { - wpa_printf(MSG_DEBUG, "RSN: Do not try to use cached PMKSA"); - sm->cached_pmk = FALSE; - } -} - - -static void eapol_sm_abort_cached(struct eapol_sm *sm) -{ - wpa_printf(MSG_DEBUG, "RSN: Authenticator did not accept PMKID, " - "doing full EAP authentication"); - if (sm == NULL) - return; - sm->cached_pmk = FALSE; - sm->SUPP_PAE_state = SUPP_PAE_CONNECTING; - sm->suppPortStatus = Unauthorized; - - /* Make sure we do not start sending EAPOL-Start frames first, but - * instead move to RESTART state to start EAPOL authentication. */ - sm->startWhen = 3; - eapol_enable_timer_tick(sm); - - if (sm->ctx->aborted_cached) - sm->ctx->aborted_cached(sm->ctx->ctx); -} - - -/** - * eapol_sm_register_scard_ctx - Notification of smart card context - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @ctx: Context data for smart card operations - * - * Notify EAPOL state machines of context data for smart card operations. This - * context data will be used as a parameter for scard_*() functions. - */ -void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx) -{ - if (sm) { - sm->ctx->scard_ctx = ctx; - eap_register_scard_ctx(sm->eap, ctx); - } -} - - -/** - * eapol_sm_notify_portControl - Notification of portControl changes - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @portControl: New value for portControl variable - * - * Notify EAPOL state machines that portControl variable has changed. - */ -void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAPOL: External notification - " - "portControl=%s", eapol_port_control(portControl)); - sm->portControl = portControl; - eapol_sm_step(sm); -} - - -/** - * eapol_sm_notify_ctrl_attached - Notification of attached monitor - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * - * Notify EAPOL state machines that a monitor was attached to the control - * interface to trigger re-sending of pending requests for user input. - */ -void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm) -{ - if (sm == NULL) - return; - eap_sm_notify_ctrl_attached(sm->eap); -} - - -/** - * eapol_sm_notify_ctrl_response - Notification of received user input - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * - * Notify EAPOL state machines that a control response, i.e., user - * input, was received in order to trigger retrying of a pending EAP request. - */ -void eapol_sm_notify_ctrl_response(struct eapol_sm *sm) -{ - if (sm == NULL) - return; - if (sm->eapReqData && !sm->eapReq) { - wpa_printf(MSG_DEBUG, "EAPOL: received control response (user " - "input) notification - retrying pending EAP " - "Request"); - sm->eapolEap = TRUE; - sm->eapReq = TRUE; - eapol_sm_step(sm); - } -} - - -/** - * eapol_sm_request_reauth - Request reauthentication - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * - * This function can be used to request EAPOL reauthentication, e.g., when the - * current PMKSA entry is nearing expiration. - */ -void eapol_sm_request_reauth(struct eapol_sm *sm) -{ - if (sm == NULL || sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED) - return; - eapol_sm_txStart(sm); -} - - -/** - * eapol_sm_notify_lower_layer_success - Notification of lower layer success - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @in_eapol_sm: Whether the caller is already running inside EAPOL state - * machine loop (eapol_sm_step()) - * - * Notify EAPOL (and EAP) state machines that a lower layer has detected a - * successful authentication. This is used to recover from dropped EAP-Success - * messages. - */ -void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm) -{ - if (sm == NULL) - return; - eap_notify_lower_layer_success(sm->eap); - if (!in_eapol_sm) - eapol_sm_step(sm); -} - - -/** - * eapol_sm_invalidate_cached_session - Mark cached EAP session data invalid - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - */ -void eapol_sm_invalidate_cached_session(struct eapol_sm *sm) -{ - if (sm) - eap_invalidate_cached_session(sm->eap); -} - - -static struct eap_peer_config * eapol_sm_get_config(void *ctx) -{ - struct eapol_sm *sm = ctx; - return sm ? sm->config : NULL; -} - - -static struct wpabuf * eapol_sm_get_eapReqData(void *ctx) -{ - struct eapol_sm *sm = ctx; - if (sm == NULL || sm->eapReqData == NULL) - return NULL; - - return sm->eapReqData; -} - - -static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable) -{ - struct eapol_sm *sm = ctx; - if (sm == NULL) - return FALSE; - switch (variable) { - case EAPOL_eapSuccess: - return sm->eapSuccess; - case EAPOL_eapRestart: - return sm->eapRestart; - case EAPOL_eapFail: - return sm->eapFail; - case EAPOL_eapResp: - return sm->eapResp; - case EAPOL_eapNoResp: - return sm->eapNoResp; - case EAPOL_eapReq: - return sm->eapReq; - case EAPOL_portEnabled: - return sm->portEnabled; - case EAPOL_altAccept: - return sm->altAccept; - case EAPOL_altReject: - return sm->altReject; - } - return FALSE; -} - - -static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable, - Boolean value) -{ - struct eapol_sm *sm = ctx; - if (sm == NULL) - return; - switch (variable) { - case EAPOL_eapSuccess: - sm->eapSuccess = value; - break; - case EAPOL_eapRestart: - sm->eapRestart = value; - break; - case EAPOL_eapFail: - sm->eapFail = value; - break; - case EAPOL_eapResp: - sm->eapResp = value; - break; - case EAPOL_eapNoResp: - sm->eapNoResp = value; - break; - case EAPOL_eapReq: - sm->eapReq = value; - break; - case EAPOL_portEnabled: - sm->portEnabled = value; - break; - case EAPOL_altAccept: - sm->altAccept = value; - break; - case EAPOL_altReject: - sm->altReject = value; - break; - } -} - - -static unsigned int eapol_sm_get_int(void *ctx, enum eapol_int_var variable) -{ - struct eapol_sm *sm = ctx; - if (sm == NULL) - return 0; - switch (variable) { - case EAPOL_idleWhile: - return sm->idleWhile; - } - return 0; -} - - -static void eapol_sm_set_int(void *ctx, enum eapol_int_var variable, - unsigned int value) -{ - struct eapol_sm *sm = ctx; - if (sm == NULL) - return; - switch (variable) { - case EAPOL_idleWhile: - sm->idleWhile = value; - eapol_enable_timer_tick(sm); - break; - } -} - - -static void eapol_sm_set_config_blob(void *ctx, struct wpa_config_blob *blob) -{ -#ifndef CONFIG_NO_CONFIG_BLOBS - struct eapol_sm *sm = ctx; - if (sm && sm->ctx && sm->ctx->set_config_blob) - sm->ctx->set_config_blob(sm->ctx->ctx, blob); -#endif /* CONFIG_NO_CONFIG_BLOBS */ -} - - -static const struct wpa_config_blob * -eapol_sm_get_config_blob(void *ctx, const char *name) -{ -#ifndef CONFIG_NO_CONFIG_BLOBS - struct eapol_sm *sm = ctx; - if (sm && sm->ctx && sm->ctx->get_config_blob) - return sm->ctx->get_config_blob(sm->ctx->ctx, name); - else - return NULL; -#else /* CONFIG_NO_CONFIG_BLOBS */ - return NULL; -#endif /* CONFIG_NO_CONFIG_BLOBS */ -} - - -static void eapol_sm_notify_pending(void *ctx) -{ - struct eapol_sm *sm = ctx; - if (sm == NULL) - return; - if (sm->eapReqData && !sm->eapReq) { - wpa_printf(MSG_DEBUG, "EAPOL: received notification from EAP " - "state machine - retrying pending EAP Request"); - sm->eapolEap = TRUE; - sm->eapReq = TRUE; - eapol_sm_step(sm); - } -} - - -#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) -static void eapol_sm_eap_param_needed(void *ctx, const char *field, - const char *txt) -{ - struct eapol_sm *sm = ctx; - wpa_printf(MSG_DEBUG, "EAPOL: EAP parameter needed"); - if (sm->ctx->eap_param_needed) - sm->ctx->eap_param_needed(sm->ctx->ctx, field, txt); -} -#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ -#define eapol_sm_eap_param_needed NULL -#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ - - -static struct eapol_callbacks eapol_cb = -{ - eapol_sm_get_config, - eapol_sm_get_bool, - eapol_sm_set_bool, - eapol_sm_get_int, - eapol_sm_set_int, - eapol_sm_get_eapReqData, - eapol_sm_set_config_blob, - eapol_sm_get_config_blob, - eapol_sm_notify_pending, - eapol_sm_eap_param_needed -}; - - -/** - * eapol_sm_init - Initialize EAPOL state machine - * @ctx: Pointer to EAPOL context data; this needs to be an allocated buffer - * and EAPOL state machine will free it in eapol_sm_deinit() - * Returns: Pointer to the allocated EAPOL state machine or %NULL on failure - * - * Allocate and initialize an EAPOL state machine. - */ -struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx) -{ - struct eapol_sm *sm; - struct eap_config conf; - sm = os_zalloc(sizeof(*sm)); - if (sm == NULL) - return NULL; - sm->ctx = ctx; - - sm->portControl = Auto; - - /* Supplicant PAE state machine */ - sm->heldPeriod = 60; - sm->startPeriod = 30; - sm->maxStart = 3; - - /* Supplicant Backend state machine */ - sm->authPeriod = 30; - - os_memset(&conf, 0, sizeof(conf)); -#ifdef EAP_TLS_OPENSSL - conf.opensc_engine_path = ctx->opensc_engine_path; - conf.pkcs11_engine_path = ctx->pkcs11_engine_path; - conf.pkcs11_module_path = ctx->pkcs11_module_path; -#endif /* EAP_TLS_OPENSSL */ - conf.wps = ctx->wps; - - sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf); - if (sm->eap == NULL) { - os_free(sm); - return NULL; - } - - /* Initialize EAPOL state machines */ - sm->initialize = TRUE; - eapol_sm_step(sm); - sm->initialize = FALSE; - eapol_sm_step(sm); - - sm->timer_tick_enabled = 1; - eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm); - - return sm; -} - - -/** - * eapol_sm_deinit - Deinitialize EAPOL state machine - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * - * Deinitialize and free EAPOL state machine. - */ -void eapol_sm_deinit(struct eapol_sm *sm) -{ - if (sm == NULL) - return; - eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm); - eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); - eap_peer_sm_deinit(sm->eap); - os_free(sm->last_rx_key); - wpabuf_free(sm->eapReqData); - os_free(sm->ctx); - os_free(sm); -} diff --git a/contrib/hostapd/src/eapol_supp/eapol_supp_sm.h b/contrib/hostapd/src/eapol_supp/eapol_supp_sm.h deleted file mode 100644 index 57d7bc1ab1..0000000000 --- a/contrib/hostapd/src/eapol_supp/eapol_supp_sm.h +++ /dev/null @@ -1,342 +0,0 @@ -/* - * EAPOL supplicant state machines - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAPOL_SUPP_SM_H -#define EAPOL_SUPP_SM_H - -#include "defs.h" - -typedef enum { Unauthorized, Authorized } PortStatus; -typedef enum { Auto, ForceUnauthorized, ForceAuthorized } PortControl; - -/** - * struct eapol_config - Per network configuration for EAPOL state machines - */ -struct eapol_config { - /** - * accept_802_1x_keys - Accept IEEE 802.1X (non-WPA) EAPOL-Key frames - * - * This variable should be set to 1 when using EAPOL state machines - * with non-WPA security policy to generate dynamic WEP keys. When - * using WPA, this should be set to 0 so that WPA state machine can - * process the EAPOL-Key frames. - */ - int accept_802_1x_keys; - -#define EAPOL_REQUIRE_KEY_UNICAST BIT(0) -#define EAPOL_REQUIRE_KEY_BROADCAST BIT(1) - /** - * required_keys - Which EAPOL-Key packets are required - * - * This variable determines which EAPOL-Key packets are required before - * marking connection authenticated. This is a bit field of - * EAPOL_REQUIRE_KEY_UNICAST and EAPOL_REQUIRE_KEY_BROADCAST flags. - */ - int required_keys; - - /** - * fast_reauth - Whether fast EAP reauthentication is enabled - */ - int fast_reauth; - - /** - * workaround - Whether EAP workarounds are enabled - */ - unsigned int workaround; - - /** - * eap_disabled - Whether EAP is disabled - */ - int eap_disabled; -}; - -struct eapol_sm; -struct wpa_config_blob; - -/** - * struct eapol_ctx - Global (for all networks) EAPOL state machine context - */ -struct eapol_ctx { - /** - * ctx - Pointer to arbitrary upper level context - */ - void *ctx; - - /** - * preauth - IEEE 802.11i/RSN pre-authentication - * - * This EAPOL state machine is used for IEEE 802.11i/RSN - * pre-authentication - */ - int preauth; - - /** - * cb - Function to be called when EAPOL negotiation has been completed - * @eapol: Pointer to EAPOL state machine data - * @success: Whether the authentication was completed successfully - * @ctx: Pointer to context data (cb_ctx) - * - * This optional callback function will be called when the EAPOL - * authentication has been completed. This allows the owner of the - * EAPOL state machine to process the key and terminate the EAPOL state - * machine. Currently, this is used only in RSN pre-authentication. - */ - void (*cb)(struct eapol_sm *eapol, int success, void *ctx); - - /** - * cb_ctx - Callback context for cb() - */ - void *cb_ctx; - - /** - * msg_ctx - Callback context for wpa_msg() calls - */ - void *msg_ctx; - - /** - * scard_ctx - Callback context for PC/SC scard_*() function calls - * - * This context can be updated with eapol_sm_register_scard_ctx(). - */ - void *scard_ctx; - - /** - * eapol_send_ctx - Callback context for eapol_send() calls - */ - void *eapol_send_ctx; - - /** - * eapol_done_cb - Function to be called at successful completion - * @ctx: Callback context (ctx) - * - * This function is called at the successful completion of EAPOL - * authentication. If dynamic WEP keys are used, this is called only - * after all the expected keys have been received. - */ - void (*eapol_done_cb)(void *ctx); - - /** - * eapol_send - Send EAPOL packets - * @ctx: Callback context (eapol_send_ctx) - * @type: EAPOL type (IEEE802_1X_TYPE_*) - * @buf: Pointer to EAPOL payload - * @len: Length of the EAPOL payload - * Returns: 0 on success, -1 on failure - */ - int (*eapol_send)(void *ctx, int type, const u8 *buf, size_t len); - - /** - * set_wep_key - Configure WEP keys - * @ctx: Callback context (ctx) - * @unicast: Non-zero = unicast, 0 = multicast/broadcast key - * @keyidx: Key index (0..3) - * @key: WEP key - * @keylen: Length of the WEP key - * Returns: 0 on success, -1 on failure - */ - int (*set_wep_key)(void *ctx, int unicast, int keyidx, - const u8 *key, size_t keylen); - - /** - * set_config_blob - Set or add a named configuration blob - * @ctx: Callback context (ctx) - * @blob: New value for the blob - * - * Adds a new configuration blob or replaces the current value of an - * existing blob. - */ - void (*set_config_blob)(void *ctx, struct wpa_config_blob *blob); - - /** - * get_config_blob - Get a named configuration blob - * @ctx: Callback context (ctx) - * @name: Name of the blob - * Returns: Pointer to blob data or %NULL if not found - */ - const struct wpa_config_blob * (*get_config_blob)(void *ctx, - const char *name); - - /** - * aborted_cached - Notify that cached PMK attempt was aborted - * @ctx: Callback context (ctx) - */ - void (*aborted_cached)(void *ctx); - -#ifdef EAP_TLS_OPENSSL - /** - * opensc_engine_path - Path to the OpenSSL engine for opensc - * - * This is an OpenSSL specific configuration option for loading OpenSC - * engine (engine_opensc.so); if %NULL, this engine is not loaded. - */ - const char *opensc_engine_path; - - /** - * pkcs11_engine_path - Path to the OpenSSL engine for PKCS#11 - * - * This is an OpenSSL specific configuration option for loading PKCS#11 - * engine (engine_pkcs11.so); if %NULL, this engine is not loaded. - */ - const char *pkcs11_engine_path; - - /** - * pkcs11_module_path - Path to the OpenSSL OpenSC/PKCS#11 module - * - * This is an OpenSSL specific configuration option for configuring - * path to OpenSC/PKCS#11 engine (opensc-pkcs11.so); if %NULL, this - * module is not loaded. - */ - const char *pkcs11_module_path; -#endif /* EAP_TLS_OPENSSL */ - - /** - * wps - WPS context data - * - * This is only used by EAP-WSC and can be left %NULL if not available. - */ - struct wps_context *wps; - - /** - * eap_param_needed - Notify that EAP parameter is needed - * @ctx: Callback context (ctx) - * @field: Field name (e.g., "IDENTITY") - * @txt: User readable text describing the required parameter - */ - void (*eap_param_needed)(void *ctx, const char *field, - const char *txt); -}; - - -struct eap_peer_config; - -#ifdef IEEE8021X_EAPOL -struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx); -void eapol_sm_deinit(struct eapol_sm *sm); -void eapol_sm_step(struct eapol_sm *sm); -int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen, - int verbose); -int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen); -void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod, - int startPeriod, int maxStart); -int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf, - size_t len); -void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm); -void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled); -void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid); -void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success); -void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail); -void eapol_sm_notify_config(struct eapol_sm *sm, - struct eap_peer_config *config, - const struct eapol_config *conf); -int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len); -void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff); -void eapol_sm_notify_cached(struct eapol_sm *sm); -void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm, int attempt); -void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx); -void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl); -void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm); -void eapol_sm_notify_ctrl_response(struct eapol_sm *sm); -void eapol_sm_request_reauth(struct eapol_sm *sm); -void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm); -void eapol_sm_invalidate_cached_session(struct eapol_sm *sm); -#else /* IEEE8021X_EAPOL */ -static inline struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx) -{ - free(ctx); - return (struct eapol_sm *) 1; -} -static inline void eapol_sm_deinit(struct eapol_sm *sm) -{ -} -static inline void eapol_sm_step(struct eapol_sm *sm) -{ -} -static inline int eapol_sm_get_status(struct eapol_sm *sm, char *buf, - size_t buflen, int verbose) -{ - return 0; -} -static inline int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, - size_t buflen) -{ - return 0; -} -static inline void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, - int authPeriod, int startPeriod, - int maxStart) -{ -} -static inline int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, - const u8 *buf, size_t len) -{ - return 0; -} -static inline void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm) -{ -} -static inline void eapol_sm_notify_portEnabled(struct eapol_sm *sm, - Boolean enabled) -{ -} -static inline void eapol_sm_notify_portValid(struct eapol_sm *sm, - Boolean valid) -{ -} -static inline void eapol_sm_notify_eap_success(struct eapol_sm *sm, - Boolean success) -{ -} -static inline void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail) -{ -} -static inline void eapol_sm_notify_config(struct eapol_sm *sm, - struct eap_peer_config *config, - struct eapol_config *conf) -{ -} -static inline int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len) -{ - return -1; -} -static inline void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff) -{ -} -static inline void eapol_sm_notify_cached(struct eapol_sm *sm) -{ -} -#define eapol_sm_notify_pmkid_attempt(sm, attempt) do { } while (0) -#define eapol_sm_register_scard_ctx(sm, ctx) do { } while (0) -static inline void eapol_sm_notify_portControl(struct eapol_sm *sm, - PortControl portControl) -{ -} -static inline void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm) -{ -} -static inline void eapol_sm_notify_ctrl_response(struct eapol_sm *sm) -{ -} -static inline void eapol_sm_request_reauth(struct eapol_sm *sm) -{ -} -static inline void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, - int in_eapol_sm) -{ -} -static inline void eapol_sm_invalidate_cached_session(struct eapol_sm *sm) -{ -} -#endif /* IEEE8021X_EAPOL */ - -#endif /* EAPOL_SUPP_SM_H */ diff --git a/contrib/hostapd/src/hlr_auc_gw/hlr_auc_gw.c b/contrib/hostapd/src/hlr_auc_gw/hlr_auc_gw.c deleted file mode 100644 index e318903543..0000000000 --- a/contrib/hostapd/src/hlr_auc_gw/hlr_auc_gw.c +++ /dev/null @@ -1,714 +0,0 @@ -/* - * HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator - * Copyright (c) 2005-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This is an example implementation of the EAP-SIM/AKA database/authentication - * gateway interface to HLR/AuC. It is expected to be replaced with an - * implementation of SS7 gateway to GSM/UMTS authentication center (HLR/AuC) or - * a local implementation of SIM triplet and AKA authentication data generator. - * - * hostapd will send SIM/AKA authentication queries over a UNIX domain socket - * to and external program, e.g., this hlr_auc_gw. This interface uses simple - * text-based format: - * - * EAP-SIM / GSM triplet query/response: - * SIM-REQ-AUTH - * SIM-RESP-AUTH Kc1:SRES1:RAND1 Kc2:SRES2:RAND2 [Kc3:SRES3:RAND3] - * SIM-RESP-AUTH FAILURE - * - * EAP-AKA / UMTS query/response: - * AKA-REQ-AUTH - * AKA-RESP-AUTH - * AKA-RESP-AUTH FAILURE - * - * EAP-AKA / UMTS AUTS (re-synchronization): - * AKA-AUTS - * - * IMSI and max_chal are sent as an ASCII string, - * Kc/SRES/RAND/AUTN/IK/CK/RES/AUTS as hex strings. - * - * The example implementation here reads GSM authentication triplets from a - * text file in IMSI:Kc:SRES:RAND format, IMSI in ASCII, other fields as hex - * strings. This is used to simulate an HLR/AuC. As such, it is not very useful - * for real life authentication, but it is useful both as an example - * implementation and for EAP-SIM testing. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "milenage.h" - -static const char *default_socket_path = "/tmp/hlr_auc_gw.sock"; -static const char *socket_path; -static int serv_sock = -1; - -/* GSM triplets */ -struct gsm_triplet { - struct gsm_triplet *next; - char imsi[20]; - u8 kc[8]; - u8 sres[4]; - u8 _rand[16]; -}; - -static struct gsm_triplet *gsm_db = NULL, *gsm_db_pos = NULL; - -/* OPc and AMF parameters for Milenage (Example algorithms for AKA). */ -struct milenage_parameters { - struct milenage_parameters *next; - char imsi[20]; - u8 ki[16]; - u8 opc[16]; - u8 amf[2]; - u8 sqn[6]; -}; - -static struct milenage_parameters *milenage_db = NULL; - -#define EAP_SIM_MAX_CHAL 3 - -#define EAP_AKA_RAND_LEN 16 -#define EAP_AKA_AUTN_LEN 16 -#define EAP_AKA_AUTS_LEN 14 -#define EAP_AKA_RES_MAX_LEN 16 -#define EAP_AKA_IK_LEN 16 -#define EAP_AKA_CK_LEN 16 - - -static int open_socket(const char *path) -{ - struct sockaddr_un addr; - int s; - - s = socket(PF_UNIX, SOCK_DGRAM, 0); - if (s < 0) { - perror("socket(PF_UNIX)"); - return -1; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_strlcpy(addr.sun_path, path, sizeof(addr.sun_path)); - if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind(PF_UNIX)"); - close(s); - return -1; - } - - return s; -} - - -static int read_gsm_triplets(const char *fname) -{ - FILE *f; - char buf[200], *pos, *pos2; - struct gsm_triplet *g = NULL; - int line, ret = 0; - - if (fname == NULL) - return -1; - - f = fopen(fname, "r"); - if (f == NULL) { - printf("Could not open GSM tripler data file '%s'\n", fname); - return -1; - } - - line = 0; - while (fgets(buf, sizeof(buf), f)) { - line++; - - /* Parse IMSI:Kc:SRES:RAND */ - buf[sizeof(buf) - 1] = '\0'; - if (buf[0] == '#') - continue; - pos = buf; - while (*pos != '\0' && *pos != '\n') - pos++; - if (*pos == '\n') - *pos = '\0'; - pos = buf; - if (*pos == '\0') - continue; - - g = os_zalloc(sizeof(*g)); - if (g == NULL) { - ret = -1; - break; - } - - /* IMSI */ - pos2 = strchr(pos, ':'); - if (pos2 == NULL) { - printf("%s:%d - Invalid IMSI (%s)\n", - fname, line, pos); - ret = -1; - break; - } - *pos2 = '\0'; - if (strlen(pos) >= sizeof(g->imsi)) { - printf("%s:%d - Too long IMSI (%s)\n", - fname, line, pos); - ret = -1; - break; - } - os_strlcpy(g->imsi, pos, sizeof(g->imsi)); - pos = pos2 + 1; - - /* Kc */ - pos2 = strchr(pos, ':'); - if (pos2 == NULL) { - printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos); - ret = -1; - break; - } - *pos2 = '\0'; - if (strlen(pos) != 16 || hexstr2bin(pos, g->kc, 8)) { - printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos); - ret = -1; - break; - } - pos = pos2 + 1; - - /* SRES */ - pos2 = strchr(pos, ':'); - if (pos2 == NULL) { - printf("%s:%d - Invalid SRES (%s)\n", fname, line, - pos); - ret = -1; - break; - } - *pos2 = '\0'; - if (strlen(pos) != 8 || hexstr2bin(pos, g->sres, 4)) { - printf("%s:%d - Invalid SRES (%s)\n", fname, line, - pos); - ret = -1; - break; - } - pos = pos2 + 1; - - /* RAND */ - pos2 = strchr(pos, ':'); - if (pos2) - *pos2 = '\0'; - if (strlen(pos) != 32 || hexstr2bin(pos, g->_rand, 16)) { - printf("%s:%d - Invalid RAND (%s)\n", fname, line, - pos); - ret = -1; - break; - } - pos = pos2 + 1; - - g->next = gsm_db; - gsm_db = g; - g = NULL; - } - free(g); - - fclose(f); - - return ret; -} - - -static struct gsm_triplet * get_gsm_triplet(const char *imsi) -{ - struct gsm_triplet *g = gsm_db_pos; - - while (g) { - if (strcmp(g->imsi, imsi) == 0) { - gsm_db_pos = g->next; - return g; - } - g = g->next; - } - - g = gsm_db; - while (g && g != gsm_db_pos) { - if (strcmp(g->imsi, imsi) == 0) { - gsm_db_pos = g->next; - return g; - } - g = g->next; - } - - return NULL; -} - - -static int read_milenage(const char *fname) -{ - FILE *f; - char buf[200], *pos, *pos2; - struct milenage_parameters *m = NULL; - int line, ret = 0; - - if (fname == NULL) - return -1; - - f = fopen(fname, "r"); - if (f == NULL) { - printf("Could not open Milenage data file '%s'\n", fname); - return -1; - } - - line = 0; - while (fgets(buf, sizeof(buf), f)) { - line++; - - /* Parse IMSI Ki OPc AMF SQN */ - buf[sizeof(buf) - 1] = '\0'; - if (buf[0] == '#') - continue; - pos = buf; - while (*pos != '\0' && *pos != '\n') - pos++; - if (*pos == '\n') - *pos = '\0'; - pos = buf; - if (*pos == '\0') - continue; - - m = os_zalloc(sizeof(*m)); - if (m == NULL) { - ret = -1; - break; - } - - /* IMSI */ - pos2 = strchr(pos, ' '); - if (pos2 == NULL) { - printf("%s:%d - Invalid IMSI (%s)\n", - fname, line, pos); - ret = -1; - break; - } - *pos2 = '\0'; - if (strlen(pos) >= sizeof(m->imsi)) { - printf("%s:%d - Too long IMSI (%s)\n", - fname, line, pos); - ret = -1; - break; - } - os_strlcpy(m->imsi, pos, sizeof(m->imsi)); - pos = pos2 + 1; - - /* Ki */ - pos2 = strchr(pos, ' '); - if (pos2 == NULL) { - printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos); - ret = -1; - break; - } - *pos2 = '\0'; - if (strlen(pos) != 32 || hexstr2bin(pos, m->ki, 16)) { - printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos); - ret = -1; - break; - } - pos = pos2 + 1; - - /* OPc */ - pos2 = strchr(pos, ' '); - if (pos2 == NULL) { - printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos); - ret = -1; - break; - } - *pos2 = '\0'; - if (strlen(pos) != 32 || hexstr2bin(pos, m->opc, 16)) { - printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos); - ret = -1; - break; - } - pos = pos2 + 1; - - /* AMF */ - pos2 = strchr(pos, ' '); - if (pos2 == NULL) { - printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos); - ret = -1; - break; - } - *pos2 = '\0'; - if (strlen(pos) != 4 || hexstr2bin(pos, m->amf, 2)) { - printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos); - ret = -1; - break; - } - pos = pos2 + 1; - - /* SQN */ - pos2 = strchr(pos, ' '); - if (pos2) - *pos2 = '\0'; - if (strlen(pos) != 12 || hexstr2bin(pos, m->sqn, 6)) { - printf("%s:%d - Invalid SEQ (%s)\n", fname, line, pos); - ret = -1; - break; - } - pos = pos2 + 1; - - m->next = milenage_db; - milenage_db = m; - m = NULL; - } - free(m); - - fclose(f); - - return ret; -} - - -static struct milenage_parameters * get_milenage(const char *imsi) -{ - struct milenage_parameters *m = milenage_db; - - while (m) { - if (strcmp(m->imsi, imsi) == 0) - break; - m = m->next; - } - - return m; -} - - -static void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen, - char *imsi) -{ - int count, max_chal, ret; - char *pos; - char reply[1000], *rpos, *rend; - struct milenage_parameters *m; - struct gsm_triplet *g; - - reply[0] = '\0'; - - pos = strchr(imsi, ' '); - if (pos) { - *pos++ = '\0'; - max_chal = atoi(pos); - if (max_chal < 1 || max_chal < EAP_SIM_MAX_CHAL) - max_chal = EAP_SIM_MAX_CHAL; - } else - max_chal = EAP_SIM_MAX_CHAL; - - rend = &reply[sizeof(reply)]; - rpos = reply; - ret = snprintf(rpos, rend - rpos, "SIM-RESP-AUTH %s", imsi); - if (ret < 0 || ret >= rend - rpos) - return; - rpos += ret; - - m = get_milenage(imsi); - if (m) { - u8 _rand[16], sres[4], kc[8]; - for (count = 0; count < max_chal; count++) { - if (os_get_random(_rand, 16) < 0) - return; - gsm_milenage(m->opc, m->ki, _rand, sres, kc); - *rpos++ = ' '; - rpos += wpa_snprintf_hex(rpos, rend - rpos, kc, 8); - *rpos++ = ':'; - rpos += wpa_snprintf_hex(rpos, rend - rpos, sres, 4); - *rpos++ = ':'; - rpos += wpa_snprintf_hex(rpos, rend - rpos, _rand, 16); - } - *rpos = '\0'; - goto send; - } - - count = 0; - while (count < max_chal && (g = get_gsm_triplet(imsi))) { - if (strcmp(g->imsi, imsi) != 0) - continue; - - if (rpos < rend) - *rpos++ = ' '; - rpos += wpa_snprintf_hex(rpos, rend - rpos, g->kc, 8); - if (rpos < rend) - *rpos++ = ':'; - rpos += wpa_snprintf_hex(rpos, rend - rpos, g->sres, 4); - if (rpos < rend) - *rpos++ = ':'; - rpos += wpa_snprintf_hex(rpos, rend - rpos, g->_rand, 16); - count++; - } - - if (count == 0) { - printf("No GSM triplets found for %s\n", imsi); - ret = snprintf(rpos, rend - rpos, " FAILURE"); - if (ret < 0 || ret >= rend - rpos) - return; - rpos += ret; - } - -send: - printf("Send: %s\n", reply); - if (sendto(s, reply, rpos - reply, 0, - (struct sockaddr *) from, fromlen) < 0) - perror("send"); -} - - -static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen, - char *imsi) -{ - /* AKA-RESP-AUTH */ - char reply[1000], *pos, *end; - u8 _rand[EAP_AKA_RAND_LEN]; - u8 autn[EAP_AKA_AUTN_LEN]; - u8 ik[EAP_AKA_IK_LEN]; - u8 ck[EAP_AKA_CK_LEN]; - u8 res[EAP_AKA_RES_MAX_LEN]; - size_t res_len; - int ret; - struct milenage_parameters *m; - - m = get_milenage(imsi); - if (m) { - if (os_get_random(_rand, EAP_AKA_RAND_LEN) < 0) - return; - res_len = EAP_AKA_RES_MAX_LEN; - inc_byte_array(m->sqn, 6); - printf("AKA: Milenage with SQN=%02x%02x%02x%02x%02x%02x\n", - m->sqn[0], m->sqn[1], m->sqn[2], - m->sqn[3], m->sqn[4], m->sqn[5]); - milenage_generate(m->opc, m->amf, m->ki, m->sqn, _rand, - autn, ik, ck, res, &res_len); - } else { - printf("Unknown IMSI: %s\n", imsi); -#ifdef AKA_USE_FIXED_TEST_VALUES - printf("Using fixed test values for AKA\n"); - memset(_rand, '0', EAP_AKA_RAND_LEN); - memset(autn, '1', EAP_AKA_AUTN_LEN); - memset(ik, '3', EAP_AKA_IK_LEN); - memset(ck, '4', EAP_AKA_CK_LEN); - memset(res, '2', EAP_AKA_RES_MAX_LEN); - res_len = EAP_AKA_RES_MAX_LEN; -#else /* AKA_USE_FIXED_TEST_VALUES */ - return; -#endif /* AKA_USE_FIXED_TEST_VALUES */ - } - - pos = reply; - end = &reply[sizeof(reply)]; - ret = snprintf(pos, end - pos, "AKA-RESP-AUTH %s ", imsi); - if (ret < 0 || ret >= end - pos) - return; - pos += ret; - pos += wpa_snprintf_hex(pos, end - pos, _rand, EAP_AKA_RAND_LEN); - *pos++ = ' '; - pos += wpa_snprintf_hex(pos, end - pos, autn, EAP_AKA_AUTN_LEN); - *pos++ = ' '; - pos += wpa_snprintf_hex(pos, end - pos, ik, EAP_AKA_IK_LEN); - *pos++ = ' '; - pos += wpa_snprintf_hex(pos, end - pos, ck, EAP_AKA_CK_LEN); - *pos++ = ' '; - pos += wpa_snprintf_hex(pos, end - pos, res, res_len); - - printf("Send: %s\n", reply); - - if (sendto(s, reply, pos - reply, 0, (struct sockaddr *) from, - fromlen) < 0) - perror("send"); -} - - -static void aka_auts(int s, struct sockaddr_un *from, socklen_t fromlen, - char *imsi) -{ - char *auts, *__rand; - u8 _auts[EAP_AKA_AUTS_LEN], _rand[EAP_AKA_RAND_LEN], sqn[6]; - struct milenage_parameters *m; - - /* AKA-AUTS */ - - auts = strchr(imsi, ' '); - if (auts == NULL) - return; - *auts++ = '\0'; - - __rand = strchr(auts, ' '); - if (__rand == NULL) - return; - *__rand++ = '\0'; - - printf("AKA-AUTS: IMSI=%s AUTS=%s RAND=%s\n", imsi, auts, __rand); - if (hexstr2bin(auts, _auts, EAP_AKA_AUTS_LEN) || - hexstr2bin(__rand, _rand, EAP_AKA_RAND_LEN)) { - printf("Could not parse AUTS/RAND\n"); - return; - } - - m = get_milenage(imsi); - if (m == NULL) { - printf("Unknown IMSI: %s\n", imsi); - return; - } - - if (milenage_auts(m->opc, m->ki, _rand, _auts, sqn)) { - printf("AKA-AUTS: Incorrect MAC-S\n"); - } else { - memcpy(m->sqn, sqn, 6); - printf("AKA-AUTS: Re-synchronized: " - "SQN=%02x%02x%02x%02x%02x%02x\n", - sqn[0], sqn[1], sqn[2], sqn[3], sqn[4], sqn[5]); - } -} - - -static int process(int s) -{ - char buf[1000]; - struct sockaddr_un from; - socklen_t fromlen; - ssize_t res; - - fromlen = sizeof(from); - res = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *) &from, - &fromlen); - if (res < 0) { - perror("recvfrom"); - return -1; - } - - if (res == 0) - return 0; - - if ((size_t) res >= sizeof(buf)) - res = sizeof(buf) - 1; - buf[res] = '\0'; - - printf("Received: %s\n", buf); - - if (strncmp(buf, "SIM-REQ-AUTH ", 13) == 0) - sim_req_auth(s, &from, fromlen, buf + 13); - else if (strncmp(buf, "AKA-REQ-AUTH ", 13) == 0) - aka_req_auth(s, &from, fromlen, buf + 13); - else if (strncmp(buf, "AKA-AUTS ", 9) == 0) - aka_auts(s, &from, fromlen, buf + 9); - else - printf("Unknown request: %s\n", buf); - - return 0; -} - - -static void cleanup(void) -{ - struct gsm_triplet *g, *gprev; - struct milenage_parameters *m, *prev; - - g = gsm_db; - while (g) { - gprev = g; - g = g->next; - free(gprev); - } - - m = milenage_db; - while (m) { - prev = m; - m = m->next; - free(prev); - } - - close(serv_sock); - unlink(socket_path); -} - - -static void handle_term(int sig) -{ - printf("Signal %d - terminate\n", sig); - exit(0); -} - - -static void usage(void) -{ - printf("HLR/AuC testing gateway for hostapd EAP-SIM/AKA " - "database/authenticator\n" - "Copyright (c) 2005-2007, Jouni Malinen \n" - "\n" - "usage:\n" - "hlr_auc_gw [-h] [-s] [-g] " - "[-m]\n" - "\n" - "options:\n" - " -h = show this usage help\n" - " -s = path for UNIX domain socket\n" - " (default: %s)\n" - " -g = path for GSM authentication triplets\n" - " -m = path for Milenage keys\n", - default_socket_path); -} - - -int main(int argc, char *argv[]) -{ - int c; - char *milenage_file = NULL; - char *gsm_triplet_file = NULL; - - socket_path = default_socket_path; - - for (;;) { - c = getopt(argc, argv, "g:hm:s:"); - if (c < 0) - break; - switch (c) { - case 'g': - gsm_triplet_file = optarg; - break; - case 'h': - usage(); - return 0; - case 'm': - milenage_file = optarg; - break; - case 's': - socket_path = optarg; - break; - default: - usage(); - return -1; - } - } - - if (gsm_triplet_file && read_gsm_triplets(gsm_triplet_file) < 0) - return -1; - - if (milenage_file && read_milenage(milenage_file) < 0) - return -1; - - serv_sock = open_socket(socket_path); - if (serv_sock < 0) - return -1; - - printf("Listening for requests on %s\n", socket_path); - - atexit(cleanup); - signal(SIGTERM, handle_term); - signal(SIGINT, handle_term); - - for (;;) - process(serv_sock); - - return 0; -} diff --git a/contrib/hostapd/src/hlr_auc_gw/milenage.c b/contrib/hostapd/src/hlr_auc_gw/milenage.c deleted file mode 100644 index 0ce5ef3ff6..0000000000 --- a/contrib/hostapd/src/hlr_auc_gw/milenage.c +++ /dev/null @@ -1,1142 +0,0 @@ -/* - * 3GPP AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208) - * Copyright (c) 2006-2007 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file implements an example authentication algorithm defined for 3GPP - * AKA. This can be used to implement a simple HLR/AuC into hlr_auc_gw to allow - * EAP-AKA to be tested properly with real USIM cards. - * - * This implementations assumes that the r1..r5 and c1..c5 constants defined in - * TS 35.206 are used, i.e., r1=64, r2=0, r3=32, r4=64, r5=96, c1=00..00, - * c2=00..01, c3=00..02, c4=00..04, c5=00..08. The block cipher is assumed to - * be AES (Rijndael). - */ - -#include "includes.h" - -#include "common.h" -#include "milenage.h" -#include "aes_wrap.h" - - -/** - * milenage_f1 - Milenage f1 and f1* algorithms - * @opc: OPc = 128-bit value derived from OP and K - * @k: K = 128-bit subscriber key - * @_rand: RAND = 128-bit random challenge - * @sqn: SQN = 48-bit sequence number - * @amf: AMF = 16-bit authentication management field - * @mac_a: Buffer for MAC-A = 64-bit network authentication code, or %NULL - * @mac_s: Buffer for MAC-S = 64-bit resync authentication code, or %NULL - * Returns: 0 on success, -1 on failure - */ -static int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand, - const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s) -{ - u8 tmp1[16], tmp2[16], tmp3[16]; - int i; - - /* tmp1 = TEMP = E_K(RAND XOR OP_C) */ - for (i = 0; i < 16; i++) - tmp1[i] = _rand[i] ^ opc[i]; - if (aes_128_encrypt_block(k, tmp1, tmp1)) - return -1; - - /* tmp2 = IN1 = SQN || AMF || SQN || AMF */ - os_memcpy(tmp2, sqn, 6); - os_memcpy(tmp2 + 6, amf, 2); - os_memcpy(tmp2 + 8, tmp2, 8); - - /* OUT1 = E_K(TEMP XOR rot(IN1 XOR OP_C, r1) XOR c1) XOR OP_C */ - - /* rotate (tmp2 XOR OP_C) by r1 (= 0x40 = 8 bytes) */ - for (i = 0; i < 16; i++) - tmp3[(i + 8) % 16] = tmp2[i] ^ opc[i]; - /* XOR with TEMP = E_K(RAND XOR OP_C) */ - for (i = 0; i < 16; i++) - tmp3[i] ^= tmp1[i]; - /* XOR with c1 (= ..00, i.e., NOP) */ - - /* f1 || f1* = E_K(tmp3) XOR OP_c */ - if (aes_128_encrypt_block(k, tmp3, tmp1)) - return -1; - for (i = 0; i < 16; i++) - tmp1[i] ^= opc[i]; - if (mac_a) - os_memcpy(mac_a, tmp1, 8); /* f1 */ - if (mac_s) - os_memcpy(mac_s, tmp1 + 8, 8); /* f1* */ - return 0; -} - - -/** - * milenage_f2345 - Milenage f2, f3, f4, f5, f5* algorithms - * @opc: OPc = 128-bit value derived from OP and K - * @k: K = 128-bit subscriber key - * @_rand: RAND = 128-bit random challenge - * @res: Buffer for RES = 64-bit signed response (f2), or %NULL - * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL - * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL - * @ak: Buffer for AK = 48-bit anonymity key (f5), or %NULL - * @akstar: Buffer for AK = 48-bit anonymity key (f5*), or %NULL - * Returns: 0 on success, -1 on failure - */ -static int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand, - u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar) -{ - u8 tmp1[16], tmp2[16], tmp3[16]; - int i; - - /* tmp2 = TEMP = E_K(RAND XOR OP_C) */ - for (i = 0; i < 16; i++) - tmp1[i] = _rand[i] ^ opc[i]; - if (aes_128_encrypt_block(k, tmp1, tmp2)) - return -1; - - /* OUT2 = E_K(rot(TEMP XOR OP_C, r2) XOR c2) XOR OP_C */ - /* OUT3 = E_K(rot(TEMP XOR OP_C, r3) XOR c3) XOR OP_C */ - /* OUT4 = E_K(rot(TEMP XOR OP_C, r4) XOR c4) XOR OP_C */ - /* OUT5 = E_K(rot(TEMP XOR OP_C, r5) XOR c5) XOR OP_C */ - - /* f2 and f5 */ - /* rotate by r2 (= 0, i.e., NOP) */ - for (i = 0; i < 16; i++) - tmp1[i] = tmp2[i] ^ opc[i]; - tmp1[15] ^= 1; /* XOR c2 (= ..01) */ - /* f5 || f2 = E_K(tmp1) XOR OP_c */ - if (aes_128_encrypt_block(k, tmp1, tmp3)) - return -1; - for (i = 0; i < 16; i++) - tmp3[i] ^= opc[i]; - if (res) - os_memcpy(res, tmp3 + 8, 8); /* f2 */ - if (ak) - os_memcpy(ak, tmp3, 6); /* f5 */ - - /* f3 */ - if (ck) { - /* rotate by r3 = 0x20 = 4 bytes */ - for (i = 0; i < 16; i++) - tmp1[(i + 12) % 16] = tmp2[i] ^ opc[i]; - tmp1[15] ^= 2; /* XOR c3 (= ..02) */ - if (aes_128_encrypt_block(k, tmp1, ck)) - return -1; - for (i = 0; i < 16; i++) - ck[i] ^= opc[i]; - } - - /* f4 */ - if (ik) { - /* rotate by r4 = 0x40 = 8 bytes */ - for (i = 0; i < 16; i++) - tmp1[(i + 8) % 16] = tmp2[i] ^ opc[i]; - tmp1[15] ^= 4; /* XOR c4 (= ..04) */ - if (aes_128_encrypt_block(k, tmp1, ik)) - return -1; - for (i = 0; i < 16; i++) - ik[i] ^= opc[i]; - } - - /* f5* */ - if (akstar) { - /* rotate by r5 = 0x60 = 12 bytes */ - for (i = 0; i < 16; i++) - tmp1[(i + 4) % 16] = tmp2[i] ^ opc[i]; - tmp1[15] ^= 8; /* XOR c5 (= ..08) */ - if (aes_128_encrypt_block(k, tmp1, tmp1)) - return -1; - for (i = 0; i < 6; i++) - akstar[i] = tmp1[i] ^ opc[i]; - } - - return 0; -} - - -/** - * milenage_generate - Generate AKA AUTN,IK,CK,RES - * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) - * @amf: AMF = 16-bit authentication management field - * @k: K = 128-bit subscriber key - * @sqn: SQN = 48-bit sequence number - * @_rand: RAND = 128-bit random challenge - * @autn: Buffer for AUTN = 128-bit authentication token - * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL - * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL - * @res: Buffer for RES = 64-bit signed response (f2), or %NULL - * @res_len: Max length for res; set to used length or 0 on failure - */ -void milenage_generate(const u8 *opc, const u8 *amf, const u8 *k, - const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik, - u8 *ck, u8 *res, size_t *res_len) -{ - int i; - u8 mac_a[8], ak[6]; - - if (*res_len < 8) { - *res_len = 0; - return; - } - if (milenage_f1(opc, k, _rand, sqn, amf, mac_a, NULL) || - milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL)) { - *res_len = 0; - return; - } - *res_len = 8; - - /* AUTN = (SQN ^ AK) || AMF || MAC */ - for (i = 0; i < 6; i++) - autn[i] = sqn[i] ^ ak[i]; - os_memcpy(autn + 6, amf, 2); - os_memcpy(autn + 8, mac_a, 8); -} - - -/** - * milenage_auts - Milenage AUTS validation - * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) - * @k: K = 128-bit subscriber key - * @_rand: RAND = 128-bit random challenge - * @auts: AUTS = 112-bit authentication token from client - * @sqn: Buffer for SQN = 48-bit sequence number - * Returns: 0 = success (sqn filled), -1 on failure - */ -int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts, - u8 *sqn) -{ - u8 amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */ - u8 ak[6], mac_s[8]; - int i; - - if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak)) - return -1; - for (i = 0; i < 6; i++) - sqn[i] = auts[i] ^ ak[i]; - if (milenage_f1(opc, k, _rand, sqn, amf, NULL, mac_s) || - memcmp(mac_s, auts + 6, 8) != 0) - return -1; - return 0; -} - - -/** - * gsm_milenage - Generate GSM-Milenage (3GPP TS 55.205) authentication triplet - * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) - * @k: K = 128-bit subscriber key - * @_rand: RAND = 128-bit random challenge - * @sres: Buffer for SRES = 32-bit SRES - * @kc: Buffer for Kc = 64-bit Kc - * Returns: 0 on success, -1 on failure - */ -int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc) -{ - u8 res[8], ck[16], ik[16]; - int i; - - if (milenage_f2345(opc, k, _rand, res, ck, ik, NULL, NULL)) - return -1; - - for (i = 0; i < 8; i++) - kc[i] = ck[i] ^ ck[i + 8] ^ ik[i] ^ ik[i + 8]; - -#ifdef GSM_MILENAGE_ALT_SRES - os_memcpy(sres, res, 4); -#else /* GSM_MILENAGE_ALT_SRES */ - for (i = 0; i < 4; i++) - sres[i] = res[i] ^ res[i + 4]; -#endif /* GSM_MILENAGE_ALT_SRES */ - return 0; -} - - -/** - * milenage_generate - Generate AKA AUTN,IK,CK,RES - * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) - * @k: K = 128-bit subscriber key - * @sqn: SQN = 48-bit sequence number - * @_rand: RAND = 128-bit random challenge - * @autn: AUTN = 128-bit authentication token - * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL - * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL - * @res: Buffer for RES = 64-bit signed response (f2), or %NULL - * @res_len: Variable that will be set to RES length - * @auts: 112-bit buffer for AUTS - * Returns: 0 on success, -1 on failure, or -2 on synchronization failure - */ -int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand, - const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len, - u8 *auts) -{ - int i; - u8 mac_a[8], ak[6], rx_sqn[6]; - const u8 *amf; - - wpa_hexdump(MSG_DEBUG, "Milenage: AUTN", autn, 16); - wpa_hexdump(MSG_DEBUG, "Milenage: RAND", _rand, 16); - - if (milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL)) - return -1; - - *res_len = 8; - wpa_hexdump_key(MSG_DEBUG, "Milenage: RES", res, *res_len); - wpa_hexdump_key(MSG_DEBUG, "Milenage: CK", ck, 16); - wpa_hexdump_key(MSG_DEBUG, "Milenage: IK", ik, 16); - wpa_hexdump_key(MSG_DEBUG, "Milenage: AK", ak, 6); - - /* AUTN = (SQN ^ AK) || AMF || MAC */ - for (i = 0; i < 6; i++) - rx_sqn[i] = autn[i] ^ ak[i]; - wpa_hexdump(MSG_DEBUG, "Milenage: SQN", rx_sqn, 6); - - if (os_memcmp(rx_sqn, sqn, 6) <= 0) { - u8 auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */ - if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak)) - return -1; - wpa_hexdump_key(MSG_DEBUG, "Milenage: AK*", ak, 6); - for (i = 0; i < 6; i++) - auts[i] = sqn[i] ^ ak[i]; - if (milenage_f1(opc, k, _rand, sqn, auts_amf, NULL, auts + 6)) - return -1; - wpa_hexdump(MSG_DEBUG, "Milenage: AUTS", auts, 14); - return -2; - } - - amf = autn + 6; - wpa_hexdump(MSG_DEBUG, "Milenage: AMF", amf, 2); - if (milenage_f1(opc, k, _rand, rx_sqn, amf, mac_a, NULL)) - return -1; - - wpa_hexdump(MSG_DEBUG, "Milenage: MAC_A", mac_a, 8); - - if (os_memcmp(mac_a, autn + 8, 8) != 0) { - wpa_printf(MSG_DEBUG, "Milenage: MAC mismatch"); - wpa_hexdump(MSG_DEBUG, "Milenage: Received MAC_A", - autn + 8, 8); - return -1; - } - - return 0; -} - - -#ifdef TEST_MAIN_MILENAGE - -extern int wpa_debug_level; - - -/** - * milenage_opc - Determine OPc from OP and K - * @op: OP = 128-bit operator variant algorithm configuration field - * @k: K = 128-bit subscriber key - * @opc: Buffer for OPc = 128-bit value derived from OP and K - */ -static void milenage_opc(const u8 *op, const u8 *k, u8 *opc) -{ - int i; - /* OP_C = OP XOR E_K(OP) */ - aes_128_encrypt_block(k, op, opc); - for (i = 0; i < 16; i++) - opc[i] ^= op[i]; -} - - -struct gsm_milenage_test_set { - u8 ki[16]; - u8 rand[16]; - u8 opc[16]; - u8 sres1[4]; - u8 sres2[4]; - u8 kc[8]; -}; - -static const struct gsm_milenage_test_set gsm_test_sets[] = -{ - { - /* 3GPP TS 55.205 v6.0.0 - Test Set 1 */ - { 0x46, 0x5b, 0x5c, 0xe8, 0xb1, 0x99, 0xb4, 0x9f, - 0xaa, 0x5f, 0x0a, 0x2e, 0xe2, 0x38, 0xa6, 0xbc }, - { 0x23, 0x55, 0x3c, 0xbe, 0x96, 0x37, 0xa8, 0x9d, - 0x21, 0x8a, 0xe6, 0x4d, 0xae, 0x47, 0xbf, 0x35 }, - { 0xcd, 0x63, 0xcb, 0x71, 0x95, 0x4a, 0x9f, 0x4e, - 0x48, 0xa5, 0x99, 0x4e, 0x37, 0xa0, 0x2b, 0xaf }, - { 0x46, 0xf8, 0x41, 0x6a }, - { 0xa5, 0x42, 0x11, 0xd5 }, - { 0xea, 0xe4, 0xbe, 0x82, 0x3a, 0xf9, 0xa0, 0x8b } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 2 */ - { 0xfe, 0xc8, 0x6b, 0xa6, 0xeb, 0x70, 0x7e, 0xd0, - 0x89, 0x05, 0x75, 0x7b, 0x1b, 0xb4, 0x4b, 0x8f }, - { 0x9f, 0x7c, 0x8d, 0x02, 0x1a, 0xcc, 0xf4, 0xdb, - 0x21, 0x3c, 0xcf, 0xf0, 0xc7, 0xf7, 0x1a, 0x6a }, - { 0x10, 0x06, 0x02, 0x0f, 0x0a, 0x47, 0x8b, 0xf6, - 0xb6, 0x99, 0xf1, 0x5c, 0x06, 0x2e, 0x42, 0xb3 }, - { 0x8c, 0x30, 0x8a, 0x5e }, - { 0x80, 0x11, 0xc4, 0x8c }, - { 0xaa, 0x01, 0x73, 0x9b, 0x8c, 0xaa, 0x97, 0x6d } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 3 */ - { 0x9e, 0x59, 0x44, 0xae, 0xa9, 0x4b, 0x81, 0x16, - 0x5c, 0x82, 0xfb, 0xf9, 0xf3, 0x2d, 0xb7, 0x51 }, - { 0xce, 0x83, 0xdb, 0xc5, 0x4a, 0xc0, 0x27, 0x4a, - 0x15, 0x7c, 0x17, 0xf8, 0x0d, 0x01, 0x7b, 0xd6 }, - { 0xa6, 0x4a, 0x50, 0x7a, 0xe1, 0xa2, 0xa9, 0x8b, - 0xb8, 0x8e, 0xb4, 0x21, 0x01, 0x35, 0xdc, 0x87 }, - { 0xcf, 0xbc, 0xe3, 0xfe }, - { 0xf3, 0x65, 0xcd, 0x68 }, - { 0x9a, 0x8e, 0xc9, 0x5f, 0x40, 0x8c, 0xc5, 0x07 } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 4 */ - { 0x4a, 0xb1, 0xde, 0xb0, 0x5c, 0xa6, 0xce, 0xb0, - 0x51, 0xfc, 0x98, 0xe7, 0x7d, 0x02, 0x6a, 0x84 }, - { 0x74, 0xb0, 0xcd, 0x60, 0x31, 0xa1, 0xc8, 0x33, - 0x9b, 0x2b, 0x6c, 0xe2, 0xb8, 0xc4, 0xa1, 0x86 }, - { 0xdc, 0xf0, 0x7c, 0xbd, 0x51, 0x85, 0x52, 0x90, - 0xb9, 0x2a, 0x07, 0xa9, 0x89, 0x1e, 0x52, 0x3e }, - { 0x96, 0x55, 0xe2, 0x65 }, - { 0x58, 0x60, 0xfc, 0x1b }, - { 0xcd, 0xc1, 0xdc, 0x08, 0x41, 0xb8, 0x1a, 0x22 } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 5 */ - { 0x6c, 0x38, 0xa1, 0x16, 0xac, 0x28, 0x0c, 0x45, - 0x4f, 0x59, 0x33, 0x2e, 0xe3, 0x5c, 0x8c, 0x4f }, - { 0xee, 0x64, 0x66, 0xbc, 0x96, 0x20, 0x2c, 0x5a, - 0x55, 0x7a, 0xbb, 0xef, 0xf8, 0xba, 0xbf, 0x63 }, - { 0x38, 0x03, 0xef, 0x53, 0x63, 0xb9, 0x47, 0xc6, - 0xaa, 0xa2, 0x25, 0xe5, 0x8f, 0xae, 0x39, 0x34 }, - { 0x13, 0x68, 0x8f, 0x17 }, - { 0x16, 0xc8, 0x23, 0x3f }, - { 0xdf, 0x75, 0xbc, 0x5e, 0xa8, 0x99, 0x87, 0x9f } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 6 */ - { 0x2d, 0x60, 0x9d, 0x4d, 0xb0, 0xac, 0x5b, 0xf0, - 0xd2, 0xc0, 0xde, 0x26, 0x70, 0x14, 0xde, 0x0d }, - { 0x19, 0x4a, 0xa7, 0x56, 0x01, 0x38, 0x96, 0xb7, - 0x4b, 0x4a, 0x2a, 0x3b, 0x0a, 0xf4, 0x53, 0x9e }, - { 0xc3, 0x5a, 0x0a, 0xb0, 0xbc, 0xbf, 0xc9, 0x25, - 0x2c, 0xaf, 0xf1, 0x5f, 0x24, 0xef, 0xbd, 0xe0 }, - { 0x55, 0x3d, 0x00, 0xb3 }, - { 0x8c, 0x25, 0xa1, 0x6c }, - { 0x84, 0xb4, 0x17, 0xae, 0x3a, 0xea, 0xb4, 0xf3 } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 7 */ - { 0xa5, 0x30, 0xa7, 0xfe, 0x42, 0x8f, 0xad, 0x10, - 0x82, 0xc4, 0x5e, 0xdd, 0xfc, 0xe1, 0x38, 0x84 }, - { 0x3a, 0x4c, 0x2b, 0x32, 0x45, 0xc5, 0x0e, 0xb5, - 0xc7, 0x1d, 0x08, 0x63, 0x93, 0x95, 0x76, 0x4d }, - { 0x27, 0x95, 0x3e, 0x49, 0xbc, 0x8a, 0xf6, 0xdc, - 0xc6, 0xe7, 0x30, 0xeb, 0x80, 0x28, 0x6b, 0xe3 }, - { 0x59, 0xf1, 0xa4, 0x4a }, - { 0xa6, 0x32, 0x41, 0xe1 }, - { 0x3b, 0x4e, 0x24, 0x4c, 0xdc, 0x60, 0xce, 0x03 } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 8 */ - { 0xd9, 0x15, 0x1c, 0xf0, 0x48, 0x96, 0xe2, 0x58, - 0x30, 0xbf, 0x2e, 0x08, 0x26, 0x7b, 0x83, 0x60 }, - { 0xf7, 0x61, 0xe5, 0xe9, 0x3d, 0x60, 0x3f, 0xeb, - 0x73, 0x0e, 0x27, 0x55, 0x6c, 0xb8, 0xa2, 0xca }, - { 0xc4, 0xc9, 0x3e, 0xff, 0xe8, 0xa0, 0x81, 0x38, - 0xc2, 0x03, 0xd4, 0xc2, 0x7c, 0xe4, 0xe3, 0xd9 }, - { 0x50, 0x58, 0x88, 0x61 }, - { 0x4a, 0x90, 0xb2, 0x17 }, - { 0x8d, 0x4e, 0xc0, 0x1d, 0xe5, 0x97, 0xac, 0xfe } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 9 */ - { 0xa0, 0xe2, 0x97, 0x1b, 0x68, 0x22, 0xe8, 0xd3, - 0x54, 0xa1, 0x8c, 0xc2, 0x35, 0x62, 0x4e, 0xcb }, - { 0x08, 0xef, 0xf8, 0x28, 0xb1, 0x3f, 0xdb, 0x56, - 0x27, 0x22, 0xc6, 0x5c, 0x7f, 0x30, 0xa9, 0xb2 }, - { 0x82, 0xa2, 0x6f, 0x22, 0xbb, 0xa9, 0xe9, 0x48, - 0x8f, 0x94, 0x9a, 0x10, 0xd9, 0x8e, 0x9c, 0xc4 }, - { 0xcd, 0xe6, 0xb0, 0x27 }, - { 0x4b, 0xc2, 0x21, 0x2d }, - { 0xd8, 0xde, 0xbc, 0x4f, 0xfb, 0xcd, 0x60, 0xaa } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 10 */ - { 0x0d, 0xa6, 0xf7, 0xba, 0x86, 0xd5, 0xea, 0xc8, - 0xa1, 0x9c, 0xf5, 0x63, 0xac, 0x58, 0x64, 0x2d }, - { 0x67, 0x9a, 0xc4, 0xdb, 0xac, 0xd7, 0xd2, 0x33, - 0xff, 0x9d, 0x68, 0x06, 0xf4, 0x14, 0x9c, 0xe3 }, - { 0x0d, 0xb1, 0x07, 0x1f, 0x87, 0x67, 0x56, 0x2c, - 0xa4, 0x3a, 0x0a, 0x64, 0xc4, 0x1e, 0x8d, 0x08 }, - { 0x02, 0xd1, 0x3a, 0xcd }, - { 0x6f, 0xc3, 0x0f, 0xee }, - { 0xf0, 0xea, 0xa5, 0x0a, 0x1e, 0xdc, 0xeb, 0xb7 } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 11 */ - { 0x77, 0xb4, 0x58, 0x43, 0xc8, 0x8e, 0x58, 0xc1, - 0x0d, 0x20, 0x26, 0x84, 0x51, 0x5e, 0xd4, 0x30 }, - { 0x4c, 0x47, 0xeb, 0x30, 0x76, 0xdc, 0x55, 0xfe, - 0x51, 0x06, 0xcb, 0x20, 0x34, 0xb8, 0xcd, 0x78 }, - { 0xd4, 0x83, 0xaf, 0xae, 0x56, 0x24, 0x09, 0xa3, - 0x26, 0xb5, 0xbb, 0x0b, 0x20, 0xc4, 0xd7, 0x62 }, - { 0x44, 0x38, 0x9d, 0x01 }, - { 0xae, 0xfa, 0x35, 0x7b }, - { 0x82, 0xdb, 0xab, 0x7f, 0x83, 0xf0, 0x63, 0xda } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 12 */ - { 0x72, 0x9b, 0x17, 0x72, 0x92, 0x70, 0xdd, 0x87, - 0xcc, 0xdf, 0x1b, 0xfe, 0x29, 0xb4, 0xe9, 0xbb }, - { 0x31, 0x1c, 0x4c, 0x92, 0x97, 0x44, 0xd6, 0x75, - 0xb7, 0x20, 0xf3, 0xb7, 0xe9, 0xb1, 0xcb, 0xd0 }, - { 0x22, 0x8c, 0x2f, 0x2f, 0x06, 0xac, 0x32, 0x68, - 0xa9, 0xe6, 0x16, 0xee, 0x16, 0xdb, 0x4b, 0xa1 }, - { 0x03, 0xe0, 0xfd, 0x84 }, - { 0x98, 0xdb, 0xbd, 0x09 }, - { 0x3c, 0x66, 0xcb, 0x98, 0xca, 0xb2, 0xd3, 0x3d } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 13 */ - { 0xd3, 0x2d, 0xd2, 0x3e, 0x89, 0xdc, 0x66, 0x23, - 0x54, 0xca, 0x12, 0xeb, 0x79, 0xdd, 0x32, 0xfa }, - { 0xcf, 0x7d, 0x0a, 0xb1, 0xd9, 0x43, 0x06, 0x95, - 0x0b, 0xf1, 0x20, 0x18, 0xfb, 0xd4, 0x68, 0x87 }, - { 0xd2, 0x2a, 0x4b, 0x41, 0x80, 0xa5, 0x32, 0x57, - 0x08, 0xa5, 0xff, 0x70, 0xd9, 0xf6, 0x7e, 0xc7 }, - { 0xbe, 0x73, 0xb3, 0xdc }, - { 0xaf, 0x4a, 0x41, 0x1e }, - { 0x96, 0x12, 0xb5, 0xd8, 0x8a, 0x41, 0x30, 0xbb } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 14 */ - { 0xaf, 0x7c, 0x65, 0xe1, 0x92, 0x72, 0x21, 0xde, - 0x59, 0x11, 0x87, 0xa2, 0xc5, 0x98, 0x7a, 0x53 }, - { 0x1f, 0x0f, 0x85, 0x78, 0x46, 0x4f, 0xd5, 0x9b, - 0x64, 0xbe, 0xd2, 0xd0, 0x94, 0x36, 0xb5, 0x7a }, - { 0xa4, 0xcf, 0x5c, 0x81, 0x55, 0xc0, 0x8a, 0x7e, - 0xff, 0x41, 0x8e, 0x54, 0x43, 0xb9, 0x8e, 0x55 }, - { 0x8f, 0xe0, 0x19, 0xc7 }, - { 0x7b, 0xff, 0xa5, 0xc2 }, - { 0x75, 0xa1, 0x50, 0xdf, 0x3c, 0x6a, 0xed, 0x08 } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 15 */ - { 0x5b, 0xd7, 0xec, 0xd3, 0xd3, 0x12, 0x7a, 0x41, - 0xd1, 0x25, 0x39, 0xbe, 0xd4, 0xe7, 0xcf, 0x71 }, - { 0x59, 0xb7, 0x5f, 0x14, 0x25, 0x1c, 0x75, 0x03, - 0x1d, 0x0b, 0xcb, 0xac, 0x1c, 0x2c, 0x04, 0xc7 }, - { 0x76, 0x08, 0x9d, 0x3c, 0x0f, 0xf3, 0xef, 0xdc, - 0x6e, 0x36, 0x72, 0x1d, 0x4f, 0xce, 0xb7, 0x47 }, - { 0x27, 0x20, 0x2b, 0x82 }, - { 0x7e, 0x3f, 0x44, 0xc7 }, - { 0xb7, 0xf9, 0x2e, 0x42, 0x6a, 0x36, 0xfe, 0xc5 } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 16 */ - { 0x6c, 0xd1, 0xc6, 0xce, 0xb1, 0xe0, 0x1e, 0x14, - 0xf1, 0xb8, 0x23, 0x16, 0xa9, 0x0b, 0x7f, 0x3d }, - { 0xf6, 0x9b, 0x78, 0xf3, 0x00, 0xa0, 0x56, 0x8b, - 0xce, 0x9f, 0x0c, 0xb9, 0x3c, 0x4b, 0xe4, 0xc9 }, - { 0xa2, 0x19, 0xdc, 0x37, 0xf1, 0xdc, 0x7d, 0x66, - 0x73, 0x8b, 0x58, 0x43, 0xc7, 0x99, 0xf2, 0x06 }, - { 0xdd, 0xd7, 0xef, 0xe6 }, - { 0x70, 0xf6, 0xbd, 0xb9 }, - { 0x88, 0xd9, 0xde, 0x10, 0xa2, 0x20, 0x04, 0xc5 } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 17 */ - { 0xb7, 0x3a, 0x90, 0xcb, 0xcf, 0x3a, 0xfb, 0x62, - 0x2d, 0xba, 0x83, 0xc5, 0x8a, 0x84, 0x15, 0xdf }, - { 0xb1, 0x20, 0xf1, 0xc1, 0xa0, 0x10, 0x2a, 0x2f, - 0x50, 0x7d, 0xd5, 0x43, 0xde, 0x68, 0x28, 0x1f }, - { 0xdf, 0x0c, 0x67, 0x86, 0x8f, 0xa2, 0x5f, 0x74, - 0x8b, 0x70, 0x44, 0xc6, 0xe7, 0xc2, 0x45, 0xb8 }, - { 0x67, 0xe4, 0xff, 0x3f }, - { 0x47, 0x9d, 0xd2, 0x5c }, - { 0xa8, 0x19, 0xe5, 0x77, 0xa8, 0xd6, 0x17, 0x5b } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 18 */ - { 0x51, 0x22, 0x25, 0x02, 0x14, 0xc3, 0x3e, 0x72, - 0x3a, 0x5d, 0xd5, 0x23, 0xfc, 0x14, 0x5f, 0xc0 }, - { 0x81, 0xe9, 0x2b, 0x6c, 0x0e, 0xe0, 0xe1, 0x2e, - 0xbc, 0xeb, 0xa8, 0xd9, 0x2a, 0x99, 0xdf, 0xa5 }, - { 0x98, 0x1d, 0x46, 0x4c, 0x7c, 0x52, 0xeb, 0x6e, - 0x50, 0x36, 0x23, 0x49, 0x84, 0xad, 0x0b, 0xcf }, - { 0x8a, 0x3b, 0x8d, 0x17 }, - { 0x28, 0xd7, 0xb0, 0xf2 }, - { 0x9a, 0x8d, 0x0e, 0x88, 0x3f, 0xf0, 0x88, 0x7a } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 19 */ - { 0x90, 0xdc, 0xa4, 0xed, 0xa4, 0x5b, 0x53, 0xcf, - 0x0f, 0x12, 0xd7, 0xc9, 0xc3, 0xbc, 0x6a, 0x89 }, - { 0x9f, 0xdd, 0xc7, 0x20, 0x92, 0xc6, 0xad, 0x03, - 0x6b, 0x6e, 0x46, 0x47, 0x89, 0x31, 0x5b, 0x78 }, - { 0xcb, 0x9c, 0xcc, 0xc4, 0xb9, 0x25, 0x8e, 0x6d, - 0xca, 0x47, 0x60, 0x37, 0x9f, 0xb8, 0x25, 0x81 }, - { 0xdf, 0x58, 0x52, 0x2f }, - { 0xa9, 0x51, 0x00, 0xe2 }, - { 0xed, 0x29, 0xb2, 0xf1, 0xc2, 0x7f, 0x9f, 0x34 } - } -}; - -#define NUM_GSM_TESTS (sizeof(gsm_test_sets) / sizeof(gsm_test_sets[0])) - - -struct milenage_test_set { - u8 k[16]; - u8 rand[16]; - u8 sqn[6]; - u8 amf[2]; - u8 op[16]; - u8 opc[16]; - u8 f1[8]; - u8 f1star[8]; - u8 f2[8]; - u8 f3[16]; - u8 f4[16]; - u8 f5[6]; - u8 f5star[6]; -}; - -static const struct milenage_test_set test_sets[] = -{ - { - /* 3GPP TS 35.208 v6.0.0 - 4.3.1 Test Set 1 */ - { 0x46, 0x5b, 0x5c, 0xe8, 0xb1, 0x99, 0xb4, 0x9f, - 0xaa, 0x5f, 0x0a, 0x2e, 0xe2, 0x38, 0xa6, 0xbc }, - { 0x23, 0x55, 0x3c, 0xbe, 0x96, 0x37, 0xa8, 0x9d, - 0x21, 0x8a, 0xe6, 0x4d, 0xae, 0x47, 0xbf, 0x35 }, - { 0xff, 0x9b, 0xb4, 0xd0, 0xb6, 0x07 }, - { 0xb9, 0xb9 }, - { 0xcd, 0xc2, 0x02, 0xd5, 0x12, 0x3e, 0x20, 0xf6, - 0x2b, 0x6d, 0x67, 0x6a, 0xc7, 0x2c, 0xb3, 0x18 }, - { 0xcd, 0x63, 0xcb, 0x71, 0x95, 0x4a, 0x9f, 0x4e, - 0x48, 0xa5, 0x99, 0x4e, 0x37, 0xa0, 0x2b, 0xaf }, - { 0x4a, 0x9f, 0xfa, 0xc3, 0x54, 0xdf, 0xaf, 0xb3 }, - { 0x01, 0xcf, 0xaf, 0x9e, 0xc4, 0xe8, 0x71, 0xe9 }, - { 0xa5, 0x42, 0x11, 0xd5, 0xe3, 0xba, 0x50, 0xbf }, - { 0xb4, 0x0b, 0xa9, 0xa3, 0xc5, 0x8b, 0x2a, 0x05, - 0xbb, 0xf0, 0xd9, 0x87, 0xb2, 0x1b, 0xf8, 0xcb }, - { 0xf7, 0x69, 0xbc, 0xd7, 0x51, 0x04, 0x46, 0x04, - 0x12, 0x76, 0x72, 0x71, 0x1c, 0x6d, 0x34, 0x41 }, - { 0xaa, 0x68, 0x9c, 0x64, 0x83, 0x70 }, - { 0x45, 0x1e, 0x8b, 0xec, 0xa4, 0x3b } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.2 Test Set 2 */ - { 0x46, 0x5b, 0x5c, 0xe8, 0xb1, 0x99, 0xb4, 0x9f, - 0xaa, 0x5f, 0x0a, 0x2e, 0xe2, 0x38, 0xa6, 0xbc }, - { 0x23, 0x55, 0x3c, 0xbe, 0x96, 0x37, 0xa8, 0x9d, - 0x21, 0x8a, 0xe6, 0x4d, 0xae, 0x47, 0xbf, 0x35 }, - { 0xff, 0x9b, 0xb4, 0xd0, 0xb6, 0x07 }, - { 0xb9, 0xb9 }, - { 0xcd, 0xc2, 0x02, 0xd5, 0x12, 0x3e, 0x20, 0xf6, - 0x2b, 0x6d, 0x67, 0x6a, 0xc7, 0x2c, 0xb3, 0x18 }, - { 0xcd, 0x63, 0xcb, 0x71, 0x95, 0x4a, 0x9f, 0x4e, - 0x48, 0xa5, 0x99, 0x4e, 0x37, 0xa0, 0x2b, 0xaf }, - { 0x4a, 0x9f, 0xfa, 0xc3, 0x54, 0xdf, 0xaf, 0xb3 }, - { 0x01, 0xcf, 0xaf, 0x9e, 0xc4, 0xe8, 0x71, 0xe9 }, - { 0xa5, 0x42, 0x11, 0xd5, 0xe3, 0xba, 0x50, 0xbf }, - { 0xb4, 0x0b, 0xa9, 0xa3, 0xc5, 0x8b, 0x2a, 0x05, - 0xbb, 0xf0, 0xd9, 0x87, 0xb2, 0x1b, 0xf8, 0xcb }, - { 0xf7, 0x69, 0xbc, 0xd7, 0x51, 0x04, 0x46, 0x04, - 0x12, 0x76, 0x72, 0x71, 0x1c, 0x6d, 0x34, 0x41 }, - { 0xaa, 0x68, 0x9c, 0x64, 0x83, 0x70 }, - { 0x45, 0x1e, 0x8b, 0xec, 0xa4, 0x3b } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.3 Test Set 3 */ - { 0xfe, 0xc8, 0x6b, 0xa6, 0xeb, 0x70, 0x7e, 0xd0, - 0x89, 0x05, 0x75, 0x7b, 0x1b, 0xb4, 0x4b, 0x8f }, - { 0x9f, 0x7c, 0x8d, 0x02, 0x1a, 0xcc, 0xf4, 0xdb, - 0x21, 0x3c, 0xcf, 0xf0, 0xc7, 0xf7, 0x1a, 0x6a }, - { 0x9d, 0x02, 0x77, 0x59, 0x5f, 0xfc }, - { 0x72, 0x5c }, - { 0xdb, 0xc5, 0x9a, 0xdc, 0xb6, 0xf9, 0xa0, 0xef, - 0x73, 0x54, 0x77, 0xb7, 0xfa, 0xdf, 0x83, 0x74 }, - { 0x10, 0x06, 0x02, 0x0f, 0x0a, 0x47, 0x8b, 0xf6, - 0xb6, 0x99, 0xf1, 0x5c, 0x06, 0x2e, 0x42, 0xb3 }, - { 0x9c, 0xab, 0xc3, 0xe9, 0x9b, 0xaf, 0x72, 0x81 }, - { 0x95, 0x81, 0x4b, 0xa2, 0xb3, 0x04, 0x43, 0x24 }, - { 0x80, 0x11, 0xc4, 0x8c, 0x0c, 0x21, 0x4e, 0xd2 }, - { 0x5d, 0xbd, 0xbb, 0x29, 0x54, 0xe8, 0xf3, 0xcd, - 0xe6, 0x65, 0xb0, 0x46, 0x17, 0x9a, 0x50, 0x98 }, - { 0x59, 0xa9, 0x2d, 0x3b, 0x47, 0x6a, 0x04, 0x43, - 0x48, 0x70, 0x55, 0xcf, 0x88, 0xb2, 0x30, 0x7b }, - { 0x33, 0x48, 0x4d, 0xc2, 0x13, 0x6b }, - { 0xde, 0xac, 0xdd, 0x84, 0x8c, 0xc6 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.4 Test Set 4 */ - { 0x9e, 0x59, 0x44, 0xae, 0xa9, 0x4b, 0x81, 0x16, - 0x5c, 0x82, 0xfb, 0xf9, 0xf3, 0x2d, 0xb7, 0x51 }, - { 0xce, 0x83, 0xdb, 0xc5, 0x4a, 0xc0, 0x27, 0x4a, - 0x15, 0x7c, 0x17, 0xf8, 0x0d, 0x01, 0x7b, 0xd6 }, - { 0x0b, 0x60, 0x4a, 0x81, 0xec, 0xa8 }, - { 0x9e, 0x09 }, - { 0x22, 0x30, 0x14, 0xc5, 0x80, 0x66, 0x94, 0xc0, - 0x07, 0xca, 0x1e, 0xee, 0xf5, 0x7f, 0x00, 0x4f }, - { 0xa6, 0x4a, 0x50, 0x7a, 0xe1, 0xa2, 0xa9, 0x8b, - 0xb8, 0x8e, 0xb4, 0x21, 0x01, 0x35, 0xdc, 0x87 }, - { 0x74, 0xa5, 0x82, 0x20, 0xcb, 0xa8, 0x4c, 0x49 }, - { 0xac, 0x2c, 0xc7, 0x4a, 0x96, 0x87, 0x18, 0x37 }, - { 0xf3, 0x65, 0xcd, 0x68, 0x3c, 0xd9, 0x2e, 0x96 }, - { 0xe2, 0x03, 0xed, 0xb3, 0x97, 0x15, 0x74, 0xf5, - 0xa9, 0x4b, 0x0d, 0x61, 0xb8, 0x16, 0x34, 0x5d }, - { 0x0c, 0x45, 0x24, 0xad, 0xea, 0xc0, 0x41, 0xc4, - 0xdd, 0x83, 0x0d, 0x20, 0x85, 0x4f, 0xc4, 0x6b }, - { 0xf0, 0xb9, 0xc0, 0x8a, 0xd0, 0x2e }, - { 0x60, 0x85, 0xa8, 0x6c, 0x6f, 0x63 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.5 Test Set 5 */ - { 0x4a, 0xb1, 0xde, 0xb0, 0x5c, 0xa6, 0xce, 0xb0, - 0x51, 0xfc, 0x98, 0xe7, 0x7d, 0x02, 0x6a, 0x84 }, - { 0x74, 0xb0, 0xcd, 0x60, 0x31, 0xa1, 0xc8, 0x33, - 0x9b, 0x2b, 0x6c, 0xe2, 0xb8, 0xc4, 0xa1, 0x86 }, - { 0xe8, 0x80, 0xa1, 0xb5, 0x80, 0xb6 }, - { 0x9f, 0x07 }, - { 0x2d, 0x16, 0xc5, 0xcd, 0x1f, 0xdf, 0x6b, 0x22, - 0x38, 0x35, 0x84, 0xe3, 0xbe, 0xf2, 0xa8, 0xd8 }, - { 0xdc, 0xf0, 0x7c, 0xbd, 0x51, 0x85, 0x52, 0x90, - 0xb9, 0x2a, 0x07, 0xa9, 0x89, 0x1e, 0x52, 0x3e }, - { 0x49, 0xe7, 0x85, 0xdd, 0x12, 0x62, 0x6e, 0xf2 }, - { 0x9e, 0x85, 0x79, 0x03, 0x36, 0xbb, 0x3f, 0xa2 }, - { 0x58, 0x60, 0xfc, 0x1b, 0xce, 0x35, 0x1e, 0x7e }, - { 0x76, 0x57, 0x76, 0x6b, 0x37, 0x3d, 0x1c, 0x21, - 0x38, 0xf3, 0x07, 0xe3, 0xde, 0x92, 0x42, 0xf9 }, - { 0x1c, 0x42, 0xe9, 0x60, 0xd8, 0x9b, 0x8f, 0xa9, - 0x9f, 0x27, 0x44, 0xe0, 0x70, 0x8c, 0xcb, 0x53 }, - { 0x31, 0xe1, 0x1a, 0x60, 0x91, 0x18 }, - { 0xfe, 0x25, 0x55, 0xe5, 0x4a, 0xa9 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.6 Test Set 6 */ - { 0x6c, 0x38, 0xa1, 0x16, 0xac, 0x28, 0x0c, 0x45, - 0x4f, 0x59, 0x33, 0x2e, 0xe3, 0x5c, 0x8c, 0x4f }, - { 0xee, 0x64, 0x66, 0xbc, 0x96, 0x20, 0x2c, 0x5a, - 0x55, 0x7a, 0xbb, 0xef, 0xf8, 0xba, 0xbf, 0x63 }, - { 0x41, 0x4b, 0x98, 0x22, 0x21, 0x81 }, - { 0x44, 0x64 }, - { 0x1b, 0xa0, 0x0a, 0x1a, 0x7c, 0x67, 0x00, 0xac, - 0x8c, 0x3f, 0xf3, 0xe9, 0x6a, 0xd0, 0x87, 0x25 }, - { 0x38, 0x03, 0xef, 0x53, 0x63, 0xb9, 0x47, 0xc6, - 0xaa, 0xa2, 0x25, 0xe5, 0x8f, 0xae, 0x39, 0x34 }, - { 0x07, 0x8a, 0xdf, 0xb4, 0x88, 0x24, 0x1a, 0x57 }, - { 0x80, 0x24, 0x6b, 0x8d, 0x01, 0x86, 0xbc, 0xf1 }, - { 0x16, 0xc8, 0x23, 0x3f, 0x05, 0xa0, 0xac, 0x28 }, - { 0x3f, 0x8c, 0x75, 0x87, 0xfe, 0x8e, 0x4b, 0x23, - 0x3a, 0xf6, 0x76, 0xae, 0xde, 0x30, 0xba, 0x3b }, - { 0xa7, 0x46, 0x6c, 0xc1, 0xe6, 0xb2, 0xa1, 0x33, - 0x7d, 0x49, 0xd3, 0xb6, 0x6e, 0x95, 0xd7, 0xb4 }, - { 0x45, 0xb0, 0xf6, 0x9a, 0xb0, 0x6c }, - { 0x1f, 0x53, 0xcd, 0x2b, 0x11, 0x13 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.7 Test Set 7 */ - { 0x2d, 0x60, 0x9d, 0x4d, 0xb0, 0xac, 0x5b, 0xf0, - 0xd2, 0xc0, 0xde, 0x26, 0x70, 0x14, 0xde, 0x0d }, - { 0x19, 0x4a, 0xa7, 0x56, 0x01, 0x38, 0x96, 0xb7, - 0x4b, 0x4a, 0x2a, 0x3b, 0x0a, 0xf4, 0x53, 0x9e }, - { 0x6b, 0xf6, 0x94, 0x38, 0xc2, 0xe4 }, - { 0x5f, 0x67 }, - { 0x46, 0x0a, 0x48, 0x38, 0x54, 0x27, 0xaa, 0x39, - 0x26, 0x4a, 0xac, 0x8e, 0xfc, 0x9e, 0x73, 0xe8 }, - { 0xc3, 0x5a, 0x0a, 0xb0, 0xbc, 0xbf, 0xc9, 0x25, - 0x2c, 0xaf, 0xf1, 0x5f, 0x24, 0xef, 0xbd, 0xe0 }, - { 0xbd, 0x07, 0xd3, 0x00, 0x3b, 0x9e, 0x5c, 0xc3 }, - { 0xbc, 0xb6, 0xc2, 0xfc, 0xad, 0x15, 0x22, 0x50 }, - { 0x8c, 0x25, 0xa1, 0x6c, 0xd9, 0x18, 0xa1, 0xdf }, - { 0x4c, 0xd0, 0x84, 0x60, 0x20, 0xf8, 0xfa, 0x07, - 0x31, 0xdd, 0x47, 0xcb, 0xdc, 0x6b, 0xe4, 0x11 }, - { 0x88, 0xab, 0x80, 0xa4, 0x15, 0xf1, 0x5c, 0x73, - 0x71, 0x12, 0x54, 0xa1, 0xd3, 0x88, 0xf6, 0x96 }, - { 0x7e, 0x64, 0x55, 0xf3, 0x4c, 0xf3 }, - { 0xdc, 0x6d, 0xd0, 0x1e, 0x8f, 0x15 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.8 Test Set 8 */ - { 0xa5, 0x30, 0xa7, 0xfe, 0x42, 0x8f, 0xad, 0x10, - 0x82, 0xc4, 0x5e, 0xdd, 0xfc, 0xe1, 0x38, 0x84 }, - { 0x3a, 0x4c, 0x2b, 0x32, 0x45, 0xc5, 0x0e, 0xb5, - 0xc7, 0x1d, 0x08, 0x63, 0x93, 0x95, 0x76, 0x4d }, - { 0xf6, 0x3f, 0x5d, 0x76, 0x87, 0x84 }, - { 0xb9, 0x0e }, - { 0x51, 0x1c, 0x6c, 0x4e, 0x83, 0xe3, 0x8c, 0x89, - 0xb1, 0xc5, 0xd8, 0xdd, 0xe6, 0x24, 0x26, 0xfa }, - { 0x27, 0x95, 0x3e, 0x49, 0xbc, 0x8a, 0xf6, 0xdc, - 0xc6, 0xe7, 0x30, 0xeb, 0x80, 0x28, 0x6b, 0xe3 }, - { 0x53, 0x76, 0x1f, 0xbd, 0x67, 0x9b, 0x0b, 0xad }, - { 0x21, 0xad, 0xfd, 0x33, 0x4a, 0x10, 0xe7, 0xce }, - { 0xa6, 0x32, 0x41, 0xe1, 0xff, 0xc3, 0xe5, 0xab }, - { 0x10, 0xf0, 0x5b, 0xab, 0x75, 0xa9, 0x9a, 0x5f, - 0xbb, 0x98, 0xa9, 0xc2, 0x87, 0x67, 0x9c, 0x3b }, - { 0xf9, 0xec, 0x08, 0x65, 0xeb, 0x32, 0xf2, 0x23, - 0x69, 0xca, 0xde, 0x40, 0xc5, 0x9c, 0x3a, 0x44 }, - { 0x88, 0x19, 0x6c, 0x47, 0x98, 0x6f }, - { 0xc9, 0x87, 0xa3, 0xd2, 0x31, 0x15 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.9 Test Set 9 */ - { 0xd9, 0x15, 0x1c, 0xf0, 0x48, 0x96, 0xe2, 0x58, - 0x30, 0xbf, 0x2e, 0x08, 0x26, 0x7b, 0x83, 0x60 }, - { 0xf7, 0x61, 0xe5, 0xe9, 0x3d, 0x60, 0x3f, 0xeb, - 0x73, 0x0e, 0x27, 0x55, 0x6c, 0xb8, 0xa2, 0xca }, - { 0x47, 0xee, 0x01, 0x99, 0x82, 0x0a }, - { 0x91, 0x13 }, - { 0x75, 0xfc, 0x22, 0x33, 0xa4, 0x42, 0x94, 0xee, - 0x8e, 0x6d, 0xe2, 0x5c, 0x43, 0x53, 0xd2, 0x6b }, - { 0xc4, 0xc9, 0x3e, 0xff, 0xe8, 0xa0, 0x81, 0x38, - 0xc2, 0x03, 0xd4, 0xc2, 0x7c, 0xe4, 0xe3, 0xd9 }, - { 0x66, 0xcc, 0x4b, 0xe4, 0x48, 0x62, 0xaf, 0x1f }, - { 0x7a, 0x4b, 0x8d, 0x7a, 0x87, 0x53, 0xf2, 0x46 }, - { 0x4a, 0x90, 0xb2, 0x17, 0x1a, 0xc8, 0x3a, 0x76 }, - { 0x71, 0x23, 0x6b, 0x71, 0x29, 0xf9, 0xb2, 0x2a, - 0xb7, 0x7e, 0xa7, 0xa5, 0x4c, 0x96, 0xda, 0x22 }, - { 0x90, 0x52, 0x7e, 0xba, 0xa5, 0x58, 0x89, 0x68, - 0xdb, 0x41, 0x72, 0x73, 0x25, 0xa0, 0x4d, 0x9e }, - { 0x82, 0xa0, 0xf5, 0x28, 0x7a, 0x71 }, - { 0x52, 0x7d, 0xbf, 0x41, 0xf3, 0x5f } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.10 Test Set 10 */ - { 0xa0, 0xe2, 0x97, 0x1b, 0x68, 0x22, 0xe8, 0xd3, - 0x54, 0xa1, 0x8c, 0xc2, 0x35, 0x62, 0x4e, 0xcb }, - { 0x08, 0xef, 0xf8, 0x28, 0xb1, 0x3f, 0xdb, 0x56, - 0x27, 0x22, 0xc6, 0x5c, 0x7f, 0x30, 0xa9, 0xb2 }, - { 0xdb, 0x5c, 0x06, 0x64, 0x81, 0xe0 }, - { 0x71, 0x6b }, - { 0x32, 0x37, 0x92, 0xfa, 0xca, 0x21, 0xfb, 0x4d, - 0x5d, 0x6f, 0x13, 0xc1, 0x45, 0xa9, 0xd2, 0xc1 }, - { 0x82, 0xa2, 0x6f, 0x22, 0xbb, 0xa9, 0xe9, 0x48, - 0x8f, 0x94, 0x9a, 0x10, 0xd9, 0x8e, 0x9c, 0xc4 }, - { 0x94, 0x85, 0xfe, 0x24, 0x62, 0x1c, 0xb9, 0xf6 }, - { 0xbc, 0xe3, 0x25, 0xce, 0x03, 0xe2, 0xe9, 0xb9 }, - { 0x4b, 0xc2, 0x21, 0x2d, 0x86, 0x24, 0x91, 0x0a }, - { 0x08, 0xce, 0xf6, 0xd0, 0x04, 0xec, 0x61, 0x47, - 0x1a, 0x3c, 0x3c, 0xda, 0x04, 0x81, 0x37, 0xfa }, - { 0xed, 0x03, 0x18, 0xca, 0x5d, 0xeb, 0x92, 0x06, - 0x27, 0x2f, 0x6e, 0x8f, 0xa6, 0x4b, 0xa4, 0x11 }, - { 0xa2, 0xf8, 0x58, 0xaa, 0x9e, 0x5d }, - { 0x74, 0xe7, 0x6f, 0xbb, 0xec, 0x38 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.11 Test Set 11 */ - { 0x0d, 0xa6, 0xf7, 0xba, 0x86, 0xd5, 0xea, 0xc8, - 0xa1, 0x9c, 0xf5, 0x63, 0xac, 0x58, 0x64, 0x2d }, - { 0x67, 0x9a, 0xc4, 0xdb, 0xac, 0xd7, 0xd2, 0x33, - 0xff, 0x9d, 0x68, 0x06, 0xf4, 0x14, 0x9c, 0xe3 }, - { 0x6e, 0x23, 0x31, 0xd6, 0x92, 0xad }, - { 0x22, 0x4a }, - { 0x4b, 0x9a, 0x26, 0xfa, 0x45, 0x9e, 0x3a, 0xcb, - 0xff, 0x36, 0xf4, 0x01, 0x5d, 0xe3, 0xbd, 0xc1 }, - { 0x0d, 0xb1, 0x07, 0x1f, 0x87, 0x67, 0x56, 0x2c, - 0xa4, 0x3a, 0x0a, 0x64, 0xc4, 0x1e, 0x8d, 0x08 }, - { 0x28, 0x31, 0xd7, 0xae, 0x90, 0x88, 0xe4, 0x92 }, - { 0x9b, 0x2e, 0x16, 0x95, 0x11, 0x35, 0xd5, 0x23 }, - { 0x6f, 0xc3, 0x0f, 0xee, 0x6d, 0x12, 0x35, 0x23 }, - { 0x69, 0xb1, 0xca, 0xe7, 0xc7, 0x42, 0x9d, 0x97, - 0x5e, 0x24, 0x5c, 0xac, 0xb0, 0x5a, 0x51, 0x7c }, - { 0x74, 0xf2, 0x4e, 0x8c, 0x26, 0xdf, 0x58, 0xe1, - 0xb3, 0x8d, 0x7d, 0xcd, 0x4f, 0x1b, 0x7f, 0xbd }, - { 0x4c, 0x53, 0x9a, 0x26, 0xe1, 0xfa }, - { 0x07, 0x86, 0x1e, 0x12, 0x69, 0x28 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.12 Test Set 12 */ - { 0x77, 0xb4, 0x58, 0x43, 0xc8, 0x8e, 0x58, 0xc1, - 0x0d, 0x20, 0x26, 0x84, 0x51, 0x5e, 0xd4, 0x30 }, - { 0x4c, 0x47, 0xeb, 0x30, 0x76, 0xdc, 0x55, 0xfe, - 0x51, 0x06, 0xcb, 0x20, 0x34, 0xb8, 0xcd, 0x78 }, - { 0xfe, 0x1a, 0x87, 0x31, 0x00, 0x5d }, - { 0xad, 0x25 }, - { 0xbf, 0x32, 0x86, 0xc7, 0xa5, 0x14, 0x09, 0xce, - 0x95, 0x72, 0x4d, 0x50, 0x3b, 0xfe, 0x6e, 0x70 }, - { 0xd4, 0x83, 0xaf, 0xae, 0x56, 0x24, 0x09, 0xa3, - 0x26, 0xb5, 0xbb, 0x0b, 0x20, 0xc4, 0xd7, 0x62 }, - { 0x08, 0x33, 0x2d, 0x7e, 0x9f, 0x48, 0x45, 0x70 }, - { 0xed, 0x41, 0xb7, 0x34, 0x48, 0x9d, 0x52, 0x07 }, - { 0xae, 0xfa, 0x35, 0x7b, 0xea, 0xc2, 0xa8, 0x7a }, - { 0x90, 0x8c, 0x43, 0xf0, 0x56, 0x9c, 0xb8, 0xf7, - 0x4b, 0xc9, 0x71, 0xe7, 0x06, 0xc3, 0x6c, 0x5f }, - { 0xc2, 0x51, 0xdf, 0x0d, 0x88, 0x8d, 0xd9, 0x32, - 0x9b, 0xcf, 0x46, 0x65, 0x5b, 0x22, 0x6e, 0x40 }, - { 0x30, 0xff, 0x25, 0xcd, 0xad, 0xf6 }, - { 0xe8, 0x4e, 0xd0, 0xd4, 0x67, 0x7e } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.13 Test Set 13 */ - { 0x72, 0x9b, 0x17, 0x72, 0x92, 0x70, 0xdd, 0x87, - 0xcc, 0xdf, 0x1b, 0xfe, 0x29, 0xb4, 0xe9, 0xbb }, - { 0x31, 0x1c, 0x4c, 0x92, 0x97, 0x44, 0xd6, 0x75, - 0xb7, 0x20, 0xf3, 0xb7, 0xe9, 0xb1, 0xcb, 0xd0 }, - { 0xc8, 0x5c, 0x4c, 0xf6, 0x59, 0x16 }, - { 0x5b, 0xb2 }, - { 0xd0, 0x4c, 0x9c, 0x35, 0xbd, 0x22, 0x62, 0xfa, - 0x81, 0x0d, 0x29, 0x24, 0xd0, 0x36, 0xfd, 0x13 }, - { 0x22, 0x8c, 0x2f, 0x2f, 0x06, 0xac, 0x32, 0x68, - 0xa9, 0xe6, 0x16, 0xee, 0x16, 0xdb, 0x4b, 0xa1 }, - { 0xff, 0x79, 0x4f, 0xe2, 0xf8, 0x27, 0xeb, 0xf8 }, - { 0x24, 0xfe, 0x4d, 0xc6, 0x1e, 0x87, 0x4b, 0x52 }, - { 0x98, 0xdb, 0xbd, 0x09, 0x9b, 0x3b, 0x40, 0x8d }, - { 0x44, 0xc0, 0xf2, 0x3c, 0x54, 0x93, 0xcf, 0xd2, - 0x41, 0xe4, 0x8f, 0x19, 0x7e, 0x1d, 0x10, 0x12 }, - { 0x0c, 0x9f, 0xb8, 0x16, 0x13, 0x88, 0x4c, 0x25, - 0x35, 0xdd, 0x0e, 0xab, 0xf3, 0xb4, 0x40, 0xd8 }, - { 0x53, 0x80, 0xd1, 0x58, 0xcf, 0xe3 }, - { 0x87, 0xac, 0x3b, 0x55, 0x9f, 0xb6 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.14 Test Set 14 */ - { 0xd3, 0x2d, 0xd2, 0x3e, 0x89, 0xdc, 0x66, 0x23, - 0x54, 0xca, 0x12, 0xeb, 0x79, 0xdd, 0x32, 0xfa }, - { 0xcf, 0x7d, 0x0a, 0xb1, 0xd9, 0x43, 0x06, 0x95, - 0x0b, 0xf1, 0x20, 0x18, 0xfb, 0xd4, 0x68, 0x87 }, - { 0x48, 0x41, 0x07, 0xe5, 0x6a, 0x43 }, - { 0xb5, 0xe6 }, - { 0xfe, 0x75, 0x90, 0x5b, 0x9d, 0xa4, 0x7d, 0x35, - 0x62, 0x36, 0xd0, 0x31, 0x4e, 0x09, 0xc3, 0x2e }, - { 0xd2, 0x2a, 0x4b, 0x41, 0x80, 0xa5, 0x32, 0x57, - 0x08, 0xa5, 0xff, 0x70, 0xd9, 0xf6, 0x7e, 0xc7 }, - { 0xcf, 0x19, 0xd6, 0x2b, 0x6a, 0x80, 0x98, 0x66 }, - { 0x5d, 0x26, 0x95, 0x37, 0xe4, 0x5e, 0x2c, 0xe6 }, - { 0xaf, 0x4a, 0x41, 0x1e, 0x11, 0x39, 0xf2, 0xc2 }, - { 0x5a, 0xf8, 0x6b, 0x80, 0xed, 0xb7, 0x0d, 0xf5, - 0x29, 0x2c, 0xc1, 0x12, 0x1c, 0xba, 0xd5, 0x0c }, - { 0x7f, 0x4d, 0x6a, 0xe7, 0x44, 0x0e, 0x18, 0x78, - 0x9a, 0x8b, 0x75, 0xad, 0x3f, 0x42, 0xf0, 0x3a }, - { 0x21, 0x7a, 0xf4, 0x92, 0x72, 0xad }, - { 0x90, 0x0e, 0x10, 0x1c, 0x67, 0x7e } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.15 Test Set 15 */ - { 0xaf, 0x7c, 0x65, 0xe1, 0x92, 0x72, 0x21, 0xde, - 0x59, 0x11, 0x87, 0xa2, 0xc5, 0x98, 0x7a, 0x53 }, - { 0x1f, 0x0f, 0x85, 0x78, 0x46, 0x4f, 0xd5, 0x9b, - 0x64, 0xbe, 0xd2, 0xd0, 0x94, 0x36, 0xb5, 0x7a }, - { 0x3d, 0x62, 0x7b, 0x01, 0x41, 0x8d }, - { 0x84, 0xf6 }, - { 0x0c, 0x7a, 0xcb, 0x8d, 0x95, 0xb7, 0xd4, 0xa3, - 0x1c, 0x5a, 0xca, 0x6d, 0x26, 0x34, 0x5a, 0x88 }, - { 0xa4, 0xcf, 0x5c, 0x81, 0x55, 0xc0, 0x8a, 0x7e, - 0xff, 0x41, 0x8e, 0x54, 0x43, 0xb9, 0x8e, 0x55 }, - { 0xc3, 0x7c, 0xae, 0x78, 0x05, 0x64, 0x20, 0x32 }, - { 0x68, 0xcd, 0x09, 0xa4, 0x52, 0xd8, 0xdb, 0x7c }, - { 0x7b, 0xff, 0xa5, 0xc2, 0xf4, 0x1f, 0xbc, 0x05 }, - { 0x3f, 0x8c, 0x3f, 0x3c, 0xcf, 0x76, 0x25, 0xbf, - 0x77, 0xfc, 0x94, 0xbc, 0xfd, 0x22, 0xfd, 0x26 }, - { 0xab, 0xcb, 0xae, 0x8f, 0xd4, 0x61, 0x15, 0xe9, - 0x96, 0x1a, 0x55, 0xd0, 0xda, 0x5f, 0x20, 0x78 }, - { 0x83, 0x7f, 0xd7, 0xb7, 0x44, 0x19 }, - { 0x56, 0xe9, 0x7a, 0x60, 0x90, 0xb1 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.16 Test Set 16 */ - { 0x5b, 0xd7, 0xec, 0xd3, 0xd3, 0x12, 0x7a, 0x41, - 0xd1, 0x25, 0x39, 0xbe, 0xd4, 0xe7, 0xcf, 0x71 }, - { 0x59, 0xb7, 0x5f, 0x14, 0x25, 0x1c, 0x75, 0x03, - 0x1d, 0x0b, 0xcb, 0xac, 0x1c, 0x2c, 0x04, 0xc7 }, - { 0xa2, 0x98, 0xae, 0x89, 0x29, 0xdc }, - { 0xd0, 0x56 }, - { 0xf9, 0x67, 0xf7, 0x60, 0x38, 0xb9, 0x20, 0xa9, - 0xcd, 0x25, 0xe1, 0x0c, 0x08, 0xb4, 0x99, 0x24 }, - { 0x76, 0x08, 0x9d, 0x3c, 0x0f, 0xf3, 0xef, 0xdc, - 0x6e, 0x36, 0x72, 0x1d, 0x4f, 0xce, 0xb7, 0x47 }, - { 0xc3, 0xf2, 0x5c, 0xd9, 0x43, 0x09, 0x10, 0x7e }, - { 0xb0, 0xc8, 0xba, 0x34, 0x36, 0x65, 0xaf, 0xcc }, - { 0x7e, 0x3f, 0x44, 0xc7, 0x59, 0x1f, 0x6f, 0x45 }, - { 0xd4, 0x2b, 0x2d, 0x61, 0x5e, 0x49, 0xa0, 0x3a, - 0xc2, 0x75, 0xa5, 0xae, 0xf9, 0x7a, 0xf8, 0x92 }, - { 0x0b, 0x3f, 0x8d, 0x02, 0x4f, 0xe6, 0xbf, 0xaf, - 0xaa, 0x98, 0x2b, 0x8f, 0x82, 0xe3, 0x19, 0xc2 }, - { 0x5b, 0xe1, 0x14, 0x95, 0x52, 0x5d }, - { 0x4d, 0x6a, 0x34, 0xa1, 0xe4, 0xeb } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.17 Test Set 17 */ - { 0x6c, 0xd1, 0xc6, 0xce, 0xb1, 0xe0, 0x1e, 0x14, - 0xf1, 0xb8, 0x23, 0x16, 0xa9, 0x0b, 0x7f, 0x3d }, - { 0xf6, 0x9b, 0x78, 0xf3, 0x00, 0xa0, 0x56, 0x8b, - 0xce, 0x9f, 0x0c, 0xb9, 0x3c, 0x4b, 0xe4, 0xc9 }, - { 0xb4, 0xfc, 0xe5, 0xfe, 0xb0, 0x59 }, - { 0xe4, 0xbb }, - { 0x07, 0x8b, 0xfc, 0xa9, 0x56, 0x46, 0x59, 0xec, - 0xd8, 0x85, 0x1e, 0x84, 0xe6, 0xc5, 0x9b, 0x48 }, - { 0xa2, 0x19, 0xdc, 0x37, 0xf1, 0xdc, 0x7d, 0x66, - 0x73, 0x8b, 0x58, 0x43, 0xc7, 0x99, 0xf2, 0x06 }, - { 0x69, 0xa9, 0x08, 0x69, 0xc2, 0x68, 0xcb, 0x7b }, - { 0x2e, 0x0f, 0xdc, 0xf9, 0xfd, 0x1c, 0xfa, 0x6a }, - { 0x70, 0xf6, 0xbd, 0xb9, 0xad, 0x21, 0x52, 0x5f }, - { 0x6e, 0xda, 0xf9, 0x9e, 0x5b, 0xd9, 0xf8, 0x5d, - 0x5f, 0x36, 0xd9, 0x1c, 0x12, 0x72, 0xfb, 0x4b }, - { 0xd6, 0x1c, 0x85, 0x3c, 0x28, 0x0d, 0xd9, 0xc4, - 0x6f, 0x29, 0x7b, 0xae, 0xc3, 0x86, 0xde, 0x17 }, - { 0x1c, 0x40, 0x8a, 0x85, 0x8b, 0x3e }, - { 0xaa, 0x4a, 0xe5, 0x2d, 0xaa, 0x30 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.18 Test Set 18 */ - { 0xb7, 0x3a, 0x90, 0xcb, 0xcf, 0x3a, 0xfb, 0x62, - 0x2d, 0xba, 0x83, 0xc5, 0x8a, 0x84, 0x15, 0xdf }, - { 0xb1, 0x20, 0xf1, 0xc1, 0xa0, 0x10, 0x2a, 0x2f, - 0x50, 0x7d, 0xd5, 0x43, 0xde, 0x68, 0x28, 0x1f }, - { 0xf1, 0xe8, 0xa5, 0x23, 0xa3, 0x6d }, - { 0x47, 0x1b }, - { 0xb6, 0x72, 0x04, 0x7e, 0x00, 0x3b, 0xb9, 0x52, - 0xdc, 0xa6, 0xcb, 0x8a, 0xf0, 0xe5, 0xb7, 0x79 }, - { 0xdf, 0x0c, 0x67, 0x86, 0x8f, 0xa2, 0x5f, 0x74, - 0x8b, 0x70, 0x44, 0xc6, 0xe7, 0xc2, 0x45, 0xb8 }, - { 0xeb, 0xd7, 0x03, 0x41, 0xbc, 0xd4, 0x15, 0xb0 }, - { 0x12, 0x35, 0x9f, 0x5d, 0x82, 0x22, 0x0c, 0x14 }, - { 0x47, 0x9d, 0xd2, 0x5c, 0x20, 0x79, 0x2d, 0x63 }, - { 0x66, 0x19, 0x5d, 0xbe, 0xd0, 0x31, 0x32, 0x74, - 0xc5, 0xca, 0x77, 0x66, 0x61, 0x5f, 0xa2, 0x5e }, - { 0x66, 0xbe, 0xc7, 0x07, 0xeb, 0x2a, 0xfc, 0x47, - 0x6d, 0x74, 0x08, 0xa8, 0xf2, 0x92, 0x7b, 0x36 }, - { 0xae, 0xfd, 0xaa, 0x5d, 0xdd, 0x99 }, - { 0x12, 0xec, 0x2b, 0x87, 0xfb, 0xb1 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.19 Test Set 19 */ - { 0x51, 0x22, 0x25, 0x02, 0x14, 0xc3, 0x3e, 0x72, - 0x3a, 0x5d, 0xd5, 0x23, 0xfc, 0x14, 0x5f, 0xc0 }, - { 0x81, 0xe9, 0x2b, 0x6c, 0x0e, 0xe0, 0xe1, 0x2e, - 0xbc, 0xeb, 0xa8, 0xd9, 0x2a, 0x99, 0xdf, 0xa5 }, - { 0x16, 0xf3, 0xb3, 0xf7, 0x0f, 0xc2 }, - { 0xc3, 0xab }, - { 0xc9, 0xe8, 0x76, 0x32, 0x86, 0xb5, 0xb9, 0xff, - 0xbd, 0xf5, 0x6e, 0x12, 0x97, 0xd0, 0x88, 0x7b }, - { 0x98, 0x1d, 0x46, 0x4c, 0x7c, 0x52, 0xeb, 0x6e, - 0x50, 0x36, 0x23, 0x49, 0x84, 0xad, 0x0b, 0xcf }, - { 0x2a, 0x5c, 0x23, 0xd1, 0x5e, 0xe3, 0x51, 0xd5 }, - { 0x62, 0xda, 0xe3, 0x85, 0x3f, 0x3a, 0xf9, 0xd2 }, - { 0x28, 0xd7, 0xb0, 0xf2, 0xa2, 0xec, 0x3d, 0xe5 }, - { 0x53, 0x49, 0xfb, 0xe0, 0x98, 0x64, 0x9f, 0x94, - 0x8f, 0x5d, 0x2e, 0x97, 0x3a, 0x81, 0xc0, 0x0f }, - { 0x97, 0x44, 0x87, 0x1a, 0xd3, 0x2b, 0xf9, 0xbb, - 0xd1, 0xdd, 0x5c, 0xe5, 0x4e, 0x3e, 0x2e, 0x5a }, - { 0xad, 0xa1, 0x5a, 0xeb, 0x7b, 0xb8 }, - { 0xd4, 0x61, 0xbc, 0x15, 0x47, 0x5d } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.20 Test Set 20 */ - { 0x90, 0xdc, 0xa4, 0xed, 0xa4, 0x5b, 0x53, 0xcf, - 0x0f, 0x12, 0xd7, 0xc9, 0xc3, 0xbc, 0x6a, 0x89 }, - { 0x9f, 0xdd, 0xc7, 0x20, 0x92, 0xc6, 0xad, 0x03, - 0x6b, 0x6e, 0x46, 0x47, 0x89, 0x31, 0x5b, 0x78 }, - { 0x20, 0xf8, 0x13, 0xbd, 0x41, 0x41 }, - { 0x61, 0xdf }, - { 0x3f, 0xfc, 0xfe, 0x5b, 0x7b, 0x11, 0x11, 0x58, - 0x99, 0x20, 0xd3, 0x52, 0x8e, 0x84, 0xe6, 0x55 }, - { 0xcb, 0x9c, 0xcc, 0xc4, 0xb9, 0x25, 0x8e, 0x6d, - 0xca, 0x47, 0x60, 0x37, 0x9f, 0xb8, 0x25, 0x81 }, - { 0x09, 0xdb, 0x94, 0xea, 0xb4, 0xf8, 0x14, 0x9e }, - { 0xa2, 0x94, 0x68, 0xaa, 0x97, 0x75, 0xb5, 0x27 }, - { 0xa9, 0x51, 0x00, 0xe2, 0x76, 0x09, 0x52, 0xcd }, - { 0xb5, 0xf2, 0xda, 0x03, 0x88, 0x3b, 0x69, 0xf9, - 0x6b, 0xf5, 0x2e, 0x02, 0x9e, 0xd9, 0xac, 0x45 }, - { 0xb4, 0x72, 0x13, 0x68, 0xbc, 0x16, 0xea, 0x67, - 0x87, 0x5c, 0x55, 0x98, 0x68, 0x8b, 0xb0, 0xef }, - { 0x83, 0xcf, 0xd5, 0x4d, 0xb9, 0x13 }, - { 0x4f, 0x20, 0x39, 0x39, 0x2d, 0xdc } - } -}; - -#define NUM_TESTS (sizeof(test_sets) / sizeof(test_sets[0])) - - -int main(int argc, char *argv[]) -{ - u8 buf[16], buf2[16], buf3[16], buf4[16], buf5[16], opc[16]; - u8 auts[14], sqn[6], _rand[16]; - int ret = 0, res, i; - const struct milenage_test_set *t; - size_t res_len; - - wpa_debug_level = 0; - - printf("Milenage test sets\n"); - for (i = 0; i < NUM_TESTS; i++) { - t = &test_sets[i]; - printf("Test Set %d\n", i + 1); - - milenage_opc(t->op, t->k, opc); - if (memcmp(opc, t->opc, 16) != 0) { - printf("- milenage_opc failed\n"); - ret++; - } - - if (milenage_f1(opc, t->k, t->rand, t->sqn, t->amf, buf, buf2) - || memcmp(buf, t->f1, 8) != 0) { - printf("- milenage_f1 failed\n"); - ret++; - } - if (memcmp(buf2, t->f1star, 8) != 0) { - printf("- milenage_f1* failed\n"); - ret++; - } - - if (milenage_f2345(opc, t->k, t->rand, buf, buf2, buf3, buf4, - buf5) || - memcmp(buf, t->f2, 8) != 0) { - printf("- milenage_f2 failed\n"); - ret++; - } - if (memcmp(buf2, t->f3, 16) != 0) { - printf("- milenage_f3 failed\n"); - ret++; - } - if (memcmp(buf3, t->f4, 16) != 0) { - printf("- milenage_f4 failed\n"); - ret++; - } - if (memcmp(buf4, t->f5, 6) != 0) { - printf("- milenage_f5 failed\n"); - ret++; - } - if (memcmp(buf5, t->f5star, 6) != 0) { - printf("- milenage_f5* failed\n"); - ret++; - } - } - - printf("milenage_auts test:\n"); - os_memcpy(auts, "\x4f\x20\x39\x39\x2d\xdd", 6); - os_memcpy(auts + 6, "\x4b\xb4\x31\x6e\xd4\xa1\x46\x88", 8); - res = milenage_auts(t->opc, t->k, t->rand, auts, buf); - printf("AUTS for test set %d: %d / SQN=%02x%02x%02x%02x%02x%02x\n", - i, res, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); - if (res) - ret++; - - os_memset(_rand, 0xaa, sizeof(_rand)); - os_memcpy(auts, - "\x43\x68\x1a\xd3\xda\xf0\x06\xbc\xde\x40\x5a\x20\x72\x67", - 14); - res = milenage_auts(t->opc, t->k, _rand, auts, buf); - printf("AUTS from a test USIM: %d / SQN=%02x%02x%02x%02x%02x%02x\n", - res, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); - if (res) - ret++; - - printf("milenage_generate test:\n"); - os_memcpy(sqn, "\x00\x00\x00\x00\x40\x44", 6); - os_memcpy(_rand, "\x12\x69\xb8\x23\x41\x39\x35\x66\xfb\x99\x41\xe9\x84" - "\x4f\xe6\x2f", 16); - res_len = 8; - milenage_generate(t->opc, t->amf, t->k, sqn, _rand, buf, buf2, buf3, - buf4, &res_len); - wpa_hexdump(MSG_DEBUG, "SQN", sqn, 6); - wpa_hexdump(MSG_DEBUG, "RAND", _rand, 16); - wpa_hexdump(MSG_DEBUG, "AUTN", buf, 16); - wpa_hexdump(MSG_DEBUG, "IK", buf2, 16); - wpa_hexdump(MSG_DEBUG, "CK", buf3, 16); - wpa_hexdump(MSG_DEBUG, "RES", buf4, res_len); - - printf("GSM-Milenage test sets\n"); - for (i = 0; i < NUM_GSM_TESTS; i++) { - const struct gsm_milenage_test_set *g; - u8 sres[4], kc[8]; - g = &gsm_test_sets[i]; - printf("Test Set %d\n", i + 1); - gsm_milenage(g->opc, g->ki, g->rand, sres, kc); - if (memcmp(g->kc, kc, 8) != 0) { - printf("- gsm_milenage Kc failed\n"); - ret++; - } -#ifdef GSM_MILENAGE_ALT_SRES - if (memcmp(g->sres2, sres, 4) != 0) { - printf("- gsm_milenage SRES#2 failed\n"); - ret++; - } -#else /* GSM_MILENAGE_ALT_SRES */ - if (memcmp(g->sres1, sres, 4) != 0) { - printf("- gsm_milenage SRES#1 failed\n"); - ret++; - } -#endif /* GSM_MILENAGE_ALT_SRES */ - } - - if (ret) - printf("Something failed\n"); - else - printf("OK\n"); - - return ret; -} -#endif /* TEST_MAIN_MILENAGE */ diff --git a/contrib/hostapd/src/hlr_auc_gw/milenage.h b/contrib/hostapd/src/hlr_auc_gw/milenage.h deleted file mode 100644 index b35603ca86..0000000000 --- a/contrib/hostapd/src/hlr_auc_gw/milenage.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * UMTS AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208) - * Copyright (c) 2006-2007 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef MILENAGE_H -#define MILENAGE_H - -void milenage_generate(const u8 *opc, const u8 *amf, const u8 *k, - const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik, - u8 *ck, u8 *res, size_t *res_len); -int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts, - u8 *sqn); -int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, - u8 *kc); -int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand, - const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len, - u8 *auts); - -#endif /* MILENAGE_H */ diff --git a/contrib/hostapd/src/l2_packet/l2_packet.h b/contrib/hostapd/src/l2_packet/l2_packet.h deleted file mode 100644 index c7b50141e9..0000000000 --- a/contrib/hostapd/src/l2_packet/l2_packet.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * WPA Supplicant - Layer2 packet interface definition - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file defines an interface for layer 2 (link layer) packet sending and - * receiving. l2_packet_linux.c is one implementation for such a layer 2 - * implementation using Linux packet sockets and l2_packet_pcap.c another one - * using libpcap and libdnet. When porting %wpa_supplicant to other operating - * systems, a new l2_packet implementation may need to be added. - */ - -#ifndef L2_PACKET_H -#define L2_PACKET_H - -/** - * struct l2_packet_data - Internal l2_packet data structure - * - * This structure is used by the l2_packet implementation to store its private - * data. Other files use a pointer to this data when calling the l2_packet - * functions, but the contents of this structure should not be used directly - * outside l2_packet implementation. - */ -struct l2_packet_data; - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct l2_ethhdr { - u8 h_dest[ETH_ALEN]; - u8 h_source[ETH_ALEN]; - be16 h_proto; -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -/** - * l2_packet_init - Initialize l2_packet interface - * @ifname: Interface name - * @own_addr: Optional own MAC address if available from driver interface or - * %NULL if not available - * @protocol: Ethernet protocol number in host byte order - * @rx_callback: Callback function that will be called for each received packet - * @rx_callback_ctx: Callback data (ctx) for calls to rx_callback() - * @l2_hdr: 1 = include layer 2 header, 0 = do not include header - * Returns: Pointer to internal data or %NULL on failure - * - * rx_callback function will be called with src_addr pointing to the source - * address (MAC address) of the the packet. If l2_hdr is set to 0, buf - * points to len bytes of the payload after the layer 2 header and similarly, - * TX buffers start with payload. This behavior can be changed by setting - * l2_hdr=1 to include the layer 2 header in the data buffer. - */ -struct l2_packet_data * l2_packet_init( - const char *ifname, const u8 *own_addr, unsigned short protocol, - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len), - void *rx_callback_ctx, int l2_hdr); - -/** - * l2_packet_deinit - Deinitialize l2_packet interface - * @l2: Pointer to internal l2_packet data from l2_packet_init() - */ -void l2_packet_deinit(struct l2_packet_data *l2); - -/** - * l2_packet_get_own_addr - Get own layer 2 address - * @l2: Pointer to internal l2_packet data from l2_packet_init() - * @addr: Buffer for the own address (6 bytes) - * Returns: 0 on success, -1 on failure - */ -int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr); - -/** - * l2_packet_send - Send a packet - * @l2: Pointer to internal l2_packet data from l2_packet_init() - * @dst_addr: Destination address for the packet (only used if l2_hdr == 0) - * @proto: Protocol/ethertype for the packet in host byte order (only used if - * l2_hdr == 0) - * @buf: Packet contents to be sent; including layer 2 header if l2_hdr was - * set to 1 in l2_packet_init() call. Otherwise, only the payload of the packet - * is included. - * @len: Length of the buffer (including l2 header only if l2_hdr == 1) - * Returns: >=0 on success, <0 on failure - */ -int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, - const u8 *buf, size_t len); - -/** - * l2_packet_get_ip_addr - Get the current IP address from the interface - * @l2: Pointer to internal l2_packet data from l2_packet_init() - * @buf: Buffer for the IP address in text format - * @len: Maximum buffer length - * Returns: 0 on success, -1 on failure - * - * This function can be used to get the current IP address from the interface - * bound to the l2_packet. This is mainly for status information and the IP - * address will be stored as an ASCII string. This function is not essential - * for %wpa_supplicant operation, so full implementation is not required. - * l2_packet implementation will need to define the function, but it can return - * -1 if the IP address information is not available. - */ -int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len); - - -/** - * l2_packet_notify_auth_start - Notify l2_packet about start of authentication - * @l2: Pointer to internal l2_packet data from l2_packet_init() - * - * This function is called when authentication is expected to start, e.g., when - * association has been completed, in order to prepare l2_packet implementation - * for EAPOL frames. This function is used mainly if the l2_packet code needs - * to do polling in which case it can increasing polling frequency. This can - * also be an empty function if the l2_packet implementation does not benefit - * from knowing about the starting authentication. - */ -void l2_packet_notify_auth_start(struct l2_packet_data *l2); - -#endif /* L2_PACKET_H */ diff --git a/contrib/hostapd/src/l2_packet/l2_packet_freebsd.c b/contrib/hostapd/src/l2_packet/l2_packet_freebsd.c deleted file mode 100644 index d1034aa762..0000000000 --- a/contrib/hostapd/src/l2_packet/l2_packet_freebsd.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * WPA Supplicant - Layer2 packet handling with FreeBSD - * Copyright (c) 2003-2005, Jouni Malinen - * Copyright (c) 2005, Sam Leffler - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#ifdef __APPLE__ -#include -#endif /* __APPLE__ */ -#include - -#include -#include - -#include -#include -#include -#include - -#include "common.h" -#include "eloop.h" -#include "l2_packet.h" - - -static const u8 pae_group_addr[ETH_ALEN] = -{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; - -struct l2_packet_data { - pcap_t *pcap; - char ifname[100]; - u8 own_addr[ETH_ALEN]; - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len); - void *rx_callback_ctx; - int l2_hdr; /* whether to include layer 2 (Ethernet) header data - * buffers */ -}; - - -int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) -{ - os_memcpy(addr, l2->own_addr, ETH_ALEN); - return 0; -} - - -int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, - const u8 *buf, size_t len) -{ - if (!l2->l2_hdr) { - int ret; - struct l2_ethhdr *eth = os_malloc(sizeof(*eth) + len); - if (eth == NULL) - return -1; - os_memcpy(eth->h_dest, dst_addr, ETH_ALEN); - os_memcpy(eth->h_source, l2->own_addr, ETH_ALEN); - eth->h_proto = htons(proto); - os_memcpy(eth + 1, buf, len); - ret = pcap_inject(l2->pcap, (u8 *) eth, len + sizeof(*eth)); - os_free(eth); - return ret; - } else - return pcap_inject(l2->pcap, buf, len); -} - - -static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct l2_packet_data *l2 = eloop_ctx; - pcap_t *pcap = sock_ctx; - struct pcap_pkthdr hdr; - const u_char *packet; - struct l2_ethhdr *ethhdr; - unsigned char *buf; - size_t len; - - packet = pcap_next(pcap, &hdr); - - if (packet == NULL || hdr.caplen < sizeof(*ethhdr)) - return; - - ethhdr = (struct l2_ethhdr *) packet; - if (l2->l2_hdr) { - buf = (unsigned char *) ethhdr; - len = hdr.caplen; - } else { - buf = (unsigned char *) (ethhdr + 1); - len = hdr.caplen - sizeof(*ethhdr); - } - l2->rx_callback(l2->rx_callback_ctx, ethhdr->h_source, buf, len); -} - - -static int l2_packet_init_libpcap(struct l2_packet_data *l2, - unsigned short protocol) -{ - bpf_u_int32 pcap_maskp, pcap_netp; - char pcap_filter[200], pcap_err[PCAP_ERRBUF_SIZE]; - struct bpf_program pcap_fp; - - pcap_lookupnet(l2->ifname, &pcap_netp, &pcap_maskp, pcap_err); - l2->pcap = pcap_open_live(l2->ifname, 2500, 0, 10, pcap_err); - if (l2->pcap == NULL) { - fprintf(stderr, "pcap_open_live: %s\n", pcap_err); - fprintf(stderr, "ifname='%s'\n", l2->ifname); - return -1; - } - if (pcap_datalink(l2->pcap) != DLT_EN10MB && - pcap_set_datalink(l2->pcap, DLT_EN10MB) < 0) { - fprintf(stderr, "pcap_set_datalink(DLT_EN10MB): %s\n", - pcap_geterr(l2->pcap)); - return -1; - } - os_snprintf(pcap_filter, sizeof(pcap_filter), - "not ether src " MACSTR " and " - "( ether dst " MACSTR " or ether dst " MACSTR " ) and " - "ether proto 0x%x", - MAC2STR(l2->own_addr), /* do not receive own packets */ - MAC2STR(l2->own_addr), MAC2STR(pae_group_addr), - protocol); - if (pcap_compile(l2->pcap, &pcap_fp, pcap_filter, 1, pcap_netp) < 0) { - fprintf(stderr, "pcap_compile: %s\n", pcap_geterr(l2->pcap)); - return -1; - } - - if (pcap_setfilter(l2->pcap, &pcap_fp) < 0) { - fprintf(stderr, "pcap_setfilter: %s\n", pcap_geterr(l2->pcap)); - return -1; - } - - pcap_freecode(&pcap_fp); - /* - * When libpcap uses BPF we must enable "immediate mode" to - * receive frames right away; otherwise the system may - * buffer them for us. - */ - { - unsigned int on = 1; - if (ioctl(pcap_fileno(l2->pcap), BIOCIMMEDIATE, &on) < 0) { - fprintf(stderr, "%s: cannot enable immediate mode on " - "interface %s: %s\n", - __func__, l2->ifname, strerror(errno)); - /* XXX should we fail? */ - } - } - - eloop_register_read_sock(pcap_get_selectable_fd(l2->pcap), - l2_packet_receive, l2, l2->pcap); - - return 0; -} - - -static int eth_get(const char *device, u8 ea[ETH_ALEN]) -{ - struct if_msghdr *ifm; - struct sockaddr_dl *sdl; - u_char *p, *buf; - size_t len; - int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 }; - - if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) - return -1; - if ((buf = os_malloc(len)) == NULL) - return -1; - if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { - os_free(buf); - return -1; - } - for (p = buf; p < buf + len; p += ifm->ifm_msglen) { - ifm = (struct if_msghdr *)p; - sdl = (struct sockaddr_dl *)(ifm + 1); - if (ifm->ifm_type != RTM_IFINFO || - (ifm->ifm_addrs & RTA_IFP) == 0) - continue; - if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 || - os_memcmp(sdl->sdl_data, device, sdl->sdl_nlen) != 0) - continue; - os_memcpy(ea, LLADDR(sdl), sdl->sdl_alen); - break; - } - os_free(buf); - - if (p >= buf + len) { - errno = ESRCH; - return -1; - } - return 0; -} - - -struct l2_packet_data * l2_packet_init( - const char *ifname, const u8 *own_addr, unsigned short protocol, - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len), - void *rx_callback_ctx, int l2_hdr) -{ - struct l2_packet_data *l2; - - l2 = os_zalloc(sizeof(struct l2_packet_data)); - if (l2 == NULL) - return NULL; - os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); - l2->rx_callback = rx_callback; - l2->rx_callback_ctx = rx_callback_ctx; - l2->l2_hdr = l2_hdr; - - if (eth_get(l2->ifname, l2->own_addr) < 0) { - fprintf(stderr, "Failed to get link-level address for " - "interface '%s'.\n", l2->ifname); - os_free(l2); - return NULL; - } - - if (l2_packet_init_libpcap(l2, protocol)) { - os_free(l2); - return NULL; - } - - return l2; -} - - -void l2_packet_deinit(struct l2_packet_data *l2) -{ - if (l2 != NULL) { - if (l2->pcap) { - eloop_unregister_read_sock( - pcap_get_selectable_fd(l2->pcap)); - pcap_close(l2->pcap); - } - os_free(l2); - } -} - - -int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) -{ - pcap_if_t *devs, *dev; - struct pcap_addr *addr; - struct sockaddr_in *saddr; - int found = 0; - char err[PCAP_ERRBUF_SIZE + 1]; - - if (pcap_findalldevs(&devs, err) < 0) { - wpa_printf(MSG_DEBUG, "pcap_findalldevs: %s\n", err); - return -1; - } - - for (dev = devs; dev && !found; dev = dev->next) { - if (os_strcmp(dev->name, l2->ifname) != 0) - continue; - - addr = dev->addresses; - while (addr) { - saddr = (struct sockaddr_in *) addr->addr; - if (saddr && saddr->sin_family == AF_INET) { - os_strlcpy(buf, inet_ntoa(saddr->sin_addr), - len); - found = 1; - break; - } - addr = addr->next; - } - } - - pcap_freealldevs(devs); - - return found ? 0 : -1; -} - - -void l2_packet_notify_auth_start(struct l2_packet_data *l2) -{ -} diff --git a/contrib/hostapd/src/l2_packet/l2_packet_linux.c b/contrib/hostapd/src/l2_packet/l2_packet_linux.c deleted file mode 100644 index 48d1bde024..0000000000 --- a/contrib/hostapd/src/l2_packet/l2_packet_linux.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * WPA Supplicant - Layer2 packet handling with Linux packet sockets - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include -#include - -#include "common.h" -#include "eloop.h" -#include "l2_packet.h" - - -struct l2_packet_data { - int fd; /* packet socket for EAPOL frames */ - char ifname[IFNAMSIZ + 1]; - int ifindex; - u8 own_addr[ETH_ALEN]; - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len); - void *rx_callback_ctx; - int l2_hdr; /* whether to include layer 2 (Ethernet) header data - * buffers */ -}; - - -int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) -{ - os_memcpy(addr, l2->own_addr, ETH_ALEN); - return 0; -} - - -int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, - const u8 *buf, size_t len) -{ - int ret; - if (l2 == NULL) - return -1; - if (l2->l2_hdr) { - ret = send(l2->fd, buf, len, 0); - if (ret < 0) - perror("l2_packet_send - send"); - } else { - struct sockaddr_ll ll; - os_memset(&ll, 0, sizeof(ll)); - ll.sll_family = AF_PACKET; - ll.sll_ifindex = l2->ifindex; - ll.sll_protocol = htons(proto); - ll.sll_halen = ETH_ALEN; - os_memcpy(ll.sll_addr, dst_addr, ETH_ALEN); - ret = sendto(l2->fd, buf, len, 0, (struct sockaddr *) &ll, - sizeof(ll)); - if (ret < 0) - perror("l2_packet_send - sendto"); - } - return ret; -} - - -static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct l2_packet_data *l2 = eloop_ctx; - u8 buf[2300]; - int res; - struct sockaddr_ll ll; - socklen_t fromlen; - - os_memset(&ll, 0, sizeof(ll)); - fromlen = sizeof(ll); - res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &ll, - &fromlen); - if (res < 0) { - perror("l2_packet_receive - recvfrom"); - return; - } - - l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res); -} - - -struct l2_packet_data * l2_packet_init( - const char *ifname, const u8 *own_addr, unsigned short protocol, - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len), - void *rx_callback_ctx, int l2_hdr) -{ - struct l2_packet_data *l2; - struct ifreq ifr; - struct sockaddr_ll ll; - - l2 = os_zalloc(sizeof(struct l2_packet_data)); - if (l2 == NULL) - return NULL; - os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); - l2->rx_callback = rx_callback; - l2->rx_callback_ctx = rx_callback_ctx; - l2->l2_hdr = l2_hdr; - - l2->fd = socket(PF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM, - htons(protocol)); - if (l2->fd < 0) { - perror("socket(PF_PACKET)"); - os_free(l2); - return NULL; - } - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name)); - if (ioctl(l2->fd, SIOCGIFINDEX, &ifr) < 0) { - perror("ioctl[SIOCGIFINDEX]"); - close(l2->fd); - os_free(l2); - return NULL; - } - l2->ifindex = ifr.ifr_ifindex; - - os_memset(&ll, 0, sizeof(ll)); - ll.sll_family = PF_PACKET; - ll.sll_ifindex = ifr.ifr_ifindex; - ll.sll_protocol = htons(protocol); - if (bind(l2->fd, (struct sockaddr *) &ll, sizeof(ll)) < 0) { - perror("bind[PF_PACKET]"); - close(l2->fd); - os_free(l2); - return NULL; - } - - if (ioctl(l2->fd, SIOCGIFHWADDR, &ifr) < 0) { - perror("ioctl[SIOCGIFHWADDR]"); - close(l2->fd); - os_free(l2); - return NULL; - } - os_memcpy(l2->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); - - eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); - - return l2; -} - - -void l2_packet_deinit(struct l2_packet_data *l2) -{ - if (l2 == NULL) - return; - - if (l2->fd >= 0) { - eloop_unregister_read_sock(l2->fd); - close(l2->fd); - } - - os_free(l2); -} - - -int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) -{ - int s; - struct ifreq ifr; - struct sockaddr_in *saddr; - size_t res; - - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s < 0) { - perror("socket"); - return -1; - } - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name)); - if (ioctl(s, SIOCGIFADDR, &ifr) < 0) { - if (errno != EADDRNOTAVAIL) - perror("ioctl[SIOCGIFADDR]"); - close(s); - return -1; - } - close(s); - saddr = aliasing_hide_typecast(&ifr.ifr_addr, struct sockaddr_in); - if (saddr->sin_family != AF_INET) - return -1; - res = os_strlcpy(buf, inet_ntoa(saddr->sin_addr), len); - if (res >= len) - return -1; - return 0; -} - - -void l2_packet_notify_auth_start(struct l2_packet_data *l2) -{ -} diff --git a/contrib/hostapd/src/l2_packet/l2_packet_ndis.c b/contrib/hostapd/src/l2_packet/l2_packet_ndis.c deleted file mode 100644 index 7de58808d6..0000000000 --- a/contrib/hostapd/src/l2_packet/l2_packet_ndis.c +++ /dev/null @@ -1,516 +0,0 @@ -/* - * WPA Supplicant - Layer2 packet handling with Microsoft NDISUIO - * Copyright (c) 2003-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This implementation requires Windows specific event loop implementation, - * i.e., eloop_win.c. In addition, the NDISUIO connection is shared with - * driver_ndis.c, so only that driver interface can be used and - * CONFIG_USE_NDISUIO must be defined. - * - * WinXP version of the code uses overlapped I/O and a single threaded design - * with callback functions from I/O code. WinCE version uses a separate RX - * thread that blocks on ReadFile() whenever the media status is connected. - */ - -#include "includes.h" -#include -#include - -#ifdef _WIN32_WCE -#include -#include -#endif /* _WIN32_WCE */ - -#include "common.h" -#include "eloop.h" -#include "l2_packet.h" - -#ifndef _WIN32_WCE -/* from nuiouser.h */ -#define FSCTL_NDISUIO_BASE FILE_DEVICE_NETWORK -#define _NDISUIO_CTL_CODE(_Function, _Method, _Access) \ - CTL_CODE(FSCTL_NDISUIO_BASE, _Function, _Method, _Access) -#define IOCTL_NDISUIO_SET_ETHER_TYPE \ - _NDISUIO_CTL_CODE(0x202, METHOD_BUFFERED, \ - FILE_READ_ACCESS | FILE_WRITE_ACCESS) -#endif /* _WIN32_WCE */ - -/* From driver_ndis.c to shared the handle to NDISUIO */ -HANDLE driver_ndis_get_ndisuio_handle(void); - -/* - * NDISUIO supports filtering of only one ethertype at the time, so we must - * fake support for two (EAPOL and RSN pre-auth) by switching to pre-auth - * whenever wpa_supplicant is trying to pre-authenticate and then switching - * back to EAPOL when pre-authentication has been completed. - */ - -struct l2_packet_data; - -struct l2_packet_ndisuio_global { - int refcount; - unsigned short first_proto; - struct l2_packet_data *l2[2]; -#ifdef _WIN32_WCE - HANDLE rx_thread; - HANDLE stop_request; - HANDLE ready_for_read; - HANDLE rx_processed; -#endif /* _WIN32_WCE */ -}; - -static struct l2_packet_ndisuio_global *l2_ndisuio_global = NULL; - -struct l2_packet_data { - char ifname[100]; - u8 own_addr[ETH_ALEN]; - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len); - void *rx_callback_ctx; - int l2_hdr; /* whether to include layer 2 (Ethernet) header in calls to - * rx_callback and l2_packet_send() */ - HANDLE rx_avail; -#ifndef _WIN32_WCE - OVERLAPPED rx_overlapped; -#endif /* _WIN32_WCE */ - u8 rx_buf[1514]; - DWORD rx_written; -}; - - -int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) -{ - os_memcpy(addr, l2->own_addr, ETH_ALEN); - return 0; -} - - -int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, - const u8 *buf, size_t len) -{ - BOOL res; - DWORD written; - struct l2_ethhdr *eth; -#ifndef _WIN32_WCE - OVERLAPPED overlapped; -#endif /* _WIN32_WCE */ - OVERLAPPED *o; - - if (l2 == NULL) - return -1; - -#ifdef _WIN32_WCE - o = NULL; -#else /* _WIN32_WCE */ - os_memset(&overlapped, 0, sizeof(overlapped)); - o = &overlapped; -#endif /* _WIN32_WCE */ - - if (l2->l2_hdr) { - res = WriteFile(driver_ndis_get_ndisuio_handle(), buf, len, - &written, o); - } else { - size_t mlen = sizeof(*eth) + len; - eth = os_malloc(mlen); - if (eth == NULL) - return -1; - - os_memcpy(eth->h_dest, dst_addr, ETH_ALEN); - os_memcpy(eth->h_source, l2->own_addr, ETH_ALEN); - eth->h_proto = htons(proto); - os_memcpy(eth + 1, buf, len); - res = WriteFile(driver_ndis_get_ndisuio_handle(), eth, mlen, - &written, o); - os_free(eth); - } - - if (!res) { - DWORD err = GetLastError(); -#ifndef _WIN32_WCE - if (err == ERROR_IO_PENDING) { - /* For now, just assume that the packet will be sent in - * time before the next write happens. This could be - * cleaned up at some point to actually wait for - * completion before starting new writes. - */ - return 0; - } -#endif /* _WIN32_WCE */ - wpa_printf(MSG_DEBUG, "L2(NDISUIO): WriteFile failed: %d", - (int) GetLastError()); - return -1; - } - - return 0; -} - - -static void l2_packet_callback(struct l2_packet_data *l2); - -#ifdef _WIN32_WCE -static void l2_packet_rx_thread_try_read(struct l2_packet_data *l2) -{ - HANDLE handles[2]; - - wpa_printf(MSG_MSGDUMP, "l2_packet_rx_thread: -> ReadFile"); - if (!ReadFile(driver_ndis_get_ndisuio_handle(), l2->rx_buf, - sizeof(l2->rx_buf), &l2->rx_written, NULL)) { - DWORD err = GetLastError(); - wpa_printf(MSG_DEBUG, "l2_packet_rx_thread: ReadFile failed: " - "%d", (int) err); - /* - * ReadFile on NDISUIO/WinCE returns ERROR_DEVICE_NOT_CONNECTED - * error whenever the connection is not up. Yield the thread to - * avoid triggering a busy loop. Connection event should stop - * us from looping for long, but we need to allow enough CPU - * for the main thread to process the media disconnection. - */ - Sleep(100); - return; - } - - wpa_printf(MSG_DEBUG, "l2_packet_rx_thread: Read %d byte packet", - (int) l2->rx_written); - - /* - * Notify the main thread about the availability of a frame and wait - * for the frame to be processed. - */ - SetEvent(l2->rx_avail); - handles[0] = l2_ndisuio_global->stop_request; - handles[1] = l2_ndisuio_global->rx_processed; - WaitForMultipleObjects(2, handles, FALSE, INFINITE); - ResetEvent(l2_ndisuio_global->rx_processed); -} - - -static DWORD WINAPI l2_packet_rx_thread(LPVOID arg) -{ - struct l2_packet_data *l2 = arg; - DWORD res; - HANDLE handles[2]; - int run = 1; - - wpa_printf(MSG_DEBUG, "L2(NDISUIO): RX thread started"); - handles[0] = l2_ndisuio_global->stop_request; - handles[1] = l2_ndisuio_global->ready_for_read; - - /* - * Unfortunately, NDISUIO on WinCE does not seem to support waiting - * on the handle. There do not seem to be anything else that we could - * wait for either. If one were to modify NDISUIO to set a named event - * whenever packets are available, this event could be used here to - * avoid having to poll for new packets or we could even move to use a - * single threaded design. - * - * In addition, NDISUIO on WinCE is returning - * ERROR_DEVICE_NOT_CONNECTED whenever ReadFile() is attempted while - * the adapter is not in connected state. For now, we are just using a - * local event to allow ReadFile calls only after having received NDIS - * media connect event. This event could be easily converted to handle - * another event if the protocol driver is replaced with somewhat more - * useful design. - */ - - while (l2_ndisuio_global && run) { - res = WaitForMultipleObjects(2, handles, FALSE, INFINITE); - switch (res) { - case WAIT_OBJECT_0: - wpa_printf(MSG_DEBUG, "l2_packet_rx_thread: Received " - "request to stop RX thread"); - run = 0; - break; - case WAIT_OBJECT_0 + 1: - l2_packet_rx_thread_try_read(l2); - break; - case WAIT_FAILED: - default: - wpa_printf(MSG_DEBUG, "l2_packet_rx_thread: " - "WaitForMultipleObjects failed: %d", - (int) GetLastError()); - run = 0; - break; - } - } - - wpa_printf(MSG_DEBUG, "L2(NDISUIO): RX thread stopped"); - - return 0; -} -#else /* _WIN32_WCE */ -static int l2_ndisuio_start_read(struct l2_packet_data *l2, int recursive) -{ - os_memset(&l2->rx_overlapped, 0, sizeof(l2->rx_overlapped)); - l2->rx_overlapped.hEvent = l2->rx_avail; - if (!ReadFile(driver_ndis_get_ndisuio_handle(), l2->rx_buf, - sizeof(l2->rx_buf), &l2->rx_written, &l2->rx_overlapped)) - { - DWORD err = GetLastError(); - if (err != ERROR_IO_PENDING) { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): ReadFile failed: " - "%d", (int) err); - return -1; - } - /* - * Once read is completed, l2_packet_rx_event() will be - * called. - */ - } else { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): ReadFile returned data " - "without wait for completion"); - if (!recursive) - l2_packet_callback(l2); - } - - return 0; -} -#endif /* _WIN32_WCE */ - - -static void l2_packet_callback(struct l2_packet_data *l2) -{ - const u8 *rx_buf, *rx_src; - size_t rx_len; - struct l2_ethhdr *ethhdr = (struct l2_ethhdr *) l2->rx_buf; - - wpa_printf(MSG_DEBUG, "L2(NDISUIO): Read %d bytes", - (int) l2->rx_written); - - if (l2->l2_hdr || l2->rx_written < sizeof(*ethhdr)) { - rx_buf = (u8 *) ethhdr; - rx_len = l2->rx_written; - } else { - rx_buf = (u8 *) (ethhdr + 1); - rx_len = l2->rx_written - sizeof(*ethhdr); - } - rx_src = ethhdr->h_source; - - l2->rx_callback(l2->rx_callback_ctx, rx_src, rx_buf, rx_len); -#ifndef _WIN32_WCE - l2_ndisuio_start_read(l2, 1); -#endif /* _WIN32_WCE */ -} - - -static void l2_packet_rx_event(void *eloop_data, void *user_data) -{ - struct l2_packet_data *l2 = eloop_data; - - if (l2_ndisuio_global) - l2 = l2_ndisuio_global->l2[l2_ndisuio_global->refcount - 1]; - - ResetEvent(l2->rx_avail); - -#ifndef _WIN32_WCE - if (!GetOverlappedResult(driver_ndis_get_ndisuio_handle(), - &l2->rx_overlapped, &l2->rx_written, FALSE)) { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): GetOverlappedResult " - "failed: %d", (int) GetLastError()); - return; - } -#endif /* _WIN32_WCE */ - - l2_packet_callback(l2); - -#ifdef _WIN32_WCE - SetEvent(l2_ndisuio_global->rx_processed); -#endif /* _WIN32_WCE */ -} - - -static int l2_ndisuio_set_ether_type(unsigned short protocol) -{ - USHORT proto = htons(protocol); - DWORD written; - - if (!DeviceIoControl(driver_ndis_get_ndisuio_handle(), - IOCTL_NDISUIO_SET_ETHER_TYPE, &proto, - sizeof(proto), NULL, 0, &written, NULL)) { - wpa_printf(MSG_ERROR, "L2(NDISUIO): " - "IOCTL_NDISUIO_SET_ETHER_TYPE failed: %d", - (int) GetLastError()); - return -1; - } - - return 0; -} - - -struct l2_packet_data * l2_packet_init( - const char *ifname, const u8 *own_addr, unsigned short protocol, - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len), - void *rx_callback_ctx, int l2_hdr) -{ - struct l2_packet_data *l2; - - if (l2_ndisuio_global == NULL) { - l2_ndisuio_global = os_zalloc(sizeof(*l2_ndisuio_global)); - if (l2_ndisuio_global == NULL) - return NULL; - l2_ndisuio_global->first_proto = protocol; - } - if (l2_ndisuio_global->refcount >= 2) { - wpa_printf(MSG_ERROR, "L2(NDISUIO): Not more than two " - "simultaneous connections allowed"); - return NULL; - } - l2_ndisuio_global->refcount++; - - l2 = os_zalloc(sizeof(struct l2_packet_data)); - if (l2 == NULL) - return NULL; - l2_ndisuio_global->l2[l2_ndisuio_global->refcount - 1] = l2; - - os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); - l2->rx_callback = rx_callback; - l2->rx_callback_ctx = rx_callback_ctx; - l2->l2_hdr = l2_hdr; - - if (own_addr) - os_memcpy(l2->own_addr, own_addr, ETH_ALEN); - - if (l2_ndisuio_set_ether_type(protocol) < 0) { - os_free(l2); - return NULL; - } - - if (l2_ndisuio_global->refcount > 1) { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): Temporarily setting " - "filtering ethertype to %04x", protocol); - if (l2_ndisuio_global->l2[0]) - l2->rx_avail = l2_ndisuio_global->l2[0]->rx_avail; - return l2; - } - - l2->rx_avail = CreateEvent(NULL, TRUE, FALSE, NULL); - if (l2->rx_avail == NULL) { - os_free(l2); - return NULL; - } - - eloop_register_event(l2->rx_avail, sizeof(l2->rx_avail), - l2_packet_rx_event, l2, NULL); - -#ifdef _WIN32_WCE - l2_ndisuio_global->stop_request = CreateEvent(NULL, TRUE, FALSE, NULL); - /* - * This event is being set based on media connect/disconnect - * notifications in driver_ndis.c. - */ - l2_ndisuio_global->ready_for_read = - CreateEvent(NULL, TRUE, FALSE, TEXT("WpaSupplicantConnected")); - l2_ndisuio_global->rx_processed = CreateEvent(NULL, TRUE, FALSE, NULL); - if (l2_ndisuio_global->stop_request == NULL || - l2_ndisuio_global->ready_for_read == NULL || - l2_ndisuio_global->rx_processed == NULL) { - if (l2_ndisuio_global->stop_request) { - CloseHandle(l2_ndisuio_global->stop_request); - l2_ndisuio_global->stop_request = NULL; - } - if (l2_ndisuio_global->ready_for_read) { - CloseHandle(l2_ndisuio_global->ready_for_read); - l2_ndisuio_global->ready_for_read = NULL; - } - if (l2_ndisuio_global->rx_processed) { - CloseHandle(l2_ndisuio_global->rx_processed); - l2_ndisuio_global->rx_processed = NULL; - } - eloop_unregister_event(l2->rx_avail, sizeof(l2->rx_avail)); - os_free(l2); - return NULL; - } - - l2_ndisuio_global->rx_thread = CreateThread(NULL, 0, - l2_packet_rx_thread, l2, 0, - NULL); - if (l2_ndisuio_global->rx_thread == NULL) { - wpa_printf(MSG_INFO, "L2(NDISUIO): Failed to create RX " - "thread: %d", (int) GetLastError()); - eloop_unregister_event(l2->rx_avail, sizeof(l2->rx_avail)); - CloseHandle(l2_ndisuio_global->stop_request); - l2_ndisuio_global->stop_request = NULL; - os_free(l2); - return NULL; - } -#else /* _WIN32_WCE */ - l2_ndisuio_start_read(l2, 0); -#endif /* _WIN32_WCE */ - - return l2; -} - - -void l2_packet_deinit(struct l2_packet_data *l2) -{ - if (l2 == NULL) - return; - - if (l2_ndisuio_global) { - l2_ndisuio_global->refcount--; - l2_ndisuio_global->l2[l2_ndisuio_global->refcount] = NULL; - if (l2_ndisuio_global->refcount) { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): restore filtering " - "ethertype to %04x", - l2_ndisuio_global->first_proto); - l2_ndisuio_set_ether_type( - l2_ndisuio_global->first_proto); - return; - } - -#ifdef _WIN32_WCE - wpa_printf(MSG_DEBUG, "L2(NDISUIO): Waiting for RX thread to " - "stop"); - SetEvent(l2_ndisuio_global->stop_request); - /* - * Cancel pending ReadFile() in the RX thread (if we were still - * connected at this point). - */ - if (!DeviceIoControl(driver_ndis_get_ndisuio_handle(), - IOCTL_CANCEL_READ, NULL, 0, NULL, 0, NULL, - NULL)) { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): IOCTL_CANCEL_READ " - "failed: %d", (int) GetLastError()); - /* RX thread will exit blocking ReadFile once NDISUIO - * notices that the adapter is disconnected. */ - } - WaitForSingleObject(l2_ndisuio_global->rx_thread, INFINITE); - wpa_printf(MSG_DEBUG, "L2(NDISUIO): RX thread exited"); - CloseHandle(l2_ndisuio_global->rx_thread); - CloseHandle(l2_ndisuio_global->stop_request); - CloseHandle(l2_ndisuio_global->ready_for_read); - CloseHandle(l2_ndisuio_global->rx_processed); -#endif /* _WIN32_WCE */ - - os_free(l2_ndisuio_global); - l2_ndisuio_global = NULL; - } - -#ifndef _WIN32_WCE - CancelIo(driver_ndis_get_ndisuio_handle()); -#endif /* _WIN32_WCE */ - - eloop_unregister_event(l2->rx_avail, sizeof(l2->rx_avail)); - CloseHandle(l2->rx_avail); - os_free(l2); -} - - -int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) -{ - return -1; -} - - -void l2_packet_notify_auth_start(struct l2_packet_data *l2) -{ -} diff --git a/contrib/hostapd/src/l2_packet/l2_packet_none.c b/contrib/hostapd/src/l2_packet/l2_packet_none.c deleted file mode 100644 index 5e3f6e9723..0000000000 --- a/contrib/hostapd/src/l2_packet/l2_packet_none.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * WPA Supplicant - Layer2 packet handling example with dummy functions - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file can be used as a starting point for layer2 packet implementation. - */ - -#include "includes.h" - -#include "common.h" -#include "eloop.h" -#include "l2_packet.h" - - -struct l2_packet_data { - char ifname[17]; - u8 own_addr[ETH_ALEN]; - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len); - void *rx_callback_ctx; - int l2_hdr; /* whether to include layer 2 (Ethernet) header data - * buffers */ - int fd; -}; - - -int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) -{ - os_memcpy(addr, l2->own_addr, ETH_ALEN); - return 0; -} - - -int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, - const u8 *buf, size_t len) -{ - if (l2 == NULL) - return -1; - - /* - * TODO: Send frame (may need different implementation depending on - * whether l2->l2_hdr is set). - */ - - return 0; -} - - -static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct l2_packet_data *l2 = eloop_ctx; - u8 buf[2300]; - int res; - - /* TODO: receive frame (e.g., recv() using sock */ - buf[0] = 0; - res = 0; - - l2->rx_callback(l2->rx_callback_ctx, NULL /* TODO: src addr */, - buf, res); -} - - -struct l2_packet_data * l2_packet_init( - const char *ifname, const u8 *own_addr, unsigned short protocol, - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len), - void *rx_callback_ctx, int l2_hdr) -{ - struct l2_packet_data *l2; - - l2 = os_zalloc(sizeof(struct l2_packet_data)); - if (l2 == NULL) - return NULL; - os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); - l2->rx_callback = rx_callback; - l2->rx_callback_ctx = rx_callback_ctx; - l2->l2_hdr = l2_hdr; - - /* - * TODO: open connection for receiving frames - */ - l2->fd = -1; - eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); - - return l2; -} - - -void l2_packet_deinit(struct l2_packet_data *l2) -{ - if (l2 == NULL) - return; - - if (l2->fd >= 0) { - eloop_unregister_read_sock(l2->fd); - /* TODO: close connection */ - } - - os_free(l2); -} - - -int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) -{ - /* TODO: get interface IP address */ - return -1; -} - - -void l2_packet_notify_auth_start(struct l2_packet_data *l2) -{ - /* This function can be left empty */ -} diff --git a/contrib/hostapd/src/l2_packet/l2_packet_pcap.c b/contrib/hostapd/src/l2_packet/l2_packet_pcap.c deleted file mode 100644 index 8156e294b1..0000000000 --- a/contrib/hostapd/src/l2_packet/l2_packet_pcap.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * WPA Supplicant - Layer2 packet handling with libpcap/libdnet and WinPcap - * Copyright (c) 2003-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#ifndef CONFIG_NATIVE_WINDOWS -#include -#endif /* CONFIG_NATIVE_WINDOWS */ -#include -#ifndef CONFIG_WINPCAP -#include -#endif /* CONFIG_WINPCAP */ - -#include "common.h" -#include "eloop.h" -#include "l2_packet.h" - - -static const u8 pae_group_addr[ETH_ALEN] = -{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; - -struct l2_packet_data { - pcap_t *pcap; -#ifdef CONFIG_WINPCAP - unsigned int num_fast_poll; -#else /* CONFIG_WINPCAP */ - eth_t *eth; -#endif /* CONFIG_WINPCAP */ - char ifname[100]; - u8 own_addr[ETH_ALEN]; - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len); - void *rx_callback_ctx; - int l2_hdr; /* whether to include layer 2 (Ethernet) header in calls - * to rx_callback */ -}; - - -int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) -{ - os_memcpy(addr, l2->own_addr, ETH_ALEN); - return 0; -} - - -#ifndef CONFIG_WINPCAP -static int l2_packet_init_libdnet(struct l2_packet_data *l2) -{ - eth_addr_t own_addr; - - l2->eth = eth_open(l2->ifname); - if (!l2->eth) { - printf("Failed to open interface '%s'.\n", l2->ifname); - perror("eth_open"); - return -1; - } - - if (eth_get(l2->eth, &own_addr) < 0) { - printf("Failed to get own hw address from interface '%s'.\n", - l2->ifname); - perror("eth_get"); - eth_close(l2->eth); - l2->eth = NULL; - return -1; - } - os_memcpy(l2->own_addr, own_addr.data, ETH_ALEN); - - return 0; -} -#endif /* CONFIG_WINPCAP */ - - -int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, - const u8 *buf, size_t len) -{ - int ret; - struct l2_ethhdr *eth; - - if (l2 == NULL) - return -1; - - if (l2->l2_hdr) { -#ifdef CONFIG_WINPCAP - ret = pcap_sendpacket(l2->pcap, buf, len); -#else /* CONFIG_WINPCAP */ - ret = eth_send(l2->eth, buf, len); -#endif /* CONFIG_WINPCAP */ - } else { - size_t mlen = sizeof(*eth) + len; - eth = os_malloc(mlen); - if (eth == NULL) - return -1; - - os_memcpy(eth->h_dest, dst_addr, ETH_ALEN); - os_memcpy(eth->h_source, l2->own_addr, ETH_ALEN); - eth->h_proto = htons(proto); - os_memcpy(eth + 1, buf, len); - -#ifdef CONFIG_WINPCAP - ret = pcap_sendpacket(l2->pcap, (u8 *) eth, mlen); -#else /* CONFIG_WINPCAP */ - ret = eth_send(l2->eth, (u8 *) eth, mlen); -#endif /* CONFIG_WINPCAP */ - - os_free(eth); - } - - return ret; -} - - -#ifndef CONFIG_WINPCAP -static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct l2_packet_data *l2 = eloop_ctx; - pcap_t *pcap = sock_ctx; - struct pcap_pkthdr hdr; - const u_char *packet; - struct l2_ethhdr *ethhdr; - unsigned char *buf; - size_t len; - - packet = pcap_next(pcap, &hdr); - - if (packet == NULL || hdr.caplen < sizeof(*ethhdr)) - return; - - ethhdr = (struct l2_ethhdr *) packet; - if (l2->l2_hdr) { - buf = (unsigned char *) ethhdr; - len = hdr.caplen; - } else { - buf = (unsigned char *) (ethhdr + 1); - len = hdr.caplen - sizeof(*ethhdr); - } - l2->rx_callback(l2->rx_callback_ctx, ethhdr->h_source, buf, len); -} -#endif /* CONFIG_WINPCAP */ - - -#ifdef CONFIG_WINPCAP -static void l2_packet_receive_cb(u_char *user, const struct pcap_pkthdr *hdr, - const u_char *pkt_data) -{ - struct l2_packet_data *l2 = (struct l2_packet_data *) user; - struct l2_ethhdr *ethhdr; - unsigned char *buf; - size_t len; - - if (pkt_data == NULL || hdr->caplen < sizeof(*ethhdr)) - return; - - ethhdr = (struct l2_ethhdr *) pkt_data; - if (l2->l2_hdr) { - buf = (unsigned char *) ethhdr; - len = hdr->caplen; - } else { - buf = (unsigned char *) (ethhdr + 1); - len = hdr->caplen - sizeof(*ethhdr); - } - l2->rx_callback(l2->rx_callback_ctx, ethhdr->h_source, buf, len); - /* - * Use shorter poll interval for 3 seconds to reduce latency during key - * handshake. - */ - l2->num_fast_poll = 3 * 50; -} - - -static void l2_packet_receive_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct l2_packet_data *l2 = eloop_ctx; - pcap_t *pcap = timeout_ctx; - int timeout; - - if (l2->num_fast_poll > 0) { - timeout = 20000; - l2->num_fast_poll--; - } else - timeout = 100000; - - /* Register new timeout before calling l2_packet_receive() since - * receive handler may free this l2_packet instance (which will - * cancel this timeout). */ - eloop_register_timeout(0, timeout, l2_packet_receive_timeout, - l2, pcap); - pcap_dispatch(pcap, 10, l2_packet_receive_cb, (u_char *) l2); -} -#endif /* CONFIG_WINPCAP */ - - -static int l2_packet_init_libpcap(struct l2_packet_data *l2, - unsigned short protocol) -{ - bpf_u_int32 pcap_maskp, pcap_netp; - char pcap_filter[200], pcap_err[PCAP_ERRBUF_SIZE]; - struct bpf_program pcap_fp; - -#ifdef CONFIG_WINPCAP - char ifname[128]; - os_snprintf(ifname, sizeof(ifname), "\\Device\\NPF_%s", l2->ifname); - pcap_lookupnet(ifname, &pcap_netp, &pcap_maskp, pcap_err); - l2->pcap = pcap_open_live(ifname, 2500, 0, 10, pcap_err); - if (l2->pcap == NULL) { - fprintf(stderr, "pcap_open_live: %s\n", pcap_err); - fprintf(stderr, "ifname='%s'\n", ifname); - return -1; - } - if (pcap_setnonblock(l2->pcap, 1, pcap_err) < 0) - fprintf(stderr, "pcap_setnonblock: %s\n", - pcap_geterr(l2->pcap)); -#else /* CONFIG_WINPCAP */ - pcap_lookupnet(l2->ifname, &pcap_netp, &pcap_maskp, pcap_err); - l2->pcap = pcap_open_live(l2->ifname, 2500, 0, 10, pcap_err); - if (l2->pcap == NULL) { - fprintf(stderr, "pcap_open_live: %s\n", pcap_err); - fprintf(stderr, "ifname='%s'\n", l2->ifname); - return -1; - } - if (pcap_datalink(l2->pcap) != DLT_EN10MB && - pcap_set_datalink(l2->pcap, DLT_EN10MB) < 0) { - fprintf(stderr, "pcap_set_datalink(DLT_EN10MB): %s\n", - pcap_geterr(l2->pcap)); - return -1; - } -#endif /* CONFIG_WINPCAP */ - os_snprintf(pcap_filter, sizeof(pcap_filter), - "not ether src " MACSTR " and " - "( ether dst " MACSTR " or ether dst " MACSTR " ) and " - "ether proto 0x%x", - MAC2STR(l2->own_addr), /* do not receive own packets */ - MAC2STR(l2->own_addr), MAC2STR(pae_group_addr), - protocol); - if (pcap_compile(l2->pcap, &pcap_fp, pcap_filter, 1, pcap_netp) < 0) { - fprintf(stderr, "pcap_compile: %s\n", pcap_geterr(l2->pcap)); - return -1; - } - - if (pcap_setfilter(l2->pcap, &pcap_fp) < 0) { - fprintf(stderr, "pcap_setfilter: %s\n", pcap_geterr(l2->pcap)); - return -1; - } - - pcap_freecode(&pcap_fp); -#ifdef BIOCIMMEDIATE - /* - * When libpcap uses BPF we must enable "immediate mode" to - * receive frames right away; otherwise the system may - * buffer them for us. - */ - { - unsigned int on = 1; - if (ioctl(pcap_fileno(l2->pcap), BIOCIMMEDIATE, &on) < 0) { - fprintf(stderr, "%s: cannot enable immediate mode on " - "interface %s: %s\n", - __func__, l2->ifname, strerror(errno)); - /* XXX should we fail? */ - } - } -#endif /* BIOCIMMEDIATE */ - -#ifdef CONFIG_WINPCAP - eloop_register_timeout(0, 100000, l2_packet_receive_timeout, - l2, l2->pcap); -#else /* CONFIG_WINPCAP */ - eloop_register_read_sock(pcap_get_selectable_fd(l2->pcap), - l2_packet_receive, l2, l2->pcap); -#endif /* CONFIG_WINPCAP */ - - return 0; -} - - -struct l2_packet_data * l2_packet_init( - const char *ifname, const u8 *own_addr, unsigned short protocol, - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len), - void *rx_callback_ctx, int l2_hdr) -{ - struct l2_packet_data *l2; - - l2 = os_zalloc(sizeof(struct l2_packet_data)); - if (l2 == NULL) - return NULL; - os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); - l2->rx_callback = rx_callback; - l2->rx_callback_ctx = rx_callback_ctx; - l2->l2_hdr = l2_hdr; - -#ifdef CONFIG_WINPCAP - if (own_addr) - os_memcpy(l2->own_addr, own_addr, ETH_ALEN); -#else /* CONFIG_WINPCAP */ - if (l2_packet_init_libdnet(l2)) - return NULL; -#endif /* CONFIG_WINPCAP */ - - if (l2_packet_init_libpcap(l2, protocol)) { -#ifndef CONFIG_WINPCAP - eth_close(l2->eth); -#endif /* CONFIG_WINPCAP */ - os_free(l2); - return NULL; - } - - return l2; -} - - -void l2_packet_deinit(struct l2_packet_data *l2) -{ - if (l2 == NULL) - return; - -#ifdef CONFIG_WINPCAP - eloop_cancel_timeout(l2_packet_receive_timeout, l2, l2->pcap); -#else /* CONFIG_WINPCAP */ - if (l2->eth) - eth_close(l2->eth); - eloop_unregister_read_sock(pcap_get_selectable_fd(l2->pcap)); -#endif /* CONFIG_WINPCAP */ - if (l2->pcap) - pcap_close(l2->pcap); - os_free(l2); -} - - -int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) -{ - pcap_if_t *devs, *dev; - struct pcap_addr *addr; - struct sockaddr_in *saddr; - int found = 0; - char err[PCAP_ERRBUF_SIZE + 1]; - - if (pcap_findalldevs(&devs, err) < 0) { - wpa_printf(MSG_DEBUG, "pcap_findalldevs: %s\n", err); - return -1; - } - - for (dev = devs; dev && !found; dev = dev->next) { - if (os_strcmp(dev->name, l2->ifname) != 0) - continue; - - addr = dev->addresses; - while (addr) { - saddr = (struct sockaddr_in *) addr->addr; - if (saddr && saddr->sin_family == AF_INET) { - os_strlcpy(buf, inet_ntoa(saddr->sin_addr), - len); - found = 1; - break; - } - addr = addr->next; - } - } - - pcap_freealldevs(devs); - - return found ? 0 : -1; -} - - -void l2_packet_notify_auth_start(struct l2_packet_data *l2) -{ -#ifdef CONFIG_WINPCAP - /* - * Use shorter poll interval for 3 seconds to reduce latency during key - * handshake. - */ - l2->num_fast_poll = 3 * 50; - eloop_cancel_timeout(l2_packet_receive_timeout, l2, l2->pcap); - eloop_register_timeout(0, 10000, l2_packet_receive_timeout, - l2, l2->pcap); -#endif /* CONFIG_WINPCAP */ -} diff --git a/contrib/hostapd/src/l2_packet/l2_packet_privsep.c b/contrib/hostapd/src/l2_packet/l2_packet_privsep.c deleted file mode 100644 index c0e7c495a1..0000000000 --- a/contrib/hostapd/src/l2_packet/l2_packet_privsep.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * WPA Supplicant - Layer2 packet handling with privilege separation - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "eloop.h" -#include "l2_packet.h" -#include "privsep_commands.h" - - -struct l2_packet_data { - int fd; /* UNIX domain socket for privsep access */ - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len); - void *rx_callback_ctx; - u8 own_addr[ETH_ALEN]; - char *own_socket_path; - struct sockaddr_un priv_addr; -}; - - -static int wpa_priv_cmd(struct l2_packet_data *l2, int cmd, - const void *data, size_t data_len) -{ - struct msghdr msg; - struct iovec io[2]; - - io[0].iov_base = &cmd; - io[0].iov_len = sizeof(cmd); - io[1].iov_base = (u8 *) data; - io[1].iov_len = data_len; - - os_memset(&msg, 0, sizeof(msg)); - msg.msg_iov = io; - msg.msg_iovlen = data ? 2 : 1; - msg.msg_name = &l2->priv_addr; - msg.msg_namelen = sizeof(l2->priv_addr); - - if (sendmsg(l2->fd, &msg, 0) < 0) { - perror("L2: sendmsg(cmd)"); - return -1; - } - - return 0; -} - - -int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) -{ - os_memcpy(addr, l2->own_addr, ETH_ALEN); - return 0; -} - - -int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, - const u8 *buf, size_t len) -{ - struct msghdr msg; - struct iovec io[4]; - int cmd = PRIVSEP_CMD_L2_SEND; - - io[0].iov_base = &cmd; - io[0].iov_len = sizeof(cmd); - io[1].iov_base = &dst_addr; - io[1].iov_len = ETH_ALEN; - io[2].iov_base = &proto; - io[2].iov_len = 2; - io[3].iov_base = (u8 *) buf; - io[3].iov_len = len; - - os_memset(&msg, 0, sizeof(msg)); - msg.msg_iov = io; - msg.msg_iovlen = 4; - msg.msg_name = &l2->priv_addr; - msg.msg_namelen = sizeof(l2->priv_addr); - - if (sendmsg(l2->fd, &msg, 0) < 0) { - perror("L2: sendmsg(packet_send)"); - return -1; - } - - return 0; -} - - -static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct l2_packet_data *l2 = eloop_ctx; - u8 buf[2300]; - int res; - struct sockaddr_un from; - socklen_t fromlen = sizeof(from); - - os_memset(&from, 0, sizeof(from)); - res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &from, - &fromlen); - if (res < 0) { - perror("l2_packet_receive - recvfrom"); - return; - } - if (res < ETH_ALEN) { - wpa_printf(MSG_DEBUG, "L2: Too show packet received"); - return; - } - - if (from.sun_family != AF_UNIX || - os_strncmp(from.sun_path, l2->priv_addr.sun_path, - sizeof(from.sun_path)) != 0) { - wpa_printf(MSG_DEBUG, "L2: Received message from unexpected " - "source"); - return; - } - - l2->rx_callback(l2->rx_callback_ctx, buf, buf + ETH_ALEN, - res - ETH_ALEN); -} - - -struct l2_packet_data * l2_packet_init( - const char *ifname, const u8 *own_addr, unsigned short protocol, - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len), - void *rx_callback_ctx, int l2_hdr) -{ - struct l2_packet_data *l2; - char *own_dir = "/tmp"; - char *priv_dir = "/var/run/wpa_priv"; - size_t len; - static unsigned int counter = 0; - struct sockaddr_un addr; - fd_set rfds; - struct timeval tv; - int res; - u8 reply[ETH_ALEN + 1]; - int reg_cmd[2]; - - l2 = os_zalloc(sizeof(struct l2_packet_data)); - if (l2 == NULL) - return NULL; - l2->rx_callback = rx_callback; - l2->rx_callback_ctx = rx_callback_ctx; - - len = os_strlen(own_dir) + 50; - l2->own_socket_path = os_malloc(len); - if (l2->own_socket_path == NULL) { - os_free(l2); - return NULL; - } - os_snprintf(l2->own_socket_path, len, "%s/wpa_privsep-l2-%d-%d", - own_dir, getpid(), counter++); - - l2->priv_addr.sun_family = AF_UNIX; - os_snprintf(l2->priv_addr.sun_path, sizeof(l2->priv_addr.sun_path), - "%s/%s", priv_dir, ifname); - - l2->fd = socket(PF_UNIX, SOCK_DGRAM, 0); - if (l2->fd < 0) { - perror("socket(PF_UNIX)"); - os_free(l2->own_socket_path); - l2->own_socket_path = NULL; - os_free(l2); - return NULL; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_strlcpy(addr.sun_path, l2->own_socket_path, sizeof(addr.sun_path)); - if (bind(l2->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind(PF_UNIX)"); - goto fail; - } - - reg_cmd[0] = protocol; - reg_cmd[1] = l2_hdr; - if (wpa_priv_cmd(l2, PRIVSEP_CMD_L2_REGISTER, reg_cmd, sizeof(reg_cmd)) - < 0) { - wpa_printf(MSG_ERROR, "L2: Failed to register with wpa_priv"); - goto fail; - } - - FD_ZERO(&rfds); - FD_SET(l2->fd, &rfds); - tv.tv_sec = 5; - tv.tv_usec = 0; - res = select(l2->fd + 1, &rfds, NULL, NULL, &tv); - if (res < 0 && errno != EINTR) { - perror("select"); - goto fail; - } - - if (FD_ISSET(l2->fd, &rfds)) { - res = recv(l2->fd, reply, sizeof(reply), 0); - if (res < 0) { - perror("recv"); - goto fail; - } - } else { - wpa_printf(MSG_DEBUG, "L2: Timeout while waiting for " - "registration reply"); - goto fail; - } - - if (res != ETH_ALEN) { - wpa_printf(MSG_DEBUG, "L2: Unexpected registration reply " - "(len=%d)", res); - } - os_memcpy(l2->own_addr, reply, ETH_ALEN); - - eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); - - return l2; - -fail: - close(l2->fd); - l2->fd = -1; - unlink(l2->own_socket_path); - os_free(l2->own_socket_path); - l2->own_socket_path = NULL; - os_free(l2); - return NULL; -} - - -void l2_packet_deinit(struct l2_packet_data *l2) -{ - if (l2 == NULL) - return; - - if (l2->fd >= 0) { - wpa_priv_cmd(l2, PRIVSEP_CMD_L2_UNREGISTER, NULL, 0); - eloop_unregister_read_sock(l2->fd); - close(l2->fd); - } - - if (l2->own_socket_path) { - unlink(l2->own_socket_path); - os_free(l2->own_socket_path); - } - - os_free(l2); -} - - -int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) -{ - /* TODO */ - return -1; -} - - -void l2_packet_notify_auth_start(struct l2_packet_data *l2) -{ - wpa_priv_cmd(l2, PRIVSEP_CMD_L2_NOTIFY_AUTH_START, NULL, 0); -} diff --git a/contrib/hostapd/src/l2_packet/l2_packet_winpcap.c b/contrib/hostapd/src/l2_packet/l2_packet_winpcap.c deleted file mode 100644 index f76b386fc0..0000000000 --- a/contrib/hostapd/src/l2_packet/l2_packet_winpcap.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * WPA Supplicant - Layer2 packet handling with WinPcap RX thread - * Copyright (c) 2003-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This l2_packet implementation is explicitly for WinPcap and Windows events. - * l2_packet_pcap.c has support for WinPcap, but it requires polling to receive - * frames which means relatively long latency for EAPOL RX processing. The - * implementation here uses a separate thread to allow WinPcap to be receiving - * all the time to reduce latency for EAPOL receiving from about 100 ms to 3 ms - * when comparing l2_packet_pcap.c to l2_packet_winpcap.c. Extra sleep of 50 ms - * is added in to receive thread whenever no EAPOL frames has been received for - * a while. Whenever an EAPOL handshake is expected, this sleep is removed. - * - * The RX thread receives a frame and signals main thread through Windows event - * about the availability of a new frame. Processing the received frame is - * synchronized with pair of Windows events so that no extra buffer or queuing - * mechanism is needed. This implementation requires Windows specific event - * loop implementation, i.e., eloop_win.c. - * - * WinPcap has pcap_getevent() that could, in theory at least, be used to - * implement this kind of waiting with a simpler single-thread design. However, - * that event handle is not really signaled immediately when receiving each - * frame, so it does not really work for this kind of use. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "eloop.h" -#include "l2_packet.h" - - -static const u8 pae_group_addr[ETH_ALEN] = -{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; - -/* - * Number of pcap_dispatch() iterations to do without extra wait after each - * received EAPOL packet or authentication notification. This is used to reduce - * latency for EAPOL receive. - */ -static const size_t no_wait_count = 750; - -struct l2_packet_data { - pcap_t *pcap; - unsigned int num_fast_poll; - char ifname[100]; - u8 own_addr[ETH_ALEN]; - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len); - void *rx_callback_ctx; - int l2_hdr; /* whether to include layer 2 (Ethernet) header in calls to - * rx_callback and l2_packet_send() */ - int running; - HANDLE rx_avail, rx_done, rx_thread, rx_thread_done, rx_notify; - u8 *rx_buf, *rx_src; - size_t rx_len; - size_t rx_no_wait; -}; - - -int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) -{ - os_memcpy(addr, l2->own_addr, ETH_ALEN); - return 0; -} - - -int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, - const u8 *buf, size_t len) -{ - int ret; - struct l2_ethhdr *eth; - - if (l2 == NULL) - return -1; - - if (l2->l2_hdr) { - ret = pcap_sendpacket(l2->pcap, buf, len); - } else { - size_t mlen = sizeof(*eth) + len; - eth = os_malloc(mlen); - if (eth == NULL) - return -1; - - os_memcpy(eth->h_dest, dst_addr, ETH_ALEN); - os_memcpy(eth->h_source, l2->own_addr, ETH_ALEN); - eth->h_proto = htons(proto); - os_memcpy(eth + 1, buf, len); - ret = pcap_sendpacket(l2->pcap, (u8 *) eth, mlen); - os_free(eth); - } - - return ret; -} - - -/* pcap_dispatch() callback for the RX thread */ -static void l2_packet_receive_cb(u_char *user, const struct pcap_pkthdr *hdr, - const u_char *pkt_data) -{ - struct l2_packet_data *l2 = (struct l2_packet_data *) user; - struct l2_ethhdr *ethhdr; - - if (pkt_data == NULL || hdr->caplen < sizeof(*ethhdr)) - return; - - ethhdr = (struct l2_ethhdr *) pkt_data; - if (l2->l2_hdr) { - l2->rx_buf = (u8 *) ethhdr; - l2->rx_len = hdr->caplen; - } else { - l2->rx_buf = (u8 *) (ethhdr + 1); - l2->rx_len = hdr->caplen - sizeof(*ethhdr); - } - l2->rx_src = ethhdr->h_source; - SetEvent(l2->rx_avail); - WaitForSingleObject(l2->rx_done, INFINITE); - ResetEvent(l2->rx_done); - l2->rx_no_wait = no_wait_count; -} - - -/* main RX loop that is running in a separate thread */ -static DWORD WINAPI l2_packet_receive_thread(LPVOID arg) -{ - struct l2_packet_data *l2 = arg; - - while (l2->running) { - pcap_dispatch(l2->pcap, 1, l2_packet_receive_cb, - (u_char *) l2); - if (l2->rx_no_wait > 0) - l2->rx_no_wait--; - if (WaitForSingleObject(l2->rx_notify, - l2->rx_no_wait ? 0 : 50) == - WAIT_OBJECT_0) { - l2->rx_no_wait = no_wait_count; - ResetEvent(l2->rx_notify); - } - } - SetEvent(l2->rx_thread_done); - ExitThread(0); - return 0; -} - - -/* main thread RX event handler */ -static void l2_packet_rx_event(void *eloop_data, void *user_data) -{ - struct l2_packet_data *l2 = eloop_data; - l2->rx_callback(l2->rx_callback_ctx, l2->rx_src, l2->rx_buf, - l2->rx_len); - ResetEvent(l2->rx_avail); - SetEvent(l2->rx_done); -} - - -static int l2_packet_init_libpcap(struct l2_packet_data *l2, - unsigned short protocol) -{ - bpf_u_int32 pcap_maskp, pcap_netp; - char pcap_filter[200], pcap_err[PCAP_ERRBUF_SIZE]; - struct bpf_program pcap_fp; - - pcap_lookupnet(l2->ifname, &pcap_netp, &pcap_maskp, pcap_err); - l2->pcap = pcap_open_live(l2->ifname, 2500, 0, 1, pcap_err); - if (l2->pcap == NULL) { - fprintf(stderr, "pcap_open_live: %s\n", pcap_err); - fprintf(stderr, "ifname='%s'\n", l2->ifname); - return -1; - } - os_snprintf(pcap_filter, sizeof(pcap_filter), - "not ether src " MACSTR " and " - "( ether dst " MACSTR " or ether dst " MACSTR " ) and " - "ether proto 0x%x", - MAC2STR(l2->own_addr), /* do not receive own packets */ - MAC2STR(l2->own_addr), MAC2STR(pae_group_addr), - protocol); - if (pcap_compile(l2->pcap, &pcap_fp, pcap_filter, 1, pcap_netp) < 0) { - fprintf(stderr, "pcap_compile: %s\n", pcap_geterr(l2->pcap)); - return -1; - } - - if (pcap_setfilter(l2->pcap, &pcap_fp) < 0) { - fprintf(stderr, "pcap_setfilter: %s\n", pcap_geterr(l2->pcap)); - return -1; - } - - pcap_freecode(&pcap_fp); - - return 0; -} - - -struct l2_packet_data * l2_packet_init( - const char *ifname, const u8 *own_addr, unsigned short protocol, - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len), - void *rx_callback_ctx, int l2_hdr) -{ - struct l2_packet_data *l2; - DWORD thread_id; - - l2 = os_zalloc(sizeof(struct l2_packet_data)); - if (l2 == NULL) - return NULL; - if (os_strncmp(ifname, "\\Device\\NPF_", 12) == 0) - os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); - else - os_snprintf(l2->ifname, sizeof(l2->ifname), "\\Device\\NPF_%s", - ifname); - l2->rx_callback = rx_callback; - l2->rx_callback_ctx = rx_callback_ctx; - l2->l2_hdr = l2_hdr; - - if (own_addr) - os_memcpy(l2->own_addr, own_addr, ETH_ALEN); - - if (l2_packet_init_libpcap(l2, protocol)) { - os_free(l2); - return NULL; - } - - l2->rx_avail = CreateEvent(NULL, TRUE, FALSE, NULL); - l2->rx_done = CreateEvent(NULL, TRUE, FALSE, NULL); - l2->rx_notify = CreateEvent(NULL, TRUE, FALSE, NULL); - if (l2->rx_avail == NULL || l2->rx_done == NULL || - l2->rx_notify == NULL) { - CloseHandle(l2->rx_avail); - CloseHandle(l2->rx_done); - CloseHandle(l2->rx_notify); - pcap_close(l2->pcap); - os_free(l2); - return NULL; - } - - eloop_register_event(l2->rx_avail, sizeof(l2->rx_avail), - l2_packet_rx_event, l2, NULL); - - l2->running = 1; - l2->rx_thread = CreateThread(NULL, 0, l2_packet_receive_thread, l2, 0, - &thread_id); - - return l2; -} - - -static void l2_packet_deinit_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct l2_packet_data *l2 = eloop_ctx; - - if (l2->rx_thread_done && - WaitForSingleObject(l2->rx_thread_done, 2000) != WAIT_OBJECT_0) { - wpa_printf(MSG_DEBUG, "l2_packet_winpcap: RX thread did not " - "exit - kill it\n"); - TerminateThread(l2->rx_thread, 0); - } - CloseHandle(l2->rx_thread_done); - CloseHandle(l2->rx_thread); - if (l2->pcap) - pcap_close(l2->pcap); - eloop_unregister_event(l2->rx_avail, sizeof(l2->rx_avail)); - CloseHandle(l2->rx_avail); - CloseHandle(l2->rx_done); - CloseHandle(l2->rx_notify); - os_free(l2); -} - - -void l2_packet_deinit(struct l2_packet_data *l2) -{ - if (l2 == NULL) - return; - - l2->rx_thread_done = CreateEvent(NULL, TRUE, FALSE, NULL); - - l2->running = 0; - pcap_breakloop(l2->pcap); - - /* - * RX thread may be waiting in l2_packet_receive_cb() for l2->rx_done - * event and this event is set in l2_packet_rx_event(). However, - * l2_packet_deinit() may end up being called from l2->rx_callback(), - * so we need to return from here and complete deinitialization in - * a registered timeout to avoid having to forcefully kill the RX - * thread. - */ - eloop_register_timeout(0, 0, l2_packet_deinit_timeout, l2, NULL); -} - - -int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) -{ - pcap_if_t *devs, *dev; - struct pcap_addr *addr; - struct sockaddr_in *saddr; - int found = 0; - char err[PCAP_ERRBUF_SIZE + 1]; - - if (pcap_findalldevs(&devs, err) < 0) { - wpa_printf(MSG_DEBUG, "pcap_findalldevs: %s\n", err); - return -1; - } - - for (dev = devs; dev && !found; dev = dev->next) { - if (os_strcmp(dev->name, l2->ifname) != 0) - continue; - - addr = dev->addresses; - while (addr) { - saddr = (struct sockaddr_in *) addr->addr; - if (saddr && saddr->sin_family == AF_INET) { - os_strlcpy(buf, inet_ntoa(saddr->sin_addr), - len); - found = 1; - break; - } - addr = addr->next; - } - } - - pcap_freealldevs(devs); - - return found ? 0 : -1; -} - - -void l2_packet_notify_auth_start(struct l2_packet_data *l2) -{ - if (l2) - SetEvent(l2->rx_notify); -} diff --git a/contrib/hostapd/src/radius/radius.c b/contrib/hostapd/src/radius/radius.c deleted file mode 100644 index 71bbfb52ee..0000000000 --- a/contrib/hostapd/src/radius/radius.c +++ /dev/null @@ -1,1234 +0,0 @@ -/* - * hostapd / RADIUS message processing - * Copyright (c) 2002-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "radius.h" -#include "md5.h" -#include "crypto.h" - - -static struct radius_attr_hdr * -radius_get_attr_hdr(struct radius_msg *msg, int idx) -{ - return (struct radius_attr_hdr *) (msg->buf + msg->attr_pos[idx]); -} - - -struct radius_msg *radius_msg_new(u8 code, u8 identifier) -{ - struct radius_msg *msg; - - msg = os_malloc(sizeof(*msg)); - if (msg == NULL) - return NULL; - - if (radius_msg_initialize(msg, RADIUS_DEFAULT_MSG_SIZE)) { - os_free(msg); - return NULL; - } - - radius_msg_set_hdr(msg, code, identifier); - - return msg; -} - - -int radius_msg_initialize(struct radius_msg *msg, size_t init_len) -{ - if (msg == NULL || init_len < sizeof(struct radius_hdr)) - return -1; - - os_memset(msg, 0, sizeof(*msg)); - msg->buf = os_zalloc(init_len); - if (msg->buf == NULL) - return -1; - - msg->buf_size = init_len; - msg->hdr = (struct radius_hdr *) msg->buf; - msg->buf_used = sizeof(*msg->hdr); - - msg->attr_pos = - os_zalloc(RADIUS_DEFAULT_ATTR_COUNT * sizeof(*msg->attr_pos)); - if (msg->attr_pos == NULL) { - os_free(msg->buf); - msg->buf = NULL; - msg->hdr = NULL; - return -1; - } - - msg->attr_size = RADIUS_DEFAULT_ATTR_COUNT; - msg->attr_used = 0; - - return 0; -} - - -void radius_msg_set_hdr(struct radius_msg *msg, u8 code, u8 identifier) -{ - msg->hdr->code = code; - msg->hdr->identifier = identifier; -} - - -void radius_msg_free(struct radius_msg *msg) -{ - os_free(msg->buf); - msg->buf = NULL; - msg->hdr = NULL; - msg->buf_size = msg->buf_used = 0; - - os_free(msg->attr_pos); - msg->attr_pos = NULL; - msg->attr_size = msg->attr_used = 0; -} - - -static const char *radius_code_string(u8 code) -{ - switch (code) { - case RADIUS_CODE_ACCESS_REQUEST: return "Access-Request"; - case RADIUS_CODE_ACCESS_ACCEPT: return "Access-Accept"; - case RADIUS_CODE_ACCESS_REJECT: return "Access-Reject"; - case RADIUS_CODE_ACCOUNTING_REQUEST: return "Accounting-Request"; - case RADIUS_CODE_ACCOUNTING_RESPONSE: return "Accounting-Response"; - case RADIUS_CODE_ACCESS_CHALLENGE: return "Access-Challenge"; - case RADIUS_CODE_STATUS_SERVER: return "Status-Server"; - case RADIUS_CODE_STATUS_CLIENT: return "Status-Client"; - case RADIUS_CODE_RESERVED: return "Reserved"; - default: return "?Unknown?"; - } -} - - -struct radius_attr_type { - u8 type; - char *name; - enum { - RADIUS_ATTR_UNDIST, RADIUS_ATTR_TEXT, RADIUS_ATTR_IP, - RADIUS_ATTR_HEXDUMP, RADIUS_ATTR_INT32, RADIUS_ATTR_IPV6 - } data_type; -}; - -static struct radius_attr_type radius_attrs[] = -{ - { RADIUS_ATTR_USER_NAME, "User-Name", RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_USER_PASSWORD, "User-Password", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_NAS_IP_ADDRESS, "NAS-IP-Address", RADIUS_ATTR_IP }, - { RADIUS_ATTR_NAS_PORT, "NAS-Port", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_FRAMED_MTU, "Framed-MTU", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_REPLY_MESSAGE, "Reply-Message", RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_STATE, "State", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_CLASS, "Class", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_VENDOR_SPECIFIC, "Vendor-Specific", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_SESSION_TIMEOUT, "Session-Timeout", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_IDLE_TIMEOUT, "Idle-Timeout", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_TERMINATION_ACTION, "Termination-Action", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_CALLED_STATION_ID, "Called-Station-Id", - RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_CALLING_STATION_ID, "Calling-Station-Id", - RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_NAS_IDENTIFIER, "NAS-Identifier", RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_PROXY_STATE, "Proxy-State", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_ACCT_STATUS_TYPE, "Acct-Status-Type", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_DELAY_TIME, "Acct-Delay-Time", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_INPUT_OCTETS, "Acct-Input-Octets", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_OUTPUT_OCTETS, "Acct-Output-Octets", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_SESSION_ID, "Acct-Session-Id", RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_ACCT_AUTHENTIC, "Acct-Authentic", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_SESSION_TIME, "Acct-Session-Time", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_INPUT_PACKETS, "Acct-Input-Packets", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_OUTPUT_PACKETS, "Acct-Output-Packets", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_TERMINATE_CAUSE, "Acct-Terminate-Cause", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_MULTI_SESSION_ID, "Acct-Multi-Session-Id", - RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_ACCT_LINK_COUNT, "Acct-Link-Count", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_INPUT_GIGAWORDS, "Acct-Input-Gigawords", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS, "Acct-Output-Gigawords", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_EVENT_TIMESTAMP, "Event-Timestamp", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_NAS_PORT_TYPE, "NAS-Port-Type", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_TUNNEL_TYPE, "Tunnel-Type", RADIUS_ATTR_HEXDUMP }, - { RADIUS_ATTR_TUNNEL_MEDIUM_TYPE, "Tunnel-Medium-Type", - RADIUS_ATTR_HEXDUMP }, - { RADIUS_ATTR_CONNECT_INFO, "Connect-Info", RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_EAP_MESSAGE, "EAP-Message", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_MESSAGE_AUTHENTICATOR, "Message-Authenticator", - RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID, "Tunnel-Private-Group-Id", - RADIUS_ATTR_HEXDUMP }, - { RADIUS_ATTR_ACCT_INTERIM_INTERVAL, "Acct-Interim-Interval", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, "Chargable-User-Identity", - RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_NAS_IPV6_ADDRESS, "NAS-IPv6-Address", RADIUS_ATTR_IPV6 }, -}; -#define RADIUS_ATTRS (sizeof(radius_attrs) / sizeof(radius_attrs[0])) - - -static struct radius_attr_type *radius_get_attr_type(u8 type) -{ - size_t i; - - for (i = 0; i < RADIUS_ATTRS; i++) { - if (type == radius_attrs[i].type) - return &radius_attrs[i]; - } - - return NULL; -} - - -static void print_char(char c) -{ - if (c >= 32 && c < 127) - printf("%c", c); - else - printf("<%02x>", c); -} - - -static void radius_msg_dump_attr(struct radius_attr_hdr *hdr) -{ - struct radius_attr_type *attr; - int i, len; - unsigned char *pos; - - attr = radius_get_attr_type(hdr->type); - - printf(" Attribute %d (%s) length=%d\n", - hdr->type, attr ? attr->name : "?Unknown?", hdr->length); - - if (attr == NULL) - return; - - len = hdr->length - sizeof(struct radius_attr_hdr); - pos = (unsigned char *) (hdr + 1); - - switch (attr->data_type) { - case RADIUS_ATTR_TEXT: - printf(" Value: '"); - for (i = 0; i < len; i++) - print_char(pos[i]); - printf("'\n"); - break; - - case RADIUS_ATTR_IP: - if (len == 4) { - struct in_addr addr; - os_memcpy(&addr, pos, 4); - printf(" Value: %s\n", inet_ntoa(addr)); - } else - printf(" Invalid IP address length %d\n", len); - break; - -#ifdef CONFIG_IPV6 - case RADIUS_ATTR_IPV6: - if (len == 16) { - char buf[128]; - const char *atxt; - struct in6_addr *addr = (struct in6_addr *) pos; - atxt = inet_ntop(AF_INET6, addr, buf, sizeof(buf)); - printf(" Value: %s\n", atxt ? atxt : "?"); - } else - printf(" Invalid IPv6 address length %d\n", len); - break; -#endif /* CONFIG_IPV6 */ - - case RADIUS_ATTR_HEXDUMP: - case RADIUS_ATTR_UNDIST: - printf(" Value:"); - for (i = 0; i < len; i++) - printf(" %02x", pos[i]); - printf("\n"); - break; - - case RADIUS_ATTR_INT32: - if (len == 4) - printf(" Value: %u\n", WPA_GET_BE32(pos)); - else - printf(" Invalid INT32 length %d\n", len); - break; - - default: - break; - } -} - - -void radius_msg_dump(struct radius_msg *msg) -{ - size_t i; - - printf("RADIUS message: code=%d (%s) identifier=%d length=%d\n", - msg->hdr->code, radius_code_string(msg->hdr->code), - msg->hdr->identifier, ntohs(msg->hdr->length)); - - for (i = 0; i < msg->attr_used; i++) { - struct radius_attr_hdr *attr = radius_get_attr_hdr(msg, i); - radius_msg_dump_attr(attr); - } -} - - -int radius_msg_finish(struct radius_msg *msg, const u8 *secret, - size_t secret_len) -{ - if (secret) { - u8 auth[MD5_MAC_LEN]; - struct radius_attr_hdr *attr; - - os_memset(auth, 0, MD5_MAC_LEN); - attr = radius_msg_add_attr(msg, - RADIUS_ATTR_MESSAGE_AUTHENTICATOR, - auth, MD5_MAC_LEN); - if (attr == NULL) { - printf("WARNING: Could not add " - "Message-Authenticator\n"); - return -1; - } - msg->hdr->length = htons(msg->buf_used); - hmac_md5(secret, secret_len, msg->buf, msg->buf_used, - (u8 *) (attr + 1)); - } else - msg->hdr->length = htons(msg->buf_used); - - if (msg->buf_used > 0xffff) { - printf("WARNING: too long RADIUS message (%lu)\n", - (unsigned long) msg->buf_used); - return -1; - } - return 0; -} - - -int radius_msg_finish_srv(struct radius_msg *msg, const u8 *secret, - size_t secret_len, const u8 *req_authenticator) -{ - u8 auth[MD5_MAC_LEN]; - struct radius_attr_hdr *attr; - const u8 *addr[4]; - size_t len[4]; - - os_memset(auth, 0, MD5_MAC_LEN); - attr = radius_msg_add_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, - auth, MD5_MAC_LEN); - if (attr == NULL) { - printf("WARNING: Could not add Message-Authenticator\n"); - return -1; - } - msg->hdr->length = htons(msg->buf_used); - os_memcpy(msg->hdr->authenticator, req_authenticator, - sizeof(msg->hdr->authenticator)); - hmac_md5(secret, secret_len, msg->buf, msg->buf_used, - (u8 *) (attr + 1)); - - /* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */ - addr[0] = (u8 *) msg->hdr; - len[0] = 1 + 1 + 2; - addr[1] = req_authenticator; - len[1] = MD5_MAC_LEN; - addr[2] = (u8 *) (msg->hdr + 1); - len[2] = msg->buf_used - sizeof(*msg->hdr); - addr[3] = secret; - len[3] = secret_len; - md5_vector(4, addr, len, msg->hdr->authenticator); - - if (msg->buf_used > 0xffff) { - printf("WARNING: too long RADIUS message (%lu)\n", - (unsigned long) msg->buf_used); - return -1; - } - return 0; -} - - -void radius_msg_finish_acct(struct radius_msg *msg, const u8 *secret, - size_t secret_len) -{ - const u8 *addr[2]; - size_t len[2]; - - msg->hdr->length = htons(msg->buf_used); - os_memset(msg->hdr->authenticator, 0, MD5_MAC_LEN); - addr[0] = msg->buf; - len[0] = msg->buf_used; - addr[1] = secret; - len[1] = secret_len; - md5_vector(2, addr, len, msg->hdr->authenticator); - - if (msg->buf_used > 0xffff) { - printf("WARNING: too long RADIUS messages (%lu)\n", - (unsigned long) msg->buf_used); - } -} - - -static int radius_msg_add_attr_to_array(struct radius_msg *msg, - struct radius_attr_hdr *attr) -{ - if (msg->attr_used >= msg->attr_size) { - size_t *nattr_pos; - int nlen = msg->attr_size * 2; - - nattr_pos = os_realloc(msg->attr_pos, - nlen * sizeof(*msg->attr_pos)); - if (nattr_pos == NULL) - return -1; - - msg->attr_pos = nattr_pos; - msg->attr_size = nlen; - } - - msg->attr_pos[msg->attr_used++] = (unsigned char *) attr - msg->buf; - - return 0; -} - - -struct radius_attr_hdr *radius_msg_add_attr(struct radius_msg *msg, u8 type, - const u8 *data, size_t data_len) -{ - size_t buf_needed; - struct radius_attr_hdr *attr; - - if (data_len > RADIUS_MAX_ATTR_LEN) { - printf("radius_msg_add_attr: too long attribute (%lu bytes)\n", - (unsigned long) data_len); - return NULL; - } - - buf_needed = msg->buf_used + sizeof(*attr) + data_len; - - if (msg->buf_size < buf_needed) { - /* allocate more space for message buffer */ - unsigned char *nbuf; - size_t nlen = msg->buf_size; - - while (nlen < buf_needed) - nlen *= 2; - nbuf = os_realloc(msg->buf, nlen); - if (nbuf == NULL) - return NULL; - msg->buf = nbuf; - msg->hdr = (struct radius_hdr *) msg->buf; - os_memset(msg->buf + msg->buf_size, 0, nlen - msg->buf_size); - msg->buf_size = nlen; - } - - attr = (struct radius_attr_hdr *) (msg->buf + msg->buf_used); - attr->type = type; - attr->length = sizeof(*attr) + data_len; - if (data_len > 0) - os_memcpy(attr + 1, data, data_len); - - msg->buf_used += sizeof(*attr) + data_len; - - if (radius_msg_add_attr_to_array(msg, attr)) - return NULL; - - return attr; -} - - -struct radius_msg *radius_msg_parse(const u8 *data, size_t len) -{ - struct radius_msg *msg; - struct radius_hdr *hdr; - struct radius_attr_hdr *attr; - size_t msg_len; - unsigned char *pos, *end; - - if (data == NULL || len < sizeof(*hdr)) - return NULL; - - hdr = (struct radius_hdr *) data; - - msg_len = ntohs(hdr->length); - if (msg_len < sizeof(*hdr) || msg_len > len) { - printf("Invalid RADIUS message length\n"); - return NULL; - } - - if (msg_len < len) { - printf("Ignored %lu extra bytes after RADIUS message\n", - (unsigned long) len - msg_len); - } - - msg = os_malloc(sizeof(*msg)); - if (msg == NULL) - return NULL; - - if (radius_msg_initialize(msg, msg_len)) { - os_free(msg); - return NULL; - } - - os_memcpy(msg->buf, data, msg_len); - msg->buf_size = msg->buf_used = msg_len; - - /* parse attributes */ - pos = (unsigned char *) (msg->hdr + 1); - end = msg->buf + msg->buf_used; - while (pos < end) { - if ((size_t) (end - pos) < sizeof(*attr)) - goto fail; - - attr = (struct radius_attr_hdr *) pos; - - if (pos + attr->length > end || attr->length < sizeof(*attr)) - goto fail; - - /* TODO: check that attr->length is suitable for attr->type */ - - if (radius_msg_add_attr_to_array(msg, attr)) - goto fail; - - pos += attr->length; - } - - return msg; - - fail: - radius_msg_free(msg); - os_free(msg); - return NULL; -} - - -int radius_msg_add_eap(struct radius_msg *msg, const u8 *data, size_t data_len) -{ - const u8 *pos = data; - size_t left = data_len; - - while (left > 0) { - int len; - if (left > RADIUS_MAX_ATTR_LEN) - len = RADIUS_MAX_ATTR_LEN; - else - len = left; - - if (!radius_msg_add_attr(msg, RADIUS_ATTR_EAP_MESSAGE, - pos, len)) - return 0; - - pos += len; - left -= len; - } - - return 1; -} - - -u8 *radius_msg_get_eap(struct radius_msg *msg, size_t *eap_len) -{ - u8 *eap, *pos; - size_t len, i; - struct radius_attr_hdr *attr; - - if (msg == NULL) - return NULL; - - len = 0; - for (i = 0; i < msg->attr_used; i++) { - attr = radius_get_attr_hdr(msg, i); - if (attr->type == RADIUS_ATTR_EAP_MESSAGE) - len += attr->length - sizeof(struct radius_attr_hdr); - } - - if (len == 0) - return NULL; - - eap = os_malloc(len); - if (eap == NULL) - return NULL; - - pos = eap; - for (i = 0; i < msg->attr_used; i++) { - attr = radius_get_attr_hdr(msg, i); - if (attr->type == RADIUS_ATTR_EAP_MESSAGE) { - int flen = attr->length - sizeof(*attr); - os_memcpy(pos, attr + 1, flen); - pos += flen; - } - } - - if (eap_len) - *eap_len = len; - - return eap; -} - - -int radius_msg_verify_msg_auth(struct radius_msg *msg, const u8 *secret, - size_t secret_len, const u8 *req_auth) -{ - u8 auth[MD5_MAC_LEN], orig[MD5_MAC_LEN]; - u8 orig_authenticator[16]; - struct radius_attr_hdr *attr = NULL, *tmp; - size_t i; - - for (i = 0; i < msg->attr_used; i++) { - tmp = radius_get_attr_hdr(msg, i); - if (tmp->type == RADIUS_ATTR_MESSAGE_AUTHENTICATOR) { - if (attr != NULL) { - printf("Multiple Message-Authenticator " - "attributes in RADIUS message\n"); - return 1; - } - attr = tmp; - } - } - - if (attr == NULL) { - printf("No Message-Authenticator attribute found\n"); - return 1; - } - - os_memcpy(orig, attr + 1, MD5_MAC_LEN); - os_memset(attr + 1, 0, MD5_MAC_LEN); - if (req_auth) { - os_memcpy(orig_authenticator, msg->hdr->authenticator, - sizeof(orig_authenticator)); - os_memcpy(msg->hdr->authenticator, req_auth, - sizeof(msg->hdr->authenticator)); - } - hmac_md5(secret, secret_len, msg->buf, msg->buf_used, auth); - os_memcpy(attr + 1, orig, MD5_MAC_LEN); - if (req_auth) { - os_memcpy(msg->hdr->authenticator, orig_authenticator, - sizeof(orig_authenticator)); - } - - if (os_memcmp(orig, auth, MD5_MAC_LEN) != 0) { - printf("Invalid Message-Authenticator!\n"); - return 1; - } - - return 0; -} - - -int radius_msg_verify(struct radius_msg *msg, const u8 *secret, - size_t secret_len, struct radius_msg *sent_msg, int auth) -{ - const u8 *addr[4]; - size_t len[4]; - u8 hash[MD5_MAC_LEN]; - - if (sent_msg == NULL) { - printf("No matching Access-Request message found\n"); - return 1; - } - - if (auth && - radius_msg_verify_msg_auth(msg, secret, secret_len, - sent_msg->hdr->authenticator)) { - return 1; - } - - /* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */ - addr[0] = (u8 *) msg->hdr; - len[0] = 1 + 1 + 2; - addr[1] = sent_msg->hdr->authenticator; - len[1] = MD5_MAC_LEN; - addr[2] = (u8 *) (msg->hdr + 1); - len[2] = msg->buf_used - sizeof(*msg->hdr); - addr[3] = secret; - len[3] = secret_len; - md5_vector(4, addr, len, hash); - if (os_memcmp(hash, msg->hdr->authenticator, MD5_MAC_LEN) != 0) { - printf("Response Authenticator invalid!\n"); - return 1; - } - - return 0; -} - - -int radius_msg_copy_attr(struct radius_msg *dst, struct radius_msg *src, - u8 type) -{ - struct radius_attr_hdr *attr; - size_t i; - int count = 0; - - for (i = 0; i < src->attr_used; i++) { - attr = radius_get_attr_hdr(src, i); - if (attr->type == type) { - if (!radius_msg_add_attr(dst, type, (u8 *) (attr + 1), - attr->length - sizeof(*attr))) - return -1; - count++; - } - } - - return count; -} - - -/* Create Request Authenticator. The value should be unique over the lifetime - * of the shared secret between authenticator and authentication server. - * Use one-way MD5 hash calculated from current timestamp and some data given - * by the caller. */ -void radius_msg_make_authenticator(struct radius_msg *msg, - const u8 *data, size_t len) -{ - struct os_time tv; - long int l; - const u8 *addr[3]; - size_t elen[3]; - - os_get_time(&tv); - l = os_random(); - addr[0] = (u8 *) &tv; - elen[0] = sizeof(tv); - addr[1] = data; - elen[1] = len; - addr[2] = (u8 *) &l; - elen[2] = sizeof(l); - md5_vector(3, addr, elen, msg->hdr->authenticator); -} - - -/* Get Vendor-specific RADIUS Attribute from a parsed RADIUS message. - * Returns the Attribute payload and sets alen to indicate the length of the - * payload if a vendor attribute with subtype is found, otherwise returns NULL. - * The returned payload is allocated with os_malloc() and caller must free it - * by calling os_free(). - */ -static u8 *radius_msg_get_vendor_attr(struct radius_msg *msg, u32 vendor, - u8 subtype, size_t *alen) -{ - u8 *data, *pos; - size_t i, len; - - if (msg == NULL) - return NULL; - - for (i = 0; i < msg->attr_used; i++) { - struct radius_attr_hdr *attr = radius_get_attr_hdr(msg, i); - size_t left; - u32 vendor_id; - struct radius_attr_vendor *vhdr; - - if (attr->type != RADIUS_ATTR_VENDOR_SPECIFIC) - continue; - - left = attr->length - sizeof(*attr); - if (left < 4) - continue; - - pos = (u8 *) (attr + 1); - - os_memcpy(&vendor_id, pos, 4); - pos += 4; - left -= 4; - - if (ntohl(vendor_id) != vendor) - continue; - - while (left >= sizeof(*vhdr)) { - vhdr = (struct radius_attr_vendor *) pos; - if (vhdr->vendor_length > left || - vhdr->vendor_length < sizeof(*vhdr)) { - left = 0; - break; - } - if (vhdr->vendor_type != subtype) { - pos += vhdr->vendor_length; - left -= vhdr->vendor_length; - continue; - } - - len = vhdr->vendor_length - sizeof(*vhdr); - data = os_malloc(len); - if (data == NULL) - return NULL; - os_memcpy(data, pos + sizeof(*vhdr), len); - if (alen) - *alen = len; - return data; - } - } - - return NULL; -} - - -static u8 * decrypt_ms_key(const u8 *key, size_t len, - const u8 *req_authenticator, - const u8 *secret, size_t secret_len, size_t *reslen) -{ - u8 *plain, *ppos, *res; - const u8 *pos; - size_t left, plen; - u8 hash[MD5_MAC_LEN]; - int i, first = 1; - const u8 *addr[3]; - size_t elen[3]; - - /* key: 16-bit salt followed by encrypted key info */ - - if (len < 2 + 16) - return NULL; - - pos = key + 2; - left = len - 2; - if (left % 16) { - printf("Invalid ms key len %lu\n", (unsigned long) left); - return NULL; - } - - plen = left; - ppos = plain = os_malloc(plen); - if (plain == NULL) - return NULL; - plain[0] = 0; - - while (left > 0) { - /* b(1) = MD5(Secret + Request-Authenticator + Salt) - * b(i) = MD5(Secret + c(i - 1)) for i > 1 */ - - addr[0] = secret; - elen[0] = secret_len; - if (first) { - addr[1] = req_authenticator; - elen[1] = MD5_MAC_LEN; - addr[2] = key; - elen[2] = 2; /* Salt */ - } else { - addr[1] = pos - MD5_MAC_LEN; - elen[1] = MD5_MAC_LEN; - } - md5_vector(first ? 3 : 2, addr, elen, hash); - first = 0; - - for (i = 0; i < MD5_MAC_LEN; i++) - *ppos++ = *pos++ ^ hash[i]; - left -= MD5_MAC_LEN; - } - - if (plain[0] == 0 || plain[0] > plen - 1) { - printf("Failed to decrypt MPPE key\n"); - os_free(plain); - return NULL; - } - - res = os_malloc(plain[0]); - if (res == NULL) { - os_free(plain); - return NULL; - } - os_memcpy(res, plain + 1, plain[0]); - if (reslen) - *reslen = plain[0]; - os_free(plain); - return res; -} - - -static void encrypt_ms_key(const u8 *key, size_t key_len, u16 salt, - const u8 *req_authenticator, - const u8 *secret, size_t secret_len, - u8 *ebuf, size_t *elen) -{ - int i, len, first = 1; - u8 hash[MD5_MAC_LEN], saltbuf[2], *pos; - const u8 *addr[3]; - size_t _len[3]; - - WPA_PUT_BE16(saltbuf, salt); - - len = 1 + key_len; - if (len & 0x0f) { - len = (len & 0xf0) + 16; - } - os_memset(ebuf, 0, len); - ebuf[0] = key_len; - os_memcpy(ebuf + 1, key, key_len); - - *elen = len; - - pos = ebuf; - while (len > 0) { - /* b(1) = MD5(Secret + Request-Authenticator + Salt) - * b(i) = MD5(Secret + c(i - 1)) for i > 1 */ - addr[0] = secret; - _len[0] = secret_len; - if (first) { - addr[1] = req_authenticator; - _len[1] = MD5_MAC_LEN; - addr[2] = saltbuf; - _len[2] = sizeof(saltbuf); - } else { - addr[1] = pos - MD5_MAC_LEN; - _len[1] = MD5_MAC_LEN; - } - md5_vector(first ? 3 : 2, addr, _len, hash); - first = 0; - - for (i = 0; i < MD5_MAC_LEN; i++) - *pos++ ^= hash[i]; - - len -= MD5_MAC_LEN; - } -} - - -struct radius_ms_mppe_keys * -radius_msg_get_ms_keys(struct radius_msg *msg, struct radius_msg *sent_msg, - const u8 *secret, size_t secret_len) -{ - u8 *key; - size_t keylen; - struct radius_ms_mppe_keys *keys; - - if (msg == NULL || sent_msg == NULL) - return NULL; - - keys = os_zalloc(sizeof(*keys)); - if (keys == NULL) - return NULL; - - key = radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_MICROSOFT, - RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY, - &keylen); - if (key) { - keys->send = decrypt_ms_key(key, keylen, - sent_msg->hdr->authenticator, - secret, secret_len, - &keys->send_len); - os_free(key); - } - - key = radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_MICROSOFT, - RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY, - &keylen); - if (key) { - keys->recv = decrypt_ms_key(key, keylen, - sent_msg->hdr->authenticator, - secret, secret_len, - &keys->recv_len); - os_free(key); - } - - return keys; -} - - -struct radius_ms_mppe_keys * -radius_msg_get_cisco_keys(struct radius_msg *msg, struct radius_msg *sent_msg, - const u8 *secret, size_t secret_len) -{ - u8 *key; - size_t keylen; - struct radius_ms_mppe_keys *keys; - - if (msg == NULL || sent_msg == NULL) - return NULL; - - keys = os_zalloc(sizeof(*keys)); - if (keys == NULL) - return NULL; - - key = radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_CISCO, - RADIUS_CISCO_AV_PAIR, &keylen); - if (key && keylen == 51 && - os_memcmp(key, "leap:session-key=", 17) == 0) { - keys->recv = decrypt_ms_key(key + 17, keylen - 17, - sent_msg->hdr->authenticator, - secret, secret_len, - &keys->recv_len); - } - os_free(key); - - return keys; -} - - -int radius_msg_add_mppe_keys(struct radius_msg *msg, - const u8 *req_authenticator, - const u8 *secret, size_t secret_len, - const u8 *send_key, size_t send_key_len, - const u8 *recv_key, size_t recv_key_len) -{ - struct radius_attr_hdr *attr; - u32 vendor_id = htonl(RADIUS_VENDOR_ID_MICROSOFT); - u8 *buf; - struct radius_attr_vendor *vhdr; - u8 *pos; - size_t elen; - int hlen; - u16 salt; - - hlen = sizeof(vendor_id) + sizeof(*vhdr) + 2; - - /* MS-MPPE-Send-Key */ - buf = os_malloc(hlen + send_key_len + 16); - if (buf == NULL) { - return 0; - } - pos = buf; - os_memcpy(pos, &vendor_id, sizeof(vendor_id)); - pos += sizeof(vendor_id); - vhdr = (struct radius_attr_vendor *) pos; - vhdr->vendor_type = RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY; - pos = (u8 *) (vhdr + 1); - salt = os_random() | 0x8000; - WPA_PUT_BE16(pos, salt); - pos += 2; - encrypt_ms_key(send_key, send_key_len, salt, req_authenticator, secret, - secret_len, pos, &elen); - vhdr->vendor_length = hlen + elen - sizeof(vendor_id); - - attr = radius_msg_add_attr(msg, RADIUS_ATTR_VENDOR_SPECIFIC, - buf, hlen + elen); - os_free(buf); - if (attr == NULL) { - return 0; - } - - /* MS-MPPE-Recv-Key */ - buf = os_malloc(hlen + send_key_len + 16); - if (buf == NULL) { - return 0; - } - pos = buf; - os_memcpy(pos, &vendor_id, sizeof(vendor_id)); - pos += sizeof(vendor_id); - vhdr = (struct radius_attr_vendor *) pos; - vhdr->vendor_type = RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY; - pos = (u8 *) (vhdr + 1); - salt ^= 1; - WPA_PUT_BE16(pos, salt); - pos += 2; - encrypt_ms_key(recv_key, recv_key_len, salt, req_authenticator, secret, - secret_len, pos, &elen); - vhdr->vendor_length = hlen + elen - sizeof(vendor_id); - - attr = radius_msg_add_attr(msg, RADIUS_ATTR_VENDOR_SPECIFIC, - buf, hlen + elen); - os_free(buf); - if (attr == NULL) { - return 0; - } - - return 1; -} - - -/* Add User-Password attribute to a RADIUS message and encrypt it as specified - * in RFC 2865, Chap. 5.2 */ -struct radius_attr_hdr * -radius_msg_add_attr_user_password(struct radius_msg *msg, - const u8 *data, size_t data_len, - const u8 *secret, size_t secret_len) -{ - u8 buf[128]; - int padlen, i; - size_t buf_len, pos; - const u8 *addr[2]; - size_t len[2]; - u8 hash[16]; - - if (data_len > 128) - return NULL; - - os_memcpy(buf, data, data_len); - buf_len = data_len; - - padlen = data_len % 16; - if (padlen) { - padlen = 16 - padlen; - os_memset(buf + data_len, 0, padlen); - buf_len += padlen; - } - - addr[0] = secret; - len[0] = secret_len; - addr[1] = msg->hdr->authenticator; - len[1] = 16; - md5_vector(2, addr, len, hash); - - for (i = 0; i < 16; i++) - buf[i] ^= hash[i]; - pos = 16; - - while (pos < buf_len) { - addr[0] = secret; - len[0] = secret_len; - addr[1] = &buf[pos - 16]; - len[1] = 16; - md5_vector(2, addr, len, hash); - - for (i = 0; i < 16; i++) - buf[pos + i] ^= hash[i]; - - pos += 16; - } - - return radius_msg_add_attr(msg, RADIUS_ATTR_USER_PASSWORD, - buf, buf_len); -} - - -int radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len) -{ - struct radius_attr_hdr *attr = NULL, *tmp; - size_t i, dlen; - - for (i = 0; i < msg->attr_used; i++) { - tmp = radius_get_attr_hdr(msg, i); - if (tmp->type == type) { - attr = tmp; - break; - } - } - - if (!attr) - return -1; - - dlen = attr->length - sizeof(*attr); - if (buf) - os_memcpy(buf, (attr + 1), dlen > len ? len : dlen); - return dlen; -} - - -int radius_msg_get_attr_ptr(struct radius_msg *msg, u8 type, u8 **buf, - size_t *len, const u8 *start) -{ - size_t i; - struct radius_attr_hdr *attr = NULL, *tmp; - - for (i = 0; i < msg->attr_used; i++) { - tmp = radius_get_attr_hdr(msg, i); - if (tmp->type == type && - (start == NULL || (u8 *) tmp > start)) { - attr = tmp; - break; - } - } - - if (!attr) - return -1; - - *buf = (u8 *) (attr + 1); - *len = attr->length - sizeof(*attr); - return 0; -} - - -int radius_msg_count_attr(struct radius_msg *msg, u8 type, int min_len) -{ - size_t i; - int count; - - for (count = 0, i = 0; i < msg->attr_used; i++) { - struct radius_attr_hdr *attr = radius_get_attr_hdr(msg, i); - if (attr->type == type && - attr->length >= sizeof(struct radius_attr_hdr) + min_len) - count++; - } - - return count; -} - - -struct radius_tunnel_attrs { - int tag_used; - int type; /* Tunnel-Type */ - int medium_type; /* Tunnel-Medium-Type */ - int vlanid; -}; - - -/** - * radius_msg_get_vlanid - Parse RADIUS attributes for VLAN tunnel information - * @msg: RADIUS message - * Returns: VLAN ID for the first tunnel configuration of -1 if none is found - */ -int radius_msg_get_vlanid(struct radius_msg *msg) -{ - struct radius_tunnel_attrs tunnel[RADIUS_TUNNEL_TAGS], *tun; - size_t i; - struct radius_attr_hdr *attr = NULL; - const u8 *data; - char buf[10]; - size_t dlen; - - os_memset(&tunnel, 0, sizeof(tunnel)); - - for (i = 0; i < msg->attr_used; i++) { - attr = radius_get_attr_hdr(msg, i); - data = (const u8 *) (attr + 1); - dlen = attr->length - sizeof(*attr); - if (attr->length < 3) - continue; - if (data[0] >= RADIUS_TUNNEL_TAGS) - tun = &tunnel[0]; - else - tun = &tunnel[data[0]]; - - switch (attr->type) { - case RADIUS_ATTR_TUNNEL_TYPE: - if (attr->length != 6) - break; - tun->tag_used++; - tun->type = WPA_GET_BE24(data + 1); - break; - case RADIUS_ATTR_TUNNEL_MEDIUM_TYPE: - if (attr->length != 6) - break; - tun->tag_used++; - tun->medium_type = WPA_GET_BE24(data + 1); - break; - case RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID: - if (data[0] < RADIUS_TUNNEL_TAGS) { - data++; - dlen--; - } - if (dlen >= sizeof(buf)) - break; - os_memcpy(buf, data, dlen); - buf[dlen] = '\0'; - tun->tag_used++; - tun->vlanid = atoi(buf); - break; - } - } - - for (i = 0; i < RADIUS_TUNNEL_TAGS; i++) { - tun = &tunnel[i]; - if (tun->tag_used && - tun->type == RADIUS_TUNNEL_TYPE_VLAN && - tun->medium_type == RADIUS_TUNNEL_MEDIUM_TYPE_802 && - tun->vlanid > 0) - return tun->vlanid; - } - - return -1; -} diff --git a/contrib/hostapd/src/radius/radius.h b/contrib/hostapd/src/radius/radius.h deleted file mode 100644 index c30621dc2e..0000000000 --- a/contrib/hostapd/src/radius/radius.h +++ /dev/null @@ -1,272 +0,0 @@ -/* - * hostapd / RADIUS message processing - * Copyright (c) 2002-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef RADIUS_H -#define RADIUS_H - -/* RFC 2865 - RADIUS */ - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct radius_hdr { - u8 code; - u8 identifier; - u16 length; /* including this header */ - u8 authenticator[16]; - /* followed by length-20 octets of attributes */ -} STRUCT_PACKED; - -enum { RADIUS_CODE_ACCESS_REQUEST = 1, - RADIUS_CODE_ACCESS_ACCEPT = 2, - RADIUS_CODE_ACCESS_REJECT = 3, - RADIUS_CODE_ACCOUNTING_REQUEST = 4, - RADIUS_CODE_ACCOUNTING_RESPONSE = 5, - RADIUS_CODE_ACCESS_CHALLENGE = 11, - RADIUS_CODE_STATUS_SERVER = 12, - RADIUS_CODE_STATUS_CLIENT = 13, - RADIUS_CODE_RESERVED = 255 -}; - -struct radius_attr_hdr { - u8 type; - u8 length; /* including this header */ - /* followed by length-2 octets of attribute value */ -} STRUCT_PACKED; - -#define RADIUS_MAX_ATTR_LEN (255 - sizeof(struct radius_attr_hdr)) - -enum { RADIUS_ATTR_USER_NAME = 1, - RADIUS_ATTR_USER_PASSWORD = 2, - RADIUS_ATTR_NAS_IP_ADDRESS = 4, - RADIUS_ATTR_NAS_PORT = 5, - RADIUS_ATTR_FRAMED_MTU = 12, - RADIUS_ATTR_REPLY_MESSAGE = 18, - RADIUS_ATTR_STATE = 24, - RADIUS_ATTR_CLASS = 25, - RADIUS_ATTR_VENDOR_SPECIFIC = 26, - RADIUS_ATTR_SESSION_TIMEOUT = 27, - RADIUS_ATTR_IDLE_TIMEOUT = 28, - RADIUS_ATTR_TERMINATION_ACTION = 29, - RADIUS_ATTR_CALLED_STATION_ID = 30, - RADIUS_ATTR_CALLING_STATION_ID = 31, - RADIUS_ATTR_NAS_IDENTIFIER = 32, - RADIUS_ATTR_PROXY_STATE = 33, - RADIUS_ATTR_ACCT_STATUS_TYPE = 40, - RADIUS_ATTR_ACCT_DELAY_TIME = 41, - RADIUS_ATTR_ACCT_INPUT_OCTETS = 42, - RADIUS_ATTR_ACCT_OUTPUT_OCTETS = 43, - RADIUS_ATTR_ACCT_SESSION_ID = 44, - RADIUS_ATTR_ACCT_AUTHENTIC = 45, - RADIUS_ATTR_ACCT_SESSION_TIME = 46, - RADIUS_ATTR_ACCT_INPUT_PACKETS = 47, - RADIUS_ATTR_ACCT_OUTPUT_PACKETS = 48, - RADIUS_ATTR_ACCT_TERMINATE_CAUSE = 49, - RADIUS_ATTR_ACCT_MULTI_SESSION_ID = 50, - RADIUS_ATTR_ACCT_LINK_COUNT = 51, - RADIUS_ATTR_ACCT_INPUT_GIGAWORDS = 52, - RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS = 53, - RADIUS_ATTR_EVENT_TIMESTAMP = 55, - RADIUS_ATTR_NAS_PORT_TYPE = 61, - RADIUS_ATTR_TUNNEL_TYPE = 64, - RADIUS_ATTR_TUNNEL_MEDIUM_TYPE = 65, - RADIUS_ATTR_CONNECT_INFO = 77, - RADIUS_ATTR_EAP_MESSAGE = 79, - RADIUS_ATTR_MESSAGE_AUTHENTICATOR = 80, - RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID = 81, - RADIUS_ATTR_ACCT_INTERIM_INTERVAL = 85, - RADIUS_ATTR_CHARGEABLE_USER_IDENTITY = 89, - RADIUS_ATTR_NAS_IPV6_ADDRESS = 95 -}; - - -/* Termination-Action */ -#define RADIUS_TERMINATION_ACTION_DEFAULT 0 -#define RADIUS_TERMINATION_ACTION_RADIUS_REQUEST 1 - -/* NAS-Port-Type */ -#define RADIUS_NAS_PORT_TYPE_IEEE_802_11 19 - -/* Acct-Status-Type */ -#define RADIUS_ACCT_STATUS_TYPE_START 1 -#define RADIUS_ACCT_STATUS_TYPE_STOP 2 -#define RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE 3 -#define RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON 7 -#define RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_OFF 8 - -/* Acct-Authentic */ -#define RADIUS_ACCT_AUTHENTIC_RADIUS 1 -#define RADIUS_ACCT_AUTHENTIC_LOCAL 2 -#define RADIUS_ACCT_AUTHENTIC_REMOTE 3 - -/* Acct-Terminate-Cause */ -#define RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST 1 -#define RADIUS_ACCT_TERMINATE_CAUSE_LOST_CARRIER 2 -#define RADIUS_ACCT_TERMINATE_CAUSE_LOST_SERVICE 3 -#define RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT 4 -#define RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT 5 -#define RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_RESET 6 -#define RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_REBOOT 7 -#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_ERROR 8 -#define RADIUS_ACCT_TERMINATE_CAUSE_NAS_ERROR 9 -#define RADIUS_ACCT_TERMINATE_CAUSE_NAS_REQUEST 10 -#define RADIUS_ACCT_TERMINATE_CAUSE_NAS_REBOOT 11 -#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_UNNEEDED 12 -#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_PREEMPTED 13 -#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_SUSPENDED 14 -#define RADIUS_ACCT_TERMINATE_CAUSE_SERVICE_UNAVAILABLE 15 -#define RADIUS_ACCT_TERMINATE_CAUSE_CALLBACK 16 -#define RADIUS_ACCT_TERMINATE_CAUSE_USER_ERROR 17 -#define RADIUS_ACCT_TERMINATE_CAUSE_HOST_REQUEST 18 - -#define RADIUS_TUNNEL_TAGS 32 - -/* Tunnel-Type */ -#define RADIUS_TUNNEL_TYPE_PPTP 1 -#define RADIUS_TUNNEL_TYPE_L2TP 3 -#define RADIUS_TUNNEL_TYPE_IPIP 7 -#define RADIUS_TUNNEL_TYPE_GRE 10 -#define RADIUS_TUNNEL_TYPE_VLAN 13 - -/* Tunnel-Medium-Type */ -#define RADIUS_TUNNEL_MEDIUM_TYPE_IPV4 1 -#define RADIUS_TUNNEL_MEDIUM_TYPE_IPV6 2 -#define RADIUS_TUNNEL_MEDIUM_TYPE_802 6 - - -struct radius_attr_vendor { - u8 vendor_type; - u8 vendor_length; -} STRUCT_PACKED; - -#define RADIUS_VENDOR_ID_CISCO 9 -#define RADIUS_CISCO_AV_PAIR 1 - -/* RFC 2548 - Microsoft Vendor-specific RADIUS Attributes */ -#define RADIUS_VENDOR_ID_MICROSOFT 311 - -enum { RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY = 16, - RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY = 17 -}; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -struct radius_ms_mppe_keys { - u8 *send; - size_t send_len; - u8 *recv; - size_t recv_len; -}; - - -/* RADIUS message structure for new and parsed messages */ -struct radius_msg { - unsigned char *buf; - size_t buf_size; /* total size allocated for buf */ - size_t buf_used; /* bytes used in buf */ - - struct radius_hdr *hdr; - - size_t *attr_pos; /* array of indexes to attributes (number of bytes - * from buf to the beginning of - * struct radius_attr_hdr). */ - size_t attr_size; /* total size of the attribute pointer array */ - size_t attr_used; /* total number of attributes in the array */ -}; - - -/* Default size to be allocated for new RADIUS messages */ -#define RADIUS_DEFAULT_MSG_SIZE 1024 - -/* Default size to be allocated for attribute array */ -#define RADIUS_DEFAULT_ATTR_COUNT 16 - - -/* MAC address ASCII format for IEEE 802.1X use - * (draft-congdon-radius-8021x-20.txt) */ -#define RADIUS_802_1X_ADDR_FORMAT "%02X-%02X-%02X-%02X-%02X-%02X" -/* MAC address ASCII format for non-802.1X use */ -#define RADIUS_ADDR_FORMAT "%02x%02x%02x%02x%02x%02x" - -struct radius_msg *radius_msg_new(u8 code, u8 identifier); -int radius_msg_initialize(struct radius_msg *msg, size_t init_len); -void radius_msg_set_hdr(struct radius_msg *msg, u8 code, u8 identifier); -void radius_msg_free(struct radius_msg *msg); -void radius_msg_dump(struct radius_msg *msg); -int radius_msg_finish(struct radius_msg *msg, const u8 *secret, - size_t secret_len); -int radius_msg_finish_srv(struct radius_msg *msg, const u8 *secret, - size_t secret_len, const u8 *req_authenticator); -void radius_msg_finish_acct(struct radius_msg *msg, const u8 *secret, - size_t secret_len); -struct radius_attr_hdr *radius_msg_add_attr(struct radius_msg *msg, u8 type, - const u8 *data, size_t data_len); -struct radius_msg *radius_msg_parse(const u8 *data, size_t len); -int radius_msg_add_eap(struct radius_msg *msg, const u8 *data, - size_t data_len); -u8 *radius_msg_get_eap(struct radius_msg *msg, size_t *len); -int radius_msg_verify(struct radius_msg *msg, const u8 *secret, - size_t secret_len, struct radius_msg *sent_msg, - int auth); -int radius_msg_verify_msg_auth(struct radius_msg *msg, const u8 *secret, - size_t secret_len, const u8 *req_auth); -int radius_msg_copy_attr(struct radius_msg *dst, struct radius_msg *src, - u8 type); -void radius_msg_make_authenticator(struct radius_msg *msg, - const u8 *data, size_t len); -struct radius_ms_mppe_keys * -radius_msg_get_ms_keys(struct radius_msg *msg, struct radius_msg *sent_msg, - const u8 *secret, size_t secret_len); -struct radius_ms_mppe_keys * -radius_msg_get_cisco_keys(struct radius_msg *msg, struct radius_msg *sent_msg, - const u8 *secret, size_t secret_len); -int radius_msg_add_mppe_keys(struct radius_msg *msg, - const u8 *req_authenticator, - const u8 *secret, size_t secret_len, - const u8 *send_key, size_t send_key_len, - const u8 *recv_key, size_t recv_key_len); -struct radius_attr_hdr * -radius_msg_add_attr_user_password(struct radius_msg *msg, - const u8 *data, size_t data_len, - const u8 *secret, size_t secret_len); -int radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len); -int radius_msg_get_vlanid(struct radius_msg *msg); - -static inline int radius_msg_add_attr_int32(struct radius_msg *msg, u8 type, - u32 value) -{ - u32 val = htonl(value); - return radius_msg_add_attr(msg, type, (u8 *) &val, 4) != NULL; -} - -static inline int radius_msg_get_attr_int32(struct radius_msg *msg, u8 type, - u32 *value) -{ - u32 val; - int res; - res = radius_msg_get_attr(msg, type, (u8 *) &val, 4); - if (res != 4) - return -1; - - *value = ntohl(val); - return 0; -} -int radius_msg_get_attr_ptr(struct radius_msg *msg, u8 type, u8 **buf, - size_t *len, const u8 *start); -int radius_msg_count_attr(struct radius_msg *msg, u8 type, int min_len); - -#endif /* RADIUS_H */ diff --git a/contrib/hostapd/src/radius/radius_client.c b/contrib/hostapd/src/radius/radius_client.c deleted file mode 100644 index 826acad678..0000000000 --- a/contrib/hostapd/src/radius/radius_client.c +++ /dev/null @@ -1,1301 +0,0 @@ -/* - * hostapd / RADIUS client - * Copyright (c) 2002-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "radius.h" -#include "radius_client.h" -#include "eloop.h" - -/* Defaults for RADIUS retransmit values (exponential backoff) */ -#define RADIUS_CLIENT_FIRST_WAIT 3 /* seconds */ -#define RADIUS_CLIENT_MAX_WAIT 120 /* seconds */ -#define RADIUS_CLIENT_MAX_RETRIES 10 /* maximum number of retransmit attempts - * before entry is removed from retransmit - * list */ -#define RADIUS_CLIENT_MAX_ENTRIES 30 /* maximum number of entries in retransmit - * list (oldest will be removed, if this - * limit is exceeded) */ -#define RADIUS_CLIENT_NUM_FAILOVER 4 /* try to change RADIUS server after this - * many failed retry attempts */ - - -struct radius_rx_handler { - RadiusRxResult (*handler)(struct radius_msg *msg, - struct radius_msg *req, - const u8 *shared_secret, - size_t shared_secret_len, - void *data); - void *data; -}; - - -/* RADIUS message retransmit list */ -struct radius_msg_list { - u8 addr[ETH_ALEN]; /* STA/client address; used to find RADIUS messages - * for the same STA. */ - struct radius_msg *msg; - RadiusType msg_type; - os_time_t first_try; - os_time_t next_try; - int attempts; - int next_wait; - struct os_time last_attempt; - - u8 *shared_secret; - size_t shared_secret_len; - - /* TODO: server config with failover to backup server(s) */ - - struct radius_msg_list *next; -}; - - -struct radius_client_data { - void *ctx; - struct hostapd_radius_servers *conf; - - int auth_serv_sock; /* socket for authentication RADIUS messages */ - int acct_serv_sock; /* socket for accounting RADIUS messages */ - int auth_serv_sock6; - int acct_serv_sock6; - int auth_sock; /* currently used socket */ - int acct_sock; /* currently used socket */ - - struct radius_rx_handler *auth_handlers; - size_t num_auth_handlers; - struct radius_rx_handler *acct_handlers; - size_t num_acct_handlers; - - struct radius_msg_list *msgs; - size_t num_msgs; - - u8 next_radius_identifier; -}; - - -static int -radius_change_server(struct radius_client_data *radius, - struct hostapd_radius_server *nserv, - struct hostapd_radius_server *oserv, - int sock, int sock6, int auth); -static int radius_client_init_acct(struct radius_client_data *radius); -static int radius_client_init_auth(struct radius_client_data *radius); - - -static void radius_client_msg_free(struct radius_msg_list *req) -{ - radius_msg_free(req->msg); - os_free(req->msg); - os_free(req); -} - - -int radius_client_register(struct radius_client_data *radius, - RadiusType msg_type, - RadiusRxResult (*handler)(struct radius_msg *msg, - struct radius_msg *req, - const u8 *shared_secret, - size_t shared_secret_len, - void *data), - void *data) -{ - struct radius_rx_handler **handlers, *newh; - size_t *num; - - if (msg_type == RADIUS_ACCT) { - handlers = &radius->acct_handlers; - num = &radius->num_acct_handlers; - } else { - handlers = &radius->auth_handlers; - num = &radius->num_auth_handlers; - } - - newh = os_realloc(*handlers, - (*num + 1) * sizeof(struct radius_rx_handler)); - if (newh == NULL) - return -1; - - newh[*num].handler = handler; - newh[*num].data = data; - (*num)++; - *handlers = newh; - - return 0; -} - - -static void radius_client_handle_send_error(struct radius_client_data *radius, - int s, RadiusType msg_type) -{ -#ifndef CONFIG_NATIVE_WINDOWS - int _errno = errno; - perror("send[RADIUS]"); - if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL || - _errno == EBADF) { - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, - "Send failed - maybe interface status changed -" - " try to connect again"); - eloop_unregister_read_sock(s); - close(s); - if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) - radius_client_init_acct(radius); - else - radius_client_init_auth(radius); - } -#endif /* CONFIG_NATIVE_WINDOWS */ -} - - -static int radius_client_retransmit(struct radius_client_data *radius, - struct radius_msg_list *entry, - os_time_t now) -{ - struct hostapd_radius_servers *conf = radius->conf; - int s; - - if (entry->msg_type == RADIUS_ACCT || - entry->msg_type == RADIUS_ACCT_INTERIM) { - s = radius->acct_sock; - if (entry->attempts == 0) - conf->acct_server->requests++; - else { - conf->acct_server->timeouts++; - conf->acct_server->retransmissions++; - } - } else { - s = radius->auth_sock; - if (entry->attempts == 0) - conf->auth_server->requests++; - else { - conf->auth_server->timeouts++; - conf->auth_server->retransmissions++; - } - } - - /* retransmit; remove entry if too many attempts */ - entry->attempts++; - hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)", - entry->msg->hdr->identifier); - - os_get_time(&entry->last_attempt); - if (send(s, entry->msg->buf, entry->msg->buf_used, 0) < 0) - radius_client_handle_send_error(radius, s, entry->msg_type); - - entry->next_try = now + entry->next_wait; - entry->next_wait *= 2; - if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT) - entry->next_wait = RADIUS_CLIENT_MAX_WAIT; - if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) { - printf("Removing un-ACKed RADIUS message due to too many " - "failed retransmit attempts\n"); - return 1; - } - - return 0; -} - - -static void radius_client_timer(void *eloop_ctx, void *timeout_ctx) -{ - struct radius_client_data *radius = eloop_ctx; - struct hostapd_radius_servers *conf = radius->conf; - struct os_time now; - os_time_t first; - struct radius_msg_list *entry, *prev, *tmp; - int auth_failover = 0, acct_failover = 0; - char abuf[50]; - - entry = radius->msgs; - if (!entry) - return; - - os_get_time(&now); - first = 0; - - prev = NULL; - while (entry) { - if (now.sec >= entry->next_try && - radius_client_retransmit(radius, entry, now.sec)) { - if (prev) - prev->next = entry->next; - else - radius->msgs = entry->next; - - tmp = entry; - entry = entry->next; - radius_client_msg_free(tmp); - radius->num_msgs--; - continue; - } - - if (entry->attempts > RADIUS_CLIENT_NUM_FAILOVER) { - if (entry->msg_type == RADIUS_ACCT || - entry->msg_type == RADIUS_ACCT_INTERIM) - acct_failover++; - else - auth_failover++; - } - - if (first == 0 || entry->next_try < first) - first = entry->next_try; - - prev = entry; - entry = entry->next; - } - - if (radius->msgs) { - if (first < now.sec) - first = now.sec; - eloop_register_timeout(first - now.sec, 0, - radius_client_timer, radius, NULL); - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, "Next RADIUS client " - "retransmit in %ld seconds", - (long int) (first - now.sec)); - } - - if (auth_failover && conf->num_auth_servers > 1) { - struct hostapd_radius_server *next, *old; - old = conf->auth_server; - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_NOTICE, - "No response from Authentication server " - "%s:%d - failover", - hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)), - old->port); - - for (entry = radius->msgs; entry; entry = entry->next) { - if (entry->msg_type == RADIUS_AUTH) - old->timeouts++; - } - - next = old + 1; - if (next > &(conf->auth_servers[conf->num_auth_servers - 1])) - next = conf->auth_servers; - conf->auth_server = next; - radius_change_server(radius, next, old, - radius->auth_serv_sock, - radius->auth_serv_sock6, 1); - } - - if (acct_failover && conf->num_acct_servers > 1) { - struct hostapd_radius_server *next, *old; - old = conf->acct_server; - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_NOTICE, - "No response from Accounting server " - "%s:%d - failover", - hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)), - old->port); - - for (entry = radius->msgs; entry; entry = entry->next) { - if (entry->msg_type == RADIUS_ACCT || - entry->msg_type == RADIUS_ACCT_INTERIM) - old->timeouts++; - } - - next = old + 1; - if (next > &conf->acct_servers[conf->num_acct_servers - 1]) - next = conf->acct_servers; - conf->acct_server = next; - radius_change_server(radius, next, old, - radius->acct_serv_sock, - radius->acct_serv_sock6, 0); - } -} - - -static void radius_client_update_timeout(struct radius_client_data *radius) -{ - struct os_time now; - os_time_t first; - struct radius_msg_list *entry; - - eloop_cancel_timeout(radius_client_timer, radius, NULL); - - if (radius->msgs == NULL) { - return; - } - - first = 0; - for (entry = radius->msgs; entry; entry = entry->next) { - if (first == 0 || entry->next_try < first) - first = entry->next_try; - } - - os_get_time(&now); - if (first < now.sec) - first = now.sec; - eloop_register_timeout(first - now.sec, 0, radius_client_timer, radius, - NULL); - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, "Next RADIUS client retransmit in" - " %ld seconds\n", (long int) (first - now.sec)); -} - - -static void radius_client_list_add(struct radius_client_data *radius, - struct radius_msg *msg, - RadiusType msg_type, u8 *shared_secret, - size_t shared_secret_len, const u8 *addr) -{ - struct radius_msg_list *entry, *prev; - - if (eloop_terminated()) { - /* No point in adding entries to retransmit queue since event - * loop has already been terminated. */ - radius_msg_free(msg); - os_free(msg); - return; - } - - entry = os_zalloc(sizeof(*entry)); - if (entry == NULL) { - printf("Failed to add RADIUS packet into retransmit list\n"); - radius_msg_free(msg); - os_free(msg); - return; - } - - if (addr) - os_memcpy(entry->addr, addr, ETH_ALEN); - entry->msg = msg; - entry->msg_type = msg_type; - entry->shared_secret = shared_secret; - entry->shared_secret_len = shared_secret_len; - os_get_time(&entry->last_attempt); - entry->first_try = entry->last_attempt.sec; - entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; - entry->attempts = 1; - entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; - entry->next = radius->msgs; - radius->msgs = entry; - radius_client_update_timeout(radius); - - if (radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES) { - printf("Removing the oldest un-ACKed RADIUS packet due to " - "retransmit list limits.\n"); - prev = NULL; - while (entry->next) { - prev = entry; - entry = entry->next; - } - if (prev) { - prev->next = NULL; - radius_client_msg_free(entry); - } - } else - radius->num_msgs++; -} - - -static void radius_client_list_del(struct radius_client_data *radius, - RadiusType msg_type, const u8 *addr) -{ - struct radius_msg_list *entry, *prev, *tmp; - - if (addr == NULL) - return; - - entry = radius->msgs; - prev = NULL; - while (entry) { - if (entry->msg_type == msg_type && - os_memcmp(entry->addr, addr, ETH_ALEN) == 0) { - if (prev) - prev->next = entry->next; - else - radius->msgs = entry->next; - tmp = entry; - entry = entry->next; - hostapd_logger(radius->ctx, addr, - HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, - "Removing matching RADIUS message"); - radius_client_msg_free(tmp); - radius->num_msgs--; - continue; - } - prev = entry; - entry = entry->next; - } -} - - -int radius_client_send(struct radius_client_data *radius, - struct radius_msg *msg, RadiusType msg_type, - const u8 *addr) -{ - struct hostapd_radius_servers *conf = radius->conf; - u8 *shared_secret; - size_t shared_secret_len; - char *name; - int s, res; - - if (msg_type == RADIUS_ACCT_INTERIM) { - /* Remove any pending interim acct update for the same STA. */ - radius_client_list_del(radius, msg_type, addr); - } - - if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) { - if (conf->acct_server == NULL) { - hostapd_logger(radius->ctx, NULL, - HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, - "No accounting server configured"); - return -1; - } - shared_secret = conf->acct_server->shared_secret; - shared_secret_len = conf->acct_server->shared_secret_len; - radius_msg_finish_acct(msg, shared_secret, shared_secret_len); - name = "accounting"; - s = radius->acct_sock; - conf->acct_server->requests++; - } else { - if (conf->auth_server == NULL) { - hostapd_logger(radius->ctx, NULL, - HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, - "No authentication server configured"); - return -1; - } - shared_secret = conf->auth_server->shared_secret; - shared_secret_len = conf->auth_server->shared_secret_len; - radius_msg_finish(msg, shared_secret, shared_secret_len); - name = "authentication"; - s = radius->auth_sock; - conf->auth_server->requests++; - } - - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, "Sending RADIUS message to %s " - "server", name); - if (conf->msg_dumps) - radius_msg_dump(msg); - - res = send(s, msg->buf, msg->buf_used, 0); - if (res < 0) - radius_client_handle_send_error(radius, s, msg_type); - - radius_client_list_add(radius, msg, msg_type, shared_secret, - shared_secret_len, addr); - - return res; -} - - -static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct radius_client_data *radius = eloop_ctx; - struct hostapd_radius_servers *conf = radius->conf; - RadiusType msg_type = (RadiusType) sock_ctx; - int len, roundtrip; - unsigned char buf[3000]; - struct radius_msg *msg; - struct radius_rx_handler *handlers; - size_t num_handlers, i; - struct radius_msg_list *req, *prev_req; - struct os_time now; - struct hostapd_radius_server *rconf; - int invalid_authenticator = 0; - - if (msg_type == RADIUS_ACCT) { - handlers = radius->acct_handlers; - num_handlers = radius->num_acct_handlers; - rconf = conf->acct_server; - } else { - handlers = radius->auth_handlers; - num_handlers = radius->num_auth_handlers; - rconf = conf->auth_server; - } - - len = recv(sock, buf, sizeof(buf), MSG_DONTWAIT); - if (len < 0) { - perror("recv[RADIUS]"); - return; - } - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, "Received %d bytes from RADIUS " - "server", len); - if (len == sizeof(buf)) { - printf("Possibly too long UDP frame for our buffer - " - "dropping it\n"); - return; - } - - msg = radius_msg_parse(buf, len); - if (msg == NULL) { - printf("Parsing incoming RADIUS frame failed\n"); - rconf->malformed_responses++; - return; - } - - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, "Received RADIUS message"); - if (conf->msg_dumps) - radius_msg_dump(msg); - - switch (msg->hdr->code) { - case RADIUS_CODE_ACCESS_ACCEPT: - rconf->access_accepts++; - break; - case RADIUS_CODE_ACCESS_REJECT: - rconf->access_rejects++; - break; - case RADIUS_CODE_ACCESS_CHALLENGE: - rconf->access_challenges++; - break; - case RADIUS_CODE_ACCOUNTING_RESPONSE: - rconf->responses++; - break; - } - - prev_req = NULL; - req = radius->msgs; - while (req) { - /* TODO: also match by src addr:port of the packet when using - * alternative RADIUS servers (?) */ - if ((req->msg_type == msg_type || - (req->msg_type == RADIUS_ACCT_INTERIM && - msg_type == RADIUS_ACCT)) && - req->msg->hdr->identifier == msg->hdr->identifier) - break; - - prev_req = req; - req = req->next; - } - - if (req == NULL) { - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, - "No matching RADIUS request found (type=%d " - "id=%d) - dropping packet", - msg_type, msg->hdr->identifier); - goto fail; - } - - os_get_time(&now); - roundtrip = (now.sec - req->last_attempt.sec) * 100 + - (now.usec - req->last_attempt.usec) / 10000; - hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, - "Received RADIUS packet matched with a pending " - "request, round trip time %d.%02d sec", - roundtrip / 100, roundtrip % 100); - rconf->round_trip_time = roundtrip; - - /* Remove ACKed RADIUS packet from retransmit list */ - if (prev_req) - prev_req->next = req->next; - else - radius->msgs = req->next; - radius->num_msgs--; - - for (i = 0; i < num_handlers; i++) { - RadiusRxResult res; - res = handlers[i].handler(msg, req->msg, req->shared_secret, - req->shared_secret_len, - handlers[i].data); - switch (res) { - case RADIUS_RX_PROCESSED: - radius_msg_free(msg); - os_free(msg); - /* continue */ - case RADIUS_RX_QUEUED: - radius_client_msg_free(req); - return; - case RADIUS_RX_INVALID_AUTHENTICATOR: - invalid_authenticator++; - /* continue */ - case RADIUS_RX_UNKNOWN: - /* continue with next handler */ - break; - } - } - - if (invalid_authenticator) - rconf->bad_authenticators++; - else - rconf->unknown_types++; - hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found " - "(type=%d code=%d id=%d)%s - dropping packet", - msg_type, msg->hdr->code, msg->hdr->identifier, - invalid_authenticator ? " [INVALID AUTHENTICATOR]" : - ""); - radius_client_msg_free(req); - - fail: - radius_msg_free(msg); - os_free(msg); -} - - -u8 radius_client_get_id(struct radius_client_data *radius) -{ - struct radius_msg_list *entry, *prev, *_remove; - u8 id = radius->next_radius_identifier++; - - /* remove entries with matching id from retransmit list to avoid - * using new reply from the RADIUS server with an old request */ - entry = radius->msgs; - prev = NULL; - while (entry) { - if (entry->msg->hdr->identifier == id) { - hostapd_logger(radius->ctx, entry->addr, - HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, - "Removing pending RADIUS message, " - "since its id (%d) is reused", id); - if (prev) - prev->next = entry->next; - else - radius->msgs = entry->next; - _remove = entry; - } else { - _remove = NULL; - prev = entry; - } - entry = entry->next; - - if (_remove) - radius_client_msg_free(_remove); - } - - return id; -} - - -void radius_client_flush(struct radius_client_data *radius, int only_auth) -{ - struct radius_msg_list *entry, *prev, *tmp; - - if (!radius) - return; - - prev = NULL; - entry = radius->msgs; - - while (entry) { - if (!only_auth || entry->msg_type == RADIUS_AUTH) { - if (prev) - prev->next = entry->next; - else - radius->msgs = entry->next; - - tmp = entry; - entry = entry->next; - radius_client_msg_free(tmp); - radius->num_msgs--; - } else { - prev = entry; - entry = entry->next; - } - } - - if (radius->msgs == NULL) - eloop_cancel_timeout(radius_client_timer, radius, NULL); -} - - -static void radius_client_update_acct_msgs(struct radius_client_data *radius, - u8 *shared_secret, - size_t shared_secret_len) -{ - struct radius_msg_list *entry; - - if (!radius) - return; - - for (entry = radius->msgs; entry; entry = entry->next) { - if (entry->msg_type == RADIUS_ACCT) { - entry->shared_secret = shared_secret; - entry->shared_secret_len = shared_secret_len; - radius_msg_finish_acct(entry->msg, shared_secret, - shared_secret_len); - } - } -} - - -static int -radius_change_server(struct radius_client_data *radius, - struct hostapd_radius_server *nserv, - struct hostapd_radius_server *oserv, - int sock, int sock6, int auth) -{ - struct sockaddr_in serv, claddr; -#ifdef CONFIG_IPV6 - struct sockaddr_in6 serv6, claddr6; -#endif /* CONFIG_IPV6 */ - struct sockaddr *addr, *cl_addr; - socklen_t addrlen, claddrlen; - char abuf[50]; - int sel_sock; - struct radius_msg_list *entry; - struct hostapd_radius_servers *conf = radius->conf; - - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, - "%s server %s:%d", - auth ? "Authentication" : "Accounting", - hostapd_ip_txt(&nserv->addr, abuf, sizeof(abuf)), - nserv->port); - - if (!oserv || nserv->shared_secret_len != oserv->shared_secret_len || - os_memcmp(nserv->shared_secret, oserv->shared_secret, - nserv->shared_secret_len) != 0) { - /* Pending RADIUS packets used different shared secret, so - * they need to be modified. Update accounting message - * authenticators here. Authentication messages are removed - * since they would require more changes and the new RADIUS - * server may not be prepared to receive them anyway due to - * missing state information. Client will likely retry - * authentication, so this should not be an issue. */ - if (auth) - radius_client_flush(radius, 1); - else { - radius_client_update_acct_msgs( - radius, nserv->shared_secret, - nserv->shared_secret_len); - } - } - - /* Reset retry counters for the new server */ - for (entry = radius->msgs; entry; entry = entry->next) { - if ((auth && entry->msg_type != RADIUS_AUTH) || - (!auth && entry->msg_type != RADIUS_ACCT)) - continue; - entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; - entry->attempts = 0; - entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; - } - - if (radius->msgs) { - eloop_cancel_timeout(radius_client_timer, radius, NULL); - eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0, - radius_client_timer, radius, NULL); - } - - switch (nserv->addr.af) { - case AF_INET: - os_memset(&serv, 0, sizeof(serv)); - serv.sin_family = AF_INET; - serv.sin_addr.s_addr = nserv->addr.u.v4.s_addr; - serv.sin_port = htons(nserv->port); - addr = (struct sockaddr *) &serv; - addrlen = sizeof(serv); - sel_sock = sock; - break; -#ifdef CONFIG_IPV6 - case AF_INET6: - os_memset(&serv6, 0, sizeof(serv6)); - serv6.sin6_family = AF_INET6; - os_memcpy(&serv6.sin6_addr, &nserv->addr.u.v6, - sizeof(struct in6_addr)); - serv6.sin6_port = htons(nserv->port); - addr = (struct sockaddr *) &serv6; - addrlen = sizeof(serv6); - sel_sock = sock6; - break; -#endif /* CONFIG_IPV6 */ - default: - return -1; - } - - if (conf->force_client_addr) { - switch (conf->client_addr.af) { - case AF_INET: - os_memset(&claddr, 0, sizeof(claddr)); - claddr.sin_family = AF_INET; - claddr.sin_addr.s_addr = conf->client_addr.u.v4.s_addr; - claddr.sin_port = htons(0); - cl_addr = (struct sockaddr *) &claddr; - claddrlen = sizeof(claddr); - break; -#ifdef CONFIG_IPV6 - case AF_INET6: - os_memset(&claddr6, 0, sizeof(claddr6)); - claddr6.sin6_family = AF_INET6; - os_memcpy(&claddr6.sin6_addr, &conf->client_addr.u.v6, - sizeof(struct in6_addr)); - claddr6.sin6_port = htons(0); - cl_addr = (struct sockaddr *) &claddr6; - claddrlen = sizeof(claddr6); - break; -#endif /* CONFIG_IPV6 */ - default: - return -1; - } - - if (bind(sel_sock, cl_addr, claddrlen) < 0) { - perror("bind[radius]"); - return -1; - } - } - - if (connect(sel_sock, addr, addrlen) < 0) { - perror("connect[radius]"); - return -1; - } - -#ifndef CONFIG_NATIVE_WINDOWS - switch (nserv->addr.af) { - case AF_INET: - claddrlen = sizeof(claddr); - getsockname(sel_sock, (struct sockaddr *) &claddr, &claddrlen); - wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", - inet_ntoa(claddr.sin_addr), ntohs(claddr.sin_port)); - break; -#ifdef CONFIG_IPV6 - case AF_INET6: { - claddrlen = sizeof(claddr6); - getsockname(sel_sock, (struct sockaddr *) &claddr6, - &claddrlen); - wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", - inet_ntop(AF_INET6, &claddr6.sin6_addr, - abuf, sizeof(abuf)), - ntohs(claddr6.sin6_port)); - break; - } -#endif /* CONFIG_IPV6 */ - } -#endif /* CONFIG_NATIVE_WINDOWS */ - - if (auth) - radius->auth_sock = sel_sock; - else - radius->acct_sock = sel_sock; - - return 0; -} - - -static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx) -{ - struct radius_client_data *radius = eloop_ctx; - struct hostapd_radius_servers *conf = radius->conf; - struct hostapd_radius_server *oserv; - - if (radius->auth_sock >= 0 && conf->auth_servers && - conf->auth_server != conf->auth_servers) { - oserv = conf->auth_server; - conf->auth_server = conf->auth_servers; - radius_change_server(radius, conf->auth_server, oserv, - radius->auth_serv_sock, - radius->auth_serv_sock6, 1); - } - - if (radius->acct_sock >= 0 && conf->acct_servers && - conf->acct_server != conf->acct_servers) { - oserv = conf->acct_server; - conf->acct_server = conf->acct_servers; - radius_change_server(radius, conf->acct_server, oserv, - radius->acct_serv_sock, - radius->acct_serv_sock6, 0); - } - - if (conf->retry_primary_interval) - eloop_register_timeout(conf->retry_primary_interval, 0, - radius_retry_primary_timer, radius, - NULL); -} - - -static int radius_client_disable_pmtu_discovery(int s) -{ - int r = -1; -#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) - /* Turn off Path MTU discovery on IPv4/UDP sockets. */ - int action = IP_PMTUDISC_DONT; - r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action, - sizeof(action)); - if (r == -1) - wpa_printf(MSG_ERROR, "Failed to set IP_MTU_DISCOVER: " - "%s", strerror(errno)); -#endif - return r; -} - - -static int radius_client_init_auth(struct radius_client_data *radius) -{ - struct hostapd_radius_servers *conf = radius->conf; - int ok = 0; - - radius->auth_serv_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (radius->auth_serv_sock < 0) - perror("socket[PF_INET,SOCK_DGRAM]"); - else { - radius_client_disable_pmtu_discovery(radius->auth_serv_sock); - ok++; - } - -#ifdef CONFIG_IPV6 - radius->auth_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0); - if (radius->auth_serv_sock6 < 0) - perror("socket[PF_INET6,SOCK_DGRAM]"); - else - ok++; -#endif /* CONFIG_IPV6 */ - - if (ok == 0) - return -1; - - radius_change_server(radius, conf->auth_server, NULL, - radius->auth_serv_sock, radius->auth_serv_sock6, - 1); - - if (radius->auth_serv_sock >= 0 && - eloop_register_read_sock(radius->auth_serv_sock, - radius_client_receive, radius, - (void *) RADIUS_AUTH)) { - printf("Could not register read socket for authentication " - "server\n"); - return -1; - } - -#ifdef CONFIG_IPV6 - if (radius->auth_serv_sock6 >= 0 && - eloop_register_read_sock(radius->auth_serv_sock6, - radius_client_receive, radius, - (void *) RADIUS_AUTH)) { - printf("Could not register read socket for authentication " - "server\n"); - return -1; - } -#endif /* CONFIG_IPV6 */ - - return 0; -} - - -static int radius_client_init_acct(struct radius_client_data *radius) -{ - struct hostapd_radius_servers *conf = radius->conf; - int ok = 0; - - radius->acct_serv_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (radius->acct_serv_sock < 0) - perror("socket[PF_INET,SOCK_DGRAM]"); - else { - radius_client_disable_pmtu_discovery(radius->acct_serv_sock); - ok++; - } - -#ifdef CONFIG_IPV6 - radius->acct_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0); - if (radius->acct_serv_sock6 < 0) - perror("socket[PF_INET6,SOCK_DGRAM]"); - else - ok++; -#endif /* CONFIG_IPV6 */ - - if (ok == 0) - return -1; - - radius_change_server(radius, conf->acct_server, NULL, - radius->acct_serv_sock, radius->acct_serv_sock6, - 0); - - if (radius->acct_serv_sock >= 0 && - eloop_register_read_sock(radius->acct_serv_sock, - radius_client_receive, radius, - (void *) RADIUS_ACCT)) { - printf("Could not register read socket for accounting " - "server\n"); - return -1; - } - -#ifdef CONFIG_IPV6 - if (radius->acct_serv_sock6 >= 0 && - eloop_register_read_sock(radius->acct_serv_sock6, - radius_client_receive, radius, - (void *) RADIUS_ACCT)) { - printf("Could not register read socket for accounting " - "server\n"); - return -1; - } -#endif /* CONFIG_IPV6 */ - - return 0; -} - - -struct radius_client_data * -radius_client_init(void *ctx, struct hostapd_radius_servers *conf) -{ - struct radius_client_data *radius; - - radius = os_zalloc(sizeof(struct radius_client_data)); - if (radius == NULL) - return NULL; - - radius->ctx = ctx; - radius->conf = conf; - radius->auth_serv_sock = radius->acct_serv_sock = - radius->auth_serv_sock6 = radius->acct_serv_sock6 = - radius->auth_sock = radius->acct_sock = -1; - - if (conf->auth_server && radius_client_init_auth(radius)) { - radius_client_deinit(radius); - return NULL; - } - - if (conf->acct_server && radius_client_init_acct(radius)) { - radius_client_deinit(radius); - return NULL; - } - - if (conf->retry_primary_interval) - eloop_register_timeout(conf->retry_primary_interval, 0, - radius_retry_primary_timer, radius, - NULL); - - return radius; -} - - -void radius_client_deinit(struct radius_client_data *radius) -{ - if (!radius) - return; - - if (radius->auth_serv_sock >= 0) - eloop_unregister_read_sock(radius->auth_serv_sock); - if (radius->acct_serv_sock >= 0) - eloop_unregister_read_sock(radius->acct_serv_sock); -#ifdef CONFIG_IPV6 - if (radius->auth_serv_sock6 >= 0) - eloop_unregister_read_sock(radius->auth_serv_sock6); - if (radius->acct_serv_sock6 >= 0) - eloop_unregister_read_sock(radius->acct_serv_sock6); -#endif /* CONFIG_IPV6 */ - - eloop_cancel_timeout(radius_retry_primary_timer, radius, NULL); - - radius_client_flush(radius, 0); - os_free(radius->auth_handlers); - os_free(radius->acct_handlers); - os_free(radius); -} - - -void radius_client_flush_auth(struct radius_client_data *radius, u8 *addr) -{ - struct radius_msg_list *entry, *prev, *tmp; - - prev = NULL; - entry = radius->msgs; - while (entry) { - if (entry->msg_type == RADIUS_AUTH && - os_memcmp(entry->addr, addr, ETH_ALEN) == 0) { - hostapd_logger(radius->ctx, addr, - HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, - "Removing pending RADIUS authentication" - " message for removed client"); - - if (prev) - prev->next = entry->next; - else - radius->msgs = entry->next; - - tmp = entry; - entry = entry->next; - radius_client_msg_free(tmp); - radius->num_msgs--; - continue; - } - - prev = entry; - entry = entry->next; - } -} - - -static int radius_client_dump_auth_server(char *buf, size_t buflen, - struct hostapd_radius_server *serv, - struct radius_client_data *cli) -{ - int pending = 0; - struct radius_msg_list *msg; - char abuf[50]; - - if (cli) { - for (msg = cli->msgs; msg; msg = msg->next) { - if (msg->msg_type == RADIUS_AUTH) - pending++; - } - } - - return os_snprintf(buf, buflen, - "radiusAuthServerIndex=%d\n" - "radiusAuthServerAddress=%s\n" - "radiusAuthClientServerPortNumber=%d\n" - "radiusAuthClientRoundTripTime=%d\n" - "radiusAuthClientAccessRequests=%u\n" - "radiusAuthClientAccessRetransmissions=%u\n" - "radiusAuthClientAccessAccepts=%u\n" - "radiusAuthClientAccessRejects=%u\n" - "radiusAuthClientAccessChallenges=%u\n" - "radiusAuthClientMalformedAccessResponses=%u\n" - "radiusAuthClientBadAuthenticators=%u\n" - "radiusAuthClientPendingRequests=%u\n" - "radiusAuthClientTimeouts=%u\n" - "radiusAuthClientUnknownTypes=%u\n" - "radiusAuthClientPacketsDropped=%u\n", - serv->index, - hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)), - serv->port, - serv->round_trip_time, - serv->requests, - serv->retransmissions, - serv->access_accepts, - serv->access_rejects, - serv->access_challenges, - serv->malformed_responses, - serv->bad_authenticators, - pending, - serv->timeouts, - serv->unknown_types, - serv->packets_dropped); -} - - -static int radius_client_dump_acct_server(char *buf, size_t buflen, - struct hostapd_radius_server *serv, - struct radius_client_data *cli) -{ - int pending = 0; - struct radius_msg_list *msg; - char abuf[50]; - - if (cli) { - for (msg = cli->msgs; msg; msg = msg->next) { - if (msg->msg_type == RADIUS_ACCT || - msg->msg_type == RADIUS_ACCT_INTERIM) - pending++; - } - } - - return os_snprintf(buf, buflen, - "radiusAccServerIndex=%d\n" - "radiusAccServerAddress=%s\n" - "radiusAccClientServerPortNumber=%d\n" - "radiusAccClientRoundTripTime=%d\n" - "radiusAccClientRequests=%u\n" - "radiusAccClientRetransmissions=%u\n" - "radiusAccClientResponses=%u\n" - "radiusAccClientMalformedResponses=%u\n" - "radiusAccClientBadAuthenticators=%u\n" - "radiusAccClientPendingRequests=%u\n" - "radiusAccClientTimeouts=%u\n" - "radiusAccClientUnknownTypes=%u\n" - "radiusAccClientPacketsDropped=%u\n", - serv->index, - hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)), - serv->port, - serv->round_trip_time, - serv->requests, - serv->retransmissions, - serv->responses, - serv->malformed_responses, - serv->bad_authenticators, - pending, - serv->timeouts, - serv->unknown_types, - serv->packets_dropped); -} - - -int radius_client_get_mib(struct radius_client_data *radius, char *buf, - size_t buflen) -{ - struct hostapd_radius_servers *conf = radius->conf; - int i; - struct hostapd_radius_server *serv; - int count = 0; - - if (conf->auth_servers) { - for (i = 0; i < conf->num_auth_servers; i++) { - serv = &conf->auth_servers[i]; - count += radius_client_dump_auth_server( - buf + count, buflen - count, serv, - serv == conf->auth_server ? - radius : NULL); - } - } - - if (conf->acct_servers) { - for (i = 0; i < conf->num_acct_servers; i++) { - serv = &conf->acct_servers[i]; - count += radius_client_dump_acct_server( - buf + count, buflen - count, serv, - serv == conf->acct_server ? - radius : NULL); - } - } - - return count; -} - - -static int radius_servers_diff(struct hostapd_radius_server *nserv, - struct hostapd_radius_server *oserv, - int num) -{ - int i; - - for (i = 0; i < num; i++) { - if (hostapd_ip_diff(&nserv[i].addr, &oserv[i].addr) || - nserv[i].port != oserv[i].port || - nserv[i].shared_secret_len != oserv[i].shared_secret_len || - os_memcmp(nserv[i].shared_secret, oserv[i].shared_secret, - nserv[i].shared_secret_len) != 0) - return 1; - } - - return 0; -} - - -struct radius_client_data * -radius_client_reconfig(struct radius_client_data *old, void *ctx, - struct hostapd_radius_servers *oldconf, - struct hostapd_radius_servers *newconf) -{ - radius_client_flush(old, 0); - - if (newconf->retry_primary_interval != - oldconf->retry_primary_interval || - newconf->num_auth_servers != oldconf->num_auth_servers || - newconf->num_acct_servers != oldconf->num_acct_servers || - radius_servers_diff(newconf->auth_servers, oldconf->auth_servers, - newconf->num_auth_servers) || - radius_servers_diff(newconf->acct_servers, oldconf->acct_servers, - newconf->num_acct_servers)) { - hostapd_logger(ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, - "Reconfiguring RADIUS client"); - radius_client_deinit(old); - return radius_client_init(ctx, newconf); - } - - return old; -} diff --git a/contrib/hostapd/src/radius/radius_client.h b/contrib/hostapd/src/radius/radius_client.h deleted file mode 100644 index 4fe9ba9a42..0000000000 --- a/contrib/hostapd/src/radius/radius_client.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * hostapd / RADIUS client - * Copyright (c) 2002-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef RADIUS_CLIENT_H -#define RADIUS_CLIENT_H - -#include "ip_addr.h" - -struct radius_msg; - -struct hostapd_radius_server { - /* MIB prefix for shared variables: - * @ = radiusAuth or radiusAcc depending on the type of the server */ - struct hostapd_ip_addr addr; /* @ServerAddress */ - int port; /* @ClientServerPortNumber */ - u8 *shared_secret; - size_t shared_secret_len; - - /* Dynamic (not from configuration file) MIB data */ - int index; /* @ServerIndex */ - int round_trip_time; /* @ClientRoundTripTime; in hundredths of a - * second */ - u32 requests; /* @Client{Access,}Requests */ - u32 retransmissions; /* @Client{Access,}Retransmissions */ - u32 access_accepts; /* radiusAuthClientAccessAccepts */ - u32 access_rejects; /* radiusAuthClientAccessRejects */ - u32 access_challenges; /* radiusAuthClientAccessChallenges */ - u32 responses; /* radiusAccClientResponses */ - u32 malformed_responses; /* @ClientMalformed{Access,}Responses */ - u32 bad_authenticators; /* @ClientBadAuthenticators */ - u32 timeouts; /* @ClientTimeouts */ - u32 unknown_types; /* @ClientUnknownTypes */ - u32 packets_dropped; /* @ClientPacketsDropped */ - /* @ClientPendingRequests: length of hapd->radius->msgs for matching - * msg_type */ -}; - -struct hostapd_radius_servers { - /* RADIUS Authentication and Accounting servers in priority order */ - struct hostapd_radius_server *auth_servers, *auth_server; - int num_auth_servers; - struct hostapd_radius_server *acct_servers, *acct_server; - int num_acct_servers; - - int retry_primary_interval; - int acct_interim_interval; - - int msg_dumps; - - struct hostapd_ip_addr client_addr; - int force_client_addr; -}; - - -typedef enum { - RADIUS_AUTH, - RADIUS_ACCT, - RADIUS_ACCT_INTERIM /* used only with radius_client_send(); just like - * RADIUS_ACCT, but removes any pending interim - * RADIUS Accounting packages for the same STA - * before sending the new interim update */ -} RadiusType; - -typedef enum { - RADIUS_RX_PROCESSED, - RADIUS_RX_QUEUED, - RADIUS_RX_UNKNOWN, - RADIUS_RX_INVALID_AUTHENTICATOR -} RadiusRxResult; - -struct radius_client_data; - -int radius_client_register(struct radius_client_data *radius, - RadiusType msg_type, - RadiusRxResult (*handler) - (struct radius_msg *msg, struct radius_msg *req, - const u8 *shared_secret, size_t shared_secret_len, - void *data), - void *data); -int radius_client_send(struct radius_client_data *radius, - struct radius_msg *msg, - RadiusType msg_type, const u8 *addr); -u8 radius_client_get_id(struct radius_client_data *radius); - -void radius_client_flush(struct radius_client_data *radius, int only_auth); -struct radius_client_data * -radius_client_init(void *ctx, struct hostapd_radius_servers *conf); -void radius_client_deinit(struct radius_client_data *radius); -void radius_client_flush_auth(struct radius_client_data *radius, u8 *addr); -int radius_client_get_mib(struct radius_client_data *radius, char *buf, - size_t buflen); -struct radius_client_data * -radius_client_reconfig(struct radius_client_data *old, void *ctx, - struct hostapd_radius_servers *oldconf, - struct hostapd_radius_servers *newconf); - -#endif /* RADIUS_CLIENT_H */ diff --git a/contrib/hostapd/src/radius/radius_server.c b/contrib/hostapd/src/radius/radius_server.c deleted file mode 100644 index 4f399bcfd1..0000000000 --- a/contrib/hostapd/src/radius/radius_server.c +++ /dev/null @@ -1,1311 +0,0 @@ -/* - * hostapd / RADIUS authentication server - * Copyright (c) 2005-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "radius.h" -#include "eloop.h" -#include "defs.h" -#include "eap_server/eap.h" -#include "radius_server.h" - -#define RADIUS_SESSION_TIMEOUT 60 -#define RADIUS_MAX_SESSION 100 -#define RADIUS_MAX_MSG_LEN 3000 - -static struct eapol_callbacks radius_server_eapol_cb; - -struct radius_client; -struct radius_server_data; - -struct radius_server_counters { - u32 access_requests; - u32 invalid_requests; - u32 dup_access_requests; - u32 access_accepts; - u32 access_rejects; - u32 access_challenges; - u32 malformed_access_requests; - u32 bad_authenticators; - u32 packets_dropped; - u32 unknown_types; -}; - -struct radius_session { - struct radius_session *next; - struct radius_client *client; - struct radius_server_data *server; - unsigned int sess_id; - struct eap_sm *eap; - struct eap_eapol_interface *eap_if; - - struct radius_msg *last_msg; - char *last_from_addr; - int last_from_port; - struct sockaddr_storage last_from; - socklen_t last_fromlen; - u8 last_identifier; - struct radius_msg *last_reply; - u8 last_authenticator[16]; -}; - -struct radius_client { - struct radius_client *next; - struct in_addr addr; - struct in_addr mask; -#ifdef CONFIG_IPV6 - struct in6_addr addr6; - struct in6_addr mask6; -#endif /* CONFIG_IPV6 */ - char *shared_secret; - int shared_secret_len; - struct radius_session *sessions; - struct radius_server_counters counters; -}; - -struct radius_server_data { - int auth_sock; - struct radius_client *clients; - unsigned int next_sess_id; - void *conf_ctx; - int num_sess; - void *eap_sim_db_priv; - void *ssl_ctx; - u8 *pac_opaque_encr_key; - u8 *eap_fast_a_id; - size_t eap_fast_a_id_len; - char *eap_fast_a_id_info; - int eap_fast_prov; - int pac_key_lifetime; - int pac_key_refresh_time; - int eap_sim_aka_result_ind; - int tnc; - struct wps_context *wps; - int ipv6; - struct os_time start_time; - struct radius_server_counters counters; - int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len, - int phase2, struct eap_user *user); - char *eap_req_id_text; - size_t eap_req_id_text_len; -}; - - -extern int wpa_debug_level; - -#define RADIUS_DEBUG(args...) \ -wpa_printf(MSG_DEBUG, "RADIUS SRV: " args) -#define RADIUS_ERROR(args...) \ -wpa_printf(MSG_ERROR, "RADIUS SRV: " args) -#define RADIUS_DUMP(args...) \ -wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args) -#define RADIUS_DUMP_ASCII(args...) \ -wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args) - - -static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx); -static void radius_server_session_remove_timeout(void *eloop_ctx, - void *timeout_ctx); - - -static struct radius_client * -radius_server_get_client(struct radius_server_data *data, struct in_addr *addr, - int ipv6) -{ - struct radius_client *client = data->clients; - - while (client) { -#ifdef CONFIG_IPV6 - if (ipv6) { - struct in6_addr *addr6; - int i; - - addr6 = (struct in6_addr *) addr; - for (i = 0; i < 16; i++) { - if ((addr6->s6_addr[i] & - client->mask6.s6_addr[i]) != - (client->addr6.s6_addr[i] & - client->mask6.s6_addr[i])) { - i = 17; - break; - } - } - if (i == 16) { - break; - } - } -#endif /* CONFIG_IPV6 */ - if (!ipv6 && (client->addr.s_addr & client->mask.s_addr) == - (addr->s_addr & client->mask.s_addr)) { - break; - } - - client = client->next; - } - - return client; -} - - -static struct radius_session * -radius_server_get_session(struct radius_client *client, unsigned int sess_id) -{ - struct radius_session *sess = client->sessions; - - while (sess) { - if (sess->sess_id == sess_id) { - break; - } - sess = sess->next; - } - - return sess; -} - - -static void radius_server_session_free(struct radius_server_data *data, - struct radius_session *sess) -{ - eloop_cancel_timeout(radius_server_session_timeout, data, sess); - eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess); - eap_server_sm_deinit(sess->eap); - if (sess->last_msg) { - radius_msg_free(sess->last_msg); - os_free(sess->last_msg); - } - os_free(sess->last_from_addr); - if (sess->last_reply) { - radius_msg_free(sess->last_reply); - os_free(sess->last_reply); - } - os_free(sess); - data->num_sess--; -} - - -static void radius_server_session_remove(struct radius_server_data *data, - struct radius_session *sess) -{ - struct radius_client *client = sess->client; - struct radius_session *session, *prev; - - eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess); - - prev = NULL; - session = client->sessions; - while (session) { - if (session == sess) { - if (prev == NULL) { - client->sessions = sess->next; - } else { - prev->next = sess->next; - } - radius_server_session_free(data, sess); - break; - } - prev = session; - session = session->next; - } -} - - -static void radius_server_session_remove_timeout(void *eloop_ctx, - void *timeout_ctx) -{ - struct radius_server_data *data = eloop_ctx; - struct radius_session *sess = timeout_ctx; - RADIUS_DEBUG("Removing completed session 0x%x", sess->sess_id); - radius_server_session_remove(data, sess); -} - - -static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct radius_server_data *data = eloop_ctx; - struct radius_session *sess = timeout_ctx; - - RADIUS_DEBUG("Timing out authentication session 0x%x", sess->sess_id); - radius_server_session_remove(data, sess); -} - - -static struct radius_session * -radius_server_new_session(struct radius_server_data *data, - struct radius_client *client) -{ - struct radius_session *sess; - - if (data->num_sess >= RADIUS_MAX_SESSION) { - RADIUS_DEBUG("Maximum number of existing session - no room " - "for a new session"); - return NULL; - } - - sess = os_zalloc(sizeof(*sess)); - if (sess == NULL) - return NULL; - - sess->server = data; - sess->client = client; - sess->sess_id = data->next_sess_id++; - sess->next = client->sessions; - client->sessions = sess; - eloop_register_timeout(RADIUS_SESSION_TIMEOUT, 0, - radius_server_session_timeout, data, sess); - data->num_sess++; - return sess; -} - - -static struct radius_session * -radius_server_get_new_session(struct radius_server_data *data, - struct radius_client *client, - struct radius_msg *msg) -{ - u8 *user; - size_t user_len; - int res; - struct radius_session *sess; - struct eap_config eap_conf; - - RADIUS_DEBUG("Creating a new session"); - - user = os_malloc(256); - if (user == NULL) { - return NULL; - } - res = radius_msg_get_attr(msg, RADIUS_ATTR_USER_NAME, user, 256); - if (res < 0 || res > 256) { - RADIUS_DEBUG("Could not get User-Name"); - os_free(user); - return NULL; - } - user_len = res; - RADIUS_DUMP_ASCII("User-Name", user, user_len); - - res = data->get_eap_user(data->conf_ctx, user, user_len, 0, NULL); - os_free(user); - - if (res == 0) { - RADIUS_DEBUG("Matching user entry found"); - sess = radius_server_new_session(data, client); - if (sess == NULL) { - RADIUS_DEBUG("Failed to create a new session"); - return NULL; - } - } else { - RADIUS_DEBUG("User-Name not found from user database"); - return NULL; - } - - os_memset(&eap_conf, 0, sizeof(eap_conf)); - eap_conf.ssl_ctx = data->ssl_ctx; - eap_conf.eap_sim_db_priv = data->eap_sim_db_priv; - eap_conf.backend_auth = TRUE; - eap_conf.eap_server = 1; - eap_conf.pac_opaque_encr_key = data->pac_opaque_encr_key; - eap_conf.eap_fast_a_id = data->eap_fast_a_id; - eap_conf.eap_fast_a_id_len = data->eap_fast_a_id_len; - eap_conf.eap_fast_a_id_info = data->eap_fast_a_id_info; - eap_conf.eap_fast_prov = data->eap_fast_prov; - eap_conf.pac_key_lifetime = data->pac_key_lifetime; - eap_conf.pac_key_refresh_time = data->pac_key_refresh_time; - eap_conf.eap_sim_aka_result_ind = data->eap_sim_aka_result_ind; - eap_conf.tnc = data->tnc; - eap_conf.wps = data->wps; - sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb, - &eap_conf); - if (sess->eap == NULL) { - RADIUS_DEBUG("Failed to initialize EAP state machine for the " - "new session"); - radius_server_session_free(data, sess); - return NULL; - } - sess->eap_if = eap_get_interface(sess->eap); - sess->eap_if->eapRestart = TRUE; - sess->eap_if->portEnabled = TRUE; - - RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id); - - return sess; -} - - -static struct radius_msg * -radius_server_encapsulate_eap(struct radius_server_data *data, - struct radius_client *client, - struct radius_session *sess, - struct radius_msg *request) -{ - struct radius_msg *msg; - int code; - unsigned int sess_id; - - if (sess->eap_if->eapFail) { - sess->eap_if->eapFail = FALSE; - code = RADIUS_CODE_ACCESS_REJECT; - } else if (sess->eap_if->eapSuccess) { - sess->eap_if->eapSuccess = FALSE; - code = RADIUS_CODE_ACCESS_ACCEPT; - } else { - sess->eap_if->eapReq = FALSE; - code = RADIUS_CODE_ACCESS_CHALLENGE; - } - - msg = radius_msg_new(code, request->hdr->identifier); - if (msg == NULL) { - RADIUS_DEBUG("Failed to allocate reply message"); - return NULL; - } - - sess_id = htonl(sess->sess_id); - if (code == RADIUS_CODE_ACCESS_CHALLENGE && - !radius_msg_add_attr(msg, RADIUS_ATTR_STATE, - (u8 *) &sess_id, sizeof(sess_id))) { - RADIUS_DEBUG("Failed to add State attribute"); - } - - if (sess->eap_if->eapReqData && - !radius_msg_add_eap(msg, wpabuf_head(sess->eap_if->eapReqData), - wpabuf_len(sess->eap_if->eapReqData))) { - RADIUS_DEBUG("Failed to add EAP-Message attribute"); - } - - if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) { - int len; - if (sess->eap_if->eapKeyDataLen > 64) { - len = 32; - } else { - len = sess->eap_if->eapKeyDataLen / 2; - } - if (!radius_msg_add_mppe_keys(msg, request->hdr->authenticator, - (u8 *) client->shared_secret, - client->shared_secret_len, - sess->eap_if->eapKeyData + len, - len, sess->eap_if->eapKeyData, - len)) { - RADIUS_DEBUG("Failed to add MPPE key attributes"); - } - } - - if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) { - RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)"); - radius_msg_free(msg); - os_free(msg); - return NULL; - } - - if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, - client->shared_secret_len, - request->hdr->authenticator) < 0) { - RADIUS_DEBUG("Failed to add Message-Authenticator attribute"); - } - - return msg; -} - - -static int radius_server_reject(struct radius_server_data *data, - struct radius_client *client, - struct radius_msg *request, - struct sockaddr *from, socklen_t fromlen, - const char *from_addr, int from_port) -{ - struct radius_msg *msg; - int ret = 0; - struct eap_hdr eapfail; - - RADIUS_DEBUG("Reject invalid request from %s:%d", - from_addr, from_port); - - msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT, - request->hdr->identifier); - if (msg == NULL) { - return -1; - } - - os_memset(&eapfail, 0, sizeof(eapfail)); - eapfail.code = EAP_CODE_FAILURE; - eapfail.identifier = 0; - eapfail.length = host_to_be16(sizeof(eapfail)); - - if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) { - RADIUS_DEBUG("Failed to add EAP-Message attribute"); - } - - if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) { - RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)"); - radius_msg_free(msg); - os_free(msg); - return -1; - } - - if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, - client->shared_secret_len, - request->hdr->authenticator) < 0) { - RADIUS_DEBUG("Failed to add Message-Authenticator attribute"); - } - - if (wpa_debug_level <= MSG_MSGDUMP) { - radius_msg_dump(msg); - } - - data->counters.access_rejects++; - client->counters.access_rejects++; - if (sendto(data->auth_sock, msg->buf, msg->buf_used, 0, - (struct sockaddr *) from, sizeof(*from)) < 0) { - perror("sendto[RADIUS SRV]"); - ret = -1; - } - - radius_msg_free(msg); - os_free(msg); - - return ret; -} - - -static int radius_server_request(struct radius_server_data *data, - struct radius_msg *msg, - struct sockaddr *from, socklen_t fromlen, - struct radius_client *client, - const char *from_addr, int from_port, - struct radius_session *force_sess) -{ - u8 *eap = NULL; - size_t eap_len; - int res, state_included = 0; - u8 statebuf[4]; - unsigned int state; - struct radius_session *sess; - struct radius_msg *reply; - int is_complete = 0; - - if (force_sess) - sess = force_sess; - else { - res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf, - sizeof(statebuf)); - state_included = res >= 0; - if (res == sizeof(statebuf)) { - state = WPA_GET_BE32(statebuf); - sess = radius_server_get_session(client, state); - } else { - sess = NULL; - } - } - - if (sess) { - RADIUS_DEBUG("Request for session 0x%x", sess->sess_id); - } else if (state_included) { - RADIUS_DEBUG("State attribute included but no session found"); - radius_server_reject(data, client, msg, from, fromlen, - from_addr, from_port); - return -1; - } else { - sess = radius_server_get_new_session(data, client, msg); - if (sess == NULL) { - RADIUS_DEBUG("Could not create a new session"); - radius_server_reject(data, client, msg, from, fromlen, - from_addr, from_port); - return -1; - } - } - - if (sess->last_from_port == from_port && - sess->last_identifier == msg->hdr->identifier && - os_memcmp(sess->last_authenticator, msg->hdr->authenticator, 16) == - 0) { - RADIUS_DEBUG("Duplicate message from %s", from_addr); - data->counters.dup_access_requests++; - client->counters.dup_access_requests++; - - if (sess->last_reply) { - res = sendto(data->auth_sock, sess->last_reply->buf, - sess->last_reply->buf_used, 0, - (struct sockaddr *) from, fromlen); - if (res < 0) { - perror("sendto[RADIUS SRV]"); - } - return 0; - } - - RADIUS_DEBUG("No previous reply available for duplicate " - "message"); - return -1; - } - - eap = radius_msg_get_eap(msg, &eap_len); - if (eap == NULL) { - RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s", - from_addr); - data->counters.packets_dropped++; - client->counters.packets_dropped++; - return -1; - } - - RADIUS_DUMP("Received EAP data", eap, eap_len); - - /* FIX: if Code is Request, Success, or Failure, send Access-Reject; - * RFC3579 Sect. 2.6.2. - * Include EAP-Response/Nak with no preferred method if - * code == request. - * If code is not 1-4, discard the packet silently. - * Or is this already done by the EAP state machine? */ - - wpabuf_free(sess->eap_if->eapRespData); - sess->eap_if->eapRespData = wpabuf_alloc_ext_data(eap, eap_len); - if (sess->eap_if->eapRespData == NULL) - os_free(eap); - eap = NULL; - sess->eap_if->eapResp = TRUE; - eap_server_sm_step(sess->eap); - - if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess || - sess->eap_if->eapFail) && sess->eap_if->eapReqData) { - RADIUS_DUMP("EAP data from the state machine", - wpabuf_head(sess->eap_if->eapReqData), - wpabuf_len(sess->eap_if->eapReqData)); - } else if (sess->eap_if->eapFail) { - RADIUS_DEBUG("No EAP data from the state machine, but eapFail " - "set"); - } else if (eap_sm_method_pending(sess->eap)) { - if (sess->last_msg) { - radius_msg_free(sess->last_msg); - os_free(sess->last_msg); - } - sess->last_msg = msg; - sess->last_from_port = from_port; - os_free(sess->last_from_addr); - sess->last_from_addr = os_strdup(from_addr); - sess->last_fromlen = fromlen; - os_memcpy(&sess->last_from, from, fromlen); - return -2; - } else { - RADIUS_DEBUG("No EAP data from the state machine - ignore this" - " Access-Request silently (assuming it was a " - "duplicate)"); - data->counters.packets_dropped++; - client->counters.packets_dropped++; - return -1; - } - - if (sess->eap_if->eapSuccess || sess->eap_if->eapFail) - is_complete = 1; - - reply = radius_server_encapsulate_eap(data, client, sess, msg); - - if (reply) { - RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port); - if (wpa_debug_level <= MSG_MSGDUMP) { - radius_msg_dump(reply); - } - - switch (reply->hdr->code) { - case RADIUS_CODE_ACCESS_ACCEPT: - data->counters.access_accepts++; - client->counters.access_accepts++; - break; - case RADIUS_CODE_ACCESS_REJECT: - data->counters.access_rejects++; - client->counters.access_rejects++; - break; - case RADIUS_CODE_ACCESS_CHALLENGE: - data->counters.access_challenges++; - client->counters.access_challenges++; - break; - } - res = sendto(data->auth_sock, reply->buf, reply->buf_used, 0, - (struct sockaddr *) from, fromlen); - if (res < 0) { - perror("sendto[RADIUS SRV]"); - } - if (sess->last_reply) { - radius_msg_free(sess->last_reply); - os_free(sess->last_reply); - } - sess->last_reply = reply; - sess->last_from_port = from_port; - sess->last_identifier = msg->hdr->identifier; - os_memcpy(sess->last_authenticator, msg->hdr->authenticator, - 16); - } else { - data->counters.packets_dropped++; - client->counters.packets_dropped++; - } - - if (is_complete) { - RADIUS_DEBUG("Removing completed session 0x%x after timeout", - sess->sess_id); - eloop_cancel_timeout(radius_server_session_remove_timeout, - data, sess); - eloop_register_timeout(10, 0, - radius_server_session_remove_timeout, - data, sess); - } - - return 0; -} - - -static void radius_server_receive_auth(int sock, void *eloop_ctx, - void *sock_ctx) -{ - struct radius_server_data *data = eloop_ctx; - u8 *buf = NULL; - union { - struct sockaddr_storage ss; - struct sockaddr_in sin; -#ifdef CONFIG_IPV6 - struct sockaddr_in6 sin6; -#endif /* CONFIG_IPV6 */ - } from; - socklen_t fromlen; - int len; - struct radius_client *client = NULL; - struct radius_msg *msg = NULL; - char abuf[50]; - int from_port = 0; - - buf = os_malloc(RADIUS_MAX_MSG_LEN); - if (buf == NULL) { - goto fail; - } - - fromlen = sizeof(from); - len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0, - (struct sockaddr *) &from.ss, &fromlen); - if (len < 0) { - perror("recvfrom[radius_server]"); - goto fail; - } - -#ifdef CONFIG_IPV6 - if (data->ipv6) { - if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf, - sizeof(abuf)) == NULL) - abuf[0] = '\0'; - from_port = ntohs(from.sin6.sin6_port); - RADIUS_DEBUG("Received %d bytes from %s:%d", - len, abuf, from_port); - - client = radius_server_get_client(data, - (struct in_addr *) - &from.sin6.sin6_addr, 1); - } -#endif /* CONFIG_IPV6 */ - - if (!data->ipv6) { - os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf)); - from_port = ntohs(from.sin.sin_port); - RADIUS_DEBUG("Received %d bytes from %s:%d", - len, abuf, from_port); - - client = radius_server_get_client(data, &from.sin.sin_addr, 0); - } - - RADIUS_DUMP("Received data", buf, len); - - if (client == NULL) { - RADIUS_DEBUG("Unknown client %s - packet ignored", abuf); - data->counters.invalid_requests++; - goto fail; - } - - msg = radius_msg_parse(buf, len); - if (msg == NULL) { - RADIUS_DEBUG("Parsing incoming RADIUS frame failed"); - data->counters.malformed_access_requests++; - client->counters.malformed_access_requests++; - goto fail; - } - - os_free(buf); - buf = NULL; - - if (wpa_debug_level <= MSG_MSGDUMP) { - radius_msg_dump(msg); - } - - if (msg->hdr->code != RADIUS_CODE_ACCESS_REQUEST) { - RADIUS_DEBUG("Unexpected RADIUS code %d", msg->hdr->code); - data->counters.unknown_types++; - client->counters.unknown_types++; - goto fail; - } - - data->counters.access_requests++; - client->counters.access_requests++; - - if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret, - client->shared_secret_len, NULL)) { - RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf); - data->counters.bad_authenticators++; - client->counters.bad_authenticators++; - goto fail; - } - - if (radius_server_request(data, msg, (struct sockaddr *) &from, - fromlen, client, abuf, from_port, NULL) == - -2) - return; /* msg was stored with the session */ - -fail: - if (msg) { - radius_msg_free(msg); - os_free(msg); - } - os_free(buf); -} - - -static int radius_server_disable_pmtu_discovery(int s) -{ - int r = -1; -#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) - /* Turn off Path MTU discovery on IPv4/UDP sockets. */ - int action = IP_PMTUDISC_DONT; - r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action, - sizeof(action)); - if (r == -1) - wpa_printf(MSG_ERROR, "Failed to set IP_MTU_DISCOVER: " - "%s", strerror(errno)); -#endif - return r; -} - - -static int radius_server_open_socket(int port) -{ - int s; - struct sockaddr_in addr; - - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s < 0) { - perror("socket"); - return -1; - } - - radius_server_disable_pmtu_discovery(s); - - os_memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind"); - close(s); - return -1; - } - - return s; -} - - -#ifdef CONFIG_IPV6 -static int radius_server_open_socket6(int port) -{ - int s; - struct sockaddr_in6 addr; - - s = socket(PF_INET6, SOCK_DGRAM, 0); - if (s < 0) { - perror("socket[IPv6]"); - return -1; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sin6_family = AF_INET6; - os_memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any)); - addr.sin6_port = htons(port); - if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind"); - close(s); - return -1; - } - - return s; -} -#endif /* CONFIG_IPV6 */ - - -static void radius_server_free_sessions(struct radius_server_data *data, - struct radius_session *sessions) -{ - struct radius_session *session, *prev; - - session = sessions; - while (session) { - prev = session; - session = session->next; - radius_server_session_free(data, prev); - } -} - - -static void radius_server_free_clients(struct radius_server_data *data, - struct radius_client *clients) -{ - struct radius_client *client, *prev; - - client = clients; - while (client) { - prev = client; - client = client->next; - - radius_server_free_sessions(data, prev->sessions); - os_free(prev->shared_secret); - os_free(prev); - } -} - - -static struct radius_client * -radius_server_read_clients(const char *client_file, int ipv6) -{ - FILE *f; - const int buf_size = 1024; - char *buf, *pos; - struct radius_client *clients, *tail, *entry; - int line = 0, mask, failed = 0, i; - struct in_addr addr; -#ifdef CONFIG_IPV6 - struct in6_addr addr6; -#endif /* CONFIG_IPV6 */ - unsigned int val; - - f = fopen(client_file, "r"); - if (f == NULL) { - RADIUS_ERROR("Could not open client file '%s'", client_file); - return NULL; - } - - buf = os_malloc(buf_size); - if (buf == NULL) { - fclose(f); - return NULL; - } - - clients = tail = NULL; - while (fgets(buf, buf_size, f)) { - /* Configuration file format: - * 192.168.1.0/24 secret - * 192.168.1.2 secret - * fe80::211:22ff:fe33:4455/64 secretipv6 - */ - line++; - buf[buf_size - 1] = '\0'; - pos = buf; - while (*pos != '\0' && *pos != '\n') - pos++; - if (*pos == '\n') - *pos = '\0'; - if (*buf == '\0' || *buf == '#') - continue; - - pos = buf; - while ((*pos >= '0' && *pos <= '9') || *pos == '.' || - (*pos >= 'a' && *pos <= 'f') || *pos == ':' || - (*pos >= 'A' && *pos <= 'F')) { - pos++; - } - - if (*pos == '\0') { - failed = 1; - break; - } - - if (*pos == '/') { - char *end; - *pos++ = '\0'; - mask = strtol(pos, &end, 10); - if ((pos == end) || - (mask < 0 || mask > (ipv6 ? 128 : 32))) { - failed = 1; - break; - } - pos = end; - } else { - mask = ipv6 ? 128 : 32; - *pos++ = '\0'; - } - - if (!ipv6 && inet_aton(buf, &addr) == 0) { - failed = 1; - break; - } -#ifdef CONFIG_IPV6 - if (ipv6 && inet_pton(AF_INET6, buf, &addr6) <= 0) { - if (inet_pton(AF_INET, buf, &addr) <= 0) { - failed = 1; - break; - } - /* Convert IPv4 address to IPv6 */ - if (mask <= 32) - mask += (128 - 32); - os_memset(addr6.s6_addr, 0, 10); - addr6.s6_addr[10] = 0xff; - addr6.s6_addr[11] = 0xff; - os_memcpy(addr6.s6_addr + 12, (char *) &addr.s_addr, - 4); - } -#endif /* CONFIG_IPV6 */ - - while (*pos == ' ' || *pos == '\t') { - pos++; - } - - if (*pos == '\0') { - failed = 1; - break; - } - - entry = os_zalloc(sizeof(*entry)); - if (entry == NULL) { - failed = 1; - break; - } - entry->shared_secret = os_strdup(pos); - if (entry->shared_secret == NULL) { - failed = 1; - os_free(entry); - break; - } - entry->shared_secret_len = os_strlen(entry->shared_secret); - entry->addr.s_addr = addr.s_addr; - if (!ipv6) { - val = 0; - for (i = 0; i < mask; i++) - val |= 1 << (31 - i); - entry->mask.s_addr = htonl(val); - } -#ifdef CONFIG_IPV6 - if (ipv6) { - int offset = mask / 8; - - os_memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16); - os_memset(entry->mask6.s6_addr, 0xff, offset); - val = 0; - for (i = 0; i < (mask % 8); i++) - val |= 1 << (7 - i); - if (offset < 16) - entry->mask6.s6_addr[offset] = val; - } -#endif /* CONFIG_IPV6 */ - - if (tail == NULL) { - clients = tail = entry; - } else { - tail->next = entry; - tail = entry; - } - } - - if (failed) { - RADIUS_ERROR("Invalid line %d in '%s'", line, client_file); - radius_server_free_clients(NULL, clients); - clients = NULL; - } - - os_free(buf); - fclose(f); - - return clients; -} - - -struct radius_server_data * -radius_server_init(struct radius_server_conf *conf) -{ - struct radius_server_data *data; - -#ifndef CONFIG_IPV6 - if (conf->ipv6) { - fprintf(stderr, "RADIUS server compiled without IPv6 " - "support.\n"); - return NULL; - } -#endif /* CONFIG_IPV6 */ - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - os_get_time(&data->start_time); - data->conf_ctx = conf->conf_ctx; - data->eap_sim_db_priv = conf->eap_sim_db_priv; - data->ssl_ctx = conf->ssl_ctx; - data->ipv6 = conf->ipv6; - if (conf->pac_opaque_encr_key) { - data->pac_opaque_encr_key = os_malloc(16); - os_memcpy(data->pac_opaque_encr_key, conf->pac_opaque_encr_key, - 16); - } - if (conf->eap_fast_a_id) { - data->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len); - if (data->eap_fast_a_id) { - os_memcpy(data->eap_fast_a_id, conf->eap_fast_a_id, - conf->eap_fast_a_id_len); - data->eap_fast_a_id_len = conf->eap_fast_a_id_len; - } - } - if (conf->eap_fast_a_id_info) - data->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info); - data->eap_fast_prov = conf->eap_fast_prov; - data->pac_key_lifetime = conf->pac_key_lifetime; - data->pac_key_refresh_time = conf->pac_key_refresh_time; - data->get_eap_user = conf->get_eap_user; - data->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind; - data->tnc = conf->tnc; - data->wps = conf->wps; - if (conf->eap_req_id_text) { - data->eap_req_id_text = os_malloc(conf->eap_req_id_text_len); - if (data->eap_req_id_text) { - os_memcpy(data->eap_req_id_text, conf->eap_req_id_text, - conf->eap_req_id_text_len); - data->eap_req_id_text_len = conf->eap_req_id_text_len; - } - } - - data->clients = radius_server_read_clients(conf->client_file, - conf->ipv6); - if (data->clients == NULL) { - printf("No RADIUS clients configured.\n"); - radius_server_deinit(data); - return NULL; - } - -#ifdef CONFIG_IPV6 - if (conf->ipv6) - data->auth_sock = radius_server_open_socket6(conf->auth_port); - else -#endif /* CONFIG_IPV6 */ - data->auth_sock = radius_server_open_socket(conf->auth_port); - if (data->auth_sock < 0) { - printf("Failed to open UDP socket for RADIUS authentication " - "server\n"); - radius_server_deinit(data); - return NULL; - } - if (eloop_register_read_sock(data->auth_sock, - radius_server_receive_auth, - data, NULL)) { - radius_server_deinit(data); - return NULL; - } - - return data; -} - - -void radius_server_deinit(struct radius_server_data *data) -{ - if (data == NULL) - return; - - if (data->auth_sock >= 0) { - eloop_unregister_read_sock(data->auth_sock); - close(data->auth_sock); - } - - radius_server_free_clients(data, data->clients); - - os_free(data->pac_opaque_encr_key); - os_free(data->eap_fast_a_id); - os_free(data->eap_fast_a_id_info); - os_free(data->eap_req_id_text); - os_free(data); -} - - -int radius_server_get_mib(struct radius_server_data *data, char *buf, - size_t buflen) -{ - int ret, uptime; - unsigned int idx; - char *end, *pos; - struct os_time now; - struct radius_client *cli; - - /* RFC 2619 - RADIUS Authentication Server MIB */ - - if (data == NULL || buflen == 0) - return 0; - - pos = buf; - end = buf + buflen; - - os_get_time(&now); - uptime = (now.sec - data->start_time.sec) * 100 + - ((now.usec - data->start_time.usec) / 10000) % 100; - ret = os_snprintf(pos, end - pos, - "RADIUS-AUTH-SERVER-MIB\n" - "radiusAuthServIdent=hostapd\n" - "radiusAuthServUpTime=%d\n" - "radiusAuthServResetTime=0\n" - "radiusAuthServConfigReset=4\n", - uptime); - if (ret < 0 || ret >= end - pos) { - *pos = '\0'; - return pos - buf; - } - pos += ret; - - ret = os_snprintf(pos, end - pos, - "radiusAuthServTotalAccessRequests=%u\n" - "radiusAuthServTotalInvalidRequests=%u\n" - "radiusAuthServTotalDupAccessRequests=%u\n" - "radiusAuthServTotalAccessAccepts=%u\n" - "radiusAuthServTotalAccessRejects=%u\n" - "radiusAuthServTotalAccessChallenges=%u\n" - "radiusAuthServTotalMalformedAccessRequests=%u\n" - "radiusAuthServTotalBadAuthenticators=%u\n" - "radiusAuthServTotalPacketsDropped=%u\n" - "radiusAuthServTotalUnknownTypes=%u\n", - data->counters.access_requests, - data->counters.invalid_requests, - data->counters.dup_access_requests, - data->counters.access_accepts, - data->counters.access_rejects, - data->counters.access_challenges, - data->counters.malformed_access_requests, - data->counters.bad_authenticators, - data->counters.packets_dropped, - data->counters.unknown_types); - if (ret < 0 || ret >= end - pos) { - *pos = '\0'; - return pos - buf; - } - pos += ret; - - for (cli = data->clients, idx = 0; cli; cli = cli->next, idx++) { - char abuf[50], mbuf[50]; -#ifdef CONFIG_IPV6 - if (data->ipv6) { - if (inet_ntop(AF_INET6, &cli->addr6, abuf, - sizeof(abuf)) == NULL) - abuf[0] = '\0'; - if (inet_ntop(AF_INET6, &cli->mask6, abuf, - sizeof(mbuf)) == NULL) - mbuf[0] = '\0'; - } -#endif /* CONFIG_IPV6 */ - if (!data->ipv6) { - os_strlcpy(abuf, inet_ntoa(cli->addr), sizeof(abuf)); - os_strlcpy(mbuf, inet_ntoa(cli->mask), sizeof(mbuf)); - } - - ret = os_snprintf(pos, end - pos, - "radiusAuthClientIndex=%u\n" - "radiusAuthClientAddress=%s/%s\n" - "radiusAuthServAccessRequests=%u\n" - "radiusAuthServDupAccessRequests=%u\n" - "radiusAuthServAccessAccepts=%u\n" - "radiusAuthServAccessRejects=%u\n" - "radiusAuthServAccessChallenges=%u\n" - "radiusAuthServMalformedAccessRequests=%u\n" - "radiusAuthServBadAuthenticators=%u\n" - "radiusAuthServPacketsDropped=%u\n" - "radiusAuthServUnknownTypes=%u\n", - idx, - abuf, mbuf, - cli->counters.access_requests, - cli->counters.dup_access_requests, - cli->counters.access_accepts, - cli->counters.access_rejects, - cli->counters.access_challenges, - cli->counters.malformed_access_requests, - cli->counters.bad_authenticators, - cli->counters.packets_dropped, - cli->counters.unknown_types); - if (ret < 0 || ret >= end - pos) { - *pos = '\0'; - return pos - buf; - } - pos += ret; - } - - return pos - buf; -} - - -static int radius_server_get_eap_user(void *ctx, const u8 *identity, - size_t identity_len, int phase2, - struct eap_user *user) -{ - struct radius_session *sess = ctx; - struct radius_server_data *data = sess->server; - - return data->get_eap_user(data->conf_ctx, identity, identity_len, - phase2, user); -} - - -static const char * radius_server_get_eap_req_id_text(void *ctx, size_t *len) -{ - struct radius_session *sess = ctx; - struct radius_server_data *data = sess->server; - *len = data->eap_req_id_text_len; - return data->eap_req_id_text; -} - - -static struct eapol_callbacks radius_server_eapol_cb = -{ - .get_eap_user = radius_server_get_eap_user, - .get_eap_req_id_text = radius_server_get_eap_req_id_text, -}; - - -void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx) -{ - struct radius_client *cli; - struct radius_session *s, *sess = NULL; - struct radius_msg *msg; - - if (data == NULL) - return; - - for (cli = data->clients; cli; cli = cli->next) { - for (s = cli->sessions; s; s = s->next) { - if (s->eap == ctx && s->last_msg) { - sess = s; - break; - } - if (sess) - break; - } - if (sess) - break; - } - - if (sess == NULL) { - RADIUS_DEBUG("No session matched callback ctx"); - return; - } - - msg = sess->last_msg; - sess->last_msg = NULL; - eap_sm_pending_cb(sess->eap); - if (radius_server_request(data, msg, - (struct sockaddr *) &sess->last_from, - sess->last_fromlen, cli, - sess->last_from_addr, - sess->last_from_port, sess) == -2) - return; /* msg was stored with the session */ - - radius_msg_free(msg); - os_free(msg); -} diff --git a/contrib/hostapd/src/radius/radius_server.h b/contrib/hostapd/src/radius/radius_server.h deleted file mode 100644 index d5fb6a1e3f..0000000000 --- a/contrib/hostapd/src/radius/radius_server.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * hostapd / RADIUS authentication server - * Copyright (c) 2005-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef RADIUS_SERVER_H -#define RADIUS_SERVER_H - -struct radius_server_data; -struct eap_user; - -struct radius_server_conf { - int auth_port; - char *client_file; - void *conf_ctx; - void *eap_sim_db_priv; - void *ssl_ctx; - u8 *pac_opaque_encr_key; - u8 *eap_fast_a_id; - size_t eap_fast_a_id_len; - char *eap_fast_a_id_info; - int eap_fast_prov; - int pac_key_lifetime; - int pac_key_refresh_time; - int eap_sim_aka_result_ind; - int tnc; - struct wps_context *wps; - int ipv6; - int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len, - int phase2, struct eap_user *user); - const char *eap_req_id_text; - size_t eap_req_id_text_len; -}; - - -#ifdef RADIUS_SERVER - -struct radius_server_data * -radius_server_init(struct radius_server_conf *conf); - -void radius_server_deinit(struct radius_server_data *data); - -int radius_server_get_mib(struct radius_server_data *data, char *buf, - size_t buflen); - -void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx); - -#else /* RADIUS_SERVER */ - -static inline struct radius_server_data * -radius_server_init(struct radius_server_conf *conf) -{ - return NULL; -} - -static inline void radius_server_deinit(struct radius_server_data *data) -{ -} - -static inline int radius_server_get_mib(struct radius_server_data *data, - char *buf, size_t buflen) -{ - return 0; -} - -static inline void -radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx) -{ -} - -#endif /* RADIUS_SERVER */ - -#endif /* RADIUS_SERVER_H */ diff --git a/contrib/hostapd/src/rsn_supp/peerkey.c b/contrib/hostapd/src/rsn_supp/peerkey.c deleted file mode 100644 index 45c256a027..0000000000 --- a/contrib/hostapd/src/rsn_supp/peerkey.c +++ /dev/null @@ -1,1182 +0,0 @@ -/* - * WPA Supplicant - PeerKey for Direct Link Setup (DLS) - * Copyright (c) 2006-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#ifdef CONFIG_PEERKEY - -#include "common.h" -#include "sha1.h" -#include "sha256.h" -#include "eloop.h" -#include "wpa.h" -#include "wpa_i.h" -#include "wpa_ie.h" -#include "ieee802_11_defs.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 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; - - 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, ver, dst, ETH_P_EAPOL, - rbuf, rlen, err->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; - 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; - - 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, ver, src_addr, ETH_P_EAPOL, - rbuf, rlen, reply->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 = ie.pairwise_cipher & sm->allowed_pairwise_cipher; - if (cipher & WPA_CIPHER_CCMP) { - wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey"); - cipher = WPA_CIPHER_CCMP; - } else if (cipher & WPA_CIPHER_TKIP) { - wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey"); - cipher = WPA_CIPHER_TKIP; - } else { - 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; - } - - /* 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; -#ifdef CONFIG_IEEE80211W - if (ie.key_mgmt & (WPA_KEY_MGMT_IEEE8021X_SHA256 | - WPA_KEY_MGMT_PSK_SHA256)) - peerkey->use_sha256 = 1; -#endif /* CONFIG_IEEE80211W */ - - if (os_get_random(peerkey->pnonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->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; - if (cipher == WPA_CIPHER_CCMP) - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - else if (cipher == WPA_CIPHER_TKIP) - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); - 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 - * @use_sha256: Whether to use SHA256-based KDF - * - * 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 use_sha256) -{ - 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 (use_sha256) - 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_CCMP) - 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_CCMP) - 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 (os_get_random(peerkey->inonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->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, 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_CCMP) - 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_CCMP) - 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, 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 = ie.pairwise_cipher & sm->allowed_pairwise_cipher; - if (cipher & WPA_CIPHER_CCMP) { - wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey"); - peerkey->cipher = WPA_CIPHER_CCMP; - } else if (cipher & WPA_CIPHER_TKIP) { - wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey"); - peerkey->cipher = WPA_CIPHER_TKIP; - } else { - 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; - } - - 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; - struct os_time now; - - 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 expiration time */ - peerkey->lifetime = lifetime; - os_get_time(&now); - peerkey->expiration = now.sec + 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->use_sha256); - 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->use_sha256); - } - 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); - os_memcpy(&error, kde.error, sizeof(error)); - error_type = be_to_host16(error.error_type); - wpa_msg(sm->ctx->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) -{ - struct wpa_eapol_ie_parse ie; - const u8 *kde; - size_t len, 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 */ - kde = (const u8 *) (key + 1); - len = WPA_GET_BE16(key->key_data_length); - wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", kde, len); - if (wpa_supplicant_parse_ies(kde, len, &ie) < 0 || ie.pmkid == NULL) { - wpa_printf(MSG_DEBUG, "RSN: No SMKID in STK 1/4"); - return; - } - if (os_memcmp(ie.pmkid, peerkey->smkid, PMKID_LEN) != 0) { - wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 1/4", - ie.pmkid, PMKID_LEN); - return; - } - - if (os_get_random(peerkey->pnonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->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, - (u8 *) stk, sizeof(*stk), - peerkey->use_sha256); - /* Supplicant: swap tx/rx Mic keys */ - os_memcpy(buf, stk->u.auth.tx_mic_key, 8); - os_memcpy(stk->u.auth.tx_mic_key, stk->u.auth.rx_mic_key, 8); - os_memcpy(stk->u.auth.rx_mic_key, 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; - struct os_time now; - - 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; - - os_get_time(&now); - peerkey->expiration = now.sec + 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) -{ - struct wpa_eapol_ie_parse kde; - const u8 *keydata; - size_t len; - - 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. */ - keydata = (const u8 *) (key + 1); - len = WPA_GET_BE16(key->key_data_length); - wpa_hexdump(MSG_DEBUG, "RSN: msg 2/4 key data", keydata, len); - if (wpa_supplicant_parse_ies(keydata, 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(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) -{ - struct wpa_eapol_ie_parse kde; - const u8 *keydata; - size_t len, 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. */ - keydata = (const u8 *) (key + 1); - len = WPA_GET_BE16(key->key_data_length); - wpa_hexdump(MSG_DEBUG, "RSN: msg 3/4 key data", keydata, len); - if (wpa_supplicant_parse_ies(keydata, 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), - NULL, 0, &peerkey->stk)) - return; - - _key = (u8 *) peerkey->stk.tk1; - if (peerkey->cipher == WPA_CIPHER_TKIP) { - /* Swap Tx/Rx keys for Michael MIC */ - os_memcpy(key_buf, _key, 16); - os_memcpy(key_buf + 16, peerkey->stk.u.auth.rx_mic_key, 8); - os_memcpy(key_buf + 24, peerkey->stk.u.auth.tx_mic_key, 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) { - wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the " - "driver."); - return; - } -} - - -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), (u8 *) peerkey->stk.tk1, - 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 *key, u16 ver, - const u8 *buf, size_t len) -{ - u8 mic[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, - (u8 *) &peerkey->stk, sizeof(peerkey->stk), - peerkey->use_sha256); - peerkey->stk_set = 1; - } - - os_memcpy(mic, key->key_mic, 16); - if (peerkey->tstk_set) { - os_memset(key->key_mic, 0, 16); - wpa_eapol_key_mic(peerkey->tstk.kck, ver, buf, len, - key->key_mic); - if (os_memcmp(mic, key->key_mic, 16) != 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)); - } - } - - if (!ok && peerkey->stk_set) { - os_memset(key->key_mic, 0, 16); - wpa_eapol_key_mic(peerkey->stk.kck, ver, buf, len, - key->key_mic); - if (os_memcmp(mic, key->key_mic, 16) != 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_CCMP) - 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); -#ifdef CONFIG_IEEE80211W - if (wpa_key_mgmt_sha256(sm->key_mgmt)) - peerkey->use_sha256 = 1; -#endif /* CONFIG_IEEE80211W */ - - /* 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 = 0; - if (sm->allowed_pairwise_cipher & WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - pos += RSN_SELECTOR_LEN; - count++; - } - if (sm->allowed_pairwise_cipher & WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); - pos += RSN_SELECTOR_LEN; - count++; - } - 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 (os_get_random(peerkey->inonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->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, 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; - os_free(prev); - } -} - - -void peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey, - struct wpa_eapol_key *key, u16 key_info, u16 ver) -{ - 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); - } 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); - } 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); - } -} - - -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/contrib/hostapd/src/rsn_supp/peerkey.h b/contrib/hostapd/src/rsn_supp/peerkey.h deleted file mode 100644 index 2613127c3e..0000000000 --- a/contrib/hostapd/src/rsn_supp/peerkey.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * WPA Supplicant - PeerKey for Direct Link Setup (DLS) - * Copyright (c) 2006-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING 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; - os_time_t expiration; - int cipher; /* Selected cipher (WPA_CIPHER_*) */ - u8 replay_counter[WPA_REPLAY_COUNTER_LEN]; - int replay_counter_set; - int use_sha256; /* whether AKMP indicate SHA256-based derivations */ - - 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 *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); -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) -{ -} - -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/contrib/hostapd/src/rsn_supp/pmksa_cache.c b/contrib/hostapd/src/rsn_supp/pmksa_cache.c deleted file mode 100644 index f8373de6dd..0000000000 --- a/contrib/hostapd/src/rsn_supp/pmksa_cache.c +++ /dev/null @@ -1,511 +0,0 @@ -/* - * WPA Supplicant - RSN PMKSA cache - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "wpa.h" -#include "eloop.h" -#include "sha1.h" -#include "sha256.h" -#include "wpa_i.h" -#include "eapol_supp/eapol_supp_sm.h" -#include "pmksa_cache.h" - -#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2) - -static const int pmksa_cache_max_entries = 32; - -struct rsn_pmksa_cache { - struct rsn_pmksa_cache_entry *pmksa; /* PMKSA cache */ - int pmksa_count; /* number of entries in PMKSA cache */ - struct wpa_sm *sm; /* TODO: get rid of this reference(?) */ - - void (*free_cb)(struct rsn_pmksa_cache_entry *entry, void *ctx, - int replace); - void *ctx; -}; - - -/** - * rsn_pmkid - Calculate PMK identifier - * @pmk: Pairwise master key - * @pmk_len: Length of pmk in bytes - * @aa: Authenticator address - * @spa: Supplicant address - * @use_sha256: Whether to use SHA256-based KDF - * - * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy - * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA) - */ -static void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, - const u8 *spa, u8 *pmkid, int use_sha256) -{ - char *title = "PMK Name"; - const u8 *addr[3]; - const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; - unsigned char hash[SHA256_MAC_LEN]; - - addr[0] = (u8 *) title; - addr[1] = aa; - addr[2] = spa; - -#ifdef CONFIG_IEEE80211W - if (use_sha256) - hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash); - else -#endif /* CONFIG_IEEE80211W */ - hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash); - os_memcpy(pmkid, hash, PMKID_LEN); -} - - -static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa); - - -static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry) -{ - os_free(entry); -} - - -static void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa, - struct rsn_pmksa_cache_entry *entry, - int replace) -{ - pmksa->pmksa_count--; - pmksa->free_cb(entry, pmksa->ctx, replace); - _pmksa_cache_free_entry(entry); -} - - -static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx) -{ - struct rsn_pmksa_cache *pmksa = eloop_ctx; - struct os_time now; - - os_get_time(&now); - while (pmksa->pmksa && pmksa->pmksa->expiration <= now.sec) { - struct rsn_pmksa_cache_entry *entry = pmksa->pmksa; - pmksa->pmksa = entry->next; - wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for " - MACSTR, MAC2STR(entry->aa)); - pmksa_cache_free_entry(pmksa, entry, 0); - } - - pmksa_cache_set_expiration(pmksa); -} - - -static void pmksa_cache_reauth(void *eloop_ctx, void *timeout_ctx) -{ - struct rsn_pmksa_cache *pmksa = eloop_ctx; - pmksa->sm->cur_pmksa = NULL; - eapol_sm_request_reauth(pmksa->sm->eapol); -} - - -static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa) -{ - int sec; - struct rsn_pmksa_cache_entry *entry; - struct os_time now; - - eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL); - eloop_cancel_timeout(pmksa_cache_reauth, pmksa, NULL); - if (pmksa->pmksa == NULL) - return; - os_get_time(&now); - sec = pmksa->pmksa->expiration - now.sec; - if (sec < 0) - sec = 0; - 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); - if (entry) { - sec = pmksa->pmksa->reauth_time - now.sec; - if (sec < 0) - sec = 0; - eloop_register_timeout(sec, 0, pmksa_cache_reauth, pmksa, - NULL); - } -} - - -/** - * pmksa_cache_add - Add a PMKSA cache entry - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() - * @pmk: The new pairwise master key - * @pmk_len: PMK length in bytes, usually PMK_LEN (32) - * @aa: Authenticator address - * @spa: Supplicant address - * @network_ctx: Network configuration context for this PMK - * @akmp: WPA_KEY_MGMT_* used in key derivation - * 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 - * cache. If an old entry is already in the cache for the same Authenticator, - * this entry will be replaced with the new entry. PMKID will be calculated - * based on the PMK and the driver interface is notified of the new PMKID. - */ -struct rsn_pmksa_cache_entry * -pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, - const u8 *aa, const u8 *spa, void *network_ctx, int akmp) -{ - struct rsn_pmksa_cache_entry *entry, *pos, *prev; - struct os_time now; - - if (pmksa->sm->proto != WPA_PROTO_RSN || pmk_len > PMK_LEN) - return NULL; - - entry = os_zalloc(sizeof(*entry)); - if (entry == NULL) - return NULL; - os_memcpy(entry->pmk, pmk, pmk_len); - entry->pmk_len = pmk_len; - rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, - wpa_key_mgmt_sha256(akmp)); - os_get_time(&now); - entry->expiration = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime; - entry->reauth_time = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime * - pmksa->sm->dot11RSNAConfigPMKReauthThreshold / 100; - entry->akmp = akmp; - os_memcpy(entry->aa, aa, ETH_ALEN); - entry->network_ctx = network_ctx; - - /* 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(pos->pmk, pmk, pmk_len) == 0 && - os_memcmp(pos->pmkid, entry->pmkid, PMKID_LEN) == - 0) { - wpa_printf(MSG_DEBUG, "WPA: reusing previous " - "PMKSA entry"); - os_free(entry); - return pos; - } - if (prev == NULL) - pmksa->pmksa = pos->next; - else - prev->next = pos->next; - if (pos == pmksa->sm->cur_pmksa) { - /* We are about to replace the current PMKSA - * cache entry. This happens when the PMKSA - * caching attempt fails, so we don't want to - * force pmksa_cache_free_entry() to disconnect - * at this point. Let's just make sure the old - * PMKSA cache entry will not be used in the - * future. - */ - wpa_printf(MSG_DEBUG, "RSN: replacing current " - "PMKSA entry"); - pmksa->sm->cur_pmksa = NULL; - } - wpa_printf(MSG_DEBUG, "RSN: Replace PMKSA entry for " - "the current AP"); - pmksa_cache_free_entry(pmksa, pos, 1); - break; - } - prev = pos; - pos = pos->next; - } - - if (pmksa->pmksa_count >= pmksa_cache_max_entries && pmksa->pmksa) { - /* Remove the oldest entry to make room for the new entry */ - pos = pmksa->pmksa; - pmksa->pmksa = pos->next; - wpa_printf(MSG_DEBUG, "RSN: removed the oldest PMKSA cache " - "entry (for " MACSTR ") to make room for new one", - MAC2STR(pos->aa)); - wpa_sm_remove_pmkid(pmksa->sm, pos->aa, pos->pmkid); - pmksa_cache_free_entry(pmksa, pos, 0); - } - - /* Add the new entry; order by expiration time */ - pos = pmksa->pmksa; - prev = NULL; - while (pos) { - if (pos->expiration > entry->expiration) - break; - prev = pos; - pos = pos->next; - } - if (prev == NULL) { - entry->next = pmksa->pmksa; - pmksa->pmksa = entry; - pmksa_cache_set_expiration(pmksa); - } else { - entry->next = prev->next; - prev->next = entry; - } - pmksa->pmksa_count++; - wpa_printf(MSG_DEBUG, "RSN: added PMKSA cache entry for " MACSTR, - MAC2STR(entry->aa)); - wpa_sm_add_pmkid(pmksa->sm, entry->aa, entry->pmkid); - - return entry; -} - - -/** - * pmksa_cache_deinit - Free all entries in PMKSA cache - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() - */ -void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa) -{ - struct rsn_pmksa_cache_entry *entry, *prev; - - if (pmksa == NULL) - return; - - entry = pmksa->pmksa; - pmksa->pmksa = NULL; - while (entry) { - prev = entry; - entry = entry->next; - os_free(prev); - } - pmksa_cache_set_expiration(pmksa); - os_free(pmksa); -} - - -/** - * pmksa_cache_get - Fetch a PMKSA cache entry - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() - * @aa: Authenticator address or %NULL to match any - * @pmkid: PMKID or %NULL to match 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) -{ - 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)) - return entry; - entry = entry->next; - } - return NULL; -} - - -/** - * pmksa_cache_notify_reconfig - Reconfiguration notification for PMKSA cache - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() - * - * Clear references to old data structures when wpa_supplicant is reconfigured. - */ -void pmksa_cache_notify_reconfig(struct rsn_pmksa_cache *pmksa) -{ - struct rsn_pmksa_cache_entry *entry = pmksa->pmksa; - while (entry) { - entry->network_ctx = NULL; - entry = entry->next; - } -} - - -static struct rsn_pmksa_cache_entry * -pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa, - const struct rsn_pmksa_cache_entry *old_entry, - const u8 *aa) -{ - struct rsn_pmksa_cache_entry *new_entry; - - new_entry = pmksa_cache_add(pmksa, old_entry->pmk, old_entry->pmk_len, - aa, pmksa->sm->own_addr, - old_entry->network_ctx, old_entry->akmp); - if (new_entry == NULL) - return NULL; - - /* TODO: reorder entries based on expiration time? */ - new_entry->expiration = old_entry->expiration; - new_entry->opportunistic = 1; - - return new_entry; -} - - -/** - * pmksa_cache_get_opportunistic - Try to get an opportunistic PMKSA entry - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() - * @network_ctx: Network configuration context - * @aa: Authenticator address for the new AP - * 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 - * new AP is sharing the same PMK as another AP that has the same SSID and has - * already an entry in PMKSA cache. - */ -struct rsn_pmksa_cache_entry * -pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, void *network_ctx, - const u8 *aa) -{ - struct rsn_pmksa_cache_entry *entry = pmksa->pmksa; - - if (network_ctx == NULL) - return NULL; - while (entry) { - if (entry->network_ctx == network_ctx) { - entry = pmksa_cache_clone_entry(pmksa, entry, aa); - if (entry) { - wpa_printf(MSG_DEBUG, "RSN: added " - "opportunistic PMKSA cache entry " - "for " MACSTR, MAC2STR(aa)); - } - return entry; - } - entry = entry->next; - } - return NULL; -} - - -/** - * pmksa_cache_get_current - Get the current used PMKSA entry - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * Returns: Pointer to the current PMKSA cache entry or %NULL if not available - */ -struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm) -{ - if (sm == NULL) - return NULL; - return sm->cur_pmksa; -} - - -/** - * pmksa_cache_clear_current - Clear the current PMKSA entry selection - * @sm: Pointer to WPA state machine data from wpa_sm_init() - */ -void pmksa_cache_clear_current(struct wpa_sm *sm) -{ - if (sm == NULL) - return; - sm->cur_pmksa = NULL; -} - - -/** - * pmksa_cache_set_current - Set the current PMKSA entry selection - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @pmkid: PMKID for selecting PMKSA or %NULL if not used - * @bssid: BSSID for PMKSA or %NULL if not used - * @network_ctx: Network configuration context - * @try_opportunistic: Whether to allow opportunistic PMKSA caching - * 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) -{ - struct rsn_pmksa_cache *pmksa = sm->pmksa; - sm->cur_pmksa = NULL; - if (pmkid) - sm->cur_pmksa = pmksa_cache_get(pmksa, NULL, pmkid); - if (sm->cur_pmksa == NULL && bssid) - sm->cur_pmksa = pmksa_cache_get(pmksa, bssid, NULL); - if (sm->cur_pmksa == NULL && try_opportunistic && bssid) - sm->cur_pmksa = pmksa_cache_get_opportunistic(pmksa, - network_ctx, - bssid); - if (sm->cur_pmksa) { - wpa_hexdump(MSG_DEBUG, "RSN: PMKID", - sm->cur_pmksa->pmkid, PMKID_LEN); - return 0; - } - return -1; -} - - -/** - * pmksa_cache_list - Dump text list of entries in PMKSA cache - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @buf: Buffer for the list - * @len: Length of the buffer - * Returns: number of bytes written to buffer - * - * This function is used to generate a text format representation of the - * current PMKSA cache contents for the ctrl_iface PMKSA command. - */ -int pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len) -{ - int i, ret; - char *pos = buf; - struct rsn_pmksa_cache_entry *entry; - struct os_time now; - - os_get_time(&now); - ret = os_snprintf(pos, buf + len - pos, - "Index / AA / PMKID / expiration (in seconds) / " - "opportunistic\n"); - if (ret < 0 || ret >= buf + len - pos) - return pos - buf; - pos += ret; - i = 0; - entry = sm->pmksa->pmksa; - while (entry) { - i++; - ret = os_snprintf(pos, buf + len - pos, "%d " MACSTR " ", - i, MAC2STR(entry->aa)); - if (ret < 0 || ret >= buf + len - pos) - return pos - buf; - pos += ret; - pos += wpa_snprintf_hex(pos, buf + len - pos, entry->pmkid, - PMKID_LEN); - ret = os_snprintf(pos, buf + len - pos, " %d %d\n", - (int) (entry->expiration - now.sec), - entry->opportunistic); - if (ret < 0 || ret >= buf + len - pos) - return pos - buf; - pos += ret; - entry = entry->next; - } - return pos - buf; -} - - -/** - * pmksa_cache_init - Initialize PMKSA cache - * @free_cb: Callback function to be called when a PMKSA cache entry is freed - * @ctx: Context pointer for free_cb function - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * Returns: Pointer to PMKSA cache data or %NULL on failure - */ -struct rsn_pmksa_cache * -pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, - void *ctx, int replace), - void *ctx, struct wpa_sm *sm) -{ - struct rsn_pmksa_cache *pmksa; - - pmksa = os_zalloc(sizeof(*pmksa)); - if (pmksa) { - pmksa->free_cb = free_cb; - pmksa->ctx = ctx; - pmksa->sm = sm; - } - - return pmksa; -} - -#endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */ diff --git a/contrib/hostapd/src/rsn_supp/pmksa_cache.h b/contrib/hostapd/src/rsn_supp/pmksa_cache.h deleted file mode 100644 index a329b25b08..0000000000 --- a/contrib/hostapd/src/rsn_supp/pmksa_cache.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * wpa_supplicant - WPA2/RSN PMKSA cache functions - * Copyright (c) 2003-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef PMKSA_CACHE_H -#define PMKSA_CACHE_H - -/** - * struct rsn_pmksa_cache_entry - PMKSA cache entry - */ -struct rsn_pmksa_cache_entry { - struct rsn_pmksa_cache_entry *next; - u8 pmkid[PMKID_LEN]; - u8 pmk[PMK_LEN]; - size_t pmk_len; - os_time_t expiration; - int akmp; /* WPA_KEY_MGMT_* */ - u8 aa[ETH_ALEN]; - - os_time_t reauth_time; - - /** - * network_ctx - Network configuration context - * - * This field is only used to match PMKSA cache entries to a specific - * network configuration (e.g., a specific SSID and security policy). - * This can be a pointer to the configuration entry, but PMKSA caching - * code does not dereference the value and this could be any kind of - * identifier. - */ - void *network_ctx; - int opportunistic; -}; - -struct rsn_pmksa_cache; - -#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2) - -struct rsn_pmksa_cache * -pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, - void *ctx, int replace), - void *ctx, struct wpa_sm *sm); -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); -int pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len); -struct rsn_pmksa_cache_entry * -pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, - const u8 *aa, const u8 *spa, void *network_ctx, int akmp); -void pmksa_cache_notify_reconfig(struct rsn_pmksa_cache *pmksa); -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); -struct rsn_pmksa_cache_entry * -pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, - void *network_ctx, const u8 *aa); - -#else /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */ - -static inline struct rsn_pmksa_cache * -pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, - void *ctx, int replace), - void *ctx, struct wpa_sm *sm) -{ - return (void *) -1; -} - -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) -{ - return NULL; -} - -static inline struct rsn_pmksa_cache_entry * -pmksa_cache_get_current(struct wpa_sm *sm) -{ - return NULL; -} - -static inline int pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len) -{ - return -1; -} - -static inline struct rsn_pmksa_cache_entry * -pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, - const u8 *aa, const u8 *spa, void *network_ctx, int akmp) -{ - return NULL; -} - -static inline void pmksa_cache_notify_reconfig(struct rsn_pmksa_cache *pmksa) -{ -} - -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) -{ - return -1; -} - -#endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */ - -#endif /* PMKSA_CACHE_H */ diff --git a/contrib/hostapd/src/rsn_supp/preauth.c b/contrib/hostapd/src/rsn_supp/preauth.c deleted file mode 100644 index b00c004cf6..0000000000 --- a/contrib/hostapd/src/rsn_supp/preauth.c +++ /dev/null @@ -1,529 +0,0 @@ -/* - * WPA Supplicant - RSN pre-authentication - * Copyright (c) 2003-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "wpa.h" -#include "drivers/driver.h" -#include "eloop.h" -#include "l2_packet/l2_packet.h" -#include "eapol_supp/eapol_supp_sm.h" -#include "preauth.h" -#include "pmksa_cache.h" -#include "wpa_i.h" -#include "ieee802_11_defs.h" - - -#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2) - -#define PMKID_CANDIDATE_PRIO_SCAN 1000 - - -struct rsn_pmksa_candidate { - struct rsn_pmksa_candidate *next; - u8 bssid[ETH_ALEN]; - int priority; -}; - - -/** - * pmksa_candidate_free - Free all entries in PMKSA candidate list - * @sm: Pointer to WPA state machine data from wpa_sm_init() - */ -void pmksa_candidate_free(struct wpa_sm *sm) -{ - struct rsn_pmksa_candidate *entry, *prev; - - if (sm == NULL) - return; - - entry = sm->pmksa_candidates; - sm->pmksa_candidates = NULL; - while (entry) { - prev = entry; - entry = entry->next; - os_free(prev); - } -} - - -static void rsn_preauth_receive(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len) -{ - struct wpa_sm *sm = ctx; - - wpa_printf(MSG_DEBUG, "RX pre-auth from " MACSTR, MAC2STR(src_addr)); - wpa_hexdump(MSG_MSGDUMP, "RX pre-auth", buf, len); - - if (sm->preauth_eapol == NULL || - is_zero_ether_addr(sm->preauth_bssid) || - os_memcmp(sm->preauth_bssid, src_addr, ETH_ALEN) != 0) { - wpa_printf(MSG_WARNING, "RSN pre-auth frame received from " - "unexpected source " MACSTR " - dropped", - MAC2STR(src_addr)); - return; - } - - eapol_sm_rx_eapol(sm->preauth_eapol, src_addr, buf, len); -} - - -static void rsn_preauth_eapol_cb(struct eapol_sm *eapol, int success, - void *ctx) -{ - struct wpa_sm *sm = ctx; - u8 pmk[PMK_LEN]; - - if (success) { - int res, pmk_len; - pmk_len = PMK_LEN; - res = eapol_sm_get_key(eapol, pmk, PMK_LEN); - if (res) { - /* - * EAP-LEAP is an exception from other EAP methods: it - * uses only 16-byte PMK. - */ - res = eapol_sm_get_key(eapol, pmk, 16); - pmk_len = 16; - } - if (res == 0) { - wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from pre-auth", - pmk, pmk_len); - sm->pmk_len = pmk_len; - pmksa_cache_add(sm->pmksa, pmk, pmk_len, - sm->preauth_bssid, sm->own_addr, - sm->network_ctx, - WPA_KEY_MGMT_IEEE8021X); - } else { - wpa_msg(sm->ctx->ctx, MSG_INFO, "RSN: failed to get " - "master session key from pre-auth EAPOL state " - "machines"); - success = 0; - } - } - - wpa_msg(sm->ctx->ctx, MSG_INFO, "RSN: pre-authentication with " MACSTR - " %s", MAC2STR(sm->preauth_bssid), - success ? "completed successfully" : "failed"); - - rsn_preauth_deinit(sm); - rsn_preauth_candidate_process(sm); -} - - -static void rsn_preauth_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_sm *sm = eloop_ctx; - - wpa_msg(sm->ctx->ctx, MSG_INFO, "RSN: pre-authentication with " MACSTR - " timed out", MAC2STR(sm->preauth_bssid)); - rsn_preauth_deinit(sm); - rsn_preauth_candidate_process(sm); -} - - -static int rsn_preauth_eapol_send(void *ctx, int type, const u8 *buf, - size_t len) -{ - struct wpa_sm *sm = ctx; - u8 *msg; - size_t msglen; - int res; - - /* TODO: could add l2_packet_sendmsg that allows fragments to avoid - * extra copy here */ - - if (sm->l2_preauth == NULL) - return -1; - - msg = wpa_sm_alloc_eapol(sm, type, buf, len, &msglen, NULL); - if (msg == NULL) - return -1; - - wpa_hexdump(MSG_MSGDUMP, "TX EAPOL (preauth)", msg, msglen); - res = l2_packet_send(sm->l2_preauth, sm->preauth_bssid, - ETH_P_RSN_PREAUTH, msg, msglen); - os_free(msg); - return res; -} - - -/** - * rsn_preauth_init - Start new RSN pre-authentication - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @dst: Authenticator address (BSSID) with which to preauthenticate - * @eap_conf: Current EAP configuration - * Returns: 0 on success, -1 on another pre-authentication is in progress, - * -2 on layer 2 packet initialization failure, -3 on EAPOL state machine - * initialization failure, -4 on memory allocation failure - * - * This function request an RSN pre-authentication with a given destination - * address. This is usually called for PMKSA candidates found from scan results - * or from driver reports. In addition, ctrl_iface PREAUTH command can trigger - * pre-authentication. - */ -int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst, - struct eap_peer_config *eap_conf) -{ - struct eapol_config eapol_conf; - struct eapol_ctx *ctx; - - if (sm->preauth_eapol) - return -1; - - wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: starting pre-authentication " - "with " MACSTR, MAC2STR(dst)); - - sm->l2_preauth = l2_packet_init(sm->ifname, sm->own_addr, - ETH_P_RSN_PREAUTH, - rsn_preauth_receive, sm, 0); - if (sm->l2_preauth == NULL) { - wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 packet " - "processing for pre-authentication"); - return -2; - } - - if (sm->bridge_ifname) { - sm->l2_preauth_br = l2_packet_init(sm->bridge_ifname, - sm->own_addr, - ETH_P_RSN_PREAUTH, - rsn_preauth_receive, sm, 0); - if (sm->l2_preauth_br == NULL) { - wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 " - "packet processing (bridge) for " - "pre-authentication"); - return -2; - } - } - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) { - wpa_printf(MSG_WARNING, "Failed to allocate EAPOL context."); - return -4; - } - ctx->ctx = sm->ctx->ctx; - ctx->msg_ctx = sm->ctx->ctx; - ctx->preauth = 1; - ctx->cb = rsn_preauth_eapol_cb; - ctx->cb_ctx = sm; - ctx->scard_ctx = sm->scard_ctx; - ctx->eapol_send = rsn_preauth_eapol_send; - ctx->eapol_send_ctx = sm; - ctx->set_config_blob = sm->ctx->set_config_blob; - ctx->get_config_blob = sm->ctx->get_config_blob; - - sm->preauth_eapol = eapol_sm_init(ctx); - if (sm->preauth_eapol == NULL) { - os_free(ctx); - wpa_printf(MSG_WARNING, "RSN: Failed to initialize EAPOL " - "state machines for pre-authentication"); - return -3; - } - os_memset(&eapol_conf, 0, sizeof(eapol_conf)); - eapol_conf.accept_802_1x_keys = 0; - eapol_conf.required_keys = 0; - eapol_conf.fast_reauth = sm->fast_reauth; - eapol_conf.workaround = sm->eap_workaround; - eapol_sm_notify_config(sm->preauth_eapol, eap_conf, &eapol_conf); - /* - * Use a shorter startPeriod with preauthentication since the first - * preauth EAPOL-Start frame may end up being dropped due to race - * condition in the AP between the data receive and key configuration - * after the 4-Way Handshake. - */ - eapol_sm_configure(sm->preauth_eapol, -1, -1, 5, 6); - os_memcpy(sm->preauth_bssid, dst, ETH_ALEN); - - eapol_sm_notify_portValid(sm->preauth_eapol, TRUE); - /* 802.1X::portControl = Auto */ - eapol_sm_notify_portEnabled(sm->preauth_eapol, TRUE); - - eloop_register_timeout(sm->dot11RSNAConfigSATimeout, 0, - rsn_preauth_timeout, sm, NULL); - - return 0; -} - - -/** - * rsn_preauth_deinit - Abort RSN pre-authentication - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * - * This function aborts the current RSN pre-authentication (if one is started) - * and frees resources allocated for it. - */ -void rsn_preauth_deinit(struct wpa_sm *sm) -{ - if (sm == NULL || !sm->preauth_eapol) - return; - - eloop_cancel_timeout(rsn_preauth_timeout, sm, NULL); - eapol_sm_deinit(sm->preauth_eapol); - sm->preauth_eapol = NULL; - os_memset(sm->preauth_bssid, 0, ETH_ALEN); - - l2_packet_deinit(sm->l2_preauth); - sm->l2_preauth = NULL; - if (sm->l2_preauth_br) { - l2_packet_deinit(sm->l2_preauth_br); - sm->l2_preauth_br = NULL; - } -} - - -/** - * rsn_preauth_candidate_process - Process PMKSA candidates - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * - * Go through the PMKSA candidates and start pre-authentication if a candidate - * without an existing PMKSA cache entry is found. Processed candidates will be - * removed from the list. - */ -void rsn_preauth_candidate_process(struct wpa_sm *sm) -{ - struct rsn_pmksa_candidate *candidate; - - if (sm->pmksa_candidates == NULL) - return; - - /* TODO: drop priority for old candidate entries */ - - wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: processing PMKSA candidate " - "list"); - if (sm->preauth_eapol || - sm->proto != WPA_PROTO_RSN || - wpa_sm_get_state(sm) != WPA_COMPLETED || - (sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X && - sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SHA256)) { - wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: not in suitable state " - "for new pre-authentication"); - return; /* invalid state for new pre-auth */ - } - - while (sm->pmksa_candidates) { - struct rsn_pmksa_cache_entry *p = NULL; - candidate = sm->pmksa_candidates; - p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL); - if (os_memcmp(sm->bssid, candidate->bssid, ETH_ALEN) != 0 && - (p == NULL || p->opportunistic)) { - wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: PMKSA " - "candidate " MACSTR - " selected for pre-authentication", - MAC2STR(candidate->bssid)); - sm->pmksa_candidates = candidate->next; - rsn_preauth_init(sm, candidate->bssid, - sm->eap_conf_ctx); - os_free(candidate); - return; - } - wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: PMKSA candidate " - MACSTR " does not need pre-authentication anymore", - MAC2STR(candidate->bssid)); - /* 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); - } - - sm->pmksa_candidates = candidate->next; - os_free(candidate); - } - wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: no more pending PMKSA " - "candidates"); -} - - -/** - * pmksa_candidate_add - Add a new PMKSA candidate - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @bssid: BSSID (authenticator address) of the candidate - * @prio: Priority (the smaller number, the higher priority) - * @preauth: Whether the candidate AP advertises support for pre-authentication - * - * This function is used to add PMKSA candidates for RSN pre-authentication. It - * is called from scan result processing and from driver events for PMKSA - * candidates, i.e., EVENT_PMKID_CANDIDATE events to wpa_supplicant_event(). - */ -void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid, - int prio, int preauth) -{ - struct rsn_pmksa_candidate *cand, *prev, *pos; - - if (sm->network_ctx && sm->proactive_key_caching) - pmksa_cache_get_opportunistic(sm->pmksa, sm->network_ctx, - bssid); - - if (!preauth) { - wpa_printf(MSG_DEBUG, "RSN: Ignored PMKID candidate without " - "preauth flag"); - return; - } - - /* If BSSID already on candidate list, update the priority of the old - * entry. Do not override priority based on normal scan results. */ - prev = NULL; - cand = sm->pmksa_candidates; - while (cand) { - if (os_memcmp(cand->bssid, bssid, ETH_ALEN) == 0) { - if (prev) - prev->next = cand->next; - else - sm->pmksa_candidates = cand->next; - break; - } - prev = cand; - cand = cand->next; - } - - if (cand) { - if (prio < PMKID_CANDIDATE_PRIO_SCAN) - cand->priority = prio; - } else { - cand = os_zalloc(sizeof(*cand)); - if (cand == NULL) - return; - os_memcpy(cand->bssid, bssid, ETH_ALEN); - cand->priority = prio; - } - - /* Add candidate to the list; order by increasing priority value. i.e., - * highest priority (smallest value) first. */ - prev = NULL; - pos = sm->pmksa_candidates; - while (pos) { - if (cand->priority <= pos->priority) - break; - prev = pos; - pos = pos->next; - } - cand->next = pos; - if (prev) - prev->next = cand; - else - sm->pmksa_candidates = cand; - - wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: added PMKSA cache " - "candidate " MACSTR " prio %d", MAC2STR(bssid), prio); - rsn_preauth_candidate_process(sm); -} - - -/* TODO: schedule periodic scans if current AP supports preauth */ - -/** - * rsn_preauth_scan_results - Process scan results to find PMKSA candidates - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @results: Scan results - * - * This functions goes through the scan results and adds all suitable APs - * (Authenticators) into PMKSA candidate list. - */ -void rsn_preauth_scan_results(struct wpa_sm *sm, - struct wpa_scan_results *results) -{ - struct wpa_scan_res *r; - struct wpa_ie_data ie; - int i; - struct rsn_pmksa_cache_entry *pmksa; - - if (sm->ssid_len == 0) - return; - - /* - * TODO: is it ok to free all candidates? What about the entries - * received from EVENT_PMKID_CANDIDATE? - */ - pmksa_candidate_free(sm); - - for (i = results->num - 1; i >= 0; i--) { - const u8 *ssid, *rsn; - - r = results->res[i]; - - ssid = wpa_scan_get_ie(r, WLAN_EID_SSID); - if (ssid == NULL || ssid[1] != sm->ssid_len || - os_memcmp(ssid + 2, sm->ssid, ssid[1]) != 0) - continue; - - if (os_memcmp(r->bssid, sm->bssid, ETH_ALEN) == 0) - continue; - - rsn = wpa_scan_get_ie(r, WLAN_EID_RSN); - if (rsn == NULL || wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie)) - continue; - - pmksa = pmksa_cache_get(sm->pmksa, r->bssid, NULL); - if (pmksa && - (!pmksa->opportunistic || - !(ie.capabilities & WPA_CAPABILITY_PREAUTH))) - continue; - - /* - * Give less priority to candidates found from normal - * scan results. - */ - pmksa_candidate_add(sm, r->bssid, - PMKID_CANDIDATE_PRIO_SCAN, - ie.capabilities & WPA_CAPABILITY_PREAUTH); - } -} - - -#ifdef CONFIG_CTRL_IFACE -/** - * rsn_preauth_get_status - Get pre-authentication status - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @buf: Buffer for status information - * @buflen: Maximum buffer length - * @verbose: Whether to include verbose status information - * Returns: Number of bytes written to buf. - * - * Query WPA2 pre-authentication for status information. This function fills in - * a text area with current status information. If the buffer (buf) is not - * large enough, status information will be truncated to fit the buffer. - */ -int rsn_preauth_get_status(struct wpa_sm *sm, char *buf, size_t buflen, - int verbose) -{ - char *pos = buf, *end = buf + buflen; - int res, ret; - - if (sm->preauth_eapol) { - ret = os_snprintf(pos, end - pos, "Pre-authentication " - "EAPOL state machines:\n"); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - res = eapol_sm_get_status(sm->preauth_eapol, - pos, end - pos, verbose); - if (res >= 0) - pos += res; - } - - return pos - buf; -} -#endif /* CONFIG_CTRL_IFACE */ - - -/** - * rsn_preauth_in_progress - Verify whether pre-authentication is in progress - * @sm: Pointer to WPA state machine data from wpa_sm_init() - */ -int rsn_preauth_in_progress(struct wpa_sm *sm) -{ - return sm->preauth_eapol != NULL; -} - -#endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */ diff --git a/contrib/hostapd/src/rsn_supp/preauth.h b/contrib/hostapd/src/rsn_supp/preauth.h deleted file mode 100644 index b9ac57b531..0000000000 --- a/contrib/hostapd/src/rsn_supp/preauth.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * wpa_supplicant - WPA2/RSN pre-authentication functions - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef PREAUTH_H -#define PREAUTH_H - -struct wpa_scan_results; - -#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2) - -void pmksa_candidate_free(struct wpa_sm *sm); -int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst, - struct eap_peer_config *eap_conf); -void rsn_preauth_deinit(struct wpa_sm *sm); -void rsn_preauth_scan_results(struct wpa_sm *sm, - struct wpa_scan_results *results); -void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid, - int prio, int preauth); -void rsn_preauth_candidate_process(struct wpa_sm *sm); -int rsn_preauth_get_status(struct wpa_sm *sm, char *buf, size_t buflen, - int verbose); -int rsn_preauth_in_progress(struct wpa_sm *sm); - -#else /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */ - -static inline void pmksa_candidate_free(struct wpa_sm *sm) -{ -} - -static inline void rsn_preauth_candidate_process(struct wpa_sm *sm) -{ -} - -static inline int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst, - struct eap_peer_config *eap_conf) -{ - return -1; -} - -static inline void rsn_preauth_deinit(struct wpa_sm *sm) -{ -} -static inline void rsn_preauth_scan_results(struct wpa_sm *sm, - struct wpa_scan_results *results) -{ -} - -static inline void pmksa_candidate_add(struct wpa_sm *sm, - const u8 *bssid, - int prio, int preauth) -{ -} - -static inline int rsn_preauth_get_status(struct wpa_sm *sm, char *buf, - size_t buflen, int verbose) -{ - return 0; -} - -static inline int rsn_preauth_in_progress(struct wpa_sm *sm) -{ - return 0; -} - -#endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */ - -#endif /* PREAUTH_H */ diff --git a/contrib/hostapd/src/rsn_supp/wpa.c b/contrib/hostapd/src/rsn_supp/wpa.c deleted file mode 100644 index e611fc5e78..0000000000 --- a/contrib/hostapd/src/rsn_supp/wpa.c +++ /dev/null @@ -1,2408 +0,0 @@ -/* - * WPA Supplicant - WPA state machine and EAPOL-Key processing - * Copyright (c) 2003-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "rc4.h" -#include "aes_wrap.h" -#include "wpa.h" -#include "eloop.h" -#include "eapol_supp/eapol_supp_sm.h" -#include "preauth.h" -#include "pmksa_cache.h" -#include "wpa_i.h" -#include "wpa_ie.h" -#include "peerkey.h" -#include "ieee802_11_defs.h" - - -/** - * wpa_cipher_txt - Convert cipher suite to a text string - * @cipher: Cipher suite (WPA_CIPHER_* enum) - * Returns: Pointer to a text string of the cipher suite name - */ -static const char * wpa_cipher_txt(int cipher) -{ - switch (cipher) { - case WPA_CIPHER_NONE: - return "NONE"; - case WPA_CIPHER_WEP40: - return "WEP-40"; - case WPA_CIPHER_WEP104: - return "WEP-104"; - case WPA_CIPHER_TKIP: - return "TKIP"; - case WPA_CIPHER_CCMP: - return "CCMP"; - default: - return "UNKNOWN"; - } -} - - -/** - * wpa_key_mgmt_txt - Convert key management suite to a text string - * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum) - * @proto: WPA/WPA2 version (WPA_PROTO_*) - * Returns: Pointer to a text string of the key management suite name - */ -static const char * wpa_key_mgmt_txt(int key_mgmt, int proto) -{ - switch (key_mgmt) { - case WPA_KEY_MGMT_IEEE8021X: - return proto == WPA_PROTO_RSN ? - "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP"; - case WPA_KEY_MGMT_PSK: - return proto == WPA_PROTO_RSN ? - "WPA2-PSK" : "WPA-PSK"; - case WPA_KEY_MGMT_NONE: - return "NONE"; - case WPA_KEY_MGMT_IEEE8021X_NO_WPA: - return "IEEE 802.1X (no WPA)"; -#ifdef CONFIG_IEEE80211R - case WPA_KEY_MGMT_FT_IEEE8021X: - return "FT-EAP"; - case WPA_KEY_MGMT_FT_PSK: - return "FT-PSK"; -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - case WPA_KEY_MGMT_IEEE8021X_SHA256: - return "WPA2-EAP-SHA256"; - case WPA_KEY_MGMT_PSK_SHA256: - return "WPA2-PSK-SHA256"; -#endif /* CONFIG_IEEE80211W */ - default: - return "UNKNOWN"; - } -} - - -/** - * 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) - * @ver: Version field from Key Info - * @dest: Destination address for the frame - * @proto: Ethertype (usually ETH_P_EAPOL) - * @msg: EAPOL-Key message - * @msg_len: Length of message - * @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written - */ -void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, - int ver, const u8 *dest, u16 proto, - u8 *msg, size_t msg_len, u8 *key_mic) -{ - if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) { - /* - * Association event was not yet received; try to fetch - * BSSID from the driver. - */ - if (wpa_sm_get_bssid(sm, sm->bssid) < 0) { - wpa_printf(MSG_DEBUG, "WPA: Failed to read BSSID for " - "EAPOL-Key destination address"); - } else { - dest = sm->bssid; - wpa_printf(MSG_DEBUG, "WPA: Use BSSID (" MACSTR - ") as the destination for EAPOL-Key", - MAC2STR(dest)); - } - } - if (key_mic) - wpa_eapol_key_mic(kck, ver, msg, msg_len, key_mic); - wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len); - wpa_sm_ether_send(sm, dest, proto, msg, msg_len); - eapol_sm_notify_tx_eapol_key(sm->eapol); - os_free(msg); -} - - -/** - * wpa_sm_key_request - Send EAPOL-Key Request - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @error: Indicate whether this is an Michael MIC error report - * @pairwise: 1 = error report for pairwise packet, 0 = for group packet - * - * Send an EAPOL-Key Request to the current authenticator. This function is - * used to request rekeying and it is usually called when a local Michael MIC - * failure is detected. - */ -void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) -{ - size_t rlen; - struct wpa_eapol_key *reply; - int key_info, ver; - u8 bssid[ETH_ALEN], *rbuf; - - if (wpa_key_mgmt_ft(sm->key_mgmt) || wpa_key_mgmt_sha256(sm->key_mgmt)) - ver = WPA_KEY_INFO_TYPE_AES_128_CMAC; - else if (sm->pairwise_cipher == WPA_CIPHER_CCMP) - 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 " - "request"); - return; - } - - rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, - sizeof(*reply), &rlen, (void *) &reply); - if (rbuf == NULL) - return; - - reply->type = sm->proto == WPA_PROTO_RSN ? - 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; - if (error) - key_info |= WPA_KEY_INFO_ERROR; - if (pairwise) - key_info |= WPA_KEY_INFO_KEY_TYPE; - WPA_PUT_BE16(reply->key_info, key_info); - WPA_PUT_BE16(reply->key_length, 0); - os_memcpy(reply->replay_counter, sm->request_counter, - WPA_REPLAY_COUNTER_LEN); - inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); - - WPA_PUT_BE16(reply->key_data_length, 0); - - wpa_printf(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, ver, bssid, ETH_P_EAPOL, - rbuf, rlen, key_info & WPA_KEY_INFO_MIC ? - reply->key_mic : NULL); -} - - -static int wpa_supplicant_get_pmk(struct wpa_sm *sm, - const unsigned char *src_addr, - const u8 *pmkid) -{ - int abort_cached = 0; - - if (pmkid && !sm->cur_pmksa) { - /* When using drivers that generate RSN IE, wpa_supplicant may - * not have enough time to get the association information - * 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); - if (sm->cur_pmksa) { - wpa_printf(MSG_DEBUG, "RSN: found matching PMKID from " - "PMKSA cache"); - } else { - wpa_printf(MSG_DEBUG, "RSN: no matching PMKID found"); - abort_cached = 1; - } - } - - if (pmkid && sm->cur_pmksa && - os_memcmp(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) { - wpa_hexdump(MSG_DEBUG, "RSN: matched PMKID", pmkid, PMKID_LEN); - wpa_sm_set_pmk_from_pmksa(sm); - wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from PMKSA cache", - sm->pmk, sm->pmk_len); - eapol_sm_notify_cached(sm->eapol); -#ifdef CONFIG_IEEE80211R - sm->xxkey_len = 0; -#endif /* CONFIG_IEEE80211R */ - } else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && sm->eapol) { - int res, pmk_len; - pmk_len = PMK_LEN; - res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN); - if (res) { - /* - * EAP-LEAP is an exception from other EAP methods: it - * uses only 16-byte PMK. - */ - res = eapol_sm_get_key(sm->eapol, sm->pmk, 16); - pmk_len = 16; - } else { -#ifdef CONFIG_IEEE80211R - 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; - os_memset(buf, 0, sizeof(buf)); - } -#endif /* CONFIG_IEEE80211R */ - } - if (res == 0) { - wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state " - "machines", sm->pmk, pmk_len); - sm->pmk_len = pmk_len; - pmksa_cache_add(sm->pmksa, sm->pmk, pmk_len, src_addr, - sm->own_addr, sm->network_ctx, - sm->key_mgmt); - if (!sm->cur_pmksa && pmkid && - pmksa_cache_get(sm->pmksa, src_addr, pmkid)) { - wpa_printf(MSG_DEBUG, "RSN: the new PMK " - "matches with the PMKID"); - abort_cached = 0; - } - } else { - wpa_msg(sm->ctx->ctx, MSG_WARNING, - "WPA: Failed to get master session key from " - "EAPOL state machines"); - wpa_msg(sm->ctx->ctx, MSG_WARNING, - "WPA: Key handshake aborted"); - if (sm->cur_pmksa) { - wpa_printf(MSG_DEBUG, "RSN: Cancelled PMKSA " - "caching attempt"); - sm->cur_pmksa = NULL; - abort_cached = 1; - } else if (!abort_cached) { - return -1; - } - } - } - - if (abort_cached && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) { - /* Send EAPOL-Start to trigger full EAP authentication. */ - u8 *buf; - size_t buflen; - - wpa_printf(MSG_DEBUG, "RSN: no PMKSA entry found - trigger " - "full EAP authentication"); - buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START, - NULL, 0, &buflen, NULL); - if (buf) { - wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL, - buf, buflen); - os_free(buf); - } - - return -1; - } - - return 0; -} - - -/** - * wpa_supplicant_send_2_of_4 - Send message 2 of WPA/RSN 4-Way Handshake - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @dst: Destination address for the frame - * @key: Pointer to the EAPOL-Key frame header - * @ver: Version bits from EAPOL-Key Key Info - * @nonce: Nonce value for the EAPOL-Key frame - * @wpa_ie: WPA/RSN IE - * @wpa_ie_len: Length of the WPA/RSN IE - * @ptk: PTK to use for keyed hash and encryption - * Returns: 0 on success, -1 on failure - */ -int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, - const struct wpa_eapol_key *key, - int ver, const u8 *nonce, - const u8 *wpa_ie, size_t wpa_ie_len, - struct wpa_ptk *ptk) -{ - size_t rlen; - struct wpa_eapol_key *reply; - u8 *rbuf; - - if (wpa_ie == NULL) { - wpa_printf(MSG_WARNING, "WPA: No wpa_ie set - cannot " - "generate msg 2/4"); - return -1; - } - - wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len); - - rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, - NULL, sizeof(*reply) + wpa_ie_len, - &rlen, (void *) &reply); - if (rbuf == NULL) - return -1; - - reply->type = sm->proto == WPA_PROTO_RSN ? - EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; - WPA_PUT_BE16(reply->key_info, - ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC); - if (sm->proto == WPA_PROTO_RSN) - WPA_PUT_BE16(reply->key_length, 0); - else - os_memcpy(reply->key_length, key->key_length, 2); - os_memcpy(reply->replay_counter, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - - WPA_PUT_BE16(reply->key_data_length, wpa_ie_len); - os_memcpy(reply + 1, wpa_ie, wpa_ie_len); - - os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN); - - wpa_printf(MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4"); - wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL, - rbuf, rlen, reply->key_mic); - - return 0; -} - - -static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, - const struct wpa_eapol_key *key, - struct wpa_ptk *ptk) -{ - size_t ptk_len = sm->pairwise_cipher == WPA_CIPHER_CCMP ? 48 : 64; -#ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->key_mgmt)) - return wpa_derive_ptk_ft(sm, src_addr, key, ptk, ptk_len); -#endif /* CONFIG_IEEE80211R */ - - wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion", - sm->own_addr, sm->bssid, sm->snonce, key->key_nonce, - (u8 *) ptk, ptk_len, - wpa_key_mgmt_sha256(sm->key_mgmt)); - return 0; -} - - -static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, - const unsigned char *src_addr, - const struct wpa_eapol_key *key, - u16 ver) -{ - struct wpa_eapol_ie_parse ie; - struct wpa_ptk *ptk; - u8 buf[8]; - - if (wpa_sm_get_network_ctx(sm) == NULL) { - wpa_printf(MSG_WARNING, "WPA: No SSID info found (msg 1 of " - "4)."); - return; - } - - wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); - wpa_printf(MSG_DEBUG, "WPA: RX message 1 of 4-Way Handshake from " - MACSTR " (ver=%d)", MAC2STR(src_addr), ver); - - os_memset(&ie, 0, sizeof(ie)); - -#ifndef CONFIG_NO_WPA2 - if (sm->proto == WPA_PROTO_RSN) { - /* RSN: msg 1/4 should contain PMKID for the selected PMK */ - const u8 *_buf = (const u8 *) (key + 1); - size_t len = WPA_GET_BE16(key->key_data_length); - wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", _buf, len); - wpa_supplicant_parse_ies(_buf, len, &ie); - if (ie.pmkid) { - wpa_hexdump(MSG_DEBUG, "RSN: PMKID from " - "Authenticator", ie.pmkid, PMKID_LEN); - } - } -#endif /* CONFIG_NO_WPA2 */ - - if (wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid)) - goto failed; - - if (sm->renew_snonce) { - if (os_get_random(sm->snonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->ctx, MSG_WARNING, - "WPA: Failed to get random data for SNonce"); - goto failed; - } - sm->renew_snonce = 0; - wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce", - sm->snonce, WPA_NONCE_LEN); - } - - /* 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); - /* Supplicant: swap tx/rx Mic keys */ - os_memcpy(buf, ptk->u.auth.tx_mic_key, 8); - os_memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8); - os_memcpy(ptk->u.auth.rx_mic_key, buf, 8); - sm->tptk_set = 1; - - if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce, - sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, - ptk)) - goto failed; - - os_memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN); - return; - -failed: - wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); -} - - -static void wpa_sm_start_preauth(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_sm *sm = eloop_ctx; - rsn_preauth_candidate_process(sm); -} - - -static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, - const u8 *addr, int secure) -{ - wpa_msg(sm->ctx->ctx, MSG_INFO, "WPA: Key negotiation completed with " - MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr), - wpa_cipher_txt(sm->pairwise_cipher), - wpa_cipher_txt(sm->group_cipher)); - wpa_sm_cancel_auth_timeout(sm); - wpa_sm_set_state(sm, WPA_COMPLETED); - - if (secure) { - wpa_sm_mlme_setprotection( - 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)) - eapol_sm_notify_eap_success(sm->eapol, TRUE); - /* - * Start preauthentication after a short wait to avoid a - * possible race condition between the data receive and key - * configuration after the 4-Way Handshake. This increases the - * likelyhood of the first preauth EAPOL-Start frame getting to - * the target AP. - */ - eloop_register_timeout(1, 0, wpa_sm_start_preauth, sm, NULL); - } - - if (sm->cur_pmksa && sm->cur_pmksa->opportunistic) { - wpa_printf(MSG_DEBUG, "RSN: Authenticator accepted " - "opportunistic PMKSA entry - marking it valid"); - sm->cur_pmksa->opportunistic = 0; - } - -#ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->key_mgmt)) { - /* Prepare for the next transition */ - wpa_ft_prepare_auth_request(sm); - } -#endif /* CONFIG_IEEE80211R */ -} - - -static void wpa_sm_rekey_ptk(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_sm *sm = eloop_ctx; - wpa_printf(MSG_DEBUG, "WPA: Request PTK rekeying"); - wpa_sm_key_request(sm, 0, 1); -} - - -static int wpa_supplicant_install_ptk(struct wpa_sm *sm, - const struct wpa_eapol_key *key) -{ - int keylen, rsclen; - wpa_alg alg; - const u8 *key_rsc; - u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - - wpa_printf(MSG_DEBUG, "WPA: Installing PTK to the driver."); - - switch (sm->pairwise_cipher) { - case WPA_CIPHER_CCMP: - alg = WPA_ALG_CCMP; - keylen = 16; - rsclen = 6; - break; - case WPA_CIPHER_TKIP: - alg = WPA_ALG_TKIP; - keylen = 32; - rsclen = 6; - break; - case WPA_CIPHER_NONE: - wpa_printf(MSG_DEBUG, "WPA: Pairwise Cipher Suite: " - "NONE - do not use pairwise keys"); - return 0; - default: - wpa_printf(MSG_WARNING, "WPA: Unsupported pairwise cipher %d", - sm->pairwise_cipher); - return -1; - } - - if (sm->proto == WPA_PROTO_RSN) { - key_rsc = null_rsc; - } else { - key_rsc = key->key_rsc; - wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen); - } - - if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, key_rsc, rsclen, - (u8 *) sm->ptk.tk1, keylen) < 0) { - wpa_printf(MSG_WARNING, "WPA: Failed to set PTK to the " - "driver (alg=%d keylen=%d bssid=" MACSTR ")", - alg, keylen, MAC2STR(sm->bssid)); - return -1; - } - - if (sm->wpa_ptk_rekey) { - eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); - eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk, - sm, NULL); - } - - return 0; -} - - -static int wpa_supplicant_check_group_cipher(int group_cipher, - int keylen, int maxkeylen, - int *key_rsc_len, wpa_alg *alg) -{ - int ret = 0; - - switch (group_cipher) { - case WPA_CIPHER_CCMP: - if (keylen != 16 || maxkeylen < 16) { - ret = -1; - break; - } - *key_rsc_len = 6; - *alg = WPA_ALG_CCMP; - break; - case WPA_CIPHER_TKIP: - if (keylen != 32 || maxkeylen < 32) { - ret = -1; - break; - } - *key_rsc_len = 6; - *alg = WPA_ALG_TKIP; - break; - case WPA_CIPHER_WEP104: - if (keylen != 13 || maxkeylen < 13) { - ret = -1; - break; - } - *key_rsc_len = 0; - *alg = WPA_ALG_WEP; - break; - case WPA_CIPHER_WEP40: - if (keylen != 5 || maxkeylen < 5) { - ret = -1; - break; - } - *key_rsc_len = 0; - *alg = WPA_ALG_WEP; - break; - default: - wpa_printf(MSG_WARNING, "WPA: Unsupported Group Cipher %d", - group_cipher); - return -1; - } - - if (ret < 0 ) { - wpa_printf(MSG_WARNING, "WPA: Unsupported %s Group Cipher key " - "length %d (%d).", - wpa_cipher_txt(group_cipher), keylen, maxkeylen); - } - - return ret; -} - - -struct wpa_gtk_data { - wpa_alg alg; - int tx, key_rsc_len, keyidx; - u8 gtk[32]; - int gtk_len; -}; - - -static int wpa_supplicant_install_gtk(struct wpa_sm *sm, - const struct wpa_gtk_data *gd, - const u8 *key_rsc) -{ - const u8 *_gtk = gd->gtk; - u8 gtk_buf[32]; - - wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gd->gtk, gd->gtk_len); - wpa_printf(MSG_DEBUG, "WPA: Installing GTK to the driver " - "(keyidx=%d tx=%d len=%d).", gd->keyidx, gd->tx, - gd->gtk_len); - wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, gd->key_rsc_len); - if (sm->group_cipher == WPA_CIPHER_TKIP) { - /* Swap Tx/Rx keys for Michael MIC */ - os_memcpy(gtk_buf, gd->gtk, 16); - os_memcpy(gtk_buf + 16, gd->gtk + 24, 8); - os_memcpy(gtk_buf + 24, gd->gtk + 16, 8); - _gtk = gtk_buf; - } - if (sm->pairwise_cipher == WPA_CIPHER_NONE) { - if (wpa_sm_set_key(sm, gd->alg, - (u8 *) "\xff\xff\xff\xff\xff\xff", - gd->keyidx, 1, key_rsc, gd->key_rsc_len, - _gtk, gd->gtk_len) < 0) { - wpa_printf(MSG_WARNING, "WPA: Failed to set " - "GTK to the driver (Group only)."); - return -1; - } - } else if (wpa_sm_set_key(sm, gd->alg, - (u8 *) "\xff\xff\xff\xff\xff\xff", - gd->keyidx, gd->tx, key_rsc, gd->key_rsc_len, - _gtk, gd->gtk_len) < 0) { - wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to " - "the driver (alg=%d keylen=%d keyidx=%d)", - gd->alg, gd->gtk_len, gd->keyidx); - return -1; - } - - return 0; -} - - -static int wpa_supplicant_gtk_tx_bit_workaround(const struct wpa_sm *sm, - int tx) -{ - if (tx && sm->pairwise_cipher != WPA_CIPHER_NONE) { - /* Ignore Tx bit for GTK if a pairwise key is used. One AP - * seemed to set this bit (incorrectly, since Tx is only when - * doing Group Key only APs) and without this workaround, the - * data connection does not work because wpa_supplicant - * configured non-zero keyidx to be used for unicast. */ - wpa_printf(MSG_INFO, "WPA: Tx bit set for GTK, but pairwise " - "keys are used - ignore Tx bit"); - return 0; - } - return tx; -} - - -static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm, - const struct wpa_eapol_key *key, - const u8 *gtk, size_t gtk_len, - int key_info) -{ -#ifndef CONFIG_NO_WPA2 - struct wpa_gtk_data gd; - - /* - * IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames - Figure 43x - * GTK KDE format: - * KeyID[bits 0-1], Tx [bit 2], Reserved [bits 3-7] - * Reserved [bits 0-7] - * GTK - */ - - os_memset(&gd, 0, sizeof(gd)); - wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in pairwise handshake", - gtk, gtk_len); - - if (gtk_len < 2 || gtk_len - 2 > sizeof(gd.gtk)) - return -1; - - gd.keyidx = gtk[0] & 0x3; - gd.tx = wpa_supplicant_gtk_tx_bit_workaround(sm, - !!(gtk[0] & BIT(2))); - gtk += 2; - gtk_len -= 2; - - os_memcpy(gd.gtk, gtk, gtk_len); - gd.gtk_len = gtk_len; - - if (wpa_supplicant_check_group_cipher(sm->group_cipher, - gtk_len, gtk_len, - &gd.key_rsc_len, &gd.alg) || - wpa_supplicant_install_gtk(sm, &gd, key->key_rsc)) { - wpa_printf(MSG_DEBUG, "RSN: Failed to install GTK"); - return -1; - } - - wpa_supplicant_key_neg_complete(sm, sm->bssid, - key_info & WPA_KEY_INFO_SECURE); - return 0; -#else /* CONFIG_NO_WPA2 */ - return -1; -#endif /* CONFIG_NO_WPA2 */ -} - - -static int ieee80211w_set_keys(struct wpa_sm *sm, - struct wpa_eapol_ie_parse *ie) -{ -#ifdef CONFIG_IEEE80211W - if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) - return 0; - - if (ie->igtk) { - const struct wpa_igtk_kde *igtk; - u16 keyidx; - if (ie->igtk_len != sizeof(*igtk)) - return -1; - igtk = (const struct wpa_igtk_kde *) ie->igtk; - keyidx = WPA_GET_LE16(igtk->keyid); - wpa_printf(MSG_DEBUG, "WPA: IGTK keyid %d " - "pn %02x%02x%02x%02x%02x%02x", - keyidx, MAC2STR(igtk->pn)); - wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", - igtk->igtk, WPA_IGTK_LEN); - if (keyidx > 4095) { - wpa_printf(MSG_WARNING, "WPA: Invalid IGTK KeyID %d", - keyidx); - return -1; - } - if (wpa_sm_set_key(sm, WPA_ALG_IGTK, - (u8 *) "\xff\xff\xff\xff\xff\xff", - keyidx, 0, igtk->pn, sizeof(igtk->pn), - igtk->igtk, WPA_IGTK_LEN) < 0) { - wpa_printf(MSG_WARNING, "WPA: Failed to configure IGTK" - " to the driver"); - return -1; - } - } - - return 0; -#else /* CONFIG_IEEE80211W */ - return 0; -#endif /* CONFIG_IEEE80211W */ -} - - -static void wpa_report_ie_mismatch(struct wpa_sm *sm, - const char *reason, const u8 *src_addr, - const u8 *wpa_ie, size_t wpa_ie_len, - const u8 *rsn_ie, size_t rsn_ie_len) -{ - wpa_msg(sm->ctx->ctx, MSG_WARNING, "WPA: %s (src=" MACSTR ")", - reason, MAC2STR(src_addr)); - - if (sm->ap_wpa_ie) { - wpa_hexdump(MSG_INFO, "WPA: WPA IE in Beacon/ProbeResp", - sm->ap_wpa_ie, sm->ap_wpa_ie_len); - } - if (wpa_ie) { - if (!sm->ap_wpa_ie) { - wpa_printf(MSG_INFO, "WPA: No WPA IE in " - "Beacon/ProbeResp"); - } - wpa_hexdump(MSG_INFO, "WPA: WPA IE in 3/4 msg", - wpa_ie, wpa_ie_len); - } - - if (sm->ap_rsn_ie) { - wpa_hexdump(MSG_INFO, "WPA: RSN IE in Beacon/ProbeResp", - sm->ap_rsn_ie, sm->ap_rsn_ie_len); - } - if (rsn_ie) { - if (!sm->ap_rsn_ie) { - wpa_printf(MSG_INFO, "WPA: No RSN IE in " - "Beacon/ProbeResp"); - } - wpa_hexdump(MSG_INFO, "WPA: RSN IE in 3/4 msg", - rsn_ie, rsn_ie_len); - } - - wpa_sm_disassociate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS); -} - - -static int wpa_supplicant_validate_ie(struct wpa_sm *sm, - const unsigned char *src_addr, - struct wpa_eapol_ie_parse *ie) -{ - if (sm->ap_wpa_ie == NULL && sm->ap_rsn_ie == NULL) { - wpa_printf(MSG_DEBUG, "WPA: No WPA/RSN IE for this AP known. " - "Trying to get from scan results"); - if (wpa_sm_get_beacon_ie(sm) < 0) { - wpa_printf(MSG_WARNING, "WPA: Could not find AP from " - "the scan results"); - } else { - wpa_printf(MSG_DEBUG, "WPA: Found the current AP from " - "updated scan results"); - } - } - - if (ie->wpa_ie == NULL && ie->rsn_ie == NULL && - (sm->ap_wpa_ie || sm->ap_rsn_ie)) { - wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match " - "with IE in Beacon/ProbeResp (no IE?)", - src_addr, ie->wpa_ie, ie->wpa_ie_len, - ie->rsn_ie, ie->rsn_ie_len); - return -1; - } - - if ((ie->wpa_ie && sm->ap_wpa_ie && - (ie->wpa_ie_len != sm->ap_wpa_ie_len || - os_memcmp(ie->wpa_ie, sm->ap_wpa_ie, ie->wpa_ie_len) != 0)) || - (ie->rsn_ie && sm->ap_rsn_ie && - (ie->rsn_ie_len != sm->ap_rsn_ie_len || - os_memcmp(ie->rsn_ie, sm->ap_rsn_ie, ie->rsn_ie_len) != 0))) { - wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match " - "with IE in Beacon/ProbeResp", - src_addr, ie->wpa_ie, ie->wpa_ie_len, - ie->rsn_ie, ie->rsn_ie_len); - return -1; - } - - if (sm->proto == WPA_PROTO_WPA && - ie->rsn_ie && sm->ap_rsn_ie == NULL && sm->rsn_enabled) { - wpa_report_ie_mismatch(sm, "Possible downgrade attack " - "detected - RSN was enabled and RSN IE " - "was in msg 3/4, but not in " - "Beacon/ProbeResp", - src_addr, ie->wpa_ie, ie->wpa_ie_len, - ie->rsn_ie, ie->rsn_ie_len); - return -1; - } - -#ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->key_mgmt)) { - struct rsn_mdie *mdie; - /* TODO: verify that full MDIE matches with the one from scan - * results, not only mobility domain */ - mdie = (struct rsn_mdie *) (ie->mdie + 2); - if (ie->mdie == NULL || ie->mdie_len < 2 + sizeof(*mdie) || - os_memcmp(mdie->mobility_domain, sm->mobility_domain, - MOBILITY_DOMAIN_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: MDIE in msg 3/4 did not " - "match with the current mobility domain"); - return -1; - } - } -#endif /* CONFIG_IEEE80211R */ - - return 0; -} - - -/** - * wpa_supplicant_send_4_of_4 - Send message 4 of WPA/RSN 4-Way Handshake - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @dst: Destination address for the frame - * @key: Pointer to the EAPOL-Key frame header - * @ver: Version bits from EAPOL-Key Key Info - * @key_info: Key Info - * @kde: KDEs to include the EAPOL-Key frame - * @kde_len: Length of KDEs - * @ptk: PTK to use for keyed hash and encryption - * Returns: 0 on success, -1 on failure - */ -int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, - const struct wpa_eapol_key *key, - u16 ver, u16 key_info, - const u8 *kde, size_t kde_len, - struct wpa_ptk *ptk) -{ - size_t rlen; - struct wpa_eapol_key *reply; - u8 *rbuf; - - if (kde) - wpa_hexdump(MSG_DEBUG, "WPA: KDE for msg 4/4", kde, kde_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; - - reply->type = sm->proto == WPA_PROTO_RSN ? - 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; - WPA_PUT_BE16(reply->key_info, key_info); - if (sm->proto == WPA_PROTO_RSN) - WPA_PUT_BE16(reply->key_length, 0); - else - os_memcpy(reply->key_length, key->key_length, 2); - os_memcpy(reply->replay_counter, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - - WPA_PUT_BE16(reply->key_data_length, kde_len); - if (kde) - os_memcpy(reply + 1, kde, kde_len); - - wpa_printf(MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4"); - wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL, - rbuf, rlen, reply->key_mic); - - return 0; -} - - -static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, - const struct wpa_eapol_key *key, - u16 ver) -{ - u16 key_info, keylen, len; - const u8 *pos; - struct wpa_eapol_ie_parse ie; - - wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); - wpa_printf(MSG_DEBUG, "WPA: RX message 3 of 4-Way Handshake from " - MACSTR " (ver=%d)", MAC2STR(sm->bssid), ver); - - key_info = WPA_GET_BE16(key->key_info); - - pos = (const u8 *) (key + 1); - len = WPA_GET_BE16(key->key_data_length); - wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", pos, len); - wpa_supplicant_parse_ies(pos, len, &ie); - if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { - wpa_printf(MSG_WARNING, "WPA: GTK IE in unencrypted key data"); - goto failed; - } -#ifdef CONFIG_IEEE80211W - if (ie.igtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { - wpa_printf(MSG_WARNING, "WPA: IGTK KDE in unencrypted key " - "data"); - goto failed; - } - - if (ie.igtk && ie.igtk_len != sizeof(struct wpa_igtk_kde)) { - wpa_printf(MSG_WARNING, "WPA: Invalid IGTK KDE length %lu", - (unsigned long) ie.igtk_len); - goto failed; - } -#endif /* CONFIG_IEEE80211W */ - - if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) - goto failed; - - if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) { - wpa_printf(MSG_WARNING, "WPA: ANonce from message 1 of 4-Way " - "Handshake differs from 3 of 4-Way Handshake - drop" - " packet (src=" MACSTR ")", MAC2STR(sm->bssid)); - goto failed; - } - - keylen = WPA_GET_BE16(key->key_length); - switch (sm->pairwise_cipher) { - case WPA_CIPHER_CCMP: - if (keylen != 16) { - wpa_printf(MSG_WARNING, "WPA: Invalid CCMP key length " - "%d (src=" MACSTR ")", - keylen, MAC2STR(sm->bssid)); - goto failed; - } - break; - case WPA_CIPHER_TKIP: - if (keylen != 32) { - wpa_printf(MSG_WARNING, "WPA: Invalid TKIP key length " - "%d (src=" MACSTR ")", - keylen, MAC2STR(sm->bssid)); - goto failed; - } - break; - } - - if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info, - NULL, 0, &sm->ptk)) { - goto failed; - } - - /* SNonce was successfully used in msg 3/4, so mark it to be renewed - * for the next 4-Way Handshake. If msg 3 is received again, the old - * SNonce will still be used to avoid changing PTK. */ - sm->renew_snonce = 1; - - if (key_info & WPA_KEY_INFO_INSTALL) { - if (wpa_supplicant_install_ptk(sm, key)) - goto failed; - } - - if (key_info & WPA_KEY_INFO_SECURE) { - wpa_sm_mlme_setprotection( - sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX, - MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); - eapol_sm_notify_portValid(sm->eapol, TRUE); - } - wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); - - if (ie.gtk && - wpa_supplicant_pairwise_gtk(sm, key, - ie.gtk, ie.gtk_len, key_info) < 0) { - wpa_printf(MSG_INFO, "RSN: Failed to configure GTK"); - goto failed; - } - - if (ieee80211w_set_keys(sm, &ie) < 0) { - wpa_printf(MSG_INFO, "RSN: Failed to configure IGTK"); - goto failed; - } - - return; - -failed: - wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); -} - - -static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, - const u8 *keydata, - size_t keydatalen, - u16 key_info, - struct wpa_gtk_data *gd) -{ - int maxkeylen; - struct wpa_eapol_ie_parse ie; - - wpa_hexdump(MSG_DEBUG, "RSN: msg 1/2 key data", keydata, keydatalen); - wpa_supplicant_parse_ies(keydata, keydatalen, &ie); - if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { - wpa_printf(MSG_WARNING, "WPA: GTK IE in unencrypted key data"); - return -1; - } - if (ie.gtk == NULL) { - wpa_printf(MSG_INFO, "WPA: No GTK IE in Group Key msg 1/2"); - return -1; - } - maxkeylen = gd->gtk_len = ie.gtk_len - 2; - - if (wpa_supplicant_check_group_cipher(sm->group_cipher, - gd->gtk_len, maxkeylen, - &gd->key_rsc_len, &gd->alg)) - return -1; - - wpa_hexdump(MSG_DEBUG, "RSN: received GTK in group key handshake", - ie.gtk, ie.gtk_len); - gd->keyidx = ie.gtk[0] & 0x3; - gd->tx = wpa_supplicant_gtk_tx_bit_workaround(sm, - !!(ie.gtk[0] & BIT(2))); - if (ie.gtk_len - 2 > sizeof(gd->gtk)) { - wpa_printf(MSG_INFO, "RSN: Too long GTK in GTK IE " - "(len=%lu)", (unsigned long) ie.gtk_len - 2); - return -1; - } - os_memcpy(gd->gtk, ie.gtk + 2, ie.gtk_len - 2); - - if (ieee80211w_set_keys(sm, &ie) < 0) - wpa_printf(MSG_INFO, "RSN: Failed to configure IGTK"); - - return 0; -} - - -static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm, - const struct wpa_eapol_key *key, - size_t keydatalen, int key_info, - size_t extra_len, u16 ver, - struct wpa_gtk_data *gd) -{ - size_t maxkeylen; - u8 ek[32]; - - gd->gtk_len = WPA_GET_BE16(key->key_length); - maxkeylen = keydatalen; - if (keydatalen > extra_len) { - wpa_printf(MSG_INFO, "WPA: Truncated EAPOL-Key packet:" - " key_data_length=%lu > extra_len=%lu", - (unsigned long) keydatalen, - (unsigned long) extra_len); - return -1; - } - if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - if (maxkeylen < 8) { - wpa_printf(MSG_INFO, "WPA: Too short maxkeylen (%lu)", - (unsigned long) maxkeylen); - return -1; - } - maxkeylen -= 8; - } - - if (wpa_supplicant_check_group_cipher(sm->group_cipher, - gd->gtk_len, maxkeylen, - &gd->key_rsc_len, &gd->alg)) - return -1; - - gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> - WPA_KEY_INFO_KEY_INDEX_SHIFT; - if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { - os_memcpy(ek, key->key_iv, 16); - os_memcpy(ek + 16, sm->ptk.kek, 16); - if (keydatalen > sizeof(gd->gtk)) { - wpa_printf(MSG_WARNING, "WPA: RC4 key data " - "too long (%lu)", - (unsigned long) keydatalen); - return -1; - } - os_memcpy(gd->gtk, key + 1, keydatalen); - rc4_skip(ek, 32, 256, gd->gtk, keydatalen); - } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - if (keydatalen % 8) { - wpa_printf(MSG_WARNING, "WPA: Unsupported AES-WRAP " - "len %lu", (unsigned long) keydatalen); - return -1; - } - if (maxkeylen > sizeof(gd->gtk)) { - wpa_printf(MSG_WARNING, "WPA: AES-WRAP key data " - "too long (keydatalen=%lu maxkeylen=%lu)", - (unsigned long) keydatalen, - (unsigned long) maxkeylen); - return -1; - } - if (aes_unwrap(sm->ptk.kek, maxkeylen / 8, - (const u8 *) (key + 1), gd->gtk)) { - wpa_printf(MSG_WARNING, "WPA: AES unwrap " - "failed - could not decrypt GTK"); - return -1; - } - } else { - wpa_printf(MSG_WARNING, "WPA: Unsupported key_info type %d", - ver); - return -1; - } - gd->tx = wpa_supplicant_gtk_tx_bit_workaround( - sm, !!(key_info & WPA_KEY_INFO_TXRX)); - return 0; -} - - -static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm, - const struct wpa_eapol_key *key, - int ver, u16 key_info) -{ - size_t rlen; - struct wpa_eapol_key *reply; - u8 *rbuf; - - rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, - sizeof(*reply), &rlen, (void *) &reply); - if (rbuf == NULL) - return -1; - - reply->type = sm->proto == WPA_PROTO_RSN ? - 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; - WPA_PUT_BE16(reply->key_info, key_info); - if (sm->proto == WPA_PROTO_RSN) - WPA_PUT_BE16(reply->key_length, 0); - else - os_memcpy(reply->key_length, key->key_length, 2); - os_memcpy(reply->replay_counter, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - - WPA_PUT_BE16(reply->key_data_length, 0); - - wpa_printf(MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2"); - wpa_eapol_key_send(sm, sm->ptk.kck, ver, sm->bssid, ETH_P_EAPOL, - rbuf, rlen, reply->key_mic); - - return 0; -} - - -static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm, - const unsigned char *src_addr, - const struct wpa_eapol_key *key, - int extra_len, u16 ver) -{ - u16 key_info, keydatalen; - int rekey, ret; - struct wpa_gtk_data gd; - - os_memset(&gd, 0, sizeof(gd)); - - rekey = wpa_sm_get_state(sm) == WPA_COMPLETED; - wpa_printf(MSG_DEBUG, "WPA: RX message 1 of Group Key Handshake from " - MACSTR " (ver=%d)", MAC2STR(src_addr), ver); - - key_info = WPA_GET_BE16(key->key_info); - keydatalen = WPA_GET_BE16(key->key_data_length); - - if (sm->proto == WPA_PROTO_RSN) { - ret = wpa_supplicant_process_1_of_2_rsn(sm, - (const u8 *) (key + 1), - keydatalen, key_info, - &gd); - } else { - ret = wpa_supplicant_process_1_of_2_wpa(sm, key, keydatalen, - key_info, extra_len, - ver, &gd); - } - - wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); - - if (ret) - goto failed; - - if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc) || - wpa_supplicant_send_2_of_2(sm, key, ver, key_info)) - goto failed; - - if (rekey) { - wpa_msg(sm->ctx->ctx, MSG_INFO, "WPA: Group rekeying " - "completed with " MACSTR " [GTK=%s]", - MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher)); - wpa_sm_cancel_auth_timeout(sm); - wpa_sm_set_state(sm, WPA_COMPLETED); - } else { - wpa_supplicant_key_neg_complete(sm, sm->bssid, - key_info & - WPA_KEY_INFO_SECURE); - } - return; - -failed: - wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); -} - - -static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, - struct wpa_eapol_key *key, - u16 ver, - const u8 *buf, size_t len) -{ - u8 mic[16]; - int ok = 0; - - os_memcpy(mic, key->key_mic, 16); - if (sm->tptk_set) { - os_memset(key->key_mic, 0, 16); - wpa_eapol_key_mic(sm->tptk.kck, ver, buf, len, - key->key_mic); - if (os_memcmp(mic, key->key_mic, 16) != 0) { - wpa_printf(MSG_WARNING, "WPA: Invalid EAPOL-Key MIC " - "when using TPTK - ignoring TPTK"); - } else { - ok = 1; - sm->tptk_set = 0; - sm->ptk_set = 1; - os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk)); - } - } - - if (!ok && sm->ptk_set) { - os_memset(key->key_mic, 0, 16); - wpa_eapol_key_mic(sm->ptk.kck, ver, buf, len, - key->key_mic); - if (os_memcmp(mic, key->key_mic, 16) != 0) { - wpa_printf(MSG_WARNING, "WPA: Invalid EAPOL-Key MIC " - "- dropping packet"); - return -1; - } - ok = 1; - } - - if (!ok) { - wpa_printf(MSG_WARNING, "WPA: Could not verify EAPOL-Key MIC " - "- dropping packet"); - return -1; - } - - os_memcpy(sm->rx_replay_counter, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - sm->rx_replay_counter_set = 1; - return 0; -} - - -/* 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) -{ - u16 keydatalen = WPA_GET_BE16(key->key_data_length); - - wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data", - (u8 *) (key + 1), keydatalen); - if (!sm->ptk_set) { - wpa_printf(MSG_WARNING, "WPA: PTK not available, " - "cannot decrypt EAPOL-Key key data."); - return -1; - } - - /* Decrypt key data here so that this operation does not need - * to be implemented separately for each message type. */ - if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { - u8 ek[32]; - os_memcpy(ek, key->key_iv, 16); - os_memcpy(ek + 16, sm->ptk.kek, 16); - rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen); - } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || - ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) { - u8 *buf; - if (keydatalen % 8) { - wpa_printf(MSG_WARNING, "WPA: Unsupported " - "AES-WRAP len %d", keydatalen); - return -1; - } - keydatalen -= 8; /* AES-WRAP adds 8 bytes */ - buf = os_malloc(keydatalen); - if (buf == NULL) { - wpa_printf(MSG_WARNING, "WPA: No memory for " - "AES-UNWRAP buffer"); - return -1; - } - if (aes_unwrap(sm->ptk.kek, keydatalen / 8, - (u8 *) (key + 1), buf)) { - os_free(buf); - wpa_printf(MSG_WARNING, "WPA: AES unwrap failed - " - "could not decrypt EAPOL-Key key data"); - return -1; - } - os_memcpy(key + 1, buf, keydatalen); - os_free(buf); - WPA_PUT_BE16(key->key_data_length, keydatalen); - } else { - wpa_printf(MSG_WARNING, "WPA: Unsupported key_info type %d", - ver); - return -1; - } - wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data", - (u8 *) (key + 1), keydatalen); - return 0; -} - - -/** - * wpa_sm_aborted_cached - Notify WPA that PMKSA caching was aborted - * @sm: Pointer to WPA state machine data from wpa_sm_init() - */ -void wpa_sm_aborted_cached(struct wpa_sm *sm) -{ - if (sm && sm->cur_pmksa) { - wpa_printf(MSG_DEBUG, "RSN: Cancelling PMKSA caching attempt"); - sm->cur_pmksa = NULL; - } -} - - -static void wpa_eapol_key_dump(const struct wpa_eapol_key *key) -{ -#ifndef CONFIG_NO_STDOUT_DEBUG - u16 key_info = WPA_GET_BE16(key->key_info); - - wpa_printf(MSG_DEBUG, " EAPOL-Key type=%d", key->type); - wpa_printf(MSG_DEBUG, " key_info 0x%x (ver=%d keyidx=%d rsvd=%d %s" - "%s%s%s%s%s%s%s)", - key_info, key_info & WPA_KEY_INFO_TYPE_MASK, - (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> - WPA_KEY_INFO_KEY_INDEX_SHIFT, - (key_info & (BIT(13) | BIT(14) | BIT(15))) >> 13, - key_info & WPA_KEY_INFO_KEY_TYPE ? "Pairwise" : "Group", - key_info & WPA_KEY_INFO_INSTALL ? " Install" : "", - key_info & WPA_KEY_INFO_ACK ? " Ack" : "", - key_info & WPA_KEY_INFO_MIC ? " MIC" : "", - key_info & WPA_KEY_INFO_SECURE ? " Secure" : "", - key_info & WPA_KEY_INFO_ERROR ? " Error" : "", - key_info & WPA_KEY_INFO_REQUEST ? " Request" : "", - key_info & WPA_KEY_INFO_ENCR_KEY_DATA ? " Encr" : ""); - wpa_printf(MSG_DEBUG, " key_length=%u key_data_length=%u", - WPA_GET_BE16(key->key_length), - WPA_GET_BE16(key->key_data_length)); - wpa_hexdump(MSG_DEBUG, " replay_counter", - key->replay_counter, WPA_REPLAY_COUNTER_LEN); - wpa_hexdump(MSG_DEBUG, " key_nonce", key->key_nonce, WPA_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, " key_iv", key->key_iv, 16); - wpa_hexdump(MSG_DEBUG, " key_rsc", key->key_rsc, 8); - wpa_hexdump(MSG_DEBUG, " key_id (reserved)", key->key_id, 8); - wpa_hexdump(MSG_DEBUG, " key_mic", key->key_mic, 16); -#endif /* CONFIG_NO_STDOUT_DEBUG */ -} - - -/** - * wpa_sm_rx_eapol - Process received WPA EAPOL frames - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @src_addr: Source MAC address of the EAPOL packet - * @buf: Pointer to the beginning of the EAPOL data (EAPOL header) - * @len: Length of the EAPOL frame - * Returns: 1 = WPA EAPOL-Key processed, 0 = not a WPA EAPOL-Key, -1 failure - * - * This function is called for each received EAPOL frame. Other than EAPOL-Key - * frames can be skipped if filtering is done elsewhere. wpa_sm_rx_eapol() is - * only processing WPA and WPA2 EAPOL-Key frames. - * - * The received EAPOL-Key packets are validated and valid packets are replied - * to. In addition, key material (PTK, GTK) is configured at the end of a - * successful key handshake. - */ -int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, - const u8 *buf, size_t len) -{ - size_t plen, data_len, extra_len; - struct ieee802_1x_hdr *hdr; - struct wpa_eapol_key *key; - u16 key_info, ver; - u8 *tmp; - int ret = -1; - struct wpa_peerkey *peerkey = NULL; - -#ifdef CONFIG_IEEE80211R - sm->ft_completed = 0; -#endif /* CONFIG_IEEE80211R */ - - if (len < sizeof(*hdr) + sizeof(*key)) { - wpa_printf(MSG_DEBUG, "WPA: EAPOL frame too short to be a WPA " - "EAPOL-Key (len %lu, expecting at least %lu)", - (unsigned long) len, - (unsigned long) sizeof(*hdr) + sizeof(*key)); - return 0; - } - - tmp = os_malloc(len); - if (tmp == NULL) - return -1; - os_memcpy(tmp, buf, len); - - hdr = (struct ieee802_1x_hdr *) tmp; - key = (struct wpa_eapol_key *) (hdr + 1); - plen = be_to_host16(hdr->length); - data_len = plen + sizeof(*hdr); - wpa_printf(MSG_DEBUG, "IEEE 802.1X RX: version=%d type=%d length=%lu", - hdr->version, hdr->type, (unsigned long) plen); - - if (hdr->version < EAPOL_VERSION) { - /* TODO: backwards compatibility */ - } - if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) { - wpa_printf(MSG_DEBUG, "WPA: EAPOL frame (type %u) discarded, " - "not a Key frame", hdr->type); - ret = 0; - goto out; - } - if (plen > len - sizeof(*hdr) || plen < sizeof(*key)) { - wpa_printf(MSG_DEBUG, "WPA: EAPOL frame payload size %lu " - "invalid (frame size %lu)", - (unsigned long) plen, (unsigned long) len); - ret = 0; - goto out; - } - - if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN) - { - wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key type (%d) unknown, " - "discarded", key->type); - ret = 0; - goto out; - } - wpa_eapol_key_dump(key); - - eapol_sm_notify_lower_layer_success(sm->eapol, 0); - wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", tmp, len); - if (data_len < len) { - wpa_printf(MSG_DEBUG, "WPA: ignoring %lu bytes after the IEEE " - "802.1X data", (unsigned long) len - data_len); - } - key_info = WPA_GET_BE16(key->key_info); - ver = key_info & WPA_KEY_INFO_TYPE_MASK; - if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && -#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) - ver != WPA_KEY_INFO_TYPE_AES_128_CMAC && -#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ - ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - wpa_printf(MSG_INFO, "WPA: Unsupported EAPOL-Key descriptor " - "version %d.", ver); - goto out; - } - -#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) { - wpa_printf(MSG_INFO, "FT: AP did not use " - "AES-128-CMAC."); - goto out; - } - } else -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - if (wpa_key_mgmt_sha256(sm->key_mgmt)) { - if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { - wpa_printf(MSG_INFO, "WPA: AP did not use the " - "negotiated AES-128-CMAC."); - goto out; - } - } else -#endif /* CONFIG_IEEE80211W */ - if (sm->pairwise_cipher == WPA_CIPHER_CCMP && - ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - wpa_printf(MSG_INFO, "WPA: CCMP is used, but EAPOL-Key " - "descriptor version (%d) is not 2.", ver); - if (sm->group_cipher != WPA_CIPHER_CCMP && - !(key_info & WPA_KEY_INFO_KEY_TYPE)) { - /* Earlier versions of IEEE 802.11i did not explicitly - * require version 2 descriptor for all EAPOL-Key - * packets, so allow group keys to use version 1 if - * CCMP is not used for them. */ - wpa_printf(MSG_INFO, "WPA: Backwards compatibility: " - "allow invalid version for non-CCMP group " - "keys"); - } else - 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_printf(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_printf(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_printf(MSG_INFO, "RSN: Ack bit in key_info from STK peer"); - goto out; - } -#endif /* CONFIG_PEERKEY */ - - if (!peerkey && sm->rx_replay_counter_set && - os_memcmp(key->replay_counter, sm->rx_replay_counter, - WPA_REPLAY_COUNTER_LEN) <= 0) { - wpa_printf(MSG_WARNING, "WPA: EAPOL-Key Replay Counter did not" - " increase - dropping packet"); - goto out; - } - - if (!(key_info & (WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE)) -#ifdef CONFIG_PEERKEY - && (peerkey == NULL || !peerkey->initiator) -#endif /* CONFIG_PEERKEY */ - ) { - wpa_printf(MSG_INFO, "WPA: No Ack bit in key_info"); - goto out; - } - - if (key_info & WPA_KEY_INFO_REQUEST) { - wpa_printf(MSG_INFO, "WPA: EAPOL-Key with Request bit - " - "dropped"); - goto out; - } - - if ((key_info & WPA_KEY_INFO_MIC) && !peerkey && - 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, key, ver, tmp, data_len)) - goto out; -#endif /* CONFIG_PEERKEY */ - - extra_len = data_len - sizeof(*hdr) - sizeof(*key); - - if (WPA_GET_BE16(key->key_data_length) > extra_len) { - wpa_msg(sm->ctx->ctx, MSG_INFO, "WPA: Invalid EAPOL-Key " - "frame - key_data overflow (%d > %lu)", - WPA_GET_BE16(key->key_data_length), - (unsigned long) extra_len); - goto out; - } - extra_len = WPA_GET_BE16(key->key_data_length); - - if (sm->proto == WPA_PROTO_RSN && - (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { - if (wpa_supplicant_decrypt_key_data(sm, key, ver)) - goto out; - extra_len = WPA_GET_BE16(key->key_data_length); - } - - if (key_info & WPA_KEY_INFO_KEY_TYPE) { - if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) { - wpa_printf(MSG_WARNING, "WPA: Ignored EAPOL-Key " - "(Pairwise) with non-zero key index"); - goto out; - } - if (peerkey) { - /* PeerKey 4-Way Handshake */ - peerkey_rx_eapol_4way(sm, peerkey, key, key_info, ver); - } else if (key_info & WPA_KEY_INFO_MIC) { - /* 3/4 4-Way Handshake */ - wpa_supplicant_process_3_of_4(sm, key, ver); - } else { - /* 1/4 4-Way Handshake */ - wpa_supplicant_process_1_of_4(sm, src_addr, key, - ver); - } - } else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) { - /* PeerKey SMK Handshake */ - peerkey_rx_eapol_smk(sm, src_addr, key, extra_len, key_info, - ver); - } else { - if (key_info & WPA_KEY_INFO_MIC) { - /* 1/2 Group Key Handshake */ - wpa_supplicant_process_1_of_2(sm, src_addr, key, - extra_len, ver); - } else { - wpa_printf(MSG_WARNING, "WPA: EAPOL-Key (Group) " - "without Mic bit - dropped"); - } - } - - ret = 1; - -out: - os_free(tmp); - return ret; -} - - -#ifdef CONFIG_CTRL_IFACE -static int wpa_cipher_bits(int cipher) -{ - switch (cipher) { - case WPA_CIPHER_CCMP: - return 128; - case WPA_CIPHER_TKIP: - return 256; - case WPA_CIPHER_WEP104: - return 104; - case WPA_CIPHER_WEP40: - return 40; - default: - return 0; - } -} - - -static u32 wpa_key_mgmt_suite(struct wpa_sm *sm) -{ - switch (sm->key_mgmt) { - case WPA_KEY_MGMT_IEEE8021X: - return (sm->proto == WPA_PROTO_RSN ? - RSN_AUTH_KEY_MGMT_UNSPEC_802_1X : - WPA_AUTH_KEY_MGMT_UNSPEC_802_1X); - case WPA_KEY_MGMT_PSK: - return (sm->proto == WPA_PROTO_RSN ? - RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X : - WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X); -#ifdef CONFIG_IEEE80211R - case WPA_KEY_MGMT_FT_IEEE8021X: - return RSN_AUTH_KEY_MGMT_FT_802_1X; - case WPA_KEY_MGMT_FT_PSK: - return RSN_AUTH_KEY_MGMT_FT_PSK; -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - case WPA_KEY_MGMT_IEEE8021X_SHA256: - return RSN_AUTH_KEY_MGMT_802_1X_SHA256; - case WPA_KEY_MGMT_PSK_SHA256: - return RSN_AUTH_KEY_MGMT_PSK_SHA256; -#endif /* CONFIG_IEEE80211W */ - case WPA_KEY_MGMT_WPA_NONE: - return WPA_AUTH_KEY_MGMT_NONE; - default: - return 0; - } -} - - -static u32 wpa_cipher_suite(struct wpa_sm *sm, int cipher) -{ - switch (cipher) { - case WPA_CIPHER_CCMP: - return (sm->proto == WPA_PROTO_RSN ? - RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP); - case WPA_CIPHER_TKIP: - return (sm->proto == WPA_PROTO_RSN ? - RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP); - case WPA_CIPHER_WEP104: - return (sm->proto == WPA_PROTO_RSN ? - RSN_CIPHER_SUITE_WEP104 : WPA_CIPHER_SUITE_WEP104); - case WPA_CIPHER_WEP40: - return (sm->proto == WPA_PROTO_RSN ? - RSN_CIPHER_SUITE_WEP40 : WPA_CIPHER_SUITE_WEP40); - case WPA_CIPHER_NONE: - return (sm->proto == WPA_PROTO_RSN ? - RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE); - default: - return 0; - } -} - - -#define RSN_SUITE "%02x-%02x-%02x-%d" -#define RSN_SUITE_ARG(s) \ -((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff - -/** - * wpa_sm_get_mib - Dump text list of MIB entries - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @buf: Buffer for the list - * @buflen: Length of the buffer - * Returns: Number of bytes written to buffer - * - * This function is used fetch dot11 MIB variables. - */ -int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen) -{ - char pmkid_txt[PMKID_LEN * 2 + 1]; - int rsna, ret; - size_t len; - - if (sm->cur_pmksa) { - wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt), - sm->cur_pmksa->pmkid, PMKID_LEN); - } else - pmkid_txt[0] = '\0'; - - if ((wpa_key_mgmt_wpa_psk(sm->key_mgmt) || - wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) && - sm->proto == WPA_PROTO_RSN) - rsna = 1; - else - rsna = 0; - - ret = os_snprintf(buf, buflen, - "dot11RSNAOptionImplemented=TRUE\n" - "dot11RSNAPreauthenticationImplemented=TRUE\n" - "dot11RSNAEnabled=%s\n" - "dot11RSNAPreauthenticationEnabled=%s\n" - "dot11RSNAConfigVersion=%d\n" - "dot11RSNAConfigPairwiseKeysSupported=5\n" - "dot11RSNAConfigGroupCipherSize=%d\n" - "dot11RSNAConfigPMKLifetime=%d\n" - "dot11RSNAConfigPMKReauthThreshold=%d\n" - "dot11RSNAConfigNumberOfPTKSAReplayCounters=1\n" - "dot11RSNAConfigSATimeout=%d\n", - rsna ? "TRUE" : "FALSE", - rsna ? "TRUE" : "FALSE", - RSN_VERSION, - wpa_cipher_bits(sm->group_cipher), - sm->dot11RSNAConfigPMKLifetime, - sm->dot11RSNAConfigPMKReauthThreshold, - sm->dot11RSNAConfigSATimeout); - if (ret < 0 || (size_t) ret >= buflen) - return 0; - len = ret; - - ret = os_snprintf( - buf + len, buflen - len, - "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n" - "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n" - "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n" - "dot11RSNAPMKIDUsed=%s\n" - "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n" - "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n" - "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n" - "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n" - "dot11RSNA4WayHandshakeFailures=%u\n", - RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)), - RSN_SUITE_ARG(wpa_cipher_suite(sm, sm->pairwise_cipher)), - RSN_SUITE_ARG(wpa_cipher_suite(sm, sm->group_cipher)), - pmkid_txt, - RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)), - RSN_SUITE_ARG(wpa_cipher_suite(sm, sm->pairwise_cipher)), - RSN_SUITE_ARG(wpa_cipher_suite(sm, sm->group_cipher)), - sm->dot11RSNA4WayHandshakeFailures); - if (ret >= 0 && (size_t) ret < buflen) - len += ret; - - return (int) len; -} -#endif /* CONFIG_CTRL_IFACE */ - - -static void wpa_sm_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry, - void *ctx, int replace) -{ - struct wpa_sm *sm = ctx; - - if (sm->cur_pmksa == entry || - (sm->pmk_len == entry->pmk_len && - os_memcmp(sm->pmk, entry->pmk, sm->pmk_len) == 0)) { - wpa_printf(MSG_DEBUG, "RSN: removed current PMKSA entry"); - sm->cur_pmksa = NULL; - - if (replace) { - /* A new entry is being added, so no need to - * deauthenticate in this case. This happens when EAP - * authentication is completed again (reauth or failed - * PMKSA caching attempt). */ - return; - } - - os_memset(sm->pmk, 0, sizeof(sm->pmk)); - wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); - } -} - - -/** - * wpa_sm_init - Initialize WPA state machine - * @ctx: Context pointer for callbacks; this needs to be an allocated buffer - * Returns: Pointer to the allocated WPA state machine data - * - * This function is used to allocate a new WPA state machine and the returned - * value is passed to all WPA state machine calls. - */ -struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx) -{ - struct wpa_sm *sm; - - sm = os_zalloc(sizeof(*sm)); - if (sm == NULL) - return NULL; - sm->renew_snonce = 1; - sm->ctx = ctx; - - sm->dot11RSNAConfigPMKLifetime = 43200; - sm->dot11RSNAConfigPMKReauthThreshold = 70; - sm->dot11RSNAConfigSATimeout = 60; - - sm->pmksa = pmksa_cache_init(wpa_sm_pmksa_free_cb, sm, sm); - if (sm->pmksa == NULL) { - wpa_printf(MSG_ERROR, "RSN: PMKSA cache initialization " - "failed"); - os_free(sm); - return NULL; - } - - return sm; -} - - -/** - * wpa_sm_deinit - Deinitialize WPA state machine - * @sm: Pointer to WPA state machine data from wpa_sm_init() - */ -void wpa_sm_deinit(struct wpa_sm *sm) -{ - if (sm == NULL) - return; - pmksa_cache_deinit(sm->pmksa); - eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL); - eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); - os_free(sm->assoc_wpa_ie); - os_free(sm->ap_wpa_ie); - os_free(sm->ap_rsn_ie); - os_free(sm->ctx); - peerkey_deinit(sm); - os_free(sm); -} - - -/** - * wpa_sm_notify_assoc - Notify WPA state machine about association - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @bssid: The BSSID of the new association - * - * This function is called to let WPA state machine know that the connection - * was established. - */ -void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) -{ - int clear_ptk = 1; - - if (sm == NULL) - return; - - wpa_printf(MSG_DEBUG, "WPA: Association event - clear replay counter"); - os_memcpy(sm->bssid, bssid, ETH_ALEN); - os_memset(sm->rx_replay_counter, 0, WPA_REPLAY_COUNTER_LEN); - sm->rx_replay_counter_set = 0; - sm->renew_snonce = 1; - if (os_memcmp(sm->preauth_bssid, bssid, ETH_ALEN) == 0) - rsn_preauth_deinit(sm); - -#ifdef CONFIG_IEEE80211R - if (wpa_ft_is_completed(sm)) { - wpa_supplicant_key_neg_complete(sm, sm->bssid, 1); - - /* Prepare for the next transition */ - wpa_ft_prepare_auth_request(sm); - - clear_ptk = 0; - } -#endif /* CONFIG_IEEE80211R */ - - if (clear_ptk) { - /* - * IEEE 802.11, 8.4.10: Delete PTK SA on (re)association if - * this is not part of a Fast BSS Transition. - */ - wpa_printf(MSG_DEBUG, "WPA: Clear old PTK"); - sm->ptk_set = 0; - sm->tptk_set = 0; - } -} - - -/** - * wpa_sm_notify_disassoc - Notify WPA state machine about disassociation - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * - * This function is called to let WPA state machine know that the connection - * was lost. This will abort any existing pre-authentication session. - */ -void wpa_sm_notify_disassoc(struct wpa_sm *sm) -{ - rsn_preauth_deinit(sm); - if (wpa_sm_get_state(sm) == WPA_4WAY_HANDSHAKE) - sm->dot11RSNA4WayHandshakeFailures++; -} - - -/** - * wpa_sm_set_pmk - Set PMK - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @pmk: The new PMK - * @pmk_len: The length of the new PMK in bytes - * - * Configure the PMK for WPA state machine. - */ -void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len) -{ - if (sm == NULL) - return; - - sm->pmk_len = pmk_len; - os_memcpy(sm->pmk, pmk, pmk_len); - -#ifdef CONFIG_IEEE80211R - /* Set XXKey to be PSK for FT key derivation */ - sm->xxkey_len = pmk_len; - os_memcpy(sm->xxkey, pmk, pmk_len); -#endif /* CONFIG_IEEE80211R */ -} - - -/** - * wpa_sm_set_pmk_from_pmksa - Set PMK based on the current PMKSA - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * - * Take the PMK from the current PMKSA into use. If no PMKSA is active, the PMK - * will be cleared. - */ -void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm) -{ - if (sm == NULL) - return; - - if (sm->cur_pmksa) { - 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_sm_set_fast_reauth - Set fast reauthentication (EAP) enabled/disabled - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @fast_reauth: Whether fast reauthentication (EAP) is allowed - */ -void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth) -{ - if (sm) - sm->fast_reauth = fast_reauth; -} - - -/** - * wpa_sm_set_scard_ctx - Set context pointer for smartcard callbacks - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @scard_ctx: Context pointer for smartcard related callback functions - */ -void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx) -{ - if (sm == NULL) - return; - sm->scard_ctx = scard_ctx; - if (sm->preauth_eapol) - eapol_sm_register_scard_ctx(sm->preauth_eapol, scard_ctx); -} - - -/** - * wpa_sm_set_config - Notification of current configration change - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @config: Pointer to current network configuration - * - * Notify WPA state machine that configuration has changed. config will be - * stored as a backpointer to network configuration. This can be %NULL to clear - * the stored pointed. - */ -void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config) -{ - if (!sm) - return; - - 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; - sm->eap_conf_ctx = config->eap_conf_ctx; - if (config->ssid) { - os_memcpy(sm->ssid, config->ssid, config->ssid_len); - sm->ssid_len = config->ssid_len; - } else - sm->ssid_len = 0; - sm->wpa_ptk_rekey = config->wpa_ptk_rekey; - } else { - sm->network_ctx = NULL; - sm->peerkey_enabled = 0; - sm->allowed_pairwise_cipher = 0; - sm->proactive_key_caching = 0; - sm->eap_workaround = 0; - sm->eap_conf_ctx = NULL; - sm->ssid_len = 0; - sm->wpa_ptk_rekey = 0; - } - if (config == NULL || config->network_ctx != sm->network_ctx) - pmksa_cache_notify_reconfig(sm->pmksa); -} - - -/** - * wpa_sm_set_own_addr - Set own MAC address - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @addr: Own MAC address - */ -void wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr) -{ - if (sm) - os_memcpy(sm->own_addr, addr, ETH_ALEN); -} - - -/** - * wpa_sm_set_ifname - Set network interface name - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @ifname: Interface name - * @bridge_ifname: Optional bridge interface name (for pre-auth) - */ -void wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname, - const char *bridge_ifname) -{ - if (sm) { - sm->ifname = ifname; - sm->bridge_ifname = bridge_ifname; - } -} - - -/** - * wpa_sm_set_eapol - Set EAPOL state machine pointer - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @eapol: Pointer to EAPOL state machine allocated with eapol_sm_init() - */ -void wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol) -{ - if (sm) - sm->eapol = eapol; -} - - -/** - * wpa_sm_set_param - Set WPA state machine parameters - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @param: Parameter field - * @value: Parameter value - * Returns: 0 on success, -1 on failure - */ -int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, - unsigned int value) -{ - int ret = 0; - - if (sm == NULL) - return -1; - - switch (param) { - case RSNA_PMK_LIFETIME: - if (value > 0) - sm->dot11RSNAConfigPMKLifetime = value; - else - ret = -1; - break; - case RSNA_PMK_REAUTH_THRESHOLD: - if (value > 0 && value <= 100) - sm->dot11RSNAConfigPMKReauthThreshold = value; - else - ret = -1; - break; - case RSNA_SA_TIMEOUT: - if (value > 0) - sm->dot11RSNAConfigSATimeout = value; - else - ret = -1; - break; - case WPA_PARAM_PROTO: - sm->proto = value; - break; - case WPA_PARAM_PAIRWISE: - sm->pairwise_cipher = value; - break; - case WPA_PARAM_GROUP: - sm->group_cipher = value; - break; - case WPA_PARAM_KEY_MGMT: - sm->key_mgmt = value; - break; -#ifdef CONFIG_IEEE80211W - case WPA_PARAM_MGMT_GROUP: - sm->mgmt_group_cipher = value; - break; -#endif /* CONFIG_IEEE80211W */ - case WPA_PARAM_RSN_ENABLED: - sm->rsn_enabled = value; - break; - default: - break; - } - - return ret; -} - - -/** - * wpa_sm_get_param - Get WPA state machine parameters - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @param: Parameter field - * Returns: Parameter value - */ -unsigned int wpa_sm_get_param(struct wpa_sm *sm, enum wpa_sm_conf_params param) -{ - if (sm == NULL) - return 0; - - switch (param) { - case RSNA_PMK_LIFETIME: - return sm->dot11RSNAConfigPMKLifetime; - case RSNA_PMK_REAUTH_THRESHOLD: - return sm->dot11RSNAConfigPMKReauthThreshold; - case RSNA_SA_TIMEOUT: - return sm->dot11RSNAConfigSATimeout; - case WPA_PARAM_PROTO: - return sm->proto; - case WPA_PARAM_PAIRWISE: - return sm->pairwise_cipher; - case WPA_PARAM_GROUP: - return sm->group_cipher; - case WPA_PARAM_KEY_MGMT: - return sm->key_mgmt; -#ifdef CONFIG_IEEE80211W - case WPA_PARAM_MGMT_GROUP: - return sm->mgmt_group_cipher; -#endif /* CONFIG_IEEE80211W */ - case WPA_PARAM_RSN_ENABLED: - return sm->rsn_enabled; - default: - return 0; - } -} - - -/** - * wpa_sm_get_status - Get WPA state machine - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @buf: Buffer for status information - * @buflen: Maximum buffer length - * @verbose: Whether to include verbose status information - * Returns: Number of bytes written to buf. - * - * Query WPA state machine for status information. This function fills in - * a text area with current status information. If the buffer (buf) is not - * large enough, status information will be truncated to fit the buffer. - */ -int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen, - int verbose) -{ - char *pos = buf, *end = buf + buflen; - int ret; - - ret = os_snprintf(pos, end - pos, - "pairwise_cipher=%s\n" - "group_cipher=%s\n" - "key_mgmt=%s\n", - wpa_cipher_txt(sm->pairwise_cipher), - wpa_cipher_txt(sm->group_cipher), - wpa_key_mgmt_txt(sm->key_mgmt, sm->proto)); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - return pos - buf; -} - - -/** - * 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() - * @wpa_ie: Pointer to buffer for WPA/RSN IE - * @wpa_ie_len: Pointer to the length of the wpa_ie buffer - * Returns: 0 on success, -1 on failure - */ -int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie, - size_t *wpa_ie_len) -{ - int res; - - if (sm == NULL) - return -1; - - res = wpa_gen_wpa_ie(sm, wpa_ie, *wpa_ie_len); - if (res < 0) - return -1; - *wpa_ie_len = res; - - wpa_hexdump(MSG_DEBUG, "WPA: Set own WPA IE default", - wpa_ie, *wpa_ie_len); - - if (sm->assoc_wpa_ie == NULL) { - /* - * Make a copy of the WPA/RSN IE so that 4-Way Handshake gets - * 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); - 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; - } - - return 0; -} - - -/** - * wpa_sm_set_assoc_wpa_ie - Set own WPA/RSN IE from (Re)AssocReq - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @ie: Pointer to IE data (starting from id) - * @len: IE length - * Returns: 0 on success, -1 on failure - * - * Inform WPA state machine about the WPA/RSN IE used in (Re)Association - * Request frame. The IE will be used to override the default value generated - * with wpa_sm_set_assoc_wpa_ie_default(). - */ -int wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len) -{ - if (sm == NULL) - return -1; - - os_free(sm->assoc_wpa_ie); - if (ie == NULL || len == 0) { - wpa_printf(MSG_DEBUG, "WPA: clearing own WPA/RSN IE"); - sm->assoc_wpa_ie = NULL; - 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); - if (sm->assoc_wpa_ie == NULL) - return -1; - - os_memcpy(sm->assoc_wpa_ie, ie, len); - sm->assoc_wpa_ie_len = len; - } - - return 0; -} - - -/** - * wpa_sm_set_ap_wpa_ie - Set AP WPA IE from Beacon/ProbeResp - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @ie: Pointer to IE data (starting from id) - * @len: IE length - * Returns: 0 on success, -1 on failure - * - * Inform WPA state machine about the WPA IE used in Beacon / Probe Response - * frame. - */ -int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len) -{ - if (sm == NULL) - return -1; - - os_free(sm->ap_wpa_ie); - if (ie == NULL || len == 0) { - wpa_printf(MSG_DEBUG, "WPA: clearing AP WPA IE"); - sm->ap_wpa_ie = NULL; - 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); - if (sm->ap_wpa_ie == NULL) - return -1; - - os_memcpy(sm->ap_wpa_ie, ie, len); - sm->ap_wpa_ie_len = len; - } - - return 0; -} - - -/** - * wpa_sm_set_ap_rsn_ie - Set AP RSN IE from Beacon/ProbeResp - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @ie: Pointer to IE data (starting from id) - * @len: IE length - * Returns: 0 on success, -1 on failure - * - * Inform WPA state machine about the RSN IE used in Beacon / Probe Response - * frame. - */ -int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len) -{ - if (sm == NULL) - return -1; - - os_free(sm->ap_rsn_ie); - if (ie == NULL || len == 0) { - wpa_printf(MSG_DEBUG, "WPA: clearing AP RSN IE"); - sm->ap_rsn_ie = NULL; - 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); - if (sm->ap_rsn_ie == NULL) - return -1; - - os_memcpy(sm->ap_rsn_ie, ie, len); - sm->ap_rsn_ie_len = len; - } - - return 0; -} - - -/** - * wpa_sm_parse_own_wpa_ie - Parse own WPA/RSN IE - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @data: Pointer to data area for parsing results - * Returns: 0 on success, -1 if IE is not known, or -2 on parsing failure - * - * Parse the contents of the own WPA or RSN IE from (Re)AssocReq and write the - * parsed data into data. - */ -int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data) -{ - if (sm == NULL || sm->assoc_wpa_ie == NULL) { - wpa_printf(MSG_DEBUG, "WPA: No WPA/RSN IE available from " - "association info"); - return -1; - } - if (wpa_parse_wpa_ie(sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, data)) - return -2; - return 0; -} diff --git a/contrib/hostapd/src/rsn_supp/wpa.h b/contrib/hostapd/src/rsn_supp/wpa.h deleted file mode 100644 index bdf778544f..0000000000 --- a/contrib/hostapd/src/rsn_supp/wpa.h +++ /dev/null @@ -1,320 +0,0 @@ -/* - * wpa_supplicant - WPA definitions - * Copyright (c) 2003-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPA_H -#define WPA_H - -#include "defs.h" -#include "eapol_common.h" -#include "wpa_common.h" - -#ifndef ETH_P_EAPOL -#define ETH_P_EAPOL 0x888e -#endif - -#ifndef ETH_P_RSN_PREAUTH -#define ETH_P_RSN_PREAUTH 0x88c7 -#endif - -struct wpa_sm; -struct eapol_sm; -struct wpa_config_blob; - -struct wpa_sm_ctx { - void *ctx; /* pointer to arbitrary upper level context */ - - void (*set_state)(void *ctx, wpa_states state); - wpa_states (*get_state)(void *ctx); - void (*deauthenticate)(void * ctx, int reason_code); - void (*disassociate)(void *ctx, int reason_code); - int (*set_key)(void *ctx, wpa_alg alg, - const u8 *addr, int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len); - void * (*get_network_ctx)(void *ctx); - int (*get_bssid)(void *ctx, u8 *bssid); - int (*ether_send)(void *ctx, const u8 *dest, u16 proto, const u8 *buf, - size_t len); - int (*get_beacon_ie)(void *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); - void (*set_config_blob)(void *ctx, struct wpa_config_blob *blob); - const struct wpa_config_blob * (*get_config_blob)(void *ctx, - const char *name); - int (*mlme_setprotection)(void *ctx, const u8 *addr, - int protection_type, int key_type); - int (*update_ft_ies)(void *ctx, const u8 *md, const u8 *ies, - size_t ies_len); - int (*send_ft_action)(void *ctx, u8 action, const u8 *target_ap, - const u8 *ies, size_t ies_len); -}; - - -enum wpa_sm_conf_params { - RSNA_PMK_LIFETIME /* dot11RSNAConfigPMKLifetime */, - RSNA_PMK_REAUTH_THRESHOLD /* dot11RSNAConfigPMKReauthThreshold */, - RSNA_SA_TIMEOUT /* dot11RSNAConfigSATimeout */, - WPA_PARAM_PROTO, - WPA_PARAM_PAIRWISE, - WPA_PARAM_GROUP, - WPA_PARAM_KEY_MGMT, - WPA_PARAM_MGMT_GROUP, - WPA_PARAM_RSN_ENABLED -}; - -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; - void *eap_conf_ctx; - const u8 *ssid; - size_t ssid_len; - int wpa_ptk_rekey; -}; - -#ifndef CONFIG_NO_WPA - -struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx); -void wpa_sm_deinit(struct wpa_sm *sm); -void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid); -void wpa_sm_notify_disassoc(struct wpa_sm *sm); -void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len); -void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm); -void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth); -void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx); -void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config); -void wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr); -void wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname, - const char *bridge_ifname); -void wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol); -int wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len); -int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie, - size_t *wpa_ie_len); -int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len); -int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len); -int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen); - -int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, - unsigned int value); -unsigned int wpa_sm_get_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); - -void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise); - -int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, - struct wpa_ie_data *data); - -void wpa_sm_aborted_cached(struct wpa_sm *sm); -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); - -#else /* CONFIG_NO_WPA */ - -static inline struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx) -{ - return (struct wpa_sm *) 1; -} - -static inline void wpa_sm_deinit(struct wpa_sm *sm) -{ -} - -static inline void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) -{ -} - -static inline void wpa_sm_notify_disassoc(struct wpa_sm *sm) -{ -} - -static inline void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, - size_t pmk_len) -{ -} - -static inline void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm) -{ -} - -static inline void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth) -{ -} - -static inline void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx) -{ -} - -static inline void wpa_sm_set_config(struct wpa_sm *sm, - struct rsn_supp_config *config) -{ -} - -static inline void wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr) -{ -} - -static inline void wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname, - const char *bridge_ifname) -{ -} - -static inline void wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol) -{ -} - -static inline int wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, - size_t len) -{ - return -1; -} - -static inline int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, - u8 *wpa_ie, - size_t *wpa_ie_len) -{ - return -1; -} - -static inline int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, - size_t len) -{ - return -1; -} - -static inline int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, - size_t len) -{ - return -1; -} - -static inline int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen) -{ - return 0; -} - -static inline int wpa_sm_set_param(struct wpa_sm *sm, - enum wpa_sm_conf_params param, - unsigned int value) -{ - return -1; -} - -static inline unsigned int wpa_sm_get_param(struct wpa_sm *sm, - enum wpa_sm_conf_params param) -{ - return 0; -} - -static inline int wpa_sm_get_status(struct wpa_sm *sm, char *buf, - size_t buflen, int verbose) -{ - return 0; -} - -static inline void wpa_sm_key_request(struct wpa_sm *sm, int error, - int pairwise) -{ -} - -static inline int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, - struct wpa_ie_data *data) -{ - return -1; -} - -static inline void wpa_sm_aborted_cached(struct wpa_sm *sm) -{ -} - -static inline int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, - const u8 *buf, size_t len) -{ - return -1; -} - -static inline int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, - struct wpa_ie_data *data) -{ - return -1; -} - -#endif /* CONFIG_NO_WPA */ - -#ifdef CONFIG_PEERKEY -int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer); -#else /* CONFIG_PEERKEY */ -static inline int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) -{ - return -1; -} -#endif /* CONFIG_PEERKEY */ - -#ifdef CONFIG_IEEE80211R - -int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain, - const u8 *r0kh_id, size_t r0kh_id_len, - const u8 *r1kh_id); -int wpa_ft_prepare_auth_request(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); -int wpa_ft_is_completed(struct wpa_sm *sm); -int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, - size_t ies_len, const u8 *src_addr); -int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap); - -#else /* CONFIG_IEEE80211R */ - -static inline int -wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain, - const u8 *r0kh_id, const u8 *r1kh_id) -{ - return 0; -} - -static inline int wpa_ft_prepare_auth_request(struct wpa_sm *sm) -{ - 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) -{ - return 0; -} - -static inline int wpa_ft_is_completed(struct wpa_sm *sm) -{ - return 0; -} - -static inline int -wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, size_t ies_len, - const u8 *src_addr) -{ - return -1; -} - -#endif /* CONFIG_IEEE80211R */ - -#endif /* WPA_H */ diff --git a/contrib/hostapd/src/rsn_supp/wpa_ft.c b/contrib/hostapd/src/rsn_supp/wpa_ft.c deleted file mode 100644 index 557b3114d2..0000000000 --- a/contrib/hostapd/src/rsn_supp/wpa_ft.c +++ /dev/null @@ -1,872 +0,0 @@ -/* - * WPA Supplicant - IEEE 802.11r - Fast BSS Transition - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "wpa.h" -#include "wpa_i.h" -#include "wpa_ie.h" -#include "aes_wrap.h" -#include "ieee802_11_defs.h" - -#ifdef CONFIG_IEEE80211R - -int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, - const struct wpa_eapol_key *key, - struct wpa_ptk *ptk, size_t ptk_len) -{ - u8 pmk_r1_name[WPA_PMK_NAME_LEN]; - u8 ptk_name[WPA_PMK_NAME_LEN]; - const u8 *anonce = key->key_nonce; - - if (sm->xxkey_len == 0) { - wpa_printf(MSG_DEBUG, "FT: XXKey not available for key " - "derivation"); - 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); - 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, pmk_r1_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN); - wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, anonce, sm->own_addr, - sm->bssid, pmk_r1_name, - (u8 *) ptk, ptk_len, ptk_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PTK", (u8 *) ptk, ptk_len); - wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); - - return 0; -} - - -/** - * wpa_sm_set_ft_params - Set FT (IEEE 802.11r) parameters - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @mobility_domain: Mobility domain identifier (2 octets) - * @r0kh_id: PMK-R0 key holder identity (1-48 octets) - * @r0kh_id_len: R0KH-ID length (1-48) - * @r1kh_id: PMK-R1 key holder identity (16 octets) - * Returns: 0 on success, -1 on failure - */ -int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain, - const u8 *r0kh_id, size_t r0kh_id_len, - const u8 *r1kh_id) -{ - if (sm && mobility_domain) { - wpa_hexdump(MSG_DEBUG, "FT: Mobility domain", - mobility_domain, MOBILITY_DOMAIN_ID_LEN); - os_memcpy(sm->mobility_domain, mobility_domain, - MOBILITY_DOMAIN_ID_LEN); - } else if (sm) - os_memset(sm->mobility_domain, 0, MOBILITY_DOMAIN_ID_LEN); - - if (sm && r0kh_id) { - if (r0kh_id_len > FT_R0KH_ID_MAX_LEN) - return -1; - wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID", r0kh_id, r0kh_id_len); - os_memcpy(sm->r0kh_id, r0kh_id, r0kh_id_len); - sm->r0kh_id_len = r0kh_id_len; - } else if (sm) { - /* FIX: When should R0KH-ID be cleared? We need to keep the - * old R0KH-ID in order to be able to use this during FT. */ - /* - * os_memset(sm->r0kh_id, 0, FT_R0KH_ID_LEN); - * sm->r0kh_id_len = 0; - */ - } - - if (sm && r1kh_id) { - wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", r1kh_id, FT_R1KH_ID_LEN); - os_memcpy(sm->r1kh_id, r1kh_id, FT_R1KH_ID_LEN); - } else if (sm) - os_memset(sm->r1kh_id, 0, FT_R1KH_ID_LEN); - - return 0; -} - - -/** - * wpa_ft_gen_req_ies - Generate FT (IEEE 802.11r) IEs for Auth Request - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @len: Buffer for returning the length of the IEs - * @anonce: ANonce or %NULL if not yet available - * @pmk_name: PMKR0Name or PMKR1Name to be added into the RSN IE PMKID List - * @kck: 128-bit KCK for MIC or %NULL if no MIC is used - * @target_ap: Target AP address - * Returns: Pointer to buffer with IEs or %NULL on failure - * - * Caller is responsible for freeing the returned buffer with os_free(); - */ -static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, - const u8 *anonce, const u8 *pmk_name, - const u8 *kck, const u8 *target_ap) -{ - size_t buf_len; - u8 *buf, *pos, *ftie_len, *ftie_pos; - struct rsn_mdie *mdie; - struct rsn_ftie *ftie; - struct rsn_ie_hdr *rsnie; - u16 capab; - - sm->ft_completed = 0; - - buf_len = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) + - 2 + sm->r0kh_id_len + 100; - buf = os_zalloc(buf_len); - if (buf == NULL) - return NULL; - pos = buf; - - /* RSNIE[PMKR0Name] */ - rsnie = (struct rsn_ie_hdr *) pos; - rsnie->elem_id = WLAN_EID_RSN; - WPA_PUT_LE16(rsnie->version, RSN_VERSION); - pos = (u8 *) (rsnie + 1); - - /* Group Suite Selector */ - if (sm->group_cipher == WPA_CIPHER_CCMP) - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - else if (sm->group_cipher == WPA_CIPHER_TKIP) - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); - else { - wpa_printf(MSG_WARNING, "FT: Invalid group cipher (%d)", - sm->group_cipher); - os_free(buf); - return NULL; - } - pos += RSN_SELECTOR_LEN; - - /* Pairwise Suite Count */ - WPA_PUT_LE16(pos, 1); - pos += 2; - - /* Pairwise Suite List */ - if (sm->pairwise_cipher == WPA_CIPHER_CCMP) - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - else if (sm->pairwise_cipher == WPA_CIPHER_TKIP) - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); - else { - wpa_printf(MSG_WARNING, "FT: Invalid pairwise cipher (%d)", - sm->pairwise_cipher); - os_free(buf); - return NULL; - } - pos += RSN_SELECTOR_LEN; - - /* Authenticated Key Management Suite Count */ - WPA_PUT_LE16(pos, 1); - pos += 2; - - /* 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); - else if (sm->key_mgmt == WPA_KEY_MGMT_FT_PSK) - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); - else { - wpa_printf(MSG_WARNING, "FT: Invalid key management type (%d)", - sm->key_mgmt); - os_free(buf); - return NULL; - } - pos += RSN_SELECTOR_LEN; - - /* RSN Capabilities */ - capab = 0; -#ifdef CONFIG_IEEE80211W - if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) - capab |= WPA_CAPABILITY_MFPC; -#endif /* CONFIG_IEEE80211W */ - WPA_PUT_LE16(pos, capab); - pos += 2; - - /* PMKID Count */ - WPA_PUT_LE16(pos, 1); - pos += 2; - - /* PMKID List [PMKR0Name/PMKR1Name] */ - os_memcpy(pos, pmk_name, WPA_PMK_NAME_LEN); - pos += WPA_PMK_NAME_LEN; - -#ifdef CONFIG_IEEE80211W - if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) { - /* Management Group Cipher Suite */ - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); - pos += RSN_SELECTOR_LEN; - } -#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 = 0; /* FIX: copy from the target AP's MDIE */ - - /* FTIE[SNonce, 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); - /* R0KH-ID sub-element */ - *pos++ = FTIE_SUBELEM_R0KH_ID; - *pos++ = sm->r0kh_id_len; - os_memcpy(pos, sm->r0kh_id, sm->r0kh_id_len); - pos += sm->r0kh_id_len; - *ftie_len = pos - ftie_len - 1; - - if (kck) { - /* - * IEEE Std 802.11r-2008, 11A.8.4 - * MIC shall be calculated over: - * non-AP STA MAC address - * Target AP MAC address - * Transaction seq number (5 for ReassocReq, 3 otherwise) - * RSN IE - * MDIE - * FTIE (with MIC field set to 0) - * RIC-Request (if present) - */ - ftie->mic_control[1] = 3; /* Information element count */ - if (wpa_ft_mic(kck, sm->own_addr, target_ap, 5, - ((u8 *) mdie) - 2, 2 + sizeof(*mdie), - ftie_pos, 2 + *ftie_len, - (u8 *) rsnie, 2 + rsnie->len, NULL, 0, - ftie->mic) < 0) { - wpa_printf(MSG_INFO, "FT: Failed to calculate MIC"); - os_free(buf); - return NULL; - } - } - - *len = pos - buf; - - return buf; -} - - -struct wpa_ft_ies { - const u8 *mdie; - size_t mdie_len; - const u8 *ftie; - size_t ftie_len; - const u8 *r1kh_id; - const u8 *gtk; - size_t gtk_len; - const u8 *r0kh_id; - size_t r0kh_id_len; - const u8 *rsn; - size_t rsn_len; - const u8 *rsn_pmkid; - const u8 *tie; - size_t tie_len; - const u8 *igtk; - size_t igtk_len; -}; - - -static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len, - struct wpa_ft_ies *parse) -{ - const u8 *end, *pos; - - parse->ftie = ie; - parse->ftie_len = ie_len; - - pos = ie + sizeof(struct rsn_ftie); - end = ie + ie_len; - - while (pos + 2 <= end && pos + 2 + pos[1] <= end) { - switch (pos[0]) { - case FTIE_SUBELEM_R1KH_ID: - if (pos[1] != FT_R1KH_ID_LEN) { - wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID " - "length in FTIE: %d", pos[1]); - return -1; - } - parse->r1kh_id = pos + 2; - break; - case FTIE_SUBELEM_GTK: - parse->gtk = pos + 2; - parse->gtk_len = pos[1]; - break; - case FTIE_SUBELEM_R0KH_ID: - if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) { - wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID " - "length in FTIE: %d", pos[1]); - return -1; - } - parse->r0kh_id = pos + 2; - parse->r0kh_id_len = pos[1]; - break; -#ifdef CONFIG_IEEE80211W - case FTIE_SUBELEM_IGTK: - parse->igtk = pos + 2; - parse->igtk_len = pos[1]; - break; -#endif /* CONFIG_IEEE80211W */ - } - - pos += 2 + pos[1]; - } - - return 0; -} - - -static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, - struct wpa_ft_ies *parse) -{ - const u8 *end, *pos; - struct wpa_ie_data data; - int ret; - - os_memset(parse, 0, sizeof(*parse)); - if (ies == NULL) - return 0; - - pos = ies; - end = ies + ies_len; - while (pos + 2 <= end && pos + 2 + pos[1] <= end) { - switch (pos[0]) { - case WLAN_EID_RSN: - parse->rsn = pos + 2; - parse->rsn_len = pos[1]; - ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2, - parse->rsn_len + 2, - &data); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to parse " - "RSN IE: %d", ret); - return -1; - } - if (data.num_pmkid == 1 && data.pmkid) - parse->rsn_pmkid = data.pmkid; - break; - case WLAN_EID_MOBILITY_DOMAIN: - parse->mdie = pos + 2; - parse->mdie_len = pos[1]; - break; - case WLAN_EID_FAST_BSS_TRANSITION: - if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0) - return -1; - break; - case WLAN_EID_TIMEOUT_INTERVAL: - parse->tie = pos + 2; - parse->tie_len = pos[1]; - break; - } - - pos += 2 + pos[1]; - } - - return 0; -} - - -static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid) -{ - int keylen; - wpa_alg alg; - u8 null_rsc[6] = { 0, 0, 0, 0, 0, 0 }; - - wpa_printf(MSG_DEBUG, "FT: Installing PTK to the driver."); - - switch (sm->pairwise_cipher) { - case WPA_CIPHER_CCMP: - alg = WPA_ALG_CCMP; - keylen = 16; - break; - case WPA_CIPHER_TKIP: - alg = WPA_ALG_TKIP; - keylen = 32; - break; - default: - wpa_printf(MSG_WARNING, "FT: Unsupported pairwise cipher %d", - sm->pairwise_cipher); - return -1; - } - - if (wpa_sm_set_key(sm, alg, bssid, 0, 1, null_rsc, - sizeof(null_rsc), (u8 *) sm->ptk.tk1, keylen) < 0) { - wpa_printf(MSG_WARNING, "FT: Failed to set PTK to the driver"); - return -1; - } - - return 0; -} - - -/** - * wpa_ft_prepare_auth_request - Generate over-the-air auth request - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * Returns: 0 on success, -1 on failure - */ -int wpa_ft_prepare_auth_request(struct wpa_sm *sm) -{ - u8 *ft_ies; - size_t ft_ies_len; - - /* Generate a new SNonce */ - if (os_get_random(sm->snonce, WPA_NONCE_LEN)) { - wpa_printf(MSG_INFO, "FT: Failed to generate a new SNonce"); - return -1; - } - - ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name, - NULL, sm->bssid); - if (ft_ies) { - wpa_sm_update_ft_ies(sm, sm->mobility_domain, - ft_ies, ft_ies_len); - os_free(ft_ies); - } - - return 0; -} - - -int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, - int ft_action, const u8 *target_ap) -{ - u8 *ft_ies; - size_t ft_ies_len, ptk_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; - - wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len); - - if (ft_action) { - if (!sm->over_the_ds_in_progress) { - wpa_printf(MSG_DEBUG, "FT: No over-the-DS in progress " - "- drop FT Action Response"); - return -1; - } - - if (os_memcmp(target_ap, sm->target_ap, ETH_ALEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: No over-the-DS in progress " - "with this Target AP - drop FT Action " - "Response"); - return -1; - } - } - - if (sm->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X && - sm->key_mgmt != WPA_KEY_MGMT_FT_PSK) { - wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not " - "enabled for this connection"); - return -1; - } - - if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs"); - return -1; - } - - mdie = (struct rsn_mdie *) parse.mdie; - if (mdie == NULL || parse.mdie_len < sizeof(*mdie) || - os_memcmp(mdie->mobility_domain, sm->mobility_domain, - MOBILITY_DOMAIN_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: Invalid MDIE"); - 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 (parse.r0kh_id == NULL) { - wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE"); - return -1; - } - - if (parse.r0kh_id_len != sm->r0kh_id_len || - os_memcmp(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) { - wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with " - "the current R0KH-ID"); - wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE", - 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; - } - - if (parse.r1kh_id == NULL) { - wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE"); - return -1; - } - - if (parse.rsn_pmkid == NULL || - os_memcmp(parse.rsn_pmkid, sm->pmk_r0_name, WPA_PMK_NAME_LEN)) { - wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name (PMKID) in " - "RSNIE"); - return -1; - } - - 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); - 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: PMKR1Name", - sm->pmk_r1_name, WPA_PMK_NAME_LEN); - - bssid = target_ap; - ptk_len = sm->pairwise_cipher == WPA_CIPHER_CCMP ? 48 : 64; - wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, ftie->anonce, sm->own_addr, - bssid, sm->pmk_r1_name, - (u8 *) &sm->ptk, ptk_len, ptk_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PTK", - (u8 *) &sm->ptk, ptk_len); - wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); - - ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, ftie->anonce, - sm->pmk_r1_name, sm->ptk.kck, bssid); - if (ft_ies) { - wpa_sm_update_ft_ies(sm, sm->mobility_domain, - ft_ies, ft_ies_len); - os_free(ft_ies); - } - - ret = wpa_ft_install_ptk(sm, bssid); - - if (ret == 0) { - sm->ft_completed = 1; - if (ft_action) { - /* TODO: trigger re-association to the Target AP; - * MLME is now doing this automatically, but it should - * really be done only if we get here successfully. */ - os_memcpy(sm->bssid, target_ap, ETH_ALEN); - } - } - - return ret; -} - - -int wpa_ft_is_completed(struct wpa_sm *sm) -{ - if (sm == NULL) - return 0; - - if (sm->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X && - sm->key_mgmt != WPA_KEY_MGMT_FT_PSK) - return 0; - - return sm->ft_completed; -} - - -static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem, - size_t gtk_elem_len) -{ - u8 gtk[32]; - int keyidx; - wpa_alg alg; - size_t gtk_len, keylen, rsc_len; - - if (gtk_elem == NULL) { - wpa_printf(MSG_DEBUG, "FT: No GTK included in FTIE"); - return 0; - } - - wpa_hexdump_key(MSG_DEBUG, "FT: Received GTK in Reassoc Resp", - gtk_elem, gtk_elem_len); - - if (gtk_elem_len < 10 + 24 || (gtk_elem_len - 10) % 8 || - gtk_elem_len - 18 > sizeof(gtk)) { - wpa_printf(MSG_DEBUG, "FT: Invalid GTK sub-elem " - "length %lu", (unsigned long) gtk_elem_len); - return -1; - } - gtk_len = gtk_elem_len - 18; - if (aes_unwrap(sm->ptk.kek, gtk_len / 8, gtk_elem + 10, gtk)) { - wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not " - "decrypt GTK"); - return -1; - } - - switch (sm->group_cipher) { - case WPA_CIPHER_CCMP: - keylen = 16; - rsc_len = 6; - alg = WPA_ALG_CCMP; - break; - case WPA_CIPHER_TKIP: - keylen = 32; - rsc_len = 6; - alg = WPA_ALG_TKIP; - break; - case WPA_CIPHER_WEP104: - keylen = 13; - rsc_len = 0; - alg = WPA_ALG_WEP; - break; - case WPA_CIPHER_WEP40: - keylen = 5; - rsc_len = 0; - alg = WPA_ALG_WEP; - break; - default: - wpa_printf(MSG_WARNING, "WPA: Unsupported Group Cipher %d", - sm->group_cipher); - return -1; - } - - if (gtk_len < keylen) { - wpa_printf(MSG_DEBUG, "FT: Too short GTK in FTIE"); - return -1; - } - - /* Key Info[1] | Key Length[1] | RSC[8] | Key[5..32]. */ - - keyidx = gtk_elem[0] & 0x03; - - if (gtk_elem[1] != keylen) { - wpa_printf(MSG_DEBUG, "FT: GTK length mismatch: received %d " - "negotiated %lu", - gtk_elem[1], (unsigned long) keylen); - return -1; - } - - wpa_hexdump_key(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen); - if (wpa_sm_set_key(sm, alg, (u8 *) "\xff\xff\xff\xff\xff\xff", - keyidx, 0, gtk_elem + 2, rsc_len, gtk, keylen) < - 0) { - wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to the " - "driver."); - return -1; - } - - return 0; -} - - -#ifdef CONFIG_IEEE80211W -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]; - u16 keyidx; - - if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) - return 0; - - if (igtk_elem == NULL) { - wpa_printf(MSG_DEBUG, "FT: No IGTK included in FTIE"); - return 0; - } - - 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) { - 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) { - wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem Key Length " - "%d", igtk_elem[8]); - return -1; - } - - if (aes_unwrap(sm->ptk.kek, WPA_IGTK_LEN / 8, igtk_elem + 9, igtk)) { - wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not " - "decrypt IGTK"); - return -1; - } - - /* KeyID[2] | IPN[6] | Key Length[1] | Key[16+8] */ - - 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, (u8 *) "\xff\xff\xff\xff\xff\xff", - keyidx, 0, igtk_elem + 2, 6, igtk, WPA_IGTK_LEN) < - 0) { - wpa_printf(MSG_WARNING, "WPA: Failed to set IGTK to the " - "driver."); - return -1; - } - - return 0; -} -#endif /* CONFIG_IEEE80211W */ - - -int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, - size_t ies_len, const u8 *src_addr) -{ - struct wpa_ft_ies parse; - struct rsn_mdie *mdie; - struct rsn_ftie *ftie; - size_t count; - u8 mic[16]; - - wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len); - - if (sm->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X && - sm->key_mgmt != WPA_KEY_MGMT_FT_PSK) { - wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not " - "enabled for this connection"); - return -1; - } - - if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs"); - return -1; - } - - mdie = (struct rsn_mdie *) parse.mdie; - if (mdie == NULL || parse.mdie_len < sizeof(*mdie) || - os_memcmp(mdie->mobility_domain, sm->mobility_domain, - MOBILITY_DOMAIN_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: Invalid MDIE"); - 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 (parse.r0kh_id == NULL) { - wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE"); - return -1; - } - - if (parse.r0kh_id_len != sm->r0kh_id_len || - os_memcmp(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) { - wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with " - "the current R0KH-ID"); - wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE", - 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; - } - - if (parse.r1kh_id == NULL) { - wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE"); - return -1; - } - - if (os_memcmp(parse.r1kh_id, sm->r1kh_id, FT_R1KH_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in " - "ReassocResp"); - return -1; - } - - if (parse.rsn_pmkid == NULL || - os_memcmp(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN)) { - wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in " - "RSNIE (pmkid=%d)", !!parse.rsn_pmkid); - return -1; - } - - count = 3; - if (parse.tie) - count++; - - if (ftie->mic_control[1] != count) { - wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in FTIE (%d)", - ftie->mic_control[1]); - return -1; - } - - if (wpa_ft_mic(sm->ptk.kck, 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, NULL, 0, - mic) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC"); - return -1; - } - - if (os_memcmp(mic, ftie->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: Calculated MIC", mic, 16); - return -1; - } - - if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0) - return -1; - -#ifdef CONFIG_IEEE80211W - if (wpa_ft_process_igtk_subelem(sm, parse.igtk, parse.igtk_len) < 0) - return -1; -#endif /* CONFIG_IEEE80211W */ - - return 0; -} - - -/** - * wpa_ft_start_over_ds - Generate over-the-DS auth request - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * Returns: 0 on success, -1 on failure - */ -int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap) -{ - u8 *ft_ies; - size_t ft_ies_len; - - wpa_printf(MSG_DEBUG, "FT: Request over-the-DS with " MACSTR, - MAC2STR(target_ap)); - - /* Generate a new SNonce */ - if (os_get_random(sm->snonce, WPA_NONCE_LEN)) { - wpa_printf(MSG_INFO, "FT: Failed to generate a new SNonce"); - return -1; - } - - ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name, - NULL, target_ap); - if (ft_ies) { - sm->over_the_ds_in_progress = 1; - os_memcpy(sm->target_ap, target_ap, ETH_ALEN); - wpa_sm_send_ft_action(sm, 1, target_ap, ft_ies, ft_ies_len); - os_free(ft_ies); - } - - return 0; -} - -#endif /* CONFIG_IEEE80211R */ diff --git a/contrib/hostapd/src/rsn_supp/wpa_i.h b/contrib/hostapd/src/rsn_supp/wpa_i.h deleted file mode 100644 index e0dc6bd414..0000000000 --- a/contrib/hostapd/src/rsn_supp/wpa_i.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * wpa_supplicant - Internal WPA state machine definitions - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPA_I_H -#define WPA_I_H - -struct rsn_pmksa_candidate; -struct wpa_peerkey; -struct wpa_eapol_key; - -/** - * struct wpa_sm - Internal WPA state machine data - */ -struct wpa_sm { - u8 pmk[PMK_LEN]; - size_t pmk_len; - struct wpa_ptk ptk, tptk; - int ptk_set, tptk_set; - u8 snonce[WPA_NONCE_LEN]; - u8 anonce[WPA_NONCE_LEN]; /* ANonce from the last 1/4 msg */ - int renew_snonce; - u8 rx_replay_counter[WPA_REPLAY_COUNTER_LEN]; - int rx_replay_counter_set; - u8 request_counter[WPA_REPLAY_COUNTER_LEN]; - - struct eapol_sm *eapol; /* EAPOL state machine from upper level code */ - - struct rsn_pmksa_cache *pmksa; /* PMKSA cache */ - struct rsn_pmksa_cache_entry *cur_pmksa; /* current PMKSA entry */ - struct rsn_pmksa_candidate *pmksa_candidates; - - struct l2_packet_data *l2_preauth; - struct l2_packet_data *l2_preauth_br; - u8 preauth_bssid[ETH_ALEN]; /* current RSN pre-auth peer or - * 00:00:00:00:00:00 if no pre-auth is - * in progress */ - struct eapol_sm *preauth_eapol; - - struct wpa_sm_ctx *ctx; - - void *scard_ctx; /* context for smartcard callbacks */ - 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; - void *eap_conf_ctx; - u8 ssid[32]; - size_t ssid_len; - int wpa_ptk_rekey; - - u8 own_addr[ETH_ALEN]; - const char *ifname; - const char *bridge_ifname; - u8 bssid[ETH_ALEN]; - - unsigned int dot11RSNAConfigPMKLifetime; - unsigned int dot11RSNAConfigPMKReauthThreshold; - unsigned int dot11RSNAConfigSATimeout; - - unsigned int dot11RSNA4WayHandshakeFailures; - - /* Selected configuration (based on Beacon/ProbeResp WPA IE) */ - unsigned int proto; - unsigned int pairwise_cipher; - unsigned int group_cipher; - unsigned int key_mgmt; - unsigned int mgmt_group_cipher; - - int rsn_enabled; /* Whether RSN is enabled in configuration */ - - 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_IEEE80211R - u8 xxkey[PMK_LEN]; /* PSK or the second 256 bits of MSK */ - size_t xxkey_len; - u8 pmk_r0[PMK_LEN]; - u8 pmk_r0_name[WPA_PMK_NAME_LEN]; - u8 pmk_r1[PMK_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 over_the_ds_in_progress; - u8 target_ap[ETH_ALEN]; /* over-the-DS target AP */ -#endif /* CONFIG_IEEE80211R */ -}; - - -static inline void wpa_sm_set_state(struct wpa_sm *sm, wpa_states state) -{ - WPA_ASSERT(sm->ctx->set_state); - sm->ctx->set_state(sm->ctx->ctx, state); -} - -static inline wpa_states wpa_sm_get_state(struct wpa_sm *sm) -{ - WPA_ASSERT(sm->ctx->get_state); - return sm->ctx->get_state(sm->ctx->ctx); -} - -static inline void wpa_sm_deauthenticate(struct wpa_sm *sm, int reason_code) -{ - WPA_ASSERT(sm->ctx->deauthenticate); - sm->ctx->deauthenticate(sm->ctx->ctx, reason_code); -} - -static inline void wpa_sm_disassociate(struct wpa_sm *sm, int reason_code) -{ - WPA_ASSERT(sm->ctx->disassociate); - sm->ctx->disassociate(sm->ctx->ctx, reason_code); -} - -static inline int wpa_sm_set_key(struct wpa_sm *sm, wpa_alg alg, - const u8 *addr, int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - WPA_ASSERT(sm->ctx->set_key); - return sm->ctx->set_key(sm->ctx->ctx, alg, addr, key_idx, set_tx, - seq, seq_len, key, key_len); -} - -static inline void * wpa_sm_get_network_ctx(struct wpa_sm *sm) -{ - WPA_ASSERT(sm->ctx->get_network_ctx); - return sm->ctx->get_network_ctx(sm->ctx->ctx); -} - -static inline int wpa_sm_get_bssid(struct wpa_sm *sm, u8 *bssid) -{ - WPA_ASSERT(sm->ctx->get_bssid); - return sm->ctx->get_bssid(sm->ctx->ctx, bssid); -} - -static inline int wpa_sm_ether_send(struct wpa_sm *sm, const u8 *dest, - u16 proto, const u8 *buf, size_t len) -{ - WPA_ASSERT(sm->ctx->ether_send); - return sm->ctx->ether_send(sm->ctx->ctx, dest, proto, buf, len); -} - -static inline int wpa_sm_get_beacon_ie(struct wpa_sm *sm) -{ - WPA_ASSERT(sm->ctx->get_beacon_ie); - return sm->ctx->get_beacon_ie(sm->ctx->ctx); -} - -static inline void wpa_sm_cancel_auth_timeout(struct wpa_sm *sm) -{ - WPA_ASSERT(sm->ctx->cancel_auth_timeout); - sm->ctx->cancel_auth_timeout(sm->ctx->ctx); -} - -static inline u8 * wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type, - const void *data, u16 data_len, - size_t *msg_len, void **data_pos) -{ - WPA_ASSERT(sm->ctx->alloc_eapol); - return sm->ctx->alloc_eapol(sm->ctx->ctx, type, data, data_len, - msg_len, data_pos); -} - -static inline int wpa_sm_add_pmkid(struct wpa_sm *sm, const u8 *bssid, - const u8 *pmkid) -{ - WPA_ASSERT(sm->ctx->add_pmkid); - return sm->ctx->add_pmkid(sm->ctx->ctx, bssid, pmkid); -} - -static inline int wpa_sm_remove_pmkid(struct wpa_sm *sm, const u8 *bssid, - const u8 *pmkid) -{ - WPA_ASSERT(sm->ctx->remove_pmkid); - return sm->ctx->remove_pmkid(sm->ctx->ctx, bssid, pmkid); -} - -static inline int wpa_sm_mlme_setprotection(struct wpa_sm *sm, const u8 *addr, - int protect_type, int key_type) -{ - WPA_ASSERT(sm->ctx->mlme_setprotection); - return sm->ctx->mlme_setprotection(sm->ctx->ctx, addr, protect_type, - key_type); -} - -static inline int wpa_sm_update_ft_ies(struct wpa_sm *sm, const u8 *md, - const u8 *ies, size_t ies_len) -{ - if (sm->ctx->update_ft_ies) - return sm->ctx->update_ft_ies(sm->ctx->ctx, md, ies, ies_len); - return -1; -} - -static inline int wpa_sm_send_ft_action(struct wpa_sm *sm, u8 action, - const u8 *target_ap, - const u8 *ies, size_t ies_len) -{ - if (sm->ctx->send_ft_action) - return sm->ctx->send_ft_action(sm->ctx->ctx, action, target_ap, - ies, ies_len); - return -1; -} - - -void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, - 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, - const struct wpa_eapol_key *key, - int ver, const u8 *nonce, - const u8 *wpa_ie, size_t wpa_ie_len, - struct wpa_ptk *ptk); -int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, - const struct wpa_eapol_key *key, - u16 ver, u16 key_info, - const u8 *kde, size_t kde_len, - struct wpa_ptk *ptk); - -int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, - const struct wpa_eapol_key *key, - struct wpa_ptk *ptk, size_t ptk_len); - -#endif /* WPA_I_H */ diff --git a/contrib/hostapd/src/rsn_supp/wpa_ie.c b/contrib/hostapd/src/rsn_supp/wpa_ie.c deleted file mode 100644 index 84f2811b88..0000000000 --- a/contrib/hostapd/src/rsn_supp/wpa_ie.c +++ /dev/null @@ -1,536 +0,0 @@ -/* - * wpa_supplicant - WPA/RSN IE and KDE processing - * Copyright (c) 2003-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "wpa.h" -#include "pmksa_cache.h" -#include "ieee802_11_defs.h" -#include "wpa_i.h" -#include "wpa_ie.h" - - -static int wpa_selector_to_bitfield(const u8 *s) -{ - if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE) - return WPA_CIPHER_NONE; - if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP40) - return WPA_CIPHER_WEP40; - if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP) - return WPA_CIPHER_TKIP; - if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP) - return WPA_CIPHER_CCMP; - if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP104) - return WPA_CIPHER_WEP104; - return 0; -} - - -static int wpa_key_mgmt_to_bitfield(const u8 *s) -{ - if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X) - return WPA_KEY_MGMT_IEEE8021X; - if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X) - return WPA_KEY_MGMT_PSK; - if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE) - return WPA_KEY_MGMT_WPA_NONE; - return 0; -} - - -static int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, - struct wpa_ie_data *data) -{ - const struct wpa_ie_hdr *hdr; - const u8 *pos; - int left; - int i, count; - - os_memset(data, 0, sizeof(*data)); - data->proto = WPA_PROTO_WPA; - data->pairwise_cipher = WPA_CIPHER_TKIP; - data->group_cipher = WPA_CIPHER_TKIP; - data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; - data->capabilities = 0; - data->pmkid = NULL; - data->num_pmkid = 0; - data->mgmt_group_cipher = 0; - - if (wpa_ie_len == 0) { - /* No WPA IE - fail silently */ - return -1; - } - - if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) { - wpa_printf(MSG_DEBUG, "%s: ie len too short %lu", - __func__, (unsigned long) wpa_ie_len); - return -1; - } - - hdr = (const struct wpa_ie_hdr *) wpa_ie; - - if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC || - hdr->len != wpa_ie_len - 2 || - RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE || - WPA_GET_LE16(hdr->version) != WPA_VERSION) { - wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", - __func__); - return -1; - } - - pos = (const u8 *) (hdr + 1); - left = wpa_ie_len - sizeof(*hdr); - - if (left >= WPA_SELECTOR_LEN) { - data->group_cipher = wpa_selector_to_bitfield(pos); - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } else if (left > 0) { - wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", - __func__, left); - return -1; - } - - if (left >= 2) { - data->pairwise_cipher = 0; - count = WPA_GET_LE16(pos); - pos += 2; - left -= 2; - if (count == 0 || left < count * WPA_SELECTOR_LEN) { - wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " - "count %u left %u", __func__, count, left); - return -1; - } - for (i = 0; i < count; i++) { - data->pairwise_cipher |= wpa_selector_to_bitfield(pos); - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } - } else if (left == 1) { - wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", - __func__); - return -1; - } - - if (left >= 2) { - data->key_mgmt = 0; - count = WPA_GET_LE16(pos); - pos += 2; - left -= 2; - if (count == 0 || left < count * WPA_SELECTOR_LEN) { - wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " - "count %u left %u", __func__, count, left); - return -1; - } - for (i = 0; i < count; i++) { - data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos); - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } - } else if (left == 1) { - wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", - __func__); - return -1; - } - - if (left >= 2) { - data->capabilities = WPA_GET_LE16(pos); - pos += 2; - left -= 2; - } - - if (left > 0) { - wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored", - __func__, left); - } - - return 0; -} - - -/** - * wpa_parse_wpa_ie - Parse WPA/RSN IE - * @wpa_ie: Pointer to WPA or RSN IE - * @wpa_ie_len: Length of the WPA/RSN IE - * @data: Pointer to data area for parsing results - * Returns: 0 on success, -1 on failure - * - * Parse the contents of WPA or RSN IE and write the parsed data into data. - */ -int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, - struct wpa_ie_data *data) -{ - if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_RSN) - return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data); - else - return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data); -} - - -static int wpa_gen_wpa_ie_wpa(u8 *wpa_ie, size_t wpa_ie_len, - int pairwise_cipher, int group_cipher, - int key_mgmt) -{ - u8 *pos; - struct wpa_ie_hdr *hdr; - - if (wpa_ie_len < sizeof(*hdr) + WPA_SELECTOR_LEN + - 2 + WPA_SELECTOR_LEN + 2 + WPA_SELECTOR_LEN) - return -1; - - hdr = (struct wpa_ie_hdr *) wpa_ie; - hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC; - RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE); - WPA_PUT_LE16(hdr->version, WPA_VERSION); - pos = (u8 *) (hdr + 1); - - if (group_cipher == WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP); - } else if (group_cipher == WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP); - } else if (group_cipher == WPA_CIPHER_WEP104) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP104); - } else if (group_cipher == WPA_CIPHER_WEP40) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP40); - } else { - wpa_printf(MSG_WARNING, "Invalid group cipher (%d).", - group_cipher); - return -1; - } - pos += WPA_SELECTOR_LEN; - - *pos++ = 1; - *pos++ = 0; - if (pairwise_cipher == WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP); - } else if (pairwise_cipher == WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP); - } else if (pairwise_cipher == WPA_CIPHER_NONE) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE); - } else { - wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).", - pairwise_cipher); - return -1; - } - pos += WPA_SELECTOR_LEN; - - *pos++ = 1; - *pos++ = 0; - if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) { - RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X); - } else if (key_mgmt == WPA_KEY_MGMT_PSK) { - RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X); - } else if (key_mgmt == WPA_KEY_MGMT_WPA_NONE) { - RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_NONE); - } else { - wpa_printf(MSG_WARNING, "Invalid key management type (%d).", - key_mgmt); - return -1; - } - pos += WPA_SELECTOR_LEN; - - /* WPA Capabilities; use defaults, so no need to include it */ - - hdr->len = (pos - wpa_ie) - 2; - - WPA_ASSERT((size_t) (pos - wpa_ie) <= wpa_ie_len); - - return pos - wpa_ie; -} - - -static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, - int pairwise_cipher, int group_cipher, - int key_mgmt, int mgmt_group_cipher, - struct wpa_sm *sm) -{ -#ifndef CONFIG_NO_WPA2 - u8 *pos; - struct rsn_ie_hdr *hdr; - u16 capab; - - if (rsn_ie_len < sizeof(*hdr) + RSN_SELECTOR_LEN + - 2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2 + - (sm->cur_pmksa ? 2 + PMKID_LEN : 0)) { - wpa_printf(MSG_DEBUG, "RSN: Too short IE buffer (%lu bytes)", - (unsigned long) rsn_ie_len); - return -1; - } - - hdr = (struct rsn_ie_hdr *) rsn_ie; - hdr->elem_id = WLAN_EID_RSN; - WPA_PUT_LE16(hdr->version, RSN_VERSION); - pos = (u8 *) (hdr + 1); - - if (group_cipher == WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - } else if (group_cipher == WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); - } else if (group_cipher == WPA_CIPHER_WEP104) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP104); - } else if (group_cipher == WPA_CIPHER_WEP40) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP40); - } else { - wpa_printf(MSG_WARNING, "Invalid group cipher (%d).", - group_cipher); - return -1; - } - pos += RSN_SELECTOR_LEN; - - *pos++ = 1; - *pos++ = 0; - if (pairwise_cipher == WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - } else if (pairwise_cipher == WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); - } else if (pairwise_cipher == WPA_CIPHER_NONE) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE); - } else { - wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).", - pairwise_cipher); - return -1; - } - pos += RSN_SELECTOR_LEN; - - *pos++ = 1; - *pos++ = 0; - if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X); - } else if (key_mgmt == WPA_KEY_MGMT_PSK) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X); -#ifdef CONFIG_IEEE80211R - } else if (key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X); - } else if (key_mgmt == WPA_KEY_MGMT_FT_PSK) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SHA256) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256); - } else if (key_mgmt == WPA_KEY_MGMT_PSK_SHA256) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256); -#endif /* CONFIG_IEEE80211W */ - } else { - wpa_printf(MSG_WARNING, "Invalid key management type (%d).", - key_mgmt); - return -1; - } - pos += RSN_SELECTOR_LEN; - - /* RSN Capabilities */ - capab = 0; -#ifdef CONFIG_IEEE80211W - if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) - capab |= WPA_CAPABILITY_MFPC; -#endif /* CONFIG_IEEE80211W */ - WPA_PUT_LE16(pos, capab); - pos += 2; - - if (sm->cur_pmksa) { - /* PMKID Count (2 octets, little endian) */ - *pos++ = 1; - *pos++ = 0; - /* PMKID */ - os_memcpy(pos, sm->cur_pmksa->pmkid, PMKID_LEN); - pos += PMKID_LEN; - } - -#ifdef CONFIG_IEEE80211W - if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) { - if (!sm->cur_pmksa) { - /* PMKID Count */ - WPA_PUT_LE16(pos, 0); - pos += 2; - } - - /* Management Group Cipher Suite */ - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); - pos += RSN_SELECTOR_LEN; - } -#endif /* CONFIG_IEEE80211W */ - - hdr->len = (pos - rsn_ie) - 2; - - WPA_ASSERT((size_t) (pos - rsn_ie) <= rsn_ie_len); - - return pos - rsn_ie; -#else /* CONFIG_NO_WPA2 */ - return -1; -#endif /* CONFIG_NO_WPA2 */ -} - - -/** - * wpa_gen_wpa_ie - Generate WPA/RSN IE based on current security policy - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @wpa_ie: Pointer to memory area for the generated WPA/RSN IE - * @wpa_ie_len: Maximum length of the generated WPA/RSN IE - * Returns: Length of the generated WPA/RSN IE or -1 on failure - */ -int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len) -{ - if (sm->proto == WPA_PROTO_RSN) - return wpa_gen_wpa_ie_rsn(wpa_ie, wpa_ie_len, - sm->pairwise_cipher, - sm->group_cipher, - sm->key_mgmt, sm->mgmt_group_cipher, - sm); - else - return wpa_gen_wpa_ie_wpa(wpa_ie, wpa_ie_len, - sm->pairwise_cipher, - sm->group_cipher, - sm->key_mgmt); -} - - -/** - * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs - * @pos: Pointer to the IE header - * @end: Pointer to the end of the Key Data buffer - * @ie: Pointer to parsed IE data - * Returns: 0 on success, 1 if end mark is found, -1 on failure - */ -static int wpa_parse_generic(const u8 *pos, const u8 *end, - struct wpa_eapol_ie_parse *ie) -{ - if (pos[1] == 0) - return 1; - - if (pos[1] >= 6 && - RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE && - pos[2 + WPA_SELECTOR_LEN] == 1 && - pos[2 + WPA_SELECTOR_LEN + 1] == 0) { - ie->wpa_ie = pos; - ie->wpa_ie_len = pos[1] + 2; - return 0; - } - - if (pos + 1 + RSN_SELECTOR_LEN < end && - pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { - ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { - ie->gtk = pos + 2 + RSN_SELECTOR_LEN; - ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) { - ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN; - ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN; - 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; - 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; - 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; - 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; - return 0; - } -#endif /* CONFIG_PEERKEY */ - -#ifdef CONFIG_IEEE80211W - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) { - ie->igtk = pos + 2 + RSN_SELECTOR_LEN; - ie->igtk_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } -#endif /* CONFIG_IEEE80211W */ - - return 0; -} - - -/** - * wpa_supplicant_parse_ies - Parse EAPOL-Key Key Data IEs - * @buf: Pointer to the Key Data buffer - * @len: Key Data Length - * @ie: Pointer to parsed IE data - * Returns: 0 on success, -1 on failure - */ -int wpa_supplicant_parse_ies(const u8 *buf, size_t len, - struct wpa_eapol_ie_parse *ie) -{ - const u8 *pos, *end; - int ret = 0; - - os_memset(ie, 0, sizeof(*ie)); - for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) { - if (pos[0] == 0xdd && - ((pos == buf + len - 1) || pos[1] == 0)) { - /* Ignore padding */ - break; - } - if (pos + 2 + pos[1] > end) { - wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data " - "underflow (ie=%d len=%d pos=%d)", - pos[0], pos[1], (int) (pos - buf)); - wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data", - buf, len); - ret = -1; - break; - } - if (*pos == WLAN_EID_RSN) { - ie->rsn_ie = pos; - ie->rsn_ie_len = pos[1] + 2; -#ifdef CONFIG_IEEE80211R - } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) { - ie->mdie = pos; - ie->mdie_len = pos[1] + 2; -#endif /* CONFIG_IEEE80211R */ - } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { - ret = wpa_parse_generic(pos, end, ie); - if (ret < 0) - break; - if (ret > 0) { - ret = 0; - break; - } - } else { - wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key " - "Key Data IE", pos, 2 + pos[1]); - } - } - - return ret; -} diff --git a/contrib/hostapd/src/rsn_supp/wpa_ie.h b/contrib/hostapd/src/rsn_supp/wpa_ie.h deleted file mode 100644 index 17e375aa21..0000000000 --- a/contrib/hostapd/src/rsn_supp/wpa_ie.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * wpa_supplicant - WPA/RSN IE and KDE definitions - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPA_IE_H -#define WPA_IE_H - -struct wpa_eapol_ie_parse { - const u8 *wpa_ie; - size_t wpa_ie_len; - const u8 *rsn_ie; - size_t rsn_ie_len; - const u8 *pmkid; - const u8 *gtk; - 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 - const u8 *mdie; - size_t mdie_len; -#endif /* CONFIG_IEEE80211R */ -}; - -int wpa_supplicant_parse_ies(const u8 *buf, size_t len, - struct wpa_eapol_ie_parse *ie); -int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len); - -#endif /* WPA_IE_H */ diff --git a/contrib/hostapd/src/tls/asn1.c b/contrib/hostapd/src/tls/asn1.c deleted file mode 100644 index 96bc1ac78a..0000000000 --- a/contrib/hostapd/src/tls/asn1.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * ASN.1 DER parsing - * Copyright (c) 2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" - -#ifdef CONFIG_INTERNAL_X509 - -#include "asn1.h" - -int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr) -{ - const u8 *pos, *end; - u8 tmp; - - os_memset(hdr, 0, sizeof(*hdr)); - pos = buf; - end = buf + len; - - hdr->identifier = *pos++; - hdr->class = hdr->identifier >> 6; - hdr->constructed = !!(hdr->identifier & (1 << 5)); - - if ((hdr->identifier & 0x1f) == 0x1f) { - hdr->tag = 0; - do { - if (pos >= end) { - wpa_printf(MSG_DEBUG, "ASN.1: Identifier " - "underflow"); - return -1; - } - tmp = *pos++; - wpa_printf(MSG_MSGDUMP, "ASN.1: Extended tag data: " - "0x%02x", tmp); - hdr->tag = (hdr->tag << 7) | (tmp & 0x7f); - } while (tmp & 0x80); - } else - hdr->tag = hdr->identifier & 0x1f; - - tmp = *pos++; - if (tmp & 0x80) { - if (tmp == 0xff) { - wpa_printf(MSG_DEBUG, "ASN.1: Reserved length " - "value 0xff used"); - return -1; - } - tmp &= 0x7f; /* number of subsequent octets */ - hdr->length = 0; - if (tmp > 4) { - wpa_printf(MSG_DEBUG, "ASN.1: Too long length field"); - return -1; - } - while (tmp--) { - if (pos >= end) { - wpa_printf(MSG_DEBUG, "ASN.1: Length " - "underflow"); - return -1; - } - hdr->length = (hdr->length << 8) | *pos++; - } - } else { - /* Short form - length 0..127 in one octet */ - hdr->length = tmp; - } - - if (end < pos || hdr->length > (unsigned int) (end - pos)) { - wpa_printf(MSG_DEBUG, "ASN.1: Contents underflow"); - return -1; - } - - hdr->payload = pos; - return 0; -} - - -int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid, - const u8 **next) -{ - struct asn1_hdr hdr; - const u8 *pos, *end; - unsigned long val; - u8 tmp; - - os_memset(oid, 0, sizeof(*oid)); - - if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0) - return -1; - - if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OID) { - wpa_printf(MSG_DEBUG, "ASN.1: Expected OID - found class %d " - "tag 0x%x", hdr.class, hdr.tag); - return -1; - } - - pos = hdr.payload; - end = hdr.payload + hdr.length; - *next = end; - - while (pos < end) { - val = 0; - - do { - if (pos >= end) - return -1; - tmp = *pos++; - val = (val << 7) | (tmp & 0x7f); - } while (tmp & 0x80); - - if (oid->len >= ASN1_MAX_OID_LEN) { - wpa_printf(MSG_DEBUG, "ASN.1: Too long OID value"); - return -1; - } - if (oid->len == 0) { - /* - * The first octet encodes the first two object - * identifier components in (X*40) + Y formula. - * X = 0..2. - */ - oid->oid[0] = val / 40; - if (oid->oid[0] > 2) - oid->oid[0] = 2; - oid->oid[1] = val - oid->oid[0] * 40; - oid->len = 2; - } else - oid->oid[oid->len++] = val; - } - - return 0; -} - - -void asn1_oid_to_str(struct asn1_oid *oid, char *buf, size_t len) -{ - char *pos = buf; - size_t i; - int ret; - - if (len == 0) - return; - - buf[0] = '\0'; - - for (i = 0; i < oid->len; i++) { - ret = os_snprintf(pos, buf + len - pos, - "%s%lu", - i == 0 ? "" : ".", oid->oid[i]); - if (ret < 0 || ret >= buf + len - pos) - break; - pos += ret; - } - buf[len - 1] = '\0'; -} - - -static u8 rotate_bits(u8 octet) -{ - int i; - u8 res; - - res = 0; - for (i = 0; i < 8; i++) { - res <<= 1; - if (octet & 1) - res |= 1; - octet >>= 1; - } - - return res; -} - - -unsigned long asn1_bit_string_to_long(const u8 *buf, size_t len) -{ - unsigned long val = 0; - const u8 *pos = buf; - - /* BER requires that unused bits are zero, so we can ignore the number - * of unused bits */ - pos++; - - if (len >= 2) - val |= rotate_bits(*pos++); - if (len >= 3) - val |= ((unsigned long) rotate_bits(*pos++)) << 8; - if (len >= 4) - val |= ((unsigned long) rotate_bits(*pos++)) << 16; - if (len >= 5) - val |= ((unsigned long) rotate_bits(*pos++)) << 24; - if (len >= 6) - wpa_printf(MSG_DEBUG, "X509: %s - some bits ignored " - "(BIT STRING length %lu)", - __func__, (unsigned long) len); - - return val; -} - -#endif /* CONFIG_INTERNAL_X509 */ diff --git a/contrib/hostapd/src/tls/asn1.h b/contrib/hostapd/src/tls/asn1.h deleted file mode 100644 index c02ada8278..0000000000 --- a/contrib/hostapd/src/tls/asn1.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * ASN.1 DER parsing - * Copyright (c) 2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef ASN1_H -#define ASN1_H - -#define ASN1_TAG_EOC 0x00 /* not used with DER */ -#define ASN1_TAG_BOOLEAN 0x01 -#define ASN1_TAG_INTEGER 0x02 -#define ASN1_TAG_BITSTRING 0x03 -#define ASN1_TAG_OCTETSTRING 0x04 -#define ASN1_TAG_NULL 0x05 -#define ASN1_TAG_OID 0x06 -#define ASN1_TAG_OBJECT_DESCRIPTOR 0x07 /* not yet parsed */ -#define ASN1_TAG_EXTERNAL 0x08 /* not yet parsed */ -#define ASN1_TAG_REAL 0x09 /* not yet parsed */ -#define ASN1_TAG_ENUMERATED 0x0A /* not yet parsed */ -#define ASN1_TAG_UTF8STRING 0x0C /* not yet parsed */ -#define ANS1_TAG_RELATIVE_OID 0x0D -#define ASN1_TAG_SEQUENCE 0x10 /* shall be constructed */ -#define ASN1_TAG_SET 0x11 -#define ASN1_TAG_NUMERICSTRING 0x12 /* not yet parsed */ -#define ASN1_TAG_PRINTABLESTRING 0x13 -#define ASN1_TAG_TG1STRING 0x14 /* not yet parsed */ -#define ASN1_TAG_VIDEOTEXSTRING 0x15 /* not yet parsed */ -#define ASN1_TAG_IA5STRING 0x16 -#define ASN1_TAG_UTCTIME 0x17 -#define ASN1_TAG_GENERALIZEDTIME 0x18 /* not yet parsed */ -#define ASN1_TAG_GRAPHICSTRING 0x19 /* not yet parsed */ -#define ASN1_TAG_VISIBLESTRING 0x1A -#define ASN1_TAG_GENERALSTRING 0x1B /* not yet parsed */ -#define ASN1_TAG_UNIVERSALSTRING 0x1C /* not yet parsed */ -#define ASN1_TAG_BMPSTRING 0x1D /* not yet parsed */ - -#define ASN1_CLASS_UNIVERSAL 0 -#define ASN1_CLASS_APPLICATION 1 -#define ASN1_CLASS_CONTEXT_SPECIFIC 2 -#define ASN1_CLASS_PRIVATE 3 - - -struct asn1_hdr { - const u8 *payload; - u8 identifier, class, constructed; - unsigned int tag, length; -}; - -#define ASN1_MAX_OID_LEN 20 -struct asn1_oid { - unsigned long oid[ASN1_MAX_OID_LEN]; - size_t len; -}; - - -int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr); -int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid, - const u8 **next); -void asn1_oid_to_str(struct asn1_oid *oid, char *buf, size_t len); -unsigned long asn1_bit_string_to_long(const u8 *buf, size_t len); - -#endif /* ASN1_H */ diff --git a/contrib/hostapd/src/tls/asn1_test.c b/contrib/hostapd/src/tls/asn1_test.c deleted file mode 100644 index a5c7753530..0000000000 --- a/contrib/hostapd/src/tls/asn1_test.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Testing tool for ASN.1/X.509v3 routines - * Copyright (c) 2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "asn1.h" -#include "x509v3.h" - -extern int wpa_debug_level; - - -static const char * asn1_class_str(int class) -{ - switch (class) { - case ASN1_CLASS_UNIVERSAL: - return "Universal"; - case ASN1_CLASS_APPLICATION: - return "Application"; - case ASN1_CLASS_CONTEXT_SPECIFIC: - return "Context-specific"; - case ASN1_CLASS_PRIVATE: - return "Private"; - default: - return "?"; - } -} - - -int asn1_parse(const u8 *buf, size_t len, int level) -{ - const u8 *pos, *prev, *end; - char prefix[10], str[100]; - int _level; - struct asn1_hdr hdr; - struct asn1_oid oid; - u8 tmp; - - _level = level; - if ((size_t) _level > sizeof(prefix) - 1) - _level = sizeof(prefix) - 1; - memset(prefix, ' ', _level); - prefix[_level] = '\0'; - - pos = buf; - end = buf + len; - - while (pos < end) { - if (asn1_get_next(pos, end - pos, &hdr) < 0) - return -1; - - prev = pos; - pos = hdr.payload; - - wpa_printf(MSG_MSGDUMP, "ASN.1:%s Class %d(%s) P/C %d(%s) " - "Tag %u Length %u", - prefix, hdr.class, asn1_class_str(hdr.class), - hdr.constructed, - hdr.constructed ? "Constructed" : "Primitive", - hdr.tag, hdr.length); - - if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC && - hdr.constructed) { - if (asn1_parse(pos, hdr.length, level + 1) < 0) - return -1; - pos += hdr.length; - } - - if (hdr.class != ASN1_CLASS_UNIVERSAL) - continue; - - switch (hdr.tag) { - case ASN1_TAG_EOC: - if (hdr.length) { - wpa_printf(MSG_DEBUG, "ASN.1: Non-zero " - "end-of-contents length (%u)", - hdr.length); - return -1; - } - wpa_printf(MSG_MSGDUMP, "ASN.1:%s EOC", prefix); - break; - case ASN1_TAG_BOOLEAN: - if (hdr.length != 1) { - wpa_printf(MSG_DEBUG, "ASN.1: Unexpected " - "Boolean length (%u)", hdr.length); - return -1; - } - tmp = *pos++; - wpa_printf(MSG_MSGDUMP, "ASN.1:%s Boolean %s", - prefix, tmp ? "TRUE" : "FALSE"); - break; - case ASN1_TAG_INTEGER: - wpa_hexdump(MSG_MSGDUMP, "ASN.1: INTEGER", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_BITSTRING: - wpa_hexdump(MSG_MSGDUMP, "ASN.1: BitString", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_OCTETSTRING: - wpa_hexdump(MSG_MSGDUMP, "ASN.1: OctetString", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_NULL: - if (hdr.length) { - wpa_printf(MSG_DEBUG, "ASN.1: Non-zero Null " - "length (%u)", hdr.length); - return -1; - } - wpa_printf(MSG_MSGDUMP, "ASN.1:%s Null", prefix); - break; - case ASN1_TAG_OID: - if (asn1_get_oid(prev, end - prev, &oid, &prev) < 0) { - wpa_printf(MSG_DEBUG, "ASN.1: Invalid OID"); - return -1; - } - asn1_oid_to_str(&oid, str, sizeof(str)); - wpa_printf(MSG_DEBUG, "ASN.1:%s OID %s", prefix, str); - pos += hdr.length; - break; - case ANS1_TAG_RELATIVE_OID: - wpa_hexdump(MSG_MSGDUMP, "ASN.1: Relative OID", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_SEQUENCE: - wpa_printf(MSG_MSGDUMP, "ASN.1:%s SEQUENCE", prefix); - if (asn1_parse(pos, hdr.length, level + 1) < 0) - return -1; - pos += hdr.length; - break; - case ASN1_TAG_SET: - wpa_printf(MSG_MSGDUMP, "ASN.1:%s SET", prefix); - if (asn1_parse(pos, hdr.length, level + 1) < 0) - return -1; - pos += hdr.length; - break; - case ASN1_TAG_PRINTABLESTRING: - wpa_hexdump_ascii(MSG_MSGDUMP, - "ASN.1: PrintableString", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_IA5STRING: - wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: IA5String", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_UTCTIME: - wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: UTCTIME", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_VISIBLESTRING: - wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: VisibleString", - pos, hdr.length); - pos += hdr.length; - break; - default: - wpa_printf(MSG_DEBUG, "ASN.1: Unknown tag %d", - hdr.tag); - return -1; - } - } - - return 0; -} - - -int main(int argc, char *argv[]) -{ - FILE *f; - u8 buf[3000]; - size_t len; - struct x509_certificate *cert; - - wpa_debug_level = 0; - - f = fopen(argv[1], "rb"); - if (f == NULL) - return -1; - len = fread(buf, 1, sizeof(buf), f); - fclose(f); - - if (asn1_parse(buf, len, 0) < 0) - printf("Failed to parse DER ASN.1\n"); - - printf("\n\n"); - - cert = x509_certificate_parse(buf, len); - if (cert == NULL) - printf("Failed to parse X.509 certificate\n"); - x509_certificate_free(cert); - - return 0; -} diff --git a/contrib/hostapd/src/tls/bignum.c b/contrib/hostapd/src/tls/bignum.c deleted file mode 100644 index 5c0fc62ede..0000000000 --- a/contrib/hostapd/src/tls/bignum.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Big number math - * Copyright (c) 2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "bignum.h" - -#ifdef CONFIG_INTERNAL_LIBTOMMATH -#include "libtommath.c" -#else /* CONFIG_INTERNAL_LIBTOMMATH */ -#include -#endif /* CONFIG_INTERNAL_LIBTOMMATH */ - - -/* - * The current version is just a wrapper for LibTomMath library, so - * struct bignum is just typecast to mp_int. - */ - -/** - * bignum_init - Allocate memory for bignum - * Returns: Pointer to allocated bignum or %NULL on failure - */ -struct bignum * bignum_init(void) -{ - struct bignum *n = os_zalloc(sizeof(mp_int)); - if (n == NULL) - return NULL; - if (mp_init((mp_int *) n) != MP_OKAY) { - os_free(n); - n = NULL; - } - return n; -} - - -/** - * bignum_deinit - Free bignum - * @n: Bignum from bignum_init() - */ -void bignum_deinit(struct bignum *n) -{ - if (n) { - mp_clear((mp_int *) n); - os_free(n); - } -} - - -/** - * bignum_get_unsigned_bin - Get length of bignum as an unsigned binary buffer - * @n: Bignum from bignum_init() - * Returns: Length of n if written to a binary buffer - */ -size_t bignum_get_unsigned_bin_len(struct bignum *n) -{ - return mp_unsigned_bin_size((mp_int *) n); -} - - -/** - * bignum_get_unsigned_bin - Set binary buffer to unsigned bignum - * @n: Bignum from bignum_init() - * @buf: Buffer for the binary number - * @len: Length of the buffer, can be %NULL if buffer is known to be long - * enough. Set to used buffer length on success if not %NULL. - * Returns: 0 on success, -1 on failure - */ -int bignum_get_unsigned_bin(const struct bignum *n, u8 *buf, size_t *len) -{ - size_t need = mp_unsigned_bin_size((mp_int *) n); - if (len && need > *len) { - *len = need; - return -1; - } - if (mp_to_unsigned_bin((mp_int *) n, buf) != MP_OKAY) { - wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); - return -1; - } - if (len) - *len = need; - return 0; -} - - -/** - * bignum_set_unsigned_bin - Set bignum based on unsigned binary buffer - * @n: Bignum from bignum_init(); to be set to the given value - * @buf: Buffer with unsigned binary value - * @len: Length of buf in octets - * Returns: 0 on success, -1 on failure - */ -int bignum_set_unsigned_bin(struct bignum *n, const u8 *buf, size_t len) -{ - if (mp_read_unsigned_bin((mp_int *) n, (u8 *) buf, len) != MP_OKAY) { - wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); - return -1; - } - return 0; -} - - -/** - * bignum_cmp - Signed comparison - * @a: Bignum from bignum_init() - * @b: Bignum from bignum_init() - * Returns: 0 on success, -1 on failure - */ -int bignum_cmp(const struct bignum *a, const struct bignum *b) -{ - return mp_cmp((mp_int *) a, (mp_int *) b); -} - - -/** - * bignum_cmd_d - Compare bignum to standard integer - * @a: Bignum from bignum_init() - * @b: Small integer - * Returns: 0 on success, -1 on failure - */ -int bignum_cmp_d(const struct bignum *a, unsigned long b) -{ - return mp_cmp_d((mp_int *) a, b); -} - - -/** - * bignum_add - c = a + b - * @a: Bignum from bignum_init() - * @b: Bignum from bignum_init() - * @c: Bignum from bignum_init(); used to store the result of a + b - * Returns: 0 on success, -1 on failure - */ -int bignum_add(const struct bignum *a, const struct bignum *b, - struct bignum *c) -{ - if (mp_add((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) { - wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); - return -1; - } - return 0; -} - - -/** - * bignum_sub - c = a - b - * @a: Bignum from bignum_init() - * @b: Bignum from bignum_init() - * @c: Bignum from bignum_init(); used to store the result of a - b - * Returns: 0 on success, -1 on failure - */ -int bignum_sub(const struct bignum *a, const struct bignum *b, - struct bignum *c) -{ - if (mp_sub((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) { - wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); - return -1; - } - return 0; -} - - -/** - * bignum_mul - c = a * b - * @a: Bignum from bignum_init() - * @b: Bignum from bignum_init() - * @c: Bignum from bignum_init(); used to store the result of a * b - * Returns: 0 on success, -1 on failure - */ -int bignum_mul(const struct bignum *a, const struct bignum *b, - struct bignum *c) -{ - if (mp_mul((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) { - wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); - return -1; - } - return 0; -} - - -/** - * bignum_mulmod - d = a * b (mod c) - * @a: Bignum from bignum_init() - * @b: Bignum from bignum_init() - * @c: Bignum from bignum_init(); modulus - * @d: Bignum from bignum_init(); used to store the result of a * b (mod c) - * Returns: 0 on success, -1 on failure - */ -int bignum_mulmod(const struct bignum *a, const struct bignum *b, - const struct bignum *c, struct bignum *d) -{ - if (mp_mulmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d) - != MP_OKAY) { - wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); - return -1; - } - return 0; -} - - -/** - * bignum_exptmod - Modular exponentiation: d = a^b (mod c) - * @a: Bignum from bignum_init(); base - * @b: Bignum from bignum_init(); exponent - * @c: Bignum from bignum_init(); modulus - * @d: Bignum from bignum_init(); used to store the result of a^b (mod c) - * Returns: 0 on success, -1 on failure - */ -int bignum_exptmod(const struct bignum *a, const struct bignum *b, - const struct bignum *c, struct bignum *d) -{ - if (mp_exptmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d) - != MP_OKAY) { - wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); - return -1; - } - return 0; -} diff --git a/contrib/hostapd/src/tls/bignum.h b/contrib/hostapd/src/tls/bignum.h deleted file mode 100644 index f25e26783a..0000000000 --- a/contrib/hostapd/src/tls/bignum.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Big number math - * Copyright (c) 2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef BIGNUM_H -#define BIGNUM_H - -struct bignum; - -struct bignum * bignum_init(void); -void bignum_deinit(struct bignum *n); -size_t bignum_get_unsigned_bin_len(struct bignum *n); -int bignum_get_unsigned_bin(const struct bignum *n, u8 *buf, size_t *len); -int bignum_set_unsigned_bin(struct bignum *n, const u8 *buf, size_t len); -int bignum_cmp(const struct bignum *a, const struct bignum *b); -int bignum_cmp_d(const struct bignum *a, unsigned long b); -int bignum_add(const struct bignum *a, const struct bignum *b, - struct bignum *c); -int bignum_sub(const struct bignum *a, const struct bignum *b, - struct bignum *c); -int bignum_mul(const struct bignum *a, const struct bignum *b, - struct bignum *c); -int bignum_mulmod(const struct bignum *a, const struct bignum *b, - const struct bignum *c, struct bignum *d); -int bignum_exptmod(const struct bignum *a, const struct bignum *b, - const struct bignum *c, struct bignum *d); - -#endif /* BIGNUM_H */ diff --git a/contrib/hostapd/src/tls/libtommath.c b/contrib/hostapd/src/tls/libtommath.c deleted file mode 100644 index 137426421c..0000000000 --- a/contrib/hostapd/src/tls/libtommath.c +++ /dev/null @@ -1,3381 +0,0 @@ -/* - * Minimal code for RSA support from LibTomMath 0.41 - * http://libtom.org/ - * http://libtom.org/files/ltm-0.41.tar.bz2 - * This library was released in public domain by Tom St Denis. - * - * The combination in this file may not use all of the optimized algorithms - * from LibTomMath and may be considerable slower than the LibTomMath with its - * default settings. The main purpose of having this version here is to make it - * easier to build bignum.c wrapper without having to install and build an - * external library. - * - * If CONFIG_INTERNAL_LIBTOMMATH is defined, bignum.c includes this - * libtommath.c file instead of using the external LibTomMath library. - */ - -#ifndef CHAR_BIT -#define CHAR_BIT 8 -#endif - -#define BN_MP_INVMOD_C -#define BN_S_MP_EXPTMOD_C /* Note: #undef in tommath_superclass.h; this would - * require BN_MP_EXPTMOD_FAST_C instead */ -#define BN_S_MP_MUL_DIGS_C -#define BN_MP_INVMOD_SLOW_C -#define BN_S_MP_SQR_C -#define BN_S_MP_MUL_HIGH_DIGS_C /* Note: #undef in tommath_superclass.h; this - * would require other than mp_reduce */ - -#ifdef LTM_FAST - -/* Use faster div at the cost of about 1 kB */ -#define BN_MP_MUL_D_C - -/* Include faster exptmod (Montgomery) at the cost of about 2.5 kB in code */ -#define BN_MP_EXPTMOD_FAST_C -#define BN_MP_MONTGOMERY_SETUP_C -#define BN_FAST_MP_MONTGOMERY_REDUCE_C -#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C -#define BN_MP_MUL_2_C - -/* Include faster sqr at the cost of about 0.5 kB in code */ -#define BN_FAST_S_MP_SQR_C - -#else /* LTM_FAST */ - -#define BN_MP_DIV_SMALL -#define BN_MP_INIT_MULTI_C -#define BN_MP_CLEAR_MULTI_C -#define BN_MP_ABS_C -#endif /* LTM_FAST */ - -/* Current uses do not require support for negative exponent in exptmod, so we - * can save about 1.5 kB in leaving out invmod. */ -#define LTM_NO_NEG_EXP - -/* from tommath.h */ - -#ifndef MIN - #define MIN(x,y) ((x)<(y)?(x):(y)) -#endif - -#ifndef MAX - #define MAX(x,y) ((x)>(y)?(x):(y)) -#endif - -#define OPT_CAST(x) - -typedef unsigned long mp_digit; -typedef u64 mp_word; - -#define DIGIT_BIT 28 -#define MP_28BIT - - -#define XMALLOC os_malloc -#define XFREE os_free -#define XREALLOC os_realloc - - -#define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1)) - -#define MP_LT -1 /* less than */ -#define MP_EQ 0 /* equal to */ -#define MP_GT 1 /* greater than */ - -#define MP_ZPOS 0 /* positive integer */ -#define MP_NEG 1 /* negative */ - -#define MP_OKAY 0 /* ok result */ -#define MP_MEM -2 /* out of mem */ -#define MP_VAL -3 /* invalid input */ - -#define MP_YES 1 /* yes response */ -#define MP_NO 0 /* no response */ - -typedef int mp_err; - -/* define this to use lower memory usage routines (exptmods mostly) */ -#define MP_LOW_MEM - -/* default precision */ -#ifndef MP_PREC - #ifndef MP_LOW_MEM - #define MP_PREC 32 /* default digits of precision */ - #else - #define MP_PREC 8 /* default digits of precision */ - #endif -#endif - -/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */ -#define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1)) - -/* the infamous mp_int structure */ -typedef struct { - int used, alloc, sign; - mp_digit *dp; -} mp_int; - - -/* ---> Basic Manipulations <--- */ -#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO) -#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO) -#define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO) - - -/* prototypes for copied functions */ -#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1) -static int s_mp_exptmod(mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode); -static int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs); -static int s_mp_sqr(mp_int * a, mp_int * b); -static int s_mp_mul_high_digs(mp_int * a, mp_int * b, mp_int * c, int digs); - -static int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs); - -#ifdef BN_MP_INIT_MULTI_C -static int mp_init_multi(mp_int *mp, ...); -#endif -#ifdef BN_MP_CLEAR_MULTI_C -static void mp_clear_multi(mp_int *mp, ...); -#endif -static int mp_lshd(mp_int * a, int b); -static void mp_set(mp_int * a, mp_digit b); -static void mp_clamp(mp_int * a); -static void mp_exch(mp_int * a, mp_int * b); -static void mp_rshd(mp_int * a, int b); -static void mp_zero(mp_int * a); -static int mp_mod_2d(mp_int * a, int b, mp_int * c); -static int mp_div_2d(mp_int * a, int b, mp_int * c, mp_int * d); -static int mp_init_copy(mp_int * a, mp_int * b); -static int mp_mul_2d(mp_int * a, int b, mp_int * c); -#ifndef LTM_NO_NEG_EXP -static int mp_div_2(mp_int * a, mp_int * b); -static int mp_invmod(mp_int * a, mp_int * b, mp_int * c); -static int mp_invmod_slow(mp_int * a, mp_int * b, mp_int * c); -#endif /* LTM_NO_NEG_EXP */ -static int mp_copy(mp_int * a, mp_int * b); -static int mp_count_bits(mp_int * a); -static int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d); -static int mp_mod(mp_int * a, mp_int * b, mp_int * c); -static int mp_grow(mp_int * a, int size); -static int mp_cmp_mag(mp_int * a, mp_int * b); -#ifdef BN_MP_ABS_C -static int mp_abs(mp_int * a, mp_int * b); -#endif -static int mp_sqr(mp_int * a, mp_int * b); -static int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d); -static int mp_reduce_2k_setup_l(mp_int *a, mp_int *d); -static int mp_2expt(mp_int * a, int b); -static int mp_reduce_setup(mp_int * a, mp_int * b); -static int mp_reduce(mp_int * x, mp_int * m, mp_int * mu); -static int mp_init_size(mp_int * a, int size); -#ifdef BN_MP_EXPTMOD_FAST_C -static int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode); -#endif /* BN_MP_EXPTMOD_FAST_C */ -#ifdef BN_FAST_S_MP_SQR_C -static int fast_s_mp_sqr (mp_int * a, mp_int * b); -#endif /* BN_FAST_S_MP_SQR_C */ -#ifdef BN_MP_MUL_D_C -static int mp_mul_d (mp_int * a, mp_digit b, mp_int * c); -#endif /* BN_MP_MUL_D_C */ - - - -/* functions from bn_.c */ - - -/* reverse an array, used for radix code */ -static void bn_reverse (unsigned char *s, int len) -{ - int ix, iy; - unsigned char t; - - ix = 0; - iy = len - 1; - while (ix < iy) { - t = s[ix]; - s[ix] = s[iy]; - s[iy] = t; - ++ix; - --iy; - } -} - - -/* low level addition, based on HAC pp.594, Algorithm 14.7 */ -static int s_mp_add (mp_int * a, mp_int * b, mp_int * c) -{ - mp_int *x; - int olduse, res, min, max; - - /* find sizes, we let |a| <= |b| which means we have to sort - * them. "x" will point to the input with the most digits - */ - if (a->used > b->used) { - min = b->used; - max = a->used; - x = a; - } else { - min = a->used; - max = b->used; - x = b; - } - - /* init result */ - if (c->alloc < max + 1) { - if ((res = mp_grow (c, max + 1)) != MP_OKAY) { - return res; - } - } - - /* get old used digit count and set new one */ - olduse = c->used; - c->used = max + 1; - - { - register mp_digit u, *tmpa, *tmpb, *tmpc; - register int i; - - /* alias for digit pointers */ - - /* first input */ - tmpa = a->dp; - - /* second input */ - tmpb = b->dp; - - /* destination */ - tmpc = c->dp; - - /* zero the carry */ - u = 0; - for (i = 0; i < min; i++) { - /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */ - *tmpc = *tmpa++ + *tmpb++ + u; - - /* U = carry bit of T[i] */ - u = *tmpc >> ((mp_digit)DIGIT_BIT); - - /* take away carry bit from T[i] */ - *tmpc++ &= MP_MASK; - } - - /* now copy higher words if any, that is in A+B - * if A or B has more digits add those in - */ - if (min != max) { - for (; i < max; i++) { - /* T[i] = X[i] + U */ - *tmpc = x->dp[i] + u; - - /* U = carry bit of T[i] */ - u = *tmpc >> ((mp_digit)DIGIT_BIT); - - /* take away carry bit from T[i] */ - *tmpc++ &= MP_MASK; - } - } - - /* add carry */ - *tmpc++ = u; - - /* clear digits above oldused */ - for (i = c->used; i < olduse; i++) { - *tmpc++ = 0; - } - } - - mp_clamp (c); - return MP_OKAY; -} - - -/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */ -static int s_mp_sub (mp_int * a, mp_int * b, mp_int * c) -{ - int olduse, res, min, max; - - /* find sizes */ - min = b->used; - max = a->used; - - /* init result */ - if (c->alloc < max) { - if ((res = mp_grow (c, max)) != MP_OKAY) { - return res; - } - } - olduse = c->used; - c->used = max; - - { - register mp_digit u, *tmpa, *tmpb, *tmpc; - register int i; - - /* alias for digit pointers */ - tmpa = a->dp; - tmpb = b->dp; - tmpc = c->dp; - - /* set carry to zero */ - u = 0; - for (i = 0; i < min; i++) { - /* T[i] = A[i] - B[i] - U */ - *tmpc = *tmpa++ - *tmpb++ - u; - - /* U = carry bit of T[i] - * Note this saves performing an AND operation since - * if a carry does occur it will propagate all the way to the - * MSB. As a result a single shift is enough to get the carry - */ - u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); - - /* Clear carry from T[i] */ - *tmpc++ &= MP_MASK; - } - - /* now copy higher words if any, e.g. if A has more digits than B */ - for (; i < max; i++) { - /* T[i] = A[i] - U */ - *tmpc = *tmpa++ - u; - - /* U = carry bit of T[i] */ - u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); - - /* Clear carry from T[i] */ - *tmpc++ &= MP_MASK; - } - - /* clear digits above used (since we may not have grown result above) */ - for (i = c->used; i < olduse; i++) { - *tmpc++ = 0; - } - } - - mp_clamp (c); - return MP_OKAY; -} - - -/* init a new mp_int */ -static int mp_init (mp_int * a) -{ - int i; - - /* allocate memory required and clear it */ - a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC); - if (a->dp == NULL) { - return MP_MEM; - } - - /* set the digits to zero */ - for (i = 0; i < MP_PREC; i++) { - a->dp[i] = 0; - } - - /* set the used to zero, allocated digits to the default precision - * and sign to positive */ - a->used = 0; - a->alloc = MP_PREC; - a->sign = MP_ZPOS; - - return MP_OKAY; -} - - -/* clear one (frees) */ -static void mp_clear (mp_int * a) -{ - int i; - - /* only do anything if a hasn't been freed previously */ - if (a->dp != NULL) { - /* first zero the digits */ - for (i = 0; i < a->used; i++) { - a->dp[i] = 0; - } - - /* free ram */ - XFREE(a->dp); - - /* reset members to make debugging easier */ - a->dp = NULL; - a->alloc = a->used = 0; - a->sign = MP_ZPOS; - } -} - - -/* high level addition (handles signs) */ -static int mp_add (mp_int * a, mp_int * b, mp_int * c) -{ - int sa, sb, res; - - /* get sign of both inputs */ - sa = a->sign; - sb = b->sign; - - /* handle two cases, not four */ - if (sa == sb) { - /* both positive or both negative */ - /* add their magnitudes, copy the sign */ - c->sign = sa; - res = s_mp_add (a, b, c); - } else { - /* one positive, the other negative */ - /* subtract the one with the greater magnitude from */ - /* the one of the lesser magnitude. The result gets */ - /* the sign of the one with the greater magnitude. */ - if (mp_cmp_mag (a, b) == MP_LT) { - c->sign = sb; - res = s_mp_sub (b, a, c); - } else { - c->sign = sa; - res = s_mp_sub (a, b, c); - } - } - return res; -} - - -/* high level subtraction (handles signs) */ -static int mp_sub (mp_int * a, mp_int * b, mp_int * c) -{ - int sa, sb, res; - - sa = a->sign; - sb = b->sign; - - if (sa != sb) { - /* subtract a negative from a positive, OR */ - /* subtract a positive from a negative. */ - /* In either case, ADD their magnitudes, */ - /* and use the sign of the first number. */ - c->sign = sa; - res = s_mp_add (a, b, c); - } else { - /* subtract a positive from a positive, OR */ - /* subtract a negative from a negative. */ - /* First, take the difference between their */ - /* magnitudes, then... */ - if (mp_cmp_mag (a, b) != MP_LT) { - /* Copy the sign from the first */ - c->sign = sa; - /* The first has a larger or equal magnitude */ - res = s_mp_sub (a, b, c); - } else { - /* The result has the *opposite* sign from */ - /* the first number. */ - c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS; - /* The second has a larger magnitude */ - res = s_mp_sub (b, a, c); - } - } - return res; -} - - -/* high level multiplication (handles sign) */ -static int mp_mul (mp_int * a, mp_int * b, mp_int * c) -{ - int res, neg; - neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; - - /* use Toom-Cook? */ -#ifdef BN_MP_TOOM_MUL_C - if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) { - res = mp_toom_mul(a, b, c); - } else -#endif -#ifdef BN_MP_KARATSUBA_MUL_C - /* use Karatsuba? */ - if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) { - res = mp_karatsuba_mul (a, b, c); - } else -#endif - { - /* can we use the fast multiplier? - * - * The fast multiplier can be used if the output will - * have less than MP_WARRAY digits and the number of - * digits won't affect carry propagation - */ -#ifdef BN_FAST_S_MP_MUL_DIGS_C - int digs = a->used + b->used + 1; - - if ((digs < MP_WARRAY) && - MIN(a->used, b->used) <= - (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { - res = fast_s_mp_mul_digs (a, b, c, digs); - } else -#endif -#ifdef BN_S_MP_MUL_DIGS_C - res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */ -#else -#error mp_mul could fail - res = MP_VAL; -#endif - - } - c->sign = (c->used > 0) ? neg : MP_ZPOS; - return res; -} - - -/* d = a * b (mod c) */ -static int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) -{ - int res; - mp_int t; - - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } - - if ((res = mp_mul (a, b, &t)) != MP_OKAY) { - mp_clear (&t); - return res; - } - res = mp_mod (&t, c, d); - mp_clear (&t); - return res; -} - - -/* c = a mod b, 0 <= c < b */ -static int mp_mod (mp_int * a, mp_int * b, mp_int * c) -{ - mp_int t; - int res; - - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } - - if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) { - mp_clear (&t); - return res; - } - - if (t.sign != b->sign) { - res = mp_add (b, &t, c); - } else { - res = MP_OKAY; - mp_exch (&t, c); - } - - mp_clear (&t); - return res; -} - - -/* this is a shell function that calls either the normal or Montgomery - * exptmod functions. Originally the call to the montgomery code was - * embedded in the normal function but that wasted alot of stack space - * for nothing (since 99% of the time the Montgomery code would be called) - */ -static int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) -{ - int dr; - - /* modulus P must be positive */ - if (P->sign == MP_NEG) { - return MP_VAL; - } - - /* if exponent X is negative we have to recurse */ - if (X->sign == MP_NEG) { -#ifdef LTM_NO_NEG_EXP - return MP_VAL; -#else /* LTM_NO_NEG_EXP */ -#ifdef BN_MP_INVMOD_C - mp_int tmpG, tmpX; - int err; - - /* first compute 1/G mod P */ - if ((err = mp_init(&tmpG)) != MP_OKAY) { - return err; - } - if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) { - mp_clear(&tmpG); - return err; - } - - /* now get |X| */ - if ((err = mp_init(&tmpX)) != MP_OKAY) { - mp_clear(&tmpG); - return err; - } - if ((err = mp_abs(X, &tmpX)) != MP_OKAY) { - mp_clear_multi(&tmpG, &tmpX, NULL); - return err; - } - - /* and now compute (1/G)**|X| instead of G**X [X < 0] */ - err = mp_exptmod(&tmpG, &tmpX, P, Y); - mp_clear_multi(&tmpG, &tmpX, NULL); - return err; -#else -#error mp_exptmod would always fail - /* no invmod */ - return MP_VAL; -#endif -#endif /* LTM_NO_NEG_EXP */ - } - -/* modified diminished radix reduction */ -#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C) - if (mp_reduce_is_2k_l(P) == MP_YES) { - return s_mp_exptmod(G, X, P, Y, 1); - } -#endif - -#ifdef BN_MP_DR_IS_MODULUS_C - /* is it a DR modulus? */ - dr = mp_dr_is_modulus(P); -#else - /* default to no */ - dr = 0; -#endif - -#ifdef BN_MP_REDUCE_IS_2K_C - /* if not, is it a unrestricted DR modulus? */ - if (dr == 0) { - dr = mp_reduce_is_2k(P) << 1; - } -#endif - - /* if the modulus is odd or dr != 0 use the montgomery method */ -#ifdef BN_MP_EXPTMOD_FAST_C - if (mp_isodd (P) == 1 || dr != 0) { - return mp_exptmod_fast (G, X, P, Y, dr); - } else { -#endif -#ifdef BN_S_MP_EXPTMOD_C - /* otherwise use the generic Barrett reduction technique */ - return s_mp_exptmod (G, X, P, Y, 0); -#else -#error mp_exptmod could fail - /* no exptmod for evens */ - return MP_VAL; -#endif -#ifdef BN_MP_EXPTMOD_FAST_C - } -#endif -} - - -/* compare two ints (signed)*/ -static int mp_cmp (mp_int * a, mp_int * b) -{ - /* compare based on sign */ - if (a->sign != b->sign) { - if (a->sign == MP_NEG) { - return MP_LT; - } else { - return MP_GT; - } - } - - /* compare digits */ - if (a->sign == MP_NEG) { - /* if negative compare opposite direction */ - return mp_cmp_mag(b, a); - } else { - return mp_cmp_mag(a, b); - } -} - - -/* compare a digit */ -static int mp_cmp_d(mp_int * a, mp_digit b) -{ - /* compare based on sign */ - if (a->sign == MP_NEG) { - return MP_LT; - } - - /* compare based on magnitude */ - if (a->used > 1) { - return MP_GT; - } - - /* compare the only digit of a to b */ - if (a->dp[0] > b) { - return MP_GT; - } else if (a->dp[0] < b) { - return MP_LT; - } else { - return MP_EQ; - } -} - - -#ifndef LTM_NO_NEG_EXP -/* hac 14.61, pp608 */ -static int mp_invmod (mp_int * a, mp_int * b, mp_int * c) -{ - /* b cannot be negative */ - if (b->sign == MP_NEG || mp_iszero(b) == 1) { - return MP_VAL; - } - -#ifdef BN_FAST_MP_INVMOD_C - /* if the modulus is odd we can use a faster routine instead */ - if (mp_isodd (b) == 1) { - return fast_mp_invmod (a, b, c); - } -#endif - -#ifdef BN_MP_INVMOD_SLOW_C - return mp_invmod_slow(a, b, c); -#endif - -#ifndef BN_FAST_MP_INVMOD_C -#ifndef BN_MP_INVMOD_SLOW_C -#error mp_invmod would always fail -#endif -#endif - return MP_VAL; -} -#endif /* LTM_NO_NEG_EXP */ - - -/* get the size for an unsigned equivalent */ -static int mp_unsigned_bin_size (mp_int * a) -{ - int size = mp_count_bits (a); - return (size / 8 + ((size & 7) != 0 ? 1 : 0)); -} - - -#ifndef LTM_NO_NEG_EXP -/* hac 14.61, pp608 */ -static int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) -{ - mp_int x, y, u, v, A, B, C, D; - int res; - - /* b cannot be negative */ - if (b->sign == MP_NEG || mp_iszero(b) == 1) { - return MP_VAL; - } - - /* init temps */ - if ((res = mp_init_multi(&x, &y, &u, &v, - &A, &B, &C, &D, NULL)) != MP_OKAY) { - return res; - } - - /* x = a, y = b */ - if ((res = mp_mod(a, b, &x)) != MP_OKAY) { - goto LBL_ERR; - } - if ((res = mp_copy (b, &y)) != MP_OKAY) { - goto LBL_ERR; - } - - /* 2. [modified] if x,y are both even then return an error! */ - if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) { - res = MP_VAL; - goto LBL_ERR; - } - - /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ - if ((res = mp_copy (&x, &u)) != MP_OKAY) { - goto LBL_ERR; - } - if ((res = mp_copy (&y, &v)) != MP_OKAY) { - goto LBL_ERR; - } - mp_set (&A, 1); - mp_set (&D, 1); - -top: - /* 4. while u is even do */ - while (mp_iseven (&u) == 1) { - /* 4.1 u = u/2 */ - if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { - goto LBL_ERR; - } - /* 4.2 if A or B is odd then */ - if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) { - /* A = (A+y)/2, B = (B-x)/2 */ - if ((res = mp_add (&A, &y, &A)) != MP_OKAY) { - goto LBL_ERR; - } - if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { - goto LBL_ERR; - } - } - /* A = A/2, B = B/2 */ - if ((res = mp_div_2 (&A, &A)) != MP_OKAY) { - goto LBL_ERR; - } - if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { - goto LBL_ERR; - } - } - - /* 5. while v is even do */ - while (mp_iseven (&v) == 1) { - /* 5.1 v = v/2 */ - if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { - goto LBL_ERR; - } - /* 5.2 if C or D is odd then */ - if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) { - /* C = (C+y)/2, D = (D-x)/2 */ - if ((res = mp_add (&C, &y, &C)) != MP_OKAY) { - goto LBL_ERR; - } - if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { - goto LBL_ERR; - } - } - /* C = C/2, D = D/2 */ - if ((res = mp_div_2 (&C, &C)) != MP_OKAY) { - goto LBL_ERR; - } - if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { - goto LBL_ERR; - } - } - - /* 6. if u >= v then */ - if (mp_cmp (&u, &v) != MP_LT) { - /* u = u - v, A = A - C, B = B - D */ - if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { - goto LBL_ERR; - } - - if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) { - goto LBL_ERR; - } - - if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { - goto LBL_ERR; - } - } else { - /* v - v - u, C = C - A, D = D - B */ - if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { - goto LBL_ERR; - } - - if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) { - goto LBL_ERR; - } - - if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { - goto LBL_ERR; - } - } - - /* if not zero goto step 4 */ - if (mp_iszero (&u) == 0) - goto top; - - /* now a = C, b = D, gcd == g*v */ - - /* if v != 1 then there is no inverse */ - if (mp_cmp_d (&v, 1) != MP_EQ) { - res = MP_VAL; - goto LBL_ERR; - } - - /* if its too low */ - while (mp_cmp_d(&C, 0) == MP_LT) { - if ((res = mp_add(&C, b, &C)) != MP_OKAY) { - goto LBL_ERR; - } - } - - /* too big */ - while (mp_cmp_mag(&C, b) != MP_LT) { - if ((res = mp_sub(&C, b, &C)) != MP_OKAY) { - goto LBL_ERR; - } - } - - /* C is now the inverse */ - mp_exch (&C, c); - res = MP_OKAY; -LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL); - return res; -} -#endif /* LTM_NO_NEG_EXP */ - - -/* compare maginitude of two ints (unsigned) */ -static int mp_cmp_mag (mp_int * a, mp_int * b) -{ - int n; - mp_digit *tmpa, *tmpb; - - /* compare based on # of non-zero digits */ - if (a->used > b->used) { - return MP_GT; - } - - if (a->used < b->used) { - return MP_LT; - } - - /* alias for a */ - tmpa = a->dp + (a->used - 1); - - /* alias for b */ - tmpb = b->dp + (a->used - 1); - - /* compare based on digits */ - for (n = 0; n < a->used; ++n, --tmpa, --tmpb) { - if (*tmpa > *tmpb) { - return MP_GT; - } - - if (*tmpa < *tmpb) { - return MP_LT; - } - } - return MP_EQ; -} - - -/* reads a unsigned char array, assumes the msb is stored first [big endian] */ -static int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c) -{ - int res; - - /* make sure there are at least two digits */ - if (a->alloc < 2) { - if ((res = mp_grow(a, 2)) != MP_OKAY) { - return res; - } - } - - /* zero the int */ - mp_zero (a); - - /* read the bytes in */ - while (c-- > 0) { - if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) { - return res; - } - -#ifndef MP_8BIT - a->dp[0] |= *b++; - a->used += 1; -#else - a->dp[0] = (*b & MP_MASK); - a->dp[1] |= ((*b++ >> 7U) & 1); - a->used += 2; -#endif - } - mp_clamp (a); - return MP_OKAY; -} - - -/* store in unsigned [big endian] format */ -static int mp_to_unsigned_bin (mp_int * a, unsigned char *b) -{ - int x, res; - mp_int t; - - if ((res = mp_init_copy (&t, a)) != MP_OKAY) { - return res; - } - - x = 0; - while (mp_iszero (&t) == 0) { -#ifndef MP_8BIT - b[x++] = (unsigned char) (t.dp[0] & 255); -#else - b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7)); -#endif - if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) { - mp_clear (&t); - return res; - } - } - bn_reverse (b, x); - mp_clear (&t); - return MP_OKAY; -} - - -/* shift right by a certain bit count (store quotient in c, optional remainder in d) */ -static int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d) -{ - mp_digit D, r, rr; - int x, res; - mp_int t; - - - /* if the shift count is <= 0 then we do no work */ - if (b <= 0) { - res = mp_copy (a, c); - if (d != NULL) { - mp_zero (d); - } - return res; - } - - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } - - /* get the remainder */ - if (d != NULL) { - if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) { - mp_clear (&t); - return res; - } - } - - /* copy */ - if ((res = mp_copy (a, c)) != MP_OKAY) { - mp_clear (&t); - return res; - } - - /* shift by as many digits in the bit count */ - if (b >= (int)DIGIT_BIT) { - mp_rshd (c, b / DIGIT_BIT); - } - - /* shift any bit count < DIGIT_BIT */ - D = (mp_digit) (b % DIGIT_BIT); - if (D != 0) { - register mp_digit *tmpc, mask, shift; - - /* mask */ - mask = (((mp_digit)1) << D) - 1; - - /* shift for lsb */ - shift = DIGIT_BIT - D; - - /* alias */ - tmpc = c->dp + (c->used - 1); - - /* carry */ - r = 0; - for (x = c->used - 1; x >= 0; x--) { - /* get the lower bits of this word in a temp */ - rr = *tmpc & mask; - - /* shift the current word and mix in the carry bits from the previous word */ - *tmpc = (*tmpc >> D) | (r << shift); - --tmpc; - - /* set the carry to the carry bits of the current word found above */ - r = rr; - } - } - mp_clamp (c); - if (d != NULL) { - mp_exch (&t, d); - } - mp_clear (&t); - return MP_OKAY; -} - - -static int mp_init_copy (mp_int * a, mp_int * b) -{ - int res; - - if ((res = mp_init (a)) != MP_OKAY) { - return res; - } - return mp_copy (b, a); -} - - -/* set to zero */ -static void mp_zero (mp_int * a) -{ - int n; - mp_digit *tmp; - - a->sign = MP_ZPOS; - a->used = 0; - - tmp = a->dp; - for (n = 0; n < a->alloc; n++) { - *tmp++ = 0; - } -} - - -/* copy, b = a */ -static int mp_copy (mp_int * a, mp_int * b) -{ - int res, n; - - /* if dst == src do nothing */ - if (a == b) { - return MP_OKAY; - } - - /* grow dest */ - if (b->alloc < a->used) { - if ((res = mp_grow (b, a->used)) != MP_OKAY) { - return res; - } - } - - /* zero b and copy the parameters over */ - { - register mp_digit *tmpa, *tmpb; - - /* pointer aliases */ - - /* source */ - tmpa = a->dp; - - /* destination */ - tmpb = b->dp; - - /* copy all the digits */ - for (n = 0; n < a->used; n++) { - *tmpb++ = *tmpa++; - } - - /* clear high digits */ - for (; n < b->used; n++) { - *tmpb++ = 0; - } - } - - /* copy used count and sign */ - b->used = a->used; - b->sign = a->sign; - return MP_OKAY; -} - - -/* shift right a certain amount of digits */ -static void mp_rshd (mp_int * a, int b) -{ - int x; - - /* if b <= 0 then ignore it */ - if (b <= 0) { - return; - } - - /* if b > used then simply zero it and return */ - if (a->used <= b) { - mp_zero (a); - return; - } - - { - register mp_digit *bottom, *top; - - /* shift the digits down */ - - /* bottom */ - bottom = a->dp; - - /* top [offset into digits] */ - top = a->dp + b; - - /* this is implemented as a sliding window where - * the window is b-digits long and digits from - * the top of the window are copied to the bottom - * - * e.g. - - b-2 | b-1 | b0 | b1 | b2 | ... | bb | ----> - /\ | ----> - \-------------------/ ----> - */ - for (x = 0; x < (a->used - b); x++) { - *bottom++ = *top++; - } - - /* zero the top digits */ - for (; x < a->used; x++) { - *bottom++ = 0; - } - } - - /* remove excess digits */ - a->used -= b; -} - - -/* swap the elements of two integers, for cases where you can't simply swap the - * mp_int pointers around - */ -static void mp_exch (mp_int * a, mp_int * b) -{ - mp_int t; - - t = *a; - *a = *b; - *b = t; -} - - -/* trim unused digits - * - * This is used to ensure that leading zero digits are - * trimed and the leading "used" digit will be non-zero - * Typically very fast. Also fixes the sign if there - * are no more leading digits - */ -static void mp_clamp (mp_int * a) -{ - /* decrease used while the most significant digit is - * zero. - */ - while (a->used > 0 && a->dp[a->used - 1] == 0) { - --(a->used); - } - - /* reset the sign flag if used == 0 */ - if (a->used == 0) { - a->sign = MP_ZPOS; - } -} - - -/* grow as required */ -static int mp_grow (mp_int * a, int size) -{ - int i; - mp_digit *tmp; - - /* if the alloc size is smaller alloc more ram */ - if (a->alloc < size) { - /* ensure there are always at least MP_PREC digits extra on top */ - size += (MP_PREC * 2) - (size % MP_PREC); - - /* reallocate the array a->dp - * - * We store the return in a temporary variable - * in case the operation failed we don't want - * to overwrite the dp member of a. - */ - tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size); - if (tmp == NULL) { - /* reallocation failed but "a" is still valid [can be freed] */ - return MP_MEM; - } - - /* reallocation succeeded so set a->dp */ - a->dp = tmp; - - /* zero excess digits */ - i = a->alloc; - a->alloc = size; - for (; i < a->alloc; i++) { - a->dp[i] = 0; - } - } - return MP_OKAY; -} - - -#ifdef BN_MP_ABS_C -/* b = |a| - * - * Simple function copies the input and fixes the sign to positive - */ -static int mp_abs (mp_int * a, mp_int * b) -{ - int res; - - /* copy a to b */ - if (a != b) { - if ((res = mp_copy (a, b)) != MP_OKAY) { - return res; - } - } - - /* force the sign of b to positive */ - b->sign = MP_ZPOS; - - return MP_OKAY; -} -#endif - - -/* set to a digit */ -static void mp_set (mp_int * a, mp_digit b) -{ - mp_zero (a); - a->dp[0] = b & MP_MASK; - a->used = (a->dp[0] != 0) ? 1 : 0; -} - - -#ifndef LTM_NO_NEG_EXP -/* b = a/2 */ -static int mp_div_2(mp_int * a, mp_int * b) -{ - int x, res, oldused; - - /* copy */ - if (b->alloc < a->used) { - if ((res = mp_grow (b, a->used)) != MP_OKAY) { - return res; - } - } - - oldused = b->used; - b->used = a->used; - { - register mp_digit r, rr, *tmpa, *tmpb; - - /* source alias */ - tmpa = a->dp + b->used - 1; - - /* dest alias */ - tmpb = b->dp + b->used - 1; - - /* carry */ - r = 0; - for (x = b->used - 1; x >= 0; x--) { - /* get the carry for the next iteration */ - rr = *tmpa & 1; - - /* shift the current digit, add in carry and store */ - *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1)); - - /* forward carry to next iteration */ - r = rr; - } - - /* zero excess digits */ - tmpb = b->dp + b->used; - for (x = b->used; x < oldused; x++) { - *tmpb++ = 0; - } - } - b->sign = a->sign; - mp_clamp (b); - return MP_OKAY; -} -#endif /* LTM_NO_NEG_EXP */ - - -/* shift left by a certain bit count */ -static int mp_mul_2d (mp_int * a, int b, mp_int * c) -{ - mp_digit d; - int res; - - /* copy */ - if (a != c) { - if ((res = mp_copy (a, c)) != MP_OKAY) { - return res; - } - } - - if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) { - if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) { - return res; - } - } - - /* shift by as many digits in the bit count */ - if (b >= (int)DIGIT_BIT) { - if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) { - return res; - } - } - - /* shift any bit count < DIGIT_BIT */ - d = (mp_digit) (b % DIGIT_BIT); - if (d != 0) { - register mp_digit *tmpc, shift, mask, r, rr; - register int x; - - /* bitmask for carries */ - mask = (((mp_digit)1) << d) - 1; - - /* shift for msbs */ - shift = DIGIT_BIT - d; - - /* alias */ - tmpc = c->dp; - - /* carry */ - r = 0; - for (x = 0; x < c->used; x++) { - /* get the higher bits of the current word */ - rr = (*tmpc >> shift) & mask; - - /* shift the current word and OR in the carry */ - *tmpc = ((*tmpc << d) | r) & MP_MASK; - ++tmpc; - - /* set the carry to the carry bits of the current word */ - r = rr; - } - - /* set final carry */ - if (r != 0) { - c->dp[(c->used)++] = r; - } - } - mp_clamp (c); - return MP_OKAY; -} - - -#ifdef BN_MP_INIT_MULTI_C -static int mp_init_multi(mp_int *mp, ...) -{ - mp_err res = MP_OKAY; /* Assume ok until proven otherwise */ - int n = 0; /* Number of ok inits */ - mp_int* cur_arg = mp; - va_list args; - - va_start(args, mp); /* init args to next argument from caller */ - while (cur_arg != NULL) { - if (mp_init(cur_arg) != MP_OKAY) { - /* Oops - error! Back-track and mp_clear what we already - succeeded in init-ing, then return error. - */ - va_list clean_args; - - /* end the current list */ - va_end(args); - - /* now start cleaning up */ - cur_arg = mp; - va_start(clean_args, mp); - while (n--) { - mp_clear(cur_arg); - cur_arg = va_arg(clean_args, mp_int*); - } - va_end(clean_args); - res = MP_MEM; - break; - } - n++; - cur_arg = va_arg(args, mp_int*); - } - va_end(args); - return res; /* Assumed ok, if error flagged above. */ -} -#endif - - -#ifdef BN_MP_CLEAR_MULTI_C -static void mp_clear_multi(mp_int *mp, ...) -{ - mp_int* next_mp = mp; - va_list args; - va_start(args, mp); - while (next_mp != NULL) { - mp_clear(next_mp); - next_mp = va_arg(args, mp_int*); - } - va_end(args); -} -#endif - - -/* shift left a certain amount of digits */ -static int mp_lshd (mp_int * a, int b) -{ - int x, res; - - /* if its less than zero return */ - if (b <= 0) { - return MP_OKAY; - } - - /* grow to fit the new digits */ - if (a->alloc < a->used + b) { - if ((res = mp_grow (a, a->used + b)) != MP_OKAY) { - return res; - } - } - - { - register mp_digit *top, *bottom; - - /* increment the used by the shift amount then copy upwards */ - a->used += b; - - /* top */ - top = a->dp + a->used - 1; - - /* base */ - bottom = a->dp + a->used - 1 - b; - - /* much like mp_rshd this is implemented using a sliding window - * except the window goes the otherway around. Copying from - * the bottom to the top. see bn_mp_rshd.c for more info. - */ - for (x = a->used - 1; x >= b; x--) { - *top-- = *bottom--; - } - - /* zero the lower digits */ - top = a->dp; - for (x = 0; x < b; x++) { - *top++ = 0; - } - } - return MP_OKAY; -} - - -/* returns the number of bits in an int */ -static int mp_count_bits (mp_int * a) -{ - int r; - mp_digit q; - - /* shortcut */ - if (a->used == 0) { - return 0; - } - - /* get number of digits and add that */ - r = (a->used - 1) * DIGIT_BIT; - - /* take the last digit and count the bits in it */ - q = a->dp[a->used - 1]; - while (q > ((mp_digit) 0)) { - ++r; - q >>= ((mp_digit) 1); - } - return r; -} - - -/* calc a value mod 2**b */ -static int mp_mod_2d (mp_int * a, int b, mp_int * c) -{ - int x, res; - - /* if b is <= 0 then zero the int */ - if (b <= 0) { - mp_zero (c); - return MP_OKAY; - } - - /* if the modulus is larger than the value than return */ - if (b >= (int) (a->used * DIGIT_BIT)) { - res = mp_copy (a, c); - return res; - } - - /* copy */ - if ((res = mp_copy (a, c)) != MP_OKAY) { - return res; - } - - /* zero digits above the last digit of the modulus */ - for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) { - c->dp[x] = 0; - } - /* clear the digit that is not completely outside/inside the modulus */ - c->dp[b / DIGIT_BIT] &= - (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1)); - mp_clamp (c); - return MP_OKAY; -} - - -#ifdef BN_MP_DIV_SMALL - -/* slower bit-bang division... also smaller */ -static int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d) -{ - mp_int ta, tb, tq, q; - int res, n, n2; - - /* is divisor zero ? */ - if (mp_iszero (b) == 1) { - return MP_VAL; - } - - /* if a < b then q=0, r = a */ - if (mp_cmp_mag (a, b) == MP_LT) { - if (d != NULL) { - res = mp_copy (a, d); - } else { - res = MP_OKAY; - } - if (c != NULL) { - mp_zero (c); - } - return res; - } - - /* init our temps */ - if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) { - return res; - } - - - mp_set(&tq, 1); - n = mp_count_bits(a) - mp_count_bits(b); - if (((res = mp_abs(a, &ta)) != MP_OKAY) || - ((res = mp_abs(b, &tb)) != MP_OKAY) || - ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) || - ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) { - goto LBL_ERR; - } - - while (n-- >= 0) { - if (mp_cmp(&tb, &ta) != MP_GT) { - if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) || - ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) { - goto LBL_ERR; - } - } - if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) || - ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) { - goto LBL_ERR; - } - } - - /* now q == quotient and ta == remainder */ - n = a->sign; - n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG); - if (c != NULL) { - mp_exch(c, &q); - c->sign = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2; - } - if (d != NULL) { - mp_exch(d, &ta); - d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n; - } -LBL_ERR: - mp_clear_multi(&ta, &tb, &tq, &q, NULL); - return res; -} - -#else - -/* integer signed division. - * c*b + d == a [e.g. a/b, c=quotient, d=remainder] - * HAC pp.598 Algorithm 14.20 - * - * Note that the description in HAC is horribly - * incomplete. For example, it doesn't consider - * the case where digits are removed from 'x' in - * the inner loop. It also doesn't consider the - * case that y has fewer than three digits, etc.. - * - * The overall algorithm is as described as - * 14.20 from HAC but fixed to treat these cases. -*/ -static int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d) -{ - mp_int q, x, y, t1, t2; - int res, n, t, i, norm, neg; - - /* is divisor zero ? */ - if (mp_iszero (b) == 1) { - return MP_VAL; - } - - /* if a < b then q=0, r = a */ - if (mp_cmp_mag (a, b) == MP_LT) { - if (d != NULL) { - res = mp_copy (a, d); - } else { - res = MP_OKAY; - } - if (c != NULL) { - mp_zero (c); - } - return res; - } - - if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) { - return res; - } - q.used = a->used + 2; - - if ((res = mp_init (&t1)) != MP_OKAY) { - goto LBL_Q; - } - - if ((res = mp_init (&t2)) != MP_OKAY) { - goto LBL_T1; - } - - if ((res = mp_init_copy (&x, a)) != MP_OKAY) { - goto LBL_T2; - } - - if ((res = mp_init_copy (&y, b)) != MP_OKAY) { - goto LBL_X; - } - - /* fix the sign */ - neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; - x.sign = y.sign = MP_ZPOS; - - /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */ - norm = mp_count_bits(&y) % DIGIT_BIT; - if (norm < (int)(DIGIT_BIT-1)) { - norm = (DIGIT_BIT-1) - norm; - if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) { - goto LBL_Y; - } - if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) { - goto LBL_Y; - } - } else { - norm = 0; - } - - /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ - n = x.used - 1; - t = y.used - 1; - - /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ - if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */ - goto LBL_Y; - } - - while (mp_cmp (&x, &y) != MP_LT) { - ++(q.dp[n - t]); - if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) { - goto LBL_Y; - } - } - - /* reset y by shifting it back down */ - mp_rshd (&y, n - t); - - /* step 3. for i from n down to (t + 1) */ - for (i = n; i >= (t + 1); i--) { - if (i > x.used) { - continue; - } - - /* step 3.1 if xi == yt then set q{i-t-1} to b-1, - * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ - if (x.dp[i] == y.dp[t]) { - q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1); - } else { - mp_word tmp; - tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT); - tmp |= ((mp_word) x.dp[i - 1]); - tmp /= ((mp_word) y.dp[t]); - if (tmp > (mp_word) MP_MASK) - tmp = MP_MASK; - q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK)); - } - - /* while (q{i-t-1} * (yt * b + y{t-1})) > - xi * b**2 + xi-1 * b + xi-2 - - do q{i-t-1} -= 1; - */ - q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK; - do { - q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK; - - /* find left hand */ - mp_zero (&t1); - t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1]; - t1.dp[1] = y.dp[t]; - t1.used = 2; - if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) { - goto LBL_Y; - } - - /* find right hand */ - t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2]; - t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1]; - t2.dp[2] = x.dp[i]; - t2.used = 3; - } while (mp_cmp_mag(&t1, &t2) == MP_GT); - - /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */ - if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) { - goto LBL_Y; - } - - if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { - goto LBL_Y; - } - - if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) { - goto LBL_Y; - } - - /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */ - if (x.sign == MP_NEG) { - if ((res = mp_copy (&y, &t1)) != MP_OKAY) { - goto LBL_Y; - } - if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { - goto LBL_Y; - } - if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) { - goto LBL_Y; - } - - q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK; - } - } - - /* now q is the quotient and x is the remainder - * [which we have to normalize] - */ - - /* get sign before writing to c */ - x.sign = x.used == 0 ? MP_ZPOS : a->sign; - - if (c != NULL) { - mp_clamp (&q); - mp_exch (&q, c); - c->sign = neg; - } - - if (d != NULL) { - mp_div_2d (&x, norm, &x, NULL); - mp_exch (&x, d); - } - - res = MP_OKAY; - -LBL_Y:mp_clear (&y); -LBL_X:mp_clear (&x); -LBL_T2:mp_clear (&t2); -LBL_T1:mp_clear (&t1); -LBL_Q:mp_clear (&q); - return res; -} - -#endif - - -#ifdef MP_LOW_MEM - #define TAB_SIZE 32 -#else - #define TAB_SIZE 256 -#endif - -static int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) -{ - mp_int M[TAB_SIZE], res, mu; - mp_digit buf; - int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; - int (*redux)(mp_int*,mp_int*,mp_int*); - - /* find window size */ - x = mp_count_bits (X); - if (x <= 7) { - winsize = 2; - } else if (x <= 36) { - winsize = 3; - } else if (x <= 140) { - winsize = 4; - } else if (x <= 450) { - winsize = 5; - } else if (x <= 1303) { - winsize = 6; - } else if (x <= 3529) { - winsize = 7; - } else { - winsize = 8; - } - -#ifdef MP_LOW_MEM - if (winsize > 5) { - winsize = 5; - } -#endif - - /* init M array */ - /* init first cell */ - if ((err = mp_init(&M[1])) != MP_OKAY) { - return err; - } - - /* now init the second half of the array */ - for (x = 1<<(winsize-1); x < (1 << winsize); x++) { - if ((err = mp_init(&M[x])) != MP_OKAY) { - for (y = 1<<(winsize-1); y < x; y++) { - mp_clear (&M[y]); - } - mp_clear(&M[1]); - return err; - } - } - - /* create mu, used for Barrett reduction */ - if ((err = mp_init (&mu)) != MP_OKAY) { - goto LBL_M; - } - - if (redmode == 0) { - if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) { - goto LBL_MU; - } - redux = mp_reduce; - } else { - if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) { - goto LBL_MU; - } - redux = mp_reduce_2k_l; - } - - /* create M table - * - * The M table contains powers of the base, - * e.g. M[x] = G**x mod P - * - * The first half of the table is not - * computed though accept for M[0] and M[1] - */ - if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) { - goto LBL_MU; - } - - /* compute the value at M[1<<(winsize-1)] by squaring - * M[1] (winsize-1) times - */ - if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { - goto LBL_MU; - } - - for (x = 0; x < (winsize - 1); x++) { - /* square it */ - if ((err = mp_sqr (&M[1 << (winsize - 1)], - &M[1 << (winsize - 1)])) != MP_OKAY) { - goto LBL_MU; - } - - /* reduce modulo P */ - if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) { - goto LBL_MU; - } - } - - /* create upper table, that is M[x] = M[x-1] * M[1] (mod P) - * for x = (2**(winsize - 1) + 1) to (2**winsize - 1) - */ - for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { - if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { - goto LBL_MU; - } - if ((err = redux (&M[x], P, &mu)) != MP_OKAY) { - goto LBL_MU; - } - } - - /* setup result */ - if ((err = mp_init (&res)) != MP_OKAY) { - goto LBL_MU; - } - mp_set (&res, 1); - - /* set initial mode and bit cnt */ - mode = 0; - bitcnt = 1; - buf = 0; - digidx = X->used - 1; - bitcpy = 0; - bitbuf = 0; - - for (;;) { - /* grab next digit as required */ - if (--bitcnt == 0) { - /* if digidx == -1 we are out of digits */ - if (digidx == -1) { - break; - } - /* read next digit and reset the bitcnt */ - buf = X->dp[digidx--]; - bitcnt = (int) DIGIT_BIT; - } - - /* grab the next msb from the exponent */ - y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1; - buf <<= (mp_digit)1; - - /* if the bit is zero and mode == 0 then we ignore it - * These represent the leading zero bits before the first 1 bit - * in the exponent. Technically this opt is not required but it - * does lower the # of trivial squaring/reductions used - */ - if (mode == 0 && y == 0) { - continue; - } - - /* if the bit is zero and mode == 1 then we square */ - if (mode == 1 && y == 0) { - if ((err = mp_sqr (&res, &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, &mu)) != MP_OKAY) { - goto LBL_RES; - } - continue; - } - - /* else we add it to the window */ - bitbuf |= (y << (winsize - ++bitcpy)); - mode = 2; - - if (bitcpy == winsize) { - /* ok window is filled so square as required and multiply */ - /* square first */ - for (x = 0; x < winsize; x++) { - if ((err = mp_sqr (&res, &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, &mu)) != MP_OKAY) { - goto LBL_RES; - } - } - - /* then multiply */ - if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, &mu)) != MP_OKAY) { - goto LBL_RES; - } - - /* empty window and reset */ - bitcpy = 0; - bitbuf = 0; - mode = 1; - } - } - - /* if bits remain then square/multiply */ - if (mode == 2 && bitcpy > 0) { - /* square then multiply if the bit is set */ - for (x = 0; x < bitcpy; x++) { - if ((err = mp_sqr (&res, &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, &mu)) != MP_OKAY) { - goto LBL_RES; - } - - bitbuf <<= 1; - if ((bitbuf & (1 << winsize)) != 0) { - /* then multiply */ - if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, &mu)) != MP_OKAY) { - goto LBL_RES; - } - } - } - } - - mp_exch (&res, Y); - err = MP_OKAY; -LBL_RES:mp_clear (&res); -LBL_MU:mp_clear (&mu); -LBL_M: - mp_clear(&M[1]); - for (x = 1<<(winsize-1); x < (1 << winsize); x++) { - mp_clear (&M[x]); - } - return err; -} - - -/* computes b = a*a */ -static int mp_sqr (mp_int * a, mp_int * b) -{ - int res; - -#ifdef BN_MP_TOOM_SQR_C - /* use Toom-Cook? */ - if (a->used >= TOOM_SQR_CUTOFF) { - res = mp_toom_sqr(a, b); - /* Karatsuba? */ - } else -#endif -#ifdef BN_MP_KARATSUBA_SQR_C -if (a->used >= KARATSUBA_SQR_CUTOFF) { - res = mp_karatsuba_sqr (a, b); - } else -#endif - { -#ifdef BN_FAST_S_MP_SQR_C - /* can we use the fast comba multiplier? */ - if ((a->used * 2 + 1) < MP_WARRAY && - a->used < - (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) { - res = fast_s_mp_sqr (a, b); - } else -#endif -#ifdef BN_S_MP_SQR_C - res = s_mp_sqr (a, b); -#else -#error mp_sqr could fail - res = MP_VAL; -#endif - } - b->sign = MP_ZPOS; - return res; -} - - -/* reduces a modulo n where n is of the form 2**p - d - This differs from reduce_2k since "d" can be larger - than a single digit. -*/ -static int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d) -{ - mp_int q; - int p, res; - - if ((res = mp_init(&q)) != MP_OKAY) { - return res; - } - - p = mp_count_bits(n); -top: - /* q = a/2**p, a = a mod 2**p */ - if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) { - goto ERR; - } - - /* q = q * d */ - if ((res = mp_mul(&q, d, &q)) != MP_OKAY) { - goto ERR; - } - - /* a = a + q */ - if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { - goto ERR; - } - - if (mp_cmp_mag(a, n) != MP_LT) { - s_mp_sub(a, n, a); - goto top; - } - -ERR: - mp_clear(&q); - return res; -} - - -/* determines the setup value */ -static int mp_reduce_2k_setup_l(mp_int *a, mp_int *d) -{ - int res; - mp_int tmp; - - if ((res = mp_init(&tmp)) != MP_OKAY) { - return res; - } - - if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) { - goto ERR; - } - - if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) { - goto ERR; - } - -ERR: - mp_clear(&tmp); - return res; -} - - -/* computes a = 2**b - * - * Simple algorithm which zeroes the int, grows it then just sets one bit - * as required. - */ -static int mp_2expt (mp_int * a, int b) -{ - int res; - - /* zero a as per default */ - mp_zero (a); - - /* grow a to accomodate the single bit */ - if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) { - return res; - } - - /* set the used count of where the bit will go */ - a->used = b / DIGIT_BIT + 1; - - /* put the single bit in its place */ - a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT); - - return MP_OKAY; -} - - -/* pre-calculate the value required for Barrett reduction - * For a given modulus "b" it calulates the value required in "a" - */ -static int mp_reduce_setup (mp_int * a, mp_int * b) -{ - int res; - - if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) { - return res; - } - return mp_div (a, b, a, NULL); -} - - -/* reduces x mod m, assumes 0 < x < m**2, mu is - * precomputed via mp_reduce_setup. - * From HAC pp.604 Algorithm 14.42 - */ -static int mp_reduce (mp_int * x, mp_int * m, mp_int * mu) -{ - mp_int q; - int res, um = m->used; - - /* q = x */ - if ((res = mp_init_copy (&q, x)) != MP_OKAY) { - return res; - } - - /* q1 = x / b**(k-1) */ - mp_rshd (&q, um - 1); - - /* according to HAC this optimization is ok */ - if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) { - if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) { - goto CLEANUP; - } - } else { -#ifdef BN_S_MP_MUL_HIGH_DIGS_C - if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { - goto CLEANUP; - } -#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C) - if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { - goto CLEANUP; - } -#else - { -#error mp_reduce would always fail - res = MP_VAL; - goto CLEANUP; - } -#endif - } - - /* q3 = q2 / b**(k+1) */ - mp_rshd (&q, um + 1); - - /* x = x mod b**(k+1), quick (no division) */ - if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) { - goto CLEANUP; - } - - /* q = q * m mod b**(k+1), quick (no division) */ - if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) { - goto CLEANUP; - } - - /* x = x - q */ - if ((res = mp_sub (x, &q, x)) != MP_OKAY) { - goto CLEANUP; - } - - /* If x < 0, add b**(k+1) to it */ - if (mp_cmp_d (x, 0) == MP_LT) { - mp_set (&q, 1); - if ((res = mp_lshd (&q, um + 1)) != MP_OKAY) { - goto CLEANUP; - } - if ((res = mp_add (x, &q, x)) != MP_OKAY) { - goto CLEANUP; - } - } - - /* Back off if it's too big */ - while (mp_cmp (x, m) != MP_LT) { - if ((res = s_mp_sub (x, m, x)) != MP_OKAY) { - goto CLEANUP; - } - } - -CLEANUP: - mp_clear (&q); - - return res; -} - - -/* multiplies |a| * |b| and only computes upto digs digits of result - * HAC pp. 595, Algorithm 14.12 Modified so you can control how - * many digits of output are created. - */ -static int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) -{ - mp_int t; - int res, pa, pb, ix, iy; - mp_digit u; - mp_word r; - mp_digit tmpx, *tmpt, *tmpy; - - /* can we use the fast multiplier? */ - if (((digs) < MP_WARRAY) && - MIN (a->used, b->used) < - (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { - return fast_s_mp_mul_digs (a, b, c, digs); - } - - if ((res = mp_init_size (&t, digs)) != MP_OKAY) { - return res; - } - t.used = digs; - - /* compute the digits of the product directly */ - pa = a->used; - for (ix = 0; ix < pa; ix++) { - /* set the carry to zero */ - u = 0; - - /* limit ourselves to making digs digits of output */ - pb = MIN (b->used, digs - ix); - - /* setup some aliases */ - /* copy of the digit from a used within the nested loop */ - tmpx = a->dp[ix]; - - /* an alias for the destination shifted ix places */ - tmpt = t.dp + ix; - - /* an alias for the digits of b */ - tmpy = b->dp; - - /* compute the columns of the output and propagate the carry */ - for (iy = 0; iy < pb; iy++) { - /* compute the column as a mp_word */ - r = ((mp_word)*tmpt) + - ((mp_word)tmpx) * ((mp_word)*tmpy++) + - ((mp_word) u); - - /* the new column is the lower part of the result */ - *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); - - /* get the carry word from the result */ - u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); - } - /* set carry if it is placed below digs */ - if (ix + iy < digs) { - *tmpt = u; - } - } - - mp_clamp (&t); - mp_exch (&t, c); - - mp_clear (&t); - return MP_OKAY; -} - - -/* Fast (comba) multiplier - * - * This is the fast column-array [comba] multiplier. It is - * designed to compute the columns of the product first - * then handle the carries afterwards. This has the effect - * of making the nested loops that compute the columns very - * simple and schedulable on super-scalar processors. - * - * This has been modified to produce a variable number of - * digits of output so if say only a half-product is required - * you don't have to compute the upper half (a feature - * required for fast Barrett reduction). - * - * Based on Algorithm 14.12 on pp.595 of HAC. - * - */ -static int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) -{ - int olduse, res, pa, ix, iz; - mp_digit W[MP_WARRAY]; - register mp_word _W; - - /* grow the destination as required */ - if (c->alloc < digs) { - if ((res = mp_grow (c, digs)) != MP_OKAY) { - return res; - } - } - - /* number of output digits to produce */ - pa = MIN(digs, a->used + b->used); - - /* clear the carry */ - _W = 0; - for (ix = 0; ix < pa; ix++) { - int tx, ty; - int iy; - mp_digit *tmpx, *tmpy; - - /* get offsets into the two bignums */ - ty = MIN(b->used-1, ix); - tx = ix - ty; - - /* setup temp aliases */ - tmpx = a->dp + tx; - tmpy = b->dp + ty; - - /* this is the number of times the loop will iterrate, essentially - while (tx++ < a->used && ty-- >= 0) { ... } - */ - iy = MIN(a->used-tx, ty+1); - - /* execute loop */ - for (iz = 0; iz < iy; ++iz) { - _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); - - } - - /* store term */ - W[ix] = ((mp_digit)_W) & MP_MASK; - - /* make next carry */ - _W = _W >> ((mp_word)DIGIT_BIT); - } - - /* setup dest */ - olduse = c->used; - c->used = pa; - - { - register mp_digit *tmpc; - tmpc = c->dp; - for (ix = 0; ix < pa+1; ix++) { - /* now extract the previous digit [below the carry] */ - *tmpc++ = W[ix]; - } - - /* clear unused digits [that existed in the old copy of c] */ - for (; ix < olduse; ix++) { - *tmpc++ = 0; - } - } - mp_clamp (c); - return MP_OKAY; -} - - -/* init an mp_init for a given size */ -static int mp_init_size (mp_int * a, int size) -{ - int x; - - /* pad size so there are always extra digits */ - size += (MP_PREC * 2) - (size % MP_PREC); - - /* alloc mem */ - a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size); - if (a->dp == NULL) { - return MP_MEM; - } - - /* set the members */ - a->used = 0; - a->alloc = size; - a->sign = MP_ZPOS; - - /* zero the digits */ - for (x = 0; x < size; x++) { - a->dp[x] = 0; - } - - return MP_OKAY; -} - - -/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ -static int s_mp_sqr (mp_int * a, mp_int * b) -{ - mp_int t; - int res, ix, iy, pa; - mp_word r; - mp_digit u, tmpx, *tmpt; - - pa = a->used; - if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) { - return res; - } - - /* default used is maximum possible size */ - t.used = 2*pa + 1; - - for (ix = 0; ix < pa; ix++) { - /* first calculate the digit at 2*ix */ - /* calculate double precision result */ - r = ((mp_word) t.dp[2*ix]) + - ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]); - - /* store lower part in result */ - t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK)); - - /* get the carry */ - u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); - - /* left hand side of A[ix] * A[iy] */ - tmpx = a->dp[ix]; - - /* alias for where to store the results */ - tmpt = t.dp + (2*ix + 1); - - for (iy = ix + 1; iy < pa; iy++) { - /* first calculate the product */ - r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]); - - /* now calculate the double precision result, note we use - * addition instead of *2 since it's easier to optimize - */ - r = ((mp_word) *tmpt) + r + r + ((mp_word) u); - - /* store lower part */ - *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); - - /* get carry */ - u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); - } - /* propagate upwards */ - while (u != ((mp_digit) 0)) { - r = ((mp_word) *tmpt) + ((mp_word) u); - *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); - u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); - } - } - - mp_clamp (&t); - mp_exch (&t, b); - mp_clear (&t); - return MP_OKAY; -} - - -/* multiplies |a| * |b| and does not compute the lower digs digits - * [meant to get the higher part of the product] - */ -static int s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) -{ - mp_int t; - int res, pa, pb, ix, iy; - mp_digit u; - mp_word r; - mp_digit tmpx, *tmpt, *tmpy; - - /* can we use the fast multiplier? */ -#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C - if (((a->used + b->used + 1) < MP_WARRAY) - && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { - return fast_s_mp_mul_high_digs (a, b, c, digs); - } -#endif - - if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) { - return res; - } - t.used = a->used + b->used + 1; - - pa = a->used; - pb = b->used; - for (ix = 0; ix < pa; ix++) { - /* clear the carry */ - u = 0; - - /* left hand side of A[ix] * B[iy] */ - tmpx = a->dp[ix]; - - /* alias to the address of where the digits will be stored */ - tmpt = &(t.dp[digs]); - - /* alias for where to read the right hand side from */ - tmpy = b->dp + (digs - ix); - - for (iy = digs - ix; iy < pb; iy++) { - /* calculate the double precision result */ - r = ((mp_word)*tmpt) + - ((mp_word)tmpx) * ((mp_word)*tmpy++) + - ((mp_word) u); - - /* get the lower part */ - *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); - - /* carry the carry */ - u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); - } - *tmpt = u; - } - mp_clamp (&t); - mp_exch (&t, c); - mp_clear (&t); - return MP_OKAY; -} - - -#ifdef BN_MP_MONTGOMERY_SETUP_C -/* setups the montgomery reduction stuff */ -static int -mp_montgomery_setup (mp_int * n, mp_digit * rho) -{ - mp_digit x, b; - -/* fast inversion mod 2**k - * - * Based on the fact that - * - * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n) - * => 2*X*A - X*X*A*A = 1 - * => 2*(1) - (1) = 1 - */ - b = n->dp[0]; - - if ((b & 1) == 0) { - return MP_VAL; - } - - x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ - x *= 2 - b * x; /* here x*a==1 mod 2**8 */ -#if !defined(MP_8BIT) - x *= 2 - b * x; /* here x*a==1 mod 2**16 */ -#endif -#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT)) - x *= 2 - b * x; /* here x*a==1 mod 2**32 */ -#endif -#ifdef MP_64BIT - x *= 2 - b * x; /* here x*a==1 mod 2**64 */ -#endif - - /* rho = -1/m mod b */ - *rho = (unsigned long)(((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK; - - return MP_OKAY; -} -#endif - - -#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C -/* computes xR**-1 == x (mod N) via Montgomery Reduction - * - * This is an optimized implementation of montgomery_reduce - * which uses the comba method to quickly calculate the columns of the - * reduction. - * - * Based on Algorithm 14.32 on pp.601 of HAC. -*/ -int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) -{ - int ix, res, olduse; - mp_word W[MP_WARRAY]; - - /* get old used count */ - olduse = x->used; - - /* grow a as required */ - if (x->alloc < n->used + 1) { - if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) { - return res; - } - } - - /* first we have to get the digits of the input into - * an array of double precision words W[...] - */ - { - register mp_word *_W; - register mp_digit *tmpx; - - /* alias for the W[] array */ - _W = W; - - /* alias for the digits of x*/ - tmpx = x->dp; - - /* copy the digits of a into W[0..a->used-1] */ - for (ix = 0; ix < x->used; ix++) { - *_W++ = *tmpx++; - } - - /* zero the high words of W[a->used..m->used*2] */ - for (; ix < n->used * 2 + 1; ix++) { - *_W++ = 0; - } - } - - /* now we proceed to zero successive digits - * from the least significant upwards - */ - for (ix = 0; ix < n->used; ix++) { - /* mu = ai * m' mod b - * - * We avoid a double precision multiplication (which isn't required) - * by casting the value down to a mp_digit. Note this requires - * that W[ix-1] have the carry cleared (see after the inner loop) - */ - register mp_digit mu; - mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK); - - /* a = a + mu * m * b**i - * - * This is computed in place and on the fly. The multiplication - * by b**i is handled by offseting which columns the results - * are added to. - * - * Note the comba method normally doesn't handle carries in the - * inner loop In this case we fix the carry from the previous - * column since the Montgomery reduction requires digits of the - * result (so far) [see above] to work. This is - * handled by fixing up one carry after the inner loop. The - * carry fixups are done in order so after these loops the - * first m->used words of W[] have the carries fixed - */ - { - register int iy; - register mp_digit *tmpn; - register mp_word *_W; - - /* alias for the digits of the modulus */ - tmpn = n->dp; - - /* Alias for the columns set by an offset of ix */ - _W = W + ix; - - /* inner loop */ - for (iy = 0; iy < n->used; iy++) { - *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++); - } - } - - /* now fix carry for next digit, W[ix+1] */ - W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT); - } - - /* now we have to propagate the carries and - * shift the words downward [all those least - * significant digits we zeroed]. - */ - { - register mp_digit *tmpx; - register mp_word *_W, *_W1; - - /* nox fix rest of carries */ - - /* alias for current word */ - _W1 = W + ix; - - /* alias for next word, where the carry goes */ - _W = W + ++ix; - - for (; ix <= n->used * 2 + 1; ix++) { - *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT); - } - - /* copy out, A = A/b**n - * - * The result is A/b**n but instead of converting from an - * array of mp_word to mp_digit than calling mp_rshd - * we just copy them in the right order - */ - - /* alias for destination word */ - tmpx = x->dp; - - /* alias for shifted double precision result */ - _W = W + n->used; - - for (ix = 0; ix < n->used + 1; ix++) { - *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK)); - } - - /* zero oldused digits, if the input a was larger than - * m->used+1 we'll have to clear the digits - */ - for (; ix < olduse; ix++) { - *tmpx++ = 0; - } - } - - /* set the max used and clamp */ - x->used = n->used + 1; - mp_clamp (x); - - /* if A >= m then A = A - m */ - if (mp_cmp_mag (x, n) != MP_LT) { - return s_mp_sub (x, n, x); - } - return MP_OKAY; -} -#endif - - -#ifdef BN_MP_MUL_2_C -/* b = a*2 */ -static int mp_mul_2(mp_int * a, mp_int * b) -{ - int x, res, oldused; - - /* grow to accomodate result */ - if (b->alloc < a->used + 1) { - if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) { - return res; - } - } - - oldused = b->used; - b->used = a->used; - - { - register mp_digit r, rr, *tmpa, *tmpb; - - /* alias for source */ - tmpa = a->dp; - - /* alias for dest */ - tmpb = b->dp; - - /* carry */ - r = 0; - for (x = 0; x < a->used; x++) { - - /* get what will be the *next* carry bit from the - * MSB of the current digit - */ - rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1)); - - /* now shift up this digit, add in the carry [from the previous] */ - *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK; - - /* copy the carry that would be from the source - * digit into the next iteration - */ - r = rr; - } - - /* new leading digit? */ - if (r != 0) { - /* add a MSB which is always 1 at this point */ - *tmpb = 1; - ++(b->used); - } - - /* now zero any excess digits on the destination - * that we didn't write to - */ - tmpb = b->dp + b->used; - for (x = b->used; x < oldused; x++) { - *tmpb++ = 0; - } - } - b->sign = a->sign; - return MP_OKAY; -} -#endif - - -#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C -/* - * shifts with subtractions when the result is greater than b. - * - * The method is slightly modified to shift B unconditionally upto just under - * the leading bit of b. This saves alot of multiple precision shifting. - */ -static int mp_montgomery_calc_normalization (mp_int * a, mp_int * b) -{ - int x, bits, res; - - /* how many bits of last digit does b use */ - bits = mp_count_bits (b) % DIGIT_BIT; - - if (b->used > 1) { - if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) { - return res; - } - } else { - mp_set(a, 1); - bits = 1; - } - - - /* now compute C = A * B mod b */ - for (x = bits - 1; x < (int)DIGIT_BIT; x++) { - if ((res = mp_mul_2 (a, a)) != MP_OKAY) { - return res; - } - if (mp_cmp_mag (a, b) != MP_LT) { - if ((res = s_mp_sub (a, b, a)) != MP_OKAY) { - return res; - } - } - } - - return MP_OKAY; -} -#endif - - -#ifdef BN_MP_EXPTMOD_FAST_C -/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85 - * - * Uses a left-to-right k-ary sliding window to compute the modular exponentiation. - * The value of k changes based on the size of the exponent. - * - * Uses Montgomery or Diminished Radix reduction [whichever appropriate] - */ - -static int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) -{ - mp_int M[TAB_SIZE], res; - mp_digit buf, mp; - int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; - - /* use a pointer to the reduction algorithm. This allows us to use - * one of many reduction algorithms without modding the guts of - * the code with if statements everywhere. - */ - int (*redux)(mp_int*,mp_int*,mp_digit); - - /* find window size */ - x = mp_count_bits (X); - if (x <= 7) { - winsize = 2; - } else if (x <= 36) { - winsize = 3; - } else if (x <= 140) { - winsize = 4; - } else if (x <= 450) { - winsize = 5; - } else if (x <= 1303) { - winsize = 6; - } else if (x <= 3529) { - winsize = 7; - } else { - winsize = 8; - } - -#ifdef MP_LOW_MEM - if (winsize > 5) { - winsize = 5; - } -#endif - - /* init M array */ - /* init first cell */ - if ((err = mp_init(&M[1])) != MP_OKAY) { - return err; - } - - /* now init the second half of the array */ - for (x = 1<<(winsize-1); x < (1 << winsize); x++) { - if ((err = mp_init(&M[x])) != MP_OKAY) { - for (y = 1<<(winsize-1); y < x; y++) { - mp_clear (&M[y]); - } - mp_clear(&M[1]); - return err; - } - } - - /* determine and setup reduction code */ - if (redmode == 0) { -#ifdef BN_MP_MONTGOMERY_SETUP_C - /* now setup montgomery */ - if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) { - goto LBL_M; - } -#else - err = MP_VAL; - goto LBL_M; -#endif - - /* automatically pick the comba one if available (saves quite a few calls/ifs) */ -#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C - if (((P->used * 2 + 1) < MP_WARRAY) && - P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { - redux = fast_mp_montgomery_reduce; - } else -#endif - { -#ifdef BN_MP_MONTGOMERY_REDUCE_C - /* use slower baseline Montgomery method */ - redux = mp_montgomery_reduce; -#else - err = MP_VAL; - goto LBL_M; -#endif - } - } else if (redmode == 1) { -#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C) - /* setup DR reduction for moduli of the form B**k - b */ - mp_dr_setup(P, &mp); - redux = mp_dr_reduce; -#else - err = MP_VAL; - goto LBL_M; -#endif - } else { -#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C) - /* setup DR reduction for moduli of the form 2**k - b */ - if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) { - goto LBL_M; - } - redux = mp_reduce_2k; -#else - err = MP_VAL; - goto LBL_M; -#endif - } - - /* setup result */ - if ((err = mp_init (&res)) != MP_OKAY) { - goto LBL_M; - } - - /* create M table - * - - * - * The first half of the table is not computed though accept for M[0] and M[1] - */ - - if (redmode == 0) { -#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C - /* now we need R mod m */ - if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) { - goto LBL_RES; - } -#else - err = MP_VAL; - goto LBL_RES; -#endif - - /* now set M[1] to G * R mod m */ - if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) { - goto LBL_RES; - } - } else { - mp_set(&res, 1); - if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) { - goto LBL_RES; - } - } - - /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ - if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { - goto LBL_RES; - } - - for (x = 0; x < (winsize - 1); x++) { - if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) { - goto LBL_RES; - } - } - - /* create upper table */ - for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { - if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&M[x], P, mp)) != MP_OKAY) { - goto LBL_RES; - } - } - - /* set initial mode and bit cnt */ - mode = 0; - bitcnt = 1; - buf = 0; - digidx = X->used - 1; - bitcpy = 0; - bitbuf = 0; - - for (;;) { - /* grab next digit as required */ - if (--bitcnt == 0) { - /* if digidx == -1 we are out of digits so break */ - if (digidx == -1) { - break; - } - /* read next digit and reset bitcnt */ - buf = X->dp[digidx--]; - bitcnt = (int)DIGIT_BIT; - } - - /* grab the next msb from the exponent */ - y = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1; - buf <<= (mp_digit)1; - - /* if the bit is zero and mode == 0 then we ignore it - * These represent the leading zero bits before the first 1 bit - * in the exponent. Technically this opt is not required but it - * does lower the # of trivial squaring/reductions used - */ - if (mode == 0 && y == 0) { - continue; - } - - /* if the bit is zero and mode == 1 then we square */ - if (mode == 1 && y == 0) { - if ((err = mp_sqr (&res, &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, mp)) != MP_OKAY) { - goto LBL_RES; - } - continue; - } - - /* else we add it to the window */ - bitbuf |= (y << (winsize - ++bitcpy)); - mode = 2; - - if (bitcpy == winsize) { - /* ok window is filled so square as required and multiply */ - /* square first */ - for (x = 0; x < winsize; x++) { - if ((err = mp_sqr (&res, &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, mp)) != MP_OKAY) { - goto LBL_RES; - } - } - - /* then multiply */ - if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, mp)) != MP_OKAY) { - goto LBL_RES; - } - - /* empty window and reset */ - bitcpy = 0; - bitbuf = 0; - mode = 1; - } - } - - /* if bits remain then square/multiply */ - if (mode == 2 && bitcpy > 0) { - /* square then multiply if the bit is set */ - for (x = 0; x < bitcpy; x++) { - if ((err = mp_sqr (&res, &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, mp)) != MP_OKAY) { - goto LBL_RES; - } - - /* get next bit of the window */ - bitbuf <<= 1; - if ((bitbuf & (1 << winsize)) != 0) { - /* then multiply */ - if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, mp)) != MP_OKAY) { - goto LBL_RES; - } - } - } - } - - if (redmode == 0) { - /* fixup result if Montgomery reduction is used - * recall that any value in a Montgomery system is - * actually multiplied by R mod n. So we have - * to reduce one more time to cancel out the factor - * of R. - */ - if ((err = redux(&res, P, mp)) != MP_OKAY) { - goto LBL_RES; - } - } - - /* swap res with Y */ - mp_exch (&res, Y); - err = MP_OKAY; -LBL_RES:mp_clear (&res); -LBL_M: - mp_clear(&M[1]); - for (x = 1<<(winsize-1); x < (1 << winsize); x++) { - mp_clear (&M[x]); - } - return err; -} -#endif - - -#ifdef BN_FAST_S_MP_SQR_C -/* the jist of squaring... - * you do like mult except the offset of the tmpx [one that - * starts closer to zero] can't equal the offset of tmpy. - * So basically you set up iy like before then you min it with - * (ty-tx) so that it never happens. You double all those - * you add in the inner loop - -After that loop you do the squares and add them in. -*/ - -static int fast_s_mp_sqr (mp_int * a, mp_int * b) -{ - int olduse, res, pa, ix, iz; - mp_digit W[MP_WARRAY], *tmpx; - mp_word W1; - - /* grow the destination as required */ - pa = a->used + a->used; - if (b->alloc < pa) { - if ((res = mp_grow (b, pa)) != MP_OKAY) { - return res; - } - } - - /* number of output digits to produce */ - W1 = 0; - for (ix = 0; ix < pa; ix++) { - int tx, ty, iy; - mp_word _W; - mp_digit *tmpy; - - /* clear counter */ - _W = 0; - - /* get offsets into the two bignums */ - ty = MIN(a->used-1, ix); - tx = ix - ty; - - /* setup temp aliases */ - tmpx = a->dp + tx; - tmpy = a->dp + ty; - - /* this is the number of times the loop will iterrate, essentially - while (tx++ < a->used && ty-- >= 0) { ... } - */ - iy = MIN(a->used-tx, ty+1); - - /* now for squaring tx can never equal ty - * we halve the distance since they approach at a rate of 2x - * and we have to round because odd cases need to be executed - */ - iy = MIN(iy, (ty-tx+1)>>1); - - /* execute loop */ - for (iz = 0; iz < iy; iz++) { - _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); - } - - /* double the inner product and add carry */ - _W = _W + _W + W1; - - /* even columns have the square term in them */ - if ((ix&1) == 0) { - _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]); - } - - /* store it */ - W[ix] = (mp_digit)(_W & MP_MASK); - - /* make next carry */ - W1 = _W >> ((mp_word)DIGIT_BIT); - } - - /* setup dest */ - olduse = b->used; - b->used = a->used+a->used; - - { - mp_digit *tmpb; - tmpb = b->dp; - for (ix = 0; ix < pa; ix++) { - *tmpb++ = W[ix] & MP_MASK; - } - - /* clear unused digits [that existed in the old copy of c] */ - for (; ix < olduse; ix++) { - *tmpb++ = 0; - } - } - mp_clamp (b); - return MP_OKAY; -} -#endif - - -#ifdef BN_MP_MUL_D_C -/* multiply by a digit */ -static int -mp_mul_d (mp_int * a, mp_digit b, mp_int * c) -{ - mp_digit u, *tmpa, *tmpc; - mp_word r; - int ix, res, olduse; - - /* make sure c is big enough to hold a*b */ - if (c->alloc < a->used + 1) { - if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) { - return res; - } - } - - /* get the original destinations used count */ - olduse = c->used; - - /* set the sign */ - c->sign = a->sign; - - /* alias for a->dp [source] */ - tmpa = a->dp; - - /* alias for c->dp [dest] */ - tmpc = c->dp; - - /* zero carry */ - u = 0; - - /* compute columns */ - for (ix = 0; ix < a->used; ix++) { - /* compute product and carry sum for this term */ - r = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b); - - /* mask off higher bits to get a single digit */ - *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK)); - - /* send carry into next iteration */ - u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); - } - - /* store final carry [if any] and increment ix offset */ - *tmpc++ = u; - ++ix; - - /* now zero digits above the top */ - while (ix++ < olduse) { - *tmpc++ = 0; - } - - /* set used count */ - c->used = a->used + 1; - mp_clamp(c); - - return MP_OKAY; -} -#endif diff --git a/contrib/hostapd/src/tls/rsa.c b/contrib/hostapd/src/tls/rsa.c deleted file mode 100644 index 4965a2a311..0000000000 --- a/contrib/hostapd/src/tls/rsa.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - * RSA - * Copyright (c) 2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto.h" -#include "asn1.h" -#include "bignum.h" -#include "rsa.h" - - -struct crypto_rsa_key { - int private_key; /* whether private key is set */ - struct bignum *n; /* modulus (p * q) */ - struct bignum *e; /* public exponent */ - /* The following parameters are available only if private_key is set */ - struct bignum *d; /* private exponent */ - struct bignum *p; /* prime p (factor of n) */ - struct bignum *q; /* prime q (factor of n) */ - struct bignum *dmp1; /* d mod (p - 1); CRT exponent */ - struct bignum *dmq1; /* d mod (q - 1); CRT exponent */ - struct bignum *iqmp; /* 1 / q mod p; CRT coefficient */ -}; - - -#ifdef EAP_TLS_FUNCS -static const u8 * crypto_rsa_parse_integer(const u8 *pos, const u8 *end, - struct bignum *num) -{ - struct asn1_hdr hdr; - - if (pos == NULL) - return NULL; - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { - wpa_printf(MSG_DEBUG, "RSA: Expected INTEGER - found class %d " - "tag 0x%x", hdr.class, hdr.tag); - return NULL; - } - - if (bignum_set_unsigned_bin(num, hdr.payload, hdr.length) < 0) { - wpa_printf(MSG_DEBUG, "RSA: Failed to parse INTEGER"); - return NULL; - } - - return hdr.payload + hdr.length; -} - - -/** - * crypto_rsa_import_public_key - Import an RSA public key - * @buf: Key buffer (DER encoded RSA public key) - * @len: Key buffer length in bytes - * Returns: Pointer to the public key or %NULL on failure - */ -struct crypto_rsa_key * -crypto_rsa_import_public_key(const u8 *buf, size_t len) -{ - struct crypto_rsa_key *key; - struct asn1_hdr hdr; - const u8 *pos, *end; - - key = os_zalloc(sizeof(*key)); - if (key == NULL) - return NULL; - - key->n = bignum_init(); - key->e = bignum_init(); - if (key->n == NULL || key->e == NULL) { - crypto_rsa_free(key); - return NULL; - } - - /* - * PKCS #1, 7.1: - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER -- e - * } - */ - - if (asn1_get_next(buf, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "RSA: Expected SEQUENCE " - "(public key) - found class %d tag 0x%x", - hdr.class, hdr.tag); - goto error; - } - pos = hdr.payload; - end = pos + hdr.length; - - pos = crypto_rsa_parse_integer(pos, end, key->n); - pos = crypto_rsa_parse_integer(pos, end, key->e); - - if (pos == NULL) - goto error; - - if (pos != end) { - wpa_hexdump(MSG_DEBUG, - "RSA: Extra data in public key SEQUENCE", - pos, end - pos); - goto error; - } - - return key; - -error: - crypto_rsa_free(key); - return NULL; -} - - -/** - * crypto_rsa_import_private_key - Import an RSA private key - * @buf: Key buffer (DER encoded RSA private key) - * @len: Key buffer length in bytes - * Returns: Pointer to the private key or %NULL on failure - */ -struct crypto_rsa_key * -crypto_rsa_import_private_key(const u8 *buf, size_t len) -{ - struct crypto_rsa_key *key; - struct bignum *zero; - struct asn1_hdr hdr; - const u8 *pos, *end; - - key = os_zalloc(sizeof(*key)); - if (key == NULL) - return NULL; - - key->private_key = 1; - - key->n = bignum_init(); - key->e = bignum_init(); - key->d = bignum_init(); - key->p = bignum_init(); - key->q = bignum_init(); - key->dmp1 = bignum_init(); - key->dmq1 = bignum_init(); - key->iqmp = bignum_init(); - - if (key->n == NULL || key->e == NULL || key->d == NULL || - key->p == NULL || key->q == NULL || key->dmp1 == NULL || - key->dmq1 == NULL || key->iqmp == NULL) { - crypto_rsa_free(key); - return NULL; - } - - /* - * PKCS #1, 7.2: - * RSAPrivateKey ::= SEQUENCE { - * version Version, - * modulus INTEGER, -- n - * publicExponent INTEGER, -- e - * privateExponent INTEGER, -- d - * prime1 INTEGER, -- p - * prime2 INTEGER, -- q - * exponent1 INTEGER, -- d mod (p-1) - * exponent2 INTEGER, -- d mod (q-1) - * coefficient INTEGER -- (inverse of q) mod p - * } - * - * Version ::= INTEGER -- shall be 0 for this version of the standard - */ - if (asn1_get_next(buf, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "RSA: Expected SEQUENCE " - "(public key) - found class %d tag 0x%x", - hdr.class, hdr.tag); - goto error; - } - pos = hdr.payload; - end = pos + hdr.length; - - zero = bignum_init(); - if (zero == NULL) - goto error; - pos = crypto_rsa_parse_integer(pos, end, zero); - if (pos == NULL || bignum_cmp_d(zero, 0) != 0) { - wpa_printf(MSG_DEBUG, "RSA: Expected zero INTEGER in the " - "beginning of private key; not found"); - bignum_deinit(zero); - goto error; - } - bignum_deinit(zero); - - pos = crypto_rsa_parse_integer(pos, end, key->n); - pos = crypto_rsa_parse_integer(pos, end, key->e); - pos = crypto_rsa_parse_integer(pos, end, key->d); - pos = crypto_rsa_parse_integer(pos, end, key->p); - pos = crypto_rsa_parse_integer(pos, end, key->q); - pos = crypto_rsa_parse_integer(pos, end, key->dmp1); - pos = crypto_rsa_parse_integer(pos, end, key->dmq1); - pos = crypto_rsa_parse_integer(pos, end, key->iqmp); - - if (pos == NULL) - goto error; - - if (pos != end) { - wpa_hexdump(MSG_DEBUG, - "RSA: Extra data in public key SEQUENCE", - pos, end - pos); - goto error; - } - - return key; - -error: - crypto_rsa_free(key); - return NULL; -} -#endif /* EAP_TLS_FUNCS */ - - -/** - * crypto_rsa_get_modulus_len - Get the modulus length of the RSA key - * @key: RSA key - * Returns: Modulus length of the key - */ -size_t crypto_rsa_get_modulus_len(struct crypto_rsa_key *key) -{ - return bignum_get_unsigned_bin_len(key->n); -} - - -/** - * crypto_rsa_exptmod - RSA modular exponentiation - * @in: Input data - * @inlen: Input data length - * @out: Buffer for output data - * @outlen: Maximum size of the output buffer and used size on success - * @key: RSA key - * @use_private: 1 = Use RSA private key, 0 = Use RSA public key - * Returns: 0 on success, -1 on failure - */ -int crypto_rsa_exptmod(const u8 *in, size_t inlen, u8 *out, size_t *outlen, - struct crypto_rsa_key *key, int use_private) -{ - struct bignum *tmp, *a = NULL, *b = NULL; - int ret = -1; - size_t modlen; - - if (use_private && !key->private_key) - return -1; - - tmp = bignum_init(); - if (tmp == NULL) - return -1; - - if (bignum_set_unsigned_bin(tmp, in, inlen) < 0) - goto error; - if (bignum_cmp(key->n, tmp) < 0) { - /* Too large input value for the RSA key modulus */ - goto error; - } - - if (use_private) { - /* - * Decrypt (or sign) using Chinese remainer theorem to speed - * up calculation. This is equivalent to tmp = tmp^d mod n - * (which would require more CPU to calculate directly). - * - * dmp1 = (1/e) mod (p-1) - * dmq1 = (1/e) mod (q-1) - * iqmp = (1/q) mod p, where p > q - * m1 = c^dmp1 mod p - * m2 = c^dmq1 mod q - * h = q^-1 (m1 - m2) mod p - * m = m2 + hq - */ - a = bignum_init(); - b = bignum_init(); - if (a == NULL || b == NULL) - goto error; - - /* a = tmp^dmp1 mod p */ - if (bignum_exptmod(tmp, key->dmp1, key->p, a) < 0) - goto error; - - /* b = tmp^dmq1 mod q */ - if (bignum_exptmod(tmp, key->dmq1, key->q, b) < 0) - goto error; - - /* tmp = (a - b) * (1/q mod p) (mod p) */ - if (bignum_sub(a, b, tmp) < 0 || - bignum_mulmod(tmp, key->iqmp, key->p, tmp) < 0) - goto error; - - /* tmp = b + q * tmp */ - if (bignum_mul(tmp, key->q, tmp) < 0 || - bignum_add(tmp, b, tmp) < 0) - goto error; - } else { - /* Encrypt (or verify signature) */ - /* tmp = tmp^e mod N */ - if (bignum_exptmod(tmp, key->e, key->n, tmp) < 0) - goto error; - } - - modlen = crypto_rsa_get_modulus_len(key); - if (modlen > *outlen) { - *outlen = modlen; - goto error; - } - - if (bignum_get_unsigned_bin_len(tmp) > modlen) - goto error; /* should never happen */ - - *outlen = modlen; - os_memset(out, 0, modlen); - if (bignum_get_unsigned_bin( - tmp, out + - (modlen - bignum_get_unsigned_bin_len(tmp)), NULL) < 0) - goto error; - - ret = 0; - -error: - bignum_deinit(tmp); - bignum_deinit(a); - bignum_deinit(b); - return ret; -} - - -/** - * crypto_rsa_free - Free RSA key - * @key: RSA key to be freed - * - * This function frees an RSA key imported with either - * crypto_rsa_import_public_key() or crypto_rsa_import_private_key(). - */ -void crypto_rsa_free(struct crypto_rsa_key *key) -{ - if (key) { - bignum_deinit(key->n); - bignum_deinit(key->e); - bignum_deinit(key->d); - bignum_deinit(key->p); - bignum_deinit(key->q); - bignum_deinit(key->dmp1); - bignum_deinit(key->dmq1); - bignum_deinit(key->iqmp); - os_free(key); - } -} diff --git a/contrib/hostapd/src/tls/rsa.h b/contrib/hostapd/src/tls/rsa.h deleted file mode 100644 index ac50dfd69d..0000000000 --- a/contrib/hostapd/src/tls/rsa.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * RSA - * Copyright (c) 2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef RSA_H -#define RSA_H - -struct crypto_rsa_key; - -struct crypto_rsa_key * -crypto_rsa_import_public_key(const u8 *buf, size_t len); -struct crypto_rsa_key * -crypto_rsa_import_private_key(const u8 *buf, size_t len); -size_t crypto_rsa_get_modulus_len(struct crypto_rsa_key *key); -int crypto_rsa_exptmod(const u8 *in, size_t inlen, u8 *out, size_t *outlen, - struct crypto_rsa_key *key, int use_private); -void crypto_rsa_free(struct crypto_rsa_key *key); - -#endif /* RSA_H */ diff --git a/contrib/hostapd/src/tls/tlsv1_client.c b/contrib/hostapd/src/tls/tlsv1_client.c deleted file mode 100644 index 0bf11742ca..0000000000 --- a/contrib/hostapd/src/tls/tlsv1_client.c +++ /dev/null @@ -1,671 +0,0 @@ -/* - * TLSv1 client (RFC 2246) - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha1.h" -#include "tls.h" -#include "tlsv1_common.h" -#include "tlsv1_record.h" -#include "tlsv1_client.h" -#include "tlsv1_client_i.h" - -/* TODO: - * Support for a message fragmented across several records (RFC 2246, 6.2.1) - */ - - -void tls_alert(struct tlsv1_client *conn, u8 level, u8 description) -{ - conn->alert_level = level; - conn->alert_description = description; -} - - -void tlsv1_client_free_dh(struct tlsv1_client *conn) -{ - os_free(conn->dh_p); - os_free(conn->dh_g); - os_free(conn->dh_ys); - conn->dh_p = conn->dh_g = conn->dh_ys = NULL; -} - - -int tls_derive_pre_master_secret(u8 *pre_master_secret) -{ - WPA_PUT_BE16(pre_master_secret, TLS_VERSION); - if (os_get_random(pre_master_secret + 2, - TLS_PRE_MASTER_SECRET_LEN - 2)) - return -1; - return 0; -} - - -int tls_derive_keys(struct tlsv1_client *conn, - const u8 *pre_master_secret, size_t pre_master_secret_len) -{ - u8 seed[2 * TLS_RANDOM_LEN]; - u8 key_block[TLS_MAX_KEY_BLOCK_LEN]; - u8 *pos; - size_t key_block_len; - - if (pre_master_secret) { - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret", - pre_master_secret, pre_master_secret_len); - os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, - TLS_RANDOM_LEN); - if (tls_prf(pre_master_secret, pre_master_secret_len, - "master secret", seed, 2 * TLS_RANDOM_LEN, - conn->master_secret, TLS_MASTER_SECRET_LEN)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive " - "master_secret"); - return -1; - } - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret", - conn->master_secret, TLS_MASTER_SECRET_LEN); - } - - os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN); - key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len + - conn->rl.iv_size); - if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, - "key expansion", seed, 2 * TLS_RANDOM_LEN, - key_block, key_block_len)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block"); - return -1; - } - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block", - key_block, key_block_len); - - pos = key_block; - - /* client_write_MAC_secret */ - os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size); - pos += conn->rl.hash_size; - /* server_write_MAC_secret */ - os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size); - pos += conn->rl.hash_size; - - /* client_write_key */ - os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len); - pos += conn->rl.key_material_len; - /* server_write_key */ - os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len); - pos += conn->rl.key_material_len; - - /* client_write_IV */ - os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size); - pos += conn->rl.iv_size; - /* server_write_IV */ - os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size); - pos += conn->rl.iv_size; - - return 0; -} - - -/** - * tlsv1_client_handshake - Process TLS handshake - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @in_data: Input data from TLS peer - * @in_len: Input data length - * @out_len: Length of the output buffer. - * @appl_data: Pointer to application data pointer, or %NULL if dropped - * @appl_data_len: Pointer to variable that is set to appl_data length - * Returns: Pointer to output data, %NULL on failure - */ -u8 * tlsv1_client_handshake(struct tlsv1_client *conn, - const u8 *in_data, size_t in_len, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len) -{ - const u8 *pos, *end; - u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct; - size_t in_msg_len; - int no_appl_data; - - if (conn->state == CLIENT_HELLO) { - if (in_len) - return NULL; - return tls_send_client_hello(conn, out_len); - } - - if (in_data == NULL || in_len == 0) - return NULL; - - pos = in_data; - end = in_data + in_len; - in_msg = os_malloc(in_len); - if (in_msg == NULL) - return NULL; - - /* Each received packet may include multiple records */ - while (pos < end) { - in_msg_len = in_len; - if (tlsv1_record_receive(&conn->rl, pos, end - pos, - in_msg, &in_msg_len, &alert)) { - wpa_printf(MSG_DEBUG, "TLSv1: Processing received " - "record failed"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); - goto failed; - } - ct = pos[0]; - - in_pos = in_msg; - in_end = in_msg + in_msg_len; - - /* Each received record may include multiple messages of the - * same ContentType. */ - while (in_pos < in_end) { - in_msg_len = in_end - in_pos; - if (tlsv1_client_process_handshake(conn, ct, in_pos, - &in_msg_len, - appl_data, - appl_data_len) < 0) - goto failed; - in_pos += in_msg_len; - } - - pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); - } - - os_free(in_msg); - in_msg = NULL; - - no_appl_data = appl_data == NULL || *appl_data == NULL; - msg = tlsv1_client_handshake_write(conn, out_len, no_appl_data); - -failed: - os_free(in_msg); - if (conn->alert_level) { - conn->state = FAILED; - os_free(msg); - msg = tlsv1_client_send_alert(conn, conn->alert_level, - conn->alert_description, - out_len); - } else if (msg == NULL) { - msg = os_zalloc(1); - *out_len = 0; - } - - return msg; -} - - -/** - * tlsv1_client_encrypt - Encrypt data into TLS tunnel - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @in_data: Pointer to plaintext data to be encrypted - * @in_len: Input buffer length - * @out_data: Pointer to output buffer (encrypted TLS data) - * @out_len: Maximum out_data length - * Returns: Number of bytes written to out_data, -1 on failure - * - * This function is used after TLS handshake has been completed successfully to - * send data in the encrypted tunnel. - */ -int tlsv1_client_encrypt(struct tlsv1_client *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - size_t rlen; - - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData", - in_data, in_len); - - os_memcpy(out_data + TLS_RECORD_HEADER_LEN, in_data, in_len); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA, - out_data, out_len, in_len, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - return rlen; -} - - -/** - * tlsv1_client_decrypt - Decrypt data from TLS tunnel - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @in_data: Pointer to input buffer (encrypted TLS data) - * @in_len: Input buffer length - * @out_data: Pointer to output buffer (decrypted data from TLS tunnel) - * @out_len: Maximum out_data length - * Returns: Number of bytes written to out_data, -1 on failure - * - * This function is used after TLS handshake has been completed successfully to - * receive data from the encrypted tunnel. - */ -int tlsv1_client_decrypt(struct tlsv1_client *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - const u8 *in_end, *pos; - int res; - u8 alert, *out_end, *out_pos; - size_t olen; - - pos = in_data; - in_end = in_data + in_len; - out_pos = out_data; - out_end = out_data + out_len; - - while (pos < in_end) { - if (pos[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type " - "0x%x", pos[0]); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - olen = out_end - out_pos; - res = tlsv1_record_receive(&conn->rl, pos, in_end - pos, - out_pos, &olen, &alert); - if (res < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing " - "failed"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); - return -1; - } - out_pos += olen; - if (out_pos > out_end) { - wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough " - "for processing the received record"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); - } - - return out_pos - out_data; -} - - -/** - * tlsv1_client_global_init - Initialize TLSv1 client - * Returns: 0 on success, -1 on failure - * - * This function must be called before using any other TLSv1 client functions. - */ -int tlsv1_client_global_init(void) -{ - return crypto_global_init(); -} - - -/** - * tlsv1_client_global_deinit - Deinitialize TLSv1 client - * - * This function can be used to deinitialize the TLSv1 client that was - * initialized by calling tlsv1_client_global_init(). No TLSv1 client functions - * can be called after this before calling tlsv1_client_global_init() again. - */ -void tlsv1_client_global_deinit(void) -{ - crypto_global_deinit(); -} - - -/** - * tlsv1_client_init - Initialize TLSv1 client connection - * Returns: Pointer to TLSv1 client connection data or %NULL on failure - */ -struct tlsv1_client * tlsv1_client_init(void) -{ - struct tlsv1_client *conn; - size_t count; - u16 *suites; - - conn = os_zalloc(sizeof(*conn)); - if (conn == NULL) - return NULL; - - conn->state = CLIENT_HELLO; - - if (tls_verify_hash_init(&conn->verify) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify " - "hash"); - os_free(conn); - return NULL; - } - - count = 0; - suites = conn->cipher_suites; -#ifndef CONFIG_CRYPTO_INTERNAL - suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; -#endif /* CONFIG_CRYPTO_INTERNAL */ - suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; - suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; - suites[count++] = TLS_RSA_WITH_RC4_128_SHA; - suites[count++] = TLS_RSA_WITH_RC4_128_MD5; - conn->num_cipher_suites = count; - - return conn; -} - - -/** - * tlsv1_client_deinit - Deinitialize TLSv1 client connection - * @conn: TLSv1 client connection data from tlsv1_client_init() - */ -void tlsv1_client_deinit(struct tlsv1_client *conn) -{ - crypto_public_key_free(conn->server_rsa_key); - tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); - tlsv1_record_change_write_cipher(&conn->rl); - tlsv1_record_change_read_cipher(&conn->rl); - tls_verify_hash_free(&conn->verify); - os_free(conn->client_hello_ext); - tlsv1_client_free_dh(conn); - tlsv1_cred_free(conn->cred); - os_free(conn); -} - - -/** - * tlsv1_client_established - Check whether connection has been established - * @conn: TLSv1 client connection data from tlsv1_client_init() - * Returns: 1 if connection is established, 0 if not - */ -int tlsv1_client_established(struct tlsv1_client *conn) -{ - return conn->state == ESTABLISHED; -} - - -/** - * tlsv1_client_prf - Use TLS-PRF to derive keying material - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @label: Label (e.g., description of the key) for PRF - * @server_random_first: seed is 0 = client_random|server_random, - * 1 = server_random|client_random - * @out: Buffer for output data from TLS-PRF - * @out_len: Length of the output buffer - * Returns: 0 on success, -1 on failure - */ -int tlsv1_client_prf(struct tlsv1_client *conn, const char *label, - int server_random_first, u8 *out, size_t out_len) -{ - u8 seed[2 * TLS_RANDOM_LEN]; - - if (conn->state != ESTABLISHED) - return -1; - - if (server_random_first) { - os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, - TLS_RANDOM_LEN); - } else { - os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, - TLS_RANDOM_LEN); - } - - return tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, - label, seed, 2 * TLS_RANDOM_LEN, out, out_len); -} - - -/** - * tlsv1_client_get_cipher - Get current cipher name - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @buf: Buffer for the cipher name - * @buflen: buf size - * Returns: 0 on success, -1 on failure - * - * Get the name of the currently used cipher. - */ -int tlsv1_client_get_cipher(struct tlsv1_client *conn, char *buf, - size_t buflen) -{ - char *cipher; - - switch (conn->rl.cipher_suite) { - case TLS_RSA_WITH_RC4_128_MD5: - cipher = "RC4-MD5"; - break; - case TLS_RSA_WITH_RC4_128_SHA: - cipher = "RC4-SHA"; - break; - case TLS_RSA_WITH_DES_CBC_SHA: - cipher = "DES-CBC-SHA"; - break; - case TLS_RSA_WITH_3DES_EDE_CBC_SHA: - cipher = "DES-CBC3-SHA"; - break; - case TLS_DH_anon_WITH_AES_128_CBC_SHA: - cipher = "ADH-AES-128-SHA"; - break; - case TLS_RSA_WITH_AES_256_CBC_SHA: - cipher = "AES-256-SHA"; - break; - case TLS_RSA_WITH_AES_128_CBC_SHA: - cipher = "AES-128-SHA"; - break; - default: - return -1; - } - - if (os_strlcpy(buf, cipher, buflen) >= buflen) - return -1; - return 0; -} - - -/** - * tlsv1_client_shutdown - Shutdown TLS connection - * @conn: TLSv1 client connection data from tlsv1_client_init() - * Returns: 0 on success, -1 on failure - */ -int tlsv1_client_shutdown(struct tlsv1_client *conn) -{ - conn->state = CLIENT_HELLO; - - if (tls_verify_hash_init(&conn->verify) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify " - "hash"); - return -1; - } - - tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); - tlsv1_record_change_write_cipher(&conn->rl); - tlsv1_record_change_read_cipher(&conn->rl); - - conn->certificate_requested = 0; - crypto_public_key_free(conn->server_rsa_key); - conn->server_rsa_key = NULL; - conn->session_resumed = 0; - - return 0; -} - - -/** - * tlsv1_client_resumed - Was session resumption used - * @conn: TLSv1 client connection data from tlsv1_client_init() - * Returns: 1 if current session used session resumption, 0 if not - */ -int tlsv1_client_resumed(struct tlsv1_client *conn) -{ - return !!conn->session_resumed; -} - - -/** - * tlsv1_client_hello_ext - Set TLS extension for ClientHello - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @ext_type: Extension type - * @data: Extension payload (%NULL to remove extension) - * @data_len: Extension payload length - * Returns: 0 on success, -1 on failure - */ -int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type, - const u8 *data, size_t data_len) -{ - u8 *pos; - - conn->session_ticket_included = 0; - os_free(conn->client_hello_ext); - conn->client_hello_ext = NULL; - conn->client_hello_ext_len = 0; - - if (data == NULL || data_len == 0) - return 0; - - pos = conn->client_hello_ext = os_malloc(6 + data_len); - if (pos == NULL) - return -1; - - WPA_PUT_BE16(pos, 4 + data_len); - pos += 2; - WPA_PUT_BE16(pos, ext_type); - pos += 2; - WPA_PUT_BE16(pos, data_len); - pos += 2; - os_memcpy(pos, data, data_len); - conn->client_hello_ext_len = 6 + data_len; - - if (ext_type == TLS_EXT_PAC_OPAQUE) { - conn->session_ticket_included = 1; - wpa_printf(MSG_DEBUG, "TLSv1: Using session ticket"); - } - - return 0; -} - - -/** - * tlsv1_client_get_keys - Get master key and random data from TLS connection - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @keys: Structure of key/random data (filled on success) - * Returns: 0 on success, -1 on failure - */ -int tlsv1_client_get_keys(struct tlsv1_client *conn, struct tls_keys *keys) -{ - os_memset(keys, 0, sizeof(*keys)); - if (conn->state == CLIENT_HELLO) - return -1; - - keys->client_random = conn->client_random; - keys->client_random_len = TLS_RANDOM_LEN; - - if (conn->state != SERVER_HELLO) { - keys->server_random = conn->server_random; - keys->server_random_len = TLS_RANDOM_LEN; - keys->master_key = conn->master_secret; - keys->master_key_len = TLS_MASTER_SECRET_LEN; - } - - return 0; -} - - -/** - * tlsv1_client_get_keyblock_size - Get TLS key_block size - * @conn: TLSv1 client connection data from tlsv1_client_init() - * Returns: Size of the key_block for the negotiated cipher suite or -1 on - * failure - */ -int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn) -{ - if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO) - return -1; - - return 2 * (conn->rl.hash_size + conn->rl.key_material_len + - conn->rl.iv_size); -} - - -/** - * tlsv1_client_set_cipher_list - Configure acceptable cipher suites - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers - * (TLS_CIPHER_*). - * Returns: 0 on success, -1 on failure - */ -int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers) -{ -#ifdef EAP_FAST - size_t count; - u16 *suites; - - /* TODO: implement proper configuration of cipher suites */ - if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) { - count = 0; - suites = conn->cipher_suites; -#ifndef CONFIG_CRYPTO_INTERNAL - suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA; -#endif /* CONFIG_CRYPTO_INTERNAL */ - suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; - suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA; - suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5; - suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA; - - /* - * Cisco AP (at least 350 and 1200 series) local authentication - * server does not know how to search cipher suites from the - * list and seem to require that the last entry in the list is - * the one that it wants to use. However, TLS specification - * requires the list to be in the client preference order. As a - * workaround, add anon-DH AES-128-SHA1 again at the end of the - * list to allow the Cisco code to find it. - */ - suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; - conn->num_cipher_suites = count; - } - - return 0; -#else /* EAP_FAST */ - return -1; -#endif /* EAP_FAST */ -} - - -/** - * tlsv1_client_set_cred - Set client credentials - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @cred: Credentials from tlsv1_cred_alloc() - * Returns: 0 on success, -1 on failure - * - * On success, the client takes ownership of the credentials block and caller - * must not free it. On failure, caller is responsible for freeing the - * credential block. - */ -int tlsv1_client_set_cred(struct tlsv1_client *conn, - struct tlsv1_credentials *cred) -{ - tlsv1_cred_free(conn->cred); - conn->cred = cred; - return 0; -} - - -void tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn, - tlsv1_client_session_ticket_cb cb, - void *ctx) -{ - wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)", - cb, ctx); - conn->session_ticket_cb = cb; - conn->session_ticket_cb_ctx = ctx; -} diff --git a/contrib/hostapd/src/tls/tlsv1_client.h b/contrib/hostapd/src/tls/tlsv1_client.h deleted file mode 100644 index 16ad57d400..0000000000 --- a/contrib/hostapd/src/tls/tlsv1_client.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * TLSv1 client (RFC 2246) - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TLSV1_CLIENT_H -#define TLSV1_CLIENT_H - -#include "tlsv1_cred.h" - -struct tlsv1_client; - -int tlsv1_client_global_init(void); -void tlsv1_client_global_deinit(void); -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, - 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, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len); -int tlsv1_client_encrypt(struct tlsv1_client *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len); -int tlsv1_client_decrypt(struct tlsv1_client *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len); -int tlsv1_client_get_cipher(struct tlsv1_client *conn, char *buf, - size_t buflen); -int tlsv1_client_shutdown(struct tlsv1_client *conn); -int tlsv1_client_resumed(struct tlsv1_client *conn); -int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type, - const u8 *data, size_t data_len); -int tlsv1_client_get_keys(struct tlsv1_client *conn, struct tls_keys *keys); -int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn); -int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers); -int tlsv1_client_set_cred(struct tlsv1_client *conn, - struct tlsv1_credentials *cred); - -typedef int (*tlsv1_client_session_ticket_cb) -(void *ctx, const u8 *ticket, size_t len, const u8 *client_random, - const u8 *server_random, u8 *master_secret); - -void tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn, - tlsv1_client_session_ticket_cb cb, - void *ctx); - -#endif /* TLSV1_CLIENT_H */ diff --git a/contrib/hostapd/src/tls/tlsv1_client_i.h b/contrib/hostapd/src/tls/tlsv1_client_i.h deleted file mode 100644 index 7fe179f10c..0000000000 --- a/contrib/hostapd/src/tls/tlsv1_client_i.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * TLSv1 client - internal structures - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TLSV1_CLIENT_I_H -#define TLSV1_CLIENT_I_H - -struct tlsv1_client { - enum { - CLIENT_HELLO, SERVER_HELLO, SERVER_CERTIFICATE, - SERVER_KEY_EXCHANGE, SERVER_CERTIFICATE_REQUEST, - SERVER_HELLO_DONE, CLIENT_KEY_EXCHANGE, CHANGE_CIPHER_SPEC, - SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, ACK_FINISHED, - ESTABLISHED, FAILED - } state; - - struct tlsv1_record_layer rl; - - u8 session_id[TLS_SESSION_ID_MAX_LEN]; - size_t session_id_len; - u8 client_random[TLS_RANDOM_LEN]; - u8 server_random[TLS_RANDOM_LEN]; - u8 master_secret[TLS_MASTER_SECRET_LEN]; - - u8 alert_level; - u8 alert_description; - - unsigned int certificate_requested:1; - unsigned int session_resumed:1; - unsigned int session_ticket_included:1; - unsigned int use_session_ticket:1; - - struct crypto_public_key *server_rsa_key; - - struct tls_verify_hash verify; - -#define MAX_CIPHER_COUNT 30 - u16 cipher_suites[MAX_CIPHER_COUNT]; - size_t num_cipher_suites; - - u16 prev_cipher_suite; - - u8 *client_hello_ext; - size_t client_hello_ext_len; - - /* The prime modulus used for Diffie-Hellman */ - u8 *dh_p; - size_t dh_p_len; - /* The generator used for Diffie-Hellman */ - u8 *dh_g; - size_t dh_g_len; - /* The server's Diffie-Hellman public value */ - u8 *dh_ys; - size_t dh_ys_len; - - struct tlsv1_credentials *cred; - - tlsv1_client_session_ticket_cb session_ticket_cb; - void *session_ticket_cb_ctx; -}; - - -void tls_alert(struct tlsv1_client *conn, u8 level, u8 description); -void tlsv1_client_free_dh(struct tlsv1_client *conn); -int tls_derive_pre_master_secret(u8 *pre_master_secret); -int tls_derive_keys(struct tlsv1_client *conn, - const u8 *pre_master_secret, size_t pre_master_secret_len); -u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len); -u8 * tlsv1_client_send_alert(struct tlsv1_client *conn, u8 level, - u8 description, size_t *out_len); -u8 * tlsv1_client_handshake_write(struct tlsv1_client *conn, size_t *out_len, - int no_appl_data); -int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct, - const u8 *buf, size_t *len, - u8 **out_data, size_t *out_len); - -#endif /* TLSV1_CLIENT_I_H */ diff --git a/contrib/hostapd/src/tls/tlsv1_client_read.c b/contrib/hostapd/src/tls/tlsv1_client_read.c deleted file mode 100644 index ee20330ce2..0000000000 --- a/contrib/hostapd/src/tls/tlsv1_client_read.c +++ /dev/null @@ -1,976 +0,0 @@ -/* - * TLSv1 client - read handshake message - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "md5.h" -#include "sha1.h" -#include "x509v3.h" -#include "tls.h" -#include "tlsv1_common.h" -#include "tlsv1_record.h" -#include "tlsv1_client.h" -#include "tlsv1_client_i.h" - -static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len); -static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len); -static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len); - - -static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len, i; - u16 cipher_suite; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " - "received content type 0x%x", ct); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) - goto decode_error; - - /* HandshakeType msg_type */ - if (*pos != TLS_HANDSHAKE_TYPE_SERVER_HELLO) { - wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " - "message %d (expected ServerHello)", *pos); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHello"); - pos++; - /* uint24 length */ - len = WPA_GET_BE24(pos); - pos += 3; - left -= 4; - - if (len > left) - goto decode_error; - - /* body - ServerHello */ - - wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello", pos, len); - end = pos + len; - - /* ProtocolVersion server_version */ - if (end - pos < 2) - goto decode_error; - if (WPA_GET_BE16(pos) != TLS_VERSION) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in " - "ServerHello"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_PROTOCOL_VERSION); - return -1; - } - pos += 2; - - /* Random random */ - if (end - pos < TLS_RANDOM_LEN) - goto decode_error; - - os_memcpy(conn->server_random, pos, TLS_RANDOM_LEN); - pos += TLS_RANDOM_LEN; - wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random", - conn->server_random, TLS_RANDOM_LEN); - - /* SessionID session_id */ - if (end - pos < 1) - goto decode_error; - if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN) - goto decode_error; - if (conn->session_id_len && conn->session_id_len == *pos && - os_memcmp(conn->session_id, pos + 1, conn->session_id_len) == 0) { - pos += 1 + conn->session_id_len; - wpa_printf(MSG_DEBUG, "TLSv1: Resuming old session"); - conn->session_resumed = 1; - } else { - conn->session_id_len = *pos; - pos++; - os_memcpy(conn->session_id, pos, conn->session_id_len); - pos += conn->session_id_len; - } - wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id", - conn->session_id, conn->session_id_len); - - /* CipherSuite cipher_suite */ - if (end - pos < 2) - goto decode_error; - cipher_suite = WPA_GET_BE16(pos); - pos += 2; - for (i = 0; i < conn->num_cipher_suites; i++) { - if (cipher_suite == conn->cipher_suites[i]) - break; - } - if (i == conn->num_cipher_suites) { - wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected " - "cipher suite 0x%04x", cipher_suite); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_ILLEGAL_PARAMETER); - return -1; - } - - if (conn->session_resumed && cipher_suite != conn->prev_cipher_suite) { - wpa_printf(MSG_DEBUG, "TLSv1: Server selected a different " - "cipher suite for a resumed connection (0x%04x != " - "0x%04x)", cipher_suite, conn->prev_cipher_suite); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_ILLEGAL_PARAMETER); - return -1; - } - - if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for " - "record layer"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - conn->prev_cipher_suite = cipher_suite; - - /* CompressionMethod compression_method */ - if (end - pos < 1) - goto decode_error; - if (*pos != TLS_COMPRESSION_NULL) { - wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected " - "compression 0x%02x", *pos); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_ILLEGAL_PARAMETER); - return -1; - } - pos++; - - if (end != pos) { - /* TODO: ServerHello extensions */ - wpa_hexdump(MSG_DEBUG, "TLSv1: Unexpected extra data in the " - "end of ServerHello", pos, end - pos); - goto decode_error; - } - - if (conn->session_ticket_included && conn->session_ticket_cb) { - /* TODO: include SessionTicket extension if one was included in - * ServerHello */ - int res = conn->session_ticket_cb( - conn->session_ticket_cb_ctx, NULL, 0, - conn->client_random, conn->server_random, - conn->master_secret); - if (res < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback " - "indicated failure"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_HANDSHAKE_FAILURE); - return -1; - } - conn->use_session_ticket = !!res; - } - - if ((conn->session_resumed || conn->use_session_ticket) && - tls_derive_keys(conn, NULL, 0)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - *in_len = end - in_data; - - conn->state = (conn->session_resumed || conn->use_session_ticket) ? - SERVER_CHANGE_CIPHER_SPEC : SERVER_CERTIFICATE; - - return 0; - -decode_error: - wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ServerHello"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; -} - - -static int tls_process_certificate(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len, list_len, cert_len, idx; - u8 type; - struct x509_certificate *chain = NULL, *last = NULL, *cert; - int reason; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " - "received content type 0x%x", ct); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message " - "(len=%lu)", (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - type = *pos++; - len = WPA_GET_BE24(pos); - pos += 3; - left -= 4; - - if (len > left) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message " - "length (len=%lu != left=%lu)", - (unsigned long) len, (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - if (type == TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) - return tls_process_server_key_exchange(conn, ct, in_data, - in_len); - if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) - return tls_process_certificate_request(conn, ct, in_data, - in_len); - if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) - return tls_process_server_hello_done(conn, ct, in_data, - in_len); - if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) { - wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " - "message %d (expected Certificate/" - "ServerKeyExchange/CertificateRequest/" - "ServerHelloDone)", type); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_printf(MSG_DEBUG, - "TLSv1: Received Certificate (certificate_list len %lu)", - (unsigned long) len); - - /* - * opaque ASN.1Cert<2^24-1>; - * - * struct { - * ASN.1Cert certificate_list<1..2^24-1>; - * } Certificate; - */ - - end = pos + len; - - if (end - pos < 3) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate " - "(left=%lu)", (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - list_len = WPA_GET_BE24(pos); - pos += 3; - - if ((size_t) (end - pos) != list_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list " - "length (len=%lu left=%lu)", - (unsigned long) list_len, - (unsigned long) (end - pos)); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - idx = 0; - while (pos < end) { - if (end - pos < 3) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " - "certificate_list"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - x509_certificate_chain_free(chain); - return -1; - } - - cert_len = WPA_GET_BE24(pos); - pos += 3; - - if ((size_t) (end - pos) < cert_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate " - "length (len=%lu left=%lu)", - (unsigned long) cert_len, - (unsigned long) (end - pos)); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - x509_certificate_chain_free(chain); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)", - (unsigned long) idx, (unsigned long) cert_len); - - if (idx == 0) { - crypto_public_key_free(conn->server_rsa_key); - if (tls_parse_cert(pos, cert_len, - &conn->server_rsa_key)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " - "the certificate"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_BAD_CERTIFICATE); - x509_certificate_chain_free(chain); - return -1; - } - } - - cert = x509_certificate_parse(pos, cert_len); - if (cert == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " - "the certificate"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_BAD_CERTIFICATE); - x509_certificate_chain_free(chain); - return -1; - } - - if (last == NULL) - chain = cert; - else - last->next = cert; - last = cert; - - idx++; - pos += cert_len; - } - - if (conn->cred && - x509_certificate_chain_validate(conn->cred->trusted_certs, chain, - &reason) < 0) { - int tls_reason; - wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain " - "validation failed (reason=%d)", reason); - switch (reason) { - case X509_VALIDATE_BAD_CERTIFICATE: - tls_reason = TLS_ALERT_BAD_CERTIFICATE; - break; - case X509_VALIDATE_UNSUPPORTED_CERTIFICATE: - tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE; - break; - case X509_VALIDATE_CERTIFICATE_REVOKED: - tls_reason = TLS_ALERT_CERTIFICATE_REVOKED; - break; - case X509_VALIDATE_CERTIFICATE_EXPIRED: - tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED; - break; - case X509_VALIDATE_CERTIFICATE_UNKNOWN: - tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN; - break; - case X509_VALIDATE_UNKNOWN_CA: - tls_reason = TLS_ALERT_UNKNOWN_CA; - break; - default: - tls_reason = TLS_ALERT_BAD_CERTIFICATE; - break; - } - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason); - x509_certificate_chain_free(chain); - return -1; - } - - x509_certificate_chain_free(chain); - - *in_len = end - in_data; - - conn->state = SERVER_KEY_EXCHANGE; - - return 0; -} - - -static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn, - const u8 *buf, size_t len) -{ - const u8 *pos, *end; - - tlsv1_client_free_dh(conn); - - pos = buf; - end = buf + len; - - if (end - pos < 3) - goto fail; - conn->dh_p_len = WPA_GET_BE16(pos); - pos += 2; - if (conn->dh_p_len == 0 || end - pos < (int) conn->dh_p_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Invalid dh_p length %lu", - (unsigned long) conn->dh_p_len); - goto fail; - } - conn->dh_p = os_malloc(conn->dh_p_len); - if (conn->dh_p == NULL) - goto fail; - os_memcpy(conn->dh_p, pos, conn->dh_p_len); - pos += conn->dh_p_len; - wpa_hexdump(MSG_DEBUG, "TLSv1: DH p (prime)", - conn->dh_p, conn->dh_p_len); - - if (end - pos < 3) - goto fail; - conn->dh_g_len = WPA_GET_BE16(pos); - pos += 2; - if (conn->dh_g_len == 0 || end - pos < (int) conn->dh_g_len) - goto fail; - conn->dh_g = os_malloc(conn->dh_g_len); - if (conn->dh_g == NULL) - goto fail; - os_memcpy(conn->dh_g, pos, conn->dh_g_len); - pos += conn->dh_g_len; - wpa_hexdump(MSG_DEBUG, "TLSv1: DH g (generator)", - conn->dh_g, conn->dh_g_len); - if (conn->dh_g_len == 1 && conn->dh_g[0] < 2) - goto fail; - - if (end - pos < 3) - goto fail; - conn->dh_ys_len = WPA_GET_BE16(pos); - pos += 2; - if (conn->dh_ys_len == 0 || end - pos < (int) conn->dh_ys_len) - goto fail; - conn->dh_ys = os_malloc(conn->dh_ys_len); - if (conn->dh_ys == NULL) - goto fail; - os_memcpy(conn->dh_ys, pos, conn->dh_ys_len); - pos += conn->dh_ys_len; - wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)", - conn->dh_ys, conn->dh_ys_len); - - return 0; - -fail: - wpa_printf(MSG_DEBUG, "TLSv1: Processing DH params failed"); - tlsv1_client_free_dh(conn); - return -1; -} - - -static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len; - u8 type; - const struct tls_cipher_suite *suite; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " - "received content type 0x%x", ct); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerKeyExchange " - "(Left=%lu)", (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - type = *pos++; - len = WPA_GET_BE24(pos); - pos += 3; - left -= 4; - - if (len > left) { - wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerKeyExchange " - "length (len=%lu != left=%lu)", - (unsigned long) len, (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - end = pos + len; - - if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) - return tls_process_certificate_request(conn, ct, in_data, - in_len); - if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) - return tls_process_server_hello_done(conn, ct, in_data, - in_len); - if (type != TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) { - wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " - "message %d (expected ServerKeyExchange/" - "CertificateRequest/ServerHelloDone)", type); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received ServerKeyExchange"); - - if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) { - wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not allowed " - "with the selected cipher suite"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_hexdump(MSG_DEBUG, "TLSv1: ServerKeyExchange", pos, len); - suite = tls_get_cipher_suite(conn->rl.cipher_suite); - if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) { - if (tlsv1_process_diffie_hellman(conn, pos, len) < 0) { - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - } else { - wpa_printf(MSG_DEBUG, "TLSv1: UnexpectedServerKeyExchange"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - *in_len = end - in_data; - - conn->state = SERVER_CERTIFICATE_REQUEST; - - return 0; -} - - -static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len; - u8 type; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " - "received content type 0x%x", ct); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateRequest " - "(left=%lu)", (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - type = *pos++; - len = WPA_GET_BE24(pos); - pos += 3; - left -= 4; - - if (len > left) { - wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in CertificateRequest " - "length (len=%lu != left=%lu)", - (unsigned long) len, (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - end = pos + len; - - if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) - return tls_process_server_hello_done(conn, ct, in_data, - in_len); - if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) { - wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " - "message %d (expected CertificateRequest/" - "ServerHelloDone)", type); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateRequest"); - - conn->certificate_requested = 1; - - *in_len = end - in_data; - - conn->state = SERVER_HELLO_DONE; - - return 0; -} - - -static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len; - u8 type; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " - "received content type 0x%x", ct); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerHelloDone " - "(left=%lu)", (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - type = *pos++; - len = WPA_GET_BE24(pos); - pos += 3; - left -= 4; - - if (len > left) { - wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerHelloDone " - "length (len=%lu != left=%lu)", - (unsigned long) len, (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - end = pos + len; - - if (type != TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) { - wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " - "message %d (expected ServerHelloDone)", type); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHelloDone"); - - *in_len = end - in_data; - - conn->state = CLIENT_KEY_EXCHANGE; - - return 0; -} - - -static int tls_process_server_change_cipher_spec(struct tlsv1_client *conn, - u8 ct, const u8 *in_data, - size_t *in_len) -{ - const u8 *pos; - size_t left; - - if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " - "received content type 0x%x", ct); - if (conn->use_session_ticket) { - int res; - wpa_printf(MSG_DEBUG, "TLSv1: Server may have " - "rejected SessionTicket"); - conn->use_session_ticket = 0; - - /* Notify upper layers that SessionTicket failed */ - res = conn->session_ticket_cb( - conn->session_ticket_cb_ctx, NULL, 0, NULL, - NULL, NULL); - if (res < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket " - "callback indicated failure"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_HANDSHAKE_FAILURE); - return -1; - } - - conn->state = SERVER_CERTIFICATE; - return tls_process_certificate(conn, ct, in_data, - in_len); - } - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 1) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - if (*pos != TLS_CHANGE_CIPHER_SPEC) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " - "received data 0x%x", *pos); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec"); - if (tlsv1_record_change_read_cipher(&conn->rl) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher " - "for record layer"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - *in_len = pos + 1 - in_data; - - conn->state = SERVER_FINISHED; - - return 0; -} - - -static int tls_process_server_finished(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len, hlen; - u8 verify_data[TLS_VERIFY_DATA_LEN]; - u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; " - "received content type 0x%x", ct); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for " - "Finished", - (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received " - "type 0x%x", pos[0]); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - len = WPA_GET_BE24(pos + 1); - - pos += 4; - left -= 4; - - if (len > left) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished " - "(len=%lu > left=%lu)", - (unsigned long) len, (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - end = pos + len; - if (len != TLS_VERIFY_DATA_LEN) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length " - "in Finished: %lu (expected %d)", - (unsigned long) len, TLS_VERIFY_DATA_LEN); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished", - pos, TLS_VERIFY_DATA_LEN); - - hlen = MD5_MAC_LEN; - if (conn->verify.md5_server == NULL || - crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) { - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - conn->verify.md5_server = NULL; - crypto_hash_finish(conn->verify.sha1_server, NULL, NULL); - conn->verify.sha1_server = NULL; - return -1; - } - conn->verify.md5_server = NULL; - hlen = SHA1_MAC_LEN; - if (conn->verify.sha1_server == NULL || - crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN, - &hlen) < 0) { - conn->verify.sha1_server = NULL; - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - conn->verify.sha1_server = NULL; - - if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, - "server finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, - verify_data, TLS_VERIFY_DATA_LEN)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECRYPT_ERROR); - return -1; - } - wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)", - verify_data, TLS_VERIFY_DATA_LEN); - - if (os_memcmp(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) { - wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data"); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received Finished"); - - *in_len = end - in_data; - - conn->state = (conn->session_resumed || conn->use_session_ticket) ? - CHANGE_CIPHER_SPEC : ACK_FINISHED; - - return 0; -} - - -static int tls_process_application_data(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len, - u8 **out_data, size_t *out_len) -{ - const u8 *pos; - size_t left; - - if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Application Data; " - "received content type 0x%x", ct); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - wpa_hexdump(MSG_DEBUG, "TLSv1: Application Data included in Handshake", - pos, left); - - *out_data = os_malloc(left); - if (*out_data) { - os_memcpy(*out_data, pos, left); - *out_len = left; - } - - return 0; -} - - -int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct, - const u8 *buf, size_t *len, - u8 **out_data, size_t *out_len) -{ - if (ct == TLS_CONTENT_TYPE_ALERT) { - if (*len < 2) { - wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d", - buf[0], buf[1]); - *len = 2; - conn->state = FAILED; - return -1; - } - - if (ct == TLS_CONTENT_TYPE_HANDSHAKE && *len >= 4 && - buf[0] == TLS_HANDSHAKE_TYPE_HELLO_REQUEST) { - size_t hr_len = WPA_GET_BE24(buf + 1); - if (hr_len > *len - 4) { - wpa_printf(MSG_DEBUG, "TLSv1: HelloRequest underflow"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - wpa_printf(MSG_DEBUG, "TLSv1: Ignored HelloRequest"); - *len = 4 + hr_len; - return 0; - } - - switch (conn->state) { - case SERVER_HELLO: - if (tls_process_server_hello(conn, ct, buf, len)) - return -1; - break; - case SERVER_CERTIFICATE: - if (tls_process_certificate(conn, ct, buf, len)) - return -1; - break; - case SERVER_KEY_EXCHANGE: - if (tls_process_server_key_exchange(conn, ct, buf, len)) - return -1; - break; - case SERVER_CERTIFICATE_REQUEST: - if (tls_process_certificate_request(conn, ct, buf, len)) - return -1; - break; - case SERVER_HELLO_DONE: - if (tls_process_server_hello_done(conn, ct, buf, len)) - return -1; - break; - case SERVER_CHANGE_CIPHER_SPEC: - if (tls_process_server_change_cipher_spec(conn, ct, buf, len)) - return -1; - break; - case SERVER_FINISHED: - if (tls_process_server_finished(conn, ct, buf, len)) - return -1; - break; - case ACK_FINISHED: - if (out_data && - tls_process_application_data(conn, ct, buf, len, out_data, - out_len)) - return -1; - break; - default: - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d " - "while processing received message", - conn->state); - return -1; - } - - if (ct == TLS_CONTENT_TYPE_HANDSHAKE) - tls_verify_hash_add(&conn->verify, buf, *len); - - return 0; -} diff --git a/contrib/hostapd/src/tls/tlsv1_client_write.c b/contrib/hostapd/src/tls/tlsv1_client_write.c deleted file mode 100644 index e0c95cbe8e..0000000000 --- a/contrib/hostapd/src/tls/tlsv1_client_write.c +++ /dev/null @@ -1,802 +0,0 @@ -/* - * TLSv1 client - write handshake message - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "md5.h" -#include "sha1.h" -#include "x509v3.h" -#include "tls.h" -#include "tlsv1_common.h" -#include "tlsv1_record.h" -#include "tlsv1_client.h" -#include "tlsv1_client_i.h" - - -static size_t tls_client_cert_chain_der_len(struct tlsv1_client *conn) -{ - size_t len = 0; - struct x509_certificate *cert; - - if (conn->cred == NULL) - return 0; - - cert = conn->cred->cert; - while (cert) { - len += 3 + cert->cert_len; - if (x509_certificate_self_signed(cert)) - break; - cert = x509_certificate_get_subject(conn->cred->trusted_certs, - &cert->issuer); - } - - return len; -} - - -u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len) -{ - u8 *hello, *end, *pos, *hs_length, *hs_start, *rhdr; - struct os_time now; - size_t len, i; - - wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello"); - *out_len = 0; - - os_get_time(&now); - WPA_PUT_BE32(conn->client_random, now.sec); - if (os_get_random(conn->client_random + 4, TLS_RANDOM_LEN - 4)) { - wpa_printf(MSG_ERROR, "TLSv1: Could not generate " - "client_random"); - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random", - conn->client_random, TLS_RANDOM_LEN); - - len = 100 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len; - hello = os_malloc(len); - if (hello == NULL) - return NULL; - end = hello + len; - - rhdr = hello; - pos = rhdr + TLS_RECORD_HEADER_LEN; - - /* opaque fragment[TLSPlaintext.length] */ - - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_HELLO; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - /* body - ClientHello */ - /* ProtocolVersion client_version */ - WPA_PUT_BE16(pos, TLS_VERSION); - pos += 2; - /* Random random: uint32 gmt_unix_time, opaque random_bytes */ - os_memcpy(pos, conn->client_random, TLS_RANDOM_LEN); - pos += TLS_RANDOM_LEN; - /* SessionID session_id */ - *pos++ = conn->session_id_len; - os_memcpy(pos, conn->session_id, conn->session_id_len); - pos += conn->session_id_len; - /* CipherSuite cipher_suites<2..2^16-1> */ - WPA_PUT_BE16(pos, 2 * conn->num_cipher_suites); - pos += 2; - for (i = 0; i < conn->num_cipher_suites; i++) { - WPA_PUT_BE16(pos, conn->cipher_suites[i]); - pos += 2; - } - /* CompressionMethod compression_methods<1..2^8-1> */ - *pos++ = 1; - *pos++ = TLS_COMPRESSION_NULL; - - if (conn->client_hello_ext) { - os_memcpy(pos, conn->client_hello_ext, - conn->client_hello_ext_len); - pos += conn->client_hello_ext_len; - } - - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, out_len) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(hello); - return NULL; - } - - conn->state = SERVER_HELLO; - - return hello; -} - - -static int tls_write_client_certificate(struct tlsv1_client *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start; - size_t rlen; - struct x509_certificate *cert; - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate"); - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - - /* opaque fragment[TLSPlaintext.length] */ - - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - /* body - Certificate */ - /* uint24 length (to be filled) */ - cert_start = pos; - pos += 3; - cert = conn->cred ? conn->cred->cert : NULL; - while (cert) { - if (pos + 3 + cert->cert_len > end) { - wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space " - "for Certificate (cert_len=%lu left=%lu)", - (unsigned long) cert->cert_len, - (unsigned long) (end - pos)); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - WPA_PUT_BE24(pos, cert->cert_len); - pos += 3; - os_memcpy(pos, cert->cert_start, cert->cert_len); - pos += cert->cert_len; - - if (x509_certificate_self_signed(cert)) - break; - cert = x509_certificate_get_subject(conn->cred->trusted_certs, - &cert->issuer); - } - if (conn->cred == NULL || cert == conn->cred->cert || cert == NULL) { - /* - * Client was not configured with all the needed certificates - * to form a full certificate chain. The server may fail to - * validate the chain unless it is configured with all the - * missing CA certificates. - */ - wpa_printf(MSG_DEBUG, "TLSv1: Full client certificate chain " - "not configured - validation may fail"); - } - WPA_PUT_BE24(cert_start, pos - cert_start - 3); - - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - pos = rhdr + rlen; - - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - *msgpos = pos; - - return 0; -} - - -static int tlsv1_key_x_anon_dh(struct tlsv1_client *conn, u8 **pos, u8 *end) -{ -#ifdef EAP_FAST - /* ClientDiffieHellmanPublic */ - u8 *csecret, *csecret_start, *dh_yc, *shared; - size_t csecret_len, dh_yc_len, shared_len; - - csecret_len = conn->dh_p_len; - csecret = os_malloc(csecret_len); - if (csecret == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " - "memory for Yc (Diffie-Hellman)"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - if (os_get_random(csecret, csecret_len)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " - "data for Diffie-Hellman"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(csecret); - return -1; - } - - if (os_memcmp(csecret, conn->dh_p, csecret_len) > 0) - csecret[0] = 0; /* make sure Yc < p */ - - csecret_start = csecret; - while (csecret_len > 1 && *csecret_start == 0) { - csecret_start++; - csecret_len--; - } - wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH client's secret value", - csecret_start, csecret_len); - - /* Yc = g^csecret mod p */ - dh_yc_len = conn->dh_p_len; - dh_yc = os_malloc(dh_yc_len); - if (dh_yc == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " - "memory for Diffie-Hellman"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(csecret); - return -1; - } - if (crypto_mod_exp(conn->dh_g, conn->dh_g_len, - csecret_start, csecret_len, - conn->dh_p, conn->dh_p_len, - dh_yc, &dh_yc_len)) { - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(csecret); - os_free(dh_yc); - return -1; - } - - wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)", - dh_yc, dh_yc_len); - - WPA_PUT_BE16(*pos, dh_yc_len); - *pos += 2; - if (*pos + dh_yc_len > end) { - wpa_printf(MSG_DEBUG, "TLSv1: Not enough room in the " - "message buffer for Yc"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(csecret); - os_free(dh_yc); - return -1; - } - os_memcpy(*pos, dh_yc, dh_yc_len); - *pos += dh_yc_len; - os_free(dh_yc); - - shared_len = conn->dh_p_len; - shared = os_malloc(shared_len); - if (shared == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for " - "DH"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(csecret); - return -1; - } - - /* shared = Ys^csecret mod p */ - if (crypto_mod_exp(conn->dh_ys, conn->dh_ys_len, - csecret_start, csecret_len, - conn->dh_p, conn->dh_p_len, - shared, &shared_len)) { - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(csecret); - os_free(shared); - return -1; - } - wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange", - shared, shared_len); - - os_memset(csecret_start, 0, csecret_len); - os_free(csecret); - if (tls_derive_keys(conn, shared, shared_len)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(shared); - return -1; - } - os_memset(shared, 0, shared_len); - os_free(shared); - tlsv1_client_free_dh(conn); - return 0; -#else /* EAP_FAST */ - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); - return -1; -#endif /* EAP_FAST */ -} - - -static int tlsv1_key_x_rsa(struct tlsv1_client *conn, u8 **pos, u8 *end) -{ - u8 pre_master_secret[TLS_PRE_MASTER_SECRET_LEN]; - size_t clen; - int res; - - if (tls_derive_pre_master_secret(pre_master_secret) < 0 || - tls_derive_keys(conn, pre_master_secret, - TLS_PRE_MASTER_SECRET_LEN)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - /* EncryptedPreMasterSecret */ - if (conn->server_rsa_key == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: No server RSA key to " - "use for encrypting pre-master secret"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - /* RSA encrypted value is encoded with PKCS #1 v1.5 block type 2. */ - *pos += 2; - clen = end - *pos; - res = crypto_public_key_encrypt_pkcs1_v15( - conn->server_rsa_key, - pre_master_secret, TLS_PRE_MASTER_SECRET_LEN, - *pos, &clen); - os_memset(pre_master_secret, 0, TLS_PRE_MASTER_SECRET_LEN); - if (res < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: RSA encryption failed"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - WPA_PUT_BE16(*pos - 2, clen); - wpa_hexdump(MSG_MSGDUMP, "TLSv1: Encrypted pre_master_secret", - *pos, clen); - *pos += clen; - - return 0; -} - - -static int tls_write_client_key_exchange(struct tlsv1_client *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr, *hs_start, *hs_length; - size_t rlen; - tls_key_exchange keyx; - const struct tls_cipher_suite *suite; - - suite = tls_get_cipher_suite(conn->rl.cipher_suite); - if (suite == NULL) - keyx = TLS_KEY_X_NULL; - else - keyx = suite->key_exchange; - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send ClientKeyExchange"); - - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - - /* opaque fragment[TLSPlaintext.length] */ - - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - /* body - ClientKeyExchange */ - if (keyx == TLS_KEY_X_DH_anon) { - if (tlsv1_key_x_anon_dh(conn, &pos, end) < 0) - return -1; - } else { - if (tlsv1_key_x_rsa(conn, &pos, end) < 0) - return -1; - } - - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - pos = rhdr + rlen; - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - *msgpos = pos; - - return 0; -} - - -static int tls_write_client_certificate_verify(struct tlsv1_client *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr, *hs_start, *hs_length, *signed_start; - size_t rlen, hlen, clen; - u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos; - enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA; - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateVerify"); - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - - /* - * RFC 2246: 7.4.3 and 7.4.8: - * Signature signature - * - * RSA: - * digitally-signed struct { - * opaque md5_hash[16]; - * opaque sha_hash[20]; - * }; - * - * DSA: - * digitally-signed struct { - * opaque sha_hash[20]; - * }; - * - * The hash values are calculated over all handshake messages sent or - * received starting at ClientHello up to, but not including, this - * CertificateVerify message, including the type and length fields of - * the handshake messages. - */ - - hpos = hash; - - if (alg == SIGN_ALG_RSA) { - hlen = MD5_MAC_LEN; - if (conn->verify.md5_cert == NULL || - crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) - { - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - conn->verify.md5_cert = NULL; - crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL); - conn->verify.sha1_cert = NULL; - return -1; - } - hpos += MD5_MAC_LEN; - } else - crypto_hash_finish(conn->verify.md5_cert, NULL, NULL); - - conn->verify.md5_cert = NULL; - hlen = SHA1_MAC_LEN; - if (conn->verify.sha1_cert == NULL || - crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) { - conn->verify.sha1_cert = NULL; - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - conn->verify.sha1_cert = NULL; - - if (alg == SIGN_ALG_RSA) - hlen += MD5_MAC_LEN; - - wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen); - - /* - * RFC 2246, 4.7: - * In digital signing, one-way hash functions are used as input for a - * signing algorithm. A digitally-signed element is encoded as an - * opaque vector <0..2^16-1>, where the length is specified by the - * signing algorithm and key. - * - * In RSA signing, a 36-byte structure of two hashes (one SHA and one - * MD5) is signed (encrypted with the private key). It is encoded with - * PKCS #1 block type 0 or type 1 as described in [PKCS1]. - */ - signed_start = pos; /* length to be filled */ - pos += 2; - clen = end - pos; - if (conn->cred == NULL || - crypto_private_key_sign_pkcs1(conn->cred->key, hash, hlen, - pos, &clen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to sign hash (PKCS #1)"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - WPA_PUT_BE16(signed_start, clen); - - pos += clen; - - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - pos = rhdr + rlen; - - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - *msgpos = pos; - - return 0; -} - - -static int tls_write_client_change_cipher_spec(struct tlsv1_client *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr; - size_t rlen; - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec"); - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - *pos = TLS_CHANGE_CIPHER_SPEC; - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC, - rhdr, end - rhdr, 1, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - if (tlsv1_record_change_write_cipher(&conn->rl) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for " - "record layer"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - *msgpos = rhdr + rlen; - - return 0; -} - - -static int tls_write_client_finished(struct tlsv1_client *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr, *hs_start, *hs_length; - size_t rlen, hlen; - u8 verify_data[TLS_VERIFY_DATA_LEN]; - u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send Finished"); - - /* Encrypted Handshake Message: Finished */ - - hlen = MD5_MAC_LEN; - if (conn->verify.md5_client == NULL || - crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) { - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - conn->verify.md5_client = NULL; - crypto_hash_finish(conn->verify.sha1_client, NULL, NULL); - conn->verify.sha1_client = NULL; - return -1; - } - conn->verify.md5_client = NULL; - hlen = SHA1_MAC_LEN; - if (conn->verify.sha1_client == NULL || - crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN, - &hlen) < 0) { - conn->verify.sha1_client = NULL; - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - conn->verify.sha1_client = NULL; - - if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, - "client finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, - verify_data, TLS_VERIFY_DATA_LEN)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)", - verify_data, TLS_VERIFY_DATA_LEN); - - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_FINISHED; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - os_memcpy(pos, verify_data, TLS_VERIFY_DATA_LEN); - pos += TLS_VERIFY_DATA_LEN; - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - pos = rhdr + rlen; - - *msgpos = pos; - - return 0; -} - - -static u8 * tls_send_client_key_exchange(struct tlsv1_client *conn, - size_t *out_len) -{ - u8 *msg, *end, *pos; - size_t msglen; - - *out_len = 0; - - msglen = 1000; - if (conn->certificate_requested) - msglen += tls_client_cert_chain_der_len(conn); - - msg = os_malloc(msglen); - if (msg == NULL) - return NULL; - - pos = msg; - end = msg + msglen; - - if (conn->certificate_requested) { - if (tls_write_client_certificate(conn, &pos, end) < 0) { - os_free(msg); - return NULL; - } - } - - if (tls_write_client_key_exchange(conn, &pos, end) < 0 || - (conn->certificate_requested && conn->cred && conn->cred->key && - tls_write_client_certificate_verify(conn, &pos, end) < 0) || - tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || - tls_write_client_finished(conn, &pos, end) < 0) { - os_free(msg); - return NULL; - } - - *out_len = pos - msg; - - conn->state = SERVER_CHANGE_CIPHER_SPEC; - - return msg; -} - - -static u8 * tls_send_change_cipher_spec(struct tlsv1_client *conn, - size_t *out_len) -{ - u8 *msg, *end, *pos; - - *out_len = 0; - - msg = os_malloc(1000); - if (msg == NULL) - return NULL; - - pos = msg; - end = msg + 1000; - - if (tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || - tls_write_client_finished(conn, &pos, end) < 0) { - os_free(msg); - return NULL; - } - - *out_len = pos - msg; - - wpa_printf(MSG_DEBUG, "TLSv1: Session resumption completed " - "successfully"); - conn->state = ESTABLISHED; - - return msg; -} - - -u8 * tlsv1_client_handshake_write(struct tlsv1_client *conn, size_t *out_len, - int no_appl_data) -{ - switch (conn->state) { - case CLIENT_KEY_EXCHANGE: - return tls_send_client_key_exchange(conn, out_len); - case CHANGE_CIPHER_SPEC: - return tls_send_change_cipher_spec(conn, out_len); - case ACK_FINISHED: - wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed " - "successfully"); - conn->state = ESTABLISHED; - *out_len = 0; - if (no_appl_data) { - /* Need to return something to get final TLS ACK. */ - return os_malloc(1); - } - return NULL; - default: - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while " - "generating reply", conn->state); - return NULL; - } -} - - -u8 * tlsv1_client_send_alert(struct tlsv1_client *conn, u8 level, - u8 description, size_t *out_len) -{ - u8 *alert, *pos, *length; - - wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description); - *out_len = 0; - - alert = os_malloc(10); - if (alert == NULL) - return NULL; - - pos = alert; - - /* TLSPlaintext */ - /* ContentType type */ - *pos++ = TLS_CONTENT_TYPE_ALERT; - /* ProtocolVersion version */ - WPA_PUT_BE16(pos, TLS_VERSION); - pos += 2; - /* uint16 length (to be filled) */ - length = pos; - pos += 2; - /* opaque fragment[TLSPlaintext.length] */ - - /* Alert */ - /* AlertLevel level */ - *pos++ = level; - /* AlertDescription description */ - *pos++ = description; - - WPA_PUT_BE16(length, pos - length - 2); - *out_len = pos - alert; - - return alert; -} diff --git a/contrib/hostapd/src/tls/tlsv1_common.c b/contrib/hostapd/src/tls/tlsv1_common.c deleted file mode 100644 index 2f9dd0fa88..0000000000 --- a/contrib/hostapd/src/tls/tlsv1_common.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * TLSv1 common routines - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "x509v3.h" -#include "tlsv1_common.h" - - -/* - * TODO: - * RFC 2246 Section 9: Mandatory to implement TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA - * Add support for commonly used cipher suites; don't bother with exportable - * suites. - */ - -static const struct tls_cipher_suite tls_cipher_suites[] = { - { TLS_NULL_WITH_NULL_NULL, TLS_KEY_X_NULL, TLS_CIPHER_NULL, - TLS_HASH_NULL }, - { TLS_RSA_WITH_RC4_128_MD5, TLS_KEY_X_RSA, TLS_CIPHER_RC4_128, - TLS_HASH_MD5 }, - { TLS_RSA_WITH_RC4_128_SHA, TLS_KEY_X_RSA, TLS_CIPHER_RC4_128, - TLS_HASH_SHA }, - { TLS_RSA_WITH_DES_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_DES_CBC, - TLS_HASH_SHA }, - { TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_RSA, - TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA }, - { TLS_DH_anon_WITH_RC4_128_MD5, TLS_KEY_X_DH_anon, - TLS_CIPHER_RC4_128, TLS_HASH_MD5 }, - { TLS_DH_anon_WITH_DES_CBC_SHA, TLS_KEY_X_DH_anon, - TLS_CIPHER_DES_CBC, TLS_HASH_SHA }, - { TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_DH_anon, - TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA }, - { TLS_RSA_WITH_AES_128_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_AES_128_CBC, - TLS_HASH_SHA }, - { TLS_DH_anon_WITH_AES_128_CBC_SHA, TLS_KEY_X_DH_anon, - TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA }, - { TLS_RSA_WITH_AES_256_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_AES_256_CBC, - TLS_HASH_SHA }, - { TLS_DH_anon_WITH_AES_256_CBC_SHA, TLS_KEY_X_DH_anon, - TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA } -}; - -#define NUM_ELEMS(a) (sizeof(a) / sizeof((a)[0])) -#define NUM_TLS_CIPHER_SUITES NUM_ELEMS(tls_cipher_suites) - - -static const struct tls_cipher_data tls_ciphers[] = { - { TLS_CIPHER_NULL, TLS_CIPHER_STREAM, 0, 0, 0, - CRYPTO_CIPHER_NULL }, - { TLS_CIPHER_IDEA_CBC, TLS_CIPHER_BLOCK, 16, 16, 8, - CRYPTO_CIPHER_NULL }, - { TLS_CIPHER_RC2_CBC_40, TLS_CIPHER_BLOCK, 5, 16, 0, - CRYPTO_CIPHER_ALG_RC2 }, - { TLS_CIPHER_RC4_40, TLS_CIPHER_STREAM, 5, 16, 0, - CRYPTO_CIPHER_ALG_RC4 }, - { TLS_CIPHER_RC4_128, TLS_CIPHER_STREAM, 16, 16, 0, - CRYPTO_CIPHER_ALG_RC4 }, - { TLS_CIPHER_DES40_CBC, TLS_CIPHER_BLOCK, 5, 8, 8, - CRYPTO_CIPHER_ALG_DES }, - { TLS_CIPHER_DES_CBC, TLS_CIPHER_BLOCK, 8, 8, 8, - CRYPTO_CIPHER_ALG_DES }, - { TLS_CIPHER_3DES_EDE_CBC, TLS_CIPHER_BLOCK, 24, 24, 8, - CRYPTO_CIPHER_ALG_3DES }, - { TLS_CIPHER_AES_128_CBC, TLS_CIPHER_BLOCK, 16, 16, 16, - CRYPTO_CIPHER_ALG_AES }, - { TLS_CIPHER_AES_256_CBC, TLS_CIPHER_BLOCK, 32, 32, 16, - CRYPTO_CIPHER_ALG_AES } -}; - -#define NUM_TLS_CIPHER_DATA NUM_ELEMS(tls_ciphers) - - -/** - * tls_get_cipher_suite - Get TLS cipher suite - * @suite: Cipher suite identifier - * Returns: Pointer to the cipher data or %NULL if not found - */ -const struct tls_cipher_suite * tls_get_cipher_suite(u16 suite) -{ - size_t i; - for (i = 0; i < NUM_TLS_CIPHER_SUITES; i++) - if (tls_cipher_suites[i].suite == suite) - return &tls_cipher_suites[i]; - return NULL; -} - - -const struct tls_cipher_data * tls_get_cipher_data(tls_cipher cipher) -{ - size_t i; - for (i = 0; i < NUM_TLS_CIPHER_DATA; i++) - if (tls_ciphers[i].cipher == cipher) - return &tls_ciphers[i]; - return NULL; -} - - -int tls_server_key_exchange_allowed(tls_cipher cipher) -{ - const struct tls_cipher_suite *suite; - - /* RFC 2246, Section 7.4.3 */ - suite = tls_get_cipher_suite(cipher); - if (suite == NULL) - return 0; - - switch (suite->key_exchange) { - case TLS_KEY_X_DHE_DSS: - case TLS_KEY_X_DHE_DSS_EXPORT: - case TLS_KEY_X_DHE_RSA: - case TLS_KEY_X_DHE_RSA_EXPORT: - case TLS_KEY_X_DH_anon_EXPORT: - case TLS_KEY_X_DH_anon: - return 1; - case TLS_KEY_X_RSA_EXPORT: - return 1 /* FIX: public key len > 512 bits */; - default: - return 0; - } -} - - -/** - * tls_parse_cert - Parse DER encoded X.509 certificate and get public key - * @buf: ASN.1 DER encoded certificate - * @len: Length of the buffer - * @pk: Buffer for returning the allocated public key - * Returns: 0 on success, -1 on failure - * - * This functions parses an ASN.1 DER encoded X.509 certificate and retrieves - * the public key from it. The caller is responsible for freeing the public key - * by calling crypto_public_key_free(). - */ -int tls_parse_cert(const u8 *buf, size_t len, struct crypto_public_key **pk) -{ - struct x509_certificate *cert; - - wpa_hexdump(MSG_MSGDUMP, "TLSv1: Parse ASN.1 DER certificate", - buf, len); - - *pk = crypto_public_key_from_cert(buf, len); - if (*pk) - return 0; - - cert = x509_certificate_parse(buf, len); - if (cert == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse X.509 " - "certificate"); - return -1; - } - - /* TODO - * verify key usage (must allow encryption) - * - * All certificate profiles, key and cryptographic formats are - * defined by the IETF PKIX working group [PKIX]. When a key - * usage extension is present, the digitalSignature bit must be - * set for the key to be eligible for signing, as described - * above, and the keyEncipherment bit must be present to allow - * encryption, as described above. The keyAgreement bit must be - * set on Diffie-Hellman certificates. (PKIX: RFC 3280) - */ - - *pk = crypto_public_key_import(cert->public_key, cert->public_key_len); - x509_certificate_free(cert); - - if (*pk == NULL) { - wpa_printf(MSG_ERROR, "TLSv1: Failed to import " - "server public key"); - return -1; - } - - return 0; -} - - -int tls_verify_hash_init(struct tls_verify_hash *verify) -{ - tls_verify_hash_free(verify); - verify->md5_client = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0); - verify->md5_server = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0); - verify->md5_cert = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0); - verify->sha1_client = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0); - verify->sha1_server = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0); - verify->sha1_cert = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0); - if (verify->md5_client == NULL || verify->md5_server == NULL || - verify->md5_cert == NULL || verify->sha1_client == NULL || - verify->sha1_server == NULL || verify->sha1_cert == NULL) { - tls_verify_hash_free(verify); - return -1; - } - return 0; -} - - -void tls_verify_hash_add(struct tls_verify_hash *verify, const u8 *buf, - size_t len) -{ - if (verify->md5_client && verify->sha1_client) { - crypto_hash_update(verify->md5_client, buf, len); - crypto_hash_update(verify->sha1_client, buf, len); - } - if (verify->md5_server && verify->sha1_server) { - crypto_hash_update(verify->md5_server, buf, len); - crypto_hash_update(verify->sha1_server, buf, len); - } - if (verify->md5_cert && verify->sha1_cert) { - crypto_hash_update(verify->md5_cert, buf, len); - crypto_hash_update(verify->sha1_cert, buf, len); - } -} - - -void tls_verify_hash_free(struct tls_verify_hash *verify) -{ - crypto_hash_finish(verify->md5_client, NULL, NULL); - crypto_hash_finish(verify->md5_server, NULL, NULL); - crypto_hash_finish(verify->md5_cert, NULL, NULL); - crypto_hash_finish(verify->sha1_client, NULL, NULL); - crypto_hash_finish(verify->sha1_server, NULL, NULL); - crypto_hash_finish(verify->sha1_cert, NULL, NULL); - verify->md5_client = NULL; - verify->md5_server = NULL; - verify->md5_cert = NULL; - verify->sha1_client = NULL; - verify->sha1_server = NULL; - verify->sha1_cert = NULL; -} diff --git a/contrib/hostapd/src/tls/tlsv1_common.h b/contrib/hostapd/src/tls/tlsv1_common.h deleted file mode 100644 index 77505649a2..0000000000 --- a/contrib/hostapd/src/tls/tlsv1_common.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * TLSv1 common definitions - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TLSV1_COMMON_H -#define TLSV1_COMMON_H - -#include "crypto.h" - -#define TLS_VERSION 0x0301 /* TLSv1 */ -#define TLS_RANDOM_LEN 32 -#define TLS_PRE_MASTER_SECRET_LEN 48 -#define TLS_MASTER_SECRET_LEN 48 -#define TLS_SESSION_ID_MAX_LEN 32 -#define TLS_VERIFY_DATA_LEN 12 - -/* HandshakeType */ -enum { - TLS_HANDSHAKE_TYPE_HELLO_REQUEST = 0, - TLS_HANDSHAKE_TYPE_CLIENT_HELLO = 1, - TLS_HANDSHAKE_TYPE_SERVER_HELLO = 2, - TLS_HANDSHAKE_TYPE_NEW_SESSION_TICKET = 4 /* RFC 4507 */, - TLS_HANDSHAKE_TYPE_CERTIFICATE = 11, - TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE = 12, - TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST = 13, - TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE = 14, - TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY = 15, - TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE = 16, - TLS_HANDSHAKE_TYPE_FINISHED = 20, - TLS_HANDSHAKE_TYPE_CERTIFICATE_URL = 21 /* RFC 4366 */, - TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS = 22 /* RFC 4366 */ -}; - -/* CipherSuite */ -#define TLS_NULL_WITH_NULL_NULL 0x0000 /* RFC 2246 */ -#define TLS_RSA_WITH_NULL_MD5 0x0001 /* RFC 2246 */ -#define TLS_RSA_WITH_NULL_SHA 0x0002 /* RFC 2246 */ -#define TLS_RSA_EXPORT_WITH_RC4_40_MD5 0x0003 /* RFC 2246 */ -#define TLS_RSA_WITH_RC4_128_MD5 0x0004 /* RFC 2246 */ -#define TLS_RSA_WITH_RC4_128_SHA 0x0005 /* RFC 2246 */ -#define TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 0x0006 /* RFC 2246 */ -#define TLS_RSA_WITH_IDEA_CBC_SHA 0x0007 /* RFC 2246 */ -#define TLS_RSA_EXPORT_WITH_DES40_CBC_SHA 0x0008 /* RFC 2246 */ -#define TLS_RSA_WITH_DES_CBC_SHA 0x0009 /* RFC 2246 */ -#define TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x000A /* RFC 2246 */ -#define TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA 0x000B /* RFC 2246 */ -#define TLS_DH_DSS_WITH_DES_CBC_SHA 0x000C /* RFC 2246 */ -#define TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA 0x000D /* RFC 2246 */ -#define TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA 0x000E /* RFC 2246 */ -#define TLS_DH_RSA_WITH_DES_CBC_SHA 0x000F /* RFC 2246 */ -#define TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA 0x0010 /* RFC 2246 */ -#define TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA 0x0011 /* RFC 2246 */ -#define TLS_DHE_DSS_WITH_DES_CBC_SHA 0x0012 /* RFC 2246 */ -#define TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA 0x0013 /* RFC 2246 */ -#define TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA 0x0014 /* RFC 2246 */ -#define TLS_DHE_RSA_WITH_DES_CBC_SHA 0x0015 /* RFC 2246 */ -#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016 /* RFC 2246 */ -#define TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 0x0017 /* RFC 2246 */ -#define TLS_DH_anon_WITH_RC4_128_MD5 0x0018 /* RFC 2246 */ -#define TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA 0x0019 /* RFC 2246 */ -#define TLS_DH_anon_WITH_DES_CBC_SHA 0x001A /* RFC 2246 */ -#define TLS_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B /* RFC 2246 */ -#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F /* RFC 3268 */ -#define TLS_DH_DSS_WITH_AES_128_CBC_SHA 0x0030 /* RFC 3268 */ -#define TLS_DH_RSA_WITH_AES_128_CBC_SHA 0x0031 /* RFC 3268 */ -#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA 0x0032 /* RFC 3268 */ -#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033 /* RFC 3268 */ -#define TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034 /* RFC 3268 */ -#define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 /* RFC 3268 */ -#define TLS_DH_DSS_WITH_AES_256_CBC_SHA 0x0036 /* RFC 3268 */ -#define TLS_DH_RSA_WITH_AES_256_CBC_SHA 0x0037 /* RFC 3268 */ -#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA 0x0038 /* RFC 3268 */ -#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 /* RFC 3268 */ -#define TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A /* RFC 3268 */ - -/* CompressionMethod */ -#define TLS_COMPRESSION_NULL 0 - -/* AlertLevel */ -#define TLS_ALERT_LEVEL_WARNING 1 -#define TLS_ALERT_LEVEL_FATAL 2 - -/* AlertDescription */ -#define TLS_ALERT_CLOSE_NOTIFY 0 -#define TLS_ALERT_UNEXPECTED_MESSAGE 10 -#define TLS_ALERT_BAD_RECORD_MAC 20 -#define TLS_ALERT_DECRYPTION_FAILED 21 -#define TLS_ALERT_RECORD_OVERFLOW 22 -#define TLS_ALERT_DECOMPRESSION_FAILURE 30 -#define TLS_ALERT_HANDSHAKE_FAILURE 40 -#define TLS_ALERT_BAD_CERTIFICATE 42 -#define TLS_ALERT_UNSUPPORTED_CERTIFICATE 43 -#define TLS_ALERT_CERTIFICATE_REVOKED 44 -#define TLS_ALERT_CERTIFICATE_EXPIRED 45 -#define TLS_ALERT_CERTIFICATE_UNKNOWN 46 -#define TLS_ALERT_ILLEGAL_PARAMETER 47 -#define TLS_ALERT_UNKNOWN_CA 48 -#define TLS_ALERT_ACCESS_DENIED 49 -#define TLS_ALERT_DECODE_ERROR 50 -#define TLS_ALERT_DECRYPT_ERROR 51 -#define TLS_ALERT_EXPORT_RESTRICTION 60 -#define TLS_ALERT_PROTOCOL_VERSION 70 -#define TLS_ALERT_INSUFFICIENT_SECURITY 71 -#define TLS_ALERT_INTERNAL_ERROR 80 -#define TLS_ALERT_USER_CANCELED 90 -#define TLS_ALERT_NO_RENEGOTIATION 100 -#define TLS_ALERT_UNSUPPORTED_EXTENSION 110 /* RFC 4366 */ -#define TLS_ALERT_CERTIFICATE_UNOBTAINABLE 111 /* RFC 4366 */ -#define TLS_ALERT_UNRECOGNIZED_NAME 112 /* RFC 4366 */ -#define TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE 113 /* RFC 4366 */ -#define TLS_ALERT_BAD_CERTIFICATE_HASH_VALUE 114 /* RFC 4366 */ - -/* ChangeCipherSpec */ -enum { - TLS_CHANGE_CIPHER_SPEC = 1 -}; - -/* TLS Extensions */ -#define TLS_EXT_SERVER_NAME 0 /* RFC 4366 */ -#define TLS_EXT_MAX_FRAGMENT_LENGTH 1 /* RFC 4366 */ -#define TLS_EXT_CLIENT_CERTIFICATE_URL 2 /* RFC 4366 */ -#define TLS_EXT_TRUSTED_CA_KEYS 3 /* RFC 4366 */ -#define TLS_EXT_TRUNCATED_HMAC 4 /* RFC 4366 */ -#define TLS_EXT_STATUS_REQUEST 5 /* RFC 4366 */ -#define TLS_EXT_SESSION_TICKET 35 /* RFC 4507 */ - -#define TLS_EXT_PAC_OPAQUE TLS_EXT_SESSION_TICKET /* EAP-FAST terminology */ - - -typedef enum { - TLS_KEY_X_NULL, - TLS_KEY_X_RSA, - TLS_KEY_X_RSA_EXPORT, - TLS_KEY_X_DH_DSS_EXPORT, - TLS_KEY_X_DH_DSS, - TLS_KEY_X_DH_RSA_EXPORT, - TLS_KEY_X_DH_RSA, - TLS_KEY_X_DHE_DSS_EXPORT, - TLS_KEY_X_DHE_DSS, - TLS_KEY_X_DHE_RSA_EXPORT, - TLS_KEY_X_DHE_RSA, - TLS_KEY_X_DH_anon_EXPORT, - TLS_KEY_X_DH_anon -} tls_key_exchange; - -typedef enum { - TLS_CIPHER_NULL, - TLS_CIPHER_RC4_40, - TLS_CIPHER_RC4_128, - TLS_CIPHER_RC2_CBC_40, - TLS_CIPHER_IDEA_CBC, - TLS_CIPHER_DES40_CBC, - TLS_CIPHER_DES_CBC, - TLS_CIPHER_3DES_EDE_CBC, - TLS_CIPHER_AES_128_CBC, - TLS_CIPHER_AES_256_CBC -} tls_cipher; - -typedef enum { - TLS_HASH_NULL, - TLS_HASH_MD5, - TLS_HASH_SHA -} tls_hash; - -struct tls_cipher_suite { - u16 suite; - tls_key_exchange key_exchange; - tls_cipher cipher; - tls_hash hash; -}; - -typedef enum { - TLS_CIPHER_STREAM, - TLS_CIPHER_BLOCK -} tls_cipher_type; - -struct tls_cipher_data { - tls_cipher cipher; - tls_cipher_type type; - size_t key_material; - size_t expanded_key_material; - size_t block_size; /* also iv_size */ - enum crypto_cipher_alg alg; -}; - - -struct tls_verify_hash { - struct crypto_hash *md5_client; - struct crypto_hash *sha1_client; - struct crypto_hash *md5_server; - struct crypto_hash *sha1_server; - struct crypto_hash *md5_cert; - struct crypto_hash *sha1_cert; -}; - - -const struct tls_cipher_suite * tls_get_cipher_suite(u16 suite); -const struct tls_cipher_data * tls_get_cipher_data(tls_cipher cipher); -int tls_server_key_exchange_allowed(tls_cipher cipher); -int tls_parse_cert(const u8 *buf, size_t len, struct crypto_public_key **pk); -int tls_verify_hash_init(struct tls_verify_hash *verify); -void tls_verify_hash_add(struct tls_verify_hash *verify, const u8 *buf, - size_t len); -void tls_verify_hash_free(struct tls_verify_hash *verify); - -#endif /* TLSV1_COMMON_H */ diff --git a/contrib/hostapd/src/tls/tlsv1_cred.c b/contrib/hostapd/src/tls/tlsv1_cred.c deleted file mode 100644 index d5564672c8..0000000000 --- a/contrib/hostapd/src/tls/tlsv1_cred.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - * TLSv1 credentials - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "base64.h" -#include "crypto.h" -#include "x509v3.h" -#include "tlsv1_cred.h" - - -struct tlsv1_credentials * tlsv1_cred_alloc(void) -{ - struct tlsv1_credentials *cred; - cred = os_zalloc(sizeof(*cred)); - return cred; -} - - -void tlsv1_cred_free(struct tlsv1_credentials *cred) -{ - if (cred == NULL) - return; - - x509_certificate_chain_free(cred->trusted_certs); - x509_certificate_chain_free(cred->cert); - crypto_private_key_free(cred->key); - os_free(cred->dh_p); - os_free(cred->dh_g); - os_free(cred); -} - - -static int tlsv1_add_cert_der(struct x509_certificate **chain, - const u8 *buf, size_t len) -{ - struct x509_certificate *cert; - char name[128]; - - cert = x509_certificate_parse(buf, len); - if (cert == NULL) { - wpa_printf(MSG_INFO, "TLSv1: %s - failed to parse certificate", - __func__); - return -1; - } - - cert->next = *chain; - *chain = cert; - - x509_name_string(&cert->subject, name, sizeof(name)); - wpa_printf(MSG_DEBUG, "TLSv1: Added certificate: %s", name); - - return 0; -} - - -static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----"; -static const char *pem_cert_end = "-----END CERTIFICATE-----"; - - -static const u8 * search_tag(const char *tag, const u8 *buf, size_t len) -{ - size_t i, plen; - - plen = os_strlen(tag); - if (len < plen) - return NULL; - - for (i = 0; i < len - plen; i++) { - if (os_memcmp(buf + i, tag, plen) == 0) - return buf + i; - } - - return NULL; -} - - -static int tlsv1_add_cert(struct x509_certificate **chain, - const u8 *buf, size_t len) -{ - const u8 *pos, *end; - unsigned char *der; - size_t der_len; - - pos = search_tag(pem_cert_begin, buf, len); - if (!pos) { - wpa_printf(MSG_DEBUG, "TLSv1: No PEM certificate tag found - " - "assume DER format"); - return tlsv1_add_cert_der(chain, buf, len); - } - - wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format certificate into " - "DER format"); - - while (pos) { - pos += os_strlen(pem_cert_begin); - end = search_tag(pem_cert_end, pos, buf + len - pos); - if (end == NULL) { - wpa_printf(MSG_INFO, "TLSv1: Could not find PEM " - "certificate end tag (%s)", pem_cert_end); - return -1; - } - - der = base64_decode(pos, end - pos, &der_len); - if (der == NULL) { - wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM " - "certificate"); - return -1; - } - - if (tlsv1_add_cert_der(chain, der, der_len) < 0) { - wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM " - "certificate after DER conversion"); - os_free(der); - return -1; - } - - os_free(der); - - end += os_strlen(pem_cert_end); - pos = search_tag(pem_cert_begin, end, buf + len - end); - } - - return 0; -} - - -static int tlsv1_set_cert_chain(struct x509_certificate **chain, - const char *cert, const u8 *cert_blob, - size_t cert_blob_len) -{ - if (cert_blob) - return tlsv1_add_cert(chain, cert_blob, cert_blob_len); - - if (cert) { - u8 *buf; - size_t len; - int ret; - - buf = (u8 *) os_readfile(cert, &len); - if (buf == NULL) { - wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", - cert); - return -1; - } - - ret = tlsv1_add_cert(chain, buf, len); - os_free(buf); - return ret; - } - - return 0; -} - - -/** - * tlsv1_set_ca_cert - Set trusted CA certificate(s) - * @cred: TLSv1 credentials from tlsv1_cred_alloc() - * @cert: File or reference name for X.509 certificate in PEM or DER format - * @cert_blob: cert as inlined data or %NULL if not used - * @cert_blob_len: ca_cert_blob length - * @path: Path to CA certificates (not yet supported) - * Returns: 0 on success, -1 on failure - */ -int tlsv1_set_ca_cert(struct tlsv1_credentials *cred, const char *cert, - const u8 *cert_blob, size_t cert_blob_len, - const char *path) -{ - if (tlsv1_set_cert_chain(&cred->trusted_certs, cert, - cert_blob, cert_blob_len) < 0) - return -1; - - if (path) { - /* TODO: add support for reading number of certificate files */ - wpa_printf(MSG_INFO, "TLSv1: Use of CA certificate directory " - "not yet supported"); - return -1; - } - - return 0; -} - - -/** - * tlsv1_set_cert - Set certificate - * @cred: TLSv1 credentials from tlsv1_cred_alloc() - * @cert: File or reference name for X.509 certificate in PEM or DER format - * @cert_blob: cert as inlined data or %NULL if not used - * @cert_blob_len: cert_blob length - * Returns: 0 on success, -1 on failure - */ -int tlsv1_set_cert(struct tlsv1_credentials *cred, const char *cert, - const u8 *cert_blob, size_t cert_blob_len) -{ - return tlsv1_set_cert_chain(&cred->cert, cert, - cert_blob, cert_blob_len); -} - - -static int tlsv1_set_key(struct tlsv1_credentials *cred, - const u8 *key, size_t len) -{ - cred->key = crypto_private_key_import(key, len); - if (cred->key == NULL) { - wpa_printf(MSG_INFO, "TLSv1: Failed to parse private key"); - return -1; - } - return 0; -} - - -/** - * tlsv1_set_private_key - Set private key - * @cred: TLSv1 credentials from tlsv1_cred_alloc() - * @private_key: File or reference name for the key in PEM or DER format - * @private_key_passwd: Passphrase for decrypted private key, %NULL if no - * passphrase is used. - * @private_key_blob: private_key as inlined data or %NULL if not used - * @private_key_blob_len: private_key_blob length - * Returns: 0 on success, -1 on failure - */ -int tlsv1_set_private_key(struct tlsv1_credentials *cred, - const char *private_key, - const char *private_key_passwd, - const u8 *private_key_blob, - size_t private_key_blob_len) -{ - crypto_private_key_free(cred->key); - cred->key = NULL; - - if (private_key_blob) - return tlsv1_set_key(cred, private_key_blob, - private_key_blob_len); - - if (private_key) { - u8 *buf; - size_t len; - int ret; - - buf = (u8 *) os_readfile(private_key, &len); - if (buf == NULL) { - wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", - private_key); - return -1; - } - - ret = tlsv1_set_key(cred, buf, len); - os_free(buf); - return ret; - } - - return 0; -} - - -static int tlsv1_set_dhparams_der(struct tlsv1_credentials *cred, - const u8 *dh, size_t len) -{ - struct asn1_hdr hdr; - const u8 *pos, *end; - - pos = dh; - end = dh + len; - - /* - * DHParameter ::= SEQUENCE { - * prime INTEGER, -- p - * base INTEGER, -- g - * privateValueLength INTEGER OPTIONAL } - */ - - /* DHParamer ::= SEQUENCE */ - if (asn1_get_next(pos, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "DH: DH parameters did not start with a " - "valid SEQUENCE - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - pos = hdr.payload; - - /* prime INTEGER */ - if (asn1_get_next(pos, end - pos, &hdr) < 0) - return -1; - - if (hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_INTEGER) { - wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for p; " - "class=%d tag=0x%x", hdr.class, hdr.tag); - return -1; - } - - wpa_hexdump(MSG_MSGDUMP, "DH: prime (p)", hdr.payload, hdr.length); - if (hdr.length == 0) - return -1; - os_free(cred->dh_p); - cred->dh_p = os_malloc(hdr.length); - if (cred->dh_p == NULL) - return -1; - os_memcpy(cred->dh_p, hdr.payload, hdr.length); - cred->dh_p_len = hdr.length; - pos = hdr.payload + hdr.length; - - /* base INTEGER */ - if (asn1_get_next(pos, end - pos, &hdr) < 0) - return -1; - - if (hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_INTEGER) { - wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for g; " - "class=%d tag=0x%x", hdr.class, hdr.tag); - return -1; - } - - wpa_hexdump(MSG_MSGDUMP, "DH: base (g)", hdr.payload, hdr.length); - if (hdr.length == 0) - return -1; - os_free(cred->dh_g); - cred->dh_g = os_malloc(hdr.length); - if (cred->dh_g == NULL) - return -1; - os_memcpy(cred->dh_g, hdr.payload, hdr.length); - cred->dh_g_len = hdr.length; - - return 0; -} - - -static const char *pem_dhparams_begin = "-----BEGIN DH PARAMETERS-----"; -static const char *pem_dhparams_end = "-----END DH PARAMETERS-----"; - - -static int tlsv1_set_dhparams_blob(struct tlsv1_credentials *cred, - const u8 *buf, size_t len) -{ - const u8 *pos, *end; - unsigned char *der; - size_t der_len; - - pos = search_tag(pem_dhparams_begin, buf, len); - if (!pos) { - wpa_printf(MSG_DEBUG, "TLSv1: No PEM dhparams tag found - " - "assume DER format"); - return tlsv1_set_dhparams_der(cred, buf, len); - } - - wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format dhparams into DER " - "format"); - - pos += os_strlen(pem_dhparams_begin); - end = search_tag(pem_dhparams_end, pos, buf + len - pos); - if (end == NULL) { - wpa_printf(MSG_INFO, "TLSv1: Could not find PEM dhparams end " - "tag (%s)", pem_dhparams_end); - return -1; - } - - der = base64_decode(pos, end - pos, &der_len); - if (der == NULL) { - wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM dhparams"); - return -1; - } - - if (tlsv1_set_dhparams_der(cred, der, der_len) < 0) { - wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM dhparams " - "DER conversion"); - os_free(der); - return -1; - } - - os_free(der); - - return 0; -} - - -/** - * tlsv1_set_dhparams - Set Diffie-Hellman parameters - * @cred: TLSv1 credentials from tlsv1_cred_alloc() - * @dh_file: File or reference name for the DH params in PEM or DER format - * @dh_blob: DH params as inlined data or %NULL if not used - * @dh_blob_len: dh_blob length - * Returns: 0 on success, -1 on failure - */ -int tlsv1_set_dhparams(struct tlsv1_credentials *cred, const char *dh_file, - const u8 *dh_blob, size_t dh_blob_len) -{ - if (dh_blob) - return tlsv1_set_dhparams_blob(cred, dh_blob, dh_blob_len); - - if (dh_file) { - u8 *buf; - size_t len; - int ret; - - buf = (u8 *) os_readfile(dh_file, &len); - if (buf == NULL) { - wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", - dh_file); - return -1; - } - - ret = tlsv1_set_dhparams_blob(cred, buf, len); - os_free(buf); - return ret; - } - - return 0; -} diff --git a/contrib/hostapd/src/tls/tlsv1_cred.h b/contrib/hostapd/src/tls/tlsv1_cred.h deleted file mode 100644 index 8425fe4541..0000000000 --- a/contrib/hostapd/src/tls/tlsv1_cred.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * TLSv1 credentials - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TLSV1_CRED_H -#define TLSV1_CRED_H - -struct tlsv1_credentials { - struct x509_certificate *trusted_certs; - struct x509_certificate *cert; - struct crypto_private_key *key; - - /* Diffie-Hellman parameters */ - u8 *dh_p; /* prime */ - size_t dh_p_len; - u8 *dh_g; /* generator */ - size_t dh_g_len; -}; - - -struct tlsv1_credentials * tlsv1_cred_alloc(void); -void tlsv1_cred_free(struct tlsv1_credentials *cred); -int tlsv1_set_ca_cert(struct tlsv1_credentials *cred, const char *cert, - const u8 *cert_blob, size_t cert_blob_len, - const char *path); -int tlsv1_set_cert(struct tlsv1_credentials *cred, const char *cert, - const u8 *cert_blob, size_t cert_blob_len); -int tlsv1_set_private_key(struct tlsv1_credentials *cred, - const char *private_key, - const char *private_key_passwd, - const u8 *private_key_blob, - size_t private_key_blob_len); -int tlsv1_set_dhparams(struct tlsv1_credentials *cred, const char *dh_file, - const u8 *dh_blob, size_t dh_blob_len); - -#endif /* TLSV1_CRED_H */ diff --git a/contrib/hostapd/src/tls/tlsv1_record.c b/contrib/hostapd/src/tls/tlsv1_record.c deleted file mode 100644 index f226ac3f9b..0000000000 --- a/contrib/hostapd/src/tls/tlsv1_record.c +++ /dev/null @@ -1,409 +0,0 @@ -/* - * TLSv1 Record Protocol - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "md5.h" -#include "sha1.h" -#include "tlsv1_common.h" -#include "tlsv1_record.h" - - -/** - * tlsv1_record_set_cipher_suite - TLS record layer: Set cipher suite - * @rl: Pointer to TLS record layer data - * @cipher_suite: New cipher suite - * Returns: 0 on success, -1 on failure - * - * This function is used to prepare TLS record layer for cipher suite change. - * tlsv1_record_change_write_cipher() and - * tlsv1_record_change_read_cipher() functions can then be used to change the - * currently used ciphers. - */ -int tlsv1_record_set_cipher_suite(struct tlsv1_record_layer *rl, - u16 cipher_suite) -{ - const struct tls_cipher_suite *suite; - const struct tls_cipher_data *data; - - wpa_printf(MSG_DEBUG, "TLSv1: Selected cipher suite: 0x%04x", - cipher_suite); - rl->cipher_suite = cipher_suite; - - suite = tls_get_cipher_suite(cipher_suite); - if (suite == NULL) - return -1; - - if (suite->hash == TLS_HASH_MD5) { - rl->hash_alg = CRYPTO_HASH_ALG_HMAC_MD5; - rl->hash_size = MD5_MAC_LEN; - } else if (suite->hash == TLS_HASH_SHA) { - rl->hash_alg = CRYPTO_HASH_ALG_HMAC_SHA1; - rl->hash_size = SHA1_MAC_LEN; - } - - data = tls_get_cipher_data(suite->cipher); - if (data == NULL) - return -1; - - rl->key_material_len = data->key_material; - rl->iv_size = data->block_size; - rl->cipher_alg = data->alg; - - return 0; -} - - -/** - * tlsv1_record_change_write_cipher - TLS record layer: Change write cipher - * @rl: Pointer to TLS record layer data - * Returns: 0 on success (cipher changed), -1 on failure - * - * This function changes TLS record layer to use the new cipher suite - * configured with tlsv1_record_set_cipher_suite() for writing. - */ -int tlsv1_record_change_write_cipher(struct tlsv1_record_layer *rl) -{ - wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - New write cipher suite " - "0x%04x", rl->cipher_suite); - rl->write_cipher_suite = rl->cipher_suite; - os_memset(rl->write_seq_num, 0, TLS_SEQ_NUM_LEN); - - if (rl->write_cbc) { - crypto_cipher_deinit(rl->write_cbc); - rl->write_cbc = NULL; - } - if (rl->cipher_alg != CRYPTO_CIPHER_NULL) { - rl->write_cbc = crypto_cipher_init(rl->cipher_alg, - rl->write_iv, rl->write_key, - rl->key_material_len); - if (rl->write_cbc == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize " - "cipher"); - return -1; - } - } - - return 0; -} - - -/** - * tlsv1_record_change_read_cipher - TLS record layer: Change read cipher - * @rl: Pointer to TLS record layer data - * Returns: 0 on success (cipher changed), -1 on failure - * - * This function changes TLS record layer to use the new cipher suite - * configured with tlsv1_record_set_cipher_suite() for reading. - */ -int tlsv1_record_change_read_cipher(struct tlsv1_record_layer *rl) -{ - wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - New read cipher suite " - "0x%04x", rl->cipher_suite); - rl->read_cipher_suite = rl->cipher_suite; - os_memset(rl->read_seq_num, 0, TLS_SEQ_NUM_LEN); - - if (rl->read_cbc) { - crypto_cipher_deinit(rl->read_cbc); - rl->read_cbc = NULL; - } - if (rl->cipher_alg != CRYPTO_CIPHER_NULL) { - rl->read_cbc = crypto_cipher_init(rl->cipher_alg, - rl->read_iv, rl->read_key, - rl->key_material_len); - if (rl->read_cbc == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize " - "cipher"); - return -1; - } - } - - return 0; -} - - -/** - * tlsv1_record_send - TLS record layer: Send a message - * @rl: Pointer to TLS record layer data - * @content_type: Content type (TLS_CONTENT_TYPE_*) - * @buf: Buffer to send (with TLS_RECORD_HEADER_LEN octets reserved in the - * beginning for record layer to fill in; payload filled in after this and - * extra space in the end for HMAC). - * @buf_size: Maximum buf size - * @payload_len: Length of the payload - * @out_len: Buffer for returning the used buf length - * Returns: 0 on success, -1 on failure - * - * This function fills in the TLS record layer header, adds HMAC, and encrypts - * the data using the current write cipher. - */ -int tlsv1_record_send(struct tlsv1_record_layer *rl, u8 content_type, u8 *buf, - size_t buf_size, size_t payload_len, size_t *out_len) -{ - u8 *pos, *ct_start, *length, *payload; - struct crypto_hash *hmac; - size_t clen; - - pos = buf; - /* ContentType type */ - ct_start = pos; - *pos++ = content_type; - /* ProtocolVersion version */ - WPA_PUT_BE16(pos, TLS_VERSION); - pos += 2; - /* uint16 length */ - length = pos; - WPA_PUT_BE16(length, payload_len); - pos += 2; - - /* opaque fragment[TLSPlaintext.length] */ - payload = pos; - pos += payload_len; - - if (rl->write_cipher_suite != TLS_NULL_WITH_NULL_NULL) { - hmac = crypto_hash_init(rl->hash_alg, rl->write_mac_secret, - rl->hash_size); - if (hmac == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed " - "to initialize HMAC"); - return -1; - } - crypto_hash_update(hmac, rl->write_seq_num, TLS_SEQ_NUM_LEN); - /* type + version + length + fragment */ - crypto_hash_update(hmac, ct_start, pos - ct_start); - clen = buf + buf_size - pos; - if (clen < rl->hash_size) { - wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Not " - "enough room for MAC"); - crypto_hash_finish(hmac, NULL, NULL); - return -1; - } - - if (crypto_hash_finish(hmac, pos, &clen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed " - "to calculate HMAC"); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Write HMAC", - pos, clen); - pos += clen; - if (rl->iv_size) { - size_t len = pos - payload; - size_t pad; - pad = (len + 1) % rl->iv_size; - if (pad) - pad = rl->iv_size - pad; - if (pos + pad + 1 > buf + buf_size) { - wpa_printf(MSG_DEBUG, "TLSv1: No room for " - "block cipher padding"); - return -1; - } - os_memset(pos, pad, pad + 1); - pos += pad + 1; - } - - if (crypto_cipher_encrypt(rl->write_cbc, payload, - payload, pos - payload) < 0) - return -1; - } - - WPA_PUT_BE16(length, pos - length - 2); - inc_byte_array(rl->write_seq_num, TLS_SEQ_NUM_LEN); - - *out_len = pos - buf; - - return 0; -} - - -/** - * tlsv1_record_receive - TLS record layer: Process a received message - * @rl: Pointer to TLS record layer data - * @in_data: Received data - * @in_len: Length of the received data - * @out_data: Buffer for output data (must be at least as long as in_data) - * @out_len: Set to maximum out_data length by caller; used to return the - * length of the used data - * @alert: Buffer for returning an alert value on failure - * Returns: 0 on success, -1 on failure - * - * This function decrypts the received message, verifies HMAC and TLS record - * layer header. - */ -int tlsv1_record_receive(struct tlsv1_record_layer *rl, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t *out_len, u8 *alert) -{ - size_t i, rlen, hlen; - u8 padlen; - struct crypto_hash *hmac; - u8 len[2], hash[100]; - - wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Received", - in_data, in_len); - - if (in_len < TLS_RECORD_HEADER_LEN) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short record (in_len=%lu)", - (unsigned long) in_len); - *alert = TLS_ALERT_DECODE_ERROR; - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received content type %d version %d.%d " - "length %d", in_data[0], in_data[1], in_data[2], - WPA_GET_BE16(in_data + 3)); - - if (in_data[0] != TLS_CONTENT_TYPE_HANDSHAKE && - in_data[0] != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC && - in_data[0] != TLS_CONTENT_TYPE_ALERT && - in_data[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type 0x%x", - in_data[0]); - *alert = TLS_ALERT_UNEXPECTED_MESSAGE; - return -1; - } - - if (WPA_GET_BE16(in_data + 1) != TLS_VERSION) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version " - "%d.%d", in_data[1], in_data[2]); - *alert = TLS_ALERT_PROTOCOL_VERSION; - return -1; - } - - rlen = WPA_GET_BE16(in_data + 3); - - /* TLSCiphertext must not be more than 2^14+2048 bytes */ - if (TLS_RECORD_HEADER_LEN + rlen > 18432) { - wpa_printf(MSG_DEBUG, "TLSv1: Record overflow (len=%lu)", - (unsigned long) (TLS_RECORD_HEADER_LEN + rlen)); - *alert = TLS_ALERT_RECORD_OVERFLOW; - return -1; - } - - in_data += TLS_RECORD_HEADER_LEN; - in_len -= TLS_RECORD_HEADER_LEN; - - if (rlen > in_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Not all record data included " - "(rlen=%lu > in_len=%lu)", - (unsigned long) rlen, (unsigned long) in_len); - *alert = TLS_ALERT_DECODE_ERROR; - return -1; - } - - in_len = rlen; - - if (*out_len < in_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Not enough output buffer for " - "processing received record"); - *alert = TLS_ALERT_INTERNAL_ERROR; - return -1; - } - - os_memcpy(out_data, in_data, in_len); - *out_len = in_len; - - if (rl->read_cipher_suite != TLS_NULL_WITH_NULL_NULL) { - if (crypto_cipher_decrypt(rl->read_cbc, out_data, - out_data, in_len) < 0) { - *alert = TLS_ALERT_DECRYPTION_FAILED; - return -1; - } - if (rl->iv_size) { - if (in_len == 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short record" - " (no pad)"); - *alert = TLS_ALERT_DECODE_ERROR; - return -1; - } - padlen = out_data[in_len - 1]; - if (padlen >= in_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Incorrect pad " - "length (%u, in_len=%lu) in " - "received record", - padlen, (unsigned long) in_len); - *alert = TLS_ALERT_DECRYPTION_FAILED; - return -1; - } - for (i = in_len - padlen; i < in_len; i++) { - if (out_data[i] != padlen) { - wpa_hexdump(MSG_DEBUG, - "TLSv1: Invalid pad in " - "received record", - out_data + in_len - padlen, - padlen); - *alert = TLS_ALERT_DECRYPTION_FAILED; - return -1; - } - } - - *out_len -= padlen + 1; - } - - wpa_hexdump(MSG_MSGDUMP, - "TLSv1: Record Layer - Decrypted data", - out_data, in_len); - - if (*out_len < rl->hash_size) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short record; no " - "hash value"); - *alert = TLS_ALERT_INTERNAL_ERROR; - return -1; - } - - *out_len -= rl->hash_size; - - hmac = crypto_hash_init(rl->hash_alg, rl->read_mac_secret, - rl->hash_size); - if (hmac == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed " - "to initialize HMAC"); - *alert = TLS_ALERT_INTERNAL_ERROR; - return -1; - } - - crypto_hash_update(hmac, rl->read_seq_num, TLS_SEQ_NUM_LEN); - /* type + version + length + fragment */ - crypto_hash_update(hmac, in_data - TLS_RECORD_HEADER_LEN, 3); - WPA_PUT_BE16(len, *out_len); - crypto_hash_update(hmac, len, 2); - crypto_hash_update(hmac, out_data, *out_len); - hlen = sizeof(hash); - if (crypto_hash_finish(hmac, hash, &hlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed " - "to calculate HMAC"); - return -1; - } - if (hlen != rl->hash_size || - os_memcmp(hash, out_data + *out_len, hlen) != 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Invalid HMAC value in " - "received message"); - *alert = TLS_ALERT_BAD_RECORD_MAC; - return -1; - } - } - - /* TLSCompressed must not be more than 2^14+1024 bytes */ - if (TLS_RECORD_HEADER_LEN + *out_len > 17408) { - wpa_printf(MSG_DEBUG, "TLSv1: Record overflow (len=%lu)", - (unsigned long) (TLS_RECORD_HEADER_LEN + *out_len)); - *alert = TLS_ALERT_RECORD_OVERFLOW; - return -1; - } - - inc_byte_array(rl->read_seq_num, TLS_SEQ_NUM_LEN); - - return 0; -} diff --git a/contrib/hostapd/src/tls/tlsv1_record.h b/contrib/hostapd/src/tls/tlsv1_record.h deleted file mode 100644 index 9170fb1a2f..0000000000 --- a/contrib/hostapd/src/tls/tlsv1_record.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * TLSv1 Record Protocol - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TLSV1_RECORD_H -#define TLSV1_RECORD_H - -#include "crypto.h" - -#define TLS_MAX_WRITE_MAC_SECRET_LEN 20 -#define TLS_MAX_WRITE_KEY_LEN 32 -#define TLS_MAX_IV_LEN 16 -#define TLS_MAX_KEY_BLOCK_LEN (2 * (TLS_MAX_WRITE_MAC_SECRET_LEN + \ - TLS_MAX_WRITE_KEY_LEN + TLS_MAX_IV_LEN)) - -#define TLS_SEQ_NUM_LEN 8 -#define TLS_RECORD_HEADER_LEN 5 - -/* ContentType */ -enum { - TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC = 20, - TLS_CONTENT_TYPE_ALERT = 21, - TLS_CONTENT_TYPE_HANDSHAKE = 22, - TLS_CONTENT_TYPE_APPLICATION_DATA = 23 -}; - -struct tlsv1_record_layer { - u8 write_mac_secret[TLS_MAX_WRITE_MAC_SECRET_LEN]; - u8 read_mac_secret[TLS_MAX_WRITE_MAC_SECRET_LEN]; - u8 write_key[TLS_MAX_WRITE_KEY_LEN]; - u8 read_key[TLS_MAX_WRITE_KEY_LEN]; - u8 write_iv[TLS_MAX_IV_LEN]; - u8 read_iv[TLS_MAX_IV_LEN]; - - size_t hash_size; - size_t key_material_len; - size_t iv_size; /* also block_size */ - - enum crypto_hash_alg hash_alg; - enum crypto_cipher_alg cipher_alg; - - u8 write_seq_num[TLS_SEQ_NUM_LEN]; - u8 read_seq_num[TLS_SEQ_NUM_LEN]; - - u16 cipher_suite; - u16 write_cipher_suite; - u16 read_cipher_suite; - - struct crypto_cipher *write_cbc; - struct crypto_cipher *read_cbc; -}; - - -int tlsv1_record_set_cipher_suite(struct tlsv1_record_layer *rl, - u16 cipher_suite); -int tlsv1_record_change_write_cipher(struct tlsv1_record_layer *rl); -int tlsv1_record_change_read_cipher(struct tlsv1_record_layer *rl); -int tlsv1_record_send(struct tlsv1_record_layer *rl, u8 content_type, u8 *buf, - size_t buf_size, size_t payload_len, size_t *out_len); -int tlsv1_record_receive(struct tlsv1_record_layer *rl, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t *out_len, u8 *alert); - -#endif /* TLSV1_RECORD_H */ diff --git a/contrib/hostapd/src/tls/tlsv1_server.c b/contrib/hostapd/src/tls/tlsv1_server.c deleted file mode 100644 index c204a4778a..0000000000 --- a/contrib/hostapd/src/tls/tlsv1_server.c +++ /dev/null @@ -1,596 +0,0 @@ -/* - * TLSv1 server (RFC 2246) - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha1.h" -#include "tls.h" -#include "tlsv1_common.h" -#include "tlsv1_record.h" -#include "tlsv1_server.h" -#include "tlsv1_server_i.h" - -/* TODO: - * Support for a message fragmented across several records (RFC 2246, 6.2.1) - */ - - -void tlsv1_server_alert(struct tlsv1_server *conn, u8 level, u8 description) -{ - conn->alert_level = level; - conn->alert_description = description; -} - - -int tlsv1_server_derive_keys(struct tlsv1_server *conn, - const u8 *pre_master_secret, - size_t pre_master_secret_len) -{ - u8 seed[2 * TLS_RANDOM_LEN]; - u8 key_block[TLS_MAX_KEY_BLOCK_LEN]; - u8 *pos; - size_t key_block_len; - - if (pre_master_secret) { - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret", - pre_master_secret, pre_master_secret_len); - os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, - TLS_RANDOM_LEN); - if (tls_prf(pre_master_secret, pre_master_secret_len, - "master secret", seed, 2 * TLS_RANDOM_LEN, - conn->master_secret, TLS_MASTER_SECRET_LEN)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive " - "master_secret"); - return -1; - } - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret", - conn->master_secret, TLS_MASTER_SECRET_LEN); - } - - os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN); - key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len + - conn->rl.iv_size); - if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, - "key expansion", seed, 2 * TLS_RANDOM_LEN, - key_block, key_block_len)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block"); - return -1; - } - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block", - key_block, key_block_len); - - pos = key_block; - - /* client_write_MAC_secret */ - os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size); - pos += conn->rl.hash_size; - /* server_write_MAC_secret */ - os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size); - pos += conn->rl.hash_size; - - /* client_write_key */ - os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len); - pos += conn->rl.key_material_len; - /* server_write_key */ - os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len); - pos += conn->rl.key_material_len; - - /* client_write_IV */ - os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size); - pos += conn->rl.iv_size; - /* server_write_IV */ - os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size); - pos += conn->rl.iv_size; - - return 0; -} - - -/** - * tlsv1_server_handshake - Process TLS handshake - * @conn: TLSv1 server connection data from tlsv1_server_init() - * @in_data: Input data from TLS peer - * @in_len: Input data length - * @out_len: Length of the output buffer. - * Returns: Pointer to output data, %NULL on failure - */ -u8 * tlsv1_server_handshake(struct tlsv1_server *conn, - const u8 *in_data, size_t in_len, - size_t *out_len) -{ - const u8 *pos, *end; - u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct; - size_t in_msg_len; - - if (in_data == NULL || in_len == 0) { - wpa_printf(MSG_DEBUG, "TLSv1: No input data to server"); - return NULL; - } - - pos = in_data; - end = in_data + in_len; - in_msg = os_malloc(in_len); - if (in_msg == NULL) - return NULL; - - /* Each received packet may include multiple records */ - while (pos < end) { - in_msg_len = in_len; - if (tlsv1_record_receive(&conn->rl, pos, end - pos, - in_msg, &in_msg_len, &alert)) { - wpa_printf(MSG_DEBUG, "TLSv1: Processing received " - "record failed"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); - goto failed; - } - ct = pos[0]; - - in_pos = in_msg; - in_end = in_msg + in_msg_len; - - /* Each received record may include multiple messages of the - * same ContentType. */ - while (in_pos < in_end) { - in_msg_len = in_end - in_pos; - if (tlsv1_server_process_handshake(conn, ct, in_pos, - &in_msg_len) < 0) - goto failed; - in_pos += in_msg_len; - } - - pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); - } - - os_free(in_msg); - in_msg = NULL; - - msg = tlsv1_server_handshake_write(conn, out_len); - -failed: - os_free(in_msg); - if (conn->alert_level) { - if (conn->state == FAILED) { - /* Avoid alert loops */ - wpa_printf(MSG_DEBUG, "TLSv1: Drop alert loop"); - os_free(msg); - return NULL; - } - conn->state = FAILED; - os_free(msg); - msg = tlsv1_server_send_alert(conn, conn->alert_level, - conn->alert_description, - out_len); - } - - return msg; -} - - -/** - * tlsv1_server_encrypt - Encrypt data into TLS tunnel - * @conn: TLSv1 server connection data from tlsv1_server_init() - * @in_data: Pointer to plaintext data to be encrypted - * @in_len: Input buffer length - * @out_data: Pointer to output buffer (encrypted TLS data) - * @out_len: Maximum out_data length - * Returns: Number of bytes written to out_data, -1 on failure - * - * This function is used after TLS handshake has been completed successfully to - * send data in the encrypted tunnel. - */ -int tlsv1_server_encrypt(struct tlsv1_server *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - size_t rlen; - - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData", - in_data, in_len); - - os_memcpy(out_data + TLS_RECORD_HEADER_LEN, in_data, in_len); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA, - out_data, out_len, in_len, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - return rlen; -} - - -/** - * tlsv1_server_decrypt - Decrypt data from TLS tunnel - * @conn: TLSv1 server connection data from tlsv1_server_init() - * @in_data: Pointer to input buffer (encrypted TLS data) - * @in_len: Input buffer length - * @out_data: Pointer to output buffer (decrypted data from TLS tunnel) - * @out_len: Maximum out_data length - * Returns: Number of bytes written to out_data, -1 on failure - * - * This function is used after TLS handshake has been completed successfully to - * receive data from the encrypted tunnel. - */ -int tlsv1_server_decrypt(struct tlsv1_server *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - const u8 *in_end, *pos; - int res; - u8 alert, *out_end, *out_pos; - size_t olen; - - pos = in_data; - in_end = in_data + in_len; - out_pos = out_data; - out_end = out_data + out_len; - - while (pos < in_end) { - if (pos[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type " - "0x%x", pos[0]); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - olen = out_end - out_pos; - res = tlsv1_record_receive(&conn->rl, pos, in_end - pos, - out_pos, &olen, &alert); - if (res < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing " - "failed"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); - return -1; - } - out_pos += olen; - if (out_pos > out_end) { - wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough " - "for processing the received record"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); - } - - return out_pos - out_data; -} - - -/** - * tlsv1_server_global_init - Initialize TLSv1 server - * Returns: 0 on success, -1 on failure - * - * This function must be called before using any other TLSv1 server functions. - */ -int tlsv1_server_global_init(void) -{ - return crypto_global_init(); -} - - -/** - * tlsv1_server_global_deinit - Deinitialize TLSv1 server - * - * This function can be used to deinitialize the TLSv1 server that was - * initialized by calling tlsv1_server_global_init(). No TLSv1 server functions - * can be called after this before calling tlsv1_server_global_init() again. - */ -void tlsv1_server_global_deinit(void) -{ - crypto_global_deinit(); -} - - -/** - * tlsv1_server_init - Initialize TLSv1 server connection - * @cred: Pointer to server credentials from tlsv1_server_cred_alloc() - * Returns: Pointer to TLSv1 server connection data or %NULL on failure - */ -struct tlsv1_server * tlsv1_server_init(struct tlsv1_credentials *cred) -{ - struct tlsv1_server *conn; - size_t count; - u16 *suites; - - conn = os_zalloc(sizeof(*conn)); - if (conn == NULL) - return NULL; - - conn->cred = cred; - - conn->state = CLIENT_HELLO; - - if (tls_verify_hash_init(&conn->verify) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify " - "hash"); - os_free(conn); - return NULL; - } - - count = 0; - suites = conn->cipher_suites; -#ifndef CONFIG_CRYPTO_INTERNAL - suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; -#endif /* CONFIG_CRYPTO_INTERNAL */ - suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; - suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; - suites[count++] = TLS_RSA_WITH_RC4_128_SHA; - suites[count++] = TLS_RSA_WITH_RC4_128_MD5; - conn->num_cipher_suites = count; - - return conn; -} - - -static void tlsv1_server_clear_data(struct tlsv1_server *conn) -{ - tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); - tlsv1_record_change_write_cipher(&conn->rl); - tlsv1_record_change_read_cipher(&conn->rl); - tls_verify_hash_free(&conn->verify); - - crypto_public_key_free(conn->client_rsa_key); - conn->client_rsa_key = NULL; - - os_free(conn->session_ticket); - conn->session_ticket = NULL; - conn->session_ticket_len = 0; - conn->use_session_ticket = 0; - - os_free(conn->dh_secret); - conn->dh_secret = NULL; - conn->dh_secret_len = 0; -} - - -/** - * tlsv1_server_deinit - Deinitialize TLSv1 server connection - * @conn: TLSv1 server connection data from tlsv1_server_init() - */ -void tlsv1_server_deinit(struct tlsv1_server *conn) -{ - tlsv1_server_clear_data(conn); - os_free(conn); -} - - -/** - * tlsv1_server_established - Check whether connection has been established - * @conn: TLSv1 server connection data from tlsv1_server_init() - * Returns: 1 if connection is established, 0 if not - */ -int tlsv1_server_established(struct tlsv1_server *conn) -{ - return conn->state == ESTABLISHED; -} - - -/** - * tlsv1_server_prf - Use TLS-PRF to derive keying material - * @conn: TLSv1 server connection data from tlsv1_server_init() - * @label: Label (e.g., description of the key) for PRF - * @server_random_first: seed is 0 = client_random|server_random, - * 1 = server_random|client_random - * @out: Buffer for output data from TLS-PRF - * @out_len: Length of the output buffer - * Returns: 0 on success, -1 on failure - */ -int tlsv1_server_prf(struct tlsv1_server *conn, const char *label, - int server_random_first, u8 *out, size_t out_len) -{ - u8 seed[2 * TLS_RANDOM_LEN]; - - if (conn->state != ESTABLISHED) - return -1; - - if (server_random_first) { - os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, - TLS_RANDOM_LEN); - } else { - os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, - TLS_RANDOM_LEN); - } - - return tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, - label, seed, 2 * TLS_RANDOM_LEN, out, out_len); -} - - -/** - * tlsv1_server_get_cipher - Get current cipher name - * @conn: TLSv1 server connection data from tlsv1_server_init() - * @buf: Buffer for the cipher name - * @buflen: buf size - * Returns: 0 on success, -1 on failure - * - * Get the name of the currently used cipher. - */ -int tlsv1_server_get_cipher(struct tlsv1_server *conn, char *buf, - size_t buflen) -{ - char *cipher; - - switch (conn->rl.cipher_suite) { - case TLS_RSA_WITH_RC4_128_MD5: - cipher = "RC4-MD5"; - break; - case TLS_RSA_WITH_RC4_128_SHA: - cipher = "RC4-SHA"; - break; - case TLS_RSA_WITH_DES_CBC_SHA: - cipher = "DES-CBC-SHA"; - break; - case TLS_RSA_WITH_3DES_EDE_CBC_SHA: - cipher = "DES-CBC3-SHA"; - break; - case TLS_DH_anon_WITH_AES_128_CBC_SHA: - cipher = "ADH-AES-128-SHA"; - break; - case TLS_RSA_WITH_AES_256_CBC_SHA: - cipher = "AES-256-SHA"; - break; - case TLS_RSA_WITH_AES_128_CBC_SHA: - cipher = "AES-128-SHA"; - break; - default: - return -1; - } - - if (os_strlcpy(buf, cipher, buflen) >= buflen) - return -1; - return 0; -} - - -/** - * tlsv1_server_shutdown - Shutdown TLS connection - * @conn: TLSv1 server connection data from tlsv1_server_init() - * Returns: 0 on success, -1 on failure - */ -int tlsv1_server_shutdown(struct tlsv1_server *conn) -{ - conn->state = CLIENT_HELLO; - - if (tls_verify_hash_init(&conn->verify) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify " - "hash"); - return -1; - } - - tlsv1_server_clear_data(conn); - - return 0; -} - - -/** - * tlsv1_server_resumed - Was session resumption used - * @conn: TLSv1 server connection data from tlsv1_server_init() - * Returns: 1 if current session used session resumption, 0 if not - */ -int tlsv1_server_resumed(struct tlsv1_server *conn) -{ - return 0; -} - - -/** - * tlsv1_server_get_keys - Get master key and random data from TLS connection - * @conn: TLSv1 server connection data from tlsv1_server_init() - * @keys: Structure of key/random data (filled on success) - * Returns: 0 on success, -1 on failure - */ -int tlsv1_server_get_keys(struct tlsv1_server *conn, struct tls_keys *keys) -{ - os_memset(keys, 0, sizeof(*keys)); - if (conn->state == CLIENT_HELLO) - return -1; - - keys->client_random = conn->client_random; - keys->client_random_len = TLS_RANDOM_LEN; - - if (conn->state != SERVER_HELLO) { - keys->server_random = conn->server_random; - keys->server_random_len = TLS_RANDOM_LEN; - keys->master_key = conn->master_secret; - keys->master_key_len = TLS_MASTER_SECRET_LEN; - } - - return 0; -} - - -/** - * tlsv1_server_get_keyblock_size - Get TLS key_block size - * @conn: TLSv1 server connection data from tlsv1_server_init() - * Returns: Size of the key_block for the negotiated cipher suite or -1 on - * failure - */ -int tlsv1_server_get_keyblock_size(struct tlsv1_server *conn) -{ - if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO) - return -1; - - return 2 * (conn->rl.hash_size + conn->rl.key_material_len + - conn->rl.iv_size); -} - - -/** - * tlsv1_server_set_cipher_list - Configure acceptable cipher suites - * @conn: TLSv1 server connection data from tlsv1_server_init() - * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers - * (TLS_CIPHER_*). - * Returns: 0 on success, -1 on failure - */ -int tlsv1_server_set_cipher_list(struct tlsv1_server *conn, u8 *ciphers) -{ -#ifdef EAP_FAST - size_t count; - u16 *suites; - - /* TODO: implement proper configuration of cipher suites */ - if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) { - count = 0; - suites = conn->cipher_suites; -#ifndef CONFIG_CRYPTO_INTERNAL - suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; -#endif /* CONFIG_CRYPTO_INTERNAL */ - suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; - suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; - suites[count++] = TLS_RSA_WITH_RC4_128_SHA; - suites[count++] = TLS_RSA_WITH_RC4_128_MD5; -#ifndef CONFIG_CRYPTO_INTERNAL - suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA; -#endif /* CONFIG_CRYPTO_INTERNAL */ - suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; - suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA; - suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5; - suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA; - conn->num_cipher_suites = count; - } - - return 0; -#else /* EAP_FAST */ - return -1; -#endif /* EAP_FAST */ -} - - -int tlsv1_server_set_verify(struct tlsv1_server *conn, int verify_peer) -{ - conn->verify_peer = verify_peer; - return 0; -} - - -void tlsv1_server_set_session_ticket_cb(struct tlsv1_server *conn, - tlsv1_server_session_ticket_cb cb, - void *ctx) -{ - wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)", - cb, ctx); - conn->session_ticket_cb = cb; - conn->session_ticket_cb_ctx = ctx; -} diff --git a/contrib/hostapd/src/tls/tlsv1_server.h b/contrib/hostapd/src/tls/tlsv1_server.h deleted file mode 100644 index 00c536c3ee..0000000000 --- a/contrib/hostapd/src/tls/tlsv1_server.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * TLSv1 server (RFC 2246) - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TLSV1_SERVER_H -#define TLSV1_SERVER_H - -#include "tlsv1_cred.h" - -struct tlsv1_server; - -int tlsv1_server_global_init(void); -void tlsv1_server_global_deinit(void); -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, - 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); -int tlsv1_server_encrypt(struct tlsv1_server *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len); -int tlsv1_server_decrypt(struct tlsv1_server *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len); -int tlsv1_server_get_cipher(struct tlsv1_server *conn, char *buf, - size_t buflen); -int tlsv1_server_shutdown(struct tlsv1_server *conn); -int tlsv1_server_resumed(struct tlsv1_server *conn); -int tlsv1_server_get_keys(struct tlsv1_server *conn, struct tls_keys *keys); -int tlsv1_server_get_keyblock_size(struct tlsv1_server *conn); -int tlsv1_server_set_cipher_list(struct tlsv1_server *conn, u8 *ciphers); -int tlsv1_server_set_verify(struct tlsv1_server *conn, int verify_peer); - -typedef int (*tlsv1_server_session_ticket_cb) -(void *ctx, const u8 *ticket, size_t len, const u8 *client_random, - const u8 *server_random, u8 *master_secret); - -void tlsv1_server_set_session_ticket_cb(struct tlsv1_server *conn, - tlsv1_server_session_ticket_cb cb, - void *ctx); - -#endif /* TLSV1_SERVER_H */ diff --git a/contrib/hostapd/src/tls/tlsv1_server_i.h b/contrib/hostapd/src/tls/tlsv1_server_i.h deleted file mode 100644 index d11ea7559f..0000000000 --- a/contrib/hostapd/src/tls/tlsv1_server_i.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * TLSv1 server - internal structures - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TLSV1_SERVER_I_H -#define TLSV1_SERVER_I_H - -struct tlsv1_server { - enum { - CLIENT_HELLO, SERVER_HELLO, SERVER_CERTIFICATE, - SERVER_KEY_EXCHANGE, SERVER_CERTIFICATE_REQUEST, - SERVER_HELLO_DONE, CLIENT_CERTIFICATE, CLIENT_KEY_EXCHANGE, - CERTIFICATE_VERIFY, CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - ESTABLISHED, FAILED - } state; - - struct tlsv1_record_layer rl; - - u8 session_id[TLS_SESSION_ID_MAX_LEN]; - size_t session_id_len; - u8 client_random[TLS_RANDOM_LEN]; - u8 server_random[TLS_RANDOM_LEN]; - u8 master_secret[TLS_MASTER_SECRET_LEN]; - - u8 alert_level; - u8 alert_description; - - struct crypto_public_key *client_rsa_key; - - struct tls_verify_hash verify; - -#define MAX_CIPHER_COUNT 30 - u16 cipher_suites[MAX_CIPHER_COUNT]; - size_t num_cipher_suites; - - u16 cipher_suite; - - struct tlsv1_credentials *cred; - - int verify_peer; - u16 client_version; - - u8 *session_ticket; - size_t session_ticket_len; - - tlsv1_server_session_ticket_cb session_ticket_cb; - void *session_ticket_cb_ctx; - - int use_session_ticket; - - u8 *dh_secret; - size_t dh_secret_len; -}; - - -void tlsv1_server_alert(struct tlsv1_server *conn, u8 level, u8 description); -int tlsv1_server_derive_keys(struct tlsv1_server *conn, - const u8 *pre_master_secret, - size_t pre_master_secret_len); -u8 * tlsv1_server_handshake_write(struct tlsv1_server *conn, size_t *out_len); -u8 * tlsv1_server_send_alert(struct tlsv1_server *conn, u8 level, - u8 description, size_t *out_len); -int tlsv1_server_process_handshake(struct tlsv1_server *conn, u8 ct, - const u8 *buf, size_t *len); - -#endif /* TLSV1_SERVER_I_H */ diff --git a/contrib/hostapd/src/tls/tlsv1_server_read.c b/contrib/hostapd/src/tls/tlsv1_server_read.c deleted file mode 100644 index 397d74a197..0000000000 --- a/contrib/hostapd/src/tls/tlsv1_server_read.c +++ /dev/null @@ -1,1138 +0,0 @@ -/* - * TLSv1 server - read handshake message - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "md5.h" -#include "sha1.h" -#include "x509v3.h" -#include "tls.h" -#include "tlsv1_common.h" -#include "tlsv1_record.h" -#include "tlsv1_server.h" -#include "tlsv1_server_i.h" - - -static int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct, - const u8 *in_data, size_t *in_len); -static int tls_process_change_cipher_spec(struct tlsv1_server *conn, - u8 ct, const u8 *in_data, - size_t *in_len); - - -static int tls_process_client_hello(struct tlsv1_server *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end, *c; - size_t left, len, i, j; - u16 cipher_suite; - u16 num_suites; - int compr_null_found; - u16 ext_type, ext_len; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " - "received content type 0x%x", ct); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) - goto decode_error; - - /* HandshakeType msg_type */ - if (*pos != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) { - wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " - "message %d (expected ClientHello)", *pos); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - wpa_printf(MSG_DEBUG, "TLSv1: Received ClientHello"); - pos++; - /* uint24 length */ - len = WPA_GET_BE24(pos); - pos += 3; - left -= 4; - - if (len > left) - goto decode_error; - - /* body - ClientHello */ - - wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello", pos, len); - end = pos + len; - - /* ProtocolVersion client_version */ - if (end - pos < 2) - goto decode_error; - conn->client_version = WPA_GET_BE16(pos); - wpa_printf(MSG_DEBUG, "TLSv1: Client version %d.%d", - conn->client_version >> 8, conn->client_version & 0xff); - if (conn->client_version < TLS_VERSION) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in " - "ClientHello"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_PROTOCOL_VERSION); - return -1; - } - pos += 2; - - /* Random random */ - if (end - pos < TLS_RANDOM_LEN) - goto decode_error; - - os_memcpy(conn->client_random, pos, TLS_RANDOM_LEN); - pos += TLS_RANDOM_LEN; - wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random", - conn->client_random, TLS_RANDOM_LEN); - - /* SessionID session_id */ - if (end - pos < 1) - goto decode_error; - if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN) - goto decode_error; - wpa_hexdump(MSG_MSGDUMP, "TLSv1: client session_id", pos + 1, *pos); - pos += 1 + *pos; - /* TODO: add support for session resumption */ - - /* CipherSuite cipher_suites<2..2^16-1> */ - if (end - pos < 2) - goto decode_error; - num_suites = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < num_suites) - goto decode_error; - wpa_hexdump(MSG_MSGDUMP, "TLSv1: client cipher suites", - pos, num_suites); - if (num_suites & 1) - goto decode_error; - num_suites /= 2; - - cipher_suite = 0; - for (i = 0; !cipher_suite && i < conn->num_cipher_suites; i++) { - c = pos; - for (j = 0; j < num_suites; j++) { - u16 tmp = WPA_GET_BE16(c); - c += 2; - if (!cipher_suite && tmp == conn->cipher_suites[i]) { - cipher_suite = tmp; - break; - } - } - } - pos += num_suites * 2; - if (!cipher_suite) { - wpa_printf(MSG_INFO, "TLSv1: No supported cipher suite " - "available"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_ILLEGAL_PARAMETER); - return -1; - } - - if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for " - "record layer"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - conn->cipher_suite = cipher_suite; - - /* CompressionMethod compression_methods<1..2^8-1> */ - if (end - pos < 1) - goto decode_error; - num_suites = *pos++; - if (end - pos < num_suites) - goto decode_error; - wpa_hexdump(MSG_MSGDUMP, "TLSv1: client compression_methods", - pos, num_suites); - compr_null_found = 0; - for (i = 0; i < num_suites; i++) { - if (*pos++ == TLS_COMPRESSION_NULL) - compr_null_found = 1; - } - if (!compr_null_found) { - wpa_printf(MSG_INFO, "TLSv1: Client does not accept NULL " - "compression"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_ILLEGAL_PARAMETER); - return -1; - } - - if (end - pos == 1) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected extra octet in the " - "end of ClientHello: 0x%02x", *pos); - goto decode_error; - } - - if (end - pos >= 2) { - /* Extension client_hello_extension_list<0..2^16-1> */ - ext_len = WPA_GET_BE16(pos); - pos += 2; - - wpa_printf(MSG_DEBUG, "TLSv1: %u bytes of ClientHello " - "extensions", ext_len); - if (end - pos != ext_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Invalid ClientHello " - "extension list length %u (expected %u)", - ext_len, (unsigned int) (end - pos)); - goto decode_error; - } - - /* - * struct { - * ExtensionType extension_type (0..65535) - * opaque extension_data<0..2^16-1> - * } Extension; - */ - - while (pos < end) { - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "TLSv1: Invalid " - "extension_type field"); - goto decode_error; - } - - ext_type = WPA_GET_BE16(pos); - pos += 2; - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "TLSv1: Invalid " - "extension_data length field"); - goto decode_error; - } - - ext_len = WPA_GET_BE16(pos); - pos += 2; - - if (end - pos < ext_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Invalid " - "extension_data field"); - goto decode_error; - } - - wpa_printf(MSG_DEBUG, "TLSv1: ClientHello Extension " - "type %u", ext_type); - wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello " - "Extension data", pos, ext_len); - - if (ext_type == TLS_EXT_SESSION_TICKET) { - os_free(conn->session_ticket); - conn->session_ticket = os_malloc(ext_len); - if (conn->session_ticket) { - os_memcpy(conn->session_ticket, pos, - ext_len); - conn->session_ticket_len = ext_len; - } - } - - pos += ext_len; - } - } - - *in_len = end - in_data; - - wpa_printf(MSG_DEBUG, "TLSv1: ClientHello OK - proceed to " - "ServerHello"); - conn->state = SERVER_HELLO; - - return 0; - -decode_error: - wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ClientHello"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; -} - - -static int tls_process_certificate(struct tlsv1_server *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len, list_len, cert_len, idx; - u8 type; - struct x509_certificate *chain = NULL, *last = NULL, *cert; - int reason; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " - "received content type 0x%x", ct); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message " - "(len=%lu)", (unsigned long) left); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - type = *pos++; - len = WPA_GET_BE24(pos); - pos += 3; - left -= 4; - - if (len > left) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message " - "length (len=%lu != left=%lu)", - (unsigned long) len, (unsigned long) left); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - if (type == TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) { - if (conn->verify_peer) { - wpa_printf(MSG_DEBUG, "TLSv1: Client did not include " - "Certificate"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - return tls_process_client_key_exchange(conn, ct, in_data, - in_len); - } - if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) { - wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " - "message %d (expected Certificate/" - "ClientKeyExchange)", type); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_printf(MSG_DEBUG, - "TLSv1: Received Certificate (certificate_list len %lu)", - (unsigned long) len); - - /* - * opaque ASN.1Cert<2^24-1>; - * - * struct { - * ASN.1Cert certificate_list<1..2^24-1>; - * } Certificate; - */ - - end = pos + len; - - if (end - pos < 3) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate " - "(left=%lu)", (unsigned long) left); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - list_len = WPA_GET_BE24(pos); - pos += 3; - - if ((size_t) (end - pos) != list_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list " - "length (len=%lu left=%lu)", - (unsigned long) list_len, - (unsigned long) (end - pos)); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - idx = 0; - while (pos < end) { - if (end - pos < 3) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " - "certificate_list"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - x509_certificate_chain_free(chain); - return -1; - } - - cert_len = WPA_GET_BE24(pos); - pos += 3; - - if ((size_t) (end - pos) < cert_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate " - "length (len=%lu left=%lu)", - (unsigned long) cert_len, - (unsigned long) (end - pos)); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - x509_certificate_chain_free(chain); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)", - (unsigned long) idx, (unsigned long) cert_len); - - if (idx == 0) { - crypto_public_key_free(conn->client_rsa_key); - if (tls_parse_cert(pos, cert_len, - &conn->client_rsa_key)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " - "the certificate"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_BAD_CERTIFICATE); - x509_certificate_chain_free(chain); - return -1; - } - } - - cert = x509_certificate_parse(pos, cert_len); - if (cert == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " - "the certificate"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_BAD_CERTIFICATE); - x509_certificate_chain_free(chain); - return -1; - } - - if (last == NULL) - chain = cert; - else - last->next = cert; - last = cert; - - idx++; - pos += cert_len; - } - - if (x509_certificate_chain_validate(conn->cred->trusted_certs, chain, - &reason) < 0) { - int tls_reason; - wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain " - "validation failed (reason=%d)", reason); - switch (reason) { - case X509_VALIDATE_BAD_CERTIFICATE: - tls_reason = TLS_ALERT_BAD_CERTIFICATE; - break; - case X509_VALIDATE_UNSUPPORTED_CERTIFICATE: - tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE; - break; - case X509_VALIDATE_CERTIFICATE_REVOKED: - tls_reason = TLS_ALERT_CERTIFICATE_REVOKED; - break; - case X509_VALIDATE_CERTIFICATE_EXPIRED: - tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED; - break; - case X509_VALIDATE_CERTIFICATE_UNKNOWN: - tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN; - break; - case X509_VALIDATE_UNKNOWN_CA: - tls_reason = TLS_ALERT_UNKNOWN_CA; - break; - default: - tls_reason = TLS_ALERT_BAD_CERTIFICATE; - break; - } - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason); - x509_certificate_chain_free(chain); - return -1; - } - - x509_certificate_chain_free(chain); - - *in_len = end - in_data; - - conn->state = CLIENT_KEY_EXCHANGE; - - return 0; -} - - -static int tls_process_client_key_exchange_rsa( - struct tlsv1_server *conn, const u8 *pos, const u8 *end) -{ - u8 *out; - size_t outlen, outbuflen; - u16 encr_len; - int res; - int use_random = 0; - - if (end - pos < 2) { - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - encr_len = WPA_GET_BE16(pos); - pos += 2; - - outbuflen = outlen = end - pos; - out = os_malloc(outlen >= TLS_PRE_MASTER_SECRET_LEN ? - outlen : TLS_PRE_MASTER_SECRET_LEN); - if (out == NULL) { - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - /* - * struct { - * ProtocolVersion client_version; - * opaque random[46]; - * } PreMasterSecret; - * - * struct { - * public-key-encrypted PreMasterSecret pre_master_secret; - * } EncryptedPreMasterSecret; - */ - - /* - * Note: To avoid Bleichenbacher attack, we do not report decryption or - * parsing errors from EncryptedPreMasterSecret processing to the - * client. Instead, a random pre-master secret is used to force the - * handshake to fail. - */ - - if (crypto_private_key_decrypt_pkcs1_v15(conn->cred->key, - pos, end - pos, - out, &outlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt " - "PreMasterSecret (encr_len=%d outlen=%lu)", - (int) (end - pos), (unsigned long) outlen); - use_random = 1; - } - - if (outlen != TLS_PRE_MASTER_SECRET_LEN) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected PreMasterSecret " - "length %lu", (unsigned long) outlen); - use_random = 1; - } - - if (WPA_GET_BE16(out) != conn->client_version) { - wpa_printf(MSG_DEBUG, "TLSv1: Client version in " - "ClientKeyExchange does not match with version in " - "ClientHello"); - use_random = 1; - } - - if (use_random) { - wpa_printf(MSG_DEBUG, "TLSv1: Using random premaster secret " - "to avoid revealing information about private key"); - outlen = TLS_PRE_MASTER_SECRET_LEN; - if (os_get_random(out, outlen)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " - "data"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(out); - return -1; - } - } - - res = tlsv1_server_derive_keys(conn, out, outlen); - - /* Clear the pre-master secret since it is not needed anymore */ - os_memset(out, 0, outbuflen); - os_free(out); - - if (res) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - return 0; -} - - -static int tls_process_client_key_exchange_dh_anon( - struct tlsv1_server *conn, const u8 *pos, const u8 *end) -{ -#ifdef EAP_FAST - const u8 *dh_yc; - u16 dh_yc_len; - u8 *shared; - size_t shared_len; - int res; - - /* - * struct { - * select (PublicValueEncoding) { - * case implicit: struct { }; - * case explicit: opaque dh_Yc<1..2^16-1>; - * } dh_public; - * } ClientDiffieHellmanPublic; - */ - - wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientDiffieHellmanPublic", - pos, end - pos); - - if (end == pos) { - wpa_printf(MSG_DEBUG, "TLSv1: Implicit public value encoding " - "not supported"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - if (end - pos < 3) { - wpa_printf(MSG_DEBUG, "TLSv1: Invalid client public value " - "length"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - dh_yc_len = WPA_GET_BE16(pos); - dh_yc = pos + 2; - - if (dh_yc + dh_yc_len > end) { - wpa_printf(MSG_DEBUG, "TLSv1: Client public value overflow " - "(length %d)", dh_yc_len); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)", - dh_yc, dh_yc_len); - - if (conn->cred == NULL || conn->cred->dh_p == NULL || - conn->dh_secret == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - shared_len = conn->cred->dh_p_len; - shared = os_malloc(shared_len); - if (shared == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for " - "DH"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - /* shared = Yc^secret mod p */ - if (crypto_mod_exp(dh_yc, dh_yc_len, conn->dh_secret, - conn->dh_secret_len, - conn->cred->dh_p, conn->cred->dh_p_len, - shared, &shared_len)) { - os_free(shared); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange", - shared, shared_len); - - os_memset(conn->dh_secret, 0, conn->dh_secret_len); - os_free(conn->dh_secret); - conn->dh_secret = NULL; - - res = tlsv1_server_derive_keys(conn, shared, shared_len); - - /* Clear the pre-master secret since it is not needed anymore */ - os_memset(shared, 0, shared_len); - os_free(shared); - - if (res) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - return 0; -#else /* EAP_FAST */ - return -1; -#endif /* EAP_FAST */ -} - - -static int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len; - u8 type; - tls_key_exchange keyx; - const struct tls_cipher_suite *suite; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " - "received content type 0x%x", ct); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short ClientKeyExchange " - "(Left=%lu)", (unsigned long) left); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - type = *pos++; - len = WPA_GET_BE24(pos); - pos += 3; - left -= 4; - - if (len > left) { - wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ClientKeyExchange " - "length (len=%lu != left=%lu)", - (unsigned long) len, (unsigned long) left); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - end = pos + len; - - if (type != TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) { - wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " - "message %d (expected ClientKeyExchange)", type); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received ClientKeyExchange"); - - wpa_hexdump(MSG_DEBUG, "TLSv1: ClientKeyExchange", pos, len); - - suite = tls_get_cipher_suite(conn->rl.cipher_suite); - if (suite == NULL) - keyx = TLS_KEY_X_NULL; - else - keyx = suite->key_exchange; - - if (keyx == TLS_KEY_X_DH_anon && - tls_process_client_key_exchange_dh_anon(conn, pos, end) < 0) - return -1; - - if (keyx != TLS_KEY_X_DH_anon && - tls_process_client_key_exchange_rsa(conn, pos, end) < 0) - return -1; - - *in_len = end - in_data; - - conn->state = CERTIFICATE_VERIFY; - - return 0; -} - - -static int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len; - u8 type; - size_t hlen, buflen; - u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos, *buf; - enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA; - u16 slen; - - if (ct == TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { - if (conn->verify_peer) { - wpa_printf(MSG_DEBUG, "TLSv1: Client did not include " - "CertificateVerify"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - return tls_process_change_cipher_spec(conn, ct, in_data, - in_len); - } - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " - "received content type 0x%x", ct); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateVerify " - "message (len=%lu)", (unsigned long) left); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - type = *pos++; - len = WPA_GET_BE24(pos); - pos += 3; - left -= 4; - - if (len > left) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected CertificateVerify " - "message length (len=%lu != left=%lu)", - (unsigned long) len, (unsigned long) left); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - end = pos + len; - - if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY) { - wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " - "message %d (expected CertificateVerify)", type); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateVerify"); - - /* - * struct { - * Signature signature; - * } CertificateVerify; - */ - - hpos = hash; - - if (alg == SIGN_ALG_RSA) { - hlen = MD5_MAC_LEN; - if (conn->verify.md5_cert == NULL || - crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) - { - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - conn->verify.md5_cert = NULL; - crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL); - conn->verify.sha1_cert = NULL; - return -1; - } - hpos += MD5_MAC_LEN; - } else - crypto_hash_finish(conn->verify.md5_cert, NULL, NULL); - - conn->verify.md5_cert = NULL; - hlen = SHA1_MAC_LEN; - if (conn->verify.sha1_cert == NULL || - crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) { - conn->verify.sha1_cert = NULL; - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - conn->verify.sha1_cert = NULL; - - if (alg == SIGN_ALG_RSA) - hlen += MD5_MAC_LEN; - - wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen); - - if (end - pos < 2) { - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - slen = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < slen) { - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - wpa_hexdump(MSG_MSGDUMP, "TLSv1: Signature", pos, end - pos); - if (conn->client_rsa_key == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: No client public key to verify " - "signature"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - buflen = end - pos; - buf = os_malloc(end - pos); - if (crypto_public_key_decrypt_pkcs1(conn->client_rsa_key, - pos, end - pos, buf, &buflen) < 0) - { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt signature"); - os_free(buf); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECRYPT_ERROR); - return -1; - } - - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Decrypted Signature", - buf, buflen); - - if (buflen != hlen || os_memcmp(buf, hash, buflen) != 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Invalid Signature in " - "CertificateVerify - did not match with calculated " - "hash"); - os_free(buf); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECRYPT_ERROR); - return -1; - } - - os_free(buf); - - *in_len = end - in_data; - - conn->state = CHANGE_CIPHER_SPEC; - - return 0; -} - - -static int tls_process_change_cipher_spec(struct tlsv1_server *conn, - u8 ct, const u8 *in_data, - size_t *in_len) -{ - const u8 *pos; - size_t left; - - if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " - "received content type 0x%x", ct); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 1) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - if (*pos != TLS_CHANGE_CIPHER_SPEC) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " - "received data 0x%x", *pos); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec"); - if (tlsv1_record_change_read_cipher(&conn->rl) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher " - "for record layer"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - *in_len = pos + 1 - in_data; - - conn->state = CLIENT_FINISHED; - - return 0; -} - - -static int tls_process_client_finished(struct tlsv1_server *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len, hlen; - u8 verify_data[TLS_VERIFY_DATA_LEN]; - u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; " - "received content type 0x%x", ct); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for " - "Finished", - (unsigned long) left); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received " - "type 0x%x", pos[0]); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - len = WPA_GET_BE24(pos + 1); - - pos += 4; - left -= 4; - - if (len > left) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished " - "(len=%lu > left=%lu)", - (unsigned long) len, (unsigned long) left); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - end = pos + len; - if (len != TLS_VERIFY_DATA_LEN) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length " - "in Finished: %lu (expected %d)", - (unsigned long) len, TLS_VERIFY_DATA_LEN); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished", - pos, TLS_VERIFY_DATA_LEN); - - hlen = MD5_MAC_LEN; - if (conn->verify.md5_client == NULL || - crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) { - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - conn->verify.md5_client = NULL; - crypto_hash_finish(conn->verify.sha1_client, NULL, NULL); - conn->verify.sha1_client = NULL; - return -1; - } - conn->verify.md5_client = NULL; - hlen = SHA1_MAC_LEN; - if (conn->verify.sha1_client == NULL || - crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN, - &hlen) < 0) { - conn->verify.sha1_client = NULL; - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - conn->verify.sha1_client = NULL; - - if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, - "client finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, - verify_data, TLS_VERIFY_DATA_LEN)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECRYPT_ERROR); - return -1; - } - wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)", - verify_data, TLS_VERIFY_DATA_LEN); - - if (os_memcmp(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) { - wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data"); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received Finished"); - - *in_len = end - in_data; - - if (conn->use_session_ticket) { - /* Abbreviated handshake using session ticket; RFC 4507 */ - wpa_printf(MSG_DEBUG, "TLSv1: Abbreviated handshake completed " - "successfully"); - conn->state = ESTABLISHED; - } else { - /* Full handshake */ - conn->state = SERVER_CHANGE_CIPHER_SPEC; - } - - return 0; -} - - -int tlsv1_server_process_handshake(struct tlsv1_server *conn, u8 ct, - const u8 *buf, size_t *len) -{ - if (ct == TLS_CONTENT_TYPE_ALERT) { - if (*len < 2) { - wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d", - buf[0], buf[1]); - *len = 2; - conn->state = FAILED; - return -1; - } - - switch (conn->state) { - case CLIENT_HELLO: - if (tls_process_client_hello(conn, ct, buf, len)) - return -1; - break; - case CLIENT_CERTIFICATE: - if (tls_process_certificate(conn, ct, buf, len)) - return -1; - break; - case CLIENT_KEY_EXCHANGE: - if (tls_process_client_key_exchange(conn, ct, buf, len)) - return -1; - break; - case CERTIFICATE_VERIFY: - if (tls_process_certificate_verify(conn, ct, buf, len)) - return -1; - break; - case CHANGE_CIPHER_SPEC: - if (tls_process_change_cipher_spec(conn, ct, buf, len)) - return -1; - break; - case CLIENT_FINISHED: - if (tls_process_client_finished(conn, ct, buf, len)) - return -1; - break; - default: - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d " - "while processing received message", - conn->state); - return -1; - } - - if (ct == TLS_CONTENT_TYPE_HANDSHAKE) - tls_verify_hash_add(&conn->verify, buf, *len); - - return 0; -} diff --git a/contrib/hostapd/src/tls/tlsv1_server_write.c b/contrib/hostapd/src/tls/tlsv1_server_write.c deleted file mode 100644 index cf54f4265c..0000000000 --- a/contrib/hostapd/src/tls/tlsv1_server_write.c +++ /dev/null @@ -1,796 +0,0 @@ -/* - * TLSv1 server - write handshake message - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "md5.h" -#include "sha1.h" -#include "x509v3.h" -#include "tls.h" -#include "tlsv1_common.h" -#include "tlsv1_record.h" -#include "tlsv1_server.h" -#include "tlsv1_server_i.h" - - -static size_t tls_server_cert_chain_der_len(struct tlsv1_server *conn) -{ - size_t len = 0; - struct x509_certificate *cert; - - cert = conn->cred->cert; - while (cert) { - len += 3 + cert->cert_len; - if (x509_certificate_self_signed(cert)) - break; - cert = x509_certificate_get_subject(conn->cred->trusted_certs, - &cert->issuer); - } - - return len; -} - - -static int tls_write_server_hello(struct tlsv1_server *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr, *hs_start, *hs_length; - struct os_time now; - size_t rlen; - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send ServerHello"); - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - - os_get_time(&now); - WPA_PUT_BE32(conn->server_random, now.sec); - if (os_get_random(conn->server_random + 4, TLS_RANDOM_LEN - 4)) { - wpa_printf(MSG_ERROR, "TLSv1: Could not generate " - "server_random"); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random", - conn->server_random, TLS_RANDOM_LEN); - - conn->session_id_len = TLS_SESSION_ID_MAX_LEN; - if (os_get_random(conn->session_id, conn->session_id_len)) { - wpa_printf(MSG_ERROR, "TLSv1: Could not generate " - "session_id"); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id", - conn->session_id, conn->session_id_len); - - /* opaque fragment[TLSPlaintext.length] */ - - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - /* body - ServerHello */ - /* ProtocolVersion server_version */ - WPA_PUT_BE16(pos, TLS_VERSION); - pos += 2; - /* Random random: uint32 gmt_unix_time, opaque random_bytes */ - os_memcpy(pos, conn->server_random, TLS_RANDOM_LEN); - pos += TLS_RANDOM_LEN; - /* SessionID session_id */ - *pos++ = conn->session_id_len; - os_memcpy(pos, conn->session_id, conn->session_id_len); - pos += conn->session_id_len; - /* CipherSuite cipher_suite */ - WPA_PUT_BE16(pos, conn->cipher_suite); - pos += 2; - /* CompressionMethod compression_method */ - *pos++ = TLS_COMPRESSION_NULL; - - if (conn->session_ticket && conn->session_ticket_cb) { - int res = conn->session_ticket_cb( - conn->session_ticket_cb_ctx, - conn->session_ticket, conn->session_ticket_len, - conn->client_random, conn->server_random, - conn->master_secret); - if (res < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback " - "indicated failure"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_HANDSHAKE_FAILURE); - return -1; - } - conn->use_session_ticket = res; - - if (conn->use_session_ticket) { - if (tlsv1_server_derive_keys(conn, NULL, 0) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to " - "derive keys"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - } - - /* - * RFC 4507 specifies that server would include an empty - * SessionTicket extension in ServerHello and a - * NewSessionTicket message after the ServerHello. However, - * EAP-FAST (RFC 4851), i.e., the only user of SessionTicket - * extension at the moment, does not use such extensions. - * - * TODO: Add support for configuring RFC 4507 behavior and make - * EAP-FAST disable it. - */ - } - - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - pos = rhdr + rlen; - - *msgpos = pos; - - return 0; -} - - -static int tls_write_server_certificate(struct tlsv1_server *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start; - size_t rlen; - struct x509_certificate *cert; - const struct tls_cipher_suite *suite; - - suite = tls_get_cipher_suite(conn->rl.cipher_suite); - if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) { - wpa_printf(MSG_DEBUG, "TLSv1: Do not send Certificate when " - "using anonymous DH"); - return 0; - } - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate"); - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - - /* opaque fragment[TLSPlaintext.length] */ - - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - /* body - Certificate */ - /* uint24 length (to be filled) */ - cert_start = pos; - pos += 3; - cert = conn->cred->cert; - while (cert) { - if (pos + 3 + cert->cert_len > end) { - wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space " - "for Certificate (cert_len=%lu left=%lu)", - (unsigned long) cert->cert_len, - (unsigned long) (end - pos)); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - WPA_PUT_BE24(pos, cert->cert_len); - pos += 3; - os_memcpy(pos, cert->cert_start, cert->cert_len); - pos += cert->cert_len; - - if (x509_certificate_self_signed(cert)) - break; - cert = x509_certificate_get_subject(conn->cred->trusted_certs, - &cert->issuer); - } - if (cert == conn->cred->cert || cert == NULL) { - /* - * Server was not configured with all the needed certificates - * to form a full certificate chain. The client may fail to - * validate the chain unless it is configured with all the - * missing CA certificates. - */ - wpa_printf(MSG_DEBUG, "TLSv1: Full server certificate chain " - "not configured - validation may fail"); - } - WPA_PUT_BE24(cert_start, pos - cert_start - 3); - - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - pos = rhdr + rlen; - - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - *msgpos = pos; - - return 0; -} - - -static int tls_write_server_key_exchange(struct tlsv1_server *conn, - u8 **msgpos, u8 *end) -{ - tls_key_exchange keyx; - const struct tls_cipher_suite *suite; -#ifdef EAP_FAST - u8 *pos, *rhdr, *hs_start, *hs_length; - size_t rlen; - u8 *dh_ys; - size_t dh_ys_len; -#endif /* EAP_FAST */ - - suite = tls_get_cipher_suite(conn->rl.cipher_suite); - if (suite == NULL) - keyx = TLS_KEY_X_NULL; - else - keyx = suite->key_exchange; - - if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) { - wpa_printf(MSG_DEBUG, "TLSv1: No ServerKeyExchange needed"); - return 0; - } - - if (keyx != TLS_KEY_X_DH_anon) { - /* TODO? */ - wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not yet " - "supported with key exchange type %d", keyx); - return -1; - } - -#ifdef EAP_FAST - if (conn->cred == NULL || conn->cred->dh_p == NULL || - conn->cred->dh_g == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available for " - "ServerKeyExhcange"); - return -1; - } - - os_free(conn->dh_secret); - conn->dh_secret_len = conn->cred->dh_p_len; - conn->dh_secret = os_malloc(conn->dh_secret_len); - if (conn->dh_secret == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " - "memory for secret (Diffie-Hellman)"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - if (os_get_random(conn->dh_secret, conn->dh_secret_len)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " - "data for Diffie-Hellman"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(conn->dh_secret); - conn->dh_secret = NULL; - return -1; - } - - if (os_memcmp(conn->dh_secret, conn->cred->dh_p, conn->dh_secret_len) > - 0) - conn->dh_secret[0] = 0; /* make sure secret < p */ - - pos = conn->dh_secret; - while (pos + 1 < conn->dh_secret + conn->dh_secret_len && *pos == 0) - pos++; - if (pos != conn->dh_secret) { - os_memmove(conn->dh_secret, pos, - conn->dh_secret_len - (pos - conn->dh_secret)); - conn->dh_secret_len -= pos - conn->dh_secret; - } - wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH server's secret value", - conn->dh_secret, conn->dh_secret_len); - - /* Ys = g^secret mod p */ - dh_ys_len = conn->cred->dh_p_len; - dh_ys = os_malloc(dh_ys_len); - if (dh_ys == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate memory for " - "Diffie-Hellman"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - if (crypto_mod_exp(conn->cred->dh_g, conn->cred->dh_g_len, - conn->dh_secret, conn->dh_secret_len, - conn->cred->dh_p, conn->cred->dh_p_len, - dh_ys, &dh_ys_len)) { - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(dh_ys); - return -1; - } - - wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)", - dh_ys, dh_ys_len); - - /* - * struct { - * select (KeyExchangeAlgorithm) { - * case diffie_hellman: - * ServerDHParams params; - * Signature signed_params; - * case rsa: - * ServerRSAParams params; - * Signature signed_params; - * }; - * } ServerKeyExchange; - * - * struct { - * opaque dh_p<1..2^16-1>; - * opaque dh_g<1..2^16-1>; - * opaque dh_Ys<1..2^16-1>; - * } ServerDHParams; - */ - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send ServerKeyExchange"); - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - - /* opaque fragment[TLSPlaintext.length] */ - - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - - /* body - ServerDHParams */ - /* dh_p */ - if (pos + 2 + conn->cred->dh_p_len > end) { - wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " - "dh_p"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(dh_ys); - return -1; - } - WPA_PUT_BE16(pos, conn->cred->dh_p_len); - pos += 2; - os_memcpy(pos, conn->cred->dh_p, conn->cred->dh_p_len); - pos += conn->cred->dh_p_len; - - /* dh_g */ - if (pos + 2 + conn->cred->dh_g_len > end) { - wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " - "dh_g"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(dh_ys); - return -1; - } - WPA_PUT_BE16(pos, conn->cred->dh_g_len); - pos += 2; - os_memcpy(pos, conn->cred->dh_g, conn->cred->dh_g_len); - pos += conn->cred->dh_g_len; - - /* dh_Ys */ - if (pos + 2 + dh_ys_len > end) { - wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " - "dh_Ys"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(dh_ys); - return -1; - } - WPA_PUT_BE16(pos, dh_ys_len); - pos += 2; - os_memcpy(pos, dh_ys, dh_ys_len); - pos += dh_ys_len; - os_free(dh_ys); - - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - pos = rhdr + rlen; - - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - *msgpos = pos; - - return 0; -#else /* EAP_FAST */ - return -1; -#endif /* EAP_FAST */ -} - - -static int tls_write_server_certificate_request(struct tlsv1_server *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr, *hs_start, *hs_length; - size_t rlen; - - if (!conn->verify_peer) { - wpa_printf(MSG_DEBUG, "TLSv1: No CertificateRequest needed"); - return 0; - } - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateRequest"); - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - - /* opaque fragment[TLSPlaintext.length] */ - - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - /* body - CertificateRequest */ - - /* - * enum { - * rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4), - * (255) - * } ClientCertificateType; - * ClientCertificateType certificate_types<1..2^8-1> - */ - *pos++ = 1; - *pos++ = 1; /* rsa_sign */ - - /* - * opaque DistinguishedName<1..2^16-1> - * DistinguishedName certificate_authorities<3..2^16-1> - */ - /* TODO: add support for listing DNs for trusted CAs */ - WPA_PUT_BE16(pos, 0); - pos += 2; - - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - pos = rhdr + rlen; - - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - *msgpos = pos; - - return 0; -} - - -static int tls_write_server_hello_done(struct tlsv1_server *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr, *hs_start, *hs_length; - size_t rlen; - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send ServerHelloDone"); - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - - /* opaque fragment[TLSPlaintext.length] */ - - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - /* body - ServerHelloDone (empty) */ - - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - pos = rhdr + rlen; - - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - *msgpos = pos; - - return 0; -} - - -static int tls_write_server_change_cipher_spec(struct tlsv1_server *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr; - size_t rlen; - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec"); - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - *pos = TLS_CHANGE_CIPHER_SPEC; - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC, - rhdr, end - rhdr, 1, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - if (tlsv1_record_change_write_cipher(&conn->rl) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for " - "record layer"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - *msgpos = rhdr + rlen; - - return 0; -} - - -static int tls_write_server_finished(struct tlsv1_server *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr, *hs_start, *hs_length; - size_t rlen, hlen; - u8 verify_data[TLS_VERIFY_DATA_LEN]; - u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send Finished"); - - /* Encrypted Handshake Message: Finished */ - - hlen = MD5_MAC_LEN; - if (conn->verify.md5_server == NULL || - crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) { - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - conn->verify.md5_server = NULL; - crypto_hash_finish(conn->verify.sha1_server, NULL, NULL); - conn->verify.sha1_server = NULL; - return -1; - } - conn->verify.md5_server = NULL; - hlen = SHA1_MAC_LEN; - if (conn->verify.sha1_server == NULL || - crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN, - &hlen) < 0) { - conn->verify.sha1_server = NULL; - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - conn->verify.sha1_server = NULL; - - if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, - "server finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, - verify_data, TLS_VERIFY_DATA_LEN)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)", - verify_data, TLS_VERIFY_DATA_LEN); - - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_FINISHED; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - os_memcpy(pos, verify_data, TLS_VERIFY_DATA_LEN); - pos += TLS_VERIFY_DATA_LEN; - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - pos = rhdr + rlen; - - *msgpos = pos; - - return 0; -} - - -static u8 * tls_send_server_hello(struct tlsv1_server *conn, size_t *out_len) -{ - u8 *msg, *end, *pos; - size_t msglen; - - *out_len = 0; - - msglen = 1000 + tls_server_cert_chain_der_len(conn); - - msg = os_malloc(msglen); - if (msg == NULL) - return NULL; - - pos = msg; - end = msg + msglen; - - if (tls_write_server_hello(conn, &pos, end) < 0) { - os_free(msg); - return NULL; - } - - if (conn->use_session_ticket) { - /* Abbreviated handshake using session ticket; RFC 4507 */ - if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 || - tls_write_server_finished(conn, &pos, end) < 0) { - os_free(msg); - return NULL; - } - - *out_len = pos - msg; - - conn->state = CHANGE_CIPHER_SPEC; - - return msg; - } - - /* Full handshake */ - if (tls_write_server_certificate(conn, &pos, end) < 0 || - tls_write_server_key_exchange(conn, &pos, end) < 0 || - tls_write_server_certificate_request(conn, &pos, end) < 0 || - tls_write_server_hello_done(conn, &pos, end) < 0) { - os_free(msg); - return NULL; - } - - *out_len = pos - msg; - - conn->state = CLIENT_CERTIFICATE; - - return msg; -} - - -static u8 * tls_send_change_cipher_spec(struct tlsv1_server *conn, - size_t *out_len) -{ - u8 *msg, *end, *pos; - - *out_len = 0; - - msg = os_malloc(1000); - if (msg == NULL) - return NULL; - - pos = msg; - end = msg + 1000; - - if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 || - tls_write_server_finished(conn, &pos, end) < 0) { - os_free(msg); - return NULL; - } - - *out_len = pos - msg; - - wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed successfully"); - conn->state = ESTABLISHED; - - return msg; -} - - -u8 * tlsv1_server_handshake_write(struct tlsv1_server *conn, size_t *out_len) -{ - switch (conn->state) { - case SERVER_HELLO: - return tls_send_server_hello(conn, out_len); - case SERVER_CHANGE_CIPHER_SPEC: - return tls_send_change_cipher_spec(conn, out_len); - default: - if (conn->state == ESTABLISHED && conn->use_session_ticket) { - /* Abbreviated handshake was already completed. */ - return NULL; - } - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while " - "generating reply", conn->state); - return NULL; - } -} - - -u8 * tlsv1_server_send_alert(struct tlsv1_server *conn, u8 level, - u8 description, size_t *out_len) -{ - u8 *alert, *pos, *length; - - wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description); - *out_len = 0; - - alert = os_malloc(10); - if (alert == NULL) - return NULL; - - pos = alert; - - /* TLSPlaintext */ - /* ContentType type */ - *pos++ = TLS_CONTENT_TYPE_ALERT; - /* ProtocolVersion version */ - WPA_PUT_BE16(pos, TLS_VERSION); - pos += 2; - /* uint16 length (to be filled) */ - length = pos; - pos += 2; - /* opaque fragment[TLSPlaintext.length] */ - - /* Alert */ - /* AlertLevel level */ - *pos++ = level; - /* AlertDescription description */ - *pos++ = description; - - WPA_PUT_BE16(length, pos - length - 2); - *out_len = pos - alert; - - return alert; -} diff --git a/contrib/hostapd/src/tls/x509v3.c b/contrib/hostapd/src/tls/x509v3.c deleted file mode 100644 index 59bf4ff052..0000000000 --- a/contrib/hostapd/src/tls/x509v3.c +++ /dev/null @@ -1,1724 +0,0 @@ -/* - * X.509v3 certificate parsing and processing (RFC 3280 profile) - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" - -#ifdef CONFIG_INTERNAL_X509 - -#include "asn1.h" -#include "crypto.h" -#include "x509v3.h" - - -static void x509_free_name(struct x509_name *name) -{ - os_free(name->cn); - os_free(name->c); - os_free(name->l); - os_free(name->st); - os_free(name->o); - os_free(name->ou); - os_free(name->email); - name->cn = name->c = name->l = name->st = name->o = name->ou = NULL; - name->email = NULL; -} - - -/** - * x509_certificate_free - Free an X.509 certificate - * @cert: Certificate to be freed - */ -void x509_certificate_free(struct x509_certificate *cert) -{ - if (cert == NULL) - return; - if (cert->next) { - wpa_printf(MSG_DEBUG, "X509: x509_certificate_free: cer=%p " - "was still on a list (next=%p)\n", - cert, cert->next); - } - x509_free_name(&cert->issuer); - x509_free_name(&cert->subject); - os_free(cert->public_key); - os_free(cert->sign_value); - os_free(cert); -} - - -/** - * x509_certificate_free - Free an X.509 certificate chain - * @cert: Pointer to the first certificate in the chain - */ -void x509_certificate_chain_free(struct x509_certificate *cert) -{ - struct x509_certificate *next; - - while (cert) { - next = cert->next; - cert->next = NULL; - x509_certificate_free(cert); - cert = next; - } -} - - -static int x509_whitespace(char c) -{ - return c == ' ' || c == '\t'; -} - - -static void x509_str_strip_whitespace(char *a) -{ - char *ipos, *opos; - int remove_whitespace = 1; - - ipos = opos = a; - - while (*ipos) { - if (remove_whitespace && x509_whitespace(*ipos)) - ipos++; - else { - remove_whitespace = x509_whitespace(*ipos); - *opos++ = *ipos++; - } - } - - *opos-- = '\0'; - if (opos > a && x509_whitespace(*opos)) - *opos = '\0'; -} - - -static int x509_str_compare(const char *a, const char *b) -{ - char *aa, *bb; - int ret; - - if (!a && b) - return -1; - if (a && !b) - return 1; - if (!a && !b) - return 0; - - aa = os_strdup(a); - bb = os_strdup(b); - - if (aa == NULL || bb == NULL) { - os_free(aa); - os_free(bb); - return os_strcasecmp(a, b); - } - - x509_str_strip_whitespace(aa); - x509_str_strip_whitespace(bb); - - ret = os_strcasecmp(aa, bb); - - os_free(aa); - os_free(bb); - - return ret; -} - - -/** - * x509_name_compare - Compare X.509 certificate names - * @a: Certificate name - * @b: Certificate name - * Returns: <0, 0, or >0 based on whether a is less than, equal to, or - * greater than b - */ -int x509_name_compare(struct x509_name *a, struct x509_name *b) -{ - int res; - - if (!a && b) - return -1; - if (a && !b) - return 1; - if (!a && !b) - return 0; - - res = x509_str_compare(a->cn, b->cn); - if (res) - return res; - res = x509_str_compare(a->c, b->c); - if (res) - return res; - res = x509_str_compare(a->l, b->l); - if (res) - return res; - res = x509_str_compare(a->st, b->st); - if (res) - return res; - res = x509_str_compare(a->o, b->o); - if (res) - return res; - res = x509_str_compare(a->ou, b->ou); - if (res) - return res; - res = x509_str_compare(a->email, b->email); - if (res) - return res; - - return 0; -} - - -static int x509_parse_algorithm_identifier( - const u8 *buf, size_t len, - struct x509_algorithm_identifier *id, const u8 **next) -{ - struct asn1_hdr hdr; - const u8 *pos, *end; - - /* - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL - * } - */ - - if (asn1_get_next(buf, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " - "(AlgorithmIdentifier) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - pos = hdr.payload; - end = pos + hdr.length; - - if (end > buf + len) - return -1; - - *next = end; - - if (asn1_get_oid(pos, end - pos, &id->oid, &pos)) - return -1; - - /* TODO: optional parameters */ - - return 0; -} - - -static int x509_parse_public_key(const u8 *buf, size_t len, - struct x509_certificate *cert, - const u8 **next) -{ - struct asn1_hdr hdr; - const u8 *pos, *end; - - /* - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING - * } - */ - - pos = buf; - end = buf + len; - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " - "(SubjectPublicKeyInfo) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - pos = hdr.payload; - - if (pos + hdr.length > end) - return -1; - end = pos + hdr.length; - *next = end; - - if (x509_parse_algorithm_identifier(pos, end - pos, - &cert->public_key_alg, &pos)) - return -1; - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_BITSTRING) { - wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING " - "(subjectPublicKey) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - if (hdr.length < 1) - return -1; - pos = hdr.payload; - if (*pos) { - wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", - *pos); - /* - * TODO: should this be rejected? X.509 certificates are - * unlikely to use such a construction. Now we would end up - * including the extra bits in the buffer which may also be - * ok. - */ - } - os_free(cert->public_key); - cert->public_key = os_malloc(hdr.length - 1); - if (cert->public_key == NULL) { - wpa_printf(MSG_DEBUG, "X509: Failed to allocate memory for " - "public key"); - return -1; - } - os_memcpy(cert->public_key, pos + 1, hdr.length - 1); - cert->public_key_len = hdr.length - 1; - wpa_hexdump(MSG_MSGDUMP, "X509: subjectPublicKey", - cert->public_key, cert->public_key_len); - - return 0; -} - - -static int x509_parse_name(const u8 *buf, size_t len, struct x509_name *name, - const u8 **next) -{ - struct asn1_hdr hdr; - const u8 *pos, *end, *set_pos, *set_end, *seq_pos, *seq_end; - struct asn1_oid oid; - char **fieldp; - - /* - * Name ::= CHOICE { RDNSequence } - * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName - * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue - * AttributeTypeAndValue ::= SEQUENCE { - * type AttributeType, - * value AttributeValue - * } - * AttributeType ::= OBJECT IDENTIFIER - * AttributeValue ::= ANY DEFINED BY AttributeType - */ - - if (asn1_get_next(buf, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " - "(Name / RDNSequencer) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - pos = hdr.payload; - - if (pos + hdr.length > buf + len) - return -1; - - end = *next = pos + hdr.length; - - while (pos < end) { - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SET) { - wpa_printf(MSG_DEBUG, "X509: Expected SET " - "(RelativeDistinguishedName) - found class " - "%d tag 0x%x", hdr.class, hdr.tag); - x509_free_name(name); - return -1; - } - - set_pos = hdr.payload; - pos = set_end = hdr.payload + hdr.length; - - if (asn1_get_next(set_pos, set_end - set_pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " - "(AttributeTypeAndValue) - found class %d " - "tag 0x%x", hdr.class, hdr.tag); - x509_free_name(name); - return -1; - } - - seq_pos = hdr.payload; - seq_end = hdr.payload + hdr.length; - - if (asn1_get_oid(seq_pos, seq_end - seq_pos, &oid, &seq_pos)) { - x509_free_name(name); - return -1; - } - - if (asn1_get_next(seq_pos, seq_end - seq_pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL) { - wpa_printf(MSG_DEBUG, "X509: Failed to parse " - "AttributeValue"); - x509_free_name(name); - return -1; - } - - /* RFC 3280: - * MUST: country, organization, organizational-unit, - * distinguished name qualifier, state or province name, - * common name, serial number. - * SHOULD: locality, title, surname, given name, initials, - * pseudonym, generation qualifier. - * MUST: domainComponent (RFC 2247). - */ - fieldp = NULL; - if (oid.len == 4 && - oid.oid[0] == 2 && oid.oid[1] == 5 && oid.oid[2] == 4) { - /* id-at ::= 2.5.4 */ - switch (oid.oid[3]) { - case 3: - /* commonName */ - fieldp = &name->cn; - break; - case 6: - /* countryName */ - fieldp = &name->c; - break; - case 7: - /* localityName */ - fieldp = &name->l; - break; - case 8: - /* stateOrProvinceName */ - fieldp = &name->st; - break; - case 10: - /* organizationName */ - fieldp = &name->o; - break; - case 11: - /* organizationalUnitName */ - fieldp = &name->ou; - break; - } - } else if (oid.len == 7 && - oid.oid[0] == 1 && oid.oid[1] == 2 && - oid.oid[2] == 840 && oid.oid[3] == 113549 && - oid.oid[4] == 1 && oid.oid[5] == 9 && - oid.oid[6] == 1) { - /* 1.2.840.113549.1.9.1 - e-mailAddress */ - fieldp = &name->email; - } - - if (fieldp == NULL) { - wpa_hexdump(MSG_DEBUG, "X509: Unrecognized OID", - (u8 *) oid.oid, - oid.len * sizeof(oid.oid[0])); - wpa_hexdump_ascii(MSG_MSGDUMP, "X509: Attribute Data", - hdr.payload, hdr.length); - continue; - } - - os_free(*fieldp); - *fieldp = os_malloc(hdr.length + 1); - if (*fieldp == NULL) { - x509_free_name(name); - return -1; - } - os_memcpy(*fieldp, hdr.payload, hdr.length); - (*fieldp)[hdr.length] = '\0'; - } - - return 0; -} - - -/** - * x509_name_string - Convert an X.509 certificate name into a string - * @name: Name to convert - * @buf: Buffer for the string - * @len: Maximum buffer length - */ -void x509_name_string(struct x509_name *name, char *buf, size_t len) -{ - char *pos, *end; - int ret; - - if (len == 0) - return; - - pos = buf; - end = buf + len; - - if (name->c) { - ret = os_snprintf(pos, end - pos, "C=%s, ", name->c); - if (ret < 0 || ret >= end - pos) - goto done; - pos += ret; - } - if (name->st) { - ret = os_snprintf(pos, end - pos, "ST=%s, ", name->st); - if (ret < 0 || ret >= end - pos) - goto done; - pos += ret; - } - if (name->l) { - ret = os_snprintf(pos, end - pos, "L=%s, ", name->l); - if (ret < 0 || ret >= end - pos) - goto done; - pos += ret; - } - if (name->o) { - ret = os_snprintf(pos, end - pos, "O=%s, ", name->o); - if (ret < 0 || ret >= end - pos) - goto done; - pos += ret; - } - if (name->ou) { - ret = os_snprintf(pos, end - pos, "OU=%s, ", name->ou); - if (ret < 0 || ret >= end - pos) - goto done; - pos += ret; - } - if (name->cn) { - ret = os_snprintf(pos, end - pos, "CN=%s, ", name->cn); - if (ret < 0 || ret >= end - pos) - goto done; - pos += ret; - } - - if (pos > buf + 1 && pos[-1] == ' ' && pos[-2] == ',') { - *pos-- = '\0'; - *pos-- = '\0'; - } - - if (name->email) { - ret = os_snprintf(pos, end - pos, "/emailAddress=%s", - name->email); - if (ret < 0 || ret >= end - pos) - goto done; - pos += ret; - } - -done: - end[-1] = '\0'; -} - - -static int x509_parse_time(const u8 *buf, size_t len, u8 asn1_tag, - os_time_t *val) -{ - const char *pos; - int year, month, day, hour, min, sec; - - /* - * Time ::= CHOICE { - * utcTime UTCTime, - * generalTime GeneralizedTime - * } - * - * UTCTime: YYMMDDHHMMSSZ - * GeneralizedTime: YYYYMMDDHHMMSSZ - */ - - pos = (const char *) buf; - - switch (asn1_tag) { - case ASN1_TAG_UTCTIME: - if (len != 13 || buf[12] != 'Z') { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized " - "UTCTime format", buf, len); - return -1; - } - if (sscanf(pos, "%02d", &year) != 1) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse " - "UTCTime year", buf, len); - return -1; - } - if (year < 50) - year += 2000; - else - year += 1900; - pos += 2; - break; - case ASN1_TAG_GENERALIZEDTIME: - if (len != 15 || buf[14] != 'Z') { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized " - "GeneralizedTime format", buf, len); - return -1; - } - if (sscanf(pos, "%04d", &year) != 1) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse " - "GeneralizedTime year", buf, len); - return -1; - } - pos += 4; - break; - default: - wpa_printf(MSG_DEBUG, "X509: Expected UTCTime or " - "GeneralizedTime - found tag 0x%x", asn1_tag); - return -1; - } - - if (sscanf(pos, "%02d", &month) != 1) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " - "(month)", buf, len); - return -1; - } - pos += 2; - - if (sscanf(pos, "%02d", &day) != 1) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " - "(day)", buf, len); - return -1; - } - pos += 2; - - if (sscanf(pos, "%02d", &hour) != 1) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " - "(hour)", buf, len); - return -1; - } - pos += 2; - - if (sscanf(pos, "%02d", &min) != 1) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " - "(min)", buf, len); - return -1; - } - pos += 2; - - if (sscanf(pos, "%02d", &sec) != 1) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " - "(sec)", buf, len); - return -1; - } - - if (os_mktime(year, month, day, hour, min, sec, val) < 0) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to convert Time", - buf, len); - if (year < 1970) { - /* - * At least some test certificates have been configured - * to use dates prior to 1970. Set the date to - * beginning of 1970 to handle these case. - */ - wpa_printf(MSG_DEBUG, "X509: Year=%d before epoch - " - "assume epoch as the time", year); - *val = 0; - return 0; - } - return -1; - } - - return 0; -} - - -static int x509_parse_validity(const u8 *buf, size_t len, - struct x509_certificate *cert, const u8 **next) -{ - struct asn1_hdr hdr; - const u8 *pos; - size_t plen; - - /* - * Validity ::= SEQUENCE { - * notBefore Time, - * notAfter Time - * } - * - * RFC 3280, 4.1.2.5: - * CAs conforming to this profile MUST always encode certificate - * validity dates through the year 2049 as UTCTime; certificate - * validity dates in 2050 or later MUST be encoded as GeneralizedTime. - */ - - if (asn1_get_next(buf, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " - "(Validity) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - pos = hdr.payload; - plen = hdr.length; - - if (pos + plen > buf + len) - return -1; - - *next = pos + plen; - - if (asn1_get_next(pos, plen, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - x509_parse_time(hdr.payload, hdr.length, hdr.tag, - &cert->not_before) < 0) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notBefore " - "Time", hdr.payload, hdr.length); - return -1; - } - - pos = hdr.payload + hdr.length; - plen = *next - pos; - - if (asn1_get_next(pos, plen, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - x509_parse_time(hdr.payload, hdr.length, hdr.tag, - &cert->not_after) < 0) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notAfter " - "Time", hdr.payload, hdr.length); - return -1; - } - - wpa_printf(MSG_MSGDUMP, "X509: Validity: notBefore: %lu notAfter: %lu", - (unsigned long) cert->not_before, - (unsigned long) cert->not_after); - - return 0; -} - - -static int x509_id_ce_oid(struct asn1_oid *oid) -{ - /* id-ce arc from X.509 for standard X.509v3 extensions */ - return oid->len >= 4 && - oid->oid[0] == 2 /* joint-iso-ccitt */ && - oid->oid[1] == 5 /* ds */ && - oid->oid[2] == 29 /* id-ce */; -} - - -static int x509_parse_ext_key_usage(struct x509_certificate *cert, - const u8 *pos, size_t len) -{ - struct asn1_hdr hdr; - - /* - * KeyUsage ::= BIT STRING { - * digitalSignature (0), - * nonRepudiation (1), - * keyEncipherment (2), - * dataEncipherment (3), - * keyAgreement (4), - * keyCertSign (5), - * cRLSign (6), - * encipherOnly (7), - * decipherOnly (8) } - */ - - if (asn1_get_next(pos, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_BITSTRING || - hdr.length < 1) { - wpa_printf(MSG_DEBUG, "X509: Expected BIT STRING in " - "KeyUsage; found %d tag 0x%x len %d", - hdr.class, hdr.tag, hdr.length); - return -1; - } - - cert->extensions_present |= X509_EXT_KEY_USAGE; - cert->key_usage = asn1_bit_string_to_long(hdr.payload, hdr.length); - - wpa_printf(MSG_DEBUG, "X509: KeyUsage 0x%lx", cert->key_usage); - - return 0; -} - - -static int x509_parse_ext_basic_constraints(struct x509_certificate *cert, - const u8 *pos, size_t len) -{ - struct asn1_hdr hdr; - unsigned long value; - size_t left; - - /* - * BasicConstraints ::= SEQUENCE { - * cA BOOLEAN DEFAULT FALSE, - * pathLenConstraint INTEGER (0..MAX) OPTIONAL } - */ - - if (asn1_get_next(pos, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " - "BasicConstraints; found %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - - cert->extensions_present |= X509_EXT_BASIC_CONSTRAINTS; - - if (hdr.length == 0) - return 0; - - if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL) { - wpa_printf(MSG_DEBUG, "X509: Failed to parse " - "BasicConstraints"); - return -1; - } - - if (hdr.tag == ASN1_TAG_BOOLEAN) { - if (hdr.length != 1) { - wpa_printf(MSG_DEBUG, "X509: Unexpected " - "Boolean length (%u) in BasicConstraints", - hdr.length); - return -1; - } - cert->ca = hdr.payload[0]; - - if (hdr.payload + hdr.length == pos + len) { - wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d", - cert->ca); - return 0; - } - - if (asn1_get_next(hdr.payload + hdr.length, len - hdr.length, - &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL) { - wpa_printf(MSG_DEBUG, "X509: Failed to parse " - "BasicConstraints"); - return -1; - } - } - - if (hdr.tag != ASN1_TAG_INTEGER) { - wpa_printf(MSG_DEBUG, "X509: Expected INTEGER in " - "BasicConstraints; found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - - pos = hdr.payload; - left = hdr.length; - value = 0; - while (left) { - value <<= 8; - value |= *pos++; - left--; - } - - cert->path_len_constraint = value; - cert->extensions_present |= X509_EXT_PATH_LEN_CONSTRAINT; - - wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d " - "pathLenConstraint=%lu", - cert->ca, cert->path_len_constraint); - - return 0; -} - - -static int x509_parse_extension_data(struct x509_certificate *cert, - struct asn1_oid *oid, - const u8 *pos, size_t len) -{ - if (!x509_id_ce_oid(oid)) - return 1; - - /* TODO: add other extensions required by RFC 3280, Ch 4.2: - * certificate policies (section 4.2.1.5) - * the subject alternative name (section 4.2.1.7) - * name constraints (section 4.2.1.11) - * policy constraints (section 4.2.1.12) - * extended key usage (section 4.2.1.13) - * inhibit any-policy (section 4.2.1.15) - */ - switch (oid->oid[3]) { - case 15: /* id-ce-keyUsage */ - return x509_parse_ext_key_usage(cert, pos, len); - case 19: /* id-ce-basicConstraints */ - return x509_parse_ext_basic_constraints(cert, pos, len); - default: - return 1; - } -} - - -static int x509_parse_extension(struct x509_certificate *cert, - const u8 *pos, size_t len, const u8 **next) -{ - const u8 *end; - struct asn1_hdr hdr; - struct asn1_oid oid; - int critical_ext = 0, res; - char buf[80]; - - /* - * Extension ::= SEQUENCE { - * extnID OBJECT IDENTIFIER, - * critical BOOLEAN DEFAULT FALSE, - * extnValue OCTET STRING - * } - */ - - if (asn1_get_next(pos, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in " - "Extensions: class %d tag 0x%x; expected SEQUENCE", - hdr.class, hdr.tag); - return -1; - } - pos = hdr.payload; - *next = end = pos + hdr.length; - - if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) { - wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 data for " - "Extension (expected OID)"); - return -1; - } - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - (hdr.tag != ASN1_TAG_BOOLEAN && - hdr.tag != ASN1_TAG_OCTETSTRING)) { - wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in " - "Extensions: class %d tag 0x%x; expected BOOLEAN " - "or OCTET STRING", hdr.class, hdr.tag); - return -1; - } - - if (hdr.tag == ASN1_TAG_BOOLEAN) { - if (hdr.length != 1) { - wpa_printf(MSG_DEBUG, "X509: Unexpected " - "Boolean length (%u)", hdr.length); - return -1; - } - critical_ext = hdr.payload[0]; - pos = hdr.payload; - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - (hdr.class != ASN1_CLASS_UNIVERSAL && - hdr.class != ASN1_CLASS_PRIVATE) || - hdr.tag != ASN1_TAG_OCTETSTRING) { - wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header " - "in Extensions: class %d tag 0x%x; " - "expected OCTET STRING", - hdr.class, hdr.tag); - return -1; - } - } - - asn1_oid_to_str(&oid, buf, sizeof(buf)); - wpa_printf(MSG_DEBUG, "X509: Extension: extnID=%s critical=%d", - buf, critical_ext); - wpa_hexdump(MSG_MSGDUMP, "X509: extnValue", hdr.payload, hdr.length); - - res = x509_parse_extension_data(cert, &oid, hdr.payload, hdr.length); - if (res < 0) - return res; - if (res == 1 && critical_ext) { - wpa_printf(MSG_INFO, "X509: Unknown critical extension %s", - buf); - return -1; - } - - return 0; -} - - -static int x509_parse_extensions(struct x509_certificate *cert, - const u8 *pos, size_t len) -{ - const u8 *end; - struct asn1_hdr hdr; - - /* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension */ - - if (asn1_get_next(pos, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 data " - "for Extensions: class %d tag 0x%x; " - "expected SEQUENCE", hdr.class, hdr.tag); - return -1; - } - - pos = hdr.payload; - end = pos + hdr.length; - - while (pos < end) { - if (x509_parse_extension(cert, pos, end - pos, &pos) - < 0) - return -1; - } - - return 0; -} - - -static int x509_parse_tbs_certificate(const u8 *buf, size_t len, - struct x509_certificate *cert, - const u8 **next) -{ - struct asn1_hdr hdr; - const u8 *pos, *end; - size_t left; - char sbuf[128]; - unsigned long value; - - /* tbsCertificate TBSCertificate ::= SEQUENCE */ - if (asn1_get_next(buf, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: tbsCertificate did not start " - "with a valid SEQUENCE - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - pos = hdr.payload; - end = *next = pos + hdr.length; - - /* - * version [0] EXPLICIT Version DEFAULT v1 - * Version ::= INTEGER { v1(0), v2(1), v3(2) } - */ - if (asn1_get_next(pos, end - pos, &hdr) < 0) - return -1; - pos = hdr.payload; - - if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC) { - if (asn1_get_next(pos, end - pos, &hdr) < 0) - return -1; - - if (hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_INTEGER) { - wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for " - "version field - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - if (hdr.length != 1) { - wpa_printf(MSG_DEBUG, "X509: Unexpected version field " - "length %u (expected 1)", hdr.length); - return -1; - } - pos = hdr.payload; - left = hdr.length; - value = 0; - while (left) { - value <<= 8; - value |= *pos++; - left--; - } - - cert->version = value; - if (cert->version != X509_CERT_V1 && - cert->version != X509_CERT_V2 && - cert->version != X509_CERT_V3) { - wpa_printf(MSG_DEBUG, "X509: Unsupported version %d", - cert->version + 1); - return -1; - } - - if (asn1_get_next(pos, end - pos, &hdr) < 0) - return -1; - } else - cert->version = X509_CERT_V1; - wpa_printf(MSG_MSGDUMP, "X509: Version X.509v%d", cert->version + 1); - - /* serialNumber CertificateSerialNumber ::= INTEGER */ - if (hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_INTEGER) { - wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for " - "serialNumber; class=%d tag=0x%x", - hdr.class, hdr.tag); - return -1; - } - - pos = hdr.payload; - left = hdr.length; - while (left) { - cert->serial_number <<= 8; - cert->serial_number |= *pos++; - left--; - } - wpa_printf(MSG_MSGDUMP, "X509: serialNumber %lu", cert->serial_number); - - /* signature AlgorithmIdentifier */ - if (x509_parse_algorithm_identifier(pos, end - pos, &cert->signature, - &pos)) - return -1; - - /* issuer Name */ - if (x509_parse_name(pos, end - pos, &cert->issuer, &pos)) - return -1; - x509_name_string(&cert->issuer, sbuf, sizeof(sbuf)); - wpa_printf(MSG_MSGDUMP, "X509: issuer %s", sbuf); - - /* validity Validity */ - if (x509_parse_validity(pos, end - pos, cert, &pos)) - return -1; - - /* subject Name */ - if (x509_parse_name(pos, end - pos, &cert->subject, &pos)) - return -1; - x509_name_string(&cert->subject, sbuf, sizeof(sbuf)); - wpa_printf(MSG_MSGDUMP, "X509: subject %s", sbuf); - - /* subjectPublicKeyInfo SubjectPublicKeyInfo */ - if (x509_parse_public_key(pos, end - pos, cert, &pos)) - return -1; - - if (pos == end) - return 0; - - if (cert->version == X509_CERT_V1) - return 0; - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { - wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" - " tag to parse optional tbsCertificate " - "field(s); parsed class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - - if (hdr.tag == 1) { - /* issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL */ - wpa_printf(MSG_DEBUG, "X509: issuerUniqueID"); - /* TODO: parse UniqueIdentifier ::= BIT STRING */ - - if (hdr.payload + hdr.length == end) - return 0; - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { - wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" - " tag to parse optional tbsCertificate " - "field(s); parsed class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - } - - if (hdr.tag == 2) { - /* subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL */ - wpa_printf(MSG_DEBUG, "X509: subjectUniqueID"); - /* TODO: parse UniqueIdentifier ::= BIT STRING */ - - if (hdr.payload + hdr.length == end) - return 0; - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { - wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" - " tag to parse optional tbsCertificate " - "field(s); parsed class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - } - - if (hdr.tag != 3) { - wpa_printf(MSG_DEBUG, "X509: Ignored unexpected " - "Context-Specific tag %d in optional " - "tbsCertificate fields", hdr.tag); - return 0; - } - - /* extensions [3] EXPLICIT Extensions OPTIONAL */ - - if (cert->version != X509_CERT_V3) { - wpa_printf(MSG_DEBUG, "X509: X.509%d certificate and " - "Extensions data which are only allowed for " - "version 3", cert->version + 1); - return -1; - } - - if (x509_parse_extensions(cert, hdr.payload, hdr.length) < 0) - return -1; - - pos = hdr.payload + hdr.length; - if (pos < end) { - wpa_hexdump(MSG_DEBUG, - "X509: Ignored extra tbsCertificate data", - pos, end - pos); - } - - return 0; -} - - -static int x509_rsadsi_oid(struct asn1_oid *oid) -{ - return oid->len >= 4 && - oid->oid[0] == 1 /* iso */ && - oid->oid[1] == 2 /* member-body */ && - oid->oid[2] == 840 /* us */ && - oid->oid[3] == 113549 /* rsadsi */; -} - - -static int x509_pkcs_oid(struct asn1_oid *oid) -{ - return oid->len >= 5 && - x509_rsadsi_oid(oid) && - oid->oid[4] == 1 /* pkcs */; -} - - -static int x509_digest_oid(struct asn1_oid *oid) -{ - return oid->len >= 5 && - x509_rsadsi_oid(oid) && - oid->oid[4] == 2 /* digestAlgorithm */; -} - - -static int x509_sha1_oid(struct asn1_oid *oid) -{ - return oid->len == 6 && - oid->oid[0] == 1 /* iso */ && - oid->oid[1] == 3 /* identified-organization */ && - oid->oid[2] == 14 /* oiw */ && - oid->oid[3] == 3 /* secsig */ && - oid->oid[4] == 2 /* algorithms */ && - oid->oid[5] == 26 /* id-sha1 */; -} - - -static int x509_sha256_oid(struct asn1_oid *oid) -{ - return oid->len == 9 && - oid->oid[0] == 2 /* joint-iso-itu-t */ && - oid->oid[1] == 16 /* country */ && - oid->oid[2] == 840 /* us */ && - oid->oid[3] == 1 /* organization */ && - oid->oid[4] == 101 /* gov */ && - oid->oid[5] == 3 /* csor */ && - oid->oid[6] == 4 /* nistAlgorithm */ && - oid->oid[7] == 2 /* hashAlgs */ && - oid->oid[8] == 1 /* sha256 */; -} - - -/** - * x509_certificate_parse - Parse a X.509 certificate in DER format - * @buf: Pointer to the X.509 certificate in DER format - * @len: Buffer length - * Returns: Pointer to the parsed certificate or %NULL on failure - * - * Caller is responsible for freeing the returned certificate by calling - * x509_certificate_free(). - */ -struct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len) -{ - struct asn1_hdr hdr; - const u8 *pos, *end, *hash_start; - struct x509_certificate *cert; - - cert = os_zalloc(sizeof(*cert) + len); - if (cert == NULL) - return NULL; - os_memcpy(cert + 1, buf, len); - cert->cert_start = (u8 *) (cert + 1); - cert->cert_len = len; - - pos = buf; - end = buf + len; - - /* RFC 3280 - X.509 v3 certificate / ASN.1 DER */ - - /* Certificate ::= SEQUENCE */ - if (asn1_get_next(pos, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Certificate did not start with " - "a valid SEQUENCE - found class %d tag 0x%x", - hdr.class, hdr.tag); - x509_certificate_free(cert); - return NULL; - } - pos = hdr.payload; - - if (pos + hdr.length > end) { - x509_certificate_free(cert); - return NULL; - } - - if (pos + hdr.length < end) { - wpa_hexdump(MSG_MSGDUMP, "X509: Ignoring extra data after DER " - "encoded certificate", - pos + hdr.length, end - pos + hdr.length); - end = pos + hdr.length; - } - - hash_start = pos; - cert->tbs_cert_start = cert->cert_start + (hash_start - buf); - if (x509_parse_tbs_certificate(pos, end - pos, cert, &pos)) { - x509_certificate_free(cert); - return NULL; - } - cert->tbs_cert_len = pos - hash_start; - - /* signatureAlgorithm AlgorithmIdentifier */ - if (x509_parse_algorithm_identifier(pos, end - pos, - &cert->signature_alg, &pos)) { - x509_certificate_free(cert); - return NULL; - } - - /* signatureValue BIT STRING */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_BITSTRING) { - wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING " - "(signatureValue) - found class %d tag 0x%x", - hdr.class, hdr.tag); - x509_certificate_free(cert); - return NULL; - } - if (hdr.length < 1) { - x509_certificate_free(cert); - return NULL; - } - pos = hdr.payload; - if (*pos) { - wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", - *pos); - /* PKCS #1 v1.5 10.2.1: - * It is an error if the length in bits of the signature S is - * not a multiple of eight. - */ - x509_certificate_free(cert); - return NULL; - } - os_free(cert->sign_value); - cert->sign_value = os_malloc(hdr.length - 1); - if (cert->sign_value == NULL) { - wpa_printf(MSG_DEBUG, "X509: Failed to allocate memory for " - "signatureValue"); - x509_certificate_free(cert); - return NULL; - } - os_memcpy(cert->sign_value, pos + 1, hdr.length - 1); - cert->sign_value_len = hdr.length - 1; - wpa_hexdump(MSG_MSGDUMP, "X509: signature", - cert->sign_value, cert->sign_value_len); - - return cert; -} - - -/** - * x509_certificate_check_signature - Verify certificate signature - * @issuer: Issuer certificate - * @cert: Certificate to be verified - * Returns: 0 if cert has a valid signature that was signed by the issuer, - * -1 if not - */ -int x509_certificate_check_signature(struct x509_certificate *issuer, - struct x509_certificate *cert) -{ - struct crypto_public_key *pk; - u8 *data; - const u8 *pos, *end, *next, *da_end; - size_t data_len; - struct asn1_hdr hdr; - struct asn1_oid oid; - u8 hash[32]; - size_t hash_len; - - if (!x509_pkcs_oid(&cert->signature.oid) || - cert->signature.oid.len != 7 || - cert->signature.oid.oid[5] != 1 /* pkcs-1 */) { - wpa_printf(MSG_DEBUG, "X509: Unrecognized signature " - "algorithm"); - return -1; - } - - pk = crypto_public_key_import(issuer->public_key, - issuer->public_key_len); - if (pk == NULL) - return -1; - - data_len = cert->sign_value_len; - data = os_malloc(data_len); - if (data == NULL) { - crypto_public_key_free(pk); - return -1; - } - - if (crypto_public_key_decrypt_pkcs1(pk, cert->sign_value, - cert->sign_value_len, data, - &data_len) < 0) { - wpa_printf(MSG_DEBUG, "X509: Failed to decrypt signature"); - crypto_public_key_free(pk); - os_free(data); - return -1; - } - crypto_public_key_free(pk); - - wpa_hexdump(MSG_MSGDUMP, "X509: Signature data D", data, data_len); - - /* - * PKCS #1 v1.5, 10.1.2: - * - * DigestInfo ::= SEQUENCE { - * digestAlgorithm DigestAlgorithmIdentifier, - * digest Digest - * } - * - * DigestAlgorithmIdentifier ::= AlgorithmIdentifier - * - * Digest ::= OCTET STRING - * - */ - if (asn1_get_next(data, data_len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " - "(DigestInfo) - found class %d tag 0x%x", - hdr.class, hdr.tag); - os_free(data); - return -1; - } - - pos = hdr.payload; - end = pos + hdr.length; - - /* - * X.509: - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL - * } - */ - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " - "(AlgorithmIdentifier) - found class %d tag 0x%x", - hdr.class, hdr.tag); - os_free(data); - return -1; - } - da_end = hdr.payload + hdr.length; - - if (asn1_get_oid(hdr.payload, hdr.length, &oid, &next)) { - wpa_printf(MSG_DEBUG, "X509: Failed to parse digestAlgorithm"); - os_free(data); - return -1; - } - - if (x509_sha1_oid(&oid)) { - if (cert->signature.oid.oid[6] != - 5 /* sha-1WithRSAEncryption */) { - wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA1 " - "does not match with certificate " - "signatureAlgorithm (%lu)", - cert->signature.oid.oid[6]); - os_free(data); - return -1; - } - goto skip_digest_oid; - } - - if (x509_sha256_oid(&oid)) { - if (cert->signature.oid.oid[6] != - 11 /* sha2561WithRSAEncryption */) { - wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA256 " - "does not match with certificate " - "signatureAlgorithm (%lu)", - cert->signature.oid.oid[6]); - os_free(data); - return -1; - } - goto skip_digest_oid; - } - - if (!x509_digest_oid(&oid)) { - wpa_printf(MSG_DEBUG, "X509: Unrecognized digestAlgorithm"); - os_free(data); - return -1; - } - switch (oid.oid[5]) { - case 5: /* md5 */ - if (cert->signature.oid.oid[6] != 4 /* md5WithRSAEncryption */) - { - wpa_printf(MSG_DEBUG, "X509: digestAlgorithm MD5 does " - "not match with certificate " - "signatureAlgorithm (%lu)", - cert->signature.oid.oid[6]); - os_free(data); - return -1; - } - break; - case 2: /* md2 */ - case 4: /* md4 */ - default: - wpa_printf(MSG_DEBUG, "X509: Unsupported digestAlgorithm " - "(%lu)", oid.oid[5]); - os_free(data); - return -1; - } - -skip_digest_oid: - /* Digest ::= OCTET STRING */ - pos = da_end; - end = data + data_len; - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_OCTETSTRING) { - wpa_printf(MSG_DEBUG, "X509: Expected OCTETSTRING " - "(Digest) - found class %d tag 0x%x", - hdr.class, hdr.tag); - os_free(data); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "X509: Decrypted Digest", - hdr.payload, hdr.length); - - switch (cert->signature.oid.oid[6]) { - case 4: /* md5WithRSAEncryption */ - md5_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, - hash); - hash_len = 16; - wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (MD5)", - hash, hash_len); - break; - case 5: /* sha-1WithRSAEncryption */ - sha1_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, - hash); - hash_len = 20; - wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA1)", - hash, hash_len); - break; - case 11: /* sha256WithRSAEncryption */ -#ifdef NEED_SHA256 - sha256_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, - hash); - hash_len = 32; - wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA256)", - hash, hash_len); - break; -#else /* NEED_SHA256 */ - wpa_printf(MSG_INFO, "X509: SHA256 support disabled"); - os_free(data); - return -1; -#endif /* NEED_SHA256 */ - case 2: /* md2WithRSAEncryption */ - case 12: /* sha384WithRSAEncryption */ - case 13: /* sha512WithRSAEncryption */ - default: - wpa_printf(MSG_INFO, "X509: Unsupported certificate signature " - "algorithm (%lu)", cert->signature.oid.oid[6]); - os_free(data); - return -1; - } - - if (hdr.length != hash_len || - os_memcmp(hdr.payload, hash, hdr.length) != 0) { - wpa_printf(MSG_INFO, "X509: Certificate Digest does not match " - "with calculated tbsCertificate hash"); - os_free(data); - return -1; - } - - os_free(data); - - wpa_printf(MSG_DEBUG, "X509: Certificate Digest matches with " - "calculated tbsCertificate hash"); - - return 0; -} - - -static int x509_valid_issuer(const struct x509_certificate *cert) -{ - if ((cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS) && - !cert->ca) { - wpa_printf(MSG_DEBUG, "X509: Non-CA certificate used as an " - "issuer"); - return -1; - } - - if (cert->version == X509_CERT_V3 && - !(cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS)) { - wpa_printf(MSG_DEBUG, "X509: v3 CA certificate did not " - "include BasicConstraints extension"); - return -1; - } - - if ((cert->extensions_present & X509_EXT_KEY_USAGE) && - !(cert->key_usage & X509_KEY_USAGE_KEY_CERT_SIGN)) { - wpa_printf(MSG_DEBUG, "X509: Issuer certificate did not have " - "keyCertSign bit in Key Usage"); - return -1; - } - - return 0; -} - - -/** - * x509_certificate_chain_validate - Validate X.509 certificate chain - * @trusted: List of trusted certificates - * @chain: Certificate chain to be validated (first chain must be issued by - * signed by the second certificate in the chain and so on) - * @reason: Buffer for returning failure reason (X509_VALIDATE_*) - * Returns: 0 if chain is valid, -1 if not - */ -int x509_certificate_chain_validate(struct x509_certificate *trusted, - struct x509_certificate *chain, - int *reason) -{ - long unsigned idx; - int chain_trusted = 0; - struct x509_certificate *cert, *trust; - char buf[128]; - struct os_time now; - - *reason = X509_VALIDATE_OK; - - wpa_printf(MSG_DEBUG, "X509: Validate certificate chain"); - os_get_time(&now); - - for (cert = chain, idx = 0; cert; cert = cert->next, idx++) { - x509_name_string(&cert->subject, buf, sizeof(buf)); - wpa_printf(MSG_DEBUG, "X509: %lu: %s", idx, buf); - - if (chain_trusted) - continue; - - if ((unsigned long) now.sec < - (unsigned long) cert->not_before || - (unsigned long) now.sec > - (unsigned long) cert->not_after) { - wpa_printf(MSG_INFO, "X509: Certificate not valid " - "(now=%lu not_before=%lu not_after=%lu)", - now.sec, cert->not_before, cert->not_after); - *reason = X509_VALIDATE_CERTIFICATE_EXPIRED; - return -1; - } - - if (cert->next) { - if (x509_name_compare(&cert->issuer, - &cert->next->subject) != 0) { - wpa_printf(MSG_DEBUG, "X509: Certificate " - "chain issuer name mismatch"); - x509_name_string(&cert->issuer, buf, - sizeof(buf)); - wpa_printf(MSG_DEBUG, "X509: cert issuer: %s", - buf); - x509_name_string(&cert->next->subject, buf, - sizeof(buf)); - wpa_printf(MSG_DEBUG, "X509: next cert " - "subject: %s", buf); - *reason = X509_VALIDATE_CERTIFICATE_UNKNOWN; - return -1; - } - - if (x509_valid_issuer(cert->next) < 0) { - *reason = X509_VALIDATE_BAD_CERTIFICATE; - return -1; - } - - if ((cert->next->extensions_present & - X509_EXT_PATH_LEN_CONSTRAINT) && - idx > cert->next->path_len_constraint) { - wpa_printf(MSG_DEBUG, "X509: pathLenConstraint" - " not met (idx=%lu issuer " - "pathLenConstraint=%lu)", idx, - cert->next->path_len_constraint); - *reason = X509_VALIDATE_BAD_CERTIFICATE; - return -1; - } - - if (x509_certificate_check_signature(cert->next, cert) - < 0) { - wpa_printf(MSG_DEBUG, "X509: Invalid " - "certificate signature within " - "chain"); - *reason = X509_VALIDATE_BAD_CERTIFICATE; - return -1; - } - } - - for (trust = trusted; trust; trust = trust->next) { - if (x509_name_compare(&cert->issuer, &trust->subject) - == 0) - break; - } - - if (trust) { - wpa_printf(MSG_DEBUG, "X509: Found issuer from the " - "list of trusted certificates"); - if (x509_valid_issuer(trust) < 0) { - *reason = X509_VALIDATE_BAD_CERTIFICATE; - return -1; - } - - if (x509_certificate_check_signature(trust, cert) < 0) - { - wpa_printf(MSG_DEBUG, "X509: Invalid " - "certificate signature"); - *reason = X509_VALIDATE_BAD_CERTIFICATE; - return -1; - } - - wpa_printf(MSG_DEBUG, "X509: Trusted certificate " - "found to complete the chain"); - chain_trusted = 1; - } - } - - if (!chain_trusted) { - wpa_printf(MSG_DEBUG, "X509: Did not find any of the issuers " - "from the list of trusted certificates"); - if (trusted) { - *reason = X509_VALIDATE_UNKNOWN_CA; - return -1; - } - wpa_printf(MSG_DEBUG, "X509: Certificate chain validation " - "disabled - ignore unknown CA issue"); - } - - wpa_printf(MSG_DEBUG, "X509: Certificate chain valid"); - - return 0; -} - - -/** - * x509_certificate_get_subject - Get a certificate based on Subject name - * @chain: Certificate chain to search through - * @name: Subject name to search for - * Returns: Pointer to the certificate with the given Subject name or - * %NULL on failure - */ -struct x509_certificate * -x509_certificate_get_subject(struct x509_certificate *chain, - struct x509_name *name) -{ - struct x509_certificate *cert; - - for (cert = chain; cert; cert = cert->next) { - if (x509_name_compare(&cert->subject, name) == 0) - return cert; - } - return NULL; -} - - -/** - * x509_certificate_self_signed - Is the certificate self-signed? - * @cert: Certificate - * Returns: 1 if certificate is self-signed, 0 if not - */ -int x509_certificate_self_signed(struct x509_certificate *cert) -{ - return x509_name_compare(&cert->issuer, &cert->subject) == 0; -} - -#endif /* CONFIG_INTERNAL_X509 */ diff --git a/contrib/hostapd/src/tls/x509v3.h b/contrib/hostapd/src/tls/x509v3.h deleted file mode 100644 index a52bcf8864..0000000000 --- a/contrib/hostapd/src/tls/x509v3.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * X.509v3 certificate parsing and processing - * Copyright (c) 2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef X509V3_H -#define X509V3_H - -#include "asn1.h" - -struct x509_algorithm_identifier { - struct asn1_oid oid; -}; - -struct x509_name { - char *cn; /* commonName */ - char *c; /* countryName */ - char *l; /* localityName */ - char *st; /* stateOrProvinceName */ - char *o; /* organizationName */ - char *ou; /* organizationalUnitName */ - char *email; /* emailAddress */ -}; - -struct x509_certificate { - struct x509_certificate *next; - enum { X509_CERT_V1 = 0, X509_CERT_V2 = 1, X509_CERT_V3 = 2 } version; - unsigned long serial_number; - struct x509_algorithm_identifier signature; - struct x509_name issuer; - struct x509_name subject; - os_time_t not_before; - os_time_t not_after; - struct x509_algorithm_identifier public_key_alg; - u8 *public_key; - size_t public_key_len; - struct x509_algorithm_identifier signature_alg; - u8 *sign_value; - size_t sign_value_len; - - /* Extensions */ - unsigned int extensions_present; -#define X509_EXT_BASIC_CONSTRAINTS (1 << 0) -#define X509_EXT_PATH_LEN_CONSTRAINT (1 << 1) -#define X509_EXT_KEY_USAGE (1 << 2) - - /* BasicConstraints */ - int ca; /* cA */ - unsigned long path_len_constraint; /* pathLenConstraint */ - - /* KeyUsage */ - unsigned long key_usage; -#define X509_KEY_USAGE_DIGITAL_SIGNATURE (1 << 0) -#define X509_KEY_USAGE_NON_REPUDIATION (1 << 1) -#define X509_KEY_USAGE_KEY_ENCIPHERMENT (1 << 2) -#define X509_KEY_USAGE_DATA_ENCIPHERMENT (1 << 3) -#define X509_KEY_USAGE_KEY_AGREEMENT (1 << 4) -#define X509_KEY_USAGE_KEY_CERT_SIGN (1 << 5) -#define X509_KEY_USAGE_CRL_SIGN (1 << 6) -#define X509_KEY_USAGE_ENCIPHER_ONLY (1 << 7) -#define X509_KEY_USAGE_DECIPHER_ONLY (1 << 8) - - /* - * The DER format certificate follows struct x509_certificate. These - * pointers point to that buffer. - */ - const u8 *cert_start; - size_t cert_len; - const u8 *tbs_cert_start; - size_t tbs_cert_len; -}; - -enum { - X509_VALIDATE_OK, - X509_VALIDATE_BAD_CERTIFICATE, - X509_VALIDATE_UNSUPPORTED_CERTIFICATE, - X509_VALIDATE_CERTIFICATE_REVOKED, - X509_VALIDATE_CERTIFICATE_EXPIRED, - X509_VALIDATE_CERTIFICATE_UNKNOWN, - X509_VALIDATE_UNKNOWN_CA -}; - -#ifdef CONFIG_INTERNAL_X509 - -void x509_certificate_free(struct x509_certificate *cert); -struct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len); -void x509_name_string(struct x509_name *name, char *buf, size_t len); -int x509_name_compare(struct x509_name *a, struct x509_name *b); -void x509_certificate_chain_free(struct x509_certificate *cert); -int x509_certificate_check_signature(struct x509_certificate *issuer, - struct x509_certificate *cert); -int x509_certificate_chain_validate(struct x509_certificate *trusted, - struct x509_certificate *chain, - int *reason); -struct x509_certificate * -x509_certificate_get_subject(struct x509_certificate *chain, - struct x509_name *name); -int x509_certificate_self_signed(struct x509_certificate *cert); - -#else /* CONFIG_INTERNAL_X509 */ - -static inline void x509_certificate_free(struct x509_certificate *cert) -{ -} - -static inline struct x509_certificate * -x509_certificate_parse(const u8 *buf, size_t len) -{ - return NULL; -} - -static inline void x509_name_string(struct x509_name *name, char *buf, - size_t len) -{ - if (len) - buf[0] = '\0'; -} - -static inline void x509_certificate_chain_free(struct x509_certificate *cert) -{ -} - -static inline int -x509_certificate_chain_validate(struct x509_certificate *trusted, - struct x509_certificate *chain, - int *reason) -{ - return -1; -} - -static inline struct x509_certificate * -x509_certificate_get_subject(struct x509_certificate *chain, - struct x509_name *name) -{ - return NULL; -} - -static inline int x509_certificate_self_signed(struct x509_certificate *cert) -{ - return -1; -} - -#endif /* CONFIG_INTERNAL_X509 */ - -#endif /* X509V3_H */ diff --git a/contrib/hostapd/src/utils/base64.c b/contrib/hostapd/src/utils/base64.c deleted file mode 100644 index 13fc511dc6..0000000000 --- a/contrib/hostapd/src/utils/base64.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Base64 encoding/decoding (RFC1341) - * Copyright (c) 2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "os.h" -#include "base64.h" - -static const unsigned char base64_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) -{ - unsigned char *out, *pos; - const unsigned char *end, *in; - size_t olen; - int line_len; - - olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */ - olen += olen / 72; /* line feeds */ - olen++; /* nul termination */ - if (olen < len) - return NULL; /* integer overflow */ - out = os_malloc(olen); - if (out == NULL) - return NULL; - - end = src + len; - in = src; - pos = out; - line_len = 0; - while (end - in >= 3) { - *pos++ = base64_table[in[0] >> 2]; - *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)]; - *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)]; - *pos++ = base64_table[in[2] & 0x3f]; - in += 3; - line_len += 4; - if (line_len >= 72) { - *pos++ = '\n'; - line_len = 0; - } - } - - if (end - in) { - *pos++ = base64_table[in[0] >> 2]; - if (end - in == 1) { - *pos++ = base64_table[(in[0] & 0x03) << 4]; - *pos++ = '='; - } else { - *pos++ = base64_table[((in[0] & 0x03) << 4) | - (in[1] >> 4)]; - *pos++ = base64_table[(in[1] & 0x0f) << 2]; - } - *pos++ = '='; - line_len += 4; - } - - if (line_len) - *pos++ = '\n'; - - *pos = '\0'; - if (out_len) - *out_len = pos - out; - return out; -} - - -/** - * 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) -{ - unsigned char dtable[256], *out, *pos, in[4], block[4], tmp; - size_t i, count, olen; - - os_memset(dtable, 0x80, 256); - for (i = 0; i < sizeof(base64_table) - 1; i++) - dtable[base64_table[i]] = (unsigned char) i; - dtable['='] = 0; - - count = 0; - for (i = 0; i < len; i++) { - if (dtable[src[i]] != 0x80) - count++; - } - - if (count == 0 || count % 4) - return NULL; - - olen = count / 4 * 3; - pos = out = os_malloc(olen); - if (out == NULL) - return NULL; - - count = 0; - for (i = 0; i < len; i++) { - tmp = dtable[src[i]]; - if (tmp == 0x80) - continue; - - in[count] = src[i]; - block[count] = tmp; - count++; - if (count == 4) { - *pos++ = (block[0] << 2) | (block[1] >> 4); - *pos++ = (block[1] << 4) | (block[2] >> 2); - *pos++ = (block[2] << 6) | block[3]; - count = 0; - } - } - - if (pos > out) { - if (in[2] == '=') - pos -= 2; - else if (in[3] == '=') - pos--; - } - - *out_len = pos - out; - return out; -} - - -#ifdef TEST_MAIN - -int main(int argc, char *argv[]) -{ - FILE *f; - size_t len, elen; - unsigned char *buf, *e; - - if (argc != 4) { - printf("Usage: base64 \n"); - return -1; - } - - buf = os_readfile(argv[2], &len); - if (buf == NULL) - return -1; - - if (strcmp(argv[1], "encode") == 0) - e = base64_encode(buf, len, &elen); - else - e = base64_decode(buf, len, &elen); - if (e == NULL) - return -2; - f = fopen(argv[3], "w"); - if (f == NULL) - return -3; - fwrite(e, 1, elen, f); - fclose(f); - free(e); - - return 0; -} -#endif /* TEST_MAIN */ diff --git a/contrib/hostapd/src/utils/base64.h b/contrib/hostapd/src/utils/base64.h deleted file mode 100644 index 73312dde8f..0000000000 --- a/contrib/hostapd/src/utils/base64.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Base64 encoding/decoding (RFC1341) - * Copyright (c) 2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef BASE64_H -#define BASE64_h - -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); - -#endif /* BASE64_H */ diff --git a/contrib/hostapd/src/utils/build_config.h b/contrib/hostapd/src/utils/build_config.h deleted file mode 100644 index 1e147fe369..0000000000 --- a/contrib/hostapd/src/utils/build_config.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * wpa_supplicant/hostapd - Build time configuration defines - * Copyright (c) 2005-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This header file can be used to define configuration defines that were - * originally defined in Makefile. This is mainly meant for IDE use or for - * systems that do not have suitable 'make' tool. In these cases, it may be - * easier to have a single place for defining all the needed C pre-processor - * defines. - */ - -#ifndef BUILD_CONFIG_H -#define BUILD_CONFIG_H - -/* Insert configuration defines, e.g., #define EAP_MD5, here, if needed. */ - -#ifdef CONFIG_WIN32_DEFAULTS -#define CONFIG_NATIVE_WINDOWS -#define CONFIG_ANSI_C_EXTRA -#define CONFIG_WINPCAP -#define IEEE8021X_EAPOL -#define EAP_TLS_FUNCS -#define PKCS12_FUNCS -#define PCSC_FUNCS -#define CONFIG_CTRL_IFACE -#define CONFIG_CTRL_IFACE_NAMED_PIPE -#define CONFIG_DRIVER_NDIS -#define CONFIG_NDIS_EVENTS_INTEGRATED -#define CONFIG_DEBUG_FILE -#define EAP_MD5 -#define EAP_TLS -#define EAP_MSCHAPv2 -#define EAP_PEAP -#define EAP_TTLS -#define EAP_GTC -#define EAP_OTP -#define EAP_LEAP -#define EAP_TNC -#define _CRT_SECURE_NO_DEPRECATE - -#ifdef USE_INTERNAL_CRYPTO -#define CONFIG_TLS_INTERNAL -#define CONFIG_TLS_INTERNAL_CLIENT -#define CONFIG_INTERNAL_LIBTOMMATH -#define INTERNAL_AES -#define INTERNAL_SHA1 -#define INTERNAL_SHA256 -#define INTERNAL_MD5 -#define INTERNAL_MD4 -#define INTERNAL_DES -#define CONFIG_INTERNAL_X509 -#define CONFIG_CRYPTO_INTERNAL -#endif /* USE_INTERNAL_CRYPTO */ -#endif /* CONFIG_WIN32_DEFAULTS */ - -#ifdef __SYMBIAN32__ -#define OS_NO_C_LIB_DEFINES -#define CONFIG_ANSI_C_EXTRA -#define CONFIG_NO_WPA_MSG -#define CONFIG_NO_HOSTAPD_LOGGER -#define CONFIG_NO_STDOUT_DEBUG -#define CONFIG_BACKEND_FILE -#define INTERNAL_AES -#define INTERNAL_SHA1 -#define INTERNAL_MD5 -#define INTERNAL_MD4 -#define INTERNAL_DES -#define CONFIG_INTERNAL_LIBTOMMATH -#define CONFIG_INTERNAL_X509 -#define EAP_TLS_FUNCS -#define CONFIG_TLS_INTERNAL -#define CONFIG_CRYPTO_INTERNAL -#define IEEE8021X_EAPOL -#define PKCS12_FUNCS -#define EAP_MD5 -#define EAP_TLS -#define EAP_MSCHAPv2 -#define EAP_PEAP -#define EAP_TTLS -#define EAP_GTC -#define EAP_OTP -#define EAP_LEAP -#define EAP_FAST -#endif /* __SYMBIAN32__ */ - -#endif /* BUILD_CONFIG_H */ diff --git a/contrib/hostapd/src/utils/common.c b/contrib/hostapd/src/utils/common.c deleted file mode 100644 index 9a46ebe461..0000000000 --- a/contrib/hostapd/src/utils/common.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * wpa_supplicant/hostapd / common helper functions, etc. - * Copyright (c) 2002-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" - - -static int hex2num(char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - return -1; -} - - -static int hex2byte(const char *hex) -{ - int a, b; - a = hex2num(*hex++); - if (a < 0) - return -1; - b = hex2num(*hex++); - if (b < 0) - return -1; - return (a << 4) | b; -} - - -/** - * hwaddr_aton - Convert ASCII string to MAC address - * @txt: MAC address as a string (e.g., "00:11:22:33:44:55") - * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) - * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) - */ -int hwaddr_aton(const char *txt, u8 *addr) -{ - int i; - - for (i = 0; i < 6; i++) { - int a, b; - - a = hex2num(*txt++); - if (a < 0) - return -1; - b = hex2num(*txt++); - if (b < 0) - return -1; - *addr++ = (a << 4) | b; - if (i < 5 && *txt++ != ':') - return -1; - } - - return 0; -} - - -/** - * hexstr2bin - Convert ASCII hex string into binary data - * @hex: ASCII hex string (e.g., "01ab") - * @buf: Buffer for the binary data - * @len: Length of the text to convert in bytes (of buf); hex will be double - * this size - * Returns: 0 on success, -1 on failure (invalid hex string) - */ -int hexstr2bin(const char *hex, u8 *buf, size_t len) -{ - size_t i; - int a; - const char *ipos = hex; - u8 *opos = buf; - - for (i = 0; i < len; i++) { - a = hex2byte(ipos); - if (a < 0) - return -1; - *opos++ = a; - ipos += 2; - } - return 0; -} - - -/** - * inc_byte_array - Increment arbitrary length byte array by one - * @counter: Pointer to byte array - * @len: Length of the counter in bytes - * - * This function increments the last byte of the counter by one and continues - * rolling over to more significant bytes if the byte was incremented from - * 0xff to 0x00. - */ -void inc_byte_array(u8 *counter, size_t len) -{ - int pos = len - 1; - while (pos >= 0) { - counter[pos]++; - if (counter[pos] != 0) - break; - pos--; - } -} - - -void wpa_get_ntp_timestamp(u8 *buf) -{ - struct os_time now; - u32 sec, usec; - be32 tmp; - - /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */ - os_get_time(&now); - sec = now.sec + 2208988800U; /* Epoch to 1900 */ - /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */ - usec = now.usec; - usec = 4295 * usec - (usec >> 5) - (usec >> 9); - tmp = host_to_be32(sec); - os_memcpy(buf, (u8 *) &tmp, 4); - tmp = host_to_be32(usec); - os_memcpy(buf + 4, (u8 *) &tmp, 4); -} - - -static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, - size_t len, int uppercase) -{ - size_t i; - char *pos = buf, *end = buf + buf_size; - int ret; - if (buf_size == 0) - return 0; - for (i = 0; i < len; i++) { - ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", - data[i]); - if (ret < 0 || ret >= end - pos) { - end[-1] = '\0'; - return pos - buf; - } - pos += ret; - } - end[-1] = '\0'; - return pos - buf; -} - -/** - * wpa_snprintf_hex - Print data as a hex string into a buffer - * @buf: Memory area to use as the output buffer - * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) - * @data: Data to be printed - * @len: Length of data in bytes - * Returns: Number of bytes written - */ -int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) -{ - return _wpa_snprintf_hex(buf, buf_size, data, len, 0); -} - - -/** - * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf - * @buf: Memory area to use as the output buffer - * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) - * @data: Data to be printed - * @len: Length of data in bytes - * Returns: Number of bytes written - */ -int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, - size_t len) -{ - return _wpa_snprintf_hex(buf, buf_size, data, len, 1); -} - - -#ifdef CONFIG_ANSI_C_EXTRA - -#ifdef _WIN32_WCE -void perror(const char *s) -{ - wpa_printf(MSG_ERROR, "%s: GetLastError: %d", - s, (int) GetLastError()); -} -#endif /* _WIN32_WCE */ - - -int optind = 1; -int optopt; -char *optarg; - -int getopt(int argc, char *const argv[], const char *optstring) -{ - static int optchr = 1; - char *cp; - - if (optchr == 1) { - if (optind >= argc) { - /* all arguments processed */ - return EOF; - } - - if (argv[optind][0] != '-' || argv[optind][1] == '\0') { - /* no option characters */ - return EOF; - } - } - - if (os_strcmp(argv[optind], "--") == 0) { - /* no more options */ - optind++; - return EOF; - } - - optopt = argv[optind][optchr]; - cp = os_strchr(optstring, optopt); - if (cp == NULL || optopt == ':') { - if (argv[optind][++optchr] == '\0') { - optchr = 1; - optind++; - } - return '?'; - } - - if (cp[1] == ':') { - /* Argument required */ - optchr = 1; - if (argv[optind][optchr + 1]) { - /* No space between option and argument */ - optarg = &argv[optind++][optchr + 1]; - } else if (++optind >= argc) { - /* option requires an argument */ - return '?'; - } else { - /* Argument in the next argv */ - optarg = argv[optind++]; - } - } else { - /* No argument */ - if (argv[optind][++optchr] == '\0') { - optchr = 1; - optind++; - } - optarg = NULL; - } - return *cp; -} -#endif /* CONFIG_ANSI_C_EXTRA */ - - -#ifdef CONFIG_NATIVE_WINDOWS -/** - * wpa_unicode2ascii_inplace - Convert unicode string into ASCII - * @str: Pointer to string to convert - * - * This function converts a unicode string to ASCII using the same - * buffer for output. If UNICODE is not set, the buffer is not - * modified. - */ -void wpa_unicode2ascii_inplace(TCHAR *str) -{ -#ifdef UNICODE - char *dst = (char *) str; - while (*str) - *dst++ = (char) *str++; - *dst = '\0'; -#endif /* UNICODE */ -} - - -TCHAR * wpa_strdup_tchar(const char *str) -{ -#ifdef UNICODE - TCHAR *buf; - buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR)); - if (buf == NULL) - return NULL; - wsprintf(buf, L"%S", str); - return buf; -#else /* UNICODE */ - return os_strdup(str); -#endif /* UNICODE */ -} -#endif /* CONFIG_NATIVE_WINDOWS */ - - -/** - * wpa_ssid_txt - Convert SSID to a printable string - * @ssid: SSID (32-octet string) - * @ssid_len: Length of ssid in octets - * Returns: Pointer to a printable string - * - * This function can be used to convert SSIDs into printable form. In most - * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard - * does not limit the used character set, so anything could be used in an SSID. - * - * This function uses a static buffer, so only one call can be used at the - * time, i.e., this is not re-entrant and the returned buffer must be used - * before calling this again. - */ -const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len) -{ - static char ssid_txt[33]; - char *pos; - - if (ssid_len > 32) - ssid_len = 32; - os_memcpy(ssid_txt, ssid, ssid_len); - ssid_txt[ssid_len] = '\0'; - for (pos = ssid_txt; *pos != '\0'; pos++) { - if ((u8) *pos < 32 || (u8) *pos >= 127) - *pos = '_'; - } - return ssid_txt; -} - - -void * __hide_aliasing_typecast(void *foo) -{ - return foo; -} diff --git a/contrib/hostapd/src/utils/common.h b/contrib/hostapd/src/utils/common.h deleted file mode 100644 index d649391e37..0000000000 --- a/contrib/hostapd/src/utils/common.h +++ /dev/null @@ -1,458 +0,0 @@ -/* - * wpa_supplicant/hostapd / common helper functions, etc. - * Copyright (c) 2002-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef COMMON_H -#define COMMON_H - -#include "os.h" - -#ifdef __linux__ -#include -#include -#endif /* __linux__ */ - -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \ - defined(__OpenBSD__) -#include -#include -#define __BYTE_ORDER _BYTE_ORDER -#define __LITTLE_ENDIAN _LITTLE_ENDIAN -#define __BIG_ENDIAN _BIG_ENDIAN -#ifdef __OpenBSD__ -#define bswap_16 swap16 -#define bswap_32 swap32 -#define bswap_64 swap64 -#else /* __OpenBSD__ */ -#define bswap_16 bswap16 -#define bswap_32 bswap32 -#define bswap_64 bswap64 -#endif /* __OpenBSD__ */ -#endif /* defined(__FreeBSD__) || defined(__NetBSD__) || - * defined(__DragonFly__) || defined(__OpenBSD__) */ - -#ifdef __APPLE__ -#include -#include -#define __BYTE_ORDER _BYTE_ORDER -#define __LITTLE_ENDIAN _LITTLE_ENDIAN -#define __BIG_ENDIAN _BIG_ENDIAN -static inline unsigned short bswap_16(unsigned short v) -{ - return ((v & 0xff) << 8) | (v >> 8); -} - -static inline unsigned int bswap_32(unsigned int v) -{ - return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | - ((v & 0xff0000) >> 8) | (v >> 24); -} -#endif /* __APPLE__ */ - -#ifdef CONFIG_TI_COMPILER -#define __BIG_ENDIAN 4321 -#define __LITTLE_ENDIAN 1234 -#ifdef __big_endian__ -#define __BYTE_ORDER __BIG_ENDIAN -#else -#define __BYTE_ORDER __LITTLE_ENDIAN -#endif -#endif /* CONFIG_TI_COMPILER */ - -#ifdef __SYMBIAN32__ -#define __BIG_ENDIAN 4321 -#define __LITTLE_ENDIAN 1234 -#define __BYTE_ORDER __LITTLE_ENDIAN -#endif /* __SYMBIAN32__ */ - -#ifdef CONFIG_NATIVE_WINDOWS -#include - -typedef int socklen_t; - -#ifndef MSG_DONTWAIT -#define MSG_DONTWAIT 0 /* not supported */ -#endif - -#endif /* CONFIG_NATIVE_WINDOWS */ - -#ifdef _MSC_VER -#define inline __inline - -#undef vsnprintf -#define vsnprintf _vsnprintf -#undef close -#define close closesocket -#endif /* _MSC_VER */ - - -/* Define platform specific integer types */ - -#ifdef _MSC_VER -typedef UINT64 u64; -typedef UINT32 u32; -typedef UINT16 u16; -typedef UINT8 u8; -typedef INT64 s64; -typedef INT32 s32; -typedef INT16 s16; -typedef INT8 s8; -#define WPA_TYPES_DEFINED -#endif /* _MSC_VER */ - -#ifdef __vxworks -typedef unsigned long long u64; -typedef UINT32 u32; -typedef UINT16 u16; -typedef UINT8 u8; -typedef long long s64; -typedef INT32 s32; -typedef INT16 s16; -typedef INT8 s8; -#define WPA_TYPES_DEFINED -#endif /* __vxworks */ - -#ifdef CONFIG_TI_COMPILER -#ifdef _LLONG_AVAILABLE -typedef unsigned long long u64; -#else -/* - * TODO: 64-bit variable not available. Using long as a workaround to test the - * build, but this will likely not work for all operations. - */ -typedef unsigned long u64; -#endif -typedef unsigned int u32; -typedef unsigned short u16; -typedef unsigned char u8; -#define WPA_TYPES_DEFINED -#endif /* CONFIG_TI_COMPILER */ - -#ifdef __SYMBIAN32__ -#define __REMOVE_PLATSEC_DIAGNOSTICS__ -#include -typedef TUint64 u64; -typedef TUint32 u32; -typedef TUint16 u16; -typedef TUint8 u8; -#define WPA_TYPES_DEFINED -#endif /* __SYMBIAN32__ */ - -#ifndef WPA_TYPES_DEFINED -#ifdef CONFIG_USE_INTTYPES_H -#include -#else -#include -#endif -typedef uint64_t u64; -typedef uint32_t u32; -typedef uint16_t u16; -typedef uint8_t u8; -typedef int64_t s64; -typedef int32_t s32; -typedef int16_t s16; -typedef int8_t s8; -#define WPA_TYPES_DEFINED -#endif /* !WPA_TYPES_DEFINED */ - - -/* Define platform specific byte swapping macros */ - -#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS) - -static inline unsigned short wpa_swap_16(unsigned short v) -{ - return ((v & 0xff) << 8) | (v >> 8); -} - -static inline unsigned int wpa_swap_32(unsigned int v) -{ - return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | - ((v & 0xff0000) >> 8) | (v >> 24); -} - -#define le_to_host16(n) (n) -#define host_to_le16(n) (n) -#define be_to_host16(n) wpa_swap_16(n) -#define host_to_be16(n) wpa_swap_16(n) -#define le_to_host32(n) (n) -#define be_to_host32(n) wpa_swap_32(n) -#define host_to_be32(n) wpa_swap_32(n) - -#define WPA_BYTE_SWAP_DEFINED - -#endif /* __CYGWIN__ || CONFIG_NATIVE_WINDOWS */ - - -#ifndef WPA_BYTE_SWAP_DEFINED - -#ifndef __BYTE_ORDER -#ifndef __LITTLE_ENDIAN -#ifndef __BIG_ENDIAN -#define __LITTLE_ENDIAN 1234 -#define __BIG_ENDIAN 4321 -#if defined(sparc) -#define __BYTE_ORDER __BIG_ENDIAN -#endif -#endif /* __BIG_ENDIAN */ -#endif /* __LITTLE_ENDIAN */ -#endif /* __BYTE_ORDER */ - -#if __BYTE_ORDER == __LITTLE_ENDIAN -#define le_to_host16(n) ((__force u16) (le16) (n)) -#define host_to_le16(n) ((__force le16) (u16) (n)) -#define be_to_host16(n) bswap_16((__force u16) (be16) (n)) -#define host_to_be16(n) ((__force be16) bswap_16((n))) -#define le_to_host32(n) ((__force u32) (le32) (n)) -#define host_to_le32(n) ((__force le32) (u32) (n)) -#define be_to_host32(n) bswap_32((__force u32) (be32) (n)) -#define host_to_be32(n) ((__force be32) bswap_32((n))) -#define le_to_host64(n) ((__force u64) (le64) (n)) -#define host_to_le64(n) ((__force le64) (u64) (n)) -#define be_to_host64(n) bswap_64((__force u64) (be64) (n)) -#define host_to_be64(n) ((__force be64) bswap_64((n))) -#elif __BYTE_ORDER == __BIG_ENDIAN -#define le_to_host16(n) bswap_16(n) -#define host_to_le16(n) bswap_16(n) -#define be_to_host16(n) (n) -#define host_to_be16(n) (n) -#define le_to_host32(n) bswap_32(n) -#define be_to_host32(n) (n) -#define host_to_be32(n) (n) -#define le_to_host64(n) bswap_64(n) -#define host_to_le64(n) bswap_64(n) -#define be_to_host64(n) (n) -#define host_to_be64(n) (n) -#ifndef WORDS_BIGENDIAN -#define WORDS_BIGENDIAN -#endif -#else -#error Could not determine CPU byte order -#endif - -#define WPA_BYTE_SWAP_DEFINED -#endif /* !WPA_BYTE_SWAP_DEFINED */ - - -/* Macros for handling unaligned memory accesses */ - -#define WPA_GET_BE16(a) ((u16) (((a)[0] << 8) | (a)[1])) -#define WPA_PUT_BE16(a, val) \ - do { \ - (a)[0] = ((u16) (val)) >> 8; \ - (a)[1] = ((u16) (val)) & 0xff; \ - } while (0) - -#define WPA_GET_LE16(a) ((u16) (((a)[1] << 8) | (a)[0])) -#define WPA_PUT_LE16(a, val) \ - do { \ - (a)[1] = ((u16) (val)) >> 8; \ - (a)[0] = ((u16) (val)) & 0xff; \ - } while (0) - -#define WPA_GET_BE24(a) ((((u32) (a)[0]) << 16) | (((u32) (a)[1]) << 8) | \ - ((u32) (a)[2])) -#define WPA_PUT_BE24(a, val) \ - do { \ - (a)[0] = (u8) ((((u32) (val)) >> 16) & 0xff); \ - (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff); \ - (a)[2] = (u8) (((u32) (val)) & 0xff); \ - } while (0) - -#define WPA_GET_BE32(a) ((((u32) (a)[0]) << 24) | (((u32) (a)[1]) << 16) | \ - (((u32) (a)[2]) << 8) | ((u32) (a)[3])) -#define WPA_PUT_BE32(a, val) \ - do { \ - (a)[0] = (u8) ((((u32) (val)) >> 24) & 0xff); \ - (a)[1] = (u8) ((((u32) (val)) >> 16) & 0xff); \ - (a)[2] = (u8) ((((u32) (val)) >> 8) & 0xff); \ - (a)[3] = (u8) (((u32) (val)) & 0xff); \ - } while (0) - -#define WPA_GET_LE32(a) ((((u32) (a)[3]) << 24) | (((u32) (a)[2]) << 16) | \ - (((u32) (a)[1]) << 8) | ((u32) (a)[0])) -#define WPA_PUT_LE32(a, val) \ - do { \ - (a)[3] = (u8) ((((u32) (val)) >> 24) & 0xff); \ - (a)[2] = (u8) ((((u32) (val)) >> 16) & 0xff); \ - (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff); \ - (a)[0] = (u8) (((u32) (val)) & 0xff); \ - } while (0) - -#define WPA_GET_BE64(a) ((((u64) (a)[0]) << 56) | (((u64) (a)[1]) << 48) | \ - (((u64) (a)[2]) << 40) | (((u64) (a)[3]) << 32) | \ - (((u64) (a)[4]) << 24) | (((u64) (a)[5]) << 16) | \ - (((u64) (a)[6]) << 8) | ((u64) (a)[7])) -#define WPA_PUT_BE64(a, val) \ - do { \ - (a)[0] = (u8) (((u64) (val)) >> 56); \ - (a)[1] = (u8) (((u64) (val)) >> 48); \ - (a)[2] = (u8) (((u64) (val)) >> 40); \ - (a)[3] = (u8) (((u64) (val)) >> 32); \ - (a)[4] = (u8) (((u64) (val)) >> 24); \ - (a)[5] = (u8) (((u64) (val)) >> 16); \ - (a)[6] = (u8) (((u64) (val)) >> 8); \ - (a)[7] = (u8) (((u64) (val)) & 0xff); \ - } while (0) - -#define WPA_GET_LE64(a) ((((u64) (a)[7]) << 56) | (((u64) (a)[6]) << 48) | \ - (((u64) (a)[5]) << 40) | (((u64) (a)[4]) << 32) | \ - (((u64) (a)[3]) << 24) | (((u64) (a)[2]) << 16) | \ - (((u64) (a)[1]) << 8) | ((u64) (a)[0])) - - -#ifndef ETH_ALEN -#define ETH_ALEN 6 -#endif - - -#ifdef __GNUC__ -#define PRINTF_FORMAT(a,b) __attribute__ ((format (printf, (a), (b)))) -#define STRUCT_PACKED __attribute__ ((packed)) -#else -#define PRINTF_FORMAT(a,b) -#define STRUCT_PACKED -#endif - - -#ifdef CONFIG_ANSI_C_EXTRA - -#if !defined(_MSC_VER) || _MSC_VER < 1400 -/* snprintf - used in number of places; sprintf() is _not_ a good replacement - * due to possible buffer overflow; see, e.g., - * http://www.ijs.si/software/snprintf/ for portable implementation of - * snprintf. */ -int snprintf(char *str, size_t size, const char *format, ...); - -/* vsnprintf - only used for wpa_msg() in wpa_supplicant.c */ -int vsnprintf(char *str, size_t size, const char *format, va_list ap); -#endif /* !defined(_MSC_VER) || _MSC_VER < 1400 */ - -/* getopt - only used in main.c */ -int getopt(int argc, char *const argv[], const char *optstring); -extern char *optarg; -extern int optind; - -#ifndef CONFIG_NO_SOCKLEN_T_TYPEDEF -#ifndef __socklen_t_defined -typedef int socklen_t; -#endif -#endif - -/* inline - define as __inline or just define it to be empty, if needed */ -#ifdef CONFIG_NO_INLINE -#define inline -#else -#define inline __inline -#endif - -#ifndef __func__ -#define __func__ "__func__ not defined" -#endif - -#ifndef bswap_16 -#define bswap_16(a) ((((u16) (a) << 8) & 0xff00) | (((u16) (a) >> 8) & 0xff)) -#endif - -#ifndef bswap_32 -#define bswap_32(a) ((((u32) (a) << 24) & 0xff000000) | \ - (((u32) (a) << 8) & 0xff0000) | \ - (((u32) (a) >> 8) & 0xff00) | \ - (((u32) (a) >> 24) & 0xff)) -#endif - -#ifndef MSG_DONTWAIT -#define MSG_DONTWAIT 0 -#endif - -#ifdef _WIN32_WCE -void perror(const char *s); -#endif /* _WIN32_WCE */ - -#endif /* CONFIG_ANSI_C_EXTRA */ - -#ifndef MAC2STR -#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] -#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" -#endif - -#ifndef BIT -#define BIT(x) (1 << (x)) -#endif - -/* - * Definitions for sparse validation - * (http://kernel.org/pub/linux/kernel/people/josh/sparse/) - */ -#ifdef __CHECKER__ -#define __force __attribute__((force)) -#define __bitwise __attribute__((bitwise)) -#else -#define __force -#define __bitwise -#endif - -typedef u16 __bitwise be16; -typedef u16 __bitwise le16; -typedef u32 __bitwise be32; -typedef u32 __bitwise le32; -typedef u64 __bitwise be64; -typedef u64 __bitwise le64; - -#ifndef __must_check -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -#define __must_check __attribute__((__warn_unused_result__)) -#else -#define __must_check -#endif /* __GNUC__ */ -#endif /* __must_check */ - -int hwaddr_aton(const char *txt, u8 *addr); -int hexstr2bin(const char *hex, u8 *buf, size_t len); -void inc_byte_array(u8 *counter, size_t len); -void wpa_get_ntp_timestamp(u8 *buf); -int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len); -int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, - size_t len); - -#ifdef CONFIG_NATIVE_WINDOWS -void wpa_unicode2ascii_inplace(TCHAR *str); -TCHAR * wpa_strdup_tchar(const char *str); -#else /* CONFIG_NATIVE_WINDOWS */ -#define wpa_unicode2ascii_inplace(s) do { } while (0) -#define wpa_strdup_tchar(s) strdup((s)) -#endif /* CONFIG_NATIVE_WINDOWS */ - -const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len); - -static inline int is_zero_ether_addr(const u8 *a) -{ - return !(a[0] | a[1] | a[2] | a[3] | a[4] | a[5]); -} - -#include "wpa_debug.h" - - -/* - * gcc 4.4 ends up generating strict-aliasing warnings about some very common - * networking socket uses that do not really result in a real problem and - * cannot be easily avoided with union-based type-punning due to struct - * definitions including another struct in system header files. To avoid having - * to fully disable strict-aliasing warnings, provide a mechanism to hide the - * typecast from aliasing for now. A cleaner solution will hopefully be found - * in the future to handle these cases. - */ -void * __hide_aliasing_typecast(void *foo); -#define aliasing_hide_typecast(a,t) (t *) __hide_aliasing_typecast((a)) - -#endif /* COMMON_H */ diff --git a/contrib/hostapd/src/utils/eloop.c b/contrib/hostapd/src/utils/eloop.c deleted file mode 100644 index 4edb2a7033..0000000000 --- a/contrib/hostapd/src/utils/eloop.c +++ /dev/null @@ -1,577 +0,0 @@ -/* - * Event loop based on select() loop - * Copyright (c) 2002-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eloop.h" - - -struct eloop_sock { - int sock; - void *eloop_data; - void *user_data; - eloop_sock_handler handler; -}; - -struct eloop_timeout { - struct os_time time; - void *eloop_data; - void *user_data; - eloop_timeout_handler handler; - struct eloop_timeout *next; -}; - -struct eloop_signal { - int sig; - void *user_data; - eloop_signal_handler handler; - int signaled; -}; - -struct eloop_sock_table { - int count; - struct eloop_sock *table; - int changed; -}; - -struct eloop_data { - void *user_data; - - int max_sock; - - struct eloop_sock_table readers; - struct eloop_sock_table writers; - struct eloop_sock_table exceptions; - - struct eloop_timeout *timeout; - - int signal_count; - struct eloop_signal *signals; - int signaled; - int pending_terminate; - - int terminate; - int reader_table_changed; -}; - -static struct eloop_data eloop; - - -int eloop_init(void *user_data) -{ - os_memset(&eloop, 0, sizeof(eloop)); - eloop.user_data = user_data; - return 0; -} - - -static int eloop_sock_table_add_sock(struct eloop_sock_table *table, - int sock, eloop_sock_handler handler, - void *eloop_data, void *user_data) -{ - struct eloop_sock *tmp; - - if (table == NULL) - return -1; - - tmp = (struct eloop_sock *) - os_realloc(table->table, - (table->count + 1) * sizeof(struct eloop_sock)); - if (tmp == NULL) - return -1; - - tmp[table->count].sock = sock; - tmp[table->count].eloop_data = eloop_data; - tmp[table->count].user_data = user_data; - tmp[table->count].handler = handler; - table->count++; - table->table = tmp; - if (sock > eloop.max_sock) - eloop.max_sock = sock; - table->changed = 1; - - return 0; -} - - -static void eloop_sock_table_remove_sock(struct eloop_sock_table *table, - int sock) -{ - int i; - - if (table == NULL || table->table == NULL || table->count == 0) - return; - - for (i = 0; i < table->count; i++) { - if (table->table[i].sock == sock) - break; - } - if (i == table->count) - return; - if (i != table->count - 1) { - os_memmove(&table->table[i], &table->table[i + 1], - (table->count - i - 1) * - sizeof(struct eloop_sock)); - } - table->count--; - table->changed = 1; -} - - -static void eloop_sock_table_set_fds(struct eloop_sock_table *table, - fd_set *fds) -{ - int i; - - FD_ZERO(fds); - - if (table->table == NULL) - return; - - for (i = 0; i < table->count; i++) - FD_SET(table->table[i].sock, fds); -} - - -static void eloop_sock_table_dispatch(struct eloop_sock_table *table, - fd_set *fds) -{ - int i; - - if (table == NULL || table->table == NULL) - return; - - table->changed = 0; - for (i = 0; i < table->count; i++) { - if (FD_ISSET(table->table[i].sock, fds)) { - table->table[i].handler(table->table[i].sock, - table->table[i].eloop_data, - table->table[i].user_data); - if (table->changed) - break; - } - } -} - - -static void eloop_sock_table_destroy(struct eloop_sock_table *table) -{ - if (table) { - int i; - for (i = 0; i < table->count && table->table; i++) { - printf("ELOOP: remaining socket: sock=%d " - "eloop_data=%p user_data=%p handler=%p\n", - table->table[i].sock, - table->table[i].eloop_data, - table->table[i].user_data, - table->table[i].handler); - } - os_free(table->table); - } -} - - -int eloop_register_read_sock(int sock, eloop_sock_handler handler, - void *eloop_data, void *user_data) -{ - return eloop_register_sock(sock, EVENT_TYPE_READ, handler, - eloop_data, user_data); -} - - -void eloop_unregister_read_sock(int sock) -{ - eloop_unregister_sock(sock, EVENT_TYPE_READ); -} - - -static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type) -{ - switch (type) { - case EVENT_TYPE_READ: - return &eloop.readers; - case EVENT_TYPE_WRITE: - return &eloop.writers; - case EVENT_TYPE_EXCEPTION: - return &eloop.exceptions; - } - - return NULL; -} - - -int eloop_register_sock(int sock, eloop_event_type type, - eloop_sock_handler handler, - void *eloop_data, void *user_data) -{ - struct eloop_sock_table *table; - - table = eloop_get_sock_table(type); - return eloop_sock_table_add_sock(table, sock, handler, - eloop_data, user_data); -} - - -void eloop_unregister_sock(int sock, eloop_event_type type) -{ - struct eloop_sock_table *table; - - table = eloop_get_sock_table(type); - eloop_sock_table_remove_sock(table, sock); -} - - -int eloop_register_timeout(unsigned int secs, unsigned int usecs, - eloop_timeout_handler handler, - void *eloop_data, void *user_data) -{ - struct eloop_timeout *timeout, *tmp, *prev; - - timeout = os_malloc(sizeof(*timeout)); - if (timeout == NULL) - return -1; - if (os_get_time(&timeout->time) < 0) { - os_free(timeout); - return -1; - } - timeout->time.sec += secs; - timeout->time.usec += usecs; - while (timeout->time.usec >= 1000000) { - timeout->time.sec++; - timeout->time.usec -= 1000000; - } - timeout->eloop_data = eloop_data; - timeout->user_data = user_data; - timeout->handler = handler; - timeout->next = NULL; - - if (eloop.timeout == NULL) { - eloop.timeout = timeout; - return 0; - } - - prev = NULL; - tmp = eloop.timeout; - while (tmp != NULL) { - if (os_time_before(&timeout->time, &tmp->time)) - break; - prev = tmp; - tmp = tmp->next; - } - - if (prev == NULL) { - timeout->next = eloop.timeout; - eloop.timeout = timeout; - } else { - timeout->next = prev->next; - prev->next = timeout; - } - - return 0; -} - - -int eloop_cancel_timeout(eloop_timeout_handler handler, - void *eloop_data, void *user_data) -{ - struct eloop_timeout *timeout, *prev, *next; - int removed = 0; - - prev = NULL; - timeout = eloop.timeout; - while (timeout != NULL) { - next = timeout->next; - - if (timeout->handler == handler && - (timeout->eloop_data == eloop_data || - eloop_data == ELOOP_ALL_CTX) && - (timeout->user_data == user_data || - user_data == ELOOP_ALL_CTX)) { - if (prev == NULL) - eloop.timeout = next; - else - prev->next = next; - os_free(timeout); - removed++; - } else - prev = timeout; - - timeout = next; - } - - return removed; -} - - -int eloop_is_timeout_registered(eloop_timeout_handler handler, - void *eloop_data, void *user_data) -{ - struct eloop_timeout *tmp; - - tmp = eloop.timeout; - while (tmp != NULL) { - if (tmp->handler == handler && - tmp->eloop_data == eloop_data && - tmp->user_data == user_data) - return 1; - - tmp = tmp->next; - } - - return 0; -} - - -#ifndef CONFIG_NATIVE_WINDOWS -static void eloop_handle_alarm(int sig) -{ - fprintf(stderr, "eloop: could not process SIGINT or SIGTERM in two " - "seconds. Looks like there\n" - "is a bug that ends up in a busy loop that " - "prevents clean shutdown.\n" - "Killing program forcefully.\n"); - exit(1); -} -#endif /* CONFIG_NATIVE_WINDOWS */ - - -static void eloop_handle_signal(int sig) -{ - int i; - -#ifndef CONFIG_NATIVE_WINDOWS - if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) { - /* Use SIGALRM to break out from potential busy loops that - * would not allow the program to be killed. */ - eloop.pending_terminate = 1; - signal(SIGALRM, eloop_handle_alarm); - alarm(2); - } -#endif /* CONFIG_NATIVE_WINDOWS */ - - eloop.signaled++; - for (i = 0; i < eloop.signal_count; i++) { - if (eloop.signals[i].sig == sig) { - eloop.signals[i].signaled++; - break; - } - } -} - - -static void eloop_process_pending_signals(void) -{ - int i; - - if (eloop.signaled == 0) - return; - eloop.signaled = 0; - - if (eloop.pending_terminate) { -#ifndef CONFIG_NATIVE_WINDOWS - alarm(0); -#endif /* CONFIG_NATIVE_WINDOWS */ - eloop.pending_terminate = 0; - } - - for (i = 0; i < eloop.signal_count; i++) { - if (eloop.signals[i].signaled) { - eloop.signals[i].signaled = 0; - eloop.signals[i].handler(eloop.signals[i].sig, - eloop.user_data, - eloop.signals[i].user_data); - } - } -} - - -int eloop_register_signal(int sig, eloop_signal_handler handler, - void *user_data) -{ - struct eloop_signal *tmp; - - tmp = (struct eloop_signal *) - os_realloc(eloop.signals, - (eloop.signal_count + 1) * - sizeof(struct eloop_signal)); - if (tmp == NULL) - return -1; - - tmp[eloop.signal_count].sig = sig; - tmp[eloop.signal_count].user_data = user_data; - tmp[eloop.signal_count].handler = handler; - tmp[eloop.signal_count].signaled = 0; - eloop.signal_count++; - eloop.signals = tmp; - signal(sig, eloop_handle_signal); - - return 0; -} - - -int eloop_register_signal_terminate(eloop_signal_handler handler, - void *user_data) -{ - int ret = eloop_register_signal(SIGINT, handler, user_data); - if (ret == 0) - ret = eloop_register_signal(SIGTERM, handler, user_data); - return ret; -} - - -int eloop_register_signal_reconfig(eloop_signal_handler handler, - void *user_data) -{ -#ifdef CONFIG_NATIVE_WINDOWS - return 0; -#else /* CONFIG_NATIVE_WINDOWS */ - return eloop_register_signal(SIGHUP, handler, user_data); -#endif /* CONFIG_NATIVE_WINDOWS */ -} - - -void eloop_run(void) -{ - fd_set *rfds, *wfds, *efds; - int res; - struct timeval _tv; - struct os_time tv, now; - - rfds = os_malloc(sizeof(*rfds)); - wfds = os_malloc(sizeof(*wfds)); - efds = os_malloc(sizeof(*efds)); - if (rfds == NULL || wfds == NULL || efds == NULL) { - printf("eloop_run - malloc failed\n"); - goto out; - } - - while (!eloop.terminate && - (eloop.timeout || eloop.readers.count > 0 || - eloop.writers.count > 0 || eloop.exceptions.count > 0)) { - if (eloop.timeout) { - os_get_time(&now); - if (os_time_before(&now, &eloop.timeout->time)) - os_time_sub(&eloop.timeout->time, &now, &tv); - else - tv.sec = tv.usec = 0; -#if 0 - printf("next timeout in %lu.%06lu sec\n", - tv.sec, tv.usec); -#endif - _tv.tv_sec = tv.sec; - _tv.tv_usec = tv.usec; - } - - eloop_sock_table_set_fds(&eloop.readers, rfds); - eloop_sock_table_set_fds(&eloop.writers, wfds); - eloop_sock_table_set_fds(&eloop.exceptions, efds); - res = select(eloop.max_sock + 1, rfds, wfds, efds, - eloop.timeout ? &_tv : NULL); - if (res < 0 && errno != EINTR && errno != 0) { - perror("select"); - goto out; - } - eloop_process_pending_signals(); - - /* check if some registered timeouts have occurred */ - if (eloop.timeout) { - struct eloop_timeout *tmp; - - os_get_time(&now); - if (!os_time_before(&now, &eloop.timeout->time)) { - tmp = eloop.timeout; - eloop.timeout = eloop.timeout->next; - tmp->handler(tmp->eloop_data, - tmp->user_data); - os_free(tmp); - } - - } - - if (res <= 0) - continue; - - eloop_sock_table_dispatch(&eloop.readers, rfds); - eloop_sock_table_dispatch(&eloop.writers, wfds); - eloop_sock_table_dispatch(&eloop.exceptions, efds); - } - -out: - os_free(rfds); - os_free(wfds); - os_free(efds); -} - - -void eloop_terminate(void) -{ - eloop.terminate = 1; -} - - -void eloop_destroy(void) -{ - struct eloop_timeout *timeout, *prev; - struct os_time now; - - timeout = eloop.timeout; - if (timeout) - os_get_time(&now); - while (timeout != NULL) { - int sec, usec; - prev = timeout; - timeout = timeout->next; - sec = prev->time.sec - now.sec; - usec = prev->time.usec - now.usec; - if (prev->time.usec < now.usec) { - sec--; - usec += 1000000; - } - printf("ELOOP: remaining timeout: %d.%06d eloop_data=%p " - "user_data=%p handler=%p\n", - sec, usec, prev->eloop_data, prev->user_data, - prev->handler); - os_free(prev); - } - eloop_sock_table_destroy(&eloop.readers); - eloop_sock_table_destroy(&eloop.writers); - eloop_sock_table_destroy(&eloop.exceptions); - os_free(eloop.signals); -} - - -int eloop_terminated(void) -{ - return eloop.terminate; -} - - -void eloop_wait_for_read_sock(int sock) -{ - fd_set rfds; - - if (sock < 0) - return; - - FD_ZERO(&rfds); - FD_SET(sock, &rfds); - select(sock + 1, &rfds, NULL, NULL, NULL); -} - - -void * eloop_get_user_data(void) -{ - return eloop.user_data; -} diff --git a/contrib/hostapd/src/utils/eloop.h b/contrib/hostapd/src/utils/eloop.h deleted file mode 100644 index cf83f38365..0000000000 --- a/contrib/hostapd/src/utils/eloop.h +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Event loop - * Copyright (c) 2002-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file defines an event loop interface that supports processing events - * from registered timeouts (i.e., do something after N seconds), sockets - * (e.g., a new packet available for reading), and signals. eloop.c is an - * implementation of this interface using select() and sockets. This is - * suitable for most UNIX/POSIX systems. When porting to other operating - * systems, it may be necessary to replace that implementation with OS specific - * mechanisms. - */ - -#ifndef ELOOP_H -#define ELOOP_H - -/** - * ELOOP_ALL_CTX - eloop_cancel_timeout() magic number to match all timeouts - */ -#define ELOOP_ALL_CTX (void *) -1 - -/** - * eloop_event_type - eloop socket event type for eloop_register_sock() - * @EVENT_TYPE_READ: Socket has data available for reading - * @EVENT_TYPE_WRITE: Socket has room for new data to be written - * @EVENT_TYPE_EXCEPTION: An exception has been reported - */ -typedef enum { - EVENT_TYPE_READ = 0, - EVENT_TYPE_WRITE, - EVENT_TYPE_EXCEPTION -} eloop_event_type; - -/** - * eloop_sock_handler - eloop socket event callback type - * @sock: File descriptor number for the socket - * @eloop_ctx: Registered callback context data (eloop_data) - * @sock_ctx: Registered callback context data (user_data) - */ -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) - */ -typedef void (*eloop_event_handler)(void *eloop_data, 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) - */ -typedef void (*eloop_timeout_handler)(void *eloop_data, void *user_ctx); - -/** - * eloop_signal_handler - eloop signal event callback type - * @sig: Signal number - * @eloop_ctx: Registered callback context data (global user_data from - * eloop_init() call) - * @signal_ctx: Registered callback context data (user_data from - * eloop_register_signal(), eloop_register_signal_terminate(), or - * eloop_register_signal_reconfig() call) - */ -typedef void (*eloop_signal_handler)(int sig, void *eloop_ctx, - void *signal_ctx); - -/** - * eloop_init() - Initialize global event loop data - * @user_data: Pointer to global data passed as eloop_ctx to signal handlers - * Returns: 0 on success, -1 on failure - * - * This function must be called before any other eloop_* function. user_data - * can be used to configure a global (to the process) pointer that will be - * passed as eloop_ctx parameter to signal handlers. - */ -int eloop_init(void *user_data); - -/** - * eloop_register_read_sock - Register handler for read events - * @sock: File descriptor number for the socket - * @handler: Callback function to be called when data is available for reading - * @eloop_data: Callback context data (eloop_ctx) - * @user_data: Callback context data (sock_ctx) - * Returns: 0 on success, -1 on failure - * - * Register a read socket notifier for the given file descriptor. The handler - * function will be called whenever data is available for reading from the - * socket. The handler function is responsible for clearing the event after - * having processed it in order to avoid eloop from calling the handler again - * for the same event. - */ -int eloop_register_read_sock(int sock, eloop_sock_handler handler, - void *eloop_data, void *user_data); - -/** - * eloop_unregister_read_sock - Unregister handler for read events - * @sock: File descriptor number for the socket - * - * Unregister a read socket notifier that was previously registered with - * eloop_register_read_sock(). - */ -void eloop_unregister_read_sock(int sock); - -/** - * eloop_register_sock - Register handler for socket events - * @sock: File descriptor number for the socket - * @type: Type of event to wait for - * @handler: Callback function to be called when the event is triggered - * @eloop_data: Callback context data (eloop_ctx) - * @user_data: Callback context data (sock_ctx) - * Returns: 0 on success, -1 on failure - * - * Register an event notifier for the given socket's file descriptor. The - * handler function will be called whenever the that event is triggered for the - * socket. The handler function is responsible for clearing the event after - * having processed it in order to avoid eloop from calling the handler again - * for the same event. - */ -int eloop_register_sock(int sock, eloop_event_type type, - eloop_sock_handler handler, - void *eloop_data, void *user_data); - -/** - * eloop_unregister_sock - Unregister handler for socket events - * @sock: File descriptor number for the socket - * @type: Type of event for which sock was registered - * - * Unregister a socket event notifier that was previously registered with - * eloop_register_sock(). - */ -void eloop_unregister_sock(int sock, eloop_event_type type); - -/** - * eloop_register_event - Register handler for generic events - * @event: Event to wait (eloop implementation specific) - * @event_size: Size of event data - * @handler: Callback function to be called when event is triggered - * @eloop_data: Callback context data (eloop_data) - * @user_data: Callback context data (user_data) - * Returns: 0 on success, -1 on failure - * - * Register an event handler for the given event. This function is used to - * register eloop implementation specific events which are mainly targetted for - * operating system specific code (driver interface and l2_packet) since the - * portable code will not be able to use such an OS-specific call. The handler - * function will be called whenever the event is triggered. The handler - * function is responsible for clearing the event after having processed it in - * order to avoid eloop from calling the handler again for the same event. - * - * In case of Windows implementation (eloop_win.c), event pointer is of HANDLE - * type, i.e., void*. The callers are likely to have 'HANDLE h' type variable, - * and they would call this function with eloop_register_event(h, sizeof(h), - * ...). - */ -int eloop_register_event(void *event, size_t event_size, - eloop_event_handler handler, - void *eloop_data, void *user_data); - -/** - * eloop_unregister_event - Unregister handler for a generic event - * @event: Event to cancel (eloop implementation specific) - * @event_size: Size of event data - * - * Unregister a generic event notifier that was previously registered with - * eloop_register_event(). - */ -void eloop_unregister_event(void *event, size_t event_size); - -/** - * eloop_register_timeout - Register timeout - * @secs: Number of seconds to the timeout - * @usecs: Number of microseconds to the timeout - * @handler: Callback function to be called when timeout occurs - * @eloop_data: Callback context data (eloop_ctx) - * @user_data: Callback context data (sock_ctx) - * Returns: 0 on success, -1 on failure - * - * Register a timeout that will cause the handler function to be called after - * given time. - */ -int eloop_register_timeout(unsigned int secs, unsigned int usecs, - eloop_timeout_handler handler, - void *eloop_data, void *user_data); - -/** - * eloop_cancel_timeout - Cancel timeouts - * @handler: Matching callback function - * @eloop_data: Matching eloop_data or %ELOOP_ALL_CTX to match all - * @user_data: Matching user_data or %ELOOP_ALL_CTX to match all - * Returns: Number of cancelled timeouts - * - * Cancel matching timeouts registered with - * eloop_register_timeout(). ELOOP_ALL_CTX can be used as a wildcard for - * cancelling all timeouts regardless of eloop_data/user_data. - */ -int eloop_cancel_timeout(eloop_timeout_handler handler, - void *eloop_data, void *user_data); - -/** - * eloop_is_timeout_registered - Check if a timeout is already registered - * @handler: Matching callback function - * @eloop_data: Matching eloop_data - * @user_data: Matching user_data - * Returns: 1 if the timeout is registered, 0 if the timeout is not registered - * - * Determine if a matching timeout is registered - * with eloop_register_timeout(). - */ -int eloop_is_timeout_registered(eloop_timeout_handler handler, - void *eloop_data, void *user_data); - -/** - * eloop_register_signal - Register handler for signals - * @sig: Signal number (e.g., SIGHUP) - * @handler: Callback function to be called when the signal is received - * @user_data: Callback context data (signal_ctx) - * Returns: 0 on success, -1 on failure - * - * Register a callback function that will be called when a signal is received. - * The callback function is actually called only after the system signal - * handler has returned. This means that the normal limits for sighandlers - * (i.e., only "safe functions" allowed) do not apply for the registered - * callback. - * - * Signals are 'global' events and there is no local eloop_data pointer like - * with other handlers. The global user_data pointer registered with - * eloop_init() will be used as eloop_ctx for signal handlers. - */ -int eloop_register_signal(int sig, eloop_signal_handler handler, - void *user_data); - -/** - * eloop_register_signal_terminate - Register handler for terminate signals - * @handler: Callback function to be called when the signal is received - * @user_data: Callback context data (signal_ctx) - * Returns: 0 on success, -1 on failure - * - * Register a callback function that will be called when a process termination - * signal is received. The callback function is actually called only after the - * system signal handler has returned. This means that the normal limits for - * sighandlers (i.e., only "safe functions" allowed) do not apply for the - * registered callback. - * - * Signals are 'global' events and there is no local eloop_data pointer like - * with other handlers. The global user_data pointer registered with - * eloop_init() will be used as eloop_ctx for signal handlers. - * - * This function is a more portable version of eloop_register_signal() since - * the knowledge of exact details of the signals is hidden in eloop - * implementation. In case of operating systems using signal(), this function - * registers handlers for SIGINT and SIGTERM. - */ -int eloop_register_signal_terminate(eloop_signal_handler handler, - void *user_data); - -/** - * eloop_register_signal_reconfig - Register handler for reconfig signals - * @handler: Callback function to be called when the signal is received - * @user_data: Callback context data (signal_ctx) - * Returns: 0 on success, -1 on failure - * - * Register a callback function that will be called when a reconfiguration / - * hangup signal is received. The callback function is actually called only - * after the system signal handler has returned. This means that the normal - * limits for sighandlers (i.e., only "safe functions" allowed) do not apply - * for the registered callback. - * - * Signals are 'global' events and there is no local eloop_data pointer like - * with other handlers. The global user_data pointer registered with - * eloop_init() will be used as eloop_ctx for signal handlers. - * - * This function is a more portable version of eloop_register_signal() since - * the knowledge of exact details of the signals is hidden in eloop - * implementation. In case of operating systems using signal(), this function - * registers a handler for SIGHUP. - */ -int eloop_register_signal_reconfig(eloop_signal_handler handler, - void *user_data); - -/** - * eloop_run - Start the event loop - * - * Start the event loop and continue running as long as there are any - * registered event handlers. This function is run after event loop has been - * initialized with event_init() and one or more events have been registered. - */ -void eloop_run(void); - -/** - * eloop_terminate - Terminate event loop - * - * Terminate event loop even if there are registered events. This can be used - * to request the program to be terminated cleanly. - */ -void eloop_terminate(void); - -/** - * eloop_destroy - Free any resources allocated for the event loop - * - * After calling eloop_destroy(), other eloop_* functions must not be called - * before re-running eloop_init(). - */ -void eloop_destroy(void); - -/** - * eloop_terminated - Check whether event loop has been terminated - * Returns: 1 = event loop terminate, 0 = event loop still running - * - * This function can be used to check whether eloop_terminate() has been called - * to request termination of the event loop. This is normally used to abort - * operations that may still be queued to be run when eloop_terminate() was - * called. - */ -int eloop_terminated(void); - -/** - * eloop_wait_for_read_sock - Wait for a single reader - * @sock: File descriptor number for the socket - * - * Do a blocking wait for a single read socket. - */ -void eloop_wait_for_read_sock(int sock); - -/** - * eloop_get_user_data - Get global user data - * Returns: user_data pointer that was registered with eloop_init() - */ -void * eloop_get_user_data(void); - -#endif /* ELOOP_H */ diff --git a/contrib/hostapd/src/utils/eloop_none.c b/contrib/hostapd/src/utils/eloop_none.c deleted file mode 100644 index 215030b213..0000000000 --- a/contrib/hostapd/src/utils/eloop_none.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Event loop - empty template (basic structure, but no OS specific operations) - * Copyright (c) 2002-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eloop.h" - - -struct eloop_sock { - int sock; - void *eloop_data; - void *user_data; - void (*handler)(int sock, void *eloop_ctx, void *sock_ctx); -}; - -struct eloop_timeout { - struct os_time time; - void *eloop_data; - void *user_data; - void (*handler)(void *eloop_ctx, void *sock_ctx); - struct eloop_timeout *next; -}; - -struct eloop_signal { - int sig; - void *user_data; - void (*handler)(int sig, void *eloop_ctx, void *signal_ctx); - int signaled; -}; - -struct eloop_data { - void *user_data; - - int max_sock, reader_count; - struct eloop_sock *readers; - - struct eloop_timeout *timeout; - - int signal_count; - struct eloop_signal *signals; - int signaled; - int pending_terminate; - - int terminate; - int reader_table_changed; -}; - -static struct eloop_data eloop; - - -int eloop_init(void *user_data) -{ - memset(&eloop, 0, sizeof(eloop)); - eloop.user_data = user_data; - return 0; -} - - -int eloop_register_read_sock(int sock, - void (*handler)(int sock, void *eloop_ctx, - void *sock_ctx), - void *eloop_data, void *user_data) -{ - struct eloop_sock *tmp; - - tmp = (struct eloop_sock *) - realloc(eloop.readers, - (eloop.reader_count + 1) * sizeof(struct eloop_sock)); - if (tmp == NULL) - return -1; - - tmp[eloop.reader_count].sock = sock; - tmp[eloop.reader_count].eloop_data = eloop_data; - tmp[eloop.reader_count].user_data = user_data; - tmp[eloop.reader_count].handler = handler; - eloop.reader_count++; - eloop.readers = tmp; - if (sock > eloop.max_sock) - eloop.max_sock = sock; - eloop.reader_table_changed = 1; - - return 0; -} - - -void eloop_unregister_read_sock(int sock) -{ - int i; - - if (eloop.readers == NULL || eloop.reader_count == 0) - return; - - for (i = 0; i < eloop.reader_count; i++) { - if (eloop.readers[i].sock == sock) - break; - } - if (i == eloop.reader_count) - return; - if (i != eloop.reader_count - 1) { - memmove(&eloop.readers[i], &eloop.readers[i + 1], - (eloop.reader_count - i - 1) * - sizeof(struct eloop_sock)); - } - eloop.reader_count--; - eloop.reader_table_changed = 1; -} - - -int eloop_register_timeout(unsigned int secs, unsigned int usecs, - void (*handler)(void *eloop_ctx, void *timeout_ctx), - void *eloop_data, void *user_data) -{ - struct eloop_timeout *timeout, *tmp, *prev; - - timeout = (struct eloop_timeout *) malloc(sizeof(*timeout)); - if (timeout == NULL) - return -1; - os_get_time(&timeout->time); - timeout->time.sec += secs; - timeout->time.usec += usecs; - while (timeout->time.usec >= 1000000) { - timeout->time.sec++; - timeout->time.usec -= 1000000; - } - timeout->eloop_data = eloop_data; - timeout->user_data = user_data; - timeout->handler = handler; - timeout->next = NULL; - - if (eloop.timeout == NULL) { - eloop.timeout = timeout; - return 0; - } - - prev = NULL; - tmp = eloop.timeout; - while (tmp != NULL) { - if (os_time_before(&timeout->time, &tmp->time)) - break; - prev = tmp; - tmp = tmp->next; - } - - if (prev == NULL) { - timeout->next = eloop.timeout; - eloop.timeout = timeout; - } else { - timeout->next = prev->next; - prev->next = timeout; - } - - return 0; -} - - -int eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx), - void *eloop_data, void *user_data) -{ - struct eloop_timeout *timeout, *prev, *next; - int removed = 0; - - prev = NULL; - timeout = eloop.timeout; - while (timeout != NULL) { - next = timeout->next; - - if (timeout->handler == handler && - (timeout->eloop_data == eloop_data || - eloop_data == ELOOP_ALL_CTX) && - (timeout->user_data == user_data || - user_data == ELOOP_ALL_CTX)) { - if (prev == NULL) - eloop.timeout = next; - else - prev->next = next; - free(timeout); - removed++; - } else - prev = timeout; - - timeout = next; - } - - return removed; -} - - -int eloop_is_timeout_registered(void (*handler)(void *eloop_ctx, - void *timeout_ctx), - void *eloop_data, void *user_data) -{ - struct eloop_timeout *tmp; - - tmp = eloop.timeout; - while (tmp != NULL) { - if (tmp->handler == handler && - tmp->eloop_data == eloop_data && - tmp->user_data == user_data) - return 1; - - tmp = tmp->next; - } - - return 0; -} - - -/* TODO: replace with suitable signal handler */ -#if 0 -static void eloop_handle_signal(int sig) -{ - int i; - - eloop.signaled++; - for (i = 0; i < eloop.signal_count; i++) { - if (eloop.signals[i].sig == sig) { - eloop.signals[i].signaled++; - break; - } - } -} -#endif - - -static void eloop_process_pending_signals(void) -{ - int i; - - if (eloop.signaled == 0) - return; - eloop.signaled = 0; - - if (eloop.pending_terminate) { - eloop.pending_terminate = 0; - } - - for (i = 0; i < eloop.signal_count; i++) { - if (eloop.signals[i].signaled) { - eloop.signals[i].signaled = 0; - eloop.signals[i].handler(eloop.signals[i].sig, - eloop.user_data, - eloop.signals[i].user_data); - } - } -} - - -int eloop_register_signal(int sig, - void (*handler)(int sig, void *eloop_ctx, - void *signal_ctx), - void *user_data) -{ - struct eloop_signal *tmp; - - tmp = (struct eloop_signal *) - realloc(eloop.signals, - (eloop.signal_count + 1) * - sizeof(struct eloop_signal)); - if (tmp == NULL) - return -1; - - tmp[eloop.signal_count].sig = sig; - tmp[eloop.signal_count].user_data = user_data; - tmp[eloop.signal_count].handler = handler; - tmp[eloop.signal_count].signaled = 0; - eloop.signal_count++; - eloop.signals = tmp; - - /* TODO: register signal handler */ - - return 0; -} - - -int eloop_register_signal_terminate(void (*handler)(int sig, void *eloop_ctx, - void *signal_ctx), - void *user_data) -{ -#if 0 - /* TODO: for example */ - int ret = eloop_register_signal(SIGINT, handler, user_data); - if (ret == 0) - ret = eloop_register_signal(SIGTERM, handler, user_data); - return ret; -#endif - return 0; -} - - -int eloop_register_signal_reconfig(void (*handler)(int sig, void *eloop_ctx, - void *signal_ctx), - void *user_data) -{ -#if 0 - /* TODO: for example */ - return eloop_register_signal(SIGHUP, handler, user_data); -#endif - return 0; -} - - -void eloop_run(void) -{ - int i; - struct os_time tv, now; - - while (!eloop.terminate && - (eloop.timeout || eloop.reader_count > 0)) { - if (eloop.timeout) { - os_get_time(&now); - if (os_time_before(&now, &eloop.timeout->time)) - os_time_sub(&eloop.timeout->time, &now, &tv); - else - tv.sec = tv.usec = 0; - } - - /* - * TODO: wait for any event (read socket ready, timeout (tv), - * signal - */ - os_sleep(1, 0); /* just a dummy wait for testing */ - - eloop_process_pending_signals(); - - /* check if some registered timeouts have occurred */ - if (eloop.timeout) { - struct eloop_timeout *tmp; - - os_get_time(&now); - if (!os_time_before(&now, &eloop.timeout->time)) { - tmp = eloop.timeout; - eloop.timeout = eloop.timeout->next; - tmp->handler(tmp->eloop_data, - tmp->user_data); - free(tmp); - } - - } - - eloop.reader_table_changed = 0; - for (i = 0; i < eloop.reader_count; i++) { - /* - * TODO: call each handler that has pending data to - * read - */ - if (0 /* TODO: eloop.readers[i].sock ready */) { - eloop.readers[i].handler( - eloop.readers[i].sock, - eloop.readers[i].eloop_data, - eloop.readers[i].user_data); - if (eloop.reader_table_changed) - break; - } - } - } -} - - -void eloop_terminate(void) -{ - eloop.terminate = 1; -} - - -void eloop_destroy(void) -{ - struct eloop_timeout *timeout, *prev; - - timeout = eloop.timeout; - while (timeout != NULL) { - prev = timeout; - timeout = timeout->next; - free(prev); - } - free(eloop.readers); - free(eloop.signals); -} - - -int eloop_terminated(void) -{ - return eloop.terminate; -} - - -void eloop_wait_for_read_sock(int sock) -{ - /* - * TODO: wait for the file descriptor to have something available for - * reading - */ -} - - -void * eloop_get_user_data(void) -{ - return eloop.user_data; -} diff --git a/contrib/hostapd/src/utils/eloop_win.c b/contrib/hostapd/src/utils/eloop_win.c deleted file mode 100644 index c95aa76b78..0000000000 --- a/contrib/hostapd/src/utils/eloop_win.c +++ /dev/null @@ -1,622 +0,0 @@ -/* - * Event loop based on Windows events and WaitForMultipleObjects - * Copyright (c) 2002-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "eloop.h" - - -struct eloop_sock { - int sock; - void *eloop_data; - void *user_data; - eloop_sock_handler handler; - WSAEVENT event; -}; - -struct eloop_event { - void *eloop_data; - void *user_data; - eloop_event_handler handler; - HANDLE event; -}; - -struct eloop_timeout { - struct os_time time; - void *eloop_data; - void *user_data; - eloop_timeout_handler handler; - struct eloop_timeout *next; -}; - -struct eloop_signal { - int sig; - void *user_data; - eloop_signal_handler handler; - int signaled; -}; - -struct eloop_data { - void *user_data; - - int max_sock; - size_t reader_count; - struct eloop_sock *readers; - - size_t event_count; - struct eloop_event *events; - - struct eloop_timeout *timeout; - - int signal_count; - struct eloop_signal *signals; - int signaled; - int pending_terminate; - - int terminate; - int reader_table_changed; - - struct eloop_signal term_signal; - HANDLE term_event; - - HANDLE *handles; - size_t num_handles; -}; - -static struct eloop_data eloop; - - -int eloop_init(void *user_data) -{ - os_memset(&eloop, 0, sizeof(eloop)); - eloop.user_data = user_data; - eloop.num_handles = 1; - eloop.handles = os_malloc(eloop.num_handles * - sizeof(eloop.handles[0])); - if (eloop.handles == NULL) - return -1; - - eloop.term_event = CreateEvent(NULL, FALSE, FALSE, NULL); - if (eloop.term_event == NULL) { - printf("CreateEvent() failed: %d\n", - (int) GetLastError()); - os_free(eloop.handles); - return -1; - } - - return 0; -} - - -static int eloop_prepare_handles(void) -{ - HANDLE *n; - - if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8) - return 0; - n = os_realloc(eloop.handles, - eloop.num_handles * 2 * sizeof(eloop.handles[0])); - if (n == NULL) - return -1; - eloop.handles = n; - eloop.num_handles *= 2; - return 0; -} - - -int eloop_register_read_sock(int sock, eloop_sock_handler handler, - void *eloop_data, void *user_data) -{ - WSAEVENT event; - struct eloop_sock *tmp; - - if (eloop_prepare_handles()) - return -1; - - event = WSACreateEvent(); - if (event == WSA_INVALID_EVENT) { - printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); - return -1; - } - - if (WSAEventSelect(sock, event, FD_READ)) { - printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); - WSACloseEvent(event); - return -1; - } - tmp = os_realloc(eloop.readers, - (eloop.reader_count + 1) * sizeof(struct eloop_sock)); - if (tmp == NULL) { - WSAEventSelect(sock, event, 0); - WSACloseEvent(event); - return -1; - } - - tmp[eloop.reader_count].sock = sock; - tmp[eloop.reader_count].eloop_data = eloop_data; - tmp[eloop.reader_count].user_data = user_data; - tmp[eloop.reader_count].handler = handler; - tmp[eloop.reader_count].event = event; - eloop.reader_count++; - eloop.readers = tmp; - if (sock > eloop.max_sock) - eloop.max_sock = sock; - eloop.reader_table_changed = 1; - - return 0; -} - - -void eloop_unregister_read_sock(int sock) -{ - size_t i; - - if (eloop.readers == NULL || eloop.reader_count == 0) - return; - - for (i = 0; i < eloop.reader_count; i++) { - if (eloop.readers[i].sock == sock) - break; - } - if (i == eloop.reader_count) - return; - - WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0); - WSACloseEvent(eloop.readers[i].event); - - if (i != eloop.reader_count - 1) { - os_memmove(&eloop.readers[i], &eloop.readers[i + 1], - (eloop.reader_count - i - 1) * - sizeof(struct eloop_sock)); - } - eloop.reader_count--; - eloop.reader_table_changed = 1; -} - - -int eloop_register_event(void *event, size_t event_size, - eloop_event_handler handler, - void *eloop_data, void *user_data) -{ - struct eloop_event *tmp; - HANDLE h = event; - - if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE) - return -1; - - if (eloop_prepare_handles()) - return -1; - - tmp = os_realloc(eloop.events, - (eloop.event_count + 1) * sizeof(struct eloop_event)); - if (tmp == NULL) - return -1; - - tmp[eloop.event_count].eloop_data = eloop_data; - tmp[eloop.event_count].user_data = user_data; - tmp[eloop.event_count].handler = handler; - tmp[eloop.event_count].event = h; - eloop.event_count++; - eloop.events = tmp; - - return 0; -} - - -void eloop_unregister_event(void *event, size_t event_size) -{ - size_t i; - HANDLE h = event; - - if (eloop.events == NULL || eloop.event_count == 0 || - event_size != sizeof(HANDLE)) - return; - - for (i = 0; i < eloop.event_count; i++) { - if (eloop.events[i].event == h) - break; - } - if (i == eloop.event_count) - return; - - if (i != eloop.event_count - 1) { - os_memmove(&eloop.events[i], &eloop.events[i + 1], - (eloop.event_count - i - 1) * - sizeof(struct eloop_event)); - } - eloop.event_count--; -} - - -int eloop_register_timeout(unsigned int secs, unsigned int usecs, - eloop_timeout_handler handler, - void *eloop_data, void *user_data) -{ - struct eloop_timeout *timeout, *tmp, *prev; - - timeout = os_malloc(sizeof(*timeout)); - if (timeout == NULL) - return -1; - os_get_time(&timeout->time); - timeout->time.sec += secs; - timeout->time.usec += usecs; - while (timeout->time.usec >= 1000000) { - timeout->time.sec++; - timeout->time.usec -= 1000000; - } - timeout->eloop_data = eloop_data; - timeout->user_data = user_data; - timeout->handler = handler; - timeout->next = NULL; - - if (eloop.timeout == NULL) { - eloop.timeout = timeout; - return 0; - } - - prev = NULL; - tmp = eloop.timeout; - while (tmp != NULL) { - if (os_time_before(&timeout->time, &tmp->time)) - break; - prev = tmp; - tmp = tmp->next; - } - - if (prev == NULL) { - timeout->next = eloop.timeout; - eloop.timeout = timeout; - } else { - timeout->next = prev->next; - prev->next = timeout; - } - - return 0; -} - - -int eloop_cancel_timeout(eloop_timeout_handler handler, - void *eloop_data, void *user_data) -{ - struct eloop_timeout *timeout, *prev, *next; - int removed = 0; - - prev = NULL; - timeout = eloop.timeout; - while (timeout != NULL) { - next = timeout->next; - - if (timeout->handler == handler && - (timeout->eloop_data == eloop_data || - eloop_data == ELOOP_ALL_CTX) && - (timeout->user_data == user_data || - user_data == ELOOP_ALL_CTX)) { - if (prev == NULL) - eloop.timeout = next; - else - prev->next = next; - os_free(timeout); - removed++; - } else - prev = timeout; - - timeout = next; - } - - return removed; -} - - -int eloop_is_timeout_registered(eloop_timeout_handler handler, - void *eloop_data, void *user_data) -{ - struct eloop_timeout *tmp; - - tmp = eloop.timeout; - while (tmp != NULL) { - if (tmp->handler == handler && - tmp->eloop_data == eloop_data && - tmp->user_data == user_data) - return 1; - - tmp = tmp->next; - } - - return 0; -} - - -/* TODO: replace with suitable signal handler */ -#if 0 -static void eloop_handle_signal(int sig) -{ - int i; - - eloop.signaled++; - for (i = 0; i < eloop.signal_count; i++) { - if (eloop.signals[i].sig == sig) { - eloop.signals[i].signaled++; - break; - } - } -} -#endif - - -static void eloop_process_pending_signals(void) -{ - int i; - - if (eloop.signaled == 0) - return; - eloop.signaled = 0; - - if (eloop.pending_terminate) { - eloop.pending_terminate = 0; - } - - for (i = 0; i < eloop.signal_count; i++) { - if (eloop.signals[i].signaled) { - eloop.signals[i].signaled = 0; - eloop.signals[i].handler(eloop.signals[i].sig, - eloop.user_data, - eloop.signals[i].user_data); - } - } - - if (eloop.term_signal.signaled) { - eloop.term_signal.signaled = 0; - eloop.term_signal.handler(eloop.term_signal.sig, - eloop.user_data, - eloop.term_signal.user_data); - } -} - - -int eloop_register_signal(int sig, eloop_signal_handler handler, - void *user_data) -{ - struct eloop_signal *tmp; - - tmp = os_realloc(eloop.signals, - (eloop.signal_count + 1) * - sizeof(struct eloop_signal)); - if (tmp == NULL) - return -1; - - tmp[eloop.signal_count].sig = sig; - tmp[eloop.signal_count].user_data = user_data; - tmp[eloop.signal_count].handler = handler; - tmp[eloop.signal_count].signaled = 0; - eloop.signal_count++; - eloop.signals = tmp; - - /* TODO: register signal handler */ - - return 0; -} - - -#ifndef _WIN32_WCE -static BOOL eloop_handle_console_ctrl(DWORD type) -{ - switch (type) { - case CTRL_C_EVENT: - case CTRL_BREAK_EVENT: - eloop.signaled++; - eloop.term_signal.signaled++; - SetEvent(eloop.term_event); - return TRUE; - default: - return FALSE; - } -} -#endif /* _WIN32_WCE */ - - -int eloop_register_signal_terminate(eloop_signal_handler handler, - void *user_data) -{ -#ifndef _WIN32_WCE - if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl, - TRUE) == 0) { - printf("SetConsoleCtrlHandler() failed: %d\n", - (int) GetLastError()); - return -1; - } -#endif /* _WIN32_WCE */ - - eloop.term_signal.handler = handler; - eloop.term_signal.user_data = user_data; - - return 0; -} - - -int eloop_register_signal_reconfig(eloop_signal_handler handler, - void *user_data) -{ - /* TODO */ - return 0; -} - - -void eloop_run(void) -{ - struct os_time tv, now; - DWORD count, ret, timeout, err; - size_t i; - - while (!eloop.terminate && - (eloop.timeout || eloop.reader_count > 0 || - eloop.event_count > 0)) { - tv.sec = tv.usec = 0; - if (eloop.timeout) { - os_get_time(&now); - if (os_time_before(&now, &eloop.timeout->time)) - os_time_sub(&eloop.timeout->time, &now, &tv); - } - - count = 0; - for (i = 0; i < eloop.event_count; i++) - eloop.handles[count++] = eloop.events[i].event; - - for (i = 0; i < eloop.reader_count; i++) - eloop.handles[count++] = eloop.readers[i].event; - - if (eloop.term_event) - eloop.handles[count++] = eloop.term_event; - - if (eloop.timeout) - timeout = tv.sec * 1000 + tv.usec / 1000; - else - timeout = INFINITE; - - if (count > MAXIMUM_WAIT_OBJECTS) { - printf("WaitForMultipleObjects: Too many events: " - "%d > %d (ignoring extra events)\n", - (int) count, MAXIMUM_WAIT_OBJECTS); - count = MAXIMUM_WAIT_OBJECTS; - } -#ifdef _WIN32_WCE - ret = WaitForMultipleObjects(count, eloop.handles, FALSE, - timeout); -#else /* _WIN32_WCE */ - ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE, - timeout, TRUE); -#endif /* _WIN32_WCE */ - err = GetLastError(); - - eloop_process_pending_signals(); - - /* check if some registered timeouts have occurred */ - if (eloop.timeout) { - struct eloop_timeout *tmp; - - os_get_time(&now); - if (!os_time_before(&now, &eloop.timeout->time)) { - tmp = eloop.timeout; - eloop.timeout = eloop.timeout->next; - tmp->handler(tmp->eloop_data, - tmp->user_data); - os_free(tmp); - } - - } - - if (ret == WAIT_FAILED) { - printf("WaitForMultipleObjects(count=%d) failed: %d\n", - (int) count, (int) err); - os_sleep(1, 0); - continue; - } - -#ifndef _WIN32_WCE - if (ret == WAIT_IO_COMPLETION) - continue; -#endif /* _WIN32_WCE */ - - if (ret == WAIT_TIMEOUT) - continue; - - while (ret >= WAIT_OBJECT_0 && - ret < WAIT_OBJECT_0 + eloop.event_count) { - eloop.events[ret].handler( - eloop.events[ret].eloop_data, - eloop.events[ret].user_data); - ret = WaitForMultipleObjects(eloop.event_count, - eloop.handles, FALSE, 0); - } - - eloop.reader_table_changed = 0; - for (i = 0; i < eloop.reader_count; i++) { - WSANETWORKEVENTS events; - if (WSAEnumNetworkEvents(eloop.readers[i].sock, - eloop.readers[i].event, - &events) == 0 && - (events.lNetworkEvents & FD_READ)) { - eloop.readers[i].handler( - eloop.readers[i].sock, - eloop.readers[i].eloop_data, - eloop.readers[i].user_data); - if (eloop.reader_table_changed) - break; - } - } - } -} - - -void eloop_terminate(void) -{ - eloop.terminate = 1; - SetEvent(eloop.term_event); -} - - -void eloop_destroy(void) -{ - struct eloop_timeout *timeout, *prev; - - timeout = eloop.timeout; - while (timeout != NULL) { - prev = timeout; - timeout = timeout->next; - os_free(prev); - } - os_free(eloop.readers); - os_free(eloop.signals); - if (eloop.term_event) - CloseHandle(eloop.term_event); - os_free(eloop.handles); - eloop.handles = NULL; - os_free(eloop.events); - eloop.events = NULL; -} - - -int eloop_terminated(void) -{ - return eloop.terminate; -} - - -void eloop_wait_for_read_sock(int sock) -{ - WSAEVENT event; - - event = WSACreateEvent(); - if (event == WSA_INVALID_EVENT) { - printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); - return; - } - - if (WSAEventSelect(sock, event, FD_READ)) { - printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); - WSACloseEvent(event); - return ; - } - - WaitForSingleObject(event, INFINITE); - WSAEventSelect(sock, event, 0); - WSACloseEvent(event); -} - - -void * eloop_get_user_data(void) -{ - return eloop.user_data; -} diff --git a/contrib/hostapd/src/utils/includes.h b/contrib/hostapd/src/utils/includes.h deleted file mode 100644 index 63b5c23d84..0000000000 --- a/contrib/hostapd/src/utils/includes.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * wpa_supplicant/hostapd - Default include files - * Copyright (c) 2005-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This header file is included into all C files so that commonly used header - * files can be selected with OS specific ifdef blocks in one place instead of - * having to have OS/C library specific selection in many files. - */ - -#ifndef INCLUDES_H -#define INCLUDES_H - -/* Include possible build time configuration before including anything else */ -#include "build_config.h" - -#include -#include -#include -#include -#ifndef _WIN32_WCE -#ifndef CONFIG_TI_COMPILER -#include -#include -#endif /* CONFIG_TI_COMPILER */ -#include -#endif /* _WIN32_WCE */ -#include -#include - -#ifndef CONFIG_TI_COMPILER -#ifndef _MSC_VER -#include -#endif /* _MSC_VER */ -#endif /* CONFIG_TI_COMPILER */ - -#ifndef CONFIG_NATIVE_WINDOWS -#ifndef CONFIG_TI_COMPILER -#include -#include -#include -#ifndef __vxworks -#ifndef __SYMBIAN32__ -#include -#endif /* __SYMBIAN32__ */ -#include -#endif /* __vxworks */ -#endif /* CONFIG_TI_COMPILER */ -#endif /* CONFIG_NATIVE_WINDOWS */ - -#endif /* INCLUDES_H */ diff --git a/contrib/hostapd/src/utils/ip_addr.c b/contrib/hostapd/src/utils/ip_addr.c deleted file mode 100644 index 158fd57ed0..0000000000 --- a/contrib/hostapd/src/utils/ip_addr.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * IP address processing - * Copyright (c) 2003-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "ip_addr.h" - -const char * hostapd_ip_txt(const struct hostapd_ip_addr *addr, char *buf, - size_t buflen) -{ - if (buflen == 0 || addr == NULL) - return NULL; - - if (addr->af == AF_INET) { - os_strlcpy(buf, inet_ntoa(addr->u.v4), buflen); - } else { - buf[0] = '\0'; - } -#ifdef CONFIG_IPV6 - if (addr->af == AF_INET6) { - if (inet_ntop(AF_INET6, &addr->u.v6, buf, buflen) == NULL) - buf[0] = '\0'; - } -#endif /* CONFIG_IPV6 */ - - return buf; -} - - -int hostapd_ip_diff(struct hostapd_ip_addr *a, struct hostapd_ip_addr *b) -{ - if (a == NULL && b == NULL) - return 0; - if (a == NULL || b == NULL) - return 1; - - switch (a->af) { - case AF_INET: - if (a->u.v4.s_addr != b->u.v4.s_addr) - return 1; - break; -#ifdef CONFIG_IPV6 - case AF_INET6: - if (os_memcmp(&a->u.v6, &b->u.v6, sizeof(a->u.v6)) != 0) - return 1; - break; -#endif /* CONFIG_IPV6 */ - } - - return 0; -} - - -int hostapd_parse_ip_addr(const char *txt, struct hostapd_ip_addr *addr) -{ -#ifndef CONFIG_NATIVE_WINDOWS - if (inet_aton(txt, &addr->u.v4)) { - addr->af = AF_INET; - return 0; - } - -#ifdef CONFIG_IPV6 - if (inet_pton(AF_INET6, txt, &addr->u.v6) > 0) { - addr->af = AF_INET6; - return 0; - } -#endif /* CONFIG_IPV6 */ -#endif /* CONFIG_NATIVE_WINDOWS */ - - return -1; -} diff --git a/contrib/hostapd/src/utils/ip_addr.h b/contrib/hostapd/src/utils/ip_addr.h deleted file mode 100644 index 192049a583..0000000000 --- a/contrib/hostapd/src/utils/ip_addr.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * IP address processing - * Copyright (c) 2003-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IP_ADDR_H -#define IP_ADDR_H - -struct hostapd_ip_addr { - union { - struct in_addr v4; -#ifdef CONFIG_IPV6 - struct in6_addr v6; -#endif /* CONFIG_IPV6 */ - } u; - int af; /* AF_INET / AF_INET6 */ -}; - -const char * hostapd_ip_txt(const struct hostapd_ip_addr *addr, char *buf, - size_t buflen); -int hostapd_ip_diff(struct hostapd_ip_addr *a, struct hostapd_ip_addr *b); -int hostapd_parse_ip_addr(const char *txt, struct hostapd_ip_addr *addr); - -#endif /* IP_ADDR_H */ diff --git a/contrib/hostapd/src/utils/os.h b/contrib/hostapd/src/utils/os.h deleted file mode 100644 index d6dfea682c..0000000000 --- a/contrib/hostapd/src/utils/os.h +++ /dev/null @@ -1,501 +0,0 @@ -/* - * wpa_supplicant/hostapd / OS specific functions - * Copyright (c) 2005-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef OS_H -#define OS_H - -typedef long os_time_t; - -/** - * os_sleep - Sleep (sec, usec) - * @sec: Number of seconds to sleep - * @usec: Number of microseconds to sleep - */ -void os_sleep(os_time_t sec, os_time_t usec); - -struct os_time { - os_time_t sec; - os_time_t usec; -}; - -/** - * os_get_time - Get current time (sec, usec) - * @t: Pointer to buffer for the time - * Returns: 0 on success, -1 on failure - */ -int os_get_time(struct os_time *t); - - -/* Helper macros for handling struct os_time */ - -#define os_time_before(a, b) \ - ((a)->sec < (b)->sec || \ - ((a)->sec == (b)->sec && (a)->usec < (b)->usec)) - -#define os_time_sub(a, b, res) do { \ - (res)->sec = (a)->sec - (b)->sec; \ - (res)->usec = (a)->usec - (b)->usec; \ - if ((res)->usec < 0) { \ - (res)->sec--; \ - (res)->usec += 1000000; \ - } \ -} while (0) - -/** - * os_mktime - Convert broken-down time into seconds since 1970-01-01 - * @year: Four digit year - * @month: Month (1 .. 12) - * @day: Day of month (1 .. 31) - * @hour: Hour (0 .. 23) - * @min: Minute (0 .. 59) - * @sec: Second (0 .. 60) - * @t: Buffer for returning calendar time representation (seconds since - * 1970-01-01 00:00:00) - * Returns: 0 on success, -1 on failure - * - * Note: The result is in seconds from Epoch, i.e., in UTC, not in local time - * which is used by POSIX mktime(). - */ -int os_mktime(int year, int month, int day, int hour, int min, int sec, - os_time_t *t); - - -/** - * os_daemonize - Run in the background (detach from the controlling terminal) - * @pid_file: File name to write the process ID to or %NULL to skip this - * Returns: 0 on success, -1 on failure - */ -int os_daemonize(const char *pid_file); - -/** - * os_daemonize_terminate - Stop running in the background (remove pid file) - * @pid_file: File name to write the process ID to or %NULL to skip this - */ -void os_daemonize_terminate(const char *pid_file); - -/** - * os_get_random - Get cryptographically strong pseudo random data - * @buf: Buffer for pseudo random data - * @len: Length of the buffer - * Returns: 0 on success, -1 on failure - */ -int os_get_random(unsigned char *buf, size_t len); - -/** - * os_random - Get pseudo random value (not necessarily very strong) - * Returns: Pseudo random value - */ -unsigned long os_random(void); - -/** - * os_rel2abs_path - Get an absolute path for a file - * @rel_path: Relative path to a file - * Returns: Absolute path for the file or %NULL on failure - * - * This function tries to convert a relative path of a file to an absolute path - * in order for the file to be found even if current working directory has - * changed. The returned value is allocated and caller is responsible for - * freeing it. It is acceptable to just return the same path in an allocated - * buffer, e.g., return strdup(rel_path). This function is only used to find - * configuration files when os_daemonize() may have changed the current working - * directory and relative path would be pointing to a different location. - */ -char * os_rel2abs_path(const char *rel_path); - -/** - * os_program_init - Program initialization (called at start) - * Returns: 0 on success, -1 on failure - * - * This function is called when a programs starts. If there are any OS specific - * processing that is needed, it can be placed here. It is also acceptable to - * just return 0 if not special processing is needed. - */ -int os_program_init(void); - -/** - * os_program_deinit - Program deinitialization (called just before exit) - * - * This function is called just before a program exists. If there are any OS - * specific processing, e.g., freeing resourced allocated in os_program_init(), - * it should be done here. It is also acceptable for this function to do - * nothing. - */ -void os_program_deinit(void); - -/** - * os_setenv - Set environment variable - * @name: Name of the variable - * @value: Value to set to the variable - * @overwrite: Whether existing variable should be overwritten - * Returns: 0 on success, -1 on error - * - * This function is only used for wpa_cli action scripts. OS wrapper does not - * need to implement this if such functionality is not needed. - */ -int os_setenv(const char *name, const char *value, int overwrite); - -/** - * os_unsetenv - Delete environent variable - * @name: Name of the variable - * Returns: 0 on success, -1 on error - * - * This function is only used for wpa_cli action scripts. OS wrapper does not - * need to implement this if such functionality is not needed. - */ -int os_unsetenv(const char *name); - -/** - * os_readfile - Read a file to an allocated memory buffer - * @name: Name of the file to read - * @len: For returning the length of the allocated buffer - * Returns: Pointer to the allocated buffer or %NULL on failure - * - * This function allocates memory and reads the given file to this buffer. Both - * binary and text files can be read with this function. The caller is - * responsible for freeing the returned buffer with os_free(). - */ -char * os_readfile(const char *name, size_t *len); - -/** - * os_zalloc - Allocate and zero memory - * @size: Number of bytes to allocate - * Returns: Pointer to allocated and zeroed memory or %NULL on failure - * - * Caller is responsible for freeing the returned buffer with os_free(). - */ -void * os_zalloc(size_t size); - - -/* - * The following functions are wrapper for standard ANSI C or POSIX functions. - * By default, they are just defined to use the standard function name and no - * os_*.c implementation is needed for them. This avoids extra function calls - * by allowing the C pre-processor take care of the function name mapping. - * - * If the target system uses a C library that does not provide these functions, - * build_config.h can be used to define the wrappers to use a different - * function name. This can be done on function-by-function basis since the - * defines here are only used if build_config.h does not define the os_* name. - * If needed, os_*.c file can be used to implement the functions that are not - * included in the C library on the target system. Alternatively, - * OS_NO_C_LIB_DEFINES can be defined to skip all defines here in which case - * these functions need to be implemented in os_*.c file for the target system. - */ - -#ifdef OS_NO_C_LIB_DEFINES - -/** - * os_malloc - Allocate dynamic memory - * @size: Size of the buffer to allocate - * Returns: Allocated buffer or %NULL on failure - * - * Caller is responsible for freeing the returned buffer with os_free(). - */ -void * os_malloc(size_t size); - -/** - * os_realloc - Re-allocate dynamic memory - * @ptr: Old buffer from os_malloc() or os_realloc() - * @size: Size of the new buffer - * Returns: Allocated buffer or %NULL on failure - * - * Caller is responsible for freeing the returned buffer with os_free(). - * If re-allocation fails, %NULL is returned and the original buffer (ptr) is - * not freed and caller is still responsible for freeing it. - */ -void * os_realloc(void *ptr, size_t size); - -/** - * os_free - Free dynamic memory - * @ptr: Old buffer from os_malloc() or os_realloc(); can be %NULL - */ -void os_free(void *ptr); - -/** - * os_memcpy - Copy memory area - * @dest: Destination - * @src: Source - * @n: Number of bytes to copy - * Returns: dest - * - * The memory areas src and dst must not overlap. os_memmove() can be used with - * overlapping memory. - */ -void * os_memcpy(void *dest, const void *src, size_t n); - -/** - * os_memmove - Copy memory area - * @dest: Destination - * @src: Source - * @n: Number of bytes to copy - * Returns: dest - * - * The memory areas src and dst may overlap. - */ -void * os_memmove(void *dest, const void *src, size_t n); - -/** - * os_memset - Fill memory with a constant byte - * @s: Memory area to be filled - * @c: Constant byte - * @n: Number of bytes started from s to fill with c - * Returns: s - */ -void * os_memset(void *s, int c, size_t n); - -/** - * os_memcmp - Compare memory areas - * @s1: First buffer - * @s2: Second buffer - * @n: Maximum numbers of octets to compare - * Returns: An integer less than, equal to, or greater than zero if s1 is - * found to be less than, to match, or be greater than s2. Only first n - * characters will be compared. - */ -int os_memcmp(const void *s1, const void *s2, size_t n); - -/** - * os_strdup - Duplicate a string - * @s: Source string - * Returns: Allocated buffer with the string copied into it or %NULL on failure - * - * Caller is responsible for freeing the returned buffer with os_free(). - */ -char * os_strdup(const char *s); - -/** - * os_strlen - Calculate the length of a string - * @s: '\0' terminated string - * Returns: Number of characters in s (not counting the '\0' terminator) - */ -size_t os_strlen(const char *s); - -/** - * os_strcasecmp - Compare two strings ignoring case - * @s1: First string - * @s2: Second string - * Returns: An integer less than, equal to, or greater than zero if s1 is - * found to be less than, to match, or be greatred than s2 - */ -int os_strcasecmp(const char *s1, const char *s2); - -/** - * os_strncasecmp - Compare two strings ignoring case - * @s1: First string - * @s2: Second string - * @n: Maximum numbers of characters to compare - * Returns: An integer less than, equal to, or greater than zero if s1 is - * found to be less than, to match, or be greater than s2. Only first n - * characters will be compared. - */ -int os_strncasecmp(const char *s1, const char *s2, size_t n); - -/** - * os_strchr - Locate the first occurrence of a character in string - * @s: String - * @c: Character to search for - * Returns: Pointer to the matched character or %NULL if not found - */ -char * os_strchr(const char *s, int c); - -/** - * os_strrchr - Locate the last occurrence of a character in string - * @s: String - * @c: Character to search for - * Returns: Pointer to the matched character or %NULL if not found - */ -char * os_strrchr(const char *s, int c); - -/** - * os_strcmp - Compare two strings - * @s1: First string - * @s2: Second string - * Returns: An integer less than, equal to, or greater than zero if s1 is - * found to be less than, to match, or be greatred than s2 - */ -int os_strcmp(const char *s1, const char *s2); - -/** - * os_strncmp - Compare two strings - * @s1: First string - * @s2: Second string - * @n: Maximum numbers of characters to compare - * Returns: An integer less than, equal to, or greater than zero if s1 is - * found to be less than, to match, or be greater than s2. Only first n - * characters will be compared. - */ -int os_strncmp(const char *s1, const char *s2, size_t n); - -/** - * os_strncpy - Copy a string - * @dest: Destination - * @src: Source - * @n: Maximum number of characters to copy - * Returns: dest - */ -char * os_strncpy(char *dest, const char *src, size_t n); - -/** - * os_strstr - Locate a substring - * @haystack: String (haystack) to search from - * @needle: Needle to search from haystack - * Returns: Pointer to the beginning of the substring or %NULL if not found - */ -char * os_strstr(const char *haystack, const char *needle); - -/** - * os_snprintf - Print to a memory buffer - * @str: Memory buffer to print into - * @size: Maximum length of the str buffer - * @format: printf format - * Returns: Number of characters printed (not including trailing '\0'). - * - * If the output buffer is truncated, number of characters which would have - * been written is returned. Since some C libraries return -1 in such a case, - * the caller must be prepared on that value, too, to indicate truncation. - * - * Note: Some C library implementations of snprintf() may not guarantee null - * termination in case the output is truncated. The OS wrapper function of - * os_snprintf() should provide this guarantee, i.e., to null terminate the - * output buffer if a C library version of the function is used and if that - * function does not guarantee null termination. - * - * If the target system does not include snprintf(), see, e.g., - * http://www.ijs.si/software/snprintf/ for an example of a portable - * implementation of snprintf. - */ -int os_snprintf(char *str, size_t size, const char *format, ...); - -#else /* OS_NO_C_LIB_DEFINES */ - -#ifndef os_malloc -#define os_malloc(s) malloc((s)) -#endif -#ifndef os_realloc -#define os_realloc(p, s) realloc((p), (s)) -#endif -#ifndef os_free -#define os_free(p) free((p)) -#endif - -#ifndef os_memcpy -#define os_memcpy(d, s, n) memcpy((d), (s), (n)) -#endif -#ifndef os_memmove -#define os_memmove(d, s, n) memmove((d), (s), (n)) -#endif -#ifndef os_memset -#define os_memset(s, c, n) memset(s, c, n) -#endif -#ifndef os_memcmp -#define os_memcmp(s1, s2, n) memcmp((s1), (s2), (n)) -#endif - -#ifndef os_strdup -#ifdef _MSC_VER -#define os_strdup(s) _strdup(s) -#else -#define os_strdup(s) strdup(s) -#endif -#endif -#ifndef os_strlen -#define os_strlen(s) strlen(s) -#endif -#ifndef os_strcasecmp -#ifdef _MSC_VER -#define os_strcasecmp(s1, s2) _stricmp((s1), (s2)) -#else -#define os_strcasecmp(s1, s2) strcasecmp((s1), (s2)) -#endif -#endif -#ifndef os_strncasecmp -#ifdef _MSC_VER -#define os_strncasecmp(s1, s2, n) _strnicmp((s1), (s2), (n)) -#else -#define os_strncasecmp(s1, s2, n) strncasecmp((s1), (s2), (n)) -#endif -#endif -#ifndef os_strchr -#define os_strchr(s, c) strchr((s), (c)) -#endif -#ifndef os_strcmp -#define os_strcmp(s1, s2) strcmp((s1), (s2)) -#endif -#ifndef os_strncmp -#define os_strncmp(s1, s2, n) strncmp((s1), (s2), (n)) -#endif -#ifndef os_strncpy -#define os_strncpy(d, s, n) strncpy((d), (s), (n)) -#endif -#ifndef os_strrchr -#define os_strrchr(s, c) strrchr((s), (c)) -#endif -#ifndef os_strstr -#define os_strstr(h, n) strstr((h), (n)) -#endif - -#ifndef os_snprintf -#ifdef _MSC_VER -#define os_snprintf _snprintf -#else -#define os_snprintf snprintf -#endif -#endif - -#endif /* OS_NO_C_LIB_DEFINES */ - - -/** - * os_strlcpy - Copy a string with size bound and NUL-termination - * @dest: Destination - * @src: Source - * @siz: Size of the target buffer - * Returns: Total length of the target string (length of src) (not including - * NUL-termination) - * - * This function matches in behavior with the strlcpy(3) function in OpenBSD. - */ -size_t os_strlcpy(char *dest, const char *src, size_t siz); - - -#ifdef OS_REJECT_C_LIB_FUNCTIONS -#define malloc OS_DO_NOT_USE_malloc -#define realloc OS_DO_NOT_USE_realloc -#define free OS_DO_NOT_USE_free -#define memcpy OS_DO_NOT_USE_memcpy -#define memmove OS_DO_NOT_USE_memmove -#define memset OS_DO_NOT_USE_memset -#define memcmp OS_DO_NOT_USE_memcmp -#undef strdup -#define strdup OS_DO_NOT_USE_strdup -#define strlen OS_DO_NOT_USE_strlen -#define strcasecmp OS_DO_NOT_USE_strcasecmp -#define strncasecmp OS_DO_NOT_USE_strncasecmp -#undef strchr -#define strchr OS_DO_NOT_USE_strchr -#undef strcmp -#define strcmp OS_DO_NOT_USE_strcmp -#undef strncmp -#define strncmp OS_DO_NOT_USE_strncmp -#undef strncpy -#define strncpy OS_DO_NOT_USE_strncpy -#define strrchr OS_DO_NOT_USE_strrchr -#define strstr OS_DO_NOT_USE_strstr -#undef snprintf -#define snprintf OS_DO_NOT_USE_snprintf - -#define strcpy OS_DO_NOT_USE_strcpy -#endif /* OS_REJECT_C_LIB_FUNCTIONS */ - -#endif /* OS_H */ diff --git a/contrib/hostapd/src/utils/os_internal.c b/contrib/hostapd/src/utils/os_internal.c deleted file mode 100644 index 7b74bbf4ab..0000000000 --- a/contrib/hostapd/src/utils/os_internal.c +++ /dev/null @@ -1,466 +0,0 @@ -/* - * wpa_supplicant/hostapd / Internal implementation of OS specific functions - * Copyright (c) 2005-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file is an example of operating system specific wrapper functions. - * This version implements many of the functions internally, so it can be used - * to fill in missing functions from the target system C libraries. - * - * Some of the functions are using standard C library calls in order to keep - * this file in working condition to allow the functions to be tested on a - * Linux target. Please note that OS_NO_C_LIB_DEFINES needs to be defined for - * this file to work correctly. Note that these implementations are only - * examples and are not optimized for speed. - */ - -#include "includes.h" - -#undef OS_REJECT_C_LIB_FUNCTIONS -#include "os.h" - -void os_sleep(os_time_t sec, os_time_t usec) -{ - if (sec) - sleep(sec); - if (usec) - usleep(usec); -} - - -int os_get_time(struct os_time *t) -{ - int res; - struct timeval tv; - res = gettimeofday(&tv, NULL); - t->sec = tv.tv_sec; - t->usec = tv.tv_usec; - return res; -} - - -int os_mktime(int year, int month, int day, int hour, int min, int sec, - os_time_t *t) -{ - struct tm tm; - - if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || - hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || - sec > 60) - return -1; - - os_memset(&tm, 0, sizeof(tm)); - tm.tm_year = year - 1900; - tm.tm_mon = month - 1; - tm.tm_mday = day; - tm.tm_hour = hour; - tm.tm_min = min; - tm.tm_sec = sec; - - *t = (os_time_t) mktime(&tm); - return 0; -} - - -int os_daemonize(const char *pid_file) -{ - if (daemon(0, 0)) { - perror("daemon"); - return -1; - } - - if (pid_file) { - FILE *f = fopen(pid_file, "w"); - if (f) { - fprintf(f, "%u\n", getpid()); - fclose(f); - } - } - - return -0; -} - - -void os_daemonize_terminate(const char *pid_file) -{ - if (pid_file) - unlink(pid_file); -} - - -int os_get_random(unsigned char *buf, size_t len) -{ - FILE *f; - size_t rc; - - f = fopen("/dev/urandom", "rb"); - if (f == NULL) { - printf("Could not open /dev/urandom.\n"); - return -1; - } - - rc = fread(buf, 1, len, f); - fclose(f); - - return rc != len ? -1 : 0; -} - - -unsigned long os_random(void) -{ - return random(); -} - - -char * os_rel2abs_path(const char *rel_path) -{ - char *buf = NULL, *cwd, *ret; - size_t len = 128, cwd_len, rel_len, ret_len; - - if (rel_path[0] == '/') - return os_strdup(rel_path); - - for (;;) { - buf = os_malloc(len); - if (buf == NULL) - return NULL; - cwd = getcwd(buf, len); - if (cwd == NULL) { - os_free(buf); - if (errno != ERANGE) { - return NULL; - } - len *= 2; - } else { - break; - } - } - - cwd_len = strlen(cwd); - rel_len = strlen(rel_path); - ret_len = cwd_len + 1 + rel_len + 1; - ret = os_malloc(ret_len); - if (ret) { - os_memcpy(ret, cwd, cwd_len); - ret[cwd_len] = '/'; - os_memcpy(ret + cwd_len + 1, rel_path, rel_len); - ret[ret_len - 1] = '\0'; - } - os_free(buf); - return ret; -} - - -int os_program_init(void) -{ - return 0; -} - - -void os_program_deinit(void) -{ -} - - -int os_setenv(const char *name, const char *value, int overwrite) -{ - return setenv(name, value, overwrite); -} - - -int os_unsetenv(const char *name) -{ -#if defined(__FreeBSD__) || defined(__NetBSD__) - unsetenv(name); - return 0; -#else - return unsetenv(name); -#endif -} - - -char * os_readfile(const char *name, size_t *len) -{ - FILE *f; - char *buf; - - f = fopen(name, "rb"); - if (f == NULL) - return NULL; - - fseek(f, 0, SEEK_END); - *len = ftell(f); - fseek(f, 0, SEEK_SET); - - buf = os_malloc(*len); - if (buf == NULL) { - fclose(f); - return NULL; - } - - fread(buf, 1, *len, f); - fclose(f); - - return buf; -} - - -void * os_zalloc(size_t size) -{ - void *n = os_malloc(size); - if (n) - os_memset(n, 0, size); - return n; -} - - -void * os_malloc(size_t size) -{ - return malloc(size); -} - - -void * os_realloc(void *ptr, size_t size) -{ - return realloc(ptr, size); -} - - -void os_free(void *ptr) -{ - free(ptr); -} - - -void * os_memcpy(void *dest, const void *src, size_t n) -{ - char *d = dest; - const char *s = src; - while (n--) - *d++ = *s++; - return dest; -} - - -void * os_memmove(void *dest, const void *src, size_t n) -{ - if (dest < src) - os_memcpy(dest, src, n); - else { - /* overlapping areas */ - char *d = (char *) dest + n; - const char *s = (const char *) src + n; - while (n--) - *--d = *--s; - } - return dest; -} - - -void * os_memset(void *s, int c, size_t n) -{ - char *p = s; - while (n--) - *p++ = c; - return s; -} - - -int os_memcmp(const void *s1, const void *s2, size_t n) -{ - const unsigned char *p1 = s1, *p2 = s2; - - if (n == 0) - return 0; - - while (*p1 == *p2) { - p1++; - p2++; - n--; - if (n == 0) - return 0; - } - - return *p1 - *p2; -} - - -char * os_strdup(const char *s) -{ - char *res; - size_t len; - if (s == NULL) - return NULL; - len = os_strlen(s); - res = os_malloc(len + 1); - if (res) - os_memcpy(res, s, len + 1); - return res; -} - - -size_t os_strlen(const char *s) -{ - const char *p = s; - while (*p) - p++; - return p - s; -} - - -int os_strcasecmp(const char *s1, const char *s2) -{ - /* - * Ignoring case is not required for main functionality, so just use - * the case sensitive version of the function. - */ - return os_strcmp(s1, s2); -} - - -int os_strncasecmp(const char *s1, const char *s2, size_t n) -{ - /* - * Ignoring case is not required for main functionality, so just use - * the case sensitive version of the function. - */ - return os_strncmp(s1, s2, n); -} - - -char * os_strchr(const char *s, int c) -{ - while (*s) { - if (*s == c) - return (char *) s; - s++; - } - return NULL; -} - - -char * os_strrchr(const char *s, int c) -{ - const char *p = s; - while (*p) - p++; - p--; - while (p >= s) { - if (*p == c) - return (char *) p; - p--; - } - return NULL; -} - - -int os_strcmp(const char *s1, const char *s2) -{ - while (*s1 == *s2) { - if (*s1 == '\0') - break; - s1++; - s2++; - } - - return *s1 - *s2; -} - - -int os_strncmp(const char *s1, const char *s2, size_t n) -{ - if (n == 0) - return 0; - - while (*s1 == *s2) { - if (*s1 == '\0') - break; - s1++; - s2++; - n--; - if (n == 0) - return 0; - } - - return *s1 - *s2; -} - - -char * os_strncpy(char *dest, const char *src, size_t n) -{ - char *d = dest; - - while (n--) { - *d = *src; - if (*src == '\0') - break; - d++; - src++; - } - - return dest; -} - - -size_t os_strlcpy(char *dest, const char *src, size_t siz) -{ - const char *s = src; - size_t left = siz; - - if (left) { - /* Copy string up to the maximum size of the dest buffer */ - while (--left != 0) { - if ((*dest++ = *s++) == '\0') - break; - } - } - - if (left == 0) { - /* Not enough room for the string; force NUL-termination */ - if (siz != 0) - *dest = '\0'; - while (*s++) - ; /* determine total src string length */ - } - - return s - src - 1; -} - - -char * os_strstr(const char *haystack, const char *needle) -{ - size_t len = os_strlen(needle); - while (*haystack) { - if (os_strncmp(haystack, needle, len) == 0) - return (char *) haystack; - haystack++; - } - - return NULL; -} - - -int os_snprintf(char *str, size_t size, const char *format, ...) -{ - va_list ap; - int ret; - - /* See http://www.ijs.si/software/snprintf/ for portable - * implementation of snprintf. - */ - - va_start(ap, format); - ret = vsnprintf(str, size, format, ap); - va_end(ap); - if (size > 0) - str[size - 1] = '\0'; - return ret; -} diff --git a/contrib/hostapd/src/utils/os_none.c b/contrib/hostapd/src/utils/os_none.c deleted file mode 100644 index bab8f178c0..0000000000 --- a/contrib/hostapd/src/utils/os_none.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * wpa_supplicant/hostapd / Empty OS specific functions - * Copyright (c) 2005-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file can be used as a starting point when adding a new OS target. The - * functions here do not really work as-is since they are just empty or only - * return an error value. os_internal.c can be used as another starting point - * or reference since it has example implementation of many of these functions. - */ - -#include "includes.h" - -#include "os.h" - -void os_sleep(os_time_t sec, os_time_t usec) -{ -} - - -int os_get_time(struct os_time *t) -{ - return -1; -} - - -int os_mktime(int year, int month, int day, int hour, int min, int sec, - os_time_t *t) -{ - return -1; -} - - -int os_daemonize(const char *pid_file) -{ - return -1; -} - - -void os_daemonize_terminate(const char *pid_file) -{ -} - - -int os_get_random(unsigned char *buf, size_t len) -{ - return -1; -} - - -unsigned long os_random(void) -{ - return 0; -} - - -char * os_rel2abs_path(const char *rel_path) -{ - return NULL; /* strdup(rel_path) can be used here */ -} - - -int os_program_init(void) -{ - return 0; -} - - -void os_program_deinit(void) -{ -} - - -int os_setenv(const char *name, const char *value, int overwrite) -{ - return -1; -} - - -int os_unsetenv(const char *name) -{ - return -1; -} - - -char * os_readfile(const char *name, size_t *len) -{ - return NULL; -} - - -void * os_zalloc(size_t size) -{ - return NULL; -} - - -#ifdef OS_NO_C_LIB_DEFINES -void * os_malloc(size_t size) -{ - return NULL; -} - - -void * os_realloc(void *ptr, size_t size) -{ - return NULL; -} - - -void os_free(void *ptr) -{ -} - - -void * os_memcpy(void *dest, const void *src, size_t n) -{ - return dest; -} - - -void * os_memmove(void *dest, const void *src, size_t n) -{ - return dest; -} - - -void * os_memset(void *s, int c, size_t n) -{ - return s; -} - - -int os_memcmp(const void *s1, const void *s2, size_t n) -{ - return 0; -} - - -char * os_strdup(const char *s) -{ - return NULL; -} - - -size_t os_strlen(const char *s) -{ - return 0; -} - - -int os_strcasecmp(const char *s1, const char *s2) -{ - /* - * Ignoring case is not required for main functionality, so just use - * the case sensitive version of the function. - */ - return os_strcmp(s1, s2); -} - - -int os_strncasecmp(const char *s1, const char *s2, size_t n) -{ - /* - * Ignoring case is not required for main functionality, so just use - * the case sensitive version of the function. - */ - return os_strncmp(s1, s2, n); -} - - -char * os_strchr(const char *s, int c) -{ - return NULL; -} - - -char * os_strrchr(const char *s, int c) -{ - return NULL; -} - - -int os_strcmp(const char *s1, const char *s2) -{ - return 0; -} - - -int os_strncmp(const char *s1, const char *s2, size_t n) -{ - return 0; -} - - -char * os_strncpy(char *dest, const char *src, size_t n) -{ - return dest; -} - - -size_t os_strlcpy(char *dest, const char *src, size_t size) -{ - return 0; -} - - -char * os_strstr(const char *haystack, const char *needle) -{ - return NULL; -} - - -int os_snprintf(char *str, size_t size, const char *format, ...) -{ - return 0; -} -#endif /* OS_NO_C_LIB_DEFINES */ diff --git a/contrib/hostapd/src/utils/os_unix.c b/contrib/hostapd/src/utils/os_unix.c deleted file mode 100644 index ea46094cd2..0000000000 --- a/contrib/hostapd/src/utils/os_unix.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * wpa_supplicant/hostapd / OS specific functions for UNIX/POSIX systems - * Copyright (c) 2005-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "os.h" - -void os_sleep(os_time_t sec, os_time_t usec) -{ - if (sec) - sleep(sec); - if (usec) - usleep(usec); -} - - -int os_get_time(struct os_time *t) -{ - int res; - struct timeval tv; - res = gettimeofday(&tv, NULL); - t->sec = tv.tv_sec; - t->usec = tv.tv_usec; - return res; -} - - -int os_mktime(int year, int month, int day, int hour, int min, int sec, - os_time_t *t) -{ - struct tm tm, *tm1; - time_t t_local, t1, t2; - os_time_t tz_offset; - - if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || - hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || - sec > 60) - return -1; - - memset(&tm, 0, sizeof(tm)); - tm.tm_year = year - 1900; - tm.tm_mon = month - 1; - tm.tm_mday = day; - tm.tm_hour = hour; - tm.tm_min = min; - tm.tm_sec = sec; - - t_local = mktime(&tm); - - /* figure out offset to UTC */ - tm1 = localtime(&t_local); - if (tm1) { - t1 = mktime(tm1); - tm1 = gmtime(&t_local); - if (tm1) { - t2 = mktime(tm1); - tz_offset = t2 - t1; - } else - tz_offset = 0; - } else - tz_offset = 0; - - *t = (os_time_t) t_local - tz_offset; - return 0; -} - - -#ifdef __APPLE__ -#include -static int os_daemon(int nochdir, int noclose) -{ - int devnull; - - if (chdir("/") < 0) - return -1; - - devnull = open("/dev/null", O_RDWR); - if (devnull < 0) - return -1; - - if (dup2(devnull, STDIN_FILENO) < 0) { - close(devnull); - return -1; - } - - if (dup2(devnull, STDOUT_FILENO) < 0) { - close(devnull); - return -1; - } - - if (dup2(devnull, STDERR_FILENO) < 0) { - close(devnull); - return -1; - } - - return 0; -} -#else /* __APPLE__ */ -#define os_daemon daemon -#endif /* __APPLE__ */ - - -int os_daemonize(const char *pid_file) -{ -#ifdef __uClinux__ - return -1; -#else /* __uClinux__ */ - if (os_daemon(0, 0)) { - perror("daemon"); - return -1; - } - - if (pid_file) { - FILE *f = fopen(pid_file, "w"); - if (f) { - fprintf(f, "%u\n", getpid()); - fclose(f); - } - } - - return -0; -#endif /* __uClinux__ */ -} - - -void os_daemonize_terminate(const char *pid_file) -{ - if (pid_file) - unlink(pid_file); -} - - -int os_get_random(unsigned char *buf, size_t len) -{ - FILE *f; - size_t rc; - - f = fopen("/dev/urandom", "rb"); - if (f == NULL) { - printf("Could not open /dev/urandom.\n"); - return -1; - } - - rc = fread(buf, 1, len, f); - fclose(f); - - return rc != len ? -1 : 0; -} - - -unsigned long os_random(void) -{ - return random(); -} - - -char * os_rel2abs_path(const char *rel_path) -{ - char *buf = NULL, *cwd, *ret; - size_t len = 128, cwd_len, rel_len, ret_len; - int last_errno; - - if (rel_path[0] == '/') - return strdup(rel_path); - - for (;;) { - buf = malloc(len); - if (buf == NULL) - return NULL; - cwd = getcwd(buf, len); - if (cwd == NULL) { - last_errno = errno; - free(buf); - if (last_errno != ERANGE) - return NULL; - len *= 2; - if (len > 2000) - return NULL; - } else { - buf[len - 1] = '\0'; - break; - } - } - - cwd_len = strlen(cwd); - rel_len = strlen(rel_path); - ret_len = cwd_len + 1 + rel_len + 1; - ret = malloc(ret_len); - if (ret) { - memcpy(ret, cwd, cwd_len); - ret[cwd_len] = '/'; - memcpy(ret + cwd_len + 1, rel_path, rel_len); - ret[ret_len - 1] = '\0'; - } - free(buf); - return ret; -} - - -int os_program_init(void) -{ - return 0; -} - - -void os_program_deinit(void) -{ -} - - -int os_setenv(const char *name, const char *value, int overwrite) -{ - return setenv(name, value, overwrite); -} - - -int os_unsetenv(const char *name) -{ -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \ - defined(__OpenBSD__) || defined(__DragonFly__) - unsetenv(name); - return 0; -#else - return unsetenv(name); -#endif -} - - -char * os_readfile(const char *name, size_t *len) -{ - FILE *f; - char *buf; - - f = fopen(name, "rb"); - if (f == NULL) - return NULL; - - fseek(f, 0, SEEK_END); - *len = ftell(f); - fseek(f, 0, SEEK_SET); - - buf = malloc(*len); - if (buf == NULL) { - fclose(f); - return NULL; - } - - if (fread(buf, 1, *len, f) != *len) { - fclose(f); - free(buf); - return NULL; - } - - fclose(f); - - return buf; -} - - -void * os_zalloc(size_t size) -{ - return calloc(1, size); -} - - -size_t os_strlcpy(char *dest, const char *src, size_t siz) -{ - const char *s = src; - size_t left = siz; - - if (left) { - /* Copy string up to the maximum size of the dest buffer */ - while (--left != 0) { - if ((*dest++ = *s++) == '\0') - break; - } - } - - if (left == 0) { - /* Not enough room for the string; force NUL-termination */ - if (siz != 0) - *dest = '\0'; - while (*s++) - ; /* determine total src string length */ - } - - return s - src - 1; -} diff --git a/contrib/hostapd/src/utils/os_win32.c b/contrib/hostapd/src/utils/os_win32.c deleted file mode 100644 index 074096480a..0000000000 --- a/contrib/hostapd/src/utils/os_win32.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * wpa_supplicant/hostapd / OS specific functions for Win32 systems - * Copyright (c) 2005-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include - -#include "os.h" - -void os_sleep(os_time_t sec, os_time_t usec) -{ - if (sec) - Sleep(sec * 1000); - if (usec) - Sleep(usec / 1000); -} - - -int os_get_time(struct os_time *t) -{ -#define EPOCHFILETIME (116444736000000000ULL) - FILETIME ft; - LARGE_INTEGER li; - ULONGLONG tt; - -#ifdef _WIN32_WCE - SYSTEMTIME st; - - GetSystemTime(&st); - SystemTimeToFileTime(&st, &ft); -#else /* _WIN32_WCE */ - GetSystemTimeAsFileTime(&ft); -#endif /* _WIN32_WCE */ - li.LowPart = ft.dwLowDateTime; - li.HighPart = ft.dwHighDateTime; - tt = (li.QuadPart - EPOCHFILETIME) / 10; - t->sec = (os_time_t) (tt / 1000000); - t->usec = (os_time_t) (tt % 1000000); - - return 0; -} - - -int os_mktime(int year, int month, int day, int hour, int min, int sec, - os_time_t *t) -{ - struct tm tm, *tm1; - time_t t_local, t1, t2; - os_time_t tz_offset; - - if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || - hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || - sec > 60) - return -1; - - memset(&tm, 0, sizeof(tm)); - tm.tm_year = year - 1900; - tm.tm_mon = month - 1; - tm.tm_mday = day; - tm.tm_hour = hour; - tm.tm_min = min; - tm.tm_sec = sec; - - t_local = mktime(&tm); - - /* figure out offset to UTC */ - tm1 = localtime(&t_local); - if (tm1) { - t1 = mktime(tm1); - tm1 = gmtime(&t_local); - if (tm1) { - t2 = mktime(tm1); - tz_offset = t2 - t1; - } else - tz_offset = 0; - } else - tz_offset = 0; - - *t = (os_time_t) t_local - tz_offset; - return 0; -} - - -int os_daemonize(const char *pid_file) -{ - /* TODO */ - return -1; -} - - -void os_daemonize_terminate(const char *pid_file) -{ -} - - -int os_get_random(unsigned char *buf, size_t len) -{ - HCRYPTPROV prov; - BOOL ret; - - if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT)) - return -1; - - ret = CryptGenRandom(prov, len, buf); - CryptReleaseContext(prov, 0); - - return ret ? 0 : -1; -} - - -unsigned long os_random(void) -{ - return rand(); -} - - -char * os_rel2abs_path(const char *rel_path) -{ - return _strdup(rel_path); -} - - -int os_program_init(void) -{ -#ifdef CONFIG_NATIVE_WINDOWS - WSADATA wsaData; - if (WSAStartup(MAKEWORD(2, 0), &wsaData)) { - printf("Could not find a usable WinSock.dll\n"); - return -1; - } -#endif /* CONFIG_NATIVE_WINDOWS */ - return 0; -} - - -void os_program_deinit(void) -{ -#ifdef CONFIG_NATIVE_WINDOWS - WSACleanup(); -#endif /* CONFIG_NATIVE_WINDOWS */ -} - - -int os_setenv(const char *name, const char *value, int overwrite) -{ - return -1; -} - - -int os_unsetenv(const char *name) -{ - return -1; -} - - -char * os_readfile(const char *name, size_t *len) -{ - FILE *f; - char *buf; - - f = fopen(name, "rb"); - if (f == NULL) - return NULL; - - fseek(f, 0, SEEK_END); - *len = ftell(f); - fseek(f, 0, SEEK_SET); - - buf = malloc(*len); - if (buf == NULL) { - fclose(f); - return NULL; - } - - fread(buf, 1, *len, f); - fclose(f); - - return buf; -} - - -void * os_zalloc(size_t size) -{ - return calloc(1, size); -} - - -size_t os_strlcpy(char *dest, const char *src, size_t siz) -{ - const char *s = src; - size_t left = siz; - - if (left) { - /* Copy string up to the maximum size of the dest buffer */ - while (--left != 0) { - if ((*dest++ = *s++) == '\0') - break; - } - } - - if (left == 0) { - /* Not enough room for the string; force NUL-termination */ - if (siz != 0) - *dest = '\0'; - while (*s++) - ; /* determine total src string length */ - } - - return s - src - 1; -} diff --git a/contrib/hostapd/src/utils/pcsc_funcs.c b/contrib/hostapd/src/utils/pcsc_funcs.c deleted file mode 100644 index bf9f04a719..0000000000 --- a/contrib/hostapd/src/utils/pcsc_funcs.c +++ /dev/null @@ -1,1238 +0,0 @@ -/* - * WPA Supplicant / PC/SC smartcard interface for USIM, GSM SIM - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file implements wrapper functions for accessing GSM SIM and 3GPP USIM - * cards through PC/SC smartcard library. These functions are used to implement - * authentication routines for EAP-SIM and EAP-AKA. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "pcsc_funcs.h" - - -/* See ETSI GSM 11.11 and ETSI TS 102 221 for details. - * SIM commands: - * Command APDU: CLA INS P1 P2 P3 Data - * CLA (class of instruction): A0 for GSM, 00 for USIM - * INS (instruction) - * P1 P2 P3 (parameters, P3 = length of Data) - * Response APDU: Data SW1 SW2 - * SW1 SW2 (Status words) - * Commands (INS P1 P2 P3): - * SELECT: A4 00 00 02 - * GET RESPONSE: C0 00 00 - * RUN GSM ALG: 88 00 00 00 - * RUN UMTS ALG: 88 00 81 data: 0x10 | RAND | 0x10 | AUTN - * P1 = ID of alg in card - * P2 = ID of secret key - * READ BINARY: B0 - * READ RECORD: B2 - * P2 (mode) = '02' (next record), '03' (previous record), - * '04' (absolute mode) - * VERIFY CHV: 20 00 08 - * CHANGE CHV: 24 00 10 - * DISABLE CHV: 26 00 01 08 - * ENABLE CHV: 28 00 01 08 - * UNBLOCK CHV: 2C 00 <00=CHV1, 02=CHV2> 10 - * SLEEP: FA 00 00 00 - */ - -/* GSM SIM commands */ -#define SIM_CMD_SELECT 0xa0, 0xa4, 0x00, 0x00, 0x02 -#define SIM_CMD_RUN_GSM_ALG 0xa0, 0x88, 0x00, 0x00, 0x10 -#define SIM_CMD_GET_RESPONSE 0xa0, 0xc0, 0x00, 0x00 -#define SIM_CMD_READ_BIN 0xa0, 0xb0, 0x00, 0x00 -#define SIM_CMD_READ_RECORD 0xa0, 0xb2, 0x00, 0x00 -#define SIM_CMD_VERIFY_CHV1 0xa0, 0x20, 0x00, 0x01, 0x08 - -/* USIM commands */ -#define USIM_CLA 0x00 -#define USIM_CMD_RUN_UMTS_ALG 0x00, 0x88, 0x00, 0x81, 0x22 -#define USIM_CMD_GET_RESPONSE 0x00, 0xc0, 0x00, 0x00 - -#define SIM_RECORD_MODE_ABSOLUTE 0x04 - -#define USIM_FSP_TEMPL_TAG 0x62 - -#define USIM_TLV_FILE_DESC 0x82 -#define USIM_TLV_FILE_ID 0x83 -#define USIM_TLV_DF_NAME 0x84 -#define USIM_TLV_PROPR_INFO 0xA5 -#define USIM_TLV_LIFE_CYCLE_STATUS 0x8A -#define USIM_TLV_FILE_SIZE 0x80 -#define USIM_TLV_TOTAL_FILE_SIZE 0x81 -#define USIM_TLV_PIN_STATUS_TEMPLATE 0xC6 -#define USIM_TLV_SHORT_FILE_ID 0x88 - -#define USIM_PS_DO_TAG 0x90 - -#define AKA_RAND_LEN 16 -#define AKA_AUTN_LEN 16 -#define AKA_AUTS_LEN 14 -#define RES_MAX_LEN 16 -#define IK_LEN 16 -#define CK_LEN 16 - - -typedef enum { SCARD_GSM_SIM, SCARD_USIM } sim_types; - -struct scard_data { - SCARDCONTEXT ctx; - SCARDHANDLE card; - DWORD protocol; - sim_types sim_type; - int pin1_required; -}; - -#ifdef __MINGW32_VERSION -/* MinGW does not yet support WinScard, so load the needed functions - * dynamically from winscard.dll for now. */ - -static HINSTANCE dll = NULL; /* winscard.dll */ - -static const SCARD_IO_REQUEST *dll_g_rgSCardT0Pci, *dll_g_rgSCardT1Pci; -#undef SCARD_PCI_T0 -#define SCARD_PCI_T0 (dll_g_rgSCardT0Pci) -#undef SCARD_PCI_T1 -#define SCARD_PCI_T1 (dll_g_rgSCardT1Pci) - - -static WINSCARDAPI LONG WINAPI -(*dll_SCardEstablishContext)(IN DWORD dwScope, - IN LPCVOID pvReserved1, - IN LPCVOID pvReserved2, - OUT LPSCARDCONTEXT phContext); -#define SCardEstablishContext dll_SCardEstablishContext - -static long (*dll_SCardReleaseContext)(long hContext); -#define SCardReleaseContext dll_SCardReleaseContext - -static WINSCARDAPI LONG WINAPI -(*dll_SCardListReadersA)(IN SCARDCONTEXT hContext, - IN LPCSTR mszGroups, - OUT LPSTR mszReaders, - IN OUT LPDWORD pcchReaders); -#undef SCardListReaders -#define SCardListReaders dll_SCardListReadersA - -static WINSCARDAPI LONG WINAPI -(*dll_SCardConnectA)(IN SCARDCONTEXT hContext, - IN LPCSTR szReader, - IN DWORD dwShareMode, - IN DWORD dwPreferredProtocols, - OUT LPSCARDHANDLE phCard, - OUT LPDWORD pdwActiveProtocol); -#undef SCardConnect -#define SCardConnect dll_SCardConnectA - -static WINSCARDAPI LONG WINAPI -(*dll_SCardDisconnect)(IN SCARDHANDLE hCard, - IN DWORD dwDisposition); -#define SCardDisconnect dll_SCardDisconnect - -static WINSCARDAPI LONG WINAPI -(*dll_SCardTransmit)(IN SCARDHANDLE hCard, - IN LPCSCARD_IO_REQUEST pioSendPci, - IN LPCBYTE pbSendBuffer, - IN DWORD cbSendLength, - IN OUT LPSCARD_IO_REQUEST pioRecvPci, - OUT LPBYTE pbRecvBuffer, - IN OUT LPDWORD pcbRecvLength); -#define SCardTransmit dll_SCardTransmit - -static WINSCARDAPI LONG WINAPI -(*dll_SCardBeginTransaction)(IN SCARDHANDLE hCard); -#define SCardBeginTransaction dll_SCardBeginTransaction - -static WINSCARDAPI LONG WINAPI -(*dll_SCardEndTransaction)(IN SCARDHANDLE hCard, IN DWORD dwDisposition); -#define SCardEndTransaction dll_SCardEndTransaction - - -static int mingw_load_symbols(void) -{ - char *sym; - - if (dll) - return 0; - - dll = LoadLibrary("winscard"); - if (dll == NULL) { - wpa_printf(MSG_DEBUG, "WinSCard: Could not load winscard.dll " - "library"); - return -1; - } - -#define LOADSYM(s) \ - sym = #s; \ - dll_ ## s = (void *) GetProcAddress(dll, sym); \ - if (dll_ ## s == NULL) \ - goto fail; - - LOADSYM(SCardEstablishContext); - LOADSYM(SCardReleaseContext); - LOADSYM(SCardListReadersA); - LOADSYM(SCardConnectA); - LOADSYM(SCardDisconnect); - LOADSYM(SCardTransmit); - LOADSYM(SCardBeginTransaction); - LOADSYM(SCardEndTransaction); - LOADSYM(g_rgSCardT0Pci); - LOADSYM(g_rgSCardT1Pci); - -#undef LOADSYM - - return 0; - -fail: - wpa_printf(MSG_DEBUG, "WinSCard: Could not get address for %s from " - "winscard.dll", sym); - FreeLibrary(dll); - dll = NULL; - return -1; -} - - -static void mingw_unload_symbols(void) -{ - if (dll == NULL) - return; - - FreeLibrary(dll); - dll = NULL; -} - -#else /* __MINGW32_VERSION */ - -#define mingw_load_symbols() 0 -#define mingw_unload_symbols() do { } while (0) - -#endif /* __MINGW32_VERSION */ - - -static int _scard_select_file(struct scard_data *scard, unsigned short file_id, - unsigned char *buf, size_t *buf_len, - sim_types sim_type, unsigned char *aid, - size_t aidlen); -static int scard_select_file(struct scard_data *scard, unsigned short file_id, - unsigned char *buf, size_t *buf_len); -static int scard_verify_pin(struct scard_data *scard, const char *pin); -static int scard_get_record_len(struct scard_data *scard, - unsigned char recnum, unsigned char mode); -static int scard_read_record(struct scard_data *scard, - unsigned char *data, size_t len, - unsigned char recnum, unsigned char mode); - - -static int scard_parse_fsp_templ(unsigned char *buf, size_t buf_len, - int *ps_do, int *file_len) -{ - unsigned char *pos, *end; - - if (ps_do) - *ps_do = -1; - if (file_len) - *file_len = -1; - - pos = buf; - end = pos + buf_len; - if (*pos != USIM_FSP_TEMPL_TAG) { - wpa_printf(MSG_DEBUG, "SCARD: file header did not " - "start with FSP template tag"); - return -1; - } - pos++; - if (pos >= end) - return -1; - if ((pos + pos[0]) < end) - end = pos + 1 + pos[0]; - pos++; - wpa_hexdump(MSG_DEBUG, "SCARD: file header FSP template", - pos, end - pos); - - while (pos + 1 < end) { - wpa_printf(MSG_MSGDUMP, "SCARD: file header TLV " - "0x%02x len=%d", pos[0], pos[1]); - if (pos + 2 + pos[1] > end) - break; - - if (pos[0] == USIM_TLV_FILE_SIZE && - (pos[1] == 1 || pos[1] == 2) && file_len) { - if (pos[1] == 1) - *file_len = (int) pos[2]; - else - *file_len = ((int) pos[2] << 8) | - (int) pos[3]; - wpa_printf(MSG_DEBUG, "SCARD: file_size=%d", - *file_len); - } - - if (pos[0] == USIM_TLV_PIN_STATUS_TEMPLATE && - pos[1] >= 2 && pos[2] == USIM_PS_DO_TAG && - pos[3] >= 1 && ps_do) { - wpa_printf(MSG_DEBUG, "SCARD: PS_DO=0x%02x", - pos[4]); - *ps_do = (int) pos[4]; - } - - pos += 2 + pos[1]; - - if (pos == end) - return 0; - } - return -1; -} - - -static int scard_pin_needed(struct scard_data *scard, - unsigned char *hdr, size_t hlen) -{ - if (scard->sim_type == SCARD_GSM_SIM) { - if (hlen > SCARD_CHV1_OFFSET && - !(hdr[SCARD_CHV1_OFFSET] & SCARD_CHV1_FLAG)) - return 1; - return 0; - } - - if (scard->sim_type == SCARD_USIM) { - int ps_do; - if (scard_parse_fsp_templ(hdr, hlen, &ps_do, NULL)) - return -1; - /* TODO: there could be more than one PS_DO entry because of - * multiple PINs in key reference.. */ - if (ps_do > 0 && (ps_do & 0x80)) - return 1; - return 0; - } - - return -1; -} - - -static int scard_get_aid(struct scard_data *scard, unsigned char *aid, - size_t maxlen) -{ - int rlen, rec; - struct efdir { - unsigned char appl_template_tag; /* 0x61 */ - unsigned char appl_template_len; - unsigned char appl_id_tag; /* 0x4f */ - unsigned char aid_len; - unsigned char rid[5]; - unsigned char appl_code[2]; /* 0x1002 for 3G USIM */ - } *efdir; - unsigned char buf[100]; - size_t blen; - - efdir = (struct efdir *) buf; - blen = sizeof(buf); - if (scard_select_file(scard, SCARD_FILE_EF_DIR, buf, &blen)) { - wpa_printf(MSG_DEBUG, "SCARD: Failed to read EF_DIR"); - return -1; - } - wpa_hexdump(MSG_DEBUG, "SCARD: EF_DIR select", buf, blen); - - for (rec = 1; rec < 10; rec++) { - rlen = scard_get_record_len(scard, rec, - SIM_RECORD_MODE_ABSOLUTE); - if (rlen < 0) { - wpa_printf(MSG_DEBUG, "SCARD: Failed to get EF_DIR " - "record length"); - return -1; - } - blen = sizeof(buf); - if (rlen > (int) blen) { - wpa_printf(MSG_DEBUG, "SCARD: Too long EF_DIR record"); - return -1; - } - if (scard_read_record(scard, buf, rlen, rec, - SIM_RECORD_MODE_ABSOLUTE) < 0) { - wpa_printf(MSG_DEBUG, "SCARD: Failed to read " - "EF_DIR record %d", rec); - return -1; - } - wpa_hexdump(MSG_DEBUG, "SCARD: EF_DIR record", buf, rlen); - - if (efdir->appl_template_tag != 0x61) { - wpa_printf(MSG_DEBUG, "SCARD: Unexpected application " - "template tag 0x%x", - efdir->appl_template_tag); - continue; - } - - if (efdir->appl_template_len > rlen - 2) { - wpa_printf(MSG_DEBUG, "SCARD: Too long application " - "template (len=%d rlen=%d)", - efdir->appl_template_len, rlen); - continue; - } - - if (efdir->appl_id_tag != 0x4f) { - wpa_printf(MSG_DEBUG, "SCARD: Unexpected application " - "identifier tag 0x%x", efdir->appl_id_tag); - continue; - } - - if (efdir->aid_len < 1 || efdir->aid_len > 16) { - wpa_printf(MSG_DEBUG, "SCARD: Invalid AID length %d", - efdir->aid_len); - continue; - } - - wpa_hexdump(MSG_DEBUG, "SCARD: AID from EF_DIR record", - efdir->rid, efdir->aid_len); - - if (efdir->appl_code[0] == 0x10 && - efdir->appl_code[1] == 0x02) { - wpa_printf(MSG_DEBUG, "SCARD: 3G USIM app found from " - "EF_DIR record %d", rec); - break; - } - } - - if (rec >= 10) { - wpa_printf(MSG_DEBUG, "SCARD: 3G USIM app not found " - "from EF_DIR records"); - return -1; - } - - if (efdir->aid_len > maxlen) { - wpa_printf(MSG_DEBUG, "SCARD: Too long AID"); - return -1; - } - - os_memcpy(aid, efdir->rid, efdir->aid_len); - - return efdir->aid_len; -} - - -/** - * scard_init - Initialize SIM/USIM connection using PC/SC - * @sim_type: Allowed SIM types (SIM, USIM, or both) - * Returns: Pointer to private data structure, or %NULL on failure - * - * This function is used to initialize SIM/USIM connection. PC/SC is used to - * open connection to the SIM/USIM card and the card is verified to support the - * selected sim_type. In addition, local flag is set if a PIN is needed to - * access some of the card functions. Once the connection is not needed - * anymore, scard_deinit() can be used to close it. - */ -struct scard_data * scard_init(scard_sim_type sim_type) -{ - long ret; - unsigned long len; - struct scard_data *scard; -#ifdef CONFIG_NATIVE_WINDOWS - TCHAR *readers = NULL; -#else /* CONFIG_NATIVE_WINDOWS */ - char *readers = NULL; -#endif /* CONFIG_NATIVE_WINDOWS */ - unsigned char buf[100]; - size_t blen; - int transaction = 0; - int pin_needed; - - wpa_printf(MSG_DEBUG, "SCARD: initializing smart card interface"); - if (mingw_load_symbols()) - return NULL; - scard = os_zalloc(sizeof(*scard)); - if (scard == NULL) - return NULL; - - ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, - &scard->ctx); - if (ret != SCARD_S_SUCCESS) { - wpa_printf(MSG_DEBUG, "SCARD: Could not establish smart card " - "context (err=%ld)", ret); - goto failed; - } - - ret = SCardListReaders(scard->ctx, NULL, NULL, &len); - if (ret != SCARD_S_SUCCESS) { - wpa_printf(MSG_DEBUG, "SCARD: SCardListReaders failed " - "(err=%ld)", ret); - goto failed; - } - -#ifdef UNICODE - len *= 2; -#endif /* UNICODE */ - readers = os_malloc(len); - if (readers == NULL) { - wpa_printf(MSG_INFO, "SCARD: malloc failed\n"); - goto failed; - } - - ret = SCardListReaders(scard->ctx, NULL, readers, &len); - if (ret != SCARD_S_SUCCESS) { - wpa_printf(MSG_DEBUG, "SCARD: SCardListReaders failed(2) " - "(err=%ld)", ret); - goto failed; - } - if (len < 3) { - wpa_printf(MSG_WARNING, "SCARD: No smart card readers " - "available."); - goto failed; - } - /* readers is a list of available reader. Last entry is terminated with - * double NUL. - * TODO: add support for selecting the reader; now just use the first - * one.. */ -#ifdef UNICODE - wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%S'", readers); -#else /* UNICODE */ - wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%s'", readers); -#endif /* UNICODE */ - - ret = SCardConnect(scard->ctx, readers, SCARD_SHARE_SHARED, - SCARD_PROTOCOL_T0, &scard->card, &scard->protocol); - if (ret != SCARD_S_SUCCESS) { - if (ret == (long) SCARD_E_NO_SMARTCARD) - wpa_printf(MSG_INFO, "No smart card inserted."); - else - wpa_printf(MSG_WARNING, "SCardConnect err=%lx", ret); - goto failed; - } - - os_free(readers); - readers = NULL; - - wpa_printf(MSG_DEBUG, "SCARD: card=0x%x active_protocol=%lu (%s)", - (unsigned int) scard->card, scard->protocol, - scard->protocol == SCARD_PROTOCOL_T0 ? "T0" : "T1"); - - ret = SCardBeginTransaction(scard->card); - if (ret != SCARD_S_SUCCESS) { - wpa_printf(MSG_DEBUG, "SCARD: Could not begin transaction: " - "0x%x", (unsigned int) ret); - goto failed; - } - transaction = 1; - - blen = sizeof(buf); - - scard->sim_type = SCARD_GSM_SIM; - if (sim_type == SCARD_USIM_ONLY || sim_type == SCARD_TRY_BOTH) { - wpa_printf(MSG_DEBUG, "SCARD: verifying USIM support"); - if (_scard_select_file(scard, SCARD_FILE_MF, buf, &blen, - SCARD_USIM, NULL, 0)) { - wpa_printf(MSG_DEBUG, "SCARD: USIM is not supported"); - if (sim_type == SCARD_USIM_ONLY) - goto failed; - wpa_printf(MSG_DEBUG, "SCARD: Trying to use GSM SIM"); - scard->sim_type = SCARD_GSM_SIM; - } else { - wpa_printf(MSG_DEBUG, "SCARD: USIM is supported"); - scard->sim_type = SCARD_USIM; - } - } - - if (scard->sim_type == SCARD_GSM_SIM) { - blen = sizeof(buf); - if (scard_select_file(scard, SCARD_FILE_MF, buf, &blen)) { - wpa_printf(MSG_DEBUG, "SCARD: Failed to read MF"); - goto failed; - } - - blen = sizeof(buf); - if (scard_select_file(scard, SCARD_FILE_GSM_DF, buf, &blen)) { - wpa_printf(MSG_DEBUG, "SCARD: Failed to read GSM DF"); - goto failed; - } - } else { - unsigned char aid[32]; - int aid_len; - - aid_len = scard_get_aid(scard, aid, sizeof(aid)); - if (aid_len < 0) { - wpa_printf(MSG_DEBUG, "SCARD: Failed to find AID for " - "3G USIM app - try to use standard 3G RID"); - os_memcpy(aid, "\xa0\x00\x00\x00\x87", 5); - aid_len = 5; - } - wpa_hexdump(MSG_DEBUG, "SCARD: 3G USIM AID", aid, aid_len); - - /* Select based on AID = 3G RID from EF_DIR. This is usually - * starting with A0 00 00 00 87. */ - blen = sizeof(buf); - if (_scard_select_file(scard, 0, buf, &blen, scard->sim_type, - aid, aid_len)) { - wpa_printf(MSG_INFO, "SCARD: Failed to read 3G USIM " - "app"); - wpa_hexdump(MSG_INFO, "SCARD: 3G USIM AID", - aid, aid_len); - goto failed; - } - } - - /* Verify whether CHV1 (PIN1) is needed to access the card. */ - pin_needed = scard_pin_needed(scard, buf, blen); - if (pin_needed < 0) { - wpa_printf(MSG_DEBUG, "SCARD: Failed to determine whether PIN " - "is needed"); - goto failed; - } - if (pin_needed) { - scard->pin1_required = 1; - wpa_printf(MSG_DEBUG, "PIN1 needed for SIM access"); - } - - ret = SCardEndTransaction(scard->card, SCARD_LEAVE_CARD); - if (ret != SCARD_S_SUCCESS) { - wpa_printf(MSG_DEBUG, "SCARD: Could not end transaction: " - "0x%x", (unsigned int) ret); - } - - return scard; - -failed: - if (transaction) - SCardEndTransaction(scard->card, SCARD_LEAVE_CARD); - os_free(readers); - scard_deinit(scard); - return NULL; -} - - -/** - * scard_set_pin - Set PIN (CHV1/PIN1) code for accessing SIM/USIM commands - * @scard: Pointer to private data from scard_init() - * @pin: PIN code as an ASCII string (e.g., "1234") - * Returns: 0 on success, -1 on failure - */ -int scard_set_pin(struct scard_data *scard, const char *pin) -{ - if (scard == NULL) - return -1; - - /* Verify whether CHV1 (PIN1) is needed to access the card. */ - if (scard->pin1_required) { - if (pin == NULL) { - wpa_printf(MSG_DEBUG, "No PIN configured for SIM " - "access"); - return -1; - } - if (scard_verify_pin(scard, pin)) { - wpa_printf(MSG_INFO, "PIN verification failed for " - "SIM access"); - return -1; - } - } - - return 0; -} - - -/** - * scard_deinit - Deinitialize SIM/USIM connection - * @scard: Pointer to private data from scard_init() - * - * This function closes the SIM/USIM connect opened with scard_init(). - */ -void scard_deinit(struct scard_data *scard) -{ - long ret; - - if (scard == NULL) - return; - - wpa_printf(MSG_DEBUG, "SCARD: deinitializing smart card interface"); - if (scard->card) { - ret = SCardDisconnect(scard->card, SCARD_UNPOWER_CARD); - if (ret != SCARD_S_SUCCESS) { - wpa_printf(MSG_DEBUG, "SCARD: Failed to disconnect " - "smart card (err=%ld)", ret); - } - } - - if (scard->ctx) { - ret = SCardReleaseContext(scard->ctx); - if (ret != SCARD_S_SUCCESS) { - wpa_printf(MSG_DEBUG, "Failed to release smart card " - "context (err=%ld)", ret); - } - } - os_free(scard); - mingw_unload_symbols(); -} - - -static long scard_transmit(struct scard_data *scard, - unsigned char *_send, size_t send_len, - unsigned char *_recv, size_t *recv_len) -{ - long ret; - unsigned long rlen; - - wpa_hexdump_key(MSG_DEBUG, "SCARD: scard_transmit: send", - _send, send_len); - rlen = *recv_len; - ret = SCardTransmit(scard->card, - scard->protocol == SCARD_PROTOCOL_T1 ? - SCARD_PCI_T1 : SCARD_PCI_T0, - _send, (unsigned long) send_len, - NULL, _recv, &rlen); - *recv_len = rlen; - if (ret == SCARD_S_SUCCESS) { - wpa_hexdump(MSG_DEBUG, "SCARD: scard_transmit: recv", - _recv, rlen); - } else { - wpa_printf(MSG_WARNING, "SCARD: SCardTransmit failed " - "(err=0x%lx)", ret); - } - return ret; -} - - -static int _scard_select_file(struct scard_data *scard, unsigned short file_id, - unsigned char *buf, size_t *buf_len, - sim_types sim_type, unsigned char *aid, - size_t aidlen) -{ - long ret; - unsigned char resp[3]; - unsigned char cmd[50] = { SIM_CMD_SELECT }; - int cmdlen; - unsigned char get_resp[5] = { SIM_CMD_GET_RESPONSE }; - size_t len, rlen; - - if (sim_type == SCARD_USIM) { - cmd[0] = USIM_CLA; - cmd[3] = 0x04; - get_resp[0] = USIM_CLA; - } - - wpa_printf(MSG_DEBUG, "SCARD: select file %04x", file_id); - if (aid) { - wpa_hexdump(MSG_DEBUG, "SCARD: select file by AID", - aid, aidlen); - if (5 + aidlen > sizeof(cmd)) - return -1; - cmd[2] = 0x04; /* Select by AID */ - cmd[4] = aidlen; /* len */ - os_memcpy(cmd + 5, aid, aidlen); - cmdlen = 5 + aidlen; - } else { - cmd[5] = file_id >> 8; - cmd[6] = file_id & 0xff; - cmdlen = 7; - } - len = sizeof(resp); - ret = scard_transmit(scard, cmd, cmdlen, resp, &len); - if (ret != SCARD_S_SUCCESS) { - wpa_printf(MSG_WARNING, "SCARD: SCardTransmit failed " - "(err=0x%lx)", ret); - return -1; - } - - if (len != 2) { - wpa_printf(MSG_WARNING, "SCARD: unexpected resp len " - "%d (expected 2)", (int) len); - return -1; - } - - if (resp[0] == 0x98 && resp[1] == 0x04) { - /* Security status not satisfied (PIN_WLAN) */ - wpa_printf(MSG_WARNING, "SCARD: Security status not satisfied " - "(PIN_WLAN)"); - return -1; - } - - if (resp[0] == 0x6e) { - wpa_printf(MSG_DEBUG, "SCARD: used CLA not supported"); - return -1; - } - - if (resp[0] != 0x6c && resp[0] != 0x9f && resp[0] != 0x61) { - wpa_printf(MSG_WARNING, "SCARD: unexpected response 0x%02x " - "(expected 0x61, 0x6c, or 0x9f)", resp[0]); - return -1; - } - /* Normal ending of command; resp[1] bytes available */ - get_resp[4] = resp[1]; - wpa_printf(MSG_DEBUG, "SCARD: trying to get response (%d bytes)", - resp[1]); - - rlen = *buf_len; - ret = scard_transmit(scard, get_resp, sizeof(get_resp), buf, &rlen); - if (ret == SCARD_S_SUCCESS) { - *buf_len = resp[1] < rlen ? resp[1] : rlen; - return 0; - } - - wpa_printf(MSG_WARNING, "SCARD: SCardTransmit err=0x%lx\n", ret); - return -1; -} - - -static int scard_select_file(struct scard_data *scard, unsigned short file_id, - unsigned char *buf, size_t *buf_len) -{ - return _scard_select_file(scard, file_id, buf, buf_len, - scard->sim_type, NULL, 0); -} - - -static int scard_get_record_len(struct scard_data *scard, unsigned char recnum, - unsigned char mode) -{ - unsigned char buf[255]; - unsigned char cmd[5] = { SIM_CMD_READ_RECORD /* , len */ }; - size_t blen; - long ret; - - if (scard->sim_type == SCARD_USIM) - cmd[0] = USIM_CLA; - cmd[2] = recnum; - cmd[3] = mode; - cmd[4] = sizeof(buf); - - blen = sizeof(buf); - ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen); - if (ret != SCARD_S_SUCCESS) { - wpa_printf(MSG_DEBUG, "SCARD: failed to determine file " - "length for record %d", recnum); - return -1; - } - - wpa_hexdump(MSG_DEBUG, "SCARD: file length determination response", - buf, blen); - - if (blen < 2 || buf[0] != 0x6c) { - wpa_printf(MSG_DEBUG, "SCARD: unexpected response to file " - "length determination"); - return -1; - } - - return buf[1]; -} - - -static int scard_read_record(struct scard_data *scard, - unsigned char *data, size_t len, - unsigned char recnum, unsigned char mode) -{ - unsigned char cmd[5] = { SIM_CMD_READ_RECORD /* , len */ }; - size_t blen = len + 3; - unsigned char *buf; - long ret; - - if (scard->sim_type == SCARD_USIM) - cmd[0] = USIM_CLA; - cmd[2] = recnum; - cmd[3] = mode; - cmd[4] = len; - - buf = os_malloc(blen); - if (buf == NULL) - return -1; - - ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen); - if (ret != SCARD_S_SUCCESS) { - os_free(buf); - return -2; - } - if (blen != len + 2) { - wpa_printf(MSG_DEBUG, "SCARD: record read returned unexpected " - "length %ld (expected %ld)", - (long) blen, (long) len + 2); - os_free(buf); - return -3; - } - - if (buf[len] != 0x90 || buf[len + 1] != 0x00) { - wpa_printf(MSG_DEBUG, "SCARD: record read returned unexpected " - "status %02x %02x (expected 90 00)", - buf[len], buf[len + 1]); - os_free(buf); - return -4; - } - - os_memcpy(data, buf, len); - os_free(buf); - - return 0; -} - - -static int scard_read_file(struct scard_data *scard, - unsigned char *data, size_t len) -{ - unsigned char cmd[5] = { SIM_CMD_READ_BIN /* , len */ }; - size_t blen = len + 3; - unsigned char *buf; - long ret; - - cmd[4] = len; - - buf = os_malloc(blen); - if (buf == NULL) - return -1; - - if (scard->sim_type == SCARD_USIM) - cmd[0] = USIM_CLA; - ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen); - if (ret != SCARD_S_SUCCESS) { - os_free(buf); - return -2; - } - if (blen != len + 2) { - wpa_printf(MSG_DEBUG, "SCARD: file read returned unexpected " - "length %ld (expected %ld)", - (long) blen, (long) len + 2); - os_free(buf); - return -3; - } - - if (buf[len] != 0x90 || buf[len + 1] != 0x00) { - wpa_printf(MSG_DEBUG, "SCARD: file read returned unexpected " - "status %02x %02x (expected 90 00)", - buf[len], buf[len + 1]); - os_free(buf); - return -4; - } - - os_memcpy(data, buf, len); - os_free(buf); - - return 0; -} - - -static int scard_verify_pin(struct scard_data *scard, const char *pin) -{ - long ret; - unsigned char resp[3]; - unsigned char cmd[5 + 8] = { SIM_CMD_VERIFY_CHV1 }; - size_t len; - - wpa_printf(MSG_DEBUG, "SCARD: verifying PIN"); - - if (pin == NULL || os_strlen(pin) > 8) - return -1; - - if (scard->sim_type == SCARD_USIM) - cmd[0] = USIM_CLA; - os_memcpy(cmd + 5, pin, os_strlen(pin)); - os_memset(cmd + 5 + os_strlen(pin), 0xff, 8 - os_strlen(pin)); - - len = sizeof(resp); - ret = scard_transmit(scard, cmd, sizeof(cmd), resp, &len); - if (ret != SCARD_S_SUCCESS) - return -2; - - if (len != 2 || resp[0] != 0x90 || resp[1] != 0x00) { - wpa_printf(MSG_WARNING, "SCARD: PIN verification failed"); - return -1; - } - - wpa_printf(MSG_DEBUG, "SCARD: PIN verified successfully"); - return 0; -} - - -/** - * scard_get_imsi - Read IMSI from SIM/USIM card - * @scard: Pointer to private data from scard_init() - * @imsi: Buffer for IMSI - * @len: Length of imsi buffer; set to IMSI length on success - * Returns: 0 on success, -1 if IMSI file cannot be selected, -2 if IMSI file - * selection returns invalid result code, -3 if parsing FSP template file fails - * (USIM only), -4 if IMSI does not fit in the provided imsi buffer (len is set - * to needed length), -5 if reading IMSI file fails. - * - * This function can be used to read IMSI from the SIM/USIM card. If the IMSI - * file is PIN protected, scard_set_pin() must have been used to set the - * correct PIN code before calling scard_get_imsi(). - */ -int scard_get_imsi(struct scard_data *scard, char *imsi, size_t *len) -{ - unsigned char buf[100]; - size_t blen, imsilen, i; - char *pos; - - wpa_printf(MSG_DEBUG, "SCARD: reading IMSI from (GSM) EF-IMSI"); - blen = sizeof(buf); - if (scard_select_file(scard, SCARD_FILE_GSM_EF_IMSI, buf, &blen)) - return -1; - if (blen < 4) { - wpa_printf(MSG_WARNING, "SCARD: too short (GSM) EF-IMSI " - "header (len=%ld)", (long) blen); - return -2; - } - - if (scard->sim_type == SCARD_GSM_SIM) { - blen = (buf[2] << 8) | buf[3]; - } else { - int file_size; - if (scard_parse_fsp_templ(buf, blen, NULL, &file_size)) - return -3; - blen = file_size; - } - if (blen < 2 || blen > sizeof(buf)) { - wpa_printf(MSG_DEBUG, "SCARD: invalid IMSI file length=%ld", - (long) blen); - return -3; - } - - imsilen = (blen - 2) * 2 + 1; - wpa_printf(MSG_DEBUG, "SCARD: IMSI file length=%ld imsilen=%ld", - (long) blen, (long) imsilen); - if (blen < 2 || imsilen > *len) { - *len = imsilen; - return -4; - } - - if (scard_read_file(scard, buf, blen)) - return -5; - - pos = imsi; - *pos++ = '0' + (buf[1] >> 4 & 0x0f); - for (i = 2; i < blen; i++) { - unsigned char digit; - - digit = buf[i] & 0x0f; - if (digit < 10) - *pos++ = '0' + digit; - else - imsilen--; - - digit = buf[i] >> 4 & 0x0f; - if (digit < 10) - *pos++ = '0' + digit; - else - imsilen--; - } - *len = imsilen; - - return 0; -} - - -/** - * scard_gsm_auth - Run GSM authentication command on SIM card - * @scard: Pointer to private data from scard_init() - * @_rand: 16-byte RAND value from HLR/AuC - * @sres: 4-byte buffer for SRES - * @kc: 8-byte buffer for Kc - * Returns: 0 on success, -1 if SIM/USIM connection has not been initialized, - * -2 if authentication command execution fails, -3 if unknown response code - * for authentication command is received, -4 if reading of response fails, - * -5 if if response data is of unexpected length - * - * This function performs GSM authentication using SIM/USIM card and the - * provided RAND value from HLR/AuC. If authentication command can be completed - * successfully, SRES and Kc values will be written into sres and kc buffers. - */ -int scard_gsm_auth(struct scard_data *scard, const unsigned char *_rand, - unsigned char *sres, unsigned char *kc) -{ - unsigned char cmd[5 + 1 + 16] = { SIM_CMD_RUN_GSM_ALG }; - int cmdlen; - unsigned char get_resp[5] = { SIM_CMD_GET_RESPONSE }; - unsigned char resp[3], buf[12 + 3 + 2]; - size_t len; - long ret; - - if (scard == NULL) - return -1; - - wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - RAND", _rand, 16); - if (scard->sim_type == SCARD_GSM_SIM) { - cmdlen = 5 + 16; - os_memcpy(cmd + 5, _rand, 16); - } else { - cmdlen = 5 + 1 + 16; - cmd[0] = USIM_CLA; - cmd[3] = 0x80; - cmd[4] = 17; - cmd[5] = 16; - os_memcpy(cmd + 6, _rand, 16); - } - len = sizeof(resp); - ret = scard_transmit(scard, cmd, cmdlen, resp, &len); - if (ret != SCARD_S_SUCCESS) - return -2; - - if ((scard->sim_type == SCARD_GSM_SIM && - (len != 2 || resp[0] != 0x9f || resp[1] != 0x0c)) || - (scard->sim_type == SCARD_USIM && - (len != 2 || resp[0] != 0x61 || resp[1] != 0x0e))) { - wpa_printf(MSG_WARNING, "SCARD: unexpected response for GSM " - "auth request (len=%ld resp=%02x %02x)", - (long) len, resp[0], resp[1]); - return -3; - } - get_resp[4] = resp[1]; - - len = sizeof(buf); - ret = scard_transmit(scard, get_resp, sizeof(get_resp), buf, &len); - if (ret != SCARD_S_SUCCESS) - return -4; - - if (scard->sim_type == SCARD_GSM_SIM) { - if (len != 4 + 8 + 2) { - wpa_printf(MSG_WARNING, "SCARD: unexpected data " - "length for GSM auth (len=%ld, expected 14)", - (long) len); - return -5; - } - os_memcpy(sres, buf, 4); - os_memcpy(kc, buf + 4, 8); - } else { - if (len != 1 + 4 + 1 + 8 + 2) { - wpa_printf(MSG_WARNING, "SCARD: unexpected data " - "length for USIM auth (len=%ld, " - "expected 16)", (long) len); - return -5; - } - if (buf[0] != 4 || buf[5] != 8) { - wpa_printf(MSG_WARNING, "SCARD: unexpected SREC/Kc " - "length (%d %d, expected 4 8)", - buf[0], buf[5]); - } - os_memcpy(sres, buf + 1, 4); - os_memcpy(kc, buf + 6, 8); - } - - wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - SRES", sres, 4); - wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - Kc", kc, 8); - - return 0; -} - - -/** - * scard_umts_auth - Run UMTS authentication command on USIM card - * @scard: Pointer to private data from scard_init() - * @_rand: 16-byte RAND value from HLR/AuC - * @autn: 16-byte AUTN value from HLR/AuC - * @res: 16-byte buffer for RES - * @res_len: Variable that will be set to RES length - * @ik: 16-byte buffer for IK - * @ck: 16-byte buffer for CK - * @auts: 14-byte buffer for AUTS - * Returns: 0 on success, -1 on failure, or -2 if USIM reports synchronization - * failure - * - * This function performs AKA authentication using USIM card and the provided - * RAND and AUTN values from HLR/AuC. If authentication command can be - * completed successfully, RES, IK, and CK values will be written into provided - * buffers and res_len is set to length of received RES value. If USIM reports - * synchronization failure, the received AUTS value will be written into auts - * buffer. In this case, RES, IK, and CK are not valid. - */ -int scard_umts_auth(struct scard_data *scard, const unsigned char *_rand, - const unsigned char *autn, - unsigned char *res, size_t *res_len, - unsigned char *ik, unsigned char *ck, unsigned char *auts) -{ - unsigned char cmd[5 + 1 + AKA_RAND_LEN + 1 + AKA_AUTN_LEN] = - { USIM_CMD_RUN_UMTS_ALG }; - unsigned char get_resp[5] = { USIM_CMD_GET_RESPONSE }; - unsigned char resp[3], buf[64], *pos, *end; - size_t len; - long ret; - - if (scard == NULL) - return -1; - - if (scard->sim_type == SCARD_GSM_SIM) { - wpa_printf(MSG_ERROR, "SCARD: Non-USIM card - cannot do UMTS " - "auth"); - return -1; - } - - wpa_hexdump(MSG_DEBUG, "SCARD: UMTS auth - RAND", _rand, AKA_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "SCARD: UMTS auth - AUTN", autn, AKA_AUTN_LEN); - cmd[5] = AKA_RAND_LEN; - os_memcpy(cmd + 6, _rand, AKA_RAND_LEN); - cmd[6 + AKA_RAND_LEN] = AKA_AUTN_LEN; - os_memcpy(cmd + 6 + AKA_RAND_LEN + 1, autn, AKA_AUTN_LEN); - - len = sizeof(resp); - ret = scard_transmit(scard, cmd, sizeof(cmd), resp, &len); - if (ret != SCARD_S_SUCCESS) - return -1; - - if (len <= sizeof(resp)) - wpa_hexdump(MSG_DEBUG, "SCARD: UMTS alg response", resp, len); - - if (len == 2 && resp[0] == 0x98 && resp[1] == 0x62) { - wpa_printf(MSG_WARNING, "SCARD: UMTS auth failed - " - "MAC != XMAC"); - return -1; - } else if (len != 2 || resp[0] != 0x61) { - wpa_printf(MSG_WARNING, "SCARD: unexpected response for UMTS " - "auth request (len=%ld resp=%02x %02x)", - (long) len, resp[0], resp[1]); - return -1; - } - get_resp[4] = resp[1]; - - len = sizeof(buf); - ret = scard_transmit(scard, get_resp, sizeof(get_resp), buf, &len); - if (ret != SCARD_S_SUCCESS || len > sizeof(buf)) - return -1; - - wpa_hexdump(MSG_DEBUG, "SCARD: UMTS get response result", buf, len); - if (len >= 2 + AKA_AUTS_LEN && buf[0] == 0xdc && - buf[1] == AKA_AUTS_LEN) { - wpa_printf(MSG_DEBUG, "SCARD: UMTS Synchronization-Failure"); - os_memcpy(auts, buf + 2, AKA_AUTS_LEN); - wpa_hexdump(MSG_DEBUG, "SCARD: AUTS", auts, AKA_AUTS_LEN); - return -2; - } else if (len >= 6 + IK_LEN + CK_LEN && buf[0] == 0xdb) { - pos = buf + 1; - end = buf + len; - - /* RES */ - if (pos[0] > RES_MAX_LEN || pos + pos[0] > end) { - wpa_printf(MSG_DEBUG, "SCARD: Invalid RES"); - return -1; - } - *res_len = *pos++; - os_memcpy(res, pos, *res_len); - pos += *res_len; - wpa_hexdump(MSG_DEBUG, "SCARD: RES", res, *res_len); - - /* CK */ - if (pos[0] != CK_LEN || pos + CK_LEN > end) { - wpa_printf(MSG_DEBUG, "SCARD: Invalid CK"); - return -1; - } - pos++; - os_memcpy(ck, pos, CK_LEN); - pos += CK_LEN; - wpa_hexdump(MSG_DEBUG, "SCARD: CK", ck, CK_LEN); - - /* IK */ - if (pos[0] != IK_LEN || pos + IK_LEN > end) { - wpa_printf(MSG_DEBUG, "SCARD: Invalid IK"); - return -1; - } - pos++; - os_memcpy(ik, pos, IK_LEN); - pos += IK_LEN; - wpa_hexdump(MSG_DEBUG, "SCARD: IK", ik, IK_LEN); - - return 0; - } - - wpa_printf(MSG_DEBUG, "SCARD: Unrecognized response"); - return -1; -} diff --git a/contrib/hostapd/src/utils/pcsc_funcs.h b/contrib/hostapd/src/utils/pcsc_funcs.h deleted file mode 100644 index 543f7c5984..0000000000 --- a/contrib/hostapd/src/utils/pcsc_funcs.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * WPA Supplicant / PC/SC smartcard interface for USIM, GSM SIM - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef PCSC_FUNCS_H -#define PCSC_FUNCS_H - -/* GSM files - * File type in first octet: - * 3F = Master File - * 7F = Dedicated File - * 2F = Elementary File under the Master File - * 6F = Elementary File under a Dedicated File - */ -#define SCARD_FILE_MF 0x3F00 -#define SCARD_FILE_GSM_DF 0x7F20 -#define SCARD_FILE_UMTS_DF 0x7F50 -#define SCARD_FILE_GSM_EF_IMSI 0x6F07 -#define SCARD_FILE_EF_DIR 0x2F00 -#define SCARD_FILE_EF_ICCID 0x2FE2 -#define SCARD_FILE_EF_CK 0x6FE1 -#define SCARD_FILE_EF_IK 0x6FE2 - -#define SCARD_CHV1_OFFSET 13 -#define SCARD_CHV1_FLAG 0x80 - -typedef enum { - SCARD_GSM_SIM_ONLY, - SCARD_USIM_ONLY, - SCARD_TRY_BOTH -} scard_sim_type; - - -#ifdef PCSC_FUNCS -struct scard_data * scard_init(scard_sim_type sim_type); -void scard_deinit(struct scard_data *scard); - -int scard_set_pin(struct scard_data *scard, const char *pin); -int scard_get_imsi(struct scard_data *scard, char *imsi, size_t *len); -int scard_gsm_auth(struct scard_data *scard, const unsigned char *_rand, - unsigned char *sres, unsigned char *kc); -int scard_umts_auth(struct scard_data *scard, const unsigned char *_rand, - const unsigned char *autn, - unsigned char *res, size_t *res_len, - unsigned char *ik, unsigned char *ck, unsigned char *auts); - -#else /* PCSC_FUNCS */ - -#define scard_init(s) NULL -#define scard_deinit(s) do { } while (0) -#define scard_set_pin(s, p) -1 -#define scard_get_imsi(s, i, l) -1 -#define scard_gsm_auth(s, r, s2, k) -1 -#define scard_umts_auth(s, r, a, r2, rl, i, c, a2) -1 - -#endif /* PCSC_FUNCS */ - -#endif /* PCSC_FUNCS_H */ diff --git a/contrib/hostapd/src/utils/state_machine.h b/contrib/hostapd/src/utils/state_machine.h deleted file mode 100644 index 31f667217f..0000000000 --- a/contrib/hostapd/src/utils/state_machine.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * wpa_supplicant/hostapd - State machine definitions - * Copyright (c) 2002-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file includes a set of pre-processor macros that can be used to - * implement a state machine. In addition to including this header file, each - * file implementing a state machine must define STATE_MACHINE_DATA to be the - * data structure including state variables (enum machine_state, - * Boolean changed), and STATE_MACHINE_DEBUG_PREFIX to be a string that is used - * as a prefix for all debug messages. If SM_ENTRY_MA macro is used to define - * a group of state machines with shared data structure, STATE_MACHINE_ADDR - * needs to be defined to point to the MAC address used in debug output. - * SM_ENTRY_M macro can be used to define similar group of state machines - * without this additional debug info. - */ - -#ifndef STATE_MACHINE_H -#define STATE_MACHINE_H - -/** - * SM_STATE - Declaration of a state machine function - * @machine: State machine name - * @state: State machine state - * - * This macro is used to declare a state machine function. It is used in place - * of a C function definition to declare functions to be run when the state is - * entered by calling SM_ENTER or SM_ENTER_GLOBAL. - */ -#define SM_STATE(machine, state) \ -static void sm_ ## machine ## _ ## state ## _Enter(STATE_MACHINE_DATA *sm, \ - int global) - -/** - * SM_ENTRY - State machine function entry point - * @machine: State machine name - * @state: State machine state - * - * This macro is used inside each state machine function declared with - * SM_STATE. SM_ENTRY should be in the beginning of the function body, but - * after declaration of possible local variables. This macro prints debug - * information about state transition and update the state machine state. - */ -#define SM_ENTRY(machine, state) \ -if (!global || sm->machine ## _state != machine ## _ ## state) { \ - sm->changed = TRUE; \ - wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " #machine \ - " entering state " #state); \ -} \ -sm->machine ## _state = machine ## _ ## state; - -/** - * SM_ENTRY_M - State machine function entry point for state machine group - * @machine: State machine name - * @_state: State machine state - * @data: State variable prefix (full variable: prefix_state) - * - * This macro is like SM_ENTRY, but for state machine groups that use a shared - * data structure for more than one state machine. Both machine and prefix - * parameters are set to "sub-state machine" name. prefix is used to allow more - * than one state variable to be stored in the same data structure. - */ -#define SM_ENTRY_M(machine, _state, data) \ -if (!global || sm->data ## _ ## state != machine ## _ ## _state) { \ - sm->changed = TRUE; \ - wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " \ - #machine " entering state " #_state); \ -} \ -sm->data ## _ ## state = machine ## _ ## _state; - -/** - * SM_ENTRY_MA - State machine function entry point for state machine group - * @machine: State machine name - * @_state: State machine state - * @data: State variable prefix (full variable: prefix_state) - * - * This macro is like SM_ENTRY_M, but a MAC address is included in debug - * output. STATE_MACHINE_ADDR has to be defined to point to the MAC address to - * be included in debug. - */ -#define SM_ENTRY_MA(machine, _state, data) \ -if (!global || sm->data ## _ ## state != machine ## _ ## _state) { \ - sm->changed = TRUE; \ - wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " MACSTR " " \ - #machine " entering state " #_state, \ - MAC2STR(STATE_MACHINE_ADDR)); \ -} \ -sm->data ## _ ## state = machine ## _ ## _state; - -/** - * SM_ENTER - Enter a new state machine state - * @machine: State machine name - * @state: State machine state - * - * This macro expands to a function call to a state machine function defined - * with SM_STATE macro. SM_ENTER is used in a state machine step function to - * move the state machine to a new state. - */ -#define SM_ENTER(machine, state) \ -sm_ ## machine ## _ ## state ## _Enter(sm, 0) - -/** - * SM_ENTER_GLOBAL - Enter a new state machine state based on global rule - * @machine: State machine name - * @state: State machine state - * - * This macro is like SM_ENTER, but this is used when entering a new state - * based on a global (not specific to any particular state) rule. A separate - * macro is used to avoid unwanted debug message floods when the same global - * rule is forcing a state machine to remain in on state. - */ -#define SM_ENTER_GLOBAL(machine, state) \ -sm_ ## machine ## _ ## state ## _Enter(sm, 1) - -/** - * SM_STEP - Declaration of a state machine step function - * @machine: State machine name - * - * This macro is used to declare a state machine step function. It is used in - * place of a C function definition to declare a function that is used to move - * state machine to a new state based on state variables. This function uses - * SM_ENTER and SM_ENTER_GLOBAL macros to enter new state. - */ -#define SM_STEP(machine) \ -static void sm_ ## machine ## _Step(STATE_MACHINE_DATA *sm) - -/** - * SM_STEP_RUN - Call the state machine step function - * @machine: State machine name - * - * This macro expands to a function call to a state machine step function - * defined with SM_STEP macro. - */ -#define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm) - -#endif /* STATE_MACHINE_H */ diff --git a/contrib/hostapd/src/utils/uuid.c b/contrib/hostapd/src/utils/uuid.c deleted file mode 100644 index 620d3d610c..0000000000 --- a/contrib/hostapd/src/utils/uuid.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Universally Unique IDentifier (UUID) - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto.h" -#include "sha1.h" -#include "uuid.h" - -int uuid_str2bin(const char *str, u8 *bin) -{ - const char *pos; - u8 *opos; - - pos = str; - opos = bin; - - if (hexstr2bin(pos, opos, 4)) - return -1; - pos += 8; - opos += 4; - - if (*pos++ != '-' || hexstr2bin(pos, opos, 2)) - return -1; - pos += 4; - opos += 2; - - if (*pos++ != '-' || hexstr2bin(pos, opos, 2)) - return -1; - pos += 4; - opos += 2; - - if (*pos++ != '-' || hexstr2bin(pos, opos, 2)) - return -1; - pos += 4; - opos += 2; - - if (*pos++ != '-' || hexstr2bin(pos, opos, 6)) - return -1; - - return 0; -} - - -int uuid_bin2str(const u8 *bin, char *str, size_t max_len) -{ - int len; - len = os_snprintf(str, max_len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-" - "%02x%02x-%02x%02x%02x%02x%02x%02x", - bin[0], bin[1], bin[2], bin[3], - bin[4], bin[5], bin[6], bin[7], - bin[8], bin[9], bin[10], bin[11], - bin[12], bin[13], bin[14], bin[15]); - if (len < 0 || (size_t) len >= max_len) - return -1; - return 0; -} - - -int is_nil_uuid(const u8 *uuid) -{ - int i; - for (i = 0; i < UUID_LEN; i++) - if (uuid[i]) - return 0; - return 1; -} - - -void uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid) -{ - const u8 *addr[2]; - size_t len[2]; - u8 hash[SHA1_MAC_LEN]; - u8 nsid[16] = { - 0x52, 0x64, 0x80, 0xf8, - 0xc9, 0x9b, - 0x4b, 0xe5, - 0xa6, 0x55, - 0x58, 0xed, 0x5f, 0x5d, 0x60, 0x84 - }; - - addr[0] = nsid; - len[0] = sizeof(nsid); - addr[1] = mac_addr; - len[1] = 6; - sha1_vector(2, addr, len, hash); - os_memcpy(uuid, hash, 16); - - /* Version: 5 = named-based version using SHA-1 */ - uuid[6] = (5 << 4) | (uuid[6] & 0x0f); - - /* Variant specified in RFC 4122 */ - uuid[8] = 0x80 | (uuid[8] & 0x3f); -} diff --git a/contrib/hostapd/src/utils/uuid.h b/contrib/hostapd/src/utils/uuid.h deleted file mode 100644 index 9fc2ba0682..0000000000 --- a/contrib/hostapd/src/utils/uuid.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Universally Unique IDentifier (UUID) - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef UUID_H -#define UUID_H - -#define UUID_LEN 16 - -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); -void uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid); - -#endif /* UUID_H */ diff --git a/contrib/hostapd/src/utils/wpa_debug.c b/contrib/hostapd/src/utils/wpa_debug.c deleted file mode 100644 index 4dd073230d..0000000000 --- a/contrib/hostapd/src/utils/wpa_debug.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - * wpa_supplicant/hostapd / Debug prints - * Copyright (c) 2002-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" - - -#ifdef CONFIG_DEBUG_FILE -static FILE *out_file = NULL; -#endif /* CONFIG_DEBUG_FILE */ -int wpa_debug_level = MSG_INFO; -int wpa_debug_show_keys = 0; -int wpa_debug_timestamp = 0; - - -#ifndef CONFIG_NO_STDOUT_DEBUG - -void wpa_debug_print_timestamp(void) -{ - struct os_time tv; - - if (!wpa_debug_timestamp) - return; - - os_get_time(&tv); -#ifdef CONFIG_DEBUG_FILE - if (out_file) { - fprintf(out_file, "%ld.%06u: ", (long) tv.sec, - (unsigned int) tv.usec); - } else -#endif /* CONFIG_DEBUG_FILE */ - printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec); -} - - -/** - * wpa_printf - conditional printf - * @level: priority level (MSG_*) of the message - * @fmt: printf format string, followed by optional arguments - * - * This function is used to print conditional debugging and error messages. The - * output may be directed to stdout, stderr, and/or syslog based on - * configuration. - * - * Note: New line '\n' is added to the end of the text when printing to stdout. - */ -void wpa_printf(int level, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - if (level >= wpa_debug_level) { - wpa_debug_print_timestamp(); -#ifdef CONFIG_DEBUG_FILE - if (out_file) { - vfprintf(out_file, fmt, ap); - fprintf(out_file, "\n"); - } else { -#endif /* CONFIG_DEBUG_FILE */ - vprintf(fmt, ap); - printf("\n"); -#ifdef CONFIG_DEBUG_FILE - } -#endif /* CONFIG_DEBUG_FILE */ - } - va_end(ap); -} - - -static void _wpa_hexdump(int level, const char *title, const u8 *buf, - size_t len, int show) -{ - size_t i; - if (level < wpa_debug_level) - return; - wpa_debug_print_timestamp(); -#ifdef CONFIG_DEBUG_FILE - if (out_file) { - fprintf(out_file, "%s - hexdump(len=%lu):", - title, (unsigned long) len); - if (buf == NULL) { - fprintf(out_file, " [NULL]"); - } else if (show) { - for (i = 0; i < len; i++) - fprintf(out_file, " %02x", buf[i]); - } else { - fprintf(out_file, " [REMOVED]"); - } - fprintf(out_file, "\n"); - } else { -#endif /* CONFIG_DEBUG_FILE */ - printf("%s - hexdump(len=%lu):", title, (unsigned long) len); - if (buf == NULL) { - printf(" [NULL]"); - } else if (show) { - for (i = 0; i < len; i++) - printf(" %02x", buf[i]); - } else { - printf(" [REMOVED]"); - } - printf("\n"); -#ifdef CONFIG_DEBUG_FILE - } -#endif /* CONFIG_DEBUG_FILE */ -} - -void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len) -{ - _wpa_hexdump(level, title, buf, len, 1); -} - - -void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len) -{ - _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys); -} - - -static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf, - size_t len, int show) -{ - size_t i, llen; - const u8 *pos = buf; - const size_t line_len = 16; - - if (level < wpa_debug_level) - return; - wpa_debug_print_timestamp(); -#ifdef CONFIG_DEBUG_FILE - if (out_file) { - if (!show) { - fprintf(out_file, - "%s - hexdump_ascii(len=%lu): [REMOVED]\n", - title, (unsigned long) len); - return; - } - if (buf == NULL) { - fprintf(out_file, - "%s - hexdump_ascii(len=%lu): [NULL]\n", - title, (unsigned long) len); - return; - } - fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n", - title, (unsigned long) len); - while (len) { - llen = len > line_len ? line_len : len; - fprintf(out_file, " "); - for (i = 0; i < llen; i++) - fprintf(out_file, " %02x", pos[i]); - for (i = llen; i < line_len; i++) - fprintf(out_file, " "); - fprintf(out_file, " "); - for (i = 0; i < llen; i++) { - if (isprint(pos[i])) - fprintf(out_file, "%c", pos[i]); - else - fprintf(out_file, "_"); - } - for (i = llen; i < line_len; i++) - fprintf(out_file, " "); - fprintf(out_file, "\n"); - pos += llen; - len -= llen; - } - } else { -#endif /* CONFIG_DEBUG_FILE */ - if (!show) { - printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n", - title, (unsigned long) len); - return; - } - if (buf == NULL) { - printf("%s - hexdump_ascii(len=%lu): [NULL]\n", - title, (unsigned long) len); - return; - } - printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len); - while (len) { - llen = len > line_len ? line_len : len; - printf(" "); - for (i = 0; i < llen; i++) - printf(" %02x", pos[i]); - for (i = llen; i < line_len; i++) - printf(" "); - printf(" "); - for (i = 0; i < llen; i++) { - if (isprint(pos[i])) - printf("%c", pos[i]); - else - printf("_"); - } - for (i = llen; i < line_len; i++) - printf(" "); - printf("\n"); - pos += llen; - len -= llen; - } -#ifdef CONFIG_DEBUG_FILE - } -#endif /* CONFIG_DEBUG_FILE */ -} - - -void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len) -{ - _wpa_hexdump_ascii(level, title, buf, len, 1); -} - - -void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf, - size_t len) -{ - _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys); -} - - -int wpa_debug_open_file(const char *path) -{ -#ifdef CONFIG_DEBUG_FILE - if (!path) - return 0; - out_file = fopen(path, "a"); - if (out_file == NULL) { - wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open " - "output file, using standard output"); - return -1; - } -#ifndef _WIN32 - setvbuf(out_file, NULL, _IOLBF, 0); -#endif /* _WIN32 */ -#endif /* CONFIG_DEBUG_FILE */ - return 0; -} - - -void wpa_debug_close_file(void) -{ -#ifdef CONFIG_DEBUG_FILE - if (!out_file) - return; - fclose(out_file); - out_file = NULL; -#endif /* CONFIG_DEBUG_FILE */ -} - -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - -#ifndef CONFIG_NO_WPA_MSG -static wpa_msg_cb_func wpa_msg_cb = NULL; - -void wpa_msg_register_cb(wpa_msg_cb_func func) -{ - wpa_msg_cb = func; -} - - -void wpa_msg(void *ctx, int level, const char *fmt, ...) -{ - va_list ap; - char *buf; - const int buflen = 2048; - int len; - - buf = os_malloc(buflen); - if (buf == NULL) { - wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message " - "buffer"); - return; - } - va_start(ap, fmt); - len = vsnprintf(buf, buflen, fmt, ap); - va_end(ap); - wpa_printf(level, "%s", buf); - if (wpa_msg_cb) - wpa_msg_cb(ctx, level, buf, len); - os_free(buf); -} - - -void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) -{ - va_list ap; - char *buf; - const int buflen = 2048; - int len; - - if (!wpa_msg_cb) - return; - - buf = os_malloc(buflen); - if (buf == NULL) { - wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate " - "message buffer"); - return; - } - va_start(ap, fmt); - len = vsnprintf(buf, buflen, fmt, ap); - va_end(ap); - wpa_msg_cb(ctx, level, buf, len); - os_free(buf); -} -#endif /* CONFIG_NO_WPA_MSG */ - - -#ifndef CONFIG_NO_HOSTAPD_LOGGER -static hostapd_logger_cb_func hostapd_logger_cb = NULL; - -void hostapd_logger_register_cb(hostapd_logger_cb_func func) -{ - hostapd_logger_cb = func; -} - - -void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, - const char *fmt, ...) -{ - va_list ap; - char *buf; - const int buflen = 2048; - int len; - - buf = os_malloc(buflen); - if (buf == NULL) { - wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate " - "message buffer"); - return; - } - va_start(ap, fmt); - len = vsnprintf(buf, buflen, fmt, ap); - va_end(ap); - if (hostapd_logger_cb) - hostapd_logger_cb(ctx, addr, module, level, buf, len); - else - wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf); - os_free(buf); -} -#endif /* CONFIG_NO_HOSTAPD_LOGGER */ diff --git a/contrib/hostapd/src/utils/wpa_debug.h b/contrib/hostapd/src/utils/wpa_debug.h deleted file mode 100644 index b4010d5427..0000000000 --- a/contrib/hostapd/src/utils/wpa_debug.h +++ /dev/null @@ -1,239 +0,0 @@ -/* - * wpa_supplicant/hostapd / Debug prints - * Copyright (c) 2002-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPA_DEBUG_H -#define WPA_DEBUG_H - -#include "wpabuf.h" - -/* Debugging function - conditional printf and hex dump. Driver wrappers can - * use these for debugging purposes. */ - -enum { MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR }; - -#ifdef CONFIG_NO_STDOUT_DEBUG - -#define wpa_debug_print_timestamp() do { } while (0) -#define wpa_printf(args...) do { } while (0) -#define wpa_hexdump(l,t,b,le) do { } while (0) -#define wpa_hexdump_buf(l,t,b) do { } while (0) -#define wpa_hexdump_key(l,t,b,le) do { } while (0) -#define wpa_hexdump_buf_key(l,t,b) do { } while (0) -#define wpa_hexdump_ascii(l,t,b,le) do { } while (0) -#define wpa_hexdump_ascii_key(l,t,b,le) do { } while (0) -#define wpa_debug_open_file(p) do { } while (0) -#define wpa_debug_close_file() do { } while (0) - -#else /* CONFIG_NO_STDOUT_DEBUG */ - -int wpa_debug_open_file(const char *path); -void wpa_debug_close_file(void); - -/** - * wpa_debug_printf_timestamp - Print timestamp for debug output - * - * This function prints a timestamp in seconds_from_1970.microsoconds - * format if debug output has been configured to include timestamps in debug - * messages. - */ -void wpa_debug_print_timestamp(void); - -/** - * wpa_printf - conditional printf - * @level: priority level (MSG_*) of the message - * @fmt: printf format string, followed by optional arguments - * - * This function is used to print conditional debugging and error messages. The - * output may be directed to stdout, stderr, and/or syslog based on - * configuration. - * - * Note: New line '\n' is added to the end of the text when printing to stdout. - */ -void wpa_printf(int level, const char *fmt, ...) -PRINTF_FORMAT(2, 3); - -/** - * wpa_hexdump - conditional hex dump - * @level: priority level (MSG_*) of the message - * @title: title of for the message - * @buf: data buffer to be dumped - * @len: length of the buf - * - * This function is used to print conditional debugging and error messages. The - * output may be directed to stdout, stderr, and/or syslog based on - * configuration. The contents of buf is printed out has hex dump. - */ -void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len); - -static inline void wpa_hexdump_buf(int level, const char *title, - const struct wpabuf *buf) -{ - wpa_hexdump(level, title, wpabuf_head(buf), wpabuf_len(buf)); -} - -/** - * wpa_hexdump_key - conditional hex dump, hide keys - * @level: priority level (MSG_*) of the message - * @title: title of for the message - * @buf: data buffer to be dumped - * @len: length of the buf - * - * This function is used to print conditional debugging and error messages. The - * output may be directed to stdout, stderr, and/or syslog based on - * configuration. The contents of buf is printed out has hex dump. This works - * like wpa_hexdump(), but by default, does not include secret keys (passwords, - * etc.) in debug output. - */ -void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len); - -static inline void wpa_hexdump_buf_key(int level, const char *title, - const struct wpabuf *buf) -{ - wpa_hexdump_key(level, title, wpabuf_head(buf), wpabuf_len(buf)); -} - -/** - * wpa_hexdump_ascii - conditional hex dump - * @level: priority level (MSG_*) of the message - * @title: title of for the message - * @buf: data buffer to be dumped - * @len: length of the buf - * - * This function is used to print conditional debugging and error messages. The - * output may be directed to stdout, stderr, and/or syslog based on - * configuration. The contents of buf is printed out has hex dump with both - * the hex numbers and ASCII characters (for printable range) are shown. 16 - * bytes per line will be shown. - */ -void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, - size_t len); - -/** - * wpa_hexdump_ascii_key - conditional hex dump, hide keys - * @level: priority level (MSG_*) of the message - * @title: title of for the message - * @buf: data buffer to be dumped - * @len: length of the buf - * - * This function is used to print conditional debugging and error messages. The - * output may be directed to stdout, stderr, and/or syslog based on - * configuration. The contents of buf is printed out has hex dump with both - * the hex numbers and ASCII characters (for printable range) are shown. 16 - * bytes per line will be shown. This works like wpa_hexdump_ascii(), but by - * default, does not include secret keys (passwords, etc.) in debug output. - */ -void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf, - size_t len); - -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - -#ifdef CONFIG_NO_WPA_MSG -#define wpa_msg(args...) do { } while (0) -#define wpa_msg_ctrl(args...) do { } while (0) -#define wpa_msg_register_cb(f) do { } while (0) -#else /* CONFIG_NO_WPA_MSG */ -/** - * wpa_msg - Conditional printf for default target and ctrl_iface monitors - * @ctx: Pointer to context data; this is the ctx variable registered - * with struct wpa_driver_ops::init() - * @level: priority level (MSG_*) of the message - * @fmt: printf format string, followed by optional arguments - * - * This function is used to print conditional debugging and error messages. The - * output may be directed to stdout, stderr, and/or syslog based on - * configuration. This function is like wpa_printf(), but it also sends the - * same message to all attached ctrl_iface monitors. - * - * Note: New line '\n' is added to the end of the text when printing to stdout. - */ -void wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4); - -/** - * wpa_msg_ctrl - Conditional printf for ctrl_iface monitors - * @ctx: Pointer to context data; this is the ctx variable registered - * with struct wpa_driver_ops::init() - * @level: priority level (MSG_*) of the message - * @fmt: printf format string, followed by optional arguments - * - * This function is used to print conditional debugging and error messages. - * This function is like wpa_msg(), but it sends the output only to the - * attached ctrl_iface monitors. In other words, it can be used for frequent - * events that do not need to be sent to syslog. - */ -void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) -PRINTF_FORMAT(3, 4); - -typedef void (*wpa_msg_cb_func)(void *ctx, int level, const char *txt, - size_t len); - -/** - * wpa_msg_register_cb - Register callback function for wpa_msg() messages - * @func: Callback function (%NULL to unregister) - */ -void wpa_msg_register_cb(wpa_msg_cb_func func); -#endif /* CONFIG_NO_WPA_MSG */ - - -#ifdef CONFIG_NO_HOSTAPD_LOGGER -#define hostapd_logger(args...) do { } while (0) -#define hostapd_logger_register_cb(f) do { } while (0) -#else /* CONFIG_NO_HOSTAPD_LOGGER */ -void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, - const char *fmt, ...) PRINTF_FORMAT(5, 6); - -typedef void (*hostapd_logger_cb_func)(void *ctx, const u8 *addr, - unsigned int module, int level, - const char *txt, size_t len); - -/** - * hostapd_logger_register_cb - Register callback function for hostapd_logger() - * @func: Callback function (%NULL to unregister) - */ -void hostapd_logger_register_cb(hostapd_logger_cb_func func); -#endif /* CONFIG_NO_HOSTAPD_LOGGER */ - -#define HOSTAPD_MODULE_IEEE80211 0x00000001 -#define HOSTAPD_MODULE_IEEE8021X 0x00000002 -#define HOSTAPD_MODULE_RADIUS 0x00000004 -#define HOSTAPD_MODULE_WPA 0x00000008 -#define HOSTAPD_MODULE_DRIVER 0x00000010 -#define HOSTAPD_MODULE_IAPP 0x00000020 -#define HOSTAPD_MODULE_MLME 0x00000040 - -enum hostapd_logger_level { - HOSTAPD_LEVEL_DEBUG_VERBOSE = 0, - HOSTAPD_LEVEL_DEBUG = 1, - HOSTAPD_LEVEL_INFO = 2, - HOSTAPD_LEVEL_NOTICE = 3, - HOSTAPD_LEVEL_WARNING = 4 -}; - - - -#ifdef EAPOL_TEST -#define WPA_ASSERT(a) \ - do { \ - if (!(a)) { \ - printf("WPA_ASSERT FAILED '" #a "' " \ - "%s %s:%d\n", \ - __FUNCTION__, __FILE__, __LINE__); \ - exit(1); \ - } \ - } while (0) -#else -#define WPA_ASSERT(a) do { } while (0) -#endif - -#endif /* WPA_DEBUG_H */ diff --git a/contrib/hostapd/src/utils/wpabuf.c b/contrib/hostapd/src/utils/wpabuf.c deleted file mode 100644 index 8181912ea9..0000000000 --- a/contrib/hostapd/src/utils/wpabuf.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Dynamic data buffer - * Copyright (c) 2007-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "wpabuf.h" - -static void wpabuf_overflow(const struct wpabuf *buf, size_t len) -{ - wpa_printf(MSG_ERROR, "wpabuf %p (size=%lu used=%lu) overflow len=%lu", - buf, (unsigned long) buf->size, (unsigned long) buf->used, - (unsigned long) len); - abort(); -} - - -int wpabuf_resize(struct wpabuf **_buf, size_t add_len) -{ - struct wpabuf *buf = *_buf; - if (buf == NULL) { - *_buf = wpabuf_alloc(add_len); - return *_buf == NULL ? -1 : 0; - } - if (buf->used + add_len > buf->size) { - unsigned char *nbuf; - if (buf->ext_data) { - nbuf = os_realloc(buf->ext_data, buf->used + add_len); - if (nbuf == NULL) - return -1; - os_memset(nbuf + buf->used, 0, add_len); - buf->ext_data = nbuf; - } else { - nbuf = os_realloc(buf, sizeof(struct wpabuf) + - buf->used + add_len); - if (nbuf == NULL) - return -1; - buf = (struct wpabuf *) nbuf; - os_memset(nbuf + sizeof(struct wpabuf) + buf->used, 0, - add_len); - *_buf = buf; - } - buf->size = buf->used + add_len; - } - - return 0; -} - - -/** - * wpabuf_alloc - Allocate a wpabuf of the given size - * @len: Length for the allocated buffer - * Returns: Buffer to the allocated wpabuf or %NULL on failure - */ -struct wpabuf * wpabuf_alloc(size_t len) -{ - struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf) + len); - if (buf == NULL) - return NULL; - buf->size = len; - return buf; -} - - -struct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len) -{ - struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf)); - if (buf == NULL) - return NULL; - - buf->size = len; - buf->used = len; - buf->ext_data = data; - - return buf; -} - - -struct wpabuf * wpabuf_alloc_copy(const void *data, size_t len) -{ - struct wpabuf *buf = wpabuf_alloc(len); - if (buf) - wpabuf_put_data(buf, data, len); - return buf; -} - - -struct wpabuf * wpabuf_dup(const struct wpabuf *src) -{ - struct wpabuf *buf = wpabuf_alloc(wpabuf_len(src)); - if (buf) - wpabuf_put_data(buf, wpabuf_head(src), wpabuf_len(src)); - return buf; -} - - -/** - * wpabuf_free - Free a wpabuf - * @buf: wpabuf buffer - */ -void wpabuf_free(struct wpabuf *buf) -{ - if (buf == NULL) - return; - os_free(buf->ext_data); - os_free(buf); -} - - -void * wpabuf_put(struct wpabuf *buf, size_t len) -{ - void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf); - buf->used += len; - if (buf->used > buf->size) { - wpabuf_overflow(buf, len); - } - return tmp; -} - - -/** - * wpabuf_concat - Concatenate two buffers into a newly allocated one - * @a: First buffer - * @b: Second buffer - * Returns: wpabuf with concatenated a + b data or %NULL on failure - * - * Both buffers a and b will be freed regardless of the return value. Input - * buffers can be %NULL which is interpreted as an empty buffer. - */ -struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b) -{ - struct wpabuf *n = NULL; - size_t len = 0; - - if (b == NULL) - return a; - - if (a) - len += wpabuf_len(a); - if (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_free(a); - wpabuf_free(b); - - return n; -} - - -/** - * wpabuf_zeropad - Pad buffer with 0x00 octets (prefix) to specified length - * @buf: Buffer to be padded - * @len: Length for the padded buffer - * Returns: wpabuf padded to len octets or %NULL on failure - * - * If buf is longer than len octets or of same size, it will be returned as-is. - * Otherwise a new buffer is allocated and prefixed with 0x00 octets followed - * by the source data. The source buffer will be freed on error, i.e., caller - * will only be responsible on freeing the returned buffer. If buf is %NULL, - * %NULL will be returned. - */ -struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len) -{ - struct wpabuf *ret; - size_t blen; - - if (buf == NULL) - return NULL; - - blen = wpabuf_len(buf); - if (blen >= len) - return buf; - - ret = wpabuf_alloc(len); - if (ret) { - os_memset(wpabuf_put(ret, len - blen), 0, len - blen); - wpabuf_put_buf(ret, buf); - } - wpabuf_free(buf); - - return ret; -} - - -void wpabuf_printf(struct wpabuf *buf, char *fmt, ...) -{ - va_list ap; - void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf); - int res; - - va_start(ap, fmt); - res = vsnprintf(tmp, buf->size - buf->used, fmt, ap); - va_end(ap); - if (res < 0 || (size_t) res >= buf->size - buf->used) - wpabuf_overflow(buf, res); - buf->used += res; -} diff --git a/contrib/hostapd/src/utils/wpabuf.h b/contrib/hostapd/src/utils/wpabuf.h deleted file mode 100644 index bd8f09e94f..0000000000 --- a/contrib/hostapd/src/utils/wpabuf.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Dynamic data buffer - * Copyright (c) 2007-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPABUF_H -#define WPABUF_H - -/* - * Internal data structure for wpabuf. Please do not touch this directly from - * elsewhere. This is only defined in header file to allow inline functions - * from this file to access data. - */ -struct wpabuf { - size_t size; /* total size of the allocated buffer */ - size_t used; /* length of data in the buffer */ - u8 *ext_data; /* pointer to external data; NULL if data follows - * struct wpabuf */ - /* optionally followed by the allocated buffer */ -}; - - -int wpabuf_resize(struct wpabuf **buf, size_t add_len); -struct wpabuf * wpabuf_alloc(size_t len); -struct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len); -struct wpabuf * wpabuf_alloc_copy(const void *data, size_t len); -struct wpabuf * wpabuf_dup(const struct wpabuf *src); -void wpabuf_free(struct wpabuf *buf); -void * wpabuf_put(struct wpabuf *buf, size_t len); -struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b); -struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len); -void wpabuf_printf(struct wpabuf *buf, char *fmt, ...) PRINTF_FORMAT(2, 3); - - -/** - * wpabuf_size - Get the currently allocated size of a wpabuf buffer - * @buf: wpabuf buffer - * Returns: Currently allocated size of the buffer - */ -static inline size_t wpabuf_size(const struct wpabuf *buf) -{ - return buf->size; -} - -/** - * wpabuf_len - Get the current length of a wpabuf buffer data - * @buf: wpabuf buffer - * Returns: Currently used length of the buffer - */ -static inline size_t wpabuf_len(const struct wpabuf *buf) -{ - return buf->used; -} - -/** - * wpabuf_tailroom - Get size of available tail room in the end of the buffer - * @buf: wpabuf buffer - * Returns: Tail room (in bytes) of available space in the end of the buffer - */ -static inline size_t wpabuf_tailroom(const struct wpabuf *buf) -{ - return buf->size - buf->used; -} - -/** - * wpabuf_head - Get pointer to the head of the buffer data - * @buf: wpabuf buffer - * Returns: Pointer to the head of the buffer data - */ -static inline const void * wpabuf_head(const struct wpabuf *buf) -{ - if (buf->ext_data) - return buf->ext_data; - return buf + 1; -} - -static inline const u8 * wpabuf_head_u8(const struct wpabuf *buf) -{ - return wpabuf_head(buf); -} - -/** - * wpabuf_mhead - Get modifiable pointer to the head of the buffer data - * @buf: wpabuf buffer - * Returns: Pointer to the head of the buffer data - */ -static inline void * wpabuf_mhead(struct wpabuf *buf) -{ - if (buf->ext_data) - return buf->ext_data; - return buf + 1; -} - -static inline u8 * wpabuf_mhead_u8(struct wpabuf *buf) -{ - return wpabuf_mhead(buf); -} - -static inline void wpabuf_put_u8(struct wpabuf *buf, u8 data) -{ - u8 *pos = wpabuf_put(buf, 1); - *pos = data; -} - -static inline void wpabuf_put_be16(struct wpabuf *buf, u16 data) -{ - u8 *pos = wpabuf_put(buf, 2); - WPA_PUT_BE16(pos, data); -} - -static inline void wpabuf_put_be24(struct wpabuf *buf, u32 data) -{ - u8 *pos = wpabuf_put(buf, 3); - WPA_PUT_BE24(pos, data); -} - -static inline void wpabuf_put_be32(struct wpabuf *buf, u32 data) -{ - u8 *pos = wpabuf_put(buf, 4); - WPA_PUT_BE32(pos, data); -} - -static inline void wpabuf_put_data(struct wpabuf *buf, const void *data, - size_t len) -{ - if (data) - os_memcpy(wpabuf_put(buf, len), data, len); -} - -static inline void wpabuf_put_buf(struct wpabuf *dst, - const struct wpabuf *src) -{ - wpabuf_put_data(dst, wpabuf_head(src), wpabuf_len(src)); -} - -static inline void wpabuf_set(struct wpabuf *buf, const void *data, size_t len) -{ - buf->ext_data = (u8 *) data; - buf->size = buf->used = len; -} - -static inline void wpabuf_put_str(struct wpabuf *dst, const char *str) -{ - wpabuf_put_data(dst, str, os_strlen(str)); -} - -#endif /* WPABUF_H */ diff --git a/contrib/hostapd/src/wps/httpread.c b/contrib/hostapd/src/wps/httpread.c deleted file mode 100644 index 0d7165e9c2..0000000000 --- a/contrib/hostapd/src/wps/httpread.c +++ /dev/null @@ -1,861 +0,0 @@ -/** - * httpread - Manage reading file(s) from HTTP/TCP socket - * Author: Ted Merrill - * Copyright 2008 Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * The files are buffered via internal callbacks from eloop, then presented to - * an application callback routine when completely read into memory. May also - * be used if no file is expected but just to get the header, including HTTP - * replies (e.g. HTTP/1.1 200 OK etc.). - * - * This does not attempt to be an optimally efficient implementation, but does - * attempt to be of reasonably small size and memory consumption; assuming that - * only small files are to be read. A maximum file size is provided by - * application and enforced. - * - * It is assumed that the application does not expect any of the following: - * -- transfer encoding other than chunked - * -- trailer fields - * It is assumed that, even if the other side requested that the connection be - * kept open, that we will close it (thus HTTP messages sent by application - * should have the connection closed field); this is allowed by HTTP/1.1 and - * simplifies things for us. - * - * Other limitations: - * -- HTTP header may not exceed a hard-coded size. - * - * Notes: - * This code would be massively simpler without some of the new features of - * HTTP/1.1, especially chunked data. - */ - -#include "includes.h" - -#include "common.h" -#include "eloop.h" -#include "httpread.h" - - -/* Tunable parameters */ -#define HTTPREAD_READBUF_SIZE 1024 /* read in chunks of this size */ -#define HTTPREAD_HEADER_MAX_SIZE 4096 /* max allowed for headers */ -#define HTTPREAD_BODYBUF_DELTA 4096 /* increase allocation by this */ - -#if 0 -/* httpread_debug -- set this global variable > 0 e.g. from debugger - * to enable debugs (larger numbers for more debugs) - * Make this a #define of 0 to eliminate the debugging code. - */ -int httpread_debug = 99; -#else -#define httpread_debug 0 /* eliminates even the debugging code */ -#endif - - -/* control instance -- actual definition (opaque to application) - */ -struct httpread { - /* information from creation */ - int sd; /* descriptor of TCP socket to read from */ - void (*cb)(struct httpread *handle, void *cookie, - enum httpread_event e); /* call on event */ - void *cookie; /* pass to callback */ - int max_bytes; /* maximum file size else abort it */ - int timeout_seconds; /* 0 or total duration timeout period */ - - /* dynamically used information follows */ - int sd_registered; /* nonzero if we need to unregister socket */ - int to_registered; /* nonzero if we need to unregister timeout */ - - int got_hdr; /* nonzero when header is finalized */ - char hdr[HTTPREAD_HEADER_MAX_SIZE+1]; /* headers stored here */ - int hdr_nbytes; - - enum httpread_hdr_type hdr_type; - int version; /* 1 if we've seen 1.1 */ - int reply_code; /* for type REPLY, e.g. 200 for HTTP/1.1 200 OK */ - int got_content_length; /* true if we know content length for sure */ - int content_length; /* body length, iff got_content_length */ - int chunked; /* nonzero for chunked data */ - char *uri; - - int got_body; /* nonzero when body is finalized */ - char *body; - int body_nbytes; - int body_alloc_nbytes; /* amount allocated */ - - int got_file; /* here when we are done */ - - /* The following apply if data is chunked: */ - int in_chunk_data; /* 0=in/at header, 1=in the data or tail*/ - int chunk_start; /* offset in body of chunk hdr or data */ - int chunk_size; /* data of chunk (not hdr or ending CRLF)*/ - int in_trailer; /* in header fields after data (chunked only)*/ - enum trailer_state { - trailer_line_begin = 0, - trailer_empty_cr, /* empty line + CR */ - trailer_nonempty, - trailer_nonempty_cr, - } trailer_state; -}; - - -/* Check words for equality, where words consist of graphical characters - * delimited by whitespace - * Returns nonzero if "equal" doing case insensitive comparison. - */ -static int word_eq(char *s1, char *s2) -{ - int c1; - int c2; - int end1 = 0; - int end2 = 0; - for (;;) { - c1 = *s1++; - c2 = *s2++; - if (isalpha(c1) && isupper(c1)) - c1 = tolower(c1); - if (isalpha(c2) && isupper(c2)) - c2 = tolower(c2); - end1 = !isgraph(c1); - end2 = !isgraph(c2); - if (end1 || end2 || c1 != c2) - break; - } - return end1 && end2; /* reached end of both words? */ -} - - -/* convert hex to binary - * Requires that c have been previously tested true with isxdigit(). - */ -static int hex_value(int c) -{ - if (isdigit(c)) - return c - '0'; - if (islower(c)) - return 10 + c - 'a'; - return 10 + c - 'A'; -} - - -static void httpread_timeout_handler(void *eloop_data, void *user_ctx); - -/* httpread_destroy -- if h is non-NULL, clean up - * This must eventually be called by the application following - * call of the application's callback and may be called - * earlier if desired. - */ -void httpread_destroy(struct httpread *h) -{ - if (httpread_debug >= 10) - wpa_printf(MSG_DEBUG, "ENTER httpread_destroy(%p)", h); - if (!h) - return; - - if (h->to_registered) - eloop_cancel_timeout(httpread_timeout_handler, NULL, h); - h->to_registered = 0; - if (h->sd_registered) - eloop_unregister_sock(h->sd, EVENT_TYPE_READ); - h->sd_registered = 0; - os_free(h->body); - os_free(h->uri); - os_memset(h, 0, sizeof(*h)); /* aid debugging */ - h->sd = -1; /* aid debugging */ - os_free(h); -} - - -/* httpread_timeout_handler -- called on excessive total duration - */ -static void httpread_timeout_handler(void *eloop_data, void *user_ctx) -{ - struct httpread *h = user_ctx; - wpa_printf(MSG_DEBUG, "httpread timeout (%p)", h); - h->to_registered = 0; /* is self-cancelling */ - (*h->cb)(h, h->cookie, HTTPREAD_EVENT_TIMEOUT); -} - - -/* Analyze options only so far as is needed to correctly obtain the file. - * The application can look at the raw header to find other options. - */ -static int httpread_hdr_option_analyze( - struct httpread *h, - char *hbp /* pointer to current line in header buffer */ - ) -{ - if (word_eq(hbp, "CONTENT-LENGTH:")) { - while (isgraph(*hbp)) - hbp++; - while (*hbp == ' ' || *hbp == '\t') - hbp++; - if (!isdigit(*hbp)) - return -1; - h->content_length = atol(hbp); - h->got_content_length = 1; - return 0; - } - if (word_eq(hbp, "TRANSFER_ENCODING:") || - word_eq(hbp, "TRANSFER-ENCODING:")) { - while (isgraph(*hbp)) - hbp++; - while (*hbp == ' ' || *hbp == '\t') - hbp++; - /* There should (?) be no encodings of interest - * other than chunked... - */ - if (word_eq(hbp, "CHUNKED")) { - h->chunked = 1; - h->in_chunk_data = 0; - /* ignore possible ; */ - } - return 0; - } - /* skip anything we don't know, which is a lot */ - return 0; -} - - -static int httpread_hdr_analyze(struct httpread *h) -{ - char *hbp = h->hdr; /* pointer into h->hdr */ - int standard_first_line = 1; - - /* First line is special */ - h->hdr_type = HTTPREAD_HDR_TYPE_UNKNOWN; - if (!isgraph(*hbp)) - goto bad; - if (os_strncmp(hbp, "HTTP/", 5) == 0) { - h->hdr_type = HTTPREAD_HDR_TYPE_REPLY; - standard_first_line = 0; - hbp += 5; - if (hbp[0] == '1' && hbp[1] == '.' && - isdigit(hbp[2]) && hbp[2] != '0') - h->version = 1; - while (isgraph(*hbp)) - hbp++; - while (*hbp == ' ' || *hbp == '\t') - hbp++; - if (!isdigit(*hbp)) - goto bad; - h->reply_code = atol(hbp); - } else if (word_eq(hbp, "GET")) - h->hdr_type = HTTPREAD_HDR_TYPE_GET; - else if (word_eq(hbp, "HEAD")) - h->hdr_type = HTTPREAD_HDR_TYPE_HEAD; - else if (word_eq(hbp, "POST")) - h->hdr_type = HTTPREAD_HDR_TYPE_POST; - else if (word_eq(hbp, "PUT")) - h->hdr_type = HTTPREAD_HDR_TYPE_PUT; - else if (word_eq(hbp, "DELETE")) - h->hdr_type = HTTPREAD_HDR_TYPE_DELETE; - else if (word_eq(hbp, "TRACE")) - h->hdr_type = HTTPREAD_HDR_TYPE_TRACE; - else if (word_eq(hbp, "CONNECT")) - h->hdr_type = HTTPREAD_HDR_TYPE_CONNECT; - else if (word_eq(hbp, "NOTIFY")) - h->hdr_type = HTTPREAD_HDR_TYPE_NOTIFY; - else if (word_eq(hbp, "M-SEARCH")) - h->hdr_type = HTTPREAD_HDR_TYPE_M_SEARCH; - else if (word_eq(hbp, "M-POST")) - h->hdr_type = HTTPREAD_HDR_TYPE_M_POST; - else if (word_eq(hbp, "SUBSCRIBE")) - h->hdr_type = HTTPREAD_HDR_TYPE_SUBSCRIBE; - else if (word_eq(hbp, "UNSUBSCRIBE")) - h->hdr_type = HTTPREAD_HDR_TYPE_UNSUBSCRIBE; - else { - } - - if (standard_first_line) { - char *rawuri; - char *uri; - /* skip type */ - while (isgraph(*hbp)) - hbp++; - while (*hbp == ' ' || *hbp == '\t') - hbp++; - /* parse uri. - * Find length, allocate memory for translated - * copy, then translate by changing % - * into represented value. - */ - rawuri = hbp; - while (isgraph(*hbp)) - hbp++; - h->uri = os_malloc((hbp - rawuri) + 1); - if (h->uri == NULL) - goto bad; - uri = h->uri; - while (rawuri < hbp) { - int c = *rawuri; - if (c == '%' && - isxdigit(rawuri[1]) && isxdigit(rawuri[2])) { - *uri++ = (hex_value(rawuri[1]) << 4) | - hex_value(rawuri[2]); - rawuri += 3; - } else { - *uri++ = c; - rawuri++; - } - } - *uri = 0; /* null terminate */ - while (isgraph(*hbp)) - hbp++; - while (*hbp == ' ' || *hbp == '\t') - hbp++; - /* get version */ - if (0 == strncmp(hbp, "HTTP/", 5)) { - hbp += 5; - if (hbp[0] == '1' && hbp[1] == '.' && - isdigit(hbp[2]) && hbp[2] != '0') - h->version = 1; - } - } - /* skip rest of line */ - while (*hbp) - if (*hbp++ == '\n') - break; - - /* Remainder of lines are options, in any order; - * or empty line to terminate - */ - for (;;) { - /* Empty line to terminate */ - if (hbp[0] == '\n' || - (hbp[0] == '\r' && hbp[1] == '\n')) - break; - if (!isgraph(*hbp)) - goto bad; - if (httpread_hdr_option_analyze(h, hbp)) - goto bad; - /* skip line */ - while (*hbp) - if (*hbp++ == '\n') - break; - } - - /* chunked overrides content-length always */ - if (h->chunked) - h->got_content_length = 0; - - /* For some types, we should not try to read a body - * This is in addition to the application determining - * that we should not read a body. - */ - switch (h->hdr_type) { - case HTTPREAD_HDR_TYPE_REPLY: - /* Some codes can have a body and some not. - * For now, just assume that any other than 200 - * do not... - */ - if (h->reply_code != 200) - h->max_bytes = 0; - break; - case HTTPREAD_HDR_TYPE_GET: - case HTTPREAD_HDR_TYPE_HEAD: - /* in practice it appears that it is assumed - * that GETs have a body length of 0... ? - */ - if (h->chunked == 0 && h->got_content_length == 0) - h->max_bytes = 0; - break; - case HTTPREAD_HDR_TYPE_POST: - case HTTPREAD_HDR_TYPE_PUT: - case HTTPREAD_HDR_TYPE_DELETE: - case HTTPREAD_HDR_TYPE_TRACE: - case HTTPREAD_HDR_TYPE_CONNECT: - case HTTPREAD_HDR_TYPE_NOTIFY: - case HTTPREAD_HDR_TYPE_M_SEARCH: - case HTTPREAD_HDR_TYPE_M_POST: - case HTTPREAD_HDR_TYPE_SUBSCRIBE: - case HTTPREAD_HDR_TYPE_UNSUBSCRIBE: - default: - break; - } - - return 0; - -bad: - /* Error */ - return -1; -} - - -/* httpread_read_handler -- called when socket ready to read - * - * Note: any extra data we read past end of transmitted file is ignored; - * if we were to support keeping connections open for multiple files then - * this would have to be addressed. - */ -static void httpread_read_handler(int sd, void *eloop_ctx, void *sock_ctx) -{ - struct httpread *h = sock_ctx; - int nread; - char *rbp; /* pointer into read buffer */ - char *hbp; /* pointer into header buffer */ - char *bbp; /* pointer into body buffer */ - char readbuf[HTTPREAD_READBUF_SIZE]; /* temp use to read into */ - - if (httpread_debug >= 20) - wpa_printf(MSG_DEBUG, "ENTER httpread_read_handler(%p)", h); - - /* read some at a time, then search for the interal - * boundaries between header and data and etc. - */ - nread = read(h->sd, readbuf, sizeof(readbuf)); - if (nread < 0) - goto bad; - if (nread == 0) { - /* end of transmission... this may be normal - * or may be an error... in some cases we can't - * tell which so we must assume it is normal then. - */ - if (!h->got_hdr) { - /* Must at least have completed header */ - wpa_printf(MSG_DEBUG, "httpread premature eof(%p)", h); - goto bad; - } - if (h->chunked || h->got_content_length) { - /* Premature EOF; e.g. dropped connection */ - wpa_printf(MSG_DEBUG, - "httpread premature eof(%p) %d/%d", - h, h->body_nbytes, - h->content_length); - goto bad; - } - /* No explicit length, hopefully we have all the data - * although dropped connections can cause false - * end - */ - if (httpread_debug >= 10) - wpa_printf(MSG_DEBUG, "httpread ok eof(%p)", h); - h->got_body = 1; - goto got_file; - } - rbp = readbuf; - - /* Header consists of text lines (terminated by both CR and LF) - * and an empty line (CR LF only). - */ - if (!h->got_hdr) { - hbp = h->hdr + h->hdr_nbytes; - /* add to headers until: - * -- we run out of data in read buffer - * -- or, we run out of header buffer room - * -- or, we get double CRLF in headers - */ - for (;;) { - if (nread == 0) - goto get_more; - if (h->hdr_nbytes == HTTPREAD_HEADER_MAX_SIZE) { - goto bad; - } - *hbp++ = *rbp++; - nread--; - h->hdr_nbytes++; - if (h->hdr_nbytes >= 4 && - hbp[-1] == '\n' && - hbp[-2] == '\r' && - hbp[-3] == '\n' && - hbp[-4] == '\r' ) { - h->got_hdr = 1; - *hbp = 0; /* null terminate */ - break; - } - } - /* here we've just finished reading the header */ - if (httpread_hdr_analyze(h)) { - wpa_printf(MSG_DEBUG, "httpread bad hdr(%p)", h); - goto bad; - } - if (h->max_bytes == 0) { - if (httpread_debug >= 10) - wpa_printf(MSG_DEBUG, - "httpread no body hdr end(%p)", h); - goto got_file; - } - if (h->got_content_length && h->content_length == 0) { - if (httpread_debug >= 10) - wpa_printf(MSG_DEBUG, - "httpread zero content length(%p)", - h); - goto got_file; - } - } - - /* Certain types of requests never have data and so - * must be specially recognized. - */ - if (!os_strncasecmp(h->hdr, "SUBSCRIBE", 9) || - !os_strncasecmp(h->hdr, "UNSUBSCRIBE", 11) || - !os_strncasecmp(h->hdr, "HEAD", 4) || - !os_strncasecmp(h->hdr, "GET", 3)) { - if (!h->got_body) { - if (httpread_debug >= 10) - wpa_printf(MSG_DEBUG, - "httpread NO BODY for sp. type"); - } - h->got_body = 1; - goto got_file; - } - - /* Data can be just plain binary data, or if "chunked" - * consists of chunks each with a header, ending with - * an ending header. - */ - if (nread == 0) - goto get_more; - if (!h->got_body) { - /* Here to get (more of) body */ - /* ensure we have enough room for worst case for body - * plus a null termination character - */ - if (h->body_alloc_nbytes < (h->body_nbytes + nread + 1)) { - char *new_body; - int new_alloc_nbytes; - - if (h->body_nbytes >= h->max_bytes) - goto bad; - new_alloc_nbytes = h->body_alloc_nbytes + - HTTPREAD_BODYBUF_DELTA; - /* For content-length case, the first time - * through we allocate the whole amount - * we need. - */ - if (h->got_content_length && - new_alloc_nbytes < (h->content_length + 1)) - new_alloc_nbytes = h->content_length + 1; - if ((new_body = os_realloc(h->body, new_alloc_nbytes)) - == NULL) - goto bad; - - h->body = new_body; - h->body_alloc_nbytes = new_alloc_nbytes; - } - /* add bytes */ - bbp = h->body + h->body_nbytes; - for (;;) { - int ncopy; - /* See if we need to stop */ - if (h->chunked && h->in_chunk_data == 0) { - /* in chunk header */ - char *cbp = h->body + h->chunk_start; - if (bbp-cbp >= 2 && bbp[-2] == '\r' && - bbp[-1] == '\n') { - /* end of chunk hdr line */ - /* hdr line consists solely - * of a hex numeral and CFLF - */ - if (!isxdigit(*cbp)) - goto bad; - h->chunk_size = strtoul(cbp, NULL, 16); - /* throw away chunk header - * so we have only real data - */ - h->body_nbytes = h->chunk_start; - bbp = cbp; - if (h->chunk_size == 0) { - /* end of chunking */ - /* trailer follows */ - h->in_trailer = 1; - if (httpread_debug >= 20) - wpa_printf( - MSG_DEBUG, - "httpread end chunks(%p)", h); - break; - } - h->in_chunk_data = 1; - /* leave chunk_start alone */ - } - } else if (h->chunked) { - /* in chunk data */ - if ((h->body_nbytes - h->chunk_start) == - (h->chunk_size + 2)) { - /* end of chunk reached, - * new chunk starts - */ - /* check chunk ended w/ CRLF - * which we'll throw away - */ - if (bbp[-1] == '\n' && - bbp[-2] == '\r') { - } else - goto bad; - h->body_nbytes -= 2; - bbp -= 2; - h->chunk_start = h->body_nbytes; - h->in_chunk_data = 0; - h->chunk_size = 0; /* just in case */ - } - } else if (h->got_content_length && - h->body_nbytes >= h->content_length) { - h->got_body = 1; - if (httpread_debug >= 10) - wpa_printf( - MSG_DEBUG, - "httpread got content(%p)", h); - goto got_file; - } - if (nread <= 0) - break; - /* Now transfer. Optimize using memcpy where we can. */ - if (h->chunked && h->in_chunk_data) { - /* copy up to remainder of chunk data - * plus the required CR+LF at end - */ - ncopy = (h->chunk_start + h->chunk_size + 2) - - h->body_nbytes; - } else if (h->chunked) { - /*in chunk header -- don't optimize */ - *bbp++ = *rbp++; - nread--; - h->body_nbytes++; - continue; - } else if (h->got_content_length) { - ncopy = h->content_length - h->body_nbytes; - } else { - ncopy = nread; - } - /* Note: should never be 0 */ - if (ncopy > nread) - ncopy = nread; - os_memcpy(bbp, rbp, ncopy); - bbp += ncopy; - h->body_nbytes += ncopy; - rbp += ncopy; - nread -= ncopy; - } /* body copy loop */ - } /* !got_body */ - if (h->chunked && h->in_trailer) { - /* If "chunked" then there is always a trailer, - * consisting of zero or more non-empty lines - * ending with CR LF and then an empty line w/ CR LF. - * We do NOT support trailers except to skip them -- - * this is supported (generally) by the http spec. - */ - bbp = h->body + h->body_nbytes; - for (;;) { - int c; - if (nread <= 0) - break; - c = *rbp++; - nread--; - switch (h->trailer_state) { - case trailer_line_begin: - if (c == '\r') - h->trailer_state = trailer_empty_cr; - else - h->trailer_state = trailer_nonempty; - break; - case trailer_empty_cr: - /* end empty line */ - if (c == '\n') { - h->trailer_state = trailer_line_begin; - h->in_trailer = 0; - if (httpread_debug >= 10) - wpa_printf( - MSG_DEBUG, - "httpread got content(%p)", h); - h->got_body = 1; - goto got_file; - } - h->trailer_state = trailer_nonempty; - break; - case trailer_nonempty: - if (c == '\r') - h->trailer_state = trailer_nonempty_cr; - break; - case trailer_nonempty_cr: - if (c == '\n') - h->trailer_state = trailer_line_begin; - else - h->trailer_state = trailer_nonempty; - break; - } - } - } - goto get_more; - -bad: - /* Error */ - wpa_printf(MSG_DEBUG, "httpread read/parse failure (%p)", h); - (*h->cb)(h, h->cookie, HTTPREAD_EVENT_ERROR); - return; - -get_more: - return; - -got_file: - if (httpread_debug >= 10) - wpa_printf(MSG_DEBUG, - "httpread got file %d bytes type %d", - h->body_nbytes, h->hdr_type); - /* Null terminate for convenience of some applications */ - if (h->body) - h->body[h->body_nbytes] = 0; /* null terminate */ - h->got_file = 1; - /* Assume that we do NOT support keeping connection alive, - * and just in case somehow we don't get destroyed right away, - * unregister now. - */ - if (h->sd_registered) - eloop_unregister_sock(h->sd, EVENT_TYPE_READ); - h->sd_registered = 0; - /* The application can destroy us whenever they feel like... - * cancel timeout. - */ - if (h->to_registered) - eloop_cancel_timeout(httpread_timeout_handler, NULL, h); - h->to_registered = 0; - (*h->cb)(h, h->cookie, HTTPREAD_EVENT_FILE_READY); -} - - -/* httpread_create -- start a new reading session making use of eloop. - * The new instance will use the socket descriptor for reading (until - * it gets a file and not after) but will not close the socket, even - * when the instance is destroyed (the application must do that). - * Return NULL on error. - * - * Provided that httpread_create successfully returns a handle, - * the callback fnc is called to handle httpread_event events. - * The caller should do destroy on any errors or unknown events. - * - * Pass max_bytes == 0 to not read body at all (required for e.g. - * reply to HEAD request). - */ -struct httpread * httpread_create( - int sd, /* descriptor of TCP socket to read from */ - void (*cb)(struct httpread *handle, void *cookie, - enum httpread_event e), /* call on event */ - void *cookie, /* pass to callback */ - int max_bytes, /* maximum body size else abort it */ - int timeout_seconds /* 0; or total duration timeout period */ - ) -{ - struct httpread *h = NULL; - - h = os_zalloc(sizeof(*h)); - if (h == NULL) - goto fail; - h->sd = sd; - h->cb = cb; - h->cookie = cookie; - h->max_bytes = max_bytes; - h->timeout_seconds = timeout_seconds; - - if (timeout_seconds > 0) { - if (eloop_register_timeout(timeout_seconds, 0, - httpread_timeout_handler, - NULL, h)) { - /* No way to recover (from malloc failure) */ - goto fail; - } - h->to_registered = 1; - } - if (eloop_register_sock(sd, EVENT_TYPE_READ, httpread_read_handler, - NULL, h)) { - /* No way to recover (from malloc failure) */ - goto fail; - } - h->sd_registered = 1; - return h; - -fail: - - /* Error */ - httpread_destroy(h); - return NULL; -} - - -/* httpread_hdr_type_get -- When file is ready, returns header type. */ -enum httpread_hdr_type httpread_hdr_type_get(struct httpread *h) -{ - return h->hdr_type; -} - - -/* httpread_uri_get -- When file is ready, uri_get returns (translated) URI - * or possibly NULL (which would be an error). - */ -char * httpread_uri_get(struct httpread *h) -{ - return h->uri; -} - - -/* httpread_reply_code_get -- When reply is ready, returns reply code */ -int httpread_reply_code_get(struct httpread *h) -{ - return h->reply_code; -} - - -/* httpread_length_get -- When file is ready, returns file length. */ -int httpread_length_get(struct httpread *h) -{ - return h->body_nbytes; -} - - -/* httpread_data_get -- When file is ready, returns file content - * with null byte appened. - * Might return NULL in some error condition. - */ -void * httpread_data_get(struct httpread *h) -{ - return h->body ? h->body : ""; -} - - -/* httpread_hdr_get -- When file is ready, returns header content - * with null byte appended. - * Might return NULL in some error condition. - */ -char * httpread_hdr_get(struct httpread *h) -{ - return h->hdr; -} - - -/* httpread_hdr_line_get -- When file is ready, returns pointer - * to line within header content matching the given tag - * (after the tag itself and any spaces/tabs). - * - * The tag should end with a colon for reliable matching. - * - * If not found, returns NULL; - */ -char * httpread_hdr_line_get(struct httpread *h, const char *tag) -{ - int tag_len = os_strlen(tag); - char *hdr = h->hdr; - hdr = os_strchr(hdr, '\n'); - if (hdr == NULL) - return NULL; - hdr++; - for (;;) { - if (!os_strncasecmp(hdr, tag, tag_len)) { - hdr += tag_len; - while (*hdr == ' ' || *hdr == '\t') - hdr++; - return hdr; - } - hdr = os_strchr(hdr, '\n'); - if (hdr == NULL) - return NULL; - hdr++; - } -} diff --git a/contrib/hostapd/src/wps/httpread.h b/contrib/hostapd/src/wps/httpread.h deleted file mode 100644 index fb1ecb7de3..0000000000 --- a/contrib/hostapd/src/wps/httpread.h +++ /dev/null @@ -1,123 +0,0 @@ -/** - * httpread - Manage reading file(s) from HTTP/TCP socket - * Author: Ted Merrill - * Copyright 2008 Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef HTTPREAD_H -#define HTTPREAD_H - -/* event types (passed to callback) */ -enum httpread_event { - HTTPREAD_EVENT_FILE_READY = 1, /* including reply ready */ - HTTPREAD_EVENT_TIMEOUT = 2, - HTTPREAD_EVENT_ERROR = 3 /* misc. error, esp malloc error */ -}; - - -/* header type detected - * available to callback via call to httpread_reply_code_get() - */ -enum httpread_hdr_type { - HTTPREAD_HDR_TYPE_UNKNOWN = 0, /* none of the following */ - HTTPREAD_HDR_TYPE_REPLY = 1, /* hdr begins w/ HTTP/ */ - HTTPREAD_HDR_TYPE_GET = 2, /* hdr begins with GET */ - HTTPREAD_HDR_TYPE_HEAD = 3, /* hdr begins with HEAD */ - HTTPREAD_HDR_TYPE_POST = 4, /* hdr begins with POST */ - HTTPREAD_HDR_TYPE_PUT = 5, /* hdr begins with ... */ - HTTPREAD_HDR_TYPE_DELETE = 6, /* hdr begins with ... */ - HTTPREAD_HDR_TYPE_TRACE = 7, /* hdr begins with ... */ - HTTPREAD_HDR_TYPE_CONNECT = 8, /* hdr begins with ... */ - HTTPREAD_HDR_TYPE_NOTIFY = 9, /* hdr begins with ... */ - HTTPREAD_HDR_TYPE_M_SEARCH = 10, /* hdr begins with ... */ - HTTPREAD_HDR_TYPE_M_POST = 11, /* hdr begins with ... */ - HTTPREAD_HDR_TYPE_SUBSCRIBE = 12, /* hdr begins with ... */ - HTTPREAD_HDR_TYPE_UNSUBSCRIBE = 13, /* hdr begins with ... */ - - HTTPREAD_N_HDR_TYPES /* keep last */ -}; - - -/* control instance -- opaque struct declaration - */ -struct httpread; - - -/* httpread_destroy -- if h is non-NULL, clean up - * This must eventually be called by the application following - * call of the application's callback and may be called - * earlier if desired. - */ -void httpread_destroy(struct httpread *h); - -/* httpread_create -- start a new reading session making use of eloop. - * The new instance will use the socket descriptor for reading (until - * it gets a file and not after) but will not close the socket, even - * when the instance is destroyed (the application must do that). - * Return NULL on error. - * - * Provided that httpread_create successfully returns a handle, - * the callback fnc is called to handle httpread_event events. - * The caller should do destroy on any errors or unknown events. - * - * Pass max_bytes == 0 to not read body at all (required for e.g. - * reply to HEAD request). - */ -struct httpread * httpread_create( - int sd, /* descriptor of TCP socket to read from */ - void (*cb)(struct httpread *handle, void *cookie, - enum httpread_event e), /* call on event */ - void *cookie, /* pass to callback */ - int max_bytes, /* maximum file size else abort it */ - int timeout_seconds /* 0; or total duration timeout period */ - ); - -/* httpread_hdr_type_get -- When file is ready, returns header type. - */ -enum httpread_hdr_type httpread_hdr_type_get(struct httpread *h); - - -/* httpread_uri_get -- When file is ready, uri_get returns (translated) URI - * or possibly NULL (which would be an error). - */ -char *httpread_uri_get(struct httpread *h); - -/* httpread_reply_code_get -- When reply is ready, returns reply code */ -int httpread_reply_code_get(struct httpread *h); - - -/* httpread_length_get -- When file is ready, returns file length. */ -int httpread_length_get(struct httpread *h); - -/* httpread_data_get -- When file is ready, returns file content - * with null byte appened. - * Might return NULL in some error condition. - */ -void * httpread_data_get(struct httpread *h); - -/* httpread_hdr_get -- When file is ready, returns header content - * with null byte appended. - * Might return NULL in some error condition. - */ -char * httpread_hdr_get(struct httpread *h); - -/* httpread_hdr_line_get -- When file is ready, returns pointer - * to line within header content matching the given tag - * (after the tag itself and any spaces/tabs). - * - * The tag should end with a colon for reliable matching. - * - * If not found, returns NULL; - */ -char * httpread_hdr_line_get(struct httpread *h, const char *tag); - -#endif /* HTTPREAD_H */ diff --git a/contrib/hostapd/src/wps/wps.c b/contrib/hostapd/src/wps/wps.c deleted file mode 100644 index 395eba6af2..0000000000 --- a/contrib/hostapd/src/wps/wps.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Wi-Fi Protected Setup - * Copyright (c) 2007-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "wps_i.h" -#include "wps_dev_attr.h" -#include "ieee802_11_defs.h" - - -/** - * wps_init - Initialize WPS Registration protocol data - * @cfg: WPS configuration - * Returns: Pointer to allocated data or %NULL on failure - * - * This function is used to initialize WPS data for a registration protocol - * instance (i.e., each run of registration protocol as a Registrar of - * Enrollee. The caller is responsible for freeing this data after the - * registration run has been completed by calling wps_deinit(). - */ -struct wps_data * wps_init(const struct wps_config *cfg) -{ - struct wps_data *data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->wps = cfg->wps; - data->registrar = cfg->registrar; - if (cfg->registrar) { - os_memcpy(data->uuid_r, cfg->wps->uuid, WPS_UUID_LEN); - } else { - os_memcpy(data->mac_addr_e, cfg->wps->dev.mac_addr, ETH_ALEN); - os_memcpy(data->uuid_e, cfg->wps->uuid, WPS_UUID_LEN); - } - if (cfg->pin) { - data->dev_pw_id = DEV_PW_DEFAULT; - data->dev_password = os_malloc(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; - } - - data->pbc = cfg->pbc; - if (cfg->pbc) { - /* Use special PIN '00000000' for PBC */ - data->dev_pw_id = DEV_PW_PUSHBUTTON; - os_free(data->dev_password); - data->dev_password = os_malloc(8); - if (data->dev_password == NULL) { - os_free(data); - return NULL; - } - os_memset(data->dev_password, '0', 8); - data->dev_password_len = 8; - } - - data->state = data->registrar ? RECV_M1 : SEND_M1; - - if (cfg->assoc_wps_ie) { - struct wps_parse_attr attr; - wpa_hexdump_buf(MSG_DEBUG, "WPS: WPS IE from (Re)AssocReq", - cfg->assoc_wps_ie); - if (wps_parse_msg(cfg->assoc_wps_ie, &attr) < 0) { - wpa_printf(MSG_DEBUG, "WPS: Failed to parse WPS IE " - "from (Re)AssocReq"); - } else if (attr.request_type == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Request Type attribute " - "in (Re)AssocReq WPS IE"); - } else { - wpa_printf(MSG_DEBUG, "WPS: Request Type (from WPS IE " - "in (Re)AssocReq WPS IE): %d", - *attr.request_type); - data->request_type = *attr.request_type; - } - } - - return data; -} - - -/** - * wps_deinit - Deinitialize WPS Registration protocol data - * @data: WPS Registration protocol data from wps_init() - */ -void wps_deinit(struct wps_data *data) -{ - if (data->wps_pin_revealed) { - wpa_printf(MSG_DEBUG, "WPS: Full PIN information revealed and " - "negotiation failed"); - if (data->registrar) - wps_registrar_invalidate_pin(data->wps->registrar, - data->uuid_e); - } else if (data->registrar) - wps_registrar_unlock_pin(data->wps->registrar, data->uuid_e); - - wpabuf_free(data->dh_privkey); - wpabuf_free(data->dh_pubkey_e); - wpabuf_free(data->dh_pubkey_r); - wpabuf_free(data->last_msg); - os_free(data->dev_password); - os_free(data->new_psk); - wps_device_data_free(&data->peer_dev); - os_free(data); -} - - -/** - * wps_process_msg - Process a WPS message - * @wps: WPS Registration protocol data from wps_init() - * @op_code: Message OP Code - * @msg: Message data - * Returns: Processing result - * - * This function is used to process WPS messages with OP Codes WSC_ACK, - * WSC_NACK, WSC_MSG, and WSC_Done. The caller (e.g., EAP server/peer) is - * responsible for reassembling the messages before calling this function. - * Response to this message is built by calling wps_get_msg(). - */ -enum wps_process_res wps_process_msg(struct wps_data *wps, - enum wsc_op_code op_code, - const struct wpabuf *msg) -{ - if (wps->registrar) - return wps_registrar_process_msg(wps, op_code, msg); - else - return wps_enrollee_process_msg(wps, op_code, msg); -} - - -/** - * wps_get_msg - Build a WPS message - * @wps: WPS Registration protocol data from wps_init() - * @op_code: Buffer for returning message OP Code - * Returns: The generated WPS message or %NULL on failure - * - * This function is used to build a response to a message processed by calling - * wps_process_msg(). The caller is responsible for freeing the buffer. - */ -struct wpabuf * wps_get_msg(struct wps_data *wps, enum wsc_op_code *op_code) -{ - if (wps->registrar) - return wps_registrar_get_msg(wps, op_code); - else - return wps_enrollee_get_msg(wps, op_code); -} - - -/** - * wps_is_selected_pbc_registrar - Check whether WPS IE indicates active PBC - * @msg: WPS IE contents from Beacon or Probe Response frame - * Returns: 1 if PBC Registrar is active, 0 if not - */ -int wps_is_selected_pbc_registrar(const struct wpabuf *msg) -{ - struct wps_parse_attr attr; - - /* - * In theory, this could also verify that attr.sel_reg_config_methods - * includes WPS_CONFIG_PUSHBUTTON, but some deployed AP implementations - * do not set Selected Registrar Config Methods attribute properly, so - * it is safer to just use Device Password ID here. - */ - - if (wps_parse_msg(msg, &attr) < 0 || - !attr.selected_registrar || *attr.selected_registrar == 0 || - !attr.dev_password_id || - WPA_GET_BE16(attr.dev_password_id) != DEV_PW_PUSHBUTTON) - return 0; - - return 1; -} - - -/** - * wps_is_selected_pin_registrar - Check whether WPS IE indicates active PIN - * @msg: WPS IE contents from Beacon or Probe Response frame - * Returns: 1 if PIN Registrar is active, 0 if not - */ -int wps_is_selected_pin_registrar(const struct wpabuf *msg) -{ - struct wps_parse_attr attr; - - /* - * In theory, this could also verify that attr.sel_reg_config_methods - * includes WPS_CONFIG_LABEL, WPS_CONFIG_DISPLAY, or WPS_CONFIG_KEYPAD, - * but some deployed AP implementations do not set Selected Registrar - * Config Methods attribute properly, so it is safer to just use - * Device Password ID here. - */ - - if (wps_parse_msg(msg, &attr) < 0) - return 0; - - if (!attr.selected_registrar || *attr.selected_registrar == 0) - return 0; - - if (attr.dev_password_id != NULL && - WPA_GET_BE16(attr.dev_password_id) == DEV_PW_PUSHBUTTON) - return 0; - - return 1; -} - - -/** - * wps_get_uuid_e - Get UUID-E from WPS IE - * @msg: WPS IE contents from Beacon or Probe Response frame - * Returns: Pointer to UUID-E or %NULL if not included - * - * The returned pointer is to the msg contents and it remains valid only as - * long as the msg buffer is valid. - */ -const u8 * wps_get_uuid_e(const struct wpabuf *msg) -{ - struct wps_parse_attr attr; - - if (wps_parse_msg(msg, &attr) < 0) - return NULL; - return attr.uuid_e; -} - - -/** - * wps_build_assoc_req_ie - Build WPS IE for (Re)Association Request - * @req_type: Value for Request Type attribute - * Returns: WPS IE or %NULL on failure - * - * The caller is responsible for freeing the buffer. - */ -struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type) -{ - struct wpabuf *ie; - u8 *len; - - wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association " - "Request"); - ie = wpabuf_alloc(100); - if (ie == NULL) - return NULL; - - wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); - len = wpabuf_put(ie, 1); - wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); - - if (wps_build_version(ie) || - wps_build_req_type(ie, req_type)) { - wpabuf_free(ie); - return NULL; - } - - *len = wpabuf_len(ie) - 2; - - return ie; -} - - -/** - * wps_build_probe_req_ie - Build WPS IE for Probe Request - * @pbc: Whether searching for PBC mode APs - * @dev: Device attributes - * @uuid: Own UUID - * @req_type: Value for Request Type attribute - * Returns: WPS IE or %NULL on failure - * - * The caller is responsible for freeing the buffer. - */ -struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev, - const u8 *uuid, - enum wps_request_type req_type) -{ - struct wpabuf *ie; - u8 *len; - u16 methods; - - wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for Probe Request"); - - ie = wpabuf_alloc(200); - if (ie == NULL) - return NULL; - - wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); - len = wpabuf_put(ie, 1); - wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); - - if (pbc) - methods = WPS_CONFIG_PUSHBUTTON; - else - methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | - WPS_CONFIG_KEYPAD; - - if (wps_build_version(ie) || - wps_build_req_type(ie, req_type) || - wps_build_config_methods(ie, methods) || - wps_build_uuid_e(ie, uuid) || - wps_build_primary_dev_type(dev, ie) || - wps_build_rf_bands(dev, ie) || - wps_build_assoc_state(NULL, ie) || - wps_build_config_error(ie, WPS_CFG_NO_ERROR) || - wps_build_dev_password_id(ie, pbc ? DEV_PW_PUSHBUTTON : - DEV_PW_DEFAULT)) { - wpabuf_free(ie); - return NULL; - } - - *len = wpabuf_len(ie) - 2; - - return ie; -} - - -void wps_free_pending_msgs(struct upnp_pending_message *msgs) -{ - struct upnp_pending_message *p, *prev; - p = msgs; - while (p) { - prev = p; - p = p->next; - wpabuf_free(prev->msg); - os_free(prev); - } -} diff --git a/contrib/hostapd/src/wps/wps.h b/contrib/hostapd/src/wps/wps.h deleted file mode 100644 index faf32c48e8..0000000000 --- a/contrib/hostapd/src/wps/wps.h +++ /dev/null @@ -1,533 +0,0 @@ -/* - * Wi-Fi Protected Setup - * Copyright (c) 2007-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPS_H -#define WPS_H - -#include "wps_defs.h" - -/** - * enum wsc_op_code - EAP-WSC OP-Code values - */ -enum wsc_op_code { - WSC_UPnP = 0 /* No OP Code in UPnP transport */, - WSC_Start = 0x01, - WSC_ACK = 0x02, - WSC_NACK = 0x03, - WSC_MSG = 0x04, - WSC_Done = 0x05, - WSC_FRAG_ACK = 0x06 -}; - -struct wps_registrar; -struct upnp_wps_device_sm; - -/** - * struct wps_credential - WPS Credential - * @ssid: SSID - * @ssid_len: Length of SSID - * @auth_type: Authentication Type (WPS_AUTH_OPEN, .. flags) - * @encr_type: Encryption Type (WPS_ENCR_NONE, .. flags) - * @key_idx: Key index - * @key: Key - * @key_len: Key length in octets - * @mac_addr: MAC address of the Credential receiver - * @cred_attr: Unparsed Credential attribute data (used only in cred_cb()); - * this may be %NULL, if not used - * @cred_attr_len: Length of cred_attr in octets - */ -struct wps_credential { - u8 ssid[32]; - size_t ssid_len; - u16 auth_type; - u16 encr_type; - u8 key_idx; - u8 key[64]; - size_t key_len; - u8 mac_addr[ETH_ALEN]; - const u8 *cred_attr; - size_t cred_attr_len; -}; - -/** - * struct wps_device_data - WPS Device Data - * @mac_addr: Device MAC address - * @device_name: Device Name (0..32 octets encoded in UTF-8) - * @manufacturer: Manufacturer (0..64 octets encoded in UTF-8) - * @model_name: Model Name (0..32 octets encoded in UTF-8) - * @model_number: Model Number (0..32 octets encoded in UTF-8) - * @serial_number: Serial Number (0..32 octets encoded in UTF-8) - * @categ: Primary Device Category - * @oui: Primary Device OUI - * @sub_categ: Primary Device Sub-Category - * @os_version: OS Version - * @rf_bands: RF bands (WPS_RF_24GHZ, WPS_RF_50GHZ flags) - */ -struct wps_device_data { - u8 mac_addr[ETH_ALEN]; - char *device_name; - char *manufacturer; - char *model_name; - char *model_number; - char *serial_number; - u16 categ; - u32 oui; - u16 sub_categ; - u32 os_version; - u8 rf_bands; -}; - -/** - * struct wps_config - WPS configuration for a single registration protocol run - */ -struct wps_config { - /** - * wps - Pointer to long term WPS context - */ - struct wps_context *wps; - - /** - * registrar - Whether this end is a Registrar - */ - int registrar; - - /** - * pin - Enrollee Device Password (%NULL for Registrar or PBC) - */ - const u8 *pin; - - /** - * pin_len - Length on pin in octets - */ - size_t pin_len; - - /** - * pbc - Whether this is protocol run uses PBC - */ - int pbc; - - /** - * assoc_wps_ie: (Re)AssocReq WPS IE (in AP; %NULL if not AP) - */ - const struct wpabuf *assoc_wps_ie; -}; - -struct wps_data * wps_init(const struct wps_config *cfg); - -void wps_deinit(struct wps_data *data); - -/** - * enum wps_process_res - WPS message processing result - */ -enum wps_process_res { - /** - * WPS_DONE - Processing done - */ - WPS_DONE, - - /** - * WPS_CONTINUE - Processing continues - */ - WPS_CONTINUE, - - /** - * WPS_FAILURE - Processing failed - */ - WPS_FAILURE, - - /** - * WPS_PENDING - Processing continues, but waiting for an external - * event (e.g., UPnP message from an external Registrar) - */ - WPS_PENDING -}; -enum wps_process_res wps_process_msg(struct wps_data *wps, - enum wsc_op_code op_code, - const struct wpabuf *msg); - -struct wpabuf * wps_get_msg(struct wps_data *wps, enum wsc_op_code *op_code); - -int wps_is_selected_pbc_registrar(const struct wpabuf *msg); -int wps_is_selected_pin_registrar(const struct wpabuf *msg); -const u8 * wps_get_uuid_e(const struct wpabuf *msg); - -struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type); -struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev, - const u8 *uuid, - enum wps_request_type req_type); - - -/** - * struct wps_registrar_config - WPS Registrar configuration - */ -struct wps_registrar_config { - /** - * new_psk_cb - Callback for new PSK - * @ctx: Higher layer context data (cb_ctx) - * @mac_addr: MAC address of the Enrollee - * @psk: The new PSK - * @psk_len: The length of psk in octets - * Returns: 0 on success, -1 on failure - * - * This callback is called when a new per-device PSK is provisioned. - */ - int (*new_psk_cb)(void *ctx, const u8 *mac_addr, const u8 *psk, - size_t psk_len); - - /** - * set_ie_cb - Callback for WPS IE changes - * @ctx: Higher layer context data (cb_ctx) - * @beacon_ie: WPS IE for Beacon - * @beacon_ie_len: WPS IE length for Beacon - * @probe_resp_ie: WPS IE for Probe Response - * @probe_resp_ie_len: WPS IE length for Probe Response - * Returns: 0 on success, -1 on failure - * - * This callback is called whenever the WPS IE in Beacon or Probe - * Response frames needs to be changed (AP only). - */ - int (*set_ie_cb)(void *ctx, const u8 *beacon_ie, size_t beacon_ie_len, - const u8 *probe_resp_ie, size_t probe_resp_ie_len); - - /** - * pin_needed_cb - Callback for requesting a PIN - * @ctx: Higher layer context data (cb_ctx) - * @uuid_e: UUID-E of the unknown Enrollee - * @dev: Device Data from the unknown Enrollee - * - * This callback is called whenever an unknown Enrollee requests to use - * PIN method and a matching PIN (Device Password) is not found in - * Registrar data. - */ - void (*pin_needed_cb)(void *ctx, const u8 *uuid_e, - const struct wps_device_data *dev); - - /** - * reg_success_cb - Callback for reporting successful registration - * @ctx: Higher layer context data (cb_ctx) - * @mac_addr: MAC address of the Enrollee - * @uuid_e: UUID-E of the Enrollee - * - * This callback is called whenever an Enrollee completes registration - * successfully. - */ - void (*reg_success_cb)(void *ctx, const u8 *mac_addr, - const u8 *uuid_e); - - /** - * cb_ctx: Higher layer context data for Registrar callbacks - */ - void *cb_ctx; - - /** - * skip_cred_build: Do not build credential - * - * This option can be used to disable internal code that builds - * Credential attribute into M8 based on the current network - * configuration and Enrollee capabilities. The extra_cred data will - * then be used as the Credential(s). - */ - int skip_cred_build; - - /** - * extra_cred: Additional Credential attribute(s) - * - * This optional data (set to %NULL to disable) can be used to add - * Credential attribute(s) for other networks into M8. If - * skip_cred_build is set, this will also override the automatically - * generated Credential attribute. - */ - const u8 *extra_cred; - - /** - * extra_cred_len: Length of extra_cred in octets - */ - size_t extra_cred_len; - - /** - * disable_auto_conf - Disable auto-configuration on first registration - * - * By default, the AP that is started in not configured state will - * generate a random PSK and move to configured state when the first - * registration protocol run is completed successfully. This option can - * be used to disable this functionality and leave it up to an external - * program to take care of configuration. This requires the extra_cred - * to be set with a suitable Credential and skip_cred_build being used. - */ - int disable_auto_conf; - - /** - * static_wep_only - Whether the BSS supports only static WEP - */ - int static_wep_only; -}; - - -/** - * enum wps_event - WPS event types - */ -enum wps_event { - /** - * WPS_EV_M2D - M2D received (Registrar did not know us) - */ - WPS_EV_M2D, - - /** - * WPS_EV_FAIL - Registration failed - */ - WPS_EV_FAIL, - - /** - * WPS_EV_SUCCESS - Registration succeeded - */ - WPS_EV_SUCCESS, - - /** - * WPS_EV_PWD_AUTH_FAIL - Password authentication failed - */ - WPS_EV_PWD_AUTH_FAIL, - - /** - * WPS_EV_PBC_OVERLAP - PBC session overlap detected - */ - WPS_EV_PBC_OVERLAP, - - /** - * WPS_EV_PBC_TIMEOUT - PBC walktime expired before protocol run start - */ - WPS_EV_PBC_TIMEOUT -}; - -/** - * union wps_event_data - WPS event data - */ -union wps_event_data { - /** - * struct wps_event_m2d - M2D event data - */ - struct wps_event_m2d { - u16 config_methods; - const u8 *manufacturer; - size_t manufacturer_len; - const u8 *model_name; - size_t model_name_len; - const u8 *model_number; - size_t model_number_len; - const u8 *serial_number; - size_t serial_number_len; - const u8 *dev_name; - size_t dev_name_len; - const u8 *primary_dev_type; /* 8 octets */ - u16 config_error; - u16 dev_password_id; - } m2d; - - /** - * struct wps_event_fail - Registration failure information - * @msg: enum wps_msg_type - */ - struct wps_event_fail { - int msg; - } fail; - - struct wps_event_pwd_auth_fail { - int enrollee; - int part; - } pwd_auth_fail; -}; - -/** - * struct upnp_pending_message - Pending PutWLANResponse messages - * @next: Pointer to next pending message or %NULL - * @addr: NewWLANEventMAC - * @msg: NewMessage - * @type: Message Type - */ -struct upnp_pending_message { - struct upnp_pending_message *next; - u8 addr[ETH_ALEN]; - struct wpabuf *msg; - enum wps_msg_type type; -}; - -/** - * struct wps_context - Long term WPS context data - * - * This data is stored at the higher layer Authenticator or Supplicant data - * structures and it is maintained over multiple registration protocol runs. - */ -struct wps_context { - /** - * ap - Whether the local end is an access point - */ - int ap; - - /** - * registrar - Pointer to WPS registrar data from wps_registrar_init() - */ - struct wps_registrar *registrar; - - /** - * wps_state - Current WPS state - */ - enum wps_state wps_state; - - /** - * ap_setup_locked - Whether AP setup is locked (only used at AP) - */ - int ap_setup_locked; - - /** - * uuid - Own UUID - */ - u8 uuid[16]; - - /** - * ssid - SSID - * - * This SSID is used by the Registrar to fill in information for - * Credentials. In addition, AP uses it when acting as an Enrollee to - * notify Registrar of the current configuration. - */ - u8 ssid[32]; - - /** - * ssid_len - Length of ssid in octets - */ - size_t ssid_len; - - /** - * dev - Own WPS device data - */ - struct wps_device_data dev; - - /** - * config_methods - Enabled configuration methods - * - * Bit field of WPS_CONFIG_* - */ - u16 config_methods; - - /** - * encr_types - Enabled encryption types (bit field of WPS_ENCR_*) - */ - u16 encr_types; - - /** - * auth_types - Authentication types (bit field of WPS_AUTH_*) - */ - u16 auth_types; - - /** - * network_key - The current Network Key (PSK) or %NULL to generate new - * - * If %NULL, Registrar will generate per-device PSK. In addition, AP - * uses this when acting as an Enrollee to notify Registrar of the - * current configuration. - */ - u8 *network_key; - - /** - * network_key_len - Length of network_key in octets - */ - size_t network_key_len; - - /** - * ap_settings - AP Settings override for M7 (only used at AP) - * - * If %NULL, AP Settings attributes will be generated based on the - * current network configuration. - */ - u8 *ap_settings; - - /** - * ap_settings_len - Length of ap_settings in octets - */ - size_t ap_settings_len; - - /** - * friendly_name - Friendly Name (required for UPnP) - */ - char *friendly_name; - - /** - * manufacturer_url - Manufacturer URL (optional for UPnP) - */ - char *manufacturer_url; - - /** - * model_description - Model Description (recommended for UPnP) - */ - char *model_description; - - /** - * model_url - Model URL (optional for UPnP) - */ - char *model_url; - - /** - * upc - Universal Product Code (optional for UPnP) - */ - char *upc; - - /** - * cred_cb - Callback to notify that new Credentials were received - * @ctx: Higher layer context data (cb_ctx) - * @cred: The received Credential - * Return: 0 on success, -1 on failure - */ - int (*cred_cb)(void *ctx, const struct wps_credential *cred); - - /** - * event_cb - Event callback (state information about progress) - * @ctx: Higher layer context data (cb_ctx) - * @event: Event type - * @data: Event data - */ - void (*event_cb)(void *ctx, enum wps_event event, - union wps_event_data *data); - - /** - * cb_ctx: Higher layer context data for callbacks - */ - void *cb_ctx; - - struct upnp_wps_device_sm *wps_upnp; - - /* Pending messages from UPnP PutWLANResponse */ - struct upnp_pending_message *upnp_msgs; -}; - - -struct wps_registrar * -wps_registrar_init(struct wps_context *wps, - const struct wps_registrar_config *cfg); -void wps_registrar_deinit(struct wps_registrar *reg); -int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *uuid, - const u8 *pin, size_t pin_len, int timeout); -int wps_registrar_invalidate_pin(struct wps_registrar *reg, const u8 *uuid); -int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid); -int wps_registrar_button_pushed(struct wps_registrar *reg); -void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr, - const struct wpabuf *wps_data); -int wps_registrar_update_ie(struct wps_registrar *reg); -int wps_registrar_set_selected_registrar(struct wps_registrar *reg, - const struct wpabuf *msg); - -unsigned int wps_pin_checksum(unsigned int pin); -unsigned int wps_pin_valid(unsigned int pin); -unsigned int wps_generate_pin(void); -void wps_free_pending_msgs(struct upnp_pending_message *msgs); - -#endif /* WPS_H */ diff --git a/contrib/hostapd/src/wps/wps_attr_build.c b/contrib/hostapd/src/wps/wps_attr_build.c deleted file mode 100644 index edeff5c58d..0000000000 --- a/contrib/hostapd/src/wps/wps_attr_build.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Wi-Fi Protected Setup - attribute building - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "dh_groups.h" -#include "sha256.h" -#include "aes_wrap.h" -#include "wps_i.h" - - -int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg) -{ - struct wpabuf *pubkey; - - wpa_printf(MSG_DEBUG, "WPS: * Public Key"); - pubkey = dh_init(dh_groups_get(WPS_DH_GROUP), &wps->dh_privkey); - pubkey = wpabuf_zeropad(pubkey, 192); - if (pubkey == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Failed to initialize " - "Diffie-Hellman handshake"); - return -1; - } - - wpabuf_put_be16(msg, ATTR_PUBLIC_KEY); - wpabuf_put_be16(msg, wpabuf_len(pubkey)); - wpabuf_put_buf(msg, pubkey); - - if (wps->registrar) { - wpabuf_free(wps->dh_pubkey_r); - wps->dh_pubkey_r = pubkey; - } else { - wpabuf_free(wps->dh_pubkey_e); - wps->dh_pubkey_e = pubkey; - } - - return 0; -} - - -int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type) -{ - wpa_printf(MSG_DEBUG, "WPS: * Request Type"); - wpabuf_put_be16(msg, ATTR_REQUEST_TYPE); - wpabuf_put_be16(msg, 1); - wpabuf_put_u8(msg, type); - return 0; -} - - -int wps_build_config_methods(struct wpabuf *msg, u16 methods) -{ - wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods); - wpabuf_put_be16(msg, ATTR_CONFIG_METHODS); - wpabuf_put_be16(msg, 2); - wpabuf_put_be16(msg, methods); - return 0; -} - - -int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid) -{ - wpa_printf(MSG_DEBUG, "WPS: * UUID-E"); - wpabuf_put_be16(msg, ATTR_UUID_E); - wpabuf_put_be16(msg, WPS_UUID_LEN); - wpabuf_put_data(msg, uuid, WPS_UUID_LEN); - return 0; -} - - -int wps_build_dev_password_id(struct wpabuf *msg, u16 id) -{ - wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id); - wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); - wpabuf_put_be16(msg, 2); - wpabuf_put_be16(msg, id); - return 0; -} - - -int wps_build_config_error(struct wpabuf *msg, u16 err) -{ - wpa_printf(MSG_DEBUG, "WPS: * Configuration Error (%d)", err); - wpabuf_put_be16(msg, ATTR_CONFIG_ERROR); - wpabuf_put_be16(msg, 2); - wpabuf_put_be16(msg, err); - return 0; -} - - -int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg) -{ - u8 hash[SHA256_MAC_LEN]; - const u8 *addr[2]; - size_t len[2]; - - if (wps->last_msg == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Last message not available for " - "building authenticator"); - return -1; - } - - /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*) - * (M_curr* is M_curr without the Authenticator attribute) - */ - addr[0] = wpabuf_head(wps->last_msg); - len[0] = wpabuf_len(wps->last_msg); - addr[1] = wpabuf_head(msg); - len[1] = wpabuf_len(msg); - hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash); - - wpa_printf(MSG_DEBUG, "WPS: * Authenticator"); - wpabuf_put_be16(msg, ATTR_AUTHENTICATOR); - wpabuf_put_be16(msg, WPS_AUTHENTICATOR_LEN); - wpabuf_put_data(msg, hash, WPS_AUTHENTICATOR_LEN); - - return 0; -} - - -int wps_build_version(struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * Version"); - wpabuf_put_be16(msg, ATTR_VERSION); - wpabuf_put_be16(msg, 1); - wpabuf_put_u8(msg, WPS_VERSION); - return 0; -} - - -int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type) -{ - wpa_printf(MSG_DEBUG, "WPS: * Message Type (%d)", msg_type); - wpabuf_put_be16(msg, ATTR_MSG_TYPE); - wpabuf_put_be16(msg, 1); - wpabuf_put_u8(msg, msg_type); - return 0; -} - - -int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * Enrollee Nonce"); - wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE); - wpabuf_put_be16(msg, WPS_NONCE_LEN); - wpabuf_put_data(msg, wps->nonce_e, WPS_NONCE_LEN); - return 0; -} - - -int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * Registrar Nonce"); - wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE); - wpabuf_put_be16(msg, WPS_NONCE_LEN); - wpabuf_put_data(msg, wps->nonce_r, WPS_NONCE_LEN); - return 0; -} - - -int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags"); - wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS); - wpabuf_put_be16(msg, 2); - wpabuf_put_be16(msg, WPS_AUTH_TYPES); - return 0; -} - - -int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags"); - wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS); - wpabuf_put_be16(msg, 2); - wpabuf_put_be16(msg, WPS_ENCR_TYPES); - return 0; -} - - -int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * Connection Type Flags"); - wpabuf_put_be16(msg, ATTR_CONN_TYPE_FLAGS); - wpabuf_put_be16(msg, 1); - wpabuf_put_u8(msg, WPS_CONN_ESS); - return 0; -} - - -int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * Association State"); - wpabuf_put_be16(msg, ATTR_ASSOC_STATE); - wpabuf_put_be16(msg, 2); - wpabuf_put_be16(msg, WPS_ASSOC_NOT_ASSOC); - return 0; -} - - -int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg) -{ - u8 hash[SHA256_MAC_LEN]; - - wpa_printf(MSG_DEBUG, "WPS: * Key Wrap Authenticator"); - hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, wpabuf_head(msg), - wpabuf_len(msg), hash); - - wpabuf_put_be16(msg, ATTR_KEY_WRAP_AUTH); - wpabuf_put_be16(msg, WPS_KWA_LEN); - wpabuf_put_data(msg, hash, WPS_KWA_LEN); - return 0; -} - - -int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg, - struct wpabuf *plain) -{ - size_t pad_len; - const size_t block_size = 16; - u8 *iv, *data; - - wpa_printf(MSG_DEBUG, "WPS: * Encrypted Settings"); - - /* PKCS#5 v2.0 pad */ - pad_len = block_size - wpabuf_len(plain) % block_size; - os_memset(wpabuf_put(plain, pad_len), pad_len, pad_len); - - wpabuf_put_be16(msg, ATTR_ENCR_SETTINGS); - wpabuf_put_be16(msg, block_size + wpabuf_len(plain)); - - iv = wpabuf_put(msg, block_size); - if (os_get_random(iv, block_size) < 0) - return -1; - - data = wpabuf_put(msg, 0); - wpabuf_put_buf(msg, plain); - if (aes_128_cbc_encrypt(wps->keywrapkey, iv, data, wpabuf_len(plain))) - return -1; - - return 0; -} diff --git a/contrib/hostapd/src/wps/wps_attr_parse.c b/contrib/hostapd/src/wps/wps_attr_parse.c deleted file mode 100644 index f50ae39749..0000000000 --- a/contrib/hostapd/src/wps/wps_attr_parse.c +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Wi-Fi Protected Setup - attribute parsing - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "wps_i.h" - - -static int wps_set_attr(struct wps_parse_attr *attr, u16 type, - const u8 *pos, u16 len) -{ - switch (type) { - case ATTR_VERSION: - if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u", - len); - return -1; - } - attr->version = pos; - break; - case ATTR_MSG_TYPE: - if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type " - "length %u", len); - return -1; - } - attr->msg_type = pos; - break; - case ATTR_ENROLLEE_NONCE: - if (len != WPS_NONCE_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce " - "length %u", len); - return -1; - } - attr->enrollee_nonce = pos; - break; - case ATTR_REGISTRAR_NONCE: - if (len != WPS_NONCE_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce " - "length %u", len); - return -1; - } - attr->registrar_nonce = pos; - break; - case ATTR_UUID_E: - if (len != WPS_UUID_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u", - len); - return -1; - } - attr->uuid_e = pos; - break; - case ATTR_UUID_R: - if (len != WPS_UUID_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u", - len); - return -1; - } - attr->uuid_r = pos; - break; - case ATTR_AUTH_TYPE_FLAGS: - if (len != 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " - "Type Flags length %u", len); - return -1; - } - attr->auth_type_flags = pos; - break; - case ATTR_ENCR_TYPE_FLAGS: - if (len != 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type " - "Flags length %u", len); - return -1; - } - attr->encr_type_flags = pos; - break; - case ATTR_CONN_TYPE_FLAGS: - if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type " - "Flags length %u", len); - return -1; - } - attr->conn_type_flags = pos; - break; - case ATTR_CONFIG_METHODS: - if (len != 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods " - "length %u", len); - return -1; - } - attr->config_methods = pos; - break; - case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS: - if (len != 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Selected " - "Registrar Config Methods length %u", len); - return -1; - } - attr->sel_reg_config_methods = pos; - break; - case ATTR_PRIMARY_DEV_TYPE: - if (len != sizeof(struct wps_dev_type)) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device " - "Type length %u", len); - return -1; - } - attr->primary_dev_type = pos; - break; - case ATTR_RF_BANDS: - if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length " - "%u", len); - return -1; - } - attr->rf_bands = pos; - break; - case ATTR_ASSOC_STATE: - if (len != 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Association State " - "length %u", len); - return -1; - } - attr->assoc_state = pos; - break; - case ATTR_CONFIG_ERROR: - if (len != 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration " - "Error length %u", len); - return -1; - } - attr->config_error = pos; - break; - case ATTR_DEV_PASSWORD_ID: - if (len != 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password " - "ID length %u", len); - return -1; - } - attr->dev_password_id = pos; - break; - case ATTR_OS_VERSION: - if (len != 4) { - wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length " - "%u", len); - return -1; - } - attr->os_version = pos; - break; - case ATTR_WPS_STATE: - if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected " - "Setup State length %u", len); - return -1; - } - attr->wps_state = pos; - break; - case ATTR_AUTHENTICATOR: - if (len != WPS_AUTHENTICATOR_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator " - "length %u", len); - return -1; - } - attr->authenticator = pos; - break; - case ATTR_R_HASH1: - if (len != WPS_HASH_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u", - len); - return -1; - } - attr->r_hash1 = pos; - break; - case ATTR_R_HASH2: - if (len != WPS_HASH_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u", - len); - return -1; - } - attr->r_hash2 = pos; - break; - case ATTR_E_HASH1: - if (len != WPS_HASH_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u", - len); - return -1; - } - attr->e_hash1 = pos; - break; - case ATTR_E_HASH2: - if (len != WPS_HASH_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u", - len); - return -1; - } - attr->e_hash2 = pos; - break; - case ATTR_R_SNONCE1: - if (len != WPS_SECRET_NONCE_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length " - "%u", len); - return -1; - } - attr->r_snonce1 = pos; - break; - case ATTR_R_SNONCE2: - if (len != WPS_SECRET_NONCE_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length " - "%u", len); - return -1; - } - attr->r_snonce2 = pos; - break; - case ATTR_E_SNONCE1: - if (len != WPS_SECRET_NONCE_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length " - "%u", len); - return -1; - } - attr->e_snonce1 = pos; - break; - case ATTR_E_SNONCE2: - if (len != WPS_SECRET_NONCE_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length " - "%u", len); - return -1; - } - attr->e_snonce2 = pos; - break; - case ATTR_KEY_WRAP_AUTH: - if (len != WPS_KWA_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap " - "Authenticator length %u", len); - return -1; - } - attr->key_wrap_auth = pos; - break; - case ATTR_AUTH_TYPE: - if (len != 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " - "Type length %u", len); - return -1; - } - attr->auth_type = pos; - break; - case ATTR_ENCR_TYPE: - if (len != 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption " - "Type length %u", len); - return -1; - } - attr->encr_type = pos; - break; - case ATTR_NETWORK_INDEX: - if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index " - "length %u", len); - return -1; - } - attr->network_idx = pos; - break; - case ATTR_NETWORK_KEY_INDEX: - if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index " - "length %u", len); - return -1; - } - attr->network_key_idx = pos; - break; - case ATTR_MAC_ADDR: - if (len != ETH_ALEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address " - "length %u", len); - return -1; - } - attr->mac_addr = pos; - break; - case ATTR_KEY_PROVIDED_AUTO: - if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Key Provided " - "Automatically length %u", len); - return -1; - } - attr->key_prov_auto = pos; - break; - case ATTR_802_1X_ENABLED: - if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid 802.1X Enabled " - "length %u", len); - return -1; - } - attr->dot1x_enabled = pos; - break; - case ATTR_SELECTED_REGISTRAR: - if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar" - " length %u", len); - return -1; - } - attr->selected_registrar = pos; - break; - case ATTR_REQUEST_TYPE: - if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type " - "length %u", len); - return -1; - } - attr->request_type = pos; - break; - case ATTR_RESPONSE_TYPE: - if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type " - "length %u", len); - return -1; - } - attr->request_type = pos; - break; - case ATTR_MANUFACTURER: - attr->manufacturer = pos; - attr->manufacturer_len = len; - break; - case ATTR_MODEL_NAME: - attr->model_name = pos; - attr->model_name_len = len; - break; - case ATTR_MODEL_NUMBER: - attr->model_number = pos; - attr->model_number_len = len; - break; - case ATTR_SERIAL_NUMBER: - attr->serial_number = pos; - attr->serial_number_len = len; - break; - case ATTR_DEV_NAME: - attr->dev_name = pos; - attr->dev_name_len = len; - break; - case ATTR_PUBLIC_KEY: - attr->public_key = pos; - attr->public_key_len = len; - break; - case ATTR_ENCR_SETTINGS: - attr->encr_settings = pos; - attr->encr_settings_len = len; - break; - case ATTR_CRED: - if (attr->num_cred >= MAX_CRED_COUNT) { - wpa_printf(MSG_DEBUG, "WPS: Skipped Credential " - "attribute (max %d credentials)", - MAX_CRED_COUNT); - break; - } - attr->cred[attr->num_cred] = pos; - attr->cred_len[attr->num_cred] = len; - attr->num_cred++; - break; - case ATTR_SSID: - attr->ssid = pos; - attr->ssid_len = len; - break; - case ATTR_NETWORK_KEY: - attr->network_key = pos; - attr->network_key_len = len; - break; - case ATTR_EAP_TYPE: - attr->eap_type = pos; - attr->eap_type_len = len; - break; - case ATTR_EAP_IDENTITY: - attr->eap_identity = pos; - attr->eap_identity_len = len; - break; - case ATTR_AP_SETUP_LOCKED: - if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked " - "length %u", len); - return -1; - } - attr->ap_setup_locked = pos; - break; - default: - wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x " - "len=%u", type, len); - break; - } - - return 0; -} - - -int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr) -{ - const u8 *pos, *end; - u16 type, len; - - os_memset(attr, 0, sizeof(*attr)); - pos = wpabuf_head(msg); - end = pos + wpabuf_len(msg); - - while (pos < end) { - if (end - pos < 4) { - wpa_printf(MSG_DEBUG, "WPS: Invalid message - " - "%lu bytes remaining", - (unsigned long) (end - pos)); - return -1; - } - - type = WPA_GET_BE16(pos); - pos += 2; - len = WPA_GET_BE16(pos); - pos += 2; - wpa_printf(MSG_MSGDUMP, "WPS: attr type=0x%x len=%u", - type, len); - if (len > end - pos) { - wpa_printf(MSG_DEBUG, "WPS: Attribute overflow"); - return -1; - } - - if (wps_set_attr(attr, type, pos, len) < 0) - return -1; - - pos += len; - } - - return 0; -} diff --git a/contrib/hostapd/src/wps/wps_attr_process.c b/contrib/hostapd/src/wps/wps_attr_process.c deleted file mode 100644 index ae6e906c26..0000000000 --- a/contrib/hostapd/src/wps/wps_attr_process.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Wi-Fi Protected Setup - attribute processing - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha256.h" -#include "wps_i.h" - - -int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator, - const struct wpabuf *msg) -{ - u8 hash[SHA256_MAC_LEN]; - const u8 *addr[2]; - size_t len[2]; - - if (authenticator == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Authenticator attribute " - "included"); - return -1; - } - - if (wps->last_msg == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Last message not available for " - "validating authenticator"); - return -1; - } - - /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*) - * (M_curr* is M_curr without the Authenticator attribute) - */ - addr[0] = wpabuf_head(wps->last_msg); - len[0] = wpabuf_len(wps->last_msg); - addr[1] = wpabuf_head(msg); - len[1] = wpabuf_len(msg) - 4 - WPS_AUTHENTICATOR_LEN; - hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash); - - if (os_memcmp(hash, authenticator, WPS_AUTHENTICATOR_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: Incorrect Authenticator"); - return -1; - } - - return 0; -} - - -int wps_process_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg, - const u8 *key_wrap_auth) -{ - u8 hash[SHA256_MAC_LEN]; - const u8 *head; - size_t len; - - if (key_wrap_auth == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No KWA in decrypted attribute"); - return -1; - } - - head = wpabuf_head(msg); - len = wpabuf_len(msg) - 4 - WPS_KWA_LEN; - if (head + len != key_wrap_auth - 4) { - wpa_printf(MSG_DEBUG, "WPS: KWA not in the end of the " - "decrypted attribute"); - return -1; - } - - hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, head, len, hash); - if (os_memcmp(hash, key_wrap_auth, WPS_KWA_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: Invalid KWA"); - return -1; - } - - return 0; -} - - -static int wps_process_cred_network_idx(struct wps_credential *cred, - const u8 *idx) -{ - if (idx == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Credential did not include " - "Network Index"); - return -1; - } - - wpa_printf(MSG_DEBUG, "WPS: Network Index: %d", *idx); - - return 0; -} - - -static int wps_process_cred_ssid(struct wps_credential *cred, const u8 *ssid, - size_t ssid_len) -{ - if (ssid == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Credential did not include SSID"); - return -1; - } - - /* Remove zero-padding since some Registrar implementations seem to use - * hardcoded 32-octet length for this attribute */ - while (ssid_len > 0 && ssid[ssid_len - 1] == 0) - ssid_len--; - - wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", ssid, ssid_len); - if (ssid_len <= sizeof(cred->ssid)) { - os_memcpy(cred->ssid, ssid, ssid_len); - cred->ssid_len = ssid_len; - } - - return 0; -} - - -static int wps_process_cred_auth_type(struct wps_credential *cred, - const u8 *auth_type) -{ - if (auth_type == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Credential did not include " - "Authentication Type"); - return -1; - } - - cred->auth_type = WPA_GET_BE16(auth_type); - wpa_printf(MSG_DEBUG, "WPS: Authentication Type: 0x%x", - cred->auth_type); - - return 0; -} - - -static int wps_process_cred_encr_type(struct wps_credential *cred, - const u8 *encr_type) -{ - if (encr_type == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Credential did not include " - "Encryption Type"); - return -1; - } - - cred->encr_type = WPA_GET_BE16(encr_type); - wpa_printf(MSG_DEBUG, "WPS: Encryption Type: 0x%x", - cred->encr_type); - - return 0; -} - - -static int wps_process_cred_network_key_idx(struct wps_credential *cred, - const u8 *key_idx) -{ - if (key_idx == NULL) - return 0; /* optional attribute */ - - wpa_printf(MSG_DEBUG, "WPS: Network Key Index: %d", *key_idx); - cred->key_idx = *key_idx; - - return 0; -} - - -static int wps_process_cred_network_key(struct wps_credential *cred, - const u8 *key, size_t key_len) -{ - if (key == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Credential did not include " - "Network Key"); - return -1; - } - - wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key", key, key_len); - if (key_len <= sizeof(cred->key)) { - os_memcpy(cred->key, key, key_len); - cred->key_len = key_len; - } - - return 0; -} - - -static int wps_process_cred_mac_addr(struct wps_credential *cred, - const u8 *mac_addr) -{ - if (mac_addr == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Credential did not include " - "MAC Address"); - return -1; - } - - wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR, MAC2STR(mac_addr)); - os_memcpy(cred->mac_addr, mac_addr, ETH_ALEN); - - return 0; -} - - -static int wps_process_cred_eap_type(struct wps_credential *cred, - const u8 *eap_type, size_t eap_type_len) -{ - if (eap_type == NULL) - return 0; /* optional attribute */ - - wpa_hexdump(MSG_DEBUG, "WPS: EAP Type", eap_type, eap_type_len); - - return 0; -} - - -static int wps_process_cred_eap_identity(struct wps_credential *cred, - const u8 *identity, - size_t identity_len) -{ - if (identity == NULL) - return 0; /* optional attribute */ - - wpa_hexdump_ascii(MSG_DEBUG, "WPS: EAP Identity", - identity, identity_len); - - return 0; -} - - -static int wps_process_cred_key_prov_auto(struct wps_credential *cred, - const u8 *key_prov_auto) -{ - if (key_prov_auto == NULL) - return 0; /* optional attribute */ - - wpa_printf(MSG_DEBUG, "WPS: Key Provided Automatically: %d", - *key_prov_auto); - - return 0; -} - - -static int wps_process_cred_802_1x_enabled(struct wps_credential *cred, - const u8 *dot1x_enabled) -{ - if (dot1x_enabled == NULL) - return 0; /* optional attribute */ - - wpa_printf(MSG_DEBUG, "WPS: 802.1X Enabled: %d", *dot1x_enabled); - - return 0; -} - - -static void wps_workaround_cred_key(struct wps_credential *cred) -{ - if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK) && - cred->key_len > 8 && cred->key_len < 64 && - cred->key[cred->key_len - 1] == 0) { - /* - * A deployed external registrar is known to encode ASCII - * passphrases incorrectly. Remove the extra NULL termination - * to fix the encoding. - */ - wpa_printf(MSG_DEBUG, "WPS: Workaround - remove NULL " - "termination from ASCII passphrase"); - cred->key_len--; - } -} - - -int wps_process_cred(struct wps_parse_attr *attr, - struct wps_credential *cred) -{ - wpa_printf(MSG_DEBUG, "WPS: Process Credential"); - - /* TODO: support multiple Network Keys */ - if (wps_process_cred_network_idx(cred, attr->network_idx) || - wps_process_cred_ssid(cred, attr->ssid, attr->ssid_len) || - wps_process_cred_auth_type(cred, attr->auth_type) || - wps_process_cred_encr_type(cred, attr->encr_type) || - wps_process_cred_network_key_idx(cred, attr->network_key_idx) || - wps_process_cred_network_key(cred, attr->network_key, - attr->network_key_len) || - wps_process_cred_mac_addr(cred, attr->mac_addr) || - wps_process_cred_eap_type(cred, attr->eap_type, - attr->eap_type_len) || - wps_process_cred_eap_identity(cred, attr->eap_identity, - attr->eap_identity_len) || - wps_process_cred_key_prov_auto(cred, attr->key_prov_auto) || - wps_process_cred_802_1x_enabled(cred, attr->dot1x_enabled)) - return -1; - - wps_workaround_cred_key(cred); - - return 0; -} - - -int wps_process_ap_settings(struct wps_parse_attr *attr, - struct wps_credential *cred) -{ - wpa_printf(MSG_DEBUG, "WPS: Processing AP Settings"); - os_memset(cred, 0, sizeof(*cred)); - /* TODO: optional attributes New Password and Device Password ID */ - if (wps_process_cred_ssid(cred, attr->ssid, attr->ssid_len) || - wps_process_cred_auth_type(cred, attr->auth_type) || - wps_process_cred_encr_type(cred, attr->encr_type) || - wps_process_cred_network_key_idx(cred, attr->network_key_idx) || - wps_process_cred_network_key(cred, attr->network_key, - attr->network_key_len) || - wps_process_cred_mac_addr(cred, attr->mac_addr)) - return -1; - - wps_workaround_cred_key(cred); - - return 0; -} diff --git a/contrib/hostapd/src/wps/wps_common.c b/contrib/hostapd/src/wps/wps_common.c deleted file mode 100644 index 4b45f00833..0000000000 --- a/contrib/hostapd/src/wps/wps_common.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Wi-Fi Protected Setup - common functionality - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "dh_groups.h" -#include "sha256.h" -#include "aes_wrap.h" -#include "crypto.h" -#include "wps_i.h" -#include "wps_dev_attr.h" - - -void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len, - const char *label, u8 *res, size_t res_len) -{ - u8 i_buf[4], key_bits[4]; - const u8 *addr[4]; - size_t len[4]; - int i, iter; - u8 hash[SHA256_MAC_LEN], *opos; - size_t left; - - WPA_PUT_BE32(key_bits, res_len * 8); - - addr[0] = i_buf; - len[0] = sizeof(i_buf); - addr[1] = label_prefix; - len[1] = label_prefix_len; - addr[2] = (const u8 *) label; - len[2] = os_strlen(label); - addr[3] = key_bits; - len[3] = sizeof(key_bits); - - iter = (res_len + SHA256_MAC_LEN - 1) / SHA256_MAC_LEN; - opos = res; - left = res_len; - - for (i = 1; i <= iter; i++) { - WPA_PUT_BE32(i_buf, i); - hmac_sha256_vector(key, SHA256_MAC_LEN, 4, addr, len, hash); - if (i < iter) { - os_memcpy(opos, hash, SHA256_MAC_LEN); - opos += SHA256_MAC_LEN; - left -= SHA256_MAC_LEN; - } else - os_memcpy(opos, hash, left); - } -} - - -int wps_derive_keys(struct wps_data *wps) -{ - struct wpabuf *pubkey, *dh_shared; - u8 dhkey[SHA256_MAC_LEN], kdk[SHA256_MAC_LEN]; - const u8 *addr[3]; - size_t len[3]; - u8 keys[WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN + WPS_EMSK_LEN]; - - if (wps->dh_privkey == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Own DH private key not available"); - return -1; - } - - pubkey = wps->registrar ? wps->dh_pubkey_e : wps->dh_pubkey_r; - if (pubkey == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Peer DH public key not available"); - return -1; - } - - dh_shared = dh_derive_shared(pubkey, wps->dh_privkey, - dh_groups_get(WPS_DH_GROUP)); - dh_shared = wpabuf_zeropad(dh_shared, 192); - if (dh_shared == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key"); - return -1; - } - - /* Own DH private key is not needed anymore */ - wpabuf_free(wps->dh_privkey); - wps->dh_privkey = NULL; - - wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH shared key", dh_shared); - - /* DHKey = SHA-256(g^AB mod p) */ - addr[0] = wpabuf_head(dh_shared); - len[0] = wpabuf_len(dh_shared); - sha256_vector(1, addr, len, dhkey); - wpa_hexdump_key(MSG_DEBUG, "WPS: DHKey", dhkey, sizeof(dhkey)); - wpabuf_free(dh_shared); - - /* KDK = HMAC-SHA-256_DHKey(N1 || EnrolleeMAC || N2) */ - addr[0] = wps->nonce_e; - len[0] = WPS_NONCE_LEN; - addr[1] = wps->mac_addr_e; - len[1] = ETH_ALEN; - addr[2] = wps->nonce_r; - len[2] = WPS_NONCE_LEN; - hmac_sha256_vector(dhkey, sizeof(dhkey), 3, addr, len, kdk); - wpa_hexdump_key(MSG_DEBUG, "WPS: KDK", kdk, sizeof(kdk)); - - wps_kdf(kdk, NULL, 0, "Wi-Fi Easy and Secure Key Derivation", - keys, sizeof(keys)); - os_memcpy(wps->authkey, keys, WPS_AUTHKEY_LEN); - os_memcpy(wps->keywrapkey, keys + WPS_AUTHKEY_LEN, WPS_KEYWRAPKEY_LEN); - os_memcpy(wps->emsk, keys + WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN, - WPS_EMSK_LEN); - - wpa_hexdump_key(MSG_DEBUG, "WPS: AuthKey", - wps->authkey, WPS_AUTHKEY_LEN); - wpa_hexdump_key(MSG_DEBUG, "WPS: KeyWrapKey", - wps->keywrapkey, WPS_KEYWRAPKEY_LEN); - wpa_hexdump_key(MSG_DEBUG, "WPS: EMSK", wps->emsk, WPS_EMSK_LEN); - - return 0; -} - - -void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, - size_t dev_passwd_len) -{ - u8 hash[SHA256_MAC_LEN]; - - hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd, - (dev_passwd_len + 1) / 2, hash); - os_memcpy(wps->psk1, hash, WPS_PSK_LEN); - hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, - dev_passwd + (dev_passwd_len + 1) / 2, - dev_passwd_len / 2, hash); - os_memcpy(wps->psk2, hash, WPS_PSK_LEN); - - wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Device Password", - dev_passwd, dev_passwd_len); - wpa_hexdump_key(MSG_DEBUG, "WPS: PSK1", wps->psk1, WPS_PSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "WPS: PSK2", wps->psk2, WPS_PSK_LEN); -} - - -struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, - size_t encr_len) -{ - struct wpabuf *decrypted; - const size_t block_size = 16; - size_t i; - u8 pad; - const u8 *pos; - - /* AES-128-CBC */ - if (encr == NULL || encr_len < 2 * block_size || encr_len % block_size) - { - wpa_printf(MSG_DEBUG, "WPS: No Encrypted Settings received"); - return NULL; - } - - decrypted = wpabuf_alloc(encr_len - block_size); - if (decrypted == NULL) - return NULL; - - wpa_hexdump(MSG_MSGDUMP, "WPS: Encrypted Settings", encr, encr_len); - wpabuf_put_data(decrypted, encr + block_size, encr_len - block_size); - if (aes_128_cbc_decrypt(wps->keywrapkey, encr, wpabuf_mhead(decrypted), - wpabuf_len(decrypted))) { - wpabuf_free(decrypted); - return NULL; - } - - wpa_hexdump_buf_key(MSG_MSGDUMP, "WPS: Decrypted Encrypted Settings", - decrypted); - - pos = wpabuf_head_u8(decrypted) + wpabuf_len(decrypted) - 1; - pad = *pos; - if (pad > wpabuf_len(decrypted)) { - wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value"); - wpabuf_free(decrypted); - return NULL; - } - for (i = 0; i < pad; i++) { - if (*pos-- != pad) { - wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad " - "string"); - wpabuf_free(decrypted); - return NULL; - } - } - decrypted->used -= pad; - - return decrypted; -} - - -/** - * wps_pin_checksum - Compute PIN checksum - * @pin: Seven digit PIN (i.e., eight digit PIN without the checksum digit) - * Returns: Checksum digit - */ -unsigned int wps_pin_checksum(unsigned int pin) -{ - unsigned int accum = 0; - while (pin) { - accum += 3 * (pin % 10); - pin /= 10; - accum += pin % 10; - pin /= 10; - } - - return (10 - accum % 10) % 10; -} - - -/** - * wps_pin_valid - Check whether a PIN has a valid checksum - * @pin: Eight digit PIN (i.e., including the checksum digit) - * Returns: 1 if checksum digit is valid, or 0 if not - */ -unsigned int wps_pin_valid(unsigned int pin) -{ - return wps_pin_checksum(pin / 10) == (pin % 10); -} - - -/** - * wps_generate_pin - Generate a random PIN - * Returns: Eight digit PIN (i.e., including the checksum digit) - */ -unsigned int wps_generate_pin(void) -{ - unsigned int val; - - /* Generate seven random digits for the PIN */ - if (os_get_random((unsigned char *) &val, sizeof(val)) < 0) { - struct os_time now; - os_get_time(&now); - val = os_random() ^ now.sec ^ now.usec; - } - val %= 10000000; - - /* Append checksum digit */ - return val * 10 + wps_pin_checksum(val); -} - - -void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg) -{ - union wps_event_data data; - - if (wps->event_cb == NULL) - return; - - os_memset(&data, 0, sizeof(data)); - data.fail.msg = msg; - wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, &data); -} - - -void wps_success_event(struct wps_context *wps) -{ - if (wps->event_cb == NULL) - return; - - wps->event_cb(wps->cb_ctx, WPS_EV_SUCCESS, NULL); -} - - -void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part) -{ - union wps_event_data data; - - if (wps->event_cb == NULL) - return; - - os_memset(&data, 0, sizeof(data)); - data.pwd_auth_fail.enrollee = enrollee; - data.pwd_auth_fail.part = part; - wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, &data); -} - - -void wps_pbc_overlap_event(struct wps_context *wps) -{ - if (wps->event_cb == NULL) - return; - - wps->event_cb(wps->cb_ctx, WPS_EV_PBC_OVERLAP, NULL); -} - - -void wps_pbc_timeout_event(struct wps_context *wps) -{ - if (wps->event_cb == NULL) - return; - - wps->event_cb(wps->cb_ctx, WPS_EV_PBC_TIMEOUT, NULL); -} diff --git a/contrib/hostapd/src/wps/wps_defs.h b/contrib/hostapd/src/wps/wps_defs.h deleted file mode 100644 index bf6ccc5f3e..0000000000 --- a/contrib/hostapd/src/wps/wps_defs.h +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Wi-Fi Protected Setup - message definitions - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPS_DEFS_H -#define WPS_DEFS_H - -#define WPS_VERSION 0x10 - -/* Diffie-Hellman 1536-bit MODP Group; RFC 3526, Group 5 */ -#define WPS_DH_GROUP 5 - -#define WPS_UUID_LEN 16 -#define WPS_NONCE_LEN 16 -#define WPS_AUTHENTICATOR_LEN 8 -#define WPS_AUTHKEY_LEN 32 -#define WPS_KEYWRAPKEY_LEN 16 -#define WPS_EMSK_LEN 32 -#define WPS_PSK_LEN 16 -#define WPS_SECRET_NONCE_LEN 16 -#define WPS_HASH_LEN 32 -#define WPS_KWA_LEN 8 -#define WPS_MGMTAUTHKEY_LEN 32 -#define WPS_MGMTENCKEY_LEN 16 -#define WPS_MGMT_KEY_ID_LEN 16 - -/* Attribute Types */ -enum wps_attribute { - ATTR_AP_CHANNEL = 0x1001, - ATTR_ASSOC_STATE = 0x1002, - ATTR_AUTH_TYPE = 0x1003, - ATTR_AUTH_TYPE_FLAGS = 0x1004, - ATTR_AUTHENTICATOR = 0x1005, - ATTR_CONFIG_METHODS = 0x1008, - ATTR_CONFIG_ERROR = 0x1009, - ATTR_CONFIRM_URL4 = 0x100a, - ATTR_CONFIRM_URL6 = 0x100b, - ATTR_CONN_TYPE = 0x100c, - ATTR_CONN_TYPE_FLAGS = 0x100d, - ATTR_CRED = 0x100e, - ATTR_ENCR_TYPE = 0x100f, - ATTR_ENCR_TYPE_FLAGS = 0x1010, - ATTR_DEV_NAME = 0x1011, - ATTR_DEV_PASSWORD_ID = 0x1012, - ATTR_E_HASH1 = 0x1014, - ATTR_E_HASH2 = 0x1015, - ATTR_E_SNONCE1 = 0x1016, - ATTR_E_SNONCE2 = 0x1017, - ATTR_ENCR_SETTINGS = 0x1018, - ATTR_ENROLLEE_NONCE = 0x101a, - ATTR_FEATURE_ID = 0x101b, - ATTR_IDENTITY = 0x101c, - ATTR_IDENTITY_PROOF = 0x101d, - ATTR_KEY_WRAP_AUTH = 0x101e, - ATTR_KEY_ID = 0x101f, - ATTR_MAC_ADDR = 0x1020, - ATTR_MANUFACTURER = 0x1021, - ATTR_MSG_TYPE = 0x1022, - ATTR_MODEL_NAME = 0x1023, - ATTR_MODEL_NUMBER = 0x1024, - ATTR_NETWORK_INDEX = 0x1026, - ATTR_NETWORK_KEY = 0x1027, - ATTR_NETWORK_KEY_INDEX = 0x1028, - ATTR_NEW_DEVICE_NAME = 0x1029, - ATTR_NEW_PASSWORD = 0x102a, - ATTR_OOB_DEVICE_PASSWORD = 0x102c, - ATTR_OS_VERSION = 0x102d, - ATTR_POWER_LEVEL = 0x102f, - ATTR_PSK_CURRENT = 0x1030, - ATTR_PSK_MAX = 0x1031, - ATTR_PUBLIC_KEY = 0x1032, - ATTR_RADIO_ENABLE = 0x1033, - ATTR_REBOOT = 0x1034, - ATTR_REGISTRAR_CURRENT = 0x1035, - ATTR_REGISTRAR_ESTABLISHED = 0x1036, - ATTR_REGISTRAR_LIST = 0x1037, - ATTR_REGISTRAR_MAX = 0x1038, - ATTR_REGISTRAR_NONCE = 0x1039, - ATTR_REQUEST_TYPE = 0x103a, - ATTR_RESPONSE_TYPE = 0x103b, - ATTR_RF_BANDS = 0x103c, - ATTR_R_HASH1 = 0x103d, - ATTR_R_HASH2 = 0x103e, - ATTR_R_SNONCE1 = 0x103f, - ATTR_R_SNONCE2 = 0x1040, - ATTR_SELECTED_REGISTRAR = 0x1041, - ATTR_SERIAL_NUMBER = 0x1042, - ATTR_WPS_STATE = 0x1044, - ATTR_SSID = 0x1045, - ATTR_TOTAL_NETWORKS = 0x1046, - ATTR_UUID_E = 0x1047, - ATTR_UUID_R = 0x1048, - ATTR_VENDOR_EXT = 0x1049, - ATTR_VERSION = 0x104a, - ATTR_X509_CERT_REQ = 0x104b, - ATTR_X509_CERT = 0x104c, - ATTR_EAP_IDENTITY = 0x104d, - ATTR_MSG_COUNTER = 0x104e, - ATTR_PUBKEY_HASH = 0x104f, - ATTR_REKEY_KEY = 0x1050, - ATTR_KEY_LIFETIME = 0x1051, - ATTR_PERMITTED_CFG_METHODS = 0x1052, - ATTR_SELECTED_REGISTRAR_CONFIG_METHODS = 0x1053, - ATTR_PRIMARY_DEV_TYPE = 0x1054, - ATTR_SECONDARY_DEV_TYP_ELIST = 0x1055, - ATTR_PORTABLE_DEV = 0x1056, - ATTR_AP_SETUP_LOCKED = 0x1057, - ATTR_APPLICATION_EXT = 0x1058, - ATTR_EAP_TYPE = 0x1059, - ATTR_IV = 0x1060, - ATTR_KEY_PROVIDED_AUTO = 0x1061, - ATTR_802_1X_ENABLED = 0x1062, - ATTR_APPSESSIONKEY = 0x1063, - ATTR_WEPTRANSMITKEY = 0x1064 -}; - -/* Device Password ID */ -enum wps_dev_password_id { - DEV_PW_DEFAULT = 0x0000, - DEV_PW_USER_SPECIFIED = 0x0001, - DEV_PW_MACHINE_SPECIFIED = 0x0002, - DEV_PW_REKEY = 0x0003, - DEV_PW_PUSHBUTTON = 0x0004, - DEV_PW_REGISTRAR_SPECIFIED = 0x0005 -}; - -/* Message Type */ -enum wps_msg_type { - WPS_Beacon = 0x01, - WPS_ProbeRequest = 0x02, - WPS_ProbeResponse = 0x03, - WPS_M1 = 0x04, - WPS_M2 = 0x05, - WPS_M2D = 0x06, - WPS_M3 = 0x07, - WPS_M4 = 0x08, - WPS_M5 = 0x09, - WPS_M6 = 0x0a, - WPS_M7 = 0x0b, - WPS_M8 = 0x0c, - WPS_WSC_ACK = 0x0d, - WPS_WSC_NACK = 0x0e, - WPS_WSC_DONE = 0x0f -}; - -/* Authentication Type Flags */ -#define WPS_AUTH_OPEN 0x0001 -#define WPS_AUTH_WPAPSK 0x0002 -#define WPS_AUTH_SHARED 0x0004 -#define WPS_AUTH_WPA 0x0008 -#define WPS_AUTH_WPA2 0x0010 -#define WPS_AUTH_WPA2PSK 0x0020 -#define WPS_AUTH_TYPES (WPS_AUTH_OPEN | WPS_AUTH_WPAPSK | WPS_AUTH_SHARED | \ - WPS_AUTH_WPA | WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK) - -/* Encryption Type Flags */ -#define WPS_ENCR_NONE 0x0001 -#define WPS_ENCR_WEP 0x0002 -#define WPS_ENCR_TKIP 0x0004 -#define WPS_ENCR_AES 0x0008 -#define WPS_ENCR_TYPES (WPS_ENCR_NONE | WPS_ENCR_WEP | WPS_ENCR_TKIP | \ - WPS_ENCR_AES) - -/* Configuration Error */ -enum wps_config_error { - WPS_CFG_NO_ERROR = 0, - WPS_CFG_OOB_IFACE_READ_ERROR = 1, - WPS_CFG_DECRYPTION_CRC_FAILURE = 2, - WPS_CFG_24_CHAN_NOT_SUPPORTED = 3, - WPS_CFG_50_CHAN_NOT_SUPPORTED = 4, - WPS_CFG_SIGNAL_TOO_WEAK = 5, - WPS_CFG_NETWORK_AUTH_FAILURE = 6, - WPS_CFG_NETWORK_ASSOC_FAILURE = 7, - WPS_CFG_NO_DHCP_RESPONSE = 8, - WPS_CFG_FAILED_DHCP_CONFIG = 9, - WPS_CFG_IP_ADDR_CONFLICT = 10, - WPS_CFG_NO_CONN_TO_REGISTRAR = 11, - WPS_CFG_MULTIPLE_PBC_DETECTED = 12, - WPS_CFG_ROGUE_SUSPECTED = 13, - WPS_CFG_DEVICE_BUSY = 14, - WPS_CFG_SETUP_LOCKED = 15, - WPS_CFG_MSG_TIMEOUT = 16, - WPS_CFG_REG_SESS_TIMEOUT = 17, - WPS_CFG_DEV_PASSWORD_AUTH_FAILURE = 18 -}; - -/* RF Bands */ -#define WPS_RF_24GHZ 0x01 -#define WPS_RF_50GHZ 0x02 - -/* Config Methods */ -#define WPS_CONFIG_USBA 0x0001 -#define WPS_CONFIG_ETHERNET 0x0002 -#define WPS_CONFIG_LABEL 0x0004 -#define WPS_CONFIG_DISPLAY 0x0008 -#define WPS_CONFIG_EXT_NFC_TOKEN 0x0010 -#define WPS_CONFIG_INT_NFC_TOKEN 0x0020 -#define WPS_CONFIG_NFC_INTERFACE 0x0040 -#define WPS_CONFIG_PUSHBUTTON 0x0080 -#define WPS_CONFIG_KEYPAD 0x0100 - -/* Connection Type Flags */ -#define WPS_CONN_ESS 0x01 -#define WPS_CONN_IBSS 0x02 - -/* Wi-Fi Protected Setup State */ -enum wps_state { - WPS_STATE_NOT_CONFIGURED = 1, - WPS_STATE_CONFIGURED = 2 -}; - -/* Association State */ -enum wps_assoc_state { - WPS_ASSOC_NOT_ASSOC = 0, - WPS_ASSOC_CONN_SUCCESS = 1, - WPS_ASSOC_CFG_FAILURE = 2, - WPS_ASSOC_FAILURE = 3, - WPS_ASSOC_IP_FAILURE = 4 -}; - - -/* Primary Device Type */ -struct wps_dev_type { - u8 categ_id[2]; - u8 oui[4]; - u8 sub_categ_id[2]; -}; - -#define WPS_DEV_OUI_WFA 0x0050f204 - -enum wps_dev_categ { - WPS_DEV_COMPUTER = 1, - WPS_DEV_INPUT = 2, - WPS_DEV_PRINTER = 3, - WPS_DEV_CAMERA = 4, - WPS_DEV_STORAGE = 5, - WPS_DEV_NETWORK_INFRA = 6, - WPS_DEV_DISPLAY = 7, - WPS_DEV_MULTIMEDIA = 8, - WPS_DEV_GAMING = 9, - WPS_DEV_PHONE = 10 -}; - -enum wps_dev_subcateg { - WPS_DEV_COMPUTER_PC = 1, - WPS_DEV_COMPUTER_SERVER = 2, - WPS_DEV_COMPUTER_MEDIA_CENTER = 3, - WPS_DEV_PRINTER_PRINTER = 1, - WPS_DEV_PRINTER_SCANNER = 2, - WPS_DEV_CAMERA_DIGITAL_STILL_CAMERA = 1, - WPS_DEV_STORAGE_NAS = 1, - WPS_DEV_NETWORK_INFRA_AP = 1, - WPS_DEV_NETWORK_INFRA_ROUTER = 2, - WPS_DEV_NETWORK_INFRA_SWITCH = 3, - WPS_DEV_DISPLAY_TV = 1, - WPS_DEV_DISPLAY_PICTURE_FRAME = 2, - WPS_DEV_DISPLAY_PROJECTOR = 3, - WPS_DEV_MULTIMEDIA_DAR = 1, - WPS_DEV_MULTIMEDIA_PVR = 2, - WPS_DEV_MULTIMEDIA_MCX = 3, - WPS_DEV_GAMING_XBOX = 1, - WPS_DEV_GAMING_XBOX360 = 2, - WPS_DEV_GAMING_PLAYSTATION = 3, - WPS_DEV_PHONE_WINDOWS_MOBILE = 1 -}; - - -/* Request Type */ -enum wps_request_type { - WPS_REQ_ENROLLEE_INFO = 0, - WPS_REQ_ENROLLEE = 1, - WPS_REQ_REGISTRAR = 2, - WPS_REQ_WLAN_MANAGER_REGISTRAR = 3 -}; - -/* Response Type */ -enum wps_response_type { - WPS_RESP_ENROLLEE_INFO = 0, - WPS_RESP_ENROLLEE = 1, - WPS_RESP_REGISTRAR = 2, - WPS_RESP_AP = 3 -}; - -/* Walk Time for push button configuration (in seconds) */ -#define WPS_PBC_WALK_TIME 120 - -#endif /* WPS_DEFS_H */ diff --git a/contrib/hostapd/src/wps/wps_dev_attr.c b/contrib/hostapd/src/wps/wps_dev_attr.c deleted file mode 100644 index 35f58d12d3..0000000000 --- a/contrib/hostapd/src/wps/wps_dev_attr.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Wi-Fi Protected Setup - device attributes - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "wps_i.h" -#include "wps_dev_attr.h" - - -static int wps_build_manufacturer(struct wps_device_data *dev, - struct wpabuf *msg) -{ - size_t len; - wpa_printf(MSG_DEBUG, "WPS: * Manufacturer"); - wpabuf_put_be16(msg, ATTR_MANUFACTURER); - len = dev->manufacturer ? os_strlen(dev->manufacturer) : 0; - if (len == 0) { - /* - * Some deployed WPS implementations fail to parse zero-length - * attributes. As a workaround, send a null character if the - * device attribute string is empty. - */ - wpabuf_put_be16(msg, 1); - wpabuf_put_u8(msg, '\0'); - } else { - wpabuf_put_be16(msg, len); - wpabuf_put_data(msg, dev->manufacturer, len); - } - return 0; -} - - -static int wps_build_model_name(struct wps_device_data *dev, - struct wpabuf *msg) -{ - size_t len; - wpa_printf(MSG_DEBUG, "WPS: * Model Name"); - wpabuf_put_be16(msg, ATTR_MODEL_NAME); - len = dev->model_name ? os_strlen(dev->model_name) : 0; - if (len == 0) { - /* - * Some deployed WPS implementations fail to parse zero-length - * attributes. As a workaround, send a null character if the - * device attribute string is empty. - */ - wpabuf_put_be16(msg, 1); - wpabuf_put_u8(msg, '\0'); - } else { - wpabuf_put_be16(msg, len); - wpabuf_put_data(msg, dev->model_name, len); - } - return 0; -} - - -static int wps_build_model_number(struct wps_device_data *dev, - struct wpabuf *msg) -{ - size_t len; - wpa_printf(MSG_DEBUG, "WPS: * Model Number"); - wpabuf_put_be16(msg, ATTR_MODEL_NUMBER); - len = dev->model_number ? os_strlen(dev->model_number) : 0; - if (len == 0) { - /* - * Some deployed WPS implementations fail to parse zero-length - * attributes. As a workaround, send a null character if the - * device attribute string is empty. - */ - wpabuf_put_be16(msg, 1); - wpabuf_put_u8(msg, '\0'); - } else { - wpabuf_put_be16(msg, len); - wpabuf_put_data(msg, dev->model_number, len); - } - return 0; -} - - -static int wps_build_serial_number(struct wps_device_data *dev, - struct wpabuf *msg) -{ - size_t len; - wpa_printf(MSG_DEBUG, "WPS: * Serial Number"); - wpabuf_put_be16(msg, ATTR_SERIAL_NUMBER); - len = dev->serial_number ? os_strlen(dev->serial_number) : 0; - if (len == 0) { - /* - * Some deployed WPS implementations fail to parse zero-length - * attributes. As a workaround, send a null character if the - * device attribute string is empty. - */ - wpabuf_put_be16(msg, 1); - wpabuf_put_u8(msg, '\0'); - } else { - wpabuf_put_be16(msg, len); - wpabuf_put_data(msg, dev->serial_number, len); - } - return 0; -} - - -int wps_build_primary_dev_type(struct wps_device_data *dev, struct wpabuf *msg) -{ - struct wps_dev_type *d; - wpa_printf(MSG_DEBUG, "WPS: * Primary Device Type"); - wpabuf_put_be16(msg, ATTR_PRIMARY_DEV_TYPE); - wpabuf_put_be16(msg, sizeof(*d)); - d = wpabuf_put(msg, sizeof(*d)); - WPA_PUT_BE16(d->categ_id, dev->categ); - WPA_PUT_BE32(d->oui, dev->oui); - WPA_PUT_BE16(d->sub_categ_id, dev->sub_categ); - return 0; -} - - -static int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg) -{ - size_t len; - wpa_printf(MSG_DEBUG, "WPS: * Device Name"); - wpabuf_put_be16(msg, ATTR_DEV_NAME); - len = dev->device_name ? os_strlen(dev->device_name) : 0; - if (len == 0) { - /* - * Some deployed WPS implementations fail to parse zero-length - * attributes. As a workaround, send a null character if the - * device attribute string is empty. - */ - wpabuf_put_be16(msg, 1); - wpabuf_put_u8(msg, '\0'); - } else { - wpabuf_put_be16(msg, len); - wpabuf_put_data(msg, dev->device_name, len); - } - return 0; -} - - -int wps_build_device_attrs(struct wps_device_data *dev, struct wpabuf *msg) -{ - if (wps_build_manufacturer(dev, msg) || - wps_build_model_name(dev, msg) || - wps_build_model_number(dev, msg) || - wps_build_serial_number(dev, msg) || - wps_build_primary_dev_type(dev, msg) || - wps_build_dev_name(dev, msg)) - return -1; - return 0; -} - - -int wps_build_os_version(struct wps_device_data *dev, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * OS Version"); - wpabuf_put_be16(msg, ATTR_OS_VERSION); - wpabuf_put_be16(msg, 4); - wpabuf_put_be32(msg, 0x80000000 | dev->os_version); - return 0; -} - - -int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * RF Bands (%x)", dev->rf_bands); - wpabuf_put_be16(msg, ATTR_RF_BANDS); - wpabuf_put_be16(msg, 1); - wpabuf_put_u8(msg, dev->rf_bands); - return 0; -} - - -static int wps_process_manufacturer(struct wps_device_data *dev, const u8 *str, - size_t str_len) -{ - if (str == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Manufacturer received"); - return -1; - } - - wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", str, str_len); - - os_free(dev->manufacturer); - dev->manufacturer = os_malloc(str_len + 1); - if (dev->manufacturer == NULL) - return -1; - os_memcpy(dev->manufacturer, str, str_len); - dev->manufacturer[str_len] = '\0'; - - return 0; -} - - -static int wps_process_model_name(struct wps_device_data *dev, const u8 *str, - size_t str_len) -{ - if (str == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Model Name received"); - return -1; - } - - wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", str, str_len); - - os_free(dev->model_name); - dev->model_name = os_malloc(str_len + 1); - if (dev->model_name == NULL) - return -1; - os_memcpy(dev->model_name, str, str_len); - dev->model_name[str_len] = '\0'; - - return 0; -} - - -static int wps_process_model_number(struct wps_device_data *dev, const u8 *str, - size_t str_len) -{ - if (str == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Model Number received"); - return -1; - } - - wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", str, str_len); - - os_free(dev->model_number); - dev->model_number = os_malloc(str_len + 1); - if (dev->model_number == NULL) - return -1; - os_memcpy(dev->model_number, str, str_len); - dev->model_number[str_len] = '\0'; - - return 0; -} - - -static int wps_process_serial_number(struct wps_device_data *dev, - const u8 *str, size_t str_len) -{ - if (str == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Serial Number received"); - return -1; - } - - wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", str, str_len); - - os_free(dev->serial_number); - dev->serial_number = os_malloc(str_len + 1); - if (dev->serial_number == NULL) - return -1; - os_memcpy(dev->serial_number, str, str_len); - dev->serial_number[str_len] = '\0'; - - return 0; -} - - -static int wps_process_dev_name(struct wps_device_data *dev, const u8 *str, - size_t str_len) -{ - if (str == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Device Name received"); - return -1; - } - - wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", str, str_len); - - os_free(dev->device_name); - dev->device_name = os_malloc(str_len + 1); - if (dev->device_name == NULL) - return -1; - os_memcpy(dev->device_name, str, str_len); - dev->device_name[str_len] = '\0'; - - return 0; -} - - -static int wps_process_primary_dev_type(struct wps_device_data *dev, - const u8 *dev_type) -{ - struct wps_dev_type *d; - - if (dev_type == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Primary Device Type received"); - return -1; - } - - d = (struct wps_dev_type *) dev_type; - dev->categ = WPA_GET_BE16(d->categ_id); - dev->oui = WPA_GET_BE32(d->oui); - dev->sub_categ = WPA_GET_BE16(d->sub_categ_id); - - wpa_printf(MSG_DEBUG, "WPS: Primary Device Type: category %d " - "OUI %08x sub-category %d", - dev->categ, dev->oui, dev->sub_categ); - - return 0; -} - - -int wps_process_device_attrs(struct wps_device_data *dev, - struct wps_parse_attr *attr) -{ - if (wps_process_manufacturer(dev, attr->manufacturer, - attr->manufacturer_len) || - wps_process_model_name(dev, attr->model_name, - attr->model_name_len) || - wps_process_model_number(dev, attr->model_number, - attr->model_number_len) || - wps_process_serial_number(dev, attr->serial_number, - attr->serial_number_len) || - wps_process_primary_dev_type(dev, attr->primary_dev_type) || - wps_process_dev_name(dev, attr->dev_name, attr->dev_name_len)) - return -1; - return 0; -} - - -int wps_process_os_version(struct wps_device_data *dev, const u8 *ver) -{ - if (ver == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No OS Version received"); - return -1; - } - - dev->os_version = WPA_GET_BE32(ver); - wpa_printf(MSG_DEBUG, "WPS: OS Version %08x", dev->os_version); - - return 0; -} - - -int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands) -{ - if (bands == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No RF Bands received"); - return -1; - } - - dev->rf_bands = *bands; - wpa_printf(MSG_DEBUG, "WPS: Enrollee RF Bands 0x%x", dev->rf_bands); - - return 0; -} - - -void wps_device_data_dup(struct wps_device_data *dst, - const struct wps_device_data *src) -{ - if (src->device_name) - dst->device_name = os_strdup(src->device_name); - if (src->manufacturer) - dst->manufacturer = os_strdup(src->manufacturer); - if (src->model_name) - dst->model_name = os_strdup(src->model_name); - if (src->model_number) - dst->model_number = os_strdup(src->model_number); - if (src->serial_number) - dst->serial_number = os_strdup(src->serial_number); - dst->categ = src->categ; - dst->oui = src->oui; - dst->sub_categ = src->sub_categ; - dst->os_version = src->os_version; - dst->rf_bands = src->rf_bands; -} - - -void wps_device_data_free(struct wps_device_data *dev) -{ - os_free(dev->device_name); - dev->device_name = NULL; - os_free(dev->manufacturer); - dev->manufacturer = NULL; - os_free(dev->model_name); - dev->model_name = NULL; - os_free(dev->model_number); - dev->model_number = NULL; - os_free(dev->serial_number); - dev->serial_number = NULL; -} diff --git a/contrib/hostapd/src/wps/wps_dev_attr.h b/contrib/hostapd/src/wps/wps_dev_attr.h deleted file mode 100644 index a9c16ea22f..0000000000 --- a/contrib/hostapd/src/wps/wps_dev_attr.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Wi-Fi Protected Setup - device attributes - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPS_DEV_ATTR_H -#define WPS_DEV_ATTR_H - -struct wps_parse_attr; - -int wps_build_device_attrs(struct wps_device_data *dev, struct wpabuf *msg); -int wps_build_os_version(struct wps_device_data *dev, struct wpabuf *msg); -int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg); -int wps_build_primary_dev_type(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); -int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands); -void wps_device_data_dup(struct wps_device_data *dst, - const struct wps_device_data *src); -void wps_device_data_free(struct wps_device_data *dev); - -#endif /* WPS_DEV_ATTR_H */ diff --git a/contrib/hostapd/src/wps/wps_enrollee.c b/contrib/hostapd/src/wps/wps_enrollee.c deleted file mode 100644 index 5cb3e1e011..0000000000 --- a/contrib/hostapd/src/wps/wps_enrollee.c +++ /dev/null @@ -1,1211 +0,0 @@ -/* - * Wi-Fi Protected Setup - Enrollee - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha256.h" -#include "wps_i.h" -#include "wps_dev_attr.h" - - -static int wps_build_mac_addr(struct wps_data *wps, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * MAC Address"); - wpabuf_put_be16(msg, ATTR_MAC_ADDR); - wpabuf_put_be16(msg, ETH_ALEN); - wpabuf_put_data(msg, wps->mac_addr_e, ETH_ALEN); - return 0; -} - - -static int wps_build_wps_state(struct wps_data *wps, struct wpabuf *msg) -{ - u8 state; - if (wps->wps->ap) - state = wps->wps->wps_state; - else - state = WPS_STATE_NOT_CONFIGURED; - wpa_printf(MSG_DEBUG, "WPS: * Wi-Fi Protected Setup State (%d)", - state); - wpabuf_put_be16(msg, ATTR_WPS_STATE); - wpabuf_put_be16(msg, 1); - wpabuf_put_u8(msg, state); - return 0; -} - - -static int wps_build_e_hash(struct wps_data *wps, struct wpabuf *msg) -{ - u8 *hash; - const u8 *addr[4]; - size_t len[4]; - - if (os_get_random(wps->snonce, 2 * WPS_SECRET_NONCE_LEN) < 0) - return -1; - wpa_hexdump(MSG_DEBUG, "WPS: E-S1", wps->snonce, WPS_SECRET_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "WPS: E-S2", - wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN); - - if (wps->dh_pubkey_e == NULL || wps->dh_pubkey_r == NULL) { - wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for " - "E-Hash derivation"); - return -1; - } - - wpa_printf(MSG_DEBUG, "WPS: * E-Hash1"); - wpabuf_put_be16(msg, ATTR_E_HASH1); - wpabuf_put_be16(msg, SHA256_MAC_LEN); - hash = wpabuf_put(msg, SHA256_MAC_LEN); - /* E-Hash1 = HMAC_AuthKey(E-S1 || PSK1 || PK_E || PK_R) */ - addr[0] = wps->snonce; - len[0] = WPS_SECRET_NONCE_LEN; - addr[1] = wps->psk1; - len[1] = WPS_PSK_LEN; - addr[2] = wpabuf_head(wps->dh_pubkey_e); - len[2] = wpabuf_len(wps->dh_pubkey_e); - addr[3] = wpabuf_head(wps->dh_pubkey_r); - len[3] = wpabuf_len(wps->dh_pubkey_r); - hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); - wpa_hexdump(MSG_DEBUG, "WPS: E-Hash1", hash, SHA256_MAC_LEN); - - wpa_printf(MSG_DEBUG, "WPS: * E-Hash2"); - wpabuf_put_be16(msg, ATTR_E_HASH2); - wpabuf_put_be16(msg, SHA256_MAC_LEN); - hash = wpabuf_put(msg, SHA256_MAC_LEN); - /* E-Hash2 = HMAC_AuthKey(E-S2 || PSK2 || PK_E || PK_R) */ - addr[0] = wps->snonce + WPS_SECRET_NONCE_LEN; - addr[1] = wps->psk2; - hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); - wpa_hexdump(MSG_DEBUG, "WPS: E-Hash2", hash, SHA256_MAC_LEN); - - return 0; -} - - -static int wps_build_e_snonce1(struct wps_data *wps, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * E-SNonce1"); - wpabuf_put_be16(msg, ATTR_E_SNONCE1); - wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); - wpabuf_put_data(msg, wps->snonce, WPS_SECRET_NONCE_LEN); - return 0; -} - - -static int wps_build_e_snonce2(struct wps_data *wps, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * E-SNonce2"); - wpabuf_put_be16(msg, ATTR_E_SNONCE2); - wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); - wpabuf_put_data(msg, wps->snonce + WPS_SECRET_NONCE_LEN, - WPS_SECRET_NONCE_LEN); - return 0; -} - - -static struct wpabuf * wps_build_m1(struct wps_data *wps) -{ - struct wpabuf *msg; - u16 methods; - - if (os_get_random(wps->nonce_e, WPS_NONCE_LEN) < 0) - return NULL; - wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Nonce", - wps->nonce_e, WPS_NONCE_LEN); - - wpa_printf(MSG_DEBUG, "WPS: Building Message M1"); - msg = wpabuf_alloc(1000); - if (msg == NULL) - return NULL; - - methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; - if (wps->pbc) - methods |= WPS_CONFIG_PUSHBUTTON; - - if (wps_build_version(msg) || - wps_build_msg_type(msg, WPS_M1) || - wps_build_uuid_e(msg, wps->uuid_e) || - wps_build_mac_addr(wps, msg) || - wps_build_enrollee_nonce(wps, msg) || - wps_build_public_key(wps, msg) || - wps_build_auth_type_flags(wps, msg) || - wps_build_encr_type_flags(wps, msg) || - wps_build_conn_type_flags(wps, msg) || - wps_build_config_methods(msg, methods) || - wps_build_wps_state(wps, msg) || - wps_build_device_attrs(&wps->wps->dev, msg) || - wps_build_rf_bands(&wps->wps->dev, msg) || - wps_build_assoc_state(wps, msg) || - 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)) { - wpabuf_free(msg); - return NULL; - } - - wps->state = RECV_M2; - return msg; -} - - -static struct wpabuf * wps_build_m3(struct wps_data *wps) -{ - struct wpabuf *msg; - - wpa_printf(MSG_DEBUG, "WPS: Building Message M3"); - - if (wps->dev_password == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Device Password available"); - return NULL; - } - wps_derive_psk(wps, wps->dev_password, wps->dev_password_len); - - msg = wpabuf_alloc(1000); - if (msg == NULL) - return NULL; - - if (wps_build_version(msg) || - wps_build_msg_type(msg, WPS_M3) || - wps_build_registrar_nonce(wps, msg) || - wps_build_e_hash(wps, msg) || - wps_build_authenticator(wps, msg)) { - wpabuf_free(msg); - return NULL; - } - - wps->state = RECV_M4; - return msg; -} - - -static struct wpabuf * wps_build_m5(struct wps_data *wps) -{ - struct wpabuf *msg, *plain; - - wpa_printf(MSG_DEBUG, "WPS: Building Message M5"); - - plain = wpabuf_alloc(200); - if (plain == NULL) - return NULL; - - msg = wpabuf_alloc(1000); - if (msg == NULL) { - wpabuf_free(plain); - return NULL; - } - - if (wps_build_version(msg) || - wps_build_msg_type(msg, WPS_M5) || - wps_build_registrar_nonce(wps, msg) || - wps_build_e_snonce1(wps, plain) || - wps_build_key_wrap_auth(wps, plain) || - wps_build_encr_settings(wps, msg, plain) || - wps_build_authenticator(wps, msg)) { - wpabuf_free(plain); - wpabuf_free(msg); - return NULL; - } - wpabuf_free(plain); - - wps->state = RECV_M6; - return msg; -} - - -static int wps_build_cred_ssid(struct wps_data *wps, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * SSID"); - wpabuf_put_be16(msg, ATTR_SSID); - wpabuf_put_be16(msg, wps->wps->ssid_len); - wpabuf_put_data(msg, wps->wps->ssid, wps->wps->ssid_len); - return 0; -} - - -static int wps_build_cred_auth_type(struct wps_data *wps, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * Authentication Type"); - wpabuf_put_be16(msg, ATTR_AUTH_TYPE); - wpabuf_put_be16(msg, 2); - wpabuf_put_be16(msg, wps->wps->auth_types); - return 0; -} - - -static int wps_build_cred_encr_type(struct wps_data *wps, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * Encryption Type"); - wpabuf_put_be16(msg, ATTR_ENCR_TYPE); - wpabuf_put_be16(msg, 2); - wpabuf_put_be16(msg, wps->wps->encr_types); - return 0; -} - - -static int wps_build_cred_network_key(struct wps_data *wps, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * Network Key"); - wpabuf_put_be16(msg, ATTR_NETWORK_KEY); - wpabuf_put_be16(msg, wps->wps->network_key_len); - wpabuf_put_data(msg, wps->wps->network_key, wps->wps->network_key_len); - return 0; -} - - -static int wps_build_cred_mac_addr(struct wps_data *wps, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * MAC Address (AP BSSID)"); - wpabuf_put_be16(msg, ATTR_MAC_ADDR); - wpabuf_put_be16(msg, ETH_ALEN); - wpabuf_put_data(msg, wps->wps->dev.mac_addr, ETH_ALEN); - return 0; -} - - -static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *plain) -{ - if (wps->wps->ap_settings) { - wpa_printf(MSG_DEBUG, "WPS: * AP Settings (pre-configured)"); - wpabuf_put_data(plain, wps->wps->ap_settings, - wps->wps->ap_settings_len); - return 0; - } - - return wps_build_cred_ssid(wps, plain) || - wps_build_cred_mac_addr(wps, plain) || - wps_build_cred_auth_type(wps, plain) || - wps_build_cred_encr_type(wps, plain) || - wps_build_cred_network_key(wps, plain); -} - - -static struct wpabuf * wps_build_m7(struct wps_data *wps) -{ - struct wpabuf *msg, *plain; - - wpa_printf(MSG_DEBUG, "WPS: Building Message M7"); - - plain = wpabuf_alloc(500 + wps->wps->ap_settings_len); - if (plain == NULL) - return NULL; - - msg = wpabuf_alloc(1000 + wps->wps->ap_settings_len); - if (msg == NULL) { - wpabuf_free(plain); - return NULL; - } - - if (wps_build_version(msg) || - wps_build_msg_type(msg, WPS_M7) || - wps_build_registrar_nonce(wps, msg) || - wps_build_e_snonce2(wps, plain) || - (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_authenticator(wps, msg)) { - wpabuf_free(plain); - wpabuf_free(msg); - return NULL; - } - wpabuf_free(plain); - - wps->state = RECV_M8; - return msg; -} - - -static struct wpabuf * wps_build_wsc_done(struct wps_data *wps) -{ - struct wpabuf *msg; - - wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_Done"); - - msg = wpabuf_alloc(1000); - if (msg == NULL) - return NULL; - - if (wps_build_version(msg) || - wps_build_msg_type(msg, WPS_WSC_DONE) || - wps_build_enrollee_nonce(wps, msg) || - wps_build_registrar_nonce(wps, msg)) { - wpabuf_free(msg); - return NULL; - } - - if (wps->wps->ap) - wps->state = RECV_ACK; - else { - wps_success_event(wps->wps); - wps->state = WPS_FINISHED; - } - return msg; -} - - -static struct wpabuf * wps_build_wsc_ack(struct wps_data *wps) -{ - struct wpabuf *msg; - - wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK"); - - msg = wpabuf_alloc(1000); - if (msg == NULL) - return NULL; - - if (wps_build_version(msg) || - wps_build_msg_type(msg, WPS_WSC_ACK) || - wps_build_enrollee_nonce(wps, msg) || - wps_build_registrar_nonce(wps, msg)) { - wpabuf_free(msg); - return NULL; - } - - return msg; -} - - -static struct wpabuf * wps_build_wsc_nack(struct wps_data *wps) -{ - struct wpabuf *msg; - - wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK"); - - msg = wpabuf_alloc(1000); - if (msg == NULL) - return NULL; - - if (wps_build_version(msg) || - wps_build_msg_type(msg, WPS_WSC_NACK) || - wps_build_enrollee_nonce(wps, msg) || - wps_build_registrar_nonce(wps, msg) || - wps_build_config_error(msg, wps->config_error)) { - wpabuf_free(msg); - return NULL; - } - - return msg; -} - - -struct wpabuf * wps_enrollee_get_msg(struct wps_data *wps, - enum wsc_op_code *op_code) -{ - struct wpabuf *msg; - - switch (wps->state) { - case SEND_M1: - msg = wps_build_m1(wps); - *op_code = WSC_MSG; - break; - case SEND_M3: - msg = wps_build_m3(wps); - *op_code = WSC_MSG; - break; - case SEND_M5: - msg = wps_build_m5(wps); - *op_code = WSC_MSG; - break; - case SEND_M7: - msg = wps_build_m7(wps); - *op_code = WSC_MSG; - break; - case RECEIVED_M2D: - if (wps->wps->ap) { - msg = wps_build_wsc_nack(wps); - *op_code = WSC_NACK; - break; - } - msg = wps_build_wsc_ack(wps); - *op_code = WSC_ACK; - if (msg) { - /* Another M2/M2D may be received */ - wps->state = RECV_M2; - } - break; - case SEND_WSC_NACK: - msg = wps_build_wsc_nack(wps); - *op_code = WSC_NACK; - break; - case WPS_MSG_DONE: - msg = wps_build_wsc_done(wps); - *op_code = WSC_Done; - break; - default: - wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building " - "a message", wps->state); - msg = NULL; - break; - } - - if (*op_code == WSC_MSG && msg) { - /* Save a copy of the last message for Authenticator derivation - */ - wpabuf_free(wps->last_msg); - wps->last_msg = wpabuf_dup(msg); - } - - return msg; -} - - -static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce) -{ - if (r_nonce == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received"); - return -1; - } - - os_memcpy(wps->nonce_r, r_nonce, WPS_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "WPS: Registrar Nonce", - wps->nonce_r, WPS_NONCE_LEN); - - return 0; -} - - -static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce) -{ - if (e_nonce == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received"); - return -1; - } - - if (os_memcmp(wps->nonce_e, e_nonce, WPS_NONCE_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce received"); - return -1; - } - - return 0; -} - - -static int wps_process_uuid_r(struct wps_data *wps, const u8 *uuid_r) -{ - if (uuid_r == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No UUID-R received"); - return -1; - } - - os_memcpy(wps->uuid_r, uuid_r, WPS_UUID_LEN); - wpa_hexdump(MSG_DEBUG, "WPS: UUID-R", wps->uuid_r, WPS_UUID_LEN); - - return 0; -} - - -static int wps_process_pubkey(struct wps_data *wps, const u8 *pk, - size_t pk_len) -{ - if (pk == NULL || pk_len == 0) { - wpa_printf(MSG_DEBUG, "WPS: No Public Key received"); - return -1; - } - - wpabuf_free(wps->dh_pubkey_r); - wps->dh_pubkey_r = wpabuf_alloc_copy(pk, pk_len); - if (wps->dh_pubkey_r == NULL) - return -1; - - if (wps_derive_keys(wps) < 0) - return -1; - - return 0; -} - - -static int wps_process_r_hash1(struct wps_data *wps, const u8 *r_hash1) -{ - if (r_hash1 == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No R-Hash1 received"); - return -1; - } - - os_memcpy(wps->peer_hash1, r_hash1, WPS_HASH_LEN); - wpa_hexdump(MSG_DEBUG, "WPS: R-Hash1", wps->peer_hash1, WPS_HASH_LEN); - - return 0; -} - - -static int wps_process_r_hash2(struct wps_data *wps, const u8 *r_hash2) -{ - if (r_hash2 == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No R-Hash2 received"); - return -1; - } - - os_memcpy(wps->peer_hash2, r_hash2, WPS_HASH_LEN); - wpa_hexdump(MSG_DEBUG, "WPS: R-Hash2", wps->peer_hash2, WPS_HASH_LEN); - - return 0; -} - - -static int wps_process_r_snonce1(struct wps_data *wps, const u8 *r_snonce1) -{ - u8 hash[SHA256_MAC_LEN]; - const u8 *addr[4]; - size_t len[4]; - - if (r_snonce1 == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No R-SNonce1 received"); - return -1; - } - - wpa_hexdump_key(MSG_DEBUG, "WPS: R-SNonce1", r_snonce1, - WPS_SECRET_NONCE_LEN); - - /* R-Hash1 = HMAC_AuthKey(R-S1 || PSK1 || PK_E || PK_R) */ - addr[0] = r_snonce1; - len[0] = WPS_SECRET_NONCE_LEN; - addr[1] = wps->psk1; - len[1] = WPS_PSK_LEN; - addr[2] = wpabuf_head(wps->dh_pubkey_e); - len[2] = wpabuf_len(wps->dh_pubkey_e); - addr[3] = wpabuf_head(wps->dh_pubkey_r); - len[3] = wpabuf_len(wps->dh_pubkey_r); - hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); - - if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: R-Hash1 derived from R-S1 does " - "not match with the pre-committed value"); - wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; - wps_pwd_auth_fail_event(wps->wps, 1, 1); - return -1; - } - - wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the first " - "half of the device password"); - - return 0; -} - - -static int wps_process_r_snonce2(struct wps_data *wps, const u8 *r_snonce2) -{ - u8 hash[SHA256_MAC_LEN]; - const u8 *addr[4]; - size_t len[4]; - - if (r_snonce2 == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No R-SNonce2 received"); - return -1; - } - - wpa_hexdump_key(MSG_DEBUG, "WPS: R-SNonce2", r_snonce2, - WPS_SECRET_NONCE_LEN); - - /* R-Hash2 = HMAC_AuthKey(R-S2 || PSK2 || PK_E || PK_R) */ - addr[0] = r_snonce2; - len[0] = WPS_SECRET_NONCE_LEN; - addr[1] = wps->psk2; - len[1] = WPS_PSK_LEN; - addr[2] = wpabuf_head(wps->dh_pubkey_e); - len[2] = wpabuf_len(wps->dh_pubkey_e); - addr[3] = wpabuf_head(wps->dh_pubkey_r); - len[3] = wpabuf_len(wps->dh_pubkey_r); - hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); - - if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: R-Hash2 derived from R-S2 does " - "not match with the pre-committed value"); - wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; - wps_pwd_auth_fail_event(wps->wps, 1, 2); - return -1; - } - - wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the second " - "half of the device password"); - - return 0; -} - - -static int wps_process_cred_e(struct wps_data *wps, const u8 *cred, - size_t cred_len) -{ - struct wps_parse_attr attr; - struct wpabuf msg; - - wpa_printf(MSG_DEBUG, "WPS: Received Credential"); - os_memset(&wps->cred, 0, sizeof(wps->cred)); - wpabuf_set(&msg, cred, cred_len); - if (wps_parse_msg(&msg, &attr) < 0 || - wps_process_cred(&attr, &wps->cred)) - return -1; - - if (os_memcmp(wps->cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) != - 0) { - wpa_printf(MSG_DEBUG, "WPS: MAC Address in the Credential (" - MACSTR ") does not match with own address (" MACSTR - ")", MAC2STR(wps->cred.mac_addr), - MAC2STR(wps->wps->dev.mac_addr)); - /* - * In theory, this could be consider fatal error, but there are - * number of deployed implementations using other address here - * due to unclarity in the specification. For interoperability - * reasons, allow this to be processed since we do not really - * use the MAC Address information for anything. - */ - } - - if (wps->wps->cred_cb) { - wps->cred.cred_attr = cred - 4; - wps->cred.cred_attr_len = cred_len + 4; - wps->wps->cred_cb(wps->wps->cb_ctx, &wps->cred); - wps->cred.cred_attr = NULL; - wps->cred.cred_attr_len = 0; - } - - return 0; -} - - -static int wps_process_creds(struct wps_data *wps, const u8 *cred[], - size_t cred_len[], size_t num_cred) -{ - size_t i; - - if (wps->wps->ap) - return 0; - - if (num_cred == 0) { - wpa_printf(MSG_DEBUG, "WPS: No Credential attributes " - "received"); - return -1; - } - - for (i = 0; i < num_cred; i++) { - if (wps_process_cred_e(wps, cred[i], cred_len[i])) - return -1; - } - - return 0; -} - - -static int wps_process_ap_settings_e(struct wps_data *wps, - struct wps_parse_attr *attr, - struct wpabuf *attrs) -{ - struct wps_credential cred; - - if (!wps->wps->ap) - return 0; - - if (wps_process_ap_settings(attr, &cred) < 0) - return -1; - - wpa_printf(MSG_INFO, "WPS: Received new AP configuration from " - "Registrar"); - - if (os_memcmp(cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) != - 0) { - wpa_printf(MSG_DEBUG, "WPS: MAC Address in the AP Settings (" - MACSTR ") does not match with own address (" MACSTR - ")", MAC2STR(cred.mac_addr), - MAC2STR(wps->wps->dev.mac_addr)); - /* - * In theory, this could be consider fatal error, but there are - * number of deployed implementations using other address here - * due to unclarity in the specification. For interoperability - * reasons, allow this to be processed since we do not really - * use the MAC Address information for anything. - */ - } - - if (wps->wps->cred_cb) { - cred.cred_attr = wpabuf_head(attrs); - cred.cred_attr_len = wpabuf_len(attrs); - wps->wps->cred_cb(wps->wps->cb_ctx, &cred); - } - - return 0; -} - - -static enum wps_process_res wps_process_m2(struct wps_data *wps, - const struct wpabuf *msg, - struct wps_parse_attr *attr) -{ - wpa_printf(MSG_DEBUG, "WPS: Received M2"); - - if (wps->state != RECV_M2) { - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " - "receiving M2", wps->state); - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || - wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || - wps_process_uuid_r(wps, attr->uuid_r) || - wps_process_pubkey(wps, attr->public_key, attr->public_key_len) || - wps_process_authenticator(wps, attr->authenticator, msg)) { - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - if (wps->wps->ap && wps->wps->ap_setup_locked) { - wpa_printf(MSG_DEBUG, "WPS: AP Setup is locked - refuse " - "registration of a new Registrar"); - wps->config_error = WPS_CFG_SETUP_LOCKED; - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - wps->state = SEND_M3; - return WPS_CONTINUE; -} - - -static enum wps_process_res wps_process_m2d(struct wps_data *wps, - struct wps_parse_attr *attr) -{ - wpa_printf(MSG_DEBUG, "WPS: Received M2D"); - - if (wps->state != RECV_M2) { - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " - "receiving M2D", wps->state); - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", - attr->manufacturer, attr->manufacturer_len); - wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", - attr->model_name, attr->model_name_len); - wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", - attr->model_number, attr->model_number_len); - wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", - attr->serial_number, attr->serial_number_len); - wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", - attr->dev_name, attr->dev_name_len); - - if (wps->wps->event_cb) { - union wps_event_data data; - struct wps_event_m2d *m2d = &data.m2d; - os_memset(&data, 0, sizeof(data)); - if (attr->config_methods) - m2d->config_methods = - WPA_GET_BE16(attr->config_methods); - m2d->manufacturer = attr->manufacturer; - m2d->manufacturer_len = attr->manufacturer_len; - m2d->model_name = attr->model_name; - m2d->model_name_len = attr->model_name_len; - m2d->model_number = attr->model_number; - m2d->model_number_len = attr->model_number_len; - m2d->serial_number = attr->serial_number; - m2d->serial_number_len = attr->serial_number_len; - m2d->dev_name = attr->dev_name; - m2d->dev_name_len = attr->dev_name_len; - m2d->primary_dev_type = attr->primary_dev_type; - if (attr->config_error) - m2d->config_error = - WPA_GET_BE16(attr->config_error); - if (attr->dev_password_id) - m2d->dev_password_id = - WPA_GET_BE16(attr->dev_password_id); - wps->wps->event_cb(wps->wps->cb_ctx, WPS_EV_M2D, &data); - } - - wps->state = RECEIVED_M2D; - return WPS_CONTINUE; -} - - -static enum wps_process_res wps_process_m4(struct wps_data *wps, - const struct wpabuf *msg, - struct wps_parse_attr *attr) -{ - struct wpabuf *decrypted; - struct wps_parse_attr eattr; - - wpa_printf(MSG_DEBUG, "WPS: Received M4"); - - if (wps->state != RECV_M4) { - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " - "receiving M4", wps->state); - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || - wps_process_authenticator(wps, attr->authenticator, msg) || - wps_process_r_hash1(wps, attr->r_hash1) || - wps_process_r_hash2(wps, attr->r_hash2)) { - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, - attr->encr_settings_len); - if (decrypted == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " - "Settings attribute"); - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " - "attribute"); - if (wps_parse_msg(decrypted, &eattr) < 0 || - wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || - wps_process_r_snonce1(wps, eattr.r_snonce1)) { - wpabuf_free(decrypted); - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - wpabuf_free(decrypted); - - wps->state = SEND_M5; - return WPS_CONTINUE; -} - - -static enum wps_process_res wps_process_m6(struct wps_data *wps, - const struct wpabuf *msg, - struct wps_parse_attr *attr) -{ - struct wpabuf *decrypted; - struct wps_parse_attr eattr; - - wpa_printf(MSG_DEBUG, "WPS: Received M6"); - - if (wps->state != RECV_M6) { - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " - "receiving M6", wps->state); - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || - wps_process_authenticator(wps, attr->authenticator, msg)) { - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, - attr->encr_settings_len); - if (decrypted == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " - "Settings attribute"); - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " - "attribute"); - if (wps_parse_msg(decrypted, &eattr) < 0 || - wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || - wps_process_r_snonce2(wps, eattr.r_snonce2)) { - wpabuf_free(decrypted); - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - wpabuf_free(decrypted); - - wps->state = SEND_M7; - return WPS_CONTINUE; -} - - -static enum wps_process_res wps_process_m8(struct wps_data *wps, - const struct wpabuf *msg, - struct wps_parse_attr *attr) -{ - struct wpabuf *decrypted; - struct wps_parse_attr eattr; - - wpa_printf(MSG_DEBUG, "WPS: Received M8"); - - if (wps->state != RECV_M8) { - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " - "receiving M8", wps->state); - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || - wps_process_authenticator(wps, attr->authenticator, msg)) { - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, - attr->encr_settings_len); - if (decrypted == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " - "Settings attribute"); - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " - "attribute"); - if (wps_parse_msg(decrypted, &eattr) < 0 || - wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || - wps_process_creds(wps, eattr.cred, eattr.cred_len, - eattr.num_cred) || - wps_process_ap_settings_e(wps, &eattr, decrypted)) { - wpabuf_free(decrypted); - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - wpabuf_free(decrypted); - - wps->state = WPS_MSG_DONE; - return WPS_CONTINUE; -} - - -static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, - const struct wpabuf *msg) -{ - struct wps_parse_attr attr; - enum wps_process_res ret = WPS_CONTINUE; - - wpa_printf(MSG_DEBUG, "WPS: Received WSC_MSG"); - - if (wps_parse_msg(msg, &attr) < 0) - return WPS_FAILURE; - - if (!wps_version_supported(attr.version)) { - wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", - attr.version ? *attr.version : 0); - return WPS_FAILURE; - } - - if (attr.enrollee_nonce == NULL || - os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); - return WPS_FAILURE; - } - - if (attr.msg_type == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); - return WPS_FAILURE; - } - - switch (*attr.msg_type) { - case WPS_M2: - ret = wps_process_m2(wps, msg, &attr); - break; - case WPS_M2D: - ret = wps_process_m2d(wps, &attr); - break; - case WPS_M4: - ret = wps_process_m4(wps, msg, &attr); - if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) - wps_fail_event(wps->wps, WPS_M4); - break; - case WPS_M6: - ret = wps_process_m6(wps, msg, &attr); - if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) - wps_fail_event(wps->wps, WPS_M6); - break; - case WPS_M8: - ret = wps_process_m8(wps, msg, &attr); - if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) - wps_fail_event(wps->wps, WPS_M8); - break; - default: - wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d", - *attr.msg_type); - return WPS_FAILURE; - } - - /* - * Save a copy of the last message for Authenticator derivation if we - * are continuing. However, skip M2D since it is not authenticated and - * neither is the ACK/NACK response frame. This allows the possibly - * following M2 to be processed correctly by using the previously sent - * M1 in Authenticator derivation. - */ - if (ret == WPS_CONTINUE && *attr.msg_type != WPS_M2D) { - /* Save a copy of the last message for Authenticator derivation - */ - wpabuf_free(wps->last_msg); - wps->last_msg = wpabuf_dup(msg); - } - - return ret; -} - - -static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps, - const struct wpabuf *msg) -{ - struct wps_parse_attr attr; - - wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK"); - - if (wps_parse_msg(msg, &attr) < 0) - return WPS_FAILURE; - - if (!wps_version_supported(attr.version)) { - wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", - attr.version ? *attr.version : 0); - return WPS_FAILURE; - } - - if (attr.msg_type == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); - return WPS_FAILURE; - } - - if (*attr.msg_type != WPS_WSC_ACK) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", - *attr.msg_type); - return WPS_FAILURE; - } - - if (attr.registrar_nonce == NULL || - os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0)) - { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); - return WPS_FAILURE; - } - - if (attr.enrollee_nonce == NULL || - os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); - return WPS_FAILURE; - } - - if (wps->state == RECV_ACK && wps->wps->ap) { - wpa_printf(MSG_DEBUG, "WPS: External Registrar registration " - "completed successfully"); - wps_success_event(wps->wps); - wps->state = WPS_FINISHED; - return WPS_DONE; - } - - return WPS_FAILURE; -} - - -static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps, - const struct wpabuf *msg) -{ - struct wps_parse_attr attr; - - wpa_printf(MSG_DEBUG, "WPS: Received WSC_NACK"); - - if (wps_parse_msg(msg, &attr) < 0) - return WPS_FAILURE; - - if (!wps_version_supported(attr.version)) { - wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", - attr.version ? *attr.version : 0); - return WPS_FAILURE; - } - - if (attr.msg_type == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); - return WPS_FAILURE; - } - - if (*attr.msg_type != WPS_WSC_NACK) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", - *attr.msg_type); - return WPS_FAILURE; - } - - if (attr.registrar_nonce == NULL || - os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0)) - { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); - wpa_hexdump(MSG_DEBUG, "WPS: Received Registrar Nonce", - attr.registrar_nonce, WPS_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "WPS: Expected Registrar Nonce", - wps->nonce_r, WPS_NONCE_LEN); - return WPS_FAILURE; - } - - if (attr.enrollee_nonce == NULL || - os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); - wpa_hexdump(MSG_DEBUG, "WPS: Received Enrollee Nonce", - attr.enrollee_nonce, WPS_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "WPS: Expected Enrollee Nonce", - wps->nonce_e, WPS_NONCE_LEN); - return WPS_FAILURE; - } - - if (attr.config_error == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Configuration Error attribute " - "in WSC_NACK"); - return WPS_FAILURE; - } - - wpa_printf(MSG_DEBUG, "WPS: Registrar terminated negotiation with " - "Configuration Error %d", WPA_GET_BE16(attr.config_error)); - - switch (wps->state) { - case RECV_M4: - wps_fail_event(wps->wps, WPS_M3); - break; - case RECV_M6: - wps_fail_event(wps->wps, WPS_M5); - break; - case RECV_M8: - wps_fail_event(wps->wps, WPS_M7); - break; - default: - break; - } - - /* Followed by NACK if Enrollee is Supplicant or EAP-Failure if - * Enrollee is Authenticator */ - wps->state = SEND_WSC_NACK; - - return WPS_FAILURE; -} - - -enum wps_process_res wps_enrollee_process_msg(struct wps_data *wps, - enum wsc_op_code op_code, - const struct wpabuf *msg) -{ - - wpa_printf(MSG_DEBUG, "WPS: Processing received message (len=%lu " - "op_code=%d)", - (unsigned long) wpabuf_len(msg), op_code); - - if (op_code == WSC_UPnP) { - /* Determine the OpCode based on message type attribute */ - struct wps_parse_attr attr; - if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type) { - if (*attr.msg_type == WPS_WSC_ACK) - op_code = WSC_ACK; - else if (*attr.msg_type == WPS_WSC_NACK) - op_code = WSC_NACK; - } - } - - switch (op_code) { - case WSC_MSG: - case WSC_UPnP: - return wps_process_wsc_msg(wps, msg); - case WSC_ACK: - return wps_process_wsc_ack(wps, msg); - case WSC_NACK: - return wps_process_wsc_nack(wps, msg); - default: - wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code); - return WPS_FAILURE; - } -} diff --git a/contrib/hostapd/src/wps/wps_i.h b/contrib/hostapd/src/wps/wps_i.h deleted file mode 100644 index 3317a2cd4e..0000000000 --- a/contrib/hostapd/src/wps/wps_i.h +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Wi-Fi Protected Setup - internal definitions - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPS_I_H -#define WPS_I_H - -#include "wps.h" - -/** - * struct wps_data - WPS registration protocol data - * - * This data is stored at the EAP-WSC server/peer method and it is kept for a - * single registration protocol run. - */ -struct wps_data { - /** - * wps - Pointer to long term WPS context - */ - struct wps_context *wps; - - /** - * registrar - Whether this end is a Registrar - */ - int registrar; - - enum { - /* Enrollee states */ - SEND_M1, RECV_M2, SEND_M3, RECV_M4, SEND_M5, RECV_M6, SEND_M7, - RECV_M8, RECEIVED_M2D, WPS_MSG_DONE, RECV_ACK, WPS_FINISHED, - SEND_WSC_NACK, - - /* Registrar states */ - RECV_M1, SEND_M2, RECV_M3, SEND_M4, RECV_M5, SEND_M6, - RECV_M7, SEND_M8, RECV_DONE, SEND_M2D, RECV_M2D_ACK - } state; - - u8 uuid_e[WPS_UUID_LEN]; - u8 uuid_r[WPS_UUID_LEN]; - u8 mac_addr_e[ETH_ALEN]; - u8 nonce_e[WPS_NONCE_LEN]; - u8 nonce_r[WPS_NONCE_LEN]; - u8 psk1[WPS_PSK_LEN]; - u8 psk2[WPS_PSK_LEN]; - u8 snonce[2 * WPS_SECRET_NONCE_LEN]; - u8 peer_hash1[WPS_HASH_LEN]; - u8 peer_hash2[WPS_HASH_LEN]; - - struct wpabuf *dh_privkey; - struct wpabuf *dh_pubkey_e; - struct wpabuf *dh_pubkey_r; - u8 authkey[WPS_AUTHKEY_LEN]; - u8 keywrapkey[WPS_KEYWRAPKEY_LEN]; - u8 emsk[WPS_EMSK_LEN]; - - struct wpabuf *last_msg; - - u8 *dev_password; - size_t dev_password_len; - u16 dev_pw_id; - int pbc; - - /** - * request_type - Request Type attribute from (Re)AssocReq - */ - u8 request_type; - - /** - * encr_type - Available encryption types - */ - u16 encr_type; - - /** - * auth_type - Available authentication types - */ - u16 auth_type; - - u8 *new_psk; - size_t new_psk_len; - - int wps_pin_revealed; - struct wps_credential cred; - - struct wps_device_data peer_dev; - - /** - * config_error - Configuration Error value to be used in NACK - */ - u16 config_error; - - int ext_reg; -}; - - -struct wps_parse_attr { - /* fixed length fields */ - const u8 *version; /* 1 octet */ - const u8 *msg_type; /* 1 octet */ - const u8 *enrollee_nonce; /* WPS_NONCE_LEN (16) octets */ - const u8 *registrar_nonce; /* WPS_NONCE_LEN (16) octets */ - const u8 *uuid_r; /* WPS_UUID_LEN (16) octets */ - const u8 *uuid_e; /* WPS_UUID_LEN (16) octets */ - const u8 *auth_type_flags; /* 2 octets */ - const u8 *encr_type_flags; /* 2 octets */ - const u8 *conn_type_flags; /* 1 octet */ - const u8 *config_methods; /* 2 octets */ - const u8 *sel_reg_config_methods; /* 2 octets */ - const u8 *primary_dev_type; /* 8 octets */ - const u8 *rf_bands; /* 1 octet */ - const u8 *assoc_state; /* 2 octets */ - const u8 *config_error; /* 2 octets */ - const u8 *dev_password_id; /* 2 octets */ - const u8 *os_version; /* 4 octets */ - const u8 *wps_state; /* 1 octet */ - const u8 *authenticator; /* WPS_AUTHENTICATOR_LEN (8) octets */ - const u8 *r_hash1; /* WPS_HASH_LEN (32) octets */ - const u8 *r_hash2; /* WPS_HASH_LEN (32) octets */ - const u8 *e_hash1; /* WPS_HASH_LEN (32) octets */ - const u8 *e_hash2; /* WPS_HASH_LEN (32) octets */ - const u8 *r_snonce1; /* WPS_SECRET_NONCE_LEN (16) octets */ - const u8 *r_snonce2; /* WPS_SECRET_NONCE_LEN (16) octets */ - const u8 *e_snonce1; /* WPS_SECRET_NONCE_LEN (16) octets */ - const u8 *e_snonce2; /* WPS_SECRET_NONCE_LEN (16) octets */ - const u8 *key_wrap_auth; /* WPS_KWA_LEN (8) octets */ - const u8 *auth_type; /* 2 octets */ - const u8 *encr_type; /* 2 octets */ - const u8 *network_idx; /* 1 octet */ - const u8 *network_key_idx; /* 1 octet */ - const u8 *mac_addr; /* ETH_ALEN (6) octets */ - const u8 *key_prov_auto; /* 1 octet (Bool) */ - const u8 *dot1x_enabled; /* 1 octet (Bool) */ - const u8 *selected_registrar; /* 1 octet (Bool) */ - const u8 *request_type; /* 1 octet */ - const u8 *response_type; /* 1 octet */ - const u8 *ap_setup_locked; /* 1 octet */ - - /* variable length fields */ - const u8 *manufacturer; - size_t manufacturer_len; - const u8 *model_name; - size_t model_name_len; - const u8 *model_number; - size_t model_number_len; - const u8 *serial_number; - size_t serial_number_len; - const u8 *dev_name; - size_t dev_name_len; - const u8 *public_key; - size_t public_key_len; - const u8 *encr_settings; - size_t encr_settings_len; - const u8 *ssid; /* <= 32 octets */ - size_t ssid_len; - const u8 *network_key; /* <= 64 octets */ - size_t network_key_len; - const u8 *eap_type; /* <= 8 octets */ - size_t eap_type_len; - const u8 *eap_identity; /* <= 64 octets */ - size_t eap_identity_len; - - /* attributes that can occur multiple times */ -#define MAX_CRED_COUNT 10 - const u8 *cred[MAX_CRED_COUNT]; - size_t cred_len[MAX_CRED_COUNT]; - size_t num_cred; -}; - -/* wps_common.c */ -void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len, - const char *label, u8 *res, size_t res_len); -int wps_derive_keys(struct wps_data *wps); -void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, - size_t dev_passwd_len); -struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, - size_t encr_len); -void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg); -void wps_success_event(struct wps_context *wps); -void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part); -void wps_pbc_overlap_event(struct wps_context *wps); -void wps_pbc_timeout_event(struct wps_context *wps); - -/* wps_attr_parse.c */ -int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr); - -/* wps_attr_build.c */ -int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg); -int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type); -int wps_build_config_methods(struct wpabuf *msg, u16 methods); -int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid); -int wps_build_dev_password_id(struct wpabuf *msg, u16 id); -int wps_build_config_error(struct wpabuf *msg, u16 err); -int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg); -int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg); -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_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); -int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg); -int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg); -int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg); -int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg); - -/* wps_attr_process.c */ -int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator, - const struct wpabuf *msg); -int wps_process_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg, - const u8 *key_wrap_auth); -int wps_process_cred(struct wps_parse_attr *attr, - struct wps_credential *cred); -int wps_process_ap_settings(struct wps_parse_attr *attr, - struct wps_credential *cred); - -/* wps_enrollee.c */ -struct wpabuf * wps_enrollee_get_msg(struct wps_data *wps, - enum wsc_op_code *op_code); -enum wps_process_res wps_enrollee_process_msg(struct wps_data *wps, - enum wsc_op_code op_code, - const struct wpabuf *msg); - -/* wps_registrar.c */ -struct wpabuf * wps_registrar_get_msg(struct wps_data *wps, - enum wsc_op_code *op_code); -enum wps_process_res wps_registrar_process_msg(struct wps_data *wps, - enum wsc_op_code op_code, - const struct wpabuf *msg); - - -static inline int wps_version_supported(const u8 *version) -{ - /* Require major version match, but allow minor version differences */ - return version && (*version & 0xf0) == (WPS_VERSION & 0xf0); -} - -#endif /* WPS_I_H */ diff --git a/contrib/hostapd/src/wps/wps_registrar.c b/contrib/hostapd/src/wps/wps_registrar.c deleted file mode 100644 index f34c9e9af0..0000000000 --- a/contrib/hostapd/src/wps/wps_registrar.c +++ /dev/null @@ -1,2640 +0,0 @@ -/* - * Wi-Fi Protected Setup - Registrar - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha256.h" -#include "base64.h" -#include "ieee802_11_defs.h" -#include "eloop.h" -#include "wps_i.h" -#include "wps_dev_attr.h" -#include "wps_upnp.h" - -#define WPS_WORKAROUNDS - -struct wps_uuid_pin { - struct wps_uuid_pin *next; - u8 uuid[WPS_UUID_LEN]; - int wildcard_uuid; - u8 *pin; - size_t pin_len; -#define PIN_LOCKED BIT(0) -#define PIN_EXPIRES BIT(1) - int flags; - struct os_time expiration; -}; - - -static void wps_free_pin(struct wps_uuid_pin *pin) -{ - os_free(pin->pin); - os_free(pin); -} - - -static void wps_free_pins(struct wps_uuid_pin *pins) -{ - struct wps_uuid_pin *pin, *prev; - - pin = pins; - while (pin) { - prev = pin; - pin = pin->next; - wps_free_pin(prev); - } -} - - -struct wps_pbc_session { - struct wps_pbc_session *next; - u8 addr[ETH_ALEN]; - u8 uuid_e[WPS_UUID_LEN]; - struct os_time timestamp; -}; - - -static void wps_free_pbc_sessions(struct wps_pbc_session *pbc) -{ - struct wps_pbc_session *prev; - - while (pbc) { - prev = pbc; - pbc = pbc->next; - os_free(prev); - } -} - - -struct wps_registrar { - struct wps_context *wps; - - int pbc; - int selected_registrar; - - int (*new_psk_cb)(void *ctx, const u8 *mac_addr, const u8 *psk, - size_t psk_len); - int (*set_ie_cb)(void *ctx, const u8 *beacon_ie, size_t beacon_ie_len, - const u8 *probe_resp_ie, size_t probe_resp_ie_len); - void (*pin_needed_cb)(void *ctx, const u8 *uuid_e, - const struct wps_device_data *dev); - void (*reg_success_cb)(void *ctx, const u8 *mac_addr, - const u8 *uuid_e); - void *cb_ctx; - - struct wps_uuid_pin *pins; - struct wps_pbc_session *pbc_sessions; - - int skip_cred_build; - struct wpabuf *extra_cred; - int disable_auto_conf; - int sel_reg_dev_password_id_override; - int sel_reg_config_methods_override; - int static_wep_only; - - int force_pbc_overlap; -}; - - -static int wps_set_ie(struct wps_registrar *reg); -static void wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx); -static void wps_registrar_set_selected_timeout(void *eloop_ctx, - void *timeout_ctx); - - -static void wps_registrar_add_pbc_session(struct wps_registrar *reg, - const u8 *addr, const u8 *uuid_e) -{ - struct wps_pbc_session *pbc, *prev = NULL; - struct os_time now; - - os_get_time(&now); - - pbc = reg->pbc_sessions; - while (pbc) { - if (os_memcmp(pbc->addr, addr, ETH_ALEN) == 0 && - os_memcmp(pbc->uuid_e, uuid_e, WPS_UUID_LEN) == 0) { - if (prev) - prev->next = pbc->next; - else - reg->pbc_sessions = pbc->next; - break; - } - prev = pbc; - pbc = pbc->next; - } - - if (!pbc) { - pbc = os_zalloc(sizeof(*pbc)); - if (pbc == NULL) - return; - os_memcpy(pbc->addr, addr, ETH_ALEN); - if (uuid_e) - os_memcpy(pbc->uuid_e, uuid_e, WPS_UUID_LEN); - } - - pbc->next = reg->pbc_sessions; - reg->pbc_sessions = pbc; - pbc->timestamp = now; - - /* remove entries that have timed out */ - prev = pbc; - pbc = pbc->next; - - while (pbc) { - if (now.sec > pbc->timestamp.sec + WPS_PBC_WALK_TIME) { - prev->next = NULL; - wps_free_pbc_sessions(pbc); - break; - } - prev = pbc; - pbc = pbc->next; - } -} - - -static void wps_registrar_remove_pbc_session(struct wps_registrar *reg, - const u8 *addr, const u8 *uuid_e) -{ - struct wps_pbc_session *pbc, *prev = NULL; - - pbc = reg->pbc_sessions; - while (pbc) { - if (os_memcmp(pbc->addr, addr, ETH_ALEN) == 0 && - os_memcmp(pbc->uuid_e, uuid_e, WPS_UUID_LEN) == 0) { - if (prev) - prev->next = pbc->next; - else - reg->pbc_sessions = pbc->next; - os_free(pbc); - break; - } - prev = pbc; - pbc = pbc->next; - } -} - - -static int wps_registrar_pbc_overlap(struct wps_registrar *reg, - const u8 *addr, const u8 *uuid_e) -{ - int count = 0; - struct wps_pbc_session *pbc; - struct os_time now; - - os_get_time(&now); - - for (pbc = reg->pbc_sessions; pbc; pbc = pbc->next) { - if (now.sec > pbc->timestamp.sec + WPS_PBC_WALK_TIME) - break; - if (addr == NULL || os_memcmp(addr, pbc->addr, ETH_ALEN) || - uuid_e == NULL || - os_memcmp(uuid_e, pbc->uuid_e, WPS_UUID_LEN)) - count++; - } - - if (addr || uuid_e) - count++; - - return count > 1 ? 1 : 0; -} - - -static int wps_build_wps_state(struct wps_context *wps, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * Wi-Fi Protected Setup State (%d)", - wps->wps_state); - wpabuf_put_be16(msg, ATTR_WPS_STATE); - wpabuf_put_be16(msg, 1); - wpabuf_put_u8(msg, wps->wps_state); - return 0; -} - - -#ifdef CONFIG_WPS_UPNP -static void wps_registrar_free_pending_m2(struct wps_context *wps) -{ - struct upnp_pending_message *p, *p2, *prev = NULL; - p = wps->upnp_msgs; - while (p) { - if (p->type == WPS_M2 || p->type == WPS_M2D) { - if (prev == NULL) - wps->upnp_msgs = p->next; - else - prev->next = p->next; - wpa_printf(MSG_DEBUG, "WPS UPnP: Drop pending M2/M2D"); - p2 = p; - p = p->next; - wpabuf_free(p2->msg); - os_free(p2); - continue; - } - prev = p; - p = p->next; - } -} -#endif /* CONFIG_WPS_UPNP */ - - -static int wps_build_ap_setup_locked(struct wps_context *wps, - struct wpabuf *msg) -{ - if (wps->ap_setup_locked) { - wpa_printf(MSG_DEBUG, "WPS: * AP Setup Locked"); - wpabuf_put_be16(msg, ATTR_AP_SETUP_LOCKED); - wpabuf_put_be16(msg, 1); - wpabuf_put_u8(msg, 1); - } - return 0; -} - - -static int wps_build_selected_registrar(struct wps_registrar *reg, - struct wpabuf *msg) -{ - if (!reg->selected_registrar) - return 0; - wpa_printf(MSG_DEBUG, "WPS: * Selected Registrar"); - wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR); - wpabuf_put_be16(msg, 1); - wpabuf_put_u8(msg, 1); - return 0; -} - - -static int wps_build_sel_reg_dev_password_id(struct wps_registrar *reg, - struct wpabuf *msg) -{ - u16 id = reg->pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT; - if (!reg->selected_registrar) - return 0; - if (reg->sel_reg_dev_password_id_override >= 0) - id = reg->sel_reg_dev_password_id_override; - wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id); - wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); - wpabuf_put_be16(msg, 2); - wpabuf_put_be16(msg, id); - return 0; -} - - -static int wps_build_sel_reg_config_methods(struct wps_registrar *reg, - struct wpabuf *msg) -{ - u16 methods; - if (!reg->selected_registrar) - return 0; - methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; - if (reg->pbc) - methods |= WPS_CONFIG_PUSHBUTTON; - if (reg->sel_reg_config_methods_override >= 0) - methods = reg->sel_reg_config_methods_override; - wpa_printf(MSG_DEBUG, "WPS: * Selected Registrar Config Methods (%x)", - methods); - wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR_CONFIG_METHODS); - wpabuf_put_be16(msg, 2); - wpabuf_put_be16(msg, methods); - return 0; -} - - -static int wps_build_probe_config_methods(struct wps_registrar *reg, - struct wpabuf *msg) -{ - u16 methods; - methods = 0; - wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods); - wpabuf_put_be16(msg, ATTR_CONFIG_METHODS); - wpabuf_put_be16(msg, 2); - wpabuf_put_be16(msg, methods); - return 0; -} - - -static int wps_build_config_methods_r(struct wps_registrar *reg, - struct wpabuf *msg) -{ - u16 methods; - methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; - if (reg->pbc) - methods |= WPS_CONFIG_PUSHBUTTON; - return wps_build_config_methods(msg, methods); -} - - -static int wps_build_resp_type(struct wps_registrar *reg, struct wpabuf *msg) -{ - u8 resp = reg->wps->ap ? WPS_RESP_AP : WPS_RESP_REGISTRAR; - wpa_printf(MSG_DEBUG, "WPS: * Response Type (%d)", resp); - wpabuf_put_be16(msg, ATTR_RESPONSE_TYPE); - wpabuf_put_be16(msg, 1); - wpabuf_put_u8(msg, resp); - return 0; -} - - -/** - * wps_registrar_init - Initialize WPS Registrar data - * @wps: Pointer to longterm WPS context - * @cfg: Registrar configuration - * Returns: Pointer to allocated Registrar data or %NULL on failure - * - * This function is used to initialize WPS Registrar functionality. It can be - * used for a single Registrar run (e.g., when run in a supplicant) or multiple - * runs (e.g., when run as an internal Registrar in an AP). Caller is - * responsible for freeing the returned data with wps_registrar_deinit() when - * Registrar functionality is not needed anymore. - */ -struct wps_registrar * -wps_registrar_init(struct wps_context *wps, - const struct wps_registrar_config *cfg) -{ - struct wps_registrar *reg = os_zalloc(sizeof(*reg)); - if (reg == NULL) - return NULL; - - reg->wps = wps; - reg->new_psk_cb = cfg->new_psk_cb; - reg->set_ie_cb = cfg->set_ie_cb; - reg->pin_needed_cb = cfg->pin_needed_cb; - reg->reg_success_cb = cfg->reg_success_cb; - reg->cb_ctx = cfg->cb_ctx; - reg->skip_cred_build = cfg->skip_cred_build; - if (cfg->extra_cred) { - reg->extra_cred = wpabuf_alloc_copy(cfg->extra_cred, - cfg->extra_cred_len); - if (reg->extra_cred == NULL) { - os_free(reg); - return NULL; - } - } - reg->disable_auto_conf = cfg->disable_auto_conf; - reg->sel_reg_dev_password_id_override = -1; - reg->sel_reg_config_methods_override = -1; - reg->static_wep_only = cfg->static_wep_only; - - if (wps_set_ie(reg)) { - wps_registrar_deinit(reg); - return NULL; - } - - return reg; -} - - -/** - * wps_registrar_deinit - Deinitialize WPS Registrar data - * @reg: Registrar data from wps_registrar_init() - */ -void wps_registrar_deinit(struct wps_registrar *reg) -{ - if (reg == NULL) - return; - eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); - eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); - wps_free_pins(reg->pins); - wps_free_pbc_sessions(reg->pbc_sessions); - wpabuf_free(reg->extra_cred); - os_free(reg); -} - - -/** - * wps_registrar_add_pin - Configure a new PIN for Registrar - * @reg: Registrar data from wps_registrar_init() - * @uuid: UUID-E or %NULL for wildcard (any UUID) - * @pin: PIN (Device Password) - * @pin_len: Length of pin in octets - * @timeout: Time (in seconds) when the PIN will be invalidated; 0 = no timeout - * Returns: 0 on success, -1 on failure - */ -int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *uuid, - const u8 *pin, size_t pin_len, int timeout) -{ - struct wps_uuid_pin *p; - - p = os_zalloc(sizeof(*p)); - if (p == NULL) - return -1; - if (uuid == NULL) - p->wildcard_uuid = 1; - else - os_memcpy(p->uuid, uuid, WPS_UUID_LEN); - p->pin = os_malloc(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) { - p->flags |= PIN_EXPIRES; - os_get_time(&p->expiration); - p->expiration.sec += timeout; - } - - p->next = reg->pins; - reg->pins = p; - - wpa_printf(MSG_DEBUG, "WPS: A new PIN configured (timeout=%d)", - timeout); - wpa_hexdump(MSG_DEBUG, "WPS: UUID", uuid, WPS_UUID_LEN); - wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: PIN", pin, pin_len); - reg->selected_registrar = 1; - reg->pbc = 0; - wps_set_ie(reg); - eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); - eloop_register_timeout(WPS_PBC_WALK_TIME, 0, - wps_registrar_set_selected_timeout, - reg, NULL); - - return 0; -} - - -static void wps_registrar_expire_pins(struct wps_registrar *reg) -{ - struct wps_uuid_pin *pin, *prev, *del; - struct os_time now; - - os_get_time(&now); - prev = NULL; - pin = reg->pins; - while (pin) { - if ((pin->flags & PIN_EXPIRES) && - os_time_before(&pin->expiration, &now)) { - if (prev == NULL) - reg->pins = pin->next; - else - prev->next = pin->next; - del = pin; - pin = pin->next; - wpa_hexdump(MSG_DEBUG, "WPS: Expired PIN for UUID", - del->uuid, WPS_UUID_LEN); - wps_free_pin(del); - continue; - } - prev = pin; - pin = pin->next; - } -} - - -/** - * wps_registrar_invalidate_pin - Invalidate a PIN for a specific UUID-E - * @reg: Registrar data from wps_registrar_init() - * @uuid: UUID-E - * Returns: 0 on success, -1 on failure (e.g., PIN not found) - */ -int wps_registrar_invalidate_pin(struct wps_registrar *reg, const u8 *uuid) -{ - struct wps_uuid_pin *pin, *prev; - - prev = NULL; - pin = reg->pins; - while (pin) { - if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) { - if (prev == NULL) - reg->pins = pin->next; - else - prev->next = pin->next; - wpa_hexdump(MSG_DEBUG, "WPS: Invalidated PIN for UUID", - pin->uuid, WPS_UUID_LEN); - wps_free_pin(pin); - return 0; - } - prev = pin; - pin = pin->next; - } - - return -1; -} - - -static const u8 * wps_registrar_get_pin(struct wps_registrar *reg, - const u8 *uuid, size_t *pin_len) -{ - struct wps_uuid_pin *pin; - - wps_registrar_expire_pins(reg); - - pin = reg->pins; - while (pin) { - if (!pin->wildcard_uuid && - os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) - break; - pin = pin->next; - } - - if (!pin) { - /* Check for wildcard UUIDs since none of the UUID-specific - * PINs matched */ - pin = reg->pins; - while (pin) { - if (pin->wildcard_uuid == 1) { - wpa_printf(MSG_DEBUG, "WPS: Found a wildcard " - "PIN. Assigned it for this UUID-E"); - pin->wildcard_uuid = 2; - os_memcpy(pin->uuid, uuid, WPS_UUID_LEN); - break; - } - pin = pin->next; - } - } - - if (!pin) - return NULL; - - /* - * Lock the PIN to avoid attacks based on concurrent re-use of the PIN - * that could otherwise avoid PIN invalidations. - */ - if (pin->flags & PIN_LOCKED) { - wpa_printf(MSG_DEBUG, "WPS: Selected PIN locked - do not " - "allow concurrent re-use"); - return NULL; - } - *pin_len = pin->pin_len; - pin->flags |= PIN_LOCKED; - return pin->pin; -} - - -/** - * wps_registrar_unlock_pin - Unlock a PIN for a specific UUID-E - * @reg: Registrar data from wps_registrar_init() - * @uuid: UUID-E - * Returns: 0 on success, -1 on failure - * - * PINs are locked to enforce only one concurrent use. This function unlocks a - * PIN to allow it to be used again. If the specified PIN was configured using - * a wildcard UUID, it will be removed instead of allowing multiple uses. - */ -int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid) -{ - struct wps_uuid_pin *pin; - - pin = reg->pins; - while (pin) { - if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) { - if (pin->wildcard_uuid == 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalidating used " - "wildcard PIN"); - return wps_registrar_invalidate_pin(reg, uuid); - } - pin->flags &= ~PIN_LOCKED; - return 0; - } - pin = pin->next; - } - - return -1; -} - - -static void wps_registrar_stop_pbc(struct wps_registrar *reg) -{ - reg->selected_registrar = 0; - reg->pbc = 0; - wps_set_ie(reg); -} - - -static void wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wps_registrar *reg = eloop_ctx; - - wpa_printf(MSG_DEBUG, "WPS: PBC timed out - disable PBC mode"); - wps_pbc_timeout_event(reg->wps); - wps_registrar_stop_pbc(reg); -} - - -/** - * wps_registrar_button_pushed - Notify Registrar that AP button was pushed - * @reg: Registrar data from wps_registrar_init() - * Returns: 0 on success, -1 on failure - * - * This function is called on an AP when a push button is pushed to activate - * PBC mode. The PBC mode will be stopped after walk time (2 minutes) timeout - * or when a PBC registration is completed. - */ -int wps_registrar_button_pushed(struct wps_registrar *reg) -{ - if (wps_registrar_pbc_overlap(reg, NULL, NULL)) { - wpa_printf(MSG_DEBUG, "WPS: PBC overlap - do not start PBC " - "mode"); - wps_pbc_overlap_event(reg->wps); - return -1; - } - wpa_printf(MSG_DEBUG, "WPS: Button pushed - PBC mode started"); - reg->force_pbc_overlap = 0; - reg->selected_registrar = 1; - reg->pbc = 1; - wps_set_ie(reg); - - eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); - eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wps_registrar_pbc_timeout, - reg, NULL); - return 0; -} - - -static void wps_registrar_pbc_completed(struct wps_registrar *reg) -{ - wpa_printf(MSG_DEBUG, "WPS: PBC completed - stopping PBC mode"); - eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); - wps_registrar_stop_pbc(reg); -} - -static void wps_registrar_pin_completed(struct wps_registrar *reg) -{ - wpa_printf(MSG_DEBUG, "WPS: PIN completed using internal Registrar"); - eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); - reg->selected_registrar = 0; - wps_set_ie(reg); -} - - -/** - * wps_registrar_probe_req_rx - Notify Registrar of Probe Request - * @reg: Registrar data from wps_registrar_init() - * @addr: MAC address of the Probe Request sender - * @wps_data: WPS IE contents - * - * This function is called on an AP when a Probe Request with WPS IE is - * received. This is used to track PBC mode use and to detect possible overlap - * situation with other WPS APs. - */ -void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr, - const struct wpabuf *wps_data) -{ - struct wps_parse_attr attr; - u16 methods; - - wpa_hexdump_buf(MSG_MSGDUMP, - "WPS: Probe Request with WPS data received", - wps_data); - - if (wps_parse_msg(wps_data, &attr) < 0) - return; - if (!wps_version_supported(attr.version)) { - wpa_printf(MSG_DEBUG, "WPS: Unsupported ProbeReq WPS IE " - "version 0x%x", attr.version ? *attr.version : 0); - return; - } - - if (attr.config_methods == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Config Methods attribute in " - "Probe Request"); - return; - } - - methods = WPA_GET_BE16(attr.config_methods); - if (!(methods & WPS_CONFIG_PUSHBUTTON)) - return; /* Not PBC */ - - wpa_printf(MSG_DEBUG, "WPS: Probe Request for PBC received from " - MACSTR, MAC2STR(addr)); - if (attr.uuid_e == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Probe Request WPS IE: No " - "UUID-E included"); - return; - } - - wps_registrar_add_pbc_session(reg, addr, attr.uuid_e); - if (wps_registrar_pbc_overlap(reg, addr, attr.uuid_e)) { - wpa_printf(MSG_DEBUG, "WPS: PBC session overlap detected"); - reg->force_pbc_overlap = 1; - wps_pbc_overlap_event(reg->wps); - } -} - - -static int wps_cb_new_psk(struct wps_registrar *reg, const u8 *mac_addr, - const u8 *psk, size_t psk_len) -{ - if (reg->new_psk_cb == NULL) - return 0; - - return reg->new_psk_cb(reg->cb_ctx, mac_addr, psk, psk_len); -} - - -static void wps_cb_pin_needed(struct wps_registrar *reg, const u8 *uuid_e, - const struct wps_device_data *dev) -{ - if (reg->pin_needed_cb == NULL) - return; - - reg->pin_needed_cb(reg->cb_ctx, uuid_e, dev); -} - - -static void wps_cb_reg_success(struct wps_registrar *reg, const u8 *mac_addr, - const u8 *uuid_e) -{ - if (reg->reg_success_cb == NULL) - return; - - reg->reg_success_cb(reg->cb_ctx, mac_addr, uuid_e); -} - - -static int wps_cb_set_ie(struct wps_registrar *reg, - const struct wpabuf *beacon_ie, - const struct wpabuf *probe_resp_ie) -{ - if (reg->set_ie_cb == NULL) - return 0; - - return reg->set_ie_cb(reg->cb_ctx, wpabuf_head(beacon_ie), - wpabuf_len(beacon_ie), - wpabuf_head(probe_resp_ie), - wpabuf_len(probe_resp_ie)); -} - - -/* Encapsulate WPS IE data with one (or more, if needed) IE headers */ -static struct wpabuf * wps_ie_encapsulate(struct wpabuf *data) -{ - struct wpabuf *ie; - const u8 *pos, *end; - - ie = wpabuf_alloc(wpabuf_len(data) + 100); - if (ie == NULL) { - wpabuf_free(data); - return NULL; - } - - pos = wpabuf_head(data); - end = pos + wpabuf_len(data); - - while (end > pos) { - size_t frag_len = end - pos; - if (frag_len > 251) - frag_len = 251; - wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); - wpabuf_put_u8(ie, 4 + frag_len); - wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); - wpabuf_put_data(ie, pos, frag_len); - pos += frag_len; - } - - wpabuf_free(data); - - return ie; -} - - -static int wps_set_ie(struct wps_registrar *reg) -{ - struct wpabuf *beacon; - struct wpabuf *probe; - int ret; - - wpa_printf(MSG_DEBUG, "WPS: Build Beacon and Probe Response IEs"); - - beacon = wpabuf_alloc(300); - if (beacon == NULL) - return -1; - probe = wpabuf_alloc(400); - if (probe == NULL) { - wpabuf_free(beacon); - return -1; - } - - if (wps_build_version(beacon) || - wps_build_wps_state(reg->wps, beacon) || - wps_build_ap_setup_locked(reg->wps, beacon) || - wps_build_selected_registrar(reg, beacon) || - wps_build_sel_reg_dev_password_id(reg, beacon) || - wps_build_sel_reg_config_methods(reg, beacon) || - wps_build_version(probe) || - wps_build_wps_state(reg->wps, probe) || - wps_build_ap_setup_locked(reg->wps, probe) || - wps_build_selected_registrar(reg, probe) || - wps_build_sel_reg_dev_password_id(reg, probe) || - wps_build_sel_reg_config_methods(reg, probe) || - wps_build_resp_type(reg, probe) || - wps_build_uuid_e(probe, reg->wps->uuid) || - wps_build_device_attrs(®->wps->dev, probe) || - wps_build_probe_config_methods(reg, probe) || - wps_build_rf_bands(®->wps->dev, probe)) { - wpabuf_free(beacon); - wpabuf_free(probe); - return -1; - } - - beacon = wps_ie_encapsulate(beacon); - probe = wps_ie_encapsulate(probe); - - if (!beacon || !probe) { - wpabuf_free(beacon); - wpabuf_free(probe); - return -1; - } - - if (reg->static_wep_only) { - /* - * Windows XP and Vista clients can get confused about - * EAP-Identity/Request when they probe the network with - * EAPOL-Start. In such a case, they may assume the network is - * using IEEE 802.1X and prompt user for a certificate while - * the correct (non-WPS) behavior would be to ask for the - * static WEP key. As a workaround, use Microsoft Provisioning - * IE to advertise that legacy 802.1X is not supported. - */ - const u8 ms_wps[7] = { - WLAN_EID_VENDOR_SPECIFIC, 5, - /* Microsoft Provisioning IE (00:50:f2:5) */ - 0x00, 0x50, 0xf2, 5, - 0x00 /* no legacy 802.1X or MS WPS */ - }; - wpa_printf(MSG_DEBUG, "WPS: Add Microsoft Provisioning IE " - "into Beacon/Probe Response frames"); - wpabuf_put_data(beacon, ms_wps, sizeof(ms_wps)); - wpabuf_put_data(probe, ms_wps, sizeof(ms_wps)); - } - - ret = wps_cb_set_ie(reg, beacon, probe); - wpabuf_free(beacon); - wpabuf_free(probe); - - return ret; -} - - -static int wps_get_dev_password(struct wps_data *wps) -{ - const u8 *pin; - size_t pin_len = 0; - - os_free(wps->dev_password); - wps->dev_password = NULL; - - if (wps->pbc) { - wpa_printf(MSG_DEBUG, "WPS: Use default PIN for PBC"); - pin = (const u8 *) "00000000"; - pin_len = 8; - } else { - pin = wps_registrar_get_pin(wps->wps->registrar, wps->uuid_e, - &pin_len); - } - if (pin == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Device Password available for " - "the Enrollee"); - wps_cb_pin_needed(wps->wps->registrar, wps->uuid_e, - &wps->peer_dev); - return -1; - } - - wps->dev_password = os_malloc(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; -} - - -static int wps_build_uuid_r(struct wps_data *wps, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * UUID-R"); - wpabuf_put_be16(msg, ATTR_UUID_R); - wpabuf_put_be16(msg, WPS_UUID_LEN); - wpabuf_put_data(msg, wps->uuid_r, WPS_UUID_LEN); - return 0; -} - - -static int wps_build_r_hash(struct wps_data *wps, struct wpabuf *msg) -{ - u8 *hash; - const u8 *addr[4]; - size_t len[4]; - - if (os_get_random(wps->snonce, 2 * WPS_SECRET_NONCE_LEN) < 0) - return -1; - wpa_hexdump(MSG_DEBUG, "WPS: R-S1", wps->snonce, WPS_SECRET_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "WPS: R-S2", - wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN); - - if (wps->dh_pubkey_e == NULL || wps->dh_pubkey_r == NULL) { - wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for " - "R-Hash derivation"); - return -1; - } - - wpa_printf(MSG_DEBUG, "WPS: * R-Hash1"); - wpabuf_put_be16(msg, ATTR_R_HASH1); - wpabuf_put_be16(msg, SHA256_MAC_LEN); - hash = wpabuf_put(msg, SHA256_MAC_LEN); - /* R-Hash1 = HMAC_AuthKey(R-S1 || PSK1 || PK_E || PK_R) */ - addr[0] = wps->snonce; - len[0] = WPS_SECRET_NONCE_LEN; - addr[1] = wps->psk1; - len[1] = WPS_PSK_LEN; - addr[2] = wpabuf_head(wps->dh_pubkey_e); - len[2] = wpabuf_len(wps->dh_pubkey_e); - addr[3] = wpabuf_head(wps->dh_pubkey_r); - len[3] = wpabuf_len(wps->dh_pubkey_r); - hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); - wpa_hexdump(MSG_DEBUG, "WPS: R-Hash1", hash, SHA256_MAC_LEN); - - wpa_printf(MSG_DEBUG, "WPS: * R-Hash2"); - wpabuf_put_be16(msg, ATTR_R_HASH2); - wpabuf_put_be16(msg, SHA256_MAC_LEN); - hash = wpabuf_put(msg, SHA256_MAC_LEN); - /* R-Hash2 = HMAC_AuthKey(R-S2 || PSK2 || PK_E || PK_R) */ - addr[0] = wps->snonce + WPS_SECRET_NONCE_LEN; - addr[1] = wps->psk2; - hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); - wpa_hexdump(MSG_DEBUG, "WPS: R-Hash2", hash, SHA256_MAC_LEN); - - return 0; -} - - -static int wps_build_r_snonce1(struct wps_data *wps, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * R-SNonce1"); - wpabuf_put_be16(msg, ATTR_R_SNONCE1); - wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); - wpabuf_put_data(msg, wps->snonce, WPS_SECRET_NONCE_LEN); - return 0; -} - - -static int wps_build_r_snonce2(struct wps_data *wps, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * R-SNonce2"); - wpabuf_put_be16(msg, ATTR_R_SNONCE2); - wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); - wpabuf_put_data(msg, wps->snonce + WPS_SECRET_NONCE_LEN, - WPS_SECRET_NONCE_LEN); - return 0; -} - - -static int wps_build_cred_network_idx(struct wpabuf *msg, - struct wps_credential *cred) -{ - wpa_printf(MSG_DEBUG, "WPS: * Network Index"); - wpabuf_put_be16(msg, ATTR_NETWORK_INDEX); - wpabuf_put_be16(msg, 1); - wpabuf_put_u8(msg, 1); - return 0; -} - - -static int wps_build_cred_ssid(struct wpabuf *msg, - struct wps_credential *cred) -{ - wpa_printf(MSG_DEBUG, "WPS: * SSID"); - wpabuf_put_be16(msg, ATTR_SSID); - wpabuf_put_be16(msg, cred->ssid_len); - wpabuf_put_data(msg, cred->ssid, cred->ssid_len); - return 0; -} - - -static int wps_build_cred_auth_type(struct wpabuf *msg, - struct wps_credential *cred) -{ - wpa_printf(MSG_DEBUG, "WPS: * Authentication Type (0x%x)", - cred->auth_type); - wpabuf_put_be16(msg, ATTR_AUTH_TYPE); - wpabuf_put_be16(msg, 2); - wpabuf_put_be16(msg, cred->auth_type); - return 0; -} - - -static int wps_build_cred_encr_type(struct wpabuf *msg, - struct wps_credential *cred) -{ - wpa_printf(MSG_DEBUG, "WPS: * Encryption Type (0x%x)", - cred->encr_type); - wpabuf_put_be16(msg, ATTR_ENCR_TYPE); - wpabuf_put_be16(msg, 2); - wpabuf_put_be16(msg, cred->encr_type); - return 0; -} - - -static int wps_build_cred_network_key(struct wpabuf *msg, - struct wps_credential *cred) -{ - wpa_printf(MSG_DEBUG, "WPS: * Network Key"); - wpabuf_put_be16(msg, ATTR_NETWORK_KEY); - wpabuf_put_be16(msg, cred->key_len); - wpabuf_put_data(msg, cred->key, cred->key_len); - return 0; -} - - -static int wps_build_cred_mac_addr(struct wpabuf *msg, - struct wps_credential *cred) -{ - wpa_printf(MSG_DEBUG, "WPS: * MAC Address (" MACSTR ")", - MAC2STR(cred->mac_addr)); - wpabuf_put_be16(msg, ATTR_MAC_ADDR); - wpabuf_put_be16(msg, ETH_ALEN); - wpabuf_put_data(msg, cred->mac_addr, ETH_ALEN); - return 0; -} - - -static int wps_build_credential(struct wpabuf *msg, - struct wps_credential *cred) -{ - if (wps_build_cred_network_idx(msg, cred) || - wps_build_cred_ssid(msg, cred) || - wps_build_cred_auth_type(msg, cred) || - wps_build_cred_encr_type(msg, cred) || - wps_build_cred_network_key(msg, cred) || - wps_build_cred_mac_addr(msg, cred)) - return -1; - return 0; -} - - -static int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) -{ - struct wpabuf *cred; - - if (wps->wps->registrar->skip_cred_build) - goto skip_cred_build; - - wpa_printf(MSG_DEBUG, "WPS: * Credential"); - os_memset(&wps->cred, 0, sizeof(wps->cred)); - - os_memcpy(wps->cred.ssid, wps->wps->ssid, wps->wps->ssid_len); - wps->cred.ssid_len = wps->wps->ssid_len; - - /* Select the best authentication and encryption type */ - if (wps->auth_type & WPS_AUTH_WPA2PSK) - wps->auth_type = WPS_AUTH_WPA2PSK; - else if (wps->auth_type & WPS_AUTH_WPAPSK) - wps->auth_type = WPS_AUTH_WPAPSK; - else if (wps->auth_type & WPS_AUTH_OPEN) - wps->auth_type = WPS_AUTH_OPEN; - else if (wps->auth_type & WPS_AUTH_SHARED) - wps->auth_type = WPS_AUTH_SHARED; - else { - wpa_printf(MSG_DEBUG, "WPS: Unsupported auth_type 0x%x", - wps->auth_type); - return -1; - } - wps->cred.auth_type = wps->auth_type; - - if (wps->auth_type == WPS_AUTH_WPA2PSK || - wps->auth_type == WPS_AUTH_WPAPSK) { - if (wps->encr_type & WPS_ENCR_AES) - wps->encr_type = WPS_ENCR_AES; - else if (wps->encr_type & WPS_ENCR_TKIP) - wps->encr_type = WPS_ENCR_TKIP; - else { - wpa_printf(MSG_DEBUG, "WPS: No suitable encryption " - "type for WPA/WPA2"); - return -1; - } - } else { - if (wps->encr_type & WPS_ENCR_WEP) - wps->encr_type = WPS_ENCR_WEP; - else if (wps->encr_type & WPS_ENCR_NONE) - wps->encr_type = WPS_ENCR_NONE; - else { - wpa_printf(MSG_DEBUG, "WPS: No suitable encryption " - "type for non-WPA/WPA2 mode"); - return -1; - } - } - wps->cred.encr_type = wps->encr_type; - /* - * 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 (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->wps->ap && - !wps->wps->registrar->disable_auto_conf) { - u8 r[16]; - /* Generate a random passphrase */ - if (os_get_random(r, sizeof(r)) < 0) - return -1; - os_free(wps->new_psk); - wps->new_psk = base64_encode(r, sizeof(r), &wps->new_psk_len); - if (wps->new_psk == NULL) - return -1; - wps->new_psk_len--; /* remove newline */ - while (wps->new_psk_len && - wps->new_psk[wps->new_psk_len - 1] == '=') - wps->new_psk_len--; - wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Generated passphrase", - wps->new_psk, wps->new_psk_len); - os_memcpy(wps->cred.key, wps->new_psk, wps->new_psk_len); - wps->cred.key_len = wps->new_psk_len; - } else if (wps->wps->network_key) { - os_memcpy(wps->cred.key, wps->wps->network_key, - wps->wps->network_key_len); - wps->cred.key_len = wps->wps->network_key_len; - } else if (wps->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) { - char hex[65]; - /* Generate a random per-device PSK */ - os_free(wps->new_psk); - wps->new_psk_len = 32; - wps->new_psk = os_malloc(wps->new_psk_len); - if (wps->new_psk == NULL) - return -1; - if (os_get_random(wps->new_psk, wps->new_psk_len) < 0) { - os_free(wps->new_psk); - wps->new_psk = NULL; - return -1; - } - wpa_hexdump_key(MSG_DEBUG, "WPS: Generated per-device PSK", - wps->new_psk, wps->new_psk_len); - wpa_snprintf_hex(hex, sizeof(hex), wps->new_psk, - wps->new_psk_len); - os_memcpy(wps->cred.key, hex, wps->new_psk_len * 2); - wps->cred.key_len = wps->new_psk_len * 2; - } - - cred = wpabuf_alloc(200); - if (cred == NULL) - return -1; - - if (wps_build_credential(cred, &wps->cred)) { - wpabuf_free(cred); - return -1; - } - - wpabuf_put_be16(msg, ATTR_CRED); - wpabuf_put_be16(msg, wpabuf_len(cred)); - wpabuf_put_buf(msg, cred); - wpabuf_free(cred); - -skip_cred_build: - if (wps->wps->registrar->extra_cred) { - wpa_printf(MSG_DEBUG, "WPS: * Credential (pre-configured)"); - wpabuf_put_buf(msg, wps->wps->registrar->extra_cred); - } - - return 0; -} - - -static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS: * AP Settings"); - - if (wps_build_credential(msg, &wps->cred)) - return -1; - - return 0; -} - - -static struct wpabuf * wps_build_m2(struct wps_data *wps) -{ - struct wpabuf *msg; - - if (os_get_random(wps->nonce_r, WPS_NONCE_LEN) < 0) - return NULL; - wpa_hexdump(MSG_DEBUG, "WPS: Registrar Nonce", - wps->nonce_r, WPS_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "WPS: UUID-R", wps->uuid_r, WPS_UUID_LEN); - - wpa_printf(MSG_DEBUG, "WPS: Building Message M2"); - msg = wpabuf_alloc(1000); - if (msg == NULL) - return NULL; - - if (wps_build_version(msg) || - wps_build_msg_type(msg, WPS_M2) || - wps_build_enrollee_nonce(wps, msg) || - wps_build_registrar_nonce(wps, msg) || - wps_build_uuid_r(wps, msg) || - wps_build_public_key(wps, msg) || - wps_derive_keys(wps) || - wps_build_auth_type_flags(wps, msg) || - wps_build_encr_type_flags(wps, msg) || - wps_build_conn_type_flags(wps, msg) || - wps_build_config_methods_r(wps->wps->registrar, msg) || - wps_build_device_attrs(&wps->wps->dev, msg) || - wps_build_rf_bands(&wps->wps->dev, msg) || - wps_build_assoc_state(wps, msg) || - 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_authenticator(wps, msg)) { - wpabuf_free(msg); - return NULL; - } - - wps->state = RECV_M3; - return msg; -} - - -static struct wpabuf * wps_build_m2d(struct wps_data *wps) -{ - struct wpabuf *msg; - u16 err = wps->config_error; - - wpa_printf(MSG_DEBUG, "WPS: Building Message M2D"); - msg = wpabuf_alloc(1000); - if (msg == NULL) - return NULL; - - if (wps->wps->ap && wps->wps->ap_setup_locked && - err == WPS_CFG_NO_ERROR) - err = WPS_CFG_SETUP_LOCKED; - - if (wps_build_version(msg) || - wps_build_msg_type(msg, WPS_M2D) || - wps_build_enrollee_nonce(wps, msg) || - wps_build_registrar_nonce(wps, msg) || - wps_build_uuid_r(wps, msg) || - wps_build_auth_type_flags(wps, msg) || - wps_build_encr_type_flags(wps, msg) || - wps_build_conn_type_flags(wps, msg) || - wps_build_config_methods_r(wps->wps->registrar, msg) || - wps_build_device_attrs(&wps->wps->dev, msg) || - wps_build_rf_bands(&wps->wps->dev, msg) || - wps_build_assoc_state(wps, msg) || - wps_build_config_error(msg, err) || - wps_build_os_version(&wps->wps->dev, msg)) { - wpabuf_free(msg); - return NULL; - } - - wps->state = RECV_M2D_ACK; - return msg; -} - - -static struct wpabuf * wps_build_m4(struct wps_data *wps) -{ - struct wpabuf *msg, *plain; - - wpa_printf(MSG_DEBUG, "WPS: Building Message M4"); - - wps_derive_psk(wps, wps->dev_password, wps->dev_password_len); - - plain = wpabuf_alloc(200); - if (plain == NULL) - return NULL; - - msg = wpabuf_alloc(1000); - if (msg == NULL) { - wpabuf_free(plain); - return NULL; - } - - if (wps_build_version(msg) || - wps_build_msg_type(msg, WPS_M4) || - wps_build_enrollee_nonce(wps, msg) || - wps_build_r_hash(wps, msg) || - wps_build_r_snonce1(wps, plain) || - wps_build_key_wrap_auth(wps, plain) || - wps_build_encr_settings(wps, msg, plain) || - wps_build_authenticator(wps, msg)) { - wpabuf_free(plain); - wpabuf_free(msg); - return NULL; - } - wpabuf_free(plain); - - wps->state = RECV_M5; - return msg; -} - - -static struct wpabuf * wps_build_m6(struct wps_data *wps) -{ - struct wpabuf *msg, *plain; - - wpa_printf(MSG_DEBUG, "WPS: Building Message M6"); - - plain = wpabuf_alloc(200); - if (plain == NULL) - return NULL; - - msg = wpabuf_alloc(1000); - if (msg == NULL) { - wpabuf_free(plain); - return NULL; - } - - if (wps_build_version(msg) || - wps_build_msg_type(msg, WPS_M6) || - wps_build_enrollee_nonce(wps, msg) || - wps_build_r_snonce2(wps, plain) || - wps_build_key_wrap_auth(wps, plain) || - wps_build_encr_settings(wps, msg, plain) || - wps_build_authenticator(wps, msg)) { - wpabuf_free(plain); - wpabuf_free(msg); - return NULL; - } - wpabuf_free(plain); - - wps->wps_pin_revealed = 1; - wps->state = RECV_M7; - return msg; -} - - -static struct wpabuf * wps_build_m8(struct wps_data *wps) -{ - struct wpabuf *msg, *plain; - - wpa_printf(MSG_DEBUG, "WPS: Building Message M8"); - - plain = wpabuf_alloc(500); - if (plain == NULL) - return NULL; - - msg = wpabuf_alloc(1000); - if (msg == NULL) { - wpabuf_free(plain); - return NULL; - } - - if (wps_build_version(msg) || - wps_build_msg_type(msg, WPS_M8) || - wps_build_enrollee_nonce(wps, msg) || - (wps->wps->ap && wps_build_cred(wps, plain)) || - (!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_authenticator(wps, msg)) { - wpabuf_free(plain); - wpabuf_free(msg); - return NULL; - } - wpabuf_free(plain); - - wps->state = RECV_DONE; - return msg; -} - - -static struct wpabuf * wps_build_wsc_ack(struct wps_data *wps) -{ - struct wpabuf *msg; - - wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK"); - - msg = wpabuf_alloc(1000); - if (msg == NULL) - return NULL; - - if (wps_build_version(msg) || - wps_build_msg_type(msg, WPS_WSC_ACK) || - wps_build_enrollee_nonce(wps, msg) || - wps_build_registrar_nonce(wps, msg)) { - wpabuf_free(msg); - return NULL; - } - - return msg; -} - - -static struct wpabuf * wps_build_wsc_nack(struct wps_data *wps) -{ - struct wpabuf *msg; - - wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK"); - - msg = wpabuf_alloc(1000); - if (msg == NULL) - return NULL; - - if (wps_build_version(msg) || - wps_build_msg_type(msg, WPS_WSC_NACK) || - wps_build_enrollee_nonce(wps, msg) || - wps_build_registrar_nonce(wps, msg) || - wps_build_config_error(msg, wps->config_error)) { - wpabuf_free(msg); - return NULL; - } - - return msg; -} - - -struct wpabuf * wps_registrar_get_msg(struct wps_data *wps, - enum wsc_op_code *op_code) -{ - struct wpabuf *msg; - -#ifdef CONFIG_WPS_UPNP - if (wps->wps->wps_upnp) { - struct upnp_pending_message *p, *prev = NULL; - if (wps->ext_reg > 1) - wps_registrar_free_pending_m2(wps->wps); - p = wps->wps->upnp_msgs; - /* TODO: check pending message MAC address */ - while (p && p->next) { - prev = p; - p = p->next; - } - if (p) { - wpa_printf(MSG_DEBUG, "WPS: Use pending message from " - "UPnP"); - if (prev) - prev->next = NULL; - else - wps->wps->upnp_msgs = NULL; - msg = p->msg; - switch (p->type) { - case WPS_WSC_ACK: - *op_code = WSC_ACK; - break; - case WPS_WSC_NACK: - *op_code = WSC_NACK; - break; - default: - *op_code = WSC_MSG; - break; - } - os_free(p); - if (wps->ext_reg == 0) - wps->ext_reg = 1; - return msg; - } - } - if (wps->ext_reg) { - wpa_printf(MSG_DEBUG, "WPS: Using external Registrar, but no " - "pending message available"); - return NULL; - } -#endif /* CONFIG_WPS_UPNP */ - - switch (wps->state) { - case SEND_M2: - if (wps_get_dev_password(wps) < 0) - msg = wps_build_m2d(wps); - else - msg = wps_build_m2(wps); - *op_code = WSC_MSG; - break; - case SEND_M2D: - msg = wps_build_m2d(wps); - *op_code = WSC_MSG; - break; - case SEND_M4: - msg = wps_build_m4(wps); - *op_code = WSC_MSG; - break; - case SEND_M6: - msg = wps_build_m6(wps); - *op_code = WSC_MSG; - break; - case SEND_M8: - msg = wps_build_m8(wps); - *op_code = WSC_MSG; - break; - case RECV_DONE: - msg = wps_build_wsc_ack(wps); - *op_code = WSC_ACK; - break; - case SEND_WSC_NACK: - msg = wps_build_wsc_nack(wps); - *op_code = WSC_NACK; - break; - default: - wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building " - "a message", wps->state); - msg = NULL; - break; - } - - if (*op_code == WSC_MSG && msg) { - /* Save a copy of the last message for Authenticator derivation - */ - wpabuf_free(wps->last_msg); - wps->last_msg = wpabuf_dup(msg); - } - - return msg; -} - - -static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce) -{ - if (e_nonce == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received"); - return -1; - } - - os_memcpy(wps->nonce_e, e_nonce, WPS_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Nonce", - wps->nonce_e, WPS_NONCE_LEN); - - return 0; -} - - -static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce) -{ - if (r_nonce == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received"); - return -1; - } - - if (os_memcmp(wps->nonce_r, r_nonce, WPS_NONCE_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce received"); - return -1; - } - - return 0; -} - - -static int wps_process_uuid_e(struct wps_data *wps, const u8 *uuid_e) -{ - if (uuid_e == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No UUID-E received"); - return -1; - } - - os_memcpy(wps->uuid_e, uuid_e, WPS_UUID_LEN); - wpa_hexdump(MSG_DEBUG, "WPS: UUID-E", wps->uuid_e, WPS_UUID_LEN); - - return 0; -} - - -static int wps_process_dev_password_id(struct wps_data *wps, const u8 *pw_id) -{ - if (pw_id == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Device Password ID received"); - return -1; - } - - wps->dev_pw_id = WPA_GET_BE16(pw_id); - wpa_printf(MSG_DEBUG, "WPS: Device Password ID %d", wps->dev_pw_id); - - return 0; -} - - -static int wps_process_e_hash1(struct wps_data *wps, const u8 *e_hash1) -{ - if (e_hash1 == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No E-Hash1 received"); - return -1; - } - - os_memcpy(wps->peer_hash1, e_hash1, WPS_HASH_LEN); - wpa_hexdump(MSG_DEBUG, "WPS: E-Hash1", wps->peer_hash1, WPS_HASH_LEN); - - return 0; -} - - -static int wps_process_e_hash2(struct wps_data *wps, const u8 *e_hash2) -{ - if (e_hash2 == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No E-Hash2 received"); - return -1; - } - - os_memcpy(wps->peer_hash2, e_hash2, WPS_HASH_LEN); - wpa_hexdump(MSG_DEBUG, "WPS: E-Hash2", wps->peer_hash2, WPS_HASH_LEN); - - return 0; -} - - -static int wps_process_e_snonce1(struct wps_data *wps, const u8 *e_snonce1) -{ - u8 hash[SHA256_MAC_LEN]; - const u8 *addr[4]; - size_t len[4]; - - if (e_snonce1 == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No E-SNonce1 received"); - return -1; - } - - wpa_hexdump_key(MSG_DEBUG, "WPS: E-SNonce1", e_snonce1, - WPS_SECRET_NONCE_LEN); - - /* E-Hash1 = HMAC_AuthKey(E-S1 || PSK1 || PK_E || PK_R) */ - addr[0] = e_snonce1; - len[0] = WPS_SECRET_NONCE_LEN; - addr[1] = wps->psk1; - len[1] = WPS_PSK_LEN; - addr[2] = wpabuf_head(wps->dh_pubkey_e); - len[2] = wpabuf_len(wps->dh_pubkey_e); - addr[3] = wpabuf_head(wps->dh_pubkey_r); - len[3] = wpabuf_len(wps->dh_pubkey_r); - hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); - - if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: E-Hash1 derived from E-S1 does " - "not match with the pre-committed value"); - wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; - wps_pwd_auth_fail_event(wps->wps, 0, 1); - return -1; - } - - wpa_printf(MSG_DEBUG, "WPS: Enrollee proved knowledge of the first " - "half of the device password"); - - return 0; -} - - -static int wps_process_e_snonce2(struct wps_data *wps, const u8 *e_snonce2) -{ - u8 hash[SHA256_MAC_LEN]; - const u8 *addr[4]; - size_t len[4]; - - if (e_snonce2 == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No E-SNonce2 received"); - return -1; - } - - wpa_hexdump_key(MSG_DEBUG, "WPS: E-SNonce2", e_snonce2, - WPS_SECRET_NONCE_LEN); - - /* E-Hash2 = HMAC_AuthKey(E-S2 || PSK2 || PK_E || PK_R) */ - addr[0] = e_snonce2; - len[0] = WPS_SECRET_NONCE_LEN; - addr[1] = wps->psk2; - len[1] = WPS_PSK_LEN; - addr[2] = wpabuf_head(wps->dh_pubkey_e); - len[2] = wpabuf_len(wps->dh_pubkey_e); - addr[3] = wpabuf_head(wps->dh_pubkey_r); - len[3] = wpabuf_len(wps->dh_pubkey_r); - hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); - - if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: E-Hash2 derived from E-S2 does " - "not match with the pre-committed value"); - wps_registrar_invalidate_pin(wps->wps->registrar, wps->uuid_e); - wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; - wps_pwd_auth_fail_event(wps->wps, 0, 2); - return -1; - } - - wpa_printf(MSG_DEBUG, "WPS: Enrollee proved knowledge of the second " - "half of the device password"); - wps->wps_pin_revealed = 0; - wps_registrar_unlock_pin(wps->wps->registrar, wps->uuid_e); - - return 0; -} - - -static int wps_process_mac_addr(struct wps_data *wps, const u8 *mac_addr) -{ - if (mac_addr == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No MAC Address received"); - return -1; - } - - wpa_printf(MSG_DEBUG, "WPS: Enrollee MAC Address " MACSTR, - MAC2STR(mac_addr)); - os_memcpy(wps->mac_addr_e, mac_addr, ETH_ALEN); - os_memcpy(wps->peer_dev.mac_addr, mac_addr, ETH_ALEN); - - return 0; -} - - -static int wps_process_pubkey(struct wps_data *wps, const u8 *pk, - size_t pk_len) -{ - if (pk == NULL || pk_len == 0) { - wpa_printf(MSG_DEBUG, "WPS: No Public Key received"); - return -1; - } - - wpabuf_free(wps->dh_pubkey_e); - wps->dh_pubkey_e = wpabuf_alloc_copy(pk, pk_len); - if (wps->dh_pubkey_e == NULL) - return -1; - - return 0; -} - - -static int wps_process_auth_type_flags(struct wps_data *wps, const u8 *auth) -{ - u16 auth_types; - - if (auth == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Authentication Type flags " - "received"); - return -1; - } - - auth_types = WPA_GET_BE16(auth); - - wpa_printf(MSG_DEBUG, "WPS: Enrollee Authentication Type flags 0x%x", - auth_types); - wps->auth_type = wps->wps->auth_types & auth_types; - if (wps->auth_type == 0) { - wpa_printf(MSG_DEBUG, "WPS: No match in supported " - "authentication types (own 0x%x Enrollee 0x%x)", - wps->wps->auth_types, auth_types); -#ifdef WPS_WORKAROUNDS - /* - * Some deployed implementations seem to advertise incorrect - * information in this attribute. For example, Linksys WRT350N - * seems to have a byteorder bug that breaks this negotiation. - * In order to interoperate with existing implementations, - * assume that the Enrollee supports everything we do. - */ - wpa_printf(MSG_DEBUG, "WPS: Workaround - assume Enrollee " - "does not advertise supported authentication types " - "correctly"); - wps->auth_type = wps->wps->auth_types; -#else /* WPS_WORKAROUNDS */ - return -1; -#endif /* WPS_WORKAROUNDS */ - } - - return 0; -} - - -static int wps_process_encr_type_flags(struct wps_data *wps, const u8 *encr) -{ - u16 encr_types; - - if (encr == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Encryption Type flags " - "received"); - return -1; - } - - encr_types = WPA_GET_BE16(encr); - - wpa_printf(MSG_DEBUG, "WPS: Enrollee Encryption Type flags 0x%x", - encr_types); - wps->encr_type = wps->wps->encr_types & encr_types; - if (wps->encr_type == 0) { - wpa_printf(MSG_DEBUG, "WPS: No match in supported " - "encryption types (own 0x%x Enrollee 0x%x)", - wps->wps->encr_types, encr_types); -#ifdef WPS_WORKAROUNDS - /* - * Some deployed implementations seem to advertise incorrect - * information in this attribute. For example, Linksys WRT350N - * seems to have a byteorder bug that breaks this negotiation. - * In order to interoperate with existing implementations, - * assume that the Enrollee supports everything we do. - */ - wpa_printf(MSG_DEBUG, "WPS: Workaround - assume Enrollee " - "does not advertise supported encryption types " - "correctly"); - wps->encr_type = wps->wps->encr_types; -#else /* WPS_WORKAROUNDS */ - return -1; -#endif /* WPS_WORKAROUNDS */ - } - - return 0; -} - - -static int wps_process_conn_type_flags(struct wps_data *wps, const u8 *conn) -{ - if (conn == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Connection Type flags " - "received"); - return -1; - } - - wpa_printf(MSG_DEBUG, "WPS: Enrollee Connection Type flags 0x%x", - *conn); - - return 0; -} - - -static int wps_process_config_methods(struct wps_data *wps, const u8 *methods) -{ - u16 m; - - if (methods == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Config Methods received"); - return -1; - } - - m = WPA_GET_BE16(methods); - - wpa_printf(MSG_DEBUG, "WPS: Enrollee Config Methods 0x%x", m); - - return 0; -} - - -static int wps_process_wps_state(struct wps_data *wps, const u8 *state) -{ - if (state == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Wi-Fi Protected Setup State " - "received"); - return -1; - } - - wpa_printf(MSG_DEBUG, "WPS: Enrollee Wi-Fi Protected Setup State %d", - *state); - - return 0; -} - - -static int wps_process_assoc_state(struct wps_data *wps, const u8 *assoc) -{ - u16 a; - - if (assoc == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Association State received"); - return -1; - } - - a = WPA_GET_BE16(assoc); - wpa_printf(MSG_DEBUG, "WPS: Enrollee Association State %d", a); - - return 0; -} - - -static int wps_process_config_error(struct wps_data *wps, const u8 *err) -{ - u16 e; - - if (err == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Configuration Error received"); - return -1; - } - - e = WPA_GET_BE16(err); - wpa_printf(MSG_DEBUG, "WPS: Enrollee Configuration Error %d", e); - - return 0; -} - - -static enum wps_process_res wps_process_m1(struct wps_data *wps, - struct wps_parse_attr *attr) -{ - wpa_printf(MSG_DEBUG, "WPS: Received M1"); - - if (wps->state != RECV_M1) { - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " - "receiving M1", wps->state); - return WPS_FAILURE; - } - - if (wps_process_uuid_e(wps, attr->uuid_e) || - wps_process_mac_addr(wps, attr->mac_addr) || - wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || - wps_process_pubkey(wps, attr->public_key, attr->public_key_len) || - wps_process_auth_type_flags(wps, attr->auth_type_flags) || - wps_process_encr_type_flags(wps, attr->encr_type_flags) || - wps_process_conn_type_flags(wps, attr->conn_type_flags) || - wps_process_config_methods(wps, attr->config_methods) || - wps_process_wps_state(wps, attr->wps_state) || - wps_process_device_attrs(&wps->peer_dev, attr) || - wps_process_rf_bands(&wps->peer_dev, attr->rf_bands) || - wps_process_assoc_state(wps, attr->assoc_state) || - wps_process_dev_password_id(wps, attr->dev_password_id) || - wps_process_config_error(wps, attr->config_error) || - wps_process_os_version(&wps->peer_dev, attr->os_version)) - return WPS_FAILURE; - - if (wps->dev_pw_id != DEV_PW_DEFAULT && - wps->dev_pw_id != DEV_PW_USER_SPECIFIED && - wps->dev_pw_id != DEV_PW_MACHINE_SPECIFIED && - wps->dev_pw_id != DEV_PW_REGISTRAR_SPECIFIED && - (wps->dev_pw_id != DEV_PW_PUSHBUTTON || - !wps->wps->registrar->pbc)) { - wpa_printf(MSG_DEBUG, "WPS: Unsupported Device Password ID %d", - wps->dev_pw_id); - wps->state = SEND_M2D; - return WPS_CONTINUE; - } - - if (wps->dev_pw_id == DEV_PW_PUSHBUTTON) { - if (wps->wps->registrar->force_pbc_overlap || - wps_registrar_pbc_overlap(wps->wps->registrar, - wps->mac_addr_e, wps->uuid_e)) { - wpa_printf(MSG_DEBUG, "WPS: PBC overlap - deny PBC " - "negotiation"); - wps->state = SEND_M2D; - wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; - wps_pbc_overlap_event(wps->wps); - wps->wps->registrar->force_pbc_overlap = 1; - return WPS_CONTINUE; - } - wps_registrar_add_pbc_session(wps->wps->registrar, - wps->mac_addr_e, wps->uuid_e); - wps->pbc = 1; - } - - wps->state = SEND_M2; - return WPS_CONTINUE; -} - - -static enum wps_process_res wps_process_m3(struct wps_data *wps, - const struct wpabuf *msg, - struct wps_parse_attr *attr) -{ - wpa_printf(MSG_DEBUG, "WPS: Received M3"); - - if (wps->state != RECV_M3) { - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " - "receiving M3", wps->state); - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - if (wps->pbc && wps->wps->registrar->force_pbc_overlap) { - wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC " - "session overlap"); - wps->state = SEND_WSC_NACK; - wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; - return WPS_CONTINUE; - } - - if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || - wps_process_authenticator(wps, attr->authenticator, msg) || - wps_process_e_hash1(wps, attr->e_hash1) || - wps_process_e_hash2(wps, attr->e_hash2)) { - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - wps->state = SEND_M4; - return WPS_CONTINUE; -} - - -static enum wps_process_res wps_process_m5(struct wps_data *wps, - const struct wpabuf *msg, - struct wps_parse_attr *attr) -{ - struct wpabuf *decrypted; - struct wps_parse_attr eattr; - - wpa_printf(MSG_DEBUG, "WPS: Received M5"); - - if (wps->state != RECV_M5) { - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " - "receiving M5", wps->state); - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - if (wps->pbc && wps->wps->registrar->force_pbc_overlap) { - wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC " - "session overlap"); - wps->state = SEND_WSC_NACK; - wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; - return WPS_CONTINUE; - } - - if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || - wps_process_authenticator(wps, attr->authenticator, msg)) { - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, - attr->encr_settings_len); - if (decrypted == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " - "Settings attribute"); - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " - "attribute"); - if (wps_parse_msg(decrypted, &eattr) < 0 || - wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || - wps_process_e_snonce1(wps, eattr.e_snonce1)) { - wpabuf_free(decrypted); - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - wpabuf_free(decrypted); - - wps->state = SEND_M6; - return WPS_CONTINUE; -} - - -static void wps_sta_cred_cb(struct wps_data *wps) -{ - /* - * Update credential to only include a single authentication and - * encryption type in case the AP configuration includes more than one - * option. - */ - if (wps->cred.auth_type & WPS_AUTH_WPA2PSK) - wps->cred.auth_type = WPS_AUTH_WPA2PSK; - else if (wps->cred.auth_type & WPS_AUTH_WPAPSK) - wps->cred.auth_type = WPS_AUTH_WPAPSK; - if (wps->cred.encr_type & WPS_ENCR_AES) - wps->cred.encr_type = WPS_ENCR_AES; - else if (wps->cred.encr_type & WPS_ENCR_TKIP) - wps->cred.encr_type = WPS_ENCR_TKIP; - wpa_printf(MSG_DEBUG, "WPS: Update local configuration based on the " - "AP configuration"); - if (wps->wps->cred_cb) - wps->wps->cred_cb(wps->wps->cb_ctx, &wps->cred); -} - - -static int wps_process_ap_settings_r(struct wps_data *wps, - struct wps_parse_attr *attr) -{ - if (wps->wps->ap) - return 0; - - /* AP Settings Attributes in M7 when Enrollee is an AP */ - if (wps_process_ap_settings(attr, &wps->cred) < 0) - return -1; - - wpa_printf(MSG_INFO, "WPS: Received old AP configuration from AP"); - -#if 0 - /* - * TODO: Provide access to AP settings and allow changes before sending - * out M8. For now, just copy the settings unchanged into M8. - */ - - return 0; -#else - /* - * For now, use the AP PIN only to receive the current AP settings, - * not to reconfigure the AP. - */ - wps_sta_cred_cb(wps); - return 1; -#endif -} - - -static enum wps_process_res wps_process_m7(struct wps_data *wps, - const struct wpabuf *msg, - struct wps_parse_attr *attr) -{ - struct wpabuf *decrypted; - struct wps_parse_attr eattr; - - wpa_printf(MSG_DEBUG, "WPS: Received M7"); - - if (wps->state != RECV_M7) { - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " - "receiving M7", wps->state); - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - if (wps->pbc && wps->wps->registrar->force_pbc_overlap) { - wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC " - "session overlap"); - wps->state = SEND_WSC_NACK; - wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; - return WPS_CONTINUE; - } - - if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || - wps_process_authenticator(wps, attr->authenticator, msg)) { - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, - attr->encr_settings_len); - if (decrypted == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " - "Settings attribute"); - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " - "attribute"); - if (wps_parse_msg(decrypted, &eattr) < 0 || - wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || - wps_process_e_snonce2(wps, eattr.e_snonce2) || - wps_process_ap_settings_r(wps, &eattr)) { - wpabuf_free(decrypted); - wps->state = SEND_WSC_NACK; - return WPS_CONTINUE; - } - - wpabuf_free(decrypted); - - wps->state = SEND_M8; - return WPS_CONTINUE; -} - - -static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, - const struct wpabuf *msg) -{ - struct wps_parse_attr attr; - enum wps_process_res ret = WPS_CONTINUE; - - wpa_printf(MSG_DEBUG, "WPS: Received WSC_MSG"); - - if (wps_parse_msg(msg, &attr) < 0) - return WPS_FAILURE; - - if (!wps_version_supported(attr.version)) { - wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", - attr.version ? *attr.version : 0); - return WPS_FAILURE; - } - - if (attr.msg_type == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); - return WPS_FAILURE; - } - - if (*attr.msg_type != WPS_M1 && - (attr.registrar_nonce == NULL || - os_memcmp(wps->nonce_r, attr.registrar_nonce, - WPS_NONCE_LEN != 0))) { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); - return WPS_FAILURE; - } - - switch (*attr.msg_type) { - case WPS_M1: -#ifdef CONFIG_WPS_UPNP - if (wps->wps->wps_upnp && attr.mac_addr) { - /* Remove old pending messages when starting new run */ - wps_free_pending_msgs(wps->wps->upnp_msgs); - wps->wps->upnp_msgs = NULL; - - upnp_wps_device_send_wlan_event( - wps->wps->wps_upnp, attr.mac_addr, - UPNP_WPS_WLANEVENT_TYPE_EAP, msg); - } -#endif /* CONFIG_WPS_UPNP */ - ret = wps_process_m1(wps, &attr); - break; - case WPS_M3: - ret = wps_process_m3(wps, msg, &attr); - if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) - wps_fail_event(wps->wps, WPS_M3); - break; - case WPS_M5: - ret = wps_process_m5(wps, msg, &attr); - if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) - wps_fail_event(wps->wps, WPS_M5); - break; - case WPS_M7: - ret = wps_process_m7(wps, msg, &attr); - if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) - wps_fail_event(wps->wps, WPS_M7); - break; - default: - wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d", - *attr.msg_type); - return WPS_FAILURE; - } - - if (ret == WPS_CONTINUE) { - /* Save a copy of the last message for Authenticator derivation - */ - wpabuf_free(wps->last_msg); - wps->last_msg = wpabuf_dup(msg); - } - - return ret; -} - - -static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps, - const struct wpabuf *msg) -{ - struct wps_parse_attr attr; - - wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK"); - - if (wps_parse_msg(msg, &attr) < 0) - return WPS_FAILURE; - - if (!wps_version_supported(attr.version)) { - wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", - attr.version ? *attr.version : 0); - return WPS_FAILURE; - } - - if (attr.msg_type == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); - return WPS_FAILURE; - } - - if (*attr.msg_type != WPS_WSC_ACK) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", - *attr.msg_type); - return WPS_FAILURE; - } - -#ifdef CONFIG_WPS_UPNP - if (wps->wps->wps_upnp && wps->ext_reg && wps->state == RECV_M2D_ACK && - upnp_wps_subscribers(wps->wps->wps_upnp)) { - if (wps->wps->upnp_msgs) - return WPS_CONTINUE; - wpa_printf(MSG_DEBUG, "WPS: Wait for response from an " - "external Registrar"); - return WPS_PENDING; - } -#endif /* CONFIG_WPS_UPNP */ - - if (attr.registrar_nonce == NULL || - os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0)) - { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); - return WPS_FAILURE; - } - - if (attr.enrollee_nonce == NULL || - os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); - return WPS_FAILURE; - } - - if (wps->state == RECV_M2D_ACK) { -#ifdef CONFIG_WPS_UPNP - if (wps->wps->wps_upnp && - upnp_wps_subscribers(wps->wps->wps_upnp)) { - if (wps->wps->upnp_msgs) - return WPS_CONTINUE; - if (wps->ext_reg == 0) - wps->ext_reg = 1; - wpa_printf(MSG_DEBUG, "WPS: Wait for response from an " - "external Registrar"); - return WPS_PENDING; - } -#endif /* CONFIG_WPS_UPNP */ - - wpa_printf(MSG_DEBUG, "WPS: No more registrars available - " - "terminate negotiation"); - } - - return WPS_FAILURE; -} - - -static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps, - const struct wpabuf *msg) -{ - struct wps_parse_attr attr; - int old_state; - - wpa_printf(MSG_DEBUG, "WPS: Received WSC_NACK"); - - old_state = wps->state; - wps->state = SEND_WSC_NACK; - - if (wps_parse_msg(msg, &attr) < 0) - return WPS_FAILURE; - - if (!wps_version_supported(attr.version)) { - wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", - attr.version ? *attr.version : 0); - return WPS_FAILURE; - } - - if (attr.msg_type == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); - return WPS_FAILURE; - } - - if (*attr.msg_type != WPS_WSC_NACK) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", - *attr.msg_type); - return WPS_FAILURE; - } - -#ifdef CONFIG_WPS_UPNP - if (wps->wps->wps_upnp && wps->ext_reg) { - wpa_printf(MSG_DEBUG, "WPS: Negotiation using external " - "Registrar terminated by the Enrollee"); - return WPS_FAILURE; - } -#endif /* CONFIG_WPS_UPNP */ - - if (attr.registrar_nonce == NULL || - os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0)) - { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); - return WPS_FAILURE; - } - - if (attr.enrollee_nonce == NULL || - os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); - return WPS_FAILURE; - } - - if (attr.config_error == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Configuration Error attribute " - "in WSC_NACK"); - return WPS_FAILURE; - } - - wpa_printf(MSG_DEBUG, "WPS: Enrollee terminated negotiation with " - "Configuration Error %d", WPA_GET_BE16(attr.config_error)); - - switch (old_state) { - case RECV_M3: - wps_fail_event(wps->wps, WPS_M2); - break; - case RECV_M5: - wps_fail_event(wps->wps, WPS_M4); - break; - case RECV_M7: - wps_fail_event(wps->wps, WPS_M6); - break; - case RECV_DONE: - wps_fail_event(wps->wps, WPS_M8); - break; - default: - break; - } - - return WPS_FAILURE; -} - - -static enum wps_process_res wps_process_wsc_done(struct wps_data *wps, - const struct wpabuf *msg) -{ - struct wps_parse_attr attr; - - wpa_printf(MSG_DEBUG, "WPS: Received WSC_Done"); - - if (wps->state != RECV_DONE && - (!wps->wps->wps_upnp || !wps->ext_reg)) { - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " - "receiving WSC_Done", wps->state); - return WPS_FAILURE; - } - - if (wps_parse_msg(msg, &attr) < 0) - return WPS_FAILURE; - - if (!wps_version_supported(attr.version)) { - wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", - attr.version ? *attr.version : 0); - return WPS_FAILURE; - } - - if (attr.msg_type == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); - return WPS_FAILURE; - } - - if (*attr.msg_type != WPS_WSC_DONE) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", - *attr.msg_type); - return WPS_FAILURE; - } - -#ifdef CONFIG_WPS_UPNP - if (wps->wps->wps_upnp && wps->ext_reg) { - wpa_printf(MSG_DEBUG, "WPS: Negotiation using external " - "Registrar completed successfully"); - return WPS_DONE; - } -#endif /* CONFIG_WPS_UPNP */ - - if (attr.registrar_nonce == NULL || - os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0)) - { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); - return WPS_FAILURE; - } - - if (attr.enrollee_nonce == NULL || - os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); - return WPS_FAILURE; - } - - wpa_printf(MSG_DEBUG, "WPS: Negotiation completed successfully"); - - if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->new_psk && - wps->wps->ap && !wps->wps->registrar->disable_auto_conf) { - struct wps_credential cred; - - wpa_printf(MSG_DEBUG, "WPS: Moving to Configured state based " - "on first Enrollee connection"); - - os_memset(&cred, 0, sizeof(cred)); - os_memcpy(cred.ssid, wps->wps->ssid, wps->wps->ssid_len); - cred.ssid_len = wps->wps->ssid_len; - cred.auth_type = WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK; - cred.encr_type = WPS_ENCR_TKIP | WPS_ENCR_AES; - os_memcpy(cred.key, wps->new_psk, wps->new_psk_len); - cred.key_len = wps->new_psk_len; - - wps->wps->wps_state = WPS_STATE_CONFIGURED; - wpa_hexdump_ascii_key(MSG_DEBUG, - "WPS: Generated random passphrase", - wps->new_psk, wps->new_psk_len); - if (wps->wps->cred_cb) - wps->wps->cred_cb(wps->wps->cb_ctx, &cred); - - os_free(wps->new_psk); - wps->new_psk = NULL; - } - - if (!wps->wps->ap) - wps_sta_cred_cb(wps); - - if (wps->new_psk) { - if (wps_cb_new_psk(wps->wps->registrar, wps->mac_addr_e, - wps->new_psk, wps->new_psk_len)) { - wpa_printf(MSG_DEBUG, "WPS: Failed to configure the " - "new PSK"); - } - os_free(wps->new_psk); - wps->new_psk = NULL; - } - - wps_cb_reg_success(wps->wps->registrar, wps->mac_addr_e, wps->uuid_e); - - if (wps->pbc) { - wps_registrar_remove_pbc_session(wps->wps->registrar, - wps->mac_addr_e, wps->uuid_e); - wps_registrar_pbc_completed(wps->wps->registrar); - } else { - wps_registrar_pin_completed(wps->wps->registrar); - } - - wps_success_event(wps->wps); - - return WPS_DONE; -} - - -enum wps_process_res wps_registrar_process_msg(struct wps_data *wps, - enum wsc_op_code op_code, - const struct wpabuf *msg) -{ - enum wps_process_res ret; - - wpa_printf(MSG_DEBUG, "WPS: Processing received message (len=%lu " - "op_code=%d)", - (unsigned long) wpabuf_len(msg), op_code); - -#ifdef CONFIG_WPS_UPNP - if (wps->wps->wps_upnp && op_code == WSC_MSG && wps->ext_reg == 1) { - struct wps_parse_attr attr; - if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type && - *attr.msg_type == WPS_M3) - wps->ext_reg = 2; /* past M2/M2D phase */ - } - if (wps->ext_reg > 1) - wps_registrar_free_pending_m2(wps->wps); - if (wps->wps->wps_upnp && wps->ext_reg && - wps->wps->upnp_msgs == NULL && - (op_code == WSC_MSG || op_code == WSC_Done || op_code == WSC_NACK)) - { - struct wps_parse_attr attr; - int type; - if (wps_parse_msg(msg, &attr) < 0 || attr.msg_type == NULL) - type = -1; - else - type = *attr.msg_type; - wpa_printf(MSG_DEBUG, "WPS: Sending received message (type %d)" - " to external Registrar for processing", type); - upnp_wps_device_send_wlan_event(wps->wps->wps_upnp, - wps->mac_addr_e, - UPNP_WPS_WLANEVENT_TYPE_EAP, - msg); - if (op_code == WSC_MSG) - return WPS_PENDING; - } else if (wps->wps->wps_upnp && wps->ext_reg && op_code == WSC_MSG) { - wpa_printf(MSG_DEBUG, "WPS: Skip internal processing - using " - "external Registrar"); - return WPS_CONTINUE; - } -#endif /* CONFIG_WPS_UPNP */ - - switch (op_code) { - case WSC_MSG: - return wps_process_wsc_msg(wps, msg); - case WSC_ACK: - return wps_process_wsc_ack(wps, msg); - case WSC_NACK: - return wps_process_wsc_nack(wps, msg); - case WSC_Done: - ret = wps_process_wsc_done(wps, msg); - if (ret == WPS_FAILURE) { - wps->state = SEND_WSC_NACK; - wps_fail_event(wps->wps, WPS_WSC_DONE); - } - return ret; - default: - wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code); - return WPS_FAILURE; - } -} - - -int wps_registrar_update_ie(struct wps_registrar *reg) -{ - return wps_set_ie(reg); -} - - -static void wps_registrar_set_selected_timeout(void *eloop_ctx, - void *timeout_ctx) -{ - struct wps_registrar *reg = eloop_ctx; - - wpa_printf(MSG_DEBUG, "WPS: SetSelectedRegistrar timed out - " - "unselect Registrar"); - reg->selected_registrar = 0; - reg->pbc = 0; - reg->sel_reg_dev_password_id_override = -1; - reg->sel_reg_config_methods_override = -1; - wps_set_ie(reg); -} - - -/** - * wps_registrar_set_selected_registrar - Notification of SetSelectedRegistrar - * @reg: Registrar data from wps_registrar_init() - * @msg: Received message from SetSelectedRegistrar - * Returns: 0 on success, -1 on failure - * - * This function is called when an AP receives a SetSelectedRegistrar UPnP - * message. - */ -int wps_registrar_set_selected_registrar(struct wps_registrar *reg, - const struct wpabuf *msg) -{ - struct wps_parse_attr attr; - - wpa_hexdump_buf(MSG_MSGDUMP, "WPS: SetSelectedRegistrar attributes", - msg); - - if (wps_parse_msg(msg, &attr) < 0) - return -1; - if (!wps_version_supported(attr.version)) { - wpa_printf(MSG_DEBUG, "WPS: Unsupported SetSelectedRegistrar " - "version 0x%x", attr.version ? *attr.version : 0); - return -1; - } - - if (attr.selected_registrar == NULL || - *attr.selected_registrar == 0) { - wpa_printf(MSG_DEBUG, "WPS: SetSelectedRegistrar: Disable " - "Selected Registrar"); - eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, - NULL); - wps_registrar_set_selected_timeout(reg, NULL); - return 0; - } - - reg->selected_registrar = 1; - reg->sel_reg_dev_password_id_override = attr.dev_password_id ? - WPA_GET_BE16(attr.dev_password_id) : DEV_PW_DEFAULT; - reg->sel_reg_config_methods_override = attr.sel_reg_config_methods ? - WPA_GET_BE16(attr.sel_reg_config_methods) : -1; - wps_set_ie(reg); - - eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); - eloop_register_timeout(WPS_PBC_WALK_TIME, 0, - wps_registrar_set_selected_timeout, - reg, NULL); - return 0; -} diff --git a/contrib/hostapd/src/wps/wps_upnp.c b/contrib/hostapd/src/wps/wps_upnp.c deleted file mode 100644 index 4c6aac2f23..0000000000 --- a/contrib/hostapd/src/wps/wps_upnp.c +++ /dev/null @@ -1,1147 +0,0 @@ -/* - * UPnP WPS Device - * Copyright (c) 2000-2003 Intel Corporation - * Copyright (c) 2006-2007 Sony Corporation - * Copyright (c) 2008-2009 Atheros Communications - * Copyright (c) 2009, Jouni Malinen - * - * See below for more details on licensing and code history. - */ - -/* - * This has been greatly stripped down from the original file - * (upnp_wps_device.c) by Ted Merrill, Atheros Communications - * in order to eliminate use of the bulky libupnp library etc. - * - * History: - * upnp_wps_device.c is/was a shim layer between wps_opt_upnp.c and - * the libupnp library. - * The layering (by Sony) was well done; only a very minor modification - * to API of upnp_wps_device.c was required. - * libupnp was found to be undesirable because: - * -- It consumed too much code and data space - * -- It uses multiple threads, making debugging more difficult - * and possibly reducing reliability. - * -- It uses static variables and only supports one instance. - * The shim and libupnp are here replaced by special code written - * specifically for the needs of hostapd. - * Various shortcuts can and are taken to keep the code size small. - * Generally, execution time is not as crucial. - * - * BUGS: - * -- UPnP requires that we be able to resolve domain names. - * While uncommon, if we have to do it then it will stall the entire - * hostapd program, which is bad. - * This is because we use the standard linux getaddrinfo() function - * which is syncronous. - * An asyncronous solution would be to use the free "ares" library. - * -- Does not have a robust output buffering scheme. Uses a single - * fixed size output buffer per TCP/HTTP connection, with possible (although - * unlikely) possibility of overflow and likely excessive use of RAM. - * A better solution would be to write the HTTP output as a buffered stream, - * using chunking: (handle header specially, then) generate data with - * a printf-like function into a buffer, catching buffer full condition, - * then send it out surrounded by http chunking. - * -- There is some code that could be separated out into the common - * library to be shared with wpa_supplicant. - * -- Needs renaming with module prefix to avoid polluting the debugger - * namespace and causing possible collisions with other static fncs - * and structure declarations when using the debugger. - * -- The http error code generation is pretty bogus, hopefully noone cares. - * - * Author: Ted Merrill, Atheros Communications, based upon earlier work - * as explained above and below. - * - * Copyright: - * Copyright 2008 Atheros Communications. - * - * The original header (of upnp_wps_device.c) reads: - * - * Copyright (c) 2006-2007 Sony Corporation. All Rights Reserved. - * - * File Name: upnp_wps_device.c - * Description: EAP-WPS UPnP device source - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Sony Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT - * OWNER 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. - * - * Portions from Intel libupnp files, e.g. genlib/net/http/httpreadwrite.c - * typical header: - * - * Copyright (c) 2000-2003 Intel Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * 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. - * * Neither name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 INTEL 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. -*/ - -/* - * Overview of WPS over UPnP: - * - * UPnP is a protocol that allows devices to discover each other and control - * each other. In UPnP terminology, a device is either a "device" (a server - * that provides information about itself and allows itself to be controlled) - * or a "control point" (a client that controls "devices") or possibly both. - * This file implements a UPnP "device". - * - * For us, we use mostly basic UPnP discovery, but the control part of interest - * is WPS carried via UPnP messages. There is quite a bit of basic UPnP - * discovery to do before we can get to WPS, however. - * - * UPnP discovery begins with "devices" send out multicast UDP packets to a - * certain fixed multicast IP address and port, and "control points" sending - * out other such UDP packets. - * - * The packets sent by devices are NOTIFY packets (not to be confused with TCP - * NOTIFY packets that are used later) and those sent by control points are - * M-SEARCH packets. These packets contain a simple HTTP style header. The - * packets are sent redundantly to get around packet loss. Devices respond to - * M-SEARCH packets with HTTP-like UDP packets containing HTTP/1.1 200 OK - * messages, which give similar information as the UDP NOTIFY packets. - * - * The above UDP packets advertise the (arbitrary) TCP ports that the - * respective parties will listen to. The control point can then do a HTTP - * SUBSCRIBE (something like an HTTP PUT) after which the device can do a - * separate HTTP NOTIFY (also like an HTTP PUT) to do event messaging. - * - * The control point will also do HTTP GET of the "device file" listed in the - * original UDP information from the device (see UPNP_WPS_DEVICE_XML_FILE - * data), and based on this will do additional GETs... HTTP POSTs are done to - * cause an action. - * - * Beyond some basic information in HTTP headers, additional information is in - * the HTTP bodies, in a format set by the SOAP and XML standards, a markup - * language related to HTML used for web pages. This language is intended to - * provide the ultimate in self-documentation by providing a universal - * namespace based on pseudo-URLs called URIs. Note that although a URI looks - * like a URL (a web address), they are never accessed as such but are used - * only as identifiers. - * - * The POST of a GetDeviceInfo gets information similar to what might be - * obtained from a probe request or response on Wi-Fi. WPS messages M1-M8 - * are passed via a POST of a PutMessage; the M1-M8 WPS messages are converted - * to a bin64 ascii representation for encapsulation. When proxying messages, - * WLANEvent and PutWLANResponse are used. - * - * This of course glosses over a lot of details. - */ - -#include "includes.h" - -#include -#include -#include -#include - -#include "common.h" -#include "uuid.h" -#include "base64.h" -#include "wps.h" -#include "wps_i.h" -#include "wps_upnp.h" -#include "wps_upnp_i.h" - - -/* - * UPnP allows a client ("control point") to send a server like us ("device") - * a domain name for registration, and we are supposed to resolve it. This is - * bad because, using the standard Linux library, we will stall the entire - * hostapd waiting for resolution. - * - * The "correct" solution would be to use an event driven library for domain - * name resolution such as "ares". However, this would increase code size - * further. Since it is unlikely that we'll actually see such domain names, we - * can just refuse to accept them. - */ -#define NO_DOMAIN_NAME_RESOLUTION 1 /* 1 to allow only dotted ip addresses */ - - -/* - * UPnP does not scale well. If we were in a room with thousands of control - * points then potentially we could be expected to handle subscriptions for - * each of them, which would exhaust our memory. So we must set a limit. In - * practice we are unlikely to see more than one or two. - */ -#define MAX_SUBSCRIPTIONS 4 /* how many subscribing clients we handle */ -#define MAX_ADDR_PER_SUBSCRIPTION 8 - - -/* Write the current date/time per RFC */ -void format_date(struct wpabuf *buf) -{ - const char *weekday_str = "Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat"; - const char *month_str = "Jan\0Feb\0Mar\0Apr\0May\0Jun\0" - "Jul\0Aug\0Sep\0Oct\0Nov\0Dec"; - struct tm *date; - time_t t; - - t = time(NULL); - date = gmtime(&t); - wpabuf_printf(buf, "%s, %02d %s %d %02d:%02d:%02d GMT", - &weekday_str[date->tm_wday * 4], date->tm_mday, - &month_str[date->tm_mon * 4], date->tm_year + 1900, - date->tm_hour, date->tm_min, date->tm_sec); -} - - -/*************************************************************************** - * UUIDs (unique identifiers) - * - * These are supposed to be unique in all the world. - * Sometimes permanent ones are used, sometimes temporary ones - * based on random numbers... there are different rules for valid content - * of different types. - * Each uuid is 16 bytes long. - **************************************************************************/ - -/* uuid_make -- construct a random UUID - * The UPnP documents don't seem to offer any guidelines as to which method to - * use for constructing UUIDs for subscriptions. Presumably any method from - * rfc4122 is good enough; I've chosen random number method. - */ -static void uuid_make(u8 uuid[UUID_LEN]) -{ - os_get_random(uuid, UUID_LEN); - - /* Replace certain bits as specified in rfc4122 or X.667 */ - uuid[6] &= 0x0f; uuid[6] |= (4 << 4); /* version 4 == random gen */ - uuid[8] &= 0x3f; uuid[8] |= 0x80; -} - - -/* - * Subscriber address handling. - * Since a subscriber may have an arbitrary number of addresses, we have to - * add a bunch of code to handle them. - * - * Addresses are passed in text, and MAY be domain names instead of the (usual - * and expected) dotted IP addresses. Resolving domain names consumes a lot of - * resources. Worse, we are currently using the standard Linux getaddrinfo() - * which will block the entire program until complete or timeout! The proper - * solution would be to use the "ares" library or similar with more state - * machine steps etc. or just disable domain name resolution by setting - * NO_DOMAIN_NAME_RESOLUTION to 1 at top of this file. - */ - -/* subscr_addr_delete -- delete single unlinked subscriber address - * (be sure to unlink first if need be) - */ -static void subscr_addr_delete(struct subscr_addr *a) -{ - /* - * Note: do NOT free domain_and_port or path because they point to - * memory within the allocation of "a". - */ - os_free(a); -} - - -/* subscr_addr_unlink -- unlink subscriber address from linked list */ -static void subscr_addr_unlink(struct subscription *s, struct subscr_addr *a) -{ - struct subscr_addr **listp = &s->addr_list; - s->n_addr--; - a->next->prev = a->prev; - a->prev->next = a->next; - if (*listp == a) { - if (a == a->next) { - /* last in queue */ - *listp = NULL; - assert(s->n_addr == 0); - } else { - *listp = a->next; - } - } -} - - -/* subscr_addr_free_all -- unlink and delete list of subscriber addresses. */ -static void subscr_addr_free_all(struct subscription *s) -{ - struct subscr_addr **listp = &s->addr_list; - struct subscr_addr *a; - while ((a = *listp) != NULL) { - subscr_addr_unlink(s, a); - subscr_addr_delete(a); - } -} - - -/* subscr_addr_link -- add subscriber address to list of addresses */ -static void subscr_addr_link(struct subscription *s, struct subscr_addr *a) -{ - struct subscr_addr **listp = &s->addr_list; - s->n_addr++; - if (*listp == NULL) { - *listp = a->next = a->prev = a; - } else { - a->next = *listp; - a->prev = (*listp)->prev; - a->prev->next = a; - a->next->prev = a; - } -} - - -/* subscr_addr_add_url -- add address(es) for one url to subscription */ -static void subscr_addr_add_url(struct subscription *s, const char *url) -{ - int alloc_len; - char *scratch_mem = NULL; - char *mem; - char *domain_and_port; - char *delim; - char *path; - char *domain; - int port = 80; /* port to send to (default is port 80) */ - struct addrinfo hints; - struct addrinfo *result = NULL; - struct addrinfo *rp; - int rerr; - struct subscr_addr *a = NULL; - - /* url MUST begin with http: */ - if (os_strncasecmp(url, "http://", 7)) - goto fail; - url += 7; - - /* allocate memory for the extra stuff we need */ - alloc_len = (2 * (os_strlen(url) + 1)); - scratch_mem = os_zalloc(alloc_len); - if (scratch_mem == NULL) - goto fail; - mem = scratch_mem; - strcpy(mem, url); - domain_and_port = mem; - mem += 1 + os_strlen(mem); - delim = os_strchr(domain_and_port, '/'); - if (delim) { - *delim++ = 0; /* null terminate domain and port */ - path = delim; - } else { - path = domain_and_port + os_strlen(domain_and_port); - } - domain = mem; - strcpy(domain, domain_and_port); - delim = strchr(domain, ':'); - if (delim) { - *delim++ = 0; /* null terminate domain */ - if (isdigit(*delim)) - port = atol(delim); - } - - /* - * getaddrinfo does the right thing with dotted decimal notations, or - * will resolve domain names. Resolving domain names will unfortunately - * hang the entire program until it is resolved or it times out - * internal to getaddrinfo; fortunately we think that the use of actual - * domain names (vs. dotted decimal notations) should be uncommon. - */ - os_memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_INET; /* IPv4 */ - hints.ai_socktype = SOCK_STREAM; -#if NO_DOMAIN_NAME_RESOLUTION - /* Suppress domain name resolutions that would halt - * the program for periods of time - */ - hints.ai_flags = AI_NUMERICHOST; -#else - /* Allow domain name resolution. */ - hints.ai_flags = 0; -#endif - hints.ai_protocol = 0; /* Any protocol? */ - rerr = getaddrinfo(domain, NULL /* fill in port ourselves */, - &hints, &result); - if (rerr) { - wpa_printf(MSG_INFO, "WPS UPnP: Resolve error %d (%s) on: %s", - rerr, gai_strerror(rerr), domain); - goto fail; - } - for (rp = result; rp; rp = rp->ai_next) { - /* Limit no. of address to avoid denial of service attack */ - if (s->n_addr >= MAX_ADDR_PER_SUBSCRIPTION) { - wpa_printf(MSG_INFO, "WPS UPnP: subscr_addr_add_url: " - "Ignoring excessive addresses"); - break; - } - - a = os_zalloc(sizeof(*a) + alloc_len); - if (a == NULL) - continue; - a->s = s; - mem = (void *) (a + 1); - a->domain_and_port = mem; - strcpy(mem, domain_and_port); - mem += 1 + strlen(mem); - a->path = mem; - if (path[0] != '/') - *mem++ = '/'; - strcpy(mem, path); - mem += 1 + strlen(mem); - os_memcpy(&a->saddr, rp->ai_addr, sizeof(a->saddr)); - a->saddr.sin_port = htons(port); - - subscr_addr_link(s, a); - a = NULL; /* don't free it below */ - } - -fail: - if (result) - freeaddrinfo(result); - os_free(scratch_mem); - os_free(a); -} - - -/* subscr_addr_list_create -- create list from urls in string. - * Each url is enclosed by angle brackets. - */ -static void subscr_addr_list_create(struct subscription *s, - const char *url_list) -{ - char *end; - for (;;) { - while (*url_list == ' ' || *url_list == '\t') - url_list++; - if (*url_list != '<') - break; - url_list++; - end = os_strchr(url_list, '>'); - if (end == NULL) - break; - *end++ = 0; - subscr_addr_add_url(s, url_list); - url_list = end; - } -} - - -int send_wpabuf(int fd, struct wpabuf *buf) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: Send %lu byte message", - (unsigned long) wpabuf_len(buf)); - errno = 0; - if (write(fd, wpabuf_head(buf), wpabuf_len(buf)) != - (int) wpabuf_len(buf)) { - wpa_printf(MSG_ERROR, "WPS UPnP: Failed to send buffer: " - "errno=%d (%s)", - errno, strerror(errno)); - return -1; - } - - return 0; -} - - -static void wpabuf_put_property(struct wpabuf *buf, const char *name, - const char *value) -{ - wpabuf_put_str(buf, ""); - wpabuf_printf(buf, "<%s>", name); - if (value) - wpabuf_put_str(buf, value); - wpabuf_printf(buf, "", name); - wpabuf_put_str(buf, "\n"); -} - - -/** - * upnp_wps_device_send_event - Queue event messages for subscribers - * @sm: WPS UPnP state machine from upnp_wps_device_init() - * - * This function queues the last WLANEvent to be sent for all currently - * subscribed UPnP control points. sm->wlanevent must have been set with the - * encoded data before calling this function. - */ -static void upnp_wps_device_send_event(struct upnp_wps_device_sm *sm) -{ - /* Enqueue event message for all subscribers */ - struct wpabuf *buf; /* holds event message */ - int buf_size = 0; - struct subscription *s; - /* Actually, utf-8 is the default, but it doesn't hurt to specify it */ - const char *format_head = - "\n" - "\n"; - const char *format_tail = "\n"; - - if (sm->subscriptions == NULL) { - /* optimize */ - return; - } - - /* Determine buffer size needed first */ - buf_size += os_strlen(format_head); - buf_size += 50 + 2 * os_strlen("WLANEvent"); - if (sm->wlanevent) - buf_size += os_strlen(sm->wlanevent); - buf_size += os_strlen(format_tail); - - buf = wpabuf_alloc(buf_size); - if (buf == NULL) - return; - wpabuf_put_str(buf, format_head); - wpabuf_put_property(buf, "WLANEvent", sm->wlanevent); - wpabuf_put_str(buf, format_tail); - - wpa_printf(MSG_MSGDUMP, "WPS UPnP: WLANEvent message:\n%s", - (char *) wpabuf_head(buf)); - - s = sm->subscriptions; - do { - if (event_add(s, buf)) { - struct subscription *s_old = s; - wpa_printf(MSG_INFO, "WPS UPnP: Dropping " - "subscriber due to event backlog"); - s = s_old->next; - subscription_unlink(s_old); - subscription_destroy(s_old); - } else { - s = s->next; - } - } while (s != sm->subscriptions); - - wpabuf_free(buf); -} - - -/* - * Event subscription (subscriber machines register with us to receive event - * messages). - * This is the result of an incoming HTTP over TCP SUBSCRIBE request. - */ - -/* subscription_unlink -- remove from the active list */ -void subscription_unlink(struct subscription *s) -{ - struct upnp_wps_device_sm *sm = s->sm; - - if (s->next == s) { - /* only one? */ - sm->subscriptions = NULL; - } else { - if (sm->subscriptions == s) - sm->subscriptions = s->next; - s->next->prev = s->prev; - s->prev->next = s->next; - } - sm->n_subscriptions--; -} - - -/* subscription_link_to_end -- link to end of active list - * (should have high expiry time!) - */ -static void subscription_link_to_end(struct subscription *s) -{ - struct upnp_wps_device_sm *sm = s->sm; - - if (sm->subscriptions) { - s->next = sm->subscriptions; - s->prev = s->next->prev; - s->prev->next = s; - s->next->prev = s; - } else { - sm->subscriptions = s->next = s->prev = s; - } - sm->n_subscriptions++; -} - - -/* subscription_destroy -- destroy an unlinked subscription - * Be sure to unlink first if necessary. - */ -void subscription_destroy(struct subscription *s) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: Destroy subscription %p", s); - if (s->addr_list) - subscr_addr_free_all(s); - event_delete_all(s); - os_free(s); -} - - -/* subscription_list_age -- remove expired subscriptions */ -static void subscription_list_age(struct upnp_wps_device_sm *sm, time_t now) -{ - struct subscription *s; - while ((s = sm->subscriptions) != NULL && s->timeout_time < now) { - wpa_printf(MSG_DEBUG, "WPS UPnP: Removing aged subscription"); - subscription_unlink(s); - subscription_destroy(s); - } -} - - -/* subscription_find -- return existing subscription matching uuid, if any - * returns NULL if not found - */ -struct subscription * subscription_find(struct upnp_wps_device_sm *sm, - const u8 uuid[UUID_LEN]) -{ - struct subscription *s0 = sm->subscriptions; - struct subscription *s = s0; - - if (s0 == NULL) - return NULL; - do { - if (os_memcmp(s->uuid, uuid, UUID_LEN) == 0) - return s; /* Found match */ - s = s->next; - } while (s != s0); - - return NULL; -} - - -static struct wpabuf * build_fake_wsc_ack(void) -{ - struct wpabuf *msg = wpabuf_alloc(100); - if (msg == NULL) - return NULL; - wpabuf_put_u8(msg, UPNP_WPS_WLANEVENT_TYPE_EAP); - wpabuf_put_str(msg, "00:00:00:00:00:00"); - wps_build_version(msg); - wps_build_msg_type(msg, WPS_WSC_ACK); - /* Enrollee Nonce */ - wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE); - wpabuf_put_be16(msg, WPS_NONCE_LEN); - wpabuf_put(msg, WPS_NONCE_LEN); - /* Registrar Nonce */ - wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE); - wpabuf_put_be16(msg, WPS_NONCE_LEN); - wpabuf_put(msg, WPS_NONCE_LEN); - return msg; -} - - -/* subscription_first_event -- send format/queue event that is automatically - * sent on a new subscription. - */ -static int subscription_first_event(struct subscription *s) -{ - /* - * Actually, utf-8 is the default, but it doesn't hurt to specify it. - * - * APStatus is apparently a bit set, - * 0x1 = configuration change (but is always set?) - * 0x10 = ap is locked - * - * Per UPnP spec, we send out the last value of each variable, even - * for WLANEvent, whatever it was. - */ - char *wlan_event; - struct wpabuf *buf; - int ap_status = 1; /* TODO: add 0x10 if access point is locked */ - const char *head = - "\n" - "\n"; - const char *tail = "\n"; - char txt[10]; - - if (s->sm->wlanevent == NULL) { - /* - * There has been no events before the subscription. However, - * UPnP device architecture specification requires all the - * evented variables to be included, so generate a dummy event - * for this particular case using a WSC_ACK and all-zeros - * nonces. The ER (UPnP control point) will ignore this, but at - * least it will learn that WLANEvent variable will be used in - * event notifications in the future. - */ - struct wpabuf *msg; - wpa_printf(MSG_DEBUG, "WPS UPnP: Use a fake WSC_ACK as the " - "initial WLANEvent"); - msg = build_fake_wsc_ack(); - if (msg) { - s->sm->wlanevent = (char *) - base64_encode(wpabuf_head(msg), - wpabuf_len(msg), NULL); - wpabuf_free(msg); - } - } - - wlan_event = s->sm->wlanevent; - if (wlan_event == NULL || *wlan_event == '\0') { - wpa_printf(MSG_DEBUG, "WPS UPnP: WLANEvent not known for " - "initial event message"); - wlan_event = ""; - } - buf = wpabuf_alloc(500 + os_strlen(wlan_event)); - if (buf == NULL) - return 1; - - wpabuf_put_str(buf, head); - wpabuf_put_property(buf, "STAStatus", "1"); - os_snprintf(txt, sizeof(txt), "%d", ap_status); - wpabuf_put_property(buf, "APStatus", txt); - if (*wlan_event) - wpabuf_put_property(buf, "WLANEvent", wlan_event); - wpabuf_put_str(buf, tail); - - if (event_add(s, buf)) { - wpabuf_free(buf); - return 1; - } - wpabuf_free(buf); - - return 0; -} - - -/** - * subscription_start - Remember a UPnP control point to send events to. - * @sm: WPS UPnP state machine from upnp_wps_device_init() - * @callback_urls: Callback URLs - * Returns: %NULL on error, or pointer to new subscription structure. - */ -struct subscription * subscription_start(struct upnp_wps_device_sm *sm, - const char *callback_urls) -{ - struct subscription *s; - time_t now = time(NULL); - time_t expire = now + UPNP_SUBSCRIBE_SEC; - - /* Get rid of expired subscriptions so we have room */ - subscription_list_age(sm, now); - - /* If too many subscriptions, remove oldest */ - if (sm->n_subscriptions >= MAX_SUBSCRIPTIONS) { - s = sm->subscriptions; - wpa_printf(MSG_INFO, "WPS UPnP: Too many subscriptions, " - "trashing oldest"); - subscription_unlink(s); - subscription_destroy(s); - } - - s = os_zalloc(sizeof(*s)); - if (s == NULL) - return NULL; - - s->sm = sm; - s->timeout_time = expire; - uuid_make(s->uuid); - subscr_addr_list_create(s, callback_urls); - /* Add to end of list, since it has the highest expiration time */ - subscription_link_to_end(s); - /* Queue up immediate event message (our last event) - * as required by UPnP spec. - */ - if (subscription_first_event(s)) { - wpa_printf(MSG_INFO, "WPS UPnP: Dropping subscriber due to " - "event backlog"); - subscription_unlink(s); - subscription_destroy(s); - return NULL; - } - wpa_printf(MSG_DEBUG, "WPS UPnP: Subscription %p started with %s", - s, callback_urls); - /* Schedule sending this */ - event_send_all_later(sm); - return s; -} - - -/* subscription_renew -- find subscription and reset timeout */ -struct subscription * subscription_renew(struct upnp_wps_device_sm *sm, - const u8 uuid[UUID_LEN]) -{ - time_t now = time(NULL); - time_t expire = now + UPNP_SUBSCRIBE_SEC; - struct subscription *s = subscription_find(sm, uuid); - if (s == NULL) - return NULL; - wpa_printf(MSG_DEBUG, "WPS UPnP: Subscription renewed"); - subscription_unlink(s); - s->timeout_time = expire; - /* add back to end of list, since it now has highest expiry */ - subscription_link_to_end(s); - return s; -} - - -/** - * upnp_wps_device_send_wlan_event - Event notification - * @sm: WPS UPnP state machine from upnp_wps_device_init() - * @from_mac_addr: Source (Enrollee) MAC address for the event - * @ev_type: Event type - * @msg: Event data - * Returns: 0 on success, -1 on failure - * - * Tell external Registrars (UPnP control points) that something happened. In - * particular, events include WPS messages from clients that are proxied to - * external Registrars. - */ -int upnp_wps_device_send_wlan_event(struct upnp_wps_device_sm *sm, - const u8 from_mac_addr[ETH_ALEN], - enum upnp_wps_wlanevent_type ev_type, - const struct wpabuf *msg) -{ - int ret = -1; - char type[2]; - const u8 *mac = from_mac_addr; - char mac_text[18]; - u8 *raw = NULL; - size_t raw_len; - char *val; - size_t val_len; - int pos = 0; - - if (!sm) - goto fail; - - os_snprintf(type, sizeof(type), "%1u", ev_type); - - raw_len = 1 + 17 + (msg ? wpabuf_len(msg) : 0); - raw = os_zalloc(raw_len); - if (!raw) - goto fail; - - *(raw + pos) = (u8) ev_type; - pos += 1; - os_snprintf(mac_text, sizeof(mac_text), MACSTR, MAC2STR(mac)); - wpa_printf(MSG_DEBUG, "WPS UPnP: Proxying WLANEvent from %s", - mac_text); - os_memcpy(raw + pos, mac_text, 17); - pos += 17; - if (msg) { - os_memcpy(raw + pos, wpabuf_head(msg), wpabuf_len(msg)); - pos += wpabuf_len(msg); - } - raw_len = pos; - - val = (char *) base64_encode(raw, raw_len, &val_len); - if (val == NULL) - goto fail; - - os_free(sm->wlanevent); - sm->wlanevent = val; - upnp_wps_device_send_event(sm); - - ret = 0; - -fail: - os_free(raw); - - return ret; -} - - -#ifdef __FreeBSD__ -#include -#include -#include - -static int eth_get(const char *device, u8 ea[ETH_ALEN]) -{ - struct if_msghdr *ifm; - struct sockaddr_dl *sdl; - u_char *p, *buf; - size_t len; - int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 }; - - if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) - return -1; - if ((buf = os_malloc(len)) == NULL) - return -1; - if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { - os_free(buf); - return -1; - } - for (p = buf; p < buf + len; p += ifm->ifm_msglen) { - ifm = (struct if_msghdr *)p; - sdl = (struct sockaddr_dl *)(ifm + 1); - if (ifm->ifm_type != RTM_IFINFO || - (ifm->ifm_addrs & RTA_IFP) == 0) - continue; - if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 || - os_memcmp(sdl->sdl_data, device, sdl->sdl_nlen) != 0) - continue; - os_memcpy(ea, LLADDR(sdl), sdl->sdl_alen); - break; - } - os_free(buf); - - if (p >= buf + len) { - errno = ESRCH; - return -1; - } - return 0; -} -#endif /* __FreeBSD__ */ - - -/** - * get_netif_info - Get hw and IP addresses for network device - * @net_if: Selected network interface name - * @ip_addr: Buffer for returning IP address in network byte order - * @ip_addr_text: Buffer for returning a pointer to allocated IP address text - * @mac: Buffer for returning MAC address - * @mac_addr_text: Buffer for returning allocated MAC address text - * Returns: 0 on success, -1 on failure - */ -static int get_netif_info(const char *net_if, unsigned *ip_addr, - char **ip_addr_text, u8 mac[ETH_ALEN], - char **mac_addr_text) -{ - struct ifreq req; - int sock = -1; - struct sockaddr_in *addr; - struct in_addr in_addr; - - *ip_addr_text = os_zalloc(16); - *mac_addr_text = os_zalloc(18); - if (*ip_addr_text == NULL || *mac_addr_text == NULL) - goto fail; - - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock < 0) - goto fail; - - os_strlcpy(req.ifr_name, net_if, sizeof(req.ifr_name)); - if (ioctl(sock, SIOCGIFADDR, &req) < 0) { - wpa_printf(MSG_ERROR, "WPS UPnP: SIOCGIFADDR failed: %d (%s)", - errno, strerror(errno)); - goto fail; - } - addr = (void *) &req.ifr_addr; - *ip_addr = addr->sin_addr.s_addr; - in_addr.s_addr = *ip_addr; - os_snprintf(*ip_addr_text, 16, "%s", inet_ntoa(in_addr)); - -#ifdef __linux__ - os_strlcpy(req.ifr_name, net_if, sizeof(req.ifr_name)); - if (ioctl(sock, SIOCGIFHWADDR, &req) < 0) { - wpa_printf(MSG_ERROR, "WPS UPnP: SIOCGIFHWADDR failed: " - "%d (%s)", errno, strerror(errno)); - goto fail; - } - os_memcpy(mac, req.ifr_addr.sa_data, 6); -#elif defined(__FreeBSD__) - if (eth_get(net_if, mac) < 0) { - wpa_printf(MSG_ERROR, "WPS UPnP: Failed to get MAC address"); - goto fail; - } -#else -#error MAC address fetch not implemented -#endif - os_snprintf(*mac_addr_text, 18, MACSTR, MAC2STR(req.ifr_addr.sa_data)); - - close(sock); - return 0; - -fail: - if (sock >= 0) - close(sock); - os_free(*ip_addr_text); - *ip_addr_text = NULL; - os_free(*mac_addr_text); - *mac_addr_text = NULL; - return -1; -} - - -/** - * upnp_wps_device_stop - Stop WPS UPnP operations on an interface - * @sm: WPS UPnP state machine from upnp_wps_device_init() - */ -void upnp_wps_device_stop(struct upnp_wps_device_sm *sm) -{ - if (!sm || !sm->started) - return; - - wpa_printf(MSG_DEBUG, "WPS UPnP: Stop device"); - web_listener_stop(sm); - while (sm->web_connections) - web_connection_stop(sm->web_connections); - while (sm->msearch_replies) - msearchreply_state_machine_stop(sm->msearch_replies); - while (sm->subscriptions) { - struct subscription *s = sm->subscriptions; - subscription_unlink(s); - subscription_destroy(s); - } - - advertisement_state_machine_stop(sm, 1); - - event_send_stop_all(sm); - os_free(sm->wlanevent); - sm->wlanevent = NULL; - os_free(sm->net_if); - sm->net_if = NULL; - os_free(sm->mac_addr_text); - sm->mac_addr_text = NULL; - os_free(sm->ip_addr_text); - sm->ip_addr_text = NULL; - if (sm->multicast_sd >= 0) - close(sm->multicast_sd); - sm->multicast_sd = -1; - ssdp_listener_stop(sm); - - sm->started = 0; -} - - -/** - * upnp_wps_device_start - Start WPS UPnP operations on an interface - * @sm: WPS UPnP state machine from upnp_wps_device_init() - * @net_if: Selected network interface name - * Returns: 0 on success, -1 on failure - */ -int upnp_wps_device_start(struct upnp_wps_device_sm *sm, char *net_if) -{ - if (!sm || !net_if) - return -1; - - if (sm->started) - upnp_wps_device_stop(sm); - - sm->net_if = strdup(net_if); - sm->multicast_sd = -1; - sm->ssdp_sd = -1; - sm->started = 1; - sm->advertise_count = 0; - - /* Fix up linux multicast handling */ - if (add_ssdp_network(net_if)) - goto fail; - - /* Determine which IP and mac address we're using */ - if (get_netif_info(net_if, - &sm->ip_addr, &sm->ip_addr_text, - sm->mac_addr, &sm->mac_addr_text)) { - wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address " - "for %s. Does it have IP address?", net_if); - goto fail; - } - - /* Listen for incoming TCP connections so that others - * can fetch our "xml files" from us. - */ - if (web_listener_start(sm)) - goto fail; - - /* Set up for receiving discovery (UDP) packets */ - if (ssdp_listener_start(sm)) - goto fail; - - /* Set up for sending multicast */ - if (ssdp_open_multicast(sm) < 0) - goto fail; - - /* - * Broadcast NOTIFY messages to let the world know we exist. - * This is done via a state machine since the messages should not be - * all sent out at once. - */ - if (advertisement_state_machine_start(sm)) - goto fail; - - return 0; - -fail: - upnp_wps_device_stop(sm); - return -1; -} - - -/** - * upnp_wps_device_deinit - Deinitialize WPS UPnP - * @sm: WPS UPnP state machine from upnp_wps_device_init() - */ -void upnp_wps_device_deinit(struct upnp_wps_device_sm *sm) -{ - if (!sm) - return; - - upnp_wps_device_stop(sm); - - if (sm->peer.wps) - wps_deinit(sm->peer.wps); - os_free(sm->root_dir); - os_free(sm->desc_url); - os_free(sm->ctx); - os_free(sm); -} - - -/** - * upnp_wps_device_init - Initialize WPS UPnP - * @ctx: callback table; we must eventually free it - * @wps: Pointer to longterm WPS context - * @priv: External context data that will be used in callbacks - * Returns: WPS UPnP state or %NULL on failure - */ -struct upnp_wps_device_sm * -upnp_wps_device_init(struct upnp_wps_device_ctx *ctx, struct wps_context *wps, - void *priv) -{ - struct upnp_wps_device_sm *sm; - - sm = os_zalloc(sizeof(*sm)); - if (!sm) { - wpa_printf(MSG_ERROR, "WPS UPnP: upnp_wps_device_init failed"); - return NULL; - } - - sm->ctx = ctx; - sm->wps = wps; - sm->priv = priv; - - return sm; -} - - -/** - * upnp_wps_subscribers - Check whether there are any event subscribers - * @sm: WPS UPnP state machine from upnp_wps_device_init() - * Returns: 0 if no subscribers, 1 if subscribers - */ -int upnp_wps_subscribers(struct upnp_wps_device_sm *sm) -{ - return sm->subscriptions != NULL; -} diff --git a/contrib/hostapd/src/wps/wps_upnp.h b/contrib/hostapd/src/wps/wps_upnp.h deleted file mode 100644 index 31b055628b..0000000000 --- a/contrib/hostapd/src/wps/wps_upnp.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * UPnP WPS Device - * Copyright (c) 2000-2003 Intel Corporation - * Copyright (c) 2006-2007 Sony Corporation - * Copyright (c) 2008-2009 Atheros Communications - * Copyright (c) 2009, Jouni Malinen - * - * See wps_upnp.c for more details on licensing and code history. - */ - -#ifndef WPS_UPNP_H -#define WPS_UPNP_H - -struct upnp_wps_device_sm; -struct wps_context; -struct wps_data; - -struct upnp_wps_peer { - struct wps_data *wps; -}; - -enum upnp_wps_wlanevent_type { - UPNP_WPS_WLANEVENT_TYPE_PROBE = 1, - UPNP_WPS_WLANEVENT_TYPE_EAP = 2 -}; - -struct upnp_wps_device_ctx { - struct wpabuf * (*rx_req_get_device_info)( - void *priv, struct upnp_wps_peer *peer); - struct wpabuf * (*rx_req_put_message)( - void *priv, struct upnp_wps_peer *peer, - const struct wpabuf *msg); - struct wpabuf * (*rx_req_get_ap_settings)(void *priv, - const struct wpabuf *msg); - int (*rx_req_set_ap_settings)(void *priv, const struct wpabuf *msg); - int (*rx_req_del_ap_settings)(void *priv, const struct wpabuf *msg); - struct wpabuf * (*rx_req_get_sta_settings)(void *priv, - const struct wpabuf *msg); - int (*rx_req_set_sta_settings)(void *priv, const struct wpabuf *msg); - int (*rx_req_del_sta_settings)(void *priv, const struct wpabuf *msg); - int (*rx_req_put_wlan_response)( - void *priv, enum upnp_wps_wlanevent_type ev_type, - const u8 *mac_addr, const struct wpabuf *msg, - enum wps_msg_type msg_type); - int (*rx_req_set_selected_registrar)(void *priv, - const struct wpabuf *msg); - int (*rx_req_reboot_ap)(void *priv, const struct wpabuf *msg); - int (*rx_req_reset_ap)(void *priv, const struct wpabuf *msg); - int (*rx_req_reboot_sta)(void *priv, const struct wpabuf *msg); - int (*rx_req_reset_sta)(void *priv, const struct wpabuf *msg); -}; - -struct upnp_wps_device_sm * -upnp_wps_device_init(struct upnp_wps_device_ctx *ctx, struct wps_context *wps, - void *priv); -void upnp_wps_device_deinit(struct upnp_wps_device_sm *sm); - -int upnp_wps_device_start(struct upnp_wps_device_sm *sm, char *net_if); -void upnp_wps_device_stop(struct upnp_wps_device_sm *sm); - -int upnp_wps_device_send_wlan_event(struct upnp_wps_device_sm *sm, - const u8 from_mac_addr[ETH_ALEN], - enum upnp_wps_wlanevent_type ev_type, - const struct wpabuf *msg); -int upnp_wps_subscribers(struct upnp_wps_device_sm *sm); - -#endif /* WPS_UPNP_H */ diff --git a/contrib/hostapd/src/wps/wps_upnp_event.c b/contrib/hostapd/src/wps/wps_upnp_event.c deleted file mode 100644 index 4122a87de9..0000000000 --- a/contrib/hostapd/src/wps/wps_upnp_event.c +++ /dev/null @@ -1,534 +0,0 @@ -/* - * UPnP WPS Device - Event processing - * Copyright (c) 2000-2003 Intel Corporation - * Copyright (c) 2006-2007 Sony Corporation - * Copyright (c) 2008-2009 Atheros Communications - * Copyright (c) 2009, Jouni Malinen - * - * See wps_upnp.c for more details on licensing and code history. - */ - -#include "includes.h" -#include -#include - -#include "common.h" -#include "eloop.h" -#include "uuid.h" -#include "httpread.h" -#include "wps_defs.h" -#include "wps_upnp.h" -#include "wps_upnp_i.h" - -/* - * Event message generation (to subscribers) - * - * We make a separate copy for each message for each subscriber. This memory - * wasted could be limited (adding code complexity) by sharing copies, keeping - * a usage count and freeing when zero. - * - * Sending a message requires using a HTTP over TCP NOTIFY - * (like a PUT) which requires a number of states.. - */ - -#define MAX_EVENTS_QUEUED 20 /* How far behind queued events */ -#define EVENT_TIMEOUT_SEC 30 /* Drop sending event after timeout */ - -/* How long to wait before sending event */ -#define EVENT_DELAY_SECONDS 0 -#define EVENT_DELAY_MSEC 0 - -/* - * Event information that we send to each subscriber is remembered in this - * struct. The event cannot be sent by simple UDP; it has to be sent by a HTTP - * over TCP transaction which requires various states.. It may also need to be - * retried at a different address (if more than one is available). - * - * TODO: As an optimization we could share data between subscribers. - */ -struct wps_event_ { - struct wps_event_ *next; - struct wps_event_ *prev; /* double linked list */ - struct subscription *s; /* parent */ - unsigned subscriber_sequence; /* which event for this subscription*/ - int retry; /* which retry */ - struct subscr_addr *addr; /* address to connect to */ - struct wpabuf *data; /* event data to send */ - /* The following apply while we are sending an event message. */ - int sd; /* -1 or socket descriptor for open connection */ - int sd_registered; /* nonzero if we must cancel registration */ - struct httpread *hread; /* NULL or open connection for event msg */ -}; - - -static void event_timeout_handler(void *eloop_data, void *user_ctx); - -/* event_clean -- clean sockets etc. of event - * Leaves data, retry count etc. alone. - */ -static void event_clean(struct wps_event_ *e) -{ - if (e->s->current_event == e) { - eloop_cancel_timeout(event_timeout_handler, NULL, e); - e->s->current_event = NULL; - } - if (e->sd_registered) { - eloop_unregister_sock(e->sd, EVENT_TYPE_WRITE); - e->sd_registered = 0; - } - if (e->sd != -1) { - close(e->sd); - e->sd = -1; - } - if (e->hread) - httpread_destroy(e->hread); - e->hread = NULL; -} - - -/* event_delete -- delete single unqueued event - * (be sure to dequeue first if need be) - */ -static void event_delete(struct wps_event_ *e) -{ - event_clean(e); - wpabuf_free(e->data); - os_free(e); -} - - -/* event_dequeue -- get next event from the queue - * Returns NULL if empty. - */ -static struct wps_event_ *event_dequeue(struct subscription *s) -{ - struct wps_event_ **event_head = &s->event_queue; - struct wps_event_ *e = *event_head; - if (e == NULL) - return NULL; - e->next->prev = e->prev; - e->prev->next = e->next; - if (*event_head == e) { - if (e == e->next) { - /* last in queue */ - *event_head = NULL; - } else { - *event_head = e->next; - } - } - s->n_queue--; - e->next = e->prev = NULL; - /* but parent "s" is still valid */ - return e; -} - - -/* event_enqueue_at_end -- add event to end of queue */ -static void event_enqueue_at_end(struct subscription *s, struct wps_event_ *e) -{ - struct wps_event_ **event_head = &s->event_queue; - if (*event_head == NULL) { - *event_head = e->next = e->prev = e; - } else { - e->next = *event_head; - e->prev = e->next->prev; - e->prev->next = e; - e->next->prev = e; - } - s->n_queue++; -} - - -/* event_enqueue_at_begin -- add event to begin of queue - * (appropriate for retrying event only) - */ -static void event_enqueue_at_begin(struct subscription *s, - struct wps_event_ *e) -{ - struct wps_event_ **event_head = &s->event_queue; - if (*event_head == NULL) { - *event_head = e->next = e->prev = e; - } else { - e->prev = *event_head; - e->next = e->prev->next; - e->prev->next = e; - e->next->prev = e; - *event_head = e; - } - s->n_queue++; -} - - -/* event_delete_all -- delete entire event queue and current event */ -void event_delete_all(struct subscription *s) -{ - struct wps_event_ *e; - while ((e = event_dequeue(s)) != NULL) - event_delete(e); - if (s->current_event) { - event_delete(s->current_event); - /* will set: s->current_event = NULL; */ - } -} - - -/** - * event_retry - Called when we had a failure delivering event msg - * @e: Event - * @do_next_address: skip address e.g. on connect fail - */ -static void event_retry(struct wps_event_ *e, int do_next_address) -{ - struct subscription *s = e->s; - struct upnp_wps_device_sm *sm = s->sm; - - event_clean(e); - /* will set: s->current_event = NULL; */ - - if (do_next_address) - e->retry++; - if (e->retry >= s->n_addr) { - wpa_printf(MSG_DEBUG, "WPS UPnP: Giving up on sending event " - "for %s", e->addr->domain_and_port); - return; - } - event_enqueue_at_begin(s, e); - event_send_all_later(sm); -} - - -/* called if the overall event-sending process takes too long */ -static void event_timeout_handler(void *eloop_data, void *user_ctx) -{ - struct wps_event_ *e = user_ctx; - struct subscription *s = e->s; - - assert(e == s->current_event); - - wpa_printf(MSG_DEBUG, "WPS UPnP: Event send timeout"); - event_retry(e, 1); -} - - -/* event_got_response_handler -- called back when http response is received. */ -static void event_got_response_handler(struct httpread *handle, void *cookie, - enum httpread_event en) -{ - struct wps_event_ *e = cookie; - struct subscription *s = e->s; - struct upnp_wps_device_sm *sm = s->sm; - struct httpread *hread = e->hread; - int reply_code = 0; - - assert(e == s->current_event); - eloop_cancel_timeout(event_timeout_handler, NULL, e); - - if (en == HTTPREAD_EVENT_FILE_READY) { - if (httpread_hdr_type_get(hread) == HTTPREAD_HDR_TYPE_REPLY) { - reply_code = httpread_reply_code_get(hread); - if (reply_code == HTTP_OK) { - wpa_printf(MSG_DEBUG, - "WPS UPnP: Got event reply OK from " - "%s", e->addr->domain_and_port); - event_delete(e); - goto send_more; - } else { - wpa_printf(MSG_DEBUG, "WPS UPnP: Got event " - "error reply code %d from %s", - reply_code, - e->addr->domain_and_port); - goto bad; - } - } else { - wpa_printf(MSG_DEBUG, "WPS UPnP: Got bogus event " - "response %d from %s", en, - e->addr->domain_and_port); - } - } else { - wpa_printf(MSG_DEBUG, "WPS UPnP: Event response timeout/fail " - "for %s", e->addr->domain_and_port); - goto bad; - } - event_retry(e, 1); - goto send_more; - -send_more: - /* Schedule sending more if there is more to send */ - if (s->event_queue) - event_send_all_later(sm); - return; - -bad: - /* - * If other side doesn't like what we say, forget about them. - * (There is no way to tell other side that we are dropping - * them...). - * Alternately, we could just do event_delete(e) - */ - wpa_printf(MSG_DEBUG, "WPS UPnP: Deleting subscription due to errors"); - subscription_unlink(s); - subscription_destroy(s); -} - - -/* event_send_tx_ready -- actually write event message - * - * Prequisite: subscription socket descriptor has become ready to - * write (because connection to subscriber has been made). - * - * It is also possible that we are called because the connect has failed; - * it is possible to test for this, or we can just go ahead and then - * the write will fail. - */ -static void event_send_tx_ready(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct wps_event_ *e = sock_ctx; - struct subscription *s = e->s; - struct wpabuf *buf; - char *b; - - assert(e == s->current_event); - assert(e->sd == sock); - - buf = wpabuf_alloc(1000 + wpabuf_len(e->data)); - if (buf == NULL) { - event_retry(e, 0); - goto bad; - } - wpabuf_printf(buf, "NOTIFY %s HTTP/1.1\r\n", e->addr->path); - wpabuf_put_str(buf, "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n"); - wpabuf_printf(buf, "HOST: %s\r\n", e->addr->domain_and_port); - wpabuf_put_str(buf, "CONTENT-TYPE: text/xml; charset=\"utf-8\"\r\n" - "NT: upnp:event\r\n" - "NTS: upnp:propchange\r\n"); - wpabuf_put_str(buf, "SID: uuid:"); - b = wpabuf_put(buf, 0); - uuid_bin2str(s->uuid, b, 80); - wpabuf_put(buf, os_strlen(b)); - wpabuf_put_str(buf, "\r\n"); - wpabuf_printf(buf, "SEQ: %u\r\n", e->subscriber_sequence); - wpabuf_printf(buf, "CONTENT-LENGTH: %d\r\n", - (int) wpabuf_len(e->data)); - wpabuf_put_str(buf, "\r\n"); /* terminating empty line */ - wpabuf_put_buf(buf, e->data); - - /* Since the message size is pretty small, we should be - * able to get the operating system to buffer what we give it - * and not have to come back again later to write more... - */ -#if 0 - /* we could: Turn blocking back on? */ - fcntl(e->sd, F_SETFL, 0); -#endif - wpa_printf(MSG_DEBUG, "WPS UPnP: Sending event to %s", - e->addr->domain_and_port); - if (send_wpabuf(e->sd, buf) < 0) { - event_retry(e, 1); - goto bad; - } - wpabuf_free(buf); - buf = NULL; - - if (e->sd_registered) { - e->sd_registered = 0; - eloop_unregister_sock(e->sd, EVENT_TYPE_WRITE); - } - /* Set up to read the reply */ - e->hread = httpread_create(e->sd, event_got_response_handler, - e /* cookie */, - 0 /* no data expected */, - EVENT_TIMEOUT_SEC); - if (e->hread == NULL) { - wpa_printf(MSG_ERROR, "WPS UPnP: httpread_create failed"); - event_retry(e, 0); - goto bad; - } - return; - -bad: - /* Schedule sending more if there is more to send */ - if (s->event_queue) - event_send_all_later(s->sm); - wpabuf_free(buf); -} - - -/* event_send_start -- prepare to send a event message to subscriber - * - * This gets complicated because: - * -- The message is sent via TCP and we have to keep the stream open - * for 30 seconds to get a response... then close it. - * -- But we might have other event happen in the meantime... - * we have to queue them, if we lose them then the subscriber will - * be forced to unsubscribe and subscribe again. - * -- If multiple URLs are provided then we are supposed to try successive - * ones after 30 second timeout. - * -- The URLs might use domain names instead of dotted decimal addresses, - * and resolution of those may cause unwanted sleeping. - * -- Doing the initial TCP connect can take a while, so we have to come - * back after connection and then send the data. - * - * Returns nonzero on error; - * - * Prerequisite: No current event send (s->current_event == NULL) - * and non-empty queue. - */ -static int event_send_start(struct subscription *s) -{ - struct wps_event_ *e; - int itry; - - /* - * Assume we are called ONLY with no current event and ONLY with - * nonempty event queue and ONLY with at least one address to send to. - */ - assert(s->addr_list != NULL); - assert(s->current_event == NULL); - assert(s->event_queue != NULL); - - s->current_event = e = event_dequeue(s); - - /* Use address acc. to no. of retries */ - e->addr = s->addr_list; - for (itry = 0; itry < e->retry; itry++) - e->addr = e->addr->next; - - e->sd = socket(AF_INET, SOCK_STREAM, 0); - if (e->sd < 0) { - event_retry(e, 0); - return -1; - } - /* set non-blocking so we don't sleep waiting for connection */ - if (fcntl(e->sd, F_SETFL, O_NONBLOCK) != 0) { - event_retry(e, 0); - return -1; - } - /* - * Start the connect. It might succeed immediately but more likely will - * return errno EINPROGRESS. - */ - if (connect(e->sd, (struct sockaddr *) &e->addr->saddr, - sizeof(e->addr->saddr))) { - if (errno != EINPROGRESS) { - event_retry(e, 1); - return -1; - } - } - /* Call back when ready for writing (or on failure...). */ - if (eloop_register_sock(e->sd, EVENT_TYPE_WRITE, event_send_tx_ready, - NULL, e)) { - event_retry(e, 0); - return -1; - } - e->sd_registered = 1; - /* Don't wait forever! */ - if (eloop_register_timeout(EVENT_TIMEOUT_SEC, 0, event_timeout_handler, - NULL, e)) { - event_retry(e, 0); - return -1; - } - return 0; -} - - -/* event_send_all_later_handler -- actually send events as needed */ -static void event_send_all_later_handler(void *eloop_data, void *user_ctx) -{ - struct upnp_wps_device_sm *sm = user_ctx; - struct subscription *s; - struct subscription *s_old; - int nerrors = 0; - - sm->event_send_all_queued = 0; - s = sm->subscriptions; - if (s == NULL) - return; - do { - if (s->addr_list == NULL) { - /* if we've given up on all addresses */ - wpa_printf(MSG_DEBUG, "WPS UPnP: Removing " - "subscription with no addresses"); - s_old = s; - s = s_old->next; - subscription_unlink(s_old); - subscription_destroy(s_old); - } else { - if (s->current_event == NULL /* not busy */ && - s->event_queue != NULL /* more to do */) { - if (event_send_start(s)) - nerrors++; - } - s = s->next; - } - } while (sm->subscriptions != NULL && s != sm->subscriptions); - - if (nerrors) { - /* Try again later */ - event_send_all_later(sm); - } -} - - -/* event_send_all_later -- schedule sending events to all subscribers - * that need it. - * This avoids two problems: - * -- After getting a subscription, we should not send the first event - * until after our reply is fully queued to be sent back, - * -- Possible stack depth or infinite recursion issues. - */ -void event_send_all_later(struct upnp_wps_device_sm *sm) -{ - /* - * The exact time in the future isn't too important. Waiting a bit - * might let us do several together. - */ - if (sm->event_send_all_queued) - return; - sm->event_send_all_queued = 1; - eloop_register_timeout(EVENT_DELAY_SECONDS, EVENT_DELAY_MSEC, - event_send_all_later_handler, NULL, sm); -} - - -/* event_send_stop_all -- cleanup */ -void event_send_stop_all(struct upnp_wps_device_sm *sm) -{ - if (sm->event_send_all_queued) - eloop_cancel_timeout(event_send_all_later_handler, NULL, sm); - sm->event_send_all_queued = 0; -} - - -/** - * event_add - Add a new event to a queue - * @s: Subscription - * @data: Event data (is copied; caller retains ownership) - * Returns: 0 on success, 1 on error - */ -int event_add(struct subscription *s, const struct wpabuf *data) -{ - struct wps_event_ *e; - - if (s->n_queue >= MAX_EVENTS_QUEUED) { - wpa_printf(MSG_DEBUG, "WPS UPnP: Too many events queued for " - "subscriber"); - return 1; - } - - e = os_zalloc(sizeof(*e)); - if (e == NULL) - return 1; - e->s = s; - e->sd = -1; - e->data = wpabuf_dup(data); - if (e->data == NULL) { - os_free(e); - return 1; - } - e->subscriber_sequence = s->next_subscriber_sequence++; - if (s->next_subscriber_sequence == 0) - s->next_subscriber_sequence++; - event_enqueue_at_end(s, e); - event_send_all_later(s->sm); - return 0; -} diff --git a/contrib/hostapd/src/wps/wps_upnp_i.h b/contrib/hostapd/src/wps/wps_upnp_i.h deleted file mode 100644 index ba4ec200ff..0000000000 --- a/contrib/hostapd/src/wps/wps_upnp_i.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * UPnP for WPS / internal definitions - * Copyright (c) 2000-2003 Intel Corporation - * Copyright (c) 2006-2007 Sony Corporation - * Copyright (c) 2008-2009 Atheros Communications - * Copyright (c) 2009, Jouni Malinen - * - * See wps_upnp.c for more details on licensing and code history. - */ - -#ifndef WPS_UPNP_I_H -#define WPS_UPNP_I_H - -#define UPNP_MULTICAST_ADDRESS "239.255.255.250" /* for UPnP multicasting */ -#define UPNP_MULTICAST_PORT 1900 /* UDP port to monitor for UPnP */ - -/* min subscribe time per UPnP standard */ -#define UPNP_SUBSCRIBE_SEC_MIN 1800 -/* subscribe time we use */ -#define UPNP_SUBSCRIBE_SEC (UPNP_SUBSCRIBE_SEC_MIN + 1) - -/* "filenames" used in URLs that we service via our "web server": */ -#define UPNP_WPS_DEVICE_XML_FILE "wps_device.xml" -#define UPNP_WPS_SCPD_XML_FILE "wps_scpd.xml" -#define UPNP_WPS_DEVICE_CONTROL_FILE "wps_control" -#define UPNP_WPS_DEVICE_EVENT_FILE "wps_event" - - -struct web_connection; -struct subscription; -struct upnp_wps_device_sm; - - -enum http_reply_code { - HTTP_OK = 200, - HTTP_BAD_REQUEST = 400, - UPNP_INVALID_ACTION = 401, - UPNP_INVALID_ARGS = 402, - HTTP_PRECONDITION_FAILED = 412, - HTTP_INTERNAL_SERVER_ERROR = 500, - HTTP_UNIMPLEMENTED = 501, - UPNP_ACTION_FAILED = 501, - UPNP_ARG_VALUE_INVALID = 600, - UPNP_ARG_VALUE_OUT_OF_RANGE = 601, - UPNP_OUT_OF_MEMORY = 603 -}; - - -enum advertisement_type_enum { - ADVERTISE_UP = 0, - ADVERTISE_DOWN = 1, - MSEARCH_REPLY = 2 -}; - -/* - * Advertisements are broadcast via UDP NOTIFYs, and are also the essence of - * the reply to UDP M-SEARCH requests. This struct handles both cases. - * - * A state machine is needed because a number of variant forms must be sent in - * separate packets and spread out in time to avoid congestion. - */ -struct advertisement_state_machine { - /* double-linked list */ - struct advertisement_state_machine *next; - struct advertisement_state_machine *prev; - struct upnp_wps_device_sm *sm; /* parent */ - enum advertisement_type_enum type; - int state; - int nerrors; - struct sockaddr_in client; /* for M-SEARCH replies */ -}; - - -/* - * An address of a subscriber (who may have multiple addresses). We are - * supposed to send (via TCP) updates to each subscriber, trying each address - * for a subscriber until we find one that seems to work. - */ -struct subscr_addr { - /* double linked list */ - struct subscr_addr *next; - struct subscr_addr *prev; - struct subscription *s; /* parent */ - char *domain_and_port; /* domain and port part of url */ - char *path; /* "filepath" part of url (from "mem") */ - struct sockaddr_in saddr; /* address for doing connect */ -}; - - -/* - * Subscribers to our events are recorded in this struct. This includes a max - * of one outgoing connection (sending an "event message") per subscriber. We - * also have to age out subscribers unless they renew. - */ -struct subscription { - /* double linked list */ - struct subscription *next; - struct subscription *prev; - struct upnp_wps_device_sm *sm; /* parent */ - time_t timeout_time; /* when to age out the subscription */ - unsigned next_subscriber_sequence; /* number our messages */ - /* - * This uuid identifies the subscription and is randomly generated by - * us and given to the subscriber when the subscription is accepted; - * and is then included with each event sent to the subscriber. - */ - u8 uuid[UUID_LEN]; - /* Linked list of address alternatives (rotate through on failure) */ - struct subscr_addr *addr_list; - int n_addr; /* Number of addresses in list */ - struct wps_event_ *event_queue; /* Queued event messages. */ - int n_queue; /* How many events are queued */ - struct wps_event_ *current_event; /* non-NULL if being sent (not in q) - */ -}; - - -/* - * Our instance data corresponding to one WiFi network interface - * (multiple might share the same wired network interface!). - * - * This is known as an opaque struct declaration to users of the WPS UPnP code. - */ -struct upnp_wps_device_sm { - struct upnp_wps_device_ctx *ctx; /* callback table */ - struct wps_context *wps; - void *priv; - char *root_dir; - char *desc_url; - int started; /* nonzero if we are active */ - char *net_if; /* network interface we use */ - char *mac_addr_text; /* mac addr of network i.f. we use */ - u8 mac_addr[ETH_ALEN]; /* mac addr of network i.f. we use */ - char *ip_addr_text; /* IP address of network i.f. we use */ - unsigned ip_addr; /* IP address of network i.f. we use (host order) */ - int multicast_sd; /* send multicast messages over this socket */ - int ssdp_sd; /* receive discovery UPD packets on socket */ - int ssdp_sd_registered; /* nonzero if we must unregister */ - unsigned advertise_count; /* how many advertisements done */ - struct advertisement_state_machine advertisement; - struct advertisement_state_machine *msearch_replies; - int n_msearch_replies; /* no. of pending M-SEARCH replies */ - int web_port; /* our port that others get xml files from */ - int web_sd; /* socket to listen for web requests */ - int web_sd_registered; /* nonzero if we must cancel registration */ - struct web_connection *web_connections; /* linked list */ - int n_web_connections; /* no. of pending web connections */ - /* Note: subscriptions are kept in expiry order */ - struct subscription *subscriptions; /* linked list */ - int n_subscriptions; /* no of current subscriptions */ - int event_send_all_queued; /* if we are scheduled to send events soon - */ - - char *wlanevent; /* the last WLANEvent data */ - - /* FIX: maintain separate structures for each UPnP peer */ - struct upnp_wps_peer peer; -}; - -/* wps_upnp.c */ -void format_date(struct wpabuf *buf); -struct subscription * subscription_start(struct upnp_wps_device_sm *sm, - const char *callback_urls); -struct subscription * subscription_renew(struct upnp_wps_device_sm *sm, - const u8 uuid[UUID_LEN]); -void subscription_unlink(struct subscription *s); -void subscription_destroy(struct subscription *s); -struct subscription * subscription_find(struct upnp_wps_device_sm *sm, - const u8 uuid[UUID_LEN]); -int send_wpabuf(int fd, struct wpabuf *buf); - -/* wps_upnp_ssdp.c */ -void msearchreply_state_machine_stop(struct advertisement_state_machine *a); -int advertisement_state_machine_start(struct upnp_wps_device_sm *sm); -void advertisement_state_machine_stop(struct upnp_wps_device_sm *sm, - int send_byebye); -void ssdp_listener_stop(struct upnp_wps_device_sm *sm); -int ssdp_listener_start(struct upnp_wps_device_sm *sm); -int add_ssdp_network(char *net_if); -int ssdp_open_multicast(struct upnp_wps_device_sm *sm); - -/* wps_upnp_web.c */ -void web_connection_stop(struct web_connection *c); -int web_listener_start(struct upnp_wps_device_sm *sm); -void web_listener_stop(struct upnp_wps_device_sm *sm); - -/* wps_upnp_event.c */ -int event_add(struct subscription *s, const struct wpabuf *data); -void event_delete_all(struct subscription *s); -void event_send_all_later(struct upnp_wps_device_sm *sm); -void event_send_stop_all(struct upnp_wps_device_sm *sm); - -#endif /* WPS_UPNP_I_H */ diff --git a/contrib/hostapd/src/wps/wps_upnp_ssdp.c b/contrib/hostapd/src/wps/wps_upnp_ssdp.c deleted file mode 100644 index c1dc99dbab..0000000000 --- a/contrib/hostapd/src/wps/wps_upnp_ssdp.c +++ /dev/null @@ -1,921 +0,0 @@ -/* - * UPnP SSDP for WPS - * Copyright (c) 2000-2003 Intel Corporation - * Copyright (c) 2006-2007 Sony Corporation - * Copyright (c) 2008-2009 Atheros Communications - * Copyright (c) 2009, Jouni Malinen - * - * See wps_upnp.c for more details on licensing and code history. - */ - -#include "includes.h" - -#include -#include -#include - -#include "common.h" -#include "uuid.h" -#include "eloop.h" -#include "wps.h" -#include "wps_upnp.h" -#include "wps_upnp_i.h" - -#define UPNP_CACHE_SEC (UPNP_CACHE_SEC_MIN + 1) /* cache time we use */ -#define UPNP_CACHE_SEC_MIN 1800 /* min cachable time per UPnP standard */ -#define UPNP_ADVERTISE_REPEAT 2 /* no more than 3 */ -#define MULTICAST_MAX_READ 1600 /* max bytes we'll read for UPD request */ -#define MAX_MSEARCH 20 /* max simultaneous M-SEARCH replies ongoing */ -#define SSDP_TARGET "239.0.0.0" -#define SSDP_NETMASK "255.0.0.0" - - -/* Check tokens for equality, where tokens consist of letters, digits, - * underscore and hyphen, and are matched case insensitive. - */ -static int token_eq(const char *s1, const char *s2) -{ - int c1; - int c2; - int end1 = 0; - int end2 = 0; - for (;;) { - c1 = *s1++; - c2 = *s2++; - if (isalpha(c1) && isupper(c1)) - c1 = tolower(c1); - if (isalpha(c2) && isupper(c2)) - c2 = tolower(c2); - end1 = !(isalnum(c1) || c1 == '_' || c1 == '-'); - end2 = !(isalnum(c2) || c2 == '_' || c2 == '-'); - if (end1 || end2 || c1 != c2) - break; - } - return end1 && end2; /* reached end of both words? */ -} - - -/* Return length of token (see above for definition of token) */ -static int token_length(const char *s) -{ - const char *begin = s; - for (;; s++) { - int c = *s; - int end = !(isalnum(c) || c == '_' || c == '-'); - if (end) - break; - } - return s - begin; -} - - -/* return length of interword separation. - * This accepts only spaces/tabs and thus will not traverse a line - * or buffer ending. - */ -static int word_separation_length(const char *s) -{ - const char *begin = s; - for (;; s++) { - int c = *s; - if (c == ' ' || c == '\t') - continue; - break; - } - return s - begin; -} - - -/* No. of chars through (including) end of line */ -static int line_length(const char *l) -{ - const char *lp = l; - while (*lp && *lp != '\n') - lp++; - if (*lp == '\n') - lp++; - return lp - l; -} - - -/* No. of chars excluding trailing whitespace */ -static int line_length_stripped(const char *l) -{ - const char *lp = l + line_length(l); - while (lp > l && !isgraph(lp[-1])) - lp--; - return lp - l; -} - - -static int str_starts(const char *str, const char *start) -{ - return os_strncmp(str, start, os_strlen(start)) == 0; -} - - -/*************************************************************************** - * Advertisements. - * These are multicast to the world to tell them we are here. - * The individual packets are spread out in time to limit loss, - * and then after a much longer period of time the whole sequence - * is repeated again (for NOTIFYs only). - **************************************************************************/ - -/** - * next_advertisement - Build next message and advance the state machine - * @a: Advertisement state - * @islast: Buffer for indicating whether this is the last message (= 1) - * Returns: The new message (caller is responsible for freeing this) - * - * Note: next_advertisement is shared code with msearchreply_* functions - */ -static struct wpabuf * -next_advertisement(struct advertisement_state_machine *a, int *islast) -{ - struct wpabuf *msg; - char *NTString = ""; - char uuid_string[80]; - - *islast = 0; - uuid_bin2str(a->sm->wps->uuid, uuid_string, sizeof(uuid_string)); - msg = wpabuf_alloc(800); /* more than big enough */ - if (msg == NULL) - goto fail; - switch (a->type) { - case ADVERTISE_UP: - case ADVERTISE_DOWN: - NTString = "NT"; - wpabuf_put_str(msg, "NOTIFY * HTTP/1.1\r\n"); - wpabuf_printf(msg, "HOST: %s:%d\r\n", - UPNP_MULTICAST_ADDRESS, UPNP_MULTICAST_PORT); - wpabuf_printf(msg, "CACHE-CONTROL: max-age=%d\r\n", - UPNP_CACHE_SEC); - wpabuf_printf(msg, "NTS: %s\r\n", - (a->type == ADVERTISE_UP ? - "ssdp:alive" : "ssdp:byebye")); - break; - case MSEARCH_REPLY: - NTString = "ST"; - wpabuf_put_str(msg, "HTTP/1.1 200 OK\r\n"); - wpabuf_printf(msg, "CACHE-CONTROL: max-age=%d\r\n", - UPNP_CACHE_SEC); - - wpabuf_put_str(msg, "DATE: "); - format_date(msg); - wpabuf_put_str(msg, "\r\n"); - - wpabuf_put_str(msg, "EXT:\r\n"); - break; - } - - if (a->type != ADVERTISE_DOWN) { - /* Where others may get our XML files from */ - wpabuf_printf(msg, "LOCATION: http://%s:%d/%s\r\n", - a->sm->ip_addr_text, a->sm->web_port, - UPNP_WPS_DEVICE_XML_FILE); - } - - /* The SERVER line has three comma-separated fields: - * operating system / version - * upnp version - * software package / version - * However, only the UPnP version is really required, the - * others can be place holders... for security reasons - * it is better to NOT provide extra information. - */ - wpabuf_put_str(msg, "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n"); - - switch (a->state / UPNP_ADVERTISE_REPEAT) { - case 0: - wpabuf_printf(msg, "%s: upnp:rootdevice\r\n", NTString); - wpabuf_printf(msg, "USN: uuid:%s::upnp:rootdevice\r\n", - uuid_string); - break; - case 1: - wpabuf_printf(msg, "%s: uuid:%s\r\n", NTString, uuid_string); - wpabuf_printf(msg, "USN: uuid:%s\r\n", uuid_string); - break; - case 2: - wpabuf_printf(msg, "%s: urn:schemas-wifialliance-org:device:" - "WFADevice:1\r\n", NTString); - wpabuf_printf(msg, "USN: uuid:%s::urn:schemas-wifialliance-" - "org:device:WFADevice:1\r\n", uuid_string); - break; - case 3: - wpabuf_printf(msg, "%s: urn:schemas-wifialliance-org:service:" - "WFAWLANConfig:1\r\n", NTString); - wpabuf_printf(msg, "USN: uuid:%s::urn:schemas-wifialliance-" - "org:service:WFAWLANConfig:1\r\n", uuid_string); - break; - } - wpabuf_put_str(msg, "\r\n"); - - if (a->state + 1 >= 4 * UPNP_ADVERTISE_REPEAT) - *islast = 1; - - return msg; - -fail: - wpabuf_free(msg); - return NULL; -} - - -static void advertisement_state_machine_handler(void *eloop_data, - void *user_ctx); - - -/** - * advertisement_state_machine_stop - Stop SSDP advertisements - * @sm: WPS UPnP state machine from upnp_wps_device_init() - * @send_byebye: Send byebye advertisement messages immediately - */ -void advertisement_state_machine_stop(struct upnp_wps_device_sm *sm, - int send_byebye) -{ - struct advertisement_state_machine *a = &sm->advertisement; - int islast = 0; - struct wpabuf *msg; - struct sockaddr_in dest; - - eloop_cancel_timeout(advertisement_state_machine_handler, NULL, sm); - if (!send_byebye || sm->multicast_sd < 0) - return; - - a->type = ADVERTISE_DOWN; - a->state = 0; - a->sm = sm; - - os_memset(&dest, 0, sizeof(dest)); - dest.sin_family = AF_INET; - dest.sin_addr.s_addr = inet_addr(UPNP_MULTICAST_ADDRESS); - dest.sin_port = htons(UPNP_MULTICAST_PORT); - - while (!islast) { - msg = next_advertisement(a, &islast); - if (msg == NULL) - break; - if (sendto(sm->multicast_sd, wpabuf_head(msg), wpabuf_len(msg), - 0, (struct sockaddr *) &dest, sizeof(dest)) < 0) { - wpa_printf(MSG_INFO, "WPS UPnP: Advertisement sendto " - "failed: %d (%s)", errno, strerror(errno)); - } - wpabuf_free(msg); - a->state++; - } -} - - -static void advertisement_state_machine_handler(void *eloop_data, - void *user_ctx) -{ - struct upnp_wps_device_sm *sm = user_ctx; - struct advertisement_state_machine *a = &sm->advertisement; - struct wpabuf *msg; - int next_timeout_msec = 100; - int next_timeout_sec = 0; - struct sockaddr_in dest; - int islast = 0; - - /* - * Each is sent twice (in case lost) w/ 100 msec delay between; - * spec says no more than 3 times. - * One pair for rootdevice, one pair for uuid, and a pair each for - * each of the two urns. - * The entire sequence must be repeated before cache control timeout - * (which is min 1800 seconds), - * recommend random portion of half of the advertised cache control age - * to ensure against loss... perhaps 1800/4 + rand*1800/4 ? - * Delay random interval < 100 msec prior to initial sending. - * TTL of 4 - */ - - wpa_printf(MSG_MSGDUMP, "WPS UPnP: Advertisement state=%d", a->state); - msg = next_advertisement(a, &islast); - if (msg == NULL) - return; - - os_memset(&dest, 0, sizeof(dest)); - dest.sin_family = AF_INET; - dest.sin_addr.s_addr = inet_addr(UPNP_MULTICAST_ADDRESS); - dest.sin_port = htons(UPNP_MULTICAST_PORT); - - if (sendto(sm->multicast_sd, wpabuf_head(msg), wpabuf_len(msg), 0, - (struct sockaddr *) &dest, sizeof(dest)) == -1) { - wpa_printf(MSG_ERROR, "WPS UPnP: Advertisement sendto failed:" - "%d (%s)", errno, strerror(errno)); - next_timeout_msec = 0; - next_timeout_sec = 10; /* ... later */ - } else if (islast) { - a->state = 0; /* wrap around */ - if (a->type == ADVERTISE_DOWN) { - wpa_printf(MSG_DEBUG, "WPS UPnP: ADVERTISE_DOWN->UP"); - a->type = ADVERTISE_UP; - /* do it all over again right away */ - } else { - u16 r; - /* - * Start over again after a long timeout - * (see notes above) - */ - next_timeout_msec = 0; - os_get_random((void *) &r, sizeof(r)); - next_timeout_sec = UPNP_CACHE_SEC / 4 + - (((UPNP_CACHE_SEC / 4) * r) >> 16); - sm->advertise_count++; - wpa_printf(MSG_DEBUG, "WPS UPnP: ADVERTISE_UP (#%u); " - "next in %d sec", - sm->advertise_count, next_timeout_sec); - } - } else { - a->state++; - } - - wpabuf_free(msg); - - eloop_register_timeout(next_timeout_sec, next_timeout_msec, - advertisement_state_machine_handler, NULL, sm); -} - - -/** - * advertisement_state_machine_start - Start SSDP advertisements - * @sm: WPS UPnP state machine from upnp_wps_device_init() - * Returns: 0 on success, -1 on failure - */ -int advertisement_state_machine_start(struct upnp_wps_device_sm *sm) -{ - struct advertisement_state_machine *a = &sm->advertisement; - int next_timeout_msec; - - advertisement_state_machine_stop(sm, 0); - - /* - * Start out advertising down, this automatically switches - * to advertising up which signals our restart. - */ - a->type = ADVERTISE_DOWN; - a->state = 0; - a->sm = sm; - /* (other fields not used here) */ - - /* First timeout should be random interval < 100 msec */ - next_timeout_msec = (100 * (os_random() & 0xFF)) >> 8; - return eloop_register_timeout(0, next_timeout_msec, - advertisement_state_machine_handler, - NULL, sm); -} - - -/*************************************************************************** - * M-SEARCH replies - * These are very similar to the multicast advertisements, with some - * small changes in data content; and they are sent (UDP) to a specific - * unicast address instead of multicast. - * They are sent in response to a UDP M-SEARCH packet. - **************************************************************************/ - -static void msearchreply_state_machine_handler(void *eloop_data, - void *user_ctx); - - -/** - * msearchreply_state_machine_stop - Stop M-SEARCH reply state machine - * @a: Selected advertisement/reply state - */ -void msearchreply_state_machine_stop(struct advertisement_state_machine *a) -{ - struct upnp_wps_device_sm *sm = a->sm; - wpa_printf(MSG_DEBUG, "WPS UPnP: M-SEARCH stop"); - if (a->next == a) { - sm->msearch_replies = NULL; - } else { - if (sm->msearch_replies == a) - sm->msearch_replies = a->next; - a->next->prev = a->prev; - a->prev->next = a->next; - } - os_free(a); - sm->n_msearch_replies--; -} - - -static void msearchreply_state_machine_handler(void *eloop_data, - void *user_ctx) -{ - struct advertisement_state_machine *a = user_ctx; - struct upnp_wps_device_sm *sm = a->sm; - struct wpabuf *msg; - int next_timeout_msec = 100; - int next_timeout_sec = 0; - int islast = 0; - - /* - * Each response is sent twice (in case lost) w/ 100 msec delay - * between; spec says no more than 3 times. - * One pair for rootdevice, one pair for uuid, and a pair each for - * each of the two urns. - */ - - /* TODO: should only send the requested response types */ - - wpa_printf(MSG_MSGDUMP, "WPS UPnP: M-SEARCH reply state=%d (%s:%d)", - a->state, inet_ntoa(a->client.sin_addr), - ntohs(a->client.sin_port)); - msg = next_advertisement(a, &islast); - if (msg == NULL) - return; - - /* - * Send it on the multicast socket to avoid having to set up another - * socket. - */ - if (sendto(sm->multicast_sd, wpabuf_head(msg), wpabuf_len(msg), 0, - (struct sockaddr *) &a->client, sizeof(a->client)) < 0) { - wpa_printf(MSG_DEBUG, "WPS UPnP: M-SEARCH reply sendto " - "errno %d (%s) for %s:%d", - errno, strerror(errno), - inet_ntoa(a->client.sin_addr), - ntohs(a->client.sin_port)); - /* Ignore error and hope for the best */ - } - wpabuf_free(msg); - if (islast) { - wpa_printf(MSG_DEBUG, "WPS UPnP: M-SEARCH reply done"); - msearchreply_state_machine_stop(a); - return; - } - a->state++; - - wpa_printf(MSG_MSGDUMP, "WPS UPnP: M-SEARCH reply in %d.%03d sec", - next_timeout_sec, next_timeout_msec); - eloop_register_timeout(next_timeout_sec, next_timeout_msec, - msearchreply_state_machine_handler, sm, a); -} - - -/** - * msearchreply_state_machine_start - Reply to M-SEARCH discovery request - * @sm: WPS UPnP state machine from upnp_wps_device_init() - * @client: Client address - * @mx: Maximum delay in seconds - * - * Use TTL of 4 (this was done when socket set up). - * A response should be given in randomized portion of min(MX,120) seconds - * - * UPnP-arch-DeviceArchitecture, 1.2.3: - * To be found, a device must send a UDP response to the source IP address and - * port that sent the request to the multicast channel. Devices respond if the - * ST header of the M-SEARCH request is "ssdp:all", "upnp:rootdevice", "uuid:" - * followed by a UUID that exactly matches one advertised by the device. - */ -static void msearchreply_state_machine_start(struct upnp_wps_device_sm *sm, - struct sockaddr_in *client, - int mx) -{ - struct advertisement_state_machine *a; - int next_timeout_sec; - int next_timeout_msec; - - wpa_printf(MSG_DEBUG, "WPS UPnP: M-SEARCH reply start (%d " - "outstanding)", sm->n_msearch_replies); - if (sm->n_msearch_replies >= MAX_MSEARCH) { - wpa_printf(MSG_INFO, "WPS UPnP: Too many outstanding " - "M-SEARCH replies"); - return; - } - - a = os_zalloc(sizeof(*a)); - if (a == NULL) - return; - a->type = MSEARCH_REPLY; - a->state = 0; - a->sm = sm; - os_memcpy(&a->client, client, sizeof(*client)); - /* Wait time depending on MX value */ - next_timeout_msec = (1000 * mx * (os_random() & 0xFF)) >> 8; - next_timeout_sec = next_timeout_msec / 1000; - next_timeout_msec = next_timeout_msec % 1000; - if (eloop_register_timeout(next_timeout_sec, next_timeout_msec, - msearchreply_state_machine_handler, sm, - a)) { - /* No way to recover (from malloc failure) */ - goto fail; - } - /* Remember for future cleanup */ - if (sm->msearch_replies) { - a->next = sm->msearch_replies; - a->prev = a->next->prev; - a->prev->next = a; - a->next->prev = a; - } else { - sm->msearch_replies = a->next = a->prev = a; - } - sm->n_msearch_replies++; - return; - -fail: - wpa_printf(MSG_INFO, "WPS UPnP: M-SEARCH reply failure!"); - eloop_cancel_timeout(msearchreply_state_machine_handler, sm, a); - os_free(a); -} - - -/** - * ssdp_parse_msearch - Process a received M-SEARCH - * @sm: WPS UPnP state machine from upnp_wps_device_init() - * @client: Client address - * @data: NULL terminated M-SEARCH message - * - * Given that we have received a header w/ M-SEARCH, act upon it - * - * Format of M-SEARCH (case insensitive!): - * - * First line must be: - * M-SEARCH * HTTP/1.1 - * Other lines in arbitrary order: - * HOST:239.255.255.250:1900 - * ST: - * MAN:"ssdp:discover" - * MX: - * - * It should be noted that when Microsoft Vista is still learning its IP - * address, it sends out host lines like: HOST:[FF02::C]:1900 - */ -static void ssdp_parse_msearch(struct upnp_wps_device_sm *sm, - struct sockaddr_in *client, const char *data) -{ - const char *start = data; - const char *end; - int got_host = 0; - int got_st = 0, st_match = 0; - int got_man = 0; - int got_mx = 0; - int mx = 0; - - /* - * Skip first line M-SEARCH * HTTP/1.1 - * (perhaps we should check remainder of the line for syntax) - */ - data += line_length(data); - - /* Parse remaining lines */ - for (; *data != '\0'; data += line_length(data)) { - end = data + line_length_stripped(data); - if (token_eq(data, "host")) { - /* The host line indicates who the packet - * is addressed to... but do we really care? - * Note that Microsoft sometimes does funny - * stuff with the HOST: line. - */ -#if 0 /* could be */ - data += token_length(data); - data += word_separation_length(data); - if (*data != ':') - goto bad; - data++; - data += word_separation_length(data); - /* UPNP_MULTICAST_ADDRESS */ - if (!str_starts(data, "239.255.255.250")) - goto bad; - data += os_strlen("239.255.255.250"); - if (*data == ':') { - if (!str_starts(data, ":1900")) - goto bad; - } -#endif /* could be */ - got_host = 1; - continue; - } else if (token_eq(data, "st")) { - /* There are a number of forms; we look - * for one that matches our case. - */ - got_st = 1; - data += token_length(data); - data += word_separation_length(data); - if (*data != ':') - continue; - data++; - data += word_separation_length(data); - if (str_starts(data, "ssdp:all")) { - st_match = 1; - continue; - } - if (str_starts(data, "upnp:rootdevice")) { - st_match = 1; - continue; - } - if (str_starts(data, "uuid:")) { - char uuid_string[80]; - data += os_strlen("uuid:"); - uuid_bin2str(sm->wps->uuid, uuid_string, - sizeof(uuid_string)); - if (str_starts(data, uuid_string)) - st_match = 1; - continue; - } -#if 0 - /* FIX: should we really reply to IGD string? */ - if (str_starts(data, "urn:schemas-upnp-org:device:" - "InternetGatewayDevice:1")) { - st_match = 1; - continue; - } -#endif - if (str_starts(data, "urn:schemas-wifialliance-org:" - "service:WFAWLANConfig:1")) { - st_match = 1; - continue; - } - if (str_starts(data, "urn:schemas-wifialliance-org:" - "device:WFADevice:1")) { - st_match = 1; - continue; - } - continue; - } else if (token_eq(data, "man")) { - data += token_length(data); - data += word_separation_length(data); - if (*data != ':') - continue; - data++; - data += word_separation_length(data); - if (!str_starts(data, "\"ssdp:discover\"")) { - wpa_printf(MSG_DEBUG, "WPS UPnP: Unexpected " - "M-SEARCH man-field"); - goto bad; - } - got_man = 1; - continue; - } else if (token_eq(data, "mx")) { - data += token_length(data); - data += word_separation_length(data); - if (*data != ':') - continue; - data++; - data += word_separation_length(data); - mx = atol(data); - got_mx = 1; - continue; - } - /* ignore anything else */ - } - if (!got_host || !got_st || !got_man || !got_mx || mx < 0) { - wpa_printf(MSG_DEBUG, "WPS UPnP: Invalid M-SEARCH: %d %d %d " - "%d mx=%d", got_host, got_st, got_man, got_mx, mx); - goto bad; - } - if (!st_match) { - wpa_printf(MSG_DEBUG, "WPS UPnP: Ignored M-SEARCH (no ST " - "match)"); - return; - } - if (mx > 120) - mx = 120; /* UPnP-arch-DeviceArchitecture, 1.2.3 */ - msearchreply_state_machine_start(sm, client, mx); - return; - -bad: - wpa_printf(MSG_INFO, "WPS UPnP: Failed to parse M-SEARCH"); - wpa_printf(MSG_MSGDUMP, "WPS UPnP: M-SEARCH data:\n%s", start); -} - - -/* Listening for (UDP) discovery (M-SEARCH) packets */ - -/** - * ssdp_listener_stop - Stop SSDP listered - * @sm: WPS UPnP state machine from upnp_wps_device_init() - * - * This function stops the SSDP listerner that was started by calling - * ssdp_listener_start(). - */ -void ssdp_listener_stop(struct upnp_wps_device_sm *sm) -{ - if (sm->ssdp_sd_registered) { - eloop_unregister_sock(sm->ssdp_sd, EVENT_TYPE_READ); - sm->ssdp_sd_registered = 0; - } - - if (sm->ssdp_sd != -1) { - close(sm->ssdp_sd); - sm->ssdp_sd = -1; - } - - eloop_cancel_timeout(msearchreply_state_machine_handler, sm, - ELOOP_ALL_CTX); -} - - -static void ssdp_listener_handler(int sd, void *eloop_ctx, void *sock_ctx) -{ - struct upnp_wps_device_sm *sm = sock_ctx; - struct sockaddr_in addr; /* client address */ - socklen_t addr_len; - int nread; - char buf[MULTICAST_MAX_READ], *pos; - - addr_len = sizeof(addr); - nread = recvfrom(sm->ssdp_sd, buf, sizeof(buf) - 1, 0, - (struct sockaddr *) &addr, &addr_len); - if (nread <= 0) - return; - buf[nread] = '\0'; /* need null termination for algorithm */ - - if (str_starts(buf, "NOTIFY ")) { - /* - * Silently ignore NOTIFYs to avoid filling debug log with - * unwanted messages. - */ - return; - } - - pos = os_strchr(buf, '\n'); - if (pos) - *pos = '\0'; - wpa_printf(MSG_MSGDUMP, "WPS UPnP: Received SSDP packet from %s:%d: " - "%s", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), buf); - if (pos) - *pos = '\n'; - - /* Parse first line */ - if (os_strncasecmp(buf, "M-SEARCH", os_strlen("M-SEARCH")) == 0 && - !isgraph(buf[strlen("M-SEARCH")])) { - ssdp_parse_msearch(sm, &addr, buf); - return; - } - - /* Ignore anything else */ -} - - -/** - * ssdp_listener_start - Set up for receiving discovery (UDP) packets - * @sm: WPS UPnP state machine from upnp_wps_device_init() - * Returns: 0 on success, -1 on failure - * - * The SSDP listerner is stopped by calling ssdp_listener_stop(). - */ -int ssdp_listener_start(struct upnp_wps_device_sm *sm) -{ - int sd = -1; - struct sockaddr_in addr; - struct ip_mreq mcast_addr; - int on = 1; - /* per UPnP spec, keep IP packet time to live (TTL) small */ - unsigned char ttl = 4; - - sm->ssdp_sd = sd = socket(AF_INET, SOCK_DGRAM, 0); - if (sd < 0) - goto fail; - if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0) - goto fail; - if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) - goto fail; - os_memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_ANY); - addr.sin_port = htons(UPNP_MULTICAST_PORT); - if (bind(sd, (struct sockaddr *) &addr, sizeof(addr))) - goto fail; - os_memset(&mcast_addr, 0, sizeof(mcast_addr)); - mcast_addr.imr_interface.s_addr = htonl(INADDR_ANY); - mcast_addr.imr_multiaddr.s_addr = inet_addr(UPNP_MULTICAST_ADDRESS); - if (setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, - (char *) &mcast_addr, sizeof(mcast_addr))) - goto fail; - if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_TTL, - &ttl, sizeof(ttl))) - goto fail; - if (eloop_register_sock(sd, EVENT_TYPE_READ, ssdp_listener_handler, - NULL, sm)) - goto fail; - sm->ssdp_sd_registered = 1; - return 0; - -fail: - /* Error */ - wpa_printf(MSG_ERROR, "WPS UPnP: ssdp_listener_start failed"); - ssdp_listener_stop(sm); - return -1; -} - - -/** - * add_ssdp_network - Add routing entry for SSDP - * @net_if: Selected network interface name - * Returns: 0 on success, -1 on failure - * - * This function assures that the multicast address will be properly - * handled by Linux networking code (by a modification to routing tables). - * This must be done per network interface. It really only needs to be done - * once after booting up, but it does not hurt to call this more frequently - * "to be safe". - */ -int add_ssdp_network(char *net_if) -{ -#ifdef __linux__ - int ret = -1; - int sock = -1; - struct rtentry rt; - struct sockaddr_in *sin; - - if (!net_if) - goto fail; - - os_memset(&rt, 0, sizeof(rt)); - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock < 0) - goto fail; - - rt.rt_dev = net_if; - sin = aliasing_hide_typecast(&rt.rt_dst, struct sockaddr_in); - sin->sin_family = AF_INET; - sin->sin_port = 0; - sin->sin_addr.s_addr = inet_addr(SSDP_TARGET); - sin = aliasing_hide_typecast(&rt.rt_genmask, struct sockaddr_in); - sin->sin_family = AF_INET; - sin->sin_port = 0; - sin->sin_addr.s_addr = inet_addr(SSDP_NETMASK); - rt.rt_flags = RTF_UP; - if (ioctl(sock, SIOCADDRT, &rt) < 0) { - if (errno == EPERM) { - wpa_printf(MSG_DEBUG, "add_ssdp_network: No " - "permissions to add routing table entry"); - /* Continue to allow testing as non-root */ - } else if (errno != EEXIST) { - wpa_printf(MSG_INFO, "add_ssdp_network() ioctl errno " - "%d (%s)", errno, strerror(errno)); - goto fail; - } - } - - ret = 0; - -fail: - if (sock >= 0) - close(sock); - - return ret; -#else /* __linux__ */ - return 0; -#endif /* __linux__ */ -} - - -/** - * ssdp_open_multicast - Open socket for sending multicast SSDP messages - * @sm: WPS UPnP state machine from upnp_wps_device_init() - * Returns: 0 on success, -1 on failure - */ -int ssdp_open_multicast(struct upnp_wps_device_sm *sm) -{ - int sd = -1; - /* per UPnP-arch-DeviceArchitecture, 1. Discovery, keep IP packet - * time to live (TTL) small */ - unsigned char ttl = 4; - - sm->multicast_sd = sd = socket(AF_INET, SOCK_DGRAM, 0); - if (sd < 0) - return -1; - -#if 0 /* maybe ok if we sometimes block on writes */ - if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0) - return -1; -#endif - - if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, - &sm->ip_addr, sizeof(sm->ip_addr))) - return -1; - if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_TTL, - &ttl, sizeof(ttl))) - return -1; - -#if 0 /* not needed, because we don't receive using multicast_sd */ - { - struct ip_mreq mreq; - mreq.imr_multiaddr.s_addr = inet_addr(UPNP_MULTICAST_ADDRESS); - mreq.imr_interface.s_addr = sm->ip_addr; - wpa_printf(MSG_DEBUG, "WPS UPnP: Multicast addr 0x%x if addr " - "0x%x", - mreq.imr_multiaddr.s_addr, - mreq.imr_interface.s_addr); - if (setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, - sizeof(mreq))) { - wpa_printf(MSG_ERROR, - "WPS UPnP: setsockopt " - "IP_ADD_MEMBERSHIP errno %d (%s)", - errno, strerror(errno)); - return -1; - } - } -#endif /* not needed */ - - /* - * TODO: What about IP_MULTICAST_LOOP? It seems to be on by default? - * which aids debugging I suppose but isn't really necessary? - */ - - return 0; -} diff --git a/contrib/hostapd/src/wps/wps_upnp_web.c b/contrib/hostapd/src/wps/wps_upnp_web.c deleted file mode 100644 index b6374540e9..0000000000 --- a/contrib/hostapd/src/wps/wps_upnp_web.c +++ /dev/null @@ -1,1964 +0,0 @@ -/* - * UPnP WPS Device - Web connections - * Copyright (c) 2000-2003 Intel Corporation - * Copyright (c) 2006-2007 Sony Corporation - * Copyright (c) 2008-2009 Atheros Communications - * Copyright (c) 2009, Jouni Malinen - * - * See wps_upnp.c for more details on licensing and code history. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "base64.h" -#include "eloop.h" -#include "uuid.h" -#include "httpread.h" -#include "wps_i.h" -#include "wps_upnp.h" -#include "wps_upnp_i.h" - -/*************************************************************************** - * Web connections (we serve pages of info about ourselves, handle - * requests, etc. etc.). - **************************************************************************/ - -#define WEB_CONNECTION_TIMEOUT_SEC 30 /* Drop web connection after t.o. */ -#define WEB_CONNECTION_MAX_READ 8000 /* Max we'll read for TCP request */ -#define MAX_WEB_CONNECTIONS 10 /* max simultaneous web connects */ - - -static const char *urn_wfawlanconfig = - "urn:schemas-wifialliance-org:service:WFAWLANConfig:1"; -static const char *http_server_hdr = - "Server: unspecified, UPnP/1.0, unspecified\r\n"; -static const char *http_connection_close = - "Connection: close\r\n"; - -/* - * Incoming web connections are recorded in this struct. - * A web connection is a TCP connection to us, the server; - * it is called a "web connection" because we use http and serve - * data that looks like web pages. - * State information is need to track the connection until we figure - * out what they want and what we want to do about it. - */ -struct web_connection { - /* double linked list */ - struct web_connection *next; - struct web_connection *prev; - struct upnp_wps_device_sm *sm; /* parent */ - int sd; /* socket to read from */ - struct sockaddr_in cli_addr; - int sd_registered; /* nonzero if we must cancel registration */ - struct httpread *hread; /* state machine for reading socket */ - int n_rcvd_data; /* how much data read so far */ - int done; /* internal flag, set when we've finished */ -}; - - -/* - * XML parsing and formatting - * - * XML is a markup language based on unicode; usually (and in our case, - * always!) based on utf-8. utf-8 uses a variable number of bytes per - * character. utf-8 has the advantage that all non-ASCII unicode characters are - * represented by sequences of non-ascii (high bit set) bytes, whereas ASCII - * characters are single ascii bytes, thus we can use typical text processing. - * - * (One other interesting thing about utf-8 is that it is possible to look at - * any random byte and determine if it is the first byte of a character as - * versus a continuation byte). - * - * The base syntax of XML uses a few ASCII punctionation characters; any - * characters that would appear in the payload data are rewritten using - * sequences, e.g., & for ampersand(&) and < for left angle bracket (<). - * Five such escapes total (more can be defined but that does not apply to our - * case). Thus we can safely parse for angle brackets etc. - * - * XML describes tree structures of tagged data, with each element beginning - * with an opening tag with - * matching label. (There is also a self-closing tag