eapol/eapol_framework/eapol_common/include/eapol_key_state.h
changeset 0 c8830336c852
child 2 1c7bc153c08e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eapol/eapol_framework/eapol_common/include/eapol_key_state.h	Thu Dec 17 08:47:43 2009 +0200
@@ -0,0 +1,981 @@
+/*
+* Copyright (c) 2001-2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  EAP and WLAN authentication protocols.
+*
+*/
+
+
+
+
+#if !defined(_EAPOL_KEY_STATE_H_)
+#define _EAPOL_KEY_STATE_H_
+
+
+#include "eap_tools.h"
+#include "eap_am_export.h"
+#include "eapol_rsna_key_data_header.h"
+#include "eapol_rsna_key_header.h"
+#include "eap_am_network_id.h"
+#include "eapol_key_types.h"
+
+class abs_eapol_core_c;
+class abs_eapol_key_state_c;
+class eapol_rsna_key_data_payloads_c;
+class eap_core_retransmission_c;
+
+
+#if defined(EAPOL_KEY_TEST_PRIVATE_FUNCTION)
+#define EAP_KEY_TEST_PUBLIC_FUNCTION public:
+#define EAP_KEY_TEST_PRIVATE_FUNCTION private:
+#else
+#define EAP_KEY_TEST_PUBLIC_FUNCTION
+#define EAP_KEY_TEST_PRIVATE_FUNCTION
+#endif // #if defined(EAPOL_KEY_TEST_PRIVATE_FUNCTION)
+
+/** @file */
+
+/**
+ * This is the timer ID used with abs_eap_am_tools_c::set_timer() and abs_eap_am_tools_c::cancel_timer().
+ */
+enum eapol_key_state_timer_id_e
+{
+	EAPOL_KEY_STATE_TIMER_HANDSHAKE_TIMEOUT_ID, ///< See EAPOL_KEY_STATE_TIMER_HANDSHAKE_TIMEOUT_TIMEOUT.
+	EAPOL_KEY_STATE_TIMER_RETRANSMISSION_ID, ///< See EAPOL_KEY_STATE_TIMER_RETRANSMISSION_TIMEOUT.
+	EAPOL_KEY_STATE_TIMER_PMKSA_CACHING_TIMEOUT_ID, ///< See EAPOL_KEY_STATE_TIMER_PMK_CACHING_TIMEOUT.
+	EAPOL_KEY_STATE_TIMER_REASSOCIATE_TIMEOUT_ID, ///<  See EAPOL_KEY_STATE_TIMER_REASSOCIATE_TIMEOUT.
+	EAPOL_KEY_STATE_TIMER_GROUP_KEY_UPDATE_TIMEOUT_ID,  ///<  See EAPOL_KEY_STATE_TIMER_GROUP_KEY_UPDATE_TIMEOUT.
+	EAPOL_KEY_STATE_TIMER_INITIALIZE_4_WAY_HANDSHAKE_TIMEOUT_ID, ///<  See EAPOL_KEY_STATE_TIMER_INITIALIZE_4_WAY_HANDSHAKE_TIMEOUT.
+};
+
+/**
+ * These are the default timeout values.
+ */
+enum eapol_key_state_timer_timeout_value_e
+{
+	EAPOL_KEY_STATE_TIMER_HANDSHAKE_TIMEOUT_TIMEOUT = 20000ul, // milli seconds
+	EAPOL_KEY_STATE_TIMER_RETRANSMISSION_TIMEOUT    = 2000ul, // milli seconds
+	EAPOL_KEY_STATE_RETRANSMISSION_COUNTER          = 3ul,
+	EAPOL_KEY_STATE_TIMER_PMKSA_CACHING_TIMEOUT     = 43200000ul,  // milli seconds = 12 hours
+	EAPOL_KEY_STATE_TIMER_REASSOCIATE_TIMEOUT       = 500ul,  // milli seconds
+	EAPOL_KEY_STATE_TIMER_GROUP_KEY_UPDATE_TIMEOUT  = 0ul, // milli seconds, this is for testing, zero means in test case group key is updated immediately.
+	EAPOL_KEY_STATE_TIMER_INITIALIZE_4_WAY_HANDSHAKE_TIMEOUT = 100ul, // milli seconds before client initializes 4-Way Handshake.
+	EAPOL_KEY_STATE_TIMER_WPXM_CACHE_TIMEOUT       = 1000ul,  // milli seconds, This is short timeout to remove WPXM SA.
+};
+
+
+const u8_t EAPOL_RSNA_PAIRWISE_KEY_EXPANSION_LABEL[] = "Pairwise key expansion";
+const u32_t EAPOL_RSNA_PAIRWISE_KEY_EXPANSION_LABEL_LENGTH = (sizeof(EAPOL_RSNA_PAIRWISE_KEY_EXPANSION_LABEL) - 1ul); // Terminating null is not included.
+
+const u8_t EAPOL_RSNA_PMK_NAME_LABEL[] = "PMK Name";
+const u32_t EAPOL_RSNA_PMK_NAME_LABEL_LENGTH = (sizeof(EAPOL_RSNA_PMK_NAME_LABEL) - 1ul); // Terminating null is not included.
+
+enum eapol_key_wpxm_constant_e
+{
+	eapol_key_constant_wpxm_initial_wpxc_counter_value = 1,
+};
+
+
+//--------------------------------------------------------------------------------------------------
+
+
+/// Class eapol_key_state_c
+/**
+ * This class stores the EAPOL-Key state.
+ */
+class EAP_EXPORT eapol_key_state_c
+: public abs_eap_base_timer_c
+{
+
+public:
+	//--------------------------------------------------
+
+	//--------------------------------------------------
+private:
+	//--------------------------------------------------
+
+	/// This is pointer to the tools class.
+	abs_eap_am_tools_c * const m_am_tools;
+
+	/// This is back pointer to object which created this object.
+	/// Packets are sent to the partner.
+	abs_eapol_key_state_c * const m_key_state_partner;
+
+	/// This is back pointer to object which created eapol_core_c object.
+	/// eapol_key_state_c object sent packets to this object.
+	abs_eapol_core_c * const m_eapol_partner;
+
+	eap_am_network_id_c m_send_network_id;
+
+	/// Authenticator RSN IE. Authenticator sends this in Beacon or Probe message.
+	eap_variable_data_c m_authenticator_RSNA_IE;
+
+	/// If a second RSN IE is provided in the message, the Supplicant shall use
+	// the unicast cipher suite specified in the second RSN IE or deauthenticate.
+	eap_variable_data_c m_unicast_cipher_suite_RSNA_IE;
+
+	/// Supplicant RSN IE. Supplicant sends this in (re)association request message.
+	eap_variable_data_c m_supplicant_RSNA_IE;
+
+	/// Received Pairwise Master Key ID (PMKID). Authenticator sends this in 4-Way Handshake message 1.
+	eap_variable_data_c m_received_PMKID;
+
+	/// This is Supplicant's MAC address. This is given from MAC layer when EAPOL-Key state is initialized.
+	eap_variable_data_c m_supplicant_MAC_address;
+
+	/// This is Authenticator's MAC address. This is given from MAC layer when EAPOL-Key state is initialized.
+	eap_variable_data_c m_authenticator_MAC_address;
+
+	/// This is Athenticator Nonce.
+	eap_variable_data_c m_ANonce;
+
+	/// This is Supplicant Nonce.
+	eap_variable_data_c m_SNonce;
+
+	/// This is EAPOL-Key IV.
+	eap_variable_data_c m_EAPOL_key_IV;
+
+	/// This is the Pairwise Master Key (PMK 802.11i or WPXK3 WPXM) derived from a successful authentication.
+	eap_variable_data_c m_pairwise_PMK_WPXK3;
+
+	/// Pairwise Master Key ID (PMKID). Derived with function:
+	/// PMKID = HMAC-SHA1-128(PMK, "PMK Name" || Authenticator-MAC-Addr || Supplicant-MAC-Addr).
+	eap_variable_data_c m_PMKID;
+
+	/// Pairwise Transient Key (PTK).
+	/// PTK = PRF-X(PMK, "Pairwise key expansion", Min(AA,SA) || Max(AA, SA) || Min(ANonce,SNonce) || Max(ANonce,SNonce)).
+	eap_variable_data_c m_transient_PTK;
+
+	/// EAPOL-Key Confirmation Key (KCK).
+	/// KCK = L(PTK, 0, 128).
+	eap_variable_data_c m_confirmation_KCK;
+
+	/// EAPOL-Key Encryption Key (KEK).
+	/// KEK = L(PTK, 128, 128).
+	eap_variable_data_c m_encryption_KEK;
+
+	/// Temporal Key (TK).
+	/// In TKIP: TK = L(PTK, 256, 256).
+	/// In CCMP: TK = L(PTK, 256, 128).
+	eap_variable_data_c m_temporal_TK;
+
+	/// Group Temporal Key (GTK).
+	/// In TKIP: 256 bits.
+	/// In CCMP: 128 bits.
+	/// In WEP 40: 40 bits.
+	/// In WEP 104: 104 bits.
+	eap_variable_data_c m_group_GTK;
+
+#if defined(EAP_USE_WPXM)
+	eap_variable_data_c m_WPXM_WPXK1;
+	eap_variable_data_c m_WPXM_WPXK2;
+
+	u32_t m_WPXM_WPXC;
+#endif //#if defined(EAP_USE_WPXM)
+
+	bool m_received_802_1x_keys[eapol_key_type_last_type];
+
+	u8_t m_group_GTK_ID;
+
+	bool m_group_GTK_Tx_bit;
+
+	u32_t m_eapol_header_offset;
+
+	u32_t m_MTU;
+
+	u32_t m_trailer_length;
+
+	/// Re-transmission is used to test protocols.
+	/// This stores the information to resent a message. This is used for testing purposes.
+	eap_core_retransmission_c *m_retransmission;
+
+	/// Re-transmission is used to test protocols.
+	/// This is the time after resent a message. This is used for testing purposes.
+	u32_t m_retransmission_time;
+
+	/// Re-transmission is used to test protocols.
+	/// This is the maximum count of retransmission of one message. This is used for testing purposes.
+	u32_t m_retransmission_counter;
+
+	/// This is the maximum time EAPOL-Key Handshake could succeed.
+	/// EAPOl-Key Handshake is terminated after this time elapses.
+	u32_t m_handshake_timeout;
+
+
+#if defined(EAP_USE_WPXM)
+
+	/// This is the maximum time WPXM reassociation could succeed.
+	/// WPXM reassociation is terminated after this time elapses.
+	u32_t m_wpxm_reassociate_timeout;
+
+	/// This is used in test server. WPXM can be configured to to use RSNA or WPA Key descriptor.
+	eapol_key_descriptor_type_e m_EAPOL_WPXM_key_descriptor_type;
+
+#endif //#if defined(EAP_USE_WPXM)
+
+	/// This is the authentication type. One of RSNA, WPA or 802.1X.
+	eapol_key_authentication_type_e m_authentication_type;
+
+	/// This is the selected pairwise cipher.
+	eapol_RSNA_key_header_c::eapol_RSNA_cipher_e m_eapol_pairwise_cipher;
+
+	/// This is the selected group cipher.
+	eapol_RSNA_key_header_c::eapol_RSNA_cipher_e m_eapol_group_cipher;
+
+	/// This is the state of EAPOL-Key Handshake.
+	eapol_key_state_e m_eapol_key_state;
+
+	/// This is the the current running handshake type.
+	eapol_key_handshake_type_e m_eapol_key_handshake_type;
+
+	/// This used in EAPOL key MIC failure tests. Activation requires USE_EAPOL_KEY_TEST_FAILURES compiler flag.
+	eapol_key_state_e m_create_key_failure;
+
+	u32_t m_pmksa_caching_timeout;
+
+	/// This is Key Reply Counter.
+	u64_t m_key_reply_counter;
+
+	/// This is Key Reply Counter for requests that client sends.
+	u64_t m_client_send_key_reply_counter;
+
+	/// This indicates whether this object is client (true) or server (false).
+	/// In terms of EAP-protocol whether this network entity is EAP-supplicant (true) or EAP-authenticator (false).
+	bool m_is_client;
+
+	/// This indicates whether this object was generated successfully.
+	bool m_is_valid;
+
+	/// This flag indicates that this object is marked to removed asynchronously.
+	/// The very same object could be taken use before the removing timer elapses.
+	bool m_marked_removed;
+
+	bool m_shutdown_was_called;
+
+	/// This flag tells whether broken 4-Way Handshake message 1 without PMKID is allowed (true) or dropped (false).
+	/// Default value id false.
+	/// Use configuration option EAPOL_key_state_allow_missing_PMKID_in_message_1 to change this value.
+	bool m_allow_missing_PMKID_in_message_1;
+
+	/// This flag tells whether broken 4-Way Handshake message 1 without PMKID is created in server (true) or not (false).
+	/// Default value id false.
+	/// Use configuration option EAPOL_key_state_skip_PMKID_key_data_in_message_1 to change this value.
+	bool m_skip_PMKID_key_data_in_message_1;
+
+	/// This flag tells whether broken 4-Way Handshake message 1 with non zero MIC or non zero reserved is allowed (true) or dropped (false).
+	/// Default value id false.
+	/// Use configuration option EAPOL_key_state_allow_non_zero_mic_in_message_1 to change this value.
+	bool m_allow_non_zero_mic_and_reserved_in_message_1;
+
+	/// This flag tells the EAPOL must indicate PMKID to lower layers (true) or not (false).
+	/// The configuration option is EAPOL_key_state_indicate_pmkid_to_lower_layer.
+	bool m_indicate_pmkid_to_lower_layer;
+
+	/// This flag tells the handshake timeout is already active (true) or not (false).
+	bool m_handshake_timeout_set;
+
+	/// This flag activates group key update test (true) or not (false).
+	/// The configuration option is EAPOL_key_state_TEST_group_key_update.
+	bool m_server_TEST_group_key_update;
+
+#if defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE)
+	bool m_is_associated;
+#endif //#if defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE)
+
+	// - - - - - - - - - - - - - - - - - - - - - - - -
+
+	enum eapol_key_state_constants_e
+	{
+		eapol_key_state_mppe_key_length_leap                       =  16ul, // LEAP gives only 16 bytes of key material
+		eapol_key_state_mppe_key_length                            =  32ul,
+		EAPOL_RSNA_PMK_LENGTH_BYTES								   =  32ul,
+		EAPOL_RSNA_NONCE_LENGTH_BYTES                              =  32ul,
+		EAPOL_RSNA_4_WAY_HANDSHAKE_MESSAGE_1_KEY_DATA_LENGTH_BYTES = eapol_rsna_key_data_header_c::EAPOL_RSNA_KEY_HEADER_LENGTH
+																	 + eapol_RSNA_key_header_c::EAPOL_RSNA_KEY_DATA_PMKID_SIZE, // sizeof(Key Data Encapsulation header) 6 + sizeof(PMKID) 16
+		EAPOL_RSNA_RC4_KEY_STREAM_DISCARD_LENGTH                   = 256ul,
+		EAPOL_RSNA_TKIP_PTK_LENGTH_BITS                            = 512ul,
+		EAPOL_RSNA_CCMP_PTK_LENGTH_BITS                            = 384ul,
+		EAPOL_RSNA_KCK_LENGTH_BYTES                                =  16ul,
+		EAPOL_RSNA_KEK_LENGTH_BYTES                                =  16ul,
+		EAPOL_RSNA_TK_LENGTH_BYTES								   =  32ul,
+		EAPOL_RSNA_TKIP_TK_LENGTH_BYTES                            =  32ul,
+		EAPOL_RSNA_CCMP_TK_LENGTH_BYTES                            =  16ul,
+		EAPOL_RSNA_KCK_OFFSET_BYTES                                =   0ul,
+		EAPOL_RSNA_KEK_OFFSET_BYTES                                = EAPOL_RSNA_KCK_OFFSET_BYTES + EAPOL_RSNA_KCK_LENGTH_BYTES,
+		EAPOL_RSNA_TK_OFFSET_BYTES                                 = EAPOL_RSNA_KEK_OFFSET_BYTES + EAPOL_RSNA_KEK_LENGTH_BYTES,
+	};
+
+
+	EAP_FUNC_IMPORT eap_status_e trace_eapol_key_message(
+		const i8_t * const prefix,
+		eapol_RSNA_key_header_c * const eapol_key_message);
+
+	eap_status_e trace_eapol_rsna_key_data_payload(
+		const bool is_RSNA,
+		const bool is_WPXM,
+		const eapol_key_descriptor_type_e eapol_key_descriptor_type,
+		const i8_t * const prefix,
+		const eapol_rsna_key_data_header_c * const key_data_payload,
+		const u32_t buffer_length);
+
+#if defined(USE_EAP_TRACE)
+
+	#define TRACE_EAPOL_KEY_MESSAGE(prefix, eapol_key_message) \
+			trace_eapol_key_message(prefix, eapol_key_message)
+
+	#define EAPOL_RSNA_KEY_DATA_TRACE_PAYLOAD(is_RSNA, is_WPXM, eapol_key_descriptor_type, prefix, key_data_payload, buffer_length) \
+			trace_eapol_rsna_key_data_payload(is_RSNA, is_WPXM, eapol_key_descriptor_type, prefix, key_data_payload, buffer_length)
+
+#else
+
+	#define TRACE_EAPOL_KEY_MESSAGE(prefix, eapol_key_message)
+
+	#define EAPOL_RSNA_KEY_DATA_TRACE_PAYLOAD(is_RSNA, is_WPXM, eapol_key_descriptor_type, prefix, key_data_payload, buffer_length)
+
+#endif //#if defined(USE_EAP_TRACE) || defined(USE_EAP_TRACE_ALWAYS)
+
+
+	eap_status_e handshake_failure_notification();
+
+	eap_status_e set_mac_addresses(
+		const eap_am_network_id_c * const receive_network_id);
+
+	EAP_FUNC_IMPORT eap_status_e save_parameters(
+		const eapol_key_authentication_type_e authentication_type,
+		const eap_variable_data_c * const authenticator_RSNA_IE,
+		const eap_variable_data_c * const supplicant_RSNA_IE,
+		const eapol_RSNA_key_header_c::eapol_RSNA_cipher_e eapol_pairwise_cipher,
+		const eapol_RSNA_key_header_c::eapol_RSNA_cipher_e eapol_group_cipher);
+
+	eap_status_e packet_data_session_key(
+		eap_variable_data_c * const key, ///< Here is the key.
+		const eapol_key_type_e key_type, ///< This the type of the key.
+		const u32_t key_index, ///< This is the index of the key.
+		const bool key_tx_bit, ///< This is the TX bit of the key.
+		const u8_t * const key_RSC, ///< This is the RSC counter
+		const u32_t key_RSC_size ///< This is the size of RSC counter
+		);
+
+	EAP_FUNC_IMPORT eap_status_e check_is_aes_key_wrap_padding(
+		const eapol_RSNA_key_descriptor_type_e current_key_data_type,
+		eapol_rsna_key_data_header_c * const key_data_payload,
+		const u32_t key_data_max_length
+		);
+
+	EAP_FUNC_IMPORT eap_status_e parse_generic_key_data_payload(
+		const eapol_key_descriptor_type_e key_descriptor_type,
+		const eapol_RSNA_key_descriptor_type_e current_key_data_payload,
+		eapol_rsna_key_data_header_c * const key_data_payload,
+		u32_t * const key_data_max_length,
+		eapol_rsna_key_data_payloads_c * const p_rsna_key_data_payloads,
+		const eapol_key_state_e expected_key_message);
+
+	EAP_FUNC_IMPORT eap_status_e parse_key_data(
+		const eapol_key_descriptor_type_e key_descriptor_type,
+		const eapol_rsna_key_data_header_c * const p_payload,
+		u32_t * const buffer_length,
+		eapol_rsna_key_data_payloads_c * const p_rsna_key_data_payloads,
+		const eapol_key_state_e expected_key_message,
+		const eapol_RSNA_key_header_c::key_descriptor_version_e key_descriptor_version);
+
+	EAP_FUNC_IMPORT eap_status_e rsna_prf(
+		const eap_variable_data_c * const key_K,
+		const eap_variable_data_c * const label_A,
+		const eap_variable_data_c * const input_B,
+		const u32_t output_length,
+		eap_variable_data_c * const output
+		);
+
+	EAP_FUNC_IMPORT eap_status_e select_minimum(
+		const eap_variable_data_c * const input_a,
+		const eap_variable_data_c * const input_b,
+		const eap_variable_data_c ** const minimum,
+		const eap_variable_data_c ** const maximum);
+
+
+	EAP_FUNC_IMPORT eap_status_e create_PMKID();
+
+	eap_status_e set_reassociation_parameters(
+		const eap_variable_data_c * const pairwise_PMK_WPXK3,
+		const eap_variable_data_c * const PMKID,
+		const eap_variable_data_c * const transient_PTK,
+		const eap_variable_data_c * const confirmation_KCK,
+		const eap_variable_data_c * const encryption_KEK,
+		const eap_variable_data_c * const temporal_TK,
+		const eap_variable_data_c * const WPXM_WPXK1,
+		const eap_variable_data_c * const WPXM_WPXK2,
+		const u32_t WPXM_WPXC,
+		const eapol_key_handshake_type_e eapol_key_handshake_type,
+		const eapol_key_authentication_type_e authentication_type
+		);
+
+	eap_status_e send_RC4_eapol_key_message(
+		const eapol_RC4_key_flags_e flags);
+
+	void send_error_notification(const eap_status_e error);
+
+	eap_status_e save_keys_for_test_use(
+		const eap_variable_data_c * const confirmation_KCK,
+		const eap_variable_data_c * const encryption_KEK,
+		const eap_variable_data_c * const temporal_TK,
+		const u32_t WPXM_WPXC);
+
+EAP_KEY_TEST_PUBLIC_FUNCTION
+
+
+	EAP_FUNC_IMPORT eap_status_e derive_PTK();
+
+
+EAP_KEY_TEST_PRIVATE_FUNCTION
+
+
+	EAP_FUNC_IMPORT eap_status_e derive_WPXM_WPXK1_WPXK2();
+
+	EAP_FUNC_IMPORT eap_status_e derive_WPXM_PTK(const u32_t WPXM_WPXC);
+
+	EAP_FUNC_IMPORT eap_status_e verify_field_is_zero(
+		const u8_t * const field,
+		const u32_t field_length);
+
+	EAP_FUNC_IMPORT eap_status_e encrypt_key_data(
+		eapol_RSNA_key_header_c * const eapol_key_message);
+
+	EAP_FUNC_IMPORT eap_status_e decrypt_key_data(
+		eapol_RSNA_key_header_c * const eapol_key_message);
+
+
+	EAP_FUNC_IMPORT eap_status_e create_key_mic(
+		eapol_RSNA_key_header_c * const eapol_key_message,
+		const eap_variable_data_c * const confirmation_key);
+
+	EAP_FUNC_IMPORT eap_status_e verify_key_mic(
+		eapol_RSNA_key_header_c * const eapol_key_message,
+		const eap_variable_data_c * const confirmation_key);
+
+
+	EAP_FUNC_IMPORT eap_status_e create_nonce(
+		eap_variable_data_c * const nonce,
+		const u32_t nonce_length);
+
+	EAP_FUNC_IMPORT eap_status_e initialize_4_way_handshake(
+		const eap_am_network_id_c * const receive_network_id,
+		const eapol_protocol_version_e received_eapol_version);
+
+	EAP_FUNC_IMPORT eap_status_e create_4_way_handshake_message_1(
+		eap_buf_chain_wr_c * const sent_packet,
+		const u32_t eapol_header_offset,
+		u32_t * const data_length,
+		u32_t * const buffer_length,
+		const eapol_protocol_version_e received_eapol_version,
+		const eapol_key_descriptor_type_e received_key_descriptor_type);
+
+	EAP_FUNC_IMPORT eap_status_e create_4_way_handshake_message_2(
+		eap_buf_chain_wr_c * const sent_packet,
+		const u32_t eapol_header_offset,
+		u32_t * const data_length,
+		u32_t * const buffer_length,
+		const u64_t received_key_replay_counter,
+		const eapol_protocol_version_e received_eapol_version,
+		const eapol_key_descriptor_type_e received_key_descriptor_type);
+
+	EAP_FUNC_IMPORT eap_status_e create_4_way_handshake_message_3(
+		eap_buf_chain_wr_c * const sent_packet,
+		const u32_t eapol_header_offset,
+		u32_t * const data_length,
+		u32_t * const buffer_length,
+		const eapol_protocol_version_e received_eapol_version,
+		const eapol_key_descriptor_type_e received_key_descriptor_type);
+
+	EAP_FUNC_IMPORT eap_status_e create_4_way_handshake_message_4(
+		eap_buf_chain_wr_c * const sent_packet,
+		const u32_t eapol_header_offset,
+		u32_t * const data_length,
+		u32_t * const buffer_length,
+		const u64_t received_key_replay_counter,
+		const bool received_secure_bit,
+		const eapol_protocol_version_e received_eapol_version,
+		const eapol_key_descriptor_type_e received_key_descriptor_type);
+
+	EAP_FUNC_IMPORT eap_status_e process_4_way_handshake_message_2_payloads(
+		const eap_am_network_id_c * const receive_network_id,
+		eapol_RSNA_key_header_c * const eapol_key_message,
+		const u32_t packet_length);
+
+	EAP_FUNC_IMPORT eap_status_e process_4_way_handshake_message_3_payloads_a(
+		const eap_am_network_id_c * const receive_network_id,
+		eapol_RSNA_key_header_c * const eapol_key_message,
+		const u32_t packet_length,
+		bool * const group_key_received);
+
+	EAP_FUNC_IMPORT eap_status_e process_4_way_handshake_message_3_payloads_b(
+		const eap_am_network_id_c * const receive_network_id,
+		eapol_RSNA_key_header_c * const eapol_key_message,
+		const u32_t packet_length,
+		const bool group_key_received);
+
+	EAP_FUNC_IMPORT eap_status_e process_4_way_handshake_message_0(
+		const eap_am_network_id_c * const receive_network_id,
+		eapol_RSNA_key_header_c * const eapol_key_message,
+		const u32_t packet_length);
+
+	EAP_FUNC_IMPORT eap_status_e process_4_way_handshake_message_1(
+		const eap_am_network_id_c * const receive_network_id,
+		eapol_RSNA_key_header_c * const eapol_key_message,
+		const u32_t packet_length);
+
+	EAP_FUNC_IMPORT eap_status_e process_4_way_handshake_message_2(
+		const eap_am_network_id_c * const receive_network_id,
+		eapol_RSNA_key_header_c * const eapol_key_message,
+		const u32_t packet_length);
+
+	EAP_FUNC_IMPORT eap_status_e process_4_way_handshake_message_3(
+		const eap_am_network_id_c * const receive_network_id,
+		eapol_RSNA_key_header_c * const eapol_key_message,
+		const u32_t packet_length);
+
+	EAP_FUNC_IMPORT eap_status_e process_4_way_handshake_message_4(
+		const eap_am_network_id_c * const receive_network_id,
+		eapol_RSNA_key_header_c * const eapol_key_message,
+		const u32_t packet_length);
+
+
+	EAP_FUNC_IMPORT eap_status_e start_group_key_handshake(
+		const eap_am_network_id_c * const receive_network_id,
+		const eapol_protocol_version_e received_eapol_version,
+		const eapol_key_descriptor_type_e received_key_descriptor_type);
+
+	EAP_FUNC_IMPORT eap_status_e process_group_key_handshake_message_0(
+		const eap_am_network_id_c * const receive_network_id,
+		eapol_RSNA_key_header_c * const eapol_key_message,
+		const u32_t packet_length);
+
+	EAP_FUNC_IMPORT eap_status_e process_group_key_handshake_message_1(
+		const eap_am_network_id_c * const receive_network_id,
+		eapol_RSNA_key_header_c * const eapol_key_message,
+		const u32_t packet_length);
+
+	EAP_FUNC_IMPORT eap_status_e process_group_key_handshake_message_2(
+		const eap_am_network_id_c * const receive_network_id,
+		eapol_RSNA_key_header_c * const eapol_key_message,
+		const u32_t packet_length);
+
+
+	EAP_FUNC_IMPORT eap_status_e create_eapol_key_handshake_message_0(
+		const bool true_when_4_way_handshake, ///< With false initiates Group Key Handshake.
+		eap_buf_chain_wr_c * const sent_packet,
+		const u32_t eapol_header_offset,
+		u32_t * const data_length,
+		u32_t * const buffer_length,
+		const u64_t received_key_replay_counter,
+		const eapol_protocol_version_e received_eapol_version);
+
+	EAP_FUNC_IMPORT eap_status_e create_group_key_handshake_message_1(
+		eap_buf_chain_wr_c * const sent_packet,
+		const u32_t eapol_header_offset,
+		u32_t * const data_length,
+		u32_t * const buffer_length,
+		const eapol_protocol_version_e received_eapol_version,
+		const eapol_key_descriptor_type_e received_key_descriptor_type);
+
+	EAP_FUNC_IMPORT eap_status_e create_group_key_handshake_message_2(
+		eap_buf_chain_wr_c * const sent_packet,
+		const u32_t eapol_header_offset,
+		u32_t * const data_length,
+		u32_t * const buffer_length,
+		const u64_t received_key_replay_counter,
+		const eapol_protocol_version_e received_eapol_version,
+		const eapol_key_descriptor_type_e received_key_descriptor_type);
+
+
+	EAP_FUNC_IMPORT eap_status_e process_4_way_handshake_message(
+		const eap_am_network_id_c * const receive_network_id,
+		eapol_RSNA_key_header_c * const eapol_key_message,
+		const u32_t packet_length);
+
+	EAP_FUNC_IMPORT eap_status_e process_group_key_handshake_message(
+		const eap_am_network_id_c * const receive_network_id,
+		eapol_RSNA_key_header_c * const eapol_key_message,
+		const u32_t packet_length);
+
+	EAP_FUNC_IMPORT eap_status_e process_RSNA_key_descriptor(
+		const eap_am_network_id_c * const receive_network_id,
+		eap_general_header_base_c * const packet_data,
+		const u32_t packet_length);
+
+	EAP_FUNC_IMPORT eap_status_e process_RC4_key_descriptor(
+		const eap_am_network_id_c * const receive_network_id,
+		eap_general_header_base_c * const packet_data,
+		const u32_t packet_length);
+
+	// This is documented in abs_eap_stack_interface_c::set_is_valid().
+	EAP_FUNC_IMPORT void set_is_valid();
+
+	// 
+	EAP_FUNC_IMPORT eap_variable_data_c * get_authenticator_RSNA_IE();
+
+	// 
+	EAP_FUNC_IMPORT eap_variable_data_c * get_unicast_cipher_suite_RSNA_IE();
+
+	// 
+	EAP_FUNC_IMPORT eap_variable_data_c * get_supplicant_RSNA_IE();
+
+	// 
+	EAP_FUNC_IMPORT eap_variable_data_c * get_received_PMKID();
+
+	// 
+	EAP_FUNC_IMPORT eap_variable_data_c * get_supplicant_MAC_address();
+
+	// 
+	EAP_FUNC_IMPORT eap_variable_data_c * get_authenticator_MAC_address();
+
+	// 
+	EAP_FUNC_IMPORT u64_t get_key_reply_counter();
+
+	// 
+	EAP_FUNC_IMPORT void increase_key_reply_counter();
+
+	//
+	EAP_FUNC_IMPORT void set_key_reply_counter(
+		const u64_t reply_counter);
+
+	//
+	EAP_FUNC_IMPORT u64_t get_client_send_key_reply_counter();
+
+	//
+	EAP_FUNC_IMPORT void increase_client_send_key_reply_counter();
+
+	//
+	EAP_FUNC_IMPORT void set_client_send_key_reply_counter(
+		const u64_t reply_counter);
+
+	// 
+	EAP_FUNC_IMPORT eap_variable_data_c * get_ANonce();
+
+	// 
+	EAP_FUNC_IMPORT eap_variable_data_c * get_SNonce();
+
+	// 
+	EAP_FUNC_IMPORT eap_variable_data_c * get_confirmation_KCK();
+
+	// 
+	EAP_FUNC_IMPORT eap_variable_data_c * get_encryption_KEK();
+
+	//
+	EAP_FUNC_IMPORT void set_eapol_key_state(const eapol_key_state_e state);
+
+	//
+	EAP_FUNC_IMPORT eapol_key_state_e get_eapol_key_state() const;
+
+	EAP_FUNC_IMPORT eap_status_e asynchronous_init_remove_eapol_key_state();
+
+	//
+	EAP_FUNC_IMPORT eap_status_e packet_send(
+		const eap_am_network_id_c * const send_network_id,
+		eap_buf_chain_wr_c * const sent_packet,
+		const u32_t header_offset,
+		const u32_t data_length,
+		const u32_t buffer_length);
+
+	//
+	EAP_FUNC_IMPORT eap_status_e resend_packet(
+		const eap_am_network_id_c * const send_network_id,
+		eap_buf_chain_wr_c * const sent_packet,
+		const u32_t header_offset,
+		const u32_t data_length,
+		const u32_t buffer_length);
+
+	//
+	EAP_FUNC_IMPORT eap_status_e cancel_retransmission();
+
+
+	//
+	EAP_FUNC_IMPORT eap_status_e cancel_handshake_timeout();
+
+	//
+	EAP_FUNC_IMPORT eap_status_e init_handshake_timeout(
+		const u32_t timeout);
+
+
+	//
+	eap_status_e cancel_reassociate_timeout();
+
+	//
+	eap_status_e init_reassociate_timeout(
+		const u32_t timeout);
+
+
+	eap_status_e cancel_4_way_handshake_start_timeout();
+
+	eap_status_e init_4_way_handshake_start_timeout();
+
+	//
+	EAP_FUNC_IMPORT eap_status_e cancel_pmksa_caching_timeout();
+
+	//
+	EAP_FUNC_IMPORT eap_status_e init_retransmission(
+		const eap_am_network_id_c * const send_network_id,
+		eap_buf_chain_wr_c * const sent_packet,
+		const u32_t header_offset,
+		const u32_t data_length,
+		const eap_code_value_e eap_code,
+		const u8_t eap_identifier,
+		const eap_type_value_e eap_type
+		);
+
+	EAP_FUNC_IMPORT eap_status_e cancel_group_key_update_timeout();
+
+	EAP_FUNC_IMPORT eap_status_e init_group_key_update_timeout(
+		const u32_t timeout);
+
+	//
+	EAP_FUNC_IMPORT eap_status_e create_tkip_mic_failure_message(
+		eap_buf_chain_wr_c * const sent_packet,
+		const u32_t eapol_header_offset,
+		u32_t * const data_length,
+		u32_t * const buffer_length,
+		const eapol_RSNA_key_header_c::eapol_tkip_mic_failure_type_e tkip_mic_failure_type,
+		const eapol_protocol_version_e received_eapol_version);
+
+
+	EAP_FUNC_IMPORT bool get_is_RSNA();
+
+	EAP_FUNC_IMPORT bool get_is_WPA();
+
+	EAP_FUNC_IMPORT bool get_is_WPXM();
+
+
+	EAP_FUNC_IMPORT eap_status_e add_RSN_GTK_payload(
+		const eapol_RSNA_key_header_c * const eapol_key_message,
+		eap_variable_data_c * const group_GTK,
+		u32_t * const eapol_data_length);
+
+	EAP_FUNC_IMPORT eap_status_e add_RSN_IE_payload(
+		const eapol_RSNA_key_header_c * const eapol_key_message,
+		eap_variable_data_c * const RSNA_IE,
+		u32_t * const eapol_data_length);
+
+	EAP_FUNC_IMPORT eap_status_e get_key_length(
+		const eapol_RSNA_key_header_c::eapol_RSNA_cipher_e cipher,
+		u16_t * const key_length);
+
+	EAP_FUNC_IMPORT eap_status_e send_RC4_eapol_key_messages();
+
+	//--------------------------------------------------
+protected:
+	//--------------------------------------------------
+
+	//--------------------------------------------------
+public:
+	//--------------------------------------------------
+
+	// 
+	EAP_FUNC_IMPORT virtual ~eapol_key_state_c();
+
+	// 
+	EAP_FUNC_IMPORT eapol_key_state_c(
+		abs_eap_am_tools_c * const tools,
+		abs_eapol_key_state_c * const key_state_partner,
+		abs_eapol_core_c * const eapol_partner,
+		const bool is_client_when_true,
+		const eap_am_network_id_c * const receive_network_id,
+		const eapol_key_authentication_type_e authentication_type,
+		const eap_variable_data_c * const authenticator_RSNA_IE,
+		const eap_variable_data_c * const supplicant_RSNA_IE,
+		const eapol_RSNA_key_header_c::eapol_RSNA_cipher_e eapol_pairwise_cipher,
+		const eapol_RSNA_key_header_c::eapol_RSNA_cipher_e eapol_group_cipher,
+		const eap_variable_data_c * const pre_shared_key);
+
+	// 
+	EAP_FUNC_IMPORT eapol_key_state_c(
+		abs_eap_am_tools_c * const tools,
+		abs_eapol_key_state_c * const key_state_partner,
+		abs_eapol_core_c * const eapol_partner,
+		const bool is_client_when_true,
+		const eap_am_network_id_c * const receive_network_id,
+		const eapol_key_authentication_type_e authentication_type);
+
+
+	EAP_FUNC_IMPORT eap_status_e initialize(
+		const eap_am_network_id_c * const receive_network_id,
+		const eapol_key_authentication_type_e authentication_type,
+		const eap_variable_data_c * const authenticator_RSNA_IE,
+		const eap_variable_data_c * const supplicant_RSNA_IE,
+		const eapol_RSNA_key_header_c::eapol_RSNA_cipher_e eapol_pairwise_cipher,
+		const eapol_RSNA_key_header_c::eapol_RSNA_cipher_e eapol_group_cipher,
+		const eap_variable_data_c * const pre_shared_key);
+
+#if defined(USE_EAPOL_KEY_STATE) && defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE)
+
+	EAP_FUNC_IMPORT eap_status_e initialize(
+		const eap_am_network_id_c * const receive_network_id,
+		const eapol_key_authentication_type_e authentication_type);
+
+#endif //#if defined(USE_EAPOL_KEY_STATE) && defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE)
+
+	EAP_FUNC_IMPORT eapol_key_state_c *copy(const eap_am_network_id_c * const receive_network_id);
+
+	EAP_FUNC_IMPORT bool get_is_encryption_on();
+
+
+#if defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE)
+
+	EAP_FUNC_IMPORT bool get_is_associated();
+
+#endif //#if defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE)
+
+
+	//
+	EAP_FUNC_IMPORT eap_status_e started_eap_authentication();
+
+	/**
+	 * This function checks whether cached PMKSA have correct cipher suite.
+	 */
+	EAP_FUNC_IMPORT eap_status_e check_pmksa_cache(
+		const eapol_key_authentication_type_e selected_eapol_key_authentication_type,
+		const eapol_RSNA_key_header_c::eapol_RSNA_cipher_e pairwise_key_cipher_suite,
+		const eapol_RSNA_key_header_c::eapol_RSNA_cipher_e group_key_cipher_suite);
+
+	EAP_FUNC_IMPORT eap_status_e initialize_preauthentication(
+		const eap_am_network_id_c * const receive_network_id,
+		const eapol_key_authentication_type_e authentication_type);
+
+	EAP_FUNC_IMPORT eap_status_e read_reassociation_parameters(
+		const eap_am_network_id_c * const receive_network_id, ///< source includes remote address, destination includes local address.
+		const eapol_key_authentication_type_e authentication_type,
+		eap_variable_data_c * const PMKID,
+		const eap_variable_data_c * const received_WPA_ie,
+		const eap_variable_data_c * const sent_WPA_ie);
+
+	EAP_FUNC_IMPORT eap_status_e complete_reassociation(
+		const eapol_wlan_authentication_state_e reassociation_result,
+		const eap_am_network_id_c * const receive_network_id,
+		const eapol_key_authentication_type_e authentication_type,
+		const eap_variable_data_c * const received_WPA_IE, // WLM must give only the WPA IE to EAPOL
+		const eap_variable_data_c * const sent_WPA_IE,
+		const eapol_RSNA_key_header_c::eapol_RSNA_cipher_e pairwise_key_cipher_suite,
+		const eapol_RSNA_key_header_c::eapol_RSNA_cipher_e group_key_cipher_suite);
+
+	EAP_FUNC_IMPORT eap_status_e start_WPXM_reassociation(
+		const eap_am_network_id_c * const receive_network_id,
+		const eapol_key_authentication_type_e authentication_type,
+		eap_variable_data_c * const send_reassociation_request_ie);
+
+	EAP_FUNC_IMPORT eap_status_e complete_WPXM_reassociation(
+		const eapol_wlan_authentication_state_e reassociation_result,
+		const eap_am_network_id_c * const receive_network_id,
+		const eapol_key_authentication_type_e authentication_type,
+		const eap_variable_data_c * const received_reassociation_ie);
+
+	EAP_FUNC_IMPORT eap_status_e configure();
+
+	EAP_FUNC_IMPORT eap_status_e shutdown();
+
+	EAP_FUNC_IMPORT eap_status_e set_WPXM_parameters(
+		const eap_am_network_id_c * const receive_network_id);
+
+	EAP_FUNC_IMPORT eap_status_e set_s_nonce(
+		const eap_variable_data_c * const s_nonce);
+
+	EAP_FUNC_IMPORT eap_status_e set_pairwise_PMK(
+		const eap_variable_data_c * const key,
+		const eap_am_network_id_c * const send_network_id);
+
+	EAP_FUNC_IMPORT eap_status_e allow_4_way_handshake();
+
+	EAP_FUNC_IMPORT eap_status_e start_4_way_handshake(
+		const eap_am_network_id_c * const receive_network_id);
+
+	// 
+	EAP_FUNC_IMPORT eap_status_e process_eapol_key_frame(
+		const eap_am_network_id_c * const receive_network_id,
+		eap_general_header_base_c * const packet_data,
+		const u32_t packet_length);
+
+	// This is documented in abs_eap_stack_interface_c::get_is_valid().
+	EAP_FUNC_IMPORT bool get_is_valid();
+
+	/**
+	 * The object_increase_reference_count() function increases the reference count.
+	 */
+	EAP_FUNC_IMPORT void object_increase_reference_count();
+
+	/**
+	 * The object_decrease_reference_count () function decreases 
+	 * the reference count and returns the remaining value.
+	 * The EAP type is removed after there is no references to it.
+	 */
+	EAP_FUNC_IMPORT u32_t object_decrease_reference_count();
+
+	// See abs_eap_base_timer_c::timer_expired().
+	EAP_FUNC_IMPORT eap_status_e timer_expired(
+		const u32_t id, void *data);
+
+	// See abs_eap_base_timer_c::timer_delete_data().
+	EAP_FUNC_IMPORT eap_status_e timer_delete_data(
+		const u32_t id, void *data);
+
+	/**
+	 * Gets flag whether this session is marked removed.
+	 * Session is removed later if it is not reused.
+	 */
+	EAP_FUNC_IMPORT bool get_marked_removed();
+
+	/**
+	 * Marks this session removed.
+	 * Session is removed later if it is not reused.
+	 */
+	EAP_FUNC_IMPORT void set_marked_removed();
+
+	/**
+	 * Marks this session not removed.
+	 * Session is not removed it is reused.
+	 */
+	EAP_FUNC_IMPORT void unset_marked_removed();
+
+	/**
+	 * This function resets object partially.
+	 * Member attributes needed in reassociation are left untouched.
+	 */
+	EAP_FUNC_IMPORT eap_status_e reset_cached_pmksa();
+
+	/**
+	 * This function resets the full state of object to same as 
+	 * state was after the configure() function call.
+	 * If object reset succeeds this function must return eap_status_ok.
+	 * If object reset fails this function must return corresponding error status.
+	 * @return This function returns the status of reset operation.
+	 */
+	EAP_FUNC_IMPORT eap_status_e reset();
+
+	EAP_FUNC_IMPORT eap_status_e tkip_mic_failure(
+		const bool fatal_failure_when_true,
+		const eapol_RSNA_key_header_c::eapol_tkip_mic_failure_type_e tkip_mic_failure_type);
+
+	//
+	EAP_FUNC_IMPORT eap_status_e init_pmksa_caching_timeout();
+
+	//
+	EAP_FUNC_IMPORT eap_status_e cancel_authentication_session();
+
+	//--------------------------------------------------
+}; // class eapol_key_state_c
+
+
+//--------------------------------------------------
+
+#endif //#if !defined(_EAPOL_KEY_STATE_H_)
+
+//--------------------------------------------------
+
+
+// End.