[wpa_supplicant] Cumulative patch from 9fde14607

Changes include required updates to DPP R2.

Bug: 143479699
Test: Device boots up and connects to WPA3/OWE wifi networks, run traffic.
Test: Able to turn on/off softap, associate wifi STA, run traffic.
Test: Regression test Passed (Bug: 143485775)

9fde14607 Allow scans triggered by D-Bus to use MAC address randomization
10f8351d6 D-Bus: Add MAC address randomization endpoints
bb66d4675 Move ownership of MAC address randomization mask to scan params
6c2f70cc6 DPP: Mention ssid and pass parameters for DPP_AUTH_INIT in documentation
1030dec1f JSON: Fix escaping of characters that have MSB=1 with signed char
7800725af dbus: Export OWE capability and OWE BSS key_mgmt
b2ad4e6b2 D-Bus: Fix P2P NULL dereference after interface removal
937644aa2 nl80211: Indicate SUITE_B_192 capa only when CCMP-256/GCMP-256 supported
1b5865a53 SAE: Ignore commit message when waiting for confirm in STA mode
50a2c8c90 Do not indicate possible PSK failure when using SAE
df3b2e22a nl80211: Add STA node details in AP through QCA vendor subcommand
f273b2a5c Add QCA vendor cmd for setting BT coex chain mode
4dc860680 Extend QCA OEM data vendor subcmd to allow use as an event
93a1e275a SAE: Determine H2E vs. looping when restarting SAE auth in AP mode
de580bf6c crypto: Remove unused crypto_bignum_sqrtmod()
9b292a48f SAE: Drop sqrt() alternative from SSWU (H2E)
305369038 wpa_supplicant: Fix arithmetic on void pointer
00ddc1cc2 common: Fix same expression checked twice in fils_key_auth_sk()
327d09aa0 HE: Add 11ax info to ap mode ctrl iface STATUS command
d7678a084 Fix AP Extended Capability length determination
a592f2a9e P2P: Continue listening next request if no post-PD operations
a32acf391 Fix hostapd build with CONFIG_WPA_TRACE but no CONFIG_WPA_TRACE_BFD
b38c8c9cb dbus: Suppress to show NULL string
6807eee9c Interworking: Check NULL string to avoid compiler warning
ec1c0d154 Fix name of DBus interface in defconfig
f73dd0a69 FT-SAE: Add RSNXE into FT MIC
cb9925977 Add RSNXE into (Re)Association Response frames
865721c69 Merge wpa_supplicant and hostapd EAPOL-Key KDE parsers
898b6d58f SAE: Verify that STA negotiated H2E if it claims to support it
74866f537 RSN: Verify RSNXE match between (Re)AssocReq and EAPOL-Key msg 2/4
9981d5bf3 Add RSNXE into AP KDE parser
d3516cad7 Store a copy of Association Request RSNXE in AP mode for later use
6d6c88775 SAE: Add RSNXE in Association Request and EAPOL-Key msg 2/4
8401cdc8d Add RSNXE into IE parser
0b0ed907d WPS: Check SHA256 result success
8dda97c75 QCA vendor command for adding a STA node
b41dc61af Add a new QCA vendor attribute to carry device info for OEM data
bf185bfd5 QCA vendor attributes to indicate BW-based agile spectral capability
1317ea2c0 nl80211: Allow external auth based on SAE/FT-SAE key mgmt
cdb5774f4 FST: Update FST about MAC address change
49e95ee1e AP: Publish only HE capabilities and operation IEs on 6 GHz band
d7c2c5c98 AP: Add initial support for 6 GHz band
a5b2faa71 AP: Add op_class config item to specify 6 GHz channels uniquely
89450024a wpa_supplicant: Pass in operating class for channel validity checks
032c8264d SAE: Check that peer's rejected groups are not enabled in AP
a5dc2a5c1 SAE: H2E version of SAE commit message handling for AP
43b20b437 SAE: Derive H2E PT in AP when starting the AP
444d76f74 SAE: Check that peer's rejected groups are not enabled
cfe1ea5c9 SAE: H2E version of SAE commit message handling for STA
447cd5f2d SAE: Collect list of rejected groups for H2E in STA
05a2fb0d1 SAE: Derive H2E PT in STA before connection
146889e3c RSN: Verify RSNXE match between Beacon/ProbeResp and EAPOL-Key msg 3/4
3134bb13a SAE: Advertise Extended RSN Capabilities when H2E is enabled
293a01f3b SAE: Handle BSS membership selector indication for H2E-only in STA mode
cc0da0ff4 SAE: Advertise BSS membership selector for H2E-only case
85e64e634 SAE: Add sae_pwe configuration parameter for wpa_supplicant
a36e13a7c SAE: Add sae_pwe configuration parameter for hostapd
af4487148 tests: Module test for SAE hash-to-element crypto routines
cf84246eb SAE: Add Rejected Groups element into H2E Commit
efd428529 SAE: Hash algorithm selection for H2E KCK/CN()
aeb022f8e SAE: Implement hash-to-element PT/PWE crypto routines
ecd711407 SAE: Parse Rejected Groups element from H2E SAE commit
86f608486 SAE: Tell sae_parse_commit() whether H2E is used
316156739 SAE: H2E protocol defines
1766e608b wolfSSL: Fix crypto_bignum_sub()
2a1c84f4e crypto: Add more bignum/EC helper functions
9c08bfbd9 DPP: Fix confusing debug entry from Configurator
f7fe05522 SAE: Allow AP behavior for SAE Confirm to be configured
d6a7de60c wpa_cli: Clean up unnecessarily complex CONFIG_MESH use
8b426ab1e wpa_supplicant: Pass AP mode EDMG config to hostapd struct
a82aee1f4 wpa_supplicant: Add support for EDMG channels
35aed771f Indicate EDMG in scan results
f6f8c6ade AP: Show EDMG channel info in STATUS output
241dd76cf hostapd: Check EDMG configuration against capability
dc3457cc4 hostapd: Check usability of EDMG channel
bebd91e9c Add EDMG parameters to set_freq functions
fdd0fef2c EDMG: Helper functions for parameter encoding/checking
e8ff22f47 wpa_supplicant: Add EDMG channel configuration parameters
5c5ff22ef hostapd: Add EDMG channel configuration parameters
dda5d9e31 nl80211: Add support for EDMG channels
a19913c17 IEEE P802.11ay/D4.0 defines for EDMG
c34917403 MBO/OCE: Update disable_mbo_oce flag after association
b719a1568 DPP2: Parse AKM suite selector version of akm node
68fea9603 DPP2: Allow Configurator to use AKM suite selectors in Config Object
52d469de1 DPP2: Support multiple Config Objects in Enrollee
7eb06a336 DPP2: Allow multiple Config Objects to be build on Configurator
99918e069 DPP: Cleaned up netrole indication for config object building
e0d22c842 FILS+FT: Fix MFPR flag in RSNE during FILS exchange for FT
d0a4ed6a1 Allow SAE to be used in wpa_supplicant AP mode
7846e8d60 NetBSD: Fix compile
2e06cef80 MBO/OCE: Work around misbehaving MBO/OCE APs that use RSN without PMF
722c7d195 wlantest: Process VLAN tagged Data frames
83b83b461 nl80211: Migrate to current netlink key message format
7a4b01c87 AP: Provide correct keyid to wpa_send_eapol() for EAPOL-Key msg 3/4
a3ebf7175 BSD: Add support for route(4) message filtering
d9286d099 ACS: Stop before scan if no channels in chanlist are available
f32aa244e DPP: Debug print configRequest bandSupport on Configurator
8f8c423a5 DPP: Add bandSupport JSON array into config request
6d3dc9ba1 mka: Check OLPN for exhaustion on SAKuse decode
84851007d mka: Check OLPN for exhaustion on SAKuse encode
547ba732d mka: Clear out old/latest key values on CHANGE in CP state machine
536a7cfcf mka: Don't set newSAK to FALSE on ABANDON in CP state machine
0fedfba2e mka: Change RECEIVE and RETIRE states to match the standard
3f2641e7a Fix wpa_supplicant build with CONFIG_PCSC=y
5a5639b06 DPP: Allow name and mudurl to be configured for Config Request
3394def5a More consistent SA check for unexpected Data frames
16ef233bf DPP2: Connection status result (Enrollee)
b10e01a79 DPP2: Connection status result (Configurator)
e501a2eb5 DPP2: Connection status result defines
cc8399528 DPP2: Move dpp_build_conf_result() to be within ifdef block
3a6736fe8 DPP2: Fix a memory leak on error path for Config Result
21dc1627f wpa_supplicant: Don't return an error when successfully parsing WMM rules
8214b45ba P2P: Use latest BSS entry if multiple P2P Device Addr matches found
dc6c3be4e wpa_supplicant: Add support for 60 GHz band channels 5 and 6
018edec9b Remove IAPP functionality from hostapd
d86d66dc0 AP: Silently ignore management frame from unexpected source address
a84bf4438 HE: Send the AP's OBSS PD settings to the kernel
262b71eea Sync with mac80211-next.git include/uapi/linux/nl80211.h
8788a314d WPS: Update MAC address on address changes
39042d7f7 os_sleep: Use nanosleep for POSIX versions 2008 and higher
a69742c2f wpa_cli: Do not pick p2p-dev-* interfaces by default
d842e00bd SAE: Return result from confirm CN() operation to the caller
a8bfc6fff FILS: Update connect params after sending connection notification
0df82a3da Correct the type/usage of QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST
6bf6c6fec DPP: Fix hostapd build dependencies for DPP-only build
1eff2e7bf DPP2: Fix wpa_supplicant build dependencies for CONFIG_AP=y build
d2bae5763 DPP: Fix wpa_supplicant build dependencies for DPP-only build
7d2ed8bae Remove CONFIG_IEEE80211W build parameter
022926187 DFS offload: Fix hostapd state and CAC info in STATUS output
4d78ba990 EAP-TEAP peer: Clear Phase 2 EAP method on new Identity exchange
681618246 EAP-TEAP peer: Add support for machine credentials using certificates
ebee8232d Do not try to include net/ethernet.h in MinGW/Windows builds
bf15b1559 Fix Windows error code definition workaround
043de65f1 EAP peer config: Move ocsp param to phase1/phase2
8d76e0ad7 EAP server: Configurable maximum number of authentication message rounds
b99c4cadb EAP peer: Move certificate configuration params into shared struct
6e711e7ab mesh: Do not enable HE on 5 GHz without VHT
0497e4148 HE: Fix HE Capabilities element size
a2e0cc9e0 Add nl80211 vendor ACS trigger reasons related to interference
69e8e7817 HS 2.0: Do not add two copies of OSEN element into Beacon/Probe Resp
a762ba8b1 HS 2.0 AP: Do not mandate PMF for HS 2.0 Indication in open OSU network
e49ce2990 IEEE 802.1X authenticator: Coding style cleanup
31aaddc90 Clean up IEEE 802.1X authentication debug messages for EAP code
71419119f EAP-TEAP peer: Fix protected indication of inner EAP method failure
93cd29d2b EAP-TEAP server: Add support for requiring user and machine credentials
c38c62ff7 wlantest: Derive PMK-R1 and PTK for FT protocol cases
c41936566 EAP-TEAP peer: Add support for machine authentication
c724a0a16 EAP peer: Add a concept of a separate machine credential
9ce3bfaf4 RADIUS server: Abort startup on allocation failures
fa1f0751c RADIUS server: Use struct eap_config to avoid duplicated definitions
a00cb1b1f EAP-TEAP server: Fix eap_teap_pac_no_inner configuration
986033ff3 EAP-TEAP server: Fix Crypto-Binding check in PAC no-inner-auth case
e54cfbb56 EAP-TEAP server: Allow a specific Identity-Type to be requested/required
f186ec54c EAP-TEAP peer: Support Identity-Type TLV
cc661c160 EAP-TEAP: Add parsing and generation routines for Identity-Type TLV
100b2edb2 OpenSSL: Write peer certificate chain details in debug log
7eb157f1e EAP: Increase the maximum number of message exchanges
822e7c66a EAP server: Use struct eap_config to avoid duplicated definitions
62af2b18f EAP-TEAP peer: Support vendor EAP method in Phase 2
aba8dc82f EAP-PEAP server: Support vendor EAP types in Phase 2
357c1062d EAP-FAST peer: Support vendor EAP method in Phase 2
f32f76231 EAP-FAST server: Support vendor EAP types in Phase 2
887d8703b EAP-PEAP peer: Support vendor EAP method in Phase 2
f2ef4f255 EAP peer: Allow VENDOR-TEST method in Phase 2
5ddbd9e96 EAP-TTLS peer: Support vendor EAP method in Phase 2
5e94e7f23 EAP-TTLS server: Support vendor EAP types in Phase 2
5f2301a6d Replace EapType typedef with enum eap_type
76ddfae6e EAP-TEAP server: Testing mechanism for Result TLV in a separate message
4c327146f EAP-TEAP peer: Allow Result TLV without Crypto-Binding TLV
128d46be9 EAP-TEAP: Add parsing of Error TLV
234489efd EAP-TEAP server: Require Intermediate-Result TLV even with Result TLV
0f7c91f2b EAP-TEAP peer: Add Intermediate-Result TLV with Crypto-Binding TLV
a66e53c41 EAP-TEAP: Fix TLS-PRF for TLS ciphersuites that use SHA384
52069c7ef Add TLS-PRF using HMAC with P_SHA384 for TEAP
a647a0ad7 Extend server certificate TOD policy reporting to include TOD-TOFU
346d10cf8 SAE: Conditionally set PMKID while notifying the external auth status
b7cd64876 SAE: Use BSSID stored in ext_auth_bssid for set_pmk
e0b331d89 OWE: Update connect params with new DH attributes to the driver
c574a3ff1 nl80211: Request update connection params only for drivers with SME
528f263c4 FT: Reject over-the-DS response with MFPC=0 if PMF is required
ae05b6a21 RSN: Do not allow connection to proceed without MFPC=1 if PMF required
ded56f2fa FT: Fix MFPR flag in RSNE during FT protocol
0028d627c OCE: Mandate PMF for WPA2 association with OCE AP
84ebc759a HS 2.0: Match credentials based on required_roaming_consortium
d2b208384 SAE: Allow PMKID to be added into Association Request frame following SAE
2ca23faf1 Make wpa_insert_pmkid() more generic
05822609d HE: MCS size is always a minimum of 4 bytes
df4f95998 nl80211: Don't force VHT channel definition with HE
dd0153fce Check for LEAP before doing FT
6126e5f97 Fix a typo in hostapd config documentation
698a0067c Fix check_crl_strict documentation
485dd425b Add QCA vendor command for avoid frequency feature
6ae1247bf Update QCA vendor attributes for 6 GHz band support
aa23ece3d Add QCA vendor channel attribute to restart AP
85508ecf6 Add QCA vendor command to configure ACS policy
2395fdb67 Add QCA vendor attributes to enhance roaming configuration
1425caac2 Rename qca_wlan_vendor_attr_roam_subcmd to represent subcmds
f13119631 Document the attributes used by QCA_NL80211_VENDOR_SUBCMD_ROAM
b0b25c5bb Clear external eapSuccess setting in driver-authorized cases
fa1d5ec18 The master branch is now used for v2.10 development
ca8c2bd28 Preparations for v2.8 release
3263fca28 Set the default scan IEs on interface restart
d776bf8c6 EAP-TEAP peer: Fix fragmentation of final message
1c7e61a35 wolfssl: Avoid void pointer arithmetic
7122a02fa SAE: Fix order_len for FFC groups
422e73d62 DPP: Indicate authentication success on ConfReqRX if needed
d001fe31a OpenSSL: Handle EVP_PKEY_derive() secret_len changes for ECDH
29ef1c5ee DPP: Use a common helper function for ECDH operations
ac734a342 SAE: Fix KCK, PMK, and PMKID derivation for groups 22, 23, 24
c65168ccd OpenSSL: Fix crypto_bignum_to_bin() with padlen == 0
cb28bd52e nl80211: Use separate flag for 4-way handshake offload
6bb11c7a4 EAP-SIM/AKA server: Allow pseudonym/fast reauth to be disabled
c1b236521 EAP-SIM/AKA: Do not allow anonymous@realm "pseudonym" to be cleared
cc2fd9425 D-Bus: Demote timeout/flush messages to MSG_MSGDUMP
3b726df82 nl80211: Missing sysctl flags aren't fatal
f4111ff3d Extra RADIUS request attributes from SQLite
74707def8 Move hostapd_parse_radius_attr() into ap_config.c
1e5ea68d1 mka: Accept last two used MNs in Peers List of a received MKPDU
013686403 P2P: Pass HE flag to GO negotiation result
876c5eaa6 dragonfly: Disable use of groups using Brainpool curves
968520da8 nl80211: Add WMM parameters while updating TDLS peer entry
5a511924b wpa_cli: Add support to process DPP action events in action script
64e37be94 Avoid nested enum wpas_mode declaration to allow C++ compilation
fe2e1edf4 EAP-SIM server: Avoid void pointer arithmetic
cfc9ebea0 EAP-AKA server: Avoid void pointer arithmetic
bd0414043 trace: Avoid void pointer arithmetic
fc03ea2c1 DPP: Avoid void pointer arithmetic
d1b1f9fa9 Report WPA/RSN protocol and AKM suite selector in STA MIB
43aafef8d Add missed wpa_akm_to_suite() selectors
bfb6a482f dragonfly: SAE/EAP-pwd min PWE derivation iteration count to shared code
226da33d7 EAP-pwd peer: Configurable set of groups with reduced default
6a4406c01 Add QCA vendor attributes for ELNA bypass
176c133e9 Add a vendor attribute to configure disconnect IEs
123895228 Add QCA vendor command to support OEM data

