eapol/eapol_framework/eapol_common/type/simple_config/simple_config/src/simple_config_record.cpp
changeset 0 c8830336c852
child 2 1c7bc153c08e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eapol/eapol_framework/eapol_common/type/simple_config/simple_config/src/simple_config_record.cpp	Thu Dec 17 08:47:43 2009 +0200
@@ -0,0 +1,8230 @@
+/*
+* 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.
+*
+*/
+
+
+// This is enumeration of EAPOL source code.
+#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
+	#undef EAP_FILE_NUMBER_ENUM
+	#define EAP_FILE_NUMBER_ENUM 601 
+	#undef EAP_FILE_NUMBER_DATE 
+	#define EAP_FILE_NUMBER_DATE 1127594498 
+#endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
+
+#if defined(USE_EAP_SIMPLE_CONFIG)
+
+#include "eap_am_memory.h"
+#include "eap_am_export.h"
+#include "eap_am_tools.h"
+#include "eap_tools.h"
+#include "eap_crypto_api.h"
+#include "abs_simple_config_base_record.h"
+#include "simple_config_base_record.h"
+#include "simple_config_record.h"
+#include "simple_config_am_services.h"
+#include "simple_config_types.h"
+#include "simple_config_message.h"
+#include "eap_automatic_variable.h"
+#include "eap_state_notification.h"
+#include "eap_type_simple_config_types.h"
+#include "eap_header_string.h"
+#include "abs_eap_am_mutex.h"
+#include "simple_config_credential.h"
+#include "eapol_key_types.h"
+
+//--------------------------------------------------
+
+
+EAP_FUNC_EXPORT simple_config_record_c::~simple_config_record_c()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT,
+					(EAPL("%s: function: simple_config_record_c::~simple_config_record_c(): this = 0x%08x, m_am_simple_config_services")
+					 EAPL(" = 0x%08x (validity %d).\n"),
+					 (m_is_client == true ? "client": "server"),
+					 this,
+					 m_am_simple_config_services,
+					 m_am_simple_config_services->get_is_valid()));
+
+	EAP_ASSERT(m_shutdown_was_called == true);
+
+	completion_action_clenup();
+
+	if (m_free_am_simple_config_services == true)
+	{
+		delete m_am_simple_config_services;
+	}
+	m_am_simple_config_services = 0;
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+#if defined(_WIN32) && !defined(__GNUC__)
+	#pragma warning( disable : 4355 ) // 'this' : used in base member initializer list
+#endif
+
+EAP_FUNC_EXPORT simple_config_record_c::simple_config_record_c(
+	abs_eap_am_tools_c * const tools, ///< tools is pointer to the tools class. @see abs_eap_am_tools_c.
+	simple_config_am_services_c * const am_simple_config_services, ///< This is pointer to adaptation module of SIMPLE_CONFIG.
+	const bool free_am_simple_config_services,
+	const bool is_client_when_true, ///< Indicates whether this is client (true) or server (false).
+	const eap_am_network_id_c * const receive_network_id)
+	: simple_config_base_record_c(tools /*, partner */)
+	, m_am_tools(tools)
+	, m_am_simple_config_services(am_simple_config_services)
+	, m_free_am_simple_config_services(free_am_simple_config_services)
+	, m_completion_queue(tools)
+	, m_M2D_payloads(tools)
+	, m_received_simple_config_message(tools, is_client_when_true)
+	, m_received_payloads(tools)
+	, m_previous_simple_config_message(tools, is_client_when_true)
+	, m_new_simple_config_message(tools, is_client_when_true)
+	, m_current_simple_config_message_type(simple_config_Message_Type_None)
+	, m_enrollee_nonce(tools)
+	, m_enrollee_mac(tools)
+	, m_registrar_nonce(tools)
+	, m_device_password(tools)
+	, m_PSK1(tools)
+	, m_PSK2(tools)
+	, m_E_SNonce1(tools)
+	, m_E_SNonce2(tools)
+	, m_EHash1(tools)
+	, m_EHash2(tools)
+	, m_R_SNonce1(tools)
+	, m_R_SNonce2(tools)
+	, m_RHash1(tools)
+	, m_RHash2(tools)
+	, m_own_private_dhe_key(tools)
+	, m_own_public_dhe_key(tools)
+	, m_peer_public_dhe_key(tools)
+	, m_shared_dh_key(tools)
+	, m_dhe_prime(tools)
+	, m_dhe_group_generator(tools)
+	, m_kdk(tools)
+	, m_auth_key(tools)
+	, m_key_wrap_key(tools)
+	, m_EMSK(tools)
+	, m_SSID(tools)
+	, m_signed_message_hash(tools)
+	, m_NAI(tools)
+	, m_NAI_realm(tools)
+	, m_send_network_id(tools)
+#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+	, m_network_key(tools)
+	, m_authentication_type(simple_config_Authentication_Type_None)
+#endif //#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+	, m_simple_config_state(simple_config_state_wait_simple_config_start)
+	, m_handshake_error(eap_status_ok)
+	, m_UUID_E(tools)
+	, m_UUID_R(tools)
+	, m_Rf_Bands(simple_config_RF_Bands_2_4_GHz)
+	, m_MAC_address(tools)
+	, m_local_Device_Password_ID(simple_config_Device_Password_ID_Default_PIN)
+	, m_received_Device_Password_ID(simple_config_Device_Password_ID_Default_PIN)
+	, m_new_password(tools)
+	, m_new_Device_Password_ID(simple_config_Device_Password_ID_Default_PIN)
+	, m_error_message_received_timeout(SIMPLE_CONFIG_RECORD_ERROR_MESSAGE_RECEIVED_TIMEOUT)
+	, m_is_valid(false)
+	, m_is_client(is_client_when_true)
+	, m_allow_message_send(true)
+	, m_already_in_completion_action_check(false)
+	, m_pending_query_network_and_device_parameters(false)
+	, m_simple_config_test_version(false)
+	, m_key_material_generated(false)
+	, m_force_simple_config_message_send(false)
+	, m_shutdown_was_called(false)
+	, m_M2D_received_timeout_active(false)
+{
+	if (m_am_tools == 0
+		|| m_am_tools->get_is_valid() == false)
+	{
+		// No need to delete anything here because it is done in destructor.
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return;
+	}
+
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: function: simple_config_record_c::simple_config_record_c(): ")
+		 EAPL("this = 0x%08x\n"),
+		(m_is_client == true ? "client": "server"),
+		this));
+
+	if (receive_network_id == 0
+		|| receive_network_id->get_is_valid_data() == false)
+	{
+		// No need to delete anything here because it is done in destructor.
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return;
+	}
+
+	if (m_am_simple_config_services == 0
+		|| m_am_simple_config_services->get_is_valid() == false)
+	{
+		EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_SIMPLE_CONFIG_ERROR,
+						(EAPL("ERROR: %s: function: simple_config_record_c::simple_config_record_c() failed,")
+						 EAPL(" m_am_simple_config_services = 0x%08x (validity %d) is invalid.\n"),
+						 (m_is_client == true ? "client": "server"),
+						 m_am_simple_config_services, (m_am_simple_config_services != 0) ? m_am_simple_config_services->get_is_valid(): false));
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return;
+	}
+	m_am_simple_config_services->set_simple_config_am_partner(this);
+
+	// Here we swap the addresses.
+	eap_am_network_id_c send_network_id(
+		m_am_tools,
+		receive_network_id->get_destination_id(),
+		receive_network_id->get_source_id(),
+		receive_network_id->get_type());
+
+	if (send_network_id.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return;
+	}
+
+	if (m_send_network_id.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return;
+	}
+
+	eap_status_e status = m_send_network_id.set_copy_of_network_id(&send_network_id);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return;
+	}
+
+	if (m_send_network_id.get_is_valid() == false
+		|| m_received_simple_config_message.get_is_valid() == false
+		|| m_received_payloads.get_is_valid() == false
+		|| m_previous_simple_config_message.get_is_valid() == false
+		|| m_new_simple_config_message.get_is_valid() == false
+		|| m_enrollee_nonce.get_is_valid() == false
+		|| m_enrollee_mac.get_is_valid() == false
+		|| m_registrar_nonce.get_is_valid() == false
+		|| m_device_password.get_is_valid() == false
+		|| m_PSK1.get_is_valid() == false
+		|| m_PSK2.get_is_valid() == false
+		|| m_E_SNonce1.get_is_valid() == false
+		|| m_E_SNonce2.get_is_valid() == false
+		|| m_EHash1.get_is_valid() == false
+		|| m_EHash2.get_is_valid() == false
+		|| m_R_SNonce1.get_is_valid() == false
+		|| m_R_SNonce2.get_is_valid() == false
+		|| m_RHash1.get_is_valid() == false
+		|| m_RHash2.get_is_valid() == false
+		|| m_own_private_dhe_key.get_is_valid() == false
+		|| m_own_public_dhe_key.get_is_valid() == false
+		|| m_peer_public_dhe_key.get_is_valid() == false
+		|| m_shared_dh_key.get_is_valid() == false
+		|| m_dhe_prime.get_is_valid() == false
+		|| m_dhe_group_generator.get_is_valid() == false
+		|| m_kdk.get_is_valid() == false
+		|| m_auth_key.get_is_valid() == false
+		|| m_key_wrap_key.get_is_valid() == false
+		|| m_EMSK.get_is_valid() == false
+		|| m_SSID.get_is_valid() == false
+		|| m_signed_message_hash.get_is_valid() == false
+		|| m_NAI.get_is_valid() == false
+		|| m_NAI_realm.get_is_valid() == false
+		|| m_send_network_id.get_is_valid() == false
+		|| m_UUID_E.get_is_valid() == false
+		|| m_UUID_R.get_is_valid() == false
+		|| m_MAC_address.get_is_valid() == false
+		|| m_new_password.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return;
+	}
+
+#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+	if (m_is_client == false)
+	{
+		set_state(simple_config_state_wait_M1);
+	}
+#endif //#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+	set_is_valid();
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT void simple_config_record_c::set_state(const simple_config_state_e state)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	eap_simple_config_trace_string_c state_string;
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: state_function: set_state() from %s to %s\n"),
+		(m_is_client == true ? "client": "server"),
+		state_string.get_state_string(m_simple_config_state),
+		state_string.get_state_string(state)));
+
+	if (m_simple_config_state != simple_config_state_failure)
+	{
+		m_simple_config_state = state;
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT simple_config_state_e simple_config_record_c::get_state() const
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return m_simple_config_state;
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT bool simple_config_record_c::verify_state(const simple_config_state_e state)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	eap_simple_config_trace_string_c state_string;
+
+	if (m_simple_config_state == state)
+	{
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("SIMPLE_CONFIG: %s: state_function: verify_state(): current state %s == %s\n"),
+			 (m_is_client == true ? "client": "server"),
+			 state_string.get_state_string(m_simple_config_state),
+			 state_string.get_state_string(state)));
+
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return true;
+	}
+	else
+	{
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("ERROR: SIMPLE_CONFIG: %s: state_function: verify_state(): current state %s != %s\n"),
+			 (m_is_client == true ? "client": "server"),
+			 state_string.get_state_string(m_simple_config_state),
+			 state_string.get_state_string(state)));
+
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return false;
+	}
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT void simple_config_record_c::set_is_valid()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	m_is_valid = true;
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::configure()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: function: simple_config_record_c::configure(): ")
+		 EAPL("this = 0x%08x\n"),
+		(m_is_client == true ? "client": "server"),
+		this));
+
+	eap_status_e status = m_am_simple_config_services->configure();
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	if (get_type_partner() == 0)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	if (m_is_client == true)
+	{
+		// Creates Enrollee Nonce.
+		status = generate_nonce(
+			&m_enrollee_nonce,
+			SIMPLE_CONFIG_ENROLLEE_NONCE_SIZE);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+	else
+	{
+		// Creates Registrar Nonce.
+		status = generate_nonce(
+			&m_registrar_nonce,
+			SIMPLE_CONFIG_REGISTRAR_NONCE_SIZE);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	status = generate_dhe_keys();
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	//----------------------------------------------------------
+
+	{
+		status = get_type_partner()->read_configure(
+			cf_str_EAP_SIMPLE_CONFIG_device_password.get_field(),
+			&m_device_password);
+		if (status != eap_status_ok
+			|| m_device_password.get_is_valid_data() == false)
+		{
+			// This is mandatory value.
+			EAP_TRACE_ERROR(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("ERROR: SIMPLE_CONFIG: %s: simple_config_record_c::configure(): Missing device password.\n"),
+				 (m_is_client == true ? "client": "server")));
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_password);
+		}
+	}
+
+	if (m_is_client == false)
+	{
+		(void) get_type_partner()->read_configure(
+			cf_str_EAP_SIMPLE_CONFIG_server_device_password.get_field(),
+			&m_device_password);
+	}
+
+	//----------------------------------------------------------
+
+	{
+		eap_variable_data_c test_version(m_am_tools);
+
+		if (test_version.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = get_type_partner()->read_configure(
+			cf_str_EAP_SIMPLE_CONFIG_test_version.get_field(),
+			&test_version);
+		if (status == eap_status_ok
+			&& test_version.get_is_valid_data() == true
+			&& test_version.get_data_length() == sizeof(u32_t)
+			&& test_version.get_data(sizeof(u32_t)) != 0)
+		{
+			// This is optional value.
+			u32_t *flag = reinterpret_cast<u32_t *>(test_version.get_data(sizeof(u32_t)));
+			if (flag != 0)
+			{
+				if (*flag == 0)
+				{
+					m_simple_config_test_version = false;
+				}
+				else
+				{
+					m_simple_config_test_version = true;
+				}
+			}
+		}
+
+		status = eap_status_ok;
+	}
+
+	//----------------------------------------------------------
+
+	{
+		eap_variable_data_c error_message_received_timeout(m_am_tools);
+
+		if (error_message_received_timeout.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		eap_status_e status = read_configure(
+			cf_str_SIMPLE_CONFIG_error_message_received_timeout.get_field(),
+			&error_message_received_timeout);
+		if (status == eap_status_ok
+			&& error_message_received_timeout.get_is_valid_data() == true)
+		{
+			u32_t *error_message_received_timeout_value = reinterpret_cast<u32_t *>(
+				error_message_received_timeout.get_data(sizeof(u32_t)));
+			if (error_message_received_timeout_value != 0)
+			{
+				m_error_message_received_timeout = *error_message_received_timeout_value;
+			}
+		}
+	}
+
+	//----------------------------------------------------------
+
+#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+	if (m_is_client == false)
+	{
+		{
+			// This is optional.
+			(void) read_configure(
+				cf_str_SIMPLE_CONFIG_new_password.get_field(),
+				&m_new_password);
+		}
+
+		{
+			// This is optional.
+			(void) read_configure(
+				cf_str_SIMPLE_CONFIG_network_key.get_field(),
+				&m_network_key);
+		}
+
+		{
+			eap_variable_data_c authentication_type(m_am_tools);
+
+			eap_status_e status = read_configure(
+				cf_str_SIMPLE_CONFIG_authentication_type.get_field(),
+				&authentication_type);
+			if (status == eap_status_ok
+				&& authentication_type.get_is_valid() == true
+				&& authentication_type.get_data_length() > 0ul
+				&& authentication_type.get_data(
+					authentication_type.get_data_length()) != 0)
+			{
+
+				if (cf_str_SIMPLE_CONFIG_authentication_type_None.get_field()
+					->compare(
+						m_am_tools,
+						&authentication_type) == true)
+				{
+					m_authentication_type
+						= simple_config_Authentication_Type_None;
+				}
+				else if (cf_str_SIMPLE_CONFIG_authentication_type_Open.get_field()
+						 ->compare(
+							 m_am_tools,
+							 &authentication_type) == true)
+				{
+					m_authentication_type
+						= simple_config_Authentication_Type_Open;
+				}
+				else if (cf_str_SIMPLE_CONFIG_authentication_type_WPAPSK.get_field()
+						 ->compare(
+							 m_am_tools,
+							 &authentication_type) == true)
+				{
+					m_authentication_type
+						= simple_config_Authentication_Type_WPAPSK;
+				}
+				else if (cf_str_SIMPLE_CONFIG_authentication_type_Shared.get_field()
+						 ->compare(
+							 m_am_tools,
+							 &authentication_type) == true)
+				{
+					m_authentication_type
+						= simple_config_Authentication_Type_Shared;
+				}
+				else if (cf_str_SIMPLE_CONFIG_authentication_type_WPA.get_field()
+						 ->compare(
+							 m_am_tools,
+							 &authentication_type) == true)
+				{
+					m_authentication_type
+						= simple_config_Authentication_Type_WPA;
+				}
+				else if (cf_str_SIMPLE_CONFIG_authentication_type_WPA2.get_field()
+						 ->compare(
+							 m_am_tools,
+							 &authentication_type) == true)
+				{
+					m_authentication_type
+						= simple_config_Authentication_Type_WPA2;
+				}
+				else if (cf_str_SIMPLE_CONFIG_authentication_type_WPA2PSK.get_field()
+						 ->compare(
+							 m_am_tools,
+							 &authentication_type) == true)
+				{
+					m_authentication_type
+						= simple_config_Authentication_Type_WPA2PSK;
+				}
+			}
+		}
+	}
+#endif //#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+	//----------------------------------------------------------
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::shutdown()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: function: simple_config_record_c::shutdown(): ")
+		 EAPL("this = 0x%08x\n"),
+		(m_is_client == true ? "client": "server"),
+		this));
+
+	if (m_shutdown_was_called == true)
+	{
+		// Shutdown function was called already.
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+	}
+	m_shutdown_was_called = true;
+
+
+	// Cancel all timers.
+	cancel_error_message_timeout();
+	cancel_M2D_received_timeout();
+
+
+	if (get_state() != simple_config_state_simple_config_success)
+	{
+		set_state(simple_config_state_failure);
+	}
+
+	eap_status_e status = eap_status_ok;
+
+	if (m_pending_query_network_and_device_parameters == true)
+	{
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("SIMPLE_CONFIG: function: simple_config_record_c::shutdown(): calls cancel_query_dh_parameters()\n")));
+
+		m_am_simple_config_services->cancel_query_network_and_device_parameters();
+		m_pending_query_network_and_device_parameters = false;
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::set_nai_realm(
+	const eap_variable_data_c * const NAI_realm)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	eap_status_e status = m_NAI_realm.set_copy_of_buffer(NAI_realm);
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+//
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::completion_action_add(
+	simple_config_completion_action_e action)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	simple_config_completion_c *completion_action = new simple_config_completion_c(
+		m_am_tools,
+		action);
+
+	if (completion_action == 0
+		|| completion_action->get_is_valid() == false)
+	{
+		delete completion_action;
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	// add_object() will delete completion_action if operation fails.
+	eap_status_e status = m_completion_queue.add_object(completion_action, true);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT,
+					(EAPL("SIMPLE_CONFIG: %s: send_function: completion_action_add(): action %s\n"),
+					 (m_is_client == true ? "client": "server"),
+					 completion_action->get_completion_action_string()));
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+//
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::completion_action_clenup()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT,
+					(EAPL("SIMPLE_CONFIG: %s: send_function: completion_action_clenup()\n"),
+					 (m_is_client == true ? "client": "server")));
+
+	eap_status_e final_status = eap_status_ok;
+	u32_t counter(0ul);
+
+	while(m_completion_queue.get_object_count() > 0ul)
+	{
+		simple_config_completion_c * const completion_action = m_completion_queue.get_object(0ul);
+		EAP_UNREFERENCED_PARAMETER(completion_action); // Not referenced without trace.
+
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("ERROR: SIMPLE_CONFIG: %s: send_function: completion_action_clenup(): ")
+			 EAPL("action[%u] %s not completed.\n"),
+			 (m_is_client == true ? "client": "server"),
+			 counter,
+			 completion_action->get_completion_action_string()));
+
+		final_status = m_completion_queue.remove_object(0ul);
+		if (final_status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, final_status);
+		}
+
+		++counter;
+
+	} // while()
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, final_status);
+}
+
+//--------------------------------------------------
+
+//
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::completion_action_check()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT,
+					(EAPL("SIMPLE_CONFIG: %s: send_function: completion_action_check()\n"),
+					 (m_is_client == true ? "client": "server")));
+
+	if (m_already_in_completion_action_check == true)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		// This is recursive call of completion_action_check().
+		// This MUST return eap_status_ok. Other return values will skip
+		// further prosessing of completion action list.
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+	}
+	m_already_in_completion_action_check = true;
+
+	eap_automatic_simple_value_c<bool> restore_already_in_completion_action_check(
+		m_am_tools,
+		&m_already_in_completion_action_check,
+		false);
+
+	eap_status_e status = eap_status_ok;
+	bool continue_with_next_action = true;
+	u32_t counter = 0ul;
+
+	while(continue_with_next_action == true
+		&& m_completion_queue.get_object_count() > 0ul)
+	{
+		simple_config_completion_c * const completion_action = m_completion_queue.get_object(0ul);
+		EAP_UNREFERENCED_PARAMETER(completion_action); // Not referenced without trace.
+
+		EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT,
+						(EAPL("SIMPLE_CONFIG: %s: send_function: completion_action_check(): action[%u] %s\n"),
+						 (m_is_client == true ? "client": "server"),
+						 counter,
+						 completion_action->get_completion_action_string()));
+
+		if (continue_with_next_action == true)
+		{
+			status = m_completion_queue.remove_object(0ul);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+		}
+
+		++counter;
+
+	} // while()
+
+	if (continue_with_next_action == false)
+	{
+		status = eap_status_pending_request;
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+// This is commented in abs_simple_config_base_application_c.
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::read_configure(
+	const eap_configuration_field_c * const field,
+	eap_variable_data_c * const data)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	return get_type_partner()->read_configure(
+			field,
+			data);
+}
+
+//--------------------------------------------------
+
+// This is commented in abs_simple_config_base_application_c.
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::write_configure(
+	const eap_configuration_field_c * const field,
+	eap_variable_data_c * const data)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	return get_type_partner()->write_configure(
+			field,
+			data);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::add_common_attributes(
+	simple_config_payloads_c * const payloads,
+	const simple_config_Message_Type_e message_type,
+	const bool add_enrollee_nonce,
+	const bool add_registrar_nonce)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::add_common_attributes()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	if (payloads == 0
+		|| payloads->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+	}
+
+	if (message_type > simple_config_Message_keep_this_last)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+	}
+
+	eap_status_e status(eap_status_process_general_error);
+
+	{
+		u8_t Version[]
+			= { SIMPLE_CONFIG_VERSION };
+
+		status = payloads->copy_attribute_data(
+			simple_config_Attribute_Type_Version,
+			true,
+			Version,
+			sizeof(Version));
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	{
+		u8_t Message_type(static_cast<u8_t>(message_type));
+
+		status = payloads->copy_attribute_data(
+			simple_config_Attribute_Type_Message_Type,
+			true,
+			&Message_type,
+			sizeof(Message_type));
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+		
+		// Save the type for indicating it to the lower layer in transmission
+		m_current_simple_config_message_type = message_type;
+	}
+
+	if (add_enrollee_nonce == true)
+	{
+		if (m_enrollee_nonce.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+		}
+
+		status = payloads->copy_attribute_data(
+			simple_config_Attribute_Type_Enrollee_Nonce,
+			true,
+			m_enrollee_nonce.get_data(),
+			m_enrollee_nonce.get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	if (add_registrar_nonce == true)
+	{
+		if (m_registrar_nonce.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+		}
+
+		status = payloads->copy_attribute_data(
+			simple_config_Attribute_Type_Registrar_Nonce,
+			true,
+			m_registrar_nonce.get_data(),
+			m_registrar_nonce.get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::send_M1(
+	const simple_config_payloads_c * const network_and_device_parameters)
+{
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_M1()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	if (network_and_device_parameters == 0
+		|| network_and_device_parameters->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+	}
+
+	eap_status_e status(eap_status_process_general_error);
+
+
+	{
+		// Save Enrollee MAC.
+		status = m_enrollee_mac.set_copy_of_buffer(
+			m_send_network_id.get_source_id());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	
+	simple_config_payloads_c * payloads = new simple_config_payloads_c(m_am_tools);
+	eap_automatic_variable_c<simple_config_payloads_c> automatic_payloads(m_am_tools, payloads);
+
+	if (payloads == 0
+		|| payloads->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = add_common_attributes(
+		payloads,
+		simple_config_Message_Type_M1,
+		false,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_UUID_E);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	{
+		if (m_enrollee_mac.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = payloads->copy_attribute_data(
+			simple_config_Attribute_Type_MAC_Address,
+			true,
+			m_enrollee_mac.get_data(),
+			m_enrollee_mac.get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+
+	{
+		if (m_enrollee_nonce.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = payloads->copy_attribute_data(
+			simple_config_Attribute_Type_Enrollee_Nonce,
+			true,
+			m_enrollee_nonce.get_data(),
+			m_enrollee_nonce.get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	{
+		if (m_own_public_dhe_key.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = payloads->copy_attribute_data(
+			simple_config_Attribute_Type_Public_Key,
+			true,
+			m_own_public_dhe_key.get_data(),
+			m_own_public_dhe_key.get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Authentication_Type_Flags);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Encryption_Type_Flags);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Connection_Type_Flags);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Config_Methods);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Simple_Config_State);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Manufacturer);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Model_Name);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Model_Number);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Serial_Number);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Primary_Device_Type);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Device_Name);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_RF_Band);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Association_State);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Device_Password_ID);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	if (payloads->get_attribute_pointer(
+		simple_config_Attribute_Type_Configuration_Error) != 0)
+	{
+		status = payloads->copy_attribute(
+			network_and_device_parameters,
+			simple_config_Attribute_Type_Configuration_Error);
+	}
+	else
+	{
+		status = eap_status_not_found;
+	}
+
+	if (status != eap_status_ok)
+	{
+		simple_config_Configuration_Error_e Configuration_Error(simple_config_Configuration_Error_No_Error);
+		u16_t network_order_Configuration_Error(eap_htons(static_cast<u16_t>(Configuration_Error)));
+
+		status = payloads->copy_attribute_data(
+			simple_config_Attribute_Type_Configuration_Error,
+			true,
+			&network_order_Configuration_Error,
+			sizeof(network_order_Configuration_Error));
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_OS_Version);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	if (m_new_simple_config_message.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = payloads->create_simple_config_message(
+		&m_new_simple_config_message,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	set_state(simple_config_state_wait_M2);
+
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::send_M2(
+	const simple_config_payloads_c * const network_and_device_parameters)
+{
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_M2()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	if (network_and_device_parameters == 0
+		|| network_and_device_parameters->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+	}
+
+	eap_status_e status(eap_status_process_general_error);
+	
+
+	simple_config_payloads_c * payloads = new simple_config_payloads_c(m_am_tools);
+	eap_automatic_variable_c<simple_config_payloads_c> automatic_payloads(m_am_tools, payloads);
+
+	if (payloads == 0
+		|| payloads->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = add_common_attributes(
+		payloads,
+		simple_config_Message_Type_M2,
+		true,
+		true);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_UUID_R);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	{
+		status = payloads->copy_attribute_data(
+			simple_config_Attribute_Type_Public_Key,
+			true,
+			m_own_public_dhe_key.get_data(),
+			m_own_public_dhe_key.get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Authentication_Type_Flags);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Encryption_Type_Flags);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Connection_Type_Flags);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Config_Methods);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Manufacturer);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Model_Name);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Model_Number);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Serial_Number);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Primary_Device_Type);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Device_Name);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_RF_Band);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Association_State);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	if (payloads->get_attribute_pointer(
+		simple_config_Attribute_Type_Configuration_Error) != 0)
+	{
+		status = payloads->copy_attribute(
+			network_and_device_parameters,
+			simple_config_Attribute_Type_Configuration_Error);
+	}
+	else
+	{
+		status = eap_status_missing_payload;
+	}
+
+	if (status != eap_status_ok)
+	{
+		// Because the Configuration_Error is missing there is no error.
+		simple_config_Configuration_Error_e Configuration_Error(simple_config_Configuration_Error_No_Error);
+		u16_t network_order_Configuration_Error(eap_htons(static_cast<u16_t>(Configuration_Error)));
+
+		status = payloads->copy_attribute_data(
+			simple_config_Attribute_Type_Configuration_Error,
+			true,
+			&network_order_Configuration_Error,
+			sizeof(network_order_Configuration_Error));
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Device_Password_ID);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_OS_Version);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	if (m_new_simple_config_message.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = payloads->create_simple_config_message(
+		&m_new_simple_config_message,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = add_authenticator_attribute(
+		&m_received_simple_config_message,
+		&m_new_simple_config_message);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	set_state(simple_config_state_wait_M3);
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+#endif //#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+//--------------------------------------------------
+
+#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::send_M2D(
+	const simple_config_payloads_c * const network_and_device_parameters)
+{
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_M2D()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	if (network_and_device_parameters == 0
+		|| network_and_device_parameters->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+	}
+
+	eap_status_e status(eap_status_process_general_error);
+	
+
+	simple_config_payloads_c * payloads = new simple_config_payloads_c(m_am_tools);
+	eap_automatic_variable_c<simple_config_payloads_c> automatic_payloads(m_am_tools, payloads);
+
+	if (payloads == 0
+		|| payloads->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+	
+	status = add_common_attributes(
+		payloads,
+		simple_config_Message_Type_M2D,
+		true,
+		true);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_UUID_R);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Authentication_Type_Flags);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Encryption_Type_Flags);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Connection_Type_Flags);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Config_Methods);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Manufacturer);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Model_Name);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Model_Number);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Serial_Number);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Primary_Device_Type);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Device_Name);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_RF_Band);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_Association_State);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	if (network_and_device_parameters->get_attribute_pointer(
+		simple_config_Attribute_Type_Configuration_Error) != 0)
+	{
+		status = payloads->copy_attribute(
+			network_and_device_parameters,
+			simple_config_Attribute_Type_Configuration_Error);
+	}
+	else
+	{
+		status = eap_status_missing_payload;
+	}
+
+	if (status != eap_status_ok)
+	{
+		simple_config_Configuration_Error_e Configuration_Error(simple_config_Configuration_Error_No_Error);
+		u16_t network_order_Configuration_Error(eap_htons(static_cast<u16_t>(Configuration_Error)));
+
+		status = payloads->copy_attribute_data(
+			simple_config_Attribute_Type_Configuration_Error,
+			true,
+			&network_order_Configuration_Error,
+			sizeof(network_order_Configuration_Error));
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	status = payloads->copy_attribute(
+		network_and_device_parameters,
+		simple_config_Attribute_Type_OS_Version);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	if (m_new_simple_config_message.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = payloads->create_simple_config_message(
+		&m_new_simple_config_message,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	set_state(simple_config_state_wait_WSC_ACK);
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+#endif //#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::send_M3()
+{
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_M3()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	eap_status_e status(eap_status_process_general_error);
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	// Create HASHs
+	status = generate_er_hashs(
+		false,
+		&m_device_password,
+		&m_own_public_dhe_key,
+		&m_peer_public_dhe_key,
+		&m_PSK1,
+		&m_E_SNonce1,
+		&m_EHash1,
+		&m_PSK2,
+		&m_E_SNonce2,
+		&m_EHash2);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	simple_config_payloads_c * payloads = new simple_config_payloads_c(m_am_tools);
+	eap_automatic_variable_c<simple_config_payloads_c> automatic_payloads(m_am_tools, payloads);
+
+	if (payloads == 0
+		|| payloads->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+	
+	status = add_common_attributes(
+		payloads,
+		simple_config_Message_Type_M3,
+		false,
+		true);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute_data(
+		simple_config_Attribute_Type_E_Hash1,
+		true,
+		m_EHash1.get_data(),
+		m_EHash1.get_data_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute_data(
+		simple_config_Attribute_Type_E_Hash2,
+		true,
+		m_EHash2.get_data(),
+		m_EHash2.get_data_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	if (m_new_simple_config_message.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = payloads->create_simple_config_message(
+		&m_new_simple_config_message,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = add_authenticator_attribute(
+		&m_received_simple_config_message,
+		&m_new_simple_config_message);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	set_state(simple_config_state_wait_M4);
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::send_M4()
+{
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_M4()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	eap_status_e status(eap_status_process_general_error);
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	// Create HASHs
+	status = generate_er_hashs(
+		false,
+		&m_device_password,
+		&m_peer_public_dhe_key,
+		&m_own_public_dhe_key,
+		&m_PSK1,
+		&m_R_SNonce1,
+		&m_RHash1,
+		&m_PSK2,
+		&m_R_SNonce2,
+		&m_RHash2);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	simple_config_payloads_c * payloads = new simple_config_payloads_c(m_am_tools);
+	eap_automatic_variable_c<simple_config_payloads_c> automatic_payloads(m_am_tools, payloads);
+
+	if (payloads == 0
+		|| payloads->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+	
+	status = add_common_attributes(
+		payloads,
+		simple_config_Message_Type_M4,
+		true,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute_data(
+		simple_config_Attribute_Type_R_Hash1,
+		true,
+		m_RHash1.get_data(),
+		m_RHash1.get_data_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->copy_attribute_data(
+		simple_config_Attribute_Type_R_Hash2,
+		true,
+		m_RHash2.get_data(),
+		m_RHash2.get_data_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	simple_config_variable_data_c * encrypted_settings = new simple_config_variable_data_c(m_am_tools);
+	eap_automatic_variable_c<simple_config_variable_data_c> automatic_encrypted_settings(m_am_tools, encrypted_settings);
+
+	if (encrypted_settings == 0
+		|| encrypted_settings->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	{
+		// Create Encrypted Settings.
+		// This one includes R-SNonce1 (R-S1).
+		simple_config_payloads_c * plaintext_payloads = new simple_config_payloads_c(m_am_tools);
+		eap_automatic_variable_c<simple_config_payloads_c> automatic_plaintext_payloads(m_am_tools, plaintext_payloads);
+
+		if (plaintext_payloads == 0
+			|| plaintext_payloads->get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = plaintext_payloads->copy_attribute_data(
+			simple_config_Attribute_Type_R_SNonce1,
+			true,
+			m_R_SNonce1.get_data(),
+			m_R_SNonce1.get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = encrypt_payloads(
+			&m_auth_key,
+			&m_key_wrap_key,
+			plaintext_payloads,
+			encrypted_settings);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	automatic_encrypted_settings.do_not_free_variable();
+
+	status = payloads->add_attribute(
+		encrypted_settings);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	if (m_new_simple_config_message.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = payloads->create_simple_config_message(
+		&m_new_simple_config_message,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = add_authenticator_attribute(
+		&m_received_simple_config_message,
+		&m_new_simple_config_message);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	set_state(simple_config_state_wait_M5);
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+#endif //#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::send_M5()
+{
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_M5()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	eap_status_e status(eap_status_process_general_error);
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	simple_config_payloads_c * payloads = new simple_config_payloads_c(m_am_tools);
+	eap_automatic_variable_c<simple_config_payloads_c> automatic_payloads(m_am_tools, payloads);
+
+	if (payloads == 0
+		|| payloads->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+	
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_M5(): calls add_common_attributes()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	status = add_common_attributes(
+		payloads,
+		simple_config_Message_Type_M5,
+		false,
+		true);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	simple_config_variable_data_c * encrypted_settings = new simple_config_variable_data_c(m_am_tools);
+	eap_automatic_variable_c<simple_config_variable_data_c> automatic_encrypted_settings(m_am_tools, encrypted_settings);
+
+	if (encrypted_settings == 0
+		|| encrypted_settings->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	{
+		// Create Encrypted Settings.
+		// This one includes E-SNonce1 (E-S1).
+		simple_config_payloads_c * plaintext_payloads = new simple_config_payloads_c(m_am_tools);
+		eap_automatic_variable_c<simple_config_payloads_c> automatic_plaintext_payloads(m_am_tools, plaintext_payloads);
+
+		if (plaintext_payloads == 0
+			|| plaintext_payloads->get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_M5(): calls copy_attribute_data()\n"),
+			(m_is_client == true ? "client": "server")));
+
+		status = plaintext_payloads->copy_attribute_data(
+			simple_config_Attribute_Type_E_SNonce1,
+			true,
+			m_E_SNonce1.get_data(),
+			m_E_SNonce1.get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_M5(): calls encrypt_payloads()\n"),
+			(m_is_client == true ? "client": "server")));
+
+		status = encrypt_payloads(
+			&m_auth_key,
+			&m_key_wrap_key,
+			plaintext_payloads,
+			encrypted_settings);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_M5(): calls payloads.add_attribute()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	automatic_encrypted_settings.do_not_free_variable();
+
+	status = payloads->add_attribute(
+		encrypted_settings);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	if (m_new_simple_config_message.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_M5(): calls payloads.create_simple_config_message()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	status = payloads->create_simple_config_message(
+		&m_new_simple_config_message,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_M5(): calls m_received_simple_config_message.get_is_valid()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	if (m_received_simple_config_message.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_M5(): calls m_new_simple_config_message.get_is_valid()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	if (m_new_simple_config_message.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_M5(): calls add_authenticator_attribute()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	status = add_authenticator_attribute(
+		&m_received_simple_config_message,
+		&m_new_simple_config_message);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	set_state(simple_config_state_wait_M6);
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_M5(): returns\n"),
+		(m_is_client == true ? "client": "server")));
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::send_M6()
+{
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_M6()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	eap_status_e status(eap_status_process_general_error);
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	simple_config_payloads_c * payloads = new simple_config_payloads_c(m_am_tools);
+	eap_automatic_variable_c<simple_config_payloads_c> automatic_payloads(m_am_tools, payloads);
+
+	if (payloads == 0
+		|| payloads->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = add_common_attributes(
+		payloads,
+		simple_config_Message_Type_M6,
+		true,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	simple_config_variable_data_c * encrypted_settings = new simple_config_variable_data_c(m_am_tools);
+	eap_automatic_variable_c<simple_config_variable_data_c> automatic_encrypted_settings(m_am_tools, encrypted_settings);
+
+	if (encrypted_settings == 0
+		|| encrypted_settings->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	{
+		// Create Encrypted Settings.
+		// This one includes R-SNonce2 (R-S2).
+		simple_config_payloads_c * plaintext_payloads = new simple_config_payloads_c(m_am_tools);
+		eap_automatic_variable_c<simple_config_payloads_c> automatic_plaintext_payloads(m_am_tools, plaintext_payloads);
+
+		if (plaintext_payloads == 0
+			|| plaintext_payloads->get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = plaintext_payloads->copy_attribute_data(
+			simple_config_Attribute_Type_R_SNonce2,
+			true,
+			m_R_SNonce2.get_data(),
+			m_R_SNonce2.get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = encrypt_payloads(
+			&m_auth_key,
+			&m_key_wrap_key,
+			plaintext_payloads,
+			encrypted_settings);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	automatic_encrypted_settings.do_not_free_variable();
+
+	status = payloads->add_attribute(
+		encrypted_settings);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	if (m_new_simple_config_message.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = payloads->create_simple_config_message(
+		&m_new_simple_config_message,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = add_authenticator_attribute(
+		&m_received_simple_config_message,
+		&m_new_simple_config_message);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	set_state(simple_config_state_wait_M7);
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+#endif //#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::send_M7()
+{
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_M7()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	eap_status_e status(eap_status_process_general_error);
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	simple_config_payloads_c * payloads = new simple_config_payloads_c(m_am_tools);
+	eap_automatic_variable_c<simple_config_payloads_c> automatic_payloads(m_am_tools, payloads);
+
+	if (payloads == 0
+		|| payloads->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = add_common_attributes(
+		payloads,
+		simple_config_Message_Type_M7,
+		false,
+		true);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	simple_config_variable_data_c * encrypted_settings = new simple_config_variable_data_c(m_am_tools);
+	eap_automatic_variable_c<simple_config_variable_data_c> automatic_encrypted_settings(m_am_tools, encrypted_settings);
+
+	if (encrypted_settings == 0
+		|| encrypted_settings->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+
+	{
+		// Create Encrypted Settings.
+		// This one includes E-SNonce2 (E-S2).
+		simple_config_payloads_c * plaintext_payloads = new simple_config_payloads_c(m_am_tools);
+		eap_automatic_variable_c<simple_config_payloads_c> automatic_plaintext_payloads(m_am_tools, plaintext_payloads);
+
+		if (plaintext_payloads == 0
+			|| plaintext_payloads->get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = plaintext_payloads->copy_attribute_data(
+			simple_config_Attribute_Type_E_SNonce2,
+			true,
+			m_E_SNonce2.get_data(),
+			m_E_SNonce2.get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = encrypt_payloads(
+			&m_auth_key,
+			&m_key_wrap_key,
+			plaintext_payloads,
+			encrypted_settings);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	automatic_encrypted_settings.do_not_free_variable();
+
+	status = payloads->add_attribute(
+		encrypted_settings);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	if (m_new_simple_config_message.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = payloads->create_simple_config_message(
+		&m_new_simple_config_message,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = add_authenticator_attribute(
+		&m_received_simple_config_message,
+		&m_new_simple_config_message);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	set_state(simple_config_state_wait_M8);
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::send_M8()
+{
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_M8()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	eap_status_e status(eap_status_process_general_error);
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	simple_config_payloads_c * payloads = new simple_config_payloads_c(m_am_tools);
+	eap_automatic_variable_c<simple_config_payloads_c> automatic_payloads(m_am_tools, payloads);
+
+	if (payloads == 0
+		|| payloads->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+	
+	status = add_common_attributes(
+		payloads,
+		simple_config_Message_Type_M8,
+		true,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	simple_config_variable_data_c * encrypted_settings = new simple_config_variable_data_c(m_am_tools);
+	eap_automatic_variable_c<simple_config_variable_data_c> automatic_encrypted_settings(m_am_tools, encrypted_settings);
+
+	if (encrypted_settings == 0
+		|| encrypted_settings->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	// Create Encrypted Settings.
+	{
+		simple_config_payloads_c * plaintext_payloads = new simple_config_payloads_c(m_am_tools);
+		eap_automatic_variable_c<simple_config_payloads_c> automatic_plaintext_payloads(m_am_tools, plaintext_payloads);
+
+		if (plaintext_payloads == 0
+			|| plaintext_payloads->get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		// Create Credential attribute
+		{
+			u32_t SIMPLE_CONFIG_TEST_CREDENTIAL_COUNT = 2ul;
+
+			for (u32_t ind = 0ul; ind < SIMPLE_CONFIG_TEST_CREDENTIAL_COUNT; ind++)
+			{
+				simple_config_payloads_c * credential_payloads = new simple_config_payloads_c(m_am_tools);
+				eap_automatic_variable_c<simple_config_payloads_c> automatic_credential_payloads(m_am_tools, credential_payloads);
+
+				if (credential_payloads == 0
+					|| credential_payloads->get_is_valid() == false)
+				{
+					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+				}
+
+
+				{
+					u8_t network_index(static_cast<u8_t>(ind+SIMPLE_CONFIG_DEFAULT_NETWORK_KEY_INDEX));
+
+					status = credential_payloads->copy_attribute_data(
+						simple_config_Attribute_Type_Network_Index,
+						true,
+						&network_index,
+						sizeof(network_index));
+					if (status != eap_status_ok)
+					{
+						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+						return EAP_STATUS_RETURN(m_am_tools, status);
+					}
+
+					status = credential_payloads->copy_attribute_data(
+						simple_config_Attribute_Type_SSID,
+						true,
+						m_SSID.get_data(),
+						m_SSID.get_data_length());
+					if (status != eap_status_ok)
+					{
+						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+						return EAP_STATUS_RETURN(m_am_tools, status);
+					}
+
+					{
+						u16_t network_order_Authentication_Type(eap_htons(static_cast<u16_t>(m_authentication_type)));
+
+						status = credential_payloads->copy_attribute_data(
+							simple_config_Attribute_Type_Authentication_Type,
+							true,
+							&network_order_Authentication_Type,
+							sizeof(network_order_Authentication_Type));
+						if (status != eap_status_ok)
+						{
+							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+							return EAP_STATUS_RETURN(m_am_tools, status);
+						}
+					}
+
+					{
+						u16_t network_order_Encryption_Type(eap_htons(static_cast<u16_t>(simple_config_Encryption_Type_AES)));
+
+						status = credential_payloads->copy_attribute_data(
+							simple_config_Attribute_Type_Encryption_Type,
+							true,
+							&network_order_Encryption_Type,
+							sizeof(network_order_Encryption_Type));
+						if (status != eap_status_ok)
+						{
+							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+							return EAP_STATUS_RETURN(m_am_tools, status);
+						}
+					}
+
+
+					// Creates some test data.
+					eap_array_c<network_key_and_index_c> * network_keys = new eap_array_c<network_key_and_index_c>(m_am_tools);
+					eap_automatic_variable_c<eap_array_c<network_key_and_index_c> > automatic_network_keys(m_am_tools, network_keys);
+					
+					if (network_keys == 0)
+					{
+						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+						return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+					}
+
+					{
+						const u32_t MAX_COUNT_OF_KEYS = 3ul;
+
+						for (u32_t ind = 0ul; ind < MAX_COUNT_OF_KEYS; ++ind)
+						{
+							network_key_and_index_c * const obj = new network_key_and_index_c(m_am_tools);
+
+							if (obj != 0)
+							{
+								u8_t network_key_index(static_cast<u8_t>(ind));
+
+								obj->set_network_key_index(network_key_index);
+
+								status = obj->get_network_key()->set_copy_of_buffer(
+									&m_network_key);
+								if (status != eap_status_ok)
+								{
+									EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+									return EAP_STATUS_RETURN(m_am_tools, status);
+								}
+
+								status = network_keys->add_object(obj, true);
+								if (status != eap_status_ok)
+								{
+									EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+									return EAP_STATUS_RETURN(m_am_tools, status);
+								}
+							}
+						}
+					}
+
+					{
+						for (u32_t ind = 0ul; ind < network_keys->get_object_count(); ++ind)
+						{
+							network_key_and_index_c * const obj = network_keys->get_object(ind);
+
+							if (obj != 0)
+							{
+								u8_t network_key_index(obj->get_network_key_index());
+
+								status = credential_payloads->copy_attribute_data(
+									simple_config_Attribute_Type_Network_Key_Index,
+									true,
+									&network_key_index,
+									sizeof(network_key_index));
+								if (status != eap_status_ok)
+								{
+									EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+									return EAP_STATUS_RETURN(m_am_tools, status);
+								}
+
+								status = credential_payloads->copy_attribute_data(
+									simple_config_Attribute_Type_Network_Key,
+									true,
+									obj->get_network_key()->get_data(),
+									obj->get_network_key()->get_data_length());
+								if (status != eap_status_ok)
+								{
+									EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+									return EAP_STATUS_RETURN(m_am_tools, status);
+								}
+							}
+						}
+					}
+
+					status = credential_payloads->copy_attribute_data(
+						simple_config_Attribute_Type_MAC_Address,
+						true,
+						m_MAC_address.get_data(),
+						m_MAC_address.get_data_length());
+					if (status != eap_status_ok)
+					{
+						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+						return EAP_STATUS_RETURN(m_am_tools, status);
+					}
+
+				}
+
+				simple_config_message_c * credential_data = new simple_config_message_c(m_am_tools, m_is_client);
+				eap_automatic_variable_c<simple_config_message_c> automatic_credential_data(m_am_tools, credential_data);
+
+				if (credential_data == 0
+					|| credential_data->get_is_valid() == false)
+				{
+					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+				}
+
+
+				status = credential_payloads->create_simple_config_message(
+					credential_data,
+					false);
+				if (status != eap_status_ok)
+				{
+					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					return EAP_STATUS_RETURN(m_am_tools, status);
+				}
+
+				status = plaintext_payloads->copy_attribute_data(
+					simple_config_Attribute_Type_Credential,
+					true,
+					credential_data->get_simple_config_message_data()->get_data(),
+					credential_data->get_simple_config_message_data()->get_data_length());
+				if (status != eap_status_ok)
+				{
+					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					return EAP_STATUS_RETURN(m_am_tools, status);
+				}
+			}
+
+			// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+			// Add other optional encrypted attributes.
+
+			if (m_new_password.get_is_valid_data() == true)
+			{
+				status = plaintext_payloads->copy_attribute_data(
+					simple_config_Attribute_Type_New_Password,
+					true,
+					m_new_password.get_data(),
+					m_new_password.get_data_length());
+				if (status != eap_status_ok)
+				{
+					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					return EAP_STATUS_RETURN(m_am_tools, status);
+				}
+
+				{
+					u16_t device_password_id(static_cast<u16_t>(simple_config_Device_Password_ID_Default_PIN));
+					u16_t network_order_device_password_id(eap_htons(device_password_id));
+
+					status = plaintext_payloads->copy_attribute_data(
+						simple_config_Attribute_Type_Device_Password_ID,
+						true,
+						&network_order_device_password_id,
+						sizeof(network_order_device_password_id));
+					if (status != eap_status_ok)
+					{
+						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+						return EAP_STATUS_RETURN(m_am_tools, status);
+					}
+				}
+			}
+
+		}
+
+		status = encrypt_payloads(
+			&m_auth_key,
+			&m_key_wrap_key,
+			plaintext_payloads,
+			encrypted_settings);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	automatic_encrypted_settings.do_not_free_variable();
+
+	status = payloads->add_attribute(
+		encrypted_settings);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	if (m_new_simple_config_message.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = payloads->create_simple_config_message(
+		&m_new_simple_config_message,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = add_authenticator_attribute(
+		&m_received_simple_config_message,
+		&m_new_simple_config_message);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	set_state(simple_config_state_wait_WSC_DONE);
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+#endif //#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::send_WSC_ACK()
+{
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_WSC_ACK()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	eap_status_e status(eap_status_process_general_error);
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	simple_config_payloads_c * payloads = new simple_config_payloads_c(m_am_tools);
+	eap_automatic_variable_c<simple_config_payloads_c> automatic_payloads(m_am_tools, payloads);
+
+	if (payloads == 0
+		|| payloads->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+	
+	status = add_common_attributes(
+		payloads,
+		simple_config_Message_Type_WSC_ACK,
+		true,
+		true);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	if (m_new_simple_config_message.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = payloads->create_simple_config_message(
+		&m_new_simple_config_message,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	set_state(simple_config_state_failure);
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::send_WSC_NACK()
+{
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_WSC_NACK()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	eap_status_e status(eap_status_process_general_error);
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	simple_config_payloads_c * payloads = new simple_config_payloads_c(m_am_tools);
+	eap_automatic_variable_c<simple_config_payloads_c> automatic_payloads(m_am_tools, payloads);
+
+	if (payloads == 0
+		|| payloads->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = add_common_attributes(
+		payloads,
+		simple_config_Message_Type_WSC_NACK,
+		true,
+		true);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	if (m_new_simple_config_message.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = payloads->create_simple_config_message(
+		&m_new_simple_config_message,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	set_state(simple_config_state_failure);
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::send_WSC_Done()
+{
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: simple_config_record_c::send_WSC_Done()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	eap_status_e status(eap_status_process_general_error);
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	simple_config_payloads_c * payloads = new simple_config_payloads_c(m_am_tools);
+	eap_automatic_variable_c<simple_config_payloads_c> automatic_payloads(m_am_tools, payloads);
+
+	if (payloads == 0
+		|| payloads->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+	
+	status = add_common_attributes(
+		payloads,
+		simple_config_Message_Type_WSC_DONE,
+		true,
+		true);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	if (m_new_simple_config_message.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = payloads->create_simple_config_message(
+		&m_new_simple_config_message,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	set_state(simple_config_state_simple_config_success);
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT void simple_config_record_c::send_error_notification(const eap_status_e error)
+{
+	EAP_TRACE_DEBUG(m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("simple_config_record_c::send_error_notification, error=%d\n"),
+		error));	
+
+	// Notifies the lower level of an authentication error.
+	eap_state_notification_c notification(
+		m_am_tools,
+		&m_send_network_id,
+		m_is_client,
+		eap_state_notification_generic,
+		eap_protocol_layer_general,
+		eap_type_none,
+		eap_state_none,
+		eap_general_state_authentication_error,
+		0,
+		false);
+
+	notification.set_authentication_error(error);
+
+	get_type_partner()->state_notification(&notification);
+}
+
+//--------------------------------------------------
+
+//
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::initalize_error_message_timeout()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	cancel_error_message_timeout();
+
+	eap_status_e status = get_type_partner()->set_timer(
+		this,
+		SIMPLE_CONFIG_RECORD_ERROR_MESSAGE_RECEIVED_ID,
+		0,
+		m_error_message_received_timeout);
+
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("TIMER: %s: SIMPLE_CONFIG_RECORD_ERROR_MESSAGE_RECEIVED_ID set %d ms, this = 0x%08x.\n"),
+		 (m_is_client == true) ? "client": "server",
+		 m_error_message_received_timeout,
+		 this));
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+//
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::cancel_error_message_timeout()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	eap_status_e status = get_type_partner()->cancel_timer(
+		this,
+		SIMPLE_CONFIG_RECORD_ERROR_MESSAGE_RECEIVED_ID);
+
+	EAP_UNREFERENCED_PARAMETER(status); // in release
+	
+	EAP_TRACE_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("TIMER: %s, SIMPLE_CONFIG_RECORD_ERROR_MESSAGE_RECEIVED_ID cancelled status %d, this = 0x%08x.\n"),
+		 (m_is_client == true ? "client": "server"),
+		 status,
+		 this));
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//--------------------------------------------------
+
+//
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::initialize_M2D_received_timeout()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	eap_status_e status(eap_status_ok);
+
+	if (m_M2D_received_timeout_active == false)
+	{
+		cancel_M2D_received_timeout();
+
+		status = get_type_partner()->set_timer(
+			this,
+			SIMPLE_CONFIG_RECORD_M2D_RECEIVED_ID,
+			0,
+			m_error_message_received_timeout);
+
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		EAP_TRACE_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_DEFAULT, 
+			(EAPL("TIMER: %s: SIMPLE_CONFIG_RECORD_M2D_RECEIVED_ID set %d ms, this = 0x%08x.\n"),
+			 (m_is_client == true) ? "client": "server",
+			 m_error_message_received_timeout,
+			 this));
+	}
+	else
+	{
+		EAP_TRACE_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_DEFAULT, 
+			(EAPL("TIMER: %s: SIMPLE_CONFIG_RECORD_M2D_RECEIVED_ID already set.\n"),
+			 (m_is_client == true) ? "client": "server"));
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+//
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::cancel_M2D_received_timeout()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	eap_status_e status = get_type_partner()->cancel_timer(
+		this,
+		SIMPLE_CONFIG_RECORD_M2D_RECEIVED_ID);
+
+	m_M2D_received_timeout_active = false;
+
+	EAP_UNREFERENCED_PARAMETER(status); // in release
+	
+	EAP_TRACE_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("TIMER: %s, SIMPLE_CONFIG_RECORD_M2D_RECEIVED_ID cancelled status %d, this = 0x%08x.\n"),
+		 (m_is_client == true ? "client": "server"),
+		 status,
+		 this));
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//--------------------------------------------------
+
+//
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::timer_expired(
+	const u32_t id,
+	void * data
+	)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_UNREFERENCED_PARAMETER(data); // Only trace uses this.
+	
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("TIMER: [0x%08x]->simple_config_record_c::timer_expired(id 0x%02x, data 0x%08x)\n"),
+		 this,
+		 id,
+		 data));
+
+	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
+
+	eap_status_e status = eap_status_process_general_error;
+
+	if (id == SIMPLE_CONFIG_RECORD_ERROR_MESSAGE_RECEIVED_ID)
+	{
+		EAP_TRACE_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_DEFAULT, 
+			(EAPL("TIMER: %s: SIMPLE_CONFIG_RECORD_ERROR_MESSAGE_RECEIVED_ID elapsed.\n"),
+			 (m_is_client == true ? "client": "server")
+			 ));
+
+		status = send_WSC_NACK();
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = check_sent_simple_config_message();
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		(void) send_error_notification(m_handshake_error);
+
+	}
+	else if (id == SIMPLE_CONFIG_RECORD_M2D_RECEIVED_ID)
+	{
+		(void) m_am_simple_config_services->received_registrar_information(&m_M2D_payloads);
+
+		(void) send_error_notification(m_handshake_error);
+
+		m_M2D_received_timeout_active = false;
+	}
+	else
+	{
+		EAP_TRACE_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_DEFAULT, 
+			(EAPL("ERROR: TIMER: %s: unknown timer elapsed.\n"),
+			 (m_is_client == true ? "client": "server")
+			 ));
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//--------------------------------------------------
+
+//
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::timer_delete_data(
+	const u32_t /*id*/,
+	void * /*data*/
+	)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//--------------------------------------------------
+
+//
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::verify_nonces_and_authenticator(
+	const eap_variable_data_c * const auth_key,
+	const eap_variable_data_c * const enrollee_nonce,
+	const eap_variable_data_c * const registrar_nonce,
+	const simple_config_payloads_c * const payloads,
+	const bool check_enrollee_nonce,
+	const bool check_registrar_nonce,
+	const bool check_authenticator)
+{
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: parse_function: simple_config_record_c::verify_authenticator()\n"),
+		 (m_is_client == true ? "client": "server")));
+
+	if (check_enrollee_nonce == true)
+	{
+		// Verify Enrollee Nonce.
+
+		simple_config_variable_data_c * const enrollee_nonce_attribute
+			= payloads->get_attribute_pointer(simple_config_Attribute_Type_Enrollee_Nonce);
+		if (enrollee_nonce_attribute == 0)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_missing_payload);
+		}
+
+		if (enrollee_nonce->compare(
+				enrollee_nonce_attribute->get_data(enrollee_nonce_attribute->get_data_length()),
+				enrollee_nonce_attribute->get_data_length()) != 0)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
+		}
+	}
+
+	if (check_registrar_nonce == true)
+	{
+		// Verify Registrar Nonce.
+
+		simple_config_variable_data_c * const registrar_nonce_attribute
+			= payloads->get_attribute_pointer(simple_config_Attribute_Type_Registrar_Nonce);
+		if (registrar_nonce_attribute == 0)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_missing_payload);
+		}
+
+		if (registrar_nonce->compare(
+				registrar_nonce_attribute->get_data(registrar_nonce_attribute->get_data_length()),
+				registrar_nonce_attribute->get_data_length()) != 0)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
+		}
+	}
+
+	if (check_authenticator == true)
+	{
+		// Verify Authenticator.
+		crypto_sha_256_c sha_256(m_am_tools);
+		if (sha_256.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		crypto_hmac_c hmac_sha_256(
+			m_am_tools,
+			&sha_256,
+			false);
+		if (hmac_sha_256.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_DEFAULT, 
+			(EAPL("SIMPLE_CONFIG authenticator auth_key"),
+			 auth_key->get_data(),
+			 auth_key->get_data_length()));
+
+		eap_status_e status = hmac_sha_256.hmac_set_key(auth_key);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_DEFAULT, 
+			(EAPL("SIMPLE_CONFIG authenticator data"),
+			 m_previous_simple_config_message.get_simple_config_message_data()->get_data(),
+			 m_previous_simple_config_message.get_simple_config_message_data()->get_data_length()));
+
+		status = hmac_sha_256.hmac_update(
+			m_previous_simple_config_message.get_simple_config_message_data()->get_data(),
+			m_previous_simple_config_message.get_simple_config_message_data()->get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = payloads->add_payloads_to_simple_config_authenticator(
+			&hmac_sha_256,
+			false);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		{
+			eap_variable_data_c authenticator(m_am_tools);
+
+			if (authenticator.get_is_valid() == false)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+			}
+
+			status = authenticator.set_buffer_length(hmac_sha_256.get_digest_length());
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+
+			status = authenticator.set_data_length(hmac_sha_256.get_digest_length());
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+
+			u32_t md_length(hmac_sha_256.get_digest_length());
+			
+			status = hmac_sha_256.hmac_final(
+				authenticator.get_data(hmac_sha_256.get_digest_length()),
+				&md_length);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+
+			EAP_TRACE_DATA_DEBUG(
+				m_am_tools, 
+				TRACE_FLAGS_DEFAULT, 
+				(EAPL("SIMPLE_CONFIG authenticator"),
+				 authenticator.get_data(),
+				 authenticator.get_data_length()));
+			
+			status = authenticator.set_data_length(SIMPLE_CONFIG_AUTHENTICATOR_LENGTH);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+			
+			simple_config_variable_data_c * const received_authenticator
+				= payloads->get_attribute_pointer(simple_config_Attribute_Type_Authenticator);
+			if (received_authenticator == 0)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, eap_status_missing_payload);
+			}
+
+			if (authenticator.compare(
+					received_authenticator->get_data(received_authenticator->get_data_length()),
+					received_authenticator->get_data_length()) != 0)
+			{
+				EAP_TRACE_DATA_ERROR(
+					m_am_tools, 
+					TRACE_FLAGS_DEFAULT, 
+					(EAPL("SIMPLE_CONFIG    local authenticator"),
+					 authenticator.get_data(),
+					 authenticator.get_data_length()));
+
+				EAP_TRACE_DATA_ERROR(
+					m_am_tools, 
+					TRACE_FLAGS_DEFAULT, 
+					(EAPL("SIMPLE_CONFIG received authenticator"),
+					 received_authenticator->get_data(received_authenticator->get_data_length()),
+					 received_authenticator->get_data_length()));
+				
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure);
+			}
+			else
+			{
+				EAP_TRACE_DEBUG(
+					m_am_tools,
+					TRACE_FLAGS_DEFAULT,
+					(EAPL("SIMPLE_CONFIG: %s: parse_function: simple_config_record_c::verify_authenticator(): Authenticator OK\n"),
+					 (m_is_client == true ? "client": "server")));
+			}
+		}
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//--------------------------------------------------
+
+//
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::start_simple_config_authentication(
+	const eap_variable_data_c * const NAI ///< This is the full NAI of the client.
+	)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: start_simple_config_authentication()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	if (verify_state(simple_config_state_wait_simple_config_start) == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
+	}
+
+	set_state(simple_config_state_process_simple_config_start);
+
+	if (NAI == 0
+		|| NAI->get_is_valid_data() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_identity);
+	}
+
+	eap_status_e status = m_NAI.set_copy_of_buffer(NAI);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	m_allow_message_send = false;
+
+	status = m_am_simple_config_services->query_network_and_device_parameters(get_state());
+
+	m_allow_message_send = true;
+
+	if (status == eap_status_pending_request)
+	{
+		// This is pending query, that will be completed by
+		// complete_query_network_and_device_parameters() call.
+		m_pending_query_network_and_device_parameters = true;
+
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+	else if (status == eap_status_completed_request)
+	{
+		// This is already completed by complete_query_network_and_device_parameters() call.
+
+		status = check_sent_simple_config_message();
+
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+	else if (status == eap_status_ok)
+	{
+		// This is also an error case, because this call is always completed on success. 
+		status = eap_status_process_general_error;
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+	else // All other status values means error, because this call is always completed on success.
+	{
+		// This is an error case.
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+}
+
+//--------------------------------------------------
+
+#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+static const simple_config_Attribute_Type_e needed_payloads_of_M1[]
+	= {
+		simple_config_Attribute_Type_Version,
+		simple_config_Attribute_Type_Message_Type,
+		simple_config_Attribute_Type_UUID_E,
+		simple_config_Attribute_Type_MAC_Address,
+		simple_config_Attribute_Type_Enrollee_Nonce,
+		simple_config_Attribute_Type_Public_Key,
+		simple_config_Attribute_Type_Authentication_Type_Flags,
+		simple_config_Attribute_Type_Encryption_Type_Flags,
+		simple_config_Attribute_Type_Connection_Type_Flags,
+		simple_config_Attribute_Type_Config_Methods,
+		simple_config_Attribute_Type_Simple_Config_State,
+		simple_config_Attribute_Type_Manufacturer,
+		simple_config_Attribute_Type_Model_Name,
+		simple_config_Attribute_Type_Model_Number,
+		simple_config_Attribute_Type_Serial_Number,
+		simple_config_Attribute_Type_Primary_Device_Type,
+		simple_config_Attribute_Type_Device_Name,
+		simple_config_Attribute_Type_RF_Band,
+		simple_config_Attribute_Type_Association_State,
+		simple_config_Attribute_Type_Device_Password_ID,
+		simple_config_Attribute_Type_Configuration_Error,
+		simple_config_Attribute_Type_OS_Version,
+	};
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::process_M1(
+	const simple_config_payloads_c * const payloads)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: parse_function: simple_config_record_c::process_M1()\n"),
+		 (m_is_client == true ? "client": "server")));
+
+	if (verify_state(simple_config_state_wait_M1) == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
+	}
+
+	set_state(simple_config_state_process_M1);
+
+	eap_status_e status = payloads->check_payloads_existense(
+		needed_payloads_of_M1, // const simple_config_Attribute_Type_e * const needed_payloads,
+		sizeof(needed_payloads_of_M1)/sizeof(needed_payloads_of_M1[0]));
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// Save Enrollee Nonce.
+	status = payloads->get_attribute_data(
+		simple_config_Attribute_Type_Enrollee_Nonce,
+		&m_enrollee_nonce);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// Save Enrollee MAC.
+	status = payloads->get_attribute_data(
+		simple_config_Attribute_Type_MAC_Address,
+		&m_enrollee_mac);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// Save Public Key.
+	status = payloads->get_attribute_data(
+		simple_config_Attribute_Type_Public_Key,
+		&m_peer_public_dhe_key);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	{
+		u16_t data(0ul);
+
+		status = payloads->get_attribute_data(
+			simple_config_Attribute_Type_Device_Password_ID,
+			&data);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		m_received_Device_Password_ID = static_cast<simple_config_Device_Password_ID_e>(data);
+	}
+
+	eap_variable_data_c dhe_shared_secret(m_am_tools);
+
+	if (dhe_shared_secret.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = generate_dhe_shared_secret(&m_peer_public_dhe_key, &dhe_shared_secret);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = generate_kdk(
+		&dhe_shared_secret,
+		&m_enrollee_nonce,
+		&m_enrollee_mac,
+		&m_registrar_nonce,
+		&m_kdk);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = derive_additional_keys(
+		&m_kdk,
+		&m_auth_key,
+		&m_key_wrap_key,
+		&m_EMSK);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	m_allow_message_send = false;
+
+	status = m_am_simple_config_services->query_network_and_device_parameters(get_state());
+
+	m_allow_message_send = true;
+
+	if (status == eap_status_pending_request)
+	{
+		// This is pending query, that will be completed by
+		// complete_query_network_and_device_parameters() call.
+		m_pending_query_network_and_device_parameters = true;
+
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+	else if (status == eap_status_completed_request)
+	{
+		// This is already completed by complete_query_network_and_device_parameters() call.
+
+		status = check_sent_simple_config_message();
+
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+	else if (status == eap_status_ok)
+	{
+		// This is also an error case, because this call is always completed on success. 
+		status = eap_status_process_general_error;
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+	else // All other status values means error, because this call is always completed on success.
+	{
+		// This is an error case.
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+#endif //#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+//--------------------------------------------------
+
+static const simple_config_Attribute_Type_e needed_payloads_of_M2[]
+	= {
+		simple_config_Attribute_Type_Version,
+		simple_config_Attribute_Type_Message_Type,
+		simple_config_Attribute_Type_Enrollee_Nonce,
+		simple_config_Attribute_Type_Registrar_Nonce,
+		simple_config_Attribute_Type_UUID_R,
+		simple_config_Attribute_Type_Public_Key,
+		simple_config_Attribute_Type_Authentication_Type_Flags,
+		simple_config_Attribute_Type_Encryption_Type_Flags,
+		simple_config_Attribute_Type_Connection_Type_Flags,
+		simple_config_Attribute_Type_Config_Methods,
+		simple_config_Attribute_Type_Manufacturer,
+		simple_config_Attribute_Type_Model_Name,
+		simple_config_Attribute_Type_Model_Number,
+		simple_config_Attribute_Type_Serial_Number,
+		simple_config_Attribute_Type_Primary_Device_Type,
+		simple_config_Attribute_Type_Device_Name,
+		simple_config_Attribute_Type_RF_Band,
+		simple_config_Attribute_Type_Association_State,
+		simple_config_Attribute_Type_Configuration_Error,
+		simple_config_Attribute_Type_Device_Password_ID,
+		simple_config_Attribute_Type_OS_Version,
+		simple_config_Attribute_Type_Authenticator,
+	};
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::process_M2(
+	const simple_config_payloads_c * const payloads)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: parse_function: simple_config_record_c::process_M2()\n"),
+		 (m_is_client == true ? "client": "server")));
+
+	if (verify_state(simple_config_state_wait_M2) == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
+	}
+
+	eap_status_e status = payloads->check_payloads_existense(
+		needed_payloads_of_M2, // const simple_config_Attribute_Type_e * const needed_payloads,
+		sizeof(needed_payloads_of_M2)/sizeof(needed_payloads_of_M2[0]));
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	{
+		// Verify Enrollee Nonce.
+		simple_config_variable_data_c * const enrollee_nonce
+			= payloads->get_attribute_pointer(simple_config_Attribute_Type_Enrollee_Nonce);
+		if (enrollee_nonce == 0)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_missing_payload);
+		}
+
+		if (m_enrollee_nonce.compare(
+				enrollee_nonce->get_data(enrollee_nonce->get_data_length()),
+				enrollee_nonce->get_data_length()) != 0)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
+		}
+	}
+
+
+	eap_variable_data_c registrar_nonce_data(m_am_tools);
+
+	if (registrar_nonce_data.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = payloads->get_attribute_data(
+		simple_config_Attribute_Type_Registrar_Nonce,
+		&registrar_nonce_data);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	eap_variable_data_c registrar_public_key_data(m_am_tools);
+
+	if (registrar_public_key_data.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	eap_variable_data_c auth_key(m_am_tools);
+
+	if (auth_key.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	eap_variable_data_c key_wrap_key(m_am_tools);
+
+	if (key_wrap_key.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	eap_variable_data_c EMSK(m_am_tools);
+
+	if (EMSK.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	{
+		// Save Registrar Public Key.
+		status = payloads->get_attribute_data(
+			simple_config_Attribute_Type_Public_Key,
+			&registrar_public_key_data);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+
+		eap_variable_data_c dhe_shared_secret(m_am_tools);
+
+		if (dhe_shared_secret.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = generate_dhe_shared_secret(&registrar_public_key_data, &dhe_shared_secret);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		eap_variable_data_c kdk(m_am_tools);
+
+		if (kdk.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = generate_kdk(
+			&dhe_shared_secret,
+			&m_enrollee_nonce,
+			&m_enrollee_mac,
+			&registrar_nonce_data,
+			&kdk);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = derive_additional_keys(
+			&kdk,
+			&auth_key,
+			&key_wrap_key,
+			&EMSK);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	status = verify_nonces_and_authenticator(
+		&auth_key,
+		&m_enrollee_nonce,
+		&registrar_nonce_data,
+		payloads,
+		false, // No Enrolle Nonce
+		true, // Check Registrar Nonce
+		true); // Check Authenticator
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	// Check Device Password ID.
+
+	{
+		u16_t data(0ul);
+
+		status = payloads->get_attribute_data(
+			simple_config_Attribute_Type_Device_Password_ID,
+			&data);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		m_received_Device_Password_ID = static_cast<simple_config_Device_Password_ID_e>(data);
+
+#if 0 // This is done to bypass some external registrar. We do not test Device Password ID.
+		if (m_received_Device_Password_ID != m_local_Device_Password_ID)
+		{
+			// No matching Device Password ID.
+			if (m_local_Device_Password_ID == simple_config_Device_Password_ID_Default_PIN)
+			{
+				m_handshake_error = eap_status_pin_code_authentication_not_supported;
+			}
+			else if (m_local_Device_Password_ID == simple_config_Device_Password_ID_PushButton)
+			{
+				m_handshake_error = eap_status_push_button_authentication_not_supported;
+			}
+			else
+			{
+				m_handshake_error = eap_status_network_authentication_failure;
+			}
+
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, m_handshake_error);
+		}
+#endif
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	// Save Registrar Nonce.
+	status = m_registrar_nonce.set_copy_of_buffer(&registrar_nonce_data);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// Save Registrar Public Key.
+	status = m_peer_public_dhe_key.set_copy_of_buffer(&registrar_public_key_data);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// Save Authentication Key.
+	status = m_auth_key.set_copy_of_buffer(&auth_key);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// Save Key Wrap Key.
+	status = m_key_wrap_key.set_copy_of_buffer(&key_wrap_key);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// Save EMSK.
+	status = m_EMSK.set_copy_of_buffer(&EMSK);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	status = cancel_M2D_received_timeout();
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	status = send_M3();
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+static const simple_config_Attribute_Type_e needed_payloads_of_M2D[]
+	= {
+		simple_config_Attribute_Type_Version,
+		simple_config_Attribute_Type_Message_Type,
+		simple_config_Attribute_Type_Enrollee_Nonce,
+		simple_config_Attribute_Type_Registrar_Nonce,
+		simple_config_Attribute_Type_UUID_R,
+		simple_config_Attribute_Type_Authentication_Type_Flags,
+		simple_config_Attribute_Type_Encryption_Type_Flags,
+		simple_config_Attribute_Type_Connection_Type_Flags,
+		simple_config_Attribute_Type_Config_Methods,
+		simple_config_Attribute_Type_Manufacturer,
+		simple_config_Attribute_Type_Model_Name,
+		simple_config_Attribute_Type_Model_Number,
+		simple_config_Attribute_Type_Serial_Number,
+		simple_config_Attribute_Type_Primary_Device_Type,
+		simple_config_Attribute_Type_Device_Name,
+		simple_config_Attribute_Type_RF_Band,
+		simple_config_Attribute_Type_Association_State,
+		simple_config_Attribute_Type_Configuration_Error,
+		simple_config_Attribute_Type_OS_Version,
+	};
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::process_M2D(
+	const simple_config_payloads_c * const payloads)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: parse_function: simple_config_record_c::process_M2D()\n"),
+		 (m_is_client == true ? "client": "server")));
+
+	if (verify_state(simple_config_state_wait_M2) == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
+	}
+
+	eap_status_e status = payloads->check_payloads_existense(
+		needed_payloads_of_M2D, // const simple_config_Attribute_Type_e * const needed_payloads,
+		sizeof(needed_payloads_of_M2D)/sizeof(needed_payloads_of_M2D[0]));
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// Save Registrar Nonce.
+	status = payloads->get_attribute_data(
+		simple_config_Attribute_Type_Registrar_Nonce,
+		&m_registrar_nonce);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	if (m_handshake_error == eap_status_ok
+		|| m_handshake_error == eap_status_authentication_failure)
+	{
+		u8_t RF_Band(simple_config_RF_Bands_2_4_GHz);
+
+		status = payloads->get_attribute_data(
+			simple_config_Attribute_Type_RF_Band,
+			&RF_Band);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		simple_config_RF_Bands_e received_bands = static_cast<simple_config_RF_Bands_e>(RF_Band);
+
+		if ((received_bands & m_Rf_Bands) == 0)
+		{
+			// No matching RF Band.
+			if ((m_Rf_Bands & simple_config_RF_Bands_2_4_GHz) != 0)
+			{
+				m_handshake_error = eap_status_rf_band_2_4_ghz_not_supported;
+			}
+			else if ((m_Rf_Bands & simple_config_RF_Bands_5_0_GHz) != 0)
+			{
+				m_handshake_error = eap_status_rf_band_5_0_ghz_not_supported;
+			}
+		}
+
+	}
+
+	if (m_handshake_error == eap_status_ok
+		|| m_handshake_error == eap_status_authentication_failure)
+	{
+		u16_t error(0ul);
+
+		status = payloads->get_attribute_data(
+			simple_config_Attribute_Type_Configuration_Error,
+			&error);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		simple_config_Configuration_Error_e received_error = static_cast<simple_config_Configuration_Error_e>(error);
+
+		if (received_error != simple_config_Configuration_Error_No_Error)
+		{
+			if (received_error == simple_config_Configuration_Error_OOB_Interface_Read_Error)
+			{
+				m_handshake_error = eap_status_oob_interface_read_error;
+			}
+			else if (received_error == simple_config_Configuration_Error_Decryption_CRC_Failure)
+			{
+				m_handshake_error = eap_status_decryption_crc_failure;
+			}
+			else if (received_error == simple_config_Configuration_Error_2_4_channel_not_supported)
+			{
+				m_handshake_error = eap_status_rf_band_2_4_ghz_not_supported;
+			}
+			else if (received_error == simple_config_Configuration_Error_5_0_channel_not_supported)
+			{
+				m_handshake_error = eap_status_rf_band_5_0_ghz_not_supported;
+			}
+			else if (received_error == simple_config_Configuration_Error_Signal_too_weak)
+			{
+				m_handshake_error = eap_status_signal_too_weak;
+			}
+			else if (received_error == simple_config_Configuration_Error_Network_auth_failure)
+			{
+				m_handshake_error = eap_status_network_authentication_failure;
+			}
+			else if (received_error == simple_config_Configuration_Error_Network_association_failure)
+			{
+				m_handshake_error = eap_status_network_association_failure;
+			}
+			else if (received_error == simple_config_Configuration_Error_No_DHCP_response)
+			{
+				m_handshake_error = eap_status_no_dhcp_response;
+			}
+			else if (received_error == simple_config_Configuration_Error_Failed_DHCP_config)
+			{
+				m_handshake_error = eap_status_failed_dhcp_configure;
+			}
+			else if (received_error == simple_config_Configuration_Error_IP_address_conflict)
+			{
+				m_handshake_error = eap_status_ip_address_conflict;
+			}
+			else if (received_error == simple_config_Configuration_Error_Couldnt_connect_to_Registrar)
+			{
+				m_handshake_error = eap_status_could_not_connect_to_registrar;
+			}
+			else if (received_error == simple_config_Configuration_Error_Multiple_PBC_sessions_detected)
+			{
+				m_handshake_error = eap_status_multiple_pbc_sessions_detected;
+			}
+			else if (received_error == simple_config_Configuration_Error_Rogue_activity_suspected)
+			{
+				m_handshake_error = eap_status_rogue_activity_suspected;
+			}
+			else if (received_error == simple_config_Configuration_Error_Device_busy)
+			{
+				m_handshake_error = eap_status_device_busy;
+			}
+			else if (received_error == simple_config_Configuration_Error_Setup_locked)
+			{
+				m_handshake_error = eap_status_setup_locked;
+			}
+			else if (received_error == simple_config_Configuration_Error_Message_Timeout)
+			{
+				m_handshake_error = eap_status_message_timeout;
+			}
+			else if (received_error == simple_config_Configuration_Error_Registration_Session_Timeout)
+			{
+				m_handshake_error = eap_status_registration_session_timeout;
+			}
+			else if (received_error == simple_config_Configuration_Error_Device_Password_Auth_Failure)
+			{
+				m_handshake_error = eap_status_device_password_authentication_failure;
+			}
+		}
+
+	}
+
+	if (m_handshake_error == eap_status_ok)
+	{
+		m_handshake_error = eap_status_authentication_failure;
+	}
+
+	status = initialize_M2D_received_timeout();
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	{
+		simple_config_payloads_c * const copied_payloads = payloads->copy();
+
+		if (copied_payloads == 0
+			|| copied_payloads->get_is_valid() == false)
+		{
+			delete copied_payloads;
+
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = m_M2D_payloads.add_object(copied_payloads, true);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	status = send_WSC_ACK();
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+static const simple_config_Attribute_Type_e needed_payloads_of_M3[]
+	= {
+		simple_config_Attribute_Type_Version,
+		simple_config_Attribute_Type_Message_Type,
+		simple_config_Attribute_Type_Registrar_Nonce,
+		simple_config_Attribute_Type_E_Hash1,
+		simple_config_Attribute_Type_E_Hash2,
+		simple_config_Attribute_Type_Authenticator,
+	};
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::process_M3(
+	const simple_config_payloads_c * const payloads)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: parse_function: simple_config_record_c::process_M3()\n"),
+		 (m_is_client == true ? "client": "server")));
+
+	if (verify_state(simple_config_state_wait_M3) == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
+	}
+
+	eap_status_e status = payloads->check_payloads_existense(
+		needed_payloads_of_M3, // const simple_config_Attribute_Type_e * const needed_payloads,
+		sizeof(needed_payloads_of_M3)/sizeof(needed_payloads_of_M3[0]));
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+	// Save E-Hash1 and E-Hash2
+
+	status = payloads->get_attribute_data(
+		simple_config_Attribute_Type_E_Hash1,
+		&m_EHash1);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->get_attribute_data(
+		simple_config_Attribute_Type_E_Hash2,
+		&m_EHash2);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	status = send_M4();
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+#endif //#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+//--------------------------------------------------
+
+static const simple_config_Attribute_Type_e needed_payloads_of_M4[]
+	= {
+		simple_config_Attribute_Type_Version,
+		simple_config_Attribute_Type_Message_Type,
+		simple_config_Attribute_Type_Enrollee_Nonce,
+		simple_config_Attribute_Type_R_Hash1,
+		simple_config_Attribute_Type_R_Hash2,
+		simple_config_Attribute_Type_Encrypted_Settings,
+		simple_config_Attribute_Type_Authenticator,
+	};
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::process_M4(
+	const simple_config_payloads_c * const payloads)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: parse_function: simple_config_record_c::process_M4()\n"),
+		 (m_is_client == true ? "client": "server")));
+
+	if (verify_state(simple_config_state_wait_M4) == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
+	}
+
+	eap_status_e status = payloads->check_payloads_existense(
+		needed_payloads_of_M4, // const simple_config_Attribute_Type_e * const needed_payloads,
+		sizeof(needed_payloads_of_M4)/sizeof(needed_payloads_of_M4[0]));
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+	// Save R-Hash1 and R-Hash2
+
+	status = payloads->get_attribute_data(
+		simple_config_Attribute_Type_R_Hash1,
+		&m_RHash1);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = payloads->get_attribute_data(
+		simple_config_Attribute_Type_R_Hash2,
+		&m_RHash2);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	{
+		// Decrypt Encrypted Settings.
+		simple_config_variable_data_c * const Encrypted_Settings
+			= payloads->get_attribute_pointer(simple_config_Attribute_Type_Encrypted_Settings);
+		if (Encrypted_Settings == 0)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_missing_payload);
+		}
+
+		simple_config_payloads_c * plaintext_payloads = new simple_config_payloads_c(m_am_tools);
+		eap_automatic_variable_c<simple_config_payloads_c> automatic_plaintext_payloads(m_am_tools, plaintext_payloads);
+
+		if (plaintext_payloads == 0
+			|| plaintext_payloads->get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = decrypt_payloads(
+			&m_auth_key,
+			&m_key_wrap_key,
+			Encrypted_Settings,
+			plaintext_payloads);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+
+		status = plaintext_payloads->get_attribute_data(
+			simple_config_Attribute_Type_R_SNonce1,
+			&m_R_SNonce1);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	{
+		eap_variable_data_c local_RHash1(m_am_tools);
+
+		if (local_RHash1.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		// Verify m_R_SNonce1 and m_RHash1.
+		status = generate_er_hashs(
+			true,
+			&m_device_password,
+			&m_own_public_dhe_key,
+			&m_peer_public_dhe_key,
+			&m_PSK1,
+			&m_R_SNonce1,
+			&local_RHash1,
+			0,
+			0,
+			0);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		// Compare RHash1.
+		if (local_RHash1.compare(&m_RHash1) != 0)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_device_password_authentication_failure);
+		}
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	status = send_M5();
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+static const simple_config_Attribute_Type_e needed_payloads_of_M5[]
+	= {
+		simple_config_Attribute_Type_Version,
+		simple_config_Attribute_Type_Message_Type,
+		simple_config_Attribute_Type_Registrar_Nonce,
+		simple_config_Attribute_Type_Encrypted_Settings,
+		simple_config_Attribute_Type_Authenticator,
+	};
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::process_M5(
+	const simple_config_payloads_c * const payloads)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: parse_function: simple_config_record_c::process_M5()\n"),
+		 (m_is_client == true ? "client": "server")));
+
+	if (verify_state(simple_config_state_wait_M5) == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
+	}
+
+	eap_status_e status = payloads->check_payloads_existense(
+		needed_payloads_of_M5, // const simple_config_Attribute_Type_e * const needed_payloads,
+		sizeof(needed_payloads_of_M5)/sizeof(needed_payloads_of_M5[0]));
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	{
+		// Decrypt Encrypted Settings.
+		simple_config_variable_data_c * const Encrypted_Settings
+			= payloads->get_attribute_pointer(simple_config_Attribute_Type_Encrypted_Settings);
+		if (Encrypted_Settings == 0)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_missing_payload);
+		}
+
+		simple_config_payloads_c * plaintext_payloads = new simple_config_payloads_c(m_am_tools);
+		eap_automatic_variable_c<simple_config_payloads_c> automatic_plaintext_payloads(m_am_tools, plaintext_payloads);
+
+		if (plaintext_payloads == 0
+			|| plaintext_payloads->get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = decrypt_payloads(
+			&m_auth_key,
+			&m_key_wrap_key,
+			Encrypted_Settings,
+			plaintext_payloads);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+
+		status = plaintext_payloads->get_attribute_data(
+			simple_config_Attribute_Type_E_SNonce1,
+			&m_E_SNonce1);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	{
+		eap_variable_data_c local_EHash1(m_am_tools);
+
+		if (local_EHash1.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		// Verify m_E_SNonce1 and m_EHash1.
+		status = generate_er_hashs(
+			true,
+			&m_device_password,
+			&m_peer_public_dhe_key,
+			&m_own_public_dhe_key,
+			&m_PSK1,
+			&m_E_SNonce1,
+			&local_EHash1,
+			0,
+			0,
+			0);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		// Compare EHash1.
+		if (local_EHash1.compare(&m_EHash1) != 0)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_device_password_authentication_failure);
+		}
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	status = send_M6();
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+#endif //#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+//--------------------------------------------------
+
+static const simple_config_Attribute_Type_e needed_payloads_of_M6[]
+	= {
+		simple_config_Attribute_Type_Version,
+		simple_config_Attribute_Type_Message_Type,
+		simple_config_Attribute_Type_Enrollee_Nonce,
+		simple_config_Attribute_Type_Encrypted_Settings,
+		simple_config_Attribute_Type_Authenticator,
+	};
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::process_M6(
+	const simple_config_payloads_c * const payloads)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: parse_function: simple_config_record_c::process_M6()\n"),
+		 (m_is_client == true ? "client": "server")));
+
+	if (verify_state(simple_config_state_wait_M6) == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
+	}
+
+	eap_status_e status = payloads->check_payloads_existense(
+		needed_payloads_of_M6, // const simple_config_Attribute_Type_e * const needed_payloads,
+		sizeof(needed_payloads_of_M6)/sizeof(needed_payloads_of_M6[0]));
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	{
+		// Decrypt Encrypted Settings.
+		simple_config_variable_data_c * const Encrypted_Settings
+			= payloads->get_attribute_pointer(simple_config_Attribute_Type_Encrypted_Settings);
+		if (Encrypted_Settings == 0)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_missing_payload);
+		}
+
+		simple_config_payloads_c * plaintext_payloads = new simple_config_payloads_c(m_am_tools);
+		eap_automatic_variable_c<simple_config_payloads_c> automatic_plaintext_payloads(m_am_tools, plaintext_payloads);
+
+		if (plaintext_payloads == 0
+			|| plaintext_payloads->get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = decrypt_payloads(
+			&m_auth_key,
+			&m_key_wrap_key,
+			Encrypted_Settings,
+			plaintext_payloads);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+
+		status = plaintext_payloads->get_attribute_data(
+			simple_config_Attribute_Type_R_SNonce2,
+			&m_R_SNonce2);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	{
+		eap_variable_data_c local_RHash2(m_am_tools);
+
+		if (local_RHash2.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		// Verify m_R_SNonce2 and m_RHash2.
+		status = generate_er_hashs(
+			true,
+			&m_device_password,
+			&m_own_public_dhe_key,
+			&m_peer_public_dhe_key,
+			0,
+			0,
+			0,
+			&m_PSK2,
+			&m_R_SNonce2,
+			&local_RHash2);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		// Compare RHash2.
+		if (local_RHash2.compare(&m_RHash2) != 0)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_device_password_authentication_failure);
+		}
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	status = send_M7();
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+static const simple_config_Attribute_Type_e needed_payloads_of_M7[]
+	= {
+		simple_config_Attribute_Type_Version,
+		simple_config_Attribute_Type_Message_Type,
+		simple_config_Attribute_Type_Registrar_Nonce,
+		simple_config_Attribute_Type_Encrypted_Settings,
+		simple_config_Attribute_Type_Authenticator,
+	};
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::process_M7(
+	const simple_config_payloads_c * const payloads)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: parse_function: simple_config_record_c::process_M7()\n"),
+		 (m_is_client == true ? "client": "server")));
+
+	if (verify_state(simple_config_state_wait_M7) == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
+	}
+
+	eap_status_e status = payloads->check_payloads_existense(
+		needed_payloads_of_M7, // const simple_config_Attribute_Type_e * const needed_payloads,
+		sizeof(needed_payloads_of_M7)/sizeof(needed_payloads_of_M7[0]));
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	{
+		// Decrypt Encrypted Settings.
+		simple_config_variable_data_c * const Encrypted_Settings
+			= payloads->get_attribute_pointer(simple_config_Attribute_Type_Encrypted_Settings);
+		if (Encrypted_Settings == 0)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_missing_payload);
+		}
+
+		simple_config_payloads_c * plaintext_payloads = new simple_config_payloads_c(m_am_tools);
+		eap_automatic_variable_c<simple_config_payloads_c> automatic_plaintext_payloads(m_am_tools, plaintext_payloads);
+
+		if (plaintext_payloads == 0
+			|| plaintext_payloads->get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = decrypt_payloads(
+			&m_auth_key,
+			&m_key_wrap_key,
+			Encrypted_Settings,
+			plaintext_payloads);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+
+		status = plaintext_payloads->get_attribute_data(
+			simple_config_Attribute_Type_E_SNonce2,
+			&m_E_SNonce2);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	{
+		eap_variable_data_c local_EHash2(m_am_tools);
+
+		if (local_EHash2.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		// Verify m_E_SNonce2 and m_EHash2.
+		status = generate_er_hashs(
+			true,
+			&m_device_password,
+			&m_peer_public_dhe_key,
+			&m_own_public_dhe_key,
+			0,
+			0,
+			0,
+			&m_PSK2,
+			&m_E_SNonce2,
+			&local_EHash2);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		// Compare RHash2.
+		if (local_EHash2.compare(&m_EHash2) != 0)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_device_password_authentication_failure);
+		}
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	status = send_M8();
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+#endif //#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+//--------------------------------------------------
+
+eap_status_e simple_config_record_c::fix_incorrect_network_key(
+	eap_variable_data_c * const network_key, 
+	const simple_config_Authentication_Type_e authentication_type)
+{
+	if (authentication_type == simple_config_Authentication_Type_WPAPSK
+		|| authentication_type == simple_config_Authentication_Type_WPA2PSK)
+	{
+		// For example, Vista External Registar sends incorrect WPA(2)PSK that includes terminating NULL.
+		// Check the PSK is passphrase <= 64 bytes in length and the last byte is 0x00.
+		const u32_t ONE_CHARACTER_LENGTH = 1ul;
+		const u8_t STRING_TERMINATING_NULL = 0x00;
+
+		if (network_key->get_data_length() > 0ul)
+		{
+			if (network_key->get_data_offset(network_key->get_data_length()-1ul, ONE_CHARACTER_LENGTH) != 0
+			&& *(network_key->get_data_offset(network_key->get_data_length()-1ul, ONE_CHARACTER_LENGTH)) == STRING_TERMINATING_NULL)
+			{
+				// Check for passphrase characters. If it includes only passphrase characters and the last byte is NULL
+				// we assume it is broken passphrase.
+
+				bool remove_terminating_null = true;
+
+				if (network_key->get_data_length() == 2ul*EAPOL_WPA_PSK_LENGTH_BYTES)
+				{
+					for (u32_t ind = 0; ind < network_key->get_data_length()-1ul; ind++)
+					{
+						u8_t * const character = network_key->get_data_offset(ind, 1);
+						if (character == 0)
+						{
+							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+							return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
+						}
+
+						if((*character < 32) || (126 < *character))
+						{
+							// This is not passphrase.
+							remove_terminating_null = false;
+							break;
+						}
+					}
+				}
+				else
+				{
+					// Because the length is less than 64 bytes, this is passprase, and we remove the terminating NULL.
+				}
+
+				if (remove_terminating_null == true)
+				{
+					network_key->set_data_length(network_key->get_data_length()-1ul);
+				}
+			}
+		}
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//--------------------------------------------------
+
+static const simple_config_Attribute_Type_e needed_payloads_of_M8[]
+	= {
+		simple_config_Attribute_Type_Version,
+		simple_config_Attribute_Type_Message_Type,
+	};
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::process_M8(
+	const simple_config_payloads_c * const payloads)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: parse_function: simple_config_record_c::process_M8()\n"),
+		 (m_is_client == true ? "client": "server")));
+
+	if (verify_state(simple_config_state_wait_M8) == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
+	}
+
+	eap_status_e status = payloads->check_payloads_existense(
+		needed_payloads_of_M8, // const simple_config_Attribute_Type_e * const needed_payloads,
+		sizeof(needed_payloads_of_M8)/sizeof(needed_payloads_of_M8[0]));
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	simple_config_payloads_c * other_configuration = new simple_config_payloads_c(m_am_tools);
+	eap_automatic_variable_c<simple_config_payloads_c> automatic_other_configuration(m_am_tools, other_configuration);
+	
+	if (other_configuration == 0
+		|| other_configuration->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	eap_array_c<simple_config_credential_c> * credential_array = new eap_array_c<simple_config_credential_c>(m_am_tools);
+	eap_automatic_variable_c<eap_array_c<simple_config_credential_c> > automatic_credential_array(m_am_tools, credential_array);
+
+	if (credential_array == 0)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	{
+		// Decrypt Encrypted Settings.
+		simple_config_variable_data_c * const Encrypted_Settings
+			= payloads->get_attribute_pointer(simple_config_Attribute_Type_Encrypted_Settings);
+		if (Encrypted_Settings == 0)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_missing_payload);
+		}
+
+		simple_config_payloads_c * plaintext_payloads = new simple_config_payloads_c(m_am_tools);
+		eap_automatic_variable_c<simple_config_payloads_c> automatic_plaintext_payloads(m_am_tools, plaintext_payloads);
+
+		if (plaintext_payloads == 0
+			|| plaintext_payloads->get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = decrypt_payloads(
+			&m_auth_key,
+			&m_key_wrap_key,
+			Encrypted_Settings,
+			plaintext_payloads);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+
+		simple_config_variable_data_c * Credential_Attribute
+			= plaintext_payloads->get_attribute_pointer(simple_config_Attribute_Type_Credential);
+		if (Credential_Attribute == 0)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_missing_payload);
+		}
+
+		do
+		{
+			simple_config_credential_c * credential = new simple_config_credential_c(m_am_tools);
+
+			eap_automatic_variable_c<simple_config_credential_c> automatic_credential(m_am_tools, credential);
+
+			if (credential == 0
+				|| credential->get_is_valid() == false)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+			}
+
+			simple_config_payloads_c * Credential_payloads = new simple_config_payloads_c(m_am_tools);
+			eap_automatic_variable_c<simple_config_payloads_c> automatic_Credential_payloads(m_am_tools, Credential_payloads);
+	
+			if (Credential_payloads == 0
+				|| Credential_payloads->get_is_valid() == false)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+			}
+
+			u32_t payload_length(Credential_Attribute->get_data_length());
+			u32_t padding_length(0ul);
+
+			status = Credential_payloads->parse_simple_config_payloads(
+				Credential_Attribute->get_data(Credential_Attribute->get_data_length()),
+				&payload_length,
+				&padding_length);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+			
+			{
+				u8_t network_index(0ul);
+
+				status = Credential_payloads->get_attribute_data(
+					simple_config_Attribute_Type_Network_Index,
+					&network_index);
+				if (status != eap_status_ok)
+				{
+					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					return EAP_STATUS_RETURN(m_am_tools, status);
+				}
+
+				credential->set_network_index(network_index);
+			}
+
+			status = Credential_payloads->get_attribute_data(
+				simple_config_Attribute_Type_SSID,
+				credential->get_SSID());
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+
+			{
+				u16_t data(0ul);
+
+				status = Credential_payloads->get_attribute_data(
+					simple_config_Attribute_Type_Authentication_Type,
+					&data);
+				if (status != eap_status_ok)
+				{
+					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					return EAP_STATUS_RETURN(m_am_tools, status);
+				}
+
+				credential->set_Authentication_Type(static_cast<simple_config_Authentication_Type_e>(data));
+			}
+
+			{
+				u16_t data(0ul);
+
+				status = Credential_payloads->get_attribute_data(
+					simple_config_Attribute_Type_Encryption_Type,
+					&data);
+				if (status != eap_status_ok)
+				{
+					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					return EAP_STATUS_RETURN(m_am_tools, status);
+				}
+
+				credential->set_Encryption_Type(static_cast<simple_config_Encryption_Type_e>(data));
+			}
+
+			{
+				simple_config_variable_data_c * Network_Key_Index
+					= Credential_payloads->get_attribute_pointer(simple_config_Attribute_Type_Network_Key_Index);
+				// NOTE, this is optional. Omitted Network_Key_Index defaults to 1.
+
+				simple_config_variable_data_c * Network_Key
+					= Credential_payloads->get_attribute_pointer(simple_config_Attribute_Type_Network_Key);
+
+				
+				if ( Network_Key == 0 
+				        && (credential->get_Authentication_Type() != simple_config_Authentication_Type_Open 
+				            || credential->get_Encryption_Type() != simple_config_Encryption_Type_None) )
+				{
+					// We fail since the required Network Key TLV is missing in a non-open mode.
+				    EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					return EAP_STATUS_RETURN(m_am_tools, eap_status_missing_payload);
+				} 
+				else if ( Network_Key == 0 )
+				{
+                    // This is implemented for IOP reasons. The AP does not send the 
+                    // Network Key TLV (required TLV in the spec) in the Open security mode so we do not 
+                    // require it. The TLV in Open mode would be empty anyway (length would be zero).
+				
+		            EAP_TRACE_DEBUG(
+		                    m_am_tools,
+		                    TRACE_FLAGS_DEFAULT,
+		                    (EAPL("simple_config_record_c::process_M8(): Network Key TLV missing but Open network. This is ok.\n")));
+				
+				    // Just add empty parameters
+				    network_key_and_index_c * const obj = new network_key_and_index_c(m_am_tools);
+				    if(obj != 0)
+				    {                        
+                        status = credential->get_network_keys()->add_object(obj, true);
+                        if (status != eap_status_ok)
+                        {
+                            EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+                            return EAP_STATUS_RETURN(m_am_tools, status);
+                        }
+				    }
+
+                }
+				else
+				{
+				    // Normal case, i.e Network Key TLV exists
+                    do
+    				{
+    					network_key_and_index_c * const obj = new network_key_and_index_c(m_am_tools);
+    
+    					if (obj != 0)
+    					{
+    						if (Network_Key_Index != 0)
+    						{
+    							const u8_t * const network_key_index = Network_Key_Index->get_header()->get_data(sizeof(u8_t));
+    							if (network_key_index == 0)
+    							{
+    								EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+    								return EAP_STATUS_RETURN(m_am_tools, eap_status_missing_payload);
+    							}
+    
+    							obj->set_network_key_index(*network_key_index);
+    						}
+    						else
+    						{
+    							obj->set_network_key_index(SIMPLE_CONFIG_DEFAULT_NETWORK_KEY_INDEX);
+    						}
+    
+    						status = obj->get_network_key()->set_copy_of_buffer(
+    							Network_Key->get_header()->get_data(
+    								Network_Key->get_header()->get_data_length()),
+    							Network_Key->get_header()->get_data_length());
+    						if (status != eap_status_ok)
+    						{
+    							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+    							return EAP_STATUS_RETURN(m_am_tools, status);
+    						}
+    
+    						// For example, Vista External Registar sends incorrect WPA(2)PSK that includes terminating NULL.
+    						status = fix_incorrect_network_key(obj->get_network_key(), credential->get_Authentication_Type());
+    						if (status != eap_status_ok)
+    						{
+    							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+    							return EAP_STATUS_RETURN(m_am_tools, status);
+    						}
+    
+    
+    						status = credential->get_network_keys()->add_object(obj, true);
+    						if (status != eap_status_ok)
+    						{
+    							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+    							return EAP_STATUS_RETURN(m_am_tools, status);
+    						}
+    					}
+    
+    					if (Network_Key_Index != 0)
+    					{
+    						Network_Key_Index = Network_Key_Index->get_next_payload_with_same_attribute_type();
+    					}
+    
+    					Network_Key = Network_Key->get_next_payload_with_same_attribute_type();
+    				}
+    				while(Network_Key != 0);
+    			}
+			}
+
+			status = Credential_payloads->get_attribute_data(
+				simple_config_Attribute_Type_MAC_Address,
+				credential->get_MAC_address());
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+
+			automatic_credential.do_not_free_variable();
+
+			status = credential_array->add_object(credential, true);
+
+			Credential_Attribute = Credential_Attribute->get_next_payload_with_same_attribute_type();
+		}
+		while (Credential_Attribute != 0);
+
+		// This is optional attribute.
+		if (plaintext_payloads->get_attribute_pointer(
+			simple_config_Attribute_Type_New_Password) != 0)
+		{
+			status = plaintext_payloads->get_attribute_data(
+				simple_config_Attribute_Type_New_Password,
+				&m_new_password);
+			if (status != eap_status_ok
+				&& status != eap_status_missing_payload)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+		}
+
+		if (plaintext_payloads->get_attribute_pointer(
+			simple_config_Attribute_Type_Device_Password_ID) != 0)
+		{
+			u16_t data(0ul);
+
+			// This is optional attribute.
+			status = plaintext_payloads->get_attribute_data(
+				simple_config_Attribute_Type_Device_Password_ID,
+				&data);
+			if (status != eap_status_ok
+				&& status != eap_status_missing_payload)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+
+			if (status == eap_status_ok)
+			{
+				m_new_Device_Password_ID = static_cast<simple_config_Device_Password_ID_e>(data);
+			}
+		}
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	status = m_am_simple_config_services->save_simple_config_session(
+		simple_config_state_simple_config_success,
+		credential_array,
+		&m_new_password,
+		m_new_Device_Password_ID,
+		other_configuration);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	status = send_WSC_Done();
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+static const simple_config_Attribute_Type_e needed_payloads_of_WSC_ACK[]
+	= {
+		simple_config_Attribute_Type_Version,
+		simple_config_Attribute_Type_Message_Type,
+	};
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::process_WSC_ACK(
+	const simple_config_payloads_c * const payloads)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: parse_function: simple_config_record_c::process_WSC_ACK()\n"),
+		 (m_is_client == true ? "client": "server")));
+
+	if (verify_state(simple_config_state_wait_WSC_ACK) == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
+	}
+
+	eap_status_e status = payloads->check_payloads_existense(
+		needed_payloads_of_WSC_ACK, // const simple_config_Attribute_Type_e * const needed_payloads,
+		sizeof(needed_payloads_of_WSC_ACK)/sizeof(needed_payloads_of_WSC_ACK[0]));
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+static const simple_config_Attribute_Type_e needed_payloads_of_WSC_NACK[]
+	= {
+		simple_config_Attribute_Type_Version,
+		simple_config_Attribute_Type_Message_Type,
+	};
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::process_WSC_NACK(
+	const simple_config_payloads_c * const payloads)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: parse_function: simple_config_record_c::process_WSC_NACK()\n"),
+		 (m_is_client == true ? "client": "server")));
+
+	eap_status_e status = payloads->check_payloads_existense(
+		needed_payloads_of_WSC_NACK, // const simple_config_Attribute_Type_e * const needed_payloads,
+		sizeof(needed_payloads_of_WSC_NACK)/sizeof(needed_payloads_of_WSC_NACK[0]));
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	if (m_handshake_error != eap_status_ok)
+	{
+		(void) send_error_notification(m_handshake_error);
+	}
+
+	set_state(simple_config_state_failure);
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+static const simple_config_Attribute_Type_e needed_payloads_of_WSC_DONE[]
+	= {
+		simple_config_Attribute_Type_Version,
+		simple_config_Attribute_Type_Message_Type,
+	};
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::process_WSC_DONE(
+	const simple_config_payloads_c * const payloads)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: parse_function: simple_config_record_c::process_WSC_DONE()\n"),
+		 (m_is_client == true ? "client": "server")));
+
+	if (verify_state(simple_config_state_wait_WSC_DONE) == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
+	}
+
+	eap_status_e status = payloads->check_payloads_existense(
+		needed_payloads_of_WSC_DONE, // const simple_config_Attribute_Type_e * const needed_payloads,
+		sizeof(needed_payloads_of_WSC_DONE)/sizeof(needed_payloads_of_WSC_DONE[0]));
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	set_state(simple_config_state_simple_config_success);
+
+	{
+		// Send state notification to lower layer.
+		eap_state_notification_c notification(
+			m_am_tools,
+			&m_send_network_id,
+			m_is_client,
+			eap_state_notification_generic,
+			eap_protocol_layer_eap,
+			eap_type_none,
+			eap_state_none,
+			eap_state_authentication_finished_successfully,
+			0ul,
+			false);
+		get_type_partner()->state_notification(&notification);
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+#endif //#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::process_simple_config_attributes(
+	const simple_config_payloads_c * const payloads)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: parse_function: simple_config_record_c::process_simple_config_attributes()\n"),
+		 (m_is_client == true ? "client": "server")));
+
+	simple_config_variable_data_c * const message_type_payload
+		= payloads->get_attribute_pointer(simple_config_Attribute_Type_Message_Type);
+	if (message_type_payload == 0)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_missing_payload);
+	}
+
+	u8_t * const Message_type_data = message_type_payload->get_header()->get_data(sizeof(u8_t));
+	if (Message_type_data == 0)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_missing_payload);
+	}
+
+	const simple_config_Message_Type_e Message_type(static_cast<simple_config_Message_Type_e>(*Message_type_data));
+
+	eap_status_e status(eap_status_process_general_error);
+
+
+	{
+		eap_simple_config_trace_string_c trace_string;
+		EAP_UNREFERENCED_PARAMETER(trace_string);			
+
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("SIMPLE_CONFIG: %s: parse_function: simple_config_record_c::process_simple_config_attributes(): Received message %s=%d\n"),
+			 (m_is_client == true ? "client": "server"),
+			 trace_string.get_message_type_string(Message_type),
+			 Message_type));
+	}
+
+
+	switch(Message_type)
+	{
+	case simple_config_Message_Type_M1:
+	case simple_config_Message_Type_M2:
+	case simple_config_Message_Type_M2D:
+		// Check is done later inside correcponding function.
+		break;
+	case simple_config_Message_Type_M3:
+	case simple_config_Message_Type_M5:
+	case simple_config_Message_Type_M7:
+
+		status = verify_nonces_and_authenticator(
+			&m_auth_key,
+			&m_enrollee_nonce,
+			&m_registrar_nonce,
+			payloads,
+			false, // No Enrolle Nonce
+			true, // Check Registrar Nonce
+			true); // Check Authenticator
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+		break;
+	case simple_config_Message_Type_M4:
+	case simple_config_Message_Type_M6:
+	case simple_config_Message_Type_M8:
+		status = verify_nonces_and_authenticator(
+			&m_auth_key,
+			&m_enrollee_nonce,
+			&m_registrar_nonce,
+			payloads,
+			true, // Check Enrolle Nonce
+			false, // No Registrar Nonce
+			true); // Check Authenticator
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+		break;
+	case simple_config_Message_Type_WSC_ACK:
+	case simple_config_Message_Type_WSC_NACK:
+	case simple_config_Message_Type_WSC_DONE:
+		{
+			bool check_enrollee_nonce(true);
+			bool check_registrar_nonce(true);
+
+			if (get_state() == simple_config_state_wait_M1)
+			{
+				check_enrollee_nonce = false;
+				check_registrar_nonce = false;
+			}
+
+			if (get_state() == simple_config_state_wait_M2)
+			{
+				check_registrar_nonce = false;
+			}
+
+			status = verify_nonces_and_authenticator(
+				&m_auth_key,
+				&m_enrollee_nonce,
+				&m_registrar_nonce,
+				payloads,
+				check_enrollee_nonce,
+				check_registrar_nonce,
+				false); // No Authenticator
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+		}
+		break;
+	default:
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
+	};
+
+
+	switch(Message_type)
+	{
+
+	case simple_config_Message_Type_M2:
+		status = process_M2(payloads);
+		break;
+	case simple_config_Message_Type_M2D:
+		status = process_M2D(payloads);
+		break;
+	case simple_config_Message_Type_M4:
+		status = process_M4(payloads);
+		break;
+	case simple_config_Message_Type_M6:
+		status = process_M6(payloads);
+		break;
+	case simple_config_Message_Type_M8:
+		status = process_M8(payloads);
+		break;
+	case simple_config_Message_Type_WSC_ACK:
+		status = process_WSC_ACK(payloads);
+		break;
+	case simple_config_Message_Type_WSC_NACK:
+		status = process_WSC_NACK(payloads);
+		break;
+
+#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+	case simple_config_Message_Type_M1:
+		status = process_M1(payloads);
+		break;
+	case simple_config_Message_Type_M3:
+		status = process_M3(payloads);
+		break;
+	case simple_config_Message_Type_M5:
+		status = process_M5(payloads);
+		break;
+	case simple_config_Message_Type_M7:
+		status = process_M7(payloads);
+		break;
+	case simple_config_Message_Type_WSC_DONE:
+		status = process_WSC_DONE(payloads);
+		break;
+
+#endif //#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+	default:
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("ERROR: SIMPLE_CONFIG: %s: parse_function: process_simple_config_attributes(): Unknown message 0x%08x\n"),
+			 (m_is_client == true ? "client": "server"),
+			 Message_type));
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
+	};
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::process_simple_config_message()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("SIMPLE_CONFIG: %s: parse_function: simple_config_record_c::process_simple_config_message()\n"),
+		 (m_is_client == true ? "client": "server")));
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("SIMPLE_CONFIG-message"),
+		m_received_simple_config_message.get_simple_config_message_data()->get_data(
+			m_received_simple_config_message.get_simple_config_message_data()->get_data_length()),
+		m_received_simple_config_message.get_simple_config_message_data()->get_data_length()));
+
+	u32_t next_start_offset = 0ul;
+	u32_t simple_config_packet_length = m_received_simple_config_message.get_simple_config_message_data()->get_data_length();
+
+	m_received_payloads.reset();
+
+	u32_t padding_length(0ul);
+
+	eap_status_e status = m_received_payloads.parse_simple_config_payloads(
+		m_received_simple_config_message.get_simple_config_message_data()->get_data(
+			m_received_simple_config_message.get_simple_config_message_data()->get_data_length()),
+		&simple_config_packet_length,
+		&padding_length);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	if (next_start_offset != simple_config_packet_length)
+	{
+		// Parsed packet length does not match with received packet length.
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(
+			m_am_tools,
+			eap_status_process_illegal_packet_error);
+	}
+
+
+	status = process_simple_config_attributes(&m_received_payloads);
+
+	if (status == eap_status_ok)
+	{
+		status = cancel_error_message_timeout();
+	}
+	else
+	{
+		if (m_handshake_error == eap_status_ok)
+		{
+			// Save the first error.
+			m_handshake_error = status;
+		}
+
+		status = initalize_error_message_timeout();
+	}
+
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::are_pending_queries_completed()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	eap_status_e status = eap_status_pending_request;
+
+	if (m_pending_query_network_and_device_parameters == false)
+	{
+		status = eap_status_ok;
+	}
+
+	eap_status_string_c status_string;
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: pending_function: are_pending_queries_completed(): %s\n"),
+		(m_is_client == true ? "client": "server"),
+		status_string.get_status_string(status)));
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::indicate_state_to_lower_layer(
+	const simple_config_state_e indicated_state)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	// Notify lower layer the state of SIMPLE_CONFIG.
+
+	eap_simple_config_trace_string_c state_string;
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: state_function: indicate_state_to_lower_layer(): %s\n"),
+		(m_is_client == true ? "client": "server"),
+		state_string.get_state_string(indicated_state)));
+
+	eap_state_notification_c notification(
+		m_am_tools,
+		&m_send_network_id,
+		m_is_client,
+		eap_state_notification_generic,
+		eap_protocol_layer_internal_type,
+		eap_type_none,
+		simple_config_state_none,
+		indicated_state,
+		0,
+		false);
+	get_type_partner()->state_notification(&notification);
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::indicate_messages_processed()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	// Notify lower layer that SIMPLE_CONFIG-messages are processed.
+
+	eap_simple_config_trace_string_c state_string;
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: state_function: indicate_messages_processed(): %s\n"),
+		(m_is_client == true ? "client": "server"),
+		state_string.get_state_string(m_simple_config_state)));
+
+	eap_state_notification_c notification(
+		m_am_tools,
+		&m_send_network_id,
+		m_is_client,
+		eap_state_notification_generic,
+		eap_protocol_layer_internal_type,
+		eap_type_none,
+		simple_config_state_none,
+		simple_config_state_pending_simple_config_messages_processed,
+		0,
+		false);
+	get_type_partner()->state_notification(&notification);
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::send_simple_config_message()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+	
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: send_function: simple_config_record_c::send_simple_config_message()\n"),
+		 (m_is_client == true ? "client": "server")));
+
+	eap_variable_data_c simple_config_message_buffer(m_am_tools);
+
+	if (simple_config_message_buffer.get_is_valid() == false)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	// --------------------------------------------------------------------
+
+	eap_buf_chain_wr_c sent_packet(
+		eap_write_buffer,
+		m_am_tools,
+		m_new_simple_config_message.get_simple_config_message_data()->get_data(simple_config_message_buffer.get_data_length()),
+		m_new_simple_config_message.get_simple_config_message_data()->get_data_length(),
+		false,
+		false,
+		0ul);
+	if (sent_packet.get_is_valid() == false)
+	{
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("send SIMPLE_CONFIG-message"),
+		 sent_packet.get_data(sent_packet.get_data_length()),
+		 sent_packet.get_data_length()));
+
+	// --------------------------------------------------------------------
+	
+    // Send message
+	eap_status_e status = get_type_partner()->simple_config_packet_send(
+		&sent_packet,
+		m_current_simple_config_message_type);
+	
+	if (status != eap_status_ok)
+    {
+        EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+        return EAP_STATUS_RETURN(m_am_tools, status);
+    }
+
+	status = m_previous_simple_config_message.get_simple_config_message_data()->set_copy_of_buffer(
+		m_new_simple_config_message.get_simple_config_message_data());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	m_new_simple_config_message.reset();
+	
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::check_sent_simple_config_message()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: send_function: simple_config_record_c::check_sent_simple_config_message()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	eap_status_e msg_status = eap_status_authentication_failure;
+
+	if (m_already_in_completion_action_check == true)
+	{
+		// This is recursive call. Do not process yet.
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+	}
+
+	if (m_force_simple_config_message_send == true)
+	{
+		// There may be an alert message pending.
+		msg_status = send_simple_config_message();
+	}
+	else
+	{
+		msg_status = are_pending_queries_completed();
+		if (msg_status == eap_status_ok)
+		{
+			eap_status_e compl_status = completion_action_check();
+
+			if (compl_status == eap_status_pending_request)
+			{
+				// Some asyncronous query is still pending.
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, compl_status);
+			}
+			else if (compl_status != eap_status_ok)
+			{
+				// There may be Alert message to be sent.
+				msg_status = compl_status;
+			}
+
+
+			if (m_allow_message_send == true)
+			{
+				if (msg_status == eap_status_ok
+					&& m_new_simple_config_message.get_simple_config_message_data()->get_is_valid_data() == true)
+				{
+					// We could send the pending SIMPLE_CONFIG-messages.
+					msg_status = send_simple_config_message();
+				}
+				else if (m_force_simple_config_message_send == true // There may be Alert message to be sent.
+					&& m_new_simple_config_message.get_simple_config_message_data()->get_is_valid_data() == true)
+				{
+					// We could send the pending SIMPLE_CONFIG-messages.
+					send_simple_config_message();
+				}
+				else
+				{
+					// No message to sent.
+					EAP_TRACE_DEBUG(
+						m_am_tools,
+						TRACE_FLAGS_DEFAULT,
+						(EAPL("SIMPLE_CONFIG: %s: send_function: simple_config_record_c::check_sent_simple_config_message(), ")
+						 EAPL("No message to sent.\n"),
+						(m_is_client == true ? "client": "server")));
+				}
+			}
+
+			if (msg_status == eap_status_ok
+				&& m_allow_message_send == true)
+			{
+				eap_status_e indication_status = indicate_messages_processed();
+				if (indication_status != eap_status_ok)
+				{
+					// This is an error case.
+					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					return EAP_STATUS_RETURN(m_am_tools, indication_status);
+				}
+			}
+		}
+	}
+
+	if (get_state() == simple_config_state_simple_config_success)
+	{
+		// Notify lower layer that SIMPLE_CONFIG/PEAP ended successfully
+
+		eap_simple_config_trace_string_c simple_config_trace;
+
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("%s: SIMPLE_CONFIG/PEAP authentication ")
+			 EAPL("SUCCESS: EAP-type %s\n"),
+			 (m_is_client == true ? "client": "server"),
+			 eap_header_string_c::get_eap_type_string(eap_expanded_type_simple_config.get_type())));
+
+		eap_status_e notification_status = indicate_state_to_lower_layer(get_state());
+		if (notification_status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, notification_status);
+		}
+	}
+	else if (get_state() == simple_config_state_failure)
+	{
+		eap_simple_config_trace_string_c simple_config_trace;
+
+		EAP_TRACE_ERROR(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("%s: SIMPLE_CONFIG/PEAP authentication ")
+			 EAPL("FAILED: EAP-type %s\n"),
+			 (m_is_client == true ? "client": "server"),
+			 eap_header_string_c::get_eap_type_string(eap_expanded_type_simple_config.get_type())));
+
+		eap_status_e notification_status = indicate_state_to_lower_layer(get_state());
+		if (notification_status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, notification_status);
+		}
+	}
+
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, msg_status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::packet_process(
+	eap_variable_data_c * const simple_config_packet,
+	const u8_t received_eap_identifier)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	eap_simple_config_trace_string_c state_trace;
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: message_function: packet_process(): state %s\n"),
+		(m_is_client == true ? "client": "server"),
+		state_trace.get_state_string(get_state())));
+
+	m_received_simple_config_message.reset();
+
+	eap_status_e status = m_received_simple_config_message.set_simple_config_message_data(
+		simple_config_packet,
+		received_eap_identifier);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	eap_automatic_simple_value_c<bool> restore_allow_message_send(
+		m_am_tools,
+		&m_allow_message_send,
+		true);
+
+	// Packet send is delayed until after the process_simple_config_message() function returns.
+	m_allow_message_send = false;
+
+	status = process_simple_config_message();
+
+	m_allow_message_send = true;
+
+
+	if (status != eap_status_pending_request)
+	{
+		// Note this call will return eap_status_pending_request if any asyncronous call is pending.
+		eap_status_e send_status = check_sent_simple_config_message();
+		if (send_status != eap_status_ok)
+		{
+			status = send_status;
+		}
+	}
+
+	if (get_state() == simple_config_state_simple_config_success)
+	{
+		// Send state notification to lower layer.
+		eap_state_notification_c notification(
+			m_am_tools,
+			&m_send_network_id,
+			m_is_client,
+			eap_state_notification_generic,
+			eap_protocol_layer_eap,
+			eap_type_none,
+			eap_state_none,
+			eap_state_authentication_finished_successfully,
+			0ul,
+			false);
+		get_type_partner()->state_notification(&notification);
+	}
+
+
+	if (status == eap_status_success
+		&& get_state() != simple_config_state_simple_config_success)
+	{
+		status = eap_status_ok;
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT bool simple_config_record_c::get_is_valid()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return m_is_valid;
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::reset()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: function: simple_config_record_c::reset(): this = 0x%08x\n"),
+		(m_is_client == true ? "client": "server"),
+		this));
+
+	completion_action_clenup();
+
+	m_M2D_payloads.reset();
+
+	m_handshake_error = eap_status_ok;
+	m_Rf_Bands = simple_config_RF_Bands_2_4_GHz;
+
+	m_received_simple_config_message.reset();
+	m_new_simple_config_message.reset();
+	m_own_private_dhe_key.reset();
+	m_own_public_dhe_key.reset();
+	m_peer_public_dhe_key.reset();
+	m_shared_dh_key.reset();
+	m_dhe_prime.reset();
+	m_dhe_group_generator.reset();
+	m_signed_message_hash.reset();
+	m_NAI.reset();
+	m_NAI_realm.reset();
+
+	m_completion_queue.reset();
+
+	m_key_material_generated = false;
+
+	m_force_simple_config_message_send = false;
+
+#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+	if (m_is_client == false)
+	{
+		// Server
+		// NOTE: set_state() function cannot reset state.
+		m_simple_config_state = simple_config_state_wait_M1;
+	}
+	else
+#endif //#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+	{
+		// Client
+		// NOTE: set_state() function cannot reset state.
+		m_simple_config_state = simple_config_state_wait_simple_config_start;
+	}
+
+	eap_status_e status = generate_dhe_keys();
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::generate_dhe_keys()
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s:     key_function: generate_dhe_keys()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	eap_status_e status = eap_status_not_supported;
+
+	{
+		m_dhe_prime.reset();
+
+		status = m_dhe_prime.add_data(SIMPLE_CONFIG_DIFFIE_HELLMAN_PRIME, sizeof(SIMPLE_CONFIG_DIFFIE_HELLMAN_PRIME));
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		m_dhe_group_generator.reset();
+
+		status = m_dhe_group_generator.add_data(SIMPLE_CONFIG_DIFFIE_HELLMAN_GROUP_GENERATOR, sizeof(SIMPLE_CONFIG_DIFFIE_HELLMAN_GROUP_GENERATOR));
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		crypto_ephemeral_diffie_hellman_c dhe(m_am_tools);
+
+		if (dhe.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("SIMPLE_CONFIG: %s:     key_function: dhe.generate_diffie_hellman_keys()\n"),
+			(m_is_client == true ? "client": "server")));
+
+		status = dhe.generate_diffie_hellman_keys(
+			&m_own_private_dhe_key,
+			&m_own_public_dhe_key,
+			m_dhe_prime.get_data(m_dhe_prime.get_data_length()),
+			m_dhe_prime.get_data_length(),
+			m_dhe_group_generator.get_data(m_dhe_group_generator.get_data_length()),
+			m_dhe_group_generator.get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::generate_dhe_shared_secret(
+	const eap_variable_data_c * const peer_public_key_data,
+	eap_variable_data_c * const dhe_shared_secret)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s:     key_function: generate_dhe_shared_secret()\n"),
+		(m_is_client == true ? "client": "server")));
+
+
+	if (m_dhe_prime.get_is_valid_data() == false
+		|| m_dhe_group_generator.get_is_valid_data() == false
+		|| m_own_private_dhe_key.get_is_valid_data() == false
+		|| peer_public_key_data->get_is_valid_data() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
+	}
+
+	crypto_ephemeral_diffie_hellman_c dhe(m_am_tools);
+
+	if (dhe.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s:     key_function: dhe.generate_g_power_to_xy()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	eap_status_e status = dhe.generate_g_power_to_xy(
+		&m_own_private_dhe_key,
+		peer_public_key_data,
+		dhe_shared_secret,
+		m_dhe_prime.get_data(),
+		m_dhe_prime.get_data_length(),
+		m_dhe_group_generator.get_data(),
+		m_dhe_group_generator.get_data_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("SIMPLE_CONFIG: dhe_shared_secret"),
+		dhe_shared_secret->get_data(dhe_shared_secret->get_data_length()),
+		dhe_shared_secret->get_data_length()));
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::generate_nonce(
+	eap_variable_data_c * const nonce,
+	const u32_t nonce_length)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s:     key_function: generate_nonce()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	// Creates a Nonce.
+	crypto_random_c rand(m_am_tools);
+
+	eap_status_e status = nonce->set_buffer_length(nonce_length);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = nonce->set_data_length(nonce->get_buffer_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = rand.get_rand_bytes(nonce->get_data(), nonce->get_data_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::generate_erhash(
+	const bool verify,
+	const eap_variable_data_c * const half_of_device_password,
+	const eap_variable_data_c * const PKE,
+	const eap_variable_data_c * const PKR,
+	eap_variable_data_c * const PSKn,
+	eap_variable_data_c * const ERSn,
+	eap_variable_data_c * const ERHash)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s:     key_function: generate_erhash()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: PKE"),
+		PKE->get_data(),
+		PKE->get_data_length()));
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: PKR"),
+		PKR->get_data(),
+		PKR->get_data_length()));
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: half_of_device_password"),
+		half_of_device_password->get_data(),
+		half_of_device_password->get_data_length()));
+
+	eap_status_e status = keyed_hmac(&m_auth_key, half_of_device_password, PSKn);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = PSKn->set_data_length(SIMPLE_CONFIG_PSKn_LENGTH);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: PSKn"),
+		PSKn->get_data(),
+		PSKn->get_data_length()));
+
+	if (verify == false)
+	{
+		status = generate_nonce(
+			ERSn,
+			SIMPLE_CONFIG_ESn_LENGTH);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+	else
+	{
+		EAP_TRACE_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("SIMPLE_CONFIG: %s:     key_function: generate_erhash(): No new nonce is generated,\n"),
+			(m_is_client == true ? "client": "server")));
+		EAP_ASSERT(ERSn != 0 && ERSn->get_is_valid_data() == true);
+	}
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: ERSn"),
+		ERSn->get_data(),
+		ERSn->get_data_length()));
+
+	{
+		eap_variable_data_c hmac_input(m_am_tools);
+
+		if (hmac_input.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = hmac_input.add_data(ERSn);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = hmac_input.add_data(PSKn);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = hmac_input.add_data(PKE);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = hmac_input.add_data(PKR);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = keyed_hmac(&m_auth_key, &hmac_input, ERHash);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: ERHash"),
+		ERHash->get_data(),
+		ERHash->get_data_length()));
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::generate_er_hashs(
+	const bool verify,
+	const eap_variable_data_c * const device_password,
+	const eap_variable_data_c * const PKE,
+	const eap_variable_data_c * const PKR,
+	eap_variable_data_c * const PSK1,
+	eap_variable_data_c * const ER_S1,
+	eap_variable_data_c * const ER_Hash1,
+	eap_variable_data_c * const PSK2,
+	eap_variable_data_c * const ER_S2,
+	eap_variable_data_c * const ER_Hash2)
+{
+
+	eap_variable_data_c first_half_of_device_password(m_am_tools);
+
+	if (first_half_of_device_password.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	eap_status_e status = first_half_of_device_password.set_buffer(device_password);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = first_half_of_device_password.set_data_length((device_password->get_data_length() + 1ul) / 2ul);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	if (ER_Hash1 != 0)
+	{
+		// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+		// Create E/R-Hash1.
+
+		status = generate_erhash(
+			verify,
+			&first_half_of_device_password,
+			PKE,
+			PKR,
+			PSK1,
+			ER_S1,
+			ER_Hash1);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("SIMPLE_CONFIG: ER_Hash1"),
+			ER_Hash1->get_data(),
+			ER_Hash1->get_data_length()));
+	}
+
+	if (ER_Hash2 != 0)
+	{
+		// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+		// Create E/R-Hash2.
+
+		eap_variable_data_c second_half_of_device_password(m_am_tools);
+
+		if (second_half_of_device_password.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		u32_t second_half_length(device_password->get_data_length() / 2ul);
+
+		eap_status_e status = second_half_of_device_password.set_buffer(
+			device_password->get_data_offset(first_half_of_device_password.get_data_length(), second_half_length),
+			second_half_length,
+			false,
+			false);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = generate_erhash(
+			verify,
+			&second_half_of_device_password,
+			PKE,
+			PKR,
+			PSK2,
+			ER_S2,
+			ER_Hash2);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("SIMPLE_CONFIG: ER_Hash2"),
+			ER_Hash2->get_data(),
+			ER_Hash2->get_data_length()));
+	}
+
+	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::keyed_hmac(
+	const eap_variable_data_c * const key,
+	const eap_variable_data_c * const input,
+	eap_variable_data_c * const output)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s:     key_function: keyed_hmac()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	crypto_sha_256_c sha_256(m_am_tools);
+	if (sha_256.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	crypto_hmac_c hmac_sha_256(
+		m_am_tools,
+		&sha_256,
+		false);
+	if (hmac_sha_256.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: key"),
+		key->get_data(),
+		key->get_data_length()));
+
+	eap_status_e status = hmac_sha_256.hmac_set_key(key);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = hmac_sha_256.hmac_update(
+		input->get_data(),
+		input->get_data_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = output->set_buffer_length(hmac_sha_256.get_digest_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = output->set_data_length(hmac_sha_256.get_digest_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	u32_t md_length(hmac_sha_256.get_digest_length());
+
+	status = hmac_sha_256.hmac_final(
+		output->get_data(hmac_sha_256.get_digest_length()),
+		&md_length);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+	
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::generate_kdk(
+	const eap_variable_data_c * const dhe_shared_secret,
+	const eap_variable_data_c * const nonce_1,
+	const eap_variable_data_c * const enrollee_mac,
+	const eap_variable_data_c * const nonce_2,
+	eap_variable_data_c * const kdk
+	)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s:     key_function: generate_kdk()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	crypto_sha_256_c sha_256(m_am_tools);
+	if (sha_256.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	eap_status_e status = sha_256.hash_init();
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: simple_config_record_c::generate_kdk(): dhe_shared_secret"),
+		dhe_shared_secret->get_data(),
+		dhe_shared_secret->get_data_length()));
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: simple_config_record_c::generate_kdk(): nonce_1"),
+		 nonce_1->get_data(),
+		 nonce_1->get_data_length()));
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: simple_config_record_c::generate_kdk(): enrollee_mac"),
+		 enrollee_mac->get_data(),
+		 enrollee_mac->get_data_length()));
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: simple_config_record_c::generate_kdk(): nonce_2"),
+		 nonce_2->get_data(),
+		 nonce_2->get_data_length()));
+
+	status = sha_256.hash_update(
+		dhe_shared_secret->get_data(),
+		dhe_shared_secret->get_data_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	eap_variable_data_c dh_key(m_am_tools);
+	if (dh_key.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = dh_key.set_buffer_length(sha_256.get_digest_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = dh_key.set_data_length(sha_256.get_digest_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	{
+		u32_t md_length(sha_256.get_digest_length());
+
+		status = sha_256.hash_final(
+			dh_key.get_data(sha_256.get_digest_length()),
+			&md_length);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: dh_key"),
+		dh_key.get_data(),
+		dh_key.get_data_length()));
+
+	// - - - - - - - - - - - - - - - - - - - - - - - -
+
+	sha_256.hash_cleanup();
+	if (sha_256.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	crypto_hmac_c hmac_sha_256(
+		m_am_tools,
+		&sha_256,
+		false);
+	if (hmac_sha_256.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = hmac_sha_256.hmac_set_key(&dh_key);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = hmac_sha_256.hmac_update(
+		nonce_1->get_data(),
+		nonce_1->get_data_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = hmac_sha_256.hmac_update(
+		enrollee_mac->get_data(),
+		enrollee_mac->get_data_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = hmac_sha_256.hmac_update(
+		nonce_2->get_data(),
+		nonce_2->get_data_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	status = kdk->set_buffer_length(hmac_sha_256.get_digest_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = kdk->set_data_length(hmac_sha_256.get_digest_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	{
+		u32_t md_length(hmac_sha_256.get_digest_length());
+
+		status = hmac_sha_256.hmac_final(
+			kdk->get_data(hmac_sha_256.get_digest_length()),
+			&md_length);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("SIMPLE_CONFIG: simple_config_record_c::generate_kdk(): kdk"),
+			 kdk->get_data(),
+			 kdk->get_data_length()));
+	}
+
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::key_derivation_function(
+	const eap_variable_data_c * const key,
+	const eap_variable_data_c * const personalization_string,
+	const u32_t total_key_bits,
+	eap_variable_data_c * const result
+	)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s:     key_function: key_derivation_function()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	result->reset();
+
+	crypto_sha_256_c sha_256(m_am_tools);
+	if (sha_256.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	crypto_hmac_c hmac_sha_256(
+		m_am_tools,
+		&sha_256,
+		false);
+	if (hmac_sha_256.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: key"),
+		key->get_data(),
+		key->get_data_length()));
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: personalization_string"),
+		personalization_string->get_data(),
+		personalization_string->get_data_length()));
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: total_key_bits %d\n"),
+		total_key_bits));
+
+	u32_t prf_digest_size(hmac_sha_256.get_digest_length()*8ul);
+	u32_t iterations((total_key_bits + prf_digest_size - 1) / prf_digest_size);
+
+	eap_status_e status = result->set_buffer_length(iterations * hmac_sha_256.get_digest_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = result->set_data_length(iterations * hmac_sha_256.get_digest_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	for (u32_t ind = 0ul; ind != iterations; ++ind)
+	{
+		status = hmac_sha_256.hmac_set_key(key);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		{
+			u32_t ind_network_order(eap_htonl(ind+1ul));
+			status = hmac_sha_256.hmac_update(
+				&ind_network_order,
+				sizeof(ind_network_order));
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+		}
+
+		status = hmac_sha_256.hmac_update(
+			personalization_string->get_data(),
+			personalization_string->get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		{
+			u32_t total_key_bits_network_order(eap_htonl(total_key_bits));
+			status = hmac_sha_256.hmac_update(
+				&total_key_bits_network_order,
+				sizeof(total_key_bits_network_order));
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+		}
+
+		u32_t md_length(hmac_sha_256.get_digest_length());
+
+		status = hmac_sha_256.hmac_final(
+			result->get_data_offset(ind*hmac_sha_256.get_digest_length(), hmac_sha_256.get_digest_length()),
+			&md_length);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	} // for()
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::derive_additional_keys(
+	const eap_variable_data_c * const kdk,
+	eap_variable_data_c * const auth_key,
+	eap_variable_data_c * const key_wrap_key,
+	eap_variable_data_c * const EMSK
+	)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s:     key_function: derive_additional_keys()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("SIMPLE_CONFIG simple_config_record_c::derive_additional_keys(): kdk"),
+		 kdk->get_data(),
+		 kdk->get_data_length()));
+
+
+	eap_variable_data_c personalization_string(m_am_tools);
+
+	if (personalization_string.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	eap_status_e status = personalization_string.set_buffer(
+		SIMPLE_CONFIG_SECURE_KEY_DERIVATION_LABEL,
+		SIMPLE_CONFIG_SECURE_KEY_DERIVATION_LABEL_LENGTH,
+		false,
+		false);
+	if (personalization_string.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	eap_variable_data_c key_expansion(m_am_tools);
+
+	if (key_expansion.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	u32_t key_bits(SIMPLE_CONFIG_AUTH_KEY_BITS + SIMPLE_CONFIG_KEY_WRAP_KEY_BITS + SIMPLE_CONFIG_EMSK_BITS);
+	u32_t key_bytes((key_bits+7)/8);
+
+	status = key_derivation_function(
+		kdk,
+		&personalization_string,
+		key_bits,
+		&key_expansion);
+
+	if (key_expansion.get_is_valid_data() == false
+		|| key_expansion.get_data_length() < key_bytes)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+
+	u32_t key_offset(0ul);
+
+	u32_t key_length(SIMPLE_CONFIG_AUTH_KEY_BITS/8ul);
+
+	status = auth_key->set_copy_of_buffer(
+		key_expansion.get_data_offset(key_offset, key_length),
+		key_length);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+	key_offset += key_length;
+
+	key_length = SIMPLE_CONFIG_KEY_WRAP_KEY_BITS/8ul;
+
+	status = key_wrap_key->set_copy_of_buffer(
+		key_expansion.get_data_offset(key_offset, key_length),
+		key_length);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+	key_offset += key_length;
+
+	key_length = SIMPLE_CONFIG_EMSK_BITS/8ul;
+
+	status = EMSK->set_copy_of_buffer(
+		key_expansion.get_data_offset(key_offset, key_length),
+		key_length);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+	key_offset += key_length;
+
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: simple_config_record_c::derive_additional_keys():     auth_key"),
+		 auth_key->get_data(),
+		 auth_key->get_data_length()));
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: simple_config_record_c::derive_additional_keys(): key_wrap_key"),
+		 key_wrap_key->get_data(),
+		 key_wrap_key->get_data_length()));
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: simple_config_record_c::derive_additional_keys():         EMSK"),
+		 EMSK->get_data(),
+		 EMSK->get_data_length()));
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::generate_authenticator(
+	const eap_variable_data_c * const received_simple_config_message,
+	const eap_variable_data_c * const new_simple_config_message_data_without_authenticator,
+	eap_variable_data_c * const authenticator)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s:     key_function: generate_authenticator()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	eap_status_e status = eap_status_not_supported;
+
+	crypto_sha_256_c sha_256(m_am_tools);
+	if (sha_256.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	crypto_hmac_c hmac_sha_256(
+		m_am_tools,
+		&sha_256,
+		false);
+	if (hmac_sha_256.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("SIMPLE_CONFIG authenticator m_auth_key"),
+		 m_auth_key.get_data(),
+		 m_auth_key.get_data_length()));
+
+	status = hmac_sha_256.hmac_set_key(&m_auth_key);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("SIMPLE_CONFIG authenticator data"),
+		 received_simple_config_message->get_data(),
+		 received_simple_config_message->get_data_length()));
+
+	status = hmac_sha_256.hmac_update(
+		received_simple_config_message->get_data(),
+		received_simple_config_message->get_data_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("SIMPLE_CONFIG authenticator data"),
+		 new_simple_config_message_data_without_authenticator->get_data(),
+		 new_simple_config_message_data_without_authenticator->get_data_length()));
+
+	status = hmac_sha_256.hmac_update(
+		new_simple_config_message_data_without_authenticator->get_data(),
+		new_simple_config_message_data_without_authenticator->get_data_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = authenticator->set_buffer_length(hmac_sha_256.get_digest_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	status = authenticator->set_data_length(hmac_sha_256.get_digest_length());
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	{
+		u32_t md_length(hmac_sha_256.get_digest_length());
+
+		status = hmac_sha_256.hmac_final(
+			authenticator->get_data(hmac_sha_256.get_digest_length()),
+			&md_length);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_DEFAULT, 
+			(EAPL("SIMPLE_CONFIG authenticator"),
+			 authenticator->get_data(),
+			 authenticator->get_data_length()));
+
+		status = authenticator->set_data_length(SIMPLE_CONFIG_AUTHENTICATOR_LENGTH);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s:     key_function: generate_authenticator(): returns\n"),
+		(m_is_client == true ? "client": "server")));
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::add_authenticator_attribute(
+	simple_config_message_c * const received_simple_config_message,
+	simple_config_message_c * const new_simple_config_message)
+{
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s:     message_function: add_authenticator_attribute()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	eap_status_e status(eap_status_process_general_error);
+
+	simple_config_payloads_c * authenticator_payload = new simple_config_payloads_c(m_am_tools);
+	eap_automatic_variable_c<simple_config_payloads_c> automatic_payloads(m_am_tools, authenticator_payload);
+
+	if (authenticator_payload == 0
+		|| authenticator_payload->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	{
+		eap_variable_data_c authenticator(m_am_tools);
+
+		if (authenticator.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = generate_authenticator(
+			received_simple_config_message->get_simple_config_message_data(),
+			new_simple_config_message->get_simple_config_message_data(),
+			&authenticator);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = authenticator_payload->copy_attribute_data(
+			simple_config_Attribute_Type_Authenticator,
+			true,
+			authenticator.get_data(),
+			authenticator.get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	// Adds Authenticator attribute to the end of the message.
+	status = authenticator_payload->create_simple_config_message(
+		new_simple_config_message,
+		true);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s:     message_function: add_authenticator_attribute(): returns\n"),
+		(m_is_client == true ? "client": "server")));
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::encrypt_payloads(
+	const eap_variable_data_c * const auth_key,
+	const eap_variable_data_c * const key_wrap_key,
+	simple_config_payloads_c * const plaintext_payloads,
+	simple_config_variable_data_c * const encrypted_settings)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: pki_function: encrypt_payloads()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	eap_status_e status(eap_status_process_general_error);
+
+	simple_config_message_c plaintext_data(
+		m_am_tools,
+		m_is_client);
+
+	status = plaintext_payloads->create_simple_config_message(
+		&plaintext_data,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	eap_variable_data_c KWA(m_am_tools);
+
+	if (KWA.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	{
+		crypto_sha_256_c sha_256(m_am_tools);
+		if (sha_256.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		crypto_hmac_c hmac_sha_256(
+			m_am_tools,
+			&sha_256,
+			false);
+		if (hmac_sha_256.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_DEFAULT, 
+			(EAPL("SIMPLE_CONFIG auth_key"),
+			auth_key->get_data(),
+			auth_key->get_data_length()));
+
+		status = hmac_sha_256.hmac_set_key(auth_key);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_DEFAULT, 
+			(EAPL("SIMPLE_CONFIG plaintext_data"),
+			plaintext_data.get_simple_config_message_data()->get_data(),
+			plaintext_data.get_simple_config_message_data()->get_data_length()));
+
+		status = hmac_sha_256.hmac_update(
+			plaintext_data.get_simple_config_message_data()->get_data(),
+			plaintext_data.get_simple_config_message_data()->get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = KWA.set_buffer_length(hmac_sha_256.get_digest_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = KWA.set_data_length(hmac_sha_256.get_digest_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		{
+			u32_t md_length(hmac_sha_256.get_digest_length());
+
+			status = hmac_sha_256.hmac_final(
+				KWA.get_data(hmac_sha_256.get_digest_length()),
+				&md_length);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+
+			EAP_TRACE_DATA_DEBUG(
+				m_am_tools, 
+				TRACE_FLAGS_DEFAULT, 
+				(EAPL("SIMPLE_CONFIG KWA"),
+				 KWA.get_data(),
+				 KWA.get_data_length()));
+
+			status = KWA.set_data_length(SIMPLE_CONFIG_AUTHENTICATOR_LENGTH);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+		}
+	}
+
+	{
+		status = plaintext_payloads->copy_attribute_data(
+			simple_config_Attribute_Type_Key_Wrap_Authenticator,
+			true,
+			KWA.get_data(),
+			KWA.get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = plaintext_payloads->create_simple_config_message(
+			&plaintext_data,
+			false);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+	eap_variable_data_c IV(m_am_tools);
+
+	if (IV.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	{
+		// Creates Enrollee Nonce.
+		status = generate_nonce(
+			&IV,
+			SIMPLE_CONFIG_KEY_WRAP_IV_SIZE);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+
+	{
+		crypto_aes_c aes(m_am_tools);
+
+		crypto_cbc_c aes_cbc(
+			m_am_tools,
+			&aes,
+			false);
+
+		if (aes_cbc.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_DEFAULT, 
+			(EAPL("SIMPLE_CONFIG key_wrap_key"),
+			key_wrap_key->get_data(),
+			key_wrap_key->get_data_length()));
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_DEFAULT, 
+			(EAPL("SIMPLE_CONFIG IV"),
+			IV.get_data(),
+			IV.get_data_length()));
+
+		status = aes_cbc.set_encryption_key(
+			IV.get_data(),
+			IV.get_data_length(),
+			key_wrap_key->get_data(),
+			key_wrap_key->get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = plaintext_data.add_padding(aes_cbc.get_block_size());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_DEFAULT, 
+			(EAPL("SIMPLE_CONFIG plaintext data"),
+			 plaintext_data.get_simple_config_message_data()->get_data(),
+			 plaintext_data.get_simple_config_message_data()->get_data_length()));
+
+		status = aes_cbc.update_non_aligned(
+			plaintext_data.get_simple_config_message_data()->get_data(),
+			plaintext_data.get_simple_config_message_data()->get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = aes_cbc.finalize_non_aligned();
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_DEFAULT, 
+			(EAPL("SIMPLE_CONFIG encrypted data"),
+			 plaintext_data.get_simple_config_message_data()->get_data(),
+			 plaintext_data.get_simple_config_message_data()->get_data_length()));
+
+
+		status = encrypted_settings->set_copy_of_buffer(
+			simple_config_Attribute_Type_Encrypted_Settings,
+			true,
+			IV.get_data(),
+			IV.get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = encrypted_settings->add_data(
+			plaintext_data.get_simple_config_message_data()->get_data(),
+			plaintext_data.get_simple_config_message_data()->get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+	}
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: pki_function: encrypt_payloads(): returns\n"),
+		(m_is_client == true ? "client": "server")));
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::decrypt_payloads(
+	const eap_variable_data_c * const auth_key,
+	const eap_variable_data_c * const key_wrap_key,
+	simple_config_variable_data_c * const encrypted_settings,
+	simple_config_payloads_c * const plaintext_payloads)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: pki_function: decrypt_payloads()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	eap_status_e status(eap_status_process_general_error);
+
+	eap_variable_data_c data_payload(m_am_tools);
+
+	if (data_payload.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = data_payload.set_buffer(
+		encrypted_settings->get_data(encrypted_settings->get_data_length()),
+		encrypted_settings->get_data_length(),
+		false,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	if (data_payload.get_data_length() <= SIMPLE_CONFIG_KEY_WRAP_IV_SIZE)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_too_short_message);
+	}
+
+
+	eap_variable_data_c IV(m_am_tools);
+
+	if (IV.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	status = IV.set_buffer(
+		data_payload.get_data(SIMPLE_CONFIG_KEY_WRAP_IV_SIZE),
+		SIMPLE_CONFIG_KEY_WRAP_IV_SIZE,
+		false,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	eap_variable_data_c decrypted_data(m_am_tools);
+
+	if (decrypted_data.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	const u32_t encrypted_data_length(
+		data_payload.get_data_length()
+		- SIMPLE_CONFIG_KEY_WRAP_IV_SIZE);
+
+	status = decrypted_data.set_buffer(
+		data_payload.get_data_offset(
+			SIMPLE_CONFIG_KEY_WRAP_IV_SIZE,
+			encrypted_data_length),
+		encrypted_data_length,
+		false,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("SIMPLE_CONFIG key_wrap_key"),
+		key_wrap_key->get_data(),
+		key_wrap_key->get_data_length()));
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("SIMPLE_CONFIG IV"),
+		IV.get_data(),
+		IV.get_data_length()));
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("SIMPLE_CONFIG encrypted data"),
+		decrypted_data.get_data(),
+		decrypted_data.get_data_length()));
+
+	{
+		crypto_aes_c aes(m_am_tools);
+
+		crypto_cbc_c aes_cbc(
+			m_am_tools,
+			&aes,
+			false);
+
+		if (aes_cbc.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = aes_cbc.set_decryption_key(
+			IV.get_data(),
+			IV.get_data_length(),
+			key_wrap_key->get_data(),
+			key_wrap_key->get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = aes_cbc.update_non_aligned(
+			decrypted_data.get_data(),
+			decrypted_data.get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = aes_cbc.finalize_non_aligned();
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_DEFAULT, 
+			(EAPL("SIMPLE_CONFIG plaintext data"),
+			decrypted_data.get_data(),
+			decrypted_data.get_data_length()));
+	}
+
+
+	u32_t data_length(decrypted_data.get_data_length());
+	u32_t padding_length(0ul);
+
+	status = plaintext_payloads->parse_simple_config_payloads(
+		decrypted_data.get_data(),
+		&data_length,
+		&padding_length);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+
+	simple_config_variable_data_c * const received_KWA
+		= plaintext_payloads->get_attribute_pointer(simple_config_Attribute_Type_Key_Wrap_Authenticator);
+	if (received_KWA == 0)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_missing_payload);
+	}
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("SIMPLE_CONFIG received_KWA"),
+		 received_KWA->get_data(received_KWA->get_data_length()),
+		 received_KWA->get_data_length()));
+
+
+	eap_variable_data_c plaintext_data(m_am_tools);
+
+	if (plaintext_data.get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	if (decrypted_data.get_data_length() < (received_KWA->get_header()->get_length()+padding_length))
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_too_short_message);
+	}
+
+	const u32_t plaintext_data_length(
+		decrypted_data.get_data_length()
+		- (received_KWA->get_header()->get_length()+padding_length));
+
+	status = plaintext_data.set_buffer(
+		decrypted_data.get_data(plaintext_data_length),
+		plaintext_data_length,
+		false,
+		false);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("SIMPLE_CONFIG plaintext_data"),
+		 plaintext_data.get_data(),
+		 plaintext_data.get_data_length()));
+
+
+	{
+		crypto_sha_256_c sha_256(m_am_tools);
+		if (sha_256.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		crypto_hmac_c hmac_sha_256(
+			m_am_tools,
+			&sha_256,
+			false);
+		if (hmac_sha_256.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools, 
+			TRACE_FLAGS_DEFAULT, 
+			(EAPL("SIMPLE_CONFIG authenticator auth_key"),
+			 auth_key->get_data(),
+			 auth_key->get_data_length()));
+
+		status = hmac_sha_256.hmac_set_key(auth_key);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = hmac_sha_256.hmac_update(
+			plaintext_data.get_data(),
+			plaintext_data.get_data_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		eap_variable_data_c local_KWA(m_am_tools);
+
+		if (local_KWA.get_is_valid() == false)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = local_KWA.set_buffer_length(hmac_sha_256.get_digest_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = local_KWA.set_data_length(hmac_sha_256.get_digest_length());
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		{
+			u32_t md_length(hmac_sha_256.get_digest_length());
+
+			status = hmac_sha_256.hmac_final(
+				local_KWA.get_data(hmac_sha_256.get_digest_length()),
+				&md_length);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+
+			EAP_TRACE_DATA_DEBUG(
+				m_am_tools, 
+				TRACE_FLAGS_DEFAULT, 
+				(EAPL("SIMPLE_CONFIG local_KWA"),
+				 local_KWA.get_data(),
+				 local_KWA.get_data_length()));
+
+			status = local_KWA.set_data_length(SIMPLE_CONFIG_AUTHENTICATOR_LENGTH);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+
+			if (local_KWA.compare(
+				received_KWA->get_data(received_KWA->get_data_length()),
+				received_KWA->get_data_length()) != 0)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure);
+			}
+		}
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e simple_config_record_c::complete_query_network_and_device_parameters(
+	const simple_config_state_e state,
+	simple_config_payloads_c * const network_and_device_parameters,
+	const eap_status_e p_completion_status)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("SIMPLE_CONFIG: %s: pki_function: complete_query_network_and_device_parameters()\n"),
+		(m_is_client == true ? "client": "server")));
+
+	m_pending_query_network_and_device_parameters = false;
+
+	if (network_and_device_parameters == 0
+		|| network_and_device_parameters->get_is_valid() == false)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+	}
+
+	eap_status_e local_completion_status(p_completion_status);
+	eap_status_e status(eap_status_process_general_error);
+
+
+	{
+		if (m_simple_config_state == simple_config_state_process_simple_config_start)
+		{
+			status = network_and_device_parameters->get_attribute_data(
+				simple_config_Attribute_Type_UUID_E,
+				&m_UUID_E);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+
+			{
+				u16_t data(0ul);
+
+				status = network_and_device_parameters->get_attribute_data(
+					simple_config_Attribute_Type_Device_Password_ID,
+					&data);
+				if (status != eap_status_ok)
+				{
+					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					return EAP_STATUS_RETURN(m_am_tools, status);
+				}
+
+				m_local_Device_Password_ID = static_cast<simple_config_Device_Password_ID_e>(data);
+			}
+
+			{
+				u8_t RF_Band(simple_config_RF_Bands_2_4_GHz);
+
+				status = network_and_device_parameters->get_attribute_data(
+					simple_config_Attribute_Type_RF_Band,
+					&RF_Band);
+				if (status != eap_status_ok)
+				{
+					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					return EAP_STATUS_RETURN(m_am_tools, status);
+				}
+
+				m_Rf_Bands = static_cast<simple_config_RF_Bands_e>(RF_Band);
+			}
+		}
+		else if (m_simple_config_state == simple_config_state_process_M1)
+		{
+			status = network_and_device_parameters->get_attribute_data(
+				simple_config_Attribute_Type_UUID_R,
+				&m_UUID_R);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+
+			status = network_and_device_parameters->get_attribute_data(
+				simple_config_Attribute_Type_SSID,
+				&m_SSID);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+
+			status = network_and_device_parameters->get_attribute_data(
+				simple_config_Attribute_Type_MAC_Address,
+				&m_MAC_address);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+
+			{
+				u16_t data(0ul);
+
+				status = network_and_device_parameters->get_attribute_data(
+					simple_config_Attribute_Type_Device_Password_ID,
+					&data);
+				if (status != eap_status_ok)
+				{
+					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+					return EAP_STATUS_RETURN(m_am_tools, status);
+				}
+
+				if (status == eap_status_ok)
+				{
+					m_local_Device_Password_ID = static_cast<simple_config_Device_Password_ID_e>(data);
+				}
+
+				if (m_received_Device_Password_ID != m_local_Device_Password_ID)
+				{
+					// Registrar requires different Device_Password_ID.
+					local_completion_status = eap_status_user_has_not_subscribed_to_the_requested_service;
+
+					bool add_new_attribute(false);
+
+					// Change the error attribute to simple_config_Configuration_Error_Network_auth_failure.
+					simple_config_variable_data_c * Configuration_Error
+						= network_and_device_parameters->get_attribute_pointer(simple_config_Attribute_Type_Configuration_Error);
+					if (Configuration_Error == 0)
+					{
+						// Add a new simple_config_Attribute_Type_Configuration_Error attribute.
+						Configuration_Error = new simple_config_variable_data_c(m_am_tools);
+
+						if (Configuration_Error != 0)
+						{
+							add_new_attribute = true;
+						}
+						else
+						{
+							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+							return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+						}
+					}
+
+					if (Configuration_Error != 0)
+					{
+						u16_t error(simple_config_Configuration_Error_Network_auth_failure);
+						u16_t network_order_error(eap_htons(error));
+
+						status = Configuration_Error->set_copy_of_buffer(
+							simple_config_Attribute_Type_Configuration_Error,
+							true,
+							&network_order_error,
+							sizeof(network_order_error));
+						if (status != eap_status_ok)
+						{
+							if (add_new_attribute == true)
+							{
+								delete Configuration_Error;
+								Configuration_Error = 0;
+							}
+							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+							return EAP_STATUS_RETURN(m_am_tools, status);
+						}
+
+						if (add_new_attribute == true)
+						{
+							// Only the new object is added.
+							status = network_and_device_parameters->add_attribute(Configuration_Error);
+							if (status != eap_status_ok)
+							{
+								EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+								return EAP_STATUS_RETURN(m_am_tools, status);
+							}
+						}
+					}
+					else
+					{
+						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+						return EAP_STATUS_RETURN(m_am_tools, eap_status_missing_payload);
+					}
+				}
+			}
+		}
+	}
+
+
+	if (m_local_Device_Password_ID == simple_config_Device_Password_ID_PushButton)
+	{
+		// Set m_device_password to all ascii zeroes SIMPLE_CONFIG_PBC_DEVICE_PASSWORD_PIN.
+		status = m_device_password.set_copy_of_buffer(
+			SIMPLE_CONFIG_PBC_DEVICE_PASSWORD_PIN,
+			SIMPLE_CONFIG_PBC_DEVICE_PASSWORD_PIN_SIZE);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+	}
+
+
+	if (local_completion_status == eap_status_ok)
+	{
+		switch (state)
+		{
+
+		case simple_config_state_process_simple_config_start:
+			status = send_M1(network_and_device_parameters);
+			break;
+
+#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+		case simple_config_state_process_M1:
+			status = send_M2(network_and_device_parameters);
+			break;
+
+#endif //#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+		default:
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
+
+		} // switch (state)
+	}
+	else if (local_completion_status == eap_status_user_has_not_subscribed_to_the_requested_service)
+	{
+		switch (state)
+		{
+
+		case simple_config_state_process_simple_config_start:
+			status = send_WSC_NACK();
+			break;
+
+#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+		case simple_config_state_process_M1:
+			status = send_M2D(network_and_device_parameters);
+			break;
+
+#endif //#if defined(USE_EAP_TYPE_SERVER_SIMPLE_CONFIG)
+
+		default:
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
+
+		} // switch(state)
+	}
+
+	if (status == eap_status_ok)
+	{
+		status = check_sent_simple_config_message();
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = eap_status_completed_request;
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//--------------------------------------------------
+
+#endif //#if defined(USE_EAP_SIMPLE_CONFIG)
+
+
+// End.