eapol/eapol_framework/eapol_common/type/tls_peap/eap/src/eap_type_tls_peap.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 119 
       
    23 	#undef EAP_FILE_NUMBER_DATE 
       
    24 	#define EAP_FILE_NUMBER_DATE 1127594498 
       
    25 #endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
       
    26 
       
    27 
       
    28 
       
    29 #include "eap_am_memory.h"
       
    30 #include "eap_type_tls_peap_types.h"
       
    31 #include "eap_type_tls_peap.h"
       
    32 #include "eap_type_tls_peap_header.h"
       
    33 #include "eap_type_tls_peap_state_notification.h"
       
    34 #include "eap_am_type_tls_peap.h"
       
    35 #include "eap_state_notification.h"
       
    36 #include "tls_record_header.h"
       
    37 #include "tls_base_record.h"
       
    38 #include "eap_config.h"
       
    39 #include "eap_header_string.h"
       
    40 #include "eap_automatic_variable.h"
       
    41 
       
    42 //--------------------------------------------------
       
    43 
       
    44 //
       
    45 EAP_FUNC_EXPORT eap_type_tls_peap_c::~eap_type_tls_peap_c()
       
    46 {
       
    47 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
    48 
       
    49 	EAP_TRACE_DEBUG(
       
    50 		m_am_tools,
       
    51 		TRACE_FLAGS_DEFAULT,
       
    52 		(EAPL("this = 0x%08x => 0x%08x, %s: function: eap_type_tls_peap_c::~eap_type_tls_peap_c():,")
       
    53 		 EAPL(" m_am_type_tls_peap = 0x%08x (validity %d).\n"),
       
    54 		 this,
       
    55 		 dynamic_cast<abs_eap_base_timer_c *>(this),
       
    56 		 (m_is_client == true ? "client": "server"),
       
    57 		 m_am_type_tls_peap,
       
    58 		 m_am_type_tls_peap->get_is_valid()));
       
    59 
       
    60 	EAP_ASSERT(m_shutdown_was_called == true);
       
    61 
       
    62 	if (m_free_tls_record == true)
       
    63 	{
       
    64 		delete m_tls_record;
       
    65 		m_tls_record = 0;
       
    66 	}
       
    67 
       
    68 	if (m_free_am_type_tls_peap == true)
       
    69 	{
       
    70 		delete m_am_type_tls_peap;
       
    71 		m_am_type_tls_peap = 0;
       
    72 	}
       
    73 
       
    74 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
    75 }
       
    76 
       
    77 //--------------------------------------------------
       
    78 
       
    79 //
       
    80 EAP_FUNC_EXPORT eap_type_tls_peap_c::eap_type_tls_peap_c(
       
    81 	abs_eap_am_tools_c * const tools, ///< This is pointer to the tools AM of current platform.
       
    82 	abs_eap_base_type_c * const partner, ///< This is back pointer to object which created this object.
       
    83 	eap_am_type_tls_peap_c * const am_type_tls_peap, ///< This is pointer to adaptation module of TLS/PEAP EAP type.
       
    84 	const bool free_am_type_tls_peap,
       
    85 	tls_base_record_c * const tls_record, /// This is pointer to TLS implementation.
       
    86 	const bool free_tls_record,
       
    87 	const bool is_client_when_true, ///< Indicates whether this is client (true) or server (false).
       
    88 	const eap_type_value_e current_eap_type, ///< This the current EAP-type (TLS or PEAP).
       
    89 	const eap_am_network_id_c * const receive_network_id)
       
    90 	: eap_base_type_c(tools, partner)
       
    91 	  , m_am_tools(tools)
       
    92 	  , m_am_type_tls_peap(am_type_tls_peap)
       
    93 	  , m_tls_record(tls_record)
       
    94 	  , m_nai_realm(tools)
       
    95 	  , m_NAI(tools)
       
    96 	  , m_current_identity(tools)
       
    97 	  , m_send_network_id(tools)
       
    98 	  , m_tls_peap_header_offset(0u)
       
    99 	  , m_MTU(0u)
       
   100 	  , m_trailer_length(0u)
       
   101 	  , m_state(eap_type_tls_peap_state_waiting_for_identity_request)
       
   102 	  , m_saved_previous_state(eap_type_tls_peap_state_waiting_for_identity_request)
       
   103 	  , m_reassembly_state(eap_type_tls_peap_reassembly_state_wait_first_message)
       
   104 	  , m_saved_previous_reassembly_state(eap_type_tls_peap_reassembly_state_wait_first_message)
       
   105 	  , m_tls_message_send_offset(0ul)
       
   106 	  , m_tls_message_buffer(tools)
       
   107 	  , m_master_session_key(tools, current_eap_type)
       
   108 	  , m_accepted_PEAP_versions(tools)
       
   109 	  , m_current_eap_type(current_eap_type)
       
   110 	  , m_configured_peap_version(peap_version_none)
       
   111 	  , m_current_peap_version(peap_version_none)
       
   112 	  , m_first_fragment_eap_identifier(0ul)
       
   113 	  , m_tls_session_type(tls_session_type_none)
       
   114 	  , m_tunneled_eap_type_active(false)
       
   115 	  , m_tunneled_eap_type_authentication_state(eap_state_none)
       
   116 	  , m_free_am_type_tls_peap(free_am_type_tls_peap)
       
   117 	  , m_free_tls_record(free_tls_record)
       
   118 	  , m_is_valid(false)
       
   119 	  , m_is_client(is_client_when_true)
       
   120 	  , m_wait_eap_success_packet(true)
       
   121 	  , m_check_identifier_of_eap_identity_response(false)
       
   122 	  , m_tls_peap_test_version(false)
       
   123 	  , m_check_nai_realm(false)
       
   124 #if defined(USE_EAP_TLS_IDENTITY_PRIVACY)
       
   125 	  , m_tls_use_identity_privacy(false)
       
   126 #endif //#if defined(USE_EAP_TLS_IDENTITY_PRIVACY)
       
   127 	  , m_failure_message_received(false)
       
   128 	  , m_authentication_finished_successfully(false)
       
   129 	  , m_last_eap_identifier(0ul)
       
   130 	  , m_shutdown_was_called(false)
       
   131 	  , m_use_tppd_tls_peap(true)
       
   132 	  , m_use_tppd_peapv1_acknowledge_hack(true)
       
   133 	  , m_includes_tls_handshake_message(false)
       
   134 	  , m_use_eap_expanded_type(false)
       
   135 {
       
   136 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   137 
       
   138 	EAP_TRACE_DEBUG(
       
   139 		m_am_tools,
       
   140 		TRACE_FLAGS_DEFAULT,
       
   141 		(EAPL("this = 0x%08x => 0x%08x, %s: function: eap_type_tls_peap_c::eap_type_tls_peap_c(): compiled %s %s\n"),
       
   142 		 this,
       
   143 		 dynamic_cast<abs_eap_base_timer_c *>(this),
       
   144 		 (m_is_client == true ? "client": "server"),
       
   145 		 __DATE__,
       
   146 		 __TIME__));
       
   147 	
       
   148 	if (receive_network_id == 0
       
   149 		|| receive_network_id->get_is_valid_data() == false)
       
   150 	{
       
   151 		// No need to delete anything here because it is done in destructor.
       
   152 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   153 		return;
       
   154 	}
       
   155 
       
   156 	if (tls_record == 0)
       
   157 	{
       
   158 		// No need to delete anything here because it is done in destructor.
       
   159 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   160 		return;
       
   161 	}
       
   162 	m_tls_record->set_type_partner(this);
       
   163 
       
   164 	if (m_am_type_tls_peap == 0)
       
   165 	{
       
   166 		// Something wrong with AM.
       
   167 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   168 		return;
       
   169 	}
       
   170 	m_am_type_tls_peap->set_am_partner(this);
       
   171 
       
   172 
       
   173 	// Here we swap the addresses.
       
   174 	eap_am_network_id_c send_network_id(
       
   175 		m_am_tools,
       
   176 		receive_network_id->get_destination_id(),
       
   177 		receive_network_id->get_source_id(),
       
   178 		receive_network_id->get_type());
       
   179 
       
   180 	eap_status_e status = get_send_network_id()->set_copy_of_network_id(
       
   181 		&send_network_id);
       
   182 	if (status != eap_status_ok)
       
   183 	{
       
   184 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   185 		return;
       
   186 	}
       
   187 
       
   188 	if (m_is_client == false)
       
   189 	{
       
   190 		// Server waits EAP-Response/Identity.
       
   191 		m_state = eap_type_tls_peap_state_waiting_for_identity_response;
       
   192 		m_saved_previous_state
       
   193 			= eap_type_tls_peap_state_waiting_for_identity_response;
       
   194 	}
       
   195 
       
   196 	set_is_valid();
       
   197 
       
   198 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   199 }
       
   200 
       
   201 //--------------------------------------------------
       
   202 
       
   203 //
       
   204 EAP_FUNC_EXPORT void eap_type_tls_peap_c::save_current_state()
       
   205 {
       
   206 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   207 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   208 	m_saved_previous_state = m_state;
       
   209 }
       
   210 
       
   211 //--------------------------------------------------
       
   212 
       
   213 //
       
   214 EAP_FUNC_EXPORT void eap_type_tls_peap_c::restore_saved_previous_state()
       
   215 {
       
   216 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   217 	set_state(m_saved_previous_state);
       
   218 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   219 }
       
   220 
       
   221 //--------------------------------------------------
       
   222 
       
   223 //
       
   224 EAP_FUNC_EXPORT void eap_type_tls_peap_c::set_state(
       
   225 	const eap_type_tls_peap_state_variable_e state)
       
   226 {
       
   227 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   228 
       
   229 	eap_type_tls_peap_state_variable_e previous_state = m_state;
       
   230 
       
   231 	if (m_state != eap_type_tls_peap_state_failure)
       
   232 	{
       
   233 		m_state = state;
       
   234 	}
       
   235 
       
   236 	EAP_TRACE_DEBUG(
       
   237 		m_am_tools,
       
   238 		TRACE_FLAGS_DEFAULT,
       
   239 		(EAPL("this = 0x%08x, %s, %s: eap_type_tls_peap_c::set_state(): ")
       
   240 		 EAPL(" Previous state %d=%s, new state %d=%s.\n"),
       
   241 		 this,
       
   242 		 (m_is_client == true ? "client": "server"),
       
   243 		 (get_type_partner()->get_is_tunneled_eap() == true ? "tunneled" : "outer most"),
       
   244 		 previous_state,
       
   245 		 get_state_string(previous_state),
       
   246 		 m_state,
       
   247 		 get_state_string(m_state)));
       
   248 
       
   249 	eap_type_tls_peap_state_notification_c notification(
       
   250 		m_am_tools,
       
   251 		get_send_network_id(),
       
   252 		m_is_client,
       
   253 		eap_state_notification_eap,
       
   254 		eap_protocol_layer_eap_type,
       
   255 		m_current_eap_type,
       
   256 		previous_state,
       
   257 		state,
       
   258 		m_last_eap_identifier,
       
   259 		false);
       
   260 	get_type_partner()->state_notification(&notification);
       
   261 
       
   262 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   263 }
       
   264 
       
   265 //--------------------------------------------------
       
   266 
       
   267 //
       
   268 EAP_FUNC_EXPORT eap_type_tls_peap_reassembly_state_e eap_type_tls_peap_c::get_reassembly_state() const
       
   269 {
       
   270 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   271 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   272 	return m_reassembly_state;
       
   273 }
       
   274 
       
   275 //--------------------------------------------------
       
   276 
       
   277 //
       
   278 EAP_FUNC_EXPORT void eap_type_tls_peap_c::set_reassembly_state(
       
   279 	const eap_type_tls_peap_reassembly_state_e state)
       
   280 {
       
   281 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   282 
       
   283 	m_reassembly_state = state;
       
   284 
       
   285 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   286 }
       
   287 
       
   288 //--------------------------------------------------
       
   289 
       
   290 //
       
   291 EAP_FUNC_EXPORT void eap_type_tls_peap_c::save_current_reassembly_state()
       
   292 {
       
   293 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   294 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   295 	m_saved_previous_reassembly_state = m_reassembly_state;
       
   296 }
       
   297 
       
   298 //--------------------------------------------------
       
   299 
       
   300 //
       
   301 EAP_FUNC_EXPORT void eap_type_tls_peap_c::restore_saved_reassembly_state()
       
   302 {
       
   303 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   304 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   305 	m_reassembly_state = m_saved_previous_reassembly_state;
       
   306 }
       
   307 
       
   308 //--------------------------------------------------
       
   309 
       
   310 //
       
   311 EAP_FUNC_EXPORT eap_am_network_id_c * eap_type_tls_peap_c::get_send_network_id()
       
   312 {
       
   313 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   314 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   315 	return &m_send_network_id;
       
   316 }
       
   317 
       
   318 //--------------------------------------------------
       
   319 
       
   320 //
       
   321 EAP_FUNC_EXPORT void eap_type_tls_peap_c::set_last_eap_identifier(const u8_t last_eap_identifier)
       
   322 {
       
   323 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   324 
       
   325 	m_last_eap_identifier = last_eap_identifier;
       
   326 
       
   327 	EAP_TRACE_DEBUG(
       
   328 		m_am_tools,
       
   329 		TRACE_FLAGS_DEFAULT,
       
   330 		(EAPL("this = 0x%08x, %s, %s, eap_type_tls_peap_c::set_last_eap_identifier():")
       
   331 		 EAPL(" saved EAP-identifier %d, state %s\n"),
       
   332 		 this,
       
   333 		 (m_is_client == true ? "client": "server"),
       
   334 		 (get_type_partner()->get_is_tunneled_eap() == true ? "tunneled" : "outer most"),
       
   335 		 m_last_eap_identifier,
       
   336 		 get_state_string()));
       
   337 
       
   338 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   339 }
       
   340 
       
   341 //--------------------------------------------------
       
   342 
       
   343 //
       
   344 EAP_FUNC_EXPORT u8_t eap_type_tls_peap_c::get_last_eap_identifier() const
       
   345 {
       
   346 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   347 
       
   348 	EAP_TRACE_DEBUG(
       
   349 		m_am_tools,
       
   350 		TRACE_FLAGS_DEFAULT,
       
   351 		(EAPL("this = 0x%08x, eap_type_tls_peap_c::get_last_eap_identifier():")
       
   352 		 EAPL("%s, saved EAP-identifier %d, state %s\n"),
       
   353 		 this,
       
   354 		 (m_is_client == true ? "client": "server"),
       
   355 		 m_last_eap_identifier,
       
   356 		 get_state_string()));
       
   357 
       
   358 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   359 	return m_last_eap_identifier;
       
   360 }
       
   361 
       
   362 //--------------------------------------------------
       
   363 
       
   364 //
       
   365 EAP_FUNC_EXPORT eap_const_string eap_type_tls_peap_c::get_state_string(
       
   366 	eap_type_tls_peap_state_variable_e state)
       
   367 {
       
   368 
       
   369 #if defined(USE_EAP_TRACE_STRINGS)
       
   370 	EAP_IF_RETURN_STRING(state, eap_type_tls_peap_state_waiting_for_identity_request)
       
   371 	else EAP_IF_RETURN_STRING(state, eap_type_tls_peap_state_pending_identity_query)
       
   372 	else EAP_IF_RETURN_STRING(state, eap_type_tls_peap_state_waiting_for_tls_start)
       
   373 	else EAP_IF_RETURN_STRING(state, eap_type_tls_peap_state_process_tls_start)
       
   374 	else EAP_IF_RETURN_STRING(state, eap_type_tls_peap_state_waiting_for_request)
       
   375 	else EAP_IF_RETURN_STRING(state, eap_type_tls_peap_state_waiting_for_success)
       
   376 	else EAP_IF_RETURN_STRING(state, eap_type_tls_peap_state_tppd_peapv1_waits_eap_success_or_tunneled_packet)
       
   377 	else EAP_IF_RETURN_STRING(state, eap_type_tls_peap_state_waiting_for_identity_response)
       
   378 	else EAP_IF_RETURN_STRING(state, eap_type_tls_peap_state_waiting_for_first_response)
       
   379 	else EAP_IF_RETURN_STRING(state, eap_type_tls_peap_state_waiting_for_response)
       
   380 	else EAP_IF_RETURN_STRING(state, eap_type_tls_peap_state_waiting_for_empty_response)
       
   381 	else EAP_IF_RETURN_STRING(state, eap_type_tls_peap_state_process_tls_message)
       
   382 	else EAP_IF_RETURN_STRING(state, eap_type_tls_peap_state_success)
       
   383 	else EAP_IF_RETURN_STRING(state, eap_type_tls_peap_state_failure)
       
   384 	else
       
   385 #else
       
   386 EAP_UNREFERENCED_PARAMETER(state);	
       
   387 #endif // #if defined(USE_EAP_TRACE_STRINGS)
       
   388 	{
       
   389 		return EAPL("Unknown EAP-TLS/PEAP state");
       
   390 	}
       
   391 }
       
   392 
       
   393 //--------------------------------------------------
       
   394 
       
   395 //
       
   396 EAP_FUNC_EXPORT eap_const_string eap_type_tls_peap_c::get_reassembly_state_string(
       
   397 	eap_type_tls_peap_reassembly_state_e state)
       
   398 {
       
   399 
       
   400 #if defined(USE_EAP_TRACE_STRINGS)
       
   401 	EAP_IF_RETURN_STRING(state, eap_type_tls_peap_reassembly_state_none)
       
   402 	else EAP_IF_RETURN_STRING(state, eap_type_tls_peap_reassembly_state_wait_first_message)
       
   403 	else EAP_IF_RETURN_STRING(state, eap_type_tls_peap_reassembly_state_wait_last_fragment)
       
   404 	else EAP_IF_RETURN_STRING(state, eap_type_tls_peap_reassembly_state_message_reassembled)
       
   405 	else
       
   406 #else
       
   407 EAP_UNREFERENCED_PARAMETER(state);		
       
   408 #endif // #if defined(USE_EAP_TRACE_STRINGS)
       
   409 	{
       
   410 		return EAPL("Unknown TLS_PEAP reassembly state");
       
   411 	}
       
   412 }
       
   413 
       
   414 //--------------------------------------------------
       
   415 
       
   416 EAP_FUNC_EXPORT eap_const_string eap_type_tls_peap_c::get_state_string() const
       
   417 {
       
   418 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   419 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   420 	return get_state_string(m_state);
       
   421 }
       
   422 
       
   423 //--------------------------------------------------
       
   424 
       
   425 EAP_FUNC_EXPORT eap_const_string eap_type_tls_peap_c::get_reassembly_state_string() const
       
   426 {
       
   427 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   428 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   429 	return get_reassembly_state_string(m_reassembly_state);
       
   430 }
       
   431 
       
   432 //--------------------------------------------------
       
   433 
       
   434 EAP_FUNC_EXPORT eap_const_string eap_type_tls_peap_c::get_saved_previous_state_string() const
       
   435 {
       
   436 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   437 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   438 	return get_state_string(m_saved_previous_state);
       
   439 }
       
   440 
       
   441 //--------------------------------------------------
       
   442 
       
   443 EAP_FUNC_EXPORT void eap_type_tls_peap_c::set_failure_message_received()
       
   444 {
       
   445 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   446 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   447 	m_failure_message_received = true;
       
   448 }
       
   449 
       
   450 //--------------------------------------------------
       
   451 
       
   452 EAP_FUNC_EXPORT void eap_type_tls_peap_c::unset_failure_message_received()
       
   453 {
       
   454 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   455 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   456 	m_failure_message_received = false;
       
   457 }
       
   458 
       
   459 //--------------------------------------------------
       
   460 
       
   461 EAP_FUNC_EXPORT bool eap_type_tls_peap_c::get_failure_message_received() const
       
   462 {
       
   463 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   464 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   465 	return m_failure_message_received;
       
   466 }
       
   467 
       
   468 //--------------------------------------------------
       
   469 
       
   470 EAP_FUNC_EXPORT eap_type_tls_peap_state_variable_e eap_type_tls_peap_c::get_state() const
       
   471 {
       
   472 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   473 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   474 	return m_state;
       
   475 }
       
   476 
       
   477 //--------------------------------------------------
       
   478 
       
   479 //
       
   480 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::generate_nai(
       
   481 	eap_variable_data_c * const /*new_nai*/, ///< This is the new generated NAI.
       
   482 	const eap_variable_data_c * const /*domain*/, ///< This is the domain part of the NAI.
       
   483 	const eap_variable_data_c * const /*identity*/ ///< This is identity.
       
   484 	)
       
   485 {
       
   486 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   487 
       
   488 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   489 	return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
       
   490 }
       
   491 
       
   492 //--------------------------------------------------
       
   493 
       
   494 //
       
   495 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::handle_tls_peap_packet(
       
   496 	const eap_am_network_id_c * const /*receive_network_id*/, ///< This is the network identity of the received EAP packet.
       
   497 	eap_tls_peap_header_c * const /*tls_peap*/, ///< This is pointer to EAP header including EAP-TLS/PEAP fields.
       
   498 	const u32_t /*tls_peap_length*/ ///< This is length of received TLS/PEAP EAP packet.
       
   499 	)
       
   500 {
       
   501 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   502 
       
   503 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   504 	return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
       
   505 }
       
   506 
       
   507 //--------------------------------------------------
       
   508 
       
   509 //
       
   510 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::analyse_tls_peap_packet(
       
   511 	const eap_am_network_id_c * const /*receive_network_id*/, ///< This is the network identity of the received EAP packet.
       
   512 	eap_tls_peap_header_c * const /*received_tls_peap*/, ///< This is pointer to EAP header including EAP-TLS/PEAP fields.
       
   513 	const u32_t /*tls_peap_packet_length*/ ///< This is length of received TLS/PEAP EAP packet.
       
   514 	)
       
   515 {
       
   516 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   517 
       
   518 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   519 	return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
       
   520 }
       
   521 
       
   522 //--------------------------------------------------
       
   523 
       
   524 //
       
   525 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::parse_tls_peap_payload(
       
   526 	u32_t * const /*buffer_length*/ ///< This is the length of the buffer. This must match with the length of all payloads.
       
   527 	)
       
   528 {
       
   529 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   530 
       
   531 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   532 	return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
       
   533 }
       
   534 
       
   535 //--------------------------------------------------
       
   536 
       
   537 //
       
   538 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::check_version_list(
       
   539 	const u16_t /*version_list_length*/,
       
   540 	u8_t * /*version_list*/)
       
   541 {
       
   542 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   543 
       
   544 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   545 	return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
       
   546 }
       
   547 
       
   548 //--------------------------------------------------
       
   549 
       
   550 //
       
   551 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::parse_tls_peap_packet(
       
   552 	eap_tls_peap_header_c * const /*tls_peap*/, ///< This is pointer to EAP header including EAP-TLS/PEAP fields.
       
   553 	const u32_t /*tls_peap_packet_length*/ ///< This is length of received TLS/PEAP EAP packet.
       
   554 	)
       
   555 {
       
   556 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   557 
       
   558 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   559 	return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
       
   560 }
       
   561 
       
   562 //--------------------------------------------------
       
   563 
       
   564 //
       
   565 EAP_FUNC_EXPORT eap_variable_data_c * eap_type_tls_peap_c::get_nai_realm()
       
   566 {
       
   567 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   568 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   569 	return &m_nai_realm;
       
   570 }
       
   571 
       
   572 //--------------------------------------------------
       
   573 
       
   574 //
       
   575 EAP_FUNC_EXPORT eap_variable_data_c * eap_type_tls_peap_c::get_NAI()
       
   576 {
       
   577 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   578 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   579 	return &m_NAI;
       
   580 }
       
   581 
       
   582 //--------------------------------------------------
       
   583 
       
   584 //
       
   585 EAP_FUNC_EXPORT void eap_type_tls_peap_c::update_buffer_indexes(
       
   586 	const u32_t maximum_buffer_size,
       
   587 	const u32_t payload_size,
       
   588 	u32_t * const buffer_offset,
       
   589 	u32_t * const buffer_free)
       
   590 {
       
   591 	EAP_UNREFERENCED_PARAMETER(maximum_buffer_size);
       
   592 
       
   593 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   594 
       
   595 	EAP_ASSERT_ALWAYS(*buffer_offset + *buffer_free <= maximum_buffer_size-m_trailer_length);
       
   596 	EAP_ASSERT_ALWAYS(*buffer_free >= payload_size);
       
   597 	EAP_ASSERT_ALWAYS(m_tls_peap_header_offset+m_MTU == *buffer_offset + *buffer_free);
       
   598 
       
   599 	*buffer_free -= payload_size;
       
   600 	*buffer_offset += payload_size;
       
   601 
       
   602 	EAP_ASSERT_ALWAYS(*buffer_offset + *buffer_free <= maximum_buffer_size-m_trailer_length);
       
   603 	EAP_ASSERT_ALWAYS(*buffer_offset <= m_tls_peap_header_offset+m_MTU);
       
   604 
       
   605 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   606 }
       
   607 
       
   608 //--------------------------------------------------
       
   609 
       
   610 //
       
   611 EAP_FUNC_EXPORT void eap_type_tls_peap_c::update_payload_indexes(
       
   612 	const u32_t /*maximum_buffer_size*/,
       
   613 	const u32_t /*eap_header_size*/,
       
   614 	const u32_t /*payload_size*/,
       
   615 	u32_t * const /*data_offset*/,
       
   616 	u32_t * const /*data_free*/,
       
   617 	u32_t * const /*buffer_offset*/,
       
   618 	u32_t * const /*buffer_free*/)
       
   619 {
       
   620 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   621 
       
   622 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   623 }
       
   624 
       
   625 //--------------------------------------------------
       
   626 
       
   627 //
       
   628 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::parse_identity(
       
   629 	const u8_t * const identity, ///< This is pointer to received EAP-Identity buffer.
       
   630 	const u32_t identity_length ///< This is length of received EAP-Identity buffer.
       
   631 	)
       
   632 {
       
   633 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   634 
       
   635 	if (identity_length < 1u)
       
   636 	{
       
   637 		// Anonymous identity.
       
   638 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   639 		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   640 	}
       
   641 
       
   642 	const u8_t *at_character = reinterpret_cast<const u8_t *>(
       
   643 		m_am_tools->memchr(
       
   644 			identity,
       
   645 			EAP_TLS_PEAP_AT_CHARACTER,
       
   646 			identity_length));
       
   647 	if (at_character == 0)
       
   648 	{
       
   649 		// No realm.
       
   650 		// This is allowed.
       
   651 	}
       
   652 
       
   653 	eap_status_e status = check_NAI(identity, identity_length, at_character);
       
   654 	if (status != eap_status_ok)
       
   655 	{
       
   656 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   657 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   658 	}
       
   659 
       
   660 	status = eap_status_process_general_error;
       
   661 
       
   662 	u32_t username_length = identity_length;
       
   663 	if (at_character != 0)
       
   664 	{
       
   665 		username_length = static_cast<u32_t>(at_character-identity);
       
   666 	}
       
   667 
       
   668 	status = m_current_identity.set_copy_of_buffer(
       
   669 		identity,
       
   670 		username_length);
       
   671 	if (status != eap_status_ok)
       
   672 	{
       
   673 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   674 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   675 	}
       
   676 
       
   677 	status = get_NAI()->set_copy_of_buffer(identity, identity_length);
       
   678 	if (status != eap_status_ok)
       
   679 	{
       
   680 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   681 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   682 	}
       
   683 
       
   684 	EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("TLS/PEAP received EAP-identity NAI"),
       
   685 		get_NAI()->get_data(get_NAI()->get_data_length()),
       
   686 		get_NAI()->get_data_length()));
       
   687 
       
   688 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   689 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   690 }
       
   691 
       
   692 //--------------------------------------------------
       
   693 
       
   694 //
       
   695 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::handle_identity_response_message(
       
   696 	eap_header_rd_c * const /*eap_header*/, ///< This is the received EAP-Identity packet, pointer points to the header.
       
   697 	const u32_t /*tls_peap_packet_length*/ ///< This is length of received TLS/PEAP EAP packet.
       
   698 	)
       
   699 {
       
   700 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   701 
       
   702 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   703 	return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
       
   704 }
       
   705 
       
   706 //--------------------------------------------------
       
   707 
       
   708 //
       
   709 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::tls_peap_packet_send(
       
   710 	eap_buf_chain_wr_c * const sent_packet,
       
   711 	const u32_t /*header_offset*/,
       
   712 	const u32_t /*data_length*/,
       
   713 	const u32_t /*buffer_length*/,
       
   714 	const bool includes_tls_handshake_message)
       
   715 {
       
   716 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   717 
       
   718 	EAP_TRACE_DEBUG(
       
   719 		m_am_tools,
       
   720 		TRACE_FLAGS_DEFAULT, (EAPL("\n")));
       
   721 	EAP_TRACE_DEBUG(
       
   722 		m_am_tools,
       
   723 		TRACE_FLAGS_DEFAULT,
       
   724 		(EAPL("EAP_type_TLS_PEAP: %s: function: eap_type_tls_peap_c::tls_peap_packet_send()\n"),
       
   725 		(m_is_client == true ? "client": "server")));
       
   726 
       
   727 	eap_status_e status = eap_status_not_supported;
       
   728 
       
   729 	if ((m_is_client == true
       
   730 			&& get_state() == eap_type_tls_peap_state_process_tls_start)
       
   731 		|| get_state() == eap_type_tls_peap_state_process_tls_message
       
   732 		|| get_state() == eap_type_tls_peap_state_waiting_for_request // This state is needed to send messages from asyncronous completions.
       
   733 		|| get_state() == eap_type_tls_peap_state_waiting_for_response
       
   734 		|| get_state() == eap_type_tls_peap_state_failure // This state is needed to send failure messages.
       
   735 		|| get_state() == eap_type_tls_peap_state_waiting_for_empty_response
       
   736 		|| get_state() == eap_type_tls_peap_state_waiting_for_success
       
   737 		|| get_state() == eap_type_tls_peap_state_success
       
   738 #if defined(USE_EAP_TLS_PEAP_TPPD_PEAP_V1_NEW_FIXES)
       
   739 		|| get_state() == eap_type_tls_peap_state_waiting_for_empty_tppd_peap_v1_acknowledge
       
   740 		|| (m_is_client == true
       
   741 			&& m_current_eap_type == eap_type_peap
       
   742 			&& m_current_peap_version == peap_version_1
       
   743 			&& m_use_tppd_tls_peap == true
       
   744 			&& m_use_tppd_peapv1_acknowledge_hack == true
       
   745 			&& (get_tls_session_type() == tls_session_type_original_session_resumption
       
   746 				|| get_tls_session_type() == tls_session_type_stateless_session_resumption)
       
   747 			&& (get_state() == eap_type_tls_peap_state_success
       
   748 				|| get_state() == eap_type_tls_peap_state_tppd_peapv1_waits_eap_success_or_tunneled_packet))
       
   749 #endif //#if defined(USE_EAP_TLS_PEAP_TPPD_PEAP_V1_NEW_FIXES)
       
   750 #if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
       
   751 		|| get_state() == eap_type_tls_peap_state_server_waits_ttls_plain_ms_chap_v2_empty_ack
       
   752 #endif //#if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
       
   753 		)
       
   754 	{
       
   755 		status = m_tls_message_buffer.set_copy_of_buffer(
       
   756 			sent_packet->get_data(sent_packet->get_data_length()),
       
   757 			sent_packet->get_data_length());
       
   758 		if (status != eap_status_ok)
       
   759 		{
       
   760 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   761 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   762 		}
       
   763 
       
   764 		// This will start the packet send from begin of the message.
       
   765 		m_tls_message_send_offset = 0ul;
       
   766 
       
   767 		m_includes_tls_handshake_message = includes_tls_handshake_message;
       
   768 
       
   769 		status = eap_tls_peap_fragment_send();
       
   770 		if (status != eap_status_ok)
       
   771 		{
       
   772 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   773 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   774 		}
       
   775 	}
       
   776 	else
       
   777 	{
       
   778 		EAP_TRACE_ERROR(
       
   779 			m_am_tools,
       
   780 			TRACE_FLAGS_TLS_PEAP_ERROR,
       
   781 			(EAPL("ERROR: this = 0x%08x, eap_type_tls_peap_c::tls_peap_packet_send(): ")
       
   782 			 EAPL("Cannot send EAP-TLS/PEAP message in ")
       
   783 			 EAPL("eap_type_tls_peap_state_variable_e %d=%s.\n"),
       
   784 			 this,
       
   785 			 get_state(),
       
   786 			 get_state_string()));
       
   787 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   788 		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
       
   789 	}
       
   790 
       
   791 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   792 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   793 }
       
   794 
       
   795 //--------------------------------------------------
       
   796 
       
   797 //
       
   798 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::packet_send(
       
   799 	const eap_am_network_id_c * const network_id,
       
   800 	eap_buf_chain_wr_c * const sent_packet,
       
   801 	const u32_t header_offset,
       
   802 	const u32_t data_length,
       
   803 	const u32_t buffer_length)
       
   804 {
       
   805 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   806 
       
   807 	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
       
   808 	EAP_TRACE_DEBUG(
       
   809 		m_am_tools,
       
   810 		TRACE_FLAGS_DEFAULT,
       
   811 		(EAPL("EAP_type_TLS_PEAP: %s,  %s: function: eap_type_tls_peap_c::packet_send()\n"),
       
   812 		(m_is_client == true ? "client": "server"),
       
   813 		(get_type_partner()->get_is_tunneled_eap() == true ? "tunneled" : "outer most")));
       
   814 
       
   815 	eap_header_wr_c eap(
       
   816 		m_am_tools,
       
   817 		sent_packet->get_data_offset(
       
   818 			header_offset, data_length),
       
   819 		data_length);
       
   820 	if (eap.get_is_valid() == false)
       
   821 	{
       
   822 		EAP_TRACE_ERROR(
       
   823 			m_am_tools,
       
   824 			TRACE_FLAGS_DEFAULT,
       
   825 			(EAPL("packet_send: packet buffer corrupted.\n")));
       
   826 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
   827 	}
       
   828 
       
   829 	packet_trace(
       
   830 		EAPL("<-"),
       
   831 		network_id,
       
   832 		&eap,
       
   833 		data_length);
       
   834 
       
   835 	eap_status_e status = get_type_partner()->packet_send(
       
   836 		network_id, 
       
   837 		sent_packet, 
       
   838 		header_offset, 
       
   839 		data_length,
       
   840 		buffer_length
       
   841 		);
       
   842 
       
   843 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   844 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   845 }
       
   846 
       
   847 //--------------------------------------------------
       
   848 
       
   849 //
       
   850 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::check_NAI(
       
   851 	const u8_t * const identity,
       
   852 	const u32_t identity_length,
       
   853 	const u8_t * const at_character)
       
   854 {
       
   855 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   856 
       
   857 	bool includes_at = false;
       
   858 	bool includes_dot = false;
       
   859 	u32_t username_length = 0u;
       
   860 	u32_t realm_length = 0u;
       
   861 
       
   862 	for (u32_t ind = 0; ind < identity_length; ind++)
       
   863 	{
       
   864 		const u8_t character = identity[ind];
       
   865 
       
   866 		if (includes_at == false)
       
   867 		{
       
   868 			if (character != EAP_TLS_PEAP_AT_CHARACTER)
       
   869 			{
       
   870 				++username_length;
       
   871 			}
       
   872 		}
       
   873 		else
       
   874 		{
       
   875 			++realm_length;
       
   876 		}
       
   877 
       
   878 
       
   879 		if ('0' <= character && character <= '9')
       
   880 		{
       
   881 			// OK.
       
   882 		}
       
   883 		else if ('a' <= character && character <= 'z')
       
   884 		{
       
   885 			// OK.
       
   886 		}
       
   887 		else if ('A' <= character && character <= 'Z')
       
   888 		{
       
   889 			// OK.
       
   890 		}
       
   891 		else if (character == EAP_TLS_PEAP_AT_CHARACTER)
       
   892 		{
       
   893 			if (includes_at == false)
       
   894 			{
       
   895 				includes_at = true;
       
   896 			}
       
   897 			else
       
   898 			{
       
   899 				// Second at ('@').
       
   900 				EAP_TRACE_DATA_DEBUG(
       
   901 					m_am_tools,
       
   902 					TRACE_FLAGS_DEFAULT,
       
   903 					(EAPL("ERROR: Illegal NAI, includes second at \'@\' character."),
       
   904 					identity,
       
   905 					identity_length));
       
   906 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   907 				return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_nai);
       
   908 			}
       
   909 		}
       
   910 		else if (character == '.')
       
   911 		{
       
   912 			if (includes_at == true)
       
   913 			{
       
   914 				// OK.
       
   915 				includes_dot = true;
       
   916 			}
       
   917 			else
       
   918 			{
       
   919 				// dot ('.') within username
       
   920 				EAP_TRACE_DATA_DEBUG(
       
   921 					m_am_tools,
       
   922 					TRACE_FLAGS_DEFAULT,
       
   923 					(EAPL("ERROR: Illegal NAI, dot \'.\' within username."),
       
   924 					identity,
       
   925 					identity_length));
       
   926 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   927 				return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_nai);
       
   928 			}
       
   929 		}
       
   930 		else if (character == '<'
       
   931 			|| character == '>'
       
   932 			|| character == '('
       
   933 			|| character == ')'
       
   934 			|| character == '['
       
   935 			|| character == ']'
       
   936 			|| character == '\\'
       
   937 			|| character == '.'
       
   938 			|| character == ','
       
   939 			|| character == ';'
       
   940 			|| character == ':'
       
   941 			|| character == EAP_TLS_PEAP_AT_CHARACTER
       
   942 			|| character == ' ' // space
       
   943 			|| character <= 0x1f // Ctrl
       
   944 			|| character >= 0x7f) // extented characters
       
   945 		{
       
   946 			// Illegal character.
       
   947 			EAP_TRACE_ERROR(
       
   948 				m_am_tools,
       
   949 				TRACE_FLAGS_TLS_PEAP_ERROR,
       
   950 				(EAPL("ERROR: Illegal NAI, includes illegal character 0x%02x=%c.\n"),
       
   951 				character,
       
   952 				character));
       
   953 			EAP_TRACE_DATA_ERROR(
       
   954 				m_am_tools,
       
   955 				TRACE_FLAGS_DEFAULT,
       
   956 				(EAPL("ERROR: Illegal NAI, includes illegal character."),
       
   957 				identity,
       
   958 				identity_length));
       
   959 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   960 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_nai);
       
   961 		}
       
   962 		else
       
   963 		{
       
   964 			// All other ascii values are OK.
       
   965 		}
       
   966 	}
       
   967 
       
   968 	// Note the username could be zero length.
       
   969 	if ((realm_length == 1u && includes_at == true) // one at ('@') is illegal.
       
   970 		|| (realm_length == 2u && includes_at == true && includes_dot == true)) //  one at ('@') and one dot is illegal.
       
   971 	{
       
   972 		EAP_TRACE_DATA_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: Illegal NAI."),
       
   973 			identity,
       
   974 			identity_length));
       
   975 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   976 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_nai);
       
   977 	}
       
   978 
       
   979 	if (m_check_nai_realm == true)
       
   980 	{
       
   981 		if (at_character == 0
       
   982 			&& realm_length == 0
       
   983 			&& get_nai_realm()->get_data_length() == 0)
       
   984 		{
       
   985 			// OK, no realm.
       
   986 		}
       
   987 		else if (at_character == 0
       
   988 			|| realm_length != get_nai_realm()->get_data_length()
       
   989 			|| m_am_tools->memcmp(
       
   990 				at_character+1u,
       
   991 				get_nai_realm()->get_data(get_nai_realm()->get_data_length()),
       
   992 				get_nai_realm()->get_data_length()) != 0)
       
   993 		{
       
   994 			EAP_TRACE_DATA_DEBUG(
       
   995 				m_am_tools, 
       
   996 				TRACE_FLAGS_DEFAULT, 
       
   997 				(EAPL("Illegal NAI, realm unknown."),
       
   998 				identity,
       
   999 				identity_length));
       
  1000 			EAP_TRACE_DATA_DEBUG(
       
  1001 				m_am_tools, 
       
  1002 				TRACE_FLAGS_DEFAULT, 
       
  1003 				(EAPL("NAI should be"),
       
  1004 				get_nai_realm()->get_data(get_nai_realm()->get_data_length()),
       
  1005 				get_nai_realm()->get_data_length()));
       
  1006 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1007 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_nai);
       
  1008 		}
       
  1009 	}
       
  1010 
       
  1011 
       
  1012 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1013 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  1014 }
       
  1015 
       
  1016 //--------------------------------------------------
       
  1017 
       
  1018 //
       
  1019 EAP_FUNC_EXPORT void eap_type_tls_peap_c::packet_trace(
       
  1020 	eap_const_string prefix,
       
  1021 	const eap_am_network_id_c * const /*receive_network_id*/,
       
  1022 	eap_header_wr_c * const eap_packet,
       
  1023 	const u32_t eap_packet_length)
       
  1024 {
       
  1025 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1026 	
       
  1027 	EAP_UNREFERENCED_PARAMETER(prefix); // in release
       
  1028 	
       
  1029 	if (eap_packet_length > eap_header_base_c::get_header_length()
       
  1030 		&& eap_packet->get_type() == m_current_eap_type)
       
  1031 	{
       
  1032 		eap_tls_peap_header_c * const received_tls_peap
       
  1033 			= reinterpret_cast<eap_tls_peap_header_c *>(eap_packet);
       
  1034 
       
  1035 		const u8_t * const p_tls_flags = received_tls_peap->get_tls_flags();
       
  1036 		u8_t tls_flags = 0u;
       
  1037 		EAP_UNREFERENCED_PARAMETER(tls_flags); // in release
       
  1038 		if (p_tls_flags != 0)
       
  1039 		{
       
  1040 			tls_flags = *p_tls_flags;
       
  1041 		}
       
  1042 
       
  1043 		u32_t tls_message_length = 0ul;
       
  1044 		if (received_tls_peap->get_tls_message_length(&tls_message_length) != eap_status_ok)
       
  1045 		{
       
  1046 			tls_message_length = 0ul;
       
  1047 		}
       
  1048 
       
  1049 		EAP_TRACE_DEBUG(
       
  1050 			m_am_tools,
       
  1051 			TRACE_FLAGS_DEFAULT,
       
  1052 			(EAPL("%s EAP-TLS/PEAP header %s: code=0x%02x=%s, identifier=0x%02x=%d, ")
       
  1053 			 EAPL("length=0x%04x=%d, ")
       
  1054 			 EAPL("type=0x%08x=%s, TLS-flags=0x%02x %s%s%s, TLS-length=0x%08x=%d.\n"),
       
  1055 			 prefix,
       
  1056 			 (m_is_client == true) ? "client": "server",
       
  1057 			 received_tls_peap->get_code(),
       
  1058 			 received_tls_peap->get_code_string(),
       
  1059 			 received_tls_peap->get_identifier(),
       
  1060 			 received_tls_peap->get_identifier(),
       
  1061 			 received_tls_peap->get_length(),
       
  1062 			 received_tls_peap->get_length(),
       
  1063 			 convert_eap_type_to_u32_t(received_tls_peap->get_type()),
       
  1064 			 received_tls_peap->get_eap_type_string(),
       
  1065 			 tls_flags,
       
  1066 			 (tls_flags & eap_tls_peap_header_c::m_flag_mask_tls_length_included) ? "L": " ",
       
  1067 			 (tls_flags & eap_tls_peap_header_c::m_flag_mask_more_fragments) ? "M": " ",
       
  1068 			 (tls_flags & eap_tls_peap_header_c::m_flag_mask_start) ? "S": " ",
       
  1069 			 tls_message_length,
       
  1070 			 tls_message_length));
       
  1071 	}
       
  1072 	else
       
  1073 	{
       
  1074 		EAP_TRACE_DEBUG(
       
  1075 			m_am_tools,
       
  1076 			TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  1077 			(EAPL("%s EAP header %s: code=0x%02x=%s, identifier=0x%02x, length=0x%04x=%d, ")
       
  1078 			 EAPL("type=0x%08x=%s\n"),
       
  1079 			prefix,
       
  1080 			(m_is_client == true) ? "client": "server",
       
  1081 			eap_packet->get_code(),
       
  1082 			eap_packet->get_code_string(),
       
  1083 			eap_packet->get_identifier(),
       
  1084 			eap_packet->get_length(),
       
  1085 			eap_packet->get_length(),
       
  1086 			convert_eap_type_to_u32_t(eap_packet->get_type()),
       
  1087 			eap_packet->get_type_string()));
       
  1088 
       
  1089 		EAP_TRACE_DEBUG(
       
  1090 			m_am_tools,
       
  1091 			eap_am_tools_c::eap_trace_mask_eap_messages,
       
  1092 			(EAPL("\n\t%s\n\tcode       = 0x%02x   = %s\n\tidentifier = 0x%02x\n\t")
       
  1093 			 EAPL("length     = 0x%04x = %lu\n\ttype       = 0x%08x   = %s\n"),
       
  1094 			(m_is_client == true) ? "client": "server",
       
  1095 			eap_packet->get_code(),
       
  1096 			eap_packet->get_code_string(),
       
  1097 			eap_packet->get_identifier(),
       
  1098 			eap_packet->get_length(),
       
  1099 			eap_packet->get_length(),
       
  1100 			convert_eap_type_to_u32_t(eap_packet->get_type()),
       
  1101 			eap_packet->get_type_string()));
       
  1102 	}
       
  1103 
       
  1104 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1105 }
       
  1106 
       
  1107 //--------------------------------------------------
       
  1108 
       
  1109 // 
       
  1110 eap_master_session_key_c * eap_type_tls_peap_c::get_master_session_key()
       
  1111 {
       
  1112 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1113 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1114 	return &m_master_session_key;
       
  1115 }
       
  1116 
       
  1117 //--------------------------------------------------
       
  1118 
       
  1119 // 
       
  1120 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::finish_successful_authentication(
       
  1121 	const bool send_tppd_peapv1_empty_acknowledge,
       
  1122 	const bool do_quiet_finish,
       
  1123 	const bool do_send_empty_acknowledge)
       
  1124 {
       
  1125 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1126 
       
  1127 	EAP_UNREFERENCED_PARAMETER(send_tppd_peapv1_empty_acknowledge); // Not used if USE_EAP_TLS_PEAP_TPPD_PEAP_V1_NEW_FIXES defined.
       
  1128 
       
  1129 	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
       
  1130 	EAP_TRACE_DEBUG(
       
  1131 		m_am_tools,
       
  1132 		TRACE_FLAGS_DEFAULT,
       
  1133 		(EAPL("EAP_type_TLS_PEAP: %s: function: eap_type_tls_peap_c::finish_successful_authentication()\n"),
       
  1134 		(m_is_client == true ? "client": "server")));
       
  1135 
       
  1136 	EAP_TRACE_ALWAYS(
       
  1137 		m_am_tools,
       
  1138 		TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  1139 		(EAPL("EAP_type_TLS_PEAP: %s, EAP-type %s EAP-SUCCESS, m_tls_session_type=%d=%s, PEAP version %s\n"),
       
  1140 		 ((m_is_client == true) ? "client": "server"),
       
  1141 		 eap_header_string_c::get_eap_type_string(m_current_eap_type),
       
  1142 		 get_tls_session_type(),
       
  1143 		 eap_tls_trace_string_c::get_tls_session_type_string(get_tls_session_type()),
       
  1144 		 eap_tls_trace_string_c::get_peap_version_string(m_current_peap_version)));
       
  1145 
       
  1146 	eap_status_e status(eap_status_process_general_error);
       
  1147 
       
  1148 	if (do_quiet_finish == false)
       
  1149 	{
       
  1150 		if (get_master_session_key()->get_is_valid_data() == false
       
  1151 			|| get_master_session_key()->get_data_length() == 0u)
       
  1152 		{
       
  1153 			set_state(eap_type_tls_peap_state_failure);
       
  1154 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1155 			return EAP_STATUS_RETURN(m_am_tools, eap_status_key_error);
       
  1156 		}
       
  1157 
       
  1158 		eap_status_e status = get_type_partner()->packet_data_crypto_keys(
       
  1159 			get_send_network_id(),
       
  1160 			get_master_session_key());
       
  1161 		if (status != eap_status_ok)
       
  1162 		{
       
  1163 			set_state(eap_type_tls_peap_state_failure);
       
  1164 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1165 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1166 		}
       
  1167 
       
  1168 		bool send_eap_success = true;
       
  1169 #if !defined(USE_EAP_TLS_PEAP_TPPD_PEAP_V1_NEW_FIXES)
       
  1170 		if (m_is_client == true
       
  1171 			|| (m_current_eap_type == eap_type_peap
       
  1172 				&& m_current_peap_version == peap_version_1))
       
  1173 		{
       
  1174 			send_eap_success = false;
       
  1175 		}
       
  1176 #endif //#if !defined(USE_EAP_TLS_PEAP_TPPD_PEAP_V1_NEW_FIXES)
       
  1177 
       
  1178 		eap_state_notification_c notification(
       
  1179 			m_am_tools,
       
  1180 			get_send_network_id(),
       
  1181 			m_is_client,
       
  1182 			eap_state_notification_eap,
       
  1183 			eap_protocol_layer_eap,
       
  1184 			m_current_eap_type,
       
  1185 			eap_state_none,
       
  1186 			eap_state_authentication_finished_successfully,
       
  1187 			get_last_eap_identifier(), // Note the EAP-Success uses the same EAP-Identifier as the last EAP-Request.
       
  1188 			send_eap_success);
       
  1189 		get_type_partner()->state_notification(&notification);
       
  1190 
       
  1191 		if (do_send_empty_acknowledge == true
       
  1192 			&& m_is_client == true
       
  1193 			&& m_current_eap_type == eap_type_peap
       
  1194 			&& m_current_peap_version == peap_version_1
       
  1195 #if !defined(USE_EAP_TLS_PEAP_TPPD_PEAP_V1_NEW_FIXES)
       
  1196 			&& m_use_tppd_tls_peap == true
       
  1197 			&& (m_use_tppd_peapv1_acknowledge_hack == false
       
  1198 				|| get_tls_session_type() == tls_session_type_full_authentication
       
  1199 				|| send_tppd_peapv1_empty_acknowledge == true)
       
  1200 #endif //#if !defined(USE_EAP_TLS_PEAP_TPPD_PEAP_V1_NEW_FIXES)
       
  1201 				)
       
  1202 		{
       
  1203 			// Send empty acknowledge message.
       
  1204 			status = send_empty_eap_ack();
       
  1205 			if (status != eap_status_ok)
       
  1206 			{
       
  1207 				set_state(eap_type_tls_peap_state_failure);
       
  1208 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1209 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1210 			}
       
  1211 		}
       
  1212 	}
       
  1213 
       
  1214 	set_state(eap_type_tls_peap_state_success);
       
  1215 
       
  1216 	// Indicate EAP-TLS/PEAP AM authentication finished successfully.
       
  1217 	m_am_type_tls_peap->authentication_finished(true, get_tls_session_type());
       
  1218 
       
  1219 	m_authentication_finished_successfully = true;
       
  1220 	status = eap_status_success;
       
  1221 
       
  1222 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1223 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1224 }
       
  1225 
       
  1226 //--------------------------------------------------
       
  1227 
       
  1228 //
       
  1229 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::send_final_notification()
       
  1230 {
       
  1231 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1232 
       
  1233 	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
       
  1234 	EAP_TRACE_DEBUG(
       
  1235 		m_am_tools,
       
  1236 		TRACE_FLAGS_DEFAULT,
       
  1237 		(EAPL("EAP_type_TLS_PEAP: %s: function: eap_type_tls_peap_c::send_final_notification(): m_is_valid=%d, m_authentication_finished_successfully=%d\n"),
       
  1238 		(m_is_client == true ? "client": "server"),
       
  1239 		m_is_valid,
       
  1240 		m_authentication_finished_successfully));
       
  1241 
       
  1242 	if (m_is_valid == true 
       
  1243 		&& m_authentication_finished_successfully == false)
       
  1244 	{
       
  1245 		eap_tls_trace_string_c tls_trace;
       
  1246 		EAP_TRACE_ALWAYS(
       
  1247 			m_am_tools,
       
  1248 			TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  1249 			(EAPL("EAP_type_TLS_PEAP: %s, EAP-type %s FAILED, m_tls_session_type=%d=%s, PEAP version %s, state=%s\n"),
       
  1250 			 ((m_is_client == true) ? "client": "server"),
       
  1251 			 eap_header_string_c::get_eap_type_string(m_current_eap_type),
       
  1252 			 get_tls_session_type(),
       
  1253 			 eap_tls_trace_string_c::get_tls_session_type_string(get_tls_session_type()),
       
  1254 			 tls_trace.get_peap_version_string(m_current_peap_version),
       
  1255 			 get_state_string()));
       
  1256 
       
  1257 		if (m_is_client == false
       
  1258 			&& get_state() == eap_type_tls_peap_state_waiting_for_identity_response)
       
  1259 		{
       
  1260 			EAP_TRACE_DEBUG(
       
  1261 				m_am_tools,
       
  1262 				TRACE_FLAGS_DEFAULT,
       
  1263 				(EAPL("EAP_type_TLS_PEAP: %s: function: send_final_notification(): Does not send notiication.\n"),
       
  1264 				 (m_is_client == true ? "client": "server")));
       
  1265 		}
       
  1266 		else
       
  1267 		{
       
  1268 			set_state(eap_type_tls_peap_state_failure);
       
  1269 
       
  1270 			// Notifies the lower level of unsuccessfull authentication.
       
  1271 			eap_state_notification_c notification(
       
  1272 				m_am_tools,
       
  1273 				get_send_network_id(),
       
  1274 				m_is_client,
       
  1275 				eap_state_notification_eap,
       
  1276 				eap_protocol_layer_eap,
       
  1277 				m_current_eap_type,
       
  1278 				eap_state_none,
       
  1279 				eap_state_authentication_terminated_unsuccessfully,
       
  1280 				get_last_eap_identifier(),
       
  1281 				false);
       
  1282 
       
  1283 			notification.set_authentication_error(eap_status_authentication_failure);
       
  1284 
       
  1285 			get_type_partner()->state_notification(&notification);
       
  1286 
       
  1287 			// Indicate EAP-TLS/PEAP AM authentication terminated unsuccessfully.
       
  1288 			m_am_type_tls_peap->authentication_finished(false, get_tls_session_type());
       
  1289 		}
       
  1290 	}
       
  1291 
       
  1292 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1293 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  1294 }
       
  1295 
       
  1296 //--------------------------------------------------
       
  1297 
       
  1298 //
       
  1299 EAP_FUNC_EXPORT bool eap_type_tls_peap_c::get_is_client()
       
  1300 {
       
  1301 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1302 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1303 	return m_is_client;
       
  1304 }
       
  1305 
       
  1306 //--------------------------------------------------
       
  1307 
       
  1308 //
       
  1309 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::create_random_eap_identity(
       
  1310 	eap_variable_data_c * const local_identity)
       
  1311 {
       
  1312 	// Generates random username.
       
  1313 
       
  1314 	if (local_identity == 0)
       
  1315 	{
       
  1316 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1317 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1318 	}
       
  1319 
       
  1320 	const u32_t EAP_TLS_PEAP_RANDOM_IDENTITY_LENGTH = 16;
       
  1321 	eap_variable_data_c random_username(m_am_tools);
       
  1322 	eap_variable_data_c random_bytes(m_am_tools);
       
  1323 
       
  1324 	eap_status_e status = random_bytes.init(EAP_TLS_PEAP_RANDOM_IDENTITY_LENGTH);
       
  1325 	if (status != eap_status_ok)
       
  1326 	{
       
  1327 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1328 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1329 	}
       
  1330 	random_bytes.set_is_valid();
       
  1331 	random_bytes.set_data_length(EAP_TLS_PEAP_RANDOM_IDENTITY_LENGTH);
       
  1332 
       
  1333 	status = m_am_tools->get_crypto()->get_rand_bytes(
       
  1334 		random_bytes.get_data(random_bytes.get_data_length()),
       
  1335 		random_bytes.get_data_length());
       
  1336 	if (status != eap_status_ok)
       
  1337 	{
       
  1338 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1339 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1340 	}
       
  1341 
       
  1342 	const u32_t EAP_GSMSIM_RANDOM_IDENTITY_BUFFER_LENGTH
       
  1343 		= 3ul+(EAP_TLS_PEAP_RANDOM_IDENTITY_LENGTH+1u)*4u/3u;
       
  1344 	
       
  1345 	status = random_username.init(EAP_GSMSIM_RANDOM_IDENTITY_BUFFER_LENGTH);
       
  1346 	if (status != eap_status_ok)
       
  1347 	{
       
  1348 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1349 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1350 	}
       
  1351 	random_username.set_is_valid();
       
  1352 	random_username.set_data_length(EAP_GSMSIM_RANDOM_IDENTITY_BUFFER_LENGTH);
       
  1353 	
       
  1354 	u32_t random_identity_length = random_username.get_data_length();
       
  1355 	
       
  1356 	status = m_am_tools->convert_bytes_to_ascii_armor(
       
  1357 		random_bytes.get_data_offset(0u, random_bytes.get_data_length()),
       
  1358 		random_bytes.get_data_length(),
       
  1359 		random_username.get_data_offset(0u, random_username.get_data_length()),
       
  1360 		&random_identity_length);
       
  1361 	if (status != eap_status_ok)
       
  1362 	{
       
  1363 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1364 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1365 	}
       
  1366 	random_username.set_data_length(random_identity_length);
       
  1367 	
       
  1368 	status = local_identity->set_copy_of_buffer(&random_username);
       
  1369 
       
  1370 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1371 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1372 }
       
  1373 
       
  1374 
       
  1375 //--------------------------------------------------
       
  1376 
       
  1377 //
       
  1378 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::create_eap_fast_mac_identity(
       
  1379 	const eap_am_network_id_c * const send_network_id,
       
  1380 	eap_variable_data_c * const mac_identity)
       
  1381 {
       
  1382 	// EAP-FAST sends special username.
       
  1383 	const u8_t EAP_FAST_PREFIX[] = "PEAP-";
       
  1384 
       
  1385 	eap_status_e status = mac_identity->set_copy_of_buffer(EAP_FAST_PREFIX, sizeof(EAP_FAST_PREFIX)-1ul);
       
  1386 	if (status != eap_status_ok)
       
  1387 	{
       
  1388 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1389 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1390 	}
       
  1391 
       
  1392 	eap_variable_data_c mac_string(m_am_tools);
       
  1393 	if (mac_string.get_is_valid() == false)
       
  1394 	{
       
  1395 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1396 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1397 	}
       
  1398 
       
  1399 	status = mac_string.set_buffer_length(2ul*send_network_id->get_source_length());
       
  1400 	if (status != eap_status_ok)
       
  1401 	{
       
  1402 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1403 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1404 	}
       
  1405 
       
  1406 	status = mac_string.set_data_length(2ul*send_network_id->get_source_length());
       
  1407 	if (status != eap_status_ok)
       
  1408 	{
       
  1409 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1410 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1411 	}
       
  1412 
       
  1413 
       
  1414 	u32_t target_length(2ul*send_network_id->get_source_length());
       
  1415 
       
  1416 	status = m_am_tools->convert_bytes_to_hex_ascii(
       
  1417 		send_network_id->get_source(),
       
  1418 		send_network_id->get_source_length(),
       
  1419 		mac_string.get_data(2ul*send_network_id->get_source_length()),
       
  1420 		&target_length);
       
  1421 	if (status != eap_status_ok)
       
  1422 	{
       
  1423 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1424 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1425 	}
       
  1426 
       
  1427 	const u32_t TWO_CHARS(2ul);
       
  1428 
       
  1429 	for (u32_t ind = 0ul; ind < mac_string.get_data_length(); ind += TWO_CHARS)
       
  1430 	{
       
  1431 		const u8_t dash('-');
       
  1432 
       
  1433 		status = mac_identity->add_data(mac_string.get_data_offset(ind, TWO_CHARS), TWO_CHARS);
       
  1434 		if (status != eap_status_ok)
       
  1435 		{
       
  1436 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1437 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1438 		}
       
  1439 
       
  1440 		if ((ind+TWO_CHARS) < mac_string.get_data_length())
       
  1441 		{
       
  1442 			status = mac_identity->add_data(&dash, sizeof(dash));
       
  1443 			if (status != eap_status_ok)
       
  1444 			{
       
  1445 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1446 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1447 			}
       
  1448 		}
       
  1449 	}
       
  1450 
       
  1451 	status = m_am_tools->convert_ascii_to_uppercase(
       
  1452 		mac_identity->get_data(),
       
  1453 		mac_identity->get_data_length());
       
  1454 
       
  1455 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1456 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1457 }
       
  1458 
       
  1459 //--------------------------------------------------
       
  1460 
       
  1461 //
       
  1462 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::handle_eap_identity_query(
       
  1463 	const eap_variable_data_c * const user_certificate_identity,
       
  1464 	const eap_am_network_id_c * const receive_network_id,
       
  1465 	const u8_t eap_identifier,
       
  1466 	const bool use_manual_username,
       
  1467 	const eap_variable_data_c * const manual_username,
       
  1468 	const bool use_manual_realm,
       
  1469 	const eap_variable_data_c * const manual_realm
       
  1470 	)
       
  1471 {
       
  1472 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1473 
       
  1474 	eap_status_e status = eap_status_process_general_error;
       
  1475 
       
  1476 	eap_variable_data_c local_identity(m_am_tools);
       
  1477 	if (local_identity.get_is_valid() == false)
       
  1478 	{
       
  1479 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1480 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1481 	}
       
  1482 
       
  1483 	// Here we swap the addresses.
       
  1484 	eap_am_network_id_c send_network_id(
       
  1485 		m_am_tools,
       
  1486 		receive_network_id->get_destination_id(),
       
  1487 		receive_network_id->get_source_id(),
       
  1488 		receive_network_id->get_type());
       
  1489 
       
  1490 	if (use_manual_username == true
       
  1491 		&& manual_username != 0
       
  1492 		&& manual_username->get_is_valid() == true
       
  1493 		&& use_manual_realm == true
       
  1494 		&& manual_realm != 0
       
  1495 		&& manual_realm->get_is_valid() == true)
       
  1496 	{
       
  1497 #if defined(USE_EAP_TLS_IDENTITY_PRIVACY)
       
  1498 		if (m_tls_use_identity_privacy == true)
       
  1499 		{
       
  1500 
       
  1501 #if defined(USE_FAST_EAP_TYPE)
       
  1502 			if (m_current_eap_type == eap_type_fast)
       
  1503 			{
       
  1504 				// EAP-FAST sends special username.
       
  1505 				status = create_eap_fast_mac_identity(
       
  1506 					&send_network_id,
       
  1507 					&local_identity);
       
  1508 				if (status != eap_status_ok)
       
  1509 				{
       
  1510 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1511 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1512 				}
       
  1513 			}
       
  1514 			else
       
  1515 #endif //#if defined(USE_FAST_EAP_TYPE)
       
  1516 			{
       
  1517 				EAP_TRACE_DEBUG(
       
  1518 					m_am_tools,
       
  1519 					TRACE_FLAGS_DEFAULT,
       
  1520 					(EAPL("EAP_type_TLS_PEAP: this = 0x%08x, %s: eap_type_tls_peap_c::handle_eap_identity_query(): random username and manual realm.\n"),
       
  1521 					 this,
       
  1522 					(m_is_client == true ? "client": "server")));
       
  1523 
       
  1524 				// TLS identity privacy uses random username.
       
  1525 				status = create_random_eap_identity(&local_identity);
       
  1526 				if (status != eap_status_ok)
       
  1527 				{
       
  1528 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1529 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1530 				}
       
  1531 			}
       
  1532 		}
       
  1533 		else
       
  1534 #endif //#if defined(USE_EAP_TLS_IDENTITY_PRIVACY)
       
  1535 		{
       
  1536 			EAP_TRACE_DEBUG(
       
  1537 				m_am_tools,
       
  1538 				TRACE_FLAGS_DEFAULT,
       
  1539 				(EAPL("EAP_type_TLS_PEAP: this = 0x%08x, %s: eap_type_tls_peap_c::handle_eap_identity_query(): manual username and manual realm.\n"),
       
  1540 				 this,
       
  1541 				(m_is_client == true ? "client": "server")));
       
  1542 
       
  1543 			// Here manual username could be zero or more bytes in length.
       
  1544 			status = local_identity.set_copy_of_buffer(manual_username);
       
  1545 			if (status != eap_status_ok)
       
  1546 			{
       
  1547 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1548 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1549 			}
       
  1550 		}
       
  1551 
       
  1552 		if (manual_realm->get_data_length() > 0ul)
       
  1553 		{
       
  1554 			// When manual realm is one or more bytes in length
       
  1555 			// we add @ and manual realm to the identity.
       
  1556 			u8_t at_char = EAP_TLS_PEAP_AT_CHARACTER;
       
  1557 			status = local_identity.add_data(&at_char, sizeof(at_char));
       
  1558 			if (status != eap_status_ok)
       
  1559 			{
       
  1560 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1561 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1562 			}
       
  1563 			
       
  1564 			status = local_identity.add_data(manual_realm);
       
  1565 			if (status != eap_status_ok)
       
  1566 			{
       
  1567 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1568 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1569 			}
       
  1570 		}
       
  1571 	}
       
  1572 	else if (use_manual_username == true
       
  1573 			&& manual_username != 0
       
  1574 			&& manual_username->get_is_valid() == true
       
  1575 			&& use_manual_realm == false)
       
  1576 	{
       
  1577 #if defined(USE_EAP_TLS_IDENTITY_PRIVACY)
       
  1578 		if (m_tls_use_identity_privacy == true)
       
  1579 		{
       
  1580 #if defined(USE_FAST_EAP_TYPE)
       
  1581 			if (m_current_eap_type == eap_type_fast)
       
  1582 			{
       
  1583 				// EAP-FAST sends special username.
       
  1584 				status = create_eap_fast_mac_identity(
       
  1585 					&send_network_id,
       
  1586 					&local_identity);
       
  1587 				if (status != eap_status_ok)
       
  1588 				{
       
  1589 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1590 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1591 				}
       
  1592 			}
       
  1593 			else
       
  1594 #endif //#if defined(USE_FAST_EAP_TYPE)
       
  1595 			{
       
  1596 				EAP_TRACE_DEBUG(
       
  1597 					m_am_tools,
       
  1598 					TRACE_FLAGS_DEFAULT,
       
  1599 					(EAPL("EAP_type_TLS_PEAP: %s: eap_type_tls_peap_c::handle_eap_identity_query(): random username and realm from certificate.\n"),
       
  1600 					(m_is_client == true ? "client": "server")));
       
  1601 
       
  1602 				// TLS identity privacy uses random username.
       
  1603 				status = create_random_eap_identity(&local_identity);
       
  1604 				if (status != eap_status_ok)
       
  1605 				{
       
  1606 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1607 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1608 				}
       
  1609 			}
       
  1610 		}
       
  1611 		else
       
  1612 #endif //#if defined(USE_EAP_TLS_IDENTITY_PRIVACY)
       
  1613 		{
       
  1614 			EAP_TRACE_DEBUG(
       
  1615 				m_am_tools,
       
  1616 				TRACE_FLAGS_DEFAULT,
       
  1617 				(EAPL("EAP_type_TLS_PEAP: %s: eap_type_tls_peap_c::handle_eap_identity_query(): manual username and realm from certificate.\n"),
       
  1618 				(m_is_client == true ? "client": "server")));
       
  1619 
       
  1620 			status = local_identity.set_copy_of_buffer(manual_username);
       
  1621 			if (status != eap_status_ok)
       
  1622 			{
       
  1623 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1624 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1625 			}
       
  1626 		}
       
  1627 
       
  1628 		if (user_certificate_identity != 0
       
  1629 			&& user_certificate_identity->get_is_valid() == true)
       
  1630 		{
       
  1631 			eap_variable_data_c username(m_am_tools);
       
  1632 			eap_variable_data_c realm(m_am_tools);
       
  1633 
       
  1634 			status = m_am_tools->parse_nai(
       
  1635 				user_certificate_identity,
       
  1636 				&username,
       
  1637 				&realm);
       
  1638 			if (status == eap_status_ok)
       
  1639 			{
       
  1640 				if (realm.get_is_valid_data() == true)
       
  1641 				{
       
  1642 					u8_t at_char = EAP_TLS_PEAP_AT_CHARACTER;
       
  1643 					status = local_identity.add_data(&at_char, sizeof(at_char));
       
  1644 					if (status != eap_status_ok)
       
  1645 					{
       
  1646 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1647 						return EAP_STATUS_RETURN(m_am_tools, status);
       
  1648 					}
       
  1649 
       
  1650 					status = local_identity.add_data(&realm);
       
  1651 					if (status != eap_status_ok)
       
  1652 					{
       
  1653 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1654 						return EAP_STATUS_RETURN(m_am_tools, status);
       
  1655 					}
       
  1656 				}
       
  1657 			}
       
  1658 		}
       
  1659 		else
       
  1660 		{
       
  1661 			// No realm.
       
  1662 		}
       
  1663 	}
       
  1664 	else if ((use_manual_username == false
       
  1665 				 && use_manual_realm == true
       
  1666 				 && manual_realm != 0
       
  1667 				 && manual_realm->get_is_valid() == true)
       
  1668 #if defined(USE_EAP_TLS_IDENTITY_PRIVACY)
       
  1669 			 || m_tls_use_identity_privacy == true
       
  1670 #endif //#if defined(USE_EAP_TLS_IDENTITY_PRIVACY)
       
  1671 			 )
       
  1672 	{
       
  1673 #if defined(USE_EAP_TLS_IDENTITY_PRIVACY)
       
  1674 		if (m_tls_use_identity_privacy == true)
       
  1675 		{
       
  1676 #if defined(USE_FAST_EAP_TYPE)
       
  1677 			if (m_current_eap_type == eap_type_fast)
       
  1678 			{
       
  1679 				// EAP-FAST sends special username.
       
  1680 				status = create_eap_fast_mac_identity(
       
  1681 					&send_network_id,
       
  1682 					&local_identity);
       
  1683 				if (status != eap_status_ok)
       
  1684 				{
       
  1685 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1686 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1687 				}
       
  1688 			}
       
  1689 			else
       
  1690 #endif //#if defined(USE_FAST_EAP_TYPE)
       
  1691 			{
       
  1692 				EAP_TRACE_DEBUG(
       
  1693 					m_am_tools,
       
  1694 					TRACE_FLAGS_DEFAULT,
       
  1695 					(EAPL("EAP_type_TLS_PEAP: %s: eap_type_tls_peap_c::handle_eap_identity_query(): random username and manual realm.\n"),
       
  1696 					(m_is_client == true ? "client": "server")));
       
  1697 
       
  1698 				// TLS identity privacy uses random username.
       
  1699 				status = create_random_eap_identity(&local_identity);
       
  1700 				if (status != eap_status_ok)
       
  1701 				{
       
  1702 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1703 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1704 				}
       
  1705 			}
       
  1706 		}
       
  1707 		else
       
  1708 #endif //#if defined(USE_EAP_TLS_IDENTITY_PRIVACY)
       
  1709 		if (user_certificate_identity != 0
       
  1710 			&& user_certificate_identity->get_is_valid() == true)
       
  1711 		{
       
  1712 			EAP_TRACE_DEBUG(
       
  1713 				m_am_tools,
       
  1714 				TRACE_FLAGS_DEFAULT,
       
  1715 				(EAPL("EAP_type_TLS_PEAP: %s: eap_type_tls_peap_c::handle_eap_identity_query(): username from certificate and manual realm.\n"),
       
  1716 				(m_is_client == true ? "client": "server")));
       
  1717 
       
  1718 			eap_variable_data_c username(m_am_tools);
       
  1719 			eap_variable_data_c realm(m_am_tools);
       
  1720 
       
  1721 			status = m_am_tools->parse_nai(
       
  1722 				user_certificate_identity,
       
  1723 				&username,
       
  1724 				&realm);
       
  1725 			if (status == eap_status_ok)
       
  1726 			{
       
  1727 				if (username.get_is_valid_data() == true)
       
  1728 				{
       
  1729 					status = local_identity.set_copy_of_buffer(&username);
       
  1730 					if (status != eap_status_ok)
       
  1731 					{
       
  1732 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1733 						return EAP_STATUS_RETURN(m_am_tools, status);
       
  1734 					}
       
  1735 				}
       
  1736 			}
       
  1737 		}
       
  1738 		else
       
  1739 		{
       
  1740 			EAP_TRACE_DEBUG(
       
  1741 				m_am_tools,
       
  1742 				TRACE_FLAGS_DEFAULT,
       
  1743 				(EAPL("EAP_type_TLS_PEAP: %s: eap_type_tls_peap_c::handle_eap_identity_query(): random username and manual realm.\n"),
       
  1744 				(m_is_client == true ? "client": "server")));
       
  1745 
       
  1746 #if defined(USE_FAST_EAP_TYPE)
       
  1747 			if (m_current_eap_type == eap_type_fast)
       
  1748 			{
       
  1749 				// EAP-FAST sends special username.
       
  1750 				status = create_eap_fast_mac_identity(
       
  1751 					&send_network_id,
       
  1752 					&local_identity);
       
  1753 				if (status != eap_status_ok)
       
  1754 				{
       
  1755 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1756 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1757 				}
       
  1758 			}
       
  1759 			else
       
  1760 #endif //#if defined(USE_FAST_EAP_TYPE)
       
  1761 			{
       
  1762 				status = create_random_eap_identity(&local_identity);
       
  1763 				if (status != eap_status_ok)
       
  1764 				{
       
  1765 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1766 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1767 				}
       
  1768 			}
       
  1769 		}
       
  1770 
       
  1771 		if (manual_realm != 0
       
  1772 			&& manual_realm->get_data_length() > 0ul)
       
  1773 		{
       
  1774 			u8_t at_char = EAP_TLS_PEAP_AT_CHARACTER;
       
  1775 			status = local_identity.add_data(&at_char, sizeof(at_char));
       
  1776 			if (status != eap_status_ok)
       
  1777 			{
       
  1778 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1779 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1780 			}
       
  1781 			
       
  1782 			status = local_identity.add_data(manual_realm);
       
  1783 			if (status != eap_status_ok)
       
  1784 			{
       
  1785 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1786 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1787 			}
       
  1788 		}
       
  1789 		else
       
  1790 		{
       
  1791 			// No realm.
       
  1792 		}
       
  1793 	}
       
  1794 	else if (user_certificate_identity != 0
       
  1795 		&& user_certificate_identity->get_is_valid() == true)
       
  1796 	{
       
  1797 		EAP_TRACE_DEBUG(
       
  1798 			m_am_tools,
       
  1799 			TRACE_FLAGS_DEFAULT,
       
  1800 			(EAPL("EAP_type_TLS_PEAP: %s: eap_type_tls_peap_c::handle_eap_identity_query(): username from certificate and realm from certificate.\n"),
       
  1801 			(m_is_client == true ? "client": "server")));
       
  1802 
       
  1803 		// Uses NAI from certificate.
       
  1804 		status = local_identity.set_copy_of_buffer(user_certificate_identity);
       
  1805 		if (status != eap_status_ok)
       
  1806 		{
       
  1807 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1808 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1809 		}
       
  1810 	}
       
  1811 	else
       
  1812 	{
       
  1813 		EAP_TRACE_ERROR(
       
  1814 			m_am_tools,
       
  1815 			TRACE_FLAGS_DEFAULT,
       
  1816 			(EAPL("EAP_type_TLS_PEAP: %s: eap_type_tls_peap_c::handle_eap_identity_query(): no identity.\n"),
       
  1817 			(m_is_client == true ? "client": "server")));
       
  1818 
       
  1819 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1820 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_identity);
       
  1821 	}
       
  1822 
       
  1823 	status = m_current_identity.set_copy_of_buffer(&local_identity);
       
  1824 	if (status != eap_status_ok)
       
  1825 	{
       
  1826 		restore_saved_previous_state();
       
  1827 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1828 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1829 	}
       
  1830 		
       
  1831 	status = get_NAI()->set_copy_of_buffer(&local_identity);
       
  1832 	if (status != eap_status_ok)
       
  1833 	{
       
  1834 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1835 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1836 	}
       
  1837 	
       
  1838 	EAP_TRACE_DATA_DEBUG(
       
  1839 		m_am_tools,
       
  1840 		TRACE_FLAGS_DEFAULT,
       
  1841 		(EAPL("eap_type_tls_peap_c::handle_eap_identity_query(): identity"),
       
  1842 		local_identity.get_data(),
       
  1843 		local_identity.get_data_length()));
       
  1844 
       
  1845 
       
  1846 	status = get_type_partner()->complete_eap_identity_query(
       
  1847 		&send_network_id,
       
  1848 		&local_identity,
       
  1849 		eap_identifier);	
       
  1850 	if (status == eap_status_ok)
       
  1851 	{
       
  1852 		set_state(eap_type_tls_peap_state_waiting_for_tls_start);
       
  1853 	}
       
  1854 	else
       
  1855 	{
       
  1856 		m_current_identity.reset();
       
  1857 		get_NAI()->reset();
       
  1858 		restore_saved_previous_state();
       
  1859 	}
       
  1860 	
       
  1861 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1862 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1863 }
       
  1864 
       
  1865 //--------------------------------------------------
       
  1866 
       
  1867 //
       
  1868 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::complete_eap_identity_query(
       
  1869 	const eap_variable_data_c * const user_certificate_identity,
       
  1870 	const eap_am_network_id_c * const receive_network_id,
       
  1871 	const u8_t eap_identifier,
       
  1872 	const eap_status_e completion_status,
       
  1873 	const bool use_manual_username,
       
  1874 	const eap_variable_data_c * const manual_username,
       
  1875 	const bool use_manual_realm,
       
  1876 	const eap_variable_data_c * const manual_realm
       
  1877 	)
       
  1878 {
       
  1879 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1880 
       
  1881 	if (m_state == eap_type_tls_peap_state_pending_identity_query)
       
  1882 	{
       
  1883 		if (completion_status != eap_status_ok)
       
  1884 		{
       
  1885 			set_state(eap_type_tls_peap_state_failure);
       
  1886 
       
  1887 			// The completion_status error value is more important
       
  1888 			// than return value of set_session_timeout().
       
  1889 			get_type_partner()->set_session_timeout(0ul);
       
  1890 
       
  1891 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1892 			return EAP_STATUS_RETURN(m_am_tools, completion_status);
       
  1893 		}
       
  1894 
       
  1895 		eap_status_e status = handle_eap_identity_query(
       
  1896 			user_certificate_identity,
       
  1897 			receive_network_id,
       
  1898 			eap_identifier,
       
  1899 			use_manual_username,
       
  1900 			manual_username,
       
  1901 			use_manual_realm,
       
  1902 			manual_realm);
       
  1903 
       
  1904 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1905 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1906 	}
       
  1907 	else
       
  1908 	{
       
  1909 		EAP_TRACE_ERROR(
       
  1910 			m_am_tools, 
       
  1911 			TRACE_FLAGS_TLS_PEAP_ERROR, 
       
  1912 			(EAPL("ERROR: eap_type_tls_peap_c::complete_eap_identity_query(): ")
       
  1913 			 EAPL("Illegal EAP-Identity query completion in ")
       
  1914 			 EAPL("eap_type_tls_peap_state_variable_e %d=%s.\n"),
       
  1915 			get_state(),
       
  1916 			get_state_string()));
       
  1917 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1918 		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
       
  1919 	}
       
  1920 }
       
  1921 
       
  1922 //--------------------------------------------------
       
  1923 
       
  1924 //
       
  1925 eap_status_e eap_type_tls_peap_c::check_received_eap_identifier(
       
  1926 	const eap_header_wr_c * const eap_header)
       
  1927 {
       
  1928 	if (m_is_client == false
       
  1929 		&& get_type_partner()->get_is_tunneled_eap() == true
       
  1930 		&& m_check_identifier_of_eap_identity_response == false)
       
  1931 	{
       
  1932 		// Server cannot exactly verify EAP-Identifier value because of fragmentation.
       
  1933 		if (eap_header->get_identifier() < get_last_eap_identifier())
       
  1934 		{
       
  1935 			eap_status_e status(eap_status_unexpected_message);
       
  1936 
       
  1937 			eap_status_string_c status_string;
       
  1938 			EAP_TRACE_ERROR(
       
  1939 				m_am_tools,
       
  1940 				TRACE_FLAGS_TLS_PEAP_ERROR,
       
  1941 				(EAPL("ERROR: eap_type_tls_peap_c::check_received_eap_identifier() failed,")
       
  1942 				 EAPL("status %d=%s, received EAP-type 0x%08x, received EAP-code %d, ")
       
  1943 				 EAPL("received EAP-identifier %d, current EAP-identifier %d, state %s\n"),
       
  1944 				 status,
       
  1945 				 status_string.get_status_string(status),
       
  1946 				 convert_eap_type_to_u32_t(eap_header->get_type()),
       
  1947 				 eap_header->get_code(),
       
  1948 				 eap_header->get_identifier(),
       
  1949 				 get_last_eap_identifier(),
       
  1950 				 get_state_string()));
       
  1951 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1952 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1953 		}
       
  1954 	}
       
  1955 	else
       
  1956 	{
       
  1957 		if (m_is_client == false
       
  1958 			&& eap_header->get_type() == eap_type_identity
       
  1959 			&& eap_header->get_code() == eap_code_response
       
  1960 			&& m_check_identifier_of_eap_identity_response == true
       
  1961 			&& eap_header->get_identifier() != get_last_eap_identifier())
       
  1962 		{
       
  1963 			eap_status_e status(eap_status_unexpected_message);
       
  1964 
       
  1965 			eap_status_string_c status_string;
       
  1966 			EAP_TRACE_ERROR(
       
  1967 				m_am_tools,
       
  1968 				TRACE_FLAGS_TLS_PEAP_ERROR,
       
  1969 				(EAPL("ERROR: eap_type_tls_peap_c::check_received_eap_identifier() failed,")
       
  1970 				 EAPL("status %d=%s, received EAP-type 0x%08x, received EAP-code %d, ")
       
  1971 				 EAPL("received EAP-identifier %d, current EAP-identifier %d, state %s\n"),
       
  1972 				 status,
       
  1973 				 status_string.get_status_string(status),
       
  1974 				 convert_eap_type_to_u32_t(eap_header->get_type()),
       
  1975 				 eap_header->get_code(),
       
  1976 				 eap_header->get_identifier(),
       
  1977 				 get_last_eap_identifier(),
       
  1978 				 get_state_string()));
       
  1979 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1980 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1981 		}
       
  1982 		else if (m_is_client == false
       
  1983 				 && eap_header->get_type() == m_current_eap_type
       
  1984 				 && eap_header->get_identifier() != get_last_eap_identifier())
       
  1985 		{
       
  1986 			eap_status_e status(eap_status_unexpected_message);
       
  1987 
       
  1988 			eap_status_string_c status_string;
       
  1989 			EAP_TRACE_ERROR(
       
  1990 				m_am_tools,
       
  1991 				TRACE_FLAGS_TLS_PEAP_ERROR,
       
  1992 				(EAPL("ERROR: eap_type_tls_peap_c::check_received_eap_identifier() failed,")
       
  1993 				 EAPL("status %d=%s, received EAP-identifier %d, ")
       
  1994 				 EAPL("current EAP-identifier %d, state %s\n"),
       
  1995 				 status,
       
  1996 				 status_string.get_status_string(status),
       
  1997 				 eap_header->get_identifier(),
       
  1998 				 get_last_eap_identifier(),
       
  1999 				 get_state_string()));
       
  2000 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2001 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2002 		}
       
  2003 		else if (m_is_client == true
       
  2004 			&& eap_header->get_identifier() == get_last_eap_identifier())
       
  2005 		{
       
  2006 			// Client have received this packet already.
       
  2007 			eap_status_e status(eap_status_drop_packet_quietly);
       
  2008 
       
  2009 			eap_status_string_c status_string;
       
  2010 			EAP_TRACE_DEBUG(
       
  2011 				m_am_tools,
       
  2012 				TRACE_FLAGS_DEFAULT,
       
  2013 				(EAPL("WARNING: eap_type_tls_peap_c::check_received_eap_identifier() failed,")
       
  2014 				 EAPL("status %d=%s, drops already received EAP-identifier %d, ")
       
  2015 				 EAPL("current EAP-identifier %d, state %s\n"),
       
  2016 				 status,
       
  2017 				 status_string.get_status_string(status),
       
  2018 				 eap_header->get_identifier(),
       
  2019 				 get_last_eap_identifier(),
       
  2020 				 get_state_string()));
       
  2021 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2022 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2023 		}
       
  2024 	}
       
  2025 
       
  2026 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2027 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2028 }
       
  2029 
       
  2030 //--------------------------------------------------
       
  2031 
       
  2032 //
       
  2033 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::packet_process(
       
  2034 	const eap_am_network_id_c * const receive_network_id, ///< This is the network identity of the received EAP packet.
       
  2035 	eap_header_wr_c * const eap_header, ///< This is pointer to EAP header and data.
       
  2036 	const u32_t eap_packet_length ///< This is length of received EAP packet.
       
  2037 	)
       
  2038 {
       
  2039 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2040 
       
  2041 	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
       
  2042 	EAP_TRACE_DEBUG(
       
  2043 		m_am_tools,
       
  2044 		TRACE_FLAGS_DEFAULT,
       
  2045 		(EAPL("EAP_type_TLS_PEAP: %s, %s: function: eap_type_tls_peap_c::packet_process()\n"),
       
  2046 		(m_is_client == true ? "client": "server"),
       
  2047 		(get_type_partner()->get_is_tunneled_eap() == true ? "tunneled" : "outer most")));
       
  2048 
       
  2049 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eap_type_tls_peap_c::packet_process()");
       
  2050 
       
  2051 	packet_trace(
       
  2052 		EAPL("->"),
       
  2053 		receive_network_id,
       
  2054 		eap_header,
       
  2055 		eap_packet_length);
       
  2056 
       
  2057 	if (eap_packet_length < eap_header->get_length())
       
  2058 	{
       
  2059 		EAP_TRACE_ERROR(
       
  2060 			m_am_tools,
       
  2061 			TRACE_FLAGS_DEFAULT,
       
  2062 			(EAPL("eap_packet_length=0x%04x < eap_header->get_length()=0x%04x.\n"),
       
  2063 			eap_packet_length, eap_header->get_length()));
       
  2064 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2065 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  2066 	}
       
  2067 
       
  2068 	if (eap_header->get_length() < eap_header_base_c::get_header_length())
       
  2069 	{
       
  2070 		EAP_TRACE_ERROR(
       
  2071 			m_am_tools,
       
  2072 			TRACE_FLAGS_TLS_PEAP_ERROR,
       
  2073 			(EAPL("ERROR: eap_type_tls_peap_c::packet_process(): ")
       
  2074 			 EAPL("eap_header->get_length() < eap_header_base_c::get_header_length().\n")));
       
  2075 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2076 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  2077 	}
       
  2078 
       
  2079 
       
  2080 	// NOTE: by disabling these calls throughput increases about 18%.
       
  2081 	// Disabling also decreases random seeds.
       
  2082 	m_am_tools->get_crypto()->add_rand_seed(
       
  2083 		eap_header->get_header_buffer(eap_packet_length),
       
  2084 		eap_packet_length);
       
  2085 	m_am_tools->get_crypto()->add_rand_seed_hw_ticks();
       
  2086 
       
  2087 	eap_status_e status = eap_status_process_general_error;
       
  2088 
       
  2089 	eap_tls_peap_header_c tls_peap_header(
       
  2090 		m_am_tools,
       
  2091 		eap_header->get_header_buffer(eap_packet_length),
       
  2092 		eap_packet_length);
       
  2093 
       
  2094 	if ((m_is_client == true
       
  2095 		&& eap_header->get_code() == eap_code_request)
       
  2096 		|| (m_is_client == false
       
  2097 		&& eap_header->get_code() == eap_code_response))
       
  2098 	{
       
  2099 		if (eap_header->get_type() == eap_type_identity
       
  2100 			|| eap_header->get_type() == m_current_eap_type)
       
  2101 		{
       
  2102 			if (eap_header->get_type() == eap_type_identity
       
  2103 				&& eap_header->get_code() == eap_code_request)
       
  2104 			{
       
  2105 				// EAP-Request/Identity is handled in eap_core_c.
       
  2106 				status = eap_status_unexpected_message;
       
  2107 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2108 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  2109 			}
       
  2110 			else if (eap_header->get_type() == eap_type_identity
       
  2111 				&& eap_header->get_code() == eap_code_response
       
  2112 				&& eap_header->get_length() <= eap_header_base_c::get_header_length())
       
  2113 			{
       
  2114 				status = eap_status_header_corrupted;
       
  2115 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2116 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  2117 			}
       
  2118 			else if (eap_header->get_type() == m_current_eap_type
       
  2119 				&& eap_header->get_length() < tls_peap_header.get_tls_min_header_length())
       
  2120 			{
       
  2121 				status = eap_status_header_corrupted;
       
  2122 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2123 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  2124 			}
       
  2125 			else if (check_received_eap_identifier(eap_header) != eap_status_ok)
       
  2126 			{
       
  2127 				status = eap_status_unexpected_message;
       
  2128 				eap_status_string_c status_string;
       
  2129 				EAP_TRACE_ERROR(
       
  2130 					m_am_tools,
       
  2131 					TRACE_FLAGS_TLS_PEAP_ERROR,
       
  2132 					(EAPL("ERROR: eap_type_tls_peap_c::packet_process() failed,")
       
  2133 					 EAPL("status %d=%s, received EAP-type 0x%08x, received EAP-code %d, ")
       
  2134 					 EAPL("received EAP-identifier %d, current EAP-identifier %d, state %s\n"),
       
  2135 					 status,
       
  2136 					 status_string.get_status_string(status),
       
  2137 					 convert_eap_type_to_u32_t(eap_header->get_type()),
       
  2138 					 eap_header->get_code(),
       
  2139 					 eap_header->get_identifier(),
       
  2140 					 get_last_eap_identifier(),
       
  2141 					 get_state_string()));
       
  2142 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2143 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  2144 			}
       
  2145 			else
       
  2146 			{
       
  2147 				if (m_is_client == true)
       
  2148 				{
       
  2149 					// Client saves the received EAP-Identifier.
       
  2150 					set_last_eap_identifier(eap_header->get_identifier());
       
  2151 				}
       
  2152 
       
  2153 				if (eap_header->get_type() == eap_type_identity)
       
  2154 				{
       
  2155 					status = eap_identity_response_packet_process(
       
  2156 						receive_network_id,
       
  2157 						eap_header,
       
  2158 						eap_packet_length);
       
  2159 
       
  2160 					if (status != eap_status_ok
       
  2161 						&& status != eap_status_success
       
  2162 						&& status != eap_status_drop_packet_quietly)
       
  2163 					{
       
  2164 						eap_status_string_c status_string;
       
  2165 
       
  2166 						EAP_TRACE_ERROR(
       
  2167 							m_am_tools,
       
  2168 							TRACE_FLAGS_TLS_PEAP_ERROR,
       
  2169 							(EAPL("ERROR: eap_type_tls_peap_c::")
       
  2170 							 EAPL("eap_identity_response_packet_process() failed, status %d=%s\n"),
       
  2171 							 status, status_string.get_status_string(status)));
       
  2172 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2173 						return EAP_STATUS_RETURN(m_am_tools, status);
       
  2174 					}
       
  2175 					if (status == eap_status_ok)
       
  2176 					{
       
  2177 						EAP_GENERAL_HEADER_SET_ERROR_DETECTED(eap_header, false);
       
  2178 
       
  2179 						eap_state_notification_c notification(
       
  2180 							m_am_tools,
       
  2181 							get_send_network_id(),
       
  2182 							m_is_client,
       
  2183 							eap_state_notification_eap,
       
  2184 							eap_protocol_layer_eap,
       
  2185 							m_current_eap_type,
       
  2186 							eap_state_none,
       
  2187 							eap_state_identity_response_received,
       
  2188 							get_last_eap_identifier(),
       
  2189 							false);
       
  2190 						get_type_partner()->state_notification(&notification);
       
  2191 					}
       
  2192 				}
       
  2193 				else
       
  2194 				{
       
  2195 					status = tls_peap_packet_process(
       
  2196 						receive_network_id,
       
  2197 						&tls_peap_header,
       
  2198 						eap_packet_length);
       
  2199 
       
  2200 					if (status == eap_status_ok)
       
  2201 					{
       
  2202 						EAP_GENERAL_HEADER_SET_ERROR_DETECTED(eap_header, false);
       
  2203 					}
       
  2204 
       
  2205 					if (status != eap_status_ok
       
  2206 						&& status != eap_status_success
       
  2207 						&& status != eap_status_pending_request
       
  2208 						&& status != eap_status_drop_packet_quietly)
       
  2209 					{
       
  2210 						eap_status_string_c status_string;
       
  2211 
       
  2212 						EAP_TRACE_ERROR(
       
  2213 							m_am_tools,
       
  2214 							TRACE_FLAGS_TLS_PEAP_ERROR,
       
  2215 							(EAPL("ERROR: eap_type_tls_peap_c::tls_peap_packet_process() ")
       
  2216 							 EAPL("failed, status %d=%s\n"),
       
  2217 							 status, status_string.get_status_string(status)));
       
  2218 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2219 						return EAP_STATUS_RETURN(m_am_tools, status);
       
  2220 					}
       
  2221 				}
       
  2222 			}
       
  2223 
       
  2224 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2225 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2226 		}
       
  2227 		else if (eap_header->get_type() == eap_type_notification)
       
  2228 		{
       
  2229 			EAP_TRACE_ERROR(
       
  2230 				m_am_tools,
       
  2231 				TRACE_FLAGS_DEFAULT,
       
  2232 				(EAPL("dropped EAP type notification: code=0x%02x, identifier=0x%02x, ")
       
  2233 				 EAPL("length=0x%04x, type=0x%08x\n"),
       
  2234 				 eap_header->get_code(),
       
  2235 				 eap_header->get_identifier(),
       
  2236 				 eap_header->get_length(),
       
  2237 				 convert_eap_type_to_u32_t(eap_header->get_type())));
       
  2238 
       
  2239 			status = eap_status_illegal_eap_type;
       
  2240 
       
  2241 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2242 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2243 		}
       
  2244 		else
       
  2245 		{
       
  2246 			EAP_TRACE_ERROR(
       
  2247 				m_am_tools,
       
  2248 				TRACE_FLAGS_DEFAULT,
       
  2249 				(EAPL("dropped EAP type unknown: code=0x%02x, identifier=0x%02x, ")
       
  2250 				 EAPL("length=0x%04x, type=0x%08x\n"),
       
  2251 				 eap_header->get_code(),
       
  2252 				 eap_header->get_identifier(),
       
  2253 				 eap_header->get_length(),
       
  2254 				 convert_eap_type_to_u32_t(eap_header->get_type())));
       
  2255 
       
  2256 			status = eap_status_illegal_eap_type;
       
  2257 
       
  2258 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2259 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2260 		}
       
  2261 	}
       
  2262 	else if (eap_header->get_code() == eap_code_success
       
  2263 		|| eap_header->get_code() == eap_code_failure)
       
  2264 	{
       
  2265 		// Here we swap the addresses.
       
  2266 		eap_am_network_id_c send_network_id(m_am_tools,
       
  2267 			receive_network_id->get_destination_id(),
       
  2268 			receive_network_id->get_source_id(),
       
  2269 			receive_network_id->get_type());
       
  2270 
       
  2271 		if (eap_header->get_code() == eap_code_success)
       
  2272 		{
       
  2273 #if defined(USE_EAP_TLS_PEAP_TPPD_PEAP_V1_NEW_FIXES)
       
  2274 			if (get_state()
       
  2275 				== eap_type_tls_peap_state_tppd_peapv1_waits_eap_success_or_tunneled_packet
       
  2276 				&& m_current_eap_type == eap_type_peap
       
  2277 				&& m_current_peap_version == peap_version_1
       
  2278 				&& m_use_tppd_tls_peap == true
       
  2279 				&& m_use_tppd_peapv1_acknowledge_hack == true
       
  2280 				&& (get_tls_session_type() == tls_session_type_original_session_resumption
       
  2281 					|| get_tls_session_type() == tls_session_type_stateless_session_resumption))
       
  2282 			{
       
  2283 				// EAP-PEAPv1 original session resumption finishes with plain text EAP-SUCCESS.
       
  2284 				// We must forward this to the tunneled EAP-type.
       
  2285 				status = m_tls_record->plain_eap_success_failure_packet_received(
       
  2286 					receive_network_id,
       
  2287 					eap_header->get_code(),
       
  2288 					eap_header->get_identifier());
       
  2289 
       
  2290 				if (status == eap_status_ok)
       
  2291 				{
       
  2292 					EAP_GENERAL_HEADER_SET_ERROR_DETECTED(eap_header, false);
       
  2293 				}
       
  2294 
       
  2295 				status = finish_successful_authentication(false, false, true);
       
  2296 				if (status != eap_status_success)
       
  2297 				{
       
  2298 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2299 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  2300 				}
       
  2301 			}
       
  2302 			else
       
  2303 #endif //#if defined(USE_EAP_TLS_PEAP_TPPD_PEAP_V1_NEW_FIXES)
       
  2304 			if (m_current_eap_type == eap_type_ttls
       
  2305 				&& get_state() == eap_type_tls_peap_state_waiting_for_request)
       
  2306 			{
       
  2307 				// EAP-TTLS finishes with plain text EAP-SUCCESS.
       
  2308 				// We must forward this to the tunneled EAP-type.
       
  2309 				status = m_tls_record->plain_eap_success_failure_packet_received(
       
  2310 					receive_network_id,
       
  2311 					eap_header->get_code(),
       
  2312 					eap_header->get_identifier());
       
  2313 
       
  2314 				if (status == eap_status_ok)
       
  2315 				{
       
  2316 					EAP_GENERAL_HEADER_SET_ERROR_DETECTED(eap_header, false);
       
  2317 				}
       
  2318 
       
  2319 				if (status != eap_status_ok
       
  2320 					&& status != eap_status_success
       
  2321 					&& status != eap_status_pending_request
       
  2322 					&& status != eap_status_drop_packet_quietly)
       
  2323 				{
       
  2324 					eap_status_string_c status_string;
       
  2325 
       
  2326 					EAP_TRACE_ERROR(
       
  2327 						m_am_tools,
       
  2328 						TRACE_FLAGS_TLS_PEAP_ERROR,
       
  2329 						(EAPL("ERROR: eap_type_tls_peap_c::tls_peap_packet_process() ")
       
  2330 						 EAPL("failed, status %d=%s\n"),
       
  2331 						 status, status_string.get_status_string(status)));
       
  2332 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2333 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  2334 				}
       
  2335 			}
       
  2336 #if defined(USE_FAST_EAP_TYPE)
       
  2337 			else if (m_current_eap_type == eap_type_fast)
       
  2338 			{
       
  2339 				// In some cases EAP-FAST finishes only with plain text EAP-SUCCESS.
       
  2340 				// We must forward this to the tunneled EAP-type.
       
  2341 				status = m_tls_record->plain_eap_success_failure_packet_received(
       
  2342 					receive_network_id,
       
  2343 					eap_header->get_code(),
       
  2344 					eap_header->get_identifier());
       
  2345 
       
  2346 				if (status == eap_status_ok)
       
  2347 				{
       
  2348 					EAP_GENERAL_HEADER_SET_ERROR_DETECTED(eap_header, false);
       
  2349 				}
       
  2350 			}
       
  2351 #endif //#if defined(USE_FAST_EAP_TYPE)
       
  2352 			else if (get_state() == eap_type_tls_peap_state_waiting_for_success)
       
  2353 			{
       
  2354 				EAP_GENERAL_HEADER_SET_ERROR_DETECTED(eap_header, false);
       
  2355 
       
  2356 				if (m_wait_eap_success_packet == false)
       
  2357 				{
       
  2358 					/**
       
  2359 					 * @{ check right functionality.
       
  2360 					 * Here we return eap_status_ok, eap_status_success was
       
  2361 					 * returned after successfull
       
  2362 					 * EAP-Request/SIM/Challenge. This may change after EAP,
       
  2363 					 * 802.1X and 802.11i specifications are ready. }
       
  2364 					 */
       
  2365 					status = eap_status_ok;
       
  2366 				}
       
  2367 				else
       
  2368 				{
       
  2369 					if (m_current_eap_type == eap_type_tls)
       
  2370 					{
       
  2371 						status = finish_successful_authentication(false, false, true);
       
  2372 						if (status != eap_status_success)
       
  2373 						{
       
  2374 							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2375 							return EAP_STATUS_RETURN(m_am_tools, status);
       
  2376 						}
       
  2377 					}
       
  2378 					else
       
  2379 					{
       
  2380 						// We must forward this to the tunneled EAP-type.
       
  2381 
       
  2382 						status = m_tls_record->plain_eap_success_failure_packet_received(
       
  2383 							receive_network_id,
       
  2384 							eap_header->get_code(),
       
  2385 							eap_header->get_identifier());
       
  2386 
       
  2387 						if (status == eap_status_ok)
       
  2388 						{
       
  2389 							EAP_GENERAL_HEADER_SET_ERROR_DETECTED(eap_header, false);
       
  2390 						}
       
  2391 					}
       
  2392 				}
       
  2393 			}
       
  2394 			else if (get_state() == eap_type_tls_peap_state_success)
       
  2395 			{
       
  2396 				EAP_TRACE_DEBUG(
       
  2397 					m_am_tools,
       
  2398 					TRACE_FLAGS_DEFAULT,
       
  2399 					(EAPL("quietly dropped EAP-Success: code=0x%02x, identifier=0x%02x, ")
       
  2400 					 EAPL("length=0x%04x, state %d=%s, is client %d\n"),
       
  2401 					 eap_header->get_code(),
       
  2402 					 eap_header->get_identifier(),
       
  2403 					 eap_header->get_length(),
       
  2404 					 get_state(),
       
  2405 					 get_state_string(),
       
  2406 					 (m_is_client == true)));
       
  2407 				status = eap_status_drop_packet_quietly;
       
  2408 			}
       
  2409 			else
       
  2410 			{
       
  2411 				EAP_TRACE_DEBUG(
       
  2412 					m_am_tools,
       
  2413 					TRACE_FLAGS_DEFAULT,
       
  2414 					(EAPL("dropped EAP-Success: code=0x%02x, identifier=0x%02x, ")
       
  2415 					 EAPL("length=0x%04x, state %d=%s, is client %d\n"),
       
  2416 					 eap_header->get_code(),
       
  2417 					 eap_header->get_identifier(),
       
  2418 					 eap_header->get_length(),
       
  2419 					 get_state(),
       
  2420 					 get_state_string(),
       
  2421 					 (m_is_client == true)));
       
  2422 				status = eap_status_illegal_eap_code;
       
  2423 			}
       
  2424 		}
       
  2425 		else if (eap_header->get_code() == eap_code_failure)
       
  2426 		{
       
  2427 			// EAP is quite sloppy protocol.
       
  2428 			// Somebody just send a EAP-failure message and authentication is terminated.
       
  2429 
       
  2430 			// Save received failure. We do not change our state yet.
       
  2431 			// The real correct EAP message could be received later if this failure was
       
  2432 			// send by nasty attacker.
       
  2433 			set_failure_message_received();
       
  2434 			// We handle the EAP-Request/Failure message after a timeout.
       
  2435 
       
  2436 #if defined(USE_FAST_EAP_TYPE)
       
  2437 			if (m_current_eap_type == eap_type_fast)
       
  2438 			{
       
  2439 				// In some cases EAP-FAST finishes only with plain text EAP-SUCCESS.
       
  2440 				// We must forward this to the tunneled EAP-type.
       
  2441 				status = m_tls_record->plain_eap_success_failure_packet_received(
       
  2442 					receive_network_id,
       
  2443 					eap_header->get_code(),
       
  2444 					eap_header->get_identifier());
       
  2445 
       
  2446 				if (status == eap_status_ok)
       
  2447 				{
       
  2448 					EAP_GENERAL_HEADER_SET_ERROR_DETECTED(eap_header, false);
       
  2449 				}
       
  2450 			}
       
  2451 #endif //#if defined(USE_FAST_EAP_TYPE)
       
  2452 
       
  2453 			status = eap_status_ok;
       
  2454 		}
       
  2455 		else
       
  2456 		{
       
  2457 			EAP_TRACE_ERROR(
       
  2458 				m_am_tools,
       
  2459 				TRACE_FLAGS_DEFAULT,
       
  2460 				(EAPL("dropped EAP code unknown: code=0x%02x, identifier=0x%02x, ")
       
  2461 				 EAPL("length=0x%04x, is client %d\n"),
       
  2462 				 eap_header->get_code(),
       
  2463 				 eap_header->get_identifier(),
       
  2464 				 eap_header->get_length(),
       
  2465 				 (m_is_client == true)));
       
  2466 			status = eap_status_illegal_eap_code;
       
  2467 		}
       
  2468 	}
       
  2469 	else
       
  2470 	{
       
  2471 		EAP_TRACE_ERROR(
       
  2472 			m_am_tools,
       
  2473 			TRACE_FLAGS_DEFAULT,
       
  2474 			(EAPL("dropped EAP code unknown: code=0x%02x, identifier=0x%02x, ")
       
  2475 			 EAPL("length=0x%04x, is client %d\n"),
       
  2476 			 eap_header->get_code(),
       
  2477 			 eap_header->get_identifier(),
       
  2478 			 eap_header->get_length(),
       
  2479 			 (m_is_client == true)));
       
  2480 		status = eap_status_illegal_eap_code;
       
  2481 	}
       
  2482 
       
  2483 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2484 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2485 }
       
  2486 
       
  2487 //--------------------------------------------------
       
  2488 
       
  2489 //
       
  2490 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::send_empty_eap_ack()
       
  2491 {
       
  2492 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2493 
       
  2494 	EAP_TRACE_DEBUG(
       
  2495 		m_am_tools,
       
  2496 		TRACE_FLAGS_DEFAULT,
       
  2497 		(EAPL("EAP_type_TLS_PEAP: %s, %s: function: eap_type_tls_peap_c::send_empty_eap_ack()\n"),
       
  2498 		(m_is_client == true ? "client": "server"),
       
  2499 		(get_type_partner()->get_is_tunneled_eap() == true ? "tunneled" : "outer most")));
       
  2500 
       
  2501 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eap_type_tls_peap_c::send_empty_eap_ack()");
       
  2502 
       
  2503 	eap_buf_chain_wr_c eap_fragment_acknowledge_packet(
       
  2504 		eap_write_buffer, 
       
  2505 		m_am_tools, 
       
  2506 		TLS_PEAP_LOCAL_PACKET_BUFFER_LENGTH);
       
  2507 
       
  2508 	if (eap_fragment_acknowledge_packet.get_is_valid() == false)
       
  2509 	{
       
  2510 		EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("packet buffer corrupted.\n")));
       
  2511 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2512 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2513 	}
       
  2514 
       
  2515 	EAP_ASSERT_ALWAYS(TLS_PEAP_LOCAL_PACKET_BUFFER_LENGTH
       
  2516 					  >= (m_tls_peap_header_offset+m_trailer_length));
       
  2517 	u32_t packet_buffer_free = TLS_PEAP_LOCAL_PACKET_BUFFER_LENGTH-m_trailer_length;
       
  2518 	u32_t packet_buffer_offset = 0u;
       
  2519 
       
  2520 	if (m_tls_peap_header_offset+m_MTU < packet_buffer_free)
       
  2521 	{
       
  2522 		packet_buffer_free = m_tls_peap_header_offset+m_MTU;
       
  2523 	}
       
  2524 
       
  2525 	eap_tls_peap_header_c fragment_acknowledge(
       
  2526 		m_am_tools,
       
  2527 		eap_fragment_acknowledge_packet.get_data_offset(
       
  2528 			m_tls_peap_header_offset,
       
  2529 			(packet_buffer_free-m_tls_peap_header_offset)),
       
  2530 		(packet_buffer_free-m_tls_peap_header_offset));
       
  2531 
       
  2532 	if (fragment_acknowledge.get_is_valid() == false)
       
  2533 	{
       
  2534 		EAP_TRACE_ERROR(
       
  2535 			m_am_tools,
       
  2536 			TRACE_FLAGS_DEFAULT,
       
  2537 			(EAPL("packet_send: packet buffer corrupted.\n")));
       
  2538 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  2539 	}
       
  2540 
       
  2541 	fragment_acknowledge.reset_header(
       
  2542 		m_am_tools,
       
  2543 		m_current_eap_type,
       
  2544 		static_cast<u16_t>(packet_buffer_free-m_tls_peap_header_offset),
       
  2545 		m_current_peap_version,
       
  2546 		m_use_eap_expanded_type);
       
  2547 
       
  2548 	fragment_acknowledge.set_eap_length(
       
  2549 		static_cast<u16_t>(packet_buffer_free-m_tls_peap_header_offset),
       
  2550 		m_use_eap_expanded_type);
       
  2551 
       
  2552 	if (m_is_client == true)
       
  2553 	{
       
  2554 		fragment_acknowledge.set_eap_code(eap_code_response);
       
  2555 		fragment_acknowledge.set_eap_identifier(static_cast<u8_t>(get_last_eap_identifier()));
       
  2556 	}
       
  2557 	else // if (m_is_client == false)
       
  2558 	{
       
  2559 		fragment_acknowledge.set_eap_code(eap_code_request);
       
  2560 		fragment_acknowledge.set_eap_identifier(static_cast<u8_t>(get_last_eap_identifier()+1u));
       
  2561 	}
       
  2562 	fragment_acknowledge.set_eap_type(
       
  2563 		m_current_eap_type,
       
  2564 		m_use_eap_expanded_type);
       
  2565 
       
  2566 	u32_t tls_peap_data_offset = 0u;
       
  2567 
       
  2568 	update_buffer_indexes(
       
  2569 		TLS_PEAP_LOCAL_PACKET_BUFFER_LENGTH,
       
  2570 		m_tls_peap_header_offset+fragment_acknowledge.get_header_length(),
       
  2571 		&packet_buffer_offset,
       
  2572 		&packet_buffer_free);
       
  2573 
       
  2574 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  2575 
       
  2576 	// No payloads.
       
  2577 
       
  2578 	fragment_acknowledge.set_data_length(
       
  2579 		tls_peap_data_offset,
       
  2580 		m_use_eap_expanded_type);
       
  2581 	eap_fragment_acknowledge_packet.set_data_length(packet_buffer_offset);
       
  2582 
       
  2583 	EAP_ASSERT_ALWAYS(
       
  2584 		m_tls_peap_header_offset
       
  2585 		+fragment_acknowledge.get_header_length()
       
  2586 		+fragment_acknowledge.get_data_length()
       
  2587 		== packet_buffer_offset);
       
  2588 
       
  2589 	eap_status_e status = eap_status_process_general_error;
       
  2590 
       
  2591 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  2592 
       
  2593 	if (m_is_client == true)
       
  2594 	{
       
  2595 		EAP_TRACE_DATA_DEBUG(
       
  2596 			m_am_tools,
       
  2597 			TRACE_FLAGS_DEFAULT,
       
  2598 			(EAPL("    send: EAP-Response/TLS_PEAP/Acknowledge packet"),
       
  2599 			fragment_acknowledge.get_header_buffer(fragment_acknowledge.get_eap_length()),
       
  2600 			fragment_acknowledge.get_eap_length()));
       
  2601 	}
       
  2602 	else // if (m_is_client == false)
       
  2603 	{
       
  2604 		EAP_TRACE_DATA_DEBUG(
       
  2605 			m_am_tools,
       
  2606 			TRACE_FLAGS_DEFAULT,
       
  2607 			(EAPL("    send: EAP-Request/TLS_PEAP/Acknowledge packet"),
       
  2608 			fragment_acknowledge.get_header_buffer(fragment_acknowledge.get_eap_length()),
       
  2609 			fragment_acknowledge.get_eap_length()));
       
  2610 	}
       
  2611 
       
  2612 	status = packet_send(
       
  2613 		get_send_network_id(),
       
  2614 		&eap_fragment_acknowledge_packet,
       
  2615 		m_tls_peap_header_offset,
       
  2616 		fragment_acknowledge.get_eap_length(),
       
  2617 		TLS_PEAP_LOCAL_PACKET_BUFFER_LENGTH
       
  2618 		);
       
  2619 
       
  2620 	if (status == eap_status_ok)
       
  2621 	{
       
  2622 		if (m_is_client == false)
       
  2623 		{
       
  2624 			// Server saves the sent EAP-Identifier.
       
  2625 			set_last_eap_identifier(static_cast<u8_t>(get_last_eap_identifier()+1ul));
       
  2626 		}
       
  2627 	}
       
  2628 
       
  2629 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  2630 
       
  2631 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2632 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2633 }
       
  2634 
       
  2635 //--------------------------------------------------
       
  2636 
       
  2637 //
       
  2638 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::send_tls_peap_start_message(
       
  2639 	const u8_t next_eap_identifier, ///< This is EAP-Identifier of next EAP packet.
       
  2640 	const eap_variable_data_c * const authority_identity_payload
       
  2641 	)
       
  2642 {
       
  2643 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2644 
       
  2645 	EAP_TRACE_DEBUG(
       
  2646 		m_am_tools,
       
  2647 		TRACE_FLAGS_DEFAULT,
       
  2648 		(EAPL("EAP_type_TLS_PEAP: %s, %s: function: eap_type_tls_peap_c::send_tls_peap_start_message()\n"),
       
  2649 		(m_is_client == true ? "client": "server"),
       
  2650 		(get_type_partner()->get_is_tunneled_eap() == true ? "tunneled" : "outer most")));
       
  2651 
       
  2652 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eap_type_tls_peap_c::send_tls_peap_start_message()");
       
  2653 
       
  2654 	eap_buf_chain_wr_c eap_tls_start_packet(
       
  2655 		eap_write_buffer, 
       
  2656 		m_am_tools, 
       
  2657 		TLS_PEAP_LOCAL_PACKET_BUFFER_LENGTH);
       
  2658 
       
  2659 	if (eap_tls_start_packet.get_is_valid() == false)
       
  2660 	{
       
  2661 		EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("packet buffer corrupted.\n")));
       
  2662 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2663 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2664 	}
       
  2665 
       
  2666 	EAP_ASSERT_ALWAYS(TLS_PEAP_LOCAL_PACKET_BUFFER_LENGTH
       
  2667 					  >= (m_tls_peap_header_offset+m_trailer_length));
       
  2668 	u32_t packet_buffer_free = TLS_PEAP_LOCAL_PACKET_BUFFER_LENGTH-m_trailer_length;
       
  2669 	u32_t packet_buffer_offset = 0u;
       
  2670 
       
  2671 	if (m_tls_peap_header_offset+m_MTU < packet_buffer_free)
       
  2672 	{
       
  2673 		packet_buffer_free = m_tls_peap_header_offset+m_MTU;
       
  2674 	}
       
  2675 
       
  2676 	eap_tls_peap_header_c eap_tls_start_header(
       
  2677 		m_am_tools,
       
  2678 		eap_tls_start_packet.get_data_offset(
       
  2679 			m_tls_peap_header_offset,
       
  2680 			(packet_buffer_free-m_tls_peap_header_offset)),
       
  2681 		(packet_buffer_free-m_tls_peap_header_offset));
       
  2682 
       
  2683 	if (eap_tls_start_header.get_is_valid() == false)
       
  2684 	{
       
  2685 		EAP_TRACE_ERROR(
       
  2686 			m_am_tools,
       
  2687 			TRACE_FLAGS_DEFAULT,
       
  2688 			(EAPL("packet_send: packet buffer corrupted.\n")));
       
  2689 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  2690 	}
       
  2691 
       
  2692 	eap_tls_start_header.reset_header(
       
  2693 		m_am_tools,
       
  2694 		m_current_eap_type,
       
  2695 		static_cast<u16_t>(packet_buffer_free-m_tls_peap_header_offset),
       
  2696 		m_current_peap_version,
       
  2697 		m_use_eap_expanded_type);
       
  2698 
       
  2699 	eap_tls_start_header.set_flag_start(true);
       
  2700 	eap_tls_start_header.set_flag_tls_length_included(false);
       
  2701 
       
  2702 	eap_tls_start_header.set_eap_length(
       
  2703 		static_cast<u16_t>(
       
  2704 			packet_buffer_free-m_tls_peap_header_offset),
       
  2705 		m_use_eap_expanded_type);
       
  2706 
       
  2707 	eap_tls_start_header.set_eap_code(eap_code_request);
       
  2708 	eap_tls_start_header.set_eap_identifier(next_eap_identifier);
       
  2709 	eap_tls_start_header.set_eap_type(
       
  2710 		m_current_eap_type,
       
  2711 		m_use_eap_expanded_type);
       
  2712 
       
  2713 	update_buffer_indexes(
       
  2714 		TLS_PEAP_LOCAL_PACKET_BUFFER_LENGTH,
       
  2715 		m_tls_peap_header_offset+eap_tls_start_header.get_header_length(),
       
  2716 		&packet_buffer_offset,
       
  2717 		&packet_buffer_free);
       
  2718 
       
  2719 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  2720 
       
  2721 	eap_tls_start_header.set_data_length(
       
  2722 		0ul,
       
  2723 		m_use_eap_expanded_type);
       
  2724 	eap_tls_start_packet.set_data_length(packet_buffer_offset);
       
  2725 
       
  2726 	EAP_ASSERT_ALWAYS(
       
  2727 		m_tls_peap_header_offset+eap_tls_start_header.get_header_length()
       
  2728 		+eap_tls_start_header.get_data_length()
       
  2729 		== packet_buffer_offset);
       
  2730 
       
  2731 	eap_status_e status = eap_status_process_general_error;
       
  2732 
       
  2733 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  2734 	// Payload is optional authority identity (A-ID) that is used in EAP-FAST.
       
  2735 
       
  2736 	if (authority_identity_payload->get_data_length() > 0ul)
       
  2737 	{
       
  2738 		status = eap_tls_start_packet.add_data_to_offset(
       
  2739 			packet_buffer_offset,
       
  2740 			authority_identity_payload->get_data(),
       
  2741 			authority_identity_payload->get_data_length());
       
  2742 		if (status != eap_status_ok)
       
  2743 		{
       
  2744 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2745 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2746 		}
       
  2747 
       
  2748 		update_buffer_indexes(
       
  2749 			TLS_PEAP_LOCAL_PACKET_BUFFER_LENGTH,
       
  2750 			authority_identity_payload->get_data_length(),
       
  2751 			&packet_buffer_offset,
       
  2752 			&packet_buffer_free);
       
  2753 
       
  2754 		// - - - - - - - - - - - - - - - - - - - - - - - -
       
  2755 
       
  2756 		eap_tls_start_header.set_data_length(
       
  2757 			authority_identity_payload->get_data_length(),
       
  2758 			m_use_eap_expanded_type);
       
  2759 
       
  2760 		status = eap_tls_start_packet.set_data_length(packet_buffer_offset);
       
  2761 		if (status != eap_status_ok)
       
  2762 		{
       
  2763 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2764 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2765 		}
       
  2766 
       
  2767 		EAP_TRACE_DEBUG(
       
  2768 			m_am_tools,
       
  2769 			TRACE_FLAGS_DEFAULT,
       
  2770 			(EAPL("send_tls_peap_start_message(): m_tls_peap_header_offset %d ")
       
  2771 			 EAPL("+ eap_tls_start_header.get_header_length()")
       
  2772 			 EAPL("%d + eap_tls_start_header.get_data_length() ")
       
  2773 			 EAPL("%d = %d packet_buffer_offset %d.\n"),
       
  2774 			 m_tls_peap_header_offset,
       
  2775 			 eap_tls_start_header.get_header_length(),
       
  2776 			 eap_tls_start_header.get_data_length(),
       
  2777 			 (m_tls_peap_header_offset
       
  2778 			  + eap_tls_start_header.get_header_length()
       
  2779 			  + eap_tls_start_header.get_data_length()),
       
  2780 			 packet_buffer_offset));
       
  2781 
       
  2782 		EAP_ASSERT_ALWAYS(
       
  2783 			m_tls_peap_header_offset
       
  2784 			+eap_tls_start_header.get_header_length()
       
  2785 			+eap_tls_start_header.get_data_length()
       
  2786 			== packet_buffer_offset);
       
  2787 	}
       
  2788 
       
  2789 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  2790 
       
  2791 	EAP_TRACE_DATA_DEBUG(
       
  2792 		m_am_tools,
       
  2793 		TRACE_FLAGS_DEFAULT,
       
  2794 		(EAPL("    send: EAP-Request/TLS_PEAP/Start packet"),
       
  2795 		eap_tls_start_header.get_header_buffer(eap_tls_start_header.get_eap_length()),
       
  2796 		eap_tls_start_header.get_eap_length()));
       
  2797 
       
  2798 	status = packet_send(
       
  2799 		get_send_network_id(),
       
  2800 		&eap_tls_start_packet,
       
  2801 		m_tls_peap_header_offset,
       
  2802 		eap_tls_start_header.get_eap_length(),
       
  2803 		TLS_PEAP_LOCAL_PACKET_BUFFER_LENGTH
       
  2804 		);
       
  2805 
       
  2806 	if (status == eap_status_ok)
       
  2807 	{
       
  2808 		if (m_is_client == false)
       
  2809 		{
       
  2810 			// Server saves the sent EAP-Identifier.
       
  2811 			set_last_eap_identifier(next_eap_identifier);
       
  2812 		}
       
  2813 	}
       
  2814 
       
  2815 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  2816 
       
  2817 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2818 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2819 }
       
  2820 
       
  2821 //--------------------------------------------------
       
  2822 
       
  2823 //
       
  2824 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::start_tls_peap_authentication(
       
  2825 	const eap_variable_data_c * const received_authority_identity_payload
       
  2826 	)
       
  2827 {
       
  2828 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2829 
       
  2830 	EAP_TRACE_DEBUG(
       
  2831 		m_am_tools,
       
  2832 		TRACE_FLAGS_DEFAULT,
       
  2833 		(EAPL("EAP_type_TLS_PEAP: %s, %s: function: eap_type_tls_peap_c::start_tls_peap_authentication()\n"),
       
  2834 		(m_is_client == true ? "client": "server"),
       
  2835 		(get_type_partner()->get_is_tunneled_eap() == true ? "tunneled" : "outer most")));
       
  2836 
       
  2837 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eap_type_tls_peap_c::start_tls_peap_authentication()");
       
  2838 
       
  2839 	eap_status_e status = m_tls_record->start_tls_peap_authentication(received_authority_identity_payload);
       
  2840 
       
  2841 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2842 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2843 }
       
  2844 
       
  2845 //--------------------------------------------------
       
  2846 
       
  2847 //
       
  2848 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::eap_tls_peap_fragment_send()
       
  2849 {
       
  2850 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2851 
       
  2852 	EAP_TRACE_DEBUG(
       
  2853 		m_am_tools,
       
  2854 		TRACE_FLAGS_DEFAULT,
       
  2855 		(EAPL("EAP_type_TLS_PEAP: %s, %s: function: eap_type_tls_peap_c::eap_tls_peap_fragment_send()\n"),
       
  2856 		(m_is_client == true ? "client": "server"),
       
  2857 		(get_type_partner()->get_is_tunneled_eap() == true ? "tunneled" : "outer most")));
       
  2858 
       
  2859 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eap_type_tls_peap_c::eap_tls_peap_fragment_send()");
       
  2860 
       
  2861 	eap_status_e status = eap_status_not_supported;
       
  2862 
       
  2863 	if (m_tls_message_send_offset == 0ul
       
  2864 		&& m_tls_message_buffer.get_data_length()
       
  2865 		< tls_record_header_c::get_header_length())
       
  2866 	{
       
  2867 		EAP_TRACE_ERROR(
       
  2868 			m_am_tools,
       
  2869 			TRACE_FLAGS_DEFAULT,
       
  2870 			(EAPL("eap_tls_peap_fragment_send(): ")
       
  2871 			 EAPL("packet buffer too short, %d bytes.\n"),
       
  2872 			m_tls_message_buffer.get_data_length()));
       
  2873 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2874 	}
       
  2875 	else if (m_tls_message_buffer.get_data_length()
       
  2876 			 < m_tls_message_send_offset)
       
  2877 	{
       
  2878 		EAP_TRACE_ERROR(
       
  2879 			m_am_tools,
       
  2880 			TRACE_FLAGS_DEFAULT,
       
  2881 			(EAPL("eap_tls_peap_fragment_send(): ")
       
  2882 			 EAPL("packet buffer %d shorter than ")
       
  2883 			 EAPL("m_tls_message_send_offset %d.\n"),
       
  2884 			 m_tls_message_buffer.get_data_length(),
       
  2885 			 m_tls_message_send_offset));
       
  2886 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2887 	}
       
  2888 
       
  2889 
       
  2890 	eap_buf_chain_wr_c eap_tls_peap_fragment(
       
  2891 		eap_write_buffer, 
       
  2892 		m_am_tools, 
       
  2893 		EAP_MAX_LOCAL_PACKET_BUFFER_LENGTH);
       
  2894 
       
  2895 	if (eap_tls_peap_fragment.get_is_valid() == false)
       
  2896 	{
       
  2897 		EAP_TRACE_ERROR(
       
  2898 			m_am_tools,
       
  2899 			TRACE_FLAGS_DEFAULT,
       
  2900 			(EAPL("packet buffer corrupted.\n")));
       
  2901 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2902 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2903 	}
       
  2904 
       
  2905 	EAP_ASSERT_ALWAYS(EAP_MAX_LOCAL_PACKET_BUFFER_LENGTH
       
  2906 					  >= (m_tls_peap_header_offset+m_trailer_length));
       
  2907 	u32_t packet_buffer_free
       
  2908 		= EAP_MAX_LOCAL_PACKET_BUFFER_LENGTH-m_trailer_length;
       
  2909 	u32_t packet_buffer_offset = 0u;
       
  2910 
       
  2911 	if (m_tls_peap_header_offset+m_MTU < packet_buffer_free)
       
  2912 	{
       
  2913 		packet_buffer_free = m_tls_peap_header_offset+m_MTU;
       
  2914 	}
       
  2915 
       
  2916 	u32_t packet_eap_data_free
       
  2917 		= packet_buffer_free
       
  2918 		- m_tls_peap_header_offset
       
  2919 		- eap_tls_peap_header_c::get_tls_max_header_length();
       
  2920 
       
  2921 	eap_tls_peap_header_c eap_tls_packet(
       
  2922 		m_am_tools,
       
  2923 		eap_tls_peap_fragment.get_data_offset(
       
  2924 			m_tls_peap_header_offset,
       
  2925 			packet_eap_data_free),
       
  2926 		packet_eap_data_free);
       
  2927 
       
  2928 	if (eap_tls_packet.get_is_valid() == false)
       
  2929 	{
       
  2930 		EAP_TRACE_ERROR(
       
  2931 			m_am_tools,
       
  2932 			TRACE_FLAGS_DEFAULT,
       
  2933 			(EAPL("packet_send: packet buffer corrupted.\n")));
       
  2934 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  2935 	}
       
  2936 
       
  2937 	eap_tls_packet.reset_header(
       
  2938 		m_am_tools,
       
  2939 		m_current_eap_type,
       
  2940 		static_cast<u16_t>(packet_eap_data_free),
       
  2941 		m_current_peap_version,
       
  2942 		m_use_eap_expanded_type);
       
  2943 	if (m_tls_message_send_offset == 0)
       
  2944 	{
       
  2945 		// This is the first fragment.
       
  2946 		eap_tls_packet.set_flag_tls_length_included(true);
       
  2947 		eap_tls_packet.set_tls_message_length(
       
  2948 			m_tls_message_buffer.get_data_length());
       
  2949 	}
       
  2950 
       
  2951 	eap_tls_packet.set_eap_length(
       
  2952 		static_cast<u16_t>(packet_eap_data_free),
       
  2953 		m_use_eap_expanded_type);
       
  2954 
       
  2955 	if (m_is_client == true)
       
  2956 	{
       
  2957 		eap_tls_packet.set_eap_code(eap_code_response);
       
  2958 		eap_tls_packet.set_eap_identifier(get_last_eap_identifier());
       
  2959 	}
       
  2960 	else
       
  2961 	{
       
  2962 		eap_tls_packet.set_eap_code(eap_code_request);
       
  2963 		eap_tls_packet.set_eap_identifier(
       
  2964 			static_cast<u8_t>(get_last_eap_identifier()+1ul));
       
  2965 	}
       
  2966 	eap_tls_packet.set_eap_type(
       
  2967 		m_current_eap_type,
       
  2968 		m_use_eap_expanded_type);
       
  2969 
       
  2970 
       
  2971 	u32_t fragment_length
       
  2972 		= m_MTU
       
  2973 		- eap_tls_peap_header_c::get_tls_max_header_length();
       
  2974 	u32_t pending_message_length
       
  2975 		= m_tls_message_buffer.get_data_length()
       
  2976 		- m_tls_message_send_offset;
       
  2977 
       
  2978 	EAP_TRACE_DEBUG(
       
  2979 		m_am_tools,
       
  2980 		TRACE_FLAGS_DEFAULT,
       
  2981 		(EAPL("EAP-TLS fragment: packet_eap_data_free %d, ")
       
  2982 		 EAPL("fragment_length %d, pending_message_length %d, ")
       
  2983 		 EAPL("EAP-header length %d, buffer length %d\n"),
       
  2984 		 packet_eap_data_free,
       
  2985 		 fragment_length,
       
  2986 		 pending_message_length,
       
  2987 		 eap_tls_packet.get_header_length(),
       
  2988 		 eap_tls_peap_fragment.get_buffer_length()));
       
  2989 
       
  2990 	if (packet_eap_data_free >= pending_message_length)
       
  2991 	{
       
  2992 		// Message data is less than the buffer length,
       
  2993 		// so the fragment is only length of the message data.
       
  2994 		fragment_length = pending_message_length;
       
  2995 
       
  2996 		if (m_tls_message_send_offset == 0
       
  2997 			&& m_use_tppd_tls_peap == true
       
  2998 			&& m_includes_tls_handshake_message == true
       
  2999 #if defined(USE_FAST_EAP_TYPE)
       
  3000 			&& m_current_eap_type != eap_type_fast
       
  3001 #endif //#if defined(USE_FAST_EAP_TYPE)
       
  3002 			)
       
  3003 		{
       
  3004 			// TLS-message length is included,
       
  3005 			// even no fragmentation is used.
       
  3006 			eap_tls_packet.set_flag_tls_length_included(true);
       
  3007 		}
       
  3008 		else
       
  3009 		{
       
  3010 			// TLS-message length is not included,
       
  3011 			// because no fragmentation is used.
       
  3012 			eap_tls_packet.set_flag_tls_length_included(false);
       
  3013 		}
       
  3014 
       
  3015 		EAP_TRACE_DEBUG(
       
  3016 			m_am_tools,
       
  3017 			TRACE_FLAGS_DEFAULT,
       
  3018 			(EAPL("EAP-TLS fragment: packet_eap_data_free %d, ")
       
  3019 			 EAPL("fragment_length %d, pending_message_length %d, ")
       
  3020 			 EAPL("EAP-header length %d\n"),
       
  3021 			 packet_eap_data_free,
       
  3022 			 fragment_length,
       
  3023 			 pending_message_length,
       
  3024 			 eap_tls_packet.get_header_length()));
       
  3025 	}
       
  3026 
       
  3027 	if (fragment_length < pending_message_length)
       
  3028 	{
       
  3029 		EAP_TRACE_DEBUG(
       
  3030 			m_am_tools,
       
  3031 			TRACE_FLAGS_DEFAULT,
       
  3032 			(EAPL("EAP-TLS fragment: more fragments follow. ")
       
  3033 			 EAPL("fragment_length %d, pending_message_length %d, ")
       
  3034 			 EAPL("EAP-header length %d\n"),
       
  3035 			 fragment_length,
       
  3036 			 pending_message_length,
       
  3037 			 eap_tls_packet.get_header_length()));
       
  3038 
       
  3039 		eap_tls_packet.set_flag_more_fragments(true);
       
  3040 	}
       
  3041 
       
  3042 
       
  3043 	update_buffer_indexes(
       
  3044 		TLS_PEAP_LOCAL_PACKET_BUFFER_LENGTH,
       
  3045 		m_tls_peap_header_offset+eap_tls_packet.get_header_length(),
       
  3046 		&packet_buffer_offset,
       
  3047 		&packet_buffer_free);
       
  3048 
       
  3049 	status = eap_tls_peap_fragment.set_data_length(packet_buffer_offset);
       
  3050 	if (status != eap_status_ok)
       
  3051 	{
       
  3052 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3053 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3054 	}
       
  3055 
       
  3056 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  3057 	// Payload is TLS-message fragment.
       
  3058 
       
  3059 	status = eap_tls_peap_fragment.add_data_to_offset(
       
  3060 		packet_buffer_offset,
       
  3061 		m_tls_message_buffer.get_data_offset(
       
  3062 			m_tls_message_send_offset, fragment_length),
       
  3063 		fragment_length);
       
  3064 	if (status != eap_status_ok)
       
  3065 	{
       
  3066 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3067 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3068 	}
       
  3069 
       
  3070 	update_buffer_indexes(
       
  3071 		TLS_PEAP_LOCAL_PACKET_BUFFER_LENGTH,
       
  3072 		fragment_length,
       
  3073 		&packet_buffer_offset,
       
  3074 		&packet_buffer_free);
       
  3075 
       
  3076 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  3077 
       
  3078 	eap_tls_packet.set_data_length(
       
  3079 		fragment_length,
       
  3080 		m_use_eap_expanded_type);
       
  3081 
       
  3082 	status = eap_tls_peap_fragment.set_data_length(packet_buffer_offset);
       
  3083 	if (status != eap_status_ok)
       
  3084 	{
       
  3085 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3086 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3087 	}
       
  3088 
       
  3089 	EAP_TRACE_DEBUG(
       
  3090 		m_am_tools,
       
  3091 		TRACE_FLAGS_DEFAULT,
       
  3092 		(EAPL("eap_tls_peap_fragment_send(): m_tls_peap_header_offset %d ")
       
  3093 		 EAPL("+ eap_tls_packet.get_header_length()")
       
  3094 		 EAPL("%d + eap_tls_packet.get_data_length() ")
       
  3095 		 EAPL("%d = %d == packet_buffer_offset %d.\n"),
       
  3096 		 m_tls_peap_header_offset,
       
  3097 		 eap_tls_packet.get_header_length(),
       
  3098 		 eap_tls_packet.get_data_length(),
       
  3099 		 (m_tls_peap_header_offset
       
  3100 		  + eap_tls_packet.get_header_length()
       
  3101 		  + eap_tls_packet.get_data_length()),
       
  3102 		 packet_buffer_offset));
       
  3103 
       
  3104 	EAP_ASSERT_ALWAYS(
       
  3105 		m_tls_peap_header_offset
       
  3106 		+eap_tls_packet.get_header_length()
       
  3107 		+eap_tls_packet.get_data_length()
       
  3108 		== packet_buffer_offset);
       
  3109 
       
  3110 	status = eap_status_process_general_error;
       
  3111 
       
  3112 	// - - - - - - - - - - - - - - - - - - - - - - - -
       
  3113 
       
  3114 	status = packet_send(
       
  3115 		get_send_network_id(),
       
  3116 		&eap_tls_peap_fragment,
       
  3117 		m_tls_peap_header_offset,
       
  3118 		eap_tls_packet.get_eap_length(),
       
  3119 		TLS_PEAP_LOCAL_PACKET_BUFFER_LENGTH
       
  3120 		);
       
  3121 
       
  3122 	if (status == eap_status_ok)
       
  3123 	{
       
  3124 		m_tls_message_send_offset += fragment_length;
       
  3125 
       
  3126 		if (m_is_client == false)
       
  3127 		{
       
  3128 			// Server saves the sent EAP-Identifier.
       
  3129 			set_last_eap_identifier(
       
  3130 				static_cast<u8_t>(get_last_eap_identifier()+1ul));
       
  3131 		}
       
  3132 	}
       
  3133 
       
  3134 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3135 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3136 }
       
  3137 
       
  3138 //--------------------------------------------------
       
  3139 
       
  3140 //
       
  3141 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::tls_message_process(
       
  3142 	const eap_am_network_id_c * const /*receive_network_id*/, ///< This is the network identity of the received EAP packet.
       
  3143 	eap_tls_peap_header_c * const received_tls_peap, ///< This is pointer to EAP header including EAP-TLS/PEAP fields.
       
  3144 	const u32_t /*tls_peap_packet_length*/ ///< This is length of received TLS/PEAP EAP packet.
       
  3145 	)
       
  3146 {
       
  3147 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3148 
       
  3149 	EAP_TRACE_DEBUG(
       
  3150 		m_am_tools,
       
  3151 		TRACE_FLAGS_DEFAULT,
       
  3152 		(EAPL("EAP_type_TLS_PEAP: %s, %s: function: eap_type_tls_peap_c::tls_message_process()\n"),
       
  3153 		(m_is_client == true ? "client": "server"),
       
  3154 		(get_type_partner()->get_is_tunneled_eap() == true ? "tunneled" : "outer most")));
       
  3155 
       
  3156 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eap_type_tls_peap_c::tls_message_process()");
       
  3157 
       
  3158 	if (m_tls_message_buffer.get_is_valid_data() == false)
       
  3159 	{
       
  3160 		EAP_TRACE_ERROR(
       
  3161 			m_am_tools,
       
  3162 			TRACE_FLAGS_DEFAULT,
       
  3163 			(EAPL("tls_message_process: packet buffer invalid.\n")));
       
  3164 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3165 	}
       
  3166 
       
  3167 	if (m_tls_message_buffer.get_data_length() < tls_record_header_c::get_header_length())
       
  3168 	{
       
  3169 		EAP_TRACE_ERROR(
       
  3170 			m_am_tools,
       
  3171 			TRACE_FLAGS_DEFAULT,
       
  3172 			(EAPL("tls_message_process: packet buffer too short, %d bytes.\n"),
       
  3173 			m_tls_message_buffer.get_data_length()));
       
  3174 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3175 	}
       
  3176 
       
  3177 	save_current_state();
       
  3178 	set_state(eap_type_tls_peap_state_process_tls_message);
       
  3179 
       
  3180 	eap_status_e status = m_tls_record->packet_process(
       
  3181 		&m_tls_message_buffer,
       
  3182 		received_tls_peap->get_eap_identifier());
       
  3183 
       
  3184 	if (status == eap_status_ok)
       
  3185 	{
       
  3186 		// Do nothing.
       
  3187 	}
       
  3188 	else if (status == eap_status_pending_request)
       
  3189 	{
       
  3190 		// Asyncronous operation is pending.
       
  3191 		// Do nothing.
       
  3192 	}
       
  3193 	else if (status == eap_status_success)
       
  3194 	{
       
  3195 		// Authentication OK.
       
  3196 		// Do nothing.
       
  3197 	}
       
  3198 	else if (status == eap_status_drop_packet_quietly)
       
  3199 	{
       
  3200 		// Dropped packet.
       
  3201 		// Do nothing.
       
  3202 	}
       
  3203 	else
       
  3204 	{
       
  3205 		// All other return values are ERROR. Authentication is failed.
       
  3206 
       
  3207 		EAP_TRACE_ERROR(
       
  3208 			m_am_tools,
       
  3209 			TRACE_FLAGS_DEFAULT,
       
  3210 			(EAPL("%s: tls_message_process: Authentication failed.\n"),
       
  3211 			(m_is_client == true) ? "client": "server"));
       
  3212 
       
  3213 		restore_saved_previous_state();
       
  3214 		set_state(eap_type_tls_peap_state_failure);
       
  3215 	}
       
  3216 
       
  3217 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3218 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  3219 }
       
  3220 
       
  3221 //--------------------------------------------------
       
  3222 
       
  3223 //
       
  3224 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::eap_identity_response_packet_process(
       
  3225 	const eap_am_network_id_c * const /*receive_network_id*/, ///< This is the network identity of the received EAP packet.
       
  3226 	eap_header_wr_c * const eap_header, ///< This is pointer to EAP header and data.
       
  3227 	const u32_t eap_packet_length ///< This is length of received EAP packet.
       
  3228 	)
       
  3229 {
       
  3230 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3231 
       
  3232 	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
       
  3233 	EAP_TRACE_DEBUG(
       
  3234 		m_am_tools,
       
  3235 		TRACE_FLAGS_DEFAULT,
       
  3236 		(EAPL("EAP_type_TLS_PEAP: %s: function: eap_type_tls_peap_c::eap_identity_response_packet_process()\n"),
       
  3237 		(m_is_client == true ? "client": "server")));
       
  3238 
       
  3239 	if (eap_header->check_header() != eap_status_ok)
       
  3240 	{
       
  3241 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3242 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3243 	}
       
  3244 	else if (eap_header->get_length() > eap_packet_length)
       
  3245 	{
       
  3246 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3247 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3248 	}
       
  3249 
       
  3250 
       
  3251 	if (m_check_identifier_of_eap_identity_response == true)
       
  3252 	{
       
  3253 		if (m_state == eap_type_tls_peap_state_waiting_for_identity_response
       
  3254 			&& eap_header->get_identifier() != get_last_eap_identifier())
       
  3255 		{
       
  3256 			// Wrong EAP-Identifier in this state.
       
  3257 			EAP_TRACE_ERROR(
       
  3258 				m_am_tools,
       
  3259 				TRACE_FLAGS_TLS_PEAP_ERROR,
       
  3260 				(EAPL("ERROR: eap_type_tls_peap_c::handle_identity_response_message(): ")
       
  3261 				 EAPL("EAP-Identifier 0x%02x is wrong (0x%02x is correct) in ")
       
  3262 				 EAPL("eap_type_tls_peap_state_variable_e %d=%s.\n"),
       
  3263 				 eap_header->get_identifier(),
       
  3264 				 get_last_eap_identifier(),
       
  3265 				 get_state(),
       
  3266 				 get_state_string()));
       
  3267 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3268 			return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_identity);
       
  3269 		}
       
  3270 		else if (m_tls_peap_test_version == true
       
  3271 			&& m_state == eap_type_tls_peap_state_success) // This one is for testing purposes.
       
  3272 		{
       
  3273 			// NOTE here we can not check the EAP-identifier.
       
  3274 			EAP_TRACE_DEBUG(
       
  3275 				m_am_tools,
       
  3276 				TRACE_FLAGS_DEFAULT,
       
  3277 				(EAPL("WARNING: eap_type_tls_peap_c::handle_identity_response_message(): ")
       
  3278 				 EAPL("EAP-Identifier 0x%02x is not checked in ")
       
  3279 				 EAPL("eap_type_tls_peap_state_variable_e %d=%s.\n"),
       
  3280 				 eap_header->get_identifier(),
       
  3281 				 get_state(),
       
  3282 				 get_state_string()));
       
  3283 		}
       
  3284 	}
       
  3285 
       
  3286 
       
  3287 	if ((m_state == eap_type_tls_peap_state_waiting_for_identity_response
       
  3288 			|| m_state == eap_type_tls_peap_state_waiting_for_first_response)
       
  3289 		|| (m_tls_peap_test_version == true
       
  3290 			// In test version new authentication could start from this state.
       
  3291 			&& m_state == eap_type_tls_peap_state_success))
       
  3292 	{
       
  3293 		// EAP-Response/Identity is accepted only as a very first message.
       
  3294 
       
  3295 		eap_status_e status = eap_status_process_general_error;
       
  3296 
       
  3297 		save_current_state();
       
  3298 
       
  3299 		// In test version new authentication could start from this state.
       
  3300 		if (m_tls_peap_test_version == true
       
  3301 			&& m_state == eap_type_tls_peap_state_success) // This one is for testing purposes.
       
  3302 		{
       
  3303 			// NOTE here we can not check the EAP-identifier.
       
  3304 			set_state(eap_type_tls_peap_state_waiting_for_identity_response);
       
  3305 		}
       
  3306 
       
  3307 		u8_t next_eap_identifier = static_cast<u8_t>(eap_header->get_identifier()+1u);
       
  3308 
       
  3309 		status = parse_identity(
       
  3310 			eap_header->get_type_data(
       
  3311 				eap_header->get_type_data_length()),
       
  3312 			eap_header->get_type_data_length());
       
  3313 		if (status != eap_status_ok)
       
  3314 		{
       
  3315 			restore_saved_previous_state();
       
  3316 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3317 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  3318 		}
       
  3319 
       
  3320 		eap_variable_data_c authority_identity_payload(m_am_tools);
       
  3321 		if (authority_identity_payload.get_is_valid() == false)
       
  3322 		{
       
  3323 			restore_saved_previous_state();
       
  3324 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3325 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  3326 		}
       
  3327 
       
  3328 #if defined(USE_FAST_EAP_TYPE)
       
  3329 		if (m_current_eap_type == eap_type_fast)
       
  3330 		{
       
  3331 			// Read the authority identity (A-ID).
       
  3332 			status = m_tls_record->read_authority_identity(&authority_identity_payload);
       
  3333 			if (status != eap_status_ok)
       
  3334 			{
       
  3335 				restore_saved_previous_state();
       
  3336 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3337 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  3338 			}
       
  3339 		}
       
  3340 #endif //#if defined(USE_FAST_EAP_TYPE)
       
  3341 
       
  3342 		status = send_tls_peap_start_message(next_eap_identifier, &authority_identity_payload);
       
  3343 		if (status != eap_status_ok)
       
  3344 		{
       
  3345 			restore_saved_previous_state();
       
  3346 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3347 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  3348 		}
       
  3349 
       
  3350 		set_last_eap_identifier(next_eap_identifier);
       
  3351 		set_state(eap_type_tls_peap_state_waiting_for_first_response);
       
  3352 
       
  3353 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3354 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  3355 	}
       
  3356 	else
       
  3357 	{
       
  3358 		EAP_TRACE_ERROR(
       
  3359 			m_am_tools,
       
  3360 			TRACE_FLAGS_DEFAULT,
       
  3361 			(EAPL("ERROR: eap_type_tls_peap_c::handle_identity_response_message(): ")
       
  3362 			 EAPL("EAP-Identifier 0x%02x in eap_type_tls_peap_state_variable_e %d=%s. ")
       
  3363 			 EAPL("EAP-Response/Identity is accepted only in ")
       
  3364 			 EAPL("eap_type_tls_peap_state_waiting_for_identity_response.\n"),
       
  3365 			 eap_header->get_identifier(),
       
  3366 			 get_state(),
       
  3367 			 get_state_string()));
       
  3368 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3369 		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
       
  3370 	}
       
  3371 }
       
  3372 
       
  3373 //--------------------------------------------------
       
  3374 
       
  3375 //
       
  3376 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::select_peap_version(
       
  3377 	const u32_t proposed_peap_version)
       
  3378 {
       
  3379 	u32_t version_count = m_accepted_PEAP_versions.get_data_length() / sizeof(u32_t);
       
  3380 
       
  3381 	eap_tls_trace_string_c tls_trace;
       
  3382 
       
  3383 	EAP_TRACE_DEBUG(
       
  3384 		m_am_tools,
       
  3385 		TRACE_FLAGS_DEFAULT,
       
  3386 		(EAPL("this = 0x%08x, eap_type_tls_peap_c::select_peap_version(): ")
       
  3387 		 EAPL("%s: Current PEAP version %d=%s, proposed PEAP version %d=%s.\n"),
       
  3388 		 this,
       
  3389 		 (m_is_client == true ? "client": "server"),
       
  3390 		 m_current_peap_version,
       
  3391 		 tls_trace.get_peap_version_string(m_current_peap_version),
       
  3392 		 proposed_peap_version,
       
  3393 		 tls_trace.get_peap_version_string(static_cast<peap_version_e>(proposed_peap_version))));
       
  3394 
       
  3395 	// Note some PEAP version was set before PEAP actually starts.
       
  3396 	// Here we disable the default selection.
       
  3397 	m_current_peap_version = peap_version_none;
       
  3398 
       
  3399 	u32_t *p_accepted_peap_versions
       
  3400 		= reinterpret_cast<u32_t *>(m_accepted_PEAP_versions.get_data(
       
  3401 			m_accepted_PEAP_versions.get_data_length()));
       
  3402 	if (p_accepted_peap_versions == 0)
       
  3403 	{
       
  3404 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3405 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  3406 	}
       
  3407 
       
  3408 	u32_t highest_supported_version = peap_version_none;
       
  3409 
       
  3410 	for (u32_t ind = 0; ind < version_count; ind++)
       
  3411 	{
       
  3412 		if (highest_supported_version == peap_version_none
       
  3413 			|| highest_supported_version < p_accepted_peap_versions[ind])
       
  3414 		{
       
  3415 			highest_supported_version = p_accepted_peap_versions[ind];
       
  3416 		}
       
  3417 
       
  3418 		if (proposed_peap_version == p_accepted_peap_versions[ind])
       
  3419 		{
       
  3420 			m_current_peap_version = static_cast<peap_version_e>(proposed_peap_version);
       
  3421 
       
  3422 			EAP_TRACE_DEBUG(
       
  3423 				m_am_tools,
       
  3424 				TRACE_FLAGS_DEFAULT,
       
  3425 				(EAPL("eap_type_tls_peap_c::select_peap_version(): ")
       
  3426 				 EAPL("%s: Accepted PEAP version %d=%s.\n"),
       
  3427 					(m_is_client == true ? "client": "server"),
       
  3428 					m_current_peap_version,
       
  3429 					tls_trace.get_peap_version_string(m_current_peap_version)));
       
  3430 			break;
       
  3431 		}
       
  3432 	} // for()
       
  3433 
       
  3434 	// Because no matching PEAP version was not found,
       
  3435 	// we must use the highest version version we support.
       
  3436 	if (m_current_peap_version != peap_version_none)
       
  3437 	{
       
  3438 		// OK, proposed version accepted.
       
  3439 	}
       
  3440 	else if (highest_supported_version != peap_version_none)
       
  3441 	{
       
  3442 		m_current_peap_version = static_cast<peap_version_e>(highest_supported_version);
       
  3443 
       
  3444 		EAP_TRACE_DEBUG(
       
  3445 			m_am_tools,
       
  3446 			TRACE_FLAGS_DEFAULT,
       
  3447 			(EAPL("eap_type_tls_peap_c::select_peap_version(): ")
       
  3448 			 EAPL("%s: Highest supported PEAP version %d=%s.\n"),
       
  3449 				(m_is_client == true ? "client": "server"),
       
  3450 				m_current_peap_version,
       
  3451 				tls_trace.get_peap_version_string(m_current_peap_version)));
       
  3452 	}
       
  3453 	else
       
  3454 	{
       
  3455 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3456 		return EAP_STATUS_RETURN(m_am_tools, eap_status_no_matching_protocol_version);
       
  3457 	}
       
  3458 
       
  3459 	m_tls_record->set_peap_version(
       
  3460 		m_current_peap_version,
       
  3461 		m_use_tppd_tls_peap,
       
  3462 		m_use_tppd_peapv1_acknowledge_hack);
       
  3463 
       
  3464 	if (m_is_client == false
       
  3465 		&& static_cast<peap_version_e>(proposed_peap_version) != m_current_peap_version)
       
  3466 	{
       
  3467 		// Server does not accept PEAP version client proposes.
       
  3468 		// Server terminates the session immediately.
       
  3469 		get_type_partner()->set_session_timeout(0ul);
       
  3470 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3471 		return EAP_STATUS_RETURN(m_am_tools, eap_status_no_matching_protocol_version);
       
  3472 	}
       
  3473 
       
  3474 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3475 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  3476 }
       
  3477 
       
  3478 //--------------------------------------------------
       
  3479 
       
  3480 //
       
  3481 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::tls_peap_packet_process(
       
  3482 	const eap_am_network_id_c * const receive_network_id, ///< This is the network identity of the received EAP packet.
       
  3483 	eap_tls_peap_header_c * const received_tls_peap, ///< This is pointer to EAP header including EAP-TLS/PEAP fields.
       
  3484 	const u32_t tls_peap_packet_length ///< This is length of received TLS/PEAP EAP packet.
       
  3485 	)
       
  3486 {
       
  3487 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3488 
       
  3489 	EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n")));
       
  3490 	EAP_TRACE_DEBUG(
       
  3491 		m_am_tools,
       
  3492 		TRACE_FLAGS_DEFAULT,
       
  3493 		(EAPL("EAP_type_TLS_PEAP: this = 0x%08x, %s, %s, function: eap_type_tls_peap_c::tls_peap_packet_process()\n"),
       
  3494 		 this,
       
  3495 		 (m_is_client == true ? "client": "server"),
       
  3496 		 (get_type_partner()->get_is_tunneled_eap() == true ? "tunneled" : "outer most")));
       
  3497 
       
  3498 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eap_type_tls_peap_c::tls_peap_packet_process()");
       
  3499 
       
  3500 	if (m_tls_peap_test_version == true
       
  3501 		&& get_state() == eap_type_tls_peap_state_failure)
       
  3502 	{
       
  3503 		// This is for testing.
       
  3504 		if (m_is_client == false
       
  3505 			&& received_tls_peap->get_eap_code() == eap_code_response
       
  3506 			&& received_tls_peap->get_eap_type() == eap_type_identity)
       
  3507 		{
       
  3508 			set_state(eap_type_tls_peap_state_waiting_for_identity_response);
       
  3509 		}
       
  3510 		else if (m_is_client == true
       
  3511 				&& received_tls_peap->get_flag_start() == true)
       
  3512 		{
       
  3513 			set_state(eap_type_tls_peap_state_waiting_for_tls_start);
       
  3514 		}
       
  3515 	}
       
  3516 
       
  3517 	if (received_tls_peap->check_header(
       
  3518 			m_am_tools,
       
  3519 			m_current_eap_type,
       
  3520 			m_is_client,
       
  3521 			peap_version_0_xp,
       
  3522 			true) != eap_status_ok
       
  3523 		&& received_tls_peap->check_header(
       
  3524 			m_am_tools,
       
  3525 			m_current_eap_type,
       
  3526 			m_is_client,
       
  3527 			peap_version_1,
       
  3528 			true) != eap_status_ok
       
  3529 		&& received_tls_peap->check_header(
       
  3530 			m_am_tools,
       
  3531 			m_current_eap_type,
       
  3532 			m_is_client,
       
  3533 			peap_version_2,
       
  3534 			true) != eap_status_ok)
       
  3535 	{
       
  3536 		// ERROR: EAP-TLS/PEAP header is corrupted.
       
  3537 		EAP_TRACE_ERROR(
       
  3538 			m_am_tools,
       
  3539 			TRACE_FLAGS_TLS_PEAP_ERROR,
       
  3540 			(EAPL("ERROR: eap_type_tls_peap_c::tls_peap_packet_process(): ")
       
  3541 			 EAPL("EAP-TLS/PEAP header is corrupted in ")
       
  3542 			 EAPL("eap_type_tls_peap_state_variable_e %d=%s.\n"),
       
  3543 			get_state(),
       
  3544 			get_state_string()));
       
  3545 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3546 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3547 	}
       
  3548 	else if (received_tls_peap->get_eap_length() > tls_peap_packet_length)
       
  3549 	{
       
  3550 		// ERROR: EAP-Lenght field value is larger than actual received packet.
       
  3551 		EAP_TRACE_ERROR(
       
  3552 			m_am_tools,
       
  3553 			TRACE_FLAGS_TLS_PEAP_ERROR,
       
  3554 			(EAPL("ERROR: eap_type_tls_peap_c::tls_peap_packet_process(): ")
       
  3555 			 EAPL("EAP-Lenght field %d value is larger than actual received ")
       
  3556 			 EAPL("packet %d in eap_type_tls_peap_state_variable_e %d=%s.\n"),
       
  3557 			received_tls_peap->get_eap_length(),
       
  3558 			tls_peap_packet_length,
       
  3559 			get_state(),
       
  3560 			get_state_string()));
       
  3561 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3562 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3563 	}
       
  3564 	else if (m_is_client == false
       
  3565 		&& received_tls_peap->get_flag_start() == true)
       
  3566 	{
       
  3567 		// ERROR: Server cannot receive EAP-TLS/PEAP Start message.
       
  3568 		EAP_TRACE_ERROR(
       
  3569 			m_am_tools,
       
  3570 			TRACE_FLAGS_TLS_PEAP_ERROR,
       
  3571 			(EAPL("ERROR: eap_type_tls_peap_c::tls_peap_packet_process(): ")
       
  3572 			 EAPL("Server cannot receive EAP-TLS/PEAP Start message. ")
       
  3573 			 EAPL("eap_type_tls_peap_state_variable_e %d=%s.\n"),
       
  3574 			get_state(),
       
  3575 			get_state_string()));
       
  3576 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3577 		return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
       
  3578 	}
       
  3579 	else if (m_is_client == true
       
  3580 		&& (get_state() != eap_type_tls_peap_state_waiting_for_request
       
  3581 			&& get_state() != eap_type_tls_peap_state_waiting_for_identity_request
       
  3582 			// EAP-TLS could start without EAP-Request/Identity message.
       
  3583 			&& get_state() != eap_type_tls_peap_state_waiting_for_tls_start
       
  3584 			&& get_state()
       
  3585 			!= eap_type_tls_peap_state_tppd_peapv1_waits_eap_success_or_tunneled_packet
       
  3586 			))
       
  3587 	{
       
  3588 		// ERROR: Client cannot receive EAP-TLS/PEAP message in other states.
       
  3589 		EAP_TRACE_DEBUG(
       
  3590 			m_am_tools,
       
  3591 			TRACE_FLAGS_DEFAULT,
       
  3592 			(EAPL("WARNING: eap_type_tls_peap_c::tls_peap_packet_process(): ")
       
  3593 			 EAPL("Client cannot receive EAP-TLS/PEAP message in ")
       
  3594 			 EAPL("eap_type_tls_peap_state_variable_e %d=%s.\n"),
       
  3595 			get_state(),
       
  3596 			get_state_string()));
       
  3597 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3598 		return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
       
  3599 	}
       
  3600 	else if (m_is_client == false
       
  3601 		&& get_state() != eap_type_tls_peap_state_waiting_for_response
       
  3602 		&& get_state() != eap_type_tls_peap_state_waiting_for_first_response
       
  3603 		&& get_state() != eap_type_tls_peap_state_waiting_for_empty_response
       
  3604 		&& get_state() != eap_type_tls_peap_state_waiting_for_empty_tppd_peap_v1_acknowledge
       
  3605 #if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
       
  3606 		&& get_state() != eap_type_tls_peap_state_server_waits_ttls_plain_ms_chap_v2_empty_ack
       
  3607 #endif //#if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
       
  3608 		)
       
  3609 	{
       
  3610 		// WARNING: Server cannot receive EAP-TLS/PEAP message in other states.
       
  3611 		// This packet is dropped quietly.
       
  3612 		EAP_TRACE_DEBUG(
       
  3613 			m_am_tools,
       
  3614 			TRACE_FLAGS_DEFAULT,
       
  3615 			(EAPL("WARNING: eap_type_tls_peap_c::tls_peap_packet_process(): ")
       
  3616 			 EAPL("Server cannot receive EAP-TLS/PEAP message in ")
       
  3617 			 EAPL("eap_type_tls_peap_state_variable_e %d=%s.\n"),
       
  3618 			get_state(),
       
  3619 			get_state_string()));
       
  3620 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3621 		return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
       
  3622 	}
       
  3623 	else if (received_tls_peap->get_flag_start() == true
       
  3624 		&& get_state() != eap_type_tls_peap_state_waiting_for_tls_start
       
  3625 		&& get_state() != eap_type_tls_peap_state_waiting_for_identity_request)
       
  3626 		// EAP-TLS could start without EAP-Request/Identity message.
       
  3627 	{
       
  3628 		// ERROR: EAP-TLS/PEAP Start message is accepted only in
       
  3629 		// eap_type_tls_peap_state_waiting_for_tls_start.
       
  3630 		EAP_TRACE_ERROR(
       
  3631 			m_am_tools,
       
  3632 			TRACE_FLAGS_TLS_PEAP_ERROR,
       
  3633 			(EAPL("ERROR: eap_type_tls_peap_c::tls_peap_packet_process(): ")
       
  3634 			 EAPL("EAP-TLS/PEAP Start message is NOT accepted in ")
       
  3635 			 EAPL("eap_type_tls_peap_state_variable_e %d=%s.\n"),
       
  3636 			get_state(),
       
  3637 			get_state_string()));
       
  3638 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3639 		return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
       
  3640 	}
       
  3641 
       
  3642 	// EAP-TLS and PEAP fragmentation support:
       
  3643 	// 
       
  3644 	// Flags include the Length included (L), More fragments (M), and EAP-TLS Start (S) bits.
       
  3645 	// 
       
  3646 	// The L flag is set to indicate the presence of the four octet TLS Message
       
  3647 	// Length field, and MUST be set for the first fragment of a fragmented
       
  3648 	// TLS message or set of messages.
       
  3649 	// 
       
  3650 	// The M flag is set on all but the last fragment.
       
  3651 	// 
       
  3652 	// The S flag is set only within the EAP-TLS start message
       
  3653 	// sent from the EAP server to the peer. This differentiates
       
  3654 	// the EAP-TLS Start message from a fragment acknowledgement.
       
  3655 	// 
       
  3656 	// The TLS Message Length field is four octets, and provides
       
  3657 	// the total length of the TLS message or set of messages
       
  3658 	// that is being fragmented, this simplifies buffer allocation.
       
  3659 
       
  3660 	eap_status_e status = eap_status_process_general_error;
       
  3661 
       
  3662 	save_current_reassembly_state();
       
  3663 
       
  3664 	if (get_reassembly_state() == eap_type_tls_peap_reassembly_state_wait_first_message)
       
  3665 	{
       
  3666 		EAP_TRACE_DEBUG(
       
  3667 			m_am_tools,
       
  3668 			TRACE_FLAGS_DEFAULT,
       
  3669 			(EAPL("EAP_type_TLS_PEAP: this = 0x%08x, %s, %s, function: eap_type_tls_peap_c::tls_peap_packet_process(): waits first fragment.\n"),
       
  3670 			 this,
       
  3671 			 (m_is_client == true ? "client": "server"),
       
  3672 			 (get_type_partner()->get_is_tunneled_eap() == true ? "tunneled" : "outer most")));
       
  3673 
       
  3674 		if (received_tls_peap->get_flag_more_fragments() == true
       
  3675 			&& received_tls_peap->get_flag_tls_length_included() == false)
       
  3676 		{
       
  3677 			// The first fragmented message must include TLS-length field.
       
  3678 			restore_saved_reassembly_state();
       
  3679 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3680 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  3681 		}
       
  3682 
       
  3683 
       
  3684 		bool first_fragment = false;
       
  3685 		u32_t tls_message_length = 0ul;
       
  3686 
       
  3687 		if (received_tls_peap->get_flag_tls_length_included() == true)
       
  3688 		{
       
  3689 			// This is the first fragment and TLS message length is included.
       
  3690 			// We must allocate buffer for the fragments.
       
  3691 
       
  3692 			status = received_tls_peap->get_tls_message_length(&tls_message_length);
       
  3693 			if (status != eap_status_ok)
       
  3694 			{
       
  3695 				restore_saved_reassembly_state();
       
  3696 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3697 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  3698 			}
       
  3699 
       
  3700 			first_fragment = true;
       
  3701 		}
       
  3702 		else if (received_tls_peap->get_flag_more_fragments() == false
       
  3703 			&& received_tls_peap->get_flag_start() == false
       
  3704 			&& received_tls_peap->get_data_length() > 0ul)
       
  3705 		{
       
  3706 			// This is the individual message and TLS message length is not included.
       
  3707 			// We must allocate buffer for the message.
       
  3708 
       
  3709 			tls_message_length = received_tls_peap->get_data_length();
       
  3710 
       
  3711 			first_fragment = true;
       
  3712 		}
       
  3713 
       
  3714 
       
  3715 		if (first_fragment == true)
       
  3716 		{
       
  3717 			m_tls_message_buffer.reset();
       
  3718 
       
  3719 			if (tls_message_length > 0ul)
       
  3720 			{
       
  3721 				if (tls_message_length > EAP_TLS_PEAP_MAX_MESSAGE_LENGTH)
       
  3722 				{
       
  3723 					restore_saved_reassembly_state();
       
  3724 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3725 					return EAP_STATUS_RETURN(m_am_tools, eap_status_too_long_message);
       
  3726 				}
       
  3727 
       
  3728 				// Next allocate buffer for reassembled TLS-message.
       
  3729 				status = m_tls_message_buffer.set_buffer_length(tls_message_length);
       
  3730 				if (status != eap_status_ok)
       
  3731 				{
       
  3732 					restore_saved_reassembly_state();
       
  3733 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3734 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  3735 				}
       
  3736 
       
  3737 				// Copy first fragment to the reassembly buffer.
       
  3738 				status = m_tls_message_buffer.add_data(
       
  3739 					received_tls_peap->get_data(m_am_tools, received_tls_peap->get_data_length()),
       
  3740 					received_tls_peap->get_data_length());
       
  3741 				if (status != eap_status_ok)
       
  3742 				{
       
  3743 					restore_saved_reassembly_state();
       
  3744 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3745 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  3746 				}
       
  3747 
       
  3748 				m_first_fragment_eap_identifier = received_tls_peap->get_eap_identifier();
       
  3749 			}
       
  3750 		}
       
  3751 
       
  3752 
       
  3753 		if (received_tls_peap->get_flag_more_fragments() == true)
       
  3754 		{
       
  3755 			// This is NOT the last fragment.
       
  3756 
       
  3757 			EAP_TRACE_DEBUG(
       
  3758 				m_am_tools,
       
  3759 				TRACE_FLAGS_DEFAULT,
       
  3760 				(EAPL("EAP_type_TLS_PEAP: this = 0x%08x, %s, %s, function: eap_type_tls_peap_c::tls_peap_packet_process(): waits first fragment, not last fragment.\n"),
       
  3761 				 this,
       
  3762 				 (m_is_client == true ? "client": "server"),
       
  3763 				 (get_type_partner()->get_is_tunneled_eap() == true ? "tunneled" : "outer most")));
       
  3764 
       
  3765 			// Send fragment acknowledge message.
       
  3766 			status = send_empty_eap_ack();
       
  3767 			if (status != eap_status_ok)
       
  3768 			{
       
  3769 				restore_saved_reassembly_state();
       
  3770 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3771 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  3772 			}
       
  3773 
       
  3774 			// Change reassembly state.
       
  3775 			set_reassembly_state(eap_type_tls_peap_reassembly_state_wait_last_fragment);
       
  3776 		}
       
  3777 		else
       
  3778 		{
       
  3779 			// This is the last fragment or non fragmented message.
       
  3780 			EAP_TRACE_DEBUG(
       
  3781 				m_am_tools,
       
  3782 				TRACE_FLAGS_DEFAULT,
       
  3783 				(EAPL("EAP_type_TLS_PEAP: this = 0x%08x, %s, %s, function: eap_type_tls_peap_c::tls_peap_packet_process(): waits first fragment, the last fragment, start flag %d, data length %d.\n"),
       
  3784 				 this,
       
  3785 				 (m_is_client == true ? "client": "server"),
       
  3786 				 (get_type_partner()->get_is_tunneled_eap() == true ? "tunneled" : "outer most"),
       
  3787 				 received_tls_peap->get_flag_start(),
       
  3788 				 received_tls_peap->get_data_length()));
       
  3789 
       
  3790 			// Change reassembly state.
       
  3791 			set_reassembly_state(eap_type_tls_peap_reassembly_state_message_reassembled);
       
  3792 
       
  3793 			if (received_tls_peap->get_flag_start() == true)
       
  3794 			{
       
  3795 				// This is EAP-TLS/PEAP Start message.
       
  3796 				EAP_TRACE_DEBUG(
       
  3797 					m_am_tools,
       
  3798 					TRACE_FLAGS_DEFAULT,
       
  3799 					(EAPL("EAP_type_TLS_PEAP: this = 0x%08x, %s, %s, function: eap_type_tls_peap_c::tls_peap_packet_process(): waits first fragment, EAP-TLS/PEAP Start message.\n"),
       
  3800 					 this,
       
  3801 					 (m_is_client == true ? "client": "server"),
       
  3802 					 (get_type_partner()->get_is_tunneled_eap() == true ? "tunneled" : "outer most")));
       
  3803 
       
  3804 				save_current_state();
       
  3805 				set_state(eap_type_tls_peap_state_process_tls_start);
       
  3806 
       
  3807 				if (m_current_eap_type == eap_type_peap)
       
  3808 				{
       
  3809 					status = select_peap_version(received_tls_peap->get_flag_version());
       
  3810 					if (status != eap_status_ok)
       
  3811 					{
       
  3812 						restore_saved_reassembly_state();
       
  3813 						restore_saved_previous_state();
       
  3814 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3815 						return EAP_STATUS_RETURN(
       
  3816 							m_am_tools,
       
  3817 							eap_status_no_matching_protocol_version);
       
  3818 					}
       
  3819 				}
       
  3820 
       
  3821 				if (m_NAI.get_is_valid_data() == false)
       
  3822 				{
       
  3823 					// Do not care of the error. Some times there are no NAI at all.
       
  3824 					(void) get_type_partner()->get_saved_eap_identity(&m_NAI);
       
  3825 				}
       
  3826 
       
  3827 				eap_variable_data_c received_authority_identity_payload(m_am_tools);
       
  3828 				if (received_authority_identity_payload.get_is_valid() == false)
       
  3829 				{
       
  3830 					restore_saved_previous_state();
       
  3831 					restore_saved_reassembly_state();
       
  3832 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3833 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  3834 				}
       
  3835 
       
  3836 #if defined(USE_FAST_EAP_TYPE)
       
  3837 				if (m_current_eap_type == eap_type_fast)
       
  3838 				{
       
  3839 					// Read the received authority identity (A-ID).
       
  3840 					status = received_authority_identity_payload.set_buffer(
       
  3841 						received_tls_peap->get_data(m_am_tools, received_tls_peap->get_data_length()),
       
  3842 						received_tls_peap->get_data_length(),
       
  3843 						false,
       
  3844 						false);
       
  3845 				}
       
  3846 #endif //#if defined(USE_FAST_EAP_TYPE)
       
  3847 
       
  3848 				status = start_tls_peap_authentication(&received_authority_identity_payload);
       
  3849 				if (status == eap_status_pending_request)
       
  3850 				{
       
  3851 					// Do nothing.
       
  3852 				}
       
  3853 				else if (status != eap_status_ok)
       
  3854 				{
       
  3855 					restore_saved_previous_state();
       
  3856 					restore_saved_reassembly_state();
       
  3857 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3858 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  3859 				}
       
  3860 				else
       
  3861 				{
       
  3862 					// OK.
       
  3863 					set_state(eap_type_tls_peap_state_waiting_for_request);
       
  3864 				}
       
  3865 			}
       
  3866 			else if (received_tls_peap->get_flag_start() == false
       
  3867 				&& received_tls_peap->get_data_length() == 0)
       
  3868 			{
       
  3869 				EAP_TRACE_DEBUG(
       
  3870 					m_am_tools,
       
  3871 					TRACE_FLAGS_DEFAULT,
       
  3872 					(EAPL("EAP_type_TLS_PEAP: this = 0x%08x, %s, %s, function: eap_type_tls_peap_c::tls_peap_packet_process(): waits first fragment, empty EAP-TLS/PEAP message.\n"),
       
  3873 					 this,
       
  3874 					 (m_is_client == true ? "client": "server"),
       
  3875 					 (get_type_partner()->get_is_tunneled_eap() == true ? "tunneled" : "outer most")));
       
  3876 
       
  3877 				// Real TLS-tunnel type can be checked here.
       
  3878 				status = received_tls_peap->check_header(
       
  3879 					m_am_tools,
       
  3880 					m_current_eap_type,
       
  3881 					m_is_client,
       
  3882 					m_current_peap_version,
       
  3883 					true);
       
  3884 				if (status != eap_status_ok)
       
  3885 				{
       
  3886 					restore_saved_reassembly_state();
       
  3887 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3888 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  3889 				}
       
  3890 
       
  3891 #if defined(USE_EAP_CORE_SERVER)
       
  3892 				if (m_is_client == false
       
  3893 					&& get_state()
       
  3894 					== eap_type_tls_peap_state_waiting_for_empty_tppd_peap_v1_acknowledge)
       
  3895 				{
       
  3896 					// Server wait empty PEAP v1 acknowledge
       
  3897 					status = finish_successful_authentication(false, false, true);
       
  3898 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3899 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  3900 				}
       
  3901 #if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
       
  3902 				else if (m_is_client == false
       
  3903 					&& get_state() == eap_type_tls_peap_state_server_waits_ttls_plain_ms_chap_v2_empty_ack)
       
  3904 				{
       
  3905 					EAP_TRACE_DEBUG(
       
  3906 						m_am_tools,
       
  3907 						TRACE_FLAGS_DEFAULT,
       
  3908 						(EAPL("eap_type_tls_peap_c::tls_peap_packet_process(): ")
       
  3909 						 EAPL("received EAP-TTLS/PEAP empty Ack message in ")
       
  3910 						 EAPL("eap_type_tls_peap_state_variable_e %d=%s, ")
       
  3911 						 EAPL("eap_type_tls_peap_reassembly_state_e %d=%s.\n"),
       
  3912 						 get_state(),
       
  3913 						 get_state_string(),
       
  3914 						 get_reassembly_state(),
       
  3915 						 get_reassembly_state_string()));
       
  3916 
       
  3917 					status = m_tls_record->empty_ack_packet_received(
       
  3918 						receive_network_id,
       
  3919 						received_tls_peap->get_identifier());
       
  3920 					if (status != eap_status_ok)
       
  3921 					{
       
  3922 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3923 						return EAP_STATUS_RETURN(m_am_tools, status);
       
  3924 					}
       
  3925 					
       
  3926 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3927 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  3928 				}
       
  3929 #endif //#if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
       
  3930 				else if (m_is_client == false
       
  3931 					&& get_state() == eap_type_tls_peap_state_waiting_for_empty_response)
       
  3932 				{
       
  3933 					// Server waits the client sends an empty response.
       
  3934 
       
  3935 					if (received_tls_peap->get_data_length() != 0ul)
       
  3936 					{
       
  3937 						restore_saved_reassembly_state();
       
  3938 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3939 						return EAP_STATUS_RETURN(
       
  3940 							m_am_tools,
       
  3941 							eap_status_process_illegal_packet_error);
       
  3942 					}
       
  3943 					else
       
  3944 					{
       
  3945 						if (m_current_eap_type == eap_type_tls
       
  3946 							|| (m_current_eap_type == eap_type_peap
       
  3947 								&& (get_tls_session_type() == tls_session_type_original_session_resumption
       
  3948 									|| get_tls_session_type() == tls_session_type_stateless_session_resumption)))
       
  3949 						{
       
  3950 							// OK, successfull authentication.
       
  3951 							status = finish_successful_authentication(false, false, true);
       
  3952 							if (status != eap_status_success)
       
  3953 							{
       
  3954 								restore_saved_reassembly_state();
       
  3955 								EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3956 								return EAP_STATUS_RETURN(m_am_tools, status);
       
  3957 							}
       
  3958 						}
       
  3959 						else if (m_current_eap_type == eap_type_peap
       
  3960 							|| m_current_eap_type == eap_type_ttls
       
  3961 #if defined(USE_FAST_EAP_TYPE)
       
  3962 							|| (m_current_eap_type == eap_type_fast
       
  3963 								&& (get_tls_session_type() == tls_session_type_eap_fast_server_unauthenticated_provisioning_mode_ADHP
       
  3964 									|| get_tls_session_type() == tls_session_type_full_authentication))
       
  3965 #endif //#if defined(USE_FAST_EAP_TYPE)
       
  3966 								)
       
  3967 						{
       
  3968 							save_current_state();
       
  3969 							set_state(eap_type_tls_peap_state_process_tls_message);
       
  3970 
       
  3971 							// Now we must start the tunneled EAP-type.
       
  3972 							status = m_tls_record->start_peap_tunneled_authentication(
       
  3973 								receive_network_id,
       
  3974 								received_tls_peap->get_eap_identifier(),
       
  3975 								get_tls_session_type());
       
  3976 							if (status != eap_status_ok)
       
  3977 							{
       
  3978 								restore_saved_previous_state();
       
  3979 								restore_saved_reassembly_state();
       
  3980 								EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3981 								return EAP_STATUS_RETURN(m_am_tools, status);
       
  3982 							}
       
  3983 
       
  3984 							m_tunneled_eap_type_active = true;
       
  3985 							set_state(eap_type_tls_peap_state_waiting_for_response);
       
  3986 						}
       
  3987 						else
       
  3988 						{
       
  3989 							EAP_TRACE_ERROR(
       
  3990 								m_am_tools,
       
  3991 								TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  3992 								(EAPL("ERROR: EAP_type_TLS_PEAP: %s, unknown EAP-type 0x%08x\n"),
       
  3993 								 (m_is_client == true) ? "client": "server",
       
  3994 								 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  3995 
       
  3996 							restore_saved_reassembly_state();
       
  3997 							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  3998 							return EAP_STATUS_RETURN(m_am_tools, status);
       
  3999 						}
       
  4000 					}
       
  4001 				}
       
  4002 				else
       
  4003 #endif //#if defined(USE_EAP_CORE_SERVER)
       
  4004 				{
       
  4005 					// This is EAP-TLS/PEAP fragment acknowledge.
       
  4006 					if (m_tls_message_buffer.get_is_valid_data() == true
       
  4007 						&& m_tls_message_send_offset < m_tls_message_buffer.get_data_length())
       
  4008 					{
       
  4009 						// We can send next fragment.
       
  4010 
       
  4011 						save_current_state();
       
  4012 						set_state(eap_type_tls_peap_state_process_tls_message);
       
  4013 
       
  4014 						status = eap_tls_peap_fragment_send();
       
  4015 						if (status != eap_status_ok)
       
  4016 						{
       
  4017 							restore_saved_previous_state();
       
  4018 							restore_saved_reassembly_state();
       
  4019 							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4020 							return EAP_STATUS_RETURN(m_am_tools, status);
       
  4021 						}
       
  4022 						
       
  4023 						if (m_is_client == true)
       
  4024 						{
       
  4025 							set_state(eap_type_tls_peap_state_waiting_for_request);
       
  4026 						}
       
  4027 						else
       
  4028 						{
       
  4029 							set_state(eap_type_tls_peap_state_waiting_for_response);
       
  4030 						}
       
  4031 					}
       
  4032 					else
       
  4033 					{
       
  4034 						// No fragment available. Drop this packet.
       
  4035 						restore_saved_reassembly_state();
       
  4036 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4037 						return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  4038 					}
       
  4039 				}
       
  4040 			}
       
  4041 			else
       
  4042 			{
       
  4043 				EAP_TRACE_DEBUG(
       
  4044 					m_am_tools,
       
  4045 					TRACE_FLAGS_DEFAULT,
       
  4046 					(EAPL("EAP_type_TLS_PEAP: this = 0x%08x, %s, %s, function: eap_type_tls_peap_c::tls_peap_packet_process(): waits first fragment, non empty EAP-TLS/PEAP message.\n"),
       
  4047 					 this,
       
  4048 					 (m_is_client == true ? "client": "server"),
       
  4049 					 (get_type_partner()->get_is_tunneled_eap() == true ? "tunneled" : "outer most")));
       
  4050 
       
  4051 
       
  4052 #if defined(USE_EAP_CORE_SERVER)
       
  4053 				if (m_is_client == false
       
  4054 					&& get_state() == eap_type_tls_peap_state_waiting_for_empty_response
       
  4055 					&& received_tls_peap->get_data_length() != 0ul)
       
  4056 				{
       
  4057 					// Server waits the client sends an empty response.
       
  4058 					restore_saved_reassembly_state();
       
  4059 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4060 					return EAP_STATUS_RETURN(
       
  4061 						m_am_tools,
       
  4062 						eap_status_process_illegal_packet_error);
       
  4063 				}
       
  4064 				else if (m_is_client == false
       
  4065 						 && m_current_eap_type == eap_type_peap
       
  4066 						 && get_state() == eap_type_tls_peap_state_waiting_for_first_response)
       
  4067 				{
       
  4068 					// Note PEAP version is NOT checked here.
       
  4069 					status = received_tls_peap->check_header(
       
  4070 						m_am_tools,
       
  4071 						m_current_eap_type,
       
  4072 						m_is_client,
       
  4073 						m_current_peap_version,
       
  4074 						false);
       
  4075 					if (status != eap_status_ok)
       
  4076 					{
       
  4077 						restore_saved_reassembly_state();
       
  4078 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4079 						return EAP_STATUS_RETURN(m_am_tools, status);
       
  4080 					}
       
  4081 
       
  4082 					// Check the PEAP version client selected.
       
  4083 					status = select_peap_version(received_tls_peap->get_flag_version());
       
  4084 					if (status != eap_status_ok)
       
  4085 					{
       
  4086 						restore_saved_reassembly_state();
       
  4087 						restore_saved_previous_state();
       
  4088 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4089 						return EAP_STATUS_RETURN(m_am_tools, status);
       
  4090 					}
       
  4091 				}
       
  4092 #endif //#if defined(USE_EAP_CORE_SERVER)
       
  4093 
       
  4094 				// NOTE, PEAP version is checked here.
       
  4095 				status = received_tls_peap->check_header(
       
  4096 					m_am_tools,
       
  4097 					m_current_eap_type,
       
  4098 					m_is_client,
       
  4099 					m_current_peap_version,
       
  4100 					true);
       
  4101 				if (status != eap_status_ok)
       
  4102 				{
       
  4103 					restore_saved_reassembly_state();
       
  4104 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4105 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  4106 				}
       
  4107 
       
  4108 				// Process the reassembled TLS message.
       
  4109 				status = tls_message_process(
       
  4110 					receive_network_id,
       
  4111 					received_tls_peap,
       
  4112 					tls_peap_packet_length);
       
  4113 
       
  4114 				if (status != eap_status_ok
       
  4115 					&& status != eap_status_pending_request
       
  4116 					&& status != eap_status_success)
       
  4117 				{
       
  4118 					restore_saved_reassembly_state();
       
  4119 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4120 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  4121 				}
       
  4122 			}
       
  4123 
       
  4124 			set_reassembly_state(eap_type_tls_peap_reassembly_state_wait_first_message);
       
  4125 		}
       
  4126 	}
       
  4127 	else if (get_reassembly_state() == eap_type_tls_peap_reassembly_state_wait_last_fragment)
       
  4128 	{
       
  4129 		// TLS message length field may or may not be included.
       
  4130 
       
  4131 		EAP_ASSERT_ALWAYS(received_tls_peap->get_flag_start() == false);
       
  4132 
       
  4133 		// Concatenate fragment to the reassembly buffer.
       
  4134 		status = m_tls_message_buffer.add_data(
       
  4135 			received_tls_peap->get_data(m_am_tools, received_tls_peap->get_data_length()),
       
  4136 			received_tls_peap->get_data_length());
       
  4137 		if (status != eap_status_ok)
       
  4138 		{
       
  4139 			restore_saved_reassembly_state();
       
  4140 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4141 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  4142 		}
       
  4143 
       
  4144 		if (received_tls_peap->get_flag_more_fragments() == true)
       
  4145 		{
       
  4146 			// This is NOT the last fragment.
       
  4147 
       
  4148 			// Send fragment acknowledge message.
       
  4149 			status = send_empty_eap_ack();
       
  4150 			if (status != eap_status_ok)
       
  4151 			{
       
  4152 				restore_saved_reassembly_state();
       
  4153 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4154 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4155 			}
       
  4156 		}
       
  4157 		else
       
  4158 		{
       
  4159 			// This is the last fragment.
       
  4160 			// Change reassembly state.
       
  4161 			set_reassembly_state(eap_type_tls_peap_reassembly_state_message_reassembled);
       
  4162 
       
  4163 			// Process the reassembled TLS message.
       
  4164 			status = tls_message_process(
       
  4165 				receive_network_id,
       
  4166 				received_tls_peap,
       
  4167 				tls_peap_packet_length);
       
  4168 
       
  4169 			if (status != eap_status_ok
       
  4170 				&& status != eap_status_pending_request
       
  4171 				&& status != eap_status_success)
       
  4172 			{
       
  4173 				restore_saved_reassembly_state();
       
  4174 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4175 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  4176 			}
       
  4177 
       
  4178 			set_reassembly_state(eap_type_tls_peap_reassembly_state_wait_first_message);
       
  4179 		}
       
  4180 	}
       
  4181 	else if (get_reassembly_state() == eap_type_tls_peap_reassembly_state_message_reassembled)
       
  4182 	{
       
  4183 		EAP_TRACE_ERROR(
       
  4184 			m_am_tools,
       
  4185 			TRACE_FLAGS_TLS_PEAP_ERROR,
       
  4186 			(EAPL("ERROR: eap_type_tls_peap_c::tls_peap_packet_process(): ")
       
  4187 			 EAPL("Cannot receive EAP-TLS/PEAP message in ")
       
  4188 			 EAPL("eap_type_tls_peap_state_variable_e %d=%s, ")
       
  4189 			 EAPL("eap_type_tls_peap_reassembly_state_e %d=%s.\n"),
       
  4190 			 get_state(),
       
  4191 			 get_state_string(),
       
  4192 			 get_reassembly_state(),
       
  4193 			 get_reassembly_state_string()));
       
  4194 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4195 		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
       
  4196 	}
       
  4197 	else
       
  4198 	{
       
  4199 		EAP_TRACE_ERROR(
       
  4200 			m_am_tools,
       
  4201 			TRACE_FLAGS_TLS_PEAP_ERROR,
       
  4202 			(EAPL("ERROR: eap_type_tls_peap_c::tls_peap_packet_process(): ")
       
  4203 			 EAPL("Cannot receive EAP-TLS/PEAP message in ")
       
  4204 			 EAPL("eap_type_tls_peap_state_variable_e %d=%s, ")
       
  4205 			 EAPL("eap_type_tls_peap_reassembly_state_e %d=%s.\n"),
       
  4206 			 get_state(),
       
  4207 			 get_state_string(),
       
  4208 			 get_reassembly_state(),
       
  4209 			 get_reassembly_state_string()));
       
  4210 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4211 		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
       
  4212 	}
       
  4213 
       
  4214 
       
  4215 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4216 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  4217 }
       
  4218 
       
  4219 //--------------------------------------------------
       
  4220 
       
  4221 //
       
  4222 EAP_FUNC_EXPORT u32_t eap_type_tls_peap_c::get_header_offset(
       
  4223 	u32_t * const MTU,
       
  4224 	u32_t * const trailer_length
       
  4225 	)
       
  4226 {
       
  4227 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4228 
       
  4229 	// Note, EAP-TLS and PEAP supports fragmentation.
       
  4230 	// Here we could tell the MTU is big enough, the maximum memory buffer size is perfect.
       
  4231 
       
  4232 	if (m_current_eap_type == eap_type_peap
       
  4233 		&& m_current_peap_version == peap_version_0_xp)
       
  4234 	{
       
  4235 		// PEAPv0 cannot use long tunneled EAP-packets,
       
  4236 		// bacause of the inner EAP-packets does not
       
  4237 		// have own EAP-header. Long inner EAP-packets will be 
       
  4238 		// fragmented in outer PEAPv0 application data and that will cause
       
  4239 		// wrong EAP-identifier values after reassembly.
       
  4240 		u32_t offset = get_type_partner()->get_header_offset(
       
  4241 			MTU,
       
  4242 			trailer_length);
       
  4243 
       
  4244 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4245 		return offset;
       
  4246 	}
       
  4247 	else
       
  4248 	{
       
  4249 		if (MTU != 0)
       
  4250 		{
       
  4251 			*MTU = EAP_TLS_PEAP_MAX_MESSAGE_LENGTH;
       
  4252 		}
       
  4253 
       
  4254 		if (trailer_length != 0)
       
  4255 		{
       
  4256 			*trailer_length = 0ul;
       
  4257 		}
       
  4258 
       
  4259 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4260 		return 0ul; // This is the header offset of the TLS-record header.
       
  4261 	}
       
  4262 }
       
  4263 
       
  4264 //--------------------------------------------------
       
  4265 
       
  4266 //
       
  4267 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::timer_expired(
       
  4268 	const u32_t /*id*/, void * /*data*/
       
  4269 	)
       
  4270 {
       
  4271 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4272 
       
  4273 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4274 	return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
       
  4275 }
       
  4276 
       
  4277 //--------------------------------------------------
       
  4278 
       
  4279 //
       
  4280 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::timer_delete_data(
       
  4281 	const u32_t /*id*/, void * /*data*/
       
  4282 	)
       
  4283 {
       
  4284 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4285 
       
  4286 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4287 	return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
       
  4288 }
       
  4289 
       
  4290 //--------------------------------------------------
       
  4291 
       
  4292 //
       
  4293 EAP_FUNC_EXPORT void eap_type_tls_peap_c::set_is_valid()
       
  4294 {
       
  4295 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4296 
       
  4297 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4298 	m_is_valid = true;
       
  4299 }
       
  4300 
       
  4301 //--------------------------------------------------
       
  4302 
       
  4303 //
       
  4304 EAP_FUNC_EXPORT bool eap_type_tls_peap_c::get_is_valid()
       
  4305 {
       
  4306 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4307 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4308 	return m_is_valid;
       
  4309 }
       
  4310 
       
  4311 //--------------------------------------------------
       
  4312 
       
  4313 //
       
  4314 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::configure()
       
  4315 {
       
  4316 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4317 
       
  4318 	eap_status_e status = eap_status_process_general_error;
       
  4319 
       
  4320 	status = m_am_type_tls_peap->configure();
       
  4321 	if (status != eap_status_ok)
       
  4322 	{
       
  4323 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4324 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4325 	}
       
  4326 
       
  4327 	status = m_tls_record->configure();
       
  4328 	if (status != eap_status_ok)
       
  4329 	{
       
  4330 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4331 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  4332 	}
       
  4333 
       
  4334 	//----------------------------------------------------------
       
  4335 
       
  4336 #if defined(USE_EAP_TLS_IDENTITY_PRIVACY)
       
  4337 	{
       
  4338 		eap_variable_data_c tls_use_privacy(m_am_tools);
       
  4339 
       
  4340 		status = get_type_partner()->read_configure(
       
  4341 			cf_str_EAP_TLS_PEAP_use_identity_privacy.get_field(),
       
  4342 			&tls_use_privacy);
       
  4343 		if (status == eap_status_ok
       
  4344 			&& tls_use_privacy.get_is_valid_data() == true
       
  4345 			&& tls_use_privacy.get_data_length() == sizeof(u32_t)
       
  4346 			&& tls_use_privacy.get_data(sizeof(u32_t)) != 0)
       
  4347 		{
       
  4348 			// This is optional value.
       
  4349 			u32_t *flag = reinterpret_cast<u32_t *>(
       
  4350 				tls_use_privacy.get_data(sizeof(u32_t)));
       
  4351 			if (flag != 0)
       
  4352 			{
       
  4353 				if (*flag == 0)
       
  4354 				{
       
  4355 					m_tls_use_identity_privacy = false;
       
  4356 				}
       
  4357 				else
       
  4358 				{
       
  4359 					m_tls_use_identity_privacy = true;
       
  4360 				}
       
  4361 			}
       
  4362 		}
       
  4363 
       
  4364 		status = eap_status_ok;
       
  4365 	}
       
  4366 
       
  4367 	if (m_is_client == false)
       
  4368 	{
       
  4369 		eap_variable_data_c tls_server_use_privacy(m_am_tools);
       
  4370 
       
  4371 		status = get_type_partner()->read_configure(
       
  4372 			cf_str_EAP_TLS_PEAP_use_identity_privacy_server.get_field(),
       
  4373 			&tls_server_use_privacy);
       
  4374 		if (status == eap_status_ok
       
  4375 			&& tls_server_use_privacy.get_is_valid_data() == true
       
  4376 			&& tls_server_use_privacy.get_data_length() == sizeof(u32_t)
       
  4377 			&& tls_server_use_privacy.get_data(sizeof(u32_t)) != 0)
       
  4378 		{
       
  4379 			// This is optional value.
       
  4380 			u32_t *flag = reinterpret_cast<u32_t *>(
       
  4381 				tls_server_use_privacy.get_data(sizeof(u32_t)));
       
  4382 			if (flag != 0)
       
  4383 			{
       
  4384 				if (*flag == 0)
       
  4385 				{
       
  4386 					m_tls_use_identity_privacy = false;
       
  4387 				}
       
  4388 				else
       
  4389 				{
       
  4390 					m_tls_use_identity_privacy = true;
       
  4391 				}
       
  4392 			}
       
  4393 		}
       
  4394 
       
  4395 		status = eap_status_ok;
       
  4396 	}
       
  4397 
       
  4398 #endif //#if defined(USE_EAP_TLS_IDENTITY_PRIVACY)
       
  4399 
       
  4400 	//----------------------------------------------------------
       
  4401 
       
  4402 	{
       
  4403 		eap_variable_data_c wait_eap_success_packet(m_am_tools);
       
  4404 
       
  4405 		status = read_configure(
       
  4406 			cf_str_EAP_TLS_PEAP_wait_eap_success_packet.get_field(),
       
  4407 			&wait_eap_success_packet);
       
  4408 
       
  4409 		if (status == eap_status_ok
       
  4410 			&& wait_eap_success_packet.get_is_valid_data() == true)
       
  4411 		{
       
  4412 			u32_t *flag = reinterpret_cast<u32_t *>(
       
  4413 				wait_eap_success_packet.get_data(sizeof(u32_t)));
       
  4414 			if (flag != 0)
       
  4415 			{
       
  4416 				if (*flag == 0)
       
  4417 				{
       
  4418 					m_wait_eap_success_packet = false;
       
  4419 				}
       
  4420 				else
       
  4421 				{
       
  4422 					// NOTE: when plain PEAP is used no EAP-success is sent 
       
  4423 					// in plain text and this option will be set to false.
       
  4424 					m_wait_eap_success_packet = true;
       
  4425 				}
       
  4426 			}
       
  4427 			else
       
  4428 			{
       
  4429 				EAP_TRACE_ERROR(
       
  4430 					m_am_tools,
       
  4431 					TRACE_FLAGS_TLS_PEAP_ERROR,
       
  4432 					(EAPL("ERROR: illegal configuration value %s\n"),
       
  4433 					 cf_str_EAP_TLS_PEAP_wait_eap_success_packet.get_field()->get_field()));
       
  4434 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4435 				return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_configure_field);
       
  4436 			}
       
  4437 		}
       
  4438 	}
       
  4439 
       
  4440 	//----------------------------------------------------------
       
  4441 
       
  4442 	{
       
  4443 		eap_variable_data_c check_identifier_of_eap_identity_response(m_am_tools);
       
  4444 
       
  4445 		status = read_configure(
       
  4446 			cf_str_EAP_TLS_PEAP_check_identifier_of_eap_identity_response.get_field(),
       
  4447 			&check_identifier_of_eap_identity_response);
       
  4448 
       
  4449 		if (status == eap_status_ok
       
  4450 			&& check_identifier_of_eap_identity_response.get_is_valid_data() == true)
       
  4451 		{
       
  4452 			u32_t *flag = reinterpret_cast<u32_t *>(
       
  4453 				check_identifier_of_eap_identity_response.get_data(sizeof(u32_t)));
       
  4454 			if (flag != 0)
       
  4455 			{
       
  4456 				if (*flag == 0)
       
  4457 				{
       
  4458 					m_check_identifier_of_eap_identity_response = false;
       
  4459 				}
       
  4460 				else
       
  4461 				{
       
  4462 					m_check_identifier_of_eap_identity_response = true;
       
  4463 				}
       
  4464 			}
       
  4465 			else
       
  4466 			{
       
  4467 				EAP_TRACE_ERROR(
       
  4468 					m_am_tools,
       
  4469 					TRACE_FLAGS_TLS_PEAP_ERROR,
       
  4470 					(EAPL("ERROR: illegal configuration value %s\n"),
       
  4471 					 cf_str_EAP_TLS_PEAP_check_identifier_of_eap_identity_response
       
  4472 					 .get_field()->get_field()));
       
  4473 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4474 				return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_configure_field);
       
  4475 			}
       
  4476 		}
       
  4477 	}
       
  4478 
       
  4479 	//----------------------------------------------------------
       
  4480 
       
  4481 	{
       
  4482 		eap_variable_data_c EAP_TLS_PEAP_check_nai_realm(m_am_tools);
       
  4483 
       
  4484 		status = read_configure(
       
  4485 			cf_str_EAP_TLS_PEAP_check_nai_realm.get_field(),
       
  4486 			&EAP_TLS_PEAP_check_nai_realm);
       
  4487 		if (status == eap_status_ok
       
  4488 			&& EAP_TLS_PEAP_check_nai_realm.get_is_valid_data() == true)
       
  4489 		{
       
  4490 			u32_t *check_nai_realm = reinterpret_cast<u32_t *>(
       
  4491 				EAP_TLS_PEAP_check_nai_realm.get_data(sizeof(u32_t)));
       
  4492 			if (check_nai_realm != 0
       
  4493 				&& *check_nai_realm != 0)
       
  4494 			{
       
  4495 				m_check_nai_realm = true;
       
  4496 			}
       
  4497 		}
       
  4498 	}
       
  4499 
       
  4500 	//----------------------------------------------------------
       
  4501 
       
  4502 	{
       
  4503 		eap_variable_data_c test_version(m_am_tools);
       
  4504 
       
  4505 		status = read_configure(
       
  4506 			cf_str_EAP_TLS_test_version.get_field(),
       
  4507 			&test_version);
       
  4508 		if (status == eap_status_ok
       
  4509 			&& test_version.get_is_valid_data() == true
       
  4510 			&& test_version.get_data_length() == sizeof(u32_t)
       
  4511 			&& test_version.get_data(sizeof(u32_t)) != 0)
       
  4512 		{
       
  4513 			// This is optional value.
       
  4514 			u32_t *flag = reinterpret_cast<u32_t *>(test_version.get_data(sizeof(u32_t)));
       
  4515 			if (flag != 0)
       
  4516 			{
       
  4517 				if (*flag == 0)
       
  4518 				{
       
  4519 					m_tls_peap_test_version = false;
       
  4520 				}
       
  4521 				else
       
  4522 				{
       
  4523 					m_tls_peap_test_version = true;
       
  4524 				}
       
  4525 			}
       
  4526 		}
       
  4527 	}
       
  4528 
       
  4529 	//----------------------------------------------------------
       
  4530 
       
  4531 	if (m_current_eap_type == eap_type_peap)
       
  4532 	{
       
  4533 		{
       
  4534 			eap_variable_data_c use_tppd_peapv1_acknowledge_hack(m_am_tools);
       
  4535 
       
  4536 			status = read_configure(
       
  4537 				cf_str_EAP_TLS_use_tppd_peapv1_acknowledge_hack.get_field(),
       
  4538 				&use_tppd_peapv1_acknowledge_hack);
       
  4539 			if (status == eap_status_ok
       
  4540 				&& use_tppd_peapv1_acknowledge_hack.get_is_valid_data() == true
       
  4541 				&& use_tppd_peapv1_acknowledge_hack.get_data_length() == sizeof(u32_t)
       
  4542 				&& use_tppd_peapv1_acknowledge_hack.get_data(sizeof(u32_t)) != 0)
       
  4543 			{
       
  4544 				// This is optional value.
       
  4545 				u32_t *flag = reinterpret_cast<u32_t *>(
       
  4546 					use_tppd_peapv1_acknowledge_hack.get_data(sizeof(u32_t)));
       
  4547 				if (flag != 0)
       
  4548 				{
       
  4549 					if (*flag == 0)
       
  4550 					{
       
  4551 						m_use_tppd_peapv1_acknowledge_hack = false;
       
  4552 					}
       
  4553 					else
       
  4554 					{
       
  4555 						m_use_tppd_peapv1_acknowledge_hack = true;
       
  4556 					}
       
  4557 				}
       
  4558 			}
       
  4559 		}
       
  4560 
       
  4561 
       
  4562 		if (m_is_client == false)
       
  4563 		{
       
  4564 			// Server
       
  4565 
       
  4566 			eap_variable_data_c used_peap_version(m_am_tools);
       
  4567 
       
  4568 			status = read_configure(
       
  4569 				cf_str_EAP_TLS_PEAP_used_PEAP_version.get_field(),
       
  4570 				&used_peap_version);
       
  4571 			if (status == eap_status_ok
       
  4572 				&& used_peap_version.get_is_valid_data() == true)
       
  4573 			{
       
  4574 				u32_t *p_used_peap_version = reinterpret_cast<u32_t *>(
       
  4575 					used_peap_version.get_data(sizeof(u32_t)));
       
  4576 
       
  4577 				if (p_used_peap_version == 0)
       
  4578 				{
       
  4579 					EAP_TRACE_ERROR(
       
  4580 						m_am_tools,
       
  4581 						TRACE_FLAGS_TLS_PEAP_ERROR,
       
  4582 						(EAPL("ERROR: illegal configuration value %s\n"),
       
  4583 						 cf_str_EAP_TLS_PEAP_used_PEAP_version.get_field()->get_field()));
       
  4584 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4585 					return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_configure_field);
       
  4586 				}
       
  4587 				else if (*p_used_peap_version > peap_version_2)
       
  4588 				{
       
  4589 					// Not supported PEAP version.
       
  4590 					EAP_TRACE_ERROR(
       
  4591 						m_am_tools,
       
  4592 						TRACE_FLAGS_TLS_PEAP_ERROR,
       
  4593 						(EAPL("ERROR: Not supported PEAP version configuration %s: %d\n"),
       
  4594 						 cf_str_EAP_TLS_PEAP_used_PEAP_version.get_field()->get_field(),
       
  4595 						 *p_used_peap_version));
       
  4596 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4597 					return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_configure_field);
       
  4598 				}
       
  4599 				else
       
  4600 				{
       
  4601 					m_configured_peap_version = static_cast<peap_version_e>(
       
  4602 						*p_used_peap_version);
       
  4603 					m_current_peap_version = m_configured_peap_version;
       
  4604 				}
       
  4605 			}
       
  4606 
       
  4607 			//----------------------------------------------------------
       
  4608 
       
  4609 			{
       
  4610 				eap_variable_data_c use_tppd_peapv1_acknowledge_hack(m_am_tools);
       
  4611 
       
  4612 				status = read_configure(
       
  4613 					cf_str_EAP_TLS_server_use_tppd_peapv1_acknowledge_hack.get_field(),
       
  4614 					&use_tppd_peapv1_acknowledge_hack);
       
  4615 				if (status == eap_status_ok
       
  4616 					&& use_tppd_peapv1_acknowledge_hack.get_is_valid_data() == true
       
  4617 					&& use_tppd_peapv1_acknowledge_hack.get_data_length() == sizeof(u32_t)
       
  4618 					&& use_tppd_peapv1_acknowledge_hack.get_data(sizeof(u32_t)) != 0)
       
  4619 				{
       
  4620 					// This is optional value.
       
  4621 					u32_t *flag = reinterpret_cast<u32_t *>(
       
  4622 						use_tppd_peapv1_acknowledge_hack.get_data(sizeof(u32_t)));
       
  4623 					if (flag != 0)
       
  4624 					{
       
  4625 						if (*flag == 0)
       
  4626 						{
       
  4627 							m_use_tppd_peapv1_acknowledge_hack = false;
       
  4628 						}
       
  4629 						else
       
  4630 						{
       
  4631 							m_use_tppd_peapv1_acknowledge_hack = true;
       
  4632 						}
       
  4633 					}
       
  4634 				}
       
  4635 			}
       
  4636 		}
       
  4637 
       
  4638 		//----------------------------------------------------------
       
  4639 
       
  4640 		{
       
  4641 			eap_variable_data_c accepted_peap_versions(m_am_tools);
       
  4642 
       
  4643 			status = read_configure(
       
  4644 				cf_str_EAP_TLS_PEAP_accepted_PEAP_versions.get_field(),
       
  4645 				&accepted_peap_versions);
       
  4646 			if (status == eap_status_ok
       
  4647 				&& accepted_peap_versions.get_is_valid_data() == true
       
  4648 				&& accepted_peap_versions.get_data_length() >= sizeof(u32_t))
       
  4649 			{
       
  4650 				u32_t *p_accepted_peap_versions
       
  4651 					= reinterpret_cast<u32_t *>(accepted_peap_versions.get_data(
       
  4652 						accepted_peap_versions.get_data_length()));
       
  4653 
       
  4654 				if (p_accepted_peap_versions == 0)
       
  4655 				{
       
  4656 					EAP_TRACE_ERROR(
       
  4657 						m_am_tools,
       
  4658 						TRACE_FLAGS_TLS_PEAP_ERROR,
       
  4659 						(EAPL("ERROR: illegal configuration value %s\n"),
       
  4660 						 cf_str_EAP_TLS_PEAP_accepted_PEAP_versions.get_field()->get_field()));
       
  4661 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4662 					return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_configure_field);
       
  4663 				}
       
  4664 				else
       
  4665 				{
       
  4666 					u32_t version_count = accepted_peap_versions.get_data_length()
       
  4667 						/ sizeof(u32_t);
       
  4668 
       
  4669 					for (u32_t ind = 0ul; ind < version_count; ind++)
       
  4670 					{
       
  4671 						if (p_accepted_peap_versions[ind] > peap_version_2)
       
  4672 						{
       
  4673 							// Not supported PEAP version.
       
  4674 							EAP_TRACE_ERROR(
       
  4675 								m_am_tools,
       
  4676 								TRACE_FLAGS_TLS_PEAP_ERROR,
       
  4677 								(EAPL("ERROR: Not supported PEAP version configuration %s: %d\n"),
       
  4678 								 cf_str_EAP_TLS_PEAP_accepted_PEAP_versions
       
  4679 								 .get_field()->get_field(),
       
  4680 								 *p_accepted_peap_versions));
       
  4681 							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4682 							return EAP_STATUS_RETURN(
       
  4683 								m_am_tools,
       
  4684 								eap_status_illegal_configure_field);
       
  4685 						}
       
  4686 
       
  4687 						status = m_accepted_PEAP_versions.add_data(
       
  4688 							&(p_accepted_peap_versions[ind]),
       
  4689 							sizeof(p_accepted_peap_versions[ind]));
       
  4690 						if (status != eap_status_ok)
       
  4691 						{
       
  4692 							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4693 							return EAP_STATUS_RETURN(m_am_tools, status);
       
  4694 						}
       
  4695 					}
       
  4696 				}
       
  4697 			}
       
  4698 			else
       
  4699 			{
       
  4700 				// Not configured.
       
  4701 				// Accept only version 0.
       
  4702 				u32_t accepted_peap_version = peap_version_0_xp;
       
  4703 
       
  4704 				m_accepted_PEAP_versions.reset();
       
  4705 
       
  4706 				status = m_accepted_PEAP_versions.add_data(
       
  4707 					&accepted_peap_version,
       
  4708 					sizeof(accepted_peap_version));
       
  4709 				if (status != eap_status_ok)
       
  4710 				{
       
  4711 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4712 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  4713 				}
       
  4714 			}
       
  4715 		}
       
  4716 
       
  4717 		//----------------------------------------------------------
       
  4718 
       
  4719 		if (m_is_client == false)
       
  4720 		{
       
  4721 			// Server could use it's own configuration.
       
  4722 
       
  4723 			eap_variable_data_c accepted_peap_versions(m_am_tools);
       
  4724 
       
  4725 			status = read_configure(
       
  4726 				cf_str_EAP_TLS_PEAP_server_accepted_PEAP_versions.get_field(),
       
  4727 				&accepted_peap_versions);
       
  4728 			if (status == eap_status_ok
       
  4729 				&& accepted_peap_versions.get_is_valid_data() == true
       
  4730 				&& accepted_peap_versions.get_data_length() >= sizeof(u32_t))
       
  4731 			{
       
  4732 				// Server uses own configuration.
       
  4733 				m_accepted_PEAP_versions.reset();
       
  4734 
       
  4735 				u32_t *p_accepted_peap_versions
       
  4736 					= reinterpret_cast<u32_t *>(accepted_peap_versions.get_data(
       
  4737 						accepted_peap_versions.get_data_length()));
       
  4738 
       
  4739 				if (p_accepted_peap_versions == 0)
       
  4740 				{
       
  4741 					EAP_TRACE_ERROR(
       
  4742 						m_am_tools,
       
  4743 						TRACE_FLAGS_TLS_PEAP_ERROR,
       
  4744 						(EAPL("ERROR: illegal configuration value %s\n"),
       
  4745 						 cf_str_EAP_TLS_PEAP_accepted_PEAP_versions.get_field()->get_field()));
       
  4746 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4747 					return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_configure_field);
       
  4748 				}
       
  4749 				else
       
  4750 				{
       
  4751 					u32_t version_count = accepted_peap_versions.get_data_length()
       
  4752 						/ sizeof(u32_t);
       
  4753 
       
  4754 					for (u32_t ind = 0ul; ind < version_count; ind++)
       
  4755 					{
       
  4756 						if (p_accepted_peap_versions[ind] > peap_version_2)
       
  4757 						{
       
  4758 							// Not supported PEAP version.
       
  4759 							EAP_TRACE_ERROR(
       
  4760 								m_am_tools,
       
  4761 								TRACE_FLAGS_TLS_PEAP_ERROR,
       
  4762 								(EAPL("ERROR: Not supported PEAP version configuration %s: %d\n"),
       
  4763 								 cf_str_EAP_TLS_PEAP_accepted_PEAP_versions
       
  4764 								 .get_field()->get_field(),
       
  4765 								 *p_accepted_peap_versions));
       
  4766 							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4767 							return EAP_STATUS_RETURN(
       
  4768 								m_am_tools,
       
  4769 								eap_status_illegal_configure_field);
       
  4770 						}
       
  4771 
       
  4772 						status = m_accepted_PEAP_versions.add_data(
       
  4773 							&(p_accepted_peap_versions[ind]),
       
  4774 							sizeof(p_accepted_peap_versions[ind]));
       
  4775 						if (status != eap_status_ok)
       
  4776 						{
       
  4777 							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4778 							return EAP_STATUS_RETURN(m_am_tools, status);
       
  4779 						}
       
  4780 					}
       
  4781 				}
       
  4782 			}
       
  4783 			else
       
  4784 			{
       
  4785 				// Not configured.
       
  4786 				// Accept only version 0.
       
  4787 				u32_t accepted_peap_version = peap_version_0_xp;
       
  4788 
       
  4789 				m_accepted_PEAP_versions.reset();
       
  4790 
       
  4791 				status = m_accepted_PEAP_versions.add_data(
       
  4792 					&accepted_peap_version,
       
  4793 					sizeof(accepted_peap_version));
       
  4794 				if (status != eap_status_ok)
       
  4795 				{
       
  4796 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4797 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  4798 				}
       
  4799 			}
       
  4800 		}
       
  4801 	}
       
  4802 
       
  4803 	//----------------------------------------------------------
       
  4804 
       
  4805 	{
       
  4806 		eap_variable_data_c use_tppd_tls_peap(m_am_tools);
       
  4807 
       
  4808 		status = read_configure(
       
  4809 			cf_str_EAP_TLS_PEAP_use_tppd_tls_peap.get_field(),
       
  4810 			&use_tppd_tls_peap);
       
  4811 		if (status == eap_status_ok
       
  4812 			&& use_tppd_tls_peap.get_is_valid_data() == true)
       
  4813 		{
       
  4814 			u32_t *use_tppd_tls_peap_flag = reinterpret_cast<u32_t *>(
       
  4815 				use_tppd_tls_peap.get_data(sizeof(u32_t)));
       
  4816 			if (use_tppd_tls_peap_flag != 0)
       
  4817 			{
       
  4818 				if (*use_tppd_tls_peap_flag != 0)
       
  4819 				{
       
  4820 					m_use_tppd_tls_peap = true;
       
  4821 				}
       
  4822 				else
       
  4823 				{
       
  4824 					m_use_tppd_tls_peap = false;
       
  4825 				}
       
  4826 			}
       
  4827 		}
       
  4828 	}
       
  4829 
       
  4830 	//----------------------------------------------------------
       
  4831 
       
  4832 #if defined(USE_EAP_EXPANDED_TYPES)
       
  4833 	{
       
  4834 		eap_variable_data_c use_eap_expanded_type(m_am_tools);
       
  4835 
       
  4836 		eap_status_e status = read_configure(
       
  4837 			cf_str_EAP_TLS_PEAP_use_eap_expanded_type.get_field(),
       
  4838 			&use_eap_expanded_type);
       
  4839 
       
  4840 		if (status != eap_status_ok)
       
  4841 		{
       
  4842 			status = read_configure(
       
  4843 				cf_str_EAP_CORE_use_eap_expanded_type.get_field(),
       
  4844 				&use_eap_expanded_type);
       
  4845 		}
       
  4846 
       
  4847 		if (status == eap_status_ok
       
  4848 			&& use_eap_expanded_type.get_data_length() == sizeof(u32_t)
       
  4849 			&& use_eap_expanded_type.get_data() != 0)
       
  4850 		{
       
  4851 			u32_t *flag = reinterpret_cast<u32_t *>(use_eap_expanded_type.get_data(use_eap_expanded_type.get_data_length()));
       
  4852 
       
  4853 			if (flag != 0)
       
  4854 			{
       
  4855 				if ((*flag) != 0ul)
       
  4856 				{
       
  4857 					m_use_eap_expanded_type = true;
       
  4858 				}
       
  4859 				else
       
  4860 				{
       
  4861 					m_use_eap_expanded_type = false;
       
  4862 				}
       
  4863 			}
       
  4864 		}
       
  4865 	}
       
  4866 #endif //#if defined(USE_EAP_EXPANDED_TYPES)
       
  4867 
       
  4868 	//----------------------------------------------------------
       
  4869 
       
  4870 	m_tls_peap_header_offset = get_type_partner()->get_header_offset(
       
  4871 		&m_MTU, &m_trailer_length);
       
  4872 
       
  4873 	if (m_tls_peap_header_offset+m_MTU+m_trailer_length > TLS_PEAP_LOCAL_PACKET_BUFFER_LENGTH)
       
  4874 	{
       
  4875 		EAP_ASSERT_ALWAYS(TLS_PEAP_LOCAL_PACKET_BUFFER_LENGTH
       
  4876 						  >= (m_tls_peap_header_offset+m_trailer_length));
       
  4877 
       
  4878 		m_MTU = TLS_PEAP_LOCAL_PACKET_BUFFER_LENGTH
       
  4879 			- (m_tls_peap_header_offset+m_trailer_length);
       
  4880 	}
       
  4881 
       
  4882 	//----------------------------------------------------------
       
  4883 
       
  4884 #if defined(USE_FAST_EAP_TYPE)
       
  4885 	if (m_current_eap_type == eap_type_fast)
       
  4886 	{
       
  4887 		m_configured_peap_version = peap_version_1;
       
  4888 		m_current_peap_version = peap_version_1;
       
  4889 	}
       
  4890 	else
       
  4891 #endif //#if defined(USE_FAST_EAP_TYPE)
       
  4892 	if (m_current_eap_type == eap_type_tls)
       
  4893 	{
       
  4894 		m_configured_peap_version = peap_version_none;
       
  4895 		m_current_peap_version = peap_version_none;
       
  4896 	}
       
  4897 	else if (m_current_eap_type == eap_type_peap)
       
  4898 	{
       
  4899 		if (m_current_peap_version == peap_version_none)
       
  4900 		{
       
  4901 			// This is the default tunnel type.
       
  4902 			// Default tunnel type is needed if TLS-alert is sent before PEAP-starts.
       
  4903 			m_configured_peap_version = peap_version_2;
       
  4904 			m_current_peap_version = m_configured_peap_version;
       
  4905 		}
       
  4906 	}
       
  4907 
       
  4908 	if (m_current_eap_type == eap_type_peap
       
  4909 		&& m_current_peap_version == peap_version_1)
       
  4910 	{
       
  4911 		m_wait_eap_success_packet = false;
       
  4912 
       
  4913 		EAP_TRACE_DEBUG(
       
  4914 			m_am_tools,
       
  4915 			TRACE_FLAGS_DEFAULT,
       
  4916 			(EAPL("WARNING: %s: because plain PEAP is used ")
       
  4917 			 EAPL("m_wait_eap_success_packet is set to false, type 0x%08x.\n"),
       
  4918 			 (m_is_client == true ? "client": "server"),
       
  4919 			 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  4920 	}
       
  4921 	else if (m_current_eap_type == eap_type_ttls)
       
  4922 	{
       
  4923 		m_wait_eap_success_packet = true;
       
  4924 
       
  4925 		EAP_TRACE_DEBUG(
       
  4926 			m_am_tools,
       
  4927 			TRACE_FLAGS_DEFAULT,
       
  4928 			(EAPL("WARNING: %s: because plain TTLS is used ")
       
  4929 			 EAPL("m_wait_eap_success_packet is set to true, type 0x%08x.\n"),
       
  4930 			 (m_is_client == true ? "client": "server"),
       
  4931 			 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  4932 	}
       
  4933 
       
  4934 
       
  4935 	m_tls_record->set_peap_version(
       
  4936 		m_current_peap_version,
       
  4937 		m_use_tppd_tls_peap,
       
  4938 		m_use_tppd_peapv1_acknowledge_hack);
       
  4939 
       
  4940 
       
  4941 	if (get_type_partner()->get_is_tunneled_eap() == true)
       
  4942 	{
       
  4943 		m_wait_eap_success_packet = true;
       
  4944 
       
  4945 		EAP_TRACE_DEBUG(
       
  4946 			m_am_tools,
       
  4947 			TRACE_FLAGS_DEFAULT,
       
  4948 			(EAPL("WARNING: %s: because this is tunneled session ")
       
  4949 			 EAPL("m_wait_eap_success_packet is set to true, type 0x%08x.\n"),
       
  4950 			 (m_is_client == true ? "client": "server"),
       
  4951 			 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  4952 	}
       
  4953 
       
  4954 	//----------------------------------------------------------
       
  4955 
       
  4956 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4957 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  4958 }
       
  4959 
       
  4960 //--------------------------------------------------
       
  4961 
       
  4962 //
       
  4963 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::shutdown()
       
  4964 {
       
  4965 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  4966 
       
  4967 	EAP_TRACE_DEBUG(
       
  4968 		m_am_tools,
       
  4969 		TRACE_FLAGS_DEFAULT,
       
  4970 		(EAPL("this = 0x%08x => 0x%08x, %s: function: eap_type_tls_peap_c::shutdown()\n"),
       
  4971 		 this,
       
  4972 		 dynamic_cast<abs_eap_base_timer_c *>(this),
       
  4973 		 (m_is_client == true ? "client": "server")));
       
  4974 
       
  4975 	if (m_shutdown_was_called == true)
       
  4976 	{
       
  4977 		// Shutdown was already called (this prevents looping forever)
       
  4978 		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  4979 	}
       
  4980 
       
  4981 	m_shutdown_was_called = true;
       
  4982 
       
  4983 	send_final_notification();
       
  4984 	
       
  4985 	EAP_TRACE_DEBUG(
       
  4986 		m_am_tools,
       
  4987 		TRACE_FLAGS_DEFAULT,
       
  4988 		(EAPL("eap_type_tls_peap_c::shutdown() calls m_tls_record->shutdown()\n")));
       
  4989 
       
  4990 	// Here we ignore return value. Both shutdown() calls must be done.
       
  4991 	eap_status_e status = m_tls_record->shutdown();
       
  4992 
       
  4993 	EAP_TRACE_DEBUG(
       
  4994 		m_am_tools,
       
  4995 		TRACE_FLAGS_DEFAULT,
       
  4996 		(EAPL("eap_type_tls_peap_c::shutdown() calls m_am_type_tls_peap->shutdown()\n")));
       
  4997 
       
  4998 	status = m_am_type_tls_peap->shutdown();
       
  4999 
       
  5000 	EAP_TRACE_DEBUG(
       
  5001 		m_am_tools,
       
  5002 		TRACE_FLAGS_DEFAULT,
       
  5003 		(EAPL("this = 0x%08x => 0x%08x, %s: function: eap_type_tls_peap_c::shutdown() returns\n"),
       
  5004 		 this,
       
  5005 		 dynamic_cast<abs_eap_base_timer_c *>(this),
       
  5006 		 (m_is_client == true ? "client": "server")));
       
  5007 
       
  5008 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5009 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5010 }
       
  5011 
       
  5012 //--------------------------------------------------
       
  5013 
       
  5014 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::set_tls_master_secret(
       
  5015 	const eap_variable_data_c * const eap_tls_master_session_key)
       
  5016 {
       
  5017 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5018 
       
  5019 	EAP_TRACE_DEBUG(
       
  5020 		m_am_tools,
       
  5021 		TRACE_FLAGS_DEFAULT,
       
  5022 		(EAPL("this = 0x%08x => 0x%08x, %s: function: eap_type_tls_peap_c::set_tls_master_secret()\n"),
       
  5023 		 this,
       
  5024 		 dynamic_cast<abs_eap_base_timer_c *>(this),
       
  5025 		 (m_is_client == true ? "client": "server")));
       
  5026 
       
  5027 	EAP_TRACE_DATA_DEBUG(
       
  5028 		m_am_tools,
       
  5029 		TRACE_FLAGS_DEFAULT,
       
  5030 		(EAPL("eap_type_tls_peap_c::set_tls_master_secret():"),
       
  5031 		 eap_tls_master_session_key->get_data(eap_tls_master_session_key->get_data_length()),
       
  5032 		 eap_tls_master_session_key->get_data_length()));
       
  5033 
       
  5034 	eap_status_e status = get_master_session_key()->set_copy_of_buffer(eap_tls_master_session_key);
       
  5035 	if (status != eap_status_ok)
       
  5036 	{
       
  5037 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5038 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5039 	}
       
  5040 
       
  5041 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5042 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5043 }
       
  5044 
       
  5045 //--------------------------------------------------
       
  5046 
       
  5047 //
       
  5048 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::read_configure(
       
  5049 	const eap_configuration_field_c * const field,
       
  5050 	eap_variable_data_c * const data
       
  5051 	)
       
  5052 {
       
  5053 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5054 
       
  5055 	// NOTE this will be read from AM of EAP-TLS/PEAP type.
       
  5056 	eap_status_e status = m_am_type_tls_peap->type_configure_read(field, data);
       
  5057 	if (status != eap_status_ok)
       
  5058 	{
       
  5059 		// EAP-TLS/PEAP AM did not have configuration parameter.
       
  5060 		// Let's try the global configuration.
       
  5061 		status = get_type_partner()->read_configure(field, data);
       
  5062 		if (status != eap_status_ok)
       
  5063 		{
       
  5064 			EAP_TRACE_DATA_DEBUG(
       
  5065 				m_am_tools,
       
  5066 				TRACE_FLAGS_DEFAULT,
       
  5067 				(EAPL("WARNING: eap_type_tls_peap_c::read_configure(): ")
       
  5068 				 EAPL("unknown configuration parameter"),
       
  5069 				field->get_field(),
       
  5070 				field->get_field_length()));
       
  5071 
       
  5072 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5073 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  5074 		}
       
  5075 	}
       
  5076 
       
  5077 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5078 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5079 }
       
  5080 
       
  5081 //--------------------------------------------------
       
  5082 
       
  5083 //
       
  5084 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::write_configure(
       
  5085 	const eap_configuration_field_c * const field,
       
  5086 	eap_variable_data_c * const data
       
  5087 	)
       
  5088 {
       
  5089 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5090 
       
  5091 	// NOTE this will be read from AM of EAP-TLS/PEAP type.
       
  5092 	const eap_status_e status = m_am_type_tls_peap->type_configure_write(field, data);
       
  5093 
       
  5094 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5095 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  5096 }
       
  5097 
       
  5098 //--------------------------------------------------
       
  5099 
       
  5100 //
       
  5101 EAP_FUNC_EXPORT void eap_type_tls_peap_c::state_notification(
       
  5102 	const abs_eap_state_notification_c * const state
       
  5103 	)
       
  5104 {
       
  5105 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5106 
       
  5107 	EAP_TRACE_DEBUG(
       
  5108 		m_am_tools, 
       
  5109 		TRACE_FLAGS_DEFAULT, 
       
  5110 		(EAPL("EAP_type_TLS_PEAP: %s, %s: eap_type_tls_peap_c::state_notification(): ")
       
  5111 		 EAPL("eap_type_tls_peap_state_variable_e %d=%s, notification state=%s.\n"),
       
  5112 		 (m_is_client == true ? "client": "server"),
       
  5113 		 (get_type_partner()->get_is_tunneled_eap() == true ? "tunneled" : "outer most"),
       
  5114 		 get_state(),
       
  5115 		 get_state_string(),
       
  5116 		 eap_state_notification_c::get_state_string(state->get_protocol_layer(), state->get_current_state())));
       
  5117 
       
  5118 
       
  5119 	if (state->get_protocol_layer() == eap_protocol_layer_general)
       
  5120 	{
       
  5121 		// Just forward these notifications to lower layers.
       
  5122 		get_type_partner()->state_notification(state);
       
  5123 		return;
       
  5124 	}
       
  5125 
       
  5126 
       
  5127 	eap_tls_trace_string_c tls_trace;
       
  5128 
       
  5129 
       
  5130 	if (state->get_protocol_layer() == eap_protocol_layer_eap)
       
  5131 	{
       
  5132 		if (state->get_current_state() == eap_state_authentication_terminated_unsuccessfully
       
  5133 #if defined(USE_EAP_PEAPV1_EXTENSIONS)
       
  5134 			|| state->get_current_state() == eap_state_authentication_terminated_unsuccessfully_peapv1_extension
       
  5135 #endif //#if defined(USE_EAP_PEAPV1_EXTENSIONS)
       
  5136 			)
       
  5137 		{
       
  5138 			EAP_TRACE_ERROR(
       
  5139 				m_am_tools,
       
  5140 				TRACE_FLAGS_DEFAULT,
       
  5141 				(EAPL("ERROR: %s: eap_type_tls_peap_c::state_notification(): ")
       
  5142 				 EAPL("authentication failed: EAP-type 0x%08x\n"),
       
  5143 				 (m_is_client == true ? "client": "server"),
       
  5144 				 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  5145 
       
  5146 			m_tunneled_eap_type_authentication_state
       
  5147 				= eap_state_authentication_terminated_unsuccessfully;
       
  5148 
       
  5149 			// Here we must change the EAP-type of the notification.
       
  5150 			{
       
  5151 				eap_state_notification_c * notification = new eap_state_notification_c(
       
  5152 					m_am_tools,
       
  5153 					state->get_send_network_id(),
       
  5154 					state->get_is_client(),
       
  5155 					eap_state_notification_eap,
       
  5156 					state->get_protocol_layer(),
       
  5157 					m_current_eap_type,
       
  5158 					state->get_previous_state(),
       
  5159 					eap_state_authentication_terminated_unsuccessfully,
       
  5160 					state->get_eap_identifier(),
       
  5161 					false);
       
  5162 
       
  5163 				eap_automatic_variable_c<eap_state_notification_c> automatic_notification(m_am_tools, notification);
       
  5164 
       
  5165 				if (notification == 0)
       
  5166 				{
       
  5167 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5168 					set_state(eap_type_tls_peap_state_failure);
       
  5169 					return;
       
  5170 				}
       
  5171 
       
  5172 				notification->set_authentication_error(eap_status_authentication_failure);
       
  5173 
       
  5174 				get_type_partner()->state_notification(notification);
       
  5175 			}
       
  5176 		}
       
  5177 #if defined(USE_EAP_TLS_PEAP_TPPD_PEAP_V1_NEW_FIXES)
       
  5178 		else if (state->get_current_state()
       
  5179 				 == eap_state_tppd_peapv1_authentication_finished_successfully_with_tunneled_eap_success)
       
  5180 		{
       
  5181 			EAP_TRACE_ALWAYS(
       
  5182 				m_am_tools,
       
  5183 				TRACE_FLAGS_DEFAULT,
       
  5184 				(EAPL("%s: eap_type_tls_peap_c::state_notification(): ")
       
  5185 				 EAPL("PEAPv1 authentication tunneled EAP-SUCCESS: EAP-type 0x%08x\n"),
       
  5186 				 (m_is_client == true ? "client": "server"),
       
  5187 				 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  5188 
       
  5189 			m_tunneled_eap_type_authentication_state
       
  5190 				= static_cast<eap_state_variable_e>(state->get_current_state());
       
  5191 
       
  5192 			(void) finish_successful_authentication(true, false, true);
       
  5193 		}
       
  5194 #endif //#if defined(USE_EAP_TLS_PEAP_TPPD_PEAP_V1_NEW_FIXES)
       
  5195 		else if (state->get_current_state() == eap_state_authentication_finished_successfully
       
  5196 #if defined(USE_EAP_PEAPV1_EXTENSIONS)
       
  5197 			|| state->get_current_state() == eap_state_authentication_finished_successfully_peapv1_extension
       
  5198 #endif //#if defined(USE_EAP_PEAPV1_EXTENSIONS)
       
  5199 			)
       
  5200 		{
       
  5201 			EAP_TRACE_ALWAYS(
       
  5202 				m_am_tools,
       
  5203 				TRACE_FLAGS_DEFAULT,
       
  5204 				(EAPL("%s: eap_type_tls_peap_c::state_notification(): ")
       
  5205 				 EAPL("authentication EAP-SUCCESS: EAP-type 0x%08x\n"),
       
  5206 				 (m_is_client == true ? "client": "server"),
       
  5207 				 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  5208 
       
  5209 			m_tunneled_eap_type_authentication_state
       
  5210 				= eap_state_authentication_finished_successfully;
       
  5211 
       
  5212 #if defined(USE_EAP_TLS_PEAP_TPPD_PEAP_V1_NEW_FIXES)
       
  5213 			if (m_current_eap_type == eap_type_peap
       
  5214 				&& m_current_peap_version == peap_version_1
       
  5215 				&& m_use_tppd_tls_peap == true)
       
  5216 			{
       
  5217 				if (m_is_client == true)
       
  5218 				{
       
  5219 #if defined(USE_EAP_PEAPV1_EXTENSIONS)
       
  5220 					if (state->get_current_state() == eap_state_authentication_finished_successfully_peapv1_extension)
       
  5221 					{
       
  5222 						// In this case Server does wait
       
  5223 						// the client send tunneled Extension Response.
       
  5224 						// Here we do not send empty EAP-TLS/PEAP response.
       
  5225 						(void) finish_successful_authentication(false, false, false);
       
  5226 					}
       
  5227 					else
       
  5228 #endif //#if defined(USE_EAP_PEAPV1_EXTENSIONS)
       
  5229 					{
       
  5230 						// In this case Server does not wait
       
  5231 						// the client send empty EAP-TLS/PEAP response.
       
  5232 						(void) finish_successful_authentication(false, false, true);
       
  5233 					}
       
  5234 				}
       
  5235 				else
       
  5236 				{
       
  5237 #if defined(USE_EAP_PEAPV1_EXTENSIONS)
       
  5238 					if (state->get_current_state() == eap_state_authentication_finished_successfully_peapv1_extension)
       
  5239 					{
       
  5240 						// In this case Server does not wait
       
  5241 						// the client send empty EAP-TLS/PEAP response.
       
  5242 						(void) finish_successful_authentication(false, false, true);
       
  5243 					}
       
  5244 					else
       
  5245 #endif //#if defined(USE_EAP_PEAPV1_EXTENSIONS)
       
  5246 					if (m_use_tppd_peapv1_acknowledge_hack == false
       
  5247 						|| get_tls_session_type() == tls_session_type_full_authentication)
       
  5248 					{
       
  5249 						EAP_TRACE_ALWAYS(
       
  5250 							m_am_tools,
       
  5251 							TRACE_FLAGS_DEFAULT,
       
  5252 							(EAPL("%s: eap_type_tls_peap_c::state_notification(): ")
       
  5253 							 EAPL("Waits empty final acknowledge: EAP-type ")
       
  5254 							 EAPL("0x%08x, tunnel type %s\n"),
       
  5255 							 (m_is_client == true ? "client": "server"),
       
  5256 							 convert_eap_type_to_u32_t(m_current_eap_type),
       
  5257 							 tls_trace.get_peap_version_string(m_current_peap_version)));
       
  5258 
       
  5259 						// Server waits the client send empty EAP-TLS/PEAP response.
       
  5260 						set_state(eap_type_tls_peap_state_waiting_for_empty_tppd_peap_v1_acknowledge);
       
  5261 					}
       
  5262 					else
       
  5263 					{
       
  5264 #if !defined(USE_EAP_PEAPV1_EXTENSIONS)
       
  5265 						// In this case Server does not wait
       
  5266 						// the client send empty EAP-TLS/PEAP response.
       
  5267 						(void) finish_successful_authentication(false, false, true);
       
  5268 #else
       
  5269 						EAP_ASSERT_ANYWAY_TOOLS(m_am_tools);
       
  5270 #endif //#if !defined(USE_EAP_PEAPV1_EXTENSIONS)
       
  5271 					}
       
  5272 				}
       
  5273 			}
       
  5274 			else 
       
  5275 #endif //#if defined(USE_EAP_TLS_PEAP_TPPD_PEAP_V1_NEW_FIXES)
       
  5276 			if (m_current_eap_type == eap_type_ttls)
       
  5277 			{
       
  5278 				if (m_is_client == true)
       
  5279 				{
       
  5280 					// In EAP-TTLS case client finishes immediately.
       
  5281 					(void) finish_successful_authentication(false, false, true);
       
  5282 				}
       
  5283 #if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
       
  5284 				else if (m_is_client == false
       
  5285 						 && get_state() == eap_type_tls_peap_state_server_waits_ttls_plain_ms_chap_v2_empty_ack)
       
  5286 				{
       
  5287 					// EAP-TTLS server finishes immediately if plain MsChapv2
       
  5288 					// was run inside tunnel.
       
  5289 					(void) finish_successful_authentication(false, false, true);
       
  5290 				}
       
  5291 #endif //#if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
       
  5292 				else if (m_is_client == false)
       
  5293 				{
       
  5294 					(void) finish_successful_authentication(false, false, true);
       
  5295 				}
       
  5296 			}
       
  5297 			else if (m_current_eap_type == eap_type_peap
       
  5298 						&& (m_current_peap_version == peap_version_0_xp
       
  5299 							|| m_current_peap_version == peap_version_1
       
  5300 							|| m_current_peap_version == peap_version_2))
       
  5301 			{
       
  5302 				if (m_is_client == true)
       
  5303 				{
       
  5304 					(void) finish_successful_authentication(false, false, true);
       
  5305 				}
       
  5306 				else
       
  5307 				{
       
  5308 					// Server
       
  5309 					if (m_current_peap_version == peap_version_1
       
  5310 						&& m_use_tppd_tls_peap == true)
       
  5311 					{
       
  5312 						// Server waits the client send empty EAP-TLS/PEAP response.
       
  5313 						set_state(eap_type_tls_peap_state_waiting_for_empty_tppd_peap_v1_acknowledge);
       
  5314 					}
       
  5315 					else
       
  5316 					{
       
  5317 						(void) finish_successful_authentication(false, false, true);
       
  5318 					}
       
  5319 				}
       
  5320 			}
       
  5321 #if defined(USE_FAST_EAP_TYPE)
       
  5322 			else if (m_current_eap_type == eap_type_fast)
       
  5323 			{
       
  5324 				if (m_is_client == true)
       
  5325 				{
       
  5326 					(void) finish_successful_authentication(false, false, true);
       
  5327 				}
       
  5328 				else
       
  5329 				{
       
  5330 					// Server
       
  5331 					(void) finish_successful_authentication(false, false, true);
       
  5332 				}
       
  5333 			}
       
  5334 #endif //#if defined(USE_FAST_EAP_TYPE)
       
  5335 		}
       
  5336 		else if (state->get_current_state() == eap_state_wait_plain_eap_success)
       
  5337 		{
       
  5338 			m_wait_eap_success_packet = true;
       
  5339 			set_state(eap_type_tls_peap_state_waiting_for_success);
       
  5340 		}
       
  5341 		else if (state->get_current_state() == eap_state_authentication_wait_tppd_peapv1_empty_acknowledge)
       
  5342 		{
       
  5343 			if (m_is_client == false)
       
  5344 			{
       
  5345 				// Send plain EAP-Success.
       
  5346 				get_type_partner()->state_notification(state);
       
  5347 
       
  5348 				// Server waits the client send empty EAP-TLS/PEAP response.
       
  5349 				set_state(eap_type_tls_peap_state_waiting_for_empty_response);
       
  5350 			}
       
  5351 		}
       
  5352 #if defined(USE_FAST_EAP_TYPE)
       
  5353 		else if (m_is_client == false
       
  5354 			&& m_current_eap_type == eap_type_fast
       
  5355 			&& state->get_current_state() == eap_state_authentication_wait_eap_fast_empty_acknowledge)
       
  5356 		{
       
  5357 			// Server waits an empty EAP-FAST acknowledge.
       
  5358 			set_state(eap_type_tls_peap_state_waiting_for_empty_response);
       
  5359 		}
       
  5360 		else if (m_current_eap_type == eap_type_fast
       
  5361 			&& state->get_current_state() == eap_state_use_eap_failure_in_termination)
       
  5362 		{
       
  5363 			(void) finish_successful_authentication(false, true, true);
       
  5364 
       
  5365 			eap_state_notification_c notification(
       
  5366 				m_am_tools,
       
  5367 				get_send_network_id(),
       
  5368 				m_is_client,
       
  5369 				eap_state_notification_eap,
       
  5370 				eap_protocol_layer_eap,
       
  5371 				m_current_eap_type,
       
  5372 				eap_state_none,
       
  5373 				state->get_current_state(),
       
  5374 				get_last_eap_identifier(), // Note the EAP-Success uses the same EAP-Identifier as the last EAP-Request.
       
  5375 				false);
       
  5376 
       
  5377 			get_type_partner()->state_notification(&notification);
       
  5378 		}
       
  5379 #endif //#if defined(USE_FAST_EAP_TYPE)
       
  5380 	}
       
  5381 	else if (state->get_protocol_layer() == eap_protocol_layer_internal_type)
       
  5382 	{
       
  5383 		if (state->get_current_state() == tls_peap_state_failure)
       
  5384 		{
       
  5385 			EAP_TRACE_ERROR(
       
  5386 				m_am_tools,
       
  5387 				TRACE_FLAGS_DEFAULT,
       
  5388 				(EAPL("%s: eap_type_tls_peap_c::state_notification(): TLS tunneled ")
       
  5389 				 EAPL("authentication failed: EAP-type 0x%08x, tunnel type %s\n"),
       
  5390 				 (m_is_client == true ? "client": "server"),
       
  5391 				 convert_eap_type_to_u32_t(m_current_eap_type),
       
  5392 				 tls_trace.get_peap_version_string(m_current_peap_version)));
       
  5393 
       
  5394 			set_state(eap_type_tls_peap_state_failure);
       
  5395 		}
       
  5396 		else if (state->get_current_state() == tls_peap_state_tls_success)
       
  5397 		{
       
  5398 
       
  5399 			if (get_state() != eap_type_tls_peap_state_success
       
  5400 				&& get_state() != eap_type_tls_peap_state_waiting_for_success)
       
  5401 			{
       
  5402 				eap_status_e status = eap_status_process_general_error;
       
  5403 
       
  5404 				if (m_tunneled_eap_type_active == true)
       
  5405 				{
       
  5406 					EAP_TRACE_ALWAYS(
       
  5407 						m_am_tools,
       
  5408 						TRACE_FLAGS_DEFAULT,
       
  5409 						(EAPL("%s: eap_type_tls_peap_c::state_notification(): ")
       
  5410 						 EAPL("TLS tunneled authentication ")
       
  5411 						 EAPL("EAP-SUCCESS: EAP-type 0x%08x, tunnel type %s, style %d\n"),
       
  5412 						 (m_is_client == true ? "client": "server"),
       
  5413 						 convert_eap_type_to_u32_t(m_current_eap_type),
       
  5414 						 tls_trace.get_peap_version_string(m_current_peap_version),
       
  5415 						 m_use_tppd_tls_peap));
       
  5416 					
       
  5417 					if (m_tunneled_eap_type_authentication_state
       
  5418 						== eap_state_authentication_finished_successfully)
       
  5419 					{
       
  5420 						// Tunneled EAP-type finished successfully.
       
  5421 						if (m_is_client == true)
       
  5422 						{
       
  5423 							// Client
       
  5424 							status = finish_successful_authentication(false, false, true);
       
  5425 						}
       
  5426 						else
       
  5427 						{
       
  5428 							// Server
       
  5429 							if (m_current_eap_type == eap_type_peap
       
  5430 								&& m_current_peap_version == peap_version_1
       
  5431 								&& m_use_tppd_tls_peap == true)
       
  5432 							{
       
  5433 								// Server waits the client send empty EAP-TLS/PEAP response.
       
  5434 								set_state(eap_type_tls_peap_state_waiting_for_empty_tppd_peap_v1_acknowledge);
       
  5435 								status = eap_status_ok;
       
  5436 							}
       
  5437 							else
       
  5438 							{
       
  5439 								status = finish_successful_authentication(false, false, true);
       
  5440 							}
       
  5441 						}
       
  5442 					}
       
  5443 					else
       
  5444 					{
       
  5445 						set_state(eap_type_tls_peap_state_failure);
       
  5446 					}
       
  5447 				}
       
  5448 				else if (get_tls_session_type() == tls_session_type_original_session_resumption
       
  5449 					|| get_tls_session_type() == tls_session_type_stateless_session_resumption)
       
  5450 				{
       
  5451 					EAP_TRACE_DEBUG(
       
  5452 						m_am_tools,
       
  5453 						TRACE_FLAGS_DEFAULT,
       
  5454 						(EAPL("%s: eap_type_tls_peap_c::state_notification(): ")
       
  5455 						 EAPL("TLS resumed session authentication ")
       
  5456 						 EAPL("EAP-SUCCESS: EAP-type 0x%08x, m_tls_session_type=%d=%s, tunnel type %s\n"),
       
  5457 						 (m_is_client == true ? "client": "server"),
       
  5458 						 convert_eap_type_to_u32_t(m_current_eap_type),
       
  5459 						 get_tls_session_type(),
       
  5460 						 eap_tls_trace_string_c::get_tls_session_type_string(get_tls_session_type()),
       
  5461 						 tls_trace.get_peap_version_string(m_current_peap_version)));
       
  5462 
       
  5463 					// Saved previous session was resumed.
       
  5464 					m_tunneled_eap_type_authentication_state
       
  5465 						= eap_state_authentication_finished_successfully;
       
  5466 
       
  5467 					if (m_is_client == true)
       
  5468 					{
       
  5469 						if (m_wait_eap_success_packet == true)
       
  5470 						{
       
  5471 							set_state(eap_type_tls_peap_state_waiting_for_success);
       
  5472 						}
       
  5473 						else
       
  5474 						{
       
  5475 							status = finish_successful_authentication(false, false, true);
       
  5476 						}
       
  5477 					}
       
  5478 					else
       
  5479 					{
       
  5480 						// Server
       
  5481 						status = finish_successful_authentication(false, false, true);
       
  5482 					}
       
  5483 				}
       
  5484 				else
       
  5485 				{
       
  5486 					EAP_TRACE_DEBUG(
       
  5487 						m_am_tools,
       
  5488 						TRACE_FLAGS_DEFAULT,
       
  5489 						(EAPL("%s: eap_type_tls_peap_c::state_notification(): ")
       
  5490 						 EAPL("plain TLS authentication EAP-SUCCESS: EAP-type 0x%08x, tunnel type %s\n"),
       
  5491 						 (m_is_client == true ? "client": "server"),
       
  5492 						 convert_eap_type_to_u32_t(m_current_eap_type),
       
  5493 						 tls_trace.get_peap_version_string(m_current_peap_version)));
       
  5494 
       
  5495 					// Plain TLS.
       
  5496 					if (m_is_client == true)
       
  5497 					{
       
  5498 						
       
  5499 						if (get_tls_session_type() == tls_session_type_full_authentication)
       
  5500 						{
       
  5501 							// Client must send a empty response message to server.
       
  5502 							
       
  5503 							// Here we swap the addresses.
       
  5504 							eap_am_network_id_c receive_network_id(m_am_tools,
       
  5505 																   get_send_network_id()->get_destination_id(),
       
  5506 																   get_send_network_id()->get_source_id(),
       
  5507 																   get_send_network_id()->get_type());
       
  5508 							
       
  5509 							status = send_empty_eap_ack();
       
  5510 							if (status != eap_status_ok)
       
  5511 							{
       
  5512 								restore_saved_reassembly_state();
       
  5513 								EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5514 								return;
       
  5515 							}
       
  5516 						}
       
  5517 						
       
  5518 						if (m_current_eap_type == eap_type_tls
       
  5519 							|| m_current_eap_type == eap_type_peap) // This is session resumption case.
       
  5520 						{
       
  5521 							if (m_wait_eap_success_packet == true)
       
  5522 							{
       
  5523 								set_state(eap_type_tls_peap_state_waiting_for_success);
       
  5524 							}
       
  5525 							else
       
  5526 							{
       
  5527 								status = finish_successful_authentication(false, false, true);
       
  5528 							}
       
  5529 						}
       
  5530 						else
       
  5531 						{
       
  5532 							EAP_TRACE_ERROR(
       
  5533 								m_am_tools,
       
  5534 								TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  5535 								(EAPL("ERROR: EAP_type_TLS_PEAP: %s, unknown EAP-type 0x%08x\n"),
       
  5536 								 (m_is_client == true) ? "client": "server",
       
  5537 								 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  5538 							
       
  5539 							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5540 							set_state(eap_type_tls_peap_state_failure);
       
  5541 							return;
       
  5542 						}
       
  5543 					}
       
  5544 					else
       
  5545 					{
       
  5546 						// Server waits the client send empty EAP-TLS/PEAP response.
       
  5547 						set_state(eap_type_tls_peap_state_waiting_for_empty_response);
       
  5548 						status = eap_status_ok;
       
  5549 					}
       
  5550 				}
       
  5551 			}
       
  5552 			else
       
  5553 			{
       
  5554 				EAP_TRACE_DEBUG(
       
  5555 					m_am_tools, 
       
  5556 					TRACE_FLAGS_DEFAULT, 
       
  5557 					(EAPL("WARNING: eap_type_tls_peap_c::state_notification(): ")
       
  5558 					 EAPL("duplicate success notification ")
       
  5559 					 EAPL("eap_type_tls_peap_state_variable_e %d=%s, notification state %d=%s.\n"),
       
  5560 					 get_state(),
       
  5561 					 get_state_string(),
       
  5562 					 state->get_current_state(),
       
  5563 					 state->get_current_state_string()));
       
  5564 			}
       
  5565 		}
       
  5566 		else if (state->get_current_state() == tls_peap_state_full_authentication)
       
  5567 		{
       
  5568 			EAP_TRACE_DEBUG(
       
  5569 				m_am_tools,
       
  5570 				TRACE_FLAGS_DEFAULT,
       
  5571 				(EAPL("%s: eap_type_tls_peap_c::state_notification(): ")
       
  5572 				 EAPL("full TLS authentication: EAP-type 0x%08x\n"),
       
  5573 				 (m_is_client == true ? "client": "server"),
       
  5574 				 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  5575 		}
       
  5576 		else if (state->get_current_state() == tls_peap_state_original_session_resumption)
       
  5577 		{
       
  5578 			EAP_TRACE_DEBUG(
       
  5579 				m_am_tools,
       
  5580 				TRACE_FLAGS_DEFAULT,
       
  5581 				(EAPL("%s: eap_type_tls_peap_c::state_notification(): ")
       
  5582 				 EAPL("TLS session resumption: EAP-type 0x%08x\n"),
       
  5583 				 (m_is_client == true ? "client": "server"),
       
  5584 				 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  5585 		}
       
  5586 #if defined(USE_EAP_TLS_SESSION_TICKET)
       
  5587 		else if (state->get_current_state() == tls_peap_state_stateless_session_resumption)
       
  5588 		{
       
  5589 			EAP_TRACE_DEBUG(
       
  5590 				m_am_tools,
       
  5591 				TRACE_FLAGS_DEFAULT,
       
  5592 				(EAPL("%s: eap_type_tls_peap_c::state_notification(): ")
       
  5593 				 EAPL("TLS stateless session resumption: EAP-type 0x%08x\n"),
       
  5594 				 (m_is_client == true ? "client": "server"),
       
  5595 				 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  5596 		}
       
  5597 #endif // #if defined(USE_EAP_TLS_SESSION_TICKET)
       
  5598 #if defined(USE_EAP_TLS_PEAP_TPPD_PEAP_V1_NEW_FIXES)
       
  5599 		else if (state->get_current_state()
       
  5600 				 == tls_peap_state_tppd_peapv1_waits_eap_success_or_tunneled_packet)
       
  5601 		{
       
  5602 			EAP_TRACE_DEBUG(
       
  5603 				m_am_tools,
       
  5604 				TRACE_FLAGS_DEFAULT,
       
  5605 				(EAPL("%s: eap_type_tls_peap_c::state_notification(): ")
       
  5606 				 EAPL("PEAPv1 waits EAP-Success or tunneled packet: EAP-type 0x%08x\n"),
       
  5607 				 (m_is_client == true ? "client": "server"),
       
  5608 				 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  5609 
       
  5610 			set_state(eap_type_tls_peap_state_tppd_peapv1_waits_eap_success_or_tunneled_packet);
       
  5611 		}
       
  5612 #endif //#if defined(USE_EAP_TLS_PEAP_TPPD_PEAP_V1_NEW_FIXES)
       
  5613 #if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
       
  5614 		else if (state->get_current_state() == tls_peap_state_client_send_ttls_plain_ms_chap_v2_empty_ack)
       
  5615 		{
       
  5616 			EAP_TRACE_ALWAYS(
       
  5617 				m_am_tools,
       
  5618 				TRACE_FLAGS_DEFAULT,
       
  5619 				(EAPL("%s: eap_type_tls_peap_c::state_notification(): ")
       
  5620 				 EAPL("sends TTLS/plain MsChapv2 empty Ack: EAP-type 0x%08x\n"),
       
  5621 				 (m_is_client == true ? "client": "server"),
       
  5622 				 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  5623 
       
  5624 			// Send empty acknowledge message.
       
  5625 			eap_status_e status = send_empty_eap_ack();
       
  5626 			if (status != eap_status_ok)
       
  5627 			{
       
  5628 				set_state(eap_type_tls_peap_state_failure);
       
  5629 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5630 				(void) EAP_STATUS_RETURN(m_am_tools, status);
       
  5631 				return;
       
  5632 			}
       
  5633 		}
       
  5634 #endif //#if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
       
  5635 #if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
       
  5636 		else if (state->get_current_state() == tls_peap_state_server_waits_ttls_plain_ms_chap_v2_empty_ack)
       
  5637 		{
       
  5638 			EAP_TRACE_ALWAYS(
       
  5639 				m_am_tools,
       
  5640 				TRACE_FLAGS_DEFAULT,
       
  5641 				(EAPL("%s: eap_type_tls_peap_c::state_notification(): ")
       
  5642 				 EAPL("waits TTLS/plain MsChapv2 empty Ack: EAP-type 0x%08x\n"),
       
  5643 				 (m_is_client == true ? "client": "server"),
       
  5644 				 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  5645 
       
  5646 			set_state(eap_type_tls_peap_state_server_waits_ttls_plain_ms_chap_v2_empty_ack);
       
  5647 		}
       
  5648 #endif //#if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
       
  5649 		else if (state->get_current_state() == tls_peap_state_peap_tunnel_ready)
       
  5650 		{
       
  5651 			EAP_TRACE_DEBUG(
       
  5652 				m_am_tools,
       
  5653 				TRACE_FLAGS_DEFAULT,
       
  5654 				(EAPL("%s: eap_type_tls_peap_c::state_notification(): ")
       
  5655 				 EAPL("TLS tunnel ready: EAP-type 0x%08x\n"),
       
  5656 				 (m_is_client == true ? "client": "server"),
       
  5657 				 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  5658 
       
  5659 			if (m_is_client == true)
       
  5660 			{
       
  5661 				eap_status_e status = eap_status_process_general_error;
       
  5662 
       
  5663 				if (m_current_eap_type == eap_type_tls
       
  5664 					//|| m_current_eap_type == eap_type_ttls TTLS does not send empty ack.
       
  5665 					|| (m_current_eap_type == eap_type_peap
       
  5666 						&& m_current_peap_version < peap_version_2))
       
  5667 				{
       
  5668 					if (get_tls_session_type() == tls_session_type_full_authentication)
       
  5669 					{
       
  5670 						// Client must sent an empty EAP-response ONLY in full authentication.
       
  5671 
       
  5672 						// Here we swap the addresses.
       
  5673 						eap_am_network_id_c receive_network_id(
       
  5674 							m_am_tools,
       
  5675 							get_send_network_id()->get_destination_id(),
       
  5676 							get_send_network_id()->get_source_id(),
       
  5677 							get_send_network_id()->get_type());
       
  5678 
       
  5679 						status = send_empty_eap_ack();
       
  5680 						if (status != eap_status_ok)
       
  5681 						{
       
  5682 							restore_saved_reassembly_state();
       
  5683 							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5684 							return;
       
  5685 						}
       
  5686 					}
       
  5687 				}
       
  5688 
       
  5689 				if (m_current_eap_type == eap_type_tls)
       
  5690 				{
       
  5691 					if (m_wait_eap_success_packet == true)
       
  5692 					{
       
  5693 						set_state(eap_type_tls_peap_state_waiting_for_success);
       
  5694 					}
       
  5695 					else
       
  5696 					{
       
  5697 						status = finish_successful_authentication(false, false, true);
       
  5698 					}
       
  5699 				}
       
  5700 				else if (m_current_eap_type == eap_type_ttls)
       
  5701 				{
       
  5702 					m_tunneled_eap_type_active = true;
       
  5703 
       
  5704 					set_state(eap_type_tls_peap_state_waiting_for_request);
       
  5705 				}
       
  5706 #if defined(USE_FAST_EAP_TYPE)
       
  5707 				else if (m_current_eap_type == eap_type_fast)
       
  5708 				{
       
  5709 					m_tunneled_eap_type_active = true;
       
  5710 
       
  5711 					if (get_tls_session_type() == tls_session_type_eap_fast_server_unauthenticated_provisioning_mode_ADHP)
       
  5712 					{
       
  5713 						// Client must sent an empty EAP-response ONLY in unauthenticated provisioning mode.
       
  5714 
       
  5715 						// Here we swap the addresses.
       
  5716 						eap_am_network_id_c receive_network_id(
       
  5717 							m_am_tools,
       
  5718 							get_send_network_id()->get_destination_id(),
       
  5719 							get_send_network_id()->get_source_id(),
       
  5720 							get_send_network_id()->get_type());
       
  5721 
       
  5722 						status = send_empty_eap_ack();
       
  5723 						if (status != eap_status_ok)
       
  5724 						{
       
  5725 							restore_saved_reassembly_state();
       
  5726 							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5727 							return;
       
  5728 						}
       
  5729 						set_state(eap_type_tls_peap_state_waiting_for_request);
       
  5730 					}
       
  5731 					else
       
  5732 					{
       
  5733 						set_state(eap_type_tls_peap_state_waiting_for_success);
       
  5734 					}
       
  5735 				}
       
  5736 #endif //#if defined(USE_FAST_EAP_TYPE)
       
  5737 				else if (m_current_eap_type == eap_type_peap)
       
  5738 				{
       
  5739 					m_tunneled_eap_type_active = true;
       
  5740 
       
  5741 					if (m_current_peap_version < peap_version_2)
       
  5742 					{
       
  5743 
       
  5744 #if defined(USE_EAP_TLS_PEAP_TPPD_PEAP_V1_NEW_FIXES)
       
  5745 						if (m_is_client == true
       
  5746 							&& m_current_eap_type == eap_type_peap
       
  5747 							&& m_current_peap_version == peap_version_1
       
  5748 							&& m_use_tppd_tls_peap == true
       
  5749 							&& m_use_tppd_peapv1_acknowledge_hack == true
       
  5750 							&& (get_tls_session_type() == tls_session_type_original_session_resumption
       
  5751 								|| get_tls_session_type() == tls_session_type_stateless_session_resumption)
       
  5752 							&& get_state()
       
  5753 							== eap_type_tls_peap_state_tppd_peapv1_waits_eap_success_or_tunneled_packet)
       
  5754 						{
       
  5755 							// Do not change state here.
       
  5756 						}
       
  5757 						else
       
  5758 #endif //#if defined(USE_EAP_TLS_PEAP_TPPD_PEAP_V1_NEW_FIXES)
       
  5759 						{
       
  5760 							set_state(eap_type_tls_peap_state_waiting_for_request);
       
  5761 						}
       
  5762 					}
       
  5763 				}
       
  5764 				else
       
  5765 				{
       
  5766 					EAP_TRACE_ERROR(
       
  5767 						m_am_tools,
       
  5768 						TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  5769 						(EAPL("ERROR: EAP_type_TLS_PEAP: %s, unknown EAP-type 0x%08x\n"),
       
  5770 						 (m_is_client == true) ? "client": "server",
       
  5771 						 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  5772 					
       
  5773 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5774 					set_state(eap_type_tls_peap_state_failure);
       
  5775 					return;
       
  5776 				}
       
  5777 			}
       
  5778 			else
       
  5779 			{
       
  5780 				if (m_current_eap_type == eap_type_peap)
       
  5781 				{
       
  5782 					if (m_current_peap_version == peap_version_2)
       
  5783 					{
       
  5784 						// Server waits the client send EAP-TLS/PEAP response.
       
  5785 						m_tunneled_eap_type_active = true;
       
  5786 						set_state(eap_type_tls_peap_state_waiting_for_response);
       
  5787 					}
       
  5788 					else
       
  5789 					{
       
  5790 						// Server waits the client send empty EAP-TLS/PEAP response.
       
  5791 						set_state(eap_type_tls_peap_state_waiting_for_empty_response);
       
  5792 					}
       
  5793 				}
       
  5794 				else if (m_current_eap_type == eap_type_ttls)
       
  5795 				{
       
  5796 					// Server waits the client send empty EAP-TLS/PEAP response.
       
  5797 					m_tunneled_eap_type_active = true;
       
  5798 					set_state(eap_type_tls_peap_state_waiting_for_response);
       
  5799 				}
       
  5800 			}
       
  5801 		}
       
  5802 		else if (state->get_current_state() == tls_peap_state_peap_tunnel_ready_wait_request)
       
  5803 		{
       
  5804 			EAP_TRACE_DEBUG(
       
  5805 				m_am_tools,
       
  5806 				TRACE_FLAGS_DEFAULT,
       
  5807 				(EAPL("%s: eap_type_tls_peap_c::state_notification(): ")
       
  5808 				 EAPL("TLS tunnel ready: EAP-type 0x%08x\n"),
       
  5809 				 (m_is_client == true ? "client": "server"),
       
  5810 				 convert_eap_type_to_u32_t(m_current_eap_type)));
       
  5811 
       
  5812 			if (m_is_client == true)
       
  5813 			{
       
  5814 #if defined(USE_FAST_EAP_TYPE)
       
  5815 				if (m_current_eap_type == eap_type_fast)
       
  5816 				{
       
  5817 					m_tunneled_eap_type_active = true;
       
  5818 
       
  5819 					// Client must sent an empty EAP-response.
       
  5820 
       
  5821 					// Here we swap the addresses.
       
  5822 					eap_am_network_id_c receive_network_id(
       
  5823 						m_am_tools,
       
  5824 						get_send_network_id()->get_destination_id(),
       
  5825 						get_send_network_id()->get_source_id(),
       
  5826 						get_send_network_id()->get_type());
       
  5827 
       
  5828 					eap_status_e status = send_empty_eap_ack();
       
  5829 					if (status != eap_status_ok)
       
  5830 					{
       
  5831 						restore_saved_reassembly_state();
       
  5832 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5833 						return;
       
  5834 					}
       
  5835 					set_state(eap_type_tls_peap_state_waiting_for_request);
       
  5836 				}
       
  5837 				else
       
  5838 #endif //#if defined(USE_FAST_EAP_TYPE)
       
  5839 				{
       
  5840 					EAP_ASSERT_ANYWAY_TOOLS(m_am_tools);
       
  5841 				}
       
  5842 			}
       
  5843 			else
       
  5844 			{
       
  5845 				EAP_ASSERT_ANYWAY_TOOLS(m_am_tools);
       
  5846 			}
       
  5847 		}
       
  5848 		else if (state->get_current_state() == tls_peap_state_pending_tls_messages_processed)
       
  5849 		{
       
  5850 			if (get_state() == eap_type_tls_peap_state_process_tls_message
       
  5851 				|| get_state() == eap_type_tls_peap_state_process_tls_start)
       
  5852 			{
       
  5853 				if (m_is_client == true)
       
  5854 				{
       
  5855 					set_state(eap_type_tls_peap_state_waiting_for_request);
       
  5856 				}
       
  5857 				else
       
  5858 				{
       
  5859 					set_state(eap_type_tls_peap_state_waiting_for_response);
       
  5860 				}
       
  5861 			}
       
  5862 		}
       
  5863 	}
       
  5864 
       
  5865 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5866 }
       
  5867 
       
  5868 //--------------------------------------------------
       
  5869 
       
  5870 //
       
  5871 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::query_eap_identity(
       
  5872 	const bool /* must_be_synchronous */,
       
  5873 	eap_variable_data_c * const identity,
       
  5874 	const eap_am_network_id_c * const receive_network_id,
       
  5875 	const u8_t eap_identifier)
       
  5876 {
       
  5877 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5878 
       
  5879 	EAP_TRACE_DEBUG(
       
  5880 		m_am_tools, 
       
  5881 		TRACE_FLAGS_DEFAULT, 
       
  5882 		(EAPL("eap_type_tls_peap_c::query_eap_identity() ")
       
  5883 		 EAPL("in eap_type_tls_peap_state_variable_e %d=%s.\n"),
       
  5884 		 get_state(),
       
  5885 		 get_state_string()));
       
  5886 
       
  5887 	if (m_tls_peap_test_version == true
       
  5888 		&& get_state() == eap_type_tls_peap_state_failure)
       
  5889 	{
       
  5890 		// This is for testing.
       
  5891 		if (m_is_client == false)
       
  5892 		{
       
  5893 			set_state(eap_type_tls_peap_state_waiting_for_identity_response);
       
  5894 		}
       
  5895 		else if (m_is_client == true)
       
  5896 		{
       
  5897 			set_state(eap_type_tls_peap_state_waiting_for_tls_start);
       
  5898 		}
       
  5899 	}
       
  5900 
       
  5901 
       
  5902 	bool use_manual_username(false);
       
  5903 	eap_variable_data_c manual_username(m_am_tools);
       
  5904 	bool use_manual_realm(false);
       
  5905 	eap_variable_data_c manual_realm(m_am_tools);
       
  5906 
       
  5907 
       
  5908 	if (m_state == eap_type_tls_peap_state_waiting_for_identity_request
       
  5909 		|| (m_tls_peap_test_version == true // This one is for testing purposes.
       
  5910 			&& m_state == eap_type_tls_peap_state_success))
       
  5911 	{
       
  5912 		save_current_state();
       
  5913 		set_state(eap_type_tls_peap_state_pending_identity_query);
       
  5914 
       
  5915 		eap_status_e status = eap_status_process_general_error;
       
  5916 
       
  5917 		status = m_am_type_tls_peap->query_eap_identity(
       
  5918 			identity,
       
  5919 			receive_network_id,
       
  5920 			eap_identifier,
       
  5921 			&use_manual_username,
       
  5922 			&manual_username,
       
  5923 			&use_manual_realm,
       
  5924 			&manual_realm);
       
  5925 
       
  5926 		if (status == eap_status_pending_request)
       
  5927 		{
       
  5928 			// This is pending query, that will be completed by complete_eap_identity_query() call.
       
  5929 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5930 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  5931 		}
       
  5932 		else if (status == eap_status_completed_request)
       
  5933 		{
       
  5934 			// This is already completed by complete_eap_identity_query() call.
       
  5935 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5936 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  5937 		}
       
  5938 		else if (status != eap_status_ok
       
  5939 			&& status != eap_status_success)
       
  5940 		{
       
  5941 			// This is an error case.
       
  5942 			restore_saved_previous_state();
       
  5943 
       
  5944 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5945 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  5946 		}
       
  5947 		else
       
  5948 		{
       
  5949 			status = handle_eap_identity_query(
       
  5950 				identity,
       
  5951 				receive_network_id,
       
  5952 				eap_identifier,
       
  5953 				use_manual_username,
       
  5954 				&manual_username,
       
  5955 				use_manual_realm,
       
  5956 				&manual_realm);
       
  5957 		}
       
  5958 
       
  5959 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5960 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  5961 	}
       
  5962 	else if (m_state == eap_type_tls_peap_state_waiting_for_tls_start)
       
  5963 	{
       
  5964 		// This is re-transmission request. We do not change our state.
       
  5965 		// Just send EAP-Identity again.
       
  5966 		if (get_NAI()->get_is_valid_data() == true)
       
  5967 		{
       
  5968 			eap_status_e status = identity->set_copy_of_buffer(get_NAI());
       
  5969 
       
  5970 			EAP_TRACE_DEBUG(
       
  5971 				m_am_tools, 
       
  5972 				TRACE_FLAGS_DEFAULT, 
       
  5973 				(EAPL("eap_type_tls_peap_c::query_eap_identity() ")
       
  5974 				 EAPL("returns already obtained NAI in ")
       
  5975 				 EAPL("eap_type_tls_peap_state_variable_e %d=%s.\n"),
       
  5976 				 get_state(),
       
  5977 				 get_state_string()));
       
  5978 
       
  5979 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5980 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  5981 		}
       
  5982 		else
       
  5983 		{
       
  5984 			EAP_TRACE_ERROR(
       
  5985 				m_am_tools, 
       
  5986 				TRACE_FLAGS_TLS_PEAP_ERROR, 
       
  5987 				(EAPL("ERROR: eap_type_tls_peap_c::query_eap_identity(): ")
       
  5988 				 EAPL("EAP-Request/Identity cannot be completed, identity (NAI) ")
       
  5989 				 EAPL("is missing. in eap_type_tls_peap_state_variable_e %d=%s.\n"),
       
  5990 				 get_state(),
       
  5991 				 get_state_string()));
       
  5992 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  5993 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  5994 		}
       
  5995 	}
       
  5996 	else if (m_state == eap_type_tls_peap_state_pending_identity_query)
       
  5997 	{
       
  5998 		EAP_TRACE_DEBUG(
       
  5999 			m_am_tools,
       
  6000 			TRACE_FLAGS_DEFAULT,
       
  6001 			(EAPL("eap_type_tls_peap_c::query_eap_identity(): ")
       
  6002 			 EAPL("Already pending EAP-Identity query in ")
       
  6003 			 EAPL("eap_type_tls_peap_state_variable_e %d=%s.\n"),
       
  6004 			get_state(),
       
  6005 			get_state_string()));
       
  6006 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6007 		return EAP_STATUS_RETURN(m_am_tools, eap_status_pending_request);
       
  6008 	}
       
  6009 	else
       
  6010 	{	
       
  6011 		EAP_TRACE_ERROR(
       
  6012 			m_am_tools,
       
  6013 			TRACE_FLAGS_TLS_PEAP_ERROR,
       
  6014 			(EAPL("ERROR: eap_type_tls_peap_c::query_eap_identity(): ")
       
  6015 			 EAPL("Illegal EAP-Identity query in eap_type_tls_peap_state_variable_e %d=%s.\n"),
       
  6016 			get_state(),
       
  6017 			get_state_string()));
       
  6018 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6019 		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
       
  6020 	}
       
  6021 }
       
  6022 
       
  6023 //--------------------------------------------------
       
  6024 
       
  6025 //
       
  6026 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::set_initial_eap_identifier(
       
  6027 	const eap_am_network_id_c * const /*receive_network_id*/,
       
  6028 	const u8_t /*initial_identifier*/)
       
  6029 {
       
  6030 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6031 
       
  6032 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6033 	return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
       
  6034 }
       
  6035 
       
  6036 //--------------------------------------------------
       
  6037 
       
  6038 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::eap_acknowledge(
       
  6039 	const eap_am_network_id_c * const receive_network_id)
       
  6040 {
       
  6041 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6042 
       
  6043 	eap_status_e status(eap_status_ok);
       
  6044 
       
  6045 	if (get_state() == eap_type_tls_peap_state_waiting_for_success)
       
  6046 	{
       
  6047 		if (m_wait_eap_success_packet == false)
       
  6048 		{
       
  6049 			/**
       
  6050 			 * @{ check right functionality.
       
  6051 			 * Here we return eap_status_ok, eap_status_success was
       
  6052 			 * returned after successfull
       
  6053 			 * EAP-Request/SIM/Challenge. This may change after EAP,
       
  6054 			 * 802.1X and 802.11i specifications are ready. }
       
  6055 			 */
       
  6056 			status = eap_status_ok;
       
  6057 		}
       
  6058 		else
       
  6059 		{
       
  6060 			if (m_current_eap_type == eap_type_tls)
       
  6061 			{
       
  6062 				status = finish_successful_authentication(false, false, true);
       
  6063 				if (status != eap_status_success)
       
  6064 				{
       
  6065 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6066 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  6067 				}
       
  6068 			}
       
  6069 			else
       
  6070 			{
       
  6071 				// We must forward this to the tunneled EAP-type.
       
  6072 
       
  6073 				status = m_tls_record->plain_eap_success_failure_packet_received(
       
  6074 					receive_network_id,
       
  6075 					eap_code_success,
       
  6076 					m_last_eap_identifier);
       
  6077 			}
       
  6078 		}
       
  6079 	}
       
  6080 	else
       
  6081 	{
       
  6082 		EAP_TRACE_DEBUG(
       
  6083 			m_am_tools, 
       
  6084 			TRACE_FLAGS_DEFAULT, 
       
  6085 			(EAPL("ignored eap_acknowledge(): state %d=%s, is client %d, m_wait_eap_success_packet=%d, m_authentication_finished_successfully=%d\n"),
       
  6086 			get_state(),
       
  6087 			get_state_string(),
       
  6088 			(m_is_client == true),
       
  6089 			m_wait_eap_success_packet,
       
  6090 			m_authentication_finished_successfully));
       
  6091 	}
       
  6092 
       
  6093 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6094 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  6095 }
       
  6096 
       
  6097 //--------------------------------------------------
       
  6098 
       
  6099 //
       
  6100 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::reset()
       
  6101 {
       
  6102 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6103 
       
  6104 	EAP_TRACE_DEBUG(
       
  6105 		m_am_tools,
       
  6106 		TRACE_FLAGS_DEFAULT,
       
  6107 		(EAPL("this = 0x%08x, %s: eap_type_tls_peap_c::reset(): %d=%s.\n"),
       
  6108 		 this,
       
  6109 		 (m_is_client == true) ? "client": "server",
       
  6110 		 get_state(),
       
  6111 		 get_state_string()));
       
  6112 
       
  6113 	m_current_identity.reset();
       
  6114 
       
  6115 	if (m_is_client == true)
       
  6116 	{
       
  6117 		// Client waits EAP-Request/Identity.
       
  6118 		m_state = eap_type_tls_peap_state_waiting_for_identity_request;
       
  6119 		m_saved_previous_state = eap_type_tls_peap_state_waiting_for_identity_request;
       
  6120 	}
       
  6121 	else if (m_is_client == false)
       
  6122 	{
       
  6123 		// Server waits EAP-Response/Identity.
       
  6124 		m_state = eap_type_tls_peap_state_waiting_for_identity_response;
       
  6125 		m_saved_previous_state = eap_type_tls_peap_state_waiting_for_identity_response;
       
  6126 	}
       
  6127 
       
  6128 	m_reassembly_state = eap_type_tls_peap_reassembly_state_wait_first_message;
       
  6129 
       
  6130 	m_saved_previous_reassembly_state = eap_type_tls_peap_reassembly_state_wait_first_message;
       
  6131 
       
  6132 	m_tls_message_send_offset = 0ul;
       
  6133 
       
  6134 	m_includes_tls_handshake_message = false;
       
  6135 
       
  6136 	m_tls_message_buffer.reset();
       
  6137 
       
  6138 	m_master_session_key.reset();
       
  6139 
       
  6140 	m_tunneled_eap_type_active = false;
       
  6141 	m_tunneled_eap_type_authentication_state = eap_state_none;
       
  6142 
       
  6143 	set_tls_session_type(tls_session_type_none);
       
  6144 
       
  6145 	eap_status_e status = m_tls_record->reset();
       
  6146 
       
  6147 	m_failure_message_received = false;
       
  6148 	m_authentication_finished_successfully = false;
       
  6149 	m_last_eap_identifier = 0ul;
       
  6150 
       
  6151 	m_current_peap_version = m_configured_peap_version;
       
  6152 
       
  6153 	m_first_fragment_eap_identifier = 0ul;
       
  6154 
       
  6155 	m_am_type_tls_peap->reset();
       
  6156 
       
  6157 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6158 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  6159 }
       
  6160 
       
  6161 //--------------------------------------------------
       
  6162 
       
  6163 //
       
  6164 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::set_timer(
       
  6165 	abs_eap_base_timer_c * const p_initializer, 
       
  6166 	const u32_t p_id, 
       
  6167 	void * const p_data,
       
  6168 	const u32_t p_time_ms)
       
  6169 {
       
  6170 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6171 
       
  6172 	eap_status_e status = get_type_partner()->set_timer(
       
  6173 		p_initializer, 
       
  6174 		p_id, 
       
  6175 		p_data,
       
  6176 		p_time_ms);
       
  6177 
       
  6178 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6179 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  6180 }
       
  6181 
       
  6182 //--------------------------------------------------
       
  6183 
       
  6184 //
       
  6185 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::cancel_timer(
       
  6186 	abs_eap_base_timer_c * const p_initializer, 
       
  6187 	const u32_t p_id)
       
  6188 {
       
  6189 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6190 
       
  6191 	eap_status_e status = get_type_partner()->cancel_timer(
       
  6192 		p_initializer, 
       
  6193 		p_id);
       
  6194 
       
  6195 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6196 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  6197 }
       
  6198 
       
  6199 //--------------------------------------------------
       
  6200 
       
  6201 //
       
  6202 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::cancel_all_timers()
       
  6203 {
       
  6204 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6205 
       
  6206 	eap_status_e status = get_type_partner()->cancel_all_timers();
       
  6207 
       
  6208 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6209 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  6210 }
       
  6211 
       
  6212 //--------------------------------------------------
       
  6213 
       
  6214 // This is commented in abs_tls_base_application_c.
       
  6215 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::load_module(
       
  6216 	const eap_type_value_e type,
       
  6217 	const eap_type_value_e tunneling_type,
       
  6218 	abs_eap_base_type_c * const partner,
       
  6219 	eap_base_type_c ** const eap_type,
       
  6220 	const bool is_client_when_true,
       
  6221 	const eap_am_network_id_c * const receive_network_id)
       
  6222 {
       
  6223 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6224 
       
  6225 	// This call is forwarded to EAPOL AM module because it handles all the 
       
  6226 	// tunneled EAP type handlings for PEAP.
       
  6227 	const eap_status_e status =  get_type_partner()->load_module(
       
  6228 		type,
       
  6229 		tunneling_type,
       
  6230 		partner,
       
  6231 		eap_type,
       
  6232 		is_client_when_true,
       
  6233 		receive_network_id);
       
  6234 	
       
  6235 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6236 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  6237 }
       
  6238 
       
  6239 //--------------------------------------------------
       
  6240 
       
  6241 // This is commented in abs_tls_base_application_c.
       
  6242 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::unload_module(const eap_type_value_e type)
       
  6243 {
       
  6244 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6245 
       
  6246 	// This call is forwarded to EAPOL AM module because it handles all the 
       
  6247 	// tunneled EAP type handlings for PEAP.
       
  6248 	const eap_status_e status = get_type_partner()->unload_module(type);
       
  6249 
       
  6250 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6251 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  6252 }
       
  6253 
       
  6254 //--------------------------------------------------
       
  6255 
       
  6256 // This is commented in abs_tls_base_application_c.
       
  6257 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::restart_authentication(
       
  6258 	const eap_am_network_id_c * const receive_network_id,
       
  6259 	const bool is_client_when_true,
       
  6260 	const bool /*force_clean_restart*/,
       
  6261 	const bool /*from_timer*/)
       
  6262 {
       
  6263 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6264 
       
  6265 	// Here we swap the addresses.
       
  6266 	eap_am_network_id_c send_network_id(m_am_tools,
       
  6267 		receive_network_id->get_destination_id(),
       
  6268 		receive_network_id->get_source_id(),
       
  6269 		receive_network_id->get_type());
       
  6270 
       
  6271 	const eap_status_e status = get_type_partner()->restart_authentication(
       
  6272 		&send_network_id,
       
  6273 		is_client_when_true);
       
  6274 
       
  6275 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6276 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  6277 }
       
  6278 
       
  6279 //--------------------------------------------------
       
  6280 
       
  6281 // This is commented in abs_tls_base_application_c.
       
  6282 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::packet_data_crypto_keys(
       
  6283 	const eap_am_network_id_c * const /*send_network_id*/,
       
  6284 	const eap_master_session_key_c * const /*master_session_key*/)
       
  6285 {
       
  6286 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6287 
       
  6288 	// NOTE we do NOT forwrd keys to lower layer.
       
  6289 
       
  6290 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6291 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  6292 }
       
  6293 
       
  6294 //--------------------------------------------------
       
  6295 
       
  6296 // This is commented in abs_tls_base_application_c.
       
  6297 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::check_is_valid_eap_type(
       
  6298 	const eap_type_value_e eap_type)
       
  6299 {
       
  6300 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6301 
       
  6302 	// This call is forwarded to TLS AM module because it handles all the 
       
  6303 	// tunneled EAP type handlings for PEAP.
       
  6304 	const eap_status_e status = m_am_type_tls_peap->check_is_valid_eap_type(eap_type);
       
  6305 
       
  6306 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6307 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  6308 }
       
  6309 
       
  6310 //--------------------------------------------------
       
  6311 
       
  6312 // This is commented in abs_tls_base_application_c.
       
  6313 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::get_eap_type_list(
       
  6314 	eap_array_c<eap_type_value_e> * const eap_type_list)
       
  6315 {
       
  6316 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6317 
       
  6318 	const eap_status_e status = m_am_type_tls_peap->get_eap_type_list(eap_type_list);
       
  6319 
       
  6320 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6321 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  6322 }
       
  6323 
       
  6324 //--------------------------------------------------
       
  6325 
       
  6326 //
       
  6327 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::set_session_timeout(
       
  6328 	const u32_t session_timeout_ms)
       
  6329 {
       
  6330 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6331 
       
  6332 	const eap_status_e status = get_type_partner()->set_session_timeout(session_timeout_ms);
       
  6333 
       
  6334 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6335 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  6336 }
       
  6337 
       
  6338 //--------------------------------------------------
       
  6339 
       
  6340 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::add_rogue_ap(
       
  6341 	eap_array_c<eap_rogue_ap_entry_c> & rogue_ap_list)
       
  6342 {
       
  6343 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6344 
       
  6345 	const eap_status_e status = get_type_partner()->add_rogue_ap(rogue_ap_list);
       
  6346 
       
  6347 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6348 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  6349 }
       
  6350 
       
  6351 //--------------------------------------------------
       
  6352 
       
  6353 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::peap_tunnel_ready()
       
  6354 {
       
  6355 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6356 
       
  6357 	EAP_TRACE_DEBUG(
       
  6358 		m_am_tools,
       
  6359 		TRACE_FLAGS_DEFAULT,
       
  6360 		(EAPL("this = 0x%08x, %s: eap_type_tls_peap_c::peap_tunnel_ready() in ")
       
  6361 		 EAPL("eap_type_tls_peap_state_variable_e %d=%s.\n"),
       
  6362 		 this,
       
  6363 		 (m_is_client == true ? "client": "server"),
       
  6364 		 get_state(),
       
  6365 		 get_state_string()));
       
  6366 
       
  6367 	m_tunneled_eap_type_active = true;
       
  6368 
       
  6369 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6370 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  6371 }
       
  6372 
       
  6373 //--------------------------------------------------
       
  6374 
       
  6375 EAP_FUNC_EXPORT eap_status_e eap_type_tls_peap_c::set_tls_session_type(const tls_session_type_e tls_session_type)
       
  6376 {
       
  6377 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6378 
       
  6379 	EAP_TRACE_DEBUG(
       
  6380 		m_am_tools,
       
  6381 		TRACE_FLAGS_DEFAULT,
       
  6382 		(EAPL("this = 0x%08x, %s: eap_type_tls_peap_c::set_tls_session_type() in ")
       
  6383 		 EAPL("m_tls_session_type=%d=%s.\n"),
       
  6384 		 this,
       
  6385 		 (m_is_client == true ? "client": "server"),
       
  6386 		 tls_session_type,
       
  6387 		 eap_tls_trace_string_c::get_tls_session_type_string(tls_session_type)));
       
  6388 
       
  6389 	m_tls_session_type = tls_session_type;
       
  6390 
       
  6391 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  6392 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  6393 }
       
  6394 
       
  6395 //--------------------------------------------------
       
  6396 
       
  6397 EAP_FUNC_EXPORT tls_session_type_e eap_type_tls_peap_c::get_tls_session_type()
       
  6398 {
       
  6399 	return m_tls_session_type;
       
  6400 }
       
  6401 
       
  6402 //--------------------------------------------------
       
  6403 
       
  6404 // End.