Change-Id: Iaa497edcda7c5dcdad19db9d09ab09ef74e508bd
diff --git a/src/eap_server/eap.h b/src/eap_server/eap.h
index a32c883..540b4e7 100644
--- a/src/eap_server/eap.h
+++ b/src/eap_server/eap.h
@@ -108,37 +108,162 @@
 };
 
 struct eap_config {
+	/**
+	 * ssl_ctx - TLS context
+	 *
+	 * This is passed to the EAP server implementation as a callback
+	 * context for TLS operations.
+	 */
 	void *ssl_ctx;
 	void *msg_ctx;
+
+	/**
+	 * eap_sim_db_priv - EAP-SIM/AKA database context
+	 *
+	 * This is passed to the EAP-SIM/AKA server implementation as a
+	 * callback context.
+	 */
 	void *eap_sim_db_priv;
 	Boolean backend_auth;
 	int eap_server;
+
+	/**
+	 * pwd_group - The D-H group assigned for EAP-pwd
+	 *
+	 * If EAP-pwd is not used it can be set to zero.
+	 */
 	u16 pwd_group;
+
+	/**
+	 * pac_opaque_encr_key - PAC-Opaque encryption key for EAP-FAST
+	 *
+	 * This parameter is used to set a key for EAP-FAST to encrypt the
+	 * PAC-Opaque data. It can be set to %NULL if EAP-FAST is not used. If
+	 * set, must point to a 16-octet key.
+	 */
 	u8 *pac_opaque_encr_key;
+
+	/**
+	 * eap_fast_a_id - EAP-FAST authority identity (A-ID)
+	 *
+	 * If EAP-FAST is not used, this can be set to %NULL. In theory, this
+	 * is a variable length field, but due to some existing implementations
+	 * requiring A-ID to be 16 octets in length, it is recommended to use
+	 * that length for the field to provide interoperability with deployed
+	 * peer implementations.
+	 */
 	u8 *eap_fast_a_id;
+
+	/**
+	 * eap_fast_a_id_len - Length of eap_fast_a_id buffer in octets
+	 */
 	size_t eap_fast_a_id_len;
+	/**
+	 * eap_fast_a_id_info - EAP-FAST authority identifier information
+	 *
+	 * This A-ID-Info contains a user-friendly name for the A-ID. For
+	 * example, this could be the enterprise and server names in
+	 * human-readable format. This field is encoded as UTF-8. If EAP-FAST
+	 * is not used, this can be set to %NULL.
+	 */
 	char *eap_fast_a_id_info;
-	int eap_fast_prov;
+
+	/**
+	 * eap_fast_prov - EAP-FAST provisioning modes
+	 *
+	 * 0 = provisioning disabled, 1 = only anonymous provisioning allowed,
+	 * 2 = only authenticated provisioning allowed, 3 = both provisioning
+	 * modes allowed.
+	 */
+	enum {
+		NO_PROV, ANON_PROV, AUTH_PROV, BOTH_PROV
+	} eap_fast_prov;
+
+	/**
+	 * pac_key_lifetime - EAP-FAST PAC-Key lifetime in seconds
+	 *
+	 * This is the hard limit on how long a provisioned PAC-Key can be
+	 * used.
+	 */
 	int pac_key_lifetime;
+
+	/**
+	 * pac_key_refresh_time - EAP-FAST PAC-Key refresh time in seconds
+	 *
+	 * This is a soft limit on the PAC-Key. The server will automatically
+	 * generate a new PAC-Key when this number of seconds (or fewer) of the
+	 * lifetime remains.
+	 */
 	int pac_key_refresh_time;
 	int eap_teap_auth;
 	int eap_teap_pac_no_inner;
+	int eap_teap_separate_result;
+	enum eap_teap_id {
+		EAP_TEAP_ID_ALLOW_ANY = 0,
+		EAP_TEAP_ID_REQUIRE_USER = 1,
+		EAP_TEAP_ID_REQUIRE_MACHINE = 2,
+		EAP_TEAP_ID_REQUEST_USER_ACCEPT_MACHINE = 3,
+		EAP_TEAP_ID_REQUEST_MACHINE_ACCEPT_USER = 4,
+		EAP_TEAP_ID_REQUIRE_USER_AND_MACHINE = 5,
+	} eap_teap_id;
+
+	/**
+	 * eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication
+	 *
+	 * This controls whether the protected success/failure indication
+	 * (AT_RESULT_IND) is used with EAP-SIM and EAP-AKA.
+	 */
 	int eap_sim_aka_result_ind;
+	int eap_sim_id;
+
+	/**
+	 * tnc - Trusted Network Connect (TNC)
+	 *
+	 * This controls whether TNC is enabled and will be required before the
+	 * peer is allowed to connect. Note: This is only used with EAP-TTLS
+	 * and EAP-FAST. If any other EAP method is enabled, the peer will be
+	 * allowed to connect without TNC.
+	 */
 	int tnc;
+
+	/**
+	 * wps - Wi-Fi Protected Setup context
+	 *
+	 * If WPS is used with an external RADIUS server (which is quite
+	 * unlikely configuration), this is used to provide a pointer to WPS
+	 * context data. Normally, this can be set to %NULL.
+	 */
 	struct wps_context *wps;
-	const struct wpabuf *assoc_wps_ie;
-	const struct wpabuf *assoc_p2p_ie;
-	const u8 *peer_addr;
 	int fragment_size;
 
 	int pbc_in_m1;
 
-	const u8 *server_id;
+	/**
+	 * server_id - Server identity
+	 */
+	u8 *server_id;
 	size_t server_id_len;
+
+	/**
+	 * erp - Whether EAP Re-authentication Protocol (ERP) is enabled
+	 *
+	 * This controls whether the authentication server derives ERP key
+	 * hierarchy (rRK and rIK) from full EAP authentication and allows
+	 * these keys to be used to perform ERP to derive rMSK instead of full
+	 * EAP authentication to derive MSK.
+	 */
 	int erp;
 	unsigned int tls_session_lifetime;
 	unsigned int tls_flags;
 
+	unsigned int max_auth_rounds;
+	unsigned int max_auth_rounds_short;
+};
+
+struct eap_session_data {
+	const struct wpabuf *assoc_wps_ie;
+	const struct wpabuf *assoc_p2p_ie;
+	const u8 *peer_addr;
 #ifdef CONFIG_TESTING_OPTIONS
 	u32 tls_test_flags;
 #endif /* CONFIG_TESTING_OPTIONS */
@@ -147,7 +272,8 @@
 
 struct eap_sm * eap_server_sm_init(void *eapol_ctx,
 				   const struct eapol_callbacks *eapol_cb,
-				   struct eap_config *eap_conf);
+				   const struct eap_config *conf,
+				   const struct eap_session_data *sess);
 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);
@@ -164,5 +290,6 @@
 				   const u8 *challenge, const u8 *response);
 void eap_erp_update_identity(struct eap_sm *sm, const u8 *eap, size_t len);
 void eap_user_free(struct eap_user *user);
+void eap_server_config_free(struct eap_config *cfg);
 
 #endif /* EAP_H */
diff --git a/src/eap_server/eap_i.h b/src/eap_server/eap_i.h
index 8e6ac46..44896a6 100644
--- a/src/eap_server/eap_i.h
+++ b/src/eap_server/eap_i.h
@@ -23,7 +23,7 @@
  */
 struct eap_method {
 	int vendor;
-	EapType method;
+	enum eap_type method;
 	const char *name;
 
 	void * (*init)(struct eap_sm *sm);
@@ -128,7 +128,7 @@
 	/* Full authenticator state machine local variables */
 
 	/* Long-term (maintained between packets) */
-	EapType currentMethod;
+	enum eap_type currentMethod;
 	int currentId;
 	enum {
 		METHOD_PROPOSED, METHOD_CONTINUE, METHOD_END
@@ -141,7 +141,7 @@
 	Boolean rxResp;
 	Boolean rxInitiate;
 	int respId;
-	EapType respMethod;
+	enum eap_type respMethod;
 	int respVendor;
 	u32 respVendorMethod;
 	Boolean ignore;
@@ -154,7 +154,7 @@
 	const struct eap_method *m; /* selected EAP method */
 	/* not defined in RFC 4137 */
 	Boolean changed;
-	void *eapol_ctx, *msg_ctx;
+	void *eapol_ctx;
 	const struct eapol_callbacks *eapol_cb;
 	void *eap_method_priv;
 	u8 *identity;
@@ -167,13 +167,12 @@
 	struct eap_user *user;
 	int user_eap_method_index;
 	int init_phase2;
-	void *ssl_ctx;
-	struct eap_sim_db_data *eap_sim_db_priv;
-	Boolean backend_auth;
+	const struct eap_config *cfg;
+	struct eap_config cfg_buf;
 	Boolean update_user;
-	int eap_server;
 
-	int num_rounds;
+	unsigned int num_rounds;
+	unsigned int num_rounds_short;
 	enum {
 		METHOD_PENDING_NONE, METHOD_PENDING_WAIT, METHOD_PENDING_CONT
 	} method_pending;
@@ -181,21 +180,6 @@
 	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_teap_auth;
-	int eap_teap_pac_no_inner;
-	int eap_sim_aka_result_ind;
-	int tnc;
-	u16 pwd_group;
-	struct wps_context *wps;
 	struct wpabuf *assoc_wps_ie;
 	struct wpabuf *assoc_p2p_ie;
 
@@ -203,19 +187,8 @@
 
 	u8 peer_addr[ETH_ALEN];
 
-	/* Fragmentation size for EAP method init() handler */
-	int fragment_size;
-
-	int pbc_in_m1;
-
-	const u8 *server_id;
-	size_t server_id_len;
-
 	Boolean initiate_reauth_start_sent;
 	Boolean try_initiate_reauth;
-	int erp;
-	unsigned int tls_session_lifetime;
-	unsigned int tls_flags;
 
 #ifdef CONFIG_TESTING_OPTIONS
 	u32 tls_test_flags;
diff --git a/src/eap_server/eap_methods.h b/src/eap_server/eap_methods.h
index fdbea7a..ad60700 100644
--- a/src/eap_server/eap_methods.h
+++ b/src/eap_server/eap_methods.h
@@ -12,14 +12,15 @@
 #include "eap_common/eap_defs.h"
 
 const struct eap_method * eap_server_get_eap_method(int vendor,
-						    EapType method);
+						    enum eap_type method);
 struct eap_method * eap_server_method_alloc(int version, int vendor,
-					    EapType method, const char *name);
+					    enum eap_type method,
+					    const char *name);
 int eap_server_method_register(struct eap_method *method);
 
-EapType eap_server_get_type(const char *name, int *vendor);
+enum eap_type eap_server_get_type(const char *name, int *vendor);
 void eap_server_unregister_methods(void);
-const char * eap_server_get_name(int vendor, EapType type);
+const char * eap_server_get_name(int vendor, enum eap_type type);
 
 /* EAP server method registration calls for statically linked in methods */
 int eap_server_identity_register(void);
diff --git a/src/eap_server/eap_server.c b/src/eap_server/eap_server.c
index 724ec15..34ce239 100644
--- a/src/eap_server/eap_server.c
+++ b/src/eap_server/eap_server.c
@@ -23,8 +23,6 @@
 #define STATE_MACHINE_DATA struct eap_sm
 #define STATE_MACHINE_DEBUG_PREFIX "EAP"
 
-#define EAP_MAX_AUTH_ROUNDS 50
-
 /* EAP state machines are described in RFC 4137 */
 
 static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount,
@@ -37,9 +35,10 @@
 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 enum eap_type 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 Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, enum eap_type method);
 
 
 static int eap_get_erp_send_reauth_start(struct eap_sm *sm)
@@ -94,7 +93,7 @@
 	}
 
 	msg = eap_msg_alloc(EAP_VENDOR_IETF,
-			    (EapType) EAP_ERP_TYPE_REAUTH_START, plen,
+			    (enum eap_type) EAP_ERP_TYPE_REAUTH_START, plen,
 			    EAP_CODE_INITIATE, id);
 	if (msg == NULL)
 		return NULL;
@@ -215,6 +214,7 @@
 {
 	SM_ENTRY(EAP, DISABLED);
 	sm->num_rounds = 0;
+	sm->num_rounds_short = 0;
 }
 
 
@@ -222,7 +222,7 @@
 {
 	SM_ENTRY(EAP, INITIALIZE);
 
-	if (sm->eap_if.eapRestart && !sm->eap_server && sm->identity) {
+	if (sm->eap_if.eapRestart && !sm->cfg->eap_server && sm->identity) {
 		/*
 		 * Need to allow internal Identity method to be used instead
 		 * of passthrough at the beginning of reauthentication.
@@ -256,7 +256,7 @@
 	sm->m = NULL;
 	sm->user_eap_method_index = 0;
 
-	if (sm->backend_auth) {
+	if (sm->cfg->backend_auth) {
 		sm->currentMethod = EAP_TYPE_NONE;
 		/* parse rxResp, respId, respMethod */
 		eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
@@ -265,9 +265,10 @@
 		}
 	}
 	sm->num_rounds = 0;
+	sm->num_rounds_short = 0;
 	sm->method_pending = METHOD_PENDING_NONE;
 
-	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
+	wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
 		MACSTR, MAC2STR(sm->peer_addr));
 }
 
@@ -299,7 +300,7 @@
 		}
 	}
 
-	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
+	wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
 		"method=%u", sm->currentMethod);
 }
 
@@ -324,7 +325,7 @@
 			sm->eap_if.eapReq = TRUE;
 	}
 
-	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_RETRANSMIT MACSTR,
+	wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_RETRANSMIT MACSTR,
 		MAC2STR(sm->peer_addr));
 }
 
@@ -336,6 +337,10 @@
 	/* parse rxResp, respId, respMethod */
 	eap_sm_parseEapResp(sm, sm->eap_if.eapRespData);
 	sm->num_rounds++;
+	if (!sm->eap_if.eapRespData || wpabuf_len(sm->eap_if.eapRespData) < 20)
+		sm->num_rounds_short++;
+	else
+		sm->num_rounds_short = 0;
 }
 
 
@@ -353,6 +358,8 @@
 
 	sm->retransCount = 0;
 	if (sm->eap_if.eapReqData) {
+		if (wpabuf_len(sm->eap_if.eapReqData) >= 20)
+			sm->num_rounds_short = 0;
 		if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0)
 		{
 			sm->eap_if.eapResp = FALSE;
@@ -529,7 +536,7 @@
 				    sm->eap_if.eapSessionId,
 				    sm->eap_if.eapSessionIdLen);
 		}
-		if (sm->erp && sm->m->get_emsk && sm->eap_if.eapSessionId)
+		if (sm->cfg->erp && sm->m->get_emsk && sm->eap_if.eapSessionId)
 			eap_server_erp_init(sm);
 		sm->methodState = METHOD_END;
 	} else {
@@ -541,7 +548,7 @@
 SM_STATE(EAP, PROPOSE_METHOD)
 {
 	int vendor;
-	EapType type;
+	enum eap_type type;
 
 	SM_ENTRY(EAP, PROPOSE_METHOD);
 
@@ -579,7 +586,7 @@
 	else
 		sm->methodState = METHOD_PROPOSED;
 
-	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
+	wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
 		"vendor=%u method=%u", vendor, sm->currentMethod);
 	eap_log_msg(sm, "Propose EAP method vendor=%u method=%u",
 		    vendor, sm->currentMethod);
@@ -635,8 +642,8 @@
 
 	sm->eap_if.eapTimeout = TRUE;
 
-	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TIMEOUT_FAILURE MACSTR,
-		MAC2STR(sm->peer_addr));
+	wpa_msg(sm->cfg->msg_ctx, MSG_INFO,
+		WPA_EVENT_EAP_TIMEOUT_FAILURE MACSTR, MAC2STR(sm->peer_addr));
 }
 
 
