eapol/eapol_framework/eapol_common/type/aka/core/eap_type_aka_server.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 70 
       
    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 "eap_automatic_variable.h"
       
    38 #include "eap_buffer.h"
       
    39 
       
    40 
       
    41 //--------------------------------------------------
       
    42 
       
    43 /** @file */
       
    44 
       
    45 //--------------------------------------------------
       
    46 
       
    47 
       
    48 //
       
    49 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::add_mac_payload(
       
    50 	aka_header_c * const aka,
       
    51 	const u32_t aka_buffer_length,
       
    52 	const u32_t eap_header_size,
       
    53 	u32_t * const aka_data_offset,
       
    54 	u32_t * const aka_data_free,
       
    55 	u32_t * const packet_buffer_free,
       
    56 	u32_t * const packet_buffer_offset,
       
    57 	u8_t ** const MAC_data,
       
    58 	u32_t * const MAC_data_length)
       
    59 {
       
    60 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
    61 
       
    62 	aka_payload_AT_header_c gp_MAC(
       
    63 		m_am_tools,
       
    64 		aka->get_data_offset(
       
    65 			*aka_data_offset, *aka_data_free),
       
    66 		*aka_data_free);
       
    67 
       
    68 	if (gp_MAC.get_is_valid() == false)
       
    69 	{
       
    70 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
    71 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
    72 	}
       
    73 
       
    74 	u32_t eap_type_aka_mac_size = EAP_TYPE_AKA_MAC_SIZE;
       
    75 
       
    76 	gp_MAC.reset_header(static_cast<u16_t>(eap_type_aka_mac_size));
       
    77 	gp_MAC.set_data_length(static_cast<u16_t>(eap_type_aka_mac_size));
       
    78 	gp_MAC.set_current_payload(aka_payload_AT_MAC);
       
    79 
       
    80 	*MAC_data = gp_MAC.get_data(eap_type_aka_mac_size);
       
    81 	if (*MAC_data == 0)
       
    82 	{
       
    83 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
    84 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
    85 	}
       
    86 	*MAC_data_length = eap_type_aka_mac_size;
       
    87 
       
    88 	m_am_tools->memset(*MAC_data, 0, eap_type_aka_mac_size);
       
    89 
       
    90 	// MAC is calculated later using call create_message_authentication_code().
       
    91 
       
    92 	update_payload_indexes(
       
    93 		aka_buffer_length,
       
    94 		eap_header_size,
       
    95 		gp_MAC.get_header_length()+gp_MAC.get_data_length(),
       
    96 		aka_data_offset,
       
    97 		aka_data_free,
       
    98 		packet_buffer_offset,
       
    99 		packet_buffer_free);
       
   100 
       
   101 	EAP_AKA_TRACE_PAYLOAD("Payload added", &gp_MAC);
       
   102 
       
   103 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   104 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   105 }
       
   106 
       
   107 //--------------------------------------------------
       
   108 
       
   109 //
       
   110 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::add_padding_payload(
       
   111 	aka_header_c * const aka,
       
   112 	const u32_t aka_buffer_length,
       
   113 	const u32_t eap_header_size,
       
   114 	u32_t * const aka_data_offset,
       
   115 	u32_t * const aka_data_free,
       
   116 	u32_t * const packet_buffer_free,
       
   117 	u32_t * const packet_buffer_offset,
       
   118 	const u32_t plaintext_length)
       
   119 {
       
   120 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   121 
       
   122 	aka_payload_AT_header_c gp_padding(
       
   123 		m_am_tools,
       
   124 		aka->get_data_offset(
       
   125 			*aka_data_offset, *aka_data_free),
       
   126 		*aka_data_free);
       
   127 
       
   128 	if (gp_padding.get_is_valid() == false)
       
   129 	{
       
   130 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   131 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
   132 	}
       
   133 
       
   134 	crypto_aes_c aes(m_am_tools);
       
   135 	crypto_cbc_c cbc_aes(m_am_tools, &aes, false);
       
   136 
       
   137 	if (cbc_aes.get_is_valid() == false)
       
   138 	{
       
   139 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   140 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   141 	}
       
   142 
       
   143 	if ((plaintext_length % cbc_aes.get_block_size()) == 0ul)
       
   144 	{
       
   145 		// We do not need padding, because plaintext length is multiple of
       
   146 		// block size.
       
   147 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   148 		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   149 	}
       
   150 
       
   151 	u32_t cbc_aes_data_length = cbc_aes.aligned_data_length(plaintext_length);
       
   152 	u32_t padding_bytes_length = 0u;
       
   153 
       
   154 	if (cbc_aes_data_length
       
   155 		> plaintext_length+aka_payload_AT_header_c::get_header_length())
       
   156 	{
       
   157 		// Fill with zero (0x00) bytes.
       
   158 		padding_bytes_length
       
   159 			= cbc_aes_data_length
       
   160 			- (plaintext_length
       
   161 			   +aka_payload_AT_header_c::get_header_length());
       
   162 	}
       
   163 
       
   164 	u32_t padding_payload_length
       
   165 		= aka_payload_AT_header_c::get_header_length()
       
   166 		+padding_bytes_length;
       
   167 
       
   168 	if ((padding_payload_length % EAP_TYPE_AKA_PADDING_MODULUS) != 0)
       
   169 	{
       
   170 		// ERROR
       
   171 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   172 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_padding);
       
   173 	}
       
   174 
       
   175 	if (padding_payload_length > EAP_TYPE_AKA_PADDING_MAX_VALUE)
       
   176 	{
       
   177 		padding_payload_length = 0ul;
       
   178 		padding_bytes_length = 0ul;
       
   179 	}
       
   180 
       
   181 	// Note the reserved field is the begin of padding.
       
   182 	// The reserved field is set zero in reset_header() function.
       
   183 	gp_padding.reset_header(static_cast<u16_t>(padding_payload_length));
       
   184 	gp_padding.set_data_length(static_cast<u16_t>(padding_bytes_length));
       
   185 	gp_padding.set_current_payload(aka_payload_AT_PADDING);
       
   186 
       
   187 	if (padding_bytes_length > 0ul)
       
   188 	{
       
   189 		u8_t *padding = gp_padding.get_data(padding_bytes_length);
       
   190 		if (padding == 0)
       
   191 		{
       
   192 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   193 			return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
   194 		}
       
   195 
       
   196 		cbc_aes.add_padding_bytes(
       
   197 			padding,
       
   198 			padding_bytes_length,
       
   199 			0ul);
       
   200 	}
       
   201 
       
   202 	update_payload_indexes(
       
   203 		aka_buffer_length,
       
   204 		eap_header_size,
       
   205 		gp_padding.get_header_length()+gp_padding.get_data_length(),
       
   206 		aka_data_offset,
       
   207 		aka_data_free,
       
   208 		packet_buffer_offset,
       
   209 		packet_buffer_free);
       
   210 
       
   211 	EAP_AKA_TRACE_PAYLOAD("Padding payload added", &gp_padding);
       
   212 
       
   213 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   214 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   215 }
       
   216 
       
   217 //--------------------------------------------------
       
   218 
       
   219 //
       
   220 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::encrypt_DATA_payload(
       
   221 	u8_t * const data,
       
   222 	const u32_t cbc_aes_data_length,
       
   223 	const eap_variable_data_c * const IV,
       
   224 	const eap_variable_data_c * const encryption_key
       
   225 	)
       
   226 {
       
   227 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   228 
       
   229 	eap_status_e status = eap_status_process_general_error;
       
   230 
       
   231 	if (data == 0
       
   232 		|| cbc_aes_data_length == 0
       
   233 		|| IV == 0
       
   234 		|| IV->get_is_valid_data() == false
       
   235 		|| encryption_key == 0
       
   236 		|| encryption_key->get_is_valid_data() == false)
       
   237 	{
       
   238 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   239 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
   240 	}
       
   241 	
       
   242 	crypto_aes_c aes(m_am_tools);
       
   243 	crypto_cbc_c cbc_aes(m_am_tools, &aes, false);
       
   244 
       
   245 	if (cbc_aes.get_is_valid() == false)
       
   246 	{
       
   247 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   248 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   249 	}
       
   250 
       
   251 	u32_t aes_key_length = aes.get_key_length();
       
   252 	if (encryption_key->get_data_length() < aes_key_length)
       
   253 	{
       
   254 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   255 		return EAP_STATUS_RETURN(m_am_tools, eap_status_key_error);
       
   256 	}
       
   257 
       
   258 	status = cbc_aes.set_encryption_key(
       
   259 		IV->get_data(IV->get_data_length()),
       
   260 		IV->get_data_length(),
       
   261 		encryption_key->get_data(encryption_key->get_data_length()),
       
   262 		aes_key_length);
       
   263 	if (status != eap_status_ok)
       
   264 	{
       
   265 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   266 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   267 	}
       
   268 
       
   269 	status = cbc_aes.encrypt_data(
       
   270 		data,
       
   271 		cbc_aes_data_length);
       
   272 
       
   273 	store_last_encryption_iv(cbc_aes.get_tmp_IV());
       
   274 
       
   275 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   276 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   277 }
       
   278 
       
   279 //--------------------------------------------------
       
   280 
       
   281 //
       
   282 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::send_reauthentication_request_message(
       
   283 	const eap_variable_data_c * const username,
       
   284 	const bool pseudonym_decode_failed,
       
   285 	const u8_t eap_identifier)
       
   286 {
       
   287 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   288 
       
   289 	EAP_UNREFERENCED_PARAMETER(pseudonym_decode_failed);
       
   290 
       
   291 	EAP_TRACE_DEBUG(
       
   292 		m_am_tools, 
       
   293 		TRACE_FLAGS_DEFAULT, 
       
   294 		(EAPL("    send: handler 0x%08x, AKA-subtype %10s, %s, state %2d=%s\n"),
       
   295 		 this,
       
   296 		 EAPL("aka_subtype_Re_authentication"),
       
   297 		 EAPL("server"),
       
   298 		 get_state(),
       
   299 		 get_state_string()
       
   300 		 ));
       
   301 
       
   302 
       
   303 	eap_variable_data_c checkcode_digest(m_am_tools);
       
   304 
       
   305 	if (checkcode_digest.get_is_valid() == false)
       
   306 	{
       
   307 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   308 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   309 	}
       
   310 
       
   311 	eap_status_e status = eap_status_process_general_error;
       
   312 
       
   313 	status = checkcode_final(
       
   314 		&checkcode_digest);
       
   315 	if (status != eap_status_ok)
       
   316 	{
       
   317 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   318 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   319 	}
       
   320 
       
   321 
       
   322 	eap_buf_chain_wr_c request_packet(
       
   323 		eap_write_buffer, 
       
   324 		m_am_tools, 
       
   325 		EAP_MAX_LOCAL_PACKET_BUFFER_LENGTH);
       
   326 
       
   327 	if (request_packet.get_is_valid() == false)
       
   328 	{
       
   329 		EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("packet buffer corrupted.\n")));
       
   330 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   331 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   332 	}
       
   333 
       
   334 	if (m_is_client == true
       
   335 		&& m_client_responds_retransmitted_packets == true)
       
   336 	{
       
   337 		// We do not wan't lower layers do re-transmissions behalf of us.
       
   338 		// This means AKA does process every re-transmitted EAP-Request.
       
   339 		request_packet.set_do_packet_retransmission(false);
       
   340 	}
       
   341 
       
   342 	EAP_ASSERT_ALWAYS(EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH >= (m_aka_header_offset+m_trailer_length));
       
   343 	u32_t packet_buffer_free = EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH-m_trailer_length;
       
   344 	u32_t packet_buffer_offset = 0u;
       
   345 
       
   346 	if (m_aka_header_offset+m_MTU < packet_buffer_free)
       
   347 	{
       
   348 		packet_buffer_free = m_aka_header_offset+m_MTU;
       
   349 	}
       
   350 
       
   351 	aka_header_c aka_response(
       
   352 		m_am_tools,
       
   353 		request_packet.get_data_offset(
       
   354 			m_aka_header_offset,
       
   355 			(packet_buffer_free-m_aka_header_offset)),
       
   356 		(packet_buffer_free-m_aka_header_offset));
       
   357 
       
   358 	if (aka_response.get_is_valid() == false)
       
   359 	{
       
   360 		EAP_TRACE_DEBUG(
       
   361 			m_am_tools,
       
   362 			TRACE_FLAGS_DEFAULT,
       
   363 			(EAPL("send_reauthentication_request_message: packet buffer corrupted.\n")));
       
   364 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
   365 	}
       
   366 
       
   367 	aka_response.reset_header(
       
   368 		packet_buffer_free-m_aka_header_offset,
       
   369 		m_use_eap_expanded_type);
       
   370 	aka_response.set_length(
       
   371 		static_cast<u16_t>(packet_buffer_free-m_aka_header_offset),
       
   372 		m_use_eap_expanded_type);
       
   373 	aka_response.set_code(eap_code_request);
       
   374 	aka_response.set_identifier(eap_identifier);
       
   375 	aka_response.set_type(
       
   376 		eap_type_aka,
       
   377 		m_use_eap_expanded_type);
       
   378 	aka_response.set_subtype(aka_subtype_Re_authentication);
       
   379 
       
   380 	update_buffer_indexes(
       
   381 		EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
   382 		m_aka_header_offset+aka_response.get_header_length(),
       
   383 		&packet_buffer_offset,
       
   384 		&packet_buffer_free);
       
   385 
       
   386 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
   387 
       
   388 	EAP_TRACE_DEBUG(
       
   389 		m_am_tools, 
       
   390 		TRACE_FLAGS_DEFAULT, 
       
   391 		(EAPL("eap_type_aka_c::send_reauthentication_request_message(0x%08x).\n"),
       
   392 		this));
       
   393 
       
   394 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
   395 
       
   396 	u32_t aka_data_free = packet_buffer_free;
       
   397 	u32_t aka_data_offset = 0u;
       
   398 
       
   399 	eap_variable_data_c orig_XKEY(m_am_tools);
       
   400 	eap_variable_data_c orig_K_aut(m_am_tools);
       
   401 	eap_variable_data_c orig_K_encr(m_am_tools);
       
   402 
       
   403 	if (orig_XKEY.get_is_valid() == false
       
   404 		|| orig_K_aut.get_is_valid() == false
       
   405 		|| orig_K_encr.get_is_valid() == false)
       
   406 	{
       
   407 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   408 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   409 	}
       
   410 
       
   411 	u32_t reauth_counter = 0u;
       
   412 
       
   413 	eap_variable_data_c reauth_nonce_s(m_am_tools);
       
   414 
       
   415 	if (reauth_nonce_s.get_is_valid() == false)
       
   416 	{
       
   417 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   418 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   419 	}
       
   420 
       
   421 
       
   422 	// In order to use re-authentication, the client and the server need to
       
   423 	// store the following values: original XKEY, K_aut, K_encr, latest
       
   424 	// counter value and the next re-authentication identity.
       
   425 	status = m_am_type_aka->query_reauth_parameters(
       
   426 		&orig_XKEY,
       
   427 		&orig_K_aut,
       
   428 		&orig_K_encr,
       
   429 		&reauth_counter);
       
   430 	if (status != eap_status_ok)
       
   431 	{
       
   432 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   433 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   434 	}
       
   435 
       
   436 	status = generate_nonce(EAP_TYPE_AKA_NONCE_MT_SIZE, &reauth_nonce_s);
       
   437 	if (status != eap_status_ok)
       
   438 	{
       
   439 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   440 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   441 	}
       
   442 
       
   443 	status = get_NONCE_S()->set_copy_of_buffer(&reauth_nonce_s);
       
   444 	if (status != eap_status_ok)
       
   445 	{
       
   446 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   447 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   448 	}
       
   449 
       
   450 	eap_variable_data_c master_session_key(m_am_tools);
       
   451 
       
   452 	if (master_session_key.get_is_valid() == false)
       
   453 	{
       
   454 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   455 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   456 	}
       
   457 
       
   458 	status = generate_reauth_shared_secred_keys(
       
   459 		EAP_TYPE_AKA_KEYMAT_SIZE,
       
   460 		&orig_XKEY,
       
   461 		reauth_counter,
       
   462 		username,
       
   463 		&reauth_nonce_s,
       
   464 		&master_session_key);
       
   465 	if (status != eap_status_ok)
       
   466 	{
       
   467 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   468 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   469 	}
       
   470 
       
   471 	// -   -   -   -   -   -   -   -   -   -   -   -
       
   472 
       
   473 	m_use_result_indication = m_allow_use_result_indication;
       
   474 
       
   475 	if (m_use_result_indication == true)
       
   476 	{
       
   477 		// We support use of protected success indications.
       
   478 		status = add_simple_payload(
       
   479 			&aka_response,
       
   480 			EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
   481 			aka_response.get_header_length(),
       
   482 			&aka_data_offset,
       
   483 			&aka_data_free,
       
   484 			&packet_buffer_free,
       
   485 			&packet_buffer_offset,
       
   486 			aka_payload_AT_RESULT_IND);
       
   487 		if (status != eap_status_ok)
       
   488 		{
       
   489 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   490 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   491 		}
       
   492 	}
       
   493 
       
   494 	// -   -   -   -   -   -   -   -   -   -   -   -
       
   495 
       
   496 	status = add_variable_payload(
       
   497 		&aka_response,
       
   498 		EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
   499 		aka_response.get_header_length(),
       
   500 		&aka_data_offset,
       
   501 		&aka_data_free,
       
   502 		&packet_buffer_free,
       
   503 		&packet_buffer_offset,
       
   504 		&checkcode_digest,
       
   505 		aka_payload_AT_CHECKCODE);
       
   506 	if (status != eap_status_ok)
       
   507 	{
       
   508 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   509 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   510 	}
       
   511 
       
   512 	// -   -   -   -   -   -   -   -   -   -   -   -
       
   513 
       
   514 	crypto_aes_c aes(m_am_tools);
       
   515 
       
   516 	if (aes.get_is_valid() == false)
       
   517 	{
       
   518 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   519 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   520 	}
       
   521 
       
   522 	status = m_am_type_aka->generate_encryption_IV(
       
   523 		get_IV()->get_payload_buffer(),
       
   524 		aes.get_block_size());
       
   525 	if (status != eap_status_ok)
       
   526 	{
       
   527 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   528 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   529 	}
       
   530 
       
   531 	// -   -   -   -   -   -   -   -   -   -   -   -
       
   532 
       
   533 	status = add_variable_payload(
       
   534 		&aka_response,
       
   535 		EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
   536 		aka_response.get_header_length(),
       
   537 		&aka_data_offset,
       
   538 		&aka_data_free,
       
   539 		&packet_buffer_free,
       
   540 		&packet_buffer_offset,
       
   541 		get_IV()->get_payload_buffer(),
       
   542 		aka_payload_AT_IV);
       
   543 	if (status != eap_status_ok)
       
   544 	{
       
   545 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   546 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   547 	}
       
   548 
       
   549 
       
   550 	u8_t *MAC_data = 0;
       
   551 	u32_t MAC_data_length = 0u;
       
   552 	eap_type_aka_MAC_attributes_c MAC_attributes;
       
   553 
       
   554 	// Encrypted data.
       
   555 	{
       
   556 		aka_payload_AT_header_c gp_encrypted_data(
       
   557 			m_am_tools,
       
   558 			aka_response.get_data_offset(
       
   559 				aka_data_offset, 
       
   560 				aka_data_free),
       
   561 			aka_data_free);
       
   562 		if (aka_response.get_is_valid() == false)
       
   563 		{
       
   564 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   565 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   566 		}
       
   567 
       
   568 		// Initialize the length of encrypted data to maximum length.
       
   569 		// Later this will be set to correct length.
       
   570 		gp_encrypted_data.reset_header(aka_payload_AT_header_c::get_max_payload_data_length());
       
   571 		gp_encrypted_data.set_current_payload(aka_payload_AT_ENCR_DATA);
       
   572 
       
   573 		update_payload_indexes(
       
   574 			EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
   575 			aka_response.get_header_length(),
       
   576 			gp_encrypted_data.get_header_length(),
       
   577 			&aka_data_offset,
       
   578 			&aka_data_free,
       
   579 			&packet_buffer_offset,
       
   580 			&packet_buffer_free);
       
   581 
       
   582 		u32_t encrypted_data_offset_begin = packet_buffer_offset;
       
   583 
       
   584 		// -   -   -   -   -   -   -   -   -   -   -   -
       
   585 
       
   586 		status = add_counter_payload(
       
   587 			&aka_response,
       
   588 			EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
   589 			aka_response.get_header_length(),
       
   590 			&aka_data_offset,
       
   591 			&aka_data_free,
       
   592 			&packet_buffer_free,
       
   593 			&packet_buffer_offset,
       
   594 			static_cast<u16_t>(reauth_counter));
       
   595 		if (status != eap_status_ok)
       
   596 		{
       
   597 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   598 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   599 		}
       
   600 
       
   601 		// -   -   -   -   -   -   -   -   -   -   -   -
       
   602 
       
   603 		status = add_variable_payload(
       
   604 			&aka_response,
       
   605 			EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
   606 			aka_response.get_header_length(),
       
   607 			&aka_data_offset,
       
   608 			&aka_data_free,
       
   609 			&packet_buffer_free,
       
   610 			&packet_buffer_offset,
       
   611 			&reauth_nonce_s,
       
   612 			aka_payload_AT_NONCE_S);
       
   613 		if (status != eap_status_ok)
       
   614 		{
       
   615 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   616 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   617 		}
       
   618 
       
   619 		// -   -   -   -   -   -   -   -   -   -   -   -
       
   620 
       
   621 		status = m_am_type_aka->generate_reauthentication_id(
       
   622 			get_send_network_id(),
       
   623 			get_IMSI(),
       
   624 			get_reauthentication_identity(),
       
   625 			EAP_TYPE_AKA_MAX_NAI_LENGTH);
       
   626 		if (status == eap_status_ok)
       
   627 		{
       
   628 			status = add_pseudonym_or_imsi_payload(
       
   629 				&aka_response,
       
   630 				EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
   631 				aka_response.get_header_length(),
       
   632 				&aka_data_offset,
       
   633 				&aka_data_free,
       
   634 				&packet_buffer_free,
       
   635 				&packet_buffer_offset,
       
   636 				get_reauthentication_identity(),
       
   637 				aka_payload_AT_NEXT_REAUTH_ID);
       
   638 			if (status != eap_status_ok)
       
   639 			{
       
   640 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   641 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   642 			}
       
   643 		}
       
   644 
       
   645 		// -   -   -   -   -   -   -   -   -   -   -   -
       
   646 
       
   647 		status = add_padding_payload(
       
   648 			&aka_response,
       
   649 			EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
   650 			aka_response.get_header_length(),
       
   651 			&aka_data_offset,
       
   652 			&aka_data_free,
       
   653 			&packet_buffer_free,
       
   654 			&packet_buffer_offset,
       
   655 			(packet_buffer_offset - encrypted_data_offset_begin) // Length of the plain text.
       
   656 			);
       
   657 		if (status != eap_status_ok)
       
   658 		{
       
   659 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   660 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   661 		}
       
   662 
       
   663 		gp_encrypted_data.set_data_length(
       
   664 			static_cast<u16_t>(packet_buffer_offset - encrypted_data_offset_begin));
       
   665 
       
   666 		// -   -   -   -   -   -   -   -   -   -   -   -
       
   667 
       
   668 		status = encrypt_DATA_payload(
       
   669 			gp_encrypted_data.get_data(gp_encrypted_data.get_data_length()),
       
   670 			gp_encrypted_data.get_data_length(),
       
   671 			get_IV()->get_payload_buffer(),
       
   672 			&orig_K_encr);
       
   673 		if (status != eap_status_ok)
       
   674 		{
       
   675 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   676 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   677 		}
       
   678 
       
   679 		EAP_AKA_TRACE_PAYLOAD("Payload added", &gp_encrypted_data);
       
   680 	}
       
   681 
       
   682 	// -   -   -   -   -   -   -   -   -   -   -   -
       
   683 
       
   684 	status = add_mac_payload(
       
   685 		&aka_response,
       
   686 		EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
   687 		aka_response.get_header_length(),
       
   688 		&aka_data_offset,
       
   689 		&aka_data_free,
       
   690 		&packet_buffer_free,
       
   691 		&packet_buffer_offset,
       
   692 		&MAC_data,
       
   693 		&MAC_data_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 	// -   -   -   -   -   -   -   -   -   -   -   -
       
   701 
       
   702 	aka_response.set_data_length(
       
   703 		aka_data_offset,
       
   704 		m_use_eap_expanded_type);
       
   705 	request_packet.set_data_length(packet_buffer_offset);
       
   706 
       
   707 	EAP_ASSERT_ALWAYS(
       
   708 		m_aka_header_offset+aka_response.get_header_length()+aka_response.get_data_length()
       
   709 		== packet_buffer_offset);
       
   710 
       
   711 	// -   -   -   -   -   -   -   -   -   -   -   -
       
   712 
       
   713 	MAC_attributes.init(
       
   714 		MAC_data,
       
   715 		MAC_data_length,
       
   716 		aka_response.get_header_buffer(aka_response.get_length()),
       
   717 		aka_response.get_length());
       
   718 
       
   719 	status = create_message_authentication_code(
       
   720 		&MAC_attributes,
       
   721 		aka_response.get_subtype(),
       
   722 		aka_response.get_code(),
       
   723 		&orig_K_aut);
       
   724 	if (status != eap_status_ok)
       
   725 	{
       
   726 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   727 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   728 	}
       
   729 
       
   730 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
   731 
       
   732 	aka_response.set_data_length(
       
   733 		aka_data_offset,
       
   734 		m_use_eap_expanded_type);
       
   735 	request_packet.set_data_length(packet_buffer_offset);
       
   736 
       
   737 	EAP_ASSERT_ALWAYS(
       
   738 		m_aka_header_offset+aka_response.get_header_length()+aka_response.get_data_length()
       
   739 		== packet_buffer_offset);
       
   740 
       
   741 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
   742 
       
   743 	EAP_TRACE_DEBUG(
       
   744 		m_am_tools, 
       
   745 		TRACE_FLAGS_DEFAULT, 
       
   746 		(EAPL("eap_type_aka_c::send_reauthentication_request_message()\n")));
       
   747 
       
   748 	status = packet_send(
       
   749 		get_send_network_id(),
       
   750 		&request_packet,
       
   751 		m_aka_header_offset,
       
   752 		aka_response.get_header_length()+aka_response.get_data_length(),
       
   753 		EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH
       
   754 		);
       
   755 
       
   756 	if (status == eap_status_ok)
       
   757 	{
       
   758 		status = get_master_session_key()->set_copy_of_buffer(&master_session_key);
       
   759 		if (status != eap_status_ok)
       
   760 		{
       
   761 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   762 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   763 		}
       
   764 		set_state(eap_type_aka_state_waiting_for_reauth_response);
       
   765 	}
       
   766 
       
   767 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
   768 
       
   769 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   770 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   771 }
       
   772 
       
   773 //--------------------------------------------------
       
   774 
       
   775 //
       
   776 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::send_aka_identity_request_message(
       
   777 	const bool pseudonym_decode_failed,
       
   778 	const u8_t eap_identifier)
       
   779 {
       
   780 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   781 
       
   782 	EAP_TRACE_DEBUG(
       
   783 		m_am_tools, 
       
   784 		TRACE_FLAGS_DEFAULT, 
       
   785 		(EAPL("    send: handler 0x%08x, %s, AKA-subtype %10s, %s, state %2d=%s\n"),
       
   786 		 this,
       
   787 		 EAPL("initiator"),
       
   788 		 EAPL("aka_subtype_Identity"),
       
   789 		 EAPL("server"),
       
   790 		 get_state(),
       
   791 		 get_state_string()
       
   792 		 ));
       
   793 
       
   794 	EAP_TRACE_DEBUG(
       
   795 		m_am_tools, 
       
   796 		TRACE_FLAGS_DEFAULT, 
       
   797 		(EAPL("eap_type_aka_c::send_aka_identity_request_message(): ")
       
   798 		 EAPL("requested identity payload is %d=%s, state %d=%s, pseudonym decode %d.\n"),
       
   799 		 get_aka_identity_response_includes_identity(),
       
   800 		 aka_payload_AT_header_c::get_payload_AT_string(get_aka_identity_response_includes_identity()),
       
   801 		 get_state(),
       
   802 		 get_state_string(),
       
   803 		 pseudonym_decode_failed));
       
   804 
       
   805 	eap_status_e status = eap_status_process_general_error;
       
   806 
       
   807 	eap_buf_chain_wr_c request_packet(
       
   808 		eap_write_buffer, 
       
   809 		m_am_tools, 
       
   810 		EAP_MAX_LOCAL_PACKET_BUFFER_LENGTH);
       
   811 
       
   812 	if (request_packet.get_is_valid() == false)
       
   813 	{
       
   814 		EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("packet buffer corrupted.\n")));
       
   815 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   816 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   817 	}
       
   818 
       
   819 	if (m_is_client == true
       
   820 		&& m_client_responds_retransmitted_packets == true)
       
   821 	{
       
   822 		// We do not wan't lower layers do re-transmissions behalf of us.
       
   823 		// This means AKA does process every re-transmitted EAP-Request.
       
   824 		request_packet.set_do_packet_retransmission(false);
       
   825 	}
       
   826 
       
   827 	EAP_ASSERT_ALWAYS(EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH >= (m_aka_header_offset+m_trailer_length));
       
   828 	u32_t packet_buffer_free = EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH-m_trailer_length;
       
   829 	u32_t packet_buffer_offset = 0u;
       
   830 
       
   831 	if (m_aka_header_offset+m_MTU < packet_buffer_free)
       
   832 	{
       
   833 		packet_buffer_free = m_aka_header_offset+m_MTU;
       
   834 	}
       
   835 
       
   836 	aka_header_c aka_response(
       
   837 		m_am_tools,
       
   838 		request_packet.get_data_offset(
       
   839 			m_aka_header_offset,
       
   840 			(packet_buffer_free-m_aka_header_offset)),
       
   841 		(packet_buffer_free-m_aka_header_offset));
       
   842 
       
   843 	if (aka_response.get_is_valid() == false)
       
   844 	{
       
   845 		EAP_TRACE_DEBUG(
       
   846 			m_am_tools, 
       
   847 			TRACE_FLAGS_DEFAULT, 
       
   848 			(EAPL("send_aka_identity_request_message: packet buffer corrupted.\n")));
       
   849 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
   850 	}
       
   851 
       
   852 	aka_response.reset_header(
       
   853 		packet_buffer_free-m_aka_header_offset,
       
   854 		m_use_eap_expanded_type);
       
   855 	aka_response.set_length(
       
   856 		static_cast<u16_t>(packet_buffer_free-m_aka_header_offset),
       
   857 		m_use_eap_expanded_type);
       
   858 	aka_response.set_code(eap_code_request);
       
   859 	aka_response.set_identifier(eap_identifier);
       
   860 	aka_response.set_type(
       
   861 		eap_type_aka,
       
   862 		m_use_eap_expanded_type);
       
   863 	aka_response.set_subtype(aka_subtype_Identity);
       
   864 
       
   865 	update_buffer_indexes(
       
   866 		EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
   867 		m_aka_header_offset+aka_response.get_header_length(),
       
   868 		&packet_buffer_offset,
       
   869 		&packet_buffer_free);
       
   870 
       
   871 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
   872 
       
   873 	EAP_TRACE_DEBUG(
       
   874 		m_am_tools, 
       
   875 		TRACE_FLAGS_DEFAULT, 
       
   876 		(EAPL("eap_type_aka_c::send_aka_identity_request_message(0x%08x).\n"),
       
   877 		 this));
       
   878 
       
   879 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
   880 
       
   881 	u32_t aka_data_free = packet_buffer_free;
       
   882 	u32_t aka_data_offset = 0u;
       
   883 
       
   884 	if (pseudonym_decode_failed == true)
       
   885 	{
       
   886 		aka_payload_AT_type_e next_identity_request = aka_payload_NONE;
       
   887 		eap_type_aka_state_variable_e next_state = eap_type_aka_state_failure;
       
   888 
       
   889 		if (get_identity()->get_is_valid_data() == true)
       
   890 		{
       
   891 			if (get_aka_identity_response_includes_identity() == aka_payload_AT_FULLAUTH_ID_REQ)
       
   892 			{
       
   893 				next_identity_request = aka_payload_AT_FULLAUTH_ID_REQ;
       
   894 				next_state = eap_type_aka_state_waiting_for_aka_identity_response_with_at_full_auth_identity;
       
   895 			}
       
   896 			else if (get_aka_identity_response_includes_identity() == aka_payload_AT_PERMANENT_ID_REQ)
       
   897 			{
       
   898 				next_identity_request = aka_payload_AT_PERMANENT_ID_REQ;
       
   899 				next_state = eap_type_aka_state_waiting_for_aka_identity_response_with_at_permanent_identity;
       
   900 			}
       
   901 			else if (get_aka_identity_response_includes_identity() == aka_payload_AT_ANY_ID_REQ)
       
   902 			{
       
   903 				next_identity_request = aka_payload_AT_ANY_ID_REQ;
       
   904 				next_state = eap_type_aka_state_waiting_for_aka_identity_response_with_at_any_identity;
       
   905 			}
       
   906 			else
       
   907 			{
       
   908 				// We drop this message because no real identity is received from client.
       
   909 				EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_AKA_ERROR, (EAPL("ERROR: send_aka_identity_request_message: no real identity received.\n")));
       
   910 				return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_identity);
       
   911 			}
       
   912 		}
       
   913 		else
       
   914 		{
       
   915 			next_identity_request = aka_payload_AT_ANY_ID_REQ;
       
   916 			next_state = eap_type_aka_state_waiting_for_aka_identity_response_with_at_any_identity;
       
   917 		}
       
   918 
       
   919 		status = add_variable_payload(
       
   920 			&aka_response,
       
   921 			EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
   922 			aka_response.get_header_length(),
       
   923 			&aka_data_offset,
       
   924 			&aka_data_free,
       
   925 			&packet_buffer_free,
       
   926 			&packet_buffer_offset,
       
   927 			0,
       
   928 			next_identity_request);
       
   929 		if (status != eap_status_ok)
       
   930 		{
       
   931 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   932 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   933 		}
       
   934 
       
   935 		set_state(next_state);
       
   936 	}
       
   937 	else
       
   938 	{
       
   939 		set_state(eap_type_aka_state_waiting_for_aka_identity_response);
       
   940 	}
       
   941 
       
   942 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
   943 
       
   944 	aka_response.set_data_length(
       
   945 		aka_data_offset,
       
   946 		m_use_eap_expanded_type);
       
   947 	request_packet.set_data_length(packet_buffer_offset);
       
   948 
       
   949 	EAP_ASSERT_ALWAYS(
       
   950 		m_aka_header_offset+aka_response.get_header_length()+aka_response.get_data_length()
       
   951 		== packet_buffer_offset);
       
   952 
       
   953 	status = checkcode_save_message_server(
       
   954 		aka_response.get_header_buffer(
       
   955 			aka_response.get_header_length()
       
   956 			+aka_response.get_data_length()),
       
   957 		aka_response.get_header_length()
       
   958 		+aka_response.get_data_length());
       
   959 	if (status != eap_status_ok)
       
   960 	{
       
   961 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   962 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   963 	}
       
   964 
       
   965 	EAP_TRACE_DEBUG(
       
   966 		m_am_tools, 
       
   967 		TRACE_FLAGS_DEFAULT, 
       
   968 		(EAPL("eap_type_aka_c::send_aka_identity_request_message()\n")));
       
   969 
       
   970 	status = packet_send(
       
   971 		get_send_network_id(),
       
   972 		&request_packet,
       
   973 		m_aka_header_offset,
       
   974 		aka_response.get_header_length()+aka_response.get_data_length(),
       
   975 		EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH
       
   976 		);
       
   977 
       
   978 	if (status == eap_status_ok)
       
   979 	{
       
   980 	}
       
   981 
       
   982 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
   983 
       
   984 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   985 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   986 }
       
   987 
       
   988 //--------------------------------------------------
       
   989 
       
   990 //
       
   991 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::send_challenge_request_message(
       
   992 	const u8_t eap_identifier)
       
   993 {
       
   994 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   995 
       
   996 	EAP_TRACE_DEBUG(
       
   997 		m_am_tools, 
       
   998 		TRACE_FLAGS_DEFAULT, 
       
   999 		(EAPL("    send: handler 0x%08x, AKA-type %10s, %s, state %2d=%s\n"),
       
  1000 		 this,
       
  1001 		 EAPL("aka_subtype_Challenge"),
       
  1002 		 (get_is_client()) ? EAPL("client") : EAPL("server"),
       
  1003 		 get_state(),
       
  1004 		 get_state_string()
       
  1005 		 ));
       
  1006 
       
  1007 	eap_variable_data_c checkcode_digest(m_am_tools);
       
  1008 
       
  1009 	if (checkcode_digest.get_is_valid() == false)
       
  1010 	{
       
  1011 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1012 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1013 	}
       
  1014 
       
  1015 	eap_status_e status = eap_status_process_general_error;
       
  1016 
       
  1017 	status = checkcode_final(
       
  1018 		&checkcode_digest);
       
  1019 	if (status != eap_status_ok)
       
  1020 	{
       
  1021 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1022 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1023 	}
       
  1024 
       
  1025 
       
  1026 	eap_buf_chain_wr_c aka_initial_reply(
       
  1027 		eap_write_buffer, 
       
  1028 		m_am_tools, 
       
  1029 		EAP_MAX_LOCAL_PACKET_BUFFER_LENGTH);
       
  1030 
       
  1031 	if (aka_initial_reply.get_is_valid() == false)
       
  1032 	{
       
  1033 		EAP_TRACE_DEBUG(
       
  1034 			m_am_tools, 
       
  1035 			TRACE_FLAGS_DEFAULT, 
       
  1036 			(EAPL("packet buffer corrupted.\n")));
       
  1037 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1038 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1039 	}
       
  1040 
       
  1041 	if (m_is_client == true
       
  1042 		&& m_client_responds_retransmitted_packets == true)
       
  1043 	{
       
  1044 		// We do not wan't lower layers do re-transmissions behalf of us.
       
  1045 		// This means AKA does process every re-transmitted EAP-Request.
       
  1046 		aka_initial_reply.set_do_packet_retransmission(false);
       
  1047 	}
       
  1048 
       
  1049 	EAP_ASSERT_ALWAYS(EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH >= (m_aka_header_offset+m_trailer_length));
       
  1050 	u32_t packet_buffer_free = EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH-m_trailer_length;
       
  1051 	u32_t packet_buffer_offset = 0u;
       
  1052 
       
  1053 	if (m_aka_header_offset+m_MTU < packet_buffer_free)
       
  1054 	{
       
  1055 		packet_buffer_free = m_aka_header_offset+m_MTU;
       
  1056 	}
       
  1057 
       
  1058 	aka_header_c aka_response(
       
  1059 		m_am_tools,
       
  1060 		aka_initial_reply.get_data_offset(
       
  1061 			m_aka_header_offset,
       
  1062 			(packet_buffer_free-m_aka_header_offset)),
       
  1063 		(packet_buffer_free-m_aka_header_offset));
       
  1064 
       
  1065 	if (aka_response.get_is_valid() == false)
       
  1066 	{
       
  1067 		EAP_TRACE_DEBUG(
       
  1068 			m_am_tools, 
       
  1069 			TRACE_FLAGS_DEFAULT, 
       
  1070 			(EAPL("packet_send: packet buffer corrupted.\n")));
       
  1071 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1072 	}
       
  1073 
       
  1074 	aka_response.reset_header(
       
  1075 		packet_buffer_free-m_aka_header_offset,
       
  1076 		m_use_eap_expanded_type);
       
  1077 	aka_response.set_length(
       
  1078 		static_cast<u16_t>(packet_buffer_free-m_aka_header_offset),
       
  1079 		m_use_eap_expanded_type);
       
  1080 	aka_response.set_code(eap_code_request);
       
  1081 	aka_response.set_identifier(eap_identifier);
       
  1082 	aka_response.set_type(
       
  1083 		eap_type_aka,
       
  1084 		m_use_eap_expanded_type);
       
  1085 
       
  1086 	aka_response.set_subtype(aka_subtype_Challenge);
       
  1087 
       
  1088 	EAP_TRACE_DEBUG(
       
  1089 		m_am_tools, 
       
  1090 		TRACE_FLAGS_DEFAULT, 
       
  1091 		(EAPL("eap_type_aka_c::send_challenge_request_message(0x%08x).\n"),
       
  1092 		this));
       
  1093 
       
  1094 	update_buffer_indexes(
       
  1095 		EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
  1096 		m_aka_header_offset+aka_response.get_header_length(),
       
  1097 		&packet_buffer_offset,
       
  1098 		&packet_buffer_free);
       
  1099 
       
  1100 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  1101 
       
  1102 	u32_t aka_data_free = packet_buffer_free;
       
  1103 	u32_t aka_data_offset = 0u;
       
  1104 
       
  1105 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  1106 
       
  1107 	if (get_authentication_vector()->get_RAND()->get_is_valid_data() == false)
       
  1108 	{
       
  1109 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1110 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  1111 	}
       
  1112 
       
  1113 	if (get_authentication_vector()->get_AUTN()->get_is_valid_data() == false)
       
  1114 	{
       
  1115 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1116 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  1117 	}
       
  1118 
       
  1119 	if (get_authentication_vector()->get_RES()->get_is_valid_data() == false)
       
  1120 	{
       
  1121 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1122 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  1123 	}
       
  1124 
       
  1125 	if (get_authentication_vector()->get_CK()->get_is_valid_data() == false)
       
  1126 	{
       
  1127 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1128 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  1129 	}
       
  1130 
       
  1131 	if (get_authentication_vector()->get_IK()->get_is_valid_data() == false)
       
  1132 	{
       
  1133 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1134 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  1135 	}
       
  1136 
       
  1137 
       
  1138 
       
  1139 	if (get_identity()->get_is_valid_data() == false)
       
  1140 	{
       
  1141 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1142 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  1143 	}
       
  1144 
       
  1145 	if (get_IMSI()->get_is_valid_data() == false)
       
  1146 	{
       
  1147 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1148 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  1149 	}
       
  1150 
       
  1151 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, (EAPL("RAND"),
       
  1152 		get_authentication_vector()->get_RAND()->get_data(
       
  1153 			get_authentication_vector()->get_RAND()->get_data_length()),
       
  1154 		get_authentication_vector()->get_RAND()->get_data_length()));
       
  1155 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("AUTN"),
       
  1156 		get_authentication_vector()->get_AUTN()->get_data(
       
  1157 			get_authentication_vector()->get_AUTN()->get_data_length()),
       
  1158 		get_authentication_vector()->get_AUTN()->get_data_length()));
       
  1159 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("RES"),
       
  1160 		get_authentication_vector()->get_RES()->get_data(
       
  1161 			get_authentication_vector()->get_RES()->get_data_length()),
       
  1162 		get_authentication_vector()->get_RES()->get_data_length()));
       
  1163 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("CK"),
       
  1164 		get_authentication_vector()->get_CK()->get_data(
       
  1165 			get_authentication_vector()->get_CK()->get_data_length()),
       
  1166 		get_authentication_vector()->get_CK()->get_data_length()));
       
  1167 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("IK"),
       
  1168 		get_authentication_vector()->get_IK()->get_data(
       
  1169 			get_authentication_vector()->get_IK()->get_data_length()),
       
  1170 		get_authentication_vector()->get_IK()->get_data_length()));
       
  1171 
       
  1172 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("identity"),
       
  1173 		get_identity()->get_data(get_identity()->get_data_length()),
       
  1174 		get_identity()->get_data_length()));
       
  1175 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("IMSI"),
       
  1176 		get_IMSI()->get_data(get_IMSI()->get_data_length()),
       
  1177 		get_IMSI()->get_data_length()));
       
  1178 
       
  1179 	eap_variable_data_c XKEY(m_am_tools);
       
  1180 	eap_variable_data_c K_encr(m_am_tools);
       
  1181 	eap_variable_data_c K_aut(m_am_tools);
       
  1182 	eap_variable_data_c master_session_key(m_am_tools);
       
  1183 
       
  1184 	if (XKEY.get_is_valid() == false
       
  1185 		|| K_encr.get_is_valid() == false
       
  1186 		|| K_aut.get_is_valid() == false
       
  1187 		|| master_session_key.get_is_valid() == false)
       
  1188 	{
       
  1189 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1190 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1191 	}
       
  1192 
       
  1193 	status = generate_shared_secred_keys(
       
  1194 		EAP_TYPE_AKA_KEYMAT_SIZE,
       
  1195 		get_authentication_vector()->get_CK(),
       
  1196 		get_authentication_vector()->get_IK(),
       
  1197 		&XKEY,
       
  1198 		&K_encr,
       
  1199 		&K_aut,
       
  1200 		&master_session_key);
       
  1201 	if (status != eap_status_ok)
       
  1202 	{
       
  1203 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1204 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1205 	}
       
  1206 
       
  1207 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  1208 
       
  1209 	m_use_result_indication = m_allow_use_result_indication;
       
  1210 
       
  1211 	if (m_use_result_indication == true)
       
  1212 	{
       
  1213 		// We support use of protected success indications.
       
  1214 		status = add_simple_payload(
       
  1215 			&aka_response,
       
  1216 			EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
  1217 			aka_response.get_header_length(),
       
  1218 			&aka_data_offset,
       
  1219 			&aka_data_free,
       
  1220 			&packet_buffer_free,
       
  1221 			&packet_buffer_offset,
       
  1222 			aka_payload_AT_RESULT_IND);
       
  1223 		if (status != eap_status_ok)
       
  1224 		{
       
  1225 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1226 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1227 		}
       
  1228 	}
       
  1229 
       
  1230 	// -   -   -   -   -   -   -   -   -   -   -   -
       
  1231 
       
  1232 	status = add_variable_payload(
       
  1233 		&aka_response,
       
  1234 		EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
  1235 		aka_response.get_header_length(),
       
  1236 		&aka_data_offset,
       
  1237 		&aka_data_free,
       
  1238 		&packet_buffer_free,
       
  1239 		&packet_buffer_offset,
       
  1240 		&checkcode_digest,
       
  1241 		aka_payload_AT_CHECKCODE);
       
  1242 	if (status != eap_status_ok)
       
  1243 	{
       
  1244 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1245 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1246 	}
       
  1247 
       
  1248 	// -   -   -   -   -   -   -   -   -   -   -   -
       
  1249 
       
  1250 	status = add_variable_payload(
       
  1251 		&aka_response,
       
  1252 		EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
  1253 		aka_response.get_header_length(),
       
  1254 		&aka_data_offset,
       
  1255 		&aka_data_free,
       
  1256 		&packet_buffer_free,
       
  1257 		&packet_buffer_offset,
       
  1258 		get_authentication_vector()->get_RAND(),
       
  1259 		aka_payload_AT_RAND);
       
  1260 	if (status != eap_status_ok)
       
  1261 	{
       
  1262 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1263 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1264 	}
       
  1265 
       
  1266 	status = add_variable_payload(
       
  1267 		&aka_response,
       
  1268 		EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
  1269 		aka_response.get_header_length(),
       
  1270 		&aka_data_offset,
       
  1271 		&aka_data_free,
       
  1272 		&packet_buffer_free,
       
  1273 		&packet_buffer_offset,
       
  1274 		get_authentication_vector()->get_AUTN(),
       
  1275 		aka_payload_AT_AUTN);
       
  1276 	if (status != eap_status_ok)
       
  1277 	{
       
  1278 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1279 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1280 	}
       
  1281 
       
  1282 	// -   -   -   -   -   -   -   -   -   -   -   -
       
  1283 
       
  1284 	u8_t *MAC_data = 0;
       
  1285 	u32_t MAC_data_length = 0u;
       
  1286 	eap_type_aka_MAC_attributes_c MAC_attributes;
       
  1287 
       
  1288 	if (m_use_pseudonym_identity == true
       
  1289 		|| m_use_reauthentication_identity == true)
       
  1290 	{
       
  1291 		u32_t saved_aka_data_offset = aka_data_offset;
       
  1292 		u32_t saved_aka_data_free = aka_data_free;
       
  1293 		u32_t saved_packet_buffer_offset = packet_buffer_offset;
       
  1294 		u32_t saved_packet_buffer_free = packet_buffer_free;
       
  1295 
       
  1296 		crypto_aes_c aes(m_am_tools);
       
  1297 
       
  1298 		if (aes.get_is_valid() == false)
       
  1299 		{
       
  1300 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1301 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1302 		}
       
  1303 
       
  1304 		status = m_am_type_aka->generate_encryption_IV(
       
  1305 			get_IV()->get_payload_buffer(),
       
  1306 			aes.get_block_size());
       
  1307 		if (status != eap_status_ok)
       
  1308 		{
       
  1309 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1310 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1311 		}
       
  1312 
       
  1313 
       
  1314 		status = add_variable_payload(
       
  1315 			&aka_response,
       
  1316 			EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
  1317 			aka_response.get_header_length(),
       
  1318 			&aka_data_offset,
       
  1319 			&aka_data_free,
       
  1320 			&packet_buffer_free,
       
  1321 			&packet_buffer_offset,
       
  1322 			get_IV()->get_payload_buffer(),
       
  1323 			aka_payload_AT_IV);
       
  1324 		if (status != eap_status_ok)
       
  1325 		{
       
  1326 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1327 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1328 		}
       
  1329 
       
  1330 
       
  1331 		// Encrypted data.
       
  1332 		{
       
  1333 			aka_payload_AT_header_c gp_encrypted_data(
       
  1334 				m_am_tools,
       
  1335 				aka_response.get_data_offset(
       
  1336 					aka_data_offset, 
       
  1337 					aka_data_free),
       
  1338 				aka_data_free);
       
  1339 			if (gp_encrypted_data.get_is_valid() == false)
       
  1340 			{
       
  1341 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1342 				return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1343 			}
       
  1344 
       
  1345 			// Initialize the length of encrypted data to maximum length.
       
  1346 			// Later this will be set to correct length.
       
  1347 			gp_encrypted_data.reset_header(aka_payload_AT_header_c::get_max_payload_data_length());
       
  1348 			gp_encrypted_data.set_current_payload(aka_payload_AT_ENCR_DATA);
       
  1349 
       
  1350 			update_payload_indexes(
       
  1351 				EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
  1352 				aka_response.get_header_length(),
       
  1353 				gp_encrypted_data.get_header_length(),
       
  1354 				&aka_data_offset,
       
  1355 				&aka_data_free,
       
  1356 				&packet_buffer_offset,
       
  1357 				&packet_buffer_free);
       
  1358 
       
  1359 			u32_t encrypted_data_offset_begin = packet_buffer_offset;
       
  1360 
       
  1361 			// -   -   -   -   -   -   -   -   -   -   -   -
       
  1362 
       
  1363 			if (m_use_pseudonym_identity == true)
       
  1364 			{
       
  1365 				status = m_am_type_aka->generate_pseudonym_id(
       
  1366 					get_send_network_id(),
       
  1367 					get_IMSI(),
       
  1368 					get_pseudonym(),
       
  1369 					EAP_TYPE_AKA_MAX_NAI_LENGTH);
       
  1370 				if (status == eap_status_ok)
       
  1371 				{
       
  1372 					status = add_pseudonym_or_imsi_payload(
       
  1373 						&aka_response,
       
  1374 						EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
  1375 						aka_response.get_header_length(),
       
  1376 						&aka_data_offset,
       
  1377 						&aka_data_free,
       
  1378 						&packet_buffer_free,
       
  1379 						&packet_buffer_offset,
       
  1380 						get_pseudonym(),
       
  1381 						aka_payload_AT_NEXT_PSEUDONYM);
       
  1382 					if (status != eap_status_ok)
       
  1383 					{
       
  1384 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1385 						return EAP_STATUS_RETURN(m_am_tools, status);
       
  1386 					}
       
  1387 				}
       
  1388 			}
       
  1389 
       
  1390 			// -   -   -   -   -   -   -   -   -   -   -   -
       
  1391 
       
  1392 			if (m_use_reauthentication_identity == true)
       
  1393 			{
       
  1394 				status = m_am_type_aka->generate_reauthentication_id(
       
  1395 					get_send_network_id(),
       
  1396 					get_IMSI(),
       
  1397 					get_reauthentication_identity(),
       
  1398 					EAP_TYPE_AKA_MAX_NAI_LENGTH);
       
  1399 				if (status == eap_status_ok)
       
  1400 				{
       
  1401 					status = add_pseudonym_or_imsi_payload(
       
  1402 						&aka_response,
       
  1403 						EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
  1404 						aka_response.get_header_length(),
       
  1405 						&aka_data_offset,
       
  1406 						&aka_data_free,
       
  1407 						&packet_buffer_free,
       
  1408 						&packet_buffer_offset,
       
  1409 						get_reauthentication_identity(),
       
  1410 						aka_payload_AT_NEXT_REAUTH_ID);
       
  1411 					if (status != eap_status_ok)
       
  1412 					{
       
  1413 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1414 						return EAP_STATUS_RETURN(m_am_tools, status);
       
  1415 					}
       
  1416 				}
       
  1417 			}
       
  1418 
       
  1419 			// -   -   -   -   -   -   -   -   -   -   -   -
       
  1420 
       
  1421 			u32_t plain_text_length = packet_buffer_offset - encrypted_data_offset_begin;
       
  1422 
       
  1423 			if (plain_text_length > 0ul)
       
  1424 			{
       
  1425 				status = add_padding_payload(
       
  1426 					&aka_response,
       
  1427 					EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
  1428 					aka_response.get_header_length(),
       
  1429 					&aka_data_offset,
       
  1430 					&aka_data_free,
       
  1431 					&packet_buffer_free,
       
  1432 					&packet_buffer_offset,
       
  1433 					plain_text_length // Length of the plain text.
       
  1434 					);
       
  1435 				if (status != eap_status_ok)
       
  1436 				{
       
  1437 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1438 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1439 				}
       
  1440 
       
  1441 				// Re calculate after adding the padding.
       
  1442 				plain_text_length = packet_buffer_offset - encrypted_data_offset_begin;
       
  1443 
       
  1444 				gp_encrypted_data.set_data_length(
       
  1445 					static_cast<u16_t>(plain_text_length));
       
  1446 
       
  1447 				// -   -   -   -   -   -   -   -   -   -   -   -
       
  1448 
       
  1449 				status = encrypt_DATA_payload(
       
  1450 					gp_encrypted_data.get_data(gp_encrypted_data.get_data_length()),
       
  1451 					gp_encrypted_data.get_data_length(),
       
  1452 					get_IV()->get_payload_buffer(),
       
  1453 					&K_encr);
       
  1454 				if (status != eap_status_ok)
       
  1455 				{
       
  1456 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1457 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1458 				}
       
  1459 
       
  1460 				EAP_AKA_TRACE_PAYLOAD("Payload added", &gp_encrypted_data);
       
  1461 			}
       
  1462 			else
       
  1463 			{
       
  1464 				// No encrypted data, remove AT_ENCR_DATA header.
       
  1465 				aka_data_offset = saved_aka_data_offset;
       
  1466 				aka_data_free = saved_aka_data_free;
       
  1467 				packet_buffer_offset = saved_packet_buffer_offset;
       
  1468 				packet_buffer_free = saved_packet_buffer_free;
       
  1469 			}
       
  1470 		}
       
  1471 	}
       
  1472 
       
  1473 	// -   -   -   -   -   -   -   -   -   -   -   -
       
  1474 
       
  1475 	status = add_mac_payload(
       
  1476 		&aka_response,
       
  1477 		EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
  1478 		aka_response.get_header_length(),
       
  1479 		&aka_data_offset,
       
  1480 		&aka_data_free,
       
  1481 		&packet_buffer_free,
       
  1482 		&packet_buffer_offset,
       
  1483 		&MAC_data,
       
  1484 		&MAC_data_length);
       
  1485 	if (status != eap_status_ok)
       
  1486 	{
       
  1487 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1488 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1489 	}
       
  1490 
       
  1491 	// -   -   -   -   -   -   -   -   -   -   -   -
       
  1492 
       
  1493 	aka_response.set_data_length(
       
  1494 		aka_data_offset,
       
  1495 		m_use_eap_expanded_type);
       
  1496 	aka_initial_reply.set_data_length(packet_buffer_offset);
       
  1497 
       
  1498 	EAP_ASSERT_ALWAYS(
       
  1499 		m_aka_header_offset+aka_response.get_header_length()+aka_response.get_data_length()
       
  1500 		== packet_buffer_offset);
       
  1501 
       
  1502 	// -   -   -   -   -   -   -   -   -   -   -   -
       
  1503 
       
  1504 	MAC_attributes.init(
       
  1505 		MAC_data,
       
  1506 		MAC_data_length,
       
  1507 		aka_response.get_header_buffer(aka_response.get_length()),
       
  1508 		aka_response.get_length());
       
  1509 
       
  1510 	status = create_message_authentication_code(
       
  1511 		&MAC_attributes,
       
  1512 		aka_response.get_subtype(),
       
  1513 		aka_response.get_code(),
       
  1514 		&K_aut);
       
  1515 	if (status != eap_status_ok)
       
  1516 	{
       
  1517 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1518 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1519 	}
       
  1520 
       
  1521 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  1522 
       
  1523 	aka_response.set_data_length(
       
  1524 		aka_data_offset,
       
  1525 		m_use_eap_expanded_type);
       
  1526 	aka_initial_reply.set_data_length(packet_buffer_offset);
       
  1527 
       
  1528 	EAP_ASSERT_ALWAYS(
       
  1529 		m_aka_header_offset+aka_response.get_header_length()+aka_response.get_data_length()
       
  1530 		== packet_buffer_offset);
       
  1531 
       
  1532 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  1533 
       
  1534 	status = packet_send(
       
  1535 		get_send_network_id(),
       
  1536 		&aka_initial_reply,
       
  1537 		m_aka_header_offset,
       
  1538 		aka_response.get_header_length()+aka_response.get_data_length(),
       
  1539 		EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH
       
  1540 		);
       
  1541 
       
  1542 	if (status == eap_status_ok)
       
  1543 	{
       
  1544 		// Store keys.
       
  1545 		status = get_XKEY()->set_copy_of_buffer(&XKEY);
       
  1546 		if (status != eap_status_ok)
       
  1547 		{
       
  1548 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1549 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1550 		}
       
  1551 		status = get_K_encr()->set_copy_of_buffer(&K_encr);
       
  1552 		if (status != eap_status_ok)
       
  1553 		{
       
  1554 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1555 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1556 		}
       
  1557 		status = get_K_aut()->set_copy_of_buffer(&K_aut);
       
  1558 		if (status != eap_status_ok)
       
  1559 		{
       
  1560 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1561 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1562 		}
       
  1563 		status = get_master_session_key()->set_copy_of_buffer(&master_session_key);
       
  1564 		if (status != eap_status_ok)
       
  1565 		{
       
  1566 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1567 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1568 		}
       
  1569 	}
       
  1570 
       
  1571 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  1572 
       
  1573 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1574 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1575 }
       
  1576 
       
  1577 //--------------------------------------------------
       
  1578 
       
  1579 //
       
  1580 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::send_aka_notification_request(
       
  1581 	const eap_aka_notification_codes_e notification_code,
       
  1582 	const bool add_at_counter_attribute)
       
  1583 {
       
  1584 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1585 
       
  1586 	EAP_TRACE_DEBUG(
       
  1587 		m_am_tools, 
       
  1588 		TRACE_FLAGS_DEFAULT, 
       
  1589 		(EAPL("send: handler 0x%08x, AKA-type %10s, %s, state %2d=%s, notification_code = %d\n"),
       
  1590 		 this,
       
  1591 		 EAPL("send_aka_notification_request"),
       
  1592 		 (get_is_client()) ? EAPL("client") : EAPL("server"),
       
  1593 		 get_state(),
       
  1594 		 get_state_string(),
       
  1595 		 notification_code
       
  1596 		 ));
       
  1597 
       
  1598 	eap_buf_chain_wr_c eap_notification_packet(
       
  1599 		eap_write_buffer, 
       
  1600 		m_am_tools, 
       
  1601 		EAP_MAX_LOCAL_PACKET_BUFFER_LENGTH);
       
  1602 
       
  1603 	if (eap_notification_packet.get_is_valid() == false)
       
  1604 	{
       
  1605 		EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("packet buffer corrupted.\n")));
       
  1606 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1607 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1608 	}
       
  1609 
       
  1610 	if (m_is_client == true
       
  1611 		&& m_client_responds_retransmitted_packets == true)
       
  1612 	{
       
  1613 		// We do not wan't lower layers do re-transmissions behalf of us.
       
  1614 		// This means AKA does process every re-transmitted EAP-Request.
       
  1615 		eap_notification_packet.set_do_packet_retransmission(false);
       
  1616 	}
       
  1617 
       
  1618 	EAP_ASSERT_ALWAYS(EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH >= (m_aka_header_offset+m_trailer_length));
       
  1619 	u32_t packet_buffer_free = EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH-m_trailer_length;
       
  1620 	u32_t packet_buffer_offset = 0u;
       
  1621 
       
  1622 	if (m_aka_header_offset+m_MTU < packet_buffer_free)
       
  1623 	{
       
  1624 		packet_buffer_free = m_aka_header_offset+m_MTU;
       
  1625 	}
       
  1626 
       
  1627 	aka_header_c aka_response(
       
  1628 		m_am_tools,
       
  1629 		eap_notification_packet.get_data_offset(
       
  1630 			m_aka_header_offset,
       
  1631 			(packet_buffer_free-m_aka_header_offset)),
       
  1632 		(packet_buffer_free-m_aka_header_offset));
       
  1633 
       
  1634 	if (aka_response.get_is_valid() == false)
       
  1635 	{
       
  1636 		EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("packet_send: packet buffer corrupted.\n")));
       
  1637 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1638 	}
       
  1639 
       
  1640 	set_last_eap_identifier(static_cast<u8_t>(get_last_eap_identifier()+1u));
       
  1641 
       
  1642 	aka_response.reset_header(
       
  1643 		static_cast<u16_t>(packet_buffer_free-m_aka_header_offset),
       
  1644 		m_use_eap_expanded_type);
       
  1645 	aka_response.set_length(
       
  1646 		static_cast<u16_t>(packet_buffer_free-m_aka_header_offset),
       
  1647 		m_use_eap_expanded_type);
       
  1648 	aka_response.set_code(eap_code_request);
       
  1649 	aka_response.set_identifier(get_last_eap_identifier());
       
  1650 	aka_response.set_type(
       
  1651 		eap_type_aka,
       
  1652 		m_use_eap_expanded_type);
       
  1653 	aka_response.set_subtype(aka_subtype_Notification);
       
  1654 
       
  1655 
       
  1656 	update_buffer_indexes(
       
  1657 		EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
  1658 		m_aka_header_offset+aka_response.get_header_length(),
       
  1659 		&packet_buffer_offset,
       
  1660 		&packet_buffer_free);
       
  1661 
       
  1662 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  1663 
       
  1664 	u32_t aka_data_free = packet_buffer_free;
       
  1665 	u32_t aka_data_offset = 0u;
       
  1666 
       
  1667 	eap_status_e status = add_notification_payload(
       
  1668 		&aka_response,
       
  1669 		EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
  1670 		aka_response.get_header_length(),
       
  1671 		&aka_data_offset,
       
  1672 		&aka_data_free,
       
  1673 		&packet_buffer_free,
       
  1674 		&packet_buffer_offset,
       
  1675 		notification_code);
       
  1676 	if (status != eap_status_ok)
       
  1677 	{
       
  1678 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1679 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1680 	}
       
  1681 
       
  1682 
       
  1683 	eap_variable_data_c * K_aut = 0;
       
  1684 
       
  1685 	eap_variable_data_c orig_K_aut(m_am_tools);
       
  1686 
       
  1687 	if (orig_K_aut.get_is_valid() == false)
       
  1688 	{
       
  1689 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1690 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1691 	}
       
  1692 
       
  1693 	if (get_aka_notification_code_P_bit(notification_code) == false)
       
  1694 	{
       
  1695 		u8_t *MAC_data = 0;
       
  1696 		u32_t MAC_data_length = 0u;
       
  1697 		eap_type_aka_MAC_attributes_c MAC_attributes;
       
  1698 
       
  1699 		if (add_at_counter_attribute == true)
       
  1700 		{
       
  1701 			// If EAP-Request/AKA/Notification is used on fast a re-authentication
       
  1702 			// exchange, and if the P bit in AT_NOTIFICATION is set to zero, then
       
  1703 			// AT_COUNTER is used for replay protection. In this case, the
       
  1704 			// AT_ENCR_DATA and AT_IV attributes MUST be included, and the
       
  1705 			// encapsulated plaintext attributes MUST include the AT_COUNTER
       
  1706 			// attribute. The counter value included in AT_COUNTER MUST be the same
       
  1707 			// as in the EAP-Request/AKA/Re-authentication packet on the same fast
       
  1708 			// re-authentication exchange.
       
  1709 
       
  1710 			// - - - - - - - - - - - - - - - - - - - - - - - -
       
  1711 
       
  1712 			eap_variable_data_c orig_XKEY(m_am_tools);
       
  1713 			eap_variable_data_c orig_K_encr(m_am_tools);
       
  1714 
       
  1715 			if (orig_XKEY.get_is_valid() == false
       
  1716 				|| orig_K_encr.get_is_valid() == false)
       
  1717 			{
       
  1718 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1719 				return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1720 			}
       
  1721 
       
  1722 			u32_t reauth_counter = 0u;
       
  1723 
       
  1724 			// In order to use re-authentication, the client and the server need to
       
  1725 			// store the following values: original XKEY, K_aut, K_encr, latest
       
  1726 			// counter value and the next re-authentication identity.
       
  1727 			status = m_am_type_aka->query_reauth_parameters(
       
  1728 				&orig_XKEY,
       
  1729 				&orig_K_aut,
       
  1730 				&orig_K_encr,
       
  1731 				&reauth_counter);
       
  1732 			if (status != eap_status_ok)
       
  1733 			{
       
  1734 				restore_saved_previous_state();
       
  1735 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1736 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1737 			}
       
  1738 
       
  1739 			K_aut = &orig_K_aut;
       
  1740 
       
  1741 			// -   -   -   -   -   -   -   -   -   -   -   -
       
  1742 
       
  1743 			crypto_aes_c aes(m_am_tools);
       
  1744 
       
  1745 			if (aes.get_is_valid() == false)
       
  1746 			{
       
  1747 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1748 				return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1749 			}
       
  1750 
       
  1751 			status = m_am_type_aka->generate_encryption_IV(
       
  1752 				get_IV()->get_payload_buffer(),
       
  1753 				aes.get_block_size());
       
  1754 			if (status != eap_status_ok)
       
  1755 			{
       
  1756 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1757 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1758 			}
       
  1759 
       
  1760 
       
  1761 			status = add_variable_payload(
       
  1762 				&aka_response,
       
  1763 				EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
  1764 				aka_response.get_header_length(),
       
  1765 				&aka_data_offset,
       
  1766 				&aka_data_free,
       
  1767 				&packet_buffer_free,
       
  1768 				&packet_buffer_offset,
       
  1769 				get_IV()->get_payload_buffer(),
       
  1770 				aka_payload_AT_IV);
       
  1771 			if (status != eap_status_ok)
       
  1772 			{
       
  1773 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1774 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1775 			}
       
  1776 
       
  1777 
       
  1778 			// Encrypted data.
       
  1779 			{
       
  1780 				aka_payload_AT_header_c gp_encrypted_data(
       
  1781 					m_am_tools,
       
  1782 					aka_response.get_data_offset(
       
  1783 						aka_data_offset, 
       
  1784 						aka_data_free),
       
  1785 					aka_data_free);
       
  1786 				if (aka_response.get_is_valid() == false)
       
  1787 				{
       
  1788 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1789 					return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1790 				}
       
  1791 
       
  1792 				// Initialize the length of encrypted data to maximum length.
       
  1793 				// Later this will be set to correct length.
       
  1794 				gp_encrypted_data.reset_header(aka_payload_AT_header_c::get_max_payload_data_length());
       
  1795 				gp_encrypted_data.set_current_payload(aka_payload_AT_ENCR_DATA);
       
  1796 
       
  1797 				update_payload_indexes(
       
  1798 					EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
  1799 					aka_response.get_header_length(),
       
  1800 					gp_encrypted_data.get_header_length(),
       
  1801 					&aka_data_offset,
       
  1802 					&aka_data_free,
       
  1803 					&packet_buffer_offset,
       
  1804 					&packet_buffer_free);
       
  1805 
       
  1806 				u32_t encrypted_data_offset_begin = packet_buffer_offset;
       
  1807 
       
  1808 				// -   -   -   -   -   -   -   -   -   -   -   -
       
  1809 
       
  1810 				status = add_counter_payload(
       
  1811 					&aka_response,
       
  1812 					EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
  1813 					aka_response.get_header_length(),
       
  1814 					&aka_data_offset,
       
  1815 					&aka_data_free,
       
  1816 					&packet_buffer_free,
       
  1817 					&packet_buffer_offset,
       
  1818 					static_cast<u16_t>(reauth_counter));
       
  1819 				if (status != eap_status_ok)
       
  1820 				{
       
  1821 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1822 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1823 				}
       
  1824 
       
  1825 				// -   -   -   -   -   -   -   -   -   -   -   -
       
  1826 
       
  1827 				status = add_padding_payload(
       
  1828 					&aka_response,
       
  1829 					EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
  1830 					aka_response.get_header_length(),
       
  1831 					&aka_data_offset,
       
  1832 					&aka_data_free,
       
  1833 					&packet_buffer_free,
       
  1834 					&packet_buffer_offset,
       
  1835 					(packet_buffer_offset - encrypted_data_offset_begin) // Length of the plain text.
       
  1836 					);
       
  1837 				if (status != eap_status_ok)
       
  1838 				{
       
  1839 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1840 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1841 				}
       
  1842 
       
  1843 				gp_encrypted_data.set_data_length(
       
  1844 					static_cast<u16_t>(packet_buffer_offset - encrypted_data_offset_begin));
       
  1845 
       
  1846 				// -   -   -   -   -   -   -   -   -   -   -   -
       
  1847 
       
  1848 				status = encrypt_DATA_payload(
       
  1849 					gp_encrypted_data.get_data(gp_encrypted_data.get_data_length()),
       
  1850 					gp_encrypted_data.get_data_length(),
       
  1851 					get_IV()->get_payload_buffer(),
       
  1852 					&orig_K_encr);
       
  1853 				if (status != eap_status_ok)
       
  1854 				{
       
  1855 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1856 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1857 				}
       
  1858 
       
  1859 				EAP_AKA_TRACE_PAYLOAD("Payload added", &gp_encrypted_data);
       
  1860 			}
       
  1861 
       
  1862 		}
       
  1863 		else
       
  1864 		{
       
  1865 			K_aut = get_K_aut();
       
  1866 		} // if (add_counter_payload == true)
       
  1867 
       
  1868 		// -   -   -   -   -   -   -   -   -   -   -   -
       
  1869 
       
  1870 		// Add AT_MAC attribute.
       
  1871 		status = add_mac_payload(
       
  1872 			&aka_response,
       
  1873 			EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH,
       
  1874 			aka_response.get_header_length(),
       
  1875 			&aka_data_offset,
       
  1876 			&aka_data_free,
       
  1877 			&packet_buffer_free,
       
  1878 			&packet_buffer_offset,
       
  1879 			&MAC_data,
       
  1880 			&MAC_data_length);
       
  1881 		if (status != eap_status_ok)
       
  1882 		{
       
  1883 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1884 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1885 		}
       
  1886 
       
  1887 		// -   -   -   -   -   -   -   -   -   -   -   -
       
  1888 
       
  1889 		aka_response.set_data_length(
       
  1890 			aka_data_offset,
       
  1891 			m_use_eap_expanded_type);
       
  1892 		eap_notification_packet.set_data_length(packet_buffer_offset);
       
  1893 
       
  1894 		EAP_ASSERT_ALWAYS(
       
  1895 			m_aka_header_offset+aka_response.get_header_length()+aka_response.get_data_length()
       
  1896 			== packet_buffer_offset);
       
  1897 
       
  1898 		// -   -   -   -   -   -   -   -   -   -   -   -
       
  1899 
       
  1900 		MAC_attributes.init(
       
  1901 			MAC_data,
       
  1902 			MAC_data_length,
       
  1903 			aka_response.get_header_buffer(aka_response.get_length()),
       
  1904 			aka_response.get_length());
       
  1905 
       
  1906 		status = create_message_authentication_code(
       
  1907 			&MAC_attributes,
       
  1908 			aka_response.get_subtype(),
       
  1909 			aka_response.get_code(),
       
  1910 			K_aut);
       
  1911 		if (status != eap_status_ok)
       
  1912 		{
       
  1913 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1914 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1915 		}
       
  1916 
       
  1917 	}
       
  1918 	else
       
  1919 	{
       
  1920 		aka_response.set_data_length(
       
  1921 			aka_data_offset,
       
  1922 			m_use_eap_expanded_type);
       
  1923 		eap_notification_packet.set_data_length(packet_buffer_offset);
       
  1924 
       
  1925 		EAP_ASSERT_ALWAYS(
       
  1926 			m_aka_header_offset+aka_response.get_header_length()+aka_response.get_data_length()
       
  1927 			== packet_buffer_offset);
       
  1928 	}
       
  1929 
       
  1930 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  1931 
       
  1932 	eap_notification_packet.set_data_length(packet_buffer_offset);
       
  1933 
       
  1934 	EAP_TRACE_DATA_DEBUG(
       
  1935 		m_am_tools,
       
  1936 		TRACE_FLAGS_DEFAULT,
       
  1937 		(EAPL("send_aka_notification_request: aka_subtype_Notification packet"),
       
  1938 		aka_response.get_header_buffer(aka_response.get_length()),
       
  1939 		aka_response.get_length()));
       
  1940 
       
  1941 	status = packet_send(
       
  1942 		get_send_network_id(),
       
  1943 		&eap_notification_packet,
       
  1944 		m_aka_header_offset,
       
  1945 		aka_response.get_length(),
       
  1946 		EAP_TYPE_AKA_LOCAL_PACKET_BUFFER_LENGTH
       
  1947 		);
       
  1948 
       
  1949 	if (status == eap_status_ok)
       
  1950 	{
       
  1951 	}
       
  1952 
       
  1953 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  1954 
       
  1955 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1956 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1957 }
       
  1958 
       
  1959 
       
  1960 //--------------------------------------------------
       
  1961 
       
  1962 //
       
  1963 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::query_AKA_authentication_vector(
       
  1964 	const u8_t next_eap_identifier,
       
  1965 	eap_type_aka_identity_type * const identity_type)
       
  1966 {
       
  1967 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1968 
       
  1969 	eap_type_aka_authentication_vector_c authentication_vector(m_am_tools);
       
  1970 
       
  1971 	set_state(eap_type_aka_state_pending_authentication_vector_query);
       
  1972 
       
  1973 	eap_status_e status = m_am_type_aka->query_AKA_authentication_vector(
       
  1974 		get_identity(), // This is username part from payload AT_IDENTITY.
       
  1975 		next_eap_identifier,
       
  1976 		get_IMSI(), // This is the real IMSI. If this is uninitialized get_identity() must be initialized, imsi will be initialized after this call is complete.
       
  1977 		&authentication_vector,
       
  1978 		identity_type);
       
  1979 
       
  1980 	if (status == eap_status_pending_request)
       
  1981 	{
       
  1982 		// This is pending query, that will be completed by complete_AKA_authentication_vector_query() call.
       
  1983 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1984 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1985 	}
       
  1986 	else if (status == eap_status_completed_request)
       
  1987 	{
       
  1988 		// This query was already completed by complete_AKA_authentication_vector_query() call.
       
  1989 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1990 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1991 	}
       
  1992 	else if (status != eap_status_ok)
       
  1993 	{
       
  1994 		// Some error occurred.
       
  1995 		restore_saved_previous_state();
       
  1996 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1997 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1998 	}
       
  1999 
       
  2000 	set_authentication_vector(authentication_vector.copy());
       
  2001 	if (get_authentication_vector() == 0
       
  2002 		|| get_authentication_vector()->get_is_valid() == false)
       
  2003 	{
       
  2004 		restore_saved_previous_state();
       
  2005 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2006 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2007 	}
       
  2008 
       
  2009 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2010 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2011 }
       
  2012 
       
  2013 //--------------------------------------------------
       
  2014 
       
  2015 //
       
  2016 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::complete_AKA_authentication_vector_query(
       
  2017 	eap_type_aka_authentication_vector_c * const authentication_vector,
       
  2018 	const eap_variable_data_c * const IMSI,
       
  2019 	const eap_aka_authentication_vector_status_e authentication_vector_status,
       
  2020 	const eap_type_aka_identity_type identity_type,
       
  2021 	const eap_status_e completion_status,
       
  2022 	const u8_t next_eap_identifier)
       
  2023 {
       
  2024 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2025 
       
  2026 	EAP_TRACE_DEBUG(
       
  2027 		m_am_tools, 
       
  2028 		TRACE_FLAGS_DEFAULT, 
       
  2029 		(EAPL("eap_type_aka_c::complete_AKA_authentication_vector_query(): ")
       
  2030 		 EAPL("EAP-identity is %d=%s, identity payload was %d=%s, state %d=%s.\n"),
       
  2031 		 identity_type,
       
  2032 		 get_identity_string(identity_type),
       
  2033 		 get_aka_identity_response_includes_identity(),
       
  2034 		 aka_payload_AT_header_c::get_payload_AT_string(get_aka_identity_response_includes_identity()),
       
  2035 		 get_state(),
       
  2036 		 get_state_string()));
       
  2037 
       
  2038 	if (completion_status != eap_status_ok
       
  2039 		|| authentication_vector == 0)
       
  2040 	{
       
  2041 		set_state(eap_type_aka_state_failure);
       
  2042 
       
  2043 		// The eap_status_process_general_error error value is more important
       
  2044 		// than return value of set_session_timeout().
       
  2045 		(void) get_type_partner()->set_session_timeout(0ul);
       
  2046 
       
  2047 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2048 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  2049 	}
       
  2050 
       
  2051 
       
  2052 	if (get_state() != eap_type_aka_state_pending_authentication_vector_query)
       
  2053 	{
       
  2054 		// Authentication is terminated or state is wrong. Cannot continue.
       
  2055 		set_state(eap_type_aka_state_failure);
       
  2056 
       
  2057 		// The eap_status_handler_does_not_exists_error error value is more important
       
  2058 		// than return value of set_session_timeout().
       
  2059 		(void) get_type_partner()->set_session_timeout(0ul);
       
  2060 
       
  2061 		return EAP_STATUS_RETURN(m_am_tools, eap_status_handler_does_not_exists_error);
       
  2062 	}
       
  2063 
       
  2064 	eap_status_e status = eap_status_process_general_error;
       
  2065 
       
  2066 	if (m_identity_type != AKA_IDENTITY_TYPE_RE_AUTH_ID)
       
  2067 	{
       
  2068 		set_identity_type(identity_type);
       
  2069 	}
       
  2070 
       
  2071 	if (m_identity_type == AKA_IDENTITY_TYPE_IMSI_ID
       
  2072 		&& IMSI->get_is_valid_data() == true)
       
  2073 	{
       
  2074 		status = m_IMSI.set_copy_of_buffer(IMSI);
       
  2075 		if (status != eap_status_ok)
       
  2076 		{
       
  2077 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2078 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2079 		}
       
  2080 	}
       
  2081 
       
  2082 	if (authentication_vector_status == eap_aka_authentication_vector_status_ok)
       
  2083 	{
       
  2084 		// First check the identity type is correct.
       
  2085 		if ((m_identity_type == AKA_IDENTITY_TYPE_IMSI_ID
       
  2086 				&& (get_aka_identity_response_includes_identity() == aka_payload_AT_PERMANENT_ID_REQ
       
  2087 					|| get_aka_identity_response_includes_identity() == aka_payload_AT_FULLAUTH_ID_REQ
       
  2088 					|| get_aka_identity_response_includes_identity() == aka_payload_AT_ANY_ID_REQ))
       
  2089 			|| (m_identity_type == AKA_IDENTITY_TYPE_PSEUDONYM_ID
       
  2090 				&& (get_aka_identity_response_includes_identity() == aka_payload_AT_FULLAUTH_ID_REQ
       
  2091 					|| get_aka_identity_response_includes_identity() == aka_payload_AT_ANY_ID_REQ))
       
  2092 			|| (m_identity_type == AKA_IDENTITY_TYPE_RE_AUTH_ID
       
  2093 				&& get_aka_identity_response_includes_identity() == aka_payload_AT_ANY_ID_REQ)
       
  2094 			|| get_aka_identity_response_includes_identity() == aka_payload_NONE)
       
  2095 		{
       
  2096 			// OK, correct identity received.
       
  2097 			EAP_TRACE_DEBUG(
       
  2098 				m_am_tools, 
       
  2099 				TRACE_FLAGS_DEFAULT, 
       
  2100 				(EAPL("eap_type_aka_c::complete_AKA_authentication_vector_query(): OK\n")));
       
  2101 		}
       
  2102 		else
       
  2103 		{
       
  2104 			EAP_TRACE_DEBUG(
       
  2105 				m_am_tools, 
       
  2106 				TRACE_FLAGS_AKA_ERROR, 
       
  2107 				(EAPL("ERROR: eap_type_aka_c::complete_AKA_authentication_vector_query(): ")
       
  2108 				 EAPL("EAP-identity is wrong, state %d=%s.\n"),
       
  2109 				 get_state(), get_state_string()));
       
  2110 
       
  2111 			if (get_aka_identity_response_includes_identity() == aka_payload_AT_PERMANENT_ID_REQ)
       
  2112 			{
       
  2113 				EAP_TRACE_DEBUG(
       
  2114 					m_am_tools, 
       
  2115 					TRACE_FLAGS_AKA_ERROR, 
       
  2116 					(EAPL("ERROR: eap_type_aka_c::complete_AKA_authentication_vector_query(): ")
       
  2117 					 EAPL("permanent identity was required, %d=%s was get.\n"),
       
  2118 					 m_identity_type,
       
  2119 					 get_identity_string(m_identity_type)));
       
  2120 			}
       
  2121 			else if (get_aka_identity_response_includes_identity() == aka_payload_AT_FULLAUTH_ID_REQ)
       
  2122 			{
       
  2123 				EAP_TRACE_DEBUG(
       
  2124 					m_am_tools, 
       
  2125 					TRACE_FLAGS_AKA_ERROR, 
       
  2126 					(EAPL("ERROR: eap_type_aka_c::complete_AKA_authentication_vector_query(): ")
       
  2127 					 EAPL("full authentication identity was required, %d=%s was get.\n"),
       
  2128 					 m_identity_type,
       
  2129 					 get_identity_string(m_identity_type)));
       
  2130 			}
       
  2131 			else if (get_aka_identity_response_includes_identity() == aka_payload_AT_ANY_ID_REQ)
       
  2132 			{
       
  2133 				EAP_TRACE_DEBUG(
       
  2134 					m_am_tools, 
       
  2135 					TRACE_FLAGS_AKA_ERROR, 
       
  2136 					(EAPL("ERROR: eap_type_aka_c::complete_AKA_authentication_vector_query(): ")
       
  2137 					 EAPL("any identity was required, %d=%s was get.\n"),
       
  2138 					 m_identity_type,
       
  2139 					 get_identity_string(m_identity_type)));
       
  2140 			}
       
  2141 			else
       
  2142 			{
       
  2143 				EAP_TRACE_DEBUG(
       
  2144 					m_am_tools, 
       
  2145 					TRACE_FLAGS_AKA_ERROR, 
       
  2146 					(EAPL("ERROR: eap_type_aka_c::complete_AKA_authentication_vector_query(): ")
       
  2147 					 EAPL("no special identity was required, %d=%s was get.\n"),
       
  2148 					 m_identity_type,
       
  2149 					 get_identity_string(m_identity_type)));
       
  2150 			}
       
  2151 			
       
  2152 			EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR, wrong identity"),
       
  2153 				get_NAI()->get_data(get_NAI()->get_data_length()),
       
  2154 				get_NAI()->get_data_length()));
       
  2155 
       
  2156 			restore_saved_previous_state();
       
  2157 
       
  2158 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2159 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_identity);
       
  2160 		}
       
  2161 
       
  2162 		if (get_IMSI()->get_is_valid_data() == false
       
  2163 			&& IMSI != get_IMSI())
       
  2164 		{
       
  2165 			// We must copy queried IMSI.
       
  2166 			status = get_IMSI()->set_copy_of_buffer(IMSI);
       
  2167 			if (status != eap_status_ok)
       
  2168 			{
       
  2169 				restore_saved_previous_state();
       
  2170 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2171 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  2172 			}
       
  2173 		}
       
  2174 
       
  2175 		set_authentication_vector(authentication_vector->copy());
       
  2176 		if (get_authentication_vector() == 0
       
  2177 		|| get_authentication_vector()->get_is_valid() == false)
       
  2178 		{
       
  2179 			restore_saved_previous_state();
       
  2180 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2181 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2182 		}
       
  2183 
       
  2184 		status = send_challenge_request_message(
       
  2185 			next_eap_identifier);
       
  2186 		if (status != eap_status_ok)
       
  2187 		{
       
  2188 			restore_saved_previous_state();
       
  2189 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2190 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2191 		}
       
  2192 
       
  2193 		set_last_eap_identifier(next_eap_identifier);
       
  2194 		set_state(eap_type_aka_state_waiting_for_challenge_response);
       
  2195 	}
       
  2196 	else
       
  2197 	{
       
  2198 		// Error occurred in tripler query.
       
  2199 		// We must send EAP-Notification message.
       
  2200 		// 
       
  2201 
       
  2202 		// eap_aka_notification_no_F_no_P_users_calls_are_barred and eap_aka_notification_no_F_no_P_user_has_not_subscribed_to_the_requested_service cannot be used because P bit is not set.
       
  2203 
       
  2204 		m_aka_notification_code = eap_aka_notification_no_F_P_set_general_failure;
       
  2205 
       
  2206 		status = initialize_notification_message();
       
  2207 
       
  2208 		set_last_eap_identifier(static_cast<u8_t>(get_last_eap_identifier()+1u));
       
  2209 
       
  2210 		set_state(eap_type_aka_state_waiting_for_notification_response_failure);
       
  2211 	}
       
  2212 
       
  2213 
       
  2214 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2215 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2216 }
       
  2217 
       
  2218 //--------------------------------------------------
       
  2219 
       
  2220 EAP_FUNC_EXPORT bool eap_type_aka_c::randomly_refuse_eap_identity()
       
  2221 {
       
  2222 	bool skip_query_imsi_from_username = false;
       
  2223 
       
  2224 	if (m_aka_test_version == true
       
  2225 		&& m_aka_randomly_refuse_eap_identity == true)
       
  2226 	{
       
  2227 		crypto_random_c rand(m_am_tools);
       
  2228 
       
  2229 		if (rand.get_is_valid() == false)
       
  2230 		{
       
  2231 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2232 			return false;
       
  2233 		}
       
  2234 
       
  2235 		u32_t random_guard;
       
  2236 
       
  2237 		eap_status_e status = rand.get_rand_bytes(
       
  2238 			reinterpret_cast<u8_t *>(&random_guard),
       
  2239 			sizeof(random_guard));
       
  2240 		if (status != eap_status_ok)
       
  2241 		{
       
  2242 			return false;
       
  2243 		}
       
  2244 
       
  2245 		if ((random_guard % 2) == 0)
       
  2246 		{
       
  2247 			// Note, this is just for testing.
       
  2248 			skip_query_imsi_from_username = true;
       
  2249 
       
  2250 			EAP_TRACE_DEBUG(
       
  2251 				m_am_tools, 
       
  2252 				TRACE_FLAGS_DEFAULT, 
       
  2253 				(EAPL("TEST: eap_type_aka_c::randomly_refuse_eap_identity(): ")
       
  2254 				 EAPL("randomly fails EAP-Identity.\n")));
       
  2255 		}
       
  2256 	}
       
  2257 
       
  2258 	return skip_query_imsi_from_username;
       
  2259 }
       
  2260 
       
  2261 //--------------------------------------------------
       
  2262 
       
  2263 //
       
  2264 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::handle_identity_response_message(
       
  2265 	eap_header_rd_c * const eap_header,
       
  2266 	const u32_t aka_packet_length)
       
  2267 {
       
  2268 	eap_status_e status = eap_status_process_general_error;
       
  2269 
       
  2270 	if (get_state() == eap_type_aka_state_waiting_for_identity_response
       
  2271 		|| get_state() == eap_type_aka_state_waiting_for_aka_identity_response
       
  2272 		|| get_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_any_identity
       
  2273 		|| get_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_full_auth_identity
       
  2274 		|| get_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_permanent_identity
       
  2275 		// In test version new authentication could start from this state.
       
  2276 		|| (m_aka_test_version == true
       
  2277 			&& get_state() == eap_type_aka_state_success) // This one is for testing purposes.
       
  2278 		)
       
  2279 	{
       
  2280 		// OK correct state.
       
  2281 	}
       
  2282 	else
       
  2283 	{
       
  2284 		// Wrong state, dischard packet.
       
  2285 		EAP_TRACE_DEBUG(
       
  2286 			m_am_tools, 
       
  2287 			TRACE_FLAGS_AKA_ERROR, 
       
  2288 			(EAPL("ERROR: eap_type_aka_c::handle_identity_response_message(): ")
       
  2289 			 EAPL("EAP-Response/Identity received in wrong state %d=%s. This EAP-packet is dropped.\n"),
       
  2290 			 get_state(), get_state_string()));
       
  2291 		EAP_TRACE_DEBUG(
       
  2292 			m_am_tools, 
       
  2293 			TRACE_FLAGS_AKA_ERROR, 
       
  2294 			(EAPL("ERROR: erroneous EAP packet: code=0x%02x, ")
       
  2295 			 EAPL("identifier=0x%02x, length=0x%04x, type=0x%08x, client %d\n"),
       
  2296 			 eap_header->get_code(),
       
  2297 			 eap_header->get_identifier(),
       
  2298 			 eap_header->get_length(),
       
  2299 			 convert_eap_type_to_u32_t(eap_header->get_type()),
       
  2300 			 get_is_client()));
       
  2301 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  2302 	}
       
  2303 
       
  2304 	if (m_check_identifier_of_eap_identity_response == true)
       
  2305 	{
       
  2306 		if (get_state() == eap_type_aka_state_waiting_for_identity_response
       
  2307 		&& eap_header->get_identifier() != get_last_eap_identifier())
       
  2308 		{
       
  2309 			// Wrong EAP-Identifier in this state.
       
  2310 			EAP_TRACE_DEBUG(
       
  2311 				m_am_tools, 
       
  2312 				TRACE_FLAGS_AKA_ERROR, 
       
  2313 				(EAPL("ERROR: eap_type_aka_c::handle_identity_response_message(): ")
       
  2314 				 EAPL("EAP-Identifier 0x%02x is wrong (0x%02x is correct) ")
       
  2315 				 EAPL("in eap_type_aka_state_variable_e %d=%s.\n"),
       
  2316 				 eap_header->get_identifier(),
       
  2317 				 get_last_eap_identifier(), 
       
  2318 				 get_state(),
       
  2319 				 get_state_string()));
       
  2320 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2321 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_identity);
       
  2322 		}
       
  2323 		else if ((get_state() == eap_type_aka_state_waiting_for_aka_identity_response
       
  2324 			|| get_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_any_identity
       
  2325 			|| get_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_full_auth_identity
       
  2326 			|| get_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_permanent_identity
       
  2327 			)
       
  2328 		&& eap_header->get_identifier() != get_last_eap_identifier()-1u)
       
  2329 		{
       
  2330 			// Wrong EAP-Identifier in this state.
       
  2331 			EAP_TRACE_DEBUG(
       
  2332 				m_am_tools, 
       
  2333 				TRACE_FLAGS_AKA_ERROR, 
       
  2334 				(EAPL("ERROR: eap_type_aka_c::handle_identity_response_message(): ")
       
  2335 				 EAPL("EAP-Identifier 0x%02x is wrong (0x%02x is correct) ")
       
  2336 				 EAPL("in eap_type_aka_state_variable_e %d=%s.\n"),
       
  2337 				 eap_header->get_identifier(),
       
  2338 				 get_last_eap_identifier()-1u, 
       
  2339 				 get_state(),
       
  2340 				 get_state_string()));
       
  2341 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2342 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_identity);
       
  2343 		}
       
  2344 		// In test version new authentication could start from this state.
       
  2345 		else if (m_aka_test_version == true
       
  2346 			&& get_state() == eap_type_aka_state_success) // This one is for testing purposes.
       
  2347 		{
       
  2348 			// NOTE here we can not check the EAP-identifier.
       
  2349 			EAP_TRACE_DEBUG(
       
  2350 				m_am_tools, 
       
  2351 				TRACE_FLAGS_DEFAULT, 
       
  2352 				(EAPL("WARNING: eap_type_aka_c::handle_identity_response_message(): ")
       
  2353 				 EAPL("EAP-Identifier 0x%02x is not checked in eap_type_aka_state_variable_e %d=%s.\n"),
       
  2354 				 eap_header->get_identifier(),
       
  2355 				 get_state(),
       
  2356 				 get_state_string()));
       
  2357 		}
       
  2358 	}
       
  2359 
       
  2360 	{
       
  2361 		// This could be first or retransmission request.
       
  2362 
       
  2363 		if (eap_header->get_type_data_length() > aka_packet_length)
       
  2364 		{
       
  2365 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2366 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_identity);
       
  2367 		}
       
  2368 
       
  2369 		status = parse_identity(
       
  2370 			eap_header->get_type_data(
       
  2371 				eap_header->get_type_data_length()),
       
  2372 			eap_header->get_type_data_length());
       
  2373 		if (status != eap_status_ok)
       
  2374 		{
       
  2375 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2376 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2377 		}
       
  2378 
       
  2379 		EAP_TRACE_DATA_DEBUG(
       
  2380 			m_am_tools, 
       
  2381 			TRACE_FLAGS_DEFAULT,
       
  2382 			(EAPL("AKA received EAP-identity NAI"),
       
  2383 			 get_NAI()->get_data(get_NAI()->get_data_length()),
       
  2384 			 get_NAI()->get_data_length()));
       
  2385 
       
  2386 		u8_t next_eap_identifier = static_cast<u8_t>(eap_header->get_identifier()+1u);
       
  2387 
       
  2388 		if (get_state() == eap_type_aka_state_waiting_for_aka_identity_response
       
  2389 		|| get_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_any_identity
       
  2390 		|| get_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_full_auth_identity
       
  2391 		|| get_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_permanent_identity
       
  2392 		)
       
  2393 		{
       
  2394 			// This is retransmission, so the EAP-identifier is not increased.
       
  2395 			next_eap_identifier = get_last_eap_identifier();
       
  2396 		}
       
  2397 		// In test version new authentication could start from this state.
       
  2398 		else if (m_aka_test_version == true
       
  2399 			&& get_state() == eap_type_aka_state_success) // This one is for testing purposes.
       
  2400 		{
       
  2401 			// NOTE here we can not check the EAP-identifier.
       
  2402 			next_eap_identifier = static_cast<u8_t>(eap_header->get_identifier()+1u);
       
  2403 			set_state(eap_type_aka_state_waiting_for_identity_response);
       
  2404 			get_IMSI()->reset();
       
  2405 		}
       
  2406 
       
  2407 		save_current_state();
       
  2408 		set_state(eap_type_aka_state_pending_pseudonym_decode_query);
       
  2409 
       
  2410 		eap_type_aka_identity_type identity_type = AKA_IDENTITY_TYPE_NONE;
       
  2411 
       
  2412 		if (m_accept_eap_identity_response == true)
       
  2413 		{
       
  2414 			if (randomly_refuse_eap_identity() == false)
       
  2415 			{
       
  2416 				status = m_am_type_aka->query_imsi_from_username(
       
  2417 					next_eap_identifier,
       
  2418 					get_send_network_id(),
       
  2419 					get_identity(),
       
  2420 					get_IMSI(),
       
  2421 					&identity_type,
       
  2422 					eap_type_aka_complete_handle_imsi_from_username);
       
  2423 			}
       
  2424 			else
       
  2425 			{
       
  2426 				status = eap_status_illegal_eap_identity;
       
  2427 			}
       
  2428 
       
  2429 			if (status == eap_status_pending_request)
       
  2430 			{
       
  2431 				// This is pending query, that will be completed by complete_imsi_from_username() call.
       
  2432 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2433 				return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2434 			}
       
  2435 			else if (status == eap_status_completed_request)
       
  2436 			{
       
  2437 				// This is already completed by complete_imsi_from_username() call.
       
  2438 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2439 				return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2440 			}
       
  2441 			else if (status != eap_status_ok)
       
  2442 			{
       
  2443 				// Identity decoding failed.
       
  2444 				// We must query IMSI of client.
       
  2445 
       
  2446 				if (m_use_manual_username == true)
       
  2447 				{
       
  2448 					// We reset the illegal identity.
       
  2449 					// EAP-AKA/request/start will query identity.
       
  2450 					get_identity()->reset();
       
  2451 				}
       
  2452 			}
       
  2453 			else // status == eap_status_ok
       
  2454 			{
       
  2455 				// The query_imsi_from_username() function call was synchronous.
       
  2456 				// We must call send_aka_identity_request_message().
       
  2457 			}
       
  2458 		}
       
  2459 
       
  2460 
       
  2461 		{
       
  2462 			status = handle_imsi_from_username(
       
  2463 				next_eap_identifier,
       
  2464 				get_send_network_id(),
       
  2465 				get_identity(),
       
  2466 				get_IMSI(),
       
  2467 				identity_type);
       
  2468 			if (status != eap_status_ok)
       
  2469 			{
       
  2470 				// ERROR in handle_imsi_from_username().
       
  2471 				// This will return error status of handle_imsi_from_username() call.
       
  2472 			}
       
  2473 			else
       
  2474 			{
       
  2475 				// OK handle_imsi_from_username().
       
  2476 			}
       
  2477 		}
       
  2478 	}
       
  2479 
       
  2480 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2481 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2482 }
       
  2483 
       
  2484 //--------------------------------------------------
       
  2485 
       
  2486 //
       
  2487 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::handle_imsi_from_username(
       
  2488 	const u8_t next_eap_identifier,
       
  2489 	const eap_am_network_id_c * const network_id,
       
  2490 	const eap_variable_data_c * const username,
       
  2491 	const eap_variable_data_c * const imsi, ///< The result is stored to imsi parameter.
       
  2492 	const eap_type_aka_identity_type received_identity_type)
       
  2493 {
       
  2494 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2495 
       
  2496 	EAP_UNREFERENCED_PARAMETER(username);
       
  2497 	EAP_UNREFERENCED_PARAMETER(network_id);
       
  2498 
       
  2499 	EAP_ASSERT(received_identity_type == AKA_IDENTITY_TYPE_IMSI_ID
       
  2500 		|| received_identity_type == AKA_IDENTITY_TYPE_PSEUDONYM_ID
       
  2501 		|| received_identity_type == AKA_IDENTITY_TYPE_RE_AUTH_ID
       
  2502 		|| received_identity_type == AKA_IDENTITY_TYPE_NONE);
       
  2503 
       
  2504 	if (get_state() != eap_type_aka_state_pending_pseudonym_decode_query)
       
  2505 	{
       
  2506 		// State is wrong. Cannot continue.
       
  2507 		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_gsmsim_state);
       
  2508 	}
       
  2509 
       
  2510 	eap_status_e status = eap_status_process_general_error;
       
  2511 	bool pseudonym_decode_failed = true;
       
  2512 
       
  2513 	//eap_type_aka_identity_type local_identity_type = identity_type;
       
  2514 	set_identity_type(received_identity_type);
       
  2515 
       
  2516 	if (imsi != 0
       
  2517 		&& imsi->get_is_valid_data() == true)
       
  2518 	{
       
  2519 		pseudonym_decode_failed = false;
       
  2520 		status = get_IMSI()->set_copy_of_buffer(imsi);
       
  2521 		if (status != eap_status_ok)
       
  2522 		{
       
  2523 			restore_saved_previous_state();
       
  2524 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2525 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2526 		}
       
  2527 
       
  2528 		if (received_identity_type == AKA_IDENTITY_TYPE_NONE)
       
  2529 		{
       
  2530 			set_identity_type(AKA_IDENTITY_TYPE_IMSI_ID);
       
  2531 		}
       
  2532 	}
       
  2533 	else
       
  2534 	{
       
  2535 		get_IMSI()->reset();
       
  2536 	}
       
  2537 
       
  2538 	if (received_identity_type == AKA_IDENTITY_TYPE_IMSI_ID)
       
  2539 	{
       
  2540 		m_authentication_type = AKA_AUTHENTICATION_TYPE_FULL_AUTH;
       
  2541 		set_identity_type(received_identity_type);
       
  2542 		set_aka_identity_response_includes_identity(aka_payload_AT_ANY_ID_REQ);
       
  2543 
       
  2544 		EAP_TRACE_DEBUG(
       
  2545 			m_am_tools, 
       
  2546 			TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
  2547 			(EAPL("Identity: IMSI\n")));
       
  2548 	}
       
  2549 	else if (received_identity_type == AKA_IDENTITY_TYPE_PSEUDONYM_ID)
       
  2550 	{
       
  2551 		m_authentication_type = AKA_AUTHENTICATION_TYPE_FULL_AUTH;
       
  2552 		set_identity_type(received_identity_type);
       
  2553 		set_aka_identity_response_includes_identity(aka_payload_AT_ANY_ID_REQ);
       
  2554 
       
  2555 		EAP_TRACE_DEBUG(
       
  2556 			m_am_tools, 
       
  2557 			TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
  2558 			(EAPL("Identity: pseudonym\n")));
       
  2559 	}
       
  2560 	else if (received_identity_type == AKA_IDENTITY_TYPE_RE_AUTH_ID)
       
  2561 	{
       
  2562 		m_authentication_type = AKA_AUTHENTICATION_TYPE_REAUTHENTICATION;
       
  2563 		set_identity_type(received_identity_type);
       
  2564 		set_aka_identity_response_includes_identity(aka_payload_AT_ANY_ID_REQ);
       
  2565 
       
  2566 		EAP_TRACE_DEBUG(
       
  2567 			m_am_tools, 
       
  2568 			TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
  2569 			(EAPL("Identity: re-authentication\n")));
       
  2570 	}
       
  2571 	else
       
  2572 	{
       
  2573 		m_authentication_type = AKA_AUTHENTICATION_TYPE_NONE;
       
  2574 
       
  2575 		EAP_TRACE_DEBUG(
       
  2576 			m_am_tools, 
       
  2577 			TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
  2578 			(EAPL("Identity: other\n")));
       
  2579 	}
       
  2580 
       
  2581 
       
  2582 	if (m_authentication_type == AKA_AUTHENTICATION_TYPE_FULL_AUTH
       
  2583 		&& (m_identity_type == AKA_IDENTITY_TYPE_IMSI_ID
       
  2584 			&& (get_saved_previous_state() == eap_type_aka_state_waiting_for_identity_response
       
  2585 				|| get_saved_previous_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_permanent_identity
       
  2586 				|| get_saved_previous_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_full_auth_identity
       
  2587 				|| get_saved_previous_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_any_identity
       
  2588 				|| get_saved_previous_state() == eap_type_aka_state_waiting_for_aka_identity_response))
       
  2589 		|| (m_identity_type == AKA_IDENTITY_TYPE_PSEUDONYM_ID
       
  2590 			&& (get_saved_previous_state() == eap_type_aka_state_waiting_for_identity_response
       
  2591 				|| get_saved_previous_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_permanent_identity
       
  2592 				|| get_saved_previous_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_any_identity
       
  2593 				|| get_saved_previous_state() == eap_type_aka_state_waiting_for_aka_identity_response))
       
  2594 		)
       
  2595 	{
       
  2596 		eap_type_aka_identity_type local_identity_type = m_identity_type;
       
  2597 
       
  2598 		eap_status_e local_status = query_AKA_authentication_vector(next_eap_identifier, &local_identity_type);
       
  2599 		if (local_status == eap_status_pending_request)
       
  2600 		{
       
  2601 			// Request will be completed later with complete_AKA_authentication_vector_query() function.
       
  2602 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2603 			return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2604 		}
       
  2605 		else if (local_status == eap_status_completed_request)
       
  2606 		{
       
  2607 			// Request was already completed with complete_AKA_authentication_vector_query() function.
       
  2608 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2609 			return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2610 		}
       
  2611 		else if (local_status != eap_status_ok)
       
  2612 		{
       
  2613 			// This is an error case.
       
  2614 			restore_saved_previous_state();
       
  2615 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2616 			return EAP_STATUS_RETURN(m_am_tools, local_status);
       
  2617 		}
       
  2618 		else //if (local_status == eap_status_ok)
       
  2619 		{
       
  2620 			// The query_AKA_authentication_vector() function call is synchronous.
       
  2621 			// We must call send_challenge_request_message().
       
  2622 		}
       
  2623 
       
  2624 		const u8_t local_eap_identifier = static_cast<u8_t>(get_last_eap_identifier()+1u);
       
  2625 
       
  2626 		local_status = send_challenge_request_message(
       
  2627 			local_eap_identifier);
       
  2628 		if (local_status != eap_status_ok)
       
  2629 		{
       
  2630 			restore_saved_previous_state();
       
  2631 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2632 			return EAP_STATUS_RETURN(m_am_tools, local_status);
       
  2633 		}
       
  2634 
       
  2635 		set_last_eap_identifier(local_eap_identifier);
       
  2636 		set_state(eap_type_aka_state_waiting_for_challenge_response);
       
  2637 
       
  2638 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2639 		return EAP_STATUS_RETURN(m_am_tools, local_status);
       
  2640 	}
       
  2641 	else if (m_identity_type == AKA_IDENTITY_TYPE_RE_AUTH_ID
       
  2642 		&& (get_saved_previous_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_any_identity
       
  2643 			|| get_saved_previous_state() == eap_type_aka_state_waiting_for_identity_response
       
  2644 			|| get_saved_previous_state() == eap_type_aka_state_waiting_for_aka_identity_response))
       
  2645 	{
       
  2646 		// Here we need to send EAP-Request/Re-authentication
       
  2647 		status = send_reauthentication_request_message(
       
  2648 			get_NAI(),
       
  2649 			pseudonym_decode_failed,
       
  2650 			next_eap_identifier);
       
  2651 	}
       
  2652 	else if (m_identity_type == AKA_IDENTITY_TYPE_NONE
       
  2653 		&& get_saved_previous_state() == eap_type_aka_state_waiting_for_identity_response)
       
  2654 	{
       
  2655 		set_aka_identity_response_includes_identity(aka_payload_AT_ANY_ID_REQ);
       
  2656 
       
  2657 		status = send_aka_identity_request_message(
       
  2658 			pseudonym_decode_failed,
       
  2659 			next_eap_identifier);
       
  2660 	}
       
  2661 	else
       
  2662 	{
       
  2663 		EAP_TRACE_DEBUG(
       
  2664 			m_am_tools, 
       
  2665 			TRACE_FLAGS_AKA_ERROR, 
       
  2666 			(EAPL("ERROR: eap_type_aka_c::handle_imsi_from_username(): ")
       
  2667 			 EAPL("EAP-Identity type 0x%02x is wrong in eap_type_aka_state_variable_e %d=%s.\n"),
       
  2668 			m_identity_type,
       
  2669 			get_saved_previous_state(),
       
  2670 			get_saved_previous_state_string()));
       
  2671 
       
  2672 		status = eap_status_illegal_eap_identity;
       
  2673 	}
       
  2674 
       
  2675 	if (status != eap_status_ok)
       
  2676 	{
       
  2677 		restore_saved_previous_state();
       
  2678 	}
       
  2679 	else
       
  2680 	{
       
  2681 		set_last_eap_identifier(next_eap_identifier);
       
  2682 	}
       
  2683 
       
  2684 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2685 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2686 }
       
  2687 
       
  2688 //--------------------------------------------------
       
  2689 
       
  2690 //
       
  2691 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::complete_imsi_from_username(
       
  2692 	const u8_t next_eap_identifier,
       
  2693 	const eap_am_network_id_c * const network_id,
       
  2694 	const eap_variable_data_c * const username,
       
  2695 	const eap_variable_data_c * const imsi, ///< The result is stored to imsi parameter.
       
  2696 	const eap_type_aka_identity_type identity_type,
       
  2697 	const eap_status_e completion_status,
       
  2698 	const eap_type_aka_complete_e completion_action)
       
  2699 {
       
  2700 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2701 
       
  2702 	EAP_TRACE_DEBUG(
       
  2703 		m_am_tools, 
       
  2704 		TRACE_FLAGS_DEFAULT, 
       
  2705 		(EAPL("eap_type_aka_c::complete_imsi_from_username(): ")
       
  2706 		 EAPL("EAP-identity is %d=%s, identity payload was %d=%s, state %d=%s.\n"),
       
  2707 		 identity_type,
       
  2708 		 get_identity_string(identity_type),
       
  2709 		 get_aka_identity_response_includes_identity(),
       
  2710 		 aka_payload_AT_header_c::get_payload_AT_string(get_aka_identity_response_includes_identity()),
       
  2711 		 get_state(),
       
  2712 		 get_state_string()));
       
  2713 
       
  2714 	EAP_UNREFERENCED_PARAMETER(username);
       
  2715 	EAP_UNREFERENCED_PARAMETER(network_id);
       
  2716 
       
  2717 	if (get_state() == eap_type_aka_state_none)
       
  2718 	{
       
  2719 		// The eap_status_handler_does_not_exists_error error value is more important
       
  2720 		// than return value of set_session_timeout().
       
  2721 		(void) get_type_partner()->set_session_timeout(0ul);
       
  2722 
       
  2723 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2724 		return EAP_STATUS_RETURN(m_am_tools, eap_status_handler_does_not_exists_error);
       
  2725 	}
       
  2726 
       
  2727 	if (completion_status != eap_status_ok)
       
  2728 	{
       
  2729 		set_state(eap_type_aka_state_failure);
       
  2730 
       
  2731 		// The completion_status error value is more important
       
  2732 		// than return value of set_session_timeout().
       
  2733 		(void) get_type_partner()->set_session_timeout(0ul);
       
  2734 
       
  2735 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2736 		return EAP_STATUS_RETURN(m_am_tools, completion_status);
       
  2737 	}
       
  2738 
       
  2739 	eap_status_e status = eap_status_not_supported;
       
  2740 
       
  2741 	if (completion_action == eap_type_aka_complete_handle_imsi_from_username)
       
  2742 	{
       
  2743 		status = handle_imsi_from_username(
       
  2744 			next_eap_identifier,
       
  2745 			network_id,
       
  2746 			username,
       
  2747 			imsi, ///< The result is stored to imsi parameter.
       
  2748 			identity_type);
       
  2749 
       
  2750 		status = eap_status_completed_request;
       
  2751 	}
       
  2752 	else if (completion_action == eap_type_aka_complete_handle_aka_identity_response_message_completion)
       
  2753 	{
       
  2754 		// NOTE the identity_payload_was_included parameter is
       
  2755 		// true in this completion.
       
  2756 		status = handle_aka_identity_response_message_completion(
       
  2757 			next_eap_identifier,
       
  2758 			completion_status,
       
  2759 			identity_type,
       
  2760 			true);
       
  2761 
       
  2762 		status = eap_status_completed_request;
       
  2763 	}
       
  2764 	else
       
  2765 	{
       
  2766 		// Unknown completion.
       
  2767 		EAP_TRACE_DEBUG(
       
  2768 			m_am_tools, 
       
  2769 			TRACE_FLAGS_AKA_ERROR, 
       
  2770 			(EAPL("ERROR: eap_type_aka_c::complete_imsi_from_username(): ")
       
  2771 			 EAPL("Unknown eap_type_aka_complete_e %d in eap_type_aka_state_variable_e %d=%s.\n"),
       
  2772 			completion_action,
       
  2773 			get_saved_previous_state(),
       
  2774 			get_saved_previous_state_string()));
       
  2775 	}
       
  2776 
       
  2777 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2778 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2779 }
       
  2780 
       
  2781 //--------------------------------------------------
       
  2782 
       
  2783 //
       
  2784 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::check_synchronization_failure_response_message(
       
  2785 	const eap_am_network_id_c * const /* receive_network_id */,
       
  2786 	aka_header_c * const /*received_aka*/,
       
  2787 	const u32_t /*aka_packet_length*/,
       
  2788 	aka_payloads_c * const p_aka_payloads)
       
  2789 {
       
  2790 	eap_status_e status = eap_status_process_general_error;
       
  2791 
       
  2792 		// Checks the payloads existence.
       
  2793 		if (p_aka_payloads->check_payloads(
       
  2794 				aka_payloads_c::eap_aka_payload_status_must_not_be, // nonce_s
       
  2795 				aka_payloads_c::eap_aka_payload_status_must_not_be, // MAC
       
  2796 				aka_payloads_c::eap_aka_payload_status_must_not_be, // ENCR_DATA
       
  2797 				aka_payloads_c::eap_aka_payload_status_must_not_be, // IDENTITY
       
  2798 				aka_payloads_c::eap_aka_payload_status_must_not_be, // padding
       
  2799 				aka_payloads_c::eap_aka_payload_status_must_not_be, // n_RANDs
       
  2800 				aka_payloads_c::eap_aka_payload_status_must_not_be, // AUTN
       
  2801 				aka_payloads_c::eap_aka_payload_status_must_be,     // AUTS
       
  2802 				aka_payloads_c::eap_aka_payload_status_must_not_be, // RES
       
  2803 				aka_payloads_c::eap_aka_payload_status_must_not_be, // PERMANENT_ID_REQ
       
  2804 				aka_payloads_c::eap_aka_payload_status_must_not_be, // FULLAUTH_ID_REQ
       
  2805 				aka_payloads_c::eap_aka_payload_status_must_not_be, // ANY_ID_REQ
       
  2806 				aka_payloads_c::eap_aka_payload_status_must_not_be, // IV
       
  2807 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NEXT_PSEUDONYM
       
  2808 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NEXT_REAUTH_ID
       
  2809 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NOTIFICATION
       
  2810 				aka_payloads_c::eap_aka_payload_status_must_not_be, // COUNTER
       
  2811 				aka_payloads_c::eap_aka_payload_status_must_not_be, // COUNTER_TOO_SMALL
       
  2812 				aka_payloads_c::eap_aka_payload_status_must_not_be, // CLIENT_ERROR_CODE
       
  2813 				aka_payloads_c::eap_aka_payload_status_must_not_be, // RESULT_IND
       
  2814 				aka_payloads_c::eap_aka_payload_status_must_not_be  // CHECKCODE
       
  2815 				) == true
       
  2816 			)
       
  2817 		{
       
  2818 			const u8_t next_eap_identifier = static_cast<u8_t>(get_last_eap_identifier()+1u);
       
  2819 
       
  2820 			save_current_state();
       
  2821 			set_state(eap_type_aka_state_pending_re_syncronization_query);
       
  2822 
       
  2823 			// - - - - - - - - - - - - - - - - - - - - - - - -
       
  2824 
       
  2825 			eap_type_aka_authentication_vector_c authentication_vector(m_am_tools);
       
  2826 
       
  2827 			status = authentication_vector.get_AUTS()->set_copy_of_buffer(
       
  2828 				p_aka_payloads->get_AUTS()->get_payload_buffer());
       
  2829 			if (status != eap_status_ok)
       
  2830 			{
       
  2831 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2832 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  2833 			}
       
  2834 
       
  2835 			status = authentication_vector.get_RAND()->set_copy_of_buffer(get_authentication_vector()->get_RAND());
       
  2836 			if (status != eap_status_ok)
       
  2837 			{
       
  2838 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2839 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  2840 			}
       
  2841 
       
  2842 			status = m_am_type_aka->query_re_syncronization(
       
  2843 				next_eap_identifier,
       
  2844 				&authentication_vector);
       
  2845 			if (status == eap_status_pending_request)
       
  2846 			{
       
  2847 				// Request will be completed later using complete_re_syncronization_query() function.
       
  2848 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2849 				return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2850 			}
       
  2851 			else if (status == eap_status_completed_request)
       
  2852 			{
       
  2853 				// Request was already completed by AM using complete_re_syncronization_query() function.
       
  2854 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2855 				return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2856 			}
       
  2857 			else if (status == eap_status_success)
       
  2858 			{
       
  2859 				// eap_status_success means the authentication was successful.
       
  2860 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2861 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  2862 			}
       
  2863 			else if (status == eap_status_ok)
       
  2864 			{
       
  2865 				// The query_re_syncronization() function call is synchronous.
       
  2866 				// We must call process_re_syncronization().
       
  2867 			}
       
  2868 			else
       
  2869 			{
       
  2870 				// This is an error case.
       
  2871 				restore_saved_previous_state();
       
  2872 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2873 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  2874 			}
       
  2875 
       
  2876 			// eap_status_ok status value means n_kc and n_sres were read but not processed.
       
  2877 			// Next we must call process_re_syncronization().
       
  2878 
       
  2879 			// - - - - - - - - - - - - - - - - - - - - - - - -
       
  2880 
       
  2881 			status = process_re_syncronization(
       
  2882 				next_eap_identifier,
       
  2883 				&authentication_vector);
       
  2884 
       
  2885 			if (status != eap_status_ok
       
  2886 				&& status != eap_status_success)
       
  2887 			{
       
  2888 				restore_saved_previous_state();
       
  2889 			}
       
  2890 
       
  2891 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2892 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2893 		}
       
  2894 		else
       
  2895 		{
       
  2896 			// Not correct AKA-payloads are included.
       
  2897 			EAP_TRACE_DEBUG(
       
  2898 				m_am_tools, 
       
  2899 				TRACE_FLAGS_AKA_ERROR, 
       
  2900 				(EAPL("ERROR: eap_type_aka_c::handle_challenge_request_message(6): ")
       
  2901 				 EAPL("Not correct AKA-payloads are included in eap_type_aka_state_variable_e %d=%s.\n"),
       
  2902 				 get_state(),
       
  2903 				 get_state_string()));
       
  2904 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2905 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2906 		}
       
  2907 }
       
  2908 
       
  2909 //--------------------------------------------------
       
  2910 
       
  2911 //
       
  2912 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::complete_re_syncronization_query(
       
  2913 	const u8_t next_eap_identifier,
       
  2914 	const eap_type_aka_authentication_vector_c * const authentication_vector)
       
  2915 {
       
  2916 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2917 
       
  2918 	eap_status_e status = eap_status_process_general_error;
       
  2919 
       
  2920 	if (get_state() != eap_type_aka_state_pending_re_syncronization_query
       
  2921 		|| authentication_vector == 0
       
  2922 		|| authentication_vector->get_is_valid() == false)
       
  2923 	{
       
  2924 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2925 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  2926 	}
       
  2927 
       
  2928 	status = process_re_syncronization(
       
  2929 		next_eap_identifier,
       
  2930 		authentication_vector);
       
  2931 
       
  2932 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2933 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2934 }
       
  2935 
       
  2936 //--------------------------------------------------
       
  2937 
       
  2938 //
       
  2939 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::process_re_syncronization(
       
  2940 	const u8_t next_eap_identifier,
       
  2941 	const eap_type_aka_authentication_vector_c * const authentication_vector)
       
  2942 {
       
  2943 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2944 
       
  2945 	eap_status_e status = eap_status_process_general_error;
       
  2946 
       
  2947 	if (get_state() != eap_type_aka_state_pending_re_syncronization_query
       
  2948 		|| authentication_vector == 0
       
  2949 		|| authentication_vector->get_is_valid() == false)
       
  2950 	{
       
  2951 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2952 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  2953 	}
       
  2954 
       
  2955 	set_authentication_vector(authentication_vector->copy());
       
  2956 	if (get_authentication_vector() == 0
       
  2957 		|| get_authentication_vector()->get_is_valid() == false)
       
  2958 	{
       
  2959 		restore_saved_previous_state();
       
  2960 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2961 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2962 	}
       
  2963 
       
  2964 	status = send_challenge_request_message(
       
  2965 		next_eap_identifier);
       
  2966 	if (status != eap_status_ok)
       
  2967 	{
       
  2968 		restore_saved_previous_state();
       
  2969 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2970 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2971 	}
       
  2972 
       
  2973 	set_last_eap_identifier(next_eap_identifier);
       
  2974 	set_state(eap_type_aka_state_waiting_for_challenge_response);
       
  2975 
       
  2976 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2977 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2978 }
       
  2979 
       
  2980 //--------------------------------------------------
       
  2981 
       
  2982 //
       
  2983 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::handle_synchronization_failure_response_message(
       
  2984 	const eap_am_network_id_c * const receive_network_id,
       
  2985 	aka_header_c * const received_aka,
       
  2986 	const u32_t aka_packet_length,
       
  2987 	aka_payloads_c * const p_aka_payloads)
       
  2988 {
       
  2989 	eap_status_e status = eap_status_process_general_error;
       
  2990 
       
  2991 	if (get_state() == eap_type_aka_state_waiting_for_challenge_response)
       
  2992 	{
       
  2993 		// This could be first or retransmission request.
       
  2994 		if (received_aka->get_identifier() != get_last_eap_identifier())
       
  2995 		{
       
  2996 			// Wrong EAP-Identifier in this state.
       
  2997 			EAP_TRACE_DEBUG(
       
  2998 				m_am_tools, 
       
  2999 				TRACE_FLAGS_AKA_ERROR, 
       
  3000 				(EAPL("ERROR: eap_type_aka_c::handle_synchronization_failure_response_message(): ")
       
  3001 				 EAPL("EAP-Identifier 0x%02x is wrong (0x%02x is correct) ")
       
  3002 				 EAPL("in eap_type_aka_state_variable_e %d=%s.\n"),
       
  3003 				 received_aka->get_identifier(),
       
  3004 				 get_last_eap_identifier(), 
       
  3005 				 get_state(),
       
  3006 				 get_state_string()));
       
  3007 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3008 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_identity);
       
  3009 		}
       
  3010 
       
  3011 		status = check_synchronization_failure_response_message(
       
  3012 			receive_network_id,
       
  3013 			received_aka,
       
  3014 			aka_packet_length,
       
  3015 			p_aka_payloads);
       
  3016 	}
       
  3017 	else if (get_state() == eap_type_aka_state_success)
       
  3018 	{
       
  3019 		if (received_aka->get_identifier() != get_last_eap_identifier()-1u)
       
  3020 		{
       
  3021 			// Wrong EAP-Identifier in this state.
       
  3022 			EAP_TRACE_DEBUG(
       
  3023 				m_am_tools, 
       
  3024 				TRACE_FLAGS_AKA_ERROR, 
       
  3025 				(EAPL("ERROR: eap_type_aka_c::handle_synchronization_failure_response_message(): ")
       
  3026 				 EAPL("EAP-Identifier 0x%02x is wrong (0x%02x is correct) ")
       
  3027 				 EAPL("in eap_type_aka_state_variable_e %d=%s.\n"),
       
  3028 				 received_aka->get_identifier(),
       
  3029 				 get_last_eap_identifier()-1u, 
       
  3030 				 get_state(),
       
  3031 				 get_state_string()));
       
  3032 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3033 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_identity);
       
  3034 		}
       
  3035 
       
  3036 		status = check_synchronization_failure_response_message(
       
  3037 			receive_network_id,
       
  3038 			received_aka,
       
  3039 			aka_packet_length,
       
  3040 			p_aka_payloads);
       
  3041 	}
       
  3042 	else if (get_state() == eap_type_aka_state_pending_re_syncronization_query)
       
  3043 	{
       
  3044 		// This is re-transmitted EAP-Response/AKA/Challenge.
       
  3045 		// We dischard it quietly.
       
  3046 		EAP_TRACE_DEBUG(
       
  3047 			m_am_tools, 
       
  3048 			TRACE_FLAGS_DEFAULT, 
       
  3049 			(EAPL("WARNING: eap_type_aka_c::handle_challenge_response_message(): ")
       
  3050 			 EAPL("Re-transmitted message %d=%s dropped in eap_type_aka_state_variable_e %d=%s.\n"),
       
  3051 			 received_aka->get_subtype(),
       
  3052 			 received_aka->get_subtype_string(),
       
  3053 			 get_state(),
       
  3054 			 get_state_string()));
       
  3055 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3056 		return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
       
  3057 	}
       
  3058 	else
       
  3059 	{
       
  3060 		// Wrong message in this state.
       
  3061 		EAP_TRACE_DEBUG(
       
  3062 			m_am_tools, 
       
  3063 			TRACE_FLAGS_AKA_ERROR, 
       
  3064 			(EAPL("ERROR: eap_type_aka_c::handle_challenge_request_message(): ")
       
  3065 			 EAPL("Wrong message %d=%s in eap_type_aka_state_variable_e %d=%s.\n"),
       
  3066 			 received_aka->get_subtype(),
       
  3067 			 received_aka->get_subtype_string(),
       
  3068 			 get_state(),
       
  3069 			 get_state_string()));
       
  3070 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3071 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3072 	}
       
  3073 
       
  3074 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3075 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3076 }
       
  3077 
       
  3078 //--------------------------------------------------
       
  3079 
       
  3080 //
       
  3081 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::handle_aka_identity_response_message_completion(
       
  3082 	const u8_t next_eap_identifier,
       
  3083 	const eap_status_e identity_status,
       
  3084 	eap_type_aka_identity_type received_identity_type,
       
  3085 	const bool identity_payload_was_included)
       
  3086 {
       
  3087 	EAP_TRACE_DEBUG(
       
  3088 		m_am_tools, 
       
  3089 		TRACE_FLAGS_DEFAULT, 
       
  3090 		(EAPL("eap_type_aka_c::handle_aka_identity_response_message_completion(): ")
       
  3091 		 EAPL("received_identity_type %d=%s, identity payload was %d=%s, state %d=%s.\n"),
       
  3092 		 received_identity_type,
       
  3093 		 get_identity_string(received_identity_type),
       
  3094 		 get_aka_identity_response_includes_identity(),
       
  3095 		 aka_payload_AT_header_c::get_payload_AT_string(get_aka_identity_response_includes_identity()),
       
  3096 		 get_state(),
       
  3097 		 get_state_string()));
       
  3098 
       
  3099 	if (get_state() == eap_type_aka_state_none)
       
  3100 	{
       
  3101 		// Authentication is terminated or state is wrong. Cannot continue.
       
  3102 
       
  3103 		// The eap_status_handler_does_not_exists_error error value is more important
       
  3104 		// than return value of set_session_timeout().
       
  3105 		(void) get_type_partner()->set_session_timeout(0ul);
       
  3106 
       
  3107 		return EAP_STATUS_RETURN(m_am_tools, eap_status_handler_does_not_exists_error);
       
  3108 	}
       
  3109 
       
  3110 	if (identity_payload_was_included == true)
       
  3111 	{
       
  3112 		if (identity_status != eap_status_ok
       
  3113 			|| received_identity_type == AKA_IDENTITY_TYPE_NONE)
       
  3114 		{
       
  3115 			// We did not get valid identity.
       
  3116 			set_identity_type(AKA_IDENTITY_TYPE_NONE);
       
  3117 			if (get_aka_identity_response_includes_identity() == aka_payload_AT_ANY_ID_REQ)
       
  3118 			{
       
  3119 				set_aka_identity_response_includes_identity(aka_payload_AT_FULLAUTH_ID_REQ);
       
  3120 			}
       
  3121 			else // if (get_aka_identity_response_includes_identity() == aka_payload_AT_FULLAUTH_ID_REQ)
       
  3122 			{
       
  3123 				set_aka_identity_response_includes_identity(aka_payload_AT_PERMANENT_ID_REQ);
       
  3124 			}
       
  3125 		}
       
  3126 		else
       
  3127 		{
       
  3128 			// We receive an identity.
       
  3129 			set_identity_type(received_identity_type);
       
  3130 		}
       
  3131 
       
  3132 		if (m_identity_type == AKA_IDENTITY_TYPE_IMSI_ID)
       
  3133 		{
       
  3134 			m_authentication_type = AKA_AUTHENTICATION_TYPE_FULL_AUTH;
       
  3135 
       
  3136 			EAP_TRACE_DEBUG(
       
  3137 				m_am_tools, 
       
  3138 				TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
  3139 				(EAPL("Identity: IMSI\n")));
       
  3140 		}
       
  3141 		else if (m_identity_type == AKA_IDENTITY_TYPE_PSEUDONYM_ID)
       
  3142 		{
       
  3143 			m_authentication_type = AKA_AUTHENTICATION_TYPE_FULL_AUTH;
       
  3144 
       
  3145 			EAP_TRACE_DEBUG(
       
  3146 				m_am_tools, 
       
  3147 				TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
  3148 				(EAPL("Identity: pseudonym\n")));
       
  3149 		}
       
  3150 		else if (m_identity_type == AKA_IDENTITY_TYPE_RE_AUTH_ID)
       
  3151 		{
       
  3152 			m_authentication_type = AKA_AUTHENTICATION_TYPE_REAUTHENTICATION;
       
  3153 
       
  3154 			EAP_TRACE_DEBUG(
       
  3155 				m_am_tools, 
       
  3156 				TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
  3157 				(EAPL("Identity: re-authentication\n")));
       
  3158 		}
       
  3159 		else
       
  3160 		{
       
  3161 			m_authentication_type = AKA_AUTHENTICATION_TYPE_NONE;
       
  3162 
       
  3163 			EAP_TRACE_DEBUG(
       
  3164 				m_am_tools, 
       
  3165 				TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
  3166 				(EAPL("Identity: other\n")));
       
  3167 		}
       
  3168 	}
       
  3169 	else
       
  3170 	{
       
  3171 		// No AT_IDENTITY payload.
       
  3172 		// We may have identity already.
       
  3173 		if (get_identity()->get_is_valid_data() == true
       
  3174 			&& m_authentication_type != AKA_AUTHENTICATION_TYPE_NONE
       
  3175 			&& m_identity_type != AKA_IDENTITY_TYPE_NONE)
       
  3176 		{
       
  3177 			// OK identity is known.
       
  3178 			EAP_TRACE_DEBUG(
       
  3179 				m_am_tools, 
       
  3180 				TRACE_FLAGS_DEFAULT, 
       
  3181 				(EAPL("eap_type_aka_c::handle_aka_identity_response_message_completion(): ")
       
  3182 				 EAPL("Known  m_identity_type %d=%s, identity payload was %d=%s, state %d=%s.\n"),
       
  3183 				 m_identity_type,
       
  3184 				 get_identity_string(m_identity_type),
       
  3185 				 get_aka_identity_response_includes_identity(),
       
  3186 				 aka_payload_AT_header_c::get_payload_AT_string(get_aka_identity_response_includes_identity()),
       
  3187 				 get_state(),
       
  3188 				 get_state_string()));
       
  3189 		}
       
  3190 		else
       
  3191 		{
       
  3192 			// ERROR no accepted identity.
       
  3193 			EAP_TRACE_ERROR(
       
  3194 				m_am_tools, 
       
  3195 				TRACE_FLAGS_AKA_ERROR, 
       
  3196 				(EAPL("ERROR: eap_type_aka_c::handle_aka_identity_response_message_completion(5): ")
       
  3197 				EAPL("No correct AKA-identity were received in eap_type_gsmsim_state_variable_e %d=%s.\n"),
       
  3198 				get_state(),
       
  3199 				get_state_string()));
       
  3200 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3201 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3202 		}
       
  3203 	}
       
  3204 
       
  3205 	save_current_state();
       
  3206 
       
  3207 	u8_t local_eap_identifier = 0u;
       
  3208 
       
  3209 	if (get_saved_previous_state() == eap_type_aka_state_waiting_for_challenge_response)
       
  3210 	{
       
  3211 		// Do not increase EAP-Identifier, this was re-transmission.
       
  3212 		local_eap_identifier = get_last_eap_identifier();
       
  3213 	}
       
  3214 	else
       
  3215 	{
       
  3216 		local_eap_identifier = static_cast<u8_t>(get_last_eap_identifier()+1u);
       
  3217 	}
       
  3218 
       
  3219 	if (m_identity_type == AKA_IDENTITY_TYPE_NONE)
       
  3220 	{
       
  3221 		eap_status_e local_status = send_aka_identity_request_message(
       
  3222 			true,
       
  3223 			local_eap_identifier);
       
  3224 		if (local_status != eap_status_ok)
       
  3225 		{
       
  3226 			restore_saved_previous_state();
       
  3227 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3228 			return EAP_STATUS_RETURN(m_am_tools, local_status);
       
  3229 		}
       
  3230 		set_last_eap_identifier(local_eap_identifier);
       
  3231 
       
  3232 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3233 		return EAP_STATUS_RETURN(m_am_tools, local_status);
       
  3234 	}
       
  3235 	else if (m_identity_type == AKA_IDENTITY_TYPE_IMSI_ID
       
  3236 		|| m_identity_type == AKA_IDENTITY_TYPE_PSEUDONYM_ID
       
  3237 		|| (m_identity_type == AKA_IDENTITY_TYPE_RE_AUTH_ID
       
  3238 			&& m_authentication_type == AKA_AUTHENTICATION_TYPE_FULL_AUTH))
       
  3239 	{
       
  3240 		eap_type_aka_identity_type local_identity_type = m_identity_type;
       
  3241 
       
  3242 		eap_status_e local_status = query_AKA_authentication_vector(
       
  3243 			next_eap_identifier,
       
  3244 			&local_identity_type);
       
  3245 		if (local_status == eap_status_pending_request)
       
  3246 		{
       
  3247 			// Request will be completed later with complete_AKA_authentication_vector_query() function.
       
  3248 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3249 			return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  3250 		}
       
  3251 		else if (local_status == eap_status_completed_request)
       
  3252 		{
       
  3253 			// Request was already completed with complete_AKA_authentication_vector_query() function.
       
  3254 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3255 			return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  3256 		}
       
  3257 		else if (local_status != eap_status_ok)
       
  3258 		{
       
  3259 			// This is an error case.
       
  3260 			restore_saved_previous_state();
       
  3261 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3262 			return EAP_STATUS_RETURN(m_am_tools, local_status);
       
  3263 		}
       
  3264 		else //if (local_status == eap_status_ok)
       
  3265 		{
       
  3266 			// The query_AKA_authentication_vector() function call is synchronous.
       
  3267 			// We must call send_challenge_request_message().
       
  3268 		}
       
  3269 
       
  3270 		local_status = send_challenge_request_message(
       
  3271 			local_eap_identifier);
       
  3272 		if (local_status != eap_status_ok)
       
  3273 		{
       
  3274 			restore_saved_previous_state();
       
  3275 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3276 			return EAP_STATUS_RETURN(m_am_tools, local_status);
       
  3277 		}
       
  3278 
       
  3279 		set_last_eap_identifier(local_eap_identifier);
       
  3280 		set_state(eap_type_aka_state_waiting_for_challenge_response);
       
  3281 
       
  3282 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3283 		return EAP_STATUS_RETURN(m_am_tools, local_status);
       
  3284 	}
       
  3285 	else if (m_identity_type == AKA_IDENTITY_TYPE_RE_AUTH_ID
       
  3286 		&& m_authentication_type == AKA_AUTHENTICATION_TYPE_REAUTHENTICATION)
       
  3287 	{
       
  3288 		// Here we need to send EAP-Request/Re-authentication
       
  3289 		eap_status_e local_status = send_reauthentication_request_message(
       
  3290 			get_NAI(),
       
  3291 			false,
       
  3292 			local_eap_identifier);
       
  3293 
       
  3294 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3295 		return EAP_STATUS_RETURN(m_am_tools, local_status);
       
  3296 	}
       
  3297 	else
       
  3298 	{
       
  3299 		// Unnown identity type, do nothing.
       
  3300 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3301 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_identity);
       
  3302 	}
       
  3303 
       
  3304 }
       
  3305 
       
  3306 //--------------------------------------------------
       
  3307 
       
  3308 //
       
  3309 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::handle_aka_identity_response_message(
       
  3310 	aka_header_c * const received_aka,
       
  3311 	const u32_t aka_packet_length,
       
  3312 	aka_payloads_c * const p_aka_payloads)
       
  3313 {
       
  3314 	eap_status_e status = eap_status_process_general_error;
       
  3315 
       
  3316 	EAP_TRACE_DEBUG(
       
  3317 		m_am_tools, 
       
  3318 		TRACE_FLAGS_DEFAULT, 
       
  3319 		(EAPL("eap_type_aka_c::handle_aka_identity_response_message(): ")
       
  3320 		 EAPL("m_identity_type %d=%s, identity payload was %d=%s, state %d=%s.\n"),
       
  3321 		 m_identity_type,
       
  3322 		 get_identity_string(m_identity_type),
       
  3323 		 get_aka_identity_response_includes_identity(),
       
  3324 		 aka_payload_AT_header_c::get_payload_AT_string(get_aka_identity_response_includes_identity()),
       
  3325 		 get_state(),
       
  3326 		 get_state_string()));
       
  3327 
       
  3328 	if (aka_packet_length < received_aka->get_length())
       
  3329 	{
       
  3330 		EAP_TRACE_DEBUG(
       
  3331 			m_am_tools, 
       
  3332 			TRACE_FLAGS_AKA_ERROR, 
       
  3333 			(EAPL("ERROR: eap_type_aka_c::handle_aka_identity_response_message(): ")
       
  3334 			 EAPL("aka_packet_length < received_aka->get_length().\n")));
       
  3335 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3336 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  3337 	}
       
  3338 
       
  3339 	if (get_state() == eap_type_aka_state_waiting_for_aka_identity_response
       
  3340 		|| get_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_any_identity
       
  3341 		|| get_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_full_auth_identity
       
  3342 		|| get_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_permanent_identity
       
  3343 		|| get_state() == eap_type_aka_state_waiting_for_challenge_response
       
  3344 		)
       
  3345 	{
       
  3346 		if (get_state() == eap_type_aka_state_waiting_for_aka_identity_response
       
  3347 			|| get_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_any_identity
       
  3348 			|| get_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_full_auth_identity
       
  3349 			|| get_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_permanent_identity
       
  3350 			)
       
  3351 		{
       
  3352 			if (received_aka->get_identifier() != get_last_eap_identifier())
       
  3353 			{
       
  3354 				// Wrong EAP-Identifier in this state.
       
  3355 				EAP_TRACE_DEBUG(
       
  3356 					m_am_tools, 
       
  3357 					TRACE_FLAGS_AKA_ERROR, 
       
  3358 					(EAPL("ERROR: eap_type_aka_c::handle_aka_identity_response_message(): ")
       
  3359 					 EAPL("EAP-Identifier 0x%02x is wrong (0x%02x is correct) ")
       
  3360 					 EAPL("in eap_type_aka_state_variable_e %d=%s.\n"),
       
  3361 					 received_aka->get_identifier(),
       
  3362 					 get_last_eap_identifier(), 
       
  3363 					 get_state(),
       
  3364 					 get_state_string()));
       
  3365 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3366 				return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_identity);
       
  3367 			}
       
  3368 		}
       
  3369 		else // if (get_state() == eap_type_aka_state_waiting_for_challenge_response)
       
  3370 		{
       
  3371 			// This might be retransmission response.
       
  3372 			if (received_aka->get_identifier() != get_last_eap_identifier()-1u)
       
  3373 			{
       
  3374 				// Wrong EAP-Identifier in this state.
       
  3375 				EAP_TRACE_DEBUG(
       
  3376 					m_am_tools, 
       
  3377 					TRACE_FLAGS_AKA_ERROR, 
       
  3378 					(EAPL("ERROR: eap_type_aka_c::handle_aka_identity_response_message(): ")
       
  3379 					 EAPL("EAP-Identifier 0x%02x is wrong (0x%02x is correct) ")
       
  3380 					 EAPL("in eap_type_aka_state_variable_e %d=%s.\n"),
       
  3381 					 received_aka->get_identifier(),
       
  3382 					 get_last_eap_identifier()-1u, 
       
  3383 					 get_state(),
       
  3384 					 get_state_string()));
       
  3385 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3386 				return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_identity);
       
  3387 			}
       
  3388 		}
       
  3389 
       
  3390 
       
  3391 		// Checks the payloads existence.
       
  3392 		if (p_aka_payloads->check_payloads(
       
  3393 				aka_payloads_c::eap_aka_payload_status_must_not_be, // nonce_s
       
  3394 				aka_payloads_c::eap_aka_payload_status_must_not_be, // MAC
       
  3395 				aka_payloads_c::eap_aka_payload_status_must_not_be, // ENCR_DATA
       
  3396 				aka_payloads_c::eap_aka_payload_status_optional,    // IDENTITY
       
  3397 				aka_payloads_c::eap_aka_payload_status_must_not_be, // padding
       
  3398 				aka_payloads_c::eap_aka_payload_status_must_not_be, // n_RANDs
       
  3399 				aka_payloads_c::eap_aka_payload_status_must_not_be, // AUTN
       
  3400 				aka_payloads_c::eap_aka_payload_status_must_not_be, // AUTS
       
  3401 				aka_payloads_c::eap_aka_payload_status_must_not_be, // RES
       
  3402 				aka_payloads_c::eap_aka_payload_status_must_not_be, // PERMANENT_ID_REQ
       
  3403 				aka_payloads_c::eap_aka_payload_status_must_not_be, // FULLAUTH_ID_REQ
       
  3404 				aka_payloads_c::eap_aka_payload_status_must_not_be, // ANY_ID_REQ
       
  3405 				aka_payloads_c::eap_aka_payload_status_must_not_be, // IV
       
  3406 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NEXT_PSEUDONYM
       
  3407 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NEXT_REAUTH_ID
       
  3408 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NOTIFICATION
       
  3409 				aka_payloads_c::eap_aka_payload_status_must_not_be, // COUNTER
       
  3410 				aka_payloads_c::eap_aka_payload_status_must_not_be, // COUNTER_TOO_SMALL
       
  3411 				aka_payloads_c::eap_aka_payload_status_must_not_be, // CLIENT_ERROR_CODE
       
  3412 				aka_payloads_c::eap_aka_payload_status_must_not_be, // RESULT_IND
       
  3413 				aka_payloads_c::eap_aka_payload_status_must_not_be  // CHECKCODE
       
  3414 				) == true
       
  3415 			)
       
  3416 		{
       
  3417 			if (get_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_permanent_identity)
       
  3418 			{
       
  3419 				if (p_aka_payloads->get_IDENTITY_payload()->get_payload_included() == true)
       
  3420 				{
       
  3421 					// OK, NAI identity is included.
       
  3422 					// Identity must be IMSI. query_AKA_authentication_vector() must decode identity.
       
  3423 
       
  3424 					set_aka_identity_response_includes_identity(aka_payload_AT_PERMANENT_ID_REQ);
       
  3425 				}
       
  3426 				else
       
  3427 				{
       
  3428 					// AT_IDENTITY is missing.
       
  3429 					EAP_TRACE_DEBUG(
       
  3430 						m_am_tools, 
       
  3431 						TRACE_FLAGS_AKA_ERROR, 
       
  3432 						(EAPL("ERROR: eap_type_aka_c::handle_aka_identity_response_message(0x%08x), ")
       
  3433 						 EAPL("AT_IDENTITY is missing in state %s.\n"),
       
  3434 						 this,
       
  3435 						 get_state_string()));
       
  3436 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3437 					return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3438 				}
       
  3439 			}
       
  3440 			else if (get_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_full_auth_identity)
       
  3441 			{
       
  3442 				if (p_aka_payloads->get_IDENTITY_payload()->get_payload_included() == true)
       
  3443 				{
       
  3444 					// OK, NAI identity is included.
       
  3445 					// Identity must be IMSI or pseudonym identity. query_AKA_authentication_vector() must decode identity.
       
  3446 
       
  3447 					set_aka_identity_response_includes_identity(aka_payload_AT_FULLAUTH_ID_REQ);
       
  3448 				}
       
  3449 				else
       
  3450 				{
       
  3451 					// AT_IDENTITY is missing.
       
  3452 					EAP_TRACE_DEBUG(
       
  3453 						m_am_tools, 
       
  3454 						TRACE_FLAGS_AKA_ERROR, 
       
  3455 						(EAPL("ERROR: eap_type_aka_c::handle_aka_identity_response_message(0x%08x), ")
       
  3456 						 EAPL("AT_IDENTITY is missing in state %s.\n"),
       
  3457 						 this,
       
  3458 						 get_state_string()));
       
  3459 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3460 					return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3461 				}
       
  3462 			}			
       
  3463 			else if (get_state() == eap_type_aka_state_waiting_for_aka_identity_response_with_at_any_identity)
       
  3464 			{
       
  3465 				if (p_aka_payloads->get_IDENTITY_payload()->get_payload_included() == true)
       
  3466 				{
       
  3467 					// OK, NAI identity is included.
       
  3468 					// Identity must be IMSI, pseudonym or re-authentication identity. query_AKA_authentication_vector() must decode identity.
       
  3469 
       
  3470 					set_aka_identity_response_includes_identity(aka_payload_AT_ANY_ID_REQ);
       
  3471 				}
       
  3472 				else
       
  3473 				{
       
  3474 					// AT_IDENTITY is missing.
       
  3475 					EAP_TRACE_DEBUG(
       
  3476 						m_am_tools, 
       
  3477 						TRACE_FLAGS_AKA_ERROR, 
       
  3478 						(EAPL("ERROR: eap_type_aka_c::handle_aka_identity_response_message(0x%08x), ")
       
  3479 						 EAPL("AT_IDENTITY is missing in state %s.\n"),
       
  3480 						 this,
       
  3481 						 get_state_string()));
       
  3482 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3483 					return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3484 				}
       
  3485 			}
       
  3486 			else if (get_state() == eap_type_aka_state_waiting_for_challenge_response)
       
  3487 			{
       
  3488 				// This is re-transmission.
       
  3489 				if (p_aka_payloads->get_IDENTITY_payload()->get_payload_included() == true)
       
  3490 				{
       
  3491 					if (get_aka_identity_response_includes_identity() == aka_payload_AT_PERMANENT_ID_REQ
       
  3492 						|| get_aka_identity_response_includes_identity() == aka_payload_AT_FULLAUTH_ID_REQ
       
  3493 						|| get_aka_identity_response_includes_identity() == aka_payload_AT_ANY_ID_REQ)
       
  3494 					{
       
  3495 						// OK, NAI identity is included.
       
  3496 					}
       
  3497 					else
       
  3498 					{
       
  3499 						// Illegal IDENTITY is included.
       
  3500 						EAP_TRACE_DEBUG(
       
  3501 							m_am_tools, 
       
  3502 							TRACE_FLAGS_AKA_ERROR, 
       
  3503 							(EAPL("ERROR: eap_type_aka_c::handle_aka_identity_response_message(0x%08x), ")
       
  3504 							 EAPL("illegal AT_IDENTITY included in state %s.\n"),
       
  3505 							 this,
       
  3506 							 get_state_string()));
       
  3507 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3508 						return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3509 					}
       
  3510 				}
       
  3511 			}
       
  3512 			else
       
  3513 			{
       
  3514 				if (p_aka_payloads->get_IDENTITY_payload()->get_payload_included() == true)
       
  3515 				{
       
  3516 					// Illegal IDENTITY is included.
       
  3517 					EAP_TRACE_DEBUG(
       
  3518 						m_am_tools, 
       
  3519 						TRACE_FLAGS_AKA_ERROR, 
       
  3520 						(EAPL("ERROR: eap_type_aka_c::handle_aka_identity_response_message(0x%08x), ")
       
  3521 						 EAPL("illegal AT_IDENTITY included in state %s.\n"),
       
  3522 						 this,
       
  3523 						 get_state_string()));
       
  3524 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3525 					return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3526 				}
       
  3527 			}
       
  3528 
       
  3529 
       
  3530 			status = checkcode_update_saved_message();
       
  3531 			if (status != eap_status_ok)
       
  3532 			{
       
  3533 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3534 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  3535 			}
       
  3536 
       
  3537 			status = checkcode_update(
       
  3538 				received_aka->get_header_buffer(
       
  3539 					received_aka->get_header_length()
       
  3540 					+received_aka->get_data_length()),
       
  3541 				received_aka->get_header_length()
       
  3542 				+received_aka->get_data_length());
       
  3543 			if (status != eap_status_ok)
       
  3544 			{
       
  3545 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3546 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  3547 			}
       
  3548 
       
  3549 
       
  3550 			eap_type_aka_identity_type identity_type = AKA_IDENTITY_TYPE_NONE;
       
  3551 			bool identity_payload_was_included = false;
       
  3552 			const u8_t next_eap_identifier = static_cast<u8_t>(received_aka->get_identifier()+1u);
       
  3553 
       
  3554 			if (p_aka_payloads->get_IDENTITY_payload()->get_payload_included() == true)
       
  3555 			{
       
  3556 				status = parse_identity(
       
  3557 					p_aka_payloads->get_IDENTITY_payload()->get_data(p_aka_payloads->get_IDENTITY_payload()->get_data_length()),
       
  3558 					p_aka_payloads->get_IDENTITY_payload()->get_data_length());
       
  3559 				if (status != eap_status_ok)
       
  3560 				{
       
  3561 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3562 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  3563 				}
       
  3564 
       
  3565 				identity_payload_was_included = true;
       
  3566 
       
  3567 				// We must ask AM module whether the identity is IMSI, pseudonym or re-authentication identity.
       
  3568 				// If we have re-authentication identity we must send re-authentication query.
       
  3569 
       
  3570 				if (randomly_refuse_eap_identity() == false)
       
  3571 				{
       
  3572 					status = m_am_type_aka->query_imsi_from_username(
       
  3573 						next_eap_identifier,
       
  3574 						get_send_network_id(),
       
  3575 						get_identity(),
       
  3576 						get_IMSI(),
       
  3577 						&identity_type,
       
  3578 						eap_type_aka_complete_handle_aka_identity_response_message_completion);
       
  3579 					if (status == eap_status_pending_request)
       
  3580 					{
       
  3581 						// This is pending query, that will be completed by complete_imsi_from_username() call.
       
  3582 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3583 						return EAP_STATUS_RETURN(m_am_tools, eap_status_pending_request);
       
  3584 					}
       
  3585 					else if (status == eap_status_completed_request)
       
  3586 					{
       
  3587 						// This is already completed by complete_imsi_from_username() call.
       
  3588 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3589 						return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  3590 					}
       
  3591 					else if (status != eap_status_ok)
       
  3592 					{
       
  3593 						// ERROR in query_imsi_from_username().
       
  3594 						// This will return error status of query_imsi_from_username() call.
       
  3595 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3596 						return EAP_STATUS_RETURN(m_am_tools, status);
       
  3597 					}
       
  3598 					else // status == eap_status_ok
       
  3599 					{
       
  3600 						// The query_imsi_from_username() function call was synchronous.
       
  3601 						// We must call send_aka_identity_request_message().
       
  3602 					}
       
  3603 				}
       
  3604 				else
       
  3605 				{
       
  3606 					status = eap_status_illegal_eap_identity;
       
  3607 				}
       
  3608 			}
       
  3609 
       
  3610 
       
  3611 			status = handle_aka_identity_response_message_completion(
       
  3612 				next_eap_identifier,
       
  3613 				status,
       
  3614 				identity_type,
       
  3615 				identity_payload_was_included);
       
  3616 
       
  3617 
       
  3618 		}
       
  3619 		else
       
  3620 		{
       
  3621 			// Not correct AKA-payloads are included.
       
  3622 			EAP_TRACE_DEBUG(
       
  3623 				m_am_tools, 
       
  3624 				TRACE_FLAGS_AKA_ERROR, 
       
  3625 				(EAPL("ERROR: eap_type_aka_c::handle_aka_identity_response_message(4): ")
       
  3626 				 EAPL("Not correct AKA-payloads are included in eap_type_aka_state_variable_e %d=%s.\n"),
       
  3627 				 get_state(),
       
  3628 				 get_state_string()));
       
  3629 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3630 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3631 		}
       
  3632 	}
       
  3633 	else if (get_state() == eap_type_aka_state_pending_authentication_vector_query)
       
  3634 	{
       
  3635 		// This is retransmission of EAP-Response/AKA/Start.
       
  3636 		// Triplet query is already initialized.
       
  3637 		// We will drop this message quietly.
       
  3638 		EAP_TRACE_DEBUG(
       
  3639 			m_am_tools, 
       
  3640 			TRACE_FLAGS_DEFAULT, 
       
  3641 			(EAPL("WARNING: eap_type_aka_c::handle_aka_identity_response_message(5): ")
       
  3642 			 EAPL("Retransmission of EAP-Response/AKA/Start in eap_type_aka_state_variable_e %d=%s.\n"),
       
  3643 			 get_state(),
       
  3644 			 get_state_string()));
       
  3645 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3646 		return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
       
  3647 	}
       
  3648 	else
       
  3649 	{
       
  3650 		// Wrong message in this state.
       
  3651 		EAP_TRACE_DEBUG(
       
  3652 			m_am_tools, 
       
  3653 			TRACE_FLAGS_AKA_ERROR, 
       
  3654 			(EAPL("ERROR: eap_type_aka_c::handle_aka_identity_response_message(): ")
       
  3655 			 EAPL("Wrong message %d=%s in eap_type_aka_state_variable_e %d=%s.\n"),
       
  3656 			 received_aka->get_subtype(),
       
  3657 			 received_aka->get_subtype_string(),
       
  3658 			 get_state(),
       
  3659 			 get_state_string()));
       
  3660 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3661 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3662 	}
       
  3663 
       
  3664 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3665 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3666 }
       
  3667 
       
  3668 //--------------------------------------------------
       
  3669 
       
  3670 //
       
  3671 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::handle_notification_response_message_reauthentication(
       
  3672 	const eap_am_network_id_c * const receive_network_id,
       
  3673 	aka_header_c * const received_aka,
       
  3674 	const u32_t /*aka_packet_length*/,
       
  3675 	aka_payloads_c * const p_aka_payloads)
       
  3676 {
       
  3677 	eap_status_e status = eap_status_process_general_error;
       
  3678 
       
  3679 	EAP_TRACE_DEBUG(
       
  3680 		m_am_tools, 
       
  3681 		TRACE_FLAGS_DEFAULT, 
       
  3682 		(EAPL("send: handler 0x%08x, AKA-type %10s, %s, state %2d=%s\n"),
       
  3683 		 this,
       
  3684 		 EAPL("handle_notification_response_message_reauthentication"),
       
  3685 		 (get_is_client()) ? EAPL("client") : EAPL("server"),
       
  3686 		 get_state(),
       
  3687 		 get_state_string()
       
  3688 		 ));
       
  3689 
       
  3690 	// The second most significant bit of the notification code is called
       
  3691 	// the Phase bit (P bit). It specifies at which phase of the EAP-AKA
       
  3692 	// exchange the notification can be used.
       
  3693 	if (get_aka_notification_code_P_bit(m_aka_notification_code) == false)
       
  3694 	{
       
  3695 		// If the P bit is set to zero,
       
  3696 		// the notification can only be used after a successful EAP/AKA/
       
  3697 		// Challenge round in full authentication or a successful EAP/AKA/
       
  3698 		// Re-authentication round in reautentication. A re-authentication round
       
  3699 		// is considered successful only if the peer has successfully verified
       
  3700 		// AT_MAC and AT_COUNTER attributes, and does not include the
       
  3701 		// AT_COUNTER_TOO_SMALL attribute in EAP-Response/AKA/Re-authentication.
       
  3702 
       
  3703 		// The AT_MAC attribute MUST beincluded if the P bit of the notification
       
  3704 		// code in AT_NOTIFICATION is set to zero, and MUST NOT be included in
       
  3705 		// cases when the P bit is set to one. The P bit is discussed in Section
       
  3706 		// 4.4.
       
  3707 
       
  3708 		// Checks the payloads existence.
       
  3709 		if (p_aka_payloads->check_payloads(
       
  3710 				aka_payloads_c::eap_aka_payload_status_must_not_be, // nonce_s
       
  3711 				aka_payloads_c::eap_aka_payload_status_must_be,     // MAC
       
  3712 				aka_payloads_c::eap_aka_payload_status_must_be,     // ENCR_DATA
       
  3713 				aka_payloads_c::eap_aka_payload_status_must_not_be, // IDENTITY
       
  3714 				aka_payloads_c::eap_aka_payload_status_must_not_be, // padding
       
  3715 				aka_payloads_c::eap_aka_payload_status_must_not_be, // n_RANDs
       
  3716 				aka_payloads_c::eap_aka_payload_status_must_not_be, // AUTN
       
  3717 				aka_payloads_c::eap_aka_payload_status_must_not_be, // AUTS
       
  3718 				aka_payloads_c::eap_aka_payload_status_must_not_be, // RES
       
  3719 				aka_payloads_c::eap_aka_payload_status_must_not_be, // PERMANENT_ID_REQ
       
  3720 				aka_payloads_c::eap_aka_payload_status_must_not_be, // FULLAUTH_ID_REQ
       
  3721 				aka_payloads_c::eap_aka_payload_status_must_not_be, // ANY_ID_REQ
       
  3722 				aka_payloads_c::eap_aka_payload_status_must_be,     // IV
       
  3723 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NEXT_PSEUDONYM
       
  3724 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NEXT_REAUTH_ID
       
  3725 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NOTIFICATION
       
  3726 				aka_payloads_c::eap_aka_payload_status_must_not_be, // COUNTER
       
  3727 				aka_payloads_c::eap_aka_payload_status_must_not_be, // COUNTER_TOO_SMALL
       
  3728 				aka_payloads_c::eap_aka_payload_status_must_not_be,  // CLIENT_ERROR_CODE
       
  3729 				aka_payloads_c::eap_aka_payload_status_must_not_be, // RESULT_IND
       
  3730 				aka_payloads_c::eap_aka_payload_status_must_not_be  // CHECKCODE
       
  3731 				) == true
       
  3732 			)
       
  3733 		{
       
  3734 			eap_variable_data_c orig_XKEY(m_am_tools);
       
  3735 			eap_variable_data_c orig_K_aut(m_am_tools);
       
  3736 			eap_variable_data_c orig_K_encr(m_am_tools);
       
  3737 
       
  3738 			if (orig_XKEY.get_is_valid() == false
       
  3739 				|| orig_K_aut.get_is_valid() == false
       
  3740 				|| orig_K_encr.get_is_valid() == false)
       
  3741 			{
       
  3742 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3743 				return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  3744 			}
       
  3745 
       
  3746 			u32_t reauth_counter = 0u;
       
  3747 
       
  3748 			// In order to use re-authentication, the client and the server need to
       
  3749 			// store the following values: original XKEY, K_aut, K_encr, latest
       
  3750 			// counter value and the next re-authentication identity.
       
  3751 			status = m_am_type_aka->query_reauth_parameters(
       
  3752 				&orig_XKEY,
       
  3753 				&orig_K_aut,
       
  3754 				&orig_K_encr,
       
  3755 				&reauth_counter);
       
  3756 			if (status != eap_status_ok)
       
  3757 			{
       
  3758 				restore_saved_previous_state();
       
  3759 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3760 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  3761 			}
       
  3762 
       
  3763 			status = check_message_authentication_code(
       
  3764 				&orig_K_aut,
       
  3765 				p_aka_payloads,
       
  3766 				received_aka,
       
  3767 				received_aka->get_length());
       
  3768 			if (status != eap_status_ok)
       
  3769 			{
       
  3770 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3771 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  3772 			}
       
  3773 
       
  3774 			bool authentication_ok = true;
       
  3775 
       
  3776 			// Decrypt and parse encrypted payload.
       
  3777 			{
       
  3778 				aka_payloads_c * const l_aka_payloads = new aka_payloads_c(m_am_tools);
       
  3779 				eap_automatic_variable_c<aka_payloads_c> l_aka_payloads_automatic(m_am_tools, l_aka_payloads);
       
  3780 
       
  3781 				if (l_aka_payloads == 0
       
  3782 					|| l_aka_payloads->get_is_valid() == false)
       
  3783 				{
       
  3784 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3785 					return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  3786 				}
       
  3787 
       
  3788 				status = decrypt_DATA_payload(
       
  3789 					p_aka_payloads,
       
  3790 					&orig_K_encr);
       
  3791 				if (status != eap_status_ok)
       
  3792 				{
       
  3793 					restore_saved_previous_state();
       
  3794 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3795 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  3796 				}
       
  3797 
       
  3798 				u32_t state_payload_buffer_length = p_aka_payloads->get_ENCR_DATA()->get_data_length();
       
  3799 				const aka_payload_AT_header_c gp_data_payload(
       
  3800 					m_am_tools,
       
  3801 					p_aka_payloads->get_ENCR_DATA()->get_data(state_payload_buffer_length),
       
  3802 					state_payload_buffer_length);
       
  3803 
       
  3804 				status = parse_aka_payload(
       
  3805 					&gp_data_payload,
       
  3806 					&state_payload_buffer_length,
       
  3807 					l_aka_payloads,
       
  3808 					received_aka->get_subtype());
       
  3809 				if (status != eap_status_ok)
       
  3810 				{
       
  3811 					restore_saved_previous_state();
       
  3812 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3813 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  3814 				}
       
  3815 
       
  3816 
       
  3817 				if (l_aka_payloads->get_COUNTER()->get_payload_included() == false)
       
  3818 				{
       
  3819 					restore_saved_previous_state();
       
  3820 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3821 					return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
       
  3822 				}
       
  3823 
       
  3824 				u32_t counter = l_aka_payloads->get_COUNTER()->get_original_header()->get_reserved();
       
  3825 
       
  3826 				if (counter == reauth_counter)
       
  3827 				{
       
  3828 					EAP_TRACE_DEBUG(
       
  3829 						m_am_tools, 
       
  3830 						TRACE_FLAGS_DEFAULT, 
       
  3831 						(EAPL("eap_type_aka_c::handle_notification_response_message_reauthentication(): ")
       
  3832 						EAPL("reauth counter %d OK, %d=%s.\n"),
       
  3833 						reauth_counter,
       
  3834 						get_state(),
       
  3835 						get_state_string()));
       
  3836 				}
       
  3837 				else
       
  3838 				{
       
  3839 					EAP_TRACE_DEBUG(
       
  3840 						m_am_tools, 
       
  3841 						TRACE_FLAGS_AKA_ERROR, 
       
  3842 						(EAPL("ERROR: eap_type_aka_c::handle_notification_response_message_reauthentication(): ")
       
  3843 						EAPL("reauth counter %d wrong, should be %d, %d=%s.\n"),
       
  3844 						counter,
       
  3845 						reauth_counter,
       
  3846 						get_state(),
       
  3847 						get_state_string()));
       
  3848 
       
  3849 					authentication_ok = false;
       
  3850 				}
       
  3851 			}
       
  3852 
       
  3853 			// The most significant bit is called the Failure bit (F bit).
       
  3854 			// The F bit specifies whether the notification implies failure.
       
  3855 			if (authentication_ok == false
       
  3856 				|| get_aka_notification_code_F_bit(m_aka_notification_code) == false)
       
  3857 			{
       
  3858 				// The code values with the F bit set to zero (code values 0...32767)
       
  3859 				// are used on unsuccessful cases.
       
  3860 				// The receipt of a notification code from this range implies failed EAP
       
  3861 				// exchange, so the peer can use the notification as a failure indication.
       
  3862 
       
  3863 				set_last_eap_identifier(static_cast<u8_t>(get_last_eap_identifier()+1u));
       
  3864 				set_state(eap_type_aka_state_failure);
       
  3865 
       
  3866 				// This will terminate session immediately.
       
  3867 				(void) get_type_partner()->set_session_timeout(0UL);
       
  3868 
       
  3869 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3870 				return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  3871 			}
       
  3872 			else //if (get_aka_notification_code_F_bit(m_aka_notification_code) == true)
       
  3873 			{
       
  3874 				// The receipt of a notification code with the F bit set to one (values
       
  3875 				// 32768...65536) does not imply failure. Notification code 32768 has
       
  3876 				// been reserved as a general notification code to indicate successful
       
  3877 				// authentication.
       
  3878 				if (m_aka_notification_code == eap_aka_notification_F_set_no_P_user_authenticated)
       
  3879 				{
       
  3880 					status = finish_successful_authentication(
       
  3881 						receive_network_id);
       
  3882 
       
  3883 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3884 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  3885 				}
       
  3886 				else
       
  3887 				{
       
  3888 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3889 					return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  3890 				}
       
  3891 			}
       
  3892 		}
       
  3893 		else
       
  3894 		{
       
  3895 			// Not correct AKA-payloads are included.
       
  3896 			EAP_TRACE_DEBUG(
       
  3897 				m_am_tools, 
       
  3898 				TRACE_FLAGS_AKA_ERROR, 
       
  3899 				(EAPL("ERROR: eap_type_aka_c::handle_notification_response_message_reauthentication(): ")
       
  3900 				 EAPL("Not correct AKA-payloads are included ")
       
  3901 				 EAPL("in eap_type_aka_state_variable_e %d=%s.\n"),
       
  3902 				 get_state(),
       
  3903 				 get_state_string()));
       
  3904 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3905 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3906 		}
       
  3907 	}
       
  3908 	else //if (get_aka_notification_code_P_bit(m_aka_notification_code) == true)
       
  3909 	{
       
  3910 		// Checks the payloads existence.
       
  3911 		if (p_aka_payloads->check_payloads(
       
  3912 				aka_payloads_c::eap_aka_payload_status_must_not_be, // nonce_s
       
  3913 				aka_payloads_c::eap_aka_payload_status_must_not_be, // MAC
       
  3914 				aka_payloads_c::eap_aka_payload_status_must_not_be, // ENCR_DATA
       
  3915 				aka_payloads_c::eap_aka_payload_status_must_not_be, // IDENTITY
       
  3916 				aka_payloads_c::eap_aka_payload_status_must_not_be, // padding
       
  3917 				aka_payloads_c::eap_aka_payload_status_must_not_be, // n_RANDs
       
  3918 				aka_payloads_c::eap_aka_payload_status_must_not_be, // AUTN
       
  3919 				aka_payloads_c::eap_aka_payload_status_must_not_be, // AUTS
       
  3920 				aka_payloads_c::eap_aka_payload_status_must_not_be, // RES
       
  3921 				aka_payloads_c::eap_aka_payload_status_must_not_be, // PERMANENT_ID_REQ
       
  3922 				aka_payloads_c::eap_aka_payload_status_must_not_be, // FULLAUTH_ID_REQ
       
  3923 				aka_payloads_c::eap_aka_payload_status_must_not_be, // ANY_ID_REQ
       
  3924 				aka_payloads_c::eap_aka_payload_status_must_not_be, // IV
       
  3925 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NEXT_PSEUDONYM
       
  3926 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NEXT_REAUTH_ID
       
  3927 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NOTIFICATION
       
  3928 				aka_payloads_c::eap_aka_payload_status_must_not_be, // COUNTER
       
  3929 				aka_payloads_c::eap_aka_payload_status_must_not_be, // COUNTER_TOO_SMALL
       
  3930 				aka_payloads_c::eap_aka_payload_status_must_not_be, // CLIENT_ERROR_CODE
       
  3931 				aka_payloads_c::eap_aka_payload_status_must_not_be, // RESULT_IND
       
  3932 				aka_payloads_c::eap_aka_payload_status_must_not_be  // CHECKCODE
       
  3933 				) == true
       
  3934 			)
       
  3935 		{
       
  3936 			// If the P bit is set to one, the notification can only by used before
       
  3937 			// the EAP/AKA/Challenge round in full authentication, or before the
       
  3938 			// EAP/AKA/Re-authentication round in reauthentication.
       
  3939 
       
  3940 			// The most significant bit is called the Failure bit (F bit).
       
  3941 			// The F bit specifies whether the notification implies failure.
       
  3942 			if (get_aka_notification_code_F_bit(m_aka_notification_code) == false)
       
  3943 			{
       
  3944 				// The code values with the F bit set to zero (code values 0...32767)
       
  3945 				// are used on unsuccessful cases.
       
  3946 				// The receipt of a notification code from this range implies failed EAP
       
  3947 				// exchange, so the peer can use the notification as a failure indication.
       
  3948 			}
       
  3949 			else //if (get_aka_notification_code_F_bit(m_aka_notification_code) == true)
       
  3950 			{
       
  3951 				// The receipt of a notification code with the F bit set to one (values
       
  3952 				// 32768...65536) does not imply failure. Notification code 32768 has
       
  3953 				// been reserved as a general notification code to indicate successful
       
  3954 				// authentication.
       
  3955 			}
       
  3956 
       
  3957 			status = initialize_error_message(
       
  3958 				eap_status_process_general_error);
       
  3959 
       
  3960 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3961 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  3962 		}
       
  3963 		else
       
  3964 		{
       
  3965 			// Not correct AKA-payloads are included.
       
  3966 			EAP_TRACE_DEBUG(
       
  3967 				m_am_tools, 
       
  3968 				TRACE_FLAGS_AKA_ERROR, 
       
  3969 				(EAPL("ERROR: eap_type_aka_c::handle_notification_response_message_reauthentication(): ")
       
  3970 				 EAPL("Not correct AKA-payloads are included ")
       
  3971 				 EAPL("in eap_type_aka_state_variable_e %d=%s.\n"),
       
  3972 				 get_state(),
       
  3973 				 get_state_string()));
       
  3974 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3975 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3976 		}
       
  3977 	}
       
  3978 }
       
  3979 
       
  3980 //--------------------------------------------------
       
  3981 
       
  3982 //
       
  3983 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::handle_notification_response_message_full_authentication(
       
  3984 	const eap_am_network_id_c * const receive_network_id,
       
  3985 	aka_header_c * const received_aka,
       
  3986 	const u32_t /*aka_packet_length*/,
       
  3987 	aka_payloads_c * const p_aka_payloads)
       
  3988 {
       
  3989 	EAP_TRACE_DEBUG(
       
  3990 		m_am_tools, 
       
  3991 		TRACE_FLAGS_DEFAULT, 
       
  3992 		(EAPL("send: handler 0x%08x, AKA-type %10s, %s, state %2d=%s\n"),
       
  3993 		 this,
       
  3994 		 EAPL("handle_notification_response_message_full_authentication"),
       
  3995 		 (get_is_client()) ? EAPL("client") : EAPL("server"),
       
  3996 		 get_state(),
       
  3997 		 get_state_string()
       
  3998 		 ));
       
  3999 
       
  4000 	// The second most significant bit of the notification code is called
       
  4001 	// the Phase bit (P bit). It specifies at which phase of the EAP-AKA
       
  4002 	// exchange the notification can be used.
       
  4003 	if (get_aka_notification_code_P_bit(m_aka_notification_code) == false)
       
  4004 	{
       
  4005 		// If the P bit is set to zero,
       
  4006 		// the notification can only be used after a successful EAP/AKA/
       
  4007 		// Challenge round in full authentication or a successful EAP/AKA/
       
  4008 		// Re-authentication round in reautentication. A re-authentication round
       
  4009 		// is considered successful only if the peer has successfully verified
       
  4010 		// AT_MAC and AT_COUNTER attributes, and does not include the
       
  4011 		// AT_COUNTER_TOO_SMALL attribute in EAP-Response/AKA/Re-authentication.
       
  4012 
       
  4013 		// The AT_MAC attribute MUST beincluded if the P bit of the notification
       
  4014 		// code in AT_NOTIFICATION is set to zero, and MUST NOT be included in
       
  4015 		// cases when the P bit is set to one. The P bit is discussed in Section
       
  4016 		// 4.4.
       
  4017 
       
  4018 		// Checks the payloads existence.
       
  4019 		if (p_aka_payloads->check_payloads(
       
  4020 				aka_payloads_c::eap_aka_payload_status_must_not_be, // nonce_s
       
  4021 				aka_payloads_c::eap_aka_payload_status_must_be,     // MAC
       
  4022 				aka_payloads_c::eap_aka_payload_status_must_not_be, // ENCR_DATA
       
  4023 				aka_payloads_c::eap_aka_payload_status_must_not_be, // IDENTITY
       
  4024 				aka_payloads_c::eap_aka_payload_status_must_not_be, // padding
       
  4025 				aka_payloads_c::eap_aka_payload_status_must_not_be, // n_RANDs
       
  4026 				aka_payloads_c::eap_aka_payload_status_must_not_be, // AUTN
       
  4027 				aka_payloads_c::eap_aka_payload_status_must_not_be, // AUTS
       
  4028 				aka_payloads_c::eap_aka_payload_status_must_not_be, // RES
       
  4029 				aka_payloads_c::eap_aka_payload_status_must_not_be, // PERMANENT_ID_REQ
       
  4030 				aka_payloads_c::eap_aka_payload_status_must_not_be, // FULLAUTH_ID_REQ
       
  4031 				aka_payloads_c::eap_aka_payload_status_must_not_be, // ANY_ID_REQ
       
  4032 				aka_payloads_c::eap_aka_payload_status_must_not_be, // IV
       
  4033 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NEXT_PSEUDONYM
       
  4034 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NEXT_REAUTH_ID
       
  4035 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NOTIFICATION
       
  4036 				aka_payloads_c::eap_aka_payload_status_must_not_be, // COUNTER
       
  4037 				aka_payloads_c::eap_aka_payload_status_must_not_be, // COUNTER_TOO_SMALL
       
  4038 				aka_payloads_c::eap_aka_payload_status_must_not_be, // CLIENT_ERROR_CODE
       
  4039 				aka_payloads_c::eap_aka_payload_status_must_not_be, // RESULT_IND
       
  4040 				aka_payloads_c::eap_aka_payload_status_must_not_be  // CHECKCODE
       
  4041 				) == true
       
  4042 			)
       
  4043 		{
       
  4044 			eap_status_e status = check_message_authentication_code(
       
  4045 				get_K_aut(),
       
  4046 				p_aka_payloads,
       
  4047 				received_aka,
       
  4048 				received_aka->get_length());
       
  4049 			if (status != eap_status_ok)
       
  4050 			{
       
  4051 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4052 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4053 			}
       
  4054 
       
  4055 			// The most significant bit is called the Failure bit (F bit).
       
  4056 			// The F bit specifies whether the notification implies failure.
       
  4057 			if (get_aka_notification_code_F_bit(m_aka_notification_code) == false)
       
  4058 			{
       
  4059 				// The code values with the F bit set to zero (code values 0...32767)
       
  4060 				// are used on unsuccessful cases.
       
  4061 				// The receipt of a notification code from this range implies failed EAP
       
  4062 				// exchange, so the peer can use the notification as a failure indication.
       
  4063 
       
  4064 				set_last_eap_identifier(static_cast<u8_t>(get_last_eap_identifier()+1u));
       
  4065 				set_state(eap_type_aka_state_failure);
       
  4066 
       
  4067 				// This will terminate session immediately.
       
  4068 				(void) get_type_partner()->set_session_timeout(0UL);
       
  4069 
       
  4070 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4071 				return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  4072 			}
       
  4073 			else //if (get_aka_notification_code_F_bit(m_aka_notification_code) == true)
       
  4074 			{
       
  4075 				// The receipt of a notification code with the F bit set to one (values
       
  4076 				// 32768...65536) does not imply failure. Notification code 32768 has
       
  4077 				// been reserved as a general notification code to indicate successful
       
  4078 				// authentication.
       
  4079 				if (m_aka_notification_code == eap_aka_notification_F_set_no_P_user_authenticated)
       
  4080 				{
       
  4081 					status = finish_successful_authentication(
       
  4082 						receive_network_id);
       
  4083 
       
  4084 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4085 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  4086 				}
       
  4087 				else
       
  4088 				{
       
  4089 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4090 					return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  4091 				}
       
  4092 			}
       
  4093 		}
       
  4094 		else
       
  4095 		{
       
  4096 			// Not correct AKA-payloads are included.
       
  4097 			EAP_TRACE_DEBUG(
       
  4098 				m_am_tools, 
       
  4099 				TRACE_FLAGS_AKA_ERROR, 
       
  4100 				(EAPL("ERROR: eap_type_aka_c::handle_notification_response_message_full_authentication(): ")
       
  4101 				 EAPL("Not correct AKA-payloads are included ")
       
  4102 				 EAPL("in eap_type_aka_state_variable_e %d=%s.\n"),
       
  4103 				 get_state(),
       
  4104 				 get_state_string()));
       
  4105 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4106 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  4107 		}
       
  4108 	}
       
  4109 	else //if (get_aka_notification_code_P_bit(m_aka_notification_code) == true)
       
  4110 	{
       
  4111 		// Checks the payloads existence.
       
  4112 		if (p_aka_payloads->check_payloads(
       
  4113 				aka_payloads_c::eap_aka_payload_status_must_not_be, // nonce_s
       
  4114 				aka_payloads_c::eap_aka_payload_status_must_not_be, // MAC
       
  4115 				aka_payloads_c::eap_aka_payload_status_must_not_be, // ENCR_DATA
       
  4116 				aka_payloads_c::eap_aka_payload_status_must_not_be, // IDENTITY
       
  4117 				aka_payloads_c::eap_aka_payload_status_must_not_be, // padding
       
  4118 				aka_payloads_c::eap_aka_payload_status_must_not_be, // n_RANDs
       
  4119 				aka_payloads_c::eap_aka_payload_status_must_not_be, // AUTN
       
  4120 				aka_payloads_c::eap_aka_payload_status_must_not_be, // AUTS
       
  4121 				aka_payloads_c::eap_aka_payload_status_must_not_be, // RES
       
  4122 				aka_payloads_c::eap_aka_payload_status_must_not_be, // PERMANENT_ID_REQ
       
  4123 				aka_payloads_c::eap_aka_payload_status_must_not_be, // FULLAUTH_ID_REQ
       
  4124 				aka_payloads_c::eap_aka_payload_status_must_not_be, // ANY_ID_REQ
       
  4125 				aka_payloads_c::eap_aka_payload_status_must_not_be, // IV
       
  4126 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NEXT_PSEUDONYM
       
  4127 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NEXT_REAUTH_ID
       
  4128 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NOTIFICATION
       
  4129 				aka_payloads_c::eap_aka_payload_status_must_not_be, // COUNTER
       
  4130 				aka_payloads_c::eap_aka_payload_status_must_not_be, // COUNTER_TOO_SMALL
       
  4131 				aka_payloads_c::eap_aka_payload_status_must_not_be, // CLIENT_ERROR_CODE
       
  4132 				aka_payloads_c::eap_aka_payload_status_must_not_be, // RESULT_IND
       
  4133 				aka_payloads_c::eap_aka_payload_status_must_not_be  // CHECKCODE
       
  4134 				) == true
       
  4135 			)
       
  4136 		{
       
  4137 			// If the P bit is set to one, the notification can only by used before
       
  4138 			// the EAP/AKA/Challenge round in full authentication, or before the
       
  4139 			// EAP/AKA/Re-authentication round in reauthentication.
       
  4140 
       
  4141 			// The most significant bit is called the Failure bit (F bit).
       
  4142 			// The F bit specifies whether the notification implies failure.
       
  4143 			if (get_aka_notification_code_F_bit(m_aka_notification_code) == false)
       
  4144 			{
       
  4145 				// The code values with the F bit set to zero (code values 0...32767)
       
  4146 				// are used on unsuccessful cases.
       
  4147 				// The receipt of a notification code from this range implies failed EAP
       
  4148 				// exchange, so the peer can use the notification as a failure indication.
       
  4149 			}
       
  4150 			else //if (get_aka_notification_code_F_bit(m_aka_notification_code) == true)
       
  4151 			{
       
  4152 				// The receipt of a notification code with the F bit set to one (values
       
  4153 				// 32768...65536) does not imply failure. Notification code 32768 has
       
  4154 				// been reserved as a general notification code to indicate successful
       
  4155 				// authentication.
       
  4156 			}
       
  4157 
       
  4158 			eap_status_e status = initialize_error_message(
       
  4159 				eap_status_process_general_error);
       
  4160 
       
  4161 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4162 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  4163 		}
       
  4164 		else
       
  4165 		{
       
  4166 			// Not correct AKA-payloads are included.
       
  4167 			EAP_TRACE_DEBUG(
       
  4168 				m_am_tools, 
       
  4169 				TRACE_FLAGS_AKA_ERROR, 
       
  4170 				(EAPL("ERROR: eap_type_aka_c::handle_notification_response_message_full_authentication(): ")
       
  4171 				 EAPL("Not correct AKA-payloads are included ")
       
  4172 				 EAPL("in eap_type_aka_state_variable_e %d=%s.\n"),
       
  4173 				 get_state(),
       
  4174 				 get_state_string()));
       
  4175 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4176 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  4177 		}
       
  4178 	}
       
  4179 }
       
  4180 
       
  4181 //--------------------------------------------------
       
  4182 
       
  4183 //
       
  4184 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::handle_notification_response_message(
       
  4185 	const eap_am_network_id_c * const receive_network_id,
       
  4186 	aka_header_c * const received_aka,
       
  4187 	const u32_t aka_packet_length,
       
  4188 	aka_payloads_c * const p_aka_payloads)
       
  4189 {
       
  4190 	if (aka_packet_length < received_aka->get_length())
       
  4191 	{
       
  4192 		EAP_TRACE_DEBUG(
       
  4193 			m_am_tools, 
       
  4194 			TRACE_FLAGS_AKA_ERROR, 
       
  4195 			(EAPL("ERROR: eap_type_aka_c::handle_notification_response_message(): ")
       
  4196 			 EAPL("aka_packet_length < received_aka->get_length().\n")));
       
  4197 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4198 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  4199 	}
       
  4200 
       
  4201 	eap_status_e status = eap_status_process_general_error;
       
  4202 
       
  4203 	if (get_state() == eap_type_aka_state_waiting_for_notification_response_success
       
  4204 		|| get_state() == eap_type_aka_state_waiting_for_notification_response_failure)
       
  4205 	{
       
  4206 		// NOTE, this message is unauthenticated. Anybody could sent this message.
       
  4207 
       
  4208 		if (received_aka->get_identifier() != get_last_eap_identifier())
       
  4209 		{
       
  4210 			// Wrong EAP-Identifier in this state.
       
  4211 			EAP_TRACE_DEBUG(
       
  4212 				m_am_tools, 
       
  4213 				TRACE_FLAGS_AKA_ERROR, 
       
  4214 				(EAPL("ERROR: eap_type_aka_c::handle_notification_response_message(): ")
       
  4215 				 EAPL("EAP-Identifier 0x%02x is wrong (0x%02x is correct) ")
       
  4216 				 EAPL("in eap_type_aka_state_variable_e %d=%s.\n"),
       
  4217 				 received_aka->get_identifier(), get_last_eap_identifier(), 
       
  4218 				 get_state(), get_state_string()));
       
  4219 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4220 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_identity);
       
  4221 		}
       
  4222 
       
  4223 
       
  4224 		if (m_authentication_type == AKA_AUTHENTICATION_TYPE_REAUTHENTICATION)
       
  4225 		{
       
  4226 			status = handle_notification_response_message_reauthentication(
       
  4227 				receive_network_id,
       
  4228 				received_aka,
       
  4229 				aka_packet_length,
       
  4230 				p_aka_payloads);
       
  4231 			if (status != eap_status_ok)
       
  4232 			{
       
  4233 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4234 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4235 			}
       
  4236 		}
       
  4237 		else
       
  4238 		{
       
  4239 			status = handle_notification_response_message_full_authentication(
       
  4240 				receive_network_id,
       
  4241 				received_aka,
       
  4242 				aka_packet_length,
       
  4243 				p_aka_payloads);
       
  4244 			if (status != eap_status_ok)
       
  4245 			{
       
  4246 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4247 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4248 			}
       
  4249 		}
       
  4250 
       
  4251 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4252 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4253 	}
       
  4254 	else
       
  4255 	{
       
  4256 		// Wrong message in this state.
       
  4257 		EAP_TRACE_DEBUG(
       
  4258 			m_am_tools, 
       
  4259 			TRACE_FLAGS_AKA_ERROR, 
       
  4260 			(EAPL("ERROR: eap_type_aka_c::handle_notification_response_message(): ")
       
  4261 			 EAPL("Wrong message %d=%s in eap_type_aka_state_variable_e %d=%s.\n"),
       
  4262 			 received_aka->get_subtype(),
       
  4263 			 received_aka->get_subtype_string(),
       
  4264 			 get_state(),
       
  4265 			 get_state_string()));
       
  4266 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4267 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  4268 	}
       
  4269 }
       
  4270 
       
  4271 //--------------------------------------------------
       
  4272 
       
  4273 //
       
  4274 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::check_challenge_response_message(
       
  4275 	const eap_am_network_id_c * const receive_network_id,
       
  4276 	aka_header_c * const received_aka,
       
  4277 	const u32_t aka_packet_length,
       
  4278 	aka_payloads_c * const p_aka_payloads)
       
  4279 {
       
  4280 	eap_status_e status = eap_status_process_general_error;
       
  4281 
       
  4282 	// Checks the payloads existence.
       
  4283 	if (p_aka_payloads->check_payloads(
       
  4284 			aka_payloads_c::eap_aka_payload_status_must_not_be, // nonce_s
       
  4285 			aka_payloads_c::eap_aka_payload_status_must_be,     // MAC
       
  4286 			aka_payloads_c::eap_aka_payload_status_must_not_be, // ENCR_DATA
       
  4287 			aka_payloads_c::eap_aka_payload_status_must_not_be, // IDENTITY
       
  4288 			aka_payloads_c::eap_aka_payload_status_must_not_be, // padding
       
  4289 			aka_payloads_c::eap_aka_payload_status_must_not_be, // n_RANDs
       
  4290 			aka_payloads_c::eap_aka_payload_status_must_not_be, // AUTN
       
  4291 			aka_payloads_c::eap_aka_payload_status_must_not_be, // AUTS
       
  4292 			aka_payloads_c::eap_aka_payload_status_must_be,     // RES
       
  4293 			aka_payloads_c::eap_aka_payload_status_must_not_be, // PERMANENT_ID_REQ
       
  4294 			aka_payloads_c::eap_aka_payload_status_must_not_be, // FULLAUTH_ID_REQ
       
  4295 			aka_payloads_c::eap_aka_payload_status_must_not_be, // ANY_ID_REQ
       
  4296 			aka_payloads_c::eap_aka_payload_status_must_not_be, // IV
       
  4297 			aka_payloads_c::eap_aka_payload_status_must_not_be, // NEXT_PSEUDONYM
       
  4298 			aka_payloads_c::eap_aka_payload_status_must_not_be, // NEXT_REAUTH_ID
       
  4299 			aka_payloads_c::eap_aka_payload_status_must_not_be, // NOTIFICATION
       
  4300 			aka_payloads_c::eap_aka_payload_status_must_not_be, // COUNTER
       
  4301 			aka_payloads_c::eap_aka_payload_status_must_not_be, // COUNTER_TOO_SMALL
       
  4302 			aka_payloads_c::eap_aka_payload_status_must_not_be, // CLIENT_ERROR_CODE
       
  4303 			aka_payloads_c::eap_aka_payload_status_optional,    // RESULT_IND
       
  4304 			aka_payloads_c::eap_aka_payload_status_optional     // CHECKCODE
       
  4305 			) == true
       
  4306 		)
       
  4307 	{
       
  4308 		save_current_state();
       
  4309 		set_state(eap_type_aka_state_analyses_challenge_response);
       
  4310 
       
  4311 		status = get_saved_EAP_packet()->set_buffer(
       
  4312 			received_aka->get_header_buffer(aka_packet_length),
       
  4313 			aka_packet_length,
       
  4314 			false,
       
  4315 			true);
       
  4316 		if (status != eap_status_ok)
       
  4317 		{
       
  4318 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4319 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  4320 		}
       
  4321 
       
  4322 		status = check_message_authentication_code(
       
  4323 			get_K_aut(),
       
  4324 			p_aka_payloads,
       
  4325 			received_aka,
       
  4326 			aka_packet_length);
       
  4327 
       
  4328 		if (status != eap_status_ok)
       
  4329 		{
       
  4330 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4331 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  4332 		}
       
  4333 
       
  4334 		if (p_aka_payloads->get_CHECKCODE()->get_payload_included() == true)
       
  4335 		{
       
  4336 			// Verify AT_CHECKCODE.
       
  4337 			status = checkcode_verify(
       
  4338 				p_aka_payloads->get_CHECKCODE()->get_payload_buffer());
       
  4339 			if (status != eap_status_ok)
       
  4340 			{
       
  4341 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4342 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4343 			}
       
  4344 		}
       
  4345 
       
  4346 		if (status == eap_status_ok)
       
  4347 		{
       
  4348 			// Ok, client successfully authenticated.
       
  4349 			EAP_TRACE_DEBUG(
       
  4350 				m_am_tools, 
       
  4351 				TRACE_FLAGS_DEFAULT, 
       
  4352 				(EAPL("Authentication OK.\n")));
       
  4353 
       
  4354 			if (m_use_result_indication == false
       
  4355 				&& p_aka_payloads->get_RESULT_IND()->get_payload_included() == true)
       
  4356 			{
       
  4357 				// ERROR: We did not send AT_RESULT_IND and client responds with it.
       
  4358 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4359 				return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
       
  4360 			}
       
  4361 			else if (m_use_result_indication == true
       
  4362 				&& p_aka_payloads->get_RESULT_IND()->get_payload_included() == false)
       
  4363 			{
       
  4364 				// Client does not expect result indication.
       
  4365 				m_use_result_indication = false;
       
  4366 			}
       
  4367 
       
  4368 			// Here we swap the addresses.
       
  4369 			eap_am_network_id_c send_network_id(m_am_tools,
       
  4370 				receive_network_id->get_destination_id(),
       
  4371 				receive_network_id->get_source_id(),
       
  4372 				receive_network_id->get_type());
       
  4373 
       
  4374 			if (get_master_session_key()->get_is_valid_data() == false
       
  4375 				|| get_master_session_key()->get_data_length() == 0u)
       
  4376 			{
       
  4377 				restore_saved_previous_state();
       
  4378 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4379 				return EAP_STATUS_RETURN(m_am_tools, eap_status_key_error);
       
  4380 			}
       
  4381 
       
  4382 			// In order to use re-authentication, the client and the server need to
       
  4383 			// store the following values: original XKEY, K_aut, K_encr, latest
       
  4384 			// counter value and the next re-authentication identity.
       
  4385 			status = m_am_type_aka->store_reauth_parameters(
       
  4386 				get_XKEY(),
       
  4387 				get_K_aut(),
       
  4388 				get_K_encr(),
       
  4389 				EAP_TYPE_AKA_INITIAL_REAUTH_COUNTER);
       
  4390 			if (status != eap_status_ok)
       
  4391 			{
       
  4392 				restore_saved_previous_state();
       
  4393 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4394 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4395 			}
       
  4396 
       
  4397 			if (m_use_result_indication == true)
       
  4398 			{
       
  4399 				// Send EAP-Request/AKA/Notification.
       
  4400 				m_aka_notification_code = eap_aka_notification_F_set_no_P_user_authenticated;
       
  4401 
       
  4402 				status = send_aka_notification_request(
       
  4403 					m_aka_notification_code,
       
  4404 					false);
       
  4405 				if (status != eap_status_ok)
       
  4406 				{
       
  4407 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4408 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  4409 				}
       
  4410 
       
  4411 				set_state(eap_type_aka_state_waiting_for_notification_response_success);
       
  4412 			}
       
  4413 			else
       
  4414 			{
       
  4415 				if (m_randomly_fail_successfull_authentication == true
       
  4416 					&& random_selection() == true)
       
  4417 				{
       
  4418 					// This is for testing.
       
  4419 					m_aka_notification_code = eap_aka_notification_no_F_no_P_general_failure;
       
  4420 
       
  4421 					status = initialize_notification_message();
       
  4422 				}
       
  4423 				else
       
  4424 				{
       
  4425 					// Note the EAP-Identifier of EAP-Success must be the same as
       
  4426 					// EAP-Identifier in the last EAP-Request - EAP-Response roundtrip.
       
  4427 					status = finish_successful_authentication(
       
  4428 						receive_network_id);
       
  4429 				}
       
  4430 			}
       
  4431 		}
       
  4432 
       
  4433 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4434 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4435 	}
       
  4436 	else
       
  4437 	{
       
  4438 		// Not correct AKA-payloads are included.
       
  4439 		EAP_TRACE_DEBUG(
       
  4440 			m_am_tools, 
       
  4441 			TRACE_FLAGS_AKA_ERROR, 
       
  4442 			(EAPL("ERROR: eap_type_aka_c::handle_challenge_response_message(6): ")
       
  4443 			 EAPL("Not correct AKA-payloads are included in eap_type_aka_state_variable_e %d=%s.\n"),
       
  4444 			 get_state(),
       
  4445 			 get_state_string()));
       
  4446 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4447 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  4448 	}
       
  4449 }
       
  4450 
       
  4451 
       
  4452 //--------------------------------------------------
       
  4453 
       
  4454 //
       
  4455 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::handle_challenge_response_message(
       
  4456 	const eap_am_network_id_c * const receive_network_id,
       
  4457 	aka_header_c * const received_aka,
       
  4458 	const u32_t aka_packet_length,
       
  4459 	aka_payloads_c * const p_aka_payloads)
       
  4460 {
       
  4461 	eap_status_e status = eap_status_process_general_error;
       
  4462 
       
  4463 	if (get_state() == eap_type_aka_state_waiting_for_challenge_response)
       
  4464 	{
       
  4465 		if (received_aka->get_identifier() != get_last_eap_identifier())
       
  4466 		{
       
  4467 			// Wrong EAP-Identifier in this state.
       
  4468 			EAP_TRACE_DEBUG(
       
  4469 				m_am_tools, 
       
  4470 				TRACE_FLAGS_AKA_ERROR, 
       
  4471 				(EAPL("ERROR: eap_type_aka_c::handle_challenge_response_message(): ")
       
  4472 				 EAPL("EAP-Identifier 0x%02x is wrong (0x%02x is correct) ")
       
  4473 				 EAPL("in eap_type_aka_state_variable_e %d=%s.\n"),
       
  4474 				 received_aka->get_identifier(), get_last_eap_identifier(), 
       
  4475 				 get_state(), get_state_string()));
       
  4476 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4477 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_identity);
       
  4478 		}
       
  4479 
       
  4480 		status = check_challenge_response_message(
       
  4481 			receive_network_id,
       
  4482 			received_aka,
       
  4483 			aka_packet_length,
       
  4484 			p_aka_payloads);
       
  4485 	}
       
  4486 	else if (get_state() == eap_type_aka_state_success)
       
  4487 	{
       
  4488 		if (received_aka->get_identifier() != get_last_eap_identifier()-1u)
       
  4489 		{
       
  4490 			// Wrong EAP-Identifier in this state.
       
  4491 			EAP_TRACE_DEBUG(
       
  4492 				m_am_tools, 
       
  4493 				TRACE_FLAGS_AKA_ERROR, 
       
  4494 				(EAPL("ERROR: eap_type_aka_c::handle_challenge_response_message(): ")
       
  4495 				 EAPL("EAP-Identifier 0x%02x is wrong (0x%02x is correct) ")
       
  4496 				 EAPL("in eap_type_aka_state_variable_e %d=%s.\n"),
       
  4497 				 received_aka->get_identifier(),
       
  4498 				 get_last_eap_identifier()-1u, 
       
  4499 				 get_state(),
       
  4500 				 get_state_string()));
       
  4501 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4502 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_identity);
       
  4503 		}
       
  4504 
       
  4505 		status = check_challenge_response_message(
       
  4506 			receive_network_id,
       
  4507 			received_aka,
       
  4508 			aka_packet_length,
       
  4509 			p_aka_payloads);
       
  4510 	}
       
  4511 	else if (get_state() == eap_type_aka_state_pending_authentication_vector_query)
       
  4512 	{
       
  4513 		// This is re-transmitted EAP-Response/AKA/Challenge.
       
  4514 		// We dischard it quietly.
       
  4515 		EAP_TRACE_DEBUG(
       
  4516 			m_am_tools, 
       
  4517 			TRACE_FLAGS_DEFAULT, 
       
  4518 			(EAPL("WARNING: eap_type_aka_c::handle_challenge_response_message(): ")
       
  4519 			 EAPL("Re-transmitted message %d=%s dropped in eap_type_aka_state_variable_e %d=%s.\n"),
       
  4520 			 received_aka->get_subtype(),
       
  4521 			 received_aka->get_subtype_string(),
       
  4522 			 get_state(),
       
  4523 			 get_state_string()));
       
  4524 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4525 		return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
       
  4526 	}
       
  4527 	else
       
  4528 	{
       
  4529 		// Wrong message in this state.
       
  4530 		EAP_TRACE_DEBUG(
       
  4531 			m_am_tools, 
       
  4532 			TRACE_FLAGS_AKA_ERROR, 
       
  4533 			(EAPL("ERROR: eap_type_aka_c::handle_challenge_response_message(): ")
       
  4534 			 EAPL("Wrong message %d=%s in eap_type_aka_state_variable_e %d=%s.\n"),
       
  4535 			 received_aka->get_subtype(),
       
  4536 			 received_aka->get_subtype_string(),
       
  4537 			 get_state(),
       
  4538 			 get_state_string()));
       
  4539 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4540 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  4541 	}
       
  4542 
       
  4543 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4544 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4545 }
       
  4546 
       
  4547 //--------------------------------------------------
       
  4548 
       
  4549 //
       
  4550 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::handle_reauthentication_response_message(
       
  4551 	const eap_am_network_id_c * const receive_network_id,
       
  4552 	aka_header_c * const received_aka,
       
  4553 	const u32_t aka_packet_length,
       
  4554 	aka_payloads_c * const p_aka_payloads)
       
  4555 {
       
  4556 	eap_status_e status = eap_status_process_general_error;
       
  4557 
       
  4558 	EAP_TRACE_DEBUG(
       
  4559 		m_am_tools,
       
  4560 		TRACE_FLAGS_DEFAULT,
       
  4561 		(EAPL("eap_type_aka_c::handle_reauthentication_response_message(): %s, m_identity_type %d=%s, identity payload was %d=%s.\n"),
       
  4562 		 (m_is_client == true ? "client": "server"),
       
  4563 		 m_identity_type,
       
  4564 		 get_identity_string(m_identity_type),
       
  4565 		 get_aka_identity_response_includes_identity(),
       
  4566 		 aka_payload_AT_header_c::get_payload_AT_string(get_aka_identity_response_includes_identity())));
       
  4567 
       
  4568 	if (get_state() == eap_type_aka_state_waiting_for_reauth_response)
       
  4569 	{
       
  4570 		// This could be first or retransmission request.
       
  4571 
       
  4572 		// Checks the payloads existence.
       
  4573 		if (p_aka_payloads->check_payloads(
       
  4574 				aka_payloads_c::eap_aka_payload_status_must_not_be, // nonce_s
       
  4575 				aka_payloads_c::eap_aka_payload_status_must_be,     // MAC
       
  4576 				aka_payloads_c::eap_aka_payload_status_must_be,     // ENCR_DATA
       
  4577 				aka_payloads_c::eap_aka_payload_status_must_not_be, // IDENTITY
       
  4578 				aka_payloads_c::eap_aka_payload_status_must_not_be, // padding
       
  4579 				aka_payloads_c::eap_aka_payload_status_must_not_be, // n_RANDs
       
  4580 				aka_payloads_c::eap_aka_payload_status_must_not_be, // AUTN
       
  4581 				aka_payloads_c::eap_aka_payload_status_must_not_be, // AUTS
       
  4582 				aka_payloads_c::eap_aka_payload_status_must_not_be, // RES
       
  4583 				aka_payloads_c::eap_aka_payload_status_must_not_be, // PERMANENT_ID_REQ
       
  4584 				aka_payloads_c::eap_aka_payload_status_must_not_be, // FULLAUTH_ID_REQ
       
  4585 				aka_payloads_c::eap_aka_payload_status_must_not_be, // ANY_ID_REQ
       
  4586 				aka_payloads_c::eap_aka_payload_status_must_be,     // IV
       
  4587 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NEXT_PSEUDONYM
       
  4588 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NEXT_REAUTH_ID
       
  4589 				aka_payloads_c::eap_aka_payload_status_must_not_be, // NOTIFICATION
       
  4590 				aka_payloads_c::eap_aka_payload_status_must_not_be, // COUNTER
       
  4591 				aka_payloads_c::eap_aka_payload_status_must_not_be, // COUNTER_TOO_SMALL
       
  4592 				aka_payloads_c::eap_aka_payload_status_must_not_be, // CLIENT_ERROR_CODE
       
  4593 				aka_payloads_c::eap_aka_payload_status_optional,    // RESULT_IND
       
  4594 				aka_payloads_c::eap_aka_payload_status_optional     // CHECKCODE
       
  4595 				) == true
       
  4596 			)
       
  4597 		{
       
  4598 
       
  4599 			set_last_eap_identifier(received_aka->get_identifier());
       
  4600 
       
  4601 			save_current_state();
       
  4602 			set_state(eap_type_aka_state_analyses_reauthentication_response);
       
  4603 
       
  4604 			// - - - - - - - - - - - - - - - - - - - - - - - -
       
  4605 
       
  4606 			eap_variable_data_c orig_XKEY(m_am_tools);
       
  4607 			eap_variable_data_c orig_K_aut(m_am_tools);
       
  4608 			eap_variable_data_c orig_K_encr(m_am_tools);
       
  4609 
       
  4610 			if (orig_XKEY.get_is_valid() == false
       
  4611 				|| orig_K_aut.get_is_valid() == false
       
  4612 				|| orig_K_encr.get_is_valid() == false)
       
  4613 			{
       
  4614 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4615 				return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4616 			}
       
  4617 
       
  4618 			u32_t reauth_counter = 0u;
       
  4619 			// In order to use re-authentication, the client and the server need to
       
  4620 			// store the following values: original XKEY, K_aut, K_encr, latest
       
  4621 			// counter value and the next re-authentication identity.
       
  4622 			status = m_am_type_aka->query_reauth_parameters(
       
  4623 				&orig_XKEY,
       
  4624 				&orig_K_aut,
       
  4625 				&orig_K_encr,
       
  4626 				&reauth_counter);
       
  4627 			if (status != eap_status_ok)
       
  4628 			{
       
  4629 				restore_saved_previous_state();
       
  4630 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4631 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4632 			}
       
  4633 
       
  4634 			status = check_message_authentication_code(
       
  4635 				&orig_K_aut,
       
  4636 				p_aka_payloads,
       
  4637 				received_aka,
       
  4638 				aka_packet_length);
       
  4639 			if (status != eap_status_ok)
       
  4640 			{
       
  4641 				restore_saved_previous_state();
       
  4642 
       
  4643 				eap_status_string_c status_string;
       
  4644 				EAP_UNREFERENCED_PARAMETER(status_string);
       
  4645 				EAP_TRACE_DEBUG(
       
  4646 					m_am_tools, 
       
  4647 					TRACE_FLAGS_AKA_ERROR, 
       
  4648 					(EAPL("ERROR: Re-authentication failed: %s, state %s\n"),
       
  4649 					 status_string.get_status_string(status),
       
  4650 					 get_state_string()));
       
  4651 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4652 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4653 			}
       
  4654 
       
  4655 			if (p_aka_payloads->get_CHECKCODE()->get_payload_included() == true)
       
  4656 			{
       
  4657 				// Verify AT_CHECKCODE.
       
  4658 				status = checkcode_verify(
       
  4659 					p_aka_payloads->get_CHECKCODE()->get_payload_buffer());
       
  4660 				if (status != eap_status_ok)
       
  4661 				{
       
  4662 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4663 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  4664 				}
       
  4665 			}
       
  4666 
       
  4667 			// Decrypt and parse encrypted payload.
       
  4668 			if (p_aka_payloads->get_IV()->get_payload_included() == true
       
  4669 			|| p_aka_payloads->get_ENCR_DATA()->get_payload_included() == true)
       
  4670 			{
       
  4671 				if (p_aka_payloads->get_IV()->get_payload_included() == true
       
  4672 				&& p_aka_payloads->get_ENCR_DATA()->get_payload_included() == true
       
  4673 				&& p_aka_payloads->get_MAC()->get_payload_included() == true)
       
  4674 				{
       
  4675 					if (m_use_result_indication == false
       
  4676 						&& p_aka_payloads->get_RESULT_IND()->get_payload_included() == true)
       
  4677 					{
       
  4678 						// ERROR: We did not send AT_RESULT_IND and client responds with it.
       
  4679 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4680 						return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
       
  4681 					}
       
  4682 					else if (m_use_result_indication == true
       
  4683 						&& p_aka_payloads->get_RESULT_IND()->get_payload_included() == false)
       
  4684 					{
       
  4685 						// Client does not expect result indication.
       
  4686 						m_use_result_indication = false;
       
  4687 					}
       
  4688 
       
  4689 					aka_payloads_c * const l_aka_payloads = new aka_payloads_c(m_am_tools);
       
  4690 					eap_automatic_variable_c<aka_payloads_c> l_aka_payloads_automatic(m_am_tools, l_aka_payloads);
       
  4691 
       
  4692 					if (l_aka_payloads == 0
       
  4693 						|| l_aka_payloads->get_is_valid() == false)
       
  4694 					{
       
  4695 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4696 						return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  4697 					}
       
  4698 
       
  4699 					status = decrypt_DATA_payload(
       
  4700 						p_aka_payloads,
       
  4701 						&orig_K_encr);
       
  4702 					if (status != eap_status_ok)
       
  4703 					{
       
  4704 						restore_saved_previous_state();
       
  4705 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4706 						return EAP_STATUS_RETURN(m_am_tools, status);
       
  4707 					}
       
  4708 
       
  4709 					u32_t state_payload_buffer_length = p_aka_payloads->get_ENCR_DATA()->get_data_length();
       
  4710 
       
  4711 					const aka_payload_AT_header_c gp_data_payload(
       
  4712 						m_am_tools,
       
  4713 						p_aka_payloads->get_ENCR_DATA()->get_data(state_payload_buffer_length),
       
  4714 						state_payload_buffer_length);
       
  4715 
       
  4716 					if (gp_data_payload.get_is_valid() == false)
       
  4717 					{
       
  4718 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4719 						return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  4720 					}
       
  4721 
       
  4722 					status = parse_aka_payload(
       
  4723 						&gp_data_payload,
       
  4724 						&state_payload_buffer_length,
       
  4725 						l_aka_payloads,
       
  4726 						received_aka->get_subtype());
       
  4727 					if (status != eap_status_ok)
       
  4728 					{
       
  4729 						restore_saved_previous_state();
       
  4730 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4731 						return EAP_STATUS_RETURN(m_am_tools, status);
       
  4732 					}
       
  4733 
       
  4734 					if (l_aka_payloads->get_COUNTER_TOO_SMALL()->get_payload_included() == true)
       
  4735 					{
       
  4736 						// When the client detects that the
       
  4737 						// counter value is not fresh, it includes the AT_COUNTER_TOO_SMALL
       
  4738 						// attribute in EAP-Response/AKA/Re-authentication. This attribute
       
  4739 						// doesn't contain any data but it is a request for the server to
       
  4740 						// initiate full authentication.
       
  4741 
       
  4742 						// The full authentication must follow.
       
  4743 						m_authentication_type = AKA_AUTHENTICATION_TYPE_FULL_AUTH;
       
  4744 						set_aka_identity_response_includes_identity(aka_payload_NONE);
       
  4745 
       
  4746 						bool pseudonym_decode_failed = false;
       
  4747 
       
  4748 						if (get_identity()->get_is_valid_data() == false
       
  4749 							|| (m_identity_type != AKA_IDENTITY_TYPE_IMSI_ID
       
  4750 								&& m_identity_type != AKA_IDENTITY_TYPE_PSEUDONYM_ID
       
  4751 								&& m_identity_type != AKA_IDENTITY_TYPE_RE_AUTH_ID))
       
  4752 						{
       
  4753 							// We do not have any identity of the client.
       
  4754 							set_aka_identity_response_includes_identity(aka_payload_AT_FULLAUTH_ID_REQ);
       
  4755 							set_identity_type(AKA_IDENTITY_TYPE_NONE);
       
  4756 							(void) get_identity()->reset();
       
  4757 							pseudonym_decode_failed = true;
       
  4758 						}
       
  4759 
       
  4760 						status = send_aka_identity_request_message(
       
  4761 							pseudonym_decode_failed,
       
  4762 							static_cast<u8_t>(received_aka->get_identifier()+1u));
       
  4763 						if (status == eap_status_ok)
       
  4764 						{
       
  4765 							set_last_eap_identifier(static_cast<u8_t>(received_aka->get_identifier()+1u));
       
  4766 						}
       
  4767 
       
  4768 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4769 						return EAP_STATUS_RETURN(m_am_tools, status);
       
  4770 					}
       
  4771 
       
  4772 
       
  4773 					if (l_aka_payloads->get_COUNTER()->get_payload_included() == false)
       
  4774 					{
       
  4775 						restore_saved_previous_state();
       
  4776 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4777 						return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
       
  4778 					}
       
  4779 
       
  4780 					u32_t counter = l_aka_payloads->get_COUNTER()->get_original_header()->get_reserved();
       
  4781 
       
  4782 					if (counter != reauth_counter)
       
  4783 					{
       
  4784 						restore_saved_previous_state();
       
  4785 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4786 						return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
       
  4787 					}
       
  4788 
       
  4789 					// OK, client re-authenticates corretly.
       
  4790 
       
  4791 					if (m_use_result_indication == true)
       
  4792 					{
       
  4793 						// Send EAP-Request/AKA/Notification.
       
  4794 						m_aka_notification_code = eap_aka_notification_F_set_no_P_user_authenticated;
       
  4795 
       
  4796 						status = send_aka_notification_request(
       
  4797 							m_aka_notification_code,
       
  4798 							true);
       
  4799 						if (status != eap_status_ok)
       
  4800 						{
       
  4801 							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4802 							return EAP_STATUS_RETURN(m_am_tools, status);
       
  4803 						}
       
  4804 
       
  4805 						set_state(eap_type_aka_state_waiting_for_notification_response_success);
       
  4806 
       
  4807 						EAP_TRACE_DEBUG(
       
  4808 							m_am_tools, 
       
  4809 							TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS, 
       
  4810 							(EAPL("EAP_type_AKA: %s, re-authentication OK, waits result indication\n"),
       
  4811 							 (m_is_client == true) ? "client": "server"));
       
  4812 					}
       
  4813 					else
       
  4814 					{
       
  4815 						if (m_randomly_fail_successfull_authentication == true
       
  4816 							&& random_selection() == true)
       
  4817 						{
       
  4818 							// This is for testing.
       
  4819 							m_aka_notification_code = eap_aka_notification_no_F_no_P_general_failure;
       
  4820 
       
  4821 							status = initialize_notification_message();
       
  4822 						}
       
  4823 						else
       
  4824 						{
       
  4825 							// Note the EAP-Identifier of EAP-Success must be the same as
       
  4826 							// EAP-Identifier in the last EAP-Request - EAP-Response roundtrip.
       
  4827 							status = finish_successful_authentication(
       
  4828 								receive_network_id);
       
  4829 						}
       
  4830 					}
       
  4831 					
       
  4832 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4833 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  4834 				}
       
  4835 				else
       
  4836 				{
       
  4837 					// All of these must be included
       
  4838 					// or none of these must be included.
       
  4839 					restore_saved_previous_state();
       
  4840 					return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
       
  4841 				}
       
  4842 			}
       
  4843 			else
       
  4844 			{
       
  4845 				// Not correct AKA-payloads are included.
       
  4846 				restore_saved_previous_state();
       
  4847 				EAP_TRACE_DEBUG(
       
  4848 					m_am_tools, 
       
  4849 					TRACE_FLAGS_AKA_ERROR, 
       
  4850 					(EAPL("ERROR: eap_type_aka_c::handle_reauthentication_response_message(6): ")
       
  4851 					 EAPL("Not correct AKA-payloads are included in eap_type_aka_state_variable_e %d=%s.\n"),
       
  4852 					 get_state(),
       
  4853 					 get_state_string()));
       
  4854 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4855 				return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  4856 			}
       
  4857 		}
       
  4858 		else
       
  4859 		{
       
  4860 			// Not correct AKA-payloads are included.
       
  4861 			EAP_TRACE_DEBUG(
       
  4862 				m_am_tools, 
       
  4863 				TRACE_FLAGS_AKA_ERROR, 
       
  4864 				(EAPL("ERROR: eap_type_aka_c::handle_reauthentication_response_message(6): ")
       
  4865 				 EAPL("Not correct AKA-payloads are included in eap_type_aka_state_variable_e %d=%s.\n"),
       
  4866 				 get_state(),
       
  4867 				 get_state_string()));
       
  4868 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4869 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  4870 		}
       
  4871 	}
       
  4872 	else
       
  4873 	{
       
  4874 		// Wrong message in this state.
       
  4875 		EAP_TRACE_DEBUG(
       
  4876 			m_am_tools, 
       
  4877 			TRACE_FLAGS_AKA_ERROR, 
       
  4878 			(EAPL("ERROR: eap_type_aka_c::handle_reauthentication_response_message(): ")
       
  4879 			 EAPL("Wrong message %d=%s in eap_type_aka_state_variable_e %d=%s.\n"),
       
  4880 			 received_aka->get_subtype(),
       
  4881 			 received_aka->get_subtype_string(),
       
  4882 			 get_state(),
       
  4883 			 get_state_string()));
       
  4884 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4885 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  4886 	}
       
  4887 }
       
  4888 
       
  4889 //--------------------------------------------------
       
  4890 
       
  4891 //
       
  4892 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::handle_client_error_response_message(
       
  4893 	const eap_am_network_id_c * const /* receive_network_id */,
       
  4894 	aka_header_c * const received_aka,
       
  4895 	const u32_t aka_packet_length,
       
  4896 	aka_payloads_c * const p_aka_payloads)
       
  4897 {
       
  4898 	EAP_UNREFERENCED_PARAMETER(aka_packet_length);
       
  4899 	EAP_UNREFERENCED_PARAMETER(received_aka);
       
  4900 
       
  4901 	eap_status_e status = eap_status_process_general_error;
       
  4902 
       
  4903 	// This could be first, retransmission request
       
  4904 	// or some nasty attacker to make denial of service.
       
  4905 
       
  4906 	// Checks the payloads existence.
       
  4907 	if (p_aka_payloads->check_payloads(
       
  4908 			aka_payloads_c::eap_aka_payload_status_must_not_be, // nonce_s
       
  4909 			aka_payloads_c::eap_aka_payload_status_must_not_be, // MAC
       
  4910 			aka_payloads_c::eap_aka_payload_status_must_not_be, // ENCR_DATA
       
  4911 			aka_payloads_c::eap_aka_payload_status_must_not_be, // IDENTITY
       
  4912 			aka_payloads_c::eap_aka_payload_status_must_not_be, // padding
       
  4913 			aka_payloads_c::eap_aka_payload_status_must_not_be, // n_RANDs
       
  4914 			aka_payloads_c::eap_aka_payload_status_must_not_be, // AUTN
       
  4915 			aka_payloads_c::eap_aka_payload_status_must_not_be, // AUTS
       
  4916 			aka_payloads_c::eap_aka_payload_status_must_not_be, // RES
       
  4917 			aka_payloads_c::eap_aka_payload_status_must_not_be, // PERMANENT_ID_REQ
       
  4918 			aka_payloads_c::eap_aka_payload_status_must_not_be, // FULLAUTH_ID_REQ
       
  4919 			aka_payloads_c::eap_aka_payload_status_must_not_be, // ANY_ID_REQ
       
  4920 			aka_payloads_c::eap_aka_payload_status_must_not_be, // IV
       
  4921 			aka_payloads_c::eap_aka_payload_status_must_not_be, // NEXT_PSEUDONYM
       
  4922 			aka_payloads_c::eap_aka_payload_status_must_not_be, // NEXT_REAUTH_ID
       
  4923 			aka_payloads_c::eap_aka_payload_status_must_not_be, // NOTIFICATION
       
  4924 			aka_payloads_c::eap_aka_payload_status_must_not_be, // COUNTER
       
  4925 			aka_payloads_c::eap_aka_payload_status_must_not_be, // COUNTER_TOO_SMALL
       
  4926 			aka_payloads_c::eap_aka_payload_status_must_be,     // CLIENT_ERROR_CODE
       
  4927 			aka_payloads_c::eap_aka_payload_status_must_not_be, // RESULT_IND
       
  4928 			aka_payloads_c::eap_aka_payload_status_must_not_be  // CHECKCODE
       
  4929 			) == true
       
  4930 		)
       
  4931 	{
       
  4932 		eap_status_e client_status = eap_status_process_general_error;
       
  4933 
       
  4934 		/** @{ Add some use for the Client Error Code. } */
       
  4935 		eap_aka_client_error_code_e client_error_code
       
  4936 			= static_cast<eap_aka_client_error_code_e>(p_aka_payloads->get_CLIENT_ERROR_CODE()
       
  4937 				->get_original_header()->get_reserved());
       
  4938 
       
  4939 		EAP_UNREFERENCED_PARAMETER(client_error_code);
       
  4940 		
       
  4941 		status = initialize_error_message(
       
  4942 			client_status);
       
  4943 
       
  4944 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4945 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4946 	}
       
  4947 	else
       
  4948 	{
       
  4949 		// Not correct AKA-payloads are included.
       
  4950 		EAP_TRACE_DEBUG(
       
  4951 			m_am_tools, 
       
  4952 			TRACE_FLAGS_AKA_ERROR, 
       
  4953 			(EAPL("ERROR: eap_type_aka_c::handle_client_error_response_message(): ")
       
  4954 			 EAPL("Not correct AKA-payloads are included in eap_type_aka_state_variable_e %d=%s.\n"),
       
  4955 			 get_state(),
       
  4956 			 get_state_string()));
       
  4957 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4958 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  4959 	}
       
  4960 }
       
  4961 
       
  4962 //--------------------------------------------------
       
  4963 
       
  4964 //
       
  4965 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::check_NAI(
       
  4966 	const u8_t * const identity,
       
  4967 	const u32_t identity_length,
       
  4968 	const u8_t * const at_character)
       
  4969 {
       
  4970 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4971 
       
  4972 	bool includes_at = false;
       
  4973 	bool includes_dot = false;
       
  4974 	u32_t username_length = 0u;
       
  4975 	u32_t realm_length = 0u;
       
  4976 
       
  4977 	for (u32_t ind = 0; ind < identity_length; ind++)
       
  4978 	{
       
  4979 		const u8_t character = identity[ind];
       
  4980 
       
  4981 		if (includes_at == false)
       
  4982 		{
       
  4983 			if (character != AKA_NAI_AT_BYTE)
       
  4984 			{
       
  4985 				++username_length;
       
  4986 			}
       
  4987 		}
       
  4988 		else
       
  4989 		{
       
  4990 			++realm_length;
       
  4991 		}
       
  4992 
       
  4993 
       
  4994 		if ('0' <= character && character <= '9')
       
  4995 		{
       
  4996 			// OK.
       
  4997 		}
       
  4998 		else if ('a' <= character && character <= 'z')
       
  4999 		{
       
  5000 			// OK.
       
  5001 		}
       
  5002 		else if ('A' <= character && character <= 'Z')
       
  5003 		{
       
  5004 			// OK.
       
  5005 		}
       
  5006 		else if (character == AKA_NAI_AT_BYTE)
       
  5007 		{
       
  5008 			if (includes_at == false)
       
  5009 			{
       
  5010 				includes_at = true;
       
  5011 			}
       
  5012 			else
       
  5013 			{
       
  5014 				// Second at ('@').
       
  5015 				EAP_TRACE_DATA_DEBUG(
       
  5016 					m_am_tools, 
       
  5017 					TRACE_FLAGS_DEFAULT, 
       
  5018 					(EAPL("Illegal NAI, includes second at \'@\' character."),
       
  5019 					identity,
       
  5020 					identity_length));
       
  5021 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5022 				return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_nai);
       
  5023 			}
       
  5024 		}
       
  5025 		else if (character == '.')
       
  5026 		{
       
  5027 			if (includes_at == true)
       
  5028 			{
       
  5029 				// OK.
       
  5030 				includes_dot = true;
       
  5031 			}
       
  5032 			else
       
  5033 			{
       
  5034 				// dot ('.') within username
       
  5035 				EAP_TRACE_DATA_DEBUG(
       
  5036 					m_am_tools, 
       
  5037 					TRACE_FLAGS_DEFAULT, 
       
  5038 					(EAPL("Illegal NAI, dot \'.\' within username."),
       
  5039 					identity,
       
  5040 					identity_length));
       
  5041 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5042 				return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_nai);
       
  5043 			}
       
  5044 		}
       
  5045 		else if (character == '<'
       
  5046 			|| character == '>'
       
  5047 			|| character == '('
       
  5048 			|| character == ')'
       
  5049 			|| character == '['
       
  5050 			|| character == ']'
       
  5051 			|| character == '\\'
       
  5052 			|| character == '.'
       
  5053 			|| character == ','
       
  5054 			|| character == ';'
       
  5055 			|| character == ':'
       
  5056 			|| character == AKA_NAI_AT_BYTE
       
  5057 			|| character == ' ' // space
       
  5058 			|| character <= 0x1f // Ctrl
       
  5059 			|| character >= 0x7f) // extented characters
       
  5060 		{
       
  5061 			// Illegal character.
       
  5062 			EAP_TRACE_DEBUG(
       
  5063 				m_am_tools, 
       
  5064 				TRACE_FLAGS_AKA_ERROR, 
       
  5065 				(EAPL("ERROR: Illegal NAI, includes illegal character 0x%02x=%c.\n"),
       
  5066 				 character,
       
  5067 				 character));
       
  5068 			EAP_TRACE_DATA_DEBUG(
       
  5069 				m_am_tools, 
       
  5070 				TRACE_FLAGS_DEFAULT, 
       
  5071 				(EAPL("Illegal NAI, includes illegal character."),
       
  5072 				 identity,
       
  5073 				 identity_length));
       
  5074 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5075 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_nai);
       
  5076 		}
       
  5077 		else
       
  5078 		{
       
  5079 			// All other ascii values are OK.
       
  5080 		}
       
  5081 	}
       
  5082 
       
  5083 	// Note the username could be zero length.
       
  5084 	if ((realm_length == 1u && includes_at == true) // one at ('@') is illegal.
       
  5085 		|| (realm_length == 2u && includes_at == true && includes_dot == true)) //  one at ('@') and one dot is illegal.
       
  5086 	{
       
  5087 		EAP_TRACE_DATA_DEBUG(
       
  5088 			m_am_tools, 
       
  5089 			TRACE_FLAGS_DEFAULT, (EAPL("Illegal NAI."),
       
  5090 			identity,
       
  5091 			identity_length));
       
  5092 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5093 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_nai);
       
  5094 	}
       
  5095 
       
  5096 	if (m_check_nai_realm == true)
       
  5097 	{
       
  5098 		if (at_character == 0
       
  5099 			&& realm_length == 0
       
  5100 			&& get_nai_realm()->get_data_length() == 0)
       
  5101 		{
       
  5102 			// OK, no realm.
       
  5103 		}
       
  5104 		else if (at_character == 0
       
  5105 			|| realm_length != get_nai_realm()->get_data_length()
       
  5106 			|| m_am_tools->memcmp(
       
  5107 				at_character+1u,
       
  5108 				get_nai_realm()->get_data(get_nai_realm()->get_data_length()),
       
  5109 				get_nai_realm()->get_data_length()) != 0)
       
  5110 		{
       
  5111 			EAP_TRACE_DATA_DEBUG(
       
  5112 				m_am_tools, 
       
  5113 				TRACE_FLAGS_DEFAULT, 
       
  5114 				(EAPL("Illegal NAI, realm unknown."),
       
  5115 				identity,
       
  5116 				identity_length));
       
  5117 			EAP_TRACE_DATA_DEBUG(
       
  5118 				m_am_tools, 
       
  5119 				TRACE_FLAGS_DEFAULT, 
       
  5120 				(EAPL("NAI should be"),
       
  5121 				get_nai_realm()->get_data(get_nai_realm()->get_data_length()),
       
  5122 				get_nai_realm()->get_data_length()));
       
  5123 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5124 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_nai);
       
  5125 		}
       
  5126 	}
       
  5127 
       
  5128 
       
  5129 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5130 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  5131 }
       
  5132 
       
  5133 //--------------------------------------------------
       
  5134 
       
  5135 //
       
  5136 EAP_FUNC_EXPORT eap_status_e eap_type_aka_c::parse_identity(
       
  5137 	const u8_t * const identity,
       
  5138 	const u32_t identity_length)
       
  5139 {
       
  5140 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5141 
       
  5142 	eap_status_e status(eap_status_process_general_error);
       
  5143 
       
  5144 	if (identity_length < 1u)
       
  5145 	{
       
  5146 		status = get_identity()->init(0ul);
       
  5147 		if (status != eap_status_ok)
       
  5148 		{
       
  5149 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5150 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  5151 		}
       
  5152 
       
  5153 		status = get_NAI()->init(0ul);
       
  5154 		if (status != eap_status_ok)
       
  5155 		{
       
  5156 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5157 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  5158 		}
       
  5159 
       
  5160 		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  5161 	}
       
  5162 
       
  5163 	const u8_t *at_character = reinterpret_cast<const u8_t *>(m_am_tools->memchr(
       
  5164 		identity,
       
  5165 		AKA_AT_CHARACTER[0],
       
  5166 		identity_length));
       
  5167 
       
  5168 	// NOTE, at_character could be NULL. Realm is optional.
       
  5169 
       
  5170 	status = check_NAI(identity, identity_length, at_character);
       
  5171 	if (status != eap_status_ok)
       
  5172 	{
       
  5173 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5174 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5175 	}
       
  5176 
       
  5177 	status = eap_status_process_general_error;
       
  5178 
       
  5179 	u32_t username_length = identity_length;
       
  5180 	if (at_character != 0)
       
  5181 	{
       
  5182 		username_length = static_cast<u32_t>(at_character-identity);
       
  5183 	}
       
  5184 
       
  5185 	status = get_identity()->set_copy_of_buffer(
       
  5186 		identity, // Note we do store whole IMSI or pseudonym including possible prefix.
       
  5187 		username_length);
       
  5188 	if (status != eap_status_ok)
       
  5189 	{
       
  5190 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5191 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5192 	}
       
  5193 
       
  5194 	status = get_NAI()->set_copy_of_buffer(identity, identity_length);
       
  5195 	if (status != eap_status_ok)
       
  5196 	{
       
  5197 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5198 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5199 	}
       
  5200 
       
  5201 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5202 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5203 }
       
  5204 
       
  5205 //--------------------------------------------------
       
  5206 
       
  5207 
       
  5208 
       
  5209 // End.