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