@@ -650,7 +657,7 @@
 	sm->lastReqData = NULL;
 	sm->eap_if.eapFail = TRUE;
 
-	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
+	wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
 		MACSTR, MAC2STR(sm->peer_addr));
 }
 
@@ -667,7 +674,7 @@
 		sm->eap_if.eapKeyAvailable = TRUE;
 	sm->eap_if.eapSuccess = TRUE;
 
-	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
+	wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
 		MACSTR, MAC2STR(sm->peer_addr));
 }
 
@@ -720,7 +727,8 @@
 	plen = 1 + 2 + 2 + os_strlen(nai);
 	if (hash_len)
 		plen += 1 + hash_len;
-	msg = eap_msg_alloc(EAP_VENDOR_IETF, (EapType) EAP_ERP_TYPE_REAUTH,
+	msg = eap_msg_alloc(EAP_VENDOR_IETF,
+			    (enum eap_type) EAP_ERP_TYPE_REAUTH,
 			    plen, EAP_CODE_FINISH, id);
 	if (msg == NULL)
 		return;
@@ -753,7 +761,7 @@
 
 	if ((flags & 0x80) || !erp) {
 		sm->eap_if.eapFail = TRUE;
-		wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
+		wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
 			MACSTR, MAC2STR(sm->peer_addr));
 		return;
 	}
@@ -781,7 +789,7 @@
 			sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen);
 	sm->eap_if.eapSuccess = TRUE;
 
-	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
+	wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
 		MACSTR, MAC2STR(sm->peer_addr));
 }
 
@@ -805,7 +813,8 @@
 
 	sm->rxInitiate = FALSE;
 
-	pos = eap_hdr_validate(EAP_VENDOR_IETF, (EapType) EAP_ERP_TYPE_REAUTH,
+	pos = eap_hdr_validate(EAP_VENDOR_IETF,
+			       (enum eap_type) EAP_ERP_TYPE_REAUTH,
 			       sm->eap_if.eapRespData, &len);
 	if (pos == NULL) {
 		wpa_printf(MSG_INFO, "EAP-Initiate: Invalid frame");
@@ -852,7 +861,7 @@
 	os_memcpy(nai, parse.keyname, parse.keyname_len);
 	nai[parse.keyname_len] = '\0';
 
-	if (!sm->eap_server) {
+	if (!sm->cfg->eap_server) {
 		/*
 		 * In passthrough case, EAP-Initiate/Re-auth replaces
 		 * EAP Identity exchange. Use keyName-NAI as the user identity
@@ -1015,7 +1024,7 @@
 			sm->eap_if.eapReq = TRUE;
 	}
 
-	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_RETRANSMIT2 MACSTR,
+	wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_RETRANSMIT2 MACSTR,
 		MAC2STR(sm->peer_addr));
 }
 
@@ -1108,8 +1117,8 @@
 
 	sm->eap_if.eapTimeout = TRUE;
 
-	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TIMEOUT_FAILURE2 MACSTR,
-		MAC2STR(sm->peer_addr));
+	wpa_msg(sm->cfg->msg_ctx, MSG_INFO,
+		WPA_EVENT_EAP_TIMEOUT_FAILURE2 MACSTR, MAC2STR(sm->peer_addr));
 }
 
 
@@ -1120,7 +1129,7 @@
 	eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData);
 	sm->eap_if.eapFail = TRUE;
 
-	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE2 MACSTR,
+	wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE2 MACSTR,
 		MAC2STR(sm->peer_addr));
 }
 
@@ -1149,7 +1158,7 @@
 	 */
 	sm->start_reauth = TRUE;
 
-	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS2 MACSTR,
+	wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS2 MACSTR,
 		MAC2STR(sm->peer_addr));
 }
 
@@ -1160,17 +1169,26 @@
 		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) {
+	else if (sm->num_rounds > sm->cfg->max_auth_rounds) {
+		if (sm->num_rounds == sm->cfg->max_auth_rounds + 1) {
 			wpa_printf(MSG_DEBUG, "EAP: more than %d "
 				   "authentication rounds - abort",
-				   EAP_MAX_AUTH_ROUNDS);
+				   sm->cfg->max_auth_rounds);
 			sm->num_rounds++;
 			SM_ENTER_GLOBAL(EAP, FAILURE);
 		}
+	} else if (sm->num_rounds_short > sm->cfg->max_auth_rounds_short) {
+		if (sm->num_rounds_short ==
+		    sm->cfg->max_auth_rounds_short + 1) {
+			wpa_printf(MSG_DEBUG,
+				   "EAP: more than %d authentication rounds (short) - abort",
+				   sm->cfg->max_auth_rounds_short);
+			sm->num_rounds_short++;
+			SM_ENTER_GLOBAL(EAP, FAILURE);
+		}
 	} else switch (sm->EAP_state) {
 	case EAP_INITIALIZE:
-		if (sm->backend_auth) {
+		if (sm->cfg->backend_auth) {
 			if (!sm->rxResp)
 				SM_ENTER(EAP, SELECT_ACTION);
 			else if (sm->rxResp &&
@@ -1333,7 +1351,7 @@
 		else if (sm->decision == DECISION_INITIATE_REAUTH_START)
 			SM_ENTER(EAP, INITIATE_REAUTH_START);
 #ifdef CONFIG_ERP
-		else if (sm->eap_server && sm->erp && sm->rxInitiate)
+		else if (sm->cfg->eap_server && sm->cfg->erp && sm->rxInitiate)
 			SM_ENTER(EAP, INITIATE_RECEIVED);
 #endif /* CONFIG_ERP */
 		else
@@ -1343,7 +1361,7 @@
 		SM_ENTER(EAP, SEND_REQUEST);
 		break;
 	case EAP_INITIATE_RECEIVED:
-		if (!sm->eap_server)
+		if (!sm->cfg->eap_server)
 			SM_ENTER(EAP, SELECT_ACTION);
 		break;
 	case EAP_TIMEOUT_FAILURE:
@@ -1669,9 +1687,9 @@
 }
 
 
-static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor)
+static enum eap_type eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor)
 {
-	EapType next;
+	enum eap_type next;
 	int idx = sm->user_eap_method_index;
 
 	/* In theory, there should be no problems with starting
@@ -1703,7 +1721,7 @@
 
 static int eap_sm_Policy_getDecision(struct eap_sm *sm)
 {
-	if (!sm->eap_server && sm->identity && !sm->start_reauth) {
+	if (!sm->cfg->eap_server && sm->identity && !sm->start_reauth) {
 		wpa_printf(MSG_DEBUG, "EAP: getDecision: -> PASSTHROUGH");
 		return DECISION_PASSTHROUGH;
 	}
@@ -1783,7 +1801,7 @@
 }
 
 
-static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method)
+static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, enum eap_type method)
 {
 	return method == EAP_TYPE_IDENTITY ? TRUE : FALSE;
 }
@@ -1834,7 +1852,8 @@
  */
 struct eap_sm * eap_server_sm_init(void *eapol_ctx,
 				   const struct eapol_callbacks *eapol_cb,
-				   struct eap_config *conf)
+				   const struct eap_config *conf,
+				   const struct eap_session_data *sess)
 {
 	struct eap_sm *sm;
 
@@ -1844,53 +1863,15 @@
 	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->msg_ctx = conf->msg_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_teap_auth = conf->eap_teap_auth;
-	sm->eap_teap_pac_no_inner = conf->eap_teap_pac_no_inner;
-	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);
-	if (conf->assoc_p2p_ie)
-		sm->assoc_p2p_ie = wpabuf_dup(conf->assoc_p2p_ie);
-	if (conf->peer_addr)
-		os_memcpy(sm->peer_addr, conf->peer_addr, ETH_ALEN);
-	sm->fragment_size = conf->fragment_size;
-	sm->pwd_group = conf->pwd_group;
-	sm->pbc_in_m1 = conf->pbc_in_m1;
-	sm->server_id = conf->server_id;
-	sm->server_id_len = conf->server_id_len;
-	sm->erp = conf->erp;
-	sm->tls_session_lifetime = conf->tls_session_lifetime;
-	sm->tls_flags = conf->tls_flags;
-
+	sm->cfg = conf;
+	if (sess->assoc_wps_ie)
+		sm->assoc_wps_ie = wpabuf_dup(sess->assoc_wps_ie);
+	if (sess->assoc_p2p_ie)
+		sm->assoc_p2p_ie = wpabuf_dup(sess->assoc_p2p_ie);
+	if (sess->peer_addr)
+		os_memcpy(sm->peer_addr, sess->peer_addr, ETH_ALEN);
 #ifdef CONFIG_TESTING_OPTIONS
-	sm->tls_test_flags = conf->tls_test_flags;
+	sm->tls_test_flags = sess->tls_test_flags;
 #endif /* CONFIG_TESTING_OPTIONS */
 
 	wpa_printf(MSG_DEBUG, "EAP: Server state machine created");
@@ -1920,9 +1901,6 @@
 	wpabuf_free(sm->eap_if.eapRespData);
 	os_free(sm->identity);
 	os_free(sm->serial_num);
-	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);
 	bin_clear_free(sm->eap_if.aaaEapKeyData, sm->eap_if.aaaEapKeyDataLen);
@@ -2112,3 +2090,15 @@
 		   source, user, hex_challenge, hex_response);
 }
 #endif /* CONFIG_TESTING_OPTIONS */
+
+
+void eap_server_config_free(struct eap_config *cfg)
+{
+	if (!cfg)
+		return;
+	os_free(cfg->pac_opaque_encr_key);
+	os_free(cfg->eap_fast_a_id);
+	os_free(cfg->eap_fast_a_id_info);
+	os_free(cfg->server_id);
+	os_free(cfg);
+}
diff --git a/src/eap_server/eap_server_aka.c b/src/eap_server/eap_server_aka.c
index 5f6a1b3..22dd965 100644
--- a/src/eap_server/eap_server_aka.c
+++ b/src/eap_server/eap_server_aka.c
@@ -100,7 +100,7 @@
 		return 0;
 
 	wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth username '%s'", username);
