eapol/eapol_framework/eapol_common/type/aka/core/eap_type_aka.cpp
changeset 0 c8830336c852
child 2 1c7bc153c08e
equal deleted inserted replaced
-1:000000000000 0:c8830336c852
       
     1 /*
       
     2 * Copyright (c) 2001-2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  EAP and WLAN authentication protocols.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // This is enumeration of EAPOL source code.
       
    20 #if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
       
    21 	#undef EAP_FILE_NUMBER_ENUM
       
    22 	#define EAP_FILE_NUMBER_ENUM 67 
       
    23 	#undef EAP_FILE_NUMBER_DATE 
       
    24 	#define EAP_FILE_NUMBER_DATE 1127594498 
       
    25 #endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
       
    26 
       
    27 
       
    28 
       
    29 #include "eap_am_memory.h"
       
    30 #include "eap_tools.h"
       
    31 #include "eap_type_aka.h"
       
    32 #include "eap_type_aka_header.h"
       
    33 #include "eap_type_aka_payloads.h"
       
    34 #include "abs_eap_am_type_aka.h"
       
    35 #include "eap_crypto_api.h"
       
    36 #include "eap_state_notification.h"
       
    37 #include "abs_eap_am_mutex.h"
       
    38 #include "eap_automatic_variable.h"
       
    39 #include "eap_sort.h"
       
    40 #include "eap_buffer.h"
       
    41 #include "eap_config.h"
       
    42 
       
    43 
       
    44 //--------------------------------------------------
       
    45 
       
    46 /** @file */
       
    47 
       
    48 // 
       
    49 EAP_FUNC_EXPORT eap_type_aka_c::~eap_type_aka_c()
       
    50 {
       
    51 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
    52 
       
    53 	EAP_TRACE_DEBUG(
       
    54 		m_am_tools, 
       
    55 		TRACE_FLAGS_DEFAULT, 
       
    56 		(EAPL("eap_type_aka_c::~eap_type_aka_c(): this = 0x%08x => 0x%08x\n"),
       
    57 		this,
       
    58 		dynamic_cast<abs_eap_base_timer_c *>(this)));
       
    59 
       
    60 	EAP_ASSERT(m_shutdown_was_called == true);
       
    61 
       
    62 	if (m_free_am_type_aka == true
       
    63 		&& m_am_type_aka != 0)
       
    64 	{
       
    65 		delete m_am_type_aka;
       
    66 	}
       
    67 
       
    68 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
    69 }
       
    70 
       
    71 //--------------------------------------------------
       
    72 
       
    73 #if defined(_WIN32) && !defined(__GNUC__)
       
    74 	#pragma warning( disable : 4355 ) // 'this' : used in base member initializer list
       
    75 #endif
       
    76 
       
    77 // 
       
    78 EAP_FUNC_EXPORT eap_type_aka_c::eap_type_aka_c(
       
    79 	abs_eap_am_tools_c * const tools,
       
    80 	abs_eap_base_type_c * const partner,
       
    81 	eap_am_type_aka_c * const am_type_aka,
       
    82 	const bool free_am_type_aka,
       
    83 	const bool is_client_when_true,
       
    84 	const eap_am_network_id_c * const receive_network_id)
       
    85 	: eap_base_type_c(tools, partner)
       
    86 	, m_am_tools(tools)
       
    87 	, m_am_type_aka(am_type_aka)
       
    88 	, m_checkcode(tools)
       
    89 	, m_checkcode_update_count(0UL)
       
    90 	, m_received_checkcode(tools)
       
    91 	, m_checkcode_saved_message(tools)
       
    92 	, m_all_payloads(tools)
       
    93 	, m_nonce_mt_file(tools)
       
    94 	, m_manual_username(tools)
       
    95 	, m_manual_realm(tools)
       
    96 	, m_automatic_realm(tools)
       
    97 	, m_automatic_realm_read(false)
       
    98 	, m_aka_header_offset(0u)
       
    99 	, m_MTU(0u)
       
   100 	, m_trailer_length(0u)
       
   101 	, m_length_of_mnc(EAP_TYPE_AKA_DEFAULT_MNC_LENGTH_3_BYTES)
       
   102 	, m_authentication_type(AKA_AUTHENTICATION_TYPE_NONE)
       
   103 	, m_identity_type(AKA_IDENTITY_TYPE_NONE)
       
   104 	, m_client_error_code(eap_aka_client_error_code_none)
       
   105 	, m_aka_notification_code(eap_aka_notification_none)
       
   106 	, m_failure_message_delay_time(EAP_TYPE_AKA_TIMER_TIMEOUT_VALUE_DELAY_FAILURE_MESSAGE_SENT)
       
   107 	, m_is_valid(false)
       
   108 	, m_is_client(is_client_when_true)
       
   109 	, m_wait_eap_success_packet(true)
       
   110 	, m_check_identifier_of_eap_identity_response(false)
       
   111 	, m_free_am_type_aka(free_am_type_aka)
       
   112 	, m_client_responds_retransmitted_packets(false)
       
   113 	, m_aka_test_version(false)
       
   114 	, m_aka_randomly_refuse_eap_identity(false)
       
   115 	, m_check_nai_realm(false)
       
   116 	, m_fail_reauthentication_counter_check(false)
       
   117 	, m_accept_eap_identity_response(true)
       
   118 	, m_use_random_identity_on_eap_identity_response(false)
       
   119 	, m_shutdown_was_called(false)
       
   120 	, m_reset_was_called(false)
       
   121 	, m_use_pseudonym_identity(true)
       
   122 	, m_use_reauthentication_identity(true)
       
   123 	, m_erroneus_packet_received(false)
       
   124 	, m_aka_notification_packet_received(false)
       
   125 	, m_use_manual_username(false)
       
   126 	, m_use_manual_realm(false)
       
   127 	, m_randomly_fail_successfull_authentication(false)
       
   128 	, m_allow_use_result_indication(true)
       
   129 	, m_use_result_indication(false)
       
   130 	, m_state(eap_type_aka_state_none)
       
   131 	, m_saved_previous_state(eap_type_aka_state_none)
       
   132 	, m_send_network_id(tools)
       
   133 	, m_nonce_s(tools)
       
   134 	, m_IV(tools)
       
   135 	, m_saved_EAP_packet(tools)
       
   136 	, m_XKEY(tools)
       
   137 	, m_K_encr(tools)
       
   138 	, m_K_aut(tools)
       
   139 	, m_master_session_key(tools, eap_type_aka)
       
   140 	, m_IMSI(tools)
       
   141 	, m_pseudonym(tools)
       
   142 	, m_reauthentication_identity(tools)
       
   143 	, m_identity(tools)
       
   144 	, m_NAI(tools)
       
   145 	, m_RAND(tools)
       
   146 	, m_AUTN(tools)
       
   147 	, m_RES(tools)
       
   148 	, m_2_digit_mnc_map_of_mcc_of_imsi_array(tools)
       
   149 	, m_uma_automatic_realm_prefix(tools)
       
   150 	, m_use_uma_profile(false)
       
   151 	, m_authentication_vector(0)
       
   152 	, m_reauthentication_counter(0u)
       
   153 	, m_include_identity_to_aka_identity_response(aka_payload_NONE)
       
   154 	, m_aka_identity_response_includes_identity(aka_payload_NONE)
       
   155 	, m_failure_message_received(false)
       
   156 	, m_authentication_finished_successfully(false)
       
   157 	, m_last_eap_identifier(0)
       
   158 	, m_use_eap_expanded_type(false)
       
   159 {
       
   160 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   161 
       
   162 	EAP_TRACE_DEBUG(
       
   163 		m_am_tools, 
       
   164 		TRACE_FLAGS_DEFAULT, 
       
   165 		(EAPL("eap_type_aka_c::eap_type_aka_c(): this = 0x%08x => 0x%08x, ")
       
   166 		 EAPL("partner 0x%08x, type partner 0x%08x, compiled %s %s\n"),
       
   167 		 this,
       
   168 		 dynamic_cast<abs_eap_base_timer_c *>(this),
       
   169 		 partner,
       
   170 		 get_type_partner(),
       
   171 		__DATE__,
       
   172 		__TIME__));
       
   173 
       
   174 	if (m_am_type_aka == 0)
       
   175 	{
       
   176 		// Something wrong with AM.
       
   177 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   178 		return;
       
   179 	}
       
   180 	m_am_type_aka->set_am_partner(this);
       
   181 
       
   182 	if (m_checkcode.get_is_valid() == false
       
   183 		|| m_received_checkcode.get_is_valid() == false
       
   184 		|| m_checkcode_saved_message.get_is_valid() == false
       
   185 		|| m_nonce_mt_file.get_is_valid() == false
       
   186 		|| m_manual_username.get_is_valid() == false
       
   187 		|| m_manual_realm.get_is_valid() == false
       
   188 		|| m_send_network_id.get_is_valid() == false
       
   189 		|| m_nonce_s.get_is_valid() == false
       
   190 		|| m_IV.get_is_valid() == false
       
   191 		|| m_saved_EAP_packet.get_is_valid() == false
       
   192 		|| m_XKEY.get_is_valid() == false
       
   193 		|| m_K_encr.get_is_valid() == false
       
   194 		|| m_K_aut.get_is_valid() == false
       
   195 		|| m_master_session_key.get_is_valid() == false
       
   196 		|| m_IMSI.get_is_valid() == false
       
   197 		|| m_pseudonym.get_is_valid() == false
       
   198 		|| m_reauthentication_identity.get_is_valid() == false
       
   199 		|| m_identity.get_is_valid() == false
       
   200 		|| m_NAI.get_is_valid() == false
       
   201 		|| m_RAND.get_is_valid() == false
       
   202 		|| m_AUTN.get_is_valid() == false
       
   203 		|| m_RES.get_is_valid() == false)
       
   204 	{
       
   205 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   206 		return;
       
   207 	}
       
   208 
       
   209 	eap_status_e status = checkcode_init();
       
   210 	if (status != eap_status_ok)
       
   211 	{
       
   212 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   213 		return;
       
   214 	}
       
   215 
       
   216 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
   217 
       
   218 	initialize_state(eap_type_aka_state_pending_kc_sres_query, false, false,
       
   219 		aka_subtype_Notification,
       
   220 		aka_subtype_Challenge, // Re-transmitted EAP-Request/AKA/Challenge is allowed.
       
   221 		aka_subtype_NONE,
       
   222 		aka_subtype_NONE,
       
   223 		aka_subtype_NONE);
       
   224 
       
   225 	initialize_state(eap_type_aka_state_pending_authentication_vector_query, false, false,
       
   226 		aka_subtype_Notification,
       
   227 		aka_subtype_Identity, // Note EAP-Response/AKA/Identity message is allowed here, eap_type_aka_c::handle_aka_identity_response_message() will drop EAP-Response/AKA/Identity message quietly.
       
   228 		aka_subtype_Client_Error,
       
   229 		aka_subtype_Challenge, // Re-transmitted EAP-Response/AKA/Challenge is allowed.
       
   230 		aka_subtype_NONE);
       
   231 
       
   232 	initialize_state(eap_type_aka_state_waiting_for_aka_identity_request, false, false,
       
   233 		aka_subtype_Notification,
       
   234 		aka_subtype_Identity,
       
   235 		aka_subtype_NONE,
       
   236 		aka_subtype_NONE,
       
   237 		aka_subtype_NONE);
       
   238 
       
   239 	initialize_state(eap_type_aka_state_pseydonym_waiting_for_aka_identity_request, false, false,
       
   240 		aka_subtype_Notification,
       
   241 		aka_subtype_Identity,
       
   242 		aka_subtype_Re_authentication,
       
   243 		aka_subtype_NONE,
       
   244 		aka_subtype_NONE);
       
   245 
       
   246 	initialize_state(eap_type_aka_state_imsi_waiting_for_aka_identity_request, false, false,
       
   247 		aka_subtype_Notification,
       
   248 		aka_subtype_Identity,
       
   249 		aka_subtype_NONE,
       
   250 		aka_subtype_NONE,
       
   251 		aka_subtype_NONE);
       
   252 
       
   253 	initialize_state(eap_type_aka_state_waiting_for_aka_identity_response, true, false,
       
   254 		aka_subtype_Notification,
       
   255 		aka_subtype_Identity,
       
   256 		aka_subtype_Client_Error,
       
   257 		aka_subtype_NONE,
       
   258 		aka_subtype_NONE);
       
   259 
       
   260 	initialize_state(eap_type_aka_state_waiting_for_notification_request_success, false, true,
       
   261 		aka_subtype_Notification,
       
   262 		aka_subtype_Challenge,
       
   263 		aka_subtype_Re_authentication,
       
   264 		aka_subtype_NONE,
       
   265 		aka_subtype_NONE);
       
   266 
       
   267 	initialize_state(eap_type_aka_state_waiting_for_notification_response_failure, true, false,
       
   268 		aka_subtype_Notification,
       
   269 		aka_subtype_NONE,
       
   270 		aka_subtype_NONE,
       
   271 		aka_subtype_NONE,
       
   272 		aka_subtype_NONE);
       
   273 
       
   274 	initialize_state(eap_type_aka_state_waiting_for_notification_response_success, true, false,
       
   275 		aka_subtype_Notification,
       
   276 		aka_subtype_NONE,
       
   277 		aka_subtype_NONE,
       
   278 		aka_subtype_NONE,
       
   279 		aka_subtype_NONE);
       
   280 
       
   281 	initialize_state(eap_type_aka_state_waiting_for_aka_identity_response_with_at_permanent_identity, true, false,
       
   282 		aka_subtype_Notification,
       
   283 		aka_subtype_Identity,
       
   284 		aka_subtype_Client_Error,
       
   285 		aka_subtype_NONE,
       
   286 		aka_subtype_NONE);
       
   287 
       
   288 	initialize_state(eap_type_aka_state_waiting_for_aka_identity_response_with_at_full_auth_identity, true, false,
       
   289 		aka_subtype_Notification,
       
   290 		aka_subtype_Identity,
       
   291 		aka_subtype_Client_Error,
       
   292 		aka_subtype_NONE,
       
   293 		aka_subtype_NONE);
       
   294 
       
   295 	initialize_state(eap_type_aka_state_waiting_for_aka_identity_response_with_at_any_identity, true, false,
       
   296 		aka_subtype_Notification,
       
   297 		aka_subtype_Identity,
       
   298 		aka_subtype_Client_Error,
       
   299 		aka_subtype_NONE,
       
   300 		aka_subtype_NONE);
       
   301 
       
   302 	initialize_state(eap_type_aka_state_analyse_aka_identity_request, false, false,
       
   303 		aka_subtype_Notification,
       
   304 		aka_subtype_NONE,
       
   305 		aka_subtype_NONE,
       
   306 		aka_subtype_NONE,
       
   307 		aka_subtype_NONE);
       
   308 
       
   309 	initialize_state(eap_type_aka_state_waiting_for_challenge_request, false, false,
       
   310 		aka_subtype_Notification,
       
   311 		aka_subtype_Challenge,
       
   312 		aka_subtype_Identity,
       
   313 		aka_subtype_NONE,
       
   314 		aka_subtype_NONE);
       
   315 
       
   316 	initialize_state(eap_type_aka_state_waiting_for_challenge_response, false, false,
       
   317 		aka_subtype_Notification,
       
   318 		aka_subtype_Challenge,
       
   319 		aka_subtype_Identity,
       
   320 		aka_subtype_Client_Error,
       
   321 		aka_subtype_Synchronization_Failure);
       
   322 
       
   323 	initialize_state(eap_type_aka_state_waiting_for_reauth_request, false, false,
       
   324 		aka_subtype_Notification,
       
   325 		aka_subtype_Re_authentication,
       
   326 		aka_subtype_Identity,
       
   327 		aka_subtype_Challenge, // This is allowed because, server could start full authentication.
       
   328 		aka_subtype_NONE);
       
   329 
       
   330 	initialize_state(eap_type_aka_state_waiting_for_reauth_response, false, false,
       
   331 		aka_subtype_Notification,
       
   332 		aka_subtype_Re_authentication,
       
   333 		aka_subtype_Identity,
       
   334 		aka_subtype_Client_Error,
       
   335 		aka_subtype_NONE);
       
   336 
       
   337 	initialize_state(eap_type_aka_state_success, false, false,
       
   338 		aka_subtype_Notification,
       
   339 		aka_subtype_Challenge,
       
   340 		aka_subtype_NONE,
       
   341 		aka_subtype_NONE,
       
   342 		aka_subtype_NONE);
       
   343 
       
   344 	initialize_state(eap_type_aka_state_waiting_for_success, false, false,
       
   345 		aka_subtype_Notification,
       
   346 		aka_subtype_Challenge,
       
   347 		aka_subtype_Re_authentication,
       
   348 		aka_subtype_NONE,
       
   349 		aka_subtype_NONE);
       
   350 
       
   351 	initialize_state(eap_type_aka_state_failure, false, false,
       
   352 		aka_subtype_NONE,
       
   353 		aka_subtype_NONE,
       
   354 		aka_subtype_NONE,
       
   355 		aka_subtype_NONE,
       
   356 		aka_subtype_NONE);
       
   357 
       
   358 	{
       
   359 		// Here we swap the addresses.
       
   360 		eap_am_network_id_c send_network_id(m_am_tools,
       
   361 			receive_network_id->get_destination_id(),
       
   362 			receive_network_id->get_source_id(),
       
   363 			receive_network_id->get_type());
       
   364 
       
   365 		status = m_send_network_id.set_copy_of_network_id(&send_network_id);
       
   366 
       
   367 		if (status != eap_status_ok
       
   368 			|| m_send_network_id.get_is_valid_data() == false)
       
   369 		{
       
   370 			(void) EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   371 			return;
       
   372 		}
       
   373 	}
       
   374 
       
   375 	set_is_valid();
       
   376 
       
   377 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   378 }
       
   379 
       
   380 //-----------------------------------------------
       
   381 
       
   382 //
       
   383 void eap_type_aka_c::initialize_state(
       
   384 				const eap_type_aka_state_variable_e state,
       
   385 				const bool must_be_initiator,
       
   386 				const bool must_be_responder,
       
   387 				const aka_subtype_e type0,
       
   388 				const aka_subtype_e type1,
       
   389 				const aka_subtype_e type2,
       
   390 				const aka_subtype_e type3,
       
   391 				const aka_subtype_e type4)
       
   392 {
       
   393 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   394 
       
   395 	m_parameters[(state)].init_state(must_be_initiator, must_be_responder,
       
   396 		type0, type1, type2, type3, type4);
       
   397 
       
   398 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   399 }
       
   400 
       
   401 //--------------------------------------------------
       
   402 
       
   403 EAP_FUNC_EXPORT bool eap_type_aka_c::random_selection()
       
   404 {
       
   405 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   406 
       
   407 	crypto_random_c rand(m_am_tools);
       
   408 
       
   409 	if (rand.get_is_valid() == false)
       
   410 	{
       
   411 		return false;
       
   412 	}
       
   413 
       
   414 	return (rand.get_rand_integer(0, 1) != 0);
       
   415 }
       
   416 
       
   417 //--------------------------------------------------
       
   418 
       
   419 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::checkcode_init()
       
   420 {
       
   421 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   422 
       
   423 	m_checkcode_update_count = 0UL;
       
   424 
       
   425 	m_received_checkcode.reset();
       
   426 
       
   427 	m_checkcode_saved_message.reset();
       
   428 
       
   429 	m_all_payloads.reset();
       
   430 
       
   431 	eap_status_e status = m_checkcode.hash_init();
       
   432 	if (status != eap_status_ok)
       
   433 	{
       
   434 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   435 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   436 	}
       
   437 
       
   438 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   439 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   440 }
       
   441 
       
   442 //--------------------------------------------------
       
   443 
       
   444 EAP_FUNC_EXPORT bool eap_type_aka_c::compare_payload_first_is_less(
       
   445 	const aka_payload_AT_type_e * const first,
       
   446 	const aka_payload_AT_type_e * const second,
       
   447 	abs_eap_am_tools_c * const /* m_am_tools */)
       
   448 {
       
   449 	return *first < *second;
       
   450 }
       
   451 
       
   452 //--------------------------------------------------
       
   453 
       
   454 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::checkcode_verify_payloads(
       
   455 	aka_payloads_c * const p_aka_payloads)
       
   456 {
       
   457 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   458 
       
   459 	if (p_aka_payloads != 0
       
   460 		&& p_aka_payloads->get_all_payloads()->get_is_valid_data() == true)
       
   461 	{
       
   462 		EAP_TRACE_DATA_DEBUG(
       
   463 			m_am_tools,
       
   464 			TRACE_FLAGS_DEFAULT,
       
   465 			(EAPL(" CHECKCODE plain payload array"),
       
   466 			 p_aka_payloads->get_all_payloads()->get_data(p_aka_payloads->get_all_payloads()->get_data_length()),
       
   467 			 p_aka_payloads->get_all_payloads()->get_data_length()));
       
   468 
       
   469 		// This will sort the payload array of type aka_payload_AT_type_e in increasing order.
       
   470 		// Comparing this payload array to previous payload arrays is then easy task.
       
   471 		eap_status_e status = eap_sort_array<aka_payload_AT_type_e>(
       
   472 			reinterpret_cast<aka_payload_AT_type_e *>(
       
   473 				p_aka_payloads->get_all_payloads()->get_data(
       
   474 					p_aka_payloads->get_all_payloads()->get_data_length())),
       
   475 			p_aka_payloads->get_all_payloads()->get_data_length()/sizeof(aka_payload_AT_type_e),
       
   476 			compare_payload_first_is_less,
       
   477 			m_am_tools);
       
   478 		if (status != eap_status_ok)
       
   479 		{
       
   480 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   481 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   482 		}
       
   483 
       
   484 		EAP_TRACE_DATA_DEBUG(
       
   485 			m_am_tools,
       
   486 			TRACE_FLAGS_DEFAULT,
       
   487 			(EAPL("CHECKCODE sorted payload array"),
       
   488 			 p_aka_payloads->get_all_payloads()->get_data(p_aka_payloads->get_all_payloads()->get_data_length()),
       
   489 			 p_aka_payloads->get_all_payloads()->get_data_length()));
       
   490 
       
   491 		for (u32_t ind = 0ul; ind < m_all_payloads.get_object_count(); ind++)
       
   492 		{
       
   493 			eap_variable_data_c * const payloads =  m_all_payloads.get_object(ind);
       
   494 			if (payloads != 0)
       
   495 			{
       
   496 				if (payloads->compare(p_aka_payloads->get_all_payloads()) == 0)
       
   497 				{
       
   498 					// Message with these payloads have been seen already.
       
   499 					EAP_TRACE_DEBUG(
       
   500 						m_am_tools, 
       
   501 						TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
   502 						(EAPL("WARNING: message with these payloads have been seen already.\n")));
       
   503 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   504 					return EAP_STATUS_RETURN(m_am_tools, eap_status_already_exists);
       
   505 				}
       
   506 			}
       
   507 		}
       
   508 
       
   509 		// Save this payload array.
       
   510 		eap_variable_data_c * copy_attributes = p_aka_payloads->get_all_payloads()->copy();
       
   511 		if (copy_attributes == 0)
       
   512 		{
       
   513 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   514 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   515 		}
       
   516 
       
   517 		status = m_all_payloads.add_object(copy_attributes, true);
       
   518 		if (status != eap_status_ok)
       
   519 		{
       
   520 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   521 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   522 		}
       
   523 	}
       
   524 
       
   525 
       
   526 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   527 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   528 }
       
   529 
       
   530 //--------------------------------------------------
       
   531 
       
   532 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::checkcode_save_message_client(
       
   533 	const void * const data,
       
   534 	const u32_t data_length,
       
   535 	aka_payloads_c * const p_aka_payloads)
       
   536 {
       
   537 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   538 
       
   539 	eap_status_e status = eap_status_process_general_error;
       
   540 
       
   541 	if (p_aka_payloads != 0)
       
   542 	{
       
   543 		// Client received a message.
       
   544 
       
   545 		status = checkcode_verify_payloads(p_aka_payloads);
       
   546 		if (status == eap_status_ok)
       
   547 		{
       
   548 			// This is a new received message with new payloads.
       
   549 			status = checkcode_update_saved_message();
       
   550 
       
   551 		}
       
   552 		else
       
   553 		{
       
   554 			// Received message is duplicate.
       
   555 		}
       
   556 
       
   557 		EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("CHECKCODE saved data client"),
       
   558 			data,
       
   559 			data_length));
       
   560 
       
   561 		status = m_checkcode_saved_message.set_copy_of_buffer(
       
   562 			data,
       
   563 			data_length);
       
   564 	}
       
   565 	else
       
   566 	{
       
   567 		// Client sends a response message.
       
   568 
       
   569 		EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("CHECKCODE saved data client"),
       
   570 			data,
       
   571 			data_length));
       
   572 
       
   573 		status = m_checkcode_saved_message.add_data(
       
   574 			data,
       
   575 			data_length);
       
   576 	}
       
   577 
       
   578 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   579 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   580 }
       
   581 
       
   582 //--------------------------------------------------
       
   583 
       
   584 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::checkcode_save_message_server(
       
   585 	const void * const data,
       
   586 	const u32_t data_length)
       
   587 {
       
   588 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   589 
       
   590 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("CHECKCODE saved data server"),
       
   591 		data,
       
   592 		data_length));
       
   593 
       
   594 	eap_status_e status = m_checkcode_saved_message.set_copy_of_buffer(
       
   595 		data,
       
   596 		data_length);
       
   597 
       
   598 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   599 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   600 }
       
   601 
       
   602 //--------------------------------------------------
       
   603 
       
   604 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::checkcode_update_saved_message()
       
   605 {
       
   606 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   607 
       
   608 	eap_status_e status = eap_status_ok;
       
   609 
       
   610 	if (m_checkcode_saved_message.get_is_valid_data() == true
       
   611 		&& m_checkcode_saved_message.get_data_length() > 0UL)
       
   612 	{
       
   613 		status = checkcode_update(
       
   614 			m_checkcode_saved_message.get_data(m_checkcode_saved_message.get_data_length()),
       
   615 			m_checkcode_saved_message.get_data_length());
       
   616 
       
   617 		m_checkcode_saved_message.reset();
       
   618 	}
       
   619 
       
   620 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   621 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   622 }
       
   623 
       
   624 //--------------------------------------------------
       
   625 
       
   626 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::checkcode_update(
       
   627 	const void * const data,
       
   628 	const u32_t data_length)
       
   629 {
       
   630 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   631 
       
   632 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("CHECKCODE data"),
       
   633 		data,
       
   634 		data_length));
       
   635 
       
   636 	++m_checkcode_update_count;
       
   637 
       
   638 	eap_status_e status = m_checkcode.hash_update(
       
   639 		data,
       
   640 		data_length);
       
   641 
       
   642 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   643 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   644 }
       
   645 
       
   646 //--------------------------------------------------
       
   647 
       
   648 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::checkcode_final(
       
   649 	eap_variable_data_c * const digest)
       
   650 {
       
   651 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   652 
       
   653 	eap_status_e status = checkcode_update_saved_message();
       
   654 	if (status != eap_status_ok)
       
   655 	{
       
   656 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   657 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   658 	}
       
   659 
       
   660 	u32_t digest_length = m_checkcode.get_digest_length();
       
   661 
       
   662 	status = digest->init(digest_length);
       
   663 	if (status != eap_status_ok)
       
   664 	{
       
   665 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   666 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   667 	}
       
   668 	digest->set_is_valid();
       
   669 	digest->set_data_length(digest_length);
       
   670 
       
   671 	if (m_checkcode_update_count == 0UL)
       
   672 	{
       
   673 		// No AKA-Identity messages were sent.
       
   674 		digest->set_data_length(0UL);
       
   675 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   676 		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   677 	}
       
   678 
       
   679 	// Create a copy of crypto_sha1_c object.
       
   680 	// This will save the HASH for later use.
       
   681 	abs_crypto_hash_algorithm_c * const copy_checkcode = m_checkcode.copy();
       
   682 	eap_automatic_variable_c<abs_crypto_hash_algorithm_c> automatic_copy_checkcode(m_am_tools, copy_checkcode);
       
   683 
       
   684 	if (copy_checkcode == 0
       
   685 		|| copy_checkcode->get_is_valid() == false)
       
   686 	{
       
   687 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   688 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   689 	}
       
   690 
       
   691 	status = copy_checkcode->hash_final(
       
   692 		digest->get_data(digest_length),
       
   693 		&digest_length);
       
   694 	if (status != eap_status_ok)
       
   695 	{
       
   696 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   697 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   698 	}
       
   699 
       
   700 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   701 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   702 }
       
   703 
       
   704 //--------------------------------------------------
       
   705 
       
   706 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::checkcode_verify(
       
   707 	const eap_variable_data_c * const received_digest)
       
   708 {
       
   709 	// Verify AT_CHECKCODE.
       
   710 	eap_variable_data_c checkcode_digest(m_am_tools);
       
   711 
       
   712 	if (checkcode_digest.get_is_valid() == false)
       
   713 	{
       
   714 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   715 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   716 	}
       
   717 
       
   718 	eap_status_e status = checkcode_final(
       
   719 		&checkcode_digest);
       
   720 	if (status != eap_status_ok)
       
   721 	{
       
   722 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   723 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   724 	}
       
   725 
       
   726 	if ((m_checkcode_update_count != 0 && received_digest->get_data_length() == 0)
       
   727 		|| (m_checkcode_update_count == 0 && received_digest->get_data_length() != 0)
       
   728 		|| checkcode_digest.compare(received_digest) != 0)
       
   729 	{
       
   730 		EAP_TRACE_DEBUG(
       
   731 			m_am_tools, 
       
   732 			TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
   733 			(EAPL("ERROR: EAP_type_AKA: %s, eap_type_aka_c::checkcode_verify(): CHECKCODE failed, m_checkcode_update_count %d, state %s\n"),
       
   734 			 (m_is_client == true) ? "client": "server",
       
   735 			 m_checkcode_update_count,
       
   736 			 get_state_string()));
       
   737 
       
   738 		EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("   local digest"),
       
   739 			checkcode_digest.get_data(checkcode_digest.get_data_length()),
       
   740 			checkcode_digest.get_data_length()));
       
   741 
       
   742 		EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("received digest"),
       
   743 			received_digest->get_data(received_digest->get_data_length()),
       
   744 			received_digest->get_data_length()));
       
   745 
       
   746 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   747 		return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure);
       
   748 	}
       
   749 	else
       
   750 	{
       
   751 		EAP_TRACE_DEBUG(
       
   752 			m_am_tools, 
       
   753 			TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
   754 			(EAPL("EAP_type_AKA: %s, eap_type_aka_c::checkcode_verify(): CHECKCODE OK, state %s\n"),
       
   755 			 (m_is_client == true) ? "client": "server",
       
   756 			 get_state_string()));
       
   757 	}
       
   758 
       
   759 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   760 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   761 }
       
   762 
       
   763 //--------------------------------------------------
       
   764 
       
   765 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::send_final_notification()
       
   766 {
       
   767 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   768 
       
   769 	if (m_is_valid == true)
       
   770 	{
       
   771 		if (get_authentication_finished_successfully() == false)
       
   772 		{
       
   773 			EAP_TRACE_DEBUG(
       
   774 				m_am_tools, 
       
   775 				TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
   776 				(EAPL("ERROR: EAP_type_AKA: %s, authentication FAILED, state %s\n"),
       
   777 				 (m_is_client == true) ? "client": "server",
       
   778 				 get_state_string()));
       
   779 
       
   780 			if (m_aka_notification_code != eap_aka_notification_none)
       
   781 			{
       
   782 				// We have received EAP-Request/AKA notification, we pass the received code to the adaptation module.
       
   783 				(void) m_am_type_aka->handle_aka_notification(m_aka_notification_code);
       
   784 			}
       
   785 
       
   786 			set_state(eap_type_aka_state_failure);
       
   787 
       
   788 			// Notifies the lower level of unsuccessfull authentication.
       
   789 			eap_state_notification_c notification(
       
   790 				m_am_tools,
       
   791 				get_send_network_id(),
       
   792 				m_is_client,
       
   793 				eap_state_notification_eap,
       
   794 				eap_protocol_layer_eap,
       
   795 				eap_type_aka,
       
   796 				eap_state_none,
       
   797 				eap_state_authentication_terminated_unsuccessfully,
       
   798 				get_last_eap_identifier(),
       
   799 				false);
       
   800 
       
   801 			notification.set_authentication_error(eap_status_authentication_failure);
       
   802 
       
   803 			state_notification(&notification);
       
   804 
       
   805 			// Indicate AKA AM authentication finish.
       
   806 			m_am_type_aka->authentication_finished(false, m_authentication_type, m_identity_type);
       
   807 		}
       
   808 	}
       
   809 
       
   810 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   811 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   812 }
       
   813 
       
   814 //--------------------------------------------------
       
   815 
       
   816 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::add_variable_payload(
       
   817 	aka_header_c * const aka,
       
   818 	const u32_t aka_buffer_length,
       
   819 	const u32_t eap_header_size,
       
   820 	u32_t * const aka_data_offset,
       
   821 	u32_t * const aka_data_free,
       
   822 	u32_t * const packet_buffer_free,
       
   823 	u32_t * const packet_buffer_offset,
       
   824 	const eap_variable_data_c * const data_payload,
       
   825 	const aka_payload_AT_type_e data_payload_type)
       
   826 {
       
   827 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   828 
       
   829 	eap_status_e status = eap_status_process_general_error;
       
   830 	u16_t data_length = 0u;
       
   831 
       
   832 	if (data_payload != 0)
       
   833 	{
       
   834 		if (data_payload->get_is_valid_data() == false)
       
   835 		{
       
   836 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   837 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_data_payload);
       
   838 		}
       
   839 
       
   840 		if (data_payload->get_data_length() > aka_payload_AT_header_c::get_max_payload_data_length())
       
   841 		{
       
   842 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   843 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   844 		}
       
   845 
       
   846 		data_length = static_cast<u16_t>(data_payload->get_data_length());
       
   847 	}
       
   848 	else
       
   849 	{
       
   850 		// No data.
       
   851 		data_length = 0u;
       
   852 	}
       
   853 
       
   854 	aka_payload_AT_header_c gp_data(
       
   855 		m_am_tools,
       
   856 		aka->get_data_offset(*aka_data_offset, *aka_data_free),
       
   857 		*aka_data_free);
       
   858 
       
   859 	if (gp_data.get_is_valid() == false)
       
   860 	{
       
   861 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   862 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   863 	}
       
   864 
       
   865 	gp_data.reset_header(data_length);
       
   866 
       
   867 	if (data_length > 0u)
       
   868 	{
       
   869 		u8_t *payload_buffer = gp_data.get_data(data_length);
       
   870 
       
   871 		if (payload_buffer == 0)
       
   872 		{
       
   873 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   874 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   875 		}
       
   876 
       
   877 		m_am_tools->memmove(
       
   878 			payload_buffer,
       
   879 			data_payload->get_data(data_payload->get_data_length()),
       
   880 			data_payload->get_data_length());
       
   881 	}
       
   882 
       
   883 	gp_data.set_data_length(data_length);
       
   884 
       
   885 	status = eap_status_ok;
       
   886 
       
   887 
       
   888 	gp_data.set_current_payload(data_payload_type);
       
   889 
       
   890 	update_payload_indexes(
       
   891 		aka_buffer_length,
       
   892 		eap_header_size,
       
   893 		gp_data.get_header_length()+gp_data.get_data_length(),
       
   894 		aka_data_offset,
       
   895 		aka_data_free,
       
   896 		packet_buffer_offset,
       
   897 		packet_buffer_free);
       
   898 
       
   899 	EAP_AKA_TRACE_PAYLOAD("Payload added", &gp_data);
       
   900 
       
   901 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   902 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   903 }
       
   904 
       
   905 //--------------------------------------------------
       
   906 
       
   907 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::add_RES_payload(
       
   908 	aka_header_c * const aka,
       
   909 	const u32_t aka_buffer_length,
       
   910 	const u32_t eap_header_size,
       
   911 	u32_t * const aka_data_offset,
       
   912 	u32_t * const aka_data_free,
       
   913 	u32_t * const packet_buffer_free,
       
   914 	u32_t * const packet_buffer_offset,
       
   915 	const eap_variable_data_c * const RES,
       
   916 	const aka_payload_AT_type_e data_payload_type)
       
   917 {
       
   918 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   919 
       
   920 	eap_status_e status = eap_status_process_general_error;
       
   921 	u16_t data_length = 0u;
       
   922 
       
   923 	if (RES != 0)
       
   924 	{
       
   925 		if (RES->get_is_valid_data() == false)
       
   926 		{
       
   927 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   928 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_data_payload);
       
   929 		}
       
   930 
       
   931 		if (RES->get_data_length() > aka_payload_AT_header_c::get_max_payload_data_length())
       
   932 		{
       
   933 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   934 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   935 		}
       
   936 
       
   937 		data_length = static_cast<u16_t>(RES->get_data_length());
       
   938 	}
       
   939 	else
       
   940 	{
       
   941 		// No data.
       
   942 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   943 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   944 	}
       
   945 
       
   946 	u16_t padding_zero_count = 0u;
       
   947 	// Add padding zero octets
       
   948 	if ((data_length % 4u) != 0)
       
   949 	{
       
   950 		padding_zero_count = 4u - (data_length % 4u);
       
   951 	}
       
   952 
       
   953 	if (RES->get_data_length()+padding_zero_count
       
   954 		> aka_payload_AT_header_c::get_max_payload_data_length())
       
   955 	{
       
   956 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   957 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   958 	}
       
   959 
       
   960 	if (RES->get_data_length()+padding_zero_count > *packet_buffer_free)
       
   961 	{
       
   962 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   963 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   964 	}
       
   965 
       
   966 	aka_payload_AT_header_c gp_data(
       
   967 		m_am_tools,
       
   968 		aka->get_data_offset(*aka_data_offset, *aka_data_free),
       
   969 		*aka_data_free);
       
   970 
       
   971 	if (gp_data.get_is_valid() == false)
       
   972 	{
       
   973 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   974 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   975 	}
       
   976 
       
   977 	gp_data.reset_header(data_length+padding_zero_count);
       
   978 
       
   979 	{
       
   980 		u8_t *payload_buffer = gp_data.get_data(data_length+padding_zero_count);
       
   981 
       
   982 		if (payload_buffer == 0)
       
   983 		{
       
   984 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   985 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   986 		}
       
   987 
       
   988 		m_am_tools->memmove(
       
   989 			payload_buffer,
       
   990 			RES->get_data(data_length),
       
   991 			data_length);
       
   992 
       
   993 		if (padding_zero_count > 0u)
       
   994 		{
       
   995 			m_am_tools->memset(
       
   996 				payload_buffer+data_length,
       
   997 				0,
       
   998 				padding_zero_count);
       
   999 		}
       
  1000 	}
       
  1001 
       
  1002 	// Note the reserved field includes the actual length of RES in bits in network order.
       
  1003 	// It is always multiple of 8 bits.
       
  1004 	gp_data.set_reserved(static_cast<u16_t>(data_length*8ul));
       
  1005 
       
  1006 	gp_data.set_data_length(data_length+padding_zero_count);
       
  1007 
       
  1008 	status = eap_status_ok;
       
  1009 
       
  1010 
       
  1011 	gp_data.set_current_payload(data_payload_type);
       
  1012 
       
  1013 	update_payload_indexes(
       
  1014 		aka_buffer_length,
       
  1015 		eap_header_size,
       
  1016 		gp_data.get_header_length()+gp_data.get_data_length(),
       
  1017 		aka_data_offset,
       
  1018 		aka_data_free,
       
  1019 		packet_buffer_offset,
       
  1020 		packet_buffer_free);
       
  1021 
       
  1022 	EAP_AKA_TRACE_PAYLOAD("Payload added", &gp_data);
       
  1023 
       
  1024 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1025 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1026 }
       
  1027 
       
  1028 //--------------------------------------------------
       
  1029 
       
  1030 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::add_AUTS_payload(
       
  1031 	aka_header_c * const aka,
       
  1032 	const u32_t aka_buffer_length,
       
  1033 	const u32_t eap_header_size,
       
  1034 	u32_t * const aka_data_offset,
       
  1035 	u32_t * const aka_data_free,
       
  1036 	u32_t * const packet_buffer_free,
       
  1037 	u32_t * const packet_buffer_offset,
       
  1038 	const eap_variable_data_c * const AUTS,
       
  1039 	const aka_payload_AT_type_e data_payload_type)
       
  1040 {
       
  1041 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1042 
       
  1043 	eap_status_e status = eap_status_process_general_error;
       
  1044 	u16_t data_length = 0u;
       
  1045 
       
  1046 	if (AUTS != 0)
       
  1047 	{
       
  1048 		if (AUTS->get_is_valid_data() == false)
       
  1049 		{
       
  1050 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1051 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_data_payload);
       
  1052 		}
       
  1053 
       
  1054 		if (AUTS->get_data_length() > aka_payload_AT_header_c::get_max_payload_data_length())
       
  1055 		{
       
  1056 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1057 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1058 		}
       
  1059 
       
  1060 		if (AUTS->get_data_length() >= 2ul)
       
  1061 		{
       
  1062 			// NOTE first 2 bytes are in reserved field.
       
  1063 			data_length = static_cast<u16_t>(AUTS->get_data_length() - 2ul);
       
  1064 		}
       
  1065 		else
       
  1066 		{
       
  1067 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1068 			return EAP_STATUS_RETURN(m_am_tools, eap_status_buffer_too_short);
       
  1069 		}
       
  1070 	}
       
  1071 	else
       
  1072 	{
       
  1073 		// No data.
       
  1074 		data_length = 0u;
       
  1075 	}
       
  1076 
       
  1077 	aka_payload_AT_header_c gp_data(
       
  1078 		m_am_tools,
       
  1079 		aka->get_data_offset(*aka_data_offset, *aka_data_free),
       
  1080 		*aka_data_free);
       
  1081 
       
  1082 	if (gp_data.get_is_valid() == false)
       
  1083 	{
       
  1084 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1085 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1086 	}
       
  1087 
       
  1088 	gp_data.reset_header(data_length);
       
  1089 
       
  1090 	if (data_length > 0u)
       
  1091 	{
       
  1092 		u8_t *payload_buffer = gp_data.get_reserved_pointer(AUTS->get_data_length());
       
  1093 
       
  1094 		if (payload_buffer == 0)
       
  1095 		{
       
  1096 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1097 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1098 		}
       
  1099 
       
  1100 		// The first 2 bytes are in reserved field.
       
  1101 		m_am_tools->memmove(
       
  1102 			payload_buffer,
       
  1103 			AUTS->get_data(AUTS->get_data_length()),
       
  1104 			AUTS->get_data_length());
       
  1105 	}
       
  1106 
       
  1107 	gp_data.set_data_length(data_length);
       
  1108 
       
  1109 	status = eap_status_ok;
       
  1110 
       
  1111 
       
  1112 	gp_data.set_current_payload(data_payload_type);
       
  1113 
       
  1114 	update_payload_indexes(
       
  1115 		aka_buffer_length,
       
  1116 		eap_header_size,
       
  1117 		gp_data.get_header_length()+gp_data.get_data_length(),
       
  1118 		aka_data_offset,
       
  1119 		aka_data_free,
       
  1120 		packet_buffer_offset,
       
  1121 		packet_buffer_free);
       
  1122 
       
  1123 	EAP_AKA_TRACE_PAYLOAD("Payload added", &gp_data);
       
  1124 
       
  1125 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1126 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1127 }
       
  1128 
       
  1129 //--------------------------------------------------
       
  1130 
       
  1131 // Note the specification of IMSI payload is not same as pseudonym.
       
  1132 // IMSI and pseudonym specifications should be integrated.
       
  1133 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::add_pseudonym_or_imsi_payload(
       
  1134 	aka_header_c * const aka,
       
  1135 	const u32_t aka_buffer_length,
       
  1136 	const u32_t eap_header_size,
       
  1137 	u32_t * const aka_data_offset,
       
  1138 	u32_t * const aka_data_free,
       
  1139 	u32_t * const packet_buffer_free,
       
  1140 	u32_t * const packet_buffer_offset,
       
  1141 	const eap_variable_data_c * const pseudonym_or_imsi,
       
  1142 	const aka_payload_AT_type_e data_payload_type)
       
  1143 {
       
  1144 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1145 
       
  1146 	eap_status_e status = eap_status_process_general_error;
       
  1147 
       
  1148 	if (pseudonym_or_imsi->get_is_valid_data() == false)
       
  1149 	{
       
  1150 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1151 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_data_payload);
       
  1152 	}
       
  1153 
       
  1154 	u32_t padding_zero_count = 0u;
       
  1155 	// Add padding zero octets
       
  1156 	if ((pseudonym_or_imsi->get_data_length() % 4u) != 0)
       
  1157 	{
       
  1158 		padding_zero_count = 4u - (pseudonym_or_imsi->get_data_length() % 4u);
       
  1159 	}
       
  1160 
       
  1161 	if (pseudonym_or_imsi->get_data_length()+padding_zero_count
       
  1162 		> aka_payload_AT_header_c::get_max_payload_data_length())
       
  1163 	{
       
  1164 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1165 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1166 	}
       
  1167 
       
  1168 	if (pseudonym_or_imsi->get_data_length()+padding_zero_count > *packet_buffer_free)
       
  1169 	{
       
  1170 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1171 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1172 	}
       
  1173 
       
  1174 	aka_payload_AT_header_c gp_data(
       
  1175 		m_am_tools,
       
  1176 		aka->get_data_offset(
       
  1177 			*aka_data_offset, 
       
  1178 			*aka_data_free),
       
  1179 		*aka_data_free);
       
  1180 
       
  1181 	if (gp_data.get_is_valid() == false)
       
  1182 	{
       
  1183 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1184 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1185 	}
       
  1186 
       
  1187 	gp_data.reset_header(static_cast<u16_t>(pseudonym_or_imsi->get_data_length()+padding_zero_count));
       
  1188 
       
  1189 	u8_t *payload_buffer = gp_data.get_data(pseudonym_or_imsi->get_data_length()+padding_zero_count);
       
  1190 
       
  1191 	if (payload_buffer == 0
       
  1192 		|| pseudonym_or_imsi->get_data_length() == 0)
       
  1193 	{
       
  1194 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1195 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1196 	}
       
  1197 
       
  1198 	m_am_tools->memmove(
       
  1199 		payload_buffer,
       
  1200 		pseudonym_or_imsi->get_data(pseudonym_or_imsi->get_data_length()),
       
  1201 		pseudonym_or_imsi->get_data_length());
       
  1202 
       
  1203 	if (padding_zero_count > 0u)
       
  1204 	{
       
  1205 		m_am_tools->memset(
       
  1206 			payload_buffer+(pseudonym_or_imsi->get_data_length()),
       
  1207 			0,
       
  1208 			padding_zero_count);
       
  1209 	}
       
  1210 
       
  1211 	// Note the reserved field includes the actual length of pseudonym in network order.
       
  1212 	// This must be less or equal to the length field.
       
  1213 	gp_data.set_reserved(static_cast<u16_t>(pseudonym_or_imsi->get_data_length()));
       
  1214 
       
  1215 	gp_data.set_data_length(static_cast<u16_t>(pseudonym_or_imsi->get_data_length()+padding_zero_count));
       
  1216 
       
  1217 	status = eap_status_ok;
       
  1218 
       
  1219 	gp_data.set_current_payload(data_payload_type);
       
  1220 
       
  1221 	update_payload_indexes(
       
  1222 		aka_buffer_length,
       
  1223 		eap_header_size,
       
  1224 		gp_data.get_header_length()+gp_data.get_data_length(),
       
  1225 		aka_data_offset,
       
  1226 		aka_data_free,
       
  1227 		packet_buffer_offset,
       
  1228 		packet_buffer_free);
       
  1229 
       
  1230 	EAP_AKA_TRACE_PAYLOAD("Payload added", &gp_data);
       
  1231 
       
  1232 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1233 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1234 }
       
  1235 
       
  1236 //--------------------------------------------------
       
  1237 
       
  1238 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::add_notification_payload(
       
  1239 	aka_header_c * const aka,
       
  1240 	const u32_t aka_buffer_length,
       
  1241 	const u32_t eap_header_size,
       
  1242 	u32_t * const aka_data_offset,
       
  1243 	u32_t * const aka_data_free,
       
  1244 	u32_t * const packet_buffer_free,
       
  1245 	u32_t * const packet_buffer_offset,
       
  1246 	const eap_aka_notification_codes_e notification_code)
       
  1247 {
       
  1248 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1249 
       
  1250 	eap_status_e status = eap_status_process_general_error;
       
  1251 
       
  1252 	aka_payload_AT_header_c gp_data(
       
  1253 		m_am_tools,
       
  1254 		aka->get_data_offset(
       
  1255 			*aka_data_offset, 
       
  1256 			*aka_data_free),
       
  1257 		*aka_data_free);
       
  1258 
       
  1259 	if (gp_data.get_is_valid() == false)
       
  1260 	{
       
  1261 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1262 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1263 	}
       
  1264 
       
  1265 	gp_data.reset_header(0u);
       
  1266 
       
  1267 	// Note the reserved field includes the notificatio code in network order.
       
  1268 	gp_data.set_reserved(static_cast<u16_t>(notification_code));
       
  1269 
       
  1270 	gp_data.set_data_length(0u);
       
  1271 
       
  1272 	status = eap_status_ok;
       
  1273 
       
  1274 	gp_data.set_current_payload(aka_payload_AT_NOTIFICATION);
       
  1275 
       
  1276 	update_payload_indexes(
       
  1277 		aka_buffer_length,
       
  1278 		eap_header_size,
       
  1279 		gp_data.get_header_length()+gp_data.get_data_length(),
       
  1280 		aka_data_offset,
       
  1281 		aka_data_free,
       
  1282 		packet_buffer_offset,
       
  1283 		packet_buffer_free);
       
  1284 
       
  1285 	EAP_AKA_TRACE_PAYLOAD("Payload added", &gp_data);
       
  1286 
       
  1287 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1288 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1289 }
       
  1290 
       
  1291 //--------------------------------------------------
       
  1292 
       
  1293 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::add_client_error_payload(
       
  1294 	aka_header_c * const aka,
       
  1295 	const u32_t aka_buffer_length,
       
  1296 	const u32_t eap_header_size,
       
  1297 	u32_t * const aka_data_offset,
       
  1298 	u32_t * const aka_data_free,
       
  1299 	u32_t * const packet_buffer_free,
       
  1300 	u32_t * const packet_buffer_offset,
       
  1301 	const eap_aka_client_error_code_e client_error_code)
       
  1302 {
       
  1303 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1304 
       
  1305 	eap_status_e status = eap_status_process_general_error;
       
  1306 
       
  1307 	aka_payload_AT_header_c gp_data(
       
  1308 		m_am_tools,
       
  1309 		aka->get_data_offset(
       
  1310 			*aka_data_offset, 
       
  1311 			*aka_data_free),
       
  1312 		*aka_data_free);
       
  1313 
       
  1314 	if (gp_data.get_is_valid() == false)
       
  1315 	{
       
  1316 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1317 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1318 	}
       
  1319 
       
  1320 	gp_data.reset_header(0u);
       
  1321 
       
  1322 	// Note the reserved field includes the client error code in network order.
       
  1323 	// This must be less or equal to the length field.
       
  1324 	gp_data.set_reserved(static_cast<u16_t>(client_error_code));
       
  1325 
       
  1326 	gp_data.set_data_length(0u);
       
  1327 
       
  1328 	status = eap_status_ok;
       
  1329 
       
  1330 	gp_data.set_current_payload(aka_payload_AT_CLIENT_ERROR_CODE);
       
  1331 
       
  1332 	update_payload_indexes(
       
  1333 		aka_buffer_length,
       
  1334 		eap_header_size,
       
  1335 		gp_data.get_header_length()+gp_data.get_data_length(),
       
  1336 		aka_data_offset,
       
  1337 		aka_data_free,
       
  1338 		packet_buffer_offset,
       
  1339 		packet_buffer_free);
       
  1340 
       
  1341 	EAP_AKA_TRACE_PAYLOAD("Payload added", &gp_data);
       
  1342 
       
  1343 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1344 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1345 }
       
  1346 
       
  1347 //--------------------------------------------------
       
  1348 
       
  1349 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::add_counter_payload(
       
  1350 	aka_header_c * const aka,
       
  1351 	const u32_t aka_buffer_length,
       
  1352 	const u32_t eap_header_size,
       
  1353 	u32_t * const aka_data_offset,
       
  1354 	u32_t * const aka_data_free,
       
  1355 	u32_t * const packet_buffer_free,
       
  1356 	u32_t * const packet_buffer_offset,
       
  1357 	u16_t counter)
       
  1358 {
       
  1359 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1360 
       
  1361 	eap_status_e status = eap_status_process_general_error;
       
  1362 
       
  1363 	aka_payload_AT_header_c gp_data(
       
  1364 		m_am_tools,
       
  1365 		aka->get_data_offset(
       
  1366 			*aka_data_offset, 
       
  1367 			*aka_data_free),
       
  1368 		*aka_data_free);
       
  1369 
       
  1370 	if (gp_data.get_is_valid() == false)
       
  1371 	{
       
  1372 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1373 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1374 	}
       
  1375 
       
  1376 	gp_data.reset_header(0u);
       
  1377 
       
  1378 	// Note the reserved field includes the counter value in network order.
       
  1379 	gp_data.set_reserved(counter);
       
  1380 
       
  1381 	gp_data.set_data_length(0u);
       
  1382 
       
  1383 	status = eap_status_ok;
       
  1384 
       
  1385 	gp_data.set_current_payload(aka_payload_AT_COUNTER);
       
  1386 
       
  1387 	update_payload_indexes(
       
  1388 		aka_buffer_length,
       
  1389 		eap_header_size,
       
  1390 		gp_data.get_header_length()+gp_data.get_data_length(),
       
  1391 		aka_data_offset,
       
  1392 		aka_data_free,
       
  1393 		packet_buffer_offset,
       
  1394 		packet_buffer_free);
       
  1395 
       
  1396 	EAP_AKA_TRACE_PAYLOAD("Payload added", &gp_data);
       
  1397 
       
  1398 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1399 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1400 }
       
  1401 
       
  1402 //--------------------------------------------------
       
  1403 
       
  1404 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::add_simple_payload(
       
  1405 	aka_header_c * const aka,
       
  1406 	const u32_t aka_buffer_length,
       
  1407 	const u32_t eap_header_size,
       
  1408 	u32_t * const aka_data_offset,
       
  1409 	u32_t * const aka_data_free,
       
  1410 	u32_t * const packet_buffer_free,
       
  1411 	u32_t * const packet_buffer_offset,
       
  1412 	const aka_payload_AT_type_e data_payload_type)
       
  1413 {
       
  1414 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1415 
       
  1416 	eap_status_e status = eap_status_process_general_error;
       
  1417 
       
  1418 	aka_payload_AT_header_c gp_data(
       
  1419 		m_am_tools,
       
  1420 		aka->get_data_offset(
       
  1421 			*aka_data_offset, 
       
  1422 			*aka_data_free),
       
  1423 		*aka_data_free);
       
  1424 
       
  1425 	if (gp_data.get_is_valid() == false)
       
  1426 	{
       
  1427 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1428 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1429 	}
       
  1430 
       
  1431 	gp_data.reset_header(0u);
       
  1432 
       
  1433 	gp_data.set_reserved(0u);
       
  1434 
       
  1435 	gp_data.set_data_length(0u);
       
  1436 
       
  1437 	status = eap_status_ok;
       
  1438 
       
  1439 	gp_data.set_current_payload(data_payload_type);
       
  1440 
       
  1441 	update_payload_indexes(
       
  1442 		aka_buffer_length,
       
  1443 		eap_header_size,
       
  1444 		gp_data.get_header_length()+gp_data.get_data_length(),
       
  1445 		aka_data_offset,
       
  1446 		aka_data_free,
       
  1447 		packet_buffer_offset,
       
  1448 		packet_buffer_free);
       
  1449 
       
  1450 	EAP_AKA_TRACE_PAYLOAD("Payload added", &gp_data);
       
  1451 
       
  1452 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1453 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1454 }
       
  1455 
       
  1456 //--------------------------------------------------
       
  1457 
       
  1458 //
       
  1459 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::parse_generic_payload(
       
  1460 	const aka_payload_AT_type_e current_payload,
       
  1461 	const aka_payload_AT_header_c * const payload,
       
  1462 	aka_payloads_c * const p_aka_payloads,
       
  1463 	const aka_subtype_e /*subtype*/)
       
  1464 {
       
  1465 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1466 
       
  1467 	EAP_AKA_TRACE_PAYLOAD("Parsing payload", payload);
       
  1468 
       
  1469 	if ((payload->get_payload_length() % static_cast<u16_t>(AKA_PAYLOAD_LENGTH_ALIGN)) != 0)
       
  1470 	{
       
  1471 		EAP_TRACE_DEBUG(
       
  1472 			m_am_tools,
       
  1473 			TRACE_FLAGS_AKA_ERROR,
       
  1474 			(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1475 			 EAPL("current payload 0x%04x=%s, length 0x%04x not aligned to 0x%04x.\n"),
       
  1476 			payload, current_payload, payload->get_payload_AT_string(),
       
  1477 			payload->get_payload_length(), AKA_PAYLOAD_LENGTH_ALIGN));
       
  1478 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1479 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);		
       
  1480 	}
       
  1481 
       
  1482 	eap_status_e status(eap_status_process_general_error);
       
  1483 
       
  1484 
       
  1485 	status = p_aka_payloads->get_all_payloads()->add_data(
       
  1486 		&current_payload,
       
  1487 		sizeof(current_payload));
       
  1488 	if (status != eap_status_ok)
       
  1489 	{
       
  1490 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1491 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1492 	}
       
  1493 
       
  1494 
       
  1495 	if (current_payload == aka_payload_AT_NONCE_S)
       
  1496 	{
       
  1497 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1498 		// |AT_NONCE_S     | Length = 5    |           Reserved            |
       
  1499 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1500 		// |                                                               |
       
  1501 		// |                           NONCE_S                             |
       
  1502 		// |                                                               |
       
  1503 		// |                                                               |
       
  1504 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1505 		if (payload->get_reserved() != 0u)
       
  1506 		{
       
  1507 			EAP_TRACE_DEBUG(
       
  1508 				m_am_tools, 
       
  1509 				TRACE_FLAGS_AKA_ERROR, 
       
  1510 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1511 				 EAPL("current payload 0x%04x=%s, length 0x%04x, reserved field incorrect 0x%04x.\n"),
       
  1512 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), payload->get_reserved()));
       
  1513 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1514 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1515 		}
       
  1516 
       
  1517 		if (payload->get_data_length() != EAP_TYPE_AKA_NONCE_MT_SIZE)
       
  1518 		{
       
  1519 			EAP_TRACE_DEBUG(
       
  1520 				m_am_tools, 
       
  1521 				TRACE_FLAGS_AKA_ERROR, 
       
  1522 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1523 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data length incorrect 0x%04x.\n"),
       
  1524 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), payload->get_data_length()));
       
  1525 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1526 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1527 		}
       
  1528 
       
  1529 		u8_t * buffer
       
  1530 			= static_cast<u8_t *>(payload->get_data(EAP_TYPE_AKA_NONCE_MT_SIZE));
       
  1531 
       
  1532 		if (buffer == 0)
       
  1533 		{
       
  1534 			EAP_TRACE_DEBUG(
       
  1535 				m_am_tools, 
       
  1536 				TRACE_FLAGS_AKA_ERROR, 
       
  1537 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1538 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data buffer incorrect.\n"),
       
  1539 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length()));
       
  1540 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1541 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1542 		}
       
  1543 
       
  1544 		// Note here we get a reference to the data bytes of the received packet.
       
  1545 		status = p_aka_payloads->get_NONCE_S()->set_buffer(
       
  1546 			payload, buffer, payload->get_data_length(), false, false);
       
  1547 
       
  1548 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1549 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1550 	}
       
  1551 	else if (current_payload == aka_payload_AT_RAND)
       
  1552 	{
       
  1553 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1554 		// | AT_RAND       | Length        |           Reserved            |
       
  1555 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1556 		// |                              RAND ...
       
  1557 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1558 		if (payload->get_reserved() != 0u)
       
  1559 		{
       
  1560 			EAP_TRACE_DEBUG(
       
  1561 				m_am_tools, 
       
  1562 				TRACE_FLAGS_AKA_ERROR, 
       
  1563 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1564 				 EAPL("current payload 0x%04x=%s, length 0x%04x, reserved field incorrect 0x%04x.\n"),
       
  1565 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), payload->get_reserved()));
       
  1566 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1567 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1568 		}
       
  1569 
       
  1570 		if (payload->get_data_length() < EAP_TYPE_AKA_MINIMUM_RAND_LENGTH)
       
  1571 		{
       
  1572 			EAP_TRACE_DEBUG(
       
  1573 				m_am_tools, 
       
  1574 				TRACE_FLAGS_AKA_ERROR, 
       
  1575 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1576 				 EAPL("current payload 0x%04x=%s, length 0x%04x. Too few RAND bytes 0x%04x, 0x%04x bytes required.\n"),
       
  1577 				payload,
       
  1578 				current_payload,
       
  1579 				payload->get_payload_AT_string(),
       
  1580 				payload->get_payload_length(),
       
  1581 				payload->get_data_length(),
       
  1582 				EAP_TYPE_AKA_MINIMUM_RAND_LENGTH));
       
  1583 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1584 			return EAP_STATUS_RETURN(m_am_tools, eap_status_not_enough_challenges);
       
  1585 		}
       
  1586 
       
  1587 		u8_t * n_rands = static_cast<u8_t *>(payload->get_data(payload->get_data_length()));
       
  1588 		if (n_rands == 0)
       
  1589 		{
       
  1590 			EAP_TRACE_DEBUG(
       
  1591 				m_am_tools, 
       
  1592 				TRACE_FLAGS_AKA_ERROR, 
       
  1593 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1594 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data buffer incorrect.\n"),
       
  1595 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length()));
       
  1596 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1597 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1598 		}
       
  1599 
       
  1600 		status = p_aka_payloads->get_RAND()->set_buffer(
       
  1601 			payload, n_rands, payload->get_data_length(), false, false);
       
  1602 
       
  1603 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1604 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1605 	}
       
  1606 	else if (current_payload == aka_payload_AT_AUTN)
       
  1607 	{
       
  1608 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1609 		// | AT_AUTN       | Length        |           Reserved            |
       
  1610 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1611 		// |                              AUTN ...
       
  1612 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1613 		if (payload->get_reserved() != 0u)
       
  1614 		{
       
  1615 			EAP_TRACE_DEBUG(
       
  1616 				m_am_tools, 
       
  1617 				TRACE_FLAGS_AKA_ERROR, 
       
  1618 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1619 				 EAPL("current payload 0x%04x=%s, length 0x%04x, reserved field incorrect 0x%04x.\n"),
       
  1620 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), payload->get_reserved()));
       
  1621 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1622 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1623 		}
       
  1624 
       
  1625 		if (payload->get_data_length() < EAP_TYPE_AKA_MINIMUM_AUTN_LENGTH)
       
  1626 		{
       
  1627 			EAP_TRACE_DEBUG(
       
  1628 				m_am_tools, 
       
  1629 				TRACE_FLAGS_AKA_ERROR, 
       
  1630 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1631 				 EAPL("current payload 0x%04x=%s, length 0x%04x. Too few AUTN bytes 0x%04x, 0x%04x bytes required.\n"),
       
  1632 				payload,
       
  1633 				current_payload,
       
  1634 				payload->get_payload_AT_string(),
       
  1635 				payload->get_payload_length(),
       
  1636 				payload->get_data_length(),
       
  1637 				EAP_TYPE_AKA_MINIMUM_AUTN_LENGTH));
       
  1638 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1639 			return EAP_STATUS_RETURN(m_am_tools, eap_status_not_enough_challenges);
       
  1640 		}
       
  1641 
       
  1642 		u8_t * AUTN = static_cast<u8_t *>(payload->get_data(payload->get_data_length()));
       
  1643 		if (AUTN == 0)
       
  1644 		{
       
  1645 			EAP_TRACE_DEBUG(
       
  1646 				m_am_tools, 
       
  1647 				TRACE_FLAGS_AKA_ERROR, 
       
  1648 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1649 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data buffer incorrect.\n"),
       
  1650 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length()));
       
  1651 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1652 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1653 		}
       
  1654 
       
  1655 		status = p_aka_payloads->get_AUTN()->set_buffer(
       
  1656 			payload, AUTN, payload->get_data_length(), false, false);
       
  1657 
       
  1658 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1659 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1660 	}
       
  1661 	else if (current_payload == aka_payload_AT_AUTS)
       
  1662 	{
       
  1663 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1664 		// | AT_AUTS       | Length        |           AUTS ...            |
       
  1665 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1666 		// |                          ... AUTS ...
       
  1667 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1668 
       
  1669 		// NOTE first 2 bytes are in reserved field.
       
  1670 		if (payload->get_data_length()+2ul != EAP_TYPE_AKA_AUTS_LENGTH)
       
  1671 		{
       
  1672 			EAP_TRACE_DEBUG(
       
  1673 				m_am_tools, 
       
  1674 				TRACE_FLAGS_AKA_ERROR, 
       
  1675 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1676 				 EAPL("current payload 0x%04x=%s, length 0x%04x. Too few AUTN bytes 0x%04x, 0x%04x bytes required.\n"),
       
  1677 				payload,
       
  1678 				current_payload,
       
  1679 				payload->get_payload_AT_string(),
       
  1680 				payload->get_payload_length(),
       
  1681 				payload->get_data_length(),
       
  1682 				EAP_TYPE_AKA_MINIMUM_AUTN_LENGTH));
       
  1683 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1684 			return EAP_STATUS_RETURN(m_am_tools, eap_status_not_enough_challenges);
       
  1685 		}
       
  1686 
       
  1687 		u8_t * AUTS = static_cast<u8_t *>(payload->get_reserved_pointer(payload->get_data_length()));
       
  1688 		if (AUTS == 0)
       
  1689 		{
       
  1690 			EAP_TRACE_DEBUG(
       
  1691 				m_am_tools, 
       
  1692 				TRACE_FLAGS_AKA_ERROR, 
       
  1693 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1694 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data buffer incorrect.\n"),
       
  1695 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length()));
       
  1696 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1697 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1698 		}
       
  1699 
       
  1700 		// NOTE first 2 bytes are in reserved field.
       
  1701 		status = p_aka_payloads->get_AUTS()->set_buffer(
       
  1702 			payload, AUTS, payload->get_data_length()+2ul, false, false);
       
  1703 
       
  1704 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1705 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1706 	}
       
  1707 	else if (current_payload == aka_payload_AT_RES)
       
  1708 	{
       
  1709 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1710 		// | AT_RES        | Length        |       RES Length in bits      |
       
  1711 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1712 		// |                              RES ...
       
  1713 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1714 
       
  1715 		// Reserved field includes the length of RES in bits. It is always multiple of 8 bits.
       
  1716 		u32_t RES_length = payload->get_reserved() / 8ul;
       
  1717 
       
  1718 		if (RES_length == 0u
       
  1719 			|| RES_length > payload->get_data_length())
       
  1720 		{
       
  1721 			EAP_TRACE_DEBUG(
       
  1722 				m_am_tools, 
       
  1723 				TRACE_FLAGS_AKA_ERROR, 
       
  1724 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1725 				 EAPL("current payload 0x%04x=%s, length 0x%04x, reserved field incorrect 0x%04x.\n"),
       
  1726 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), payload->get_reserved()));
       
  1727 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1728 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1729 		}
       
  1730 
       
  1731 		if (payload->get_data_length() < EAP_TYPE_AKA_MINIMUM_RES_LENGTH)
       
  1732 		{
       
  1733 			EAP_TRACE_DEBUG(
       
  1734 				m_am_tools, 
       
  1735 				TRACE_FLAGS_AKA_ERROR, 
       
  1736 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1737 				 EAPL("current payload 0x%04x=%s, length 0x%04x. Too few RES bytes 0x%04x, 0x%04x bytes required.\n"),
       
  1738 				payload,
       
  1739 				current_payload,
       
  1740 				payload->get_payload_AT_string(),
       
  1741 				payload->get_payload_length(),
       
  1742 				payload->get_data_length(),
       
  1743 				EAP_TYPE_AKA_MINIMUM_RES_LENGTH));
       
  1744 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1745 			return EAP_STATUS_RETURN(m_am_tools, eap_status_not_enough_challenges);
       
  1746 		}
       
  1747 
       
  1748 		u8_t * RES = static_cast<u8_t *>(payload->get_data(RES_length));
       
  1749 		if (RES == 0)
       
  1750 		{
       
  1751 			EAP_TRACE_DEBUG(
       
  1752 				m_am_tools, 
       
  1753 				TRACE_FLAGS_AKA_ERROR, 
       
  1754 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1755 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data buffer incorrect.\n"),
       
  1756 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length()));
       
  1757 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1758 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1759 		}
       
  1760 
       
  1761 		status = p_aka_payloads->get_RES()->set_buffer(
       
  1762 			payload, RES, RES_length, false, false);
       
  1763 
       
  1764 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1765 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1766 	}
       
  1767 	else if (current_payload == aka_payload_AT_PADDING)
       
  1768 	{
       
  1769 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1770 		// |  AT_PADDING   | Length        | Padding...                    |
       
  1771 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
       
  1772 		// |                                                               |
       
  1773 		// |                                                               |
       
  1774 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1775 
       
  1776 		u8_t * padding = 0;
       
  1777 
       
  1778 		// Note two first octets of padding are the reserved field. It must be zero.
       
  1779 		if (payload->get_reserved() != 0u)
       
  1780 		{
       
  1781 			EAP_TRACE_DEBUG(
       
  1782 				m_am_tools, 
       
  1783 				TRACE_FLAGS_AKA_ERROR, 
       
  1784 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1785 				 EAPL("current payload 0x%04x=%s, length 0x%04x, reserved field incorrect 0x%04x.\n"),
       
  1786 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), payload->get_reserved()));
       
  1787 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1788 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1789 		}
       
  1790 
       
  1791 		// NOTE padding data length could be zero.
       
  1792 		if (payload->get_data_length() != 0u)
       
  1793 		{
       
  1794 			padding = static_cast<u8_t *>(payload->get_data(payload->get_data_length()));
       
  1795 		}
       
  1796 
       
  1797 		status = p_aka_payloads->get_padding_payload()->set_buffer(
       
  1798 			payload, padding, payload->get_data_length(), false, false);
       
  1799 
       
  1800 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1801 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1802 	}
       
  1803 	else if (current_payload == aka_payload_AT_NEXT_PSEUDONYM)
       
  1804 	{
       
  1805 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1806 		// | AT_NEXT...YM  | Length        | Actual Pseudonym Length       |
       
  1807 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1808 		// |                                                               |
       
  1809 		// |                           Pseudonym                           |
       
  1810 		// |                                                               |
       
  1811 		// |                                                               |
       
  1812 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1813 
       
  1814 		// Note the reserved field includes the actual length of pseudonym.
       
  1815 		// This must be less or equal to the length field.
       
  1816 		u16_t pseudonym_length = payload->get_reserved();
       
  1817 		if (pseudonym_length == 0u
       
  1818 			|| pseudonym_length > payload->get_data_length())
       
  1819 		{
       
  1820 			EAP_TRACE_DEBUG(
       
  1821 				m_am_tools, 
       
  1822 				TRACE_FLAGS_AKA_ERROR, 
       
  1823 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1824 				 EAPL("current payload 0x%04x=%s, length 0x%04x, pseudonym length field incorrect 0x%04x.\n"),
       
  1825 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), payload->get_reserved()));
       
  1826 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1827 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1828 		}
       
  1829 
       
  1830 		u8_t * pseudonym = static_cast<u8_t *>(payload->get_data(pseudonym_length));
       
  1831 		if (pseudonym == 0)
       
  1832 		{
       
  1833 			EAP_TRACE_DEBUG(
       
  1834 				m_am_tools,
       
  1835 				TRACE_FLAGS_AKA_ERROR,
       
  1836 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): current payload 0x%04x=%s, length 0x%04x, data buffer incorrect.\n"),
       
  1837 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length()));
       
  1838 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1839 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1840 		}
       
  1841 
       
  1842 		status = p_aka_payloads->get_NEXT_PSEUDONYM()->set_buffer(
       
  1843 			payload, pseudonym, pseudonym_length, false, false);
       
  1844 
       
  1845 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1846 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1847 	}
       
  1848 	else if (current_payload == aka_payload_AT_NEXT_REAUTH_ID)
       
  1849 	{
       
  1850 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1851 		// | AT_NEXT...ID  | Length        | Actual Identity Length        |
       
  1852 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1853 		// |                                                               |
       
  1854 		// |                  Reauthentication identity                    |
       
  1855 		// |                                                               |
       
  1856 		// |                                                               |
       
  1857 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1858 
       
  1859 		// Note the reserved field includes the actual length of reauthentication identity.
       
  1860 		// This must be less or equal to the length field.
       
  1861 		u16_t next_reauth_id_length = payload->get_reserved();
       
  1862 		if (next_reauth_id_length == 0u
       
  1863 			|| next_reauth_id_length > payload->get_data_length())
       
  1864 		{
       
  1865 			EAP_TRACE_DEBUG(
       
  1866 				m_am_tools, 
       
  1867 				TRACE_FLAGS_AKA_ERROR, 
       
  1868 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1869 				 EAPL("current payload 0x%04x=%s, length 0x%04x, reauthentication identity length field incorrect 0x%04x.\n"),
       
  1870 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), payload->get_reserved()));
       
  1871 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1872 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1873 		}
       
  1874 
       
  1875 		u8_t * next_reauth_id = static_cast<u8_t *>(payload->get_data(next_reauth_id_length));
       
  1876 		if (next_reauth_id == 0)
       
  1877 		{
       
  1878 			EAP_TRACE_DEBUG(
       
  1879 				m_am_tools, 
       
  1880 				TRACE_FLAGS_AKA_ERROR, 
       
  1881 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1882 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data buffer incorrect.\n"),
       
  1883 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length()));
       
  1884 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1885 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1886 		}
       
  1887 
       
  1888 		status = p_aka_payloads->get_NEXT_REAUTH_ID()->set_buffer(
       
  1889 			payload, next_reauth_id, next_reauth_id_length, false, false);
       
  1890 
       
  1891 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1892 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1893 	}
       
  1894 	else if (current_payload == aka_payload_AT_RESULT_IND)
       
  1895 	{
       
  1896 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1897 		// | AT_RESULT_IND | Length = 1    |      Reserved                 |
       
  1898 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1899 
       
  1900 		if (payload->get_data_length() != EAP_AKA_PAYLOAD_ZERO_DATA_LENGTH)
       
  1901 		{
       
  1902 			EAP_TRACE_DEBUG(
       
  1903 				m_am_tools, 
       
  1904 				TRACE_FLAGS_AKA_ERROR, 
       
  1905 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1906 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data length incorrect 0x%04x, should be 0x%04x.\n"),
       
  1907 				 payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), 
       
  1908 				 payload->get_data_length(), EAP_AKA_PAYLOAD_ZERO_DATA_LENGTH));
       
  1909 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1910 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1911 		}
       
  1912 
       
  1913 		EAP_TRACE_DEBUG(
       
  1914 			m_am_tools, 
       
  1915 			TRACE_FLAGS_DEFAULT, 
       
  1916 			(EAPL("eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1917 			 EAPL("current payload 0x%04x=%s, length 0x%04x, reserved %d.\n"),
       
  1918 			payload,
       
  1919 			current_payload,
       
  1920 			payload->get_payload_AT_string(),
       
  1921 			payload->get_payload_length(),
       
  1922 			payload->get_reserved()));
       
  1923 
       
  1924 		status = p_aka_payloads->get_RESULT_IND()->set_buffer(
       
  1925 			payload, 0, 0u, false, false);
       
  1926 
       
  1927 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1928 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1929 	}
       
  1930 	else if (current_payload == aka_payload_AT_NOTIFICATION)
       
  1931 	{
       
  1932 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1933 		// |AT_NOTIFICATION| Length = 1    |      Notification Code        |
       
  1934 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1935 
       
  1936 		if (payload->get_data_length() != EAP_AKA_PAYLOAD_ZERO_DATA_LENGTH)
       
  1937 		{
       
  1938 			EAP_TRACE_DEBUG(
       
  1939 				m_am_tools, 
       
  1940 				TRACE_FLAGS_AKA_ERROR, 
       
  1941 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1942 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data length incorrect 0x%04x, should be 0x%04x.\n"),
       
  1943 				 payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), 
       
  1944 				 payload->get_data_length(), EAP_AKA_PAYLOAD_ZERO_DATA_LENGTH));
       
  1945 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1946 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1947 		}
       
  1948 
       
  1949 		// Note the reserved field includes the notification code (client error code).
       
  1950 		eap_aka_notification_codes_e notification_code = static_cast<eap_aka_notification_codes_e>(payload->get_reserved());
       
  1951 		EAP_UNREFERENCED_PARAMETER(notification_code);
       
  1952 
       
  1953 		EAP_TRACE_DEBUG(
       
  1954 			m_am_tools, 
       
  1955 			TRACE_FLAGS_DEFAULT, 
       
  1956 			(EAPL("eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1957 			 EAPL("current payload 0x%04x=%s, length 0x%04x, notification code %d.\n"),
       
  1958 			payload,
       
  1959 			current_payload,
       
  1960 			payload->get_payload_AT_string(),
       
  1961 			payload->get_payload_length(),
       
  1962 			payload->get_reserved()));
       
  1963 
       
  1964 		status = p_aka_payloads->get_NOTIFICATION()->set_buffer(
       
  1965 			payload, 0, 0u, false, false);
       
  1966 
       
  1967 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1968 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1969 	}
       
  1970 	else if (current_payload == aka_payload_AT_COUNTER)
       
  1971 	{
       
  1972 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1973 		// |AT_COUNTER     | Length = 1    |      Counter                  |
       
  1974 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  1975 
       
  1976 		if (payload->get_data_length() != EAP_AKA_PAYLOAD_ZERO_DATA_LENGTH)
       
  1977 		{
       
  1978 			EAP_TRACE_DEBUG(
       
  1979 				m_am_tools, 
       
  1980 				TRACE_FLAGS_AKA_ERROR, 
       
  1981 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1982 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data length incorrect 0x%04x, should be 0x%04x.\n"),
       
  1983 				 payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), 
       
  1984 				 payload->get_data_length(), EAP_AKA_PAYLOAD_ZERO_DATA_LENGTH));
       
  1985 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1986 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1987 		}
       
  1988 
       
  1989 		EAP_TRACE_DEBUG(
       
  1990 			m_am_tools, 
       
  1991 			TRACE_FLAGS_DEFAULT, 
       
  1992 			(EAPL("eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  1993 			 EAPL("current payload 0x%04x=%s, length 0x%04x, counter %d.\n"),
       
  1994 			payload,
       
  1995 			current_payload,
       
  1996 			payload->get_payload_AT_string(),
       
  1997 			payload->get_payload_length(),
       
  1998 			payload->get_reserved()));
       
  1999 
       
  2000 		status = p_aka_payloads->get_COUNTER()->set_buffer(
       
  2001 			payload, 0, 0u, false, false);
       
  2002 
       
  2003 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2004 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2005 	}
       
  2006 	else if (current_payload == aka_payload_AT_COUNTER_TOO_SMALL)
       
  2007 	{
       
  2008 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2009 		// |AT_COUNTER_TOO.| Length = 1    |           Reserved            |
       
  2010 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2011 
       
  2012 		if (payload->get_data_length() != EAP_AKA_PAYLOAD_ZERO_DATA_LENGTH)
       
  2013 		{
       
  2014 			EAP_TRACE_DEBUG(
       
  2015 				m_am_tools, 
       
  2016 				TRACE_FLAGS_AKA_ERROR, 
       
  2017 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2018 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data length incorrect 0x%04x, should be 0x%04x.\n"),
       
  2019 				 payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), 
       
  2020 				 payload->get_data_length(), EAP_AKA_PAYLOAD_ZERO_DATA_LENGTH));
       
  2021 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2022 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2023 		}
       
  2024 
       
  2025 		EAP_TRACE_DEBUG(
       
  2026 			m_am_tools, 
       
  2027 			TRACE_FLAGS_DEFAULT, 
       
  2028 			(EAPL("eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2029 			 EAPL("current payload 0x%04x=%s, length 0x%04x, reserved %d.\n"),
       
  2030 			payload,
       
  2031 			current_payload,
       
  2032 			payload->get_payload_AT_string(),
       
  2033 			payload->get_payload_length(),
       
  2034 			payload->get_reserved()));
       
  2035 
       
  2036 		status = p_aka_payloads->get_COUNTER_TOO_SMALL()->set_buffer(
       
  2037 			payload, 0, 0u, false, false);
       
  2038 
       
  2039 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2040 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2041 	}
       
  2042 	else if (current_payload == aka_payload_AT_MAC)
       
  2043 	{
       
  2044 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2045 		// | AT_MAC        | Length = 5    |           Reserved            |
       
  2046 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2047 		// |                                                               |
       
  2048 		// |                           MAC                                 |
       
  2049 		// |                                                               |
       
  2050 		// |                                                               |
       
  2051 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2052 		if (payload->get_reserved() != 0u)
       
  2053 		{
       
  2054 			EAP_TRACE_DEBUG(
       
  2055 				m_am_tools, 
       
  2056 				TRACE_FLAGS_AKA_ERROR, 
       
  2057 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2058 				 EAPL("current payload 0x%04x=%s, length 0x%04x, reserved field incorrect 0x%04x.\n"),
       
  2059 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), payload->get_reserved()));
       
  2060 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2061 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2062 		}
       
  2063 
       
  2064 		if (payload->get_data_length() != EAP_TYPE_AKA_MAC_SIZE)
       
  2065 		{
       
  2066 			EAP_TRACE_DEBUG(
       
  2067 				m_am_tools, 
       
  2068 				TRACE_FLAGS_AKA_ERROR, 
       
  2069 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2070 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data length incorrect 0x%04x.\n"),
       
  2071 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), payload->get_data_length()));
       
  2072 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2073 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2074 		}
       
  2075 
       
  2076 		u8_t * buffer
       
  2077 			= static_cast<u8_t *>(payload->get_data(EAP_TYPE_AKA_MAC_SIZE));
       
  2078 
       
  2079 		if (buffer == 0)
       
  2080 		{
       
  2081 			EAP_TRACE_DEBUG(
       
  2082 				m_am_tools, 
       
  2083 				TRACE_FLAGS_AKA_ERROR, 
       
  2084 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2085 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data buffer incorrect.\n"),
       
  2086 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length()));
       
  2087 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2088 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2089 		}
       
  2090 
       
  2091 		status = p_aka_payloads->get_MAC()->set_buffer(
       
  2092 			payload, buffer, payload->get_data_length(), false, false);
       
  2093 
       
  2094 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2095 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2096 	}
       
  2097 	else if (current_payload == aka_payload_AT_IV)
       
  2098 	{
       
  2099 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2100 		// | AT_IV         | Length = 5    |           Reserved            |
       
  2101 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2102 		// |                                                               |
       
  2103 		// |                 Initialization Vector (optional)              |
       
  2104 		// |                                                               |
       
  2105 		// |                                                               |
       
  2106 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2107 
       
  2108 		if (payload->get_reserved() != 0u)
       
  2109 		{
       
  2110 			EAP_TRACE_DEBUG(
       
  2111 				m_am_tools, 
       
  2112 				TRACE_FLAGS_AKA_ERROR, 
       
  2113 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2114 				 EAPL("current payload 0x%04x=%s, length 0x%04x, reserved field incorrect 0x%04x.\n"),
       
  2115 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), payload->get_reserved()));
       
  2116 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2117 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2118 		}
       
  2119 
       
  2120 		crypto_aes_c aes(m_am_tools);
       
  2121 
       
  2122 		if (aes.get_is_valid() == false)
       
  2123 		{
       
  2124 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2125 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2126 		}
       
  2127 
       
  2128 		if (payload->get_data_length() != aes.get_block_size())
       
  2129 		{
       
  2130 			EAP_TRACE_DEBUG(
       
  2131 				m_am_tools, 
       
  2132 				TRACE_FLAGS_AKA_ERROR, 
       
  2133 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2134 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data length incorrect 0x%04x.\n"),
       
  2135 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), payload->get_data_length()));
       
  2136 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2137 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2138 		}
       
  2139 
       
  2140 		u8_t * buffer
       
  2141 			= static_cast<u8_t *>(payload->get_data(payload->get_data_length()));
       
  2142 
       
  2143 		if (buffer == 0)
       
  2144 		{
       
  2145 			EAP_TRACE_DEBUG(
       
  2146 				m_am_tools, 
       
  2147 				TRACE_FLAGS_AKA_ERROR, 
       
  2148 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2149 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data buffer incorrect.\n"),
       
  2150 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length()));
       
  2151 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2152 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2153 		}
       
  2154 
       
  2155 		// Note here we get a reference to the data bytes of the received packet.
       
  2156 		status = p_aka_payloads->get_IV()->set_buffer(
       
  2157 			payload, buffer, payload->get_data_length(), false, false);
       
  2158 
       
  2159 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2160 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2161 	}
       
  2162 	else if (current_payload == aka_payload_AT_ENCR_DATA)
       
  2163 	{
       
  2164 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2165 		// | AT_ENCR_DATA  | Length        |           Reserved            |
       
  2166 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2167 		// |                                                               |
       
  2168 		// |                    Encrypted Data (optional)                  |
       
  2169 		// |                                                               |
       
  2170 		// |                                                               |
       
  2171 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2172 		if (payload->get_reserved() != 0u)
       
  2173 		{
       
  2174 			EAP_TRACE_DEBUG(
       
  2175 				m_am_tools, 
       
  2176 				TRACE_FLAGS_AKA_ERROR, 
       
  2177 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2178 				 EAPL("current payload 0x%04x=%s, length 0x%04x, reserved field incorrect 0x%04x.\n"),
       
  2179 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), payload->get_reserved()));
       
  2180 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2181 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2182 		}
       
  2183 
       
  2184 		if (payload->get_data_length() < 8u)
       
  2185 		{
       
  2186 			EAP_TRACE_DEBUG(
       
  2187 				m_am_tools, 
       
  2188 				TRACE_FLAGS_AKA_ERROR, 
       
  2189 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2190 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data length incorrect 0x%04x.\n"),
       
  2191 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), payload->get_data_length()));
       
  2192 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2193 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2194 		}
       
  2195 
       
  2196 		u8_t * buffer
       
  2197 			= static_cast<u8_t *>(payload->get_data(payload->get_data_length()));
       
  2198 
       
  2199 		if (buffer == 0)
       
  2200 		{
       
  2201 			EAP_TRACE_DEBUG(
       
  2202 				m_am_tools, 
       
  2203 				TRACE_FLAGS_AKA_ERROR, 
       
  2204 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2205 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data buffer incorrect.\n"),
       
  2206 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length()));
       
  2207 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2208 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2209 		}
       
  2210 
       
  2211 		status = p_aka_payloads->get_ENCR_DATA()->set_buffer(
       
  2212 			payload, buffer, payload->get_data_length(), false, false);
       
  2213 
       
  2214 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2215 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2216 	}
       
  2217 	else if (current_payload == aka_payload_AT_PERMANENT_ID_REQ)
       
  2218 	{
       
  2219 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2220 		// |AT_PERM..._REQ | Length = 1    |           Reserved            |
       
  2221 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2222 
       
  2223 		if (payload->get_data_length() != EAP_AKA_PAYLOAD_ZERO_DATA_LENGTH)
       
  2224 		{
       
  2225 			EAP_TRACE_DEBUG(
       
  2226 				m_am_tools, 
       
  2227 				TRACE_FLAGS_AKA_ERROR, 
       
  2228 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2229 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data length incorrect 0x%04x, should be 0x%04x.\n"),
       
  2230 				 payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), 
       
  2231 				 payload->get_data_length(), EAP_AKA_PAYLOAD_ZERO_DATA_LENGTH));
       
  2232 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2233 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2234 		}
       
  2235 
       
  2236 		status = p_aka_payloads->get_PERMANENT_ID_REQ()->set_buffer(
       
  2237 			payload, 0, 0, false, false);
       
  2238 
       
  2239 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2240 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2241 	}
       
  2242 	else if (current_payload == aka_payload_AT_FULLAUTH_ID_REQ)
       
  2243 	{
       
  2244 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2245 		// |AT_FULL..._REQ | Length = 1    |           Reserved            |
       
  2246 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2247 
       
  2248 		if (payload->get_data_length() != EAP_AKA_PAYLOAD_ZERO_DATA_LENGTH)
       
  2249 		{
       
  2250 			EAP_TRACE_DEBUG(
       
  2251 				m_am_tools, 
       
  2252 				TRACE_FLAGS_AKA_ERROR, 
       
  2253 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2254 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data length incorrect 0x%04x, should be 0x%04x.\n"),
       
  2255 				 payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), 
       
  2256 				 payload->get_data_length(), EAP_AKA_PAYLOAD_ZERO_DATA_LENGTH));
       
  2257 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2258 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2259 		}
       
  2260 
       
  2261 		status = p_aka_payloads->get_FULLAUTH_ID_REQ()->set_buffer(
       
  2262 			payload, 0, 0, false, false);
       
  2263 
       
  2264 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2265 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2266 	}
       
  2267 	else if (current_payload == aka_payload_AT_ANY_ID_REQ)
       
  2268 	{
       
  2269 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2270 		// |AT_ANY..._REQ  | Length = 1    |           Reserved            |
       
  2271 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2272 
       
  2273 		if (payload->get_data_length() != EAP_AKA_PAYLOAD_ZERO_DATA_LENGTH)
       
  2274 		{
       
  2275 			EAP_TRACE_DEBUG(
       
  2276 				m_am_tools, 
       
  2277 				TRACE_FLAGS_AKA_ERROR, 
       
  2278 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2279 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data length incorrect 0x%04x, should be 0x%04x.\n"),
       
  2280 				 payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), 
       
  2281 				 payload->get_data_length(), EAP_AKA_PAYLOAD_ZERO_DATA_LENGTH));
       
  2282 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2283 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2284 		}
       
  2285 
       
  2286 		status = p_aka_payloads->get_ANY_ID_REQ()->set_buffer(
       
  2287 			payload, 0, 0, false, false);
       
  2288 
       
  2289 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2290 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2291 	}
       
  2292 	else if (current_payload == aka_payload_AT_IDENTITY)
       
  2293 	{
       
  2294 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2295 		// | AT_IDENTITY   | Length        | Actual Identity Length        |
       
  2296 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2297 		// |                                                               |
       
  2298 		// .                 Current Identity (optional)                   .
       
  2299 		// |                                                               |
       
  2300 		// |                                                               |
       
  2301 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2302 		u16_t identity_length = payload->get_reserved();
       
  2303 
       
  2304 		if (payload->get_data_length() == 0
       
  2305 			|| identity_length > payload->get_data_length()
       
  2306 			|| identity_length < 1u)
       
  2307 		{
       
  2308 			EAP_TRACE_DEBUG(
       
  2309 				m_am_tools, 
       
  2310 				TRACE_FLAGS_AKA_ERROR, 
       
  2311 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2312 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data length incorrect 0x%04x, identity_length 0x%04x.\n"),
       
  2313 				 payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), 
       
  2314 				 payload->get_data_length(), identity_length));
       
  2315 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2316 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2317 		}
       
  2318 
       
  2319 		u8_t * identity_data
       
  2320 			= static_cast<u8_t *>(payload->get_data(payload->get_data_length()));
       
  2321 
       
  2322 		if (identity_data == 0)
       
  2323 		{
       
  2324 			EAP_TRACE_DEBUG(
       
  2325 				m_am_tools, 
       
  2326 				TRACE_FLAGS_AKA_ERROR, 
       
  2327 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2328 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data buffer incorrect.\n"),
       
  2329 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length()));
       
  2330 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2331 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2332 		}
       
  2333 
       
  2334 		if (identity_length < payload->get_data_length())
       
  2335 		{
       
  2336 			crypto_aes_c aes(m_am_tools);
       
  2337 			crypto_cbc_c cbc_aes(m_am_tools, &aes, false);
       
  2338 
       
  2339 			if (cbc_aes.get_is_valid() == false)
       
  2340 			{
       
  2341 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2342 				return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2343 			}
       
  2344 
       
  2345 			// Includes padding bytes. Those must be zero.
       
  2346 			eap_status_e status = cbc_aes.check_padding_bytes(
       
  2347 				identity_data+identity_length,
       
  2348 				payload->get_data_length()-identity_length,
       
  2349 				0ul);
       
  2350 			if (status != eap_status_ok)
       
  2351 			{
       
  2352 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2353 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  2354 			}
       
  2355 		}
       
  2356 
       
  2357 		// We assume the prefix byte is included.
       
  2358 		status = p_aka_payloads->get_IDENTITY_payload()->set_buffer(
       
  2359 			payload, identity_data, identity_length, false, false);
       
  2360 
       
  2361 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2362 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2363 	}
       
  2364 	else if (current_payload == aka_payload_AT_CLIENT_ERROR_CODE)
       
  2365 	{
       
  2366 		// The format of the AT_CLIENT_ERROR_CODE attribute is shown below.
       
  2367 
       
  2368 		//  0                   1                   2                   3
       
  2369 		//  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
       
  2370 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2371 		// |AT_CLIENT_ERR..| Length = 1    |     Client Error Code         |
       
  2372 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2373 		// Note the reserved field includes the client error code.
       
  2374 
       
  2375 		if (payload->get_data_length() != EAP_AKA_PAYLOAD_ZERO_DATA_LENGTH)
       
  2376 		{
       
  2377 			EAP_TRACE_DEBUG(
       
  2378 				m_am_tools, 
       
  2379 				TRACE_FLAGS_AKA_ERROR, 
       
  2380 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2381 				 EAPL("current payload 0x%04x=%s, length 0x%04x, data length incorrect 0x%04x, should be 0x%04x.\n"),
       
  2382 				 payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), 
       
  2383 				 payload->get_data_length(), EAP_AKA_PAYLOAD_ZERO_DATA_LENGTH));
       
  2384 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2385 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2386 		}
       
  2387 
       
  2388 		eap_aka_client_error_code_e client_error_code = static_cast<eap_aka_client_error_code_e>(payload->get_reserved());
       
  2389 
       
  2390 		if (client_error_code > eap_aka_client_error_code_maximum_value)
       
  2391 		{
       
  2392 			EAP_TRACE_DEBUG(
       
  2393 				m_am_tools, 
       
  2394 				TRACE_FLAGS_AKA_ERROR, 
       
  2395 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2396 				 EAPL("current payload 0x%04x=%s, length 0x%04x, illegal AKA client error code %d.\n"),
       
  2397 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), client_error_code));
       
  2398 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2399 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2400 		}
       
  2401 
       
  2402 		EAP_TRACE_DEBUG(
       
  2403 			m_am_tools, 
       
  2404 			TRACE_FLAGS_DEFAULT, 
       
  2405 			(EAPL("eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2406 			 EAPL("current payload 0x%04x=%s, length 0x%04x, client_error_code %d.\n"),
       
  2407 			payload,
       
  2408 			current_payload,
       
  2409 			payload->get_payload_AT_string(),
       
  2410 			payload->get_payload_length(),
       
  2411 			client_error_code));
       
  2412 
       
  2413 		status = p_aka_payloads->get_CLIENT_ERROR_CODE()->set_buffer(
       
  2414 			payload, 0, 0u, false, false);
       
  2415 
       
  2416 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2417 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2418 	}
       
  2419 	else if (current_payload == aka_payload_AT_CHECKCODE)
       
  2420 	{
       
  2421 		//  0                   1                   2                   3
       
  2422 		//  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
       
  2423 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2424 		// | AT_CHECKCODE  | Length        |           Reserved            |
       
  2425 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2426 		// |                                                               |
       
  2427 		// |                     Checkcode (0 or 20 bytes)                 |
       
  2428 		// |                                                               |
       
  2429 		// |                                                               |
       
  2430 		// |                                                               |
       
  2431 		// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       
  2432 		if (payload->get_reserved() != 0u)
       
  2433 		{
       
  2434 			EAP_TRACE_DEBUG(
       
  2435 				m_am_tools, 
       
  2436 				TRACE_FLAGS_AKA_ERROR, 
       
  2437 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2438 				 EAPL("current payload 0x%04x=%s, length 0x%04x, reserved field incorrect 0x%04x.\n"),
       
  2439 				payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length(), payload->get_reserved()));
       
  2440 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2441 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2442 		}
       
  2443 
       
  2444 		if (payload->get_data_length() != 0UL
       
  2445 			&& payload->get_data_length() != EAP_TYPE_AKA_MAXIMUM_CHECKCODE_LENGTH)
       
  2446 		{
       
  2447 			EAP_TRACE_DEBUG(
       
  2448 				m_am_tools, 
       
  2449 				TRACE_FLAGS_AKA_ERROR, 
       
  2450 				(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2451 				 EAPL("current payload 0x%04x=%s, length 0x%04x. Illegal CHECKCODE bytes 0x%04x, 0 or 0x%04x bytes required.\n"),
       
  2452 				payload,
       
  2453 				current_payload,
       
  2454 				payload->get_payload_AT_string(),
       
  2455 				payload->get_payload_length(),
       
  2456 				payload->get_data_length(),
       
  2457 				EAP_TYPE_AKA_MAXIMUM_CHECKCODE_LENGTH));
       
  2458 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2459 			return EAP_STATUS_RETURN(m_am_tools, eap_status_not_enough_challenges);
       
  2460 		}
       
  2461 
       
  2462 
       
  2463 		u8_t * CHECKCODE = 0;
       
  2464 
       
  2465 		if (payload->get_data_length() != 0)
       
  2466 		{
       
  2467 			CHECKCODE = static_cast<u8_t *>(payload->get_data(payload->get_data_length()));
       
  2468 			if (CHECKCODE == 0)
       
  2469 			{
       
  2470 				EAP_TRACE_DEBUG(
       
  2471 					m_am_tools, 
       
  2472 					TRACE_FLAGS_AKA_ERROR, 
       
  2473 					(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(0x%08x): ")
       
  2474 					 EAPL("current payload 0x%04x=%s, length 0x%04x, data buffer incorrect.\n"),
       
  2475 					payload, current_payload, payload->get_payload_AT_string(), payload->get_payload_length()));
       
  2476 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2477 				return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2478 			}
       
  2479 		}
       
  2480 
       
  2481 		status = p_aka_payloads->get_CHECKCODE()->set_buffer(
       
  2482 			payload, CHECKCODE, payload->get_data_length(), false, false);
       
  2483 
       
  2484 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2485 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2486 	}
       
  2487 	else if (128 <= current_payload && current_payload <= 255)
       
  2488 	{
       
  2489 		// Unknown skippable attribute.
       
  2490 		// Silently ignore this payload.
       
  2491 		EAP_TRACE_DEBUG(
       
  2492 			m_am_tools, 
       
  2493 			TRACE_FLAGS_DEFAULT, 
       
  2494 			(EAPL("IGNORED: eap_type_aka_c::parse_generic_payload(): Ignored skippable attribute %d=0x%04x.\n"),
       
  2495 			current_payload,
       
  2496 			current_payload));
       
  2497 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2498 		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2499 	}
       
  2500 	else
       
  2501 	{
       
  2502 		// Unknown non-skippable attribute.
       
  2503 		EAP_TRACE_DEBUG(
       
  2504 			m_am_tools, 
       
  2505 			TRACE_FLAGS_AKA_ERROR, 
       
  2506 			(EAPL("ERROR: eap_type_aka_c::parse_generic_payload(): Unknown non-skippable attribute %d=0x%04x.\n"),
       
  2507 			current_payload,
       
  2508 			current_payload));
       
  2509 
       
  2510 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2511 		return EAP_STATUS_RETURN(m_am_tools, eap_status_unsupported_gsmsim_payload);
       
  2512 	}
       
  2513 }
       
  2514 
       
  2515 //--------------------------------------------------
       
  2516 
       
  2517 //
       
  2518 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::analyse_aka_packet(
       
  2519 	const eap_am_network_id_c * const receive_network_id,
       
  2520 	aka_header_c * const received_aka,
       
  2521 	const u32_t aka_packet_length,
       
  2522 	aka_payloads_c * const p_aka_payloads)
       
  2523 {
       
  2524 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2525 
       
  2526 	eap_status_e status = eap_status_process_general_error;
       
  2527 
       
  2528 	if (m_is_client == true)
       
  2529 	{
       
  2530 		// Client
       
  2531 
       
  2532 		if (received_aka->get_subtype() == aka_subtype_Identity)
       
  2533 		{
       
  2534 			status = handle_aka_identity_request_message(
       
  2535 				receive_network_id,
       
  2536 				received_aka,
       
  2537 				aka_packet_length,
       
  2538 				p_aka_payloads);
       
  2539 		}
       
  2540 		else if (received_aka->get_subtype() == aka_subtype_Challenge)
       
  2541 		{
       
  2542 			status = handle_challenge_request_message(
       
  2543 				receive_network_id,
       
  2544 				received_aka,
       
  2545 				aka_packet_length,
       
  2546 				p_aka_payloads);
       
  2547 		}
       
  2548 		else if (received_aka->get_subtype() == aka_subtype_Notification)
       
  2549 		{
       
  2550 			status = handle_aka_notification_request_message(
       
  2551 				receive_network_id,
       
  2552 				received_aka,
       
  2553 				aka_packet_length,
       
  2554 				p_aka_payloads);
       
  2555 		}
       
  2556 		else if (received_aka->get_subtype() == aka_subtype_Re_authentication)
       
  2557 		{
       
  2558 			status = handle_reauthentication_request_message(
       
  2559 				receive_network_id,
       
  2560 				received_aka,
       
  2561 				aka_packet_length,
       
  2562 				p_aka_payloads);
       
  2563 		}
       
  2564 		else
       
  2565 		{
       
  2566 			// Unknown message in this state.
       
  2567 			EAP_TRACE_DEBUG(
       
  2568 				m_am_tools, 
       
  2569 				TRACE_FLAGS_AKA_ERROR, 
       
  2570 				(EAPL("ERROR: eap_type_aka_c::analyse_aka_packet(): ")
       
  2571 				 EAPL("Unknown message %d=%s in eap_type_aka_state_variable_e %d=%s.\n"),
       
  2572 				received_aka->get_subtype(),
       
  2573 				received_aka->get_subtype_string(),
       
  2574 				get_state(),
       
  2575 				get_state_string()));
       
  2576 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2577 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2578 		}
       
  2579 	}
       
  2580 	else
       
  2581 	{
       
  2582 		// Server
       
  2583 
       
  2584 		if (received_aka->get_subtype() == aka_subtype_Identity)
       
  2585 		{
       
  2586 			status = handle_aka_identity_response_message(
       
  2587 				received_aka,
       
  2588 				aka_packet_length,
       
  2589 				p_aka_payloads);
       
  2590 		}
       
  2591 		else if (received_aka->get_subtype() == aka_subtype_Synchronization_Failure)
       
  2592 		{
       
  2593 			status = handle_synchronization_failure_response_message(
       
  2594 				receive_network_id,
       
  2595 				received_aka,
       
  2596 				aka_packet_length,
       
  2597 				p_aka_payloads);
       
  2598 		}
       
  2599 		else if (received_aka->get_subtype() == aka_subtype_Challenge)
       
  2600 		{
       
  2601 			status = handle_challenge_response_message(
       
  2602 				receive_network_id,
       
  2603 				received_aka,
       
  2604 				aka_packet_length,
       
  2605 				p_aka_payloads);
       
  2606 		}
       
  2607 		else if (received_aka->get_subtype() == aka_subtype_Notification)
       
  2608 		{
       
  2609 			status = handle_notification_response_message(
       
  2610 				receive_network_id,
       
  2611 				received_aka,
       
  2612 				aka_packet_length,
       
  2613 				p_aka_payloads);
       
  2614 		}
       
  2615 		else if (received_aka->get_subtype() == aka_subtype_Re_authentication)
       
  2616 		{
       
  2617 			status = handle_reauthentication_response_message(
       
  2618 				receive_network_id,
       
  2619 				received_aka,
       
  2620 				aka_packet_length,
       
  2621 				p_aka_payloads);
       
  2622 		}
       
  2623 		else if (received_aka->get_subtype() == aka_subtype_Client_Error)
       
  2624 		{
       
  2625 			status = handle_client_error_response_message(
       
  2626 				receive_network_id,
       
  2627 				received_aka,
       
  2628 				aka_packet_length,
       
  2629 				p_aka_payloads);
       
  2630 		}
       
  2631 		else
       
  2632 		{
       
  2633 			// Unknown message in this state.
       
  2634 			EAP_TRACE_DEBUG(
       
  2635 				m_am_tools, 
       
  2636 				TRACE_FLAGS_AKA_ERROR, 
       
  2637 				(EAPL("ERROR: eap_type_aka_c::analyse_aka_packet(): ")
       
  2638 				 EAPL("Unknown message %d=%s in eap_type_aka_state_variable_e %d=%s.\n"),
       
  2639 				received_aka->get_subtype(),
       
  2640 				received_aka->get_subtype_string(),
       
  2641 				get_state(),
       
  2642 				get_state_string()));
       
  2643 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2644 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2645 		}
       
  2646 	}
       
  2647 
       
  2648 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2649 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2650 }
       
  2651 
       
  2652 //--------------------------------------------------
       
  2653 
       
  2654 //
       
  2655 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::parse_aka_payload(
       
  2656 	const aka_payload_AT_header_c * const p_payload,
       
  2657 	u32_t * const buffer_length,
       
  2658 	aka_payloads_c * const p_aka_payloads,
       
  2659 	const aka_subtype_e subtype)
       
  2660 {
       
  2661 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2662 
       
  2663 	aka_payload_AT_header_c payload(
       
  2664 		m_am_tools,
       
  2665 		p_payload->get_header_buffer(*buffer_length),
       
  2666 		*buffer_length); // Const correctness is gone.
       
  2667 
       
  2668 	aka_payload_AT_type_e current_payload = payload.get_current_payload();
       
  2669 
       
  2670 	eap_status_e status = eap_status_header_corrupted;
       
  2671 
       
  2672 	if (payload.get_is_valid() == true
       
  2673 		&& current_payload != aka_payload_NONE)
       
  2674 	{
       
  2675 		if (*buffer_length < payload.get_header_length()+payload.get_data_length())
       
  2676 		{
       
  2677 			EAP_TRACE_DEBUG(
       
  2678 				m_am_tools,
       
  2679 				TRACE_FLAGS_AKA_ERROR,
       
  2680 				(EAPL("ERROR: eap_type_aka_c::parse_aka_payload(0x%08x): current payload 0x%04x=%s, data length 0x%04x, buffer length 0x%04x.\n"),
       
  2681 				payload.get_header_buffer(0ul),
       
  2682 				 current_payload,
       
  2683 				 payload.get_payload_AT_string(),
       
  2684 				 payload.get_data_length(),
       
  2685 				 *buffer_length));
       
  2686 			EAP_TRACE_DEBUG(
       
  2687 				m_am_tools,
       
  2688 				TRACE_FLAGS_AKA_ERROR,
       
  2689 				(EAPL("ERROR: eap_type_aka_c::parse_aka_payload(): AKA-payload header is corrupted.\n")));
       
  2690 			EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("payload"),
       
  2691 				payload.get_header_buffer(*buffer_length),
       
  2692 				*buffer_length));
       
  2693 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2694 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2695 		}
       
  2696 
       
  2697 		status = parse_generic_payload(current_payload, &payload, p_aka_payloads, subtype);
       
  2698 		if (status != eap_status_ok)
       
  2699 		{
       
  2700 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2701 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2702 		}
       
  2703 
       
  2704 		EAP_ASSERT_ALWAYS(*buffer_length >= payload.get_header_length()+payload.get_data_length());
       
  2705 		*buffer_length -= payload.get_header_length()+payload.get_data_length();
       
  2706 
       
  2707 		while(*buffer_length >= payload.get_header_length()
       
  2708 			&& payload.get_is_valid() == true
       
  2709 			&& payload.get_header_buffer_length() >= (payload.get_header_length()+payload.get_data_length()))
       
  2710 		{
       
  2711 			payload.set_header_buffer(
       
  2712 					payload.get_next_header(),
       
  2713 					payload.get_header_buffer_length()-(payload.get_header_length()+payload.get_data_length()));
       
  2714 			if (payload.get_is_valid() == false)
       
  2715 			{
       
  2716 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2717 				return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2718 			}
       
  2719 
       
  2720 			current_payload = payload.get_current_payload();
       
  2721 
       
  2722 			if (*buffer_length < payload.get_header_length()+payload.get_data_length())
       
  2723 			{
       
  2724 				EAP_TRACE_DEBUG(
       
  2725 					m_am_tools,
       
  2726 					TRACE_FLAGS_AKA_ERROR,
       
  2727 					(EAPL("ERROR: eap_type_aka_c::parse_aka_payload(0x%08x): current payload 0x%04x=%s, data length 0x%04x, buffer length 0x%04x.\n"),
       
  2728 					 payload.get_header_buffer(0ul),
       
  2729 					 current_payload,
       
  2730 					 payload.get_payload_AT_string(),
       
  2731 					 payload.get_data_length(),
       
  2732 					 *buffer_length));
       
  2733 				EAP_TRACE_DEBUG(
       
  2734 					m_am_tools,
       
  2735 					TRACE_FLAGS_AKA_ERROR,
       
  2736 					(EAPL("ERROR: eap_type_aka_c::parse_aka_payload(): AKA-payload header is corrupted.\n")));
       
  2737 				EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("payload"),
       
  2738 					payload.get_header_buffer(*buffer_length),
       
  2739 					*buffer_length));
       
  2740 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2741 				return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2742 			}
       
  2743 
       
  2744 			status = parse_generic_payload(current_payload, &payload, p_aka_payloads, subtype);
       
  2745 			if (status != eap_status_ok)
       
  2746 			{
       
  2747 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2748 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  2749 			}
       
  2750 
       
  2751 			EAP_ASSERT_ALWAYS(*buffer_length >= payload.get_header_length()+payload.get_data_length());
       
  2752 			*buffer_length -= payload.get_header_length()+payload.get_data_length();
       
  2753 		}
       
  2754 	}
       
  2755 
       
  2756 	if (*buffer_length != 0u)
       
  2757 	{
       
  2758 		EAP_TRACE_DEBUG(
       
  2759 			m_am_tools,
       
  2760 			TRACE_FLAGS_AKA_ERROR,
       
  2761 			(EAPL("ERROR: eap_type_aka_c::parse_aka_payload(): ")
       
  2762 			 EAPL("AKA-header is corrupted. Buffer length and payload length does not match. %lu illegal bytes.\n"),
       
  2763 			 *buffer_length));
       
  2764 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2765 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2766 	}
       
  2767 
       
  2768 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2769 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2770 }
       
  2771 
       
  2772 //--------------------------------------------------
       
  2773 
       
  2774 //
       
  2775 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::parse_aka_packet(
       
  2776 	aka_header_c * const aka,
       
  2777 	const u32_t aka_packet_length,
       
  2778 	aka_payloads_c * const p_aka_payloads)
       
  2779 {
       
  2780 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2781 
       
  2782 	if (aka->get_length() < aka->get_header_length())
       
  2783 	{
       
  2784 		EAP_TRACE_DEBUG(
       
  2785 			m_am_tools,
       
  2786 			TRACE_FLAGS_AKA_ERROR,
       
  2787 			(EAPL("ERROR: eap_type_aka_c::parse_aka_packet(): ")
       
  2788 			 EAPL("AKA-header is corrupted. Buffer length and payload ")
       
  2789 			 EAPL("length does not match. AKA-header length %lu < minimum AKA-header length %lu.\n"),
       
  2790 			aka->get_length(),
       
  2791 			aka->get_header_length()));
       
  2792 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2793 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2794 	}
       
  2795 
       
  2796 	if (aka->get_length() > aka_packet_length)
       
  2797 	{
       
  2798 		EAP_TRACE_DEBUG(
       
  2799 			m_am_tools, 
       
  2800 			TRACE_FLAGS_AKA_ERROR, 
       
  2801 			(EAPL("ERROR: eap_type_aka_c::parse_aka_packet(): ")
       
  2802 			 EAPL("AKA-header is corrupted. Buffer length and payload ")
       
  2803 			 EAPL("length does not match. AKA-header length %lu > packet length %lu\n"),
       
  2804 			aka->get_length(),
       
  2805 			aka_packet_length));
       
  2806 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2807 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2808 	}
       
  2809 
       
  2810 	u32_t buffer_length = aka->get_length() - aka->get_header_length();
       
  2811 
       
  2812 	if (buffer_length == 0u)
       
  2813 	{
       
  2814 		// No payload in this packet.
       
  2815 		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2816 	}
       
  2817 
       
  2818 
       
  2819 	aka_payload_AT_header_c payload(
       
  2820 		m_am_tools,
       
  2821 		aka->get_data(buffer_length),
       
  2822 		buffer_length);
       
  2823 
       
  2824 	if (payload.get_is_valid() == false)
       
  2825 	{
       
  2826 		EAP_TRACE_DEBUG(
       
  2827 			m_am_tools, 
       
  2828 			TRACE_FLAGS_AKA_ERROR, 
       
  2829 			(EAPL("ERROR: No aka_payload_AT_header_c.\n")));
       
  2830 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2831 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2832 	}
       
  2833 
       
  2834 
       
  2835 	eap_status_e status = parse_aka_payload(
       
  2836 		&payload,
       
  2837 		&buffer_length,
       
  2838 		p_aka_payloads,
       
  2839 		aka->get_subtype());
       
  2840 
       
  2841 	if (status != eap_status_ok)
       
  2842 	{
       
  2843 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2844 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2845 	}
       
  2846 	else if (buffer_length != 0u)
       
  2847 	{
       
  2848 		EAP_TRACE_DEBUG(
       
  2849 			m_am_tools,
       
  2850 			TRACE_FLAGS_AKA_ERROR,
       
  2851 			(EAPL("ERROR: eap_type_aka_c::parse_aka_packet(): ")
       
  2852 			 EAPL("AKA-header is corrupted. Buffer length and payload ")
       
  2853 			 EAPL("length does not match. Illegal byte count %lu\n"),
       
  2854 			buffer_length));
       
  2855 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2856 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2857 	}
       
  2858 
       
  2859 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2860 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2861 }
       
  2862 
       
  2863 //--------------------------------------------------
       
  2864 
       
  2865 //
       
  2866 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::handle_aka_packet(
       
  2867 	const eap_am_network_id_c * const receive_network_id,
       
  2868 	aka_header_c * const received_aka,
       
  2869 	const u32_t aka_length,
       
  2870 	aka_payloads_c * const p_aka_payloads)
       
  2871 {
       
  2872 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2873 
       
  2874 	eap_status_e status = check_valid_state(received_aka->get_subtype());
       
  2875 	if (status != eap_status_ok)
       
  2876 	{
       
  2877 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2878 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2879 	}
       
  2880 
       
  2881 	status = parse_aka_packet(received_aka, aka_length, p_aka_payloads);
       
  2882 	if (status != eap_status_ok)
       
  2883 	{
       
  2884 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2885 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2886 	}
       
  2887 
       
  2888 	status = analyse_aka_packet(
       
  2889 		receive_network_id,
       
  2890 		received_aka,
       
  2891 		aka_length,
       
  2892 		p_aka_payloads);
       
  2893 
       
  2894 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2895 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2896 }
       
  2897 
       
  2898 
       
  2899 //--------------------------------------------------
       
  2900 
       
  2901 #if defined(USE_EAP_TRACE)
       
  2902 
       
  2903 // 
       
  2904 EAP_FUNC_EXPORT void eap_type_aka_c::packet_trace(
       
  2905 	eap_const_string prefix,
       
  2906 	const eap_am_network_id_c * const /* receive_network_id */,
       
  2907 	eap_header_wr_c * const eap_packet,
       
  2908 	const u32_t /* eap_packet_length */)
       
  2909 {
       
  2910 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2911 
       
  2912 	EAP_UNREFERENCED_PARAMETER(prefix);
       
  2913 
       
  2914 	if (eap_packet->get_length() > eap_header_base_c::get_header_length()
       
  2915 		&& eap_packet->get_type() == eap_type_aka)
       
  2916 	{
       
  2917 		aka_header_c aka_eap(
       
  2918 			m_am_tools,
       
  2919 			eap_packet->get_header_buffer(eap_packet->get_header_buffer_length()),
       
  2920 			eap_packet->get_header_buffer_length());
       
  2921 
       
  2922 		EAP_UNREFERENCED_PARAMETER(aka_eap);
       
  2923 
       
  2924 		EAP_TRACE_DEBUG(
       
  2925 			m_am_tools,
       
  2926 			TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  2927 			(EAPL("%s EAP_type_AKA: %s, code=0x%02x=%s, identifier=0x%02x, ")
       
  2928 			 EAPL("length=0x%04x, type=0x%08x=%s, subtype=0x%02x=%s\n"),
       
  2929 			 prefix,
       
  2930 			 (m_is_client == true) ? "client": "server",
       
  2931 			 aka_eap.get_code(),
       
  2932 			 aka_eap.get_code_string(),
       
  2933 			 aka_eap.get_identifier(),
       
  2934 			 aka_eap.get_length(),
       
  2935 			 convert_eap_type_to_u32_t(aka_eap.get_type()),
       
  2936 			 aka_eap.get_eap_type_string(),
       
  2937 			 aka_eap.get_subtype(),
       
  2938 			 aka_eap.get_subtype_string()));
       
  2939 		
       
  2940 		EAP_TRACE_DEBUG(m_am_tools, eap_am_tools_c::eap_trace_mask_eap_messages,
       
  2941 			(EAPL("\n\t%s\n\tcode       = 0x%02x   = %s\n\tidentifier = 0x%02x")
       
  2942 			 EAPL("\n\tlength     = 0x%04x = %lu\n\ttype       = 0x%08x   = %s\n\tsubtype    = 0x%02x   = %s\n"),
       
  2943 			(m_is_client == true) ? "client": "server",
       
  2944 			aka_eap.get_code(),
       
  2945 			aka_eap.get_code_string(),
       
  2946 			aka_eap.get_identifier(),
       
  2947 			aka_eap.get_length(),
       
  2948 			aka_eap.get_length(),
       
  2949 			convert_eap_type_to_u32_t(aka_eap.get_type()),
       
  2950 			aka_eap.get_eap_type_string(),
       
  2951 			aka_eap.get_subtype(),
       
  2952 			aka_eap.get_subtype_string()));
       
  2953 	}
       
  2954 	else if (eap_packet->get_length() > eap_header_base_c::get_header_length())
       
  2955 	{
       
  2956 		EAP_TRACE_DEBUG(
       
  2957 			m_am_tools,
       
  2958 			TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  2959 			(EAPL("%s EAP_type_AKA: %s, code=0x%02x=%s, identifier=0x%02x, length=0x%04x, type=0x%08x=%s\n"),
       
  2960 			prefix,
       
  2961 			(m_is_client == true) ? "client": "server",
       
  2962 			eap_packet->get_code(),
       
  2963 			eap_packet->get_code_string(),
       
  2964 			eap_packet->get_identifier(),
       
  2965 			eap_packet->get_length(),
       
  2966 			convert_eap_type_to_u32_t(eap_packet->get_type()),
       
  2967 			eap_packet->get_type_string()));
       
  2968 
       
  2969 		EAP_TRACE_DEBUG(
       
  2970 			m_am_tools,
       
  2971 			eap_am_tools_c::eap_trace_mask_eap_messages,
       
  2972 			(EAPL("\n\t%s\n\tcode       = 0x%02x   = %s\n\tidentifier = 0x%02x\n\tlength     = 0x%04x = %lu\n\ttype       = 0x%08x   = %s\n"),
       
  2973 			(m_is_client == true) ? "client": "server",
       
  2974 			eap_packet->get_code(),
       
  2975 			eap_packet->get_code_string(),
       
  2976 			eap_packet->get_identifier(),
       
  2977 			eap_packet->get_length(),
       
  2978 			eap_packet->get_length(),
       
  2979 			convert_eap_type_to_u32_t(eap_packet->get_type()),
       
  2980 			eap_packet->get_type_string()));
       
  2981 	}
       
  2982 	else
       
  2983 	{
       
  2984 		EAP_TRACE_DEBUG(
       
  2985 			m_am_tools,
       
  2986 			TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  2987 			(EAPL("%s EAP_type_AKA: %s, code=0x%02x=%s, identifier=0x%02x, length=0x%04x\n"),
       
  2988 			prefix,
       
  2989 			(m_is_client == true) ? "client": "server",
       
  2990 			eap_packet->get_code(),
       
  2991 			eap_packet->get_code_string(),
       
  2992 			eap_packet->get_identifier(),
       
  2993 			eap_packet->get_length()));
       
  2994 
       
  2995 		EAP_TRACE_DEBUG(
       
  2996 			m_am_tools,
       
  2997 			eap_am_tools_c::eap_trace_mask_eap_messages,
       
  2998 			(EAPL("\n\t%s\n\tcode       = 0x%02x   = %s\n\tidentifier = 0x%02x\n\tlength     = 0x%04x = %lu\n"),
       
  2999 			(m_is_client == true) ? "client": "server",
       
  3000 			eap_packet->get_code(),
       
  3001 			eap_packet->get_code_string(),
       
  3002 			eap_packet->get_identifier(),
       
  3003 			eap_packet->get_length(),
       
  3004 			eap_packet->get_length()));
       
  3005 	}
       
  3006 
       
  3007 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3008 }
       
  3009 
       
  3010 #endif //#if defined(USE_EAP_TRACE)
       
  3011 
       
  3012 //--------------------------------------------------
       
  3013 
       
  3014 // 
       
  3015 EAP_FUNC_EXPORT eap_variable_data_c * eap_type_aka_c::get_nai_realm()
       
  3016 {
       
  3017 	return &m_manual_realm;
       
  3018 }
       
  3019 
       
  3020 //--------------------------------------------------
       
  3021 
       
  3022 // 
       
  3023 EAP_FUNC_EXPORT void eap_type_aka_c::update_buffer_indexes(
       
  3024 	const u32_t maximum_buffer_size,
       
  3025 	const u32_t payload_size,
       
  3026 	u32_t * const buffer_offset,
       
  3027 	u32_t * const buffer_free)
       
  3028 {
       
  3029 	EAP_UNREFERENCED_PARAMETER(maximum_buffer_size);
       
  3030 
       
  3031 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3032 
       
  3033 	EAP_ASSERT_ALWAYS(*buffer_offset + *buffer_free <= maximum_buffer_size-m_trailer_length);
       
  3034 	EAP_ASSERT_ALWAYS(*buffer_free >= payload_size);
       
  3035 	EAP_ASSERT_ALWAYS(m_aka_header_offset+m_MTU == *buffer_offset + *buffer_free);
       
  3036 
       
  3037 	*buffer_free -= payload_size;
       
  3038 	*buffer_offset += payload_size;
       
  3039 
       
  3040 	EAP_ASSERT_ALWAYS(*buffer_offset + *buffer_free <= maximum_buffer_size-m_trailer_length);
       
  3041 	EAP_ASSERT_ALWAYS(*buffer_offset <= m_aka_header_offset+m_MTU);
       
  3042 
       
  3043 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3044 }
       
  3045 
       
  3046 //--------------------------------------------------
       
  3047 
       
  3048 // 
       
  3049 EAP_FUNC_EXPORT void eap_type_aka_c::update_payload_indexes(
       
  3050 	const u32_t maximum_buffer_size,
       
  3051 	const u32_t eap_header_size,
       
  3052 	const u32_t payload_size,
       
  3053 	u32_t * const data_offset,
       
  3054 	u32_t * const data_free,
       
  3055 	u32_t * const buffer_offset,
       
  3056 	u32_t * const buffer_free)
       
  3057 {
       
  3058 	EAP_UNREFERENCED_PARAMETER(eap_header_size);
       
  3059 
       
  3060 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3061 
       
  3062 	EAP_ASSERT_ALWAYS(*buffer_offset == m_aka_header_offset + eap_header_size + *data_offset);
       
  3063 	EAP_ASSERT_ALWAYS(*buffer_free == *data_free);
       
  3064 	EAP_ASSERT_ALWAYS(*data_free >= payload_size);
       
  3065 
       
  3066 	*data_free -= payload_size;
       
  3067 	*data_offset += payload_size;
       
  3068 
       
  3069 	update_buffer_indexes(
       
  3070 		maximum_buffer_size,
       
  3071 		payload_size,
       
  3072 		buffer_offset,
       
  3073 		buffer_free);
       
  3074 
       
  3075 	EAP_ASSERT_ALWAYS(*buffer_offset == m_aka_header_offset + eap_header_size + *data_offset);
       
  3076 	EAP_ASSERT_ALWAYS(*buffer_free == *data_free);
       
  3077 
       
  3078 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3079 }
       
  3080 
       
  3081 //--------------------------------------------------
       
  3082 
       
  3083 // 
       
  3084 EAP_FUNC_EXPORT bool eap_type_aka_c::get_is_client() 
       
  3085 {
       
  3086 	return m_is_client;
       
  3087 }
       
  3088 
       
  3089 //--------------------------------------------------
       
  3090 
       
  3091 // 
       
  3092 EAP_FUNC_EXPORT void eap_type_aka_c::set_is_valid()
       
  3093 {
       
  3094 	m_is_valid = true;
       
  3095 }
       
  3096 
       
  3097 //--------------------------------------------------
       
  3098 
       
  3099 // 
       
  3100 EAP_FUNC_EXPORT bool eap_type_aka_c::get_is_valid()
       
  3101 {
       
  3102 	return m_is_valid;
       
  3103 }
       
  3104 
       
  3105 //--------------------------------------------------
       
  3106 
       
  3107 // 
       
  3108 EAP_FUNC_EXPORT void eap_type_aka_c::state_notification(
       
  3109 	const abs_eap_state_notification_c * const state
       
  3110 	)
       
  3111 {
       
  3112 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3113 
       
  3114 	EAP_TRACE_DEBUG(
       
  3115 		m_am_tools, 
       
  3116 		TRACE_FLAGS_DEFAULT, 
       
  3117 		(EAPL("eap_type_aka_c::state_notification(): get_type_partner() 0x%08x\n"), 
       
  3118 		 get_type_partner()));
       
  3119 
       
  3120 	get_type_partner()->state_notification(state);
       
  3121 
       
  3122 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3123 }
       
  3124 
       
  3125 //--------------------------------------------------
       
  3126 
       
  3127 // 
       
  3128 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::finish_successful_authentication(
       
  3129 	const eap_am_network_id_c * const receive_network_id)
       
  3130 {
       
  3131 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3132 
       
  3133 	EAP_TRACE_DEBUG(
       
  3134 		m_am_tools, 
       
  3135 		TRACE_FLAGS_DEFAULT, 
       
  3136 		(EAPL("eap_type_aka_c::finish_successful_authentication().\n")));
       
  3137 
       
  3138 
       
  3139 	// Here we swap the addresses.
       
  3140 	eap_am_network_id_c send_network_id(m_am_tools,
       
  3141 		receive_network_id->get_destination_id(),
       
  3142 		receive_network_id->get_source_id(),
       
  3143 		receive_network_id->get_type());
       
  3144 
       
  3145 	if (get_master_session_key()->get_is_valid_data() == false
       
  3146 		|| get_master_session_key()->get_data_length() == 0u)
       
  3147 	{
       
  3148 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3149 		return EAP_STATUS_RETURN(m_am_tools, eap_status_key_error);
       
  3150 	}
       
  3151 
       
  3152 	eap_status_e status = get_type_partner()->packet_data_crypto_keys(
       
  3153 		&send_network_id,
       
  3154 		get_master_session_key());
       
  3155 	if (status != eap_status_ok)
       
  3156 	{
       
  3157 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3158 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3159 	}
       
  3160 
       
  3161 	if (m_authentication_type == AKA_AUTHENTICATION_TYPE_REAUTHENTICATION)
       
  3162 	{
       
  3163 		// Re-authentication counter is increased only on successfull re-authentication.
       
  3164 		// In order to use re-authentication, the client and the server need to
       
  3165 		// update re-authentication counter value.
       
  3166 		status = m_am_type_aka->increase_reauth_counter();
       
  3167 		if (status != eap_status_ok)
       
  3168 		{
       
  3169 			restore_saved_previous_state();
       
  3170 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3171 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  3172 		}
       
  3173 	}
       
  3174 
       
  3175 	set_authentication_finished_successfully();
       
  3176 	set_state(eap_type_aka_state_success);
       
  3177 
       
  3178 	eap_state_notification_c notification(
       
  3179 		m_am_tools,
       
  3180 		get_send_network_id(),
       
  3181 		m_is_client,
       
  3182 		eap_state_notification_eap,
       
  3183 		eap_protocol_layer_eap,
       
  3184 		eap_type_aka,
       
  3185 		eap_state_none,
       
  3186 		eap_state_authentication_finished_successfully,
       
  3187 		get_last_eap_identifier(),
       
  3188 		true);
       
  3189 	state_notification(&notification);
       
  3190 
       
  3191 	// Indicate AKA AM authentication finish.
       
  3192 	m_am_type_aka->authentication_finished(true, m_authentication_type, m_identity_type);
       
  3193 
       
  3194 
       
  3195 	if (m_authentication_type == AKA_AUTHENTICATION_TYPE_REAUTHENTICATION)
       
  3196 	{
       
  3197 		EAP_TRACE_DEBUG(
       
  3198 			m_am_tools, 
       
  3199 			TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
  3200 			(EAPL("EAP_type_AKA: %s, re-authentication EAP-SUCCESS, ")
       
  3201 			 EAPL("re-authentication identity\n"),
       
  3202 			(m_is_client == true) ? "client": "server"));
       
  3203 	}
       
  3204 	else if (m_authentication_type == AKA_AUTHENTICATION_TYPE_FULL_AUTH)
       
  3205 	{
       
  3206 		if (m_identity_type == AKA_IDENTITY_TYPE_PSEUDONYM_ID)
       
  3207 		{
       
  3208 			EAP_TRACE_ALWAYS(
       
  3209 				m_am_tools, 
       
  3210 				TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
  3211 				(EAPL("EAP_type_AKA: %s, full authentication EAP-SUCCESS, ")
       
  3212 				 EAPL("pseudonym identity\n"),
       
  3213 				(m_is_client == true) ? "client": "server"));
       
  3214 		}
       
  3215 		else if (m_identity_type == AKA_IDENTITY_TYPE_IMSI_ID)
       
  3216 		{
       
  3217 			EAP_TRACE_ALWAYS(
       
  3218 				m_am_tools, 
       
  3219 				TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
  3220 				(EAPL("EAP_type_AKA: %s, full authentication EAP-SUCCESS, ")
       
  3221 				 EAPL("IMSI identity\n"),
       
  3222 				(m_is_client == true) ? "client": "server"));
       
  3223 		}
       
  3224 		else if (m_identity_type == AKA_IDENTITY_TYPE_RE_AUTH_ID)
       
  3225 		{
       
  3226 			EAP_TRACE_ALWAYS(
       
  3227 				m_am_tools, 
       
  3228 				TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
  3229 				(EAPL("EAP_type_AKA: %s, full authentication EAP-SUCCESS, ")
       
  3230 				 EAPL("Re-auth identity\n"),
       
  3231 				(m_is_client == true) ? "client": "server"));
       
  3232 		}
       
  3233 		else
       
  3234 		{
       
  3235 			EAP_TRACE_ERROR(
       
  3236 				m_am_tools, 
       
  3237 				TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS|TRACE_FLAGS_AKA_ERROR, 
       
  3238 				(EAPL("ERROR: EAP_type_AKA: %s, unknown authentication EAP-SUCCESS, ")
       
  3239 				 EAPL("unknown identity\n"),
       
  3240 				(m_is_client == true) ? "client": "server"));
       
  3241 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3242 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_identity);
       
  3243 		}
       
  3244 	}
       
  3245 	else
       
  3246 	{
       
  3247 		EAP_TRACE_ERROR(
       
  3248 			m_am_tools, 
       
  3249 			TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS|TRACE_FLAGS_AKA_ERROR, 
       
  3250 			(EAPL("ERROR: EAP_type_AKA: %s, unknown authentication EAP-SUCCESS, ")
       
  3251 			 EAPL("unknown identity\n"),
       
  3252 			(m_is_client == true) ? "client": "server"));
       
  3253 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3254 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_identity);
       
  3255 	}
       
  3256 
       
  3257 
       
  3258 	cancel_error_message_delay_timer();
       
  3259 
       
  3260 	cancel_notification_message_delay_timer();
       
  3261 
       
  3262 	status = eap_status_ok;
       
  3263 
       
  3264 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3265 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3266 }
       
  3267 
       
  3268 //--------------------------------------------------
       
  3269 
       
  3270 // 
       
  3271 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::packet_process(
       
  3272 	const eap_am_network_id_c * const receive_network_id,
       
  3273 	eap_header_wr_c * const received_eap,
       
  3274 	const u32_t eap_packet_length)
       
  3275 {
       
  3276 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3277 
       
  3278 	if (receive_network_id == 0
       
  3279 		|| receive_network_id->get_is_valid_data() == false)
       
  3280 	{
       
  3281 		EAP_TRACE_DEBUG(
       
  3282 			m_am_tools, 
       
  3283 			TRACE_FLAGS_AKA_ERROR, 
       
  3284 			(EAPL("ERROR: eap_type_aka_c::packet_process(): receive_network_id=0x%08x is invalid.\n"),
       
  3285 			receive_network_id));
       
  3286 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3287 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  3288 	}
       
  3289 
       
  3290 	if (received_eap == 0
       
  3291 		|| received_eap->get_is_valid() == false)
       
  3292 	{
       
  3293 		EAP_TRACE_DEBUG(
       
  3294 			m_am_tools, 
       
  3295 			TRACE_FLAGS_AKA_ERROR, 
       
  3296 			(EAPL("ERROR: eap_type_aka_c::packet_process(): received_eap 0x%08x is invalid.\n"),
       
  3297 			received_eap));
       
  3298 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3299 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  3300 	}
       
  3301 
       
  3302 	EAP_AKA_PACKET_TRACE(
       
  3303 		EAPL("->"),
       
  3304 		receive_network_id,
       
  3305 		received_eap,
       
  3306 		eap_packet_length);
       
  3307 
       
  3308 	if (eap_packet_length < received_eap->get_length())
       
  3309 	{
       
  3310 		EAP_TRACE_DEBUG(
       
  3311 			m_am_tools, 
       
  3312 			TRACE_FLAGS_AKA_ERROR, 
       
  3313 			(EAPL("ERROR: eap_type_aka_c::packet_process(): ")
       
  3314 			 EAPL("eap_packet_length=0x%04x < received_eap->get_length()=0x%04x.\n"),
       
  3315 			eap_packet_length, received_eap->get_length()));
       
  3316 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3317 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  3318 	}
       
  3319 
       
  3320 	if (received_eap->get_length() < eap_header_base_c::get_header_length())
       
  3321 	{
       
  3322 		EAP_TRACE_DEBUG(
       
  3323 			m_am_tools, 
       
  3324 			TRACE_FLAGS_AKA_ERROR, 
       
  3325 			(EAPL("ERROR: eap_type_aka_c::packet_process(): received_eap->get_length() ")
       
  3326 			 EAPL("< eap_header_base_c::get_header_length().\n")));
       
  3327 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3328 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  3329 	}
       
  3330 
       
  3331 
       
  3332 	// NOTE: by disabling these calls throughput increases about 18%.
       
  3333 	// Disabling also decreases random seeds.
       
  3334 	m_am_tools->get_crypto()->add_rand_seed(
       
  3335 		received_eap->get_header_buffer(eap_packet_length),
       
  3336 		eap_packet_length);
       
  3337 	m_am_tools->get_crypto()->add_rand_seed_hw_ticks();
       
  3338 
       
  3339 	eap_status_e status = eap_status_process_general_error;
       
  3340 
       
  3341 	if ((m_is_client == true
       
  3342 		&& received_eap->get_code() == eap_code_request)
       
  3343 		|| (m_is_client == false
       
  3344 		&& received_eap->get_code() == eap_code_response))
       
  3345 	{
       
  3346 		if (received_eap->get_type() == eap_type_identity
       
  3347 			|| received_eap->get_type() == eap_type_aka)
       
  3348 		{
       
  3349 			if (received_eap->get_type() == eap_type_identity
       
  3350 				&& received_eap->get_code() == eap_code_request
       
  3351 				&& received_eap->get_length() <= eap_header_base_c::get_header_length())
       
  3352 			{
       
  3353 				status = eap_status_header_corrupted;
       
  3354 			}
       
  3355 			else if (received_eap->get_type() == eap_type_identity
       
  3356 				&& received_eap->get_code() == eap_code_response
       
  3357 				&& received_eap->get_length() <= eap_header_base_c::get_header_length())
       
  3358 			{
       
  3359 				status = eap_status_header_corrupted;
       
  3360 			}
       
  3361 			else if (received_eap->get_type() == eap_type_aka
       
  3362 				&& received_eap->get_length() < received_eap->get_header_length())
       
  3363 			{
       
  3364 				status = eap_status_header_corrupted;
       
  3365 			}
       
  3366 			else
       
  3367 			{
       
  3368 				aka_header_c aka_header(
       
  3369 					m_am_tools,
       
  3370 					received_eap->get_header_buffer(received_eap->get_header_buffer_length()),
       
  3371 					received_eap->get_header_buffer_length());
       
  3372 
       
  3373 				if (aka_header.get_is_valid() == false)
       
  3374 				{
       
  3375 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3376 					return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3377 				}
       
  3378 
       
  3379 				status = aka_packet_process(
       
  3380 					receive_network_id,
       
  3381 					&aka_header,
       
  3382 					eap_packet_length,
       
  3383 					m_is_client);
       
  3384 
       
  3385 				if (status != eap_status_ok
       
  3386 					&& status != eap_status_success
       
  3387 					&& status != eap_status_drop_packet_quietly
       
  3388 					&& status != eap_status_pending_request)
       
  3389 				{
       
  3390 					eap_status_string_c status_string;
       
  3391 					EAP_UNREFERENCED_PARAMETER(status_string);
       
  3392 					EAP_TRACE_DEBUG(
       
  3393 						m_am_tools, 
       
  3394 						TRACE_FLAGS_AKA_ERROR, 
       
  3395 						(EAPL("ERROR: %s=%d eap_type_aka_c::aka_packet_process() failed\n"),
       
  3396 						status_string.get_status_string(status), status));
       
  3397 
       
  3398 					if (m_is_client == true)
       
  3399 					{
       
  3400 						status = initialize_error_message(
       
  3401 							status);
       
  3402 					}
       
  3403 					else
       
  3404 					{
       
  3405 						status = initialize_notification_message();
       
  3406 					}
       
  3407 
       
  3408 					if (status != eap_status_ok)
       
  3409 					{
       
  3410 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3411 						return EAP_STATUS_RETURN(m_am_tools, status);
       
  3412 					}
       
  3413 				}
       
  3414 				else if (status == eap_status_ok)
       
  3415 				{
       
  3416 					EAP_GENERAL_HEADER_SET_ERROR_DETECTED(received_eap, false);
       
  3417 				}
       
  3418 			}
       
  3419 
       
  3420 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3421 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  3422 		}
       
  3423 		else if (received_eap->get_type() == eap_type_notification)
       
  3424 		{
       
  3425 			EAP_TRACE_DEBUG(
       
  3426 				m_am_tools, 
       
  3427 				TRACE_FLAGS_DEFAULT, 
       
  3428 				(EAPL("dropped EAP type notification: code=0x%02x, ")
       
  3429 				 EAPL("identifier=0x%02x, length=0x%04x, type=0x%08x\n"),
       
  3430 				 received_eap->get_code(),
       
  3431 				 received_eap->get_identifier(), 
       
  3432 				 received_eap->get_length(),
       
  3433 				 convert_eap_type_to_u32_t(received_eap->get_type())));
       
  3434 
       
  3435 			status = eap_status_illegal_eap_type;
       
  3436 
       
  3437 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3438 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  3439 		}
       
  3440 		else
       
  3441 		{
       
  3442 			EAP_TRACE_DEBUG(
       
  3443 				m_am_tools, 
       
  3444 				TRACE_FLAGS_DEFAULT, 
       
  3445 				(EAPL("dropped EAP type unknown: code=0x%02x, ")
       
  3446 				 EAPL("identifier=0x%02x, length=0x%04x, type=0x%08x\n"),
       
  3447 				 received_eap->get_code(),
       
  3448 				 received_eap->get_identifier(), 
       
  3449 				 received_eap->get_length(),
       
  3450 				 convert_eap_type_to_u32_t(received_eap->get_type())));
       
  3451 
       
  3452 			status = eap_status_illegal_eap_type;
       
  3453 
       
  3454 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3455 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  3456 		}
       
  3457 	}
       
  3458 	else if (m_is_client == true
       
  3459 		&& (received_eap->get_code() == eap_code_success
       
  3460 		|| received_eap->get_code() == eap_code_failure))
       
  3461 	{
       
  3462 		// Here we swap the addresses.
       
  3463 		eap_am_network_id_c send_network_id(m_am_tools,
       
  3464 			receive_network_id->get_destination_id(),
       
  3465 			receive_network_id->get_source_id(),
       
  3466 			receive_network_id->get_type());
       
  3467 
       
  3468 		if (received_eap->get_code() == eap_code_success)
       
  3469 		{
       
  3470 			if (get_state() == eap_type_aka_state_waiting_for_success)
       
  3471 			{
       
  3472 				EAP_GENERAL_HEADER_SET_ERROR_DETECTED(received_eap, false);
       
  3473 
       
  3474 				if (m_wait_eap_success_packet == false)
       
  3475 				{
       
  3476 					/**
       
  3477 					 * @{ Check right functionality.
       
  3478 					 * Here we return eap_status_ok, eap_status_success was returned after successfull
       
  3479 					 * EAP-Request/AKA/Challenge. This may change after EAP, 802.1X and 802.11i specifications are ready. }
       
  3480 					 */
       
  3481 					status = eap_status_ok;
       
  3482 				}
       
  3483 				else
       
  3484 				{
       
  3485 					status = finish_successful_authentication(
       
  3486 						receive_network_id);
       
  3487 				}
       
  3488 			}
       
  3489 			else
       
  3490 			{
       
  3491 				EAP_TRACE_DEBUG(
       
  3492 					m_am_tools, 
       
  3493 					TRACE_FLAGS_DEFAULT, 
       
  3494 					(EAPL("dropped EAP-Success: code=0x%02x, identifier=0x%02x, ")
       
  3495 					 EAPL("length=0x%04x, state %d=%s, is client %d\n"),
       
  3496 					received_eap->get_code(),
       
  3497 					received_eap->get_identifier(),
       
  3498 					received_eap->get_length(),
       
  3499 					get_state(),
       
  3500 					get_state_string(),
       
  3501 					(m_is_client == true)));
       
  3502 				status = eap_status_drop_packet_quietly;
       
  3503 			}
       
  3504 		}
       
  3505 		else if (received_eap->get_code() == eap_code_failure)
       
  3506 		{
       
  3507 			// EAP is quite sloppy protocol.
       
  3508 			// Somebody just send a EAP-failure message and authentication is terminated.
       
  3509 
       
  3510 			// Save received failure. We do not change our state yet.
       
  3511 			// The real correct EAP message could be received later if this failure was
       
  3512 			// send by nasty attacker.
       
  3513 			set_failure_message_received();
       
  3514 			// We handle the EAP-Request/Failure message after a timeout.
       
  3515 
       
  3516 			status = eap_status_ok;
       
  3517 		}
       
  3518 		else
       
  3519 		{
       
  3520 			EAP_TRACE_DEBUG(
       
  3521 				m_am_tools, 
       
  3522 				TRACE_FLAGS_DEFAULT, 
       
  3523 				(EAPL("dropped EAP code unknown: code=0x%02x, ")
       
  3524 				 EAPL("identifier=0x%02x, length=0x%04x, is client %d\n"),
       
  3525 				 received_eap->get_code(), received_eap->get_identifier(), 
       
  3526 				 received_eap->get_length(), (m_is_client == true)));
       
  3527 			status = eap_status_illegal_eap_code;
       
  3528 		}
       
  3529 	}
       
  3530 	else
       
  3531 	{
       
  3532 		EAP_TRACE_DEBUG(
       
  3533 			m_am_tools, 
       
  3534 			TRACE_FLAGS_DEFAULT, 
       
  3535 			(EAPL("dropped EAP code unknown: code=0x%02x, ")
       
  3536 			 EAPL("identifier=0x%02x, length=0x%04x, is client %d\n"),
       
  3537 			 received_eap->get_code(), received_eap->get_identifier(), 
       
  3538 			 received_eap->get_length(), (m_is_client == true)));
       
  3539 		status = eap_status_illegal_eap_code;
       
  3540 	}
       
  3541 
       
  3542 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3543 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3544 }
       
  3545 
       
  3546 //--------------------------------------------------
       
  3547 
       
  3548 //
       
  3549 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::new_handler(
       
  3550 	const eap_am_network_id_c * const /* receive_network_id */,
       
  3551 	const bool is_client_when_true)
       
  3552 {
       
  3553 	EAP_TRACE_DEBUG(
       
  3554 		m_am_tools, 
       
  3555 		TRACE_FLAGS_DEFAULT, 
       
  3556 		(EAPL("eap_type_aka_c::new_handler(): Creating new handler 0x%08x.\n"),
       
  3557 		this));
       
  3558 
       
  3559 	// We do not have handler yet and the message is identity EAP-message.
       
  3560 	// A new handler is needed.
       
  3561 
       
  3562 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
  3563 
       
  3564 	m_is_client = is_client_when_true;
       
  3565 
       
  3566 	if (is_client_when_true == true)
       
  3567 	{
       
  3568 		set_state(eap_type_aka_state_waiting_for_identity_request);
       
  3569 	}
       
  3570 	else if (is_client_when_true == false)
       
  3571 	{
       
  3572 		set_state(eap_type_aka_state_waiting_for_identity_response);
       
  3573 	}
       
  3574 
       
  3575 
       
  3576 	EAP_TRACE_DEBUG(
       
  3577 		m_am_tools, 
       
  3578 		TRACE_FLAGS_DEFAULT, 
       
  3579 		(EAPL("eap_type_aka_c::aka_packet_process(0x%08x): New handler created.\n"),
       
  3580 		 this));
       
  3581 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL(" own address"),
       
  3582 		m_send_network_id.get_source_id()->get_data(m_send_network_id.get_source_id()->get_data_length()),
       
  3583 		m_send_network_id.get_source_id()->get_data_length()));
       
  3584 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("peer address"),
       
  3585 		m_send_network_id.get_destination_id()->get_data(m_send_network_id.get_destination_id()->get_data_length()),
       
  3586 		m_send_network_id.get_destination_id()->get_data_length()));
       
  3587 
       
  3588 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3589 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  3590 }
       
  3591 
       
  3592 //--------------------------------------------------
       
  3593 
       
  3594 //
       
  3595 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::aka_packet_process(
       
  3596 	const eap_am_network_id_c * const receive_network_id,
       
  3597 	aka_header_c * const received_aka,
       
  3598 	const u32_t aka_packet_length,
       
  3599 	const bool is_client_when_true)
       
  3600 {
       
  3601 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3602 
       
  3603 	if (receive_network_id == 0
       
  3604 		|| receive_network_id->get_is_valid_data() == false)
       
  3605 	{
       
  3606 		EAP_TRACE_DEBUG(
       
  3607 			m_am_tools, 
       
  3608 			TRACE_FLAGS_AKA_ERROR, 
       
  3609 			(EAPL("ERROR: eap_type_aka_c::aka_packet_process(): ")
       
  3610 			 EAPL("receive_network_id=0x%08x is invalid.\n"),
       
  3611 			receive_network_id));
       
  3612 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3613 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  3614 	}
       
  3615 
       
  3616 	if (received_aka == 0
       
  3617 		|| received_aka->get_is_valid() == false)
       
  3618 	{
       
  3619 		EAP_TRACE_DEBUG(
       
  3620 			m_am_tools, 
       
  3621 			TRACE_FLAGS_AKA_ERROR, 
       
  3622 			(EAPL("ERROR: eap_type_aka_c::aka_packet_process(): ")
       
  3623 			 EAPL("received_aka 0x%08x is invalid.\n"),
       
  3624 			received_aka));
       
  3625 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3626 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  3627 	}
       
  3628 
       
  3629 	if (aka_packet_length < received_aka->get_length())
       
  3630 	{
       
  3631 		EAP_TRACE_DEBUG(
       
  3632 			m_am_tools, 
       
  3633 			TRACE_FLAGS_AKA_ERROR, 
       
  3634 			(EAPL("ERROR: eap_type_aka_c::aka_packet_process(): ")
       
  3635 			 EAPL("aka_packet_length < received_aka->get_length().\n")));
       
  3636 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3637 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  3638 	}
       
  3639 
       
  3640 	if (received_aka->get_type() == eap_type_aka)
       
  3641 	{
       
  3642 		EAP_TRACE_DEBUG(
       
  3643 			m_am_tools, 
       
  3644 			TRACE_FLAGS_DEFAULT, 
       
  3645 			(EAPL("eap_type_aka_c::aka_packet_process(), AKA subtype %d=%s\n"),
       
  3646 			received_aka->get_subtype(), received_aka->get_subtype_string()));
       
  3647 	}
       
  3648 	else
       
  3649 	{
       
  3650 		EAP_TRACE_DEBUG(
       
  3651 			m_am_tools, 
       
  3652 			TRACE_FLAGS_DEFAULT, 
       
  3653 			(EAPL("eap_type_aka_c::aka_packet_process(), EAP-type 0x%08x=%s\n"),
       
  3654 			convert_eap_type_to_u32_t(received_aka->get_type()),
       
  3655 			received_aka->get_eap_type_string()));
       
  3656 	}
       
  3657 
       
  3658 	eap_status_e status = eap_status_process_general_error;
       
  3659 
       
  3660 	// Here we swap the addresses.
       
  3661 	eap_am_network_id_c send_network_id(m_am_tools,
       
  3662 		receive_network_id->get_destination_id(),
       
  3663 		receive_network_id->get_source_id(),
       
  3664 		receive_network_id->get_type());
       
  3665 
       
  3666 	if (get_state() == eap_type_aka_state_none)
       
  3667 	{
       
  3668 		EAP_TRACE_DEBUG(
       
  3669 			m_am_tools, 
       
  3670 			TRACE_FLAGS_DEFAULT, 
       
  3671 			(EAPL("eap_type_aka_c::aka_packet_process(): No handler found.\n")));
       
  3672 
       
  3673 		if (is_client_when_true == false
       
  3674 			&& received_aka->get_type() == eap_type_identity)
       
  3675 		{
       
  3676 			// The EAP-identity is plain EAP-packet without additional fields..
       
  3677 			eap_header_rd_c eap_header(
       
  3678 				m_am_tools,
       
  3679 				received_aka->get_header_buffer(received_aka->get_header_buffer_length()),
       
  3680 				received_aka->get_header_buffer_length());
       
  3681 
       
  3682 			EAP_UNREFERENCED_PARAMETER(eap_header);
       
  3683 
       
  3684 			EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("received: EAP-identity"),
       
  3685 				eap_header.get_type_data(eap_header.get_type_data_length()),
       
  3686 				eap_header.get_type_data_length()));
       
  3687 
       
  3688 			status = new_handler(
       
  3689 				receive_network_id,
       
  3690 				is_client_when_true);
       
  3691 			if (status != eap_status_ok)
       
  3692 			{
       
  3693 				EAP_TRACE_DEBUG(
       
  3694 					m_am_tools, 
       
  3695 					TRACE_FLAGS_AKA_ERROR, 
       
  3696 					(EAPL("ERROR: eap_type_aka_c::aka_packet_process(): new_handler() failed, status %d.\n"),
       
  3697 					status));
       
  3698 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3699 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  3700 			}
       
  3701 		}
       
  3702 		else if (is_client_when_true == true
       
  3703 			&& received_aka->get_code() == eap_code_request)
       
  3704 		{
       
  3705 			if (received_aka->get_length() < received_aka->get_header_length())
       
  3706 			{
       
  3707 				status = eap_status_process_illegal_packet_error;
       
  3708 				eap_status_string_c status_string;
       
  3709 				EAP_TRACE_DEBUG(
       
  3710 					m_am_tools,
       
  3711 					TRACE_FLAGS_AKA_ERROR,
       
  3712 					(EAPL("ERROR: %s=%d eap_type_aka_c::aka_packet_process(): corrupted AKA-header.\n"),
       
  3713 					status_string.get_status_string(status), status));
       
  3714 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3715 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  3716 			}
       
  3717 
       
  3718 			// Here we create a handler and set state to eap_type_aka_state_waiting_for_aka_identity_request
       
  3719 			// if first EAP-Request is EAP-Request/AKA/Identity.
       
  3720 			if (received_aka->get_subtype() == aka_subtype_Identity)
       
  3721 			{
       
  3722 				eap_header_rd_c eap_header(
       
  3723 					m_am_tools,
       
  3724 					received_aka->get_header_buffer(received_aka->get_header_buffer_length()),
       
  3725 					received_aka->get_header_buffer_length());
       
  3726 
       
  3727 				EAP_UNREFERENCED_PARAMETER(eap_header);
       
  3728 
       
  3729 				EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("received: EAP-Request/AKA/Identity"),
       
  3730 					eap_header.get_type_data(eap_header.get_type_data_length()),
       
  3731 					eap_header.get_type_data_length()));
       
  3732 
       
  3733 				status = new_handler(
       
  3734 					receive_network_id,
       
  3735 					is_client_when_true);
       
  3736 				if (status != eap_status_ok)
       
  3737 				{
       
  3738 					EAP_TRACE_DEBUG(
       
  3739 						m_am_tools, 
       
  3740 						TRACE_FLAGS_AKA_ERROR, 
       
  3741 						(EAPL("ERROR: eap_type_aka_c::aka_packet_process(): new_handler() failed, status %d.\n"),
       
  3742 						status));
       
  3743 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3744 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  3745 				}
       
  3746 				set_state(eap_type_aka_state_waiting_for_aka_identity_request);
       
  3747 			}
       
  3748 			else if (received_aka->get_subtype() == aka_subtype_Challenge)
       
  3749 			{
       
  3750 				eap_header_rd_c eap_header(
       
  3751 					m_am_tools,
       
  3752 					received_aka->get_header_buffer(received_aka->get_header_buffer_length()),
       
  3753 					received_aka->get_header_buffer_length());
       
  3754 
       
  3755 				EAP_UNREFERENCED_PARAMETER(eap_header);
       
  3756 
       
  3757 				EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("received: EAP-Request/AKA/Challenge"),
       
  3758 					eap_header.get_type_data(eap_header.get_type_data_length()),
       
  3759 					eap_header.get_type_data_length()));
       
  3760 
       
  3761 				// We must query the previous sent EAP-Identity from EAP_Core.
       
  3762 				// The EAP_Core saves the sent EAP-Identity when the EAP-Identity is
       
  3763 				// sent to the network.
       
  3764 				// Previous EAP-type was NOT this instance. EAP-Identity was queried from other instance.
       
  3765 				status = get_type_partner()->get_saved_eap_identity(get_identity());
       
  3766 				if (status != eap_status_ok)
       
  3767 				{
       
  3768 					// We do not have the identity server accepted anymore.
       
  3769 					EAP_TRACE_DEBUG(
       
  3770 						m_am_tools, 
       
  3771 						TRACE_FLAGS_AKA_ERROR, 
       
  3772 						(EAPL("ERROR: eap_type_aka_c::aka_packet_process(): ")
       
  3773 						 EAPL("Cannot create new handler because EAP-Identity is missing. This EAP-packet is dropped.\n")));
       
  3774 
       
  3775 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3776 					return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
       
  3777 				}
       
  3778 
       
  3779 				status = get_NAI()->set_copy_of_buffer(get_identity());
       
  3780 				if (status != eap_status_ok)
       
  3781 				{
       
  3782 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3783 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  3784 				}
       
  3785 
       
  3786 				m_authentication_type = AKA_AUTHENTICATION_TYPE_FULL_AUTH;
       
  3787 				set_identity_type(AKA_IDENTITY_TYPE_IMSI_ID);
       
  3788 
       
  3789 				status = new_handler(
       
  3790 					receive_network_id,
       
  3791 					is_client_when_true);
       
  3792 				if (status != eap_status_ok)
       
  3793 				{
       
  3794 					EAP_TRACE_DEBUG(
       
  3795 						m_am_tools, 
       
  3796 						TRACE_FLAGS_AKA_ERROR, 
       
  3797 						(EAPL("ERROR: eap_type_aka_c::aka_packet_process(): new_handler() failed, status %d.\n"),
       
  3798 						status));
       
  3799 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3800 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  3801 				}
       
  3802 				set_state(eap_type_aka_state_waiting_for_challenge_request);
       
  3803 			}
       
  3804 			else
       
  3805 			{
       
  3806 				EAP_TRACE_DEBUG(
       
  3807 					m_am_tools, 
       
  3808 					TRACE_FLAGS_AKA_ERROR, 
       
  3809 					(EAPL("ERROR: eap_type_aka_c::aka_packet_process(): ")
       
  3810 					 EAPL("Only EAP-Request/AKA/Identity message in EAP-AKA client ")
       
  3811 					 EAPL("causes creation of new handler. This EAP-packet is dropped.\n")));
       
  3812 
       
  3813 				EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_AKA_ERROR, (EAPL("ERROR: received:      source"),
       
  3814 					receive_network_id->get_source(),
       
  3815 					receive_network_id->get_source_length()));
       
  3816 				EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_AKA_ERROR, (EAPL("ERROR: received: destination"),
       
  3817 					receive_network_id->get_destination(),
       
  3818 					receive_network_id->get_destination_length()));
       
  3819 
       
  3820 				if (received_aka->get_type() == eap_type_aka)
       
  3821 				{
       
  3822 					EAP_TRACE_DEBUG(
       
  3823 						m_am_tools, 
       
  3824 						TRACE_FLAGS_AKA_ERROR, 
       
  3825 						(EAPL("ERROR: erroneous EAP packet: code=0x%02x, identifier=0x%02x, ")
       
  3826 						 EAPL("length=0x%04x, type=0x%08x, subtype=0x%02x, client %d\n"),
       
  3827 						received_aka->get_code(),
       
  3828 						received_aka->get_identifier(),
       
  3829 						received_aka->get_length(),
       
  3830 						convert_eap_type_to_u32_t(received_aka->get_type()),
       
  3831 						received_aka->get_subtype(),
       
  3832 						is_client_when_true));
       
  3833 				}
       
  3834 				else
       
  3835 				{
       
  3836 					EAP_TRACE_DEBUG(
       
  3837 						m_am_tools, 
       
  3838 						TRACE_FLAGS_AKA_ERROR, 
       
  3839 						(EAPL("ERROR: erroneous EAP packet: code=0x%02x, identifier=0x%02x, ")
       
  3840 						 EAPL("length=0x%04x, type=0x%08x, client %d\n"),
       
  3841 						received_aka->get_code(),
       
  3842 						received_aka->get_identifier(),
       
  3843 						received_aka->get_length(),
       
  3844 						convert_eap_type_to_u32_t(received_aka->get_type()),
       
  3845 						is_client_when_true));
       
  3846 				}
       
  3847 				return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
       
  3848 			}
       
  3849 		}
       
  3850 		else
       
  3851 		{
       
  3852 			EAP_TRACE_DEBUG(
       
  3853 				m_am_tools, 
       
  3854 				TRACE_FLAGS_AKA_ERROR, 
       
  3855 				(EAPL("ERROR: eap_type_aka_c::aka_packet_process(): ")
       
  3856 				 EAPL("Only EAP-identity message in server causes creation ")
       
  3857 				 EAPL("of new handler. This EAP-packet is dropped.\n")));
       
  3858 
       
  3859 			EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_AKA_ERROR, (EAPL("ERROR: received:      source"),
       
  3860 				receive_network_id->get_source(),
       
  3861 				receive_network_id->get_source_length()));
       
  3862 			EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_AKA_ERROR, (EAPL("ERROR: received: destination"),
       
  3863 				receive_network_id->get_destination(),
       
  3864 				receive_network_id->get_destination_length()));
       
  3865 
       
  3866 			if (received_aka->get_type() == eap_type_aka)
       
  3867 			{
       
  3868 				EAP_TRACE_DEBUG(
       
  3869 					m_am_tools, 
       
  3870 					TRACE_FLAGS_AKA_ERROR, 
       
  3871 					(EAPL("ERROR: erroneous EAP packet: code=0x%02x, identifier=0x%02x, ")
       
  3872 					 EAPL("length=0x%04x, type=0x%08x, subtype=0x%02x, client %d\n"),
       
  3873 					received_aka->get_code(),
       
  3874 					received_aka->get_identifier(),
       
  3875 					received_aka->get_length(),
       
  3876 					convert_eap_type_to_u32_t(received_aka->get_type()),
       
  3877 					received_aka->get_subtype(),
       
  3878 					is_client_when_true));
       
  3879 			}
       
  3880 			else
       
  3881 			{
       
  3882 				EAP_TRACE_DEBUG(
       
  3883 					m_am_tools, 
       
  3884 					TRACE_FLAGS_AKA_ERROR, 
       
  3885 					(EAPL("ERROR: erroneous EAP packet: code=0x%02x, identifier=0x%02x, ")
       
  3886 					 EAPL("length=0x%04x, type=0x%08x, client %d\n"),
       
  3887 					received_aka->get_code(),
       
  3888 					received_aka->get_identifier(),
       
  3889 					received_aka->get_length(),
       
  3890 					convert_eap_type_to_u32_t(received_aka->get_type()),
       
  3891 					is_client_when_true));
       
  3892 			}
       
  3893 			return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
       
  3894 		}
       
  3895 	}
       
  3896 
       
  3897 	EAP_TRACE_DEBUG(
       
  3898 		m_am_tools, 
       
  3899 		TRACE_FLAGS_DEFAULT, 
       
  3900 		(EAPL("eap_type_aka_c::aka_packet_process(): state %d=%s\n"),
       
  3901 		 get_state(),
       
  3902 		 get_state_string()));
       
  3903 	EAP_TRACE_DATA_DEBUG(
       
  3904 		m_am_tools, 
       
  3905 		TRACE_FLAGS_DEFAULT, 
       
  3906 		(EAPL("received: AKA packet"),
       
  3907 		 received_aka->get_header_buffer(
       
  3908 			 received_aka->get_header_buffer_length()),
       
  3909 		 received_aka->get_header_buffer_length()));
       
  3910 
       
  3911 	if (received_aka->get_type() == eap_type_identity)
       
  3912 	{
       
  3913 		if (is_client_when_true == true)
       
  3914 		{
       
  3915 			EAP_TRACE_DEBUG(
       
  3916 				m_am_tools, 
       
  3917 				TRACE_FLAGS_AKA_ERROR, 
       
  3918 				(EAPL("ERROR: eap_type_aka_c::aka_packet_process(): ")
       
  3919 				 EAPL("EAP-Request/Identity is not handled here anymore.\n")));
       
  3920 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3921 			status = eap_status_process_general_error;
       
  3922 		}
       
  3923 		else if (is_client_when_true == false)
       
  3924 		{
       
  3925 			eap_header_rd_c eap_header(
       
  3926 				m_am_tools,
       
  3927 				received_aka->get_header_buffer(received_aka->get_header_buffer_length()),
       
  3928 				received_aka->get_header_buffer_length());
       
  3929 
       
  3930 			const eap_type_aka_state_variable_e saved_state = get_state();
       
  3931 
       
  3932 			EAP_UNREFERENCED_PARAMETER(saved_state);
       
  3933 
       
  3934 			status = handle_identity_response_message(
       
  3935 				&eap_header,
       
  3936 				aka_packet_length
       
  3937 				);
       
  3938 
       
  3939 			if (status != eap_status_ok
       
  3940 				&& status != eap_status_success
       
  3941 				&& status != eap_status_drop_packet_quietly)
       
  3942 			{
       
  3943 				eap_status_string_c status_string;
       
  3944 				EAP_UNREFERENCED_PARAMETER(status_string);
       
  3945 				EAP_TRACE_DEBUG(
       
  3946 					m_am_tools, 
       
  3947 					TRACE_FLAGS_AKA_ERROR, 
       
  3948 					(EAPL("ERROR: %s=%d eap_type_aka_c::aka_packet_process(): ")
       
  3949 					 EAPL("handle_identity_response_message().\n"),
       
  3950 					 status_string.get_status_string(status), status));
       
  3951 			}
       
  3952 
       
  3953 			if (status == eap_status_ok)
       
  3954 			{
       
  3955 				eap_state_notification_c notification(
       
  3956 					m_am_tools,
       
  3957 					get_send_network_id(),
       
  3958 					m_is_client,
       
  3959 					eap_state_notification_eap,
       
  3960 					eap_protocol_layer_eap,
       
  3961 					eap_type_aka,
       
  3962 					eap_state_none,
       
  3963 					eap_state_identity_response_received,
       
  3964 					get_last_eap_identifier(),
       
  3965 					false);
       
  3966 				state_notification(&notification);
       
  3967 			}
       
  3968 		}
       
  3969 
       
  3970 		if (status == eap_status_ok
       
  3971 			|| status == eap_status_success)
       
  3972 		{
       
  3973 			// Ok, good EAP message received.
       
  3974 			if (m_is_client == true)
       
  3975 			{
       
  3976 				unset_failure_message_received();
       
  3977 			}
       
  3978 		}
       
  3979 		else
       
  3980 		{
       
  3981 			EAP_TRACE_DEBUG(
       
  3982 				m_am_tools, 
       
  3983 				TRACE_FLAGS_AKA_ERROR, 
       
  3984 				(EAPL("ERROR: eap_type_aka_c::aka_packet_process(): ")
       
  3985 				 EAPL("handle_identity_response_message() failed, status %d.\n"),
       
  3986 				 status));
       
  3987 		}
       
  3988 
       
  3989 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3990 	}
       
  3991 
       
  3992 	if (aka_packet_length < received_aka->get_header_length())
       
  3993 	{
       
  3994 		EAP_TRACE_DEBUG(
       
  3995 			m_am_tools,
       
  3996 			TRACE_FLAGS_AKA_ERROR,
       
  3997 			(EAPL("ERROR: eap_type_aka_c::aka_packet_process(): ")
       
  3998 			 EAPL("aka_packet_length < aka_header_c::get_header_length().\n")));
       
  3999 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4000 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  4001 	}
       
  4002 
       
  4003 	status = received_aka->check_header();
       
  4004 	if (status != eap_status_ok)
       
  4005 	{
       
  4006 		eap_status_string_c status_string;
       
  4007 		EAP_TRACE_DEBUG(
       
  4008 			m_am_tools,
       
  4009 			TRACE_FLAGS_AKA_ERROR,
       
  4010 			(EAPL("ERROR: %s=%d eap_type_aka_c::aka_packet_process(): corrupted AKA-header.\n"),
       
  4011 			status_string.get_status_string(status), status));
       
  4012 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4013 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4014 	}
       
  4015 
       
  4016 	EAP_TRACE_DEBUG(
       
  4017 		m_am_tools, 
       
  4018 		TRACE_FLAGS_DEFAULT, 
       
  4019 		(EAPL("received: handler 0x%08x, AKA-type %10s, %s, state %2d=%s\n"),
       
  4020 		 this,
       
  4021 		 received_aka->get_subtype_string(),
       
  4022 		 (get_is_client()) ? EAPL("client") : EAPL("server"),
       
  4023 		 get_state(),
       
  4024 		 get_state_string()
       
  4025 		 ));
       
  4026 
       
  4027 	aka_payloads_c * const l_aka_payloads = new aka_payloads_c(m_am_tools);
       
  4028 	eap_automatic_variable_c<aka_payloads_c> l_aka_payloads_automatic(m_am_tools, l_aka_payloads);
       
  4029 
       
  4030 	if (l_aka_payloads == 0
       
  4031 		|| l_aka_payloads->get_is_valid() == false)
       
  4032 	{
       
  4033 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4034 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4035 	}
       
  4036 
       
  4037 	status = handle_aka_packet(
       
  4038 		receive_network_id,
       
  4039 		received_aka,
       
  4040 		aka_packet_length,
       
  4041 		l_aka_payloads);
       
  4042 
       
  4043 	if (status != eap_status_ok
       
  4044 		&& status != eap_status_success
       
  4045 		&& status != eap_status_drop_packet_quietly
       
  4046 		&& status != eap_status_pending_request)
       
  4047 	{
       
  4048 		eap_status_string_c status_string;
       
  4049 		EAP_UNREFERENCED_PARAMETER(status_string);
       
  4050 		EAP_TRACE_DEBUG(
       
  4051 			m_am_tools, 
       
  4052 			TRACE_FLAGS_AKA_ERROR, 
       
  4053 			(EAPL("ERROR: %s=%d eap_type_aka_c::aka_packet_process(): handle_aka_packet().\n"),
       
  4054 			status_string.get_status_string(status), status));
       
  4055 	}
       
  4056 
       
  4057 	if (status == eap_status_ok
       
  4058 		|| status == eap_status_success
       
  4059 		|| status == eap_status_pending_request)
       
  4060 	{
       
  4061 		// Ok, good EAP message received.
       
  4062 		if (m_is_client == true)
       
  4063 		{
       
  4064 			unset_failure_message_received();
       
  4065 		}
       
  4066 	}
       
  4067 
       
  4068 	if (status == eap_status_ok)
       
  4069 	{
       
  4070 		// Do nothing special.
       
  4071 	}
       
  4072 	else if (status == eap_status_drop_packet_quietly)
       
  4073 	{
       
  4074 		// We will drop this message quietly.
       
  4075 	}
       
  4076 	else if (status != eap_status_ok)
       
  4077 	{
       
  4078 		// EAP-Failure will be sent from shutdown().
       
  4079 	}
       
  4080 
       
  4081 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4082 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4083 }
       
  4084 
       
  4085 //--------------------------------------------------
       
  4086 
       
  4087 //
       
  4088 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::cancel_error_message_delay_timer()
       
  4089 {
       
  4090 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4091 
       
  4092 	eap_status_e status = cancel_timer(
       
  4093 		this,
       
  4094 		EAP_TYPE_AKA_TIMER_DELAY_FAILURE_MESSAGE_SENT_ID);
       
  4095 
       
  4096 	m_erroneus_packet_received = false;
       
  4097 
       
  4098 	EAP_TRACE_DEBUG(
       
  4099 		m_am_tools, 
       
  4100 		TRACE_FLAGS_DEFAULT, 
       
  4101 		(EAPL("TIMER: %s: EAP_TYPE_TIMER_DELAY_FAILURE_MESSAGE_SENT_ID cancelled.\n"),
       
  4102 		 (m_is_client == true) ? "client": "server"));
       
  4103 
       
  4104 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4105 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4106 }
       
  4107 
       
  4108 //--------------------------------------------------
       
  4109 
       
  4110 //
       
  4111 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::set_error_message_delay_timer()
       
  4112 {
       
  4113 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4114 
       
  4115 	eap_status_e status = set_timer(
       
  4116 		this,
       
  4117 		EAP_TYPE_AKA_TIMER_DELAY_FAILURE_MESSAGE_SENT_ID,
       
  4118 		0,
       
  4119 		m_failure_message_delay_time);
       
  4120 
       
  4121 	EAP_TRACE_DEBUG(
       
  4122 		m_am_tools, 
       
  4123 		TRACE_FLAGS_DEFAULT, 
       
  4124 		(EAPL("TIMER: %s: EAP_TYPE_TIMER_DELAY_FAILURE_MESSAGE_SENT_ID set.\n"),
       
  4125 		 (m_is_client == true) ? "client": "server"));
       
  4126 
       
  4127 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4128 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4129 }
       
  4130 
       
  4131 //--------------------------------------------------
       
  4132 
       
  4133 //
       
  4134 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::cancel_notification_message_delay_timer()
       
  4135 {
       
  4136 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4137 
       
  4138 	eap_status_e status = cancel_timer(
       
  4139 		this,
       
  4140 		EAP_TYPE_AKA_TIMER_DELAY_NOTIFICATION_MESSAGE_ID);
       
  4141 
       
  4142 	m_erroneus_packet_received = false;
       
  4143 
       
  4144 	EAP_TRACE_DEBUG(
       
  4145 		m_am_tools, 
       
  4146 		TRACE_FLAGS_DEFAULT, 
       
  4147 		(EAPL("TIMER: %s: EAP_TYPE_TIMER_DELAY_NOTIFICATION_MESSAGE_ID cancelled.\n"),
       
  4148 		 (m_is_client == true) ? "client": "server"));
       
  4149 
       
  4150 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4151 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4152 }
       
  4153 
       
  4154 //--------------------------------------------------
       
  4155 
       
  4156 //
       
  4157 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::set_notification_message_delay_timer()
       
  4158 {
       
  4159 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4160 
       
  4161 	eap_status_e status = set_timer(
       
  4162 		this,
       
  4163 		EAP_TYPE_AKA_TIMER_DELAY_NOTIFICATION_MESSAGE_ID,
       
  4164 		0,
       
  4165 		m_failure_message_delay_time);
       
  4166 
       
  4167 	EAP_TRACE_DEBUG(
       
  4168 		m_am_tools, 
       
  4169 		TRACE_FLAGS_DEFAULT, 
       
  4170 		(EAPL("TIMER: %s: EAP_TYPE_TIMER_DELAY_NOTIFICATION_MESSAGE_ID set.\n"),
       
  4171 		 (m_is_client == true) ? "client": "server"));
       
  4172 
       
  4173 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4174 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4175 }
       
  4176 
       
  4177 //--------------------------------------------------
       
  4178 
       
  4179 //
       
  4180 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::handle_error_packet()
       
  4181 {
       
  4182 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4183 
       
  4184 	eap_status_e status = eap_status_process_general_error;
       
  4185 
       
  4186 	EAP_TRACE_DEBUG(
       
  4187 		m_am_tools, 
       
  4188 		TRACE_FLAGS_AKA_ERROR, 
       
  4189 		(EAPL("ERROR: eap_type_aka_c::handle_error_packet(): ")
       
  4190 		 EAPL("erroneus_packet_received %d, m_client_error_code %d\n"),
       
  4191 		 m_erroneus_packet_received,
       
  4192 		 m_client_error_code));
       
  4193 
       
  4194 	if (m_erroneus_packet_received == true)
       
  4195 	{
       
  4196 		set_state(eap_type_aka_state_failure);
       
  4197 
       
  4198 		if (m_is_client == true)
       
  4199 		{
       
  4200 			// Client will send EAP-Response/AKA/Client-Error.
       
  4201 			status = send_aka_client_error_response();
       
  4202 		}
       
  4203 		else
       
  4204 		{
       
  4205 			// Server will send EAP-Failure.
       
  4206 			// Notifies the lower level of unsuccessfull authentication.
       
  4207 			eap_state_notification_c notification(
       
  4208 				m_am_tools,
       
  4209 				get_send_network_id(),
       
  4210 				m_is_client,
       
  4211 				eap_state_notification_eap,
       
  4212 				eap_protocol_layer_eap,
       
  4213 				eap_type_aka,
       
  4214 				eap_state_none,
       
  4215 				eap_state_authentication_terminated_unsuccessfully,
       
  4216 				get_last_eap_identifier(),
       
  4217 				false);
       
  4218 
       
  4219 			notification.set_authentication_error(eap_status_authentication_failure);
       
  4220 
       
  4221 			state_notification(&notification);
       
  4222 
       
  4223 			status = eap_status_ok;
       
  4224 		}
       
  4225 	}
       
  4226 	else
       
  4227 	{
       
  4228 		// One erroneous packet is already received.
       
  4229 		EAP_TRACE_DEBUG(
       
  4230 			m_am_tools, 
       
  4231 			TRACE_FLAGS_AKA_ERROR, 
       
  4232 			(EAPL("WARNING: eap_type_aka_c::handle_error_packet(): one erroneus packet already received. This is ignored.\n")));
       
  4233 		status = eap_status_ok;
       
  4234 	}
       
  4235 
       
  4236 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4237 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4238 }
       
  4239 
       
  4240 //--------------------------------------------------
       
  4241 
       
  4242 //
       
  4243 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::initialize_error_message(
       
  4244 	const eap_status_e error_status)
       
  4245 {
       
  4246 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4247 
       
  4248 	eap_status_e status = eap_status_process_general_error;
       
  4249 
       
  4250 	eap_status_string_c status_string;
       
  4251 	EAP_UNREFERENCED_PARAMETER(status_string);
       
  4252 
       
  4253 	EAP_TRACE_DEBUG(
       
  4254 		m_am_tools, 
       
  4255 		TRACE_FLAGS_AKA_ERROR, 
       
  4256 		(EAPL("ERROR: eap_type_aka_c::initialize_error_message(): erroneus_packet_received %d, error_status %s\n"),
       
  4257 		 m_erroneus_packet_received,
       
  4258 		 status_string.get_status_string(error_status)));
       
  4259 
       
  4260 	if (m_erroneus_packet_received == false)
       
  4261 	{
       
  4262 		// Only the first erroneus packet is recorded.
       
  4263 		m_erroneus_packet_received = true;
       
  4264 
       
  4265 		if (m_is_client == true)
       
  4266 		{
       
  4267 			// Client will send EAP-Response/AKA/Client-Error.
       
  4268 			switch(error_status)
       
  4269 			{
       
  4270 			case eap_status_no_matching_protocol_version:
       
  4271 				m_client_error_code = eap_aka_client_error_code_unsupported_version;
       
  4272 				break;
       
  4273 			case eap_status_not_enough_challenges:
       
  4274 				m_client_error_code = eap_aka_client_error_code_insufficient_number_of_challenges;
       
  4275 				break;
       
  4276 			case eap_status_not_fresh_challenges:
       
  4277 				m_client_error_code = eap_aka_client_error_code_rands_are_not_fresh;
       
  4278 				break;
       
  4279 			default:
       
  4280 				m_client_error_code = eap_aka_client_error_code_unable_to_process_packet;
       
  4281 				break;
       
  4282 			};
       
  4283 		}
       
  4284 		else
       
  4285 		{
       
  4286 			// Server will send EAP-Failure.
       
  4287 		}
       
  4288 
       
  4289 		if (m_failure_message_delay_time > 0ul)
       
  4290 		{
       
  4291 			// First try set delay timer.
       
  4292 			status = set_error_message_delay_timer();
       
  4293 			if (status != eap_status_ok)
       
  4294 			{
       
  4295 				// ERROR: Process error packet immediately.
       
  4296 				status = handle_error_packet();
       
  4297 			}
       
  4298 		}
       
  4299 		else
       
  4300 		{
       
  4301 			// Process error packet immediately.
       
  4302 			status = handle_error_packet();
       
  4303 		}
       
  4304 	}
       
  4305 	else
       
  4306 	{
       
  4307 		// Error packet is already processed.
       
  4308 		status = eap_status_ok;
       
  4309 	}
       
  4310 
       
  4311 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4312 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4313 }
       
  4314 
       
  4315 //--------------------------------------------------
       
  4316 
       
  4317 //
       
  4318 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::handle_notification_packet()
       
  4319 {
       
  4320 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4321 
       
  4322 	eap_status_e status = eap_status_process_general_error;
       
  4323 
       
  4324 	EAP_TRACE_DEBUG(
       
  4325 		m_am_tools, 
       
  4326 		TRACE_FLAGS_DEFAULT, 
       
  4327 		(EAPL("eap_type_aka_c::handle_notification_packet(): aka_notification_packet_received %d\n"),
       
  4328 		 m_aka_notification_packet_received));
       
  4329 
       
  4330 	if (m_aka_notification_packet_received == true)
       
  4331 	{
       
  4332 		bool add_at_counter_attribute = false;
       
  4333 		if (m_authentication_type == AKA_AUTHENTICATION_TYPE_REAUTHENTICATION)
       
  4334 		{
       
  4335 			add_at_counter_attribute = true;
       
  4336 		}
       
  4337 
       
  4338 		if (m_is_client == true)
       
  4339 		{
       
  4340 			// Client will send EAP-Response/AKA/Notification.
       
  4341 			if (get_aka_notification_code_F_bit(m_aka_notification_code) == false)
       
  4342 			{
       
  4343 				// The code values with the F bit set to zero (code values 0...32767)
       
  4344 				// are used on unsuccessful cases.
       
  4345 				// The receipt of a notification code from this range implies failed EAP
       
  4346 				// exchange, so the peer can use the notification as a failure indication.
       
  4347 				set_state(eap_type_aka_state_failure);
       
  4348 			}
       
  4349 
       
  4350 			status = send_aka_notification_response(
       
  4351 				m_aka_notification_code,
       
  4352 				add_at_counter_attribute);
       
  4353 		}
       
  4354 		else
       
  4355 		{
       
  4356 			set_state(eap_type_aka_state_waiting_for_notification_response_failure);
       
  4357 
       
  4358 			// Server will send EAP-Request/AKA/Notification.
       
  4359 			status = send_aka_notification_request(
       
  4360 				m_aka_notification_code,
       
  4361 				add_at_counter_attribute);
       
  4362 		}
       
  4363 	}
       
  4364 	else
       
  4365 	{
       
  4366 		EAP_TRACE_DEBUG(
       
  4367 			m_am_tools, 
       
  4368 			TRACE_FLAGS_DEFAULT, 
       
  4369 			(EAPL("eap_type_aka_c::handle_notification_packet(): one AKA/Notification packet already received. This is ignored.\n")));
       
  4370 
       
  4371 		status = eap_status_ok;
       
  4372 	}
       
  4373 
       
  4374 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4375 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4376 }
       
  4377 
       
  4378 //--------------------------------------------------
       
  4379 
       
  4380 //
       
  4381 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::initialize_notification_message()
       
  4382 {
       
  4383 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4384 
       
  4385 	eap_status_e status = eap_status_process_general_error;
       
  4386 
       
  4387 	if (m_aka_notification_packet_received == false)
       
  4388 	{
       
  4389 		// Only the first AKA notification packet is recorded.
       
  4390 		m_aka_notification_packet_received = true;
       
  4391 
       
  4392 		if (m_is_client == true)
       
  4393 		{
       
  4394 			// Client will send empty EAP-Response/AKA/Notification.
       
  4395 		}
       
  4396 		else
       
  4397 		{
       
  4398 			// Server will send EAP-Request/AKA/Notification.
       
  4399 			if (m_aka_notification_code == eap_aka_notification_none)
       
  4400 			{
       
  4401 				m_aka_notification_code = eap_aka_notification_no_F_P_set_general_failure;
       
  4402 			}
       
  4403 
       
  4404 			EAP_TRACE_DEBUG(
       
  4405 				m_am_tools, 
       
  4406 				TRACE_FLAGS_DEFAULT, 
       
  4407 				(EAPL("eap_type_aka_c::initialize_notification_message(0x%08x), notification_code = 0x%04x, F bit %d, P bit %d.\n"),
       
  4408 				 this,
       
  4409 				 m_aka_notification_code,
       
  4410 				 get_aka_notification_code_F_bit(m_aka_notification_code),
       
  4411 				 get_aka_notification_code_P_bit(m_aka_notification_code)));
       
  4412 		}
       
  4413 
       
  4414 		if (m_failure_message_delay_time > 0ul)
       
  4415 		{
       
  4416 			// First try set delay timer.
       
  4417 			status = set_notification_message_delay_timer();
       
  4418 			if (status != eap_status_ok)
       
  4419 			{
       
  4420 				// ERROR: Process AKA notification packet immediately.
       
  4421 				status = handle_notification_packet();
       
  4422 			}
       
  4423 		}
       
  4424 		else
       
  4425 		{
       
  4426 			// Process AKA notification packet immediately.
       
  4427 			status = handle_notification_packet();
       
  4428 		}
       
  4429 	}
       
  4430 	else
       
  4431 	{
       
  4432 		// AKA notification packet is already processed.
       
  4433 		status = eap_status_ok;
       
  4434 	}
       
  4435 
       
  4436 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4437 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4438 }
       
  4439 
       
  4440 //--------------------------------------------------
       
  4441 
       
  4442 //
       
  4443 EAP_FUNC_EXPORT u32_t eap_type_aka_c::get_header_offset(
       
  4444 	u32_t * const MTU,
       
  4445 	u32_t * const trailer_length)
       
  4446 {
       
  4447 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4448 
       
  4449 	u32_t offset = get_type_partner()->get_header_offset(MTU, trailer_length);
       
  4450 
       
  4451 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4452 	return offset;
       
  4453 }
       
  4454 
       
  4455 //--------------------------------------------------
       
  4456 
       
  4457 //
       
  4458 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::extra_message_authentication_code_bytes(
       
  4459 	const aka_subtype_e subtype,
       
  4460 	const eap_code_value_e code,
       
  4461 	crypto_hmac_c *hmac_sha1)
       
  4462 {
       
  4463 	if (code == eap_code_request)
       
  4464 	{
       
  4465 	}
       
  4466 	else if (code == eap_code_response)
       
  4467 	{
       
  4468 		if (subtype == aka_subtype_Re_authentication)
       
  4469 		{
       
  4470 			eap_status_e status = hmac_sha1->hmac_update(
       
  4471 				get_NONCE_S()->get_data(get_NONCE_S()->get_data_length()),
       
  4472 				get_NONCE_S()->get_data_length());
       
  4473 			if (status != eap_status_ok)
       
  4474 			{
       
  4475 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4476 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4477 			}
       
  4478 		}
       
  4479 	}
       
  4480 	else
       
  4481 	{
       
  4482 		EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_AKA_ERROR, (EAPL("ERROR: extra_message_authentication_code_bytes(): unsupported EAP-Code %d.\n"),
       
  4483 			code));
       
  4484 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4485 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  4486 	}
       
  4487 
       
  4488 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  4489 }
       
  4490 
       
  4491 //--------------------------------------------------
       
  4492 
       
  4493 //
       
  4494 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::create_message_authentication_code(
       
  4495 	eap_type_aka_MAC_attributes_c *MAC_attributes,
       
  4496 	const aka_subtype_e subtype,
       
  4497 	const eap_code_value_e code,
       
  4498 	const eap_variable_data_c * const authentication_key
       
  4499 )
       
  4500 {
       
  4501 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4502 
       
  4503 	if (MAC_attributes == 0
       
  4504 		|| authentication_key == 0
       
  4505 		|| authentication_key->get_is_valid_data() == false
       
  4506 		|| MAC_attributes->get_data() == 0
       
  4507 		|| MAC_attributes->get_data_length() == 0u
       
  4508 		|| MAC_attributes->get_MAC() == 0)
       
  4509 	{
       
  4510 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4511 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  4512 	}
       
  4513 
       
  4514 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, (EAPL("authentication_key"),
       
  4515 		authentication_key->get_data(authentication_key->get_data_length()),
       
  4516 		authentication_key->get_data_length()));
       
  4517 
       
  4518 	eap_status_e status = eap_status_process_general_error;
       
  4519 
       
  4520 #if defined(USE_EAP_TRACE)
       
  4521 	{
       
  4522 		eap_variable_data_c buffer(m_am_tools);
       
  4523 
       
  4524 		if (buffer.get_is_valid() == false)
       
  4525 		{
       
  4526 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4527 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4528 		}
       
  4529 
       
  4530 		status = buffer.set_buffer_length(2048);
       
  4531 		if (status != eap_status_ok)
       
  4532 		{
       
  4533 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4534 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  4535 		}
       
  4536 
       
  4537 		status = buffer.set_buffer_length(buffer.get_buffer_length());
       
  4538 		if (status != eap_status_ok)
       
  4539 		{
       
  4540 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4541 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  4542 		}
       
  4543 
       
  4544 		u8_t * const tmpbuffer = buffer.get_data(buffer.get_data_length());
       
  4545 		if (tmpbuffer == 0)
       
  4546 		{
       
  4547 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4548 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4549 		}
       
  4550 
       
  4551 		u32_t offset = 0;
       
  4552 
       
  4553 		m_am_tools->memmove(tmpbuffer+offset,
       
  4554 			(MAC_attributes->get_data()),
       
  4555 			MAC_attributes->get_data_length());
       
  4556 		offset += MAC_attributes->get_data_length();
       
  4557 
       
  4558 		if (code == eap_code_request)
       
  4559 		{
       
  4560 		}
       
  4561 		else if (code == eap_code_response)
       
  4562 		{
       
  4563 			if (subtype == aka_subtype_Re_authentication)
       
  4564 			{
       
  4565 				m_am_tools->memmove(tmpbuffer+offset,
       
  4566 					get_NONCE_S()->get_data(get_NONCE_S()->get_data_length()),
       
  4567 					get_NONCE_S()->get_data_length());
       
  4568 				offset += get_NONCE_S()->get_data_length();
       
  4569 			}
       
  4570 		}
       
  4571 		else
       
  4572 		{
       
  4573 			EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_AKA_ERROR, (EAPL("ERROR: extra_message_authentication_code_bytes(): unsupported EAP-Code %d.\n"),
       
  4574 				code));
       
  4575 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4576 			return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  4577 		}
       
  4578 
       
  4579 		EAP_TRACE_DEBUG(
       
  4580 			m_am_tools, 
       
  4581 			TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
  4582 			(EAPL("create_message_authentication_code(): MAC calculated over the following bytes:\n")));
       
  4583 		EAP_TRACE_DATA_DEBUG(
       
  4584 			m_am_tools, 
       
  4585 			TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
  4586 			(EAPL("MAC data"),
       
  4587 			 tmpbuffer,
       
  4588 			 offset));
       
  4589 	}
       
  4590 #endif // #if defined(USE_EAP_TRACE)
       
  4591 
       
  4592 
       
  4593 	crypto_sha1_c sha1(m_am_tools);
       
  4594 	crypto_hmac_c hmac_sha1(m_am_tools, &sha1, false);
       
  4595 
       
  4596 	if (hmac_sha1.get_is_valid() == false)
       
  4597 	{
       
  4598 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4599 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4600 	}
       
  4601 
       
  4602 	if (hmac_sha1.hmac_set_key(
       
  4603 		authentication_key
       
  4604 		) != eap_status_ok)
       
  4605 	{
       
  4606 		EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_AKA_ERROR, (EAPL("ERROR: create_message_authentication_code(): set_key() failed.\n")));
       
  4607 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4608 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4609 	}
       
  4610 
       
  4611 	status = hmac_sha1.hmac_update(
       
  4612 		MAC_attributes->get_data(),
       
  4613 		MAC_attributes->get_data_length());
       
  4614 		if (status != eap_status_ok)
       
  4615 		{
       
  4616 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4617 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  4618 		}
       
  4619 
       
  4620 	status = extra_message_authentication_code_bytes(subtype, code, &hmac_sha1);
       
  4621 	if (status != eap_status_ok)
       
  4622 	{
       
  4623 		eap_status_string_c status_string;
       
  4624 		EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_AKA_ERROR, (EAPL("ERROR: %s=%d create_message_authentication_code(): extra_message_authentication_code_bytes().\n"),
       
  4625 			status_string.get_status_string(status), status));
       
  4626 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4627 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  4628 	}
       
  4629 
       
  4630 	u32_t length = 0u;
       
  4631 
       
  4632 	status = hmac_sha1.hmac_128_final(
       
  4633 		MAC_attributes->get_MAC(),
       
  4634 		&length);
       
  4635 	if (status != eap_status_ok
       
  4636 		|| length != EAP_TYPE_AKA_MAC_SIZE)
       
  4637 	{
       
  4638 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4639 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4640 	}
       
  4641 
       
  4642 	EAP_ASSERT(length == EAP_TYPE_AKA_MAC_SIZE);
       
  4643 
       
  4644 	EAP_TRACE_DEBUG(
       
  4645 		m_am_tools, 
       
  4646 		TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
  4647 		(EAPL("MAC:\n")));
       
  4648 	EAP_TRACE_DATA_DEBUG(
       
  4649 		m_am_tools, 
       
  4650 		TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
  4651 		(EAPL("MAC"),
       
  4652 		 MAC_attributes->get_MAC(),
       
  4653 		 length));
       
  4654 
       
  4655 
       
  4656 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4657 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  4658 }
       
  4659 
       
  4660 //--------------------------------------------------
       
  4661 
       
  4662 //
       
  4663 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::check_message_authentication_code(
       
  4664 	const eap_variable_data_c * const authentication_key,
       
  4665 	aka_payloads_c * const p_aka_payloads,
       
  4666 	const aka_header_c * const aka_packet,
       
  4667 	const u32_t aka_packet_length)
       
  4668 {
       
  4669 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4670 
       
  4671 	if (authentication_key == 0
       
  4672 		|| authentication_key->get_is_valid_data() == false)
       
  4673 	{
       
  4674 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4675 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  4676 	}
       
  4677 	if (p_aka_payloads->get_MAC() == 0
       
  4678 		|| p_aka_payloads->get_MAC()->get_payload_included() == false)
       
  4679 	{
       
  4680 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4681 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  4682 	}
       
  4683 	if (aka_packet == 0
       
  4684 		|| aka_packet_length == 0)
       
  4685 	{
       
  4686 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4687 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  4688 	}
       
  4689 
       
  4690 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, (EAPL("authentication_key"),
       
  4691 		authentication_key->get_data(authentication_key->get_data_length()),
       
  4692 		authentication_key->get_data_length()));
       
  4693 
       
  4694 	crypto_sha1_c sha1(m_am_tools);
       
  4695 	crypto_hmac_c hmac_sha1(m_am_tools, &sha1, false);
       
  4696 
       
  4697 	if (hmac_sha1.get_is_valid() == false)
       
  4698 	{
       
  4699 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4700 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4701 	}
       
  4702 
       
  4703 	if (hmac_sha1.hmac_set_key(
       
  4704 		authentication_key
       
  4705 		) != eap_status_ok)
       
  4706 	{
       
  4707 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4708 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4709 	}
       
  4710 
       
  4711 	u8_t saved_MAC[EAP_TYPE_AKA_MAC_SIZE];
       
  4712 
       
  4713 	m_am_tools->memmove(
       
  4714 		saved_MAC,
       
  4715 		p_aka_payloads->get_MAC()->get_data(p_aka_payloads->get_MAC()->get_data_length()),
       
  4716 		p_aka_payloads->get_MAC()->get_data_length());
       
  4717 
       
  4718 	m_am_tools->memset(
       
  4719 		p_aka_payloads->get_MAC()->get_data(p_aka_payloads->get_MAC()->get_data_length()),
       
  4720 		0,
       
  4721 		p_aka_payloads->get_MAC()->get_data_length());
       
  4722 
       
  4723 
       
  4724 	eap_status_e status = hmac_sha1.hmac_update(
       
  4725 		aka_packet->get_header_buffer(aka_packet_length),
       
  4726 		aka_packet_length);
       
  4727 	if (status != eap_status_ok)
       
  4728 	{
       
  4729 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4730 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4731 	}
       
  4732 
       
  4733 	status = extra_message_authentication_code_bytes(
       
  4734 		aka_packet->get_subtype(),
       
  4735 		aka_packet->get_code(),
       
  4736 		&hmac_sha1);
       
  4737 	if (status != eap_status_ok)
       
  4738 	{
       
  4739 		eap_status_string_c status_string;
       
  4740 		EAP_TRACE_ERROR(
       
  4741 			m_am_tools,
       
  4742 			TRACE_FLAGS_AKA_ERROR,
       
  4743 			(EAPL("ERROR: %s=%d check_message_authentication_code(): extra_message_authentication_code_bytes().\n"),
       
  4744 			status_string.get_status_string(status), status));
       
  4745 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4746 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  4747 	}
       
  4748 
       
  4749 
       
  4750 	eap_variable_data_c *end_of_authentication = 0;
       
  4751 	if (p_aka_payloads->get_MAC()->get_payload_included() == true)
       
  4752 	{
       
  4753 		end_of_authentication = p_aka_payloads->get_MAC()->get_payload_buffer();
       
  4754 	}
       
  4755 	else
       
  4756 	{
       
  4757 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4758 		return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure);
       
  4759 	}
       
  4760 
       
  4761 
       
  4762 	u32_t length = 0u;
       
  4763 
       
  4764 	eap_variable_data_c tmp_MAC(m_am_tools);
       
  4765 
       
  4766 	if (tmp_MAC.get_is_valid() == false)
       
  4767 	{
       
  4768 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4769 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4770 	}
       
  4771 
       
  4772 	status = tmp_MAC.init(EAP_TYPE_AKA_MAC_SIZE);
       
  4773 	if (status != eap_status_ok)
       
  4774 	{
       
  4775 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4776 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4777 	}
       
  4778 	tmp_MAC.set_is_valid();
       
  4779 	tmp_MAC.set_data_length(EAP_TYPE_AKA_MAC_SIZE);
       
  4780 
       
  4781 	u8_t * const mac_data = tmp_MAC.get_data_offset(0u, EAP_TYPE_AKA_MAC_SIZE);
       
  4782 	if (mac_data == 0)
       
  4783 	{
       
  4784 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4785 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4786 	}
       
  4787 
       
  4788 	status = hmac_sha1.hmac_128_final(
       
  4789 		mac_data,
       
  4790 		&length);
       
  4791 	if (status != eap_status_ok
       
  4792 		|| length != EAP_TYPE_AKA_MAC_SIZE)
       
  4793 	{
       
  4794 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4795 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4796 	}
       
  4797 
       
  4798 	EAP_ASSERT(length == EAP_TYPE_AKA_MAC_SIZE);
       
  4799 
       
  4800 
       
  4801 
       
  4802 #if defined(USE_EAP_TRACE)
       
  4803 	{
       
  4804 		eap_variable_data_c buffer(m_am_tools);
       
  4805 
       
  4806 		if (buffer.get_is_valid() == false)
       
  4807 		{
       
  4808 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4809 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4810 		}
       
  4811 
       
  4812 		status = buffer.set_buffer_length(2048);
       
  4813 		if (status != eap_status_ok)
       
  4814 		{
       
  4815 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4816 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  4817 		}
       
  4818 
       
  4819 		status = buffer.set_buffer_length(buffer.get_buffer_length());
       
  4820 		if (status != eap_status_ok)
       
  4821 		{
       
  4822 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4823 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  4824 		}
       
  4825 
       
  4826 		u8_t * const tmpbuffer = buffer.get_data(buffer.get_data_length());
       
  4827 		if (tmpbuffer == 0)
       
  4828 		{
       
  4829 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4830 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4831 		}
       
  4832 
       
  4833 		u32_t offset = 0;
       
  4834 
       
  4835 		m_am_tools->memmove(tmpbuffer+offset,
       
  4836 			aka_packet->get_header_buffer(aka_packet_length),
       
  4837 			aka_packet_length);
       
  4838 		offset += aka_packet_length;
       
  4839 
       
  4840 		if (aka_packet->get_code() == eap_code_request)
       
  4841 		{
       
  4842 		}
       
  4843 		else if (aka_packet->get_code() == eap_code_response)
       
  4844 		{
       
  4845 			if (aka_packet->get_subtype() == aka_subtype_Re_authentication)
       
  4846 			{
       
  4847 				m_am_tools->memmove(tmpbuffer+offset,
       
  4848 					get_NONCE_S()->get_data(get_NONCE_S()->get_data_length()),
       
  4849 					get_NONCE_S()->get_data_length());
       
  4850 				offset += get_NONCE_S()->get_data_length();
       
  4851 			}
       
  4852 		}
       
  4853 		else
       
  4854 		{
       
  4855 			EAP_TRACE_ERROR(
       
  4856 				m_am_tools,
       
  4857 				TRACE_FLAGS_AKA_ERROR,
       
  4858 				(EAPL("ERROR: extra_message_authentication_code_bytes(): unsupported EAP-Code %d.\n"),
       
  4859 				aka_packet->get_code()));
       
  4860 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4861 			return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  4862 		}
       
  4863 
       
  4864 		EAP_TRACE_DEBUG(
       
  4865 			m_am_tools, 
       
  4866 			TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
  4867 			(EAPL("check_message_authentication_code(): MAC calculated over the following bytes:\n")));
       
  4868 		EAP_TRACE_DATA_DEBUG(
       
  4869 			m_am_tools, 
       
  4870 			TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
  4871 			(EAPL("MAC data"),
       
  4872 			 tmpbuffer,
       
  4873 			 offset));
       
  4874 
       
  4875 		EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, (EAPL("MAC:\n")));
       
  4876 		EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, (EAPL("MAC"),
       
  4877 			tmp_MAC.get_data(tmp_MAC.get_data_length()),
       
  4878 			tmp_MAC.get_data_length()));
       
  4879 	}
       
  4880 #endif // #if defined(USE_EAP_TRACE)
       
  4881 
       
  4882 
       
  4883 	if (length != end_of_authentication->get_data_length()
       
  4884 		|| tmp_MAC.get_data_length()
       
  4885 			!= end_of_authentication->get_data_length())
       
  4886 	{
       
  4887 		EAP_TRACE_DEBUG(
       
  4888 			m_am_tools, 
       
  4889 			TRACE_FLAGS_EAP_AM_CRYPTO|TRACE_FLAGS_AKA_ERROR|TRACE_TEST_VECTORS, 
       
  4890 			(EAPL("ERROR: MAC differs.\n")));
       
  4891 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4892 		return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure);
       
  4893 	}
       
  4894 
       
  4895 	if (m_am_tools->memcmp(
       
  4896 			tmp_MAC.get_data(tmp_MAC.get_data_length()),
       
  4897 			saved_MAC,
       
  4898 			tmp_MAC.get_data_length()) != 0)
       
  4899 	{
       
  4900 		EAP_TRACE_DEBUG(
       
  4901 			m_am_tools, 
       
  4902 			TRACE_FLAGS_EAP_AM_CRYPTO|TRACE_FLAGS_AKA_ERROR|TRACE_TEST_VECTORS, 
       
  4903 			(EAPL("ERROR: MAC differs.\n")));
       
  4904 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4905 		return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure);
       
  4906 	}
       
  4907 
       
  4908 	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, (EAPL("MAC OK.\n")));
       
  4909 
       
  4910 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4911 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  4912 }
       
  4913 
       
  4914 //--------------------------------------------------
       
  4915 
       
  4916 //
       
  4917 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::timer_expired(
       
  4918 	const u32_t id, void *data)
       
  4919 {
       
  4920 	EAP_UNREFERENCED_PARAMETER(id);
       
  4921 	EAP_UNREFERENCED_PARAMETER(data);
       
  4922 
       
  4923 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4924 
       
  4925 	EAP_TRACE_DEBUG(
       
  4926 		m_am_tools, 
       
  4927 		TRACE_FLAGS_DEFAULT, 
       
  4928 		(EAPL("TIMER: [0x%08x]->eap_type_aka_c::timer_expired(id 0x%02x, data 0x%08x).\n"),
       
  4929 		this, id, data));
       
  4930 
       
  4931 	eap_status_e status = eap_status_process_general_error;
       
  4932 
       
  4933 	if (id == EAP_TYPE_AKA_TIMER_DELAY_FAILURE_MESSAGE_SENT_ID)
       
  4934 	{
       
  4935 		EAP_TRACE_DEBUG(
       
  4936 			m_am_tools, 
       
  4937 			TRACE_FLAGS_DEFAULT, 
       
  4938 			(EAPL("TIMER: %s: EAP_TYPE_TIMER_DELAY_FAILURE_MESSAGE_SENT_ID elapsed.\n"),
       
  4939 			 (m_is_client == true) ? "client": "server"));
       
  4940 
       
  4941 		if (get_state() == eap_type_aka_state_failure)
       
  4942 		{
       
  4943 			// Athentication is already failed.
       
  4944 
       
  4945 			// We set the session timeout to zero.
       
  4946 			// This will terminate this session immediately.
       
  4947 			status = get_type_partner()->set_session_timeout(0ul);
       
  4948 		}
       
  4949 		else
       
  4950 		{
       
  4951 			status = handle_error_packet();
       
  4952 		}
       
  4953 	}
       
  4954 	else if (id == EAP_TYPE_AKA_TIMER_DELAY_NOTIFICATION_MESSAGE_ID)
       
  4955 	{
       
  4956 		EAP_TRACE_DEBUG(
       
  4957 			m_am_tools, 
       
  4958 			TRACE_FLAGS_DEFAULT, 
       
  4959 			(EAPL("TIMER: %s: EAP_TYPE_TIMER_DELAY_NOTIFICATION_MESSAGE_ID elapsed.\n"),
       
  4960 			 (m_is_client == true) ? "client": "server"));
       
  4961 
       
  4962 		status = handle_notification_packet();
       
  4963 	}
       
  4964 
       
  4965 
       
  4966 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4967 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4968 }
       
  4969 
       
  4970 //--------------------------------------------------
       
  4971 
       
  4972 //
       
  4973 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::timer_delete_data(
       
  4974 	const u32_t id, void *data)
       
  4975 {
       
  4976 	EAP_UNREFERENCED_PARAMETER(id);
       
  4977 	EAP_UNREFERENCED_PARAMETER(data);
       
  4978 
       
  4979 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4980 
       
  4981 	EAP_TRACE_DEBUG(
       
  4982 		m_am_tools, 
       
  4983 		TRACE_FLAGS_DEFAULT, 
       
  4984 		(EAPL("TIMER: [0x%08x]->eap_type_aka_c::timer_delete_data(id 0x%02x, data 0x%08x).\n"),
       
  4985 		this, id, data));
       
  4986 
       
  4987 	if (id == EAP_TYPE_AKA_TIMER_DELAY_FAILURE_MESSAGE_SENT_ID)
       
  4988 	{
       
  4989 		EAP_TRACE_DEBUG(
       
  4990 			m_am_tools, 
       
  4991 			TRACE_FLAGS_DEFAULT, 
       
  4992 			(EAPL("TIMER: %s: EAP_TYPE_TIMER_DELAY_FAILURE_MESSAGE_SENT_ID delete data.\n"),
       
  4993 			 (m_is_client == true) ? "client": "server"));
       
  4994 	}
       
  4995 	else if (id == EAP_TYPE_AKA_TIMER_DELAY_NOTIFICATION_MESSAGE_ID)
       
  4996 	{
       
  4997 		EAP_TRACE_DEBUG(
       
  4998 			m_am_tools, 
       
  4999 			TRACE_FLAGS_DEFAULT, 
       
  5000 			(EAPL("TIMER: %s: EAP_TYPE_TIMER_DELAY_NOTIFICATION_MESSAGE_ID delete data.\n"),
       
  5001 			 (m_is_client == true) ? "client": "server"));
       
  5002 	}
       
  5003 
       
  5004 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5005 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  5006 }
       
  5007 
       
  5008 //--------------------------------------------------
       
  5009 
       
  5010 //
       
  5011 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::packet_send(
       
  5012 	const eap_am_network_id_c * const network_id,
       
  5013 	eap_buf_chain_wr_c * const sent_packet,
       
  5014 	const u32_t header_offset,
       
  5015 	const u32_t data_length,
       
  5016 	const u32_t buffer_length)
       
  5017 {
       
  5018 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5019 
       
  5020 	EAP_TRACE_DEBUG(
       
  5021 		m_am_tools, 
       
  5022 		TRACE_FLAGS_DEFAULT, 
       
  5023 		(EAPL("eap_type_aka_c::packet_send().\n")));
       
  5024 
       
  5025 	eap_header_wr_c eap(
       
  5026 		m_am_tools,
       
  5027 		sent_packet->get_data_offset(
       
  5028 			header_offset, data_length),
       
  5029 		data_length);
       
  5030 	if (eap.get_is_valid() == false)
       
  5031 	{
       
  5032 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5033 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  5034 	}
       
  5035 
       
  5036 	EAP_AKA_PACKET_TRACE(
       
  5037 		EAPL("<-"),
       
  5038 		network_id,
       
  5039 		&eap,
       
  5040 		data_length);
       
  5041 
       
  5042 	eap_status_e status = get_type_partner()->packet_send(
       
  5043 		network_id, 
       
  5044 		sent_packet, 
       
  5045 		header_offset, 
       
  5046 		data_length,
       
  5047 		buffer_length
       
  5048 		);
       
  5049 
       
  5050 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5051 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5052 }
       
  5053 
       
  5054 //--------------------------------------------------
       
  5055 
       
  5056 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::read_configure(
       
  5057 	const eap_configuration_field_c * const field,
       
  5058 	eap_variable_data_c * const data)
       
  5059 {
       
  5060 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5061 
       
  5062 	// NOTE this will be read from AM of AKA EAP-type.
       
  5063 	const eap_status_e status = m_am_type_aka->type_configure_read(field, data);
       
  5064 
       
  5065 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5066 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5067 }
       
  5068 
       
  5069 //--------------------------------------------------
       
  5070 
       
  5071 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::write_configure(
       
  5072 	const eap_configuration_field_c * const field,
       
  5073 	eap_variable_data_c * const data)
       
  5074 {
       
  5075 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5076 
       
  5077 	// NOTE this will be written to AM of AKA EAP-type.
       
  5078 	const eap_status_e status = m_am_type_aka->type_configure_write(field, data);
       
  5079 
       
  5080 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5081 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5082 }
       
  5083 
       
  5084 //--------------------------------------------------
       
  5085 
       
  5086 // This is commented in eap_base_type_c::configure().
       
  5087 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::configure()
       
  5088 {
       
  5089 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5090 
       
  5091 	EAP_TRACE_DEBUG(
       
  5092 		m_am_tools, 
       
  5093 		TRACE_FLAGS_DEFAULT, 
       
  5094 		(EAPL("eap_type_aka_c::configure(): this = 0x%08x => 0x%08x\n"),
       
  5095 		this,
       
  5096 		dynamic_cast<abs_eap_base_timer_c *>(this)));
       
  5097 
       
  5098 	eap_status_e status(eap_status_process_general_error);
       
  5099 
       
  5100 
       
  5101 	// This must be configured first.
       
  5102 	status = m_am_type_aka->configure();
       
  5103 	if (status != eap_status_ok)
       
  5104 	{
       
  5105 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5106 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5107 	}
       
  5108 
       
  5109 	//----------------------------------------------------------
       
  5110 
       
  5111 	{
       
  5112 		eap_variable_data_c error_message_delay_time(m_am_tools);
       
  5113 
       
  5114 		status = read_configure(
       
  5115 			cf_str_EAP_AKA_failure_message_delay_time.get_field(),
       
  5116 			&error_message_delay_time);
       
  5117 		if (status == eap_status_ok
       
  5118 			&& error_message_delay_time.get_is_valid_data() == true
       
  5119 			&& error_message_delay_time.get_data_length() == sizeof(u32_t)
       
  5120 			&& error_message_delay_time.get_data(sizeof(u32_t)) != 0)
       
  5121 		{
       
  5122 			// This is optional value.
       
  5123 			m_failure_message_delay_time = *reinterpret_cast<u32_t *>(
       
  5124 				error_message_delay_time.get_data(sizeof(u32_t)));
       
  5125 		}
       
  5126 	}
       
  5127 
       
  5128 	//----------------------------------------------------------
       
  5129 
       
  5130 	{
       
  5131 		eap_variable_data_c use_manual_realm(m_am_tools);
       
  5132 
       
  5133 		status = read_configure(
       
  5134 			cf_str_EAP_AKA_use_manual_realm.get_field(),
       
  5135 			&use_manual_realm);
       
  5136 		if (status == eap_status_ok
       
  5137 			&& use_manual_realm.get_is_valid_data() == true
       
  5138 			&& use_manual_realm.get_data_length() == sizeof(u32_t))
       
  5139 		{
       
  5140 			u32_t *flag = reinterpret_cast<u32_t *>(
       
  5141 				use_manual_realm.get_data(sizeof(u32_t)));
       
  5142 			if (flag != 0)
       
  5143 			{
       
  5144 				if (*flag == 0)
       
  5145 				{
       
  5146 					m_use_manual_realm = false;
       
  5147 				}
       
  5148 				else
       
  5149 				{
       
  5150 					m_use_manual_realm = true;
       
  5151 				}
       
  5152 			}
       
  5153 		}
       
  5154 	}
       
  5155 
       
  5156 	//----------------------------------------------------------
       
  5157 
       
  5158 	{
       
  5159 		status = read_configure(
       
  5160 			cf_str_EAP_AKA_manual_realm.get_field(),
       
  5161 			get_nai_realm());
       
  5162 		if (status == eap_status_ok
       
  5163 			&& get_nai_realm()->get_is_valid_data() == true)
       
  5164 		{
       
  5165 			// OK NAI realm is configured.
       
  5166 		}
       
  5167 		else
       
  5168 		{
       
  5169 			// No configured NAI realm.
       
  5170 			// We will use automatic realm "wlan.mnc456.mcc123.3gppnetwork.org" as a realm.
       
  5171 			// Look at eap_type_aka_c::generate_nai().
       
  5172 		}
       
  5173 	}
       
  5174 
       
  5175 	//----------------------------------------------------------
       
  5176 
       
  5177 	{
       
  5178 		eap_variable_data_c wait_eap_success_packet(m_am_tools);
       
  5179 
       
  5180 		status = read_configure(
       
  5181 			cf_str_EAP_AKA_wait_eap_success_packet.get_field(),
       
  5182 			&wait_eap_success_packet);
       
  5183 
       
  5184 		if (status == eap_status_ok
       
  5185 			&& wait_eap_success_packet.get_is_valid_data() == true)
       
  5186 		{
       
  5187 			u32_t *flag = reinterpret_cast<u32_t *>(
       
  5188 				wait_eap_success_packet.get_data(sizeof(u32_t)));
       
  5189 			if (flag != 0)
       
  5190 			{
       
  5191 				if (*flag == 0)
       
  5192 				{
       
  5193 					m_wait_eap_success_packet = false;
       
  5194 				}
       
  5195 				else
       
  5196 				{
       
  5197 					m_wait_eap_success_packet = true;
       
  5198 				}
       
  5199 			}
       
  5200 		}
       
  5201 
       
  5202 		if (get_type_partner()->get_is_tunneled_eap() == true)
       
  5203 		{
       
  5204 			// Inside the PEAP we must wait EAP-Success to fullfill the state machine of PEAP.
       
  5205 			m_wait_eap_success_packet = true;
       
  5206 		}
       
  5207 	}
       
  5208 
       
  5209 	//----------------------------------------------------------
       
  5210 
       
  5211 	{
       
  5212 		eap_variable_data_c check_identifier_of_eap_identity_response(m_am_tools);
       
  5213 
       
  5214 		status = read_configure(
       
  5215 			cf_str_EAP_AKA_check_identifier_of_eap_identity_response.get_field(),
       
  5216 			&check_identifier_of_eap_identity_response);
       
  5217 
       
  5218 		if (status == eap_status_ok
       
  5219 			&& check_identifier_of_eap_identity_response.get_is_valid_data() == true)
       
  5220 		{
       
  5221 			u32_t *flag = reinterpret_cast<u32_t *>(
       
  5222 				check_identifier_of_eap_identity_response.get_data(sizeof(u32_t)));
       
  5223 			if (flag != 0)
       
  5224 			{
       
  5225 				if (*flag == 0)
       
  5226 				{
       
  5227 					m_check_identifier_of_eap_identity_response = false;
       
  5228 				}
       
  5229 				else
       
  5230 				{
       
  5231 					m_check_identifier_of_eap_identity_response = true;
       
  5232 				}
       
  5233 			}
       
  5234 		}
       
  5235 	}
       
  5236 
       
  5237 	//----------------------------------------------------------
       
  5238 
       
  5239 	{
       
  5240 		eap_variable_data_c EAP_AKA_check_nai_realm(m_am_tools);
       
  5241 
       
  5242 		status = read_configure(
       
  5243 			cf_str_EAP_AKA_check_nai_realm.get_field(),
       
  5244 			&EAP_AKA_check_nai_realm);
       
  5245 		if (status == eap_status_ok
       
  5246 			&& EAP_AKA_check_nai_realm.get_is_valid_data() == true)
       
  5247 		{
       
  5248 			u32_t *check_nai_realm = reinterpret_cast<u32_t *>(
       
  5249 				EAP_AKA_check_nai_realm.get_data(sizeof(u32_t)));
       
  5250 			if (check_nai_realm != 0
       
  5251 				&& *check_nai_realm != 0)
       
  5252 			{
       
  5253 				m_check_nai_realm = true;
       
  5254 			}
       
  5255 		}
       
  5256 	}
       
  5257 
       
  5258 	//----------------------------------------------------------
       
  5259 
       
  5260 	{
       
  5261 		status = read_configure(
       
  5262 			cf_str_EAP_AKA_nonce_mt_file.get_field(),
       
  5263 			&m_nonce_mt_file);
       
  5264 		if (status == eap_status_ok
       
  5265 			&& m_nonce_mt_file.get_is_valid_data() == true
       
  5266 			&& m_nonce_mt_file.get_data_length() != 0
       
  5267 			&& m_nonce_mt_file.get_data(m_nonce_mt_file.get_data_length()) != 0)
       
  5268 		{
       
  5269 			// This is optional value.
       
  5270 		}
       
  5271 	}
       
  5272 
       
  5273 	//----------------------------------------------------------
       
  5274 
       
  5275 	{
       
  5276 		eap_variable_data_c EAP_AKA_client_responds_retransmitted_packets(m_am_tools);
       
  5277 
       
  5278 		status = read_configure(
       
  5279 			cf_str_EAP_AKA_client_responds_retransmitted_packets.get_field(),
       
  5280 			&EAP_AKA_client_responds_retransmitted_packets);
       
  5281 		if (status == eap_status_ok
       
  5282 			&& EAP_AKA_client_responds_retransmitted_packets.get_is_valid_data() == true
       
  5283 			&& EAP_AKA_client_responds_retransmitted_packets.get_data_length() == sizeof(u32_t)
       
  5284 			&& EAP_AKA_client_responds_retransmitted_packets.get_data(sizeof(u32_t)) != 0)
       
  5285 		{
       
  5286 			// This is optional value.
       
  5287 			u32_t *flag = reinterpret_cast<u32_t *>(
       
  5288 				EAP_AKA_client_responds_retransmitted_packets.get_data(sizeof(u32_t)));
       
  5289 			if (flag != 0)
       
  5290 			{
       
  5291 				if (*flag == 0)
       
  5292 				{
       
  5293 					m_client_responds_retransmitted_packets = false;
       
  5294 				}
       
  5295 				else
       
  5296 				{
       
  5297 					m_client_responds_retransmitted_packets = true;
       
  5298 				}
       
  5299 			}
       
  5300 		}
       
  5301 	}
       
  5302 
       
  5303 	//----------------------------------------------------------
       
  5304 
       
  5305 	{
       
  5306 		eap_variable_data_c test_version(m_am_tools);
       
  5307 
       
  5308 		status = read_configure(
       
  5309 			cf_str_EAP_AKA_test_version.get_field(),
       
  5310 			&test_version);
       
  5311 		if (status == eap_status_ok
       
  5312 			&& test_version.get_is_valid_data() == true
       
  5313 			&& test_version.get_data_length() == sizeof(u32_t)
       
  5314 			&& test_version.get_data(sizeof(u32_t)) != 0)
       
  5315 		{
       
  5316 			// This is optional value.
       
  5317 			u32_t *flag = reinterpret_cast<u32_t *>(test_version.get_data(sizeof(u32_t)));
       
  5318 			if (flag != 0)
       
  5319 			{
       
  5320 				if (*flag == 0)
       
  5321 				{
       
  5322 					m_aka_test_version = false;
       
  5323 				}
       
  5324 				else
       
  5325 				{
       
  5326 					m_aka_test_version = true;
       
  5327 				}
       
  5328 			}
       
  5329 		}
       
  5330 	}
       
  5331 
       
  5332 	//----------------------------------------------------------
       
  5333 
       
  5334 	{
       
  5335 		eap_variable_data_c randomly_refuse_eap_identity(m_am_tools);
       
  5336 
       
  5337 		status = read_configure(
       
  5338 			cf_str_EAP_AKA_randomly_refuse_eap_identity.get_field(),
       
  5339 			&randomly_refuse_eap_identity);
       
  5340 		if (status == eap_status_ok
       
  5341 			&& randomly_refuse_eap_identity.get_is_valid_data() == true
       
  5342 			&& randomly_refuse_eap_identity.get_data_length() == sizeof(u32_t)
       
  5343 			&& randomly_refuse_eap_identity.get_data(sizeof(u32_t)) != 0)
       
  5344 		{
       
  5345 			// This is optional value.
       
  5346 			u32_t *flag = reinterpret_cast<u32_t *>(
       
  5347 				randomly_refuse_eap_identity.get_data(sizeof(u32_t)));
       
  5348 			if (flag != 0)
       
  5349 			{
       
  5350 				if (*flag == 0)
       
  5351 				{
       
  5352 					m_aka_randomly_refuse_eap_identity = false;
       
  5353 				}
       
  5354 				else
       
  5355 				{
       
  5356 					m_aka_randomly_refuse_eap_identity = true;
       
  5357 				}
       
  5358 			}
       
  5359 		}
       
  5360 	}
       
  5361 
       
  5362 	//----------------------------------------------------------
       
  5363 
       
  5364 	{
       
  5365 		eap_variable_data_c use_manual_username(m_am_tools);
       
  5366 
       
  5367 		status = read_configure(
       
  5368 			cf_str_EAP_AKA_use_manual_username.get_field(),
       
  5369 			&use_manual_username);
       
  5370 		if (status == eap_status_ok
       
  5371 			&& use_manual_username.get_is_valid_data() == true)
       
  5372 		{
       
  5373 			u32_t *use_manual_username_flag = reinterpret_cast<u32_t *>(
       
  5374 				use_manual_username.get_data(sizeof(u32_t)));
       
  5375 			if (use_manual_username_flag != 0
       
  5376 				&& *use_manual_username_flag != 0)
       
  5377 			{
       
  5378 				m_use_manual_username = true;
       
  5379 			}
       
  5380 		}
       
  5381 	}
       
  5382 
       
  5383 	//----------------------------------------------------------
       
  5384 
       
  5385 	if (m_use_manual_username == true)
       
  5386 	{
       
  5387 		status = read_configure(
       
  5388 			cf_str_EAP_AKA_manual_username.get_field(),
       
  5389 			&m_manual_username);
       
  5390 		if (status == eap_status_ok
       
  5391 			&& m_manual_username.get_is_valid_data() == true)
       
  5392 		{
       
  5393 			// This is optional value.
       
  5394 		}
       
  5395 		else
       
  5396 		{
       
  5397 			// No username defined.
       
  5398 			m_use_manual_username = false;
       
  5399 		}
       
  5400 	}
       
  5401 
       
  5402 	//----------------------------------------------------------
       
  5403 
       
  5404 	{
       
  5405 		eap_variable_data_c fail_re_authentication_counter_check(m_am_tools);
       
  5406 
       
  5407 		status = read_configure(
       
  5408 			cf_str_EAP_AKA_fail_re_authentication_counter_check.get_field(),
       
  5409 			&fail_re_authentication_counter_check);
       
  5410 		if (status == eap_status_ok
       
  5411 			&& fail_re_authentication_counter_check.get_is_valid_data() == true
       
  5412 			&& fail_re_authentication_counter_check.get_data_length() == sizeof(u32_t)
       
  5413 			&& fail_re_authentication_counter_check.get_data(sizeof(u32_t)) != 0)
       
  5414 		{
       
  5415 			// This is optional value.
       
  5416 			u32_t *flag = reinterpret_cast<u32_t *>(
       
  5417 				fail_re_authentication_counter_check.get_data(sizeof(u32_t)));
       
  5418 			if (flag != 0)
       
  5419 			{
       
  5420 				if (*flag == 0)
       
  5421 				{
       
  5422 					m_fail_reauthentication_counter_check = false;
       
  5423 				}
       
  5424 				else
       
  5425 				{
       
  5426 					m_fail_reauthentication_counter_check = true;
       
  5427 				}
       
  5428 			}
       
  5429 		}
       
  5430 	}
       
  5431 
       
  5432 	//----------------------------------------------------------
       
  5433 
       
  5434 	{
       
  5435 		eap_variable_data_c accept_eap_identity_response(m_am_tools);
       
  5436 
       
  5437 		status = read_configure(
       
  5438 			cf_str_EAP_AKA_accept_eap_identity_response.get_field(),
       
  5439 			&accept_eap_identity_response);
       
  5440 		if (status == eap_status_ok
       
  5441 			&& accept_eap_identity_response.get_is_valid_data() == true
       
  5442 			&& accept_eap_identity_response.get_data_length() == sizeof(u32_t)
       
  5443 			&& accept_eap_identity_response.get_data(
       
  5444 				accept_eap_identity_response.get_data_length()) != 0)
       
  5445 		{
       
  5446 			// This is optional value.
       
  5447 			u32_t *flag = reinterpret_cast<u32_t *>(
       
  5448 				accept_eap_identity_response.get_data(sizeof(u32_t)));
       
  5449 			if (flag != 0)
       
  5450 			{
       
  5451 				if (*flag != 0)
       
  5452 				{
       
  5453 					m_accept_eap_identity_response = true;
       
  5454 				}
       
  5455 				else if (*flag == 0)
       
  5456 				{
       
  5457 					m_accept_eap_identity_response = false;
       
  5458 				}
       
  5459 			}
       
  5460 		}
       
  5461 	}
       
  5462 
       
  5463 	//----------------------------------------------------------
       
  5464 
       
  5465 	{
       
  5466 		eap_variable_data_c use_random_identity_on_eap_identity_response(m_am_tools);
       
  5467 
       
  5468 		status = read_configure(
       
  5469 			cf_str_EAP_AKA_use_random_identity_on_eap_identity_response.get_field(),
       
  5470 			&use_random_identity_on_eap_identity_response);
       
  5471 		if (status == eap_status_ok
       
  5472 			&& use_random_identity_on_eap_identity_response.get_is_valid_data() == true
       
  5473 			&& use_random_identity_on_eap_identity_response.get_data_length() == sizeof(u32_t)
       
  5474 			&& use_random_identity_on_eap_identity_response.get_data(
       
  5475 				use_random_identity_on_eap_identity_response.get_data_length()) != 0)
       
  5476 		{
       
  5477 			// This is optional value.
       
  5478 			u32_t *flag = reinterpret_cast<u32_t *>(
       
  5479 				use_random_identity_on_eap_identity_response.get_data(sizeof(u32_t)));
       
  5480 			if (flag != 0)
       
  5481 			{
       
  5482 				if (*flag != 0)
       
  5483 				{
       
  5484 					m_use_random_identity_on_eap_identity_response = true;
       
  5485 				}
       
  5486 				else if (*flag == 0)
       
  5487 				{
       
  5488 					m_use_random_identity_on_eap_identity_response = false;
       
  5489 				}
       
  5490 			}
       
  5491 		}
       
  5492 	}
       
  5493 
       
  5494 	//----------------------------------------------------------
       
  5495 
       
  5496 	{
       
  5497 		eap_variable_data_c use_pseudonym_identity(m_am_tools);
       
  5498 
       
  5499 		status = read_configure(
       
  5500 			cf_str_EAP_AKA_use_pseudonym_identity.get_field(),
       
  5501 			&use_pseudonym_identity);
       
  5502 		if (status == eap_status_ok
       
  5503 			&& use_pseudonym_identity.get_is_valid_data() == true
       
  5504 			&& use_pseudonym_identity.get_data_length() == sizeof(u32_t)
       
  5505 			&& use_pseudonym_identity.get_data(use_pseudonym_identity.get_data_length()) != 0)
       
  5506 		{
       
  5507 			// This is optional value.
       
  5508 			u32_t *flag = reinterpret_cast<u32_t *>(use_pseudonym_identity.get_data(sizeof(u32_t)));
       
  5509 			if (flag != 0)
       
  5510 			{
       
  5511 				if (*flag != 0)
       
  5512 				{
       
  5513 					m_use_pseudonym_identity = true;
       
  5514 				}
       
  5515 				else if (*flag == 0)
       
  5516 				{
       
  5517 					m_use_pseudonym_identity = false;
       
  5518 				}
       
  5519 			}
       
  5520 		}
       
  5521 	}
       
  5522 
       
  5523 	//----------------------------------------------------------
       
  5524 
       
  5525 	{
       
  5526 		eap_variable_data_c use_reauthentication_identity(m_am_tools);
       
  5527 
       
  5528 		status = read_configure(
       
  5529 			cf_str_EAP_AKA_use_reauthentication_identity.get_field(),
       
  5530 			&use_reauthentication_identity);
       
  5531 		if (status == eap_status_ok
       
  5532 			&& use_reauthentication_identity.get_is_valid_data() == true
       
  5533 			&& use_reauthentication_identity.get_data_length() == sizeof(u32_t)
       
  5534 			&& use_reauthentication_identity.get_data(
       
  5535 				use_reauthentication_identity.get_data_length()) != 0)
       
  5536 		{
       
  5537 			// This is optional value.
       
  5538 			u32_t *flag = reinterpret_cast<u32_t *>(
       
  5539 				use_reauthentication_identity.get_data(sizeof(u32_t)));
       
  5540 			if (flag != 0)
       
  5541 			{
       
  5542 				if (*flag != 0)
       
  5543 				{
       
  5544 					m_use_reauthentication_identity = true;
       
  5545 				}
       
  5546 				else if (*flag == 0)
       
  5547 				{
       
  5548 					m_use_reauthentication_identity = false;
       
  5549 				}
       
  5550 			}
       
  5551 		}
       
  5552 	}
       
  5553 
       
  5554 	//----------------------------------------------------------
       
  5555 
       
  5556 	{
       
  5557 		eap_variable_data_c randomly_fail_successfull_authentication(m_am_tools);
       
  5558 
       
  5559 		status = read_configure(
       
  5560 			cf_str_EAP_AKA_randomly_fail_successfull_authentication.get_field(),
       
  5561 			&randomly_fail_successfull_authentication);
       
  5562 		if (status == eap_status_ok
       
  5563 			&& randomly_fail_successfull_authentication.get_is_valid_data() == true
       
  5564 			&& randomly_fail_successfull_authentication.get_data_length() == sizeof(u32_t)
       
  5565 			&& randomly_fail_successfull_authentication.get_data(
       
  5566 				randomly_fail_successfull_authentication.get_data_length()) != 0)
       
  5567 		{
       
  5568 			// This is optional value.
       
  5569 			u32_t *flag = reinterpret_cast<u32_t *>(
       
  5570 				randomly_fail_successfull_authentication.get_data(sizeof(u32_t)));
       
  5571 			if (flag != 0)
       
  5572 			{
       
  5573 				if (*flag != 0)
       
  5574 				{
       
  5575 					m_randomly_fail_successfull_authentication = true;
       
  5576 				}
       
  5577 				else
       
  5578 				{
       
  5579 					m_randomly_fail_successfull_authentication = false;
       
  5580 				}
       
  5581 			}
       
  5582 		}
       
  5583 	}
       
  5584 
       
  5585 	//----------------------------------------------------------
       
  5586 
       
  5587 	{
       
  5588 		eap_variable_data_c allow_use_result_indication(m_am_tools);
       
  5589 
       
  5590 		status = read_configure(
       
  5591 			cf_str_EAP_AKA_allow_use_result_indication.get_field(),
       
  5592 			&allow_use_result_indication);
       
  5593 		if (status == eap_status_ok
       
  5594 			&& allow_use_result_indication.get_is_valid_data() == true
       
  5595 			&& allow_use_result_indication.get_data_length() == sizeof(u32_t)
       
  5596 			&& allow_use_result_indication.get_data(
       
  5597 				allow_use_result_indication.get_data_length()) != 0)
       
  5598 		{
       
  5599 			// This is optional value.
       
  5600 			u32_t *flag = reinterpret_cast<u32_t *>(
       
  5601 				allow_use_result_indication.get_data(sizeof(u32_t)));
       
  5602 			if (flag != 0)
       
  5603 			{
       
  5604 				if (*flag != 0)
       
  5605 				{
       
  5606 					m_allow_use_result_indication = true;
       
  5607 				}
       
  5608 				else
       
  5609 				{
       
  5610 					m_allow_use_result_indication = false;
       
  5611 				}
       
  5612 			}
       
  5613 		}
       
  5614 	}
       
  5615 
       
  5616 	if (m_is_client == false)
       
  5617 	{
       
  5618 		eap_variable_data_c server_allow_use_result_indication(m_am_tools);
       
  5619 
       
  5620 		status = read_configure(
       
  5621 			cf_str_EAP_AKA_server_allow_use_result_indication.get_field(),
       
  5622 			&server_allow_use_result_indication);
       
  5623 		if (status == eap_status_ok
       
  5624 			&& server_allow_use_result_indication.get_is_valid_data() == true
       
  5625 			&& server_allow_use_result_indication.get_data_length() == sizeof(u32_t)
       
  5626 			&& server_allow_use_result_indication.get_data(
       
  5627 				server_allow_use_result_indication.get_data_length()) != 0)
       
  5628 		{
       
  5629 			// This is optional value.
       
  5630 			u32_t *flag = reinterpret_cast<u32_t *>(
       
  5631 				server_allow_use_result_indication.get_data(sizeof(u32_t)));
       
  5632 			if (flag != 0)
       
  5633 			{
       
  5634 				if (*flag != 0)
       
  5635 				{
       
  5636 					m_allow_use_result_indication = true;
       
  5637 				}
       
  5638 				else
       
  5639 				{
       
  5640 					m_allow_use_result_indication = false;
       
  5641 				}
       
  5642 			}
       
  5643 		}
       
  5644 	}
       
  5645 
       
  5646 	//----------------------------------------------------------
       
  5647 
       
  5648 #if defined(USE_EAP_EXPANDED_TYPES)
       
  5649 	{
       
  5650 		eap_variable_data_c use_eap_expanded_type(m_am_tools);
       
  5651 
       
  5652 		eap_status_e status = read_configure(
       
  5653 			cf_str_EAP_AKA_use_eap_expanded_type.get_field(),
       
  5654 			&use_eap_expanded_type);
       
  5655 
       
  5656 		if (status != eap_status_ok)
       
  5657 		{
       
  5658 			status = read_configure(
       
  5659 				cf_str_EAP_CORE_use_eap_expanded_type.get_field(),
       
  5660 				&use_eap_expanded_type);
       
  5661 		}
       
  5662 
       
  5663 		if (status == eap_status_ok
       
  5664 			&& use_eap_expanded_type.get_data_length() == sizeof(u32_t)
       
  5665 			&& use_eap_expanded_type.get_data() != 0)
       
  5666 		{
       
  5667 			u32_t *flag = reinterpret_cast<u32_t *>(use_eap_expanded_type.get_data(use_eap_expanded_type.get_data_length()));
       
  5668 
       
  5669 			if (flag != 0)
       
  5670 			{
       
  5671 				if ((*flag) != 0ul)
       
  5672 				{
       
  5673 					m_use_eap_expanded_type = true;
       
  5674 				}
       
  5675 				else
       
  5676 				{
       
  5677 					m_use_eap_expanded_type = false;
       
  5678 				}
       
  5679 			}
       
  5680 		}
       
  5681 	}
       
  5682 #endif //#if defined(USE_EAP_EXPANDED_TYPES)
       
  5683 
       
  5684 	//----------------------------------------------------------
       
  5685 
       
  5686 	{
       
  5687 		(void) read_configure(
       
  5688 			cf_str_EAP_AKA_2_digit_mnc_map_of_mcc_of_imsi_array.get_field(),
       
  5689 			&m_2_digit_mnc_map_of_mcc_of_imsi_array);
       
  5690 		// This is optional value.
       
  5691 	}
       
  5692 
       
  5693 	{
       
  5694 		eap_variable_data_c use_uma_profile(m_am_tools);
       
  5695 
       
  5696 		eap_status_e status = read_configure(
       
  5697 			cf_str_EAP_AKA_UMA_profile.get_field(),
       
  5698 			&use_uma_profile);
       
  5699 		if (status == eap_status_ok
       
  5700 			&& use_uma_profile.get_is_valid_data() == true
       
  5701 			&& use_uma_profile.get_data_length() == sizeof(u32_t))
       
  5702 		{
       
  5703 			u32_t *flag = reinterpret_cast<u32_t *>(use_uma_profile.get_data());
       
  5704 			if (flag != 0)
       
  5705 			{
       
  5706 				if (*flag == 0)
       
  5707 				{
       
  5708 					m_use_uma_profile = false;
       
  5709 				}
       
  5710 				else
       
  5711 				{
       
  5712 					m_use_uma_profile = true;
       
  5713 				}
       
  5714 			}
       
  5715 		}		
       
  5716 	}
       
  5717 
       
  5718 	if (m_use_uma_profile == true)
       
  5719 	{
       
  5720 		(void) read_configure(
       
  5721 			cf_str_EAP_AKA_UMA_realm_prefix.get_field(),
       
  5722 			&m_uma_automatic_realm_prefix);
       
  5723 		// m_uma_automatic_realm_prefix is optional.
       
  5724 
       
  5725 		// In the UMA we must wait EAP-Success to fullfill the state machine of mVPN.
       
  5726 		m_wait_eap_success_packet = true;
       
  5727 	}
       
  5728 	else
       
  5729 	{
       
  5730 		eap_variable_data_c wait_eap_success_packet(m_am_tools);
       
  5731 
       
  5732 		status = read_configure(
       
  5733 			cf_str_EAP_AKA_wait_eap_success_packet.get_field(),
       
  5734 			&wait_eap_success_packet);
       
  5735 
       
  5736 		if (status == eap_status_ok
       
  5737 			&& wait_eap_success_packet.get_is_valid_data() == true)
       
  5738 		{
       
  5739 			u32_t *flag = reinterpret_cast<u32_t *>(wait_eap_success_packet.get_data());
       
  5740 			if (flag != 0)
       
  5741 			{
       
  5742 				if (*flag == 0)
       
  5743 				{
       
  5744 					m_wait_eap_success_packet = false;
       
  5745 				}
       
  5746 				else
       
  5747 				{
       
  5748 					m_wait_eap_success_packet = true;
       
  5749 				}
       
  5750 			}
       
  5751 		}
       
  5752 
       
  5753 		if (get_type_partner()->get_is_tunneled_eap() == true)
       
  5754 		{
       
  5755 			// Inside the PEAP we must wait EAP-Success to fullfill the state machine of PEAP.
       
  5756 			m_wait_eap_success_packet = true;
       
  5757 		}
       
  5758 	}
       
  5759 
       
  5760 	//----------------------------------------------------------
       
  5761 
       
  5762 	m_aka_header_offset = get_type_partner()->get_header_offset(
       
  5763 		&m_MTU, &m_trailer_length);
       
  5764 
       
  5765 	if (m_aka_header_offset+m_MTU+m_trailer_length > EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH)
       
  5766 	{
       
  5767 		EAP_ASSERT_ALWAYS(EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH
       
  5768 						  >= (m_aka_header_offset+m_trailer_length));
       
  5769 
       
  5770 		m_MTU = EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH - (m_aka_header_offset+m_trailer_length);
       
  5771 	}
       
  5772 
       
  5773 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5774 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  5775 }
       
  5776 
       
  5777 //--------------------------------------------------
       
  5778 
       
  5779 // This is commented in eap_base_type_c::shutdown().
       
  5780 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::shutdown()
       
  5781 {
       
  5782 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5783 
       
  5784 	EAP_TRACE_DEBUG(
       
  5785 		m_am_tools, 
       
  5786 		TRACE_FLAGS_DEFAULT, 
       
  5787 		(EAPL("eap_type_aka_c::shutdown(): this = 0x%08x => 0x%08x\n"),
       
  5788 		this,
       
  5789 		dynamic_cast<abs_eap_base_timer_c *>(this)));
       
  5790 
       
  5791 	if (m_shutdown_was_called == true)
       
  5792 	{
       
  5793 		// Shutdown function was called already.
       
  5794 		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  5795 	}
       
  5796 	m_shutdown_was_called = true;
       
  5797 
       
  5798 	cancel_error_message_delay_timer();
       
  5799 	cancel_notification_message_delay_timer();
       
  5800 
       
  5801 	if (m_am_type_aka != 0)
       
  5802 	{
       
  5803 		// We must cancel the pending query.
       
  5804 		if (get_state() == eap_type_aka_state_pending_identity_query)
       
  5805 		{
       
  5806 			(void) m_am_type_aka->cancel_AKA_IMSI_or_pseudonym_or_reauthentication_id_query();
       
  5807 		}
       
  5808 		else if (get_state() == eap_type_aka_state_pending_kc_sres_query)
       
  5809 		{
       
  5810 			(void) m_am_type_aka->cancel_AKA_RES_query();
       
  5811 		}
       
  5812 		else if (get_state() == eap_type_aka_state_pending_pseudonym_decode_query)
       
  5813 		{
       
  5814 			(void) m_am_type_aka->cancel_imsi_from_username_query();
       
  5815 		}
       
  5816 		else if (get_state() == eap_type_aka_state_pending_authentication_vector_query)
       
  5817 		{
       
  5818 			(void) m_am_type_aka->cancel_AKA_authentication_vector_query();
       
  5819 		}
       
  5820 
       
  5821 		send_final_notification();
       
  5822 	}
       
  5823 
       
  5824 	reset();
       
  5825 
       
  5826 	eap_status_e status(eap_status_ok);
       
  5827 	if (m_am_type_aka != 0)
       
  5828 	{
       
  5829 		status = m_am_type_aka->shutdown();
       
  5830 	}
       
  5831 
       
  5832 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5833 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5834 }
       
  5835 
       
  5836 //--------------------------------------------------
       
  5837 
       
  5838 // This function is to allow reuse of this object.
       
  5839 // The whole object state must be reset.
       
  5840 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::reset()
       
  5841 {
       
  5842 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5843 
       
  5844 	EAP_TRACE_DEBUG(
       
  5845 		m_am_tools,
       
  5846 		TRACE_FLAGS_DEFAULT,
       
  5847 		(EAPL("AKA: %s: function: eap_type_aka_c::reset(): this = 0x%08x\n"),
       
  5848 		(m_is_client == true ? "client": "server"),
       
  5849 		this));
       
  5850 
       
  5851 	eap_status_e status = eap_status_not_supported;
       
  5852 
       
  5853 	m_reset_was_called = true;
       
  5854 
       
  5855 	m_use_result_indication = false;
       
  5856 	m_authentication_type = AKA_AUTHENTICATION_TYPE_NONE;
       
  5857 	set_identity_type(AKA_IDENTITY_TYPE_NONE);
       
  5858 
       
  5859 
       
  5860 	{
       
  5861 		cancel_error_message_delay_timer();
       
  5862 		m_client_error_code = eap_aka_client_error_code_none;
       
  5863 		m_erroneus_packet_received = false;
       
  5864 
       
  5865 		cancel_notification_message_delay_timer();
       
  5866 		m_aka_notification_code = eap_aka_notification_none;
       
  5867 		m_aka_notification_packet_received = false;
       
  5868 
       
  5869 		if (m_authentication_vector != 0)
       
  5870 		{
       
  5871 			delete m_authentication_vector;
       
  5872 			m_authentication_vector = 0;
       
  5873 		}
       
  5874 
       
  5875 		m_state = eap_type_aka_state_none;
       
  5876 
       
  5877 		m_nonce_s.reset();
       
  5878 		m_IV.get_payload_buffer()->reset();
       
  5879 		m_saved_EAP_packet.reset();
       
  5880 		m_XKEY.reset();
       
  5881 		m_K_encr.reset();
       
  5882 		m_K_aut.reset();
       
  5883 		m_master_session_key.reset();
       
  5884 		m_automatic_realm.reset();
       
  5885 		m_automatic_realm_read = false;
       
  5886 		m_IMSI.reset();
       
  5887 		m_pseudonym.reset();
       
  5888 		m_reauthentication_identity.reset();
       
  5889 		m_identity.reset();
       
  5890 		m_NAI.reset();
       
  5891 		m_RAND.reset();
       
  5892 		m_AUTN.reset();
       
  5893 		m_RES.reset();
       
  5894 	}
       
  5895 
       
  5896 	status = checkcode_init();
       
  5897 	if (status != eap_status_ok)
       
  5898 	{
       
  5899 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5900 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5901 	}
       
  5902 
       
  5903 	status = m_am_type_aka->reset();
       
  5904 	if (status != eap_status_ok)
       
  5905 	{
       
  5906 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5907 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5908 	}
       
  5909 
       
  5910 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5911 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5912 }
       
  5913 
       
  5914 //--------------------------------------------------
       
  5915 
       
  5916 //
       
  5917 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::set_timer(
       
  5918 	abs_eap_base_timer_c * const p_initializer, 
       
  5919 	const u32_t p_id, 
       
  5920 	void * const p_data,
       
  5921 	const u32_t p_time_ms)
       
  5922 {
       
  5923 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5924 
       
  5925 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  5926 
       
  5927 	const eap_status_e status = get_type_partner()->set_timer(
       
  5928 		p_initializer, 
       
  5929 		p_id, 
       
  5930 		p_data,
       
  5931 		p_time_ms);
       
  5932 
       
  5933 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5934 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5935 }
       
  5936 
       
  5937 //--------------------------------------------------
       
  5938 
       
  5939 //
       
  5940 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::cancel_timer(
       
  5941 	abs_eap_base_timer_c * const p_initializer, 
       
  5942 	const u32_t p_id)
       
  5943 {
       
  5944 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5945 
       
  5946 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  5947 
       
  5948 	const eap_status_e status = get_type_partner()->cancel_timer(
       
  5949 		p_initializer, 
       
  5950 		p_id);
       
  5951 
       
  5952 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5953 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5954 }
       
  5955 
       
  5956 //--------------------------------------------------
       
  5957 
       
  5958 //
       
  5959 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::cancel_all_timers()
       
  5960 {
       
  5961 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5962 
       
  5963 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  5964 
       
  5965 	const eap_status_e status = get_type_partner()->cancel_all_timers();
       
  5966 
       
  5967 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5968 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5969 }
       
  5970 
       
  5971 //--------------------------------------------------
       
  5972 //--------------------------------------------------
       
  5973 
       
  5974 EAP_FUNC_EXPORT const eap_type_aka_state_variable_parameters_c * eap_type_aka_c::get_state_variable()
       
  5975 {
       
  5976 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5977 	if (get_state() < eap_type_aka_state_last_value)
       
  5978 	{
       
  5979 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5980 		return &(m_parameters[get_state()]);
       
  5981 	}
       
  5982 	else
       
  5983 	{
       
  5984 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5985 		return 0;
       
  5986 	}
       
  5987 }
       
  5988 
       
  5989 //--------------------------------------------------
       
  5990 
       
  5991 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::check_valid_state(aka_subtype_e type)
       
  5992 {
       
  5993 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5994 	const eap_type_aka_state_variable_parameters_c * const state_variable = get_state_variable();
       
  5995 
       
  5996 	if (state_variable == 0)
       
  5997 	{
       
  5998 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5999 		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_gsmsim_state);
       
  6000 	}
       
  6001 
       
  6002 	if (state_variable->check_initiator(!get_is_client()) == false)
       
  6003 	{
       
  6004 		EAP_TRACE_DEBUG(
       
  6005 			m_am_tools,
       
  6006 			TRACE_FLAGS_AKA_ERROR,
       
  6007 			(EAPL("ERROR: eap_type_aka_c::check_valid_state(): Initiator type %d is wrong in eap_type_aka_state_variable_e %d=%s.\n"),
       
  6008 			 get_is_client(),
       
  6009 			 get_state(),
       
  6010 			 get_state_string()));
       
  6011 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6012 		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_gsmsim_state);
       
  6013 	}
       
  6014 
       
  6015 	if (state_variable->check_valid_types(type) == false)
       
  6016 	{
       
  6017 		EAP_TRACE_DEBUG(
       
  6018 			m_am_tools,
       
  6019 			TRACE_FLAGS_AKA_ERROR,
       
  6020 			(EAPL("ERROR: eap_type_aka_c::check_valid_state(): aka_subtype_e %d is wrong in eap_type_aka_state_variable_e %d=%s.\n"),
       
  6021 			 type,
       
  6022 			 get_state(),
       
  6023 			 get_state_string()));
       
  6024 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6025 		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_subtype);
       
  6026 	}
       
  6027 
       
  6028 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6029 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  6030 }
       
  6031 
       
  6032 //--------------------------------------------------
       
  6033 
       
  6034 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::store_identity(
       
  6035 	const eap_variable_data_c * const IMSI_or_pseudonym,
       
  6036 	const bool IMSI_is_used)
       
  6037 {
       
  6038 	eap_status_e status = get_identity()->init(IMSI_or_pseudonym->get_data_length()+1u);
       
  6039 	if (status != eap_status_ok)
       
  6040 	{
       
  6041 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6042 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6043 	}
       
  6044 	get_identity()->set_is_valid();
       
  6045 
       
  6046 	if (IMSI_is_used == true)
       
  6047 	{
       
  6048 		// Note the first octet is reserved for IMSI prefix.
       
  6049 		status = get_identity()->set_copy_of_buffer(AKA_IMSI_PREFIX_CHARACTER, 1u);
       
  6050 		if (status != eap_status_ok)
       
  6051 		{
       
  6052 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6053 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  6054 		}
       
  6055 	}
       
  6056 
       
  6057 	status = get_identity()->add_data(IMSI_or_pseudonym);
       
  6058 	if (status != eap_status_ok)
       
  6059 	{
       
  6060 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6061 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6062 	}
       
  6063 
       
  6064 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6065 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  6066 }
       
  6067 
       
  6068 //--------------------------------------------------
       
  6069 
       
  6070 /// not used: expansion_0 = prf(key, seed | 0)
       
  6071 /// not used: expansion_i = prf(key, expansion_i-1 | seed | i), where i = 1, 2...
       
  6072 
       
  6073 /// The following is from "DIGITAL SIGNATURE STANDARD (DSS)" FIPS PUB 186-2:
       
  6074 /// Let x be the signer's private key. The following may be used to generate m values of x:
       
  6075 /// Step 1. Choose a new, secret value for the seed-key, XKEY.
       
  6076 /// Step 2. In hexadecimal notation let
       
  6077 ///             t = 67452301 EFCDAB89 98BADCFE 10325476 C3D2E1F0.
       
  6078 ///             This is the initial value for H0 || H1 || H2 || H3 || H4 in the SHS.
       
  6079 /// Step 3. For j = 0 to m - 1 do
       
  6080 ///             a. XSEEDj = optional user input.
       
  6081 ///             b. XVAL = (XKEY + XSEEDj) mod 2^b.
       
  6082 ///             c. xj = G(t,XVAL) mod q.
       
  6083 ///             d. XKEY = (1 + XKEY + xj) mod 2^b.
       
  6084 /// 
       
  6085 /// Within AKA the following parameters are used:
       
  6086 /// 160-bit XKEY and XVAL values are used, so b = 160.
       
  6087 /// XKEY = SHA1(n*Kc| NONCE_MT)
       
  6088 /// The optional user input values (XSEED_j) are set to zero.
       
  6089 /// xj = G(t, XVAL)
       
  6090 
       
  6091 /// Random generator become as follows:
       
  6092 /// Step 1. Choose a new, secret value for the seed-key, XKEY.
       
  6093 /// Step 2. In hexadecimal notation let
       
  6094 ///             t = 67452301 EFCDAB89 98BADCFE 10325476 C3D2E1F0.
       
  6095 ///             This is the initial value for H0 || H1 || H2 || H3 || H4 in the SHS.
       
  6096 /// Step 3. For j = 0 to m - 1 do
       
  6097 ///             c. xj = G(t,XKEY).
       
  6098 ///             d. XKEY = (1 + XKEY + xj) mod 2^b.
       
  6099 
       
  6100 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::data_exp(
       
  6101 	const u32_t data_length,
       
  6102 	eap_variable_data_c * const expansion,
       
  6103 	const eap_variable_data_c * const key,
       
  6104 	const eap_variable_data_c * const seed)
       
  6105 {
       
  6106 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6107 	eap_status_e status = eap_status_process_general_error;
       
  6108 
       
  6109 	EAP_UNREFERENCED_PARAMETER(seed);
       
  6110 
       
  6111 	u32_t count = data_length/EAP_TYPE_AKA_KEYMAT_SIZE;
       
  6112 	if ((data_length % EAP_TYPE_AKA_KEYMAT_SIZE) != 0)
       
  6113 	{
       
  6114 		++count;
       
  6115 	}
       
  6116 
       
  6117 	status = expansion->init(count*EAP_TYPE_AKA_KEYMAT_SIZE);
       
  6118 	if (status != eap_status_ok)
       
  6119 	{
       
  6120 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6121 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6122 	}
       
  6123 	expansion->set_is_valid();
       
  6124 
       
  6125 	status = expansion->set_data_length(count*EAP_TYPE_AKA_KEYMAT_SIZE);
       
  6126 	if (status != eap_status_ok)
       
  6127 	{
       
  6128 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6129 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6130 	}
       
  6131 
       
  6132 	status = m_am_tools->get_crypto()->dss_pseudo_random(
       
  6133 		expansion->get_data(expansion->get_data_length()),
       
  6134 		expansion->get_data_length(),
       
  6135 		key->get_data(key->get_data_length()),
       
  6136 		key->get_data_length());
       
  6137 
       
  6138 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6139 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  6140 }
       
  6141 
       
  6142 //--------------------------------------------------
       
  6143 
       
  6144 //
       
  6145 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::generate_shared_secred_keys(
       
  6146 	const u32_t key_length,
       
  6147 	const eap_variable_data_c * const CK,
       
  6148 	const eap_variable_data_c * const IK,
       
  6149 	eap_variable_data_c * const XKEY,
       
  6150 	eap_variable_data_c * const K_encr,
       
  6151 	eap_variable_data_c * const K_aut,
       
  6152 	eap_variable_data_c * const master_session_key)
       
  6153 {
       
  6154 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6155 
       
  6156 	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("generate_shared_secred_keys():\n")));
       
  6157 
       
  6158 	if (get_NAI()->get_is_valid_data() == false)
       
  6159 	{
       
  6160 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6161 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_nai);
       
  6162 	}
       
  6163 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, (EAPL("full auth NAI"),
       
  6164 		get_NAI()->get_data(get_NAI()->get_data_length()),
       
  6165 		get_NAI()->get_data_length()));
       
  6166 
       
  6167 	if (IK->get_is_valid_data() == false)
       
  6168 	{
       
  6169 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6170 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  6171 	}
       
  6172 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, (EAPL("IK"),
       
  6173 		IK->get_data(IK->get_data_length()),
       
  6174 		IK->get_data_length()));
       
  6175 
       
  6176 	if (CK->get_is_valid_data() == false)
       
  6177 	{
       
  6178 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6179 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  6180 	}
       
  6181 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, (EAPL("CK"),
       
  6182 		CK->get_data(CK->get_data_length()),
       
  6183 		CK->get_data_length()));
       
  6184 
       
  6185 	eap_status_e status = eap_status_process_general_error;
       
  6186 
       
  6187 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  6188 
       
  6189 	// XKEY = SHA1(NAI | IK | CK)
       
  6190 
       
  6191 	crypto_sha1_c sha1(m_am_tools);
       
  6192 
       
  6193 	if (sha1.get_is_valid() == false)
       
  6194 	{
       
  6195 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6196 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  6197 	}
       
  6198 
       
  6199 	if (sha1.hash_init() != eap_status_ok)
       
  6200 	{
       
  6201 		EAP_TRACE_ERROR(
       
  6202 			m_am_tools,
       
  6203 			TRACE_FLAGS_AKA_ERROR,
       
  6204 			(EAPL("ERROR: generate_shared_secred_keys(): init() failed.\n")));
       
  6205 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6206 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  6207 	}
       
  6208 
       
  6209 	status = sha1.hash_update(
       
  6210 		get_NAI()->get_data(get_NAI()->get_data_length()),
       
  6211 		get_NAI()->get_data_length());
       
  6212 	if (status != eap_status_ok)
       
  6213 	{
       
  6214 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6215 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6216 	}
       
  6217 
       
  6218 	status = sha1.hash_update(
       
  6219 		IK->get_data(IK->get_data_length()),
       
  6220 		IK->get_data_length());
       
  6221 	if (status != eap_status_ok)
       
  6222 	{
       
  6223 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6224 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6225 	}
       
  6226 
       
  6227 	status = sha1.hash_update(
       
  6228 		CK->get_data(CK->get_data_length()),
       
  6229 		CK->get_data_length());
       
  6230 	if (status != eap_status_ok)
       
  6231 	{
       
  6232 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6233 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6234 	}
       
  6235 
       
  6236 	status = XKEY->init(key_length);
       
  6237 	if (status != eap_status_ok)
       
  6238 	{
       
  6239 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6240 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6241 	}
       
  6242 	XKEY->set_is_valid();
       
  6243 	XKEY->set_data_length(key_length);
       
  6244 
       
  6245 	u32_t md_length = key_length;
       
  6246 
       
  6247 	status = sha1.hash_final(
       
  6248 		XKEY->get_data_offset(0u, key_length),
       
  6249 		&md_length);
       
  6250 	if (status != eap_status_ok)
       
  6251 	{
       
  6252 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6253 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6254 	}
       
  6255 
       
  6256 	EAP_ASSERT_ALWAYS(md_length == key_length);
       
  6257 
       
  6258 
       
  6259 	EAP_TRACE_DEBUG(
       
  6260 		m_am_tools,
       
  6261 		TRACE_FLAGS_DEFAULT,
       
  6262 		(EAPL("generate_shared_secred_keys(): XKEY\n")));
       
  6263 	EAP_TRACE_DATA_DEBUG(
       
  6264 		m_am_tools,
       
  6265 		TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  6266 		(EAPL("     XKEY"),
       
  6267 		XKEY->get_data(XKEY->get_data_length()),
       
  6268 		XKEY->get_data_length()));
       
  6269 
       
  6270 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  6271 
       
  6272 	u32_t aes_key_length = m_am_tools->get_crypto()->aes_key_length();
       
  6273 	u32_t data_length = aes_key_length + EAP_TYPE_AKA_MAC_SIZE + EAP_TYPE_AKA_MASTER_SESSION_KEY_SIZE;
       
  6274 
       
  6275 	eap_variable_data_c expansion(m_am_tools);
       
  6276 	eap_variable_data_c seed(m_am_tools);
       
  6277 
       
  6278 	if (expansion.get_is_valid() == false
       
  6279 		|| seed.get_is_valid() == false)
       
  6280 	{
       
  6281 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6282 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  6283 	}
       
  6284 
       
  6285 	status = seed.add_data(get_NAI());
       
  6286 	if (status != eap_status_ok)
       
  6287 	{
       
  6288 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6289 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6290 	}
       
  6291 
       
  6292 	status = data_exp(
       
  6293 		data_length,
       
  6294 		&expansion,
       
  6295 		XKEY,
       
  6296 		&seed);
       
  6297 	if (status != eap_status_ok)
       
  6298 	{
       
  6299 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6300 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6301 	}
       
  6302 
       
  6303 	EAP_TRACE_DEBUG(
       
  6304 		m_am_tools,
       
  6305 		TRACE_FLAGS_DEFAULT,
       
  6306 		(EAPL("generate_shared_secred_keys(): expansion\n")));
       
  6307 	EAP_TRACE_DATA_DEBUG(
       
  6308 		m_am_tools,
       
  6309 		TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  6310 		(EAPL("expansion"),
       
  6311 		expansion.get_data(expansion.get_data_length()),
       
  6312 		expansion.get_data_length()));
       
  6313 
       
  6314 	u8_t *data = expansion.get_data_offset(0u, data_length);
       
  6315 	if (data == 0)
       
  6316 	{
       
  6317 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6318 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  6319 	}
       
  6320 	const u8_t * const data_begin = data;
       
  6321 
       
  6322 	EAP_UNREFERENCED_PARAMETER(data_begin);
       
  6323 
       
  6324 	// K_encr, K_aut and master_session_key
       
  6325 
       
  6326 	status = K_encr->set_copy_of_buffer(data, aes_key_length);
       
  6327 	if (status != eap_status_ok)
       
  6328 	{
       
  6329 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6330 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6331 	}
       
  6332 	data += aes_key_length;
       
  6333 	EAP_ASSERT_ALWAYS(static_cast<u32_t>(data-data_begin) <= data_length);
       
  6334 
       
  6335 	status = K_aut->set_copy_of_buffer(data, EAP_TYPE_AKA_MAC_SIZE);
       
  6336 	if (status != eap_status_ok)
       
  6337 	{
       
  6338 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6339 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6340 	}
       
  6341 	data += EAP_TYPE_AKA_MAC_SIZE;
       
  6342 	EAP_ASSERT_ALWAYS(static_cast<u32_t>(data-data_begin) <= data_length);
       
  6343 
       
  6344 	status = master_session_key->set_copy_of_buffer(data, EAP_TYPE_AKA_MASTER_SESSION_KEY_SIZE);
       
  6345 	if (status != eap_status_ok)
       
  6346 	{
       
  6347 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6348 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6349 	}
       
  6350 	data += EAP_TYPE_AKA_MASTER_SESSION_KEY_SIZE;
       
  6351 	EAP_ASSERT_ALWAYS(static_cast<u32_t>(data-data_begin) <= data_length);
       
  6352 
       
  6353 
       
  6354 	EAP_TRACE_DEBUG(
       
  6355 		m_am_tools,
       
  6356 		TRACE_FLAGS_DEFAULT,
       
  6357 		(EAPL("generate_shared_secred_keys(): K_encr\n")));
       
  6358 	EAP_TRACE_DATA_DEBUG(
       
  6359 		m_am_tools,
       
  6360 		TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  6361 		(EAPL("   K_encr"),
       
  6362 		K_encr->get_data(K_encr->get_data_length()),
       
  6363 		K_encr->get_data_length()));
       
  6364 
       
  6365 	EAP_TRACE_DEBUG(
       
  6366 		m_am_tools,
       
  6367 		TRACE_FLAGS_DEFAULT,
       
  6368 		(EAPL("generate_shared_secred_keys(): K_aut\n")));
       
  6369 	EAP_TRACE_DATA_DEBUG(
       
  6370 		m_am_tools,
       
  6371 		TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  6372 		(EAPL("    K_aut"),
       
  6373 		K_aut->get_data(K_aut->get_data_length()),
       
  6374 		K_aut->get_data_length()));
       
  6375 
       
  6376 	EAP_TRACE_DEBUG(
       
  6377 		m_am_tools,
       
  6378 		TRACE_FLAGS_DEFAULT,
       
  6379 		(EAPL("generate_shared_secred_keys(): master_session_key\n")));
       
  6380 	EAP_TRACE_DATA_DEBUG(
       
  6381 		m_am_tools,
       
  6382 		TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  6383 		(EAPL(" MSK+EMSK"),
       
  6384 		master_session_key->get_data(master_session_key->get_data_length()),
       
  6385 		master_session_key->get_data_length()));
       
  6386 
       
  6387 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  6388 
       
  6389 
       
  6390 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6391 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  6392 }
       
  6393 
       
  6394 //--------------------------------------------------
       
  6395 
       
  6396 //
       
  6397 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::generate_reauth_shared_secred_keys(
       
  6398 	const u32_t key_length,
       
  6399 	const eap_variable_data_c * const orig_XKEY,
       
  6400 	const u32_t reauth_counter,
       
  6401 	const eap_variable_data_c * const reauth_identity,
       
  6402 	const eap_variable_data_c * const reauth_nonce_s,
       
  6403 	eap_variable_data_c * const master_session_key)
       
  6404 {
       
  6405 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6406 
       
  6407 	u16_t counter = eap_htons(static_cast<u16_t>(reauth_counter));
       
  6408 
       
  6409 	eap_variable_data_c reauth_XKEY(m_am_tools);
       
  6410 
       
  6411 	if (reauth_XKEY.get_is_valid() == false)
       
  6412 	{
       
  6413 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6414 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  6415 	}
       
  6416 
       
  6417 	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, (EAPL("generate_reauth_shared_secred_keys():\n")));
       
  6418 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, (EAPL("reauth NAI"),
       
  6419 		reauth_identity->get_data(reauth_identity->get_data_length()),
       
  6420 		reauth_identity->get_data_length()));
       
  6421 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, (EAPL("reauth_counter"),
       
  6422 		&counter,
       
  6423 		sizeof(counter)));
       
  6424 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, (EAPL("NONCE_S"),
       
  6425 		reauth_nonce_s->get_data(reauth_nonce_s->get_data_length()),
       
  6426 		reauth_nonce_s->get_data_length()));
       
  6427 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, (EAPL("orig_XKEY"),
       
  6428 		orig_XKEY->get_data(orig_XKEY->get_data_length()),
       
  6429 		orig_XKEY->get_data_length()));
       
  6430 
       
  6431 	eap_status_e status = eap_status_process_general_error;
       
  6432 
       
  6433 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  6434 
       
  6435 	// XKEY = SHA1(Identity|counter|NONCE_S|original XKEY)
       
  6436 
       
  6437 	crypto_sha1_c sha1(m_am_tools);
       
  6438 
       
  6439 	if (sha1.get_is_valid() == false)
       
  6440 	{
       
  6441 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6442 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  6443 	}
       
  6444 
       
  6445 	if (sha1.hash_init() != eap_status_ok)
       
  6446 	{
       
  6447 		EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_AKA_ERROR, (EAPL("ERROR: generate_reauth_shared_secred_keys(): init() failed.\n")));
       
  6448 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6449 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  6450 	}
       
  6451 
       
  6452 	status = sha1.hash_update(
       
  6453 		reauth_identity->get_data(reauth_identity->get_data_length()),
       
  6454 		reauth_identity->get_data_length());
       
  6455 	if (status != eap_status_ok)
       
  6456 	{
       
  6457 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6458 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6459 	}
       
  6460 
       
  6461 	status = sha1.hash_update(
       
  6462 		&counter,
       
  6463 		sizeof(counter));
       
  6464 	if (status != eap_status_ok)
       
  6465 	{
       
  6466 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6467 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6468 	}
       
  6469 
       
  6470 	status = sha1.hash_update(
       
  6471 		reauth_nonce_s->get_data(reauth_nonce_s->get_data_length()),
       
  6472 		reauth_nonce_s->get_data_length());
       
  6473 	if (status != eap_status_ok)
       
  6474 	{
       
  6475 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6476 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6477 	}
       
  6478 
       
  6479 	status = sha1.hash_update(
       
  6480 		orig_XKEY->get_data(orig_XKEY->get_data_length()),
       
  6481 		orig_XKEY->get_data_length());
       
  6482 	if (status != eap_status_ok)
       
  6483 	{
       
  6484 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6485 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6486 	}
       
  6487 
       
  6488 	status = reauth_XKEY.init(key_length);
       
  6489 	if (status != eap_status_ok)
       
  6490 	{
       
  6491 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6492 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6493 	}
       
  6494 	reauth_XKEY.set_is_valid();
       
  6495 	reauth_XKEY.set_data_length(key_length);
       
  6496 
       
  6497 	u32_t md_length = key_length;
       
  6498 
       
  6499 	status = sha1.hash_final(
       
  6500 		reauth_XKEY.get_data_offset(0u, key_length),
       
  6501 		&md_length);
       
  6502 
       
  6503 	EAP_ASSERT_ALWAYS(md_length == key_length);
       
  6504 
       
  6505 
       
  6506 	EAP_TRACE_DEBUG(
       
  6507 		m_am_tools,
       
  6508 		TRACE_FLAGS_DEFAULT,
       
  6509 		(EAPL("generate_reauth_shared_secred_keys(): reauth_XKEY\n")));
       
  6510 	EAP_TRACE_DATA_DEBUG(
       
  6511 		m_am_tools,
       
  6512 		TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  6513 		(EAPL("reauth_XKEY"),
       
  6514 		reauth_XKEY.get_data(reauth_XKEY.get_data_length()),
       
  6515 		reauth_XKEY.get_data_length()));
       
  6516 
       
  6517 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  6518 
       
  6519 	u32_t aes_key_length = m_am_tools->get_crypto()->aes_key_length();
       
  6520 	u32_t data_length = aes_key_length + EAP_TYPE_AKA_MAC_SIZE + EAP_TYPE_AKA_MASTER_SESSION_KEY_SIZE;
       
  6521 
       
  6522 	eap_variable_data_c expansion(m_am_tools);
       
  6523 	eap_variable_data_c seed(m_am_tools);
       
  6524 
       
  6525 	if (expansion.get_is_valid() == false
       
  6526 		|| seed.get_is_valid() == false)
       
  6527 	{
       
  6528 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6529 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  6530 	}
       
  6531 
       
  6532 	status = seed.add_data(get_NAI());
       
  6533 	if (status != eap_status_ok)
       
  6534 	{
       
  6535 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6536 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6537 	}
       
  6538 
       
  6539 	status = data_exp(
       
  6540 		data_length,
       
  6541 		&expansion,
       
  6542 		&reauth_XKEY,
       
  6543 		&seed);
       
  6544 	if (status != eap_status_ok)
       
  6545 	{
       
  6546 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6547 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6548 	}
       
  6549 
       
  6550 	EAP_TRACE_DEBUG(
       
  6551 		m_am_tools,
       
  6552 		TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  6553 		(EAPL("generate_reauth_shared_secred_keys(): expansion\n")));
       
  6554 	EAP_TRACE_DATA_DEBUG(
       
  6555 		m_am_tools,
       
  6556 		TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  6557 		(EAPL("expansion"),
       
  6558 		expansion.get_data(expansion.get_data_length()),
       
  6559 		expansion.get_data_length()));
       
  6560 
       
  6561 	u8_t *data = expansion.get_data_offset(0u, data_length);
       
  6562 	if (data == 0)
       
  6563 	{
       
  6564 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6565 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  6566 	}
       
  6567 	const u8_t * const data_begin = data;
       
  6568 
       
  6569 	EAP_UNREFERENCED_PARAMETER(data_begin);
       
  6570 
       
  6571 	// Only master_session_key is used in re-authentication.
       
  6572 
       
  6573 	status = master_session_key->set_copy_of_buffer(data, EAP_TYPE_AKA_MASTER_SESSION_KEY_SIZE);
       
  6574 	if (status != eap_status_ok)
       
  6575 	{
       
  6576 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6577 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  6578 	}
       
  6579 	data += EAP_TYPE_AKA_MASTER_SESSION_KEY_SIZE;
       
  6580 	EAP_ASSERT_ALWAYS(static_cast<u32_t>(data-data_begin) <= data_length);
       
  6581 
       
  6582 
       
  6583 	EAP_TRACE_DEBUG(
       
  6584 		m_am_tools,
       
  6585 		TRACE_FLAGS_DEFAULT,
       
  6586 		(EAPL("generate_reauth_shared_secred_keys(): master_session_key\n")));
       
  6587 	EAP_TRACE_DATA_DEBUG(
       
  6588 		m_am_tools,
       
  6589 		TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  6590 		(EAPL("     MSK+EMSK"),
       
  6591 		master_session_key->get_data(master_session_key->get_data_length()),
       
  6592 		master_session_key->get_data_length()));
       
  6593 
       
  6594 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  6595 
       
  6596 
       
  6597 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6598 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  6599 }
       
  6600 
       
  6601 //--------------------------------------------------
       
  6602 
       
  6603 EAP_FUNC_EXPORT void eap_type_aka_c::delete_unused_keys()
       
  6604 {
       
  6605 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6606 
       
  6607 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6608 }
       
  6609 
       
  6610 //--------------------------------------------------
       
  6611 
       
  6612 EAP_FUNC_EXPORT eap_const_string eap_type_aka_c::get_identity_string(const eap_type_aka_identity_type identity_type)
       
  6613 {
       
  6614 #if defined(USE_EAP_TRACE_STRINGS)
       
  6615 	EAP_IF_RETURN_STRING(identity_type, AKA_IDENTITY_TYPE_NONE)
       
  6616 	else EAP_IF_RETURN_STRING(identity_type, AKA_IDENTITY_TYPE_IMSI_ID)
       
  6617 	else EAP_IF_RETURN_STRING(identity_type, AKA_IDENTITY_TYPE_PSEUDONYM_ID)
       
  6618 	else EAP_IF_RETURN_STRING(identity_type, AKA_IDENTITY_TYPE_RE_AUTH_ID)
       
  6619 	else
       
  6620 #endif // #if defined(USE_EAP_TRACE_STRINGS)
       
  6621 	{
       
  6622 		EAP_UNREFERENCED_PARAMETER(identity_type);
       
  6623 		return EAPL("Unknown AKA identity");
       
  6624 	}
       
  6625 }
       
  6626 
       
  6627 //--------------------------------------------------
       
  6628 
       
  6629 EAP_FUNC_EXPORT eap_const_string eap_type_aka_c::get_state_string(eap_type_aka_state_variable_e state)
       
  6630 {
       
  6631 
       
  6632 #if defined(USE_EAP_TRACE_STRINGS)
       
  6633 	EAP_IF_RETURN_STRING(state, eap_type_aka_state_waiting_for_identity_request)
       
  6634 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_pending_identity_query)
       
  6635 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_waiting_for_aka_identity_request)
       
  6636 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_imsi_waiting_for_aka_identity_request)
       
  6637 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_pseydonym_waiting_for_aka_identity_request)
       
  6638 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_analyse_aka_identity_request)
       
  6639 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_waiting_for_challenge_request)
       
  6640 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_analyses_challenge_request)
       
  6641 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_pending_kc_sres_query)
       
  6642 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_waiting_for_success)
       
  6643 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_waiting_for_reauth_request)
       
  6644 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_analyses_reauthentication_request)
       
  6645 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_pending_pseudonym_decode_query)
       
  6646 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_waiting_for_identity_response)
       
  6647 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_waiting_for_aka_identity_response_with_at_permanent_identity)
       
  6648 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_waiting_for_aka_identity_response_with_at_full_auth_identity)
       
  6649 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_waiting_for_aka_identity_response_with_at_any_identity)
       
  6650 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_waiting_for_aka_identity_response)
       
  6651 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_waiting_for_challenge_response)
       
  6652 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_pending_authentication_vector_query)
       
  6653 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_analyses_challenge_response)
       
  6654 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_analyses_aka_identity_response)
       
  6655 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_waiting_for_notification_request_success)
       
  6656 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_waiting_for_notification_response_failure)
       
  6657 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_waiting_for_notification_response_success)
       
  6658 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_waiting_for_reauth_response)
       
  6659 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_analyses_reauthentication_response)
       
  6660 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_success)
       
  6661 	else EAP_IF_RETURN_STRING(state, eap_type_aka_state_failure)
       
  6662 	else
       
  6663 #else
       
  6664 EAP_UNREFERENCED_PARAMETER(state);		
       
  6665 #endif // #if defined(USE_EAP_TRACE_STRINGS)
       
  6666 	{
       
  6667 		return EAPL("Unknown AKA state");
       
  6668 	}
       
  6669 }
       
  6670 
       
  6671 //--------------------------------------------------
       
  6672 
       
  6673 EAP_FUNC_EXPORT eap_const_string eap_type_aka_c::get_state_string() const
       
  6674 {
       
  6675 	return get_state_string(m_state);
       
  6676 }
       
  6677 
       
  6678 //--------------------------------------------------
       
  6679 
       
  6680 EAP_FUNC_EXPORT eap_const_string eap_type_aka_c::get_saved_previous_state_string() const
       
  6681 {
       
  6682 	return get_state_string(m_saved_previous_state);
       
  6683 }
       
  6684 
       
  6685 //--------------------------------------------------
       
  6686 
       
  6687 bool eap_type_aka_c::get_aka_notification_code_F_bit(const eap_aka_notification_codes_e notification_code)
       
  6688 {
       
  6689 	return ((notification_code & aka_notification_code_bit_f) != 0);
       
  6690 }
       
  6691 
       
  6692 //--------------------------------------------------
       
  6693 
       
  6694 bool eap_type_aka_c::get_aka_notification_code_P_bit(const eap_aka_notification_codes_e notification_code)
       
  6695 {
       
  6696 	return ((notification_code & aka_notification_code_bit_p) != 0);
       
  6697 }
       
  6698 
       
  6699 //--------------------------------------------------
       
  6700 
       
  6701 void eap_type_aka_c::object_increase_reference_count()
       
  6702 {
       
  6703 }
       
  6704 
       
  6705 //--------------------------------------------------
       
  6706 
       
  6707 u32_t eap_type_aka_c::object_decrease_reference_count()
       
  6708 {
       
  6709 	return 0u;
       
  6710 }
       
  6711 
       
  6712 //--------------------------------------------------
       
  6713 
       
  6714 void eap_type_aka_c::set_authentication_vector(eap_type_aka_authentication_vector_c * const authentication_vector)
       
  6715 {
       
  6716 	if (m_authentication_vector != 0)
       
  6717 	{
       
  6718 		delete m_authentication_vector;
       
  6719 		m_authentication_vector = 0;
       
  6720 	}
       
  6721 	m_authentication_vector = authentication_vector;
       
  6722 }
       
  6723 
       
  6724 //--------------------------------------------------
       
  6725 
       
  6726 void eap_type_aka_c::set_reauthentication_counter(const u32_t reauthentication_counter)
       
  6727 {
       
  6728 	m_reauthentication_counter = reauthentication_counter;
       
  6729 }
       
  6730 
       
  6731 //--------------------------------------------------
       
  6732 
       
  6733 u32_t eap_type_aka_c::get_reauthentication_counter()
       
  6734 {
       
  6735 	return m_reauthentication_counter;
       
  6736 }
       
  6737 
       
  6738 //--------------------------------------------------
       
  6739 
       
  6740 eap_type_aka_authentication_vector_c * eap_type_aka_c::get_authentication_vector()
       
  6741 {
       
  6742 	return m_authentication_vector;
       
  6743 }
       
  6744 
       
  6745 //--------------------------------------------------
       
  6746 
       
  6747 const eap_variable_data_c * eap_type_aka_c::get_RAND() const
       
  6748 {
       
  6749 	return &m_RAND;
       
  6750 }
       
  6751 
       
  6752 //--------------------------------------------------
       
  6753 
       
  6754 eap_status_e eap_type_aka_c::set_RAND(const eap_variable_data_c * const RAND)
       
  6755 {
       
  6756 	return m_RAND.set_copy_of_buffer(RAND);
       
  6757 }
       
  6758 
       
  6759 //--------------------------------------------------
       
  6760 
       
  6761 const eap_variable_data_c * eap_type_aka_c::get_AUTN() const
       
  6762 {
       
  6763 	return &m_AUTN;
       
  6764 }
       
  6765 
       
  6766 //--------------------------------------------------
       
  6767 
       
  6768 eap_status_e eap_type_aka_c::set_AUTN(const eap_variable_data_c * const AUTN)
       
  6769 {
       
  6770 	return m_AUTN.set_copy_of_buffer(AUTN);
       
  6771 }
       
  6772 
       
  6773 //--------------------------------------------------
       
  6774 
       
  6775 void eap_type_aka_c::set_last_eap_identifier(const u8_t last_eap_identifier)
       
  6776 {
       
  6777 	m_last_eap_identifier = last_eap_identifier;
       
  6778 }
       
  6779 
       
  6780 //--------------------------------------------------
       
  6781 
       
  6782 u8_t eap_type_aka_c::get_last_eap_identifier()
       
  6783 {
       
  6784 	return m_last_eap_identifier;
       
  6785 }
       
  6786 
       
  6787 //--------------------------------------------------
       
  6788 
       
  6789 void eap_type_aka_c::set_include_identity_to_aka_identity_response(const aka_payload_AT_type_e id_type_required)
       
  6790 {
       
  6791 	m_include_identity_to_aka_identity_response = id_type_required;
       
  6792 }
       
  6793 
       
  6794 //--------------------------------------------------
       
  6795 
       
  6796 aka_payload_AT_type_e eap_type_aka_c::get_include_identity_to_aka_identity_response()
       
  6797 {
       
  6798 	return m_include_identity_to_aka_identity_response;
       
  6799 }
       
  6800 
       
  6801 //--------------------------------------------------
       
  6802 
       
  6803 void eap_type_aka_c::set_aka_identity_response_includes_identity(const aka_payload_AT_type_e id_type_required)
       
  6804 {
       
  6805 	EAP_TRACE_DEBUG(
       
  6806 		m_am_tools,
       
  6807 		TRACE_FLAGS_DEFAULT,
       
  6808 		(EAPL("EAP_type_AKA: %s: eap_type_aka_c::set_aka_identity_response_includes_identity(): %d=%s\n"),
       
  6809 		(m_is_client == true ? "client": "server"),
       
  6810 		id_type_required,
       
  6811 		aka_payload_AT_header_c::get_payload_AT_string(id_type_required)));
       
  6812 
       
  6813 	m_aka_identity_response_includes_identity = id_type_required;
       
  6814 }
       
  6815 
       
  6816 //--------------------------------------------------
       
  6817 
       
  6818 aka_payload_AT_type_e eap_type_aka_c::get_aka_identity_response_includes_identity()
       
  6819 {
       
  6820 	return m_aka_identity_response_includes_identity;
       
  6821 }
       
  6822 
       
  6823 //--------------------------------------------------
       
  6824 
       
  6825 void eap_type_aka_c::set_failure_message_received()
       
  6826 {
       
  6827 	m_failure_message_received = true;
       
  6828 }
       
  6829 
       
  6830 //--------------------------------------------------
       
  6831 
       
  6832 void eap_type_aka_c::unset_failure_message_received()
       
  6833 {
       
  6834 	m_failure_message_received = false;
       
  6835 }
       
  6836 
       
  6837 //--------------------------------------------------
       
  6838 
       
  6839 bool eap_type_aka_c::get_failure_message_received()
       
  6840 {
       
  6841 	return m_failure_message_received;
       
  6842 }
       
  6843 
       
  6844 //--------------------------------------------------
       
  6845 
       
  6846 eap_type_aka_state_variable_e eap_type_aka_c::get_state()
       
  6847 {
       
  6848 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6849 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6850 	return m_state;
       
  6851 }
       
  6852 
       
  6853 //--------------------------------------------------
       
  6854 
       
  6855 eap_type_aka_state_variable_e eap_type_aka_c::get_saved_previous_state()
       
  6856 {
       
  6857 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6858 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6859 	return m_saved_previous_state;
       
  6860 }
       
  6861 
       
  6862 //--------------------------------------------------
       
  6863 
       
  6864 void eap_type_aka_c::save_current_state()
       
  6865 {
       
  6866 	m_saved_previous_state = m_state;
       
  6867 }
       
  6868 
       
  6869 //--------------------------------------------------
       
  6870 
       
  6871 void eap_type_aka_c::restore_saved_previous_state()
       
  6872 {
       
  6873 	set_state(m_saved_previous_state);
       
  6874 }
       
  6875 
       
  6876 //--------------------------------------------------
       
  6877 
       
  6878 eap_am_network_id_c * eap_type_aka_c::get_send_network_id()
       
  6879 {
       
  6880 	return &m_send_network_id;
       
  6881 }
       
  6882 
       
  6883 //--------------------------------------------------
       
  6884 
       
  6885 void eap_type_aka_c::set_authentication_finished_successfully()
       
  6886 {
       
  6887 	m_authentication_finished_successfully = true;
       
  6888 }
       
  6889 
       
  6890 //--------------------------------------------------
       
  6891 
       
  6892 bool eap_type_aka_c::get_authentication_finished_successfully()
       
  6893 {
       
  6894 	return m_authentication_finished_successfully;
       
  6895 }
       
  6896 
       
  6897 //--------------------------------------------------
       
  6898 
       
  6899 void eap_type_aka_c::set_state(eap_type_aka_state_variable_e state)
       
  6900 {
       
  6901 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6902 
       
  6903 	eap_type_aka_state_variable_e previous_state = m_state;
       
  6904 
       
  6905 	EAP_TRACE_DEBUG(
       
  6906 		m_am_tools, 
       
  6907 		TRACE_FLAGS_DEFAULT, 
       
  6908 		(EAPL("eap_type_aka_c::set_state(): old state %d=%s\n"),
       
  6909 		 get_state(),
       
  6910 		 get_state_string()));
       
  6911 
       
  6912 	EAP_TRACE_DEBUG(
       
  6913 		m_am_tools, 
       
  6914 		TRACE_FLAGS_DEFAULT, 
       
  6915 		(EAPL("eap_type_aka_c::set_state(): new state %d=%s\n"),
       
  6916 		 state,
       
  6917 		 get_state_string(state)));
       
  6918 
       
  6919 	m_state = state;
       
  6920 
       
  6921 	eap_type_aka_state_notification_c notification(
       
  6922 		m_am_tools,
       
  6923 		get_send_network_id(),
       
  6924 		m_is_client,
       
  6925 		eap_state_notification_eap,
       
  6926 		eap_protocol_layer_eap_type,
       
  6927 		eap_type_aka,
       
  6928 		previous_state,
       
  6929 		state,
       
  6930 		m_last_eap_identifier,
       
  6931 		false);
       
  6932 	state_notification(&notification);
       
  6933 
       
  6934 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6935 }
       
  6936 
       
  6937 //--------------------------------------------------
       
  6938 
       
  6939 eap_variable_data_c * eap_type_aka_c::get_NONCE_S()
       
  6940 {
       
  6941 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6942 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6943 	return &m_nonce_s;
       
  6944 }
       
  6945 
       
  6946 //--------------------------------------------------
       
  6947 
       
  6948 eap_variable_data_c * eap_type_aka_c::get_IMSI()
       
  6949 {
       
  6950 	return &m_IMSI;
       
  6951 }
       
  6952 
       
  6953 //--------------------------------------------------
       
  6954 
       
  6955 eap_variable_data_c * eap_type_aka_c::get_identity()
       
  6956 {
       
  6957 	return &m_identity;
       
  6958 }
       
  6959 
       
  6960 //--------------------------------------------------
       
  6961 
       
  6962 eap_variable_data_c * eap_type_aka_c::get_NAI()
       
  6963 {
       
  6964 	return &m_NAI;
       
  6965 }
       
  6966 
       
  6967 //--------------------------------------------------
       
  6968 
       
  6969 eap_variable_data_c * eap_type_aka_c::get_RES()
       
  6970 {
       
  6971 	return &m_RES;
       
  6972 }
       
  6973 
       
  6974 //--------------------------------------------------
       
  6975 
       
  6976 eap_variable_data_c * eap_type_aka_c::get_pseudonym()
       
  6977 {
       
  6978 	return &m_pseudonym;
       
  6979 }
       
  6980 
       
  6981 //--------------------------------------------------
       
  6982 
       
  6983 eap_variable_data_c * eap_type_aka_c::get_reauthentication_identity()
       
  6984 {
       
  6985 	return &m_reauthentication_identity;
       
  6986 }
       
  6987 
       
  6988 //--------------------------------------------------
       
  6989 
       
  6990 aka_variable_data_c * eap_type_aka_c::get_IV()
       
  6991 {
       
  6992 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6993 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6994 	return &m_IV;
       
  6995 }
       
  6996 
       
  6997 //--------------------------------------------------
       
  6998 
       
  6999 eap_variable_data_c * eap_type_aka_c::get_saved_EAP_packet()
       
  7000 {
       
  7001 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  7002 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  7003 	return &m_saved_EAP_packet;
       
  7004 }
       
  7005 
       
  7006 //--------------------------------------------------
       
  7007 
       
  7008 eap_variable_data_c * eap_type_aka_c::get_XKEY()
       
  7009 {
       
  7010 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  7011 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  7012 	return &m_XKEY;
       
  7013 }
       
  7014 
       
  7015 //--------------------------------------------------
       
  7016 
       
  7017 eap_variable_data_c * eap_type_aka_c::get_K_encr()
       
  7018 {
       
  7019 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  7020 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  7021 	return &m_K_encr;
       
  7022 }
       
  7023 
       
  7024 //--------------------------------------------------
       
  7025 
       
  7026 eap_variable_data_c * eap_type_aka_c::get_K_aut()
       
  7027 {
       
  7028 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  7029 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  7030 	return &m_K_aut;
       
  7031 }
       
  7032 
       
  7033 //--------------------------------------------------
       
  7034 
       
  7035 eap_master_session_key_c * eap_type_aka_c::get_master_session_key()
       
  7036 {
       
  7037 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  7038 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  7039 	return &m_master_session_key;
       
  7040 }
       
  7041 
       
  7042 //--------------------------------------------------
       
  7043 
       
  7044 eap_status_e eap_type_aka_c::store_last_encryption_iv(const eap_variable_data_c * const encryption_IV)
       
  7045 {
       
  7046 	return m_IV.get_payload_buffer()->set_copy_of_buffer(encryption_IV);
       
  7047 }
       
  7048 
       
  7049 //--------------------------------------------------
       
  7050 
       
  7051 void eap_type_aka_c::set_identity_type(eap_type_aka_identity_type type)
       
  7052 {
       
  7053 	EAP_TRACE_DEBUG(
       
  7054 		m_am_tools,
       
  7055 		TRACE_FLAGS_DEFAULT,
       
  7056 		(EAPL("GSMSIM: %s: eap_type_aka_c::set_identity_type(): %d=%s\n"),
       
  7057 		(m_is_client == true ? "client": "server"),
       
  7058 		type,
       
  7059 		get_identity_string(type)));
       
  7060 
       
  7061 	m_identity_type = type;
       
  7062 }
       
  7063 
       
  7064 //--------------------------------------------------
       
  7065 //--------------------------------------------------
       
  7066 //--------------------------------------------------
       
  7067 
       
  7068 eap_type_aka_MAC_attributes_c::~eap_type_aka_MAC_attributes_c()
       
  7069 {
       
  7070 }
       
  7071 
       
  7072 //--------------------------------------------------
       
  7073 
       
  7074 eap_type_aka_MAC_attributes_c::eap_type_aka_MAC_attributes_c()
       
  7075 	: m_MAC(0)
       
  7076 	, m_MAC_size(0)
       
  7077 	, m_data(0)
       
  7078 	, m_data_length(0u)
       
  7079 {
       
  7080 }
       
  7081 
       
  7082 //--------------------------------------------------
       
  7083 
       
  7084 eap_type_aka_MAC_attributes_c::eap_type_aka_MAC_attributes_c(
       
  7085 	u8_t * MAC,
       
  7086 	u32_t MAC_size,
       
  7087 	u8_t * const EAP_data,
       
  7088 	u32_t EAP_data_length)
       
  7089 	: m_MAC(MAC)
       
  7090 	, m_MAC_size(MAC_size)
       
  7091 	, m_data(EAP_data)
       
  7092 	, m_data_length(EAP_data_length)
       
  7093 {
       
  7094 }
       
  7095 
       
  7096 //--------------------------------------------------
       
  7097 
       
  7098 void eap_type_aka_MAC_attributes_c::init(
       
  7099 	u8_t * MAC,
       
  7100 	u32_t MAC_size,
       
  7101 	u8_t * const EAP_data,
       
  7102 	u32_t EAP_data_length)
       
  7103 {
       
  7104 	m_MAC = (MAC);
       
  7105 	m_MAC_size = (MAC_size);
       
  7106 	m_data = (EAP_data);
       
  7107 	m_data_length = (EAP_data_length);
       
  7108 }
       
  7109 
       
  7110 //--------------------------------------------------
       
  7111 
       
  7112 u8_t * eap_type_aka_MAC_attributes_c::get_MAC() const
       
  7113 {
       
  7114 	return m_MAC;
       
  7115 }
       
  7116 
       
  7117 //--------------------------------------------------
       
  7118 
       
  7119 void eap_type_aka_MAC_attributes_c::set_MAC(u8_t * MAC)
       
  7120 {
       
  7121 	m_MAC = MAC;
       
  7122 }
       
  7123 
       
  7124 //--------------------------------------------------
       
  7125 
       
  7126 u32_t eap_type_aka_MAC_attributes_c::get_MAC_size() const
       
  7127 {
       
  7128 	return m_MAC_size;
       
  7129 }
       
  7130 
       
  7131 //--------------------------------------------------
       
  7132 
       
  7133 eap_type_aka_MAC_attributes_c * eap_type_aka_MAC_attributes_c::copy() const
       
  7134 {
       
  7135 	return new eap_type_aka_MAC_attributes_c(
       
  7136 		m_MAC,
       
  7137 		m_MAC_size,
       
  7138 		m_data,
       
  7139 		m_data_length);
       
  7140 }
       
  7141 
       
  7142 //--------------------------------------------------
       
  7143 
       
  7144 u8_t * eap_type_aka_MAC_attributes_c::get_data() const
       
  7145 {
       
  7146 	return m_data;
       
  7147 }
       
  7148 
       
  7149 //--------------------------------------------------
       
  7150 
       
  7151 u32_t eap_type_aka_MAC_attributes_c::get_data_length()
       
  7152 {
       
  7153 	return m_data_length;
       
  7154 }
       
  7155 
       
  7156 //--------------------------------------------------
       
  7157 
       
  7158 void eap_type_aka_MAC_attributes_c::set_data(u8_t * const data)
       
  7159 {
       
  7160 	m_data = data;
       
  7161 }
       
  7162 
       
  7163 
       
  7164 //--------------------------------------------------
       
  7165 //--------------------------------------------------
       
  7166 //--------------------------------------------------
       
  7167 // End.