eapol/eapol_framework/eapol_common/am/common/eap_am_memory_store.cpp
changeset 0 c8830336c852
child 2 1c7bc153c08e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eapol/eapol_framework/eapol_common/am/common/eap_am_memory_store.cpp	Thu Dec 17 08:47:43 2009 +0200
@@ -0,0 +1,645 @@
+/*
+* 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 10 
+	#undef EAP_FILE_NUMBER_DATE 
+	#define EAP_FILE_NUMBER_DATE 1127594498 
+#endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
+
+
+#include "eap_am_memory.h"
+#include "eap_am_memory_store.h"
+#include "eap_crypto_api.h"
+#include "eap_automatic_variable.h"
+
+//#if !defined(NO_EAP_AM_MEMORY_STORE)
+
+const u32_t EAP_MEMORY_STORE_RC4_KEY_STREAM_DISCARD_LENGTH = 256ul;
+
+//-------------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_am_memory_store_c::~eap_am_memory_store_c()
+{
+	EAP_TRACE_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("eap_am_memory_store_c::~eap_am_memory_store_c(): this = 0x%08x.\n"),
+		this));
+}
+
+//-------------------------------------------------------------------
+
+#if defined(_WIN32) && !defined(__GNUC__)
+	#pragma warning( disable : 4355 ) // 'this' : used in base member initializer list
+#endif
+
+EAP_FUNC_EXPORT eap_am_memory_store_c::eap_am_memory_store_c(
+	abs_eap_am_tools_c * const tools)
+	: m_am_tools(tools)
+	, m_store_new(tools, this)
+	, m_timer_id_counter(0ul)
+	, m_is_valid(false)
+{
+	EAP_TRACE_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("eap_am_memory_store_c::eap_am_memory_store_c(): this = 0x%08x.\n"),
+		this));
+
+	set_is_valid();
+}
+
+//-------------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e eap_am_memory_store_c::shutdown()
+{
+	EAP_TRACE_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("eap_am_memory_store_c::shutdown(): begins this = 0x%08x.\n"),
+		this));
+
+	return eap_status_ok;
+
+}
+
+//-------------------------------------------------------------------
+
+EAP_FUNC_EXPORT void eap_am_memory_store_c::set_is_valid()
+{
+	m_is_valid = true;
+}
+
+//-------------------------------------------------------------------
+
+EAP_FUNC_EXPORT bool eap_am_memory_store_c::get_is_valid()
+{
+	return m_is_valid;
+}
+
+//-------------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e eap_am_memory_store_c::add_data(
+	const eap_variable_data_c * const key,
+	const eap_tlv_message_data_c * const data,
+	const u32_t timeout)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DEBUG(
+		m_am_tools, 
+		TRACE_FLAGS_DEFAULT, 
+		(EAPL("eap_am_memory_store_c::add_data(): data = 0x%08x.\n"),
+		data));
+
+	if (key == 0
+		|| data == 0)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+	}
+
+	eap_am_memory_store_tlv_data_c * const tlv_data = new eap_am_memory_store_tlv_data_c(m_am_tools);
+	if (tlv_data == 0)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+	}
+
+	eap_automatic_variable_c<eap_am_memory_store_tlv_data_c> automatic_tlv_data(
+		m_am_tools,
+		tlv_data);
+
+	eap_status_e status = tlv_data->copy_message_data(
+		data,
+		++m_timer_id_counter);
+	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 crypted_key(m_am_tools);
+	status = crypted_key.set_copy_of_buffer(key);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	{
+		// This encryption hides the plain text data.
+		// This is lame hidden operation of credentials.
+		// @{ The key should be crypted lamely too.}
+		crypto_rc4_c rc4(m_am_tools);
+		if (rc4.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 = rc4.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 = rc4.discard_stream(EAP_MEMORY_STORE_RC4_KEY_STREAM_DISCARD_LENGTH);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = rc4.encrypt_data(
+			crypted_key.get_data(),
+			crypted_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 = rc4.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 = rc4.discard_stream(EAP_MEMORY_STORE_RC4_KEY_STREAM_DISCARD_LENGTH);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		status = rc4.encrypt_data(
+			tlv_data->get_message_data(),
+			tlv_data->get_message_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("eap_am_memory_store_c::add_data(): timeout %d, timer id %d, data = 0x%08x.\n"),
+		 timeout,
+		 tlv_data->get_timer_id(),
+		 data));
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("eap_am_memory_store_c::add_data():         key"),
+		 key->get_data(),
+		 key->get_data_length()));
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("eap_am_memory_store_c::add_data(): crypted key"),
+		 crypted_key.get_data(),
+		 crypted_key.get_data_length()));
+	
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("eap_am_memory_store_c::add_data(): plain text data"),
+		 data->get_message_data(),
+		 data->get_message_data_length()));
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("eap_am_memory_store_c::add_data():     hidden data"),
+		 tlv_data->get_message_data(),
+		 tlv_data->get_message_data_length()));
+
+	status = m_store_new.add_handler(&crypted_key, tlv_data);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	automatic_tlv_data.do_not_free_variable();
+
+	if (timeout != 0ul)
+	{
+		eap_variable_data_c * const copy_key = key->copy();
+		if (copy_key == 0)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+		}
+
+		status = m_am_tools->am_set_timer(
+			this,
+			tlv_data->get_timer_id(),
+			copy_key,
+			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_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//-------------------------------------------------------------------
+
+EAP_FUNC_EXPORT eap_status_e eap_am_memory_store_c::get_data(
+	const eap_variable_data_c * const key,
+	eap_tlv_message_data_c * const data)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	if (key == 0
+		|| data == 0)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+	}
+
+	eap_variable_data_c crypted_key(m_am_tools);
+	eap_status_e status = crypted_key.set_copy_of_buffer(key);
+	if (status != eap_status_ok)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, status);
+	}
+
+	{
+		// This encryption restores lamely hidden key of data.
+		crypto_rc4_c rc4(m_am_tools);
+		if (rc4.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 = rc4.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 = rc4.discard_stream(EAP_MEMORY_STORE_RC4_KEY_STREAM_DISCARD_LENGTH);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+		
+		status = rc4.encrypt_data(
+			crypted_key.get_data(),
+			crypted_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);
+		}
+	}
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("eap_am_memory_store_c::get_data(): key"),
+		 key->get_data(),
+		 key->get_data_length()));
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("eap_am_memory_store_c::get_data(): crypted key"),
+		 crypted_key.get_data(),
+		 crypted_key.get_data_length()));
+	
+	eap_am_memory_store_tlv_data_c * const tlv_data = m_store_new.get_handler(&crypted_key);
+
+	if (tlv_data == 0)
+	{
+		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+		return EAP_STATUS_RETURN(m_am_tools, eap_status_not_found);
+	}
+	else
+	{
+		status = data->copy_message_data(
+			tlv_data->get_message_data_length(),
+			tlv_data->get_message_data());
+		
+		{
+			// This encryption restores lamely hidden plain text data.
+			crypto_rc4_c rc4(m_am_tools);
+			if (rc4.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 = rc4.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 = rc4.discard_stream(EAP_MEMORY_STORE_RC4_KEY_STREAM_DISCARD_LENGTH);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+			
+			status = rc4.decrypt_data(
+				data->get_message_data(),
+				data->get_message_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("eap_am_memory_store_c::get_data(): timer id %d, data = 0x%08x.\n"),
+				 tlv_data->get_timer_id(),
+				 data));
+
+			EAP_TRACE_DATA_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("eap_am_memory_store_c::get_data():     hidden data"),
+				 tlv_data->get_message_data(),
+				 tlv_data->get_message_data_length()));
+
+			EAP_TRACE_DATA_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("eap_am_memory_store_c::get_data(): plain text data"),
+				 data->get_message_data(),
+				 data->get_message_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 eap_am_memory_store_c::remove_data(
+	const eap_variable_data_c * const key)
+{
+	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+
+	EAP_TRACE_DATA_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("eap_am_memory_store_c::remove_data(): key"),
+		 key->get_data(),
+		 key->get_data_length()));
+
+	eap_status_e status(eap_status_ok);
+
+	{
+		eap_variable_data_c crypted_key(m_am_tools);
+		eap_status_e status = crypted_key.set_copy_of_buffer(key);
+		if (status != eap_status_ok)
+		{
+			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+			return EAP_STATUS_RETURN(m_am_tools, status);
+		}
+
+		{
+			// This encryption restores lamely hidden key of data.
+			crypto_rc4_c rc4(m_am_tools);
+			if (rc4.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 = rc4.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 = rc4.discard_stream(EAP_MEMORY_STORE_RC4_KEY_STREAM_DISCARD_LENGTH);
+			if (status != eap_status_ok)
+			{
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, status);
+			}
+		
+			status = rc4.encrypt_data(
+				crypted_key.get_data(),
+				crypted_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);
+			}
+		}
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("eap_am_memory_store_c::remove_data(): crypted key"),
+			 crypted_key.get_data(),
+			 crypted_key.get_data_length()));
+		
+		eap_am_memory_store_tlv_data_c * const data = m_store_new.get_handler(&crypted_key);
+		if (data != 0)
+		{
+			EAP_TRACE_DEBUG(
+				m_am_tools, 
+				TRACE_FLAGS_DEFAULT, 
+				(EAPL("eap_am_memory_store_c::remove_data(): timer id %d, data = 0x%08x.\n"),
+				 data->get_timer_id(),
+				 data));
+
+			EAP_TRACE_DATA_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("eap_am_memory_store_c::remove_data(): key"),
+				 key->get_data(),
+				 key->get_data_length()));
+
+			EAP_TRACE_DATA_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("eap_am_memory_store_c::remove_data():     hidden data"),
+				 data->get_message_data(),
+				 data->get_message_data_length()));
+
+			(void) m_am_tools->am_cancel_timer(
+				this,
+				data->get_timer_id());
+
+			status = m_store_new.remove_handler(&crypted_key, true);
+			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_DATA_DEBUG(
+				m_am_tools,
+				TRACE_FLAGS_DEFAULT,
+				(EAPL("WARNING: eap_am_memory_store_c::remove_data(): key not found"),
+				 crypted_key.get_data(),
+				 crypted_key.get_data_length()));
+		}
+	}
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("eap_am_memory_store_c::remove_data(): returns %d\n"),
+		status));
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+//-------------------------------------------------------------------
+
+/**
+ * Function timer_expired() is called after the timer is elapsed.
+ * @param id and data are set by caller of abs_eap_am_tools::set_timer() function.
+ * @param id could be used to separate different timer events.
+ * @param data could be pointer to any data that is needed in timer processing.
+ */
+EAP_FUNC_EXPORT eap_status_e eap_am_memory_store_c::timer_expired(
+	const u32_t id, void *data)
+{
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("eap_am_memory_store_c::timer_expired(): id %d, data 0x%08x\n"),
+		 id,
+		 data));
+
+	if (data != 0)
+	{
+		eap_variable_data_c * const key = reinterpret_cast<eap_variable_data_c *>(data);
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("eap_am_memory_store_c::timer_expired(): key"),
+			 key->get_data(),
+			 key->get_data_length()));
+
+		eap_am_memory_store_tlv_data_c * const tlv_data = m_store_new.get_handler(key);
+		if (tlv_data != 0)
+		{
+			if (id == tlv_data->get_timer_id())
+			{
+				eap_status_e status = remove_data(key);
+
+				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_ERROR,
+					(EAPL("eap_am_memory_store_c::timer_expired(): id %d != tlv_data->id %d, tlv_data 0x%08x\n"),
+					 id,
+					 tlv_data->get_timer_id(),
+					 tlv_data));
+				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+				return EAP_STATUS_RETURN(m_am_tools, eap_status_not_found);
+			}
+		}
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//-------------------------------------------------------------------
+
+/**
+ * This function is called when timer event is deleted.
+ * Initialiser of the data must delete the data.
+ * Only the initializer knows the real type of data.
+ * @param id could be used to separate different timer events.
+ * @param data could be pointer to any data that is needed in timer processing.
+ */
+EAP_FUNC_EXPORT eap_status_e eap_am_memory_store_c::timer_delete_data(
+	const u32_t id, void *data)
+{
+	EAP_UNREFERENCED_PARAMETER(id);
+
+	EAP_TRACE_DEBUG(
+		m_am_tools,
+		TRACE_FLAGS_DEFAULT,
+		(EAPL("eap_am_memory_store_c::timer_delete_data(): id %d, data 0x%08x\n"),
+		 id,
+		 data));
+
+	if (data != 0)
+	{
+		eap_variable_data_c * const key = reinterpret_cast<eap_variable_data_c *>(data);
+
+		EAP_TRACE_DATA_DEBUG(
+			m_am_tools,
+			TRACE_FLAGS_DEFAULT,
+			(EAPL("eap_am_memory_store_c::timer_delete_data(): key"),
+			 key->get_data(),
+			 key->get_data_length()));
+
+		delete key;
+	}
+
+	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+//-------------------------------------------------------------------
+
+//#endif //#if !defined(NO_EAP_AM_MEMORY_STORE)
+
+// End.