-	data->reauth = eap_sim_db_get_reauth_entry(sm->eap_sim_db_priv,
+	data->reauth = eap_sim_db_get_reauth_entry(sm->cfg->eap_sim_db_priv,
 						   username);
 	if (data->reauth == NULL) {
 		wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown reauth identity - "
@@ -157,7 +157,7 @@
 		wpa_printf(MSG_DEBUG, "EAP-AKA: Pseudonym username '%s'",
 			   username);
 		permanent = eap_sim_db_get_permanent(
-			sm->eap_sim_db_priv, username);
+			sm->cfg->eap_sim_db_priv, username);
 		if (permanent == NULL) {
 			os_free(username);
 			wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown pseudonym "
@@ -182,7 +182,7 @@
 {
 	struct eap_aka_data *data;
 
-	if (sm->eap_sim_db_priv == NULL) {
+	if (!sm->cfg->eap_sim_db_priv) {
 		wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured");
 		return NULL;
 	}
@@ -208,7 +208,7 @@
 	/* TODO: make ANID configurable; see 3GPP TS 24.302 */
 	char *network_name = "WLAN";
 
-	if (sm->eap_sim_db_priv == NULL) {
+	if (sm->cfg->eap_sim_db_priv == NULL) {
 		wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured");
 		return NULL;
 	}
@@ -393,10 +393,13 @@
 			      const u8 *nonce_s)
 {
 	os_free(data->next_pseudonym);
-	if (nonce_s == NULL) {
+	if (!(sm->cfg->eap_sim_id & 0x01)) {
+		/* Use of pseudonyms disabled in configuration */
+		data->next_pseudonym = NULL;
+	} else if (!nonce_s) {
 		data->next_pseudonym =
 			eap_sim_db_get_next_pseudonym(
-				sm->eap_sim_db_priv,
+				sm->cfg->eap_sim_db_priv,
 				data->eap_method == EAP_TYPE_AKA_PRIME ?
 				EAP_SIM_DB_AKA_PRIME : EAP_SIM_DB_AKA);
 	} else {
@@ -404,10 +407,13 @@
 		data->next_pseudonym = NULL;
 	}
 	os_free(data->next_reauth_id);
-	if (data->counter <= EAP_AKA_MAX_FAST_REAUTHS) {
+	if (!(sm->cfg->eap_sim_id & 0x02)) {
+		/* Use of fast reauth disabled in configuration */
+		data->next_reauth_id = NULL;
+	} else if (data->counter <= EAP_AKA_MAX_FAST_REAUTHS) {
 		data->next_reauth_id =
 			eap_sim_db_get_next_reauth_id(
-				sm->eap_sim_db_priv,
+				sm->cfg->eap_sim_db_priv,
 				data->eap_method == EAP_TYPE_AKA_PRIME ?
 				EAP_SIM_DB_AKA_PRIME : EAP_SIM_DB_AKA);
 	} else {
@@ -499,7 +505,7 @@
 
 	eap_aka_add_checkcode(data, msg);
 
-	if (sm->eap_sim_aka_result_ind) {
+	if (sm->cfg->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);
 	}
@@ -576,7 +582,7 @@
 
 	eap_aka_add_checkcode(data, msg);
 
-	if (sm->eap_sim_aka_result_ind) {
+	if (sm->cfg->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);
 	}
@@ -589,7 +595,7 @@
 	 * Session-Id calculation after receiving response from the peer and
 	 * after all other checks pass. */
 	os_memcpy(data->reauth_mac,
-		  (wpabuf_head_u8(buf) + wpabuf_len(buf) - EAP_SIM_MAC_LEN),
+		  wpabuf_head_u8(buf) + wpabuf_len(buf) - EAP_SIM_MAC_LEN,
 		  EAP_SIM_MAC_LEN);
 
 	return buf;
@@ -761,7 +767,7 @@
 		wpa_printf(MSG_DEBUG, "EAP-AKA: Pseudonym username '%s'",
 			   username);
 		permanent = eap_sim_db_get_permanent(
-			sm->eap_sim_db_priv, username);
+			sm->cfg->eap_sim_db_priv, username);
 		os_free(username);
 		if (permanent == NULL) {
 			wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown pseudonym "
@@ -797,7 +803,7 @@
 	size_t identity_len;
 	int res;
 
-	res = eap_sim_db_get_aka_auth(sm->eap_sim_db_priv, data->permanent,
+	res = eap_sim_db_get_aka_auth(sm->cfg->eap_sim_db_priv, data->permanent,
 				      data->rand, data->autn, data->ik,
 				      data->ck, data->res, &data->res_len, sm);
 	if (res == EAP_SIM_DB_PENDING) {
@@ -992,7 +998,7 @@
 
 	wpa_printf(MSG_DEBUG, "EAP-AKA: Challenge response includes the "
 		   "correct AT_MAC");
-	if (sm->eap_sim_aka_result_ind && attr->result_ind) {
+	if (sm->cfg->eap_sim_aka_result_ind && attr->result_ind) {
 		data->use_result_ind = 1;
 		data->notification = EAP_SIM_SUCCESS;
 		eap_aka_state(data, NOTIFICATION);
@@ -1000,14 +1006,15 @@
 		eap_aka_state(data, SUCCESS);
 
 	if (data->next_pseudonym) {
-		eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, data->permanent,
+		eap_sim_db_add_pseudonym(sm->cfg->eap_sim_db_priv,
+					 data->permanent,
 					 data->next_pseudonym);
 		data->next_pseudonym = NULL;
 	}
 	if (data->next_reauth_id) {
 		if (data->eap_method == EAP_TYPE_AKA_PRIME) {
 #ifdef EAP_SERVER_AKA_PRIME
-			eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
+			eap_sim_db_add_reauth_prime(sm->cfg->eap_sim_db_priv,
 						    data->permanent,
 						    data->next_reauth_id,
 						    data->counter + 1,
@@ -1015,7 +1022,7 @@
 						    data->k_re);
 #endif /* EAP_SERVER_AKA_PRIME */
 		} else {
-			eap_sim_db_add_reauth(sm->eap_sim_db_priv,
+			eap_sim_db_add_reauth(sm->cfg->eap_sim_db_priv,
 					      data->permanent,
 					      data->next_reauth_id,
 					      data->counter + 1,
@@ -1045,7 +1052,7 @@
 	 * 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, data->permanent,
+	    eap_sim_db_resynchronize(sm->cfg->eap_sim_db_priv, data->permanent,
 				     attr->auts, data->rand)) {
 		wpa_printf(MSG_WARNING, "EAP-AKA: Resynchronization failed");
 		data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
@@ -1112,7 +1119,7 @@
 		return;
 	}
 
-	if (sm->eap_sim_aka_result_ind && attr->result_ind) {
+	if (sm->cfg->eap_sim_aka_result_ind && attr->result_ind) {
 		data->use_result_ind = 1;
 		data->notification = EAP_SIM_SUCCESS;
 		eap_aka_state(data, NOTIFICATION);
@@ -1122,7 +1129,7 @@
 	if (data->next_reauth_id) {
 		if (data->eap_method == EAP_TYPE_AKA_PRIME) {
 #ifdef EAP_SERVER_AKA_PRIME
-			eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
+			eap_sim_db_add_reauth_prime(sm->cfg->eap_sim_db_priv,
 						    data->permanent,
 						    data->next_reauth_id,
 						    data->counter + 1,
@@ -1130,7 +1137,7 @@
 						    data->k_re);
 #endif /* EAP_SERVER_AKA_PRIME */
 		} else {
-			eap_sim_db_add_reauth(sm->eap_sim_db_priv,
+			eap_sim_db_add_reauth(sm->cfg->eap_sim_db_priv,
 					      data->permanent,
 					      data->next_reauth_id,
 					      data->counter + 1,
@@ -1138,7 +1145,8 @@
 		}
 		data->next_reauth_id = NULL;
 	} else {
-		eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
+		eap_sim_db_remove_reauth(sm->cfg->eap_sim_db_priv,
+					 data->reauth);
 		data->reauth = NULL;
 	}
 
@@ -1147,7 +1155,7 @@
 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);
+	eap_sim_db_remove_reauth(sm->cfg->eap_sim_db_priv, data->reauth);
 	data->reauth = NULL;
 	os_free(decrypted);
 }
diff --git a/src/eap_server/eap_server_eke.c b/src/eap_server/eap_server_eke.c
index 71580bf..71fab96 100644
--- a/src/eap_server/eap_server_eke.c
+++ b/src/eap_server/eap_server_eke.c
@@ -84,11 +84,11 @@
 	eap_eke_state(data, IDENTITY);
 
 	data->serverid_type = EAP_EKE_ID_OPAQUE;
-	for (i = 0; i < sm->server_id_len; i++) {
-		if (sm->server_id[i] == '.' &&
+	for (i = 0; i < sm->cfg->server_id_len; i++) {
+		if (sm->cfg->server_id[i] == '.' &&
 		    data->serverid_type == EAP_EKE_ID_OPAQUE)
 			data->serverid_type = EAP_EKE_ID_FQDN;
-		if (sm->server_id[i] == '@')
+		if (sm->cfg->server_id[i] == '@')
 			data->serverid_type = EAP_EKE_ID_NAI;
 	}
 
@@ -186,7 +186,7 @@
 
 	wpa_printf(MSG_DEBUG, "EAP-EKE: Request/Identity");
 
-	plen = 2 + 4 * 4 + 1 + sm->server_id_len;
+	plen = 2 + 4 * 4 + 1 + sm->cfg->server_id_len;
 	msg = eap_eke_build_msg(data, id, plen, EAP_EKE_ID);
 	if (msg == NULL)
 		return NULL;
@@ -223,7 +223,7 @@
 
 	/* Server IDType + Identity */
 	wpabuf_put_u8(msg, data->serverid_type);
-	wpabuf_put_data(msg, sm->server_id, sm->server_id_len);
+	wpabuf_put_data(msg, sm->cfg->server_id, sm->cfg->server_id_len);
 
 	wpabuf_free(data->msgs);
 	data->msgs = wpabuf_dup(msg);
@@ -252,7 +252,7 @@
 
 	if (eap_eke_derive_key(&data->sess, sm->user->password,
 			       sm->user->password_len,
-			       sm->server_id, sm->server_id_len,
+			       sm->cfg->server_id, sm->cfg->server_id_len,
 			       data->peerid, data->peerid_len, data->key) < 0) {
 		wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive key");
 		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
@@ -338,7 +338,7 @@
 	wpabuf_put(msg, prot_len);
 
 	if (eap_eke_derive_ka(&data->sess,
-			      sm->server_id, sm->server_id_len,
+			      sm->cfg->server_id, sm->cfg->server_id_len,
 			      data->peerid, data->peerid_len,
 			      data->nonce_p, data->nonce_s) < 0) {
 		wpabuf_free(msg);
@@ -552,7 +552,7 @@
 	}
 
 	if (eap_eke_derive_ke_ki(&data->sess,
-				 sm->server_id, sm->server_id_len,
+				 sm->cfg->server_id, sm->cfg->server_id_len,
 				 data->peerid, data->peerid_len) < 0) {
 		wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive Ke/Ki");
 		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
@@ -641,7 +641,8 @@
 		return;
 	}
 
-	if (eap_eke_derive_msk(&data->sess, sm->server_id, sm->server_id_len,
+	if (eap_eke_derive_msk(&data->sess, sm->cfg->server_id,
+			       sm->cfg->server_id_len,
 			       data->peerid, data->peerid_len,
 			       data->nonce_s, data->nonce_p,
 			       data->msk, data->emsk) < 0) {
diff --git a/src/eap_server/eap_server_fast.c b/src/eap_server/eap_server_fast.c
index a63f820..0270821 100644
--- a/src/eap_server/eap_server_fast.c
+++ b/src/eap_server/eap_server_fast.c
@@ -108,8 +108,8 @@
 }
 
 
-static EapType eap_fast_req_failure(struct eap_sm *sm,
-				    struct eap_fast_data *data)
+static enum eap_type eap_fast_req_failure(struct eap_sm *sm,
+					  struct eap_fast_data *data)
 {
 	/* TODO: send Result TLV(FAILURE) */
 	eap_fast_state(data, FAILURE);
@@ -278,7 +278,7 @@
 	 * Extra key material after TLS key_block: session_key_seed[40]
 	 */
 
-	sks = eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn,
+	sks = eap_fast_derive_key(sm->cfg->ssl_ctx, data->ssl.conn,
 				  EAP_FAST_SKS_LEN);
 	if (sks == NULL) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive "
@@ -304,7 +304,7 @@
 {
 	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,
+		eap_fast_derive_key(sm->cfg->ssl_ctx, data->ssl.conn,
 				    sizeof(*data->key_block_p));
 	if (data->key_block_p == NULL) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive key block");
@@ -440,7 +440,7 @@
 		return NULL;
 	}
 
-	if (tls_connection_set_cipher_list(sm->ssl_ctx, data->ssl.conn,
+	if (tls_connection_set_cipher_list(sm->cfg->ssl_ctx, data->ssl.conn,
 					   ciphers) < 0) {
 		wpa_printf(MSG_INFO, "EAP-FAST: Failed to set TLS cipher "
 			   "suites");
@@ -448,7 +448,8 @@
 		return NULL;
 	}
 
-	if (tls_connection_set_session_ticket_cb(sm->ssl_ctx, data->ssl.conn,
+	if (tls_connection_set_session_ticket_cb(sm->cfg->ssl_ctx,
+						 data->ssl.conn,
 						 eap_fast_session_ticket_cb,
 						 data) < 0) {
 		wpa_printf(MSG_INFO, "EAP-FAST: Failed to set SessionTicket "
@@ -457,47 +458,48 @@
 		return NULL;
 	}
 
-	if (sm->pac_opaque_encr_key == NULL) {
+	if (sm->cfg->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,
+	os_memcpy(data->pac_opaque_encr, sm->cfg->pac_opaque_encr_key,
 		  sizeof(data->pac_opaque_encr));
 
-	if (sm->eap_fast_a_id == NULL) {
+	if (sm->cfg->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_memdup(sm->eap_fast_a_id, sm->eap_fast_a_id_len);
+	data->srv_id = os_memdup(sm->cfg->eap_fast_a_id,
+				 sm->cfg->eap_fast_a_id_len);
 	if (data->srv_id == NULL) {
 		eap_fast_reset(sm, data);
 		return NULL;
 	}
-	data->srv_id_len = sm->eap_fast_a_id_len;
+	data->srv_id_len = sm->cfg->eap_fast_a_id_len;
 
-	if (sm->eap_fast_a_id_info == NULL) {
+	if (sm->cfg->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);
+	data->srv_id_info = os_strdup(sm->cfg->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;
+	data->pac_key_lifetime = sm->cfg->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;
+	data->pac_key_refresh_time = sm->cfg->pac_key_refresh_time;
 
 	return data;
 }
@@ -552,8 +554,8 @@
 
 	wpa_printf(MSG_DEBUG, "EAP-FAST: Phase1 done, starting Phase2");
 
-	if (tls_get_cipher(sm->ssl_ctx, data->ssl.conn, cipher, sizeof(cipher))
-	    < 0) {
+	if (tls_get_cipher(sm->cfg->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);
@@ -872,7 +874,8 @@
 	case START:
 		return eap_fast_build_start(sm, data, id);
 	case PHASE1:
-		if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
+		if (tls_connection_established(sm->cfg->ssl_ctx,
+					       data->ssl.conn)) {
 			if (eap_fast_phase1_done(sm, data) < 0)
 				return NULL;
 			if (data->state == PHASE2_START) {
@@ -943,15 +946,14 @@
 
 
 static int eap_fast_phase2_init(struct eap_sm *sm, struct eap_fast_data *data,
-				EapType eap_type)
+				int vendor, enum eap_type 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);
+	data->phase2_method = eap_server_get_eap_method(vendor, eap_type);
 	if (!data->phase2_method)
 		return -1;
 
@@ -973,7 +975,8 @@
 					     struct eap_fast_data *data,
 					     u8 *in_data, size_t in_len)
 {
-	u8 next_type = EAP_TYPE_NONE;
+	int next_vendor = EAP_VENDOR_IETF;
+	enum eap_type next_type = EAP_TYPE_NONE;
 	struct eap_hdr *hdr;
 	u8 *pos;
 	size_t left;
@@ -999,8 +1002,9 @@
 		    m->method == EAP_TYPE_TNC) {
 			wpa_printf(MSG_DEBUG, "EAP-FAST: Peer Nak'ed required "
 				   "TNC negotiation");
+			next_vendor = EAP_VENDOR_IETF;
 			next_type = eap_fast_req_failure(sm, data);
-			eap_fast_phase2_init(sm, data, next_type);
+			eap_fast_phase2_init(sm, data, next_vendor, next_type);
 			return;
 		}
 #endif /* EAP_SERVER_TNC */
@@ -1008,14 +1012,17 @@
 		if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
 		    sm->user->methods[sm->user_eap_method_index].method !=
 		    EAP_TYPE_NONE) {
+			next_vendor = sm->user->methods[
+				sm->user_eap_method_index].vendor;
 			next_type = sm->user->methods[
 				sm->user_eap_method_index++].method;
-			wpa_printf(MSG_DEBUG, "EAP-FAST: try EAP type %d",
-				   next_type);
+			wpa_printf(MSG_DEBUG, "EAP-FAST: try EAP type %u:%u",
+				   next_vendor, next_type);
 		} else {
+			next_vendor = EAP_VENDOR_IETF;
 			next_type = eap_fast_req_failure(sm, data);
 		}
-		eap_fast_phase2_init(sm, data, next_type);
+		eap_fast_phase2_init(sm, data, next_vendor, next_type);
 		return;
 	}
 
@@ -1035,8 +1042,9 @@
 
 	if (!m->isSuccess(sm, priv)) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Phase2 method failed");
+		next_vendor = EAP_VENDOR_IETF;
 		next_type = eap_fast_req_failure(sm, data);
-		eap_fast_phase2_init(sm, data, next_type);
+		eap_fast_phase2_init(sm, data, next_vendor, next_type);
 		return;
 	}
 
@@ -1047,6 +1055,7 @@
 					  "Identity not found in the user "
 					  "database",
 					  sm->identity, sm->identity_len);
+			next_vendor = EAP_VENDOR_IETF;
 			next_type = eap_fast_req_failure(sm, data);
 			break;
 		}
@@ -1057,23 +1066,28 @@
 			 * Only EAP-MSCHAPv2 is allowed for anonymous
 			 * provisioning.
 			 */
+			next_vendor = EAP_VENDOR_IETF;
 			next_type = EAP_TYPE_MSCHAPV2;
 			sm->user_eap_method_index = 0;
 		} else {
+			next_vendor = sm->user->methods[0].vendor;
 			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);
+		wpa_printf(MSG_DEBUG, "EAP-FAST: try EAP type %u:%u",
+			   next_vendor, 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_vendor = EAP_VENDOR_IETF;
 		next_type = EAP_TYPE_NONE;
 #ifdef EAP_SERVER_TNC
-		if (sm->tnc && !data->tnc_started) {
+		if (sm->cfg->tnc && !data->tnc_started) {
 			wpa_printf(MSG_DEBUG, "EAP-FAST: Initialize TNC");
+			next_vendor = EAP_VENDOR_IETF;
 			next_type = EAP_TYPE_TNC;
 			data->tnc_started = 1;
 		}
@@ -1087,7 +1101,7 @@
 		break;
 	}
 
-	eap_fast_phase2_init(sm, data, next_type);
+	eap_fast_phase2_init(sm, data, next_vendor, next_type);
 }
 
 
@@ -1335,8 +1349,8 @@
 		}
 
 		if (data->anon_provisioning &&
-		    sm->eap_fast_prov != ANON_PROV &&
-		    sm->eap_fast_prov != BOTH_PROV) {
+		    sm->cfg->eap_fast_prov != ANON_PROV &&
+		    sm->cfg->eap_fast_prov != BOTH_PROV) {
 			wpa_printf(MSG_DEBUG, "EAP-FAST: Client is trying to "
 				   "use unauthenticated provisioning which is "
 				   "disabled");
@@ -1344,8 +1358,8 @@
 			return;
 		}
 
-		if (sm->eap_fast_prov != AUTH_PROV &&
-		    sm->eap_fast_prov != BOTH_PROV &&
+		if (sm->cfg->eap_fast_prov != AUTH_PROV &&
+		    sm->cfg->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)) {
@@ -1397,7 +1411,7 @@
 		return;
 	}
 
-	in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
+	in_decrypted = tls_connection_decrypt(sm->cfg->ssl_ctx, data->ssl.conn,
 					      in_buf);
 	if (in_decrypted == NULL) {
 		wpa_printf(MSG_INFO, "EAP-FAST: Failed to decrypt Phase 2 "
@@ -1457,7 +1471,7 @@
 		return -1;
 	}
 
-	if (!tls_connection_established(sm->ssl_ctx, data->ssl.conn) ||
+	if (!tls_connection_established(sm->cfg->ssl_ctx, data->ssl.conn) ||
 	    wpabuf_len(data->ssl.tls_out) > 0)
 		return 1;
 
@@ -1474,7 +1488,8 @@
 static int eap_fast_process_phase2_start(struct eap_sm *sm,
 					 struct eap_fast_data *data)
 {
-	u8 next_type;
+	int next_vendor;
+	enum eap_type next_type;
 
 	if (data->identity) {
 		os_free(sm->identity);
@@ -1488,10 +1503,12 @@
 					  "Phase2 Identity not found "
 					  "in the user database",
 					  sm->identity, sm->identity_len);
+			next_vendor = EAP_VENDOR_IETF;
 			next_type = eap_fast_req_failure(sm, data);
 		} else {
 			wpa_printf(MSG_DEBUG, "EAP-FAST: Identity already "
 				   "known - skip Phase 2 Identity Request");
+			next_vendor = sm->user->methods[0].vendor;
 			next_type = sm->user->methods[0].method;
 			sm->user_eap_method_index = 1;
 		}
@@ -1499,10 +1516,11 @@
 		eap_fast_state(data, PHASE2_METHOD);
 	} else {
 		eap_fast_state(data, PHASE2_ID);
+		next_vendor = EAP_VENDOR_IETF;
 		next_type = EAP_TYPE_IDENTITY;
 	}
 
-	return eap_fast_phase2_init(sm, data, next_type);
+	return eap_fast_phase2_init(sm, data, next_vendor, next_type);
 }
 
 
diff --git a/src/eap_server/eap_server_gpsk.c b/src/eap_server/eap_server_gpsk.c
index bebb17f..a774275 100644
--- a/src/eap_server/eap_server_gpsk.c
+++ b/src/eap_server/eap_server_gpsk.c
@@ -117,7 +117,7 @@
 	wpa_hexdump(MSG_MSGDUMP, "EAP-GPSK: RAND_Server",
 		    data->rand_server, EAP_GPSK_RAND_LEN);
 
-	len = 1 + 2 + sm->server_id_len + EAP_GPSK_RAND_LEN + 2 +
+	len = 1 + 2 + sm->cfg->server_id_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);
@@ -129,8 +129,8 @@
 	}
 
 	wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_1);
-	wpabuf_put_be16(req, sm->server_id_len);
-	wpabuf_put_data(req, sm->server_id, sm->server_id_len);
+	wpabuf_put_be16(req, sm->cfg->server_id_len);
+	wpabuf_put_data(req, sm->cfg->server_id, sm->cfg->server_id_len);
 	wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN);
 	wpabuf_put_be16(req,
 			data->csuite_count * sizeof(struct eap_gpsk_csuite));
@@ -152,7 +152,7 @@
 	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 + sm->server_id_len +
+	len = 1 + 2 * EAP_GPSK_RAND_LEN + 2 + sm->cfg->server_id_len +
 		sizeof(struct eap_gpsk_csuite) + 2 + miclen;
 	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len,
 			    EAP_CODE_REQUEST, id);
@@ -168,8 +168,8 @@
 
 	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, sm->server_id_len);
-	wpabuf_put_data(req, sm->server_id, sm->server_id_len);
+	wpabuf_put_be16(req, sm->cfg->server_id_len);
+	wpabuf_put_data(req, sm->cfg->server_id, sm->cfg->server_id_len);
 	csuite = wpabuf_put(req, sizeof(*csuite));
 	WPA_PUT_BE32(csuite->vendor, data->vendor);
 	WPA_PUT_BE16(csuite->specifier, data->specifier);
@@ -294,8 +294,8 @@
 		eap_gpsk_state(data, FAILURE);
 		return;
 	}
-	if (alen != sm->server_id_len ||
-	    os_memcmp(pos, sm->server_id, alen) != 0) {
+	if (alen != sm->cfg->server_id_len ||
+	    os_memcmp(pos, sm->cfg->server_id, alen) != 0) {
 		wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1 and "
 			   "GPSK-2 did not match");
 		eap_gpsk_state(data, FAILURE);
@@ -409,7 +409,7 @@
 				 data->vendor, data->specifier,
 				 data->rand_peer, data->rand_server,
 				 data->id_peer, data->id_peer_len,
-				 sm->server_id, sm->server_id_len,
+				 sm->cfg->server_id, sm->cfg->server_id_len,
 				 data->msk, data->emsk,
 				 data->sk, &data->sk_len,
 				 data->pk, &data->pk_len) < 0) {
@@ -423,7 +423,8 @@
 				       data->vendor, data->specifier,
 				       data->rand_peer, data->rand_server,
 				       data->id_peer, data->id_peer_len,
-				       sm->server_id, sm->server_id_len,
+				       sm->cfg->server_id,
+				       sm->cfg->server_id_len,
 				       EAP_TYPE_GPSK,
 				       data->session_id, &data->id_len) < 0) {
 		wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive Session-Id");
diff --git a/src/eap_server/eap_server_ikev2.c b/src/eap_server/eap_server_ikev2.c
index 32e6872..897637e 100644
--- a/src/eap_server/eap_server_ikev2.c
+++ b/src/eap_server/eap_server_ikev2.c
@@ -87,8 +87,8 @@
 	if (data == NULL)
 		return NULL;
 	data->state = MSG;
-	data->fragment_size = sm->fragment_size > 0 ? sm->fragment_size :
-		IKEV2_FRAGMENT_SIZE;
+	data->fragment_size = sm->cfg->fragment_size > 0 ?
+		sm->cfg->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");
@@ -103,10 +103,10 @@
 	data->ikev2.proposal.encr = ENCR_AES_CBC;
 	data->ikev2.proposal.dh = DH_GROUP2_1024BIT_MODP;
 
-	data->ikev2.IDi = os_memdup(sm->server_id, sm->server_id_len);
+	data->ikev2.IDi = os_memdup(sm->cfg->server_id, sm->cfg->server_id_len);
 	if (data->ikev2.IDi == NULL)
 		goto failed;
-	data->ikev2.IDi_len = sm->server_id_len;
+	data->ikev2.IDi_len = sm->cfg->server_id_len;
 
 	data->ikev2.get_shared_secret = eap_ikev2_get_shared_secret;
 	data->ikev2.cb_ctx = sm;
@@ -414,7 +414,7 @@
 		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)
diff --git a/src/eap_server/eap_server_methods.c b/src/eap_server/eap_server_methods.c
index 79ed344..f37c9c3 100644
--- a/src/eap_server/eap_server_methods.c
+++ b/src/eap_server/eap_server_methods.c
@@ -22,7 +22,8 @@
  * @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)
+const struct eap_method * eap_server_get_eap_method(int vendor,
+						    enum eap_type method)
 {
 	struct eap_method *m;
 	for (m = eap_methods; m; m = m->next) {
@@ -42,7 +43,7 @@
  * 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)
+enum eap_type eap_server_get_type(const char *name, int *vendor)
 {
 	struct eap_method *m;
 	for (m = eap_methods; m; m = m->next) {
@@ -69,7 +70,8 @@
  * is not needed anymore.
  */
 struct eap_method * eap_server_method_alloc(int version, int vendor,
-					    EapType method, const char *name)
+					    enum eap_type method,
+					    const char *name)
 {
 	struct eap_method *eap;
 	eap = os_zalloc(sizeof(*eap));
@@ -163,7 +165,7 @@
  * This function maps EAP type numbers into EAP type names based on the list of
  * EAP methods included in the build.
  */
-const char * eap_server_get_name(int vendor, EapType type)
+const char * eap_server_get_name(int vendor, enum eap_type type)
 {
 	struct eap_method *m;
 	if (vendor == EAP_VENDOR_IETF && type == EAP_TYPE_EXPANDED)
diff --git a/src/eap_server/eap_server_mschapv2.c b/src/eap_server/eap_server_mschapv2.c
index e9e03b0..8a1621a 100644
--- a/src/eap_server/eap_server_mschapv2.c
+++ b/src/eap_server/eap_server_mschapv2.c
@@ -109,7 +109,7 @@
 		return NULL;
 	}
 
-	ms_len = sizeof(*ms) + 1 + CHALLENGE_LEN + sm->server_id_len;
+	ms_len = sizeof(*ms) + 1 + CHALLENGE_LEN + sm->cfg->server_id_len;
 	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
 			    EAP_CODE_REQUEST, id);
 	if (req == NULL) {
@@ -131,7 +131,7 @@
 		wpabuf_put(req, CHALLENGE_LEN);
 	wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Challenge",
 		    data->auth_challenge, CHALLENGE_LEN);
-	wpabuf_put_data(req, sm->server_id, sm->server_id_len);
+	wpabuf_put_data(req, sm->cfg->server_id, sm->cfg->server_id_len);
 
 	return req;
 }
diff --git a/src/eap_server/eap_server_peap.c b/src/eap_server/eap_server_peap.c
index 5e125ac..02d8b8e 100644
--- a/src/eap_server/eap_server_peap.c
+++ b/src/eap_server/eap_server_peap.c
@@ -105,8 +105,8 @@
 {
 	struct wpabuf *buf;
 
-	if (!sm->tls_session_lifetime ||
-	    tls_connection_resumed(sm->ssl_ctx, data->ssl.conn))
+	if (!sm->cfg->tls_session_lifetime ||
+	    tls_connection_resumed(sm->cfg->ssl_ctx, data->ssl.conn))
 		return;
 
 	buf = wpabuf_alloc(1 + 1 + sm->identity_len);
@@ -336,7 +336,7 @@
 		return -1;
 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
 
-	if (tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) {
+	if (tls_connection_resumed(sm->cfg->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",
@@ -521,7 +521,8 @@
 		return eap_peap_build_start(sm, data, id);
 	case PHASE1:
 	case PHASE1_ID2:
-		if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
+		if (tls_connection_established(sm->cfg->ssl_ctx,
+					       data->ssl.conn)) {
 			wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase1 done, "
 				   "starting Phase2");
 			eap_peap_state(data, PHASE2_START);
@@ -585,7 +586,7 @@
 
 
 static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data,
-				int vendor, EapType eap_type)
+				int vendor, enum eap_type eap_type)
 {
 	if (data->phase2_priv && data->phase2_method) {
 		data->phase2_method->reset(sm, data->phase2_priv);
@@ -1020,7 +1021,7 @@
 		}
 
 #ifdef EAP_SERVER_TNC
-		if (data->state != PHASE2_SOH && sm->tnc &&
+		if (data->state != PHASE2_SOH && sm->cfg->tnc &&
 		    data->peap_version == 0) {
 			eap_peap_state(data, PHASE2_SOH);
 			wpa_printf(MSG_DEBUG, "EAP-PEAP: Try to initialize "
@@ -1077,7 +1078,7 @@
 		return;
 	}
 
-	in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
+	in_decrypted = tls_connection_decrypt(sm->cfg->ssl_ctx, data->ssl.conn,
 					      in_buf);
 	if (in_decrypted == NULL) {
 		wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "
@@ -1237,8 +1238,8 @@
 	}
 
 	if (data->state == SUCCESS ||
-	    !tls_connection_established(sm->ssl_ctx, data->ssl.conn) ||
-	    !tls_connection_resumed(sm->ssl_ctx, data->ssl.conn))
+	    !tls_connection_established(sm->cfg->ssl_ctx, data->ssl.conn) ||
+	    !tls_connection_resumed(sm->cfg->ssl_ctx, data->ssl.conn))
 		return;
 
 	buf = tls_connection_get_success_data(data->ssl.conn);
diff --git a/src/eap_server/eap_server_psk.c b/src/eap_server/eap_server_psk.c
index 0eab893..511973c 100644
--- a/src/eap_server/eap_server_psk.c
+++ b/src/eap_server/eap_server_psk.c
@@ -68,7 +68,7 @@
 		    data->rand_s, EAP_PSK_RAND_LEN);
 
 	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK,
-			    sizeof(*psk) + sm->server_id_len,
+			    sizeof(*psk) + sm->cfg->server_id_len,
 			    EAP_CODE_REQUEST, id);
 	if (req == NULL) {
 		wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory "
@@ -80,7 +80,7 @@
 	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, sm->server_id, sm->server_id_len);
+	wpabuf_put_data(req, sm->cfg->server_id, sm->cfg->server_id_len);
 
 	return req;
 }
@@ -110,13 +110,13 @@
 	os_memcpy(psk->rand_s, data->rand_s, EAP_PSK_RAND_LEN);
 
 	/* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */
-	buflen = sm->server_id_len + EAP_PSK_RAND_LEN;
+	buflen = sm->cfg->server_id_len + EAP_PSK_RAND_LEN;
 	buf = os_malloc(buflen);
 	if (buf == NULL)
 		goto fail;
 
-	os_memcpy(buf, sm->server_id, sm->server_id_len);
-	os_memcpy(buf + sm->server_id_len, data->rand_p, EAP_PSK_RAND_LEN);
+	os_memcpy(buf, sm->cfg->server_id, sm->cfg->server_id_len);
+	os_memcpy(buf + sm->cfg->server_id_len, data->rand_p, EAP_PSK_RAND_LEN);
 	if (omac1_aes_128(data->ak, buf, buflen, psk->mac_s)) {
 		os_free(buf);
 		goto fail;
@@ -293,7 +293,7 @@
 	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 + sm->server_id_len + 2 * EAP_PSK_RAND_LEN;
+	buflen = data->id_p_len + sm->cfg->server_id_len + 2 * EAP_PSK_RAND_LEN;
 	buf = os_malloc(buflen);
 	if (buf == NULL) {
 		data->state = FAILURE;
@@ -301,8 +301,8 @@
 	}
 	os_memcpy(buf, data->id_p, data->id_p_len);
 	pos = buf + data->id_p_len;
-	os_memcpy(pos, sm->server_id, sm->server_id_len);
-	pos += sm->server_id_len;
+	os_memcpy(pos, sm->cfg->server_id, sm->cfg->server_id_len);
+	pos += sm->cfg->server_id_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);
diff --git a/src/eap_server/eap_server_pwd.c b/src/eap_server/eap_server_pwd.c
index a8087c1..6bf3a23 100644
--- a/src/eap_server/eap_server_pwd.c
+++ b/src/eap_server/eap_server_pwd.c
@@ -97,7 +97,7 @@
 	if (data == NULL)
 		return NULL;
 
-	data->group_num = sm->pwd_group;
+	data->group_num = sm->cfg->pwd_group;
 	wpa_printf(MSG_DEBUG, "EAP-pwd: Selected group number %d",
 		   data->group_num);
 	data->state = PWD_ID_Req;
@@ -134,7 +134,7 @@
 	data->in_frag_pos = data->out_frag_pos = 0;
 	data->inbuf = data->outbuf = NULL;
 	/* use default MTU from RFC 5931 if not configured otherwise */
-	data->mtu = sm->fragment_size > 0 ? sm->fragment_size : 1020;
+	data->mtu = sm->cfg->fragment_size > 0 ? sm->cfg->fragment_size : 1020;
 
 	return data;
 }
diff --git a/src/eap_server/eap_server_sake.c b/src/eap_server/eap_server_sake.c
index 2fc2c05..56cfbfb 100644
--- a/src/eap_server/eap_server_sake.c
+++ b/src/eap_server/eap_server_sake.c
@@ -123,7 +123,7 @@
 	wpa_printf(MSG_DEBUG, "EAP-SAKE: Request/Identity");
 
 	plen = 4;
-	plen += 2 + sm->server_id_len;
+	plen += 2 + sm->cfg->server_id_len;
 	msg = eap_sake_build_msg(data, id, plen, EAP_SAKE_SUBTYPE_IDENTITY);
 	if (msg == NULL) {
 		data->state = FAILURE;
@@ -135,7 +135,7 @@
 
 	wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_SERVERID");
 	eap_sake_add_attr(msg, EAP_SAKE_AT_SERVERID,
-			  sm->server_id, sm->server_id_len);
+			  sm->cfg->server_id, sm->cfg->server_id_len);
 
 	return msg;
 }
@@ -158,7 +158,7 @@
 	wpa_hexdump(MSG_MSGDUMP, "EAP-SAKE: RAND_S (server rand)",
 		    data->rand_s, EAP_SAKE_RAND_LEN);
 
-	plen = 2 + EAP_SAKE_RAND_LEN + 2 + sm->server_id_len;
+	plen = 2 + EAP_SAKE_RAND_LEN + 2 + sm->cfg->server_id_len;
 	msg = eap_sake_build_msg(data, id, plen, EAP_SAKE_SUBTYPE_CHALLENGE);
 	if (msg == NULL) {
 		data->state = FAILURE;
@@ -171,7 +171,7 @@
 
 	wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_SERVERID");
 	eap_sake_add_attr(msg, EAP_SAKE_AT_SERVERID,
-			  sm->server_id, sm->server_id_len);
+			  sm->cfg->server_id, sm->cfg->server_id_len);
 
 	return msg;
 }
@@ -198,7 +198,7 @@
 	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,
-				 sm->server_id, sm->server_id_len,
+				 sm->cfg->server_id, sm->cfg->server_id_len,
 				 data->peerid, data->peerid_len, 0,
 				 wpabuf_head(msg), wpabuf_len(msg), mic, mic))
 	{
@@ -351,7 +351,7 @@
 	}
 
 	if (eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p,
-				 sm->server_id, sm->server_id_len,
+				 sm->cfg->server_id, sm->cfg->server_id_len,
 				 data->peerid, data->peerid_len, 1,
 				 wpabuf_head(respData), wpabuf_len(respData),
 				 attr.mic_p, mic_p) < 0) {
@@ -392,7 +392,7 @@
 	}
 
 	if (eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p,
-				 sm->server_id, sm->server_id_len,
+				 sm->cfg->server_id, sm->cfg->server_id_len,
 				 data->peerid, data->peerid_len, 1,
 				 wpabuf_head(respData), wpabuf_len(respData),
 				 attr.mic_p, mic_p) < 0) {
diff --git a/src/eap_server/eap_server_sim.c b/src/eap_server/eap_server_sim.c
index 8562c64..d7ac87c 100644
--- a/src/eap_server/eap_server_sim.c
+++ b/src/eap_server/eap_server_sim.c
@@ -76,7 +76,7 @@
 {
 	struct eap_sim_data *data;
 
-	if (sm->eap_sim_db_priv == NULL) {
+	if (!sm->cfg->eap_sim_db_priv) {
 		wpa_printf(MSG_WARNING, "EAP-SIM: eap_sim_db not configured");
 		return NULL;
 	}
@@ -150,18 +150,24 @@
 			      const u8 *nonce_s)
 {
 	os_free(data->next_pseudonym);
-	if (nonce_s == NULL) {
+	if (!(sm->cfg->eap_sim_id & 0x01)) {
+		/* Use of pseudonyms disabled in configuration */
+		data->next_pseudonym = NULL;
+	} else if (!nonce_s) {
 		data->next_pseudonym =
-			eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv,
+			eap_sim_db_get_next_pseudonym(sm->cfg->eap_sim_db_priv,
 						      EAP_SIM_DB_SIM);
 	} else {
 		/* Do not update pseudonym during re-authentication */
 		data->next_pseudonym = NULL;
 	}
 	os_free(data->next_reauth_id);
-	if (data->counter <= EAP_SIM_MAX_FAST_REAUTHS) {
+	if (!(sm->cfg->eap_sim_id & 0x02)) {
+		/* Use of fast reauth disabled in configuration */
+		data->next_reauth_id = NULL;
+	} else if (data->counter <= EAP_SIM_MAX_FAST_REAUTHS) {
 		data->next_reauth_id =
-			eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv,
+			eap_sim_db_get_next_reauth_id(sm->cfg->eap_sim_db_priv,
 						      EAP_SIM_DB_SIM);
 	} else {
 		wpa_printf(MSG_DEBUG, "EAP-SIM: Max fast re-authentication "
@@ -234,7 +240,7 @@
 		return NULL;
 	}
 
-	if (sm->eap_sim_aka_result_ind) {
+	if (sm->cfg->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);
 	}
@@ -273,7 +279,7 @@
 		return NULL;
 	}
 
-	if (sm->eap_sim_aka_result_ind) {
+	if (sm->cfg->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);
 	}
@@ -286,7 +292,7 @@
 	 * Session-Id calculation after receiving response from the peer and
 	 * after all other checks pass. */
 	os_memcpy(data->reauth_mac,
-		  (wpabuf_head_u8(buf) + wpabuf_len(buf) - EAP_SIM_MAC_LEN),
+		  wpabuf_head_u8(buf) + wpabuf_len(buf) - EAP_SIM_MAC_LEN,
 		  EAP_SIM_MAC_LEN);
 
 	return buf;
@@ -469,7 +475,7 @@
 		wpa_printf(MSG_DEBUG, "EAP-SIM: Reauth username '%s'",
 			   username);
 		data->reauth = eap_sim_db_get_reauth_entry(
-			sm->eap_sim_db_priv, username);
+			sm->cfg->eap_sim_db_priv, username);
 		os_free(username);
 		if (data->reauth == NULL) {
 			wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown reauth "
@@ -491,7 +497,7 @@
 		wpa_printf(MSG_DEBUG, "EAP-SIM: Pseudonym username '%s'",
 			   username);
 		permanent = eap_sim_db_get_permanent(
-			sm->eap_sim_db_priv, username);
+			sm->cfg->eap_sim_db_priv, username);
 		os_free(username);
 		if (permanent == NULL) {
 			wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown pseudonym "
@@ -532,7 +538,7 @@
 	data->reauth = NULL;
 
 	data->num_chal = eap_sim_db_get_gsm_triplets(
-		sm->eap_sim_db_priv, data->permanent, EAP_SIM_MAX_CHAL,
+		sm->cfg->eap_sim_db_priv, data->permanent, 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 "
@@ -593,7 +599,7 @@
 
 	wpa_printf(MSG_DEBUG, "EAP-SIM: Challenge response includes the "
 		   "correct AT_MAC");
-	if (sm->eap_sim_aka_result_ind && attr->result_ind) {
+	if (sm->cfg->eap_sim_aka_result_ind && attr->result_ind) {
 		data->use_result_ind = 1;
 		data->notification = EAP_SIM_SUCCESS;
 		eap_sim_state(data, NOTIFICATION);
@@ -601,12 +607,13 @@
 		eap_sim_state(data, SUCCESS);
 
 	if (data->next_pseudonym) {
-		eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, data->permanent,
+		eap_sim_db_add_pseudonym(sm->cfg->eap_sim_db_priv,
+					 data->permanent,
 					 data->next_pseudonym);
 		data->next_pseudonym = NULL;
 	}
 	if (data->next_reauth_id) {
-		eap_sim_db_add_reauth(sm->eap_sim_db_priv, data->permanent,
+		eap_sim_db_add_reauth(sm->cfg->eap_sim_db_priv, data->permanent,
 				      data->next_reauth_id, data->counter + 1,
 				      data->mk);
 		data->next_reauth_id = NULL;
@@ -666,7 +673,7 @@
 		return;
 	}
 
-	if (sm->eap_sim_aka_result_ind && attr->result_ind) {
+	if (sm->cfg->eap_sim_aka_result_ind && attr->result_ind) {
 		data->use_result_ind = 1;
 		data->notification = EAP_SIM_SUCCESS;
 		eap_sim_state(data, NOTIFICATION);
@@ -674,12 +681,13 @@
 		eap_sim_state(data, SUCCESS);
 
 	if (data->next_reauth_id) {
-		eap_sim_db_add_reauth(sm->eap_sim_db_priv, data->permanent,
+		eap_sim_db_add_reauth(sm->cfg->eap_sim_db_priv, data->permanent,
 				      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);
+		eap_sim_db_remove_reauth(sm->cfg->eap_sim_db_priv,
+					 data->reauth);
 		data->reauth = NULL;
 	}
 
@@ -688,7 +696,7 @@
 fail:
 	data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
 	eap_sim_state(data, NOTIFICATION);
-	eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
+	eap_sim_db_remove_reauth(sm->cfg->eap_sim_db_priv, data->reauth);
 	data->reauth = NULL;
 	os_free(decrypted);
 }
diff --git a/src/eap_server/eap_server_teap.c b/src/eap_server/eap_server_teap.c
index d8e5414..a2cbf7a 100644
--- a/src/eap_server/eap_server_teap.c
+++ b/src/eap_server/eap_server_teap.c
@@ -31,7 +31,7 @@
 	enum {
 		START, PHASE1, PHASE1B, PHASE2_START, PHASE2_ID,
 		PHASE2_BASIC_AUTH, PHASE2_METHOD, CRYPTO_BINDING, REQUEST_PAC,
-		FAILURE_SEND_RESULT, SUCCESS, FAILURE
+		FAILURE_SEND_RESULT, SUCCESS_SEND_RESULT, SUCCESS, FAILURE
 	} state;
 
 	u8 teap_version;
@@ -56,7 +56,10 @@
 	size_t srv_id_len;
 	char *srv_id_info;
 
+	unsigned int basic_auth_not_done:1;
+	unsigned int inner_eap_not_done:1;
 	int anon_provisioning;
+	int skipped_inner_auth;
 	int send_new_pac; /* server triggered re-keying of Tunnel PAC */
 	struct wpabuf *pending_phase2_resp;
 	struct wpabuf *server_outer_tlvs;
@@ -70,6 +73,7 @@
 	int pac_key_refresh_time;
 
 	enum teap_error_codes error_code;
+	enum teap_identity_types cur_id_type;
 };
 
 
@@ -100,6 +104,8 @@
 		return "REQUEST_PAC";
 	case FAILURE_SEND_RESULT:
 		return "FAILURE_SEND_RESULT";
+	case SUCCESS_SEND_RESULT:
+		return "SUCCESS_SEND_RESULT";
 	case SUCCESS:
 		return "SUCCESS";
 	case FAILURE:
@@ -119,8 +125,8 @@
 }
 
 
-static EapType eap_teap_req_failure(struct eap_teap_data *data,
-				    enum teap_error_codes error)
+static enum eap_type eap_teap_req_failure(struct eap_teap_data *data,
+					  enum teap_error_codes error)
 {
 	eap_teap_state(data, FAILURE_SEND_RESULT);
 	return EAP_TYPE_NONE;
@@ -285,7 +291,7 @@
 	int res;
 
 	/* RFC 7170, Section 5.1 */
-	res = tls_connection_export_key(sm->ssl_ctx, data->ssl.conn,
+	res = tls_connection_export_key(sm->cfg->ssl_ctx, data->ssl.conn,
 					TEAP_TLS_EXPORTER_LABEL_SKS, NULL, 0,
 					data->simck_msk, EAP_TEAP_SIMCK_LEN);
 	if (res)
@@ -308,8 +314,9 @@
 	wpa_printf(MSG_DEBUG, "EAP-TEAP: Deriving ICMK[%d] (S-IMCK and CMK)",
 		   data->simck_idx + 1);
 
-	if (sm->eap_teap_auth == 1)
-		return eap_teap_derive_cmk_basic_pw_auth(data->simck_msk,
+	if (sm->cfg->eap_teap_auth == 1)
+		return eap_teap_derive_cmk_basic_pw_auth(data->tls_cs,
+							 data->simck_msk,
 							 data->cmk_msk);
 
 	if (!data->phase2_method || !data->phase2_priv) {
@@ -332,7 +339,8 @@
 						     &emsk_len);
 	}
 
-	res = eap_teap_derive_imck(data->simck_msk, data->simck_emsk,
+	res = eap_teap_derive_imck(data->tls_cs,
+				   data->simck_msk, data->simck_emsk,
 				   msk, msk_len, emsk, emsk_len,
 				   data->simck_msk, data->cmk_msk,
 				   data->simck_emsk, data->cmk_emsk);
@@ -366,7 +374,8 @@
 	/* TODO: Add anon-DH TLS cipher suites (and if one is negotiated,
 	 * enforce inner EAP with mutual authentication to be used) */
 
-	if (tls_connection_set_session_ticket_cb(sm->ssl_ctx, data->ssl.conn,
+	if (tls_connection_set_session_ticket_cb(sm->cfg->ssl_ctx,
+						 data->ssl.conn,
 						 eap_teap_session_ticket_cb,
 						 data) < 0) {
 		wpa_printf(MSG_INFO,
@@ -375,48 +384,49 @@
 		return NULL;
 	}
 
-	if (!sm->pac_opaque_encr_key) {
+	if (!sm->cfg->pac_opaque_encr_key) {
 		wpa_printf(MSG_INFO,
 			   "EAP-TEAP: No PAC-Opaque encryption key configured");
 		eap_teap_reset(sm, data);
 		return NULL;
 	}
-	os_memcpy(data->pac_opaque_encr, sm->pac_opaque_encr_key,
+	os_memcpy(data->pac_opaque_encr, sm->cfg->pac_opaque_encr_key,
 		  sizeof(data->pac_opaque_encr));
 
-	if (!sm->eap_fast_a_id) {
+	if (!sm->cfg->eap_fast_a_id) {
 		wpa_printf(MSG_INFO, "EAP-TEAP: No A-ID configured");
 		eap_teap_reset(sm, data);
 		return NULL;
 	}
-	data->srv_id = os_malloc(sm->eap_fast_a_id_len);
+	data->srv_id = os_malloc(sm->cfg->eap_fast_a_id_len);
 	if (!data->srv_id) {
 		eap_teap_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;
+	os_memcpy(data->srv_id, sm->cfg->eap_fast_a_id,
+		  sm->cfg->eap_fast_a_id_len);
+	data->srv_id_len = sm->cfg->eap_fast_a_id_len;
 
-	if (!sm->eap_fast_a_id_info) {
+	if (!sm->cfg->eap_fast_a_id_info) {
 		wpa_printf(MSG_INFO, "EAP-TEAP: No A-ID-Info configured");
 		eap_teap_reset(sm, data);
 		return NULL;
 	}
-	data->srv_id_info = os_strdup(sm->eap_fast_a_id_info);
+	data->srv_id_info = os_strdup(sm->cfg->eap_fast_a_id_info);
 	if (!data->srv_id_info) {
 		eap_teap_reset(sm, data);
 		return NULL;
 	}
 
 	/* PAC-Key lifetime in seconds (hard limit) */
-	data->pac_key_lifetime = sm->pac_key_lifetime;
+	data->pac_key_lifetime = sm->cfg->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;
+	data->pac_key_refresh_time = sm->cfg->pac_key_refresh_time;
 
 	return data;
 }
@@ -496,8 +506,8 @@
 	wpa_printf(MSG_DEBUG, "EAP-TEAP: TLS cipher suite 0x%04x",
 		   data->tls_cs);
 
-	if (tls_get_cipher(sm->ssl_ctx, data->ssl.conn, cipher, sizeof(cipher))
-	    < 0) {
+	if (tls_get_cipher(sm->cfg->ssl_ctx, data->ssl.conn,
+			   cipher, sizeof(cipher)) < 0) {
 		wpa_printf(MSG_DEBUG,
 			   "EAP-TEAP: Failed to get cipher information");
 		eap_teap_state(data, FAILURE);
@@ -523,30 +533,65 @@
 						 struct eap_teap_data *data,
 						 u8 id)
 {
-	struct wpabuf *req;
+	struct wpabuf *req, *id_tlv = NULL;
 
-	if (sm->eap_teap_auth == 1) {
+	if (sm->cfg->eap_teap_auth == 1 ||
+	    (data->phase2_priv && data->phase2_method &&
+	     data->phase2_method->vendor == EAP_VENDOR_IETF &&
+	     data->phase2_method->method == EAP_TYPE_IDENTITY)) {
+		switch (sm->cfg->eap_teap_id) {
+		case EAP_TEAP_ID_ALLOW_ANY:
+			break;
+		case EAP_TEAP_ID_REQUIRE_USER:
+		case EAP_TEAP_ID_REQUEST_USER_ACCEPT_MACHINE:
+			data->cur_id_type = TEAP_IDENTITY_TYPE_USER;
+			id_tlv = eap_teap_tlv_identity_type(data->cur_id_type);
+			break;
+		case EAP_TEAP_ID_REQUIRE_MACHINE:
+		case EAP_TEAP_ID_REQUEST_MACHINE_ACCEPT_USER:
+			data->cur_id_type = TEAP_IDENTITY_TYPE_MACHINE;
+			id_tlv = eap_teap_tlv_identity_type(data->cur_id_type);
+			break;
+		case EAP_TEAP_ID_REQUIRE_USER_AND_MACHINE:
+			if (data->cur_id_type == TEAP_IDENTITY_TYPE_USER)
+				data->cur_id_type = TEAP_IDENTITY_TYPE_MACHINE;
+			else
+				data->cur_id_type = TEAP_IDENTITY_TYPE_USER;
+			id_tlv = eap_teap_tlv_identity_type(data->cur_id_type);
+			break;
+		}
+	}
+
+	if (sm->cfg->eap_teap_auth == 1) {
 		wpa_printf(MSG_DEBUG, "EAP-TEAP: Initiate Basic-Password-Auth");
+		data->basic_auth_not_done = 1;
 		req = wpabuf_alloc(sizeof(struct teap_tlv_hdr));
-		if (!req)
+		if (!req) {
+			wpabuf_free(id_tlv);
 			return NULL;
+		}
 		eap_teap_put_tlv_hdr(req, TEAP_TLV_BASIC_PASSWORD_AUTH_REQ, 0);
-		return req;
+		return wpabuf_concat(req, id_tlv);
 	}
 
 	wpa_printf(MSG_DEBUG, "EAP-TEAP: Initiate inner EAP method");
+	data->inner_eap_not_done = 1;
 	if (!data->phase2_priv) {
 		wpa_printf(MSG_DEBUG,
 			   "EAP-TEAP: Phase 2 method not initialized");
+		wpabuf_free(id_tlv);
 		return NULL;
 	}
 
 	req = data->phase2_method->buildReq(sm, data->phase2_priv, id);
-	if (!req)
+	if (!req) {
+		wpabuf_free(id_tlv);
 		return NULL;
+	}
 
 	wpa_hexdump_buf_key(MSG_MSGDUMP, "EAP-TEAP: Phase 2 EAP-Request", req);
-	return eap_teap_tlv_eap_payload(req);
+
+	return wpabuf_concat(eap_teap_tlv_eap_payload(req), id_tlv);
 }
 
 
@@ -563,12 +608,14 @@
 		return NULL;
 
 	if (data->send_new_pac || data->anon_provisioning ||
-	    data->phase2_method)
+	    data->basic_auth_not_done || data->inner_eap_not_done ||
+	    data->phase2_method || sm->cfg->eap_teap_separate_result)
 		data->final_result = 0;
 	else
 		data->final_result = 1;
 
-	if (!data->final_result || data->eap_seq > 0) {
+	if (!data->final_result || data->eap_seq > 0 ||
+	    sm->cfg->eap_teap_auth == 1) {
 		/* Intermediate-Result */
 		wpa_printf(MSG_DEBUG,
 			   "EAP-TEAP: Add Intermediate-Result TLV (status=SUCCESS)");
@@ -842,7 +889,8 @@
 	case START:
 		return eap_teap_build_start(sm, data, id);
 	case PHASE1B:
-		if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
+		if (tls_connection_established(sm->cfg->ssl_ctx,
+					       data->ssl.conn)) {
 			if (eap_teap_phase1_done(sm, data) < 0)
 				return NULL;
 			if (data->state == PHASE2_START) {
@@ -899,6 +947,10 @@
 			req = wpabuf_concat(
 				req, eap_teap_tlv_error(data->error_code));
 		break;
+	case SUCCESS_SEND_RESULT:
+		req = eap_teap_tlv_result(TEAP_STATUS_SUCCESS, 0);
+		data->final_result = 1;
+		break;
 	default:
 		wpa_printf(MSG_DEBUG, "EAP-TEAP: %s - unexpected state %d",
 			   __func__, data->state);
@@ -930,15 +982,14 @@
 
 
 static int eap_teap_phase2_init(struct eap_sm *sm, struct eap_teap_data *data,
-				EapType eap_type)
+				int vendor, enum eap_type 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);
+	data->phase2_method = eap_server_get_eap_method(vendor, eap_type);
 	if (!data->phase2_method)
 		return -1;
 
@@ -950,11 +1001,33 @@
 }
 
 
+static int eap_teap_valid_id_type(struct eap_sm *sm, struct eap_teap_data *data,
+				  enum teap_identity_types id_type)
+{
+	if (sm->cfg->eap_teap_id == EAP_TEAP_ID_REQUIRE_USER &&
+	    id_type != TEAP_IDENTITY_TYPE_USER)
+		return 0;
+	if (sm->cfg->eap_teap_id == EAP_TEAP_ID_REQUIRE_MACHINE &&
+	    id_type != TEAP_IDENTITY_TYPE_MACHINE)
+		return 0;
+	if (sm->cfg->eap_teap_id == EAP_TEAP_ID_REQUIRE_USER_AND_MACHINE &&
+	    id_type != data->cur_id_type)
+		return 0;
+	if (sm->cfg->eap_teap_id != EAP_TEAP_ID_ALLOW_ANY &&
+	    id_type != TEAP_IDENTITY_TYPE_USER &&
+	    id_type != TEAP_IDENTITY_TYPE_MACHINE)
+		return 0;
+	return 1;
+}
+
+
 static void eap_teap_process_phase2_response(struct eap_sm *sm,
 					     struct eap_teap_data *data,
-					     u8 *in_data, size_t in_len)
+					     u8 *in_data, size_t in_len,
+					     enum teap_identity_types id_type)
 {
-	u8 next_type = EAP_TYPE_NONE;
+	int next_vendor = EAP_VENDOR_IETF;
+	enum eap_type next_type = EAP_TYPE_NONE;
 	struct eap_hdr *hdr;
 	u8 *pos;
 	size_t left;
@@ -982,8 +1055,9 @@
 		    m->method == EAP_TYPE_TNC) {
 			wpa_printf(MSG_DEBUG,
 				   "EAP-TEAP: Peer Nak'ed required TNC negotiation");
+			next_vendor = EAP_VENDOR_IETF;
 			next_type = eap_teap_req_failure(data, 0);
-			eap_teap_phase2_init(sm, data, next_type);
+			eap_teap_phase2_init(sm, data, next_vendor, next_type);
 			return;
 		}
 #endif /* EAP_SERVER_TNC */
@@ -991,14 +1065,17 @@
 		if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
 		    sm->user->methods[sm->user_eap_method_index].method !=
 		    EAP_TYPE_NONE) {
+			next_vendor = sm->user->methods[
+				sm->user_eap_method_index].vendor;
 			next_type = sm->user->methods[
 				sm->user_eap_method_index++].method;
-			wpa_printf(MSG_DEBUG, "EAP-TEAP: try EAP type %d",
-				   next_type);
+			wpa_printf(MSG_DEBUG, "EAP-TEAP: try EAP type %u:%u",
+				   next_vendor, next_type);
 		} else {
+			next_vendor = EAP_VENDOR_IETF;
 			next_type = eap_teap_req_failure(data, 0);
 		}
-		eap_teap_phase2_init(sm, data, next_type);
+		eap_teap_phase2_init(sm, data, next_vendor, next_type);
 		return;
 	}
 
@@ -1018,17 +1095,26 @@
 
 	if (!m->isSuccess(sm, priv)) {
 		wpa_printf(MSG_DEBUG, "EAP-TEAP: Phase 2 method failed");
+		next_vendor = EAP_VENDOR_IETF;
 		next_type = eap_teap_req_failure(data, TEAP_ERROR_INNER_METHOD);
-		eap_teap_phase2_init(sm, data, next_type);
+		eap_teap_phase2_init(sm, data, next_vendor, next_type);
 		return;
 	}
 
 	switch (data->state) {
 	case PHASE2_ID:
+		if (!eap_teap_valid_id_type(sm, data, id_type)) {
+			wpa_printf(MSG_DEBUG,
+				   "EAP-TEAP: Provided Identity-Type %u not allowed",
+				   id_type);
+			eap_teap_req_failure(data, TEAP_ERROR_INNER_METHOD);
+			break;
+		}
 		if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
 			wpa_hexdump_ascii(MSG_DEBUG,
 					  "EAP-TEAP: Phase 2 Identity not found in the user database",
 					  sm->identity, sm->identity_len);
+			next_vendor = EAP_VENDOR_IETF;
 			next_type = eap_teap_req_failure(
 				data, TEAP_ERROR_INNER_METHOD);
 			break;
@@ -1039,23 +1125,33 @@
 			/* TODO: Allow any inner EAP method that provides
 			 * mutual authentication and EMSK derivation (i.e.,
 			 * EAP-pwd or EAP-EKE). */
+			next_vendor = EAP_VENDOR_IETF;
 			next_type = EAP_TYPE_PWD;
 			sm->user_eap_method_index = 0;
 		} else {
+			next_vendor = sm->user->methods[0].vendor;
 			next_type = sm->user->methods[0].method;
 			sm->user_eap_method_index = 1;
 		}
-		wpa_printf(MSG_DEBUG, "EAP-TEAP: Try EAP type %d", next_type);
+		wpa_printf(MSG_DEBUG, "EAP-TEAP: Try EAP type %u:%u",
+			   next_vendor, next_type);
 		break;
 	case PHASE2_METHOD:
 	case CRYPTO_BINDING:
 		eap_teap_update_icmk(sm, data);
+		if (data->state == PHASE2_METHOD &&
+		    (sm->cfg->eap_teap_id !=
+		     EAP_TEAP_ID_REQUIRE_USER_AND_MACHINE ||
+		     data->cur_id_type == TEAP_IDENTITY_TYPE_MACHINE))
+			data->inner_eap_not_done = 0;
 		eap_teap_state(data, CRYPTO_BINDING);
 		data->eap_seq++;
+		next_vendor = EAP_VENDOR_IETF;
 		next_type = EAP_TYPE_NONE;
 #ifdef EAP_SERVER_TNC
-		if (sm->tnc && !data->tnc_started) {
+		if (sm->cfg->tnc && !data->tnc_started) {
 			wpa_printf(MSG_DEBUG, "EAP-TEAP: Initialize TNC");
+			next_vendor = EAP_VENDOR_IETF;
 			next_type = EAP_TYPE_TNC;
 			data->tnc_started = 1;
 		}
@@ -1069,13 +1165,14 @@
 		break;
 	}
 
-	eap_teap_phase2_init(sm, data, next_type);
+	eap_teap_phase2_init(sm, data, next_vendor, next_type);
 }
 
 
 static void eap_teap_process_phase2_eap(struct eap_sm *sm,
 					struct eap_teap_data *data,
-					u8 *in_data, size_t in_len)
+					u8 *in_data, size_t in_len,
+					enum teap_identity_types id_type)
 {
 	struct eap_hdr *hdr;
 	size_t len;
@@ -1102,7 +1199,8 @@
 		   (unsigned long) len);
 	switch (hdr->code) {
 	case EAP_CODE_RESPONSE:
-		eap_teap_process_phase2_response(sm, data, (u8 *) hdr, len);
+		eap_teap_process_phase2_response(sm, data, (u8 *) hdr, len,
+						 id_type);
 		break;
 	default:
 		wpa_printf(MSG_INFO,
@@ -1115,11 +1213,20 @@
 
 static void eap_teap_process_basic_auth_resp(struct eap_sm *sm,
 					     struct eap_teap_data *data,
-					     u8 *in_data, size_t in_len)
+					     u8 *in_data, size_t in_len,
+					     enum teap_identity_types id_type)
 {
 	u8 *pos, *end, *username, *password, *new_id;
 	u8 userlen, passlen;
 
+	if (!eap_teap_valid_id_type(sm, data, id_type)) {
+		wpa_printf(MSG_DEBUG,
+			   "EAP-TEAP: Provided Identity-Type %u not allowed",
+			   id_type);
+		eap_teap_req_failure(data, 0);
+		return;
+	}
+
 	pos = in_data;
 	end = pos + in_len;
 
@@ -1197,6 +1304,9 @@
 		sm->identity = new_id;
 		sm->identity_len = userlen;
 	}
+	if (sm->cfg->eap_teap_id != EAP_TEAP_ID_REQUIRE_USER_AND_MACHINE ||
+	    data->cur_id_type == TEAP_IDENTITY_TYPE_MACHINE)
+		data->basic_auth_not_done = 0;
 	eap_teap_state(data, CRYPTO_BINDING);
 	eap_teap_update_icmk(sm, data);
 }
@@ -1444,7 +1554,8 @@
 			return;
 		}
 
-		if (!data->final_result &&
+		if (sm->cfg->eap_teap_auth != 1 &&
+		    !data->skipped_inner_auth &&
 		    tlv.iresult != TEAP_STATUS_SUCCESS) {
 			wpa_printf(MSG_DEBUG,
 				   "EAP-TEAP: Crypto-Binding TLV without intermediate Success Result");
@@ -1466,16 +1577,16 @@
 		}
 
 		if (data->anon_provisioning &&
-		    sm->eap_fast_prov != ANON_PROV &&
-		    sm->eap_fast_prov != BOTH_PROV) {
+		    sm->cfg->eap_fast_prov != ANON_PROV &&
+		    sm->cfg->eap_fast_prov != BOTH_PROV) {
 			wpa_printf(MSG_DEBUG,
 				   "EAP-TEAP: Client is trying to use unauthenticated provisioning which is disabled");
 			eap_teap_state(data, FAILURE);
 			return;
 		}
 
-		if (sm->eap_fast_prov != AUTH_PROV &&
-		    sm->eap_fast_prov != BOTH_PROV &&
+		if (sm->cfg->eap_fast_prov != AUTH_PROV &&
+		    sm->cfg->eap_fast_prov != BOTH_PROV &&
 		    tlv.request_action == TEAP_REQUEST_ACTION_PROCESS_TLV &&
 		    eap_teap_pac_type(tlv.pac, tlv.pac_len,
 				      PAC_TYPE_TUNNEL_PAC)) {
@@ -1496,30 +1607,55 @@
 			wpa_printf(MSG_DEBUG,
 				   "EAP-TEAP: Server triggered re-keying of Tunnel PAC");
 			eap_teap_state(data, REQUEST_PAC);
-		} else if (data->final_result)
+		} else if (data->final_result) {
 			eap_teap_state(data, SUCCESS);
+		} else if (sm->cfg->eap_teap_separate_result) {
+			eap_teap_state(data, SUCCESS_SEND_RESULT);
+		}
 	}
 
 	if (tlv.basic_auth_resp) {
-		if (sm->eap_teap_auth != 1) {
+		if (sm->cfg->eap_teap_auth != 1) {
 			wpa_printf(MSG_DEBUG,
 				   "EAP-TEAP: Unexpected Basic-Password-Auth-Resp when trying to use inner EAP");
 			eap_teap_state(data, FAILURE);
 			return;
 		}
 		eap_teap_process_basic_auth_resp(sm, data, tlv.basic_auth_resp,
-						 tlv.basic_auth_resp_len);
+						 tlv.basic_auth_resp_len,
+						 tlv.identity_type);
 	}
 
 	if (tlv.eap_payload_tlv) {
-		if (sm->eap_teap_auth == 1) {
+		if (sm->cfg->eap_teap_auth == 1) {
 			wpa_printf(MSG_DEBUG,
 				   "EAP-TEAP: Unexpected EAP Payload TLV when trying to use Basic-Password-Auth");
 			eap_teap_state(data, FAILURE);
 			return;
 		}
 		eap_teap_process_phase2_eap(sm, data, tlv.eap_payload_tlv,
-					    tlv.eap_payload_tlv_len);
+					    tlv.eap_payload_tlv_len,
+					    tlv.identity_type);
+	}
+
+	if (data->state == SUCCESS_SEND_RESULT &&
+	    tlv.result == TEAP_STATUS_SUCCESS) {
+		wpa_printf(MSG_DEBUG,
+			   "EAP-TEAP: Peer agreed with final success - authentication completed");
+		eap_teap_state(data, SUCCESS);
+	} else if (check_crypto_binding && data->state == CRYPTO_BINDING &&
+		   sm->cfg->eap_teap_auth == 1 && data->basic_auth_not_done) {
+		wpa_printf(MSG_DEBUG,
+			   "EAP-TEAP: Continue with basic password authentication for second credential");
+		eap_teap_state(data, PHASE2_BASIC_AUTH);
+	} else if (check_crypto_binding && data->state == CRYPTO_BINDING &&
+		   sm->cfg->eap_teap_auth == 0 && data->inner_eap_not_done) {
+		wpa_printf(MSG_DEBUG,
+			   "EAP-TEAP: Continue with inner EAP authentication for second credential");
+		eap_teap_state(data, PHASE2_ID);
+		if (eap_teap_phase2_init(sm, data, EAP_VENDOR_IETF,
+					 EAP_TYPE_IDENTITY) < 0)
+			eap_teap_state(data, FAILURE);
 	}
 }
 
@@ -1544,7 +1680,7 @@
 		return;
 	}
 
-	in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
+	in_decrypted = tls_connection_decrypt(sm->cfg->ssl_ctx, data->ssl.conn,
 					      in_buf);
 	if (!in_decrypted) {
 		wpa_printf(MSG_INFO,
@@ -1605,7 +1741,7 @@
 		return -1;
 	}
 
-	if (!tls_connection_established(sm->ssl_ctx, data->ssl.conn) ||
+	if (!tls_connection_established(sm->cfg->ssl_ctx, data->ssl.conn) ||
 	    wpabuf_len(data->ssl.tls_out) > 0)
 		return 1;
 
@@ -1622,7 +1758,8 @@
 static int eap_teap_process_phase2_start(struct eap_sm *sm,
 					 struct eap_teap_data *data)
 {
-	u8 next_type;
+	int next_vendor;
+	enum eap_type next_type;
 
 	if (data->identity) {
 		/* Used PAC and identity is from PAC-Opaque */
@@ -1635,38 +1772,43 @@
 			wpa_hexdump_ascii(MSG_DEBUG,
 					  "EAP-TEAP: Phase 2 Identity not found in the user database",
 					  sm->identity, sm->identity_len);
+			next_vendor = EAP_VENDOR_IETF;
 			next_type = EAP_TYPE_NONE;
 			eap_teap_state(data, PHASE2_METHOD);
-		} else if (sm->eap_teap_pac_no_inner) {
+		} else if (sm->cfg->eap_teap_pac_no_inner) {
 			wpa_printf(MSG_DEBUG,
 				   "EAP-TEAP: Used PAC and identity already known - skip inner auth");
+			data->skipped_inner_auth = 1;
 			/* FIX: Need to derive CMK here. However, how is that
 			 * supposed to be done? RFC 7170 does not tell that for
 			 * the no-inner-auth case. */
-			eap_teap_derive_cmk_basic_pw_auth(data->simck_msk,
+			eap_teap_derive_cmk_basic_pw_auth(data->tls_cs,
+							  data->simck_msk,
 							  data->cmk_msk);
 			eap_teap_state(data, CRYPTO_BINDING);
 			return 1;
-		} else if (sm->eap_teap_auth == 1) {
+		} else if (sm->cfg->eap_teap_auth == 1) {
 			eap_teap_state(data, PHASE2_BASIC_AUTH);
 			return 1;
 		} else {
 			wpa_printf(MSG_DEBUG,
 				   "EAP-TEAP: Identity already known - skip Phase 2 Identity Request");
+			next_vendor = sm->user->methods[0].vendor;
 			next_type = sm->user->methods[0].method;
 			sm->user_eap_method_index = 1;
 			eap_teap_state(data, PHASE2_METHOD);
 		}
 
-	} else if (sm->eap_teap_auth == 1) {
+	} else if (sm->cfg->eap_teap_auth == 1) {
 		eap_teap_state(data, PHASE2_BASIC_AUTH);
 		return 0;
 	} else {
 		eap_teap_state(data, PHASE2_ID);
+		next_vendor = EAP_VENDOR_IETF;
 		next_type = EAP_TYPE_IDENTITY;
 	}
 
-	return eap_teap_phase2_init(sm, data, next_type);
+	return eap_teap_phase2_init(sm, data, next_vendor, next_type);
 }
 
 
@@ -1690,6 +1832,7 @@
 	case PHASE2_METHOD:
 	case CRYPTO_BINDING:
 	case REQUEST_PAC:
+	case SUCCESS_SEND_RESULT:
 		eap_teap_process_phase2(sm, data, data->ssl.tls_in);
 		break;
 	case FAILURE_SEND_RESULT:
@@ -1853,7 +1996,8 @@
 
 	/* FIX: RFC 7170 does not describe whether MSK or EMSK based S-IMCK[j]
 	 * is used in this derivation */
-	if (eap_teap_derive_eap_msk(data->simck_msk, eapKeyData) < 0) {
+	if (eap_teap_derive_eap_msk(data->tls_cs, data->simck_msk,
+				    eapKeyData) < 0) {
 		os_free(eapKeyData);
 		return NULL;
 	}
@@ -1877,7 +2021,8 @@
 
 	/* FIX: RFC 7170 does not describe whether MSK or EMSK based S-IMCK[j]
 	 * is used in this derivation */
-	if (eap_teap_derive_eap_emsk(data->simck_msk, eapKeyData) < 0) {
+	if (eap_teap_derive_eap_emsk(data->tls_cs, data->simck_msk,
+				     eapKeyData) < 0) {
 		os_free(eapKeyData);
 		return NULL;
 	}
diff --git a/src/eap_server/eap_server_tls.c b/src/eap_server/eap_server_tls.c
index 0712d4c..c64cebb 100644
--- a/src/eap_server/eap_server_tls.c
+++ b/src/eap_server/eap_server_tls.c
@@ -58,7 +58,7 @@
 {
 	struct wpabuf *buf;
 
-	if (!sm->tls_session_lifetime)
+	if (!sm->cfg->tls_session_lifetime)
 		return;
 
 	buf = wpabuf_alloc(1);
@@ -187,7 +187,8 @@
 	case START:
 		return eap_tls_build_start(sm, data, id);
 	case CONTINUE:
-		if (tls_connection_established(sm->ssl_ctx, data->ssl.conn))
+		if (tls_connection_established(sm->cfg->ssl_ctx,
+					       data->ssl.conn))
 			data->established = 1;
 		break;
 	default:
@@ -267,7 +268,7 @@
 	}
 
 	if (data->ssl.tls_v13 &&
-	    tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
+	    tls_connection_established(sm->cfg->ssl_ctx, data->ssl.conn)) {
 		struct wpabuf *plain, *encr;
 
 		wpa_printf(MSG_DEBUG,
@@ -315,8 +316,8 @@
 		return;
 	}
 
-	if (!tls_connection_established(sm->ssl_ctx, data->ssl.conn) ||
-	    !tls_connection_resumed(sm->ssl_ctx, data->ssl.conn))
+	if (!tls_connection_established(sm->cfg->ssl_ctx, data->ssl.conn) ||
+	    !tls_connection_resumed(sm->cfg->ssl_ctx, data->ssl.conn))
 		return;
 
 	buf = tls_connection_get_success_data(data->ssl.conn);
diff --git a/src/eap_server/eap_server_tls_common.c b/src/eap_server/eap_server_tls_common.c
index 907101c..b38f1e0 100644
--- a/src/eap_server/eap_server_tls_common.c
+++ b/src/eap_server/eap_server_tls_common.c
@@ -18,7 +18,7 @@
 static void eap_server_tls_free_in_buf(struct eap_ssl_data *data);
 
 
-struct wpabuf * eap_tls_msg_alloc(EapType type, size_t payload_len,
+struct wpabuf * eap_tls_msg_alloc(enum eap_type type, size_t payload_len,
 				  u8 code, u8 identifier)
 {
 	if (type == EAP_UNAUTH_TLS_TYPE)
@@ -47,9 +47,9 @@
 			    int verify_peer, int eap_type)
 {
 	u8 session_ctx[8];
-	unsigned int flags = sm->tls_flags;
+	unsigned int flags = sm->cfg->tls_flags;
 
-	if (sm->ssl_ctx == NULL) {
+	if (!sm->cfg->ssl_ctx) {
 		wpa_printf(MSG_ERROR, "TLS context not initialized - cannot use TLS-based EAP method");
 		return -1;
 	}
@@ -57,7 +57,7 @@
 	data->eap = sm;
 	data->phase2 = sm->init_phase2;
 
-	data->conn = tls_connection_init(sm->ssl_ctx);
+	data->conn = tls_connection_init(sm->cfg->ssl_ctx);
 	if (data->conn == NULL) {
 		wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS "
 			   "connection");
@@ -75,17 +75,18 @@
 		flags |= TLS_CONN_DISABLE_SESSION_TICKET;
 	os_memcpy(session_ctx, "hostapd", 7);
 	session_ctx[7] = (u8) eap_type;
-	if (tls_connection_set_verify(sm->ssl_ctx, data->conn, verify_peer,
+	if (tls_connection_set_verify(sm->cfg->ssl_ctx, data->conn, verify_peer,
 				      flags, session_ctx,
 				      sizeof(session_ctx))) {
 		wpa_printf(MSG_INFO, "SSL: Failed to configure verification "
 			   "of TLS peer certificate");
-		tls_connection_deinit(sm->ssl_ctx, data->conn);
+		tls_connection_deinit(sm->cfg->ssl_ctx, data->conn);
 		data->conn = NULL;
 		return -1;
 	}
 
-	data->tls_out_limit = sm->fragment_size > 0 ? sm->fragment_size : 1398;
+	data->tls_out_limit = sm->cfg->fragment_size > 0 ?
+		sm->cfg->fragment_size : 1398;
 	if (data->phase2) {
 		/* Limit the fragment size in the inner TLS authentication
 		 * since the outer authentication with EAP-PEAP does not yet
@@ -99,7 +100,7 @@
 
 void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
 {
-	tls_connection_deinit(sm->ssl_ctx, data->conn);
+	tls_connection_deinit(sm->cfg->ssl_ctx, data->conn);
 	eap_server_tls_free_in_buf(data);
 	wpabuf_free(data->tls_out);
 	data->tls_out = NULL;
@@ -116,7 +117,7 @@
 	if (out == NULL)
 		return NULL;
 
-	if (tls_connection_export_key(sm->ssl_ctx, data->conn, label,
+	if (tls_connection_export_key(sm->cfg->ssl_ctx, data->conn, label,
 				      context, context_len, out, len)) {
 		os_free(out);
 		return NULL;
@@ -170,7 +171,7 @@
 		return id;
 	}
 
-	if (tls_connection_get_random(sm->ssl_ctx, data->conn, &keys))
+	if (tls_connection_get_random(sm->cfg->ssl_ctx, data->conn, &keys))
 		return NULL;
 
 	if (keys.client_random == NULL || keys.server_random == NULL)
@@ -340,29 +341,30 @@
 		WPA_ASSERT(data->tls_out == NULL);
 	}
 
-	data->tls_out = tls_connection_server_handshake(sm->ssl_ctx,
+	data->tls_out = tls_connection_server_handshake(sm->cfg->ssl_ctx,
 							data->conn,
 							data->tls_in, NULL);
 	if (data->tls_out == NULL) {
 		wpa_printf(MSG_INFO, "SSL: TLS processing failed");
 		return -1;
 	}
-	if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
+	if (tls_connection_get_failed(sm->cfg->ssl_ctx, data->conn)) {
 		/* TLS processing has failed - return error */
 		wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to "
 			   "report error");
 		return -1;
 	}
 
-	if (tls_get_version(sm->ssl_ctx, data->conn, buf, sizeof(buf)) == 0) {
+	if (tls_get_version(sm->cfg->ssl_ctx, data->conn,
+			    buf, sizeof(buf)) == 0) {
 		wpa_printf(MSG_DEBUG, "SSL: Using TLS version %s", buf);
 		data->tls_v13 = os_strcmp(buf, "TLSv1.3") == 0;
 	}
 
 	if (!sm->serial_num &&
-	    tls_connection_established(sm->ssl_ctx, data->conn))
-		sm->serial_num = tls_connection_peer_serial_num(sm->ssl_ctx,
-								data->conn);
+	    tls_connection_established(sm->cfg->ssl_ctx, data->conn))
+		sm->serial_num = tls_connection_peer_serial_num(
+			sm->cfg->ssl_ctx, data->conn);
 
 	return 0;
 }
@@ -451,8 +453,7 @@
 {
 	struct wpabuf *buf;
 
-	buf = tls_connection_encrypt(sm->ssl_ctx, data->conn,
-				     plain);
+	buf = tls_connection_encrypt(sm->cfg->ssl_ctx, data->conn, plain);
 	if (buf == NULL) {
 		wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data");
 		return NULL;
@@ -506,7 +507,7 @@
 	if (proc_msg)
 		proc_msg(sm, priv, respData);
 
-	if (tls_connection_get_write_alerts(sm->ssl_ctx, data->conn) > 1) {
+	if (tls_connection_get_write_alerts(sm->cfg->ssl_ctx, data->conn) > 1) {
 		wpa_printf(MSG_INFO, "SSL: Locally detected fatal error in "
 			   "TLS processing");
 		res = -1;
diff --git a/src/eap_server/eap_server_tnc.c b/src/eap_server/eap_server_tnc.c
index b568558..f6cdcb1 100644
--- a/src/eap_server/eap_server_tnc.c
+++ b/src/eap_server/eap_server_tnc.c
@@ -84,8 +84,8 @@
 		return NULL;
 	}
 
-	data->fragment_size = sm->fragment_size > 100 ?
-		sm->fragment_size - 98 : 1300;
+	data->fragment_size = sm->cfg->fragment_size > 100 ?
+		sm->cfg->fragment_size - 98 : 1300;
 
 	return data;
 }
@@ -508,7 +508,7 @@
 		eap_tnc_set_state(data, FAIL);
 		return;
 	}
-		
+
 	if (flags & EAP_TNC_FLAGS_MORE_FRAGMENTS) {
 		if (eap_tnc_process_fragment(data, flags, message_length,
 					     pos, end - pos) < 0)
diff --git a/src/eap_server/eap_server_ttls.c b/src/eap_server/eap_server_ttls.c
index 52bff8a..721835d 100644
--- a/src/eap_server/eap_server_ttls.c
+++ b/src/eap_server/eap_server_ttls.c
@@ -81,7 +81,7 @@
 {
 	struct wpabuf *buf;
 
-	if (!sm->tls_session_lifetime)
+	if (!sm->cfg->tls_session_lifetime)
 		return;
 
 	buf = wpabuf_alloc(1 + 1 + sm->identity_len);
@@ -480,7 +480,8 @@
 	case START:
 		return eap_ttls_build_start(sm, data, id);
 	case PHASE1:
-		if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
+		if (tls_connection_established(sm->cfg->ssl_ctx,
+					       data->ssl.conn)) {
 			wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase1 done, "
 				   "starting Phase2");
 			eap_ttls_state(data, PHASE2_START);
@@ -827,15 +828,14 @@
 
 static int eap_ttls_phase2_eap_init(struct eap_sm *sm,
 				    struct eap_ttls_data *data,
-				    EapType eap_type)
+				    int vendor, enum eap_type 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);
+	data->phase2_method = eap_server_get_eap_method(vendor, eap_type);
 	if (!data->phase2_method)
 		return -1;
 
@@ -850,7 +850,8 @@
 						 struct eap_ttls_data *data,
 						 u8 *in_data, size_t in_len)
 {
-	u8 next_type = EAP_TYPE_NONE;
+	int next_vendor = EAP_VENDOR_IETF;
+	enum eap_type next_type = EAP_TYPE_NONE;
 	struct eap_hdr *hdr;
 	u8 *pos;
 	size_t left;
@@ -875,14 +876,17 @@
 		if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
 		    sm->user->methods[sm->user_eap_method_index].method !=
 		    EAP_TYPE_NONE) {
+			next_vendor = sm->user->methods[
+				sm->user_eap_method_index].vendor;
 			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);
+			wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %u:%u",
+				   next_vendor, next_type);
+			if (eap_ttls_phase2_eap_init(sm, data, next_vendor,
+						     next_type)) {
+				wpa_printf(MSG_DEBUG,
+					   "EAP-TTLS: Failed to initialize EAP type %u:%u",
+					   next_vendor, next_type);
 				eap_ttls_state(data, FAILURE);
 				return;
 			}
@@ -930,12 +934,16 @@
 		}
 
 		eap_ttls_state(data, PHASE2_METHOD);
+		next_vendor = sm->user->methods[0].vendor;
 		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);
+		wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %u:%u",
+			   next_vendor, next_type);
+		if (eap_ttls_phase2_eap_init(sm, data, next_vendor,
+					     next_type)) {
+			wpa_printf(MSG_DEBUG,
+				   "EAP-TTLS: Failed to initialize EAP type %u:%u",
+				   next_vendor, next_type);
 			eap_ttls_state(data, FAILURE);
 		}
 		break;
@@ -962,8 +970,8 @@
 
 	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)
-		{
+		if (eap_ttls_phase2_eap_init(sm, data, EAP_VENDOR_IETF,
+					     EAP_TYPE_IDENTITY) < 0) {
 			wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: failed to "
 				   "initialize EAP-Identity");
 			return;
@@ -1022,7 +1030,7 @@
 		return;
 	}
 
-	in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
+	in_decrypted = tls_connection_decrypt(sm->cfg->ssl_ctx, data->ssl.conn,
 					      in_buf);
 	if (in_decrypted == NULL) {
 		wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 "
@@ -1112,11 +1120,11 @@
 static void eap_ttls_start_tnc(struct eap_sm *sm, struct eap_ttls_data *data)
 {
 #ifdef EAP_SERVER_TNC
-	if (!sm->tnc || data->state != SUCCESS || data->tnc_started)
+	if (!sm->cfg->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)) {
+	if (eap_ttls_phase2_eap_init(sm, data, EAP_VENDOR_IETF, EAP_TYPE_TNC)) {
 		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to initialize TNC");
 		eap_ttls_state(data, FAILURE);
 		return;
@@ -1202,8 +1210,8 @@
 		return;
 	}
 
-	if (!tls_connection_established(sm->ssl_ctx, data->ssl.conn) ||
-	    !tls_connection_resumed(sm->ssl_ctx, data->ssl.conn))
+	if (!tls_connection_established(sm->cfg->ssl_ctx, data->ssl.conn) ||
+	    !tls_connection_resumed(sm->cfg->ssl_ctx, data->ssl.conn))
 		return;
 
 	buf = tls_connection_get_success_data(data->ssl.conn);
diff --git a/src/eap_server/eap_server_wsc.c b/src/eap_server/eap_server_wsc.c
index 4a5cb98..364c089 100644
--- a/src/eap_server/eap_server_wsc.c
+++ b/src/eap_server/eap_server_wsc.c
@@ -103,10 +103,10 @@
 	data->registrar = registrar;
 
 	os_memset(&cfg, 0, sizeof(cfg));
-	cfg.wps = sm->wps;
+	cfg.wps = sm->cfg->wps;
 	cfg.registrar = registrar;
 	if (registrar) {
-		if (sm->wps == NULL || sm->wps->registrar == NULL) {
+		if (!sm->cfg->wps || !sm->cfg->wps->registrar) {
 			wpa_printf(MSG_INFO, "EAP-WSC: WPS Registrar not "
 				   "initialized");
 			os_free(data);
@@ -138,14 +138,14 @@
 		cfg.p2p_dev_addr = p2p_get_go_dev_addr(sm->assoc_p2p_ie);
 	}
 #endif /* CONFIG_P2P */
-	cfg.pbc_in_m1 = sm->pbc_in_m1;
+	cfg.pbc_in_m1 = sm->cfg->pbc_in_m1;
 	data->wps = wps_init(&cfg);
 	if (data->wps == NULL) {
 		os_free(data);
 		return NULL;
 	}
-	data->fragment_size = sm->fragment_size > 0 ? sm->fragment_size :
-		WSC_FRAGMENT_SIZE;
+	data->fragment_size = sm->cfg->fragment_size > 0 ?
+		sm->cfg->fragment_size : WSC_FRAGMENT_SIZE;
 
 	return data;
 }
diff --git a/src/eap_server/eap_tls_common.h b/src/eap_server/eap_tls_common.h
index 74b1c72..b0b7361 100644
--- a/src/eap_server/eap_tls_common.h
+++ b/src/eap_server/eap_tls_common.h
@@ -73,7 +73,7 @@
 #define EAP_WFA_UNAUTH_TLS_TYPE 254
 
 
-struct wpabuf * eap_tls_msg_alloc(EapType type, size_t payload_len,
+struct wpabuf * eap_tls_msg_alloc(enum eap_type type, size_t payload_len,
 				  u8 code, u8 identifier);
 int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
 			    int verify_peer, int eap_type);