eapol/eapol_framework/eapol_common/type/mschapv2/core/eap_type_mschapv2.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 95 
       
    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 // INCLUDE FILES
       
    29 
       
    30 #include "eap_am_memory.h"
       
    31 #include "eap_state_notification.h"
       
    32 #include "eap_type_mschapv2_header.h"
       
    33 #include "eap_type_mschapv2.h"
       
    34 #include "eap_type_mschapv2_credential_store.h"
       
    35 #include "eap_buffer.h"
       
    36 #include "eap_config.h"
       
    37 #include "eap_master_session_key.h"
       
    38 #include "eap_automatic_variable.h"
       
    39 
       
    40 /**
       
    41 * Constructor initializes all member attributes.
       
    42 */
       
    43 
       
    44 EAP_FUNC_EXPORT eap_type_mschapv2_c::eap_type_mschapv2_c(
       
    45 	abs_eap_am_tools_c * const tools,
       
    46 	abs_eap_base_type_c * const partner,
       
    47 	eap_am_type_mschapv2_c * const am_type_mschapv2,
       
    48 	const bool free_am_type_mschapv2,
       
    49 	const bool is_client_when_true,
       
    50 	const eap_am_network_id_c * const receive_network_id)
       
    51 	: eap_base_type_c(tools, partner)
       
    52 	, m_am_type_mschapv2(am_type_mschapv2)
       
    53 	, m_am_tools(tools)
       
    54 	, m_session(tools, is_client_when_true)
       
    55 	, m_send_network_id(tools)
       
    56 	, m_rand(tools)
       
    57 	, m_username_utf8(tools)
       
    58 	, m_password_utf8(tools)
       
    59 	, m_old_password_utf8(tools)
       
    60 	, m_password_hash(tools)
       
    61 	, m_password_hash_hash(tools)
       
    62 #if defined(USE_FAST_EAP_TYPE)
       
    63 	, m_client_EAP_FAST_challenge(tools)
       
    64 	, m_server_EAP_FAST_challenge(tools)
       
    65 #endif //#if defined(USE_FAST_EAP_TYPE)
       
    66 	, m_offset(0)
       
    67 	, m_mtu_length(0)
       
    68 	, m_trailer_length(0)
       
    69 	, m_error_code(0)
       
    70 	, m_is_valid(false)
       
    71 	, m_is_client(is_client_when_true)
       
    72 	, m_free_am_type_mschapv2(free_am_type_mschapv2)
       
    73 	, m_is_pending(false)
       
    74 	, m_identity_asked(false)
       
    75 	, m_wait_eap_success(false)
       
    76 	, m_wait_eap_success_packet(true)
       
    77 	, m_is_reauthentication(false)
       
    78 	, m_is_notification_sent(false)
       
    79 	, m_shutdown_was_called(false)
       
    80 	, m_password_prompt_enabled(true)
       
    81 	, m_identifier(0)
       
    82 	, m_mschapv2id(0)
       
    83 #if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
       
    84 	, m_use_implicit_challenge(false)
       
    85 #endif //#if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
       
    86 #if defined(EAP_MSCHAPV2_SERVER)
       
    87 	, m_do_password_expiration_tests(false)
       
    88 	, m_password_expired(false)
       
    89 #endif //#if defined(EAP_MSCHAPV2_SERVER)
       
    90 	, m_do_wrong_password_tests(false)
       
    91 	, m_use_eap_expanded_type(false)
       
    92 #if defined(USE_FAST_EAP_TYPE)
       
    93 	, m_use_EAP_FAST_full_key(false)
       
    94 	, m_use_EAP_FAST_challenge(false)
       
    95 #endif //#if defined(USE_FAST_EAP_TYPE)
       
    96 {
       
    97 	EAP_TRACE_DEBUG(
       
    98 		m_am_tools, 
       
    99 		TRACE_FLAGS_DEFAULT, 
       
   100 		(EAPL("eap_type_mschapv2_c::eap_type_mschapv2_c(): this = 0x%08x, ")
       
   101 		 EAPL("partner 0x%08x, type partner 0x%08x, compiled %s %s\n"),
       
   102 		 this,
       
   103 		 partner,
       
   104 		 get_type_partner(),
       
   105 		__DATE__,
       
   106 		__TIME__));
       
   107 
       
   108 	m_am_type_mschapv2->set_am_partner(this);
       
   109 
       
   110 	{
       
   111 		// Here we swap the addresses.
       
   112 		eap_am_network_id_c send_network_id(m_am_tools,
       
   113 			receive_network_id->get_destination_id(),
       
   114 			receive_network_id->get_source_id(),
       
   115 			receive_network_id->get_type());
       
   116 
       
   117 		eap_status_e status = m_send_network_id.set_copy_of_network_id(&send_network_id);
       
   118 
       
   119 		if (status != eap_status_ok
       
   120 			|| m_send_network_id.get_is_valid_data() == false)
       
   121 		{
       
   122 			(void)EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   123 			return;
       
   124 		}
       
   125 	}
       
   126 
       
   127 	m_is_valid = true;
       
   128 }
       
   129 
       
   130 //--------------------------------------------------
       
   131 
       
   132 EAP_FUNC_EXPORT eap_type_mschapv2_c::~eap_type_mschapv2_c()
       
   133 {
       
   134 	EAP_TRACE_DEBUG(
       
   135 		m_am_tools, 
       
   136 		TRACE_FLAGS_DEFAULT, 
       
   137 		(EAPL("eap_type_mschapv2_c::~eap_type_mschapv2_c(): this = 0x%08x\n"),
       
   138 		this));
       
   139 
       
   140 	EAP_ASSERT(m_shutdown_was_called == true);	
       
   141 
       
   142 	if (m_free_am_type_mschapv2 == true)
       
   143 	{
       
   144 		delete m_am_type_mschapv2;
       
   145 	}
       
   146 	m_free_am_type_mschapv2 = false;
       
   147 }
       
   148 
       
   149 //--------------------------------------------------
       
   150 
       
   151 EAP_FUNC_EXPORT eap_status_e eap_type_mschapv2_c::shutdown()
       
   152 {
       
   153 	EAP_TRACE_DEBUG(
       
   154 		m_am_tools, 
       
   155 		TRACE_FLAGS_DEFAULT, 
       
   156 		(EAPL("eap_type_mschapv2_c::shutdown(): this = 0x%08x, m_session.get_state()=%d, m_is_notification_sent=%d\n"),
       
   157 		this,
       
   158 		m_session.get_state(),
       
   159 		m_is_notification_sent));
       
   160 
       
   161 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eap_type_mschapv2_c::shutdown()");
       
   162 
       
   163 	m_am_type_mschapv2->shutdown();
       
   164 	m_shutdown_was_called = true;
       
   165 
       
   166 	if (m_session.get_state() != eap_type_mschapv2_state_none)
       
   167 	{
       
   168 		if (m_is_notification_sent == false)
       
   169 		{
       
   170 			finish_unsuccessful_authentication(false);
       
   171 		}
       
   172 	}
       
   173 
       
   174 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   175 }
       
   176 
       
   177 //--------------------------------------------------
       
   178 
       
   179 EAP_FUNC_EXPORT void eap_type_mschapv2_c::set_is_valid()
       
   180 {
       
   181 	m_is_valid = true;
       
   182 }
       
   183 
       
   184 //--------------------------------------------------
       
   185 
       
   186 EAP_FUNC_EXPORT bool eap_type_mschapv2_c::get_is_valid()
       
   187 {
       
   188 	return m_is_valid;
       
   189 }
       
   190 
       
   191 //--------------------------------------------------
       
   192 
       
   193 EAP_FUNC_EXPORT bool eap_type_mschapv2_c::get_is_client() 
       
   194 {
       
   195 	return m_is_client;
       
   196 }
       
   197 
       
   198 //--------------------------------------------------
       
   199 
       
   200 void eap_type_mschapv2_c::send_error_notification(const eap_status_e error)
       
   201 {
       
   202 	// Notifies the lower level of an authentication error.
       
   203 	eap_state_notification_c notification(
       
   204 		m_am_tools,
       
   205 		&m_send_network_id,
       
   206 		m_is_client,
       
   207 		eap_state_notification_eap,
       
   208 		eap_protocol_layer_general,
       
   209 		eap_type_mschapv2,
       
   210 		eap_state_none,
       
   211 		eap_general_state_authentication_error,
       
   212 		0,
       
   213 		false);
       
   214 
       
   215 	notification.set_authentication_error(error);
       
   216 
       
   217 	get_type_partner()->state_notification(&notification);
       
   218 }
       
   219 
       
   220 //--------------------------------------------------
       
   221 
       
   222 eap_buf_chain_wr_c * eap_type_mschapv2_c::create_send_packet(u32_t length)
       
   223 {
       
   224 	eap_buf_chain_wr_c * packet = new eap_buf_chain_wr_c(
       
   225 		eap_write_buffer, 
       
   226 		m_am_tools,
       
   227 		length + m_offset + m_trailer_length);
       
   228 	if (!packet)
       
   229 	{
       
   230 		return 0;
       
   231 	}
       
   232 	if (packet->get_is_valid() == false)
       
   233 	{
       
   234 		delete packet;
       
   235 		return 0;
       
   236 	}
       
   237 	packet->set_data_length(length + m_offset);
       
   238 
       
   239 	return packet;
       
   240 }
       
   241 
       
   242 //--------------------------------------------------
       
   243 
       
   244 eap_status_e eap_type_mschapv2_c::packet_send(
       
   245 	eap_buf_chain_wr_c * const data,
       
   246 	const u32_t data_length)
       
   247 {
       
   248 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   249 	if (m_mtu_length < data_length)
       
   250 	{
       
   251 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
   252 	}
       
   253 
       
   254 	if (data->get_is_valid_data() == false)
       
   255 	{
       
   256 		EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("packet buffer corrupted.\n")));
       
   257 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   258 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   259 	}
       
   260 
       
   261 	eap_status_e status = get_type_partner()->packet_send(
       
   262 		&m_send_network_id,
       
   263 		data,
       
   264 		m_offset,
       
   265 		data_length,
       
   266 		data->get_buffer_length());
       
   267 
       
   268 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   269 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   270 }
       
   271 
       
   272 //--------------------------------------------------
       
   273 
       
   274 EAP_FUNC_EXPORT eap_status_e eap_type_mschapv2_c::finish_successful_authentication()
       
   275 {
       
   276 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   277 	EAP_TRACE_DEBUG(
       
   278 		m_am_tools,
       
   279 		TRACE_FLAGS_DEFAULT,
       
   280 		(EAPL("EAP_type_MSCHAPV2: %s: EAP-SUCCESS: function: eap_type_mschapv2_c::finish_successful_authentication()\n"),
       
   281 		(m_is_client == true) ? "client": "server"));
       
   282 
       
   283 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eap_type_mschapv2_c::finish_successful_authentication()");
       
   284 
       
   285 	eap_state_notification_c notification(
       
   286 		m_am_tools,
       
   287 		&m_send_network_id,
       
   288 		m_is_client,
       
   289 		eap_state_notification_eap,
       
   290 		eap_protocol_layer_eap,
       
   291 		eap_type_mschapv2,
       
   292 		eap_state_none,
       
   293 		eap_state_authentication_finished_successfully,
       
   294 		m_identifier,
       
   295 		true);
       
   296 	get_type_partner()->state_notification(&notification);
       
   297 
       
   298 	// set notification flag
       
   299 	m_is_notification_sent = true;
       
   300 
       
   301 	// Store credential for reauthentication (client only)
       
   302 	//if (m_is_client)
       
   303 	{
       
   304 		eap_variable_data_c key(m_am_tools);
       
   305 		eap_status_e status = m_am_type_mschapv2->get_memory_store_key(&key);
       
   306 		if (status != eap_status_ok)
       
   307 		{
       
   308 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   309 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   310 		}
       
   311 
       
   312 		status = key.add_data(
       
   313 			&m_is_client,
       
   314 			sizeof(m_is_client));
       
   315 		if (status != eap_status_ok)
       
   316 		{
       
   317 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   318 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   319 		}
       
   320 
       
   321 		// Remove the old data. Do not care status.
       
   322 		(void) m_am_tools->memory_store_remove_data(&key);
       
   323 		
       
   324 		EAP_TRACE_DEBUG(
       
   325 			m_am_tools,
       
   326 			TRACE_FLAGS_DEFAULT,
       
   327 			(EAPL("%s: EAP_type_MSCHAPV2: finish_successful_authentication(): Credentials removed from mem store\n"),
       
   328 			(m_is_client == true) ? "client": "server"));		
       
   329 
       
   330 		// Store the creditials always, if the password prompt is NOT enabled or
       
   331 		// if the Session is valid.
       
   332 		
       
   333 		if(m_password_prompt_enabled == false 
       
   334 			|| m_am_type_mschapv2->is_session_valid() == true)
       
   335 		{
       
   336 			EAP_TRACE_DEBUG(
       
   337 				m_am_tools,
       
   338 				TRACE_FLAGS_DEFAULT,
       
   339 				(EAPL("%s: EAP_type_MSCHAPV2: finish_successful_authentication(): Session valid or PW prompt disabled, Storing Credentials\n"),
       
   340 				(m_is_client == true) ? "client": "server"));
       
   341 		
       
   342 			eap_tlv_message_data_c tlv_data(m_am_tools);
       
   343 
       
   344 			status = tlv_data.add_message_data(
       
   345 				eap_type_mschapv2_stored_username,
       
   346 				m_username_utf8.get_data_length(),
       
   347 				m_username_utf8.get_data());
       
   348 			if (status != eap_status_ok)
       
   349 			{
       
   350 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   351 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   352 			}
       
   353 
       
   354 			status = tlv_data.add_message_data(
       
   355 				eap_type_mschapv2_stored_password,
       
   356 				m_password_utf8.get_data_length(),
       
   357 				m_password_utf8.get_data());
       
   358 			if (status != eap_status_ok)
       
   359 			{
       
   360 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   361 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   362 			}
       
   363 
       
   364 #if defined(EAP_MSCHAPV2_SERVER)
       
   365 			status = tlv_data.add_message_data(
       
   366 				eap_type_mschapv2_stored_password_expired_flag,
       
   367 				sizeof(m_password_expired),
       
   368 				&m_password_expired);
       
   369 			if (status != eap_status_ok)
       
   370 			{
       
   371 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   372 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   373 			}
       
   374 #endif //#if defined(EAP_MSCHAPV2_SERVER)
       
   375 
       
   376 			status = m_am_tools->memory_store_add_data(
       
   377 				&key,
       
   378 				&tlv_data,
       
   379 				eap_type_default_credential_timeout);
       
   380 			if (status != eap_status_ok)
       
   381 			{
       
   382 				EAP_TRACE_DEBUG(
       
   383 					m_am_tools,
       
   384 					TRACE_FLAGS_DEFAULT,
       
   385 					(EAPL("EAP_type_MSCHAPV2: finish_successful_authentication(): cannot store credentials\n")));
       
   386 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   387 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   388 			}
       
   389 			
       
   390 			EAP_TRACE_DEBUG(
       
   391 				m_am_tools,
       
   392 				TRACE_FLAGS_DEFAULT,
       
   393 				(EAPL("%s: EAP_type_MSCHAPV2: finish_successful_authentication(): Credentials stored \n"),
       
   394 				(m_is_client == true) ? "client": "server"));
       
   395 			
       
   396 		} // End of if(m_password_prompt_enabled == true ....
       
   397 
       
   398 	}
       
   399 
       
   400 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   401 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   402 }
       
   403 
       
   404 //--------------------------------------------------
       
   405 
       
   406 EAP_FUNC_EXPORT eap_status_e eap_type_mschapv2_c::finish_unsuccessful_authentication(
       
   407 	const bool authentication_cancelled)
       
   408 {
       
   409 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   410 	EAP_TRACE_DEBUG(
       
   411 		m_am_tools,
       
   412 		TRACE_FLAGS_DEFAULT,
       
   413 		(EAPL("ERROR: %s: EAP_type_MSCHAPV2: FAILED: function: eap_type_mschapv2_c::finish_unsuccessful_authentication()\n"),
       
   414 		(m_is_client == true) ? "client": "server"));
       
   415 
       
   416 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eap_type_mschapv2_c::finish_unsuccessful_authentication()");
       
   417 
       
   418 	if (m_is_client == true)
       
   419 	{
       
   420 		if (authentication_cancelled == true)
       
   421 		{
       
   422 			eap_state_notification_c notification(
       
   423 				m_am_tools,
       
   424 				&m_send_network_id,
       
   425 				m_is_client,
       
   426 				eap_state_notification_eap,
       
   427 				eap_protocol_layer_general, // This must be used with eap_general_state_authentication_cancelled.
       
   428 				eap_type_mschapv2,
       
   429 				eap_state_none,
       
   430 				eap_general_state_authentication_cancelled,
       
   431 				m_identifier,
       
   432 				false);
       
   433 
       
   434 			notification.set_authentication_error(eap_status_authentication_failure);
       
   435 
       
   436 			get_type_partner()->state_notification(&notification);
       
   437 		}
       
   438 		else
       
   439 		{			
       
   440 			eap_state_notification_c notification(
       
   441 				m_am_tools,
       
   442 				&m_send_network_id,
       
   443 				m_is_client,
       
   444 				eap_state_notification_eap,
       
   445 				eap_protocol_layer_eap,
       
   446 				eap_type_mschapv2,
       
   447 				eap_state_none,
       
   448 				eap_state_authentication_terminated_unsuccessfully,
       
   449 				m_identifier,
       
   450 				false);
       
   451 
       
   452 			notification.set_authentication_error(eap_status_authentication_failure);
       
   453 
       
   454 			get_type_partner()->state_notification(&notification);
       
   455 		}		
       
   456 
       
   457 #if defined(USE_USER_NOTIFICATIONS)
       
   458 		eap_variable_data_c string(m_am_tools);
       
   459 		eap_status_e status = m_am_type_mschapv2->read_auth_failure_string(EAP_MSCHAPV2_ERROR_AUTHENTICATION_FAILURE, string);
       
   460 		if (status == eap_status_ok)
       
   461 		{
       
   462 			eap_state_notification_c notification(
       
   463 				m_am_tools,
       
   464 				&m_send_network_id,
       
   465 				m_is_client,
       
   466 				eap_state_notification_eap,
       
   467 				eap_protocol_layer_general, // This must be used with eap_general_state_show_notification_string.
       
   468 				eap_type_mschapv2,
       
   469 				eap_state_none,
       
   470 				eap_general_state_show_notification_string,
       
   471 				0,
       
   472 				false);
       
   473 			status = notification.set_notification_string(&string, true);
       
   474 			if (status == eap_status_ok)
       
   475 			{
       
   476 				get_type_partner()->state_notification(&notification);
       
   477 			}
       
   478 		}
       
   479 #endif //#if defined(USE_USER_NOTIFICATIONS)
       
   480 	}
       
   481 	else
       
   482 	{			
       
   483 		eap_state_notification_c notification(
       
   484 			m_am_tools,
       
   485 			&m_send_network_id,
       
   486 			m_is_client,
       
   487 			eap_state_notification_eap,
       
   488 			eap_protocol_layer_eap,
       
   489 			eap_type_mschapv2,
       
   490 			eap_state_none,
       
   491 			eap_state_authentication_terminated_unsuccessfully,
       
   492 			m_identifier,
       
   493 			false);
       
   494 
       
   495 		notification.set_authentication_error(eap_status_authentication_failure);
       
   496 
       
   497 		get_type_partner()->state_notification(&notification);
       
   498 	}
       
   499 
       
   500 	EAP_TRACE_DEBUG(
       
   501 		m_am_tools,
       
   502 		TRACE_FLAGS_DEFAULT,
       
   503 		(EAPL("%s: EAP_type_MSCHAPV2: finish_unsuccessful_authentication(): EAP-FAILED\n"),
       
   504 		(m_is_client == true) ? "client": "server"));
       
   505 
       
   506 	// set notification flag
       
   507 	m_is_notification_sent = true;
       
   508 
       
   509 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   510 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   511 }
       
   512 
       
   513 //--------------------------------------------------
       
   514 
       
   515 EAP_FUNC_EXPORT eap_status_e eap_type_mschapv2_c::packet_process(
       
   516 	const eap_am_network_id_c * const /*receive_network_id*/,
       
   517 	eap_header_wr_c * const received_eap,
       
   518 	const u32_t eap_packet_length)
       
   519 {
       
   520 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   521 	eap_status_e status = eap_status_drop_packet_quietly;
       
   522 
       
   523 	if (eap_packet_length > received_eap->get_header_buffer_length())
       
   524 	{
       
   525 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   526 		return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
       
   527 	}
       
   528 
       
   529 	if (eap_packet_length < eap_header_base_c::get_header_length()) // Without type code
       
   530 	{
       
   531 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   532 		return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
       
   533 	}
       
   534 
       
   535 	if (received_eap->get_type() == eap_type_notification)
       
   536 	{
       
   537 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   538 		return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
       
   539 	}
       
   540 
       
   541 #ifdef EAP_MSCHAPV2_SERVER
       
   542 	if (m_is_client) // Client
       
   543 	{
       
   544 #endif
       
   545 
       
   546 		status = client_packet_process(
       
   547 			received_eap,
       
   548 			eap_packet_length);
       
   549 
       
   550 #ifdef EAP_MSCHAPV2_SERVER
       
   551 	}
       
   552 	else // Server
       
   553 	{
       
   554 		status = server_packet_process(
       
   555 			received_eap,
       
   556 			eap_packet_length);
       
   557 	}
       
   558 #endif
       
   559 
       
   560 	if (status == eap_status_ok)
       
   561 	{
       
   562 		EAP_GENERAL_HEADER_SET_ERROR_DETECTED(received_eap, false);
       
   563 	}
       
   564 
       
   565 	if (status == eap_status_ok
       
   566 		|| status == eap_status_pending_request
       
   567 		|| status == eap_status_drop_packet_quietly)
       
   568 	{    
       
   569 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   570 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   571 	}
       
   572 
       
   573 	// Internal error
       
   574 	status = finish_unsuccessful_authentication(false);
       
   575 
       
   576 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   577 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   578 }
       
   579 
       
   580 //--------------------------------------------------
       
   581 
       
   582 EAP_FUNC_EXPORT eap_status_e eap_type_mschapv2_c::configure()
       
   583 {
       
   584 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   585 
       
   586 	EAP_TRACE_DEBUG(
       
   587 		m_am_tools, 
       
   588 		TRACE_FLAGS_DEFAULT, 
       
   589 		(EAPL("eap_type_mschapv2_c::configure(): this = 0x%08x\n"),
       
   590 		this));
       
   591 
       
   592 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eap_type_mschapv2_c::configure()");
       
   593 
       
   594 	eap_status_e status = eap_status_process_general_error;
       
   595 
       
   596 	status = m_am_type_mschapv2->configure();
       
   597 	if (status != eap_status_ok)
       
   598 	{
       
   599 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   600 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   601 	}
       
   602 
       
   603 	m_offset = get_type_partner()->get_header_offset(&m_mtu_length, &m_trailer_length);
       
   604 
       
   605 	// read configures
       
   606 
       
   607 	// Password promt
       
   608 	eap_variable_data_c password_prompt(m_am_tools);
       
   609 
       
   610 	status = m_am_type_mschapv2->type_configure_read(
       
   611 		cf_str_EAP_MSCHAPV2_password_prompt.get_field(),
       
   612 		&password_prompt);
       
   613 	if (status == eap_status_ok)
       
   614 	{
       
   615 		const u32_t * const flag = reinterpret_cast<u32_t *>(
       
   616 			password_prompt.get_data(sizeof(u32_t)));
       
   617 		if (flag && *flag == 0)
       
   618 		{
       
   619 			m_password_prompt_enabled = false;
       
   620 		}
       
   621 		else
       
   622 		{
       
   623 			m_password_prompt_enabled = true;
       
   624 		}
       
   625 	}
       
   626 
       
   627 	// Username
       
   628 	eap_variable_data_c username_uc(m_am_tools);
       
   629 
       
   630 	status = m_am_type_mschapv2->type_configure_read(
       
   631 		cf_str_EAP_MSCHAPV2_username.get_field(),
       
   632 		&m_username_utf8);
       
   633 	if (status != eap_status_ok
       
   634 		|| m_username_utf8.get_is_valid() == false)
       
   635 	{
       
   636 		// This is optional.
       
   637 	}
       
   638 
       
   639 	// Password
       
   640 	status = m_am_type_mschapv2->type_configure_read(
       
   641 		cf_str_EAP_MSCHAPV2_password.get_field(),
       
   642 		&m_password_utf8);
       
   643 	if (status != eap_status_ok
       
   644 		|| m_password_utf8.get_is_valid() == false)
       
   645 	{
       
   646 		// This is optional.
       
   647 	}
       
   648 
       
   649 	if (m_is_client == true
       
   650 		&& m_password_prompt_enabled == true)
       
   651 	{
       
   652 		m_password_utf8.reset();
       
   653 	}
       
   654 
       
   655 
       
   656 
       
   657 #if defined(EAP_MSCHAPV2_SERVER)
       
   658 	{
       
   659 		eap_variable_data_c do_password_expiration_tests(m_am_tools);
       
   660 
       
   661 		status = m_am_type_mschapv2->type_configure_read(
       
   662 			cf_str_EAP_MSCHAPV2_do_password_expiration_tests.get_field(),
       
   663 			&do_password_expiration_tests);
       
   664 		if (status == eap_status_ok)
       
   665 		{
       
   666 			const u32_t * const flag = reinterpret_cast<u32_t *>(
       
   667 				do_password_expiration_tests.get_data(sizeof(u32_t)));
       
   668 			if (flag != 0
       
   669 				&& *flag == 0)
       
   670 			{
       
   671 				m_do_password_expiration_tests = false;
       
   672 			}
       
   673 			else
       
   674 			{
       
   675 				m_do_password_expiration_tests = true;
       
   676 			}
       
   677 		}
       
   678 	}
       
   679 #endif //#if defined(EAP_MSCHAPV2_SERVER)
       
   680 
       
   681 	
       
   682 	if (m_is_client == true)
       
   683 	{
       
   684 		eap_variable_data_c do_wrong_password_tests(m_am_tools);
       
   685 
       
   686 		status = m_am_type_mschapv2->type_configure_read(
       
   687 			cf_str_EAP_MSCHAPV2_do_wrong_password_tests.get_field(),
       
   688 			&do_wrong_password_tests);
       
   689 		if (status == eap_status_ok)
       
   690 		{
       
   691 			const u32_t * const flag = reinterpret_cast<u32_t *>(
       
   692 				do_wrong_password_tests.get_data(sizeof(u32_t)));
       
   693 			if (flag != 0
       
   694 				&& *flag == 0)
       
   695 			{
       
   696 				m_do_wrong_password_tests = false;
       
   697 			}
       
   698 			else
       
   699 			{
       
   700 				m_do_wrong_password_tests = true;
       
   701 			}
       
   702 		}
       
   703 	}
       
   704 
       
   705 #if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
       
   706 	{
       
   707 		eap_variable_data_c use_implicit_challenge(m_am_tools);
       
   708 
       
   709 		status = m_am_type_mschapv2->type_configure_read(
       
   710 			cf_str_EAP_MSCHAPV2_use_implicit_challenge.get_field(),
       
   711 			&use_implicit_challenge);
       
   712 		if (status == eap_status_ok)
       
   713 		{
       
   714 			const u32_t * const flag = reinterpret_cast<u32_t *>(
       
   715 				use_implicit_challenge.get_data(sizeof(u32_t)));
       
   716 			if (flag != 0 && *flag != 0)
       
   717 			{
       
   718 				m_use_implicit_challenge = true;
       
   719 			}
       
   720 			else
       
   721 			{
       
   722 				m_use_implicit_challenge = false;
       
   723 			}
       
   724 		}
       
   725 	}
       
   726 #endif //#if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
       
   727 
       
   728 	//----------------------------------------------------------
       
   729 
       
   730 #if defined(USE_EAP_EXPANDED_TYPES)
       
   731 	{
       
   732 		eap_variable_data_c use_eap_expanded_type(m_am_tools);
       
   733 
       
   734 		eap_status_e status = m_am_type_mschapv2->type_configure_read(
       
   735 			cf_str_EAP_MSCHAPV2_use_eap_expanded_type.get_field(),
       
   736 			&use_eap_expanded_type);
       
   737 
       
   738 		if (status != eap_status_ok)
       
   739 		{
       
   740 			status = m_am_type_mschapv2->type_configure_read(
       
   741 				cf_str_EAP_CORE_use_eap_expanded_type.get_field(),
       
   742 				&use_eap_expanded_type);
       
   743 		}
       
   744 
       
   745 		if (status == eap_status_ok
       
   746 			&& use_eap_expanded_type.get_data_length() == sizeof(u32_t)
       
   747 			&& use_eap_expanded_type.get_data() != 0)
       
   748 		{
       
   749 			u32_t *flag = reinterpret_cast<u32_t *>(use_eap_expanded_type.get_data(use_eap_expanded_type.get_data_length()));
       
   750 
       
   751 			if (flag != 0)
       
   752 			{
       
   753 				if ((*flag) != 0ul)
       
   754 				{
       
   755 					m_use_eap_expanded_type = true;
       
   756 				}
       
   757 				else
       
   758 				{
       
   759 					m_use_eap_expanded_type = false;
       
   760 				}
       
   761 			}
       
   762 		}
       
   763 	}
       
   764 #endif //#if defined(USE_EAP_EXPANDED_TYPES)
       
   765 
       
   766 	//----------------------------------------------------------
       
   767 
       
   768 #if defined(USE_FAST_EAP_TYPE)
       
   769 	
       
   770 	{
       
   771 		eap_variable_data_c use_EAP_FAST_challenge(m_am_tools);
       
   772 
       
   773 		status = m_am_type_mschapv2->type_configure_read(
       
   774 			cf_str_EAP_MSCHAPV2_use_EAP_FAST_challenge.get_field(),
       
   775 			&use_EAP_FAST_challenge);
       
   776 		if (status == eap_status_ok)
       
   777 		{
       
   778 			const u32_t * const flag = reinterpret_cast<u32_t *>(
       
   779 				use_EAP_FAST_challenge.get_data(sizeof(u32_t)));
       
   780 			if (flag != 0 && *flag != 0)
       
   781 			{
       
   782 				m_use_EAP_FAST_challenge = true;
       
   783 			}
       
   784 			else
       
   785 			{
       
   786 				m_use_EAP_FAST_challenge = false;
       
   787 			}
       
   788 		}
       
   789 	}
       
   790 
       
   791 	if (m_use_EAP_FAST_challenge == true)
       
   792 	{
       
   793 		status = m_am_type_mschapv2->type_configure_read(
       
   794 			cf_str_EAP_MSCHAPV2_client_EAP_FAST_challenge.get_field(),
       
   795 			&m_client_EAP_FAST_challenge);
       
   796 		if (status != eap_status_ok
       
   797 			|| m_client_EAP_FAST_challenge.get_is_valid_data() == false)
       
   798 		{
       
   799 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   800 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   801 		}
       
   802 
       
   803 		EAP_TRACE_DATA_DEBUG(
       
   804 			m_am_tools,
       
   805 			TRACE_FLAGS_DEFAULT,
       
   806 			(EAPL("eap_type_mschapv2_c::configure(): m_client_EAP_FAST_challenge"),
       
   807 			 m_client_EAP_FAST_challenge.get_data(),
       
   808 			 m_client_EAP_FAST_challenge.get_data_length()));
       
   809 
       
   810 		status = m_am_type_mschapv2->type_configure_read(
       
   811 			cf_str_EAP_MSCHAPV2_server_EAP_FAST_challenge.get_field(),
       
   812 			&m_server_EAP_FAST_challenge);
       
   813 		if (status != eap_status_ok
       
   814 			|| m_server_EAP_FAST_challenge.get_is_valid_data() == false)
       
   815 		{
       
   816 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   817 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   818 		}
       
   819 
       
   820 		EAP_TRACE_DATA_DEBUG(
       
   821 			m_am_tools,
       
   822 			TRACE_FLAGS_DEFAULT,
       
   823 			(EAPL("eap_type_mschapv2_c::configure(): m_server_EAP_FAST_challenge"),
       
   824 			 m_server_EAP_FAST_challenge.get_data(),
       
   825 			 m_server_EAP_FAST_challenge.get_data_length()));
       
   826 	}
       
   827 
       
   828 	{
       
   829 		eap_variable_data_c use_EAP_FAST_full_key(m_am_tools);
       
   830 
       
   831 		status = m_am_type_mschapv2->type_configure_read(
       
   832 			cf_str_EAP_MSCHAPV2_use_EAP_FAST_full_key.get_field(),
       
   833 			&use_EAP_FAST_full_key);
       
   834 		if (status == eap_status_ok)
       
   835 		{
       
   836 			const u32_t * const flag = reinterpret_cast<u32_t *>(
       
   837 				use_EAP_FAST_full_key.get_data(sizeof(u32_t)));
       
   838 			if (flag != 0 && *flag != 0)
       
   839 			{
       
   840 				m_use_EAP_FAST_full_key = true;
       
   841 			}
       
   842 			else
       
   843 			{
       
   844 				m_use_EAP_FAST_full_key = false;
       
   845 			}
       
   846 		}
       
   847 	}
       
   848 
       
   849 
       
   850 #endif //#if defined(USE_FAST_EAP_TYPE)
       
   851 
       
   852 	//----------------------------------------------------------
       
   853 
       
   854 	eap_variable_data_c wait_eap_success_prompt(m_am_tools);
       
   855 
       
   856 	m_wait_eap_success = true;
       
   857 
       
   858 	// Check if the case is reauthentication (client only)
       
   859 	//if (m_is_client)
       
   860 	{
       
   861 		eap_variable_data_c key(m_am_tools);
       
   862 		status = m_am_type_mschapv2->get_memory_store_key(&key);
       
   863 		if (status != eap_status_ok)
       
   864 		{
       
   865 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   866 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   867 		}
       
   868 
       
   869 		status = key.add_data(
       
   870 			&m_is_client,
       
   871 			sizeof(m_is_client));
       
   872 		if (status != eap_status_ok)
       
   873 		{
       
   874 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   875 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   876 		}
       
   877 
       
   878 		eap_tlv_message_data_c tlv_data(m_am_tools);
       
   879 
       
   880 		status = m_am_tools->memory_store_get_data(
       
   881 			&key,
       
   882 			&tlv_data);
       
   883 		if (status != eap_status_ok)
       
   884 		{
       
   885 			EAP_TRACE_DEBUG(
       
   886 				m_am_tools,
       
   887 				TRACE_FLAGS_DEFAULT,
       
   888 				(EAPL("EAP_type_MSCHAPV2: configure(): cannot get credentials\n")));
       
   889 		}
       
   890 		else
       
   891 		{
       
   892 			EAP_TRACE_DEBUG(
       
   893 				m_am_tools,
       
   894 				TRACE_FLAGS_DEFAULT,
       
   895 				(EAPL("EAP_type_MSCHAPV2: configure: credentials found\n")));
       
   896 
       
   897 			// Parse read data.
       
   898 			eap_array_c<eap_tlv_header_c> tlv_blocks(m_am_tools);
       
   899 				
       
   900 			status = tlv_data.parse_message_data(&tlv_blocks);
       
   901 			if (status != eap_status_ok)
       
   902 			{
       
   903 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   904 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   905 			}
       
   906 
       
   907 			for (u32_t ind = 0ul; ind < tlv_blocks.get_object_count(); ind++)
       
   908 			{
       
   909 				eap_tlv_header_c * const tlv = tlv_blocks.get_object(ind);
       
   910 				if (tlv != 0)
       
   911 				{
       
   912 					if (tlv->get_type() == eap_type_mschapv2_stored_username)
       
   913 					{
       
   914 						if (m_username_utf8.get_is_valid_data() == false)
       
   915 						{
       
   916 							status = m_username_utf8.set_copy_of_buffer(
       
   917 								tlv->get_value(tlv->get_value_length()),
       
   918 								tlv->get_value_length());
       
   919 							if (status != eap_status_ok)
       
   920 							{
       
   921 								EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   922 								return EAP_STATUS_RETURN(m_am_tools, status);
       
   923 							}
       
   924 						}
       
   925 					}
       
   926 					else if (tlv->get_type() == eap_type_mschapv2_stored_password)
       
   927 					{
       
   928 						if (m_password_prompt_enabled == true
       
   929 							|| m_password_utf8.get_is_valid_data() == false)
       
   930 						{
       
   931 							status = m_password_utf8.set_copy_of_buffer(
       
   932 								tlv->get_value(tlv->get_value_length()),
       
   933 								tlv->get_value_length());
       
   934 							if (status != eap_status_ok)
       
   935 							{
       
   936 								EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   937 								return EAP_STATUS_RETURN(m_am_tools, status);
       
   938 							}
       
   939 						}
       
   940 					}
       
   941 #if defined(EAP_MSCHAPV2_SERVER)
       
   942 					else if (tlv->get_type() == eap_type_mschapv2_stored_password_expired_flag)
       
   943 					{
       
   944 						bool * const password_expired = reinterpret_cast<bool *>(tlv->get_value(sizeof(*password_expired)));
       
   945 						if (password_expired == 0)
       
   946 						{
       
   947 							EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   948 							return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   949 						}
       
   950 
       
   951 						m_password_expired = *password_expired;
       
   952 					}
       
   953 #endif //#if defined(EAP_MSCHAPV2_SERVER)
       
   954 					else
       
   955 					{
       
   956 						EAP_TRACE_DEBUG(
       
   957 							m_am_tools,
       
   958 							TRACE_FLAGS_DEFAULT,
       
   959 							(EAPL("EAP_type_MSCHAPV2: unknown credential type %d, length %d\n"),
       
   960 							 tlv->get_type(),
       
   961 							 tlv->get_value_length()));
       
   962 					}
       
   963 				}
       
   964 			}
       
   965 
       
   966 			status = m_am_tools->memory_store_remove_data(&key);
       
   967 			EAP_TRACE_DEBUG(
       
   968 				m_am_tools,
       
   969 				TRACE_FLAGS_DEFAULT,
       
   970 				(EAPL("EAP_type_MSCHAPV2: configure: credentials removed from eapol\n")));
       
   971 
       
   972 			m_is_reauthentication = true;
       
   973 			m_identity_asked = true;
       
   974 		}
       
   975 	}
       
   976 
       
   977 	EAP_TRACE_DATA_DEBUG(
       
   978 		m_am_tools,
       
   979 		TRACE_FLAGS_DEFAULT,
       
   980 		(EAPL("EAP_type_MSCHAPV2: configure, username:"),
       
   981 		m_username_utf8.get_data(),
       
   982 		m_username_utf8.get_buffer_length()));
       
   983 
       
   984 	EAP_TRACE_DATA_DEBUG(
       
   985 		m_am_tools,
       
   986 		TRACE_FLAGS_DEFAULT,
       
   987 		(EAPL("EAP_type_MSCHAPV2: configure, password:"),
       
   988 		m_password_utf8.get_data(),
       
   989 		m_password_utf8.get_buffer_length()));
       
   990 
       
   991 
       
   992 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   993 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   994 }
       
   995 
       
   996 //--------------------------------------------------
       
   997 
       
   998 // This function is to allow reuse of this object.
       
   999 // The whole object state must be reset.
       
  1000 EAP_FUNC_EXPORT eap_status_e eap_type_mschapv2_c::reset()
       
  1001 {
       
  1002 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1003 
       
  1004 	EAP_TRACE_DEBUG(
       
  1005 		m_am_tools, 
       
  1006 		TRACE_FLAGS_DEFAULT, 
       
  1007 		(EAPL("eap_type_mschapv2_c::reset(): this = 0x%08x\n"),
       
  1008 		this));
       
  1009 
       
  1010 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eap_type_mschapv2_c::reset()");
       
  1011 
       
  1012 	m_session.set_state(eap_type_mschapv2_state_none);
       
  1013 
       
  1014 	m_username_utf8.reset();
       
  1015 	eap_variable_data_c username_uc(m_am_tools);
       
  1016 
       
  1017 	eap_status_e status = m_am_type_mschapv2->type_configure_read(
       
  1018 		cf_str_EAP_MSCHAPV2_username.get_field(),
       
  1019 		&m_username_utf8);
       
  1020 	if (status != eap_status_ok
       
  1021 		|| m_username_utf8.get_is_valid() == false)
       
  1022 	{
       
  1023 		// This is optional.
       
  1024 	}
       
  1025 
       
  1026 	status = m_am_type_mschapv2->type_configure_read(
       
  1027 		cf_str_EAP_MSCHAPV2_password.get_field(),
       
  1028 		&m_password_utf8);
       
  1029 	if (status != eap_status_ok
       
  1030 		|| m_password_utf8.get_is_valid() == false)
       
  1031 	{
       
  1032 		// This is optional.
       
  1033 	}
       
  1034 
       
  1035 	if (m_is_client == true
       
  1036 		&& m_password_prompt_enabled == true)
       
  1037 	{
       
  1038 		m_password_utf8.reset();
       
  1039 	}
       
  1040 
       
  1041 	m_old_password_utf8.reset();
       
  1042 
       
  1043 	m_is_notification_sent = false;
       
  1044 	m_is_reauthentication = false;
       
  1045 
       
  1046 	status = m_am_type_mschapv2->reset();
       
  1047 	if (status != eap_status_ok)
       
  1048 	{
       
  1049 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1050 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1051 	}
       
  1052 
       
  1053 #if defined(USE_FAST_EAP_TYPE)
       
  1054 
       
  1055 	{
       
  1056 		eap_variable_data_c use_EAP_FAST_challenge(m_am_tools);
       
  1057 
       
  1058 		status = m_am_type_mschapv2->type_configure_read(
       
  1059 			cf_str_EAP_MSCHAPV2_use_EAP_FAST_challenge.get_field(),
       
  1060 			&use_EAP_FAST_challenge);
       
  1061 		if (status == eap_status_ok)
       
  1062 		{
       
  1063 			const u32_t * const flag = reinterpret_cast<u32_t *>(
       
  1064 				use_EAP_FAST_challenge.get_data(sizeof(u32_t)));
       
  1065 			if (flag != 0 && *flag != 0)
       
  1066 			{
       
  1067 				m_use_EAP_FAST_challenge = true;
       
  1068 			}
       
  1069 			else
       
  1070 			{
       
  1071 				m_use_EAP_FAST_challenge = false;
       
  1072 			}
       
  1073 		}
       
  1074 	}
       
  1075 
       
  1076 	if (m_use_EAP_FAST_challenge == true)
       
  1077 	{
       
  1078 		status = m_am_type_mschapv2->type_configure_read(
       
  1079 			cf_str_EAP_MSCHAPV2_client_EAP_FAST_challenge.get_field(),
       
  1080 			&m_client_EAP_FAST_challenge);
       
  1081 		if (status != eap_status_ok
       
  1082 			|| m_client_EAP_FAST_challenge.get_is_valid_data() == false)
       
  1083 		{
       
  1084 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1085 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1086 		}
       
  1087 
       
  1088 		EAP_TRACE_DATA_DEBUG(
       
  1089 			m_am_tools,
       
  1090 			TRACE_FLAGS_DEFAULT,
       
  1091 			(EAPL("eap_type_mschapv2_c::reset(): m_client_EAP_FAST_challenge"),
       
  1092 			 m_client_EAP_FAST_challenge.get_data(),
       
  1093 			 m_client_EAP_FAST_challenge.get_data_length()));
       
  1094 
       
  1095 		status = m_am_type_mschapv2->type_configure_read(
       
  1096 			cf_str_EAP_MSCHAPV2_server_EAP_FAST_challenge.get_field(),
       
  1097 			&m_server_EAP_FAST_challenge);
       
  1098 		if (status != eap_status_ok
       
  1099 			|| m_server_EAP_FAST_challenge.get_is_valid_data() == false)
       
  1100 		{
       
  1101 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1102 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1103 		}
       
  1104 
       
  1105 		EAP_TRACE_DATA_DEBUG(
       
  1106 			m_am_tools,
       
  1107 			TRACE_FLAGS_DEFAULT,
       
  1108 			(EAPL("eap_type_mschapv2_c::reset(): m_server_EAP_FAST_challenge"),
       
  1109 			 m_server_EAP_FAST_challenge.get_data(),
       
  1110 			 m_server_EAP_FAST_challenge.get_data_length()));
       
  1111 
       
  1112 	}
       
  1113 
       
  1114 	{
       
  1115 		eap_variable_data_c use_EAP_FAST_full_key(m_am_tools);
       
  1116 
       
  1117 		status = m_am_type_mschapv2->type_configure_read(
       
  1118 			cf_str_EAP_MSCHAPV2_use_EAP_FAST_full_key.get_field(),
       
  1119 			&use_EAP_FAST_full_key);
       
  1120 		if (status == eap_status_ok)
       
  1121 		{
       
  1122 			const u32_t * const flag = reinterpret_cast<u32_t *>(
       
  1123 				use_EAP_FAST_full_key.get_data(sizeof(u32_t)));
       
  1124 			if (flag != 0 && *flag != 0)
       
  1125 			{
       
  1126 				m_use_EAP_FAST_full_key = true;
       
  1127 			}
       
  1128 			else
       
  1129 			{
       
  1130 				m_use_EAP_FAST_full_key = false;
       
  1131 			}
       
  1132 		}
       
  1133 	}
       
  1134 
       
  1135 
       
  1136 #endif //#if defined(USE_FAST_EAP_TYPE)
       
  1137 
       
  1138 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1139 
       
  1140 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  1141 }
       
  1142 
       
  1143 //--------------------------------------------------
       
  1144 
       
  1145 eap_status_e eap_type_mschapv2_c::mschapv2_convert_unicode_to_ascii(
       
  1146 	eap_variable_data_c & dest,
       
  1147 	const eap_variable_data_c & src)
       
  1148 {
       
  1149 	EAP_TRACE_DEBUG(
       
  1150 		m_am_tools, 
       
  1151 		TRACE_FLAGS_DEFAULT, 
       
  1152 		(EAPL("eap_type_mschapv2_c::mschapv2_convert_unicode_to_ascii(): this = 0x%08x\n"),
       
  1153 		this));
       
  1154 
       
  1155 	if (src.get_is_valid())
       
  1156 	{
       
  1157 		u32_t len = src.get_data_length();
       
  1158 		u8_t * ascii = new u8_t[len / 2];
       
  1159 		if (!ascii)
       
  1160 		{
       
  1161 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1162 		}
       
  1163 		u8_t * src_ptr = src.get_data(len);
       
  1164 		u32_t dest_len = len / 2;
       
  1165 		u32_t i;
       
  1166 		for (i = 0; i < dest_len; i++)
       
  1167 		{
       
  1168 			ascii[i] = src_ptr[i * 2];
       
  1169 		}
       
  1170 
       
  1171 		return dest.set_buffer(ascii, dest_len, true, true);
       
  1172 	}
       
  1173 	return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  1174 }
       
  1175 
       
  1176 //--------------------------------------------------
       
  1177 
       
  1178 /* Pseudocode implementation can be found from       */
       
  1179 /* RFC 2759 Microsoft PPP CHAP Extensions, Version 2 */
       
  1180 
       
  1181 //--------------------------------------------------
       
  1182 
       
  1183 eap_status_e eap_type_mschapv2_c::generate_nt_response(
       
  1184 	const u8_t * const authenticator_challenge,
       
  1185 	const u8_t * const peer_challenge,
       
  1186 	const u8_t * const username_utf8,
       
  1187 	const u32_t username_size,
       
  1188 	const eap_variable_data_c * const password_hash,
       
  1189 	u8_t * const response)
       
  1190 {
       
  1191 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1192 
       
  1193 	EAP_TRACE_DEBUG(
       
  1194 		m_am_tools, 
       
  1195 		TRACE_FLAGS_DEFAULT, 
       
  1196 		(EAPL("eap_type_mschapv2_c::generate_nt_response(): this = 0x%08x\n"),
       
  1197 		this));
       
  1198 
       
  1199 	if (!authenticator_challenge
       
  1200 		|| !peer_challenge
       
  1201 		|| !username_utf8
       
  1202 		|| username_size == 0
       
  1203 		|| username_size > EAP_MSCHAPV2_USERNAME_MAX_SIZE
       
  1204 		|| !password_hash
       
  1205 		|| !response)
       
  1206 	{
       
  1207 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  1208 	}
       
  1209 
       
  1210 	EAP_TRACE_DATA_DEBUG(
       
  1211 		m_am_tools,
       
  1212 		TRACE_FLAGS_DEFAULT,
       
  1213 		(EAPL("EAP_type_MSCHAPV2: generate_nt_response, authenticator challenge:"),
       
  1214 		authenticator_challenge,
       
  1215 		EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE));
       
  1216 
       
  1217 	EAP_TRACE_DATA_DEBUG(
       
  1218 		m_am_tools,
       
  1219 		TRACE_FLAGS_DEFAULT,
       
  1220 		(EAPL("EAP_type_MSCHAPV2: generate_nt_response, peer challenge:"),
       
  1221 		peer_challenge,
       
  1222 		 EAP_MSCHAPV2_PEER_CHALLENGE_SIZE));
       
  1223 
       
  1224 	EAP_TRACE_DATA_DEBUG(
       
  1225 		m_am_tools,
       
  1226 		TRACE_FLAGS_DEFAULT,
       
  1227 		(EAPL("EAP_type_MSCHAPV2: generate_nt_response, username_utf8:"),
       
  1228 		username_utf8,
       
  1229 		username_size));
       
  1230 
       
  1231 	EAP_TRACE_DATA_DEBUG(
       
  1232 		m_am_tools,
       
  1233 		TRACE_FLAGS_DEFAULT,
       
  1234 		(EAPL("EAP_type_MSCHAPV2: generate_nt_response, password_hash:"),
       
  1235 		password_hash->get_data(),
       
  1236 		password_hash->get_data_length()));
       
  1237 
       
  1238 	u8_t * const challenge = new u8_t[8];
       
  1239 	if (!challenge)
       
  1240 	{
       
  1241 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1242 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1243 	}
       
  1244 
       
  1245 	eap_status_e status = challenge_hash(
       
  1246 		peer_challenge,
       
  1247 		authenticator_challenge,
       
  1248 		username_utf8,
       
  1249 		username_size,
       
  1250 		challenge);
       
  1251 	if (status != eap_status_ok)
       
  1252 	{
       
  1253 		delete [] challenge;
       
  1254 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1255 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1256 	}
       
  1257 
       
  1258 	EAP_TRACE_DATA_DEBUG(
       
  1259 		m_am_tools,
       
  1260 		TRACE_FLAGS_DEFAULT,
       
  1261 		(EAPL("EAP_type_MSCHAPV2: generate_nt_response, challenge_hash:"),
       
  1262 		challenge,
       
  1263 		EAP_MSCHAPV2_CHALLENGE_HASH_SIZE));
       
  1264 
       
  1265 	status = challenge_response(
       
  1266 		challenge,
       
  1267 		password_hash->get_data(),
       
  1268 		response);
       
  1269 	delete [] challenge;
       
  1270 
       
  1271 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1272 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1273 }
       
  1274 
       
  1275 //--------------------------------------------------
       
  1276 
       
  1277 eap_status_e eap_type_mschapv2_c::challenge_hash(
       
  1278 	const u8_t * const peer_challenge,
       
  1279 	const u8_t * const authenticator_challenge,
       
  1280 	const u8_t * const username,
       
  1281 	const u32_t username_size,
       
  1282 	u8_t * const challenge)
       
  1283 { 
       
  1284 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1285 
       
  1286 	EAP_TRACE_DEBUG(
       
  1287 		m_am_tools, 
       
  1288 		TRACE_FLAGS_DEFAULT, 
       
  1289 		(EAPL("eap_type_mschapv2_c::challenge_hash(): this = 0x%08x\n"),
       
  1290 		this));
       
  1291 
       
  1292 	if (!peer_challenge
       
  1293 		|| !authenticator_challenge
       
  1294 		|| !username
       
  1295 		|| username_size == 0
       
  1296 		|| username_size > EAP_MSCHAPV2_USERNAME_MAX_SIZE
       
  1297 		|| !challenge)
       
  1298 	{
       
  1299 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1300 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  1301 	}
       
  1302 	
       
  1303 	crypto_sha1_c sha1(m_am_tools);
       
  1304 
       
  1305 	eap_status_e status = sha1.hash_init();
       
  1306 	if (status != eap_status_ok)
       
  1307 	{
       
  1308 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1309 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1310 	}
       
  1311 
       
  1312 	status = sha1.hash_update(peer_challenge, EAP_MSCHAPV2_MD4_DIGEST_SIZE);
       
  1313 	if (status != eap_status_ok)
       
  1314 	{
       
  1315 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1316 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1317 	}
       
  1318 
       
  1319 	status = sha1.hash_update(authenticator_challenge, EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE);
       
  1320 	if (status != eap_status_ok)
       
  1321 	{
       
  1322 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1323 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1324 	}
       
  1325 
       
  1326     // username without domain part
       
  1327     u32_t i;
       
  1328     for (i = username_size; i > 0 && username[i - 1] != '\\'; i--)
       
  1329 	{
       
  1330 		// Nothing to do, the index is the output.
       
  1331 	}
       
  1332 
       
  1333     status = sha1.hash_update(username + i, username_size - i);
       
  1334 	if (status != eap_status_ok)
       
  1335 	{
       
  1336 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1337 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1338 	}
       
  1339 
       
  1340 	u8_t * const digest = new u8_t[EAP_MSCHAPV2_SHA1_DIGEST_SIZE];
       
  1341 	if (!digest)
       
  1342 	{
       
  1343 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1344 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1345 	}
       
  1346 	
       
  1347 	status = sha1.hash_final(digest, 0);
       
  1348 	if (status != eap_status_ok)
       
  1349 	{
       
  1350 		delete [] digest;
       
  1351 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1352 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1353 	}
       
  1354 
       
  1355 	m_am_tools->memmove(challenge, digest, EAP_MSCHAPV2_CHALLENGE_HASH_SIZE);
       
  1356 
       
  1357 	delete [] digest;
       
  1358 	
       
  1359 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1360 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  1361 }
       
  1362 
       
  1363 //--------------------------------------------------
       
  1364 
       
  1365 eap_status_e eap_type_mschapv2_c::challenge_response(
       
  1366 	const u8_t * const challenge,     //  8 bytes
       
  1367 	const u8_t * const password_hash, // 16 bytes
       
  1368 	u8_t * const response)            // 24 bytes
       
  1369 {
       
  1370 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1371 
       
  1372 	EAP_TRACE_DEBUG(
       
  1373 		m_am_tools, 
       
  1374 		TRACE_FLAGS_DEFAULT, 
       
  1375 		(EAPL("eap_type_mschapv2_c::challenge_response(): this = 0x%08x\n"),
       
  1376 		this));
       
  1377 
       
  1378 	if (!challenge
       
  1379 		|| !password_hash
       
  1380 		|| !response)
       
  1381 	{
       
  1382 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1383 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  1384 	}
       
  1385 
       
  1386 	// 3rd 7-octets of password_hash has to be zero padded
       
  1387 	u8_t * zero_padded_password_hash_last_part = new u8_t[7];
       
  1388 	if (!zero_padded_password_hash_last_part)
       
  1389 	{
       
  1390 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1391 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1392 	}
       
  1393 
       
  1394 	m_am_tools->memmove(
       
  1395 		zero_padded_password_hash_last_part,
       
  1396 		password_hash + 14, // 2 * 7 bytes
       
  1397 		2);                 // 16 - 2 * 7 bytes
       
  1398 
       
  1399 	// Zero padding
       
  1400 	m_am_tools->memset(
       
  1401 		zero_padded_password_hash_last_part + 2, // 16 - 2 * 7
       
  1402 		0,                                       // 7 - 2
       
  1403 		5);
       
  1404 
       
  1405 	eap_status_e status = des_encrypt(
       
  1406 		challenge,
       
  1407 		zero_padded_password_hash_last_part, // 3rd 7-octets of (zero_padded_)password_hash
       
  1408 		response + 16);                      // 3rd 8-octets of response
       
  1409 
       
  1410 	delete [] zero_padded_password_hash_last_part;
       
  1411 
       
  1412 	if (status != eap_status_ok)
       
  1413 	{
       
  1414 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1415 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1416 	}
       
  1417 
       
  1418 	status = des_encrypt(
       
  1419 		challenge,
       
  1420 		password_hash, // 1st 7-octets of password_hash
       
  1421 		response);     // 1st 8-octets of response
       
  1422 
       
  1423 	if (status != eap_status_ok)
       
  1424 	{
       
  1425 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1426 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1427 	}
       
  1428 
       
  1429 	status = des_encrypt(
       
  1430 		challenge,
       
  1431 		password_hash + 7, // 2nd 7-octets of password_hash
       
  1432 		response + 8);     // 2nd 8-octets of response
       
  1433 
       
  1434 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1435 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1436 }
       
  1437 
       
  1438 //--------------------------------------------------
       
  1439 
       
  1440 eap_status_e eap_type_mschapv2_c::des_crypt(
       
  1441 	const u8_t * const data_in, //  8 octets
       
  1442 	const u8_t * const key,     // 56 bits
       
  1443 	u8_t * const data_out,
       
  1444 	const bool is_encrypt)
       
  1445 {
       
  1446 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1447 
       
  1448 	EAP_TRACE_DEBUG(
       
  1449 		m_am_tools, 
       
  1450 		TRACE_FLAGS_DEFAULT, 
       
  1451 		(EAPL("eap_type_mschapv2_c::des_crypt(): this = 0x%08x\n"),
       
  1452 		this));
       
  1453 
       
  1454 	if (!data_in
       
  1455 		|| !key
       
  1456 		|| !data_out)
       
  1457 	{
       
  1458 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1459 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  1460 	}
       
  1461 
       
  1462 	u8_t * const newkey = new u8_t[3 * EAP_MSCHAPV2_DES_KEY_SIZE]; // 3des key is triple size
       
  1463 
       
  1464 	if (!newkey)
       
  1465 	{
       
  1466 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1467 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1468 	}
       
  1469 
       
  1470 	m_am_tools->memset(newkey, 0, 3 * EAP_MSCHAPV2_DES_KEY_SIZE); // 3 * 8 bytes
       
  1471 
       
  1472 	// Add parity bits to key, 56 -> 64 bits
       
  1473 
       
  1474 	// First octet
       
  1475 	// key bit shifting [1, 7]
       
  1476 	// newkey copy bit shifting [1, 7], parity bit shifting 0
       
  1477 
       
  1478 	// Second octet
       
  1479 	// key bit shifting for second octet [2, 7] and for first octet 0
       
  1480 	// newkey copy bit shifting [1, 7], parity bit shifting 0
       
  1481 
       
  1482 	// Third octet
       
  1483 	// key bit shifting for second octet [3, 7] and for first octet [0, 1}
       
  1484 	// newkey copy bit shifting [1, 7], parity bit shifting 0
       
  1485 
       
  1486 	// bit no: 7 6 5 4 3 2 1 0, 0 = parity bit
       
  1487 	{
       
  1488 		int newkey_byte, newkey_bit, newkey_bit_shifting,
       
  1489 			key_bit_no, key_byte, key_bit_shifting, bit_counter;
       
  1490 
       
  1491 		for (newkey_byte = 0; newkey_byte < 8; newkey_byte++)
       
  1492 		{
       
  1493 			bit_counter = 0;
       
  1494 
       
  1495 			for (newkey_bit = 0; newkey_bit < 7; newkey_bit++)
       
  1496 			{
       
  1497 				key_bit_no = newkey_byte * 7 + newkey_bit;
       
  1498 				key_byte = key_bit_no / 8;
       
  1499 
       
  1500 				key_bit_shifting = 7 - (key_bit_no % 8);
       
  1501 				newkey_bit_shifting = 7 - (key_bit_no % 7);
       
  1502 
       
  1503 				if (key[key_byte] & (1 << key_bit_shifting)) // If bit is 1...
       
  1504 				{
       
  1505 					newkey[newkey_byte] |= (1 << newkey_bit_shifting); // ...set bit to 1
       
  1506 					bit_counter++;
       
  1507 				}
       
  1508 			}
       
  1509 
       
  1510 			if (bit_counter % 2 == 0) // If even number of bits...
       
  1511 			{
       
  1512 				// Add parity bit
       
  1513 				newkey[newkey_byte] |= 1; // ...set the 1st bit to 1
       
  1514 			}
       
  1515 		}
       
  1516 	}
       
  1517 
       
  1518 	// Copy key three times into triple size key because we are internally using 3des instead of des
       
  1519 	// des: Ek == 3des: Ek3(Dk2(Ek1)) when k == k1 == k2 == k3
       
  1520 	m_am_tools->memmove(newkey + EAP_MSCHAPV2_DES_KEY_SIZE, newkey, EAP_MSCHAPV2_DES_KEY_SIZE);
       
  1521 	m_am_tools->memmove(newkey + 2 * EAP_MSCHAPV2_DES_KEY_SIZE, newkey, EAP_MSCHAPV2_DES_KEY_SIZE);
       
  1522 
       
  1523 	eap_status_e status;
       
  1524 
       
  1525 	crypto_3des_ede_c des(m_am_tools);
       
  1526 
       
  1527 	if (is_encrypt)
       
  1528 	{
       
  1529 		status = des.set_encryption_key(newkey, 3 * EAP_MSCHAPV2_DES_KEY_SIZE);
       
  1530 
       
  1531 		if (status != eap_status_ok)
       
  1532 		{
       
  1533 			delete [] newkey;
       
  1534 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1535 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1536 		}
       
  1537 
       
  1538 		status = des.encrypt_block(data_in, data_out, EAP_MSCHAPV2_DES_BLOCK_SIZE);
       
  1539 	}
       
  1540 
       
  1541 	else // Decrypt mode
       
  1542 	{
       
  1543 		status = des.set_decryption_key(newkey, 3 * EAP_MSCHAPV2_DES_KEY_SIZE);
       
  1544 		if (status != eap_status_ok)
       
  1545 		{
       
  1546 			delete [] newkey;
       
  1547 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1548 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1549 		}
       
  1550 
       
  1551 		status = des.decrypt_block(data_in, data_out, EAP_MSCHAPV2_DES_BLOCK_SIZE);
       
  1552 	}
       
  1553 
       
  1554 	delete [] newkey;
       
  1555 
       
  1556 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1557 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1558 }
       
  1559 
       
  1560 //--------------------------------------------------
       
  1561 
       
  1562 static const u8_t eap_type_mschapv2_magic1a[] = { 
       
  1563 	0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
       
  1564 	0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
       
  1565 	0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
       
  1566 	0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 };
       
  1567 
       
  1568 static const u8_t eap_type_mschapv2_magic2a[] = {
       
  1569 	0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
       
  1570 	0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
       
  1571 	0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
       
  1572 	0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
       
  1573 	0x6E };
       
  1574 
       
  1575 eap_status_e eap_type_mschapv2_c::generate_authenticator_response(
       
  1576 	const u8_t * const password_hash_hash,
       
  1577 	const u8_t * const nt_response,
       
  1578 	const u8_t * const peer_challenge,
       
  1579 	const u8_t * const authenticator_challenge,
       
  1580 	const u8_t * const username,
       
  1581 	const u32_t username_size,
       
  1582 	u8_t * const authenticator_response)
       
  1583 {
       
  1584 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1585 
       
  1586 	EAP_TRACE_DEBUG(
       
  1587 		m_am_tools, 
       
  1588 		TRACE_FLAGS_DEFAULT, 
       
  1589 		(EAPL("eap_type_mschapv2_c::generate_authenticator_response(): this = 0x%08x\n"),
       
  1590 		this));
       
  1591 
       
  1592 	if (!password_hash_hash
       
  1593 		|| !nt_response
       
  1594 		|| !peer_challenge
       
  1595 		|| !authenticator_challenge
       
  1596 		|| !username
       
  1597 		|| username_size == 0
       
  1598 		|| username_size > EAP_MSCHAPV2_USERNAME_MAX_SIZE
       
  1599 		|| !authenticator_response)
       
  1600 	{
       
  1601 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1602 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  1603 	}
       
  1604 	crypto_sha1_c sha1(m_am_tools);
       
  1605 
       
  1606 	eap_status_e status = sha1.hash_init();
       
  1607 	if (status != eap_status_ok)
       
  1608 	{
       
  1609 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1610 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1611 	}
       
  1612 
       
  1613 	{
       
  1614 		status = sha1.hash_update(password_hash_hash, EAP_MSCHAPV2_MD4_DIGEST_SIZE);
       
  1615 		if (status != eap_status_ok)
       
  1616 		{
       
  1617 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1618 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1619 		}
       
  1620 	}
       
  1621 
       
  1622 	status = sha1.hash_update(nt_response, EAP_MSCHAPV2_NT_RESPONSE_SIZE);
       
  1623 	if (status != eap_status_ok)
       
  1624 	{
       
  1625 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1626 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1627 	}
       
  1628 
       
  1629 	status = sha1.hash_update(eap_type_mschapv2_magic1a, sizeof(eap_type_mschapv2_magic1a));
       
  1630 	if (status != eap_status_ok)
       
  1631 	{
       
  1632 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1633 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1634 	}
       
  1635 
       
  1636 	u8_t * const digest = new u8_t[EAP_MSCHAPV2_SHA1_DIGEST_SIZE];
       
  1637 	if (!digest)
       
  1638 	{
       
  1639 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1640 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1641 	}
       
  1642 
       
  1643 	status = sha1.hash_final(digest, 0);
       
  1644 
       
  1645 	if (status != eap_status_ok)
       
  1646 	{
       
  1647 		delete [] digest;
       
  1648 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1649 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1650 	}
       
  1651 
       
  1652 	u8_t * const challenge = new u8_t[EAP_MSCHAPV2_CHALLENGE_HASH_SIZE];
       
  1653 	if (!challenge)
       
  1654 	{
       
  1655 		delete [] digest;
       
  1656 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1657 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1658 	}
       
  1659 
       
  1660 	status = challenge_hash(
       
  1661 		peer_challenge,
       
  1662 		authenticator_challenge,
       
  1663 		username,
       
  1664 		username_size,
       
  1665 		challenge);
       
  1666 
       
  1667 	if (status != eap_status_ok)
       
  1668 	{
       
  1669 		delete [] digest;
       
  1670 		delete [] challenge;
       
  1671 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1672 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1673 	}
       
  1674 
       
  1675 	sha1.hash_cleanup();
       
  1676 
       
  1677 	status = sha1.hash_init();
       
  1678 	if (status != eap_status_ok)
       
  1679 	{
       
  1680 		delete [] digest;
       
  1681 		delete [] challenge;
       
  1682 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1683 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1684 	}
       
  1685 
       
  1686 	status = sha1.hash_update(digest, EAP_MSCHAPV2_SHA1_DIGEST_SIZE);
       
  1687 
       
  1688 	if (status != eap_status_ok)
       
  1689 	{
       
  1690 		delete [] digest;
       
  1691 		delete [] challenge;
       
  1692 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1693 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1694 	}
       
  1695 
       
  1696 	status = sha1.hash_update(challenge, EAP_MSCHAPV2_CHALLENGE_HASH_SIZE);
       
  1697 
       
  1698 	delete [] challenge;
       
  1699 
       
  1700 	if (status != eap_status_ok)
       
  1701 	{
       
  1702 		delete [] digest;
       
  1703 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1704 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1705 	}
       
  1706 
       
  1707 	status = sha1.hash_update(eap_type_mschapv2_magic2a, sizeof(eap_type_mschapv2_magic2a));
       
  1708 	if (status != eap_status_ok)
       
  1709 	{
       
  1710 		delete [] digest;
       
  1711 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1712 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1713 	}
       
  1714 
       
  1715 	status = sha1.hash_final(digest, 0);
       
  1716 
       
  1717 	if (status != eap_status_ok)
       
  1718 	{
       
  1719 		delete [] digest;
       
  1720 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1721 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1722 	}
       
  1723 
       
  1724 	m_am_tools->memmove(authenticator_response, "S=", 2);
       
  1725 	u32_t length = EAP_MSCHAPV2_SHA1_DIGEST_SIZE * 2;
       
  1726 	m_am_tools->convert_bytes_to_hex_ascii(
       
  1727 		digest, 
       
  1728 		EAP_MSCHAPV2_SHA1_DIGEST_SIZE,
       
  1729 		authenticator_response + 2,
       
  1730 		&length);
       
  1731 
       
  1732 	m_am_tools->convert_ascii_to_uppercase(authenticator_response + 2, length);
       
  1733 
       
  1734 	delete [] digest;
       
  1735 
       
  1736 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1737 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  1738 }
       
  1739 
       
  1740 //--------------------------------------------------
       
  1741 
       
  1742 eap_status_e eap_type_mschapv2_c::check_authenticator_response(
       
  1743 	const eap_variable_data_c * const password_hash_hash,
       
  1744 	const u8_t * const nt_response,
       
  1745 	const u8_t * const peer_challenge,
       
  1746 	const u8_t * const authenticator_challenge,
       
  1747 	const u8_t * const username,
       
  1748 	const u32_t username_size,
       
  1749 	const u8_t * const received_response,
       
  1750 	bool & response_ok)
       
  1751 {
       
  1752 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1753 
       
  1754 	EAP_TRACE_DEBUG(
       
  1755 		m_am_tools, 
       
  1756 		TRACE_FLAGS_DEFAULT, 
       
  1757 		(EAPL("eap_type_mschapv2_c::check_authenticator_response(): this = 0x%08x\n"),
       
  1758 		this));
       
  1759 
       
  1760 	if (!password_hash_hash
       
  1761 		|| password_hash_hash->get_data_length() < EAP_MSCHAPV2_MD4_DIGEST_SIZE
       
  1762 		|| !nt_response
       
  1763 		|| !peer_challenge
       
  1764 		|| !authenticator_challenge
       
  1765 		|| !username
       
  1766 		|| username_size == 0
       
  1767 		|| username_size > EAP_MSCHAPV2_USERNAME_MAX_SIZE
       
  1768 		|| !received_response)
       
  1769 	{
       
  1770 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1771 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  1772 	}
       
  1773 
       
  1774 	response_ok = false;
       
  1775 	
       
  1776 	u8_t * const response = new u8_t[EAP_MSCHAPV2_AUTHENTICATOR_RESPONSE_SIZE];
       
  1777 	if (!response)
       
  1778 	{
       
  1779 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1780 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1781 	}
       
  1782 
       
  1783 	eap_status_e status = generate_authenticator_response(
       
  1784 		password_hash_hash->get_data(),
       
  1785 		nt_response,
       
  1786 		peer_challenge,
       
  1787 		authenticator_challenge,
       
  1788 		username,
       
  1789 		username_size,
       
  1790 		response);
       
  1791 	if (status != eap_status_ok)
       
  1792 	{
       
  1793 		delete [] response;
       
  1794 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1795 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1796 	}
       
  1797 
       
  1798 	EAP_TRACE_DATA_DEBUG(
       
  1799 		m_am_tools,
       
  1800 		TRACE_FLAGS_DEFAULT,
       
  1801 		(EAPL("client_handle_success_request(): response"),
       
  1802 		 response,
       
  1803 		 EAP_MSCHAPV2_AUTHENTICATOR_RESPONSE_SIZE));
       
  1804 
       
  1805 	EAP_TRACE_DATA_DEBUG(
       
  1806 		m_am_tools,
       
  1807 		TRACE_FLAGS_DEFAULT,
       
  1808 		(EAPL("client_handle_success_request(): received_response"),
       
  1809 		 received_response,
       
  1810 		 EAP_MSCHAPV2_AUTHENTICATOR_RESPONSE_SIZE));
       
  1811 
       
  1812 	if (m_am_tools->memcmp(
       
  1813 			response,
       
  1814 			received_response,
       
  1815 			EAP_MSCHAPV2_AUTHENTICATOR_RESPONSE_SIZE)
       
  1816 		== 0)
       
  1817 	{
       
  1818 		response_ok = true;
       
  1819 	}
       
  1820 	else
       
  1821 	{
       
  1822 #if defined(USE_FAST_EAP_TYPE)
       
  1823 		if (m_use_EAP_FAST_challenge == true)
       
  1824 		{
       
  1825 			(void) send_error_notification(eap_status_tunnel_compromise_error);
       
  1826 		}
       
  1827 #endif //#if defined(USE_FAST_EAP_TYPE)
       
  1828 	}
       
  1829 
       
  1830 	delete [] response;
       
  1831 	
       
  1832 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1833 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1834 }
       
  1835 
       
  1836 //--------------------------------------------------
       
  1837 
       
  1838 eap_status_e eap_type_mschapv2_c::new_password_encrypted_with_old_nt_password_hash(
       
  1839 	const eap_variable_data_c * const new_password_utf8,
       
  1840 	const eap_variable_data_c * const old_password_hash,
       
  1841 	u8_t * encrypted_pw_block)
       
  1842 {
       
  1843 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1844 
       
  1845 	EAP_TRACE_DEBUG(
       
  1846 		m_am_tools, 
       
  1847 		TRACE_FLAGS_DEFAULT, 
       
  1848 		(EAPL("eap_type_mschapv2_c::new_password_encrypted_with_old_nt_password_hash(): this = 0x%08x\n"),
       
  1849 		this));
       
  1850 
       
  1851 	if (!new_password_utf8
       
  1852 		|| new_password_utf8->get_data_length() > EAP_MSCHAPV2_PASSWORD_MAX_SIZE
       
  1853 		|| !old_password_hash
       
  1854 		|| !encrypted_pw_block)
       
  1855 	{
       
  1856 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1857 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  1858 	}
       
  1859 
       
  1860 	eap_status_e status = encrypt_pw_block_with_password_hash(
       
  1861 		new_password_utf8,
       
  1862 		old_password_hash->get_data(),
       
  1863 		encrypted_pw_block);
       
  1864 
       
  1865 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1866 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1867 }
       
  1868 
       
  1869 //--------------------------------------------------
       
  1870 
       
  1871 eap_status_e eap_type_mschapv2_c::encrypt_pw_block_with_password_hash(
       
  1872 	const eap_variable_data_c * const password_utf8,
       
  1873 	const u8_t * const password_hash,
       
  1874 	u8_t * pw_block)
       
  1875 {
       
  1876 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1877 
       
  1878 	EAP_TRACE_DEBUG(
       
  1879 		m_am_tools, 
       
  1880 		TRACE_FLAGS_DEFAULT, 
       
  1881 		(EAPL("eap_type_mschapv2_c::encrypt_pw_block_with_password_hash(): this = 0x%08x\n"),
       
  1882 		this));
       
  1883 
       
  1884 	if (!password_utf8
       
  1885 		|| password_utf8->get_data_length() > EAP_MSCHAPV2_PASSWORD_MAX_SIZE
       
  1886 		|| !password_hash
       
  1887 		|| !pw_block
       
  1888 		|| !m_rand.get_is_valid())
       
  1889 	{
       
  1890 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1891 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  1892 	}
       
  1893 
       
  1894 	eap_status_e status = m_rand.add_rand_seed_hw_ticks();
       
  1895 	if (status != eap_status_ok)
       
  1896 	{
       
  1897 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1898 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1899 	}
       
  1900 
       
  1901 	status = m_rand.add_rand_seed(password_utf8->get_data(), password_utf8->get_data_length()); 
       
  1902 	if (status != eap_status_ok)
       
  1903 	{
       
  1904 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1905 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1906 	}
       
  1907 
       
  1908 	pw_block_s * clear_pw_block = new pw_block_s;
       
  1909 	if (!clear_pw_block)
       
  1910 	{
       
  1911 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1912 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1913 	}
       
  1914 
       
  1915 	eap_variable_data_c tmp_password_unicode(m_am_tools);
       
  1916 	status = m_am_tools->convert_utf8_to_unicode(tmp_password_unicode, *password_utf8);
       
  1917 	if (status != eap_status_ok)
       
  1918 	{
       
  1919 		delete clear_pw_block;
       
  1920 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1921 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1922 	}
       
  1923 
       
  1924 	u32_t pw_offset = EAP_MSCHAPV2_PASSWORD_MAX_SIZE - tmp_password_unicode.get_data_length();
       
  1925 
       
  1926 	// Fill begin of clear_pw_block with random octet values
       
  1927 	status = m_rand.get_rand_bytes(clear_pw_block->password, pw_offset);
       
  1928 	if (status != eap_status_ok)
       
  1929 	{
       
  1930 		delete clear_pw_block;
       
  1931 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1932 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1933 	}
       
  1934 	
       
  1935 	// Copy password to end of clear_pw_block
       
  1936 	m_am_tools->memmove(
       
  1937 		clear_pw_block->password + pw_offset,
       
  1938 		tmp_password_unicode.get_data(),
       
  1939 		tmp_password_unicode.get_data_length());
       
  1940 
       
  1941 	// Password size must be little endian
       
  1942 #ifdef EAP_BIG_ENDIAN
       
  1943 	u8_t * pw_bytes = reinterpret_cast<u8_t *>(&pw_size);
       
  1944 	u8_t tmp;
       
  1945 
       
  1946 	tmp = bytes[0];
       
  1947 	bytes[0] = bytes[3];
       
  1948 	bytes[3] = tmp;
       
  1949 	tmp = bytes[1];
       
  1950 	bytes[1] = bytes[2];
       
  1951 	bytes[2] = tmp;
       
  1952 #endif
       
  1953 
       
  1954 	clear_pw_block->password_length = tmp_password_unicode.get_data_length();
       
  1955 
       
  1956 	status = rc4_encrypt(
       
  1957 		reinterpret_cast<u8_t *>(clear_pw_block),
       
  1958 		sizeof(pw_block_s),
       
  1959 		password_hash,
       
  1960 		EAP_MSCHAPV2_MD4_DIGEST_SIZE,
       
  1961 		pw_block);
       
  1962 
       
  1963 	delete clear_pw_block;
       
  1964 
       
  1965 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1966 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1967 }
       
  1968 
       
  1969 //--------------------------------------------------
       
  1970 
       
  1971 eap_status_e eap_type_mschapv2_c::rc4_encrypt(
       
  1972 	const u8_t * const clear,
       
  1973 	const u32_t clear_length,
       
  1974 	const u8_t * const key,
       
  1975 	const u32_t key_length,
       
  1976 	u8_t * const cypher)
       
  1977 {
       
  1978 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1979 
       
  1980 	EAP_TRACE_DEBUG(
       
  1981 		m_am_tools, 
       
  1982 		TRACE_FLAGS_DEFAULT, 
       
  1983 		(EAPL("eap_type_mschapv2_c::rc4_encrypt(): this = 0x%08x\n"),
       
  1984 		this));
       
  1985 
       
  1986 	if (!clear
       
  1987 		|| clear_length == 0
       
  1988 		|| !key
       
  1989 		|| key_length == 0
       
  1990 		|| !cypher)
       
  1991 	{
       
  1992 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1993 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  1994 	}
       
  1995 
       
  1996 	eap_variable_data_c v_key(m_am_tools);
       
  1997 
       
  1998 	eap_status_e status = v_key.set_buffer(key, key_length, false, false); // Cannot fail
       
  1999 	if (status != eap_status_ok
       
  2000 		|| v_key.get_is_valid() == false)
       
  2001 	{
       
  2002 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2003 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2004 	}
       
  2005 
       
  2006 	crypto_rc4_c rc4(m_am_tools);
       
  2007 
       
  2008 	status = rc4.set_key(&v_key);
       
  2009 
       
  2010 	if (status != eap_status_ok)
       
  2011 	{
       
  2012 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2013 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2014 	}
       
  2015 
       
  2016 	status = rc4.encrypt_data(clear, cypher, clear_length);
       
  2017 
       
  2018 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2019 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2020 }
       
  2021 
       
  2022 //--------------------------------------------------
       
  2023 
       
  2024 eap_status_e eap_type_mschapv2_c::old_nt_password_hash_encrypted_with_new_nt_password_hash(
       
  2025 	const eap_variable_data_c * const new_password_hash,
       
  2026 	const eap_variable_data_c * const old_password_hash,
       
  2027 	eap_variable_data_c * const encrypted_password_hash)
       
  2028 {
       
  2029 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2030 
       
  2031 	EAP_TRACE_DEBUG(
       
  2032 		m_am_tools, 
       
  2033 		TRACE_FLAGS_DEFAULT, 
       
  2034 		(EAPL("eap_type_mschapv2_c::old_nt_password_hash_encrypted_with_new_nt_password_hash(): this = 0x%08x\n"),
       
  2035 		this));
       
  2036 
       
  2037 	if (!new_password_hash
       
  2038 		|| !old_password_hash
       
  2039 		|| !encrypted_password_hash)
       
  2040 	{
       
  2041 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2042 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  2043 	}
       
  2044 
       
  2045 	eap_status_e status = nt_password_hash_encrypted_with_block(
       
  2046 		old_password_hash,
       
  2047 		new_password_hash,
       
  2048 		encrypted_password_hash);
       
  2049 
       
  2050 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2051 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2052 }
       
  2053 
       
  2054 //--------------------------------------------------
       
  2055 
       
  2056 eap_status_e eap_type_mschapv2_c::nt_password_hash_encrypted_with_block(
       
  2057 	const eap_variable_data_c * const password_hash,
       
  2058 	const eap_variable_data_c * const block,
       
  2059 	eap_variable_data_c * const cypher)
       
  2060 {
       
  2061 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2062 
       
  2063 	EAP_TRACE_DEBUG(
       
  2064 		m_am_tools, 
       
  2065 		TRACE_FLAGS_DEFAULT, 
       
  2066 		(EAPL("eap_type_mschapv2_c::nt_password_hash_encrypted_with_block(): this = 0x%08x\n"),
       
  2067 		this));
       
  2068 
       
  2069 	if (!password_hash
       
  2070 		|| !block
       
  2071 		|| !cypher)
       
  2072 	{
       
  2073 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2074 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  2075 	}
       
  2076 
       
  2077 	eap_status_e status = cypher->set_buffer_length(EAP_MSCHAPV2_MD4_DIGEST_SIZE);
       
  2078 	if (status != eap_status_ok)
       
  2079 	{
       
  2080 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2081 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2082 	}
       
  2083 
       
  2084 	status = cypher->set_data_length(EAP_MSCHAPV2_MD4_DIGEST_SIZE);
       
  2085 	if (status != eap_status_ok)
       
  2086 	{
       
  2087 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2088 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2089 	}
       
  2090 
       
  2091 	status = des_encrypt(
       
  2092 		password_hash->get_data(), // 1st 8-octets password_hash
       
  2093 		block->get_data(),         // 1st 7-octets block
       
  2094 		cypher->get_data(EAP_MSCHAPV2_DES_BLOCK_SIZE));       // giving 1st 8-octets cypher
       
  2095 
       
  2096 	if (status != eap_status_ok)
       
  2097 	{
       
  2098 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2099 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2100 	}
       
  2101 
       
  2102 	status = des_encrypt(
       
  2103 		password_hash->get_data_offset(8,8), // 2nd 8-octets password_hash
       
  2104 		block->get_data_offset(7,7),         // 2nd 7-octets block
       
  2105 		cypher->get_data_offset(8,EAP_MSCHAPV2_DES_BLOCK_SIZE));       // giving 2nd 8-octets cypher
       
  2106 
       
  2107 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2108 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2109 }
       
  2110 
       
  2111 //--------------------------------------------------
       
  2112 
       
  2113 eap_status_e eap_type_mschapv2_c::generate_session_key(
       
  2114 	eap_master_session_key_c * const key)
       
  2115 {
       
  2116 	EAP_TRACE_DEBUG(
       
  2117 		m_am_tools, 
       
  2118 		TRACE_FLAGS_DEFAULT, 
       
  2119 		(EAPL("eap_type_mschapv2_c::generate_session_key(): this = 0x%08x\n"),
       
  2120 		this));
       
  2121 
       
  2122 	eap_status_e status(eap_status_ok);
       
  2123 
       
  2124 	eap_variable_data_c master_key(m_am_tools);
       
  2125 	if (master_key.get_is_valid() == false)
       
  2126 	{
       
  2127 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2128 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2129 	}
       
  2130 
       
  2131 	crypto_nt_hash_c nt_hash(m_am_tools);
       
  2132 	if (nt_hash.get_is_valid() == false)
       
  2133 	{
       
  2134 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2135 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2136 	}
       
  2137 
       
  2138 	eap_variable_data_c nt_response(m_am_tools);
       
  2139 	if (nt_response.get_is_valid() == false)
       
  2140 	{
       
  2141 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2142 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2143 	}
       
  2144 
       
  2145 	status = nt_response.set_buffer(
       
  2146 		m_nt_response,
       
  2147 		EAP_MSCHAPV2_NT_RESPONSE_SIZE,
       
  2148 		false,
       
  2149 		true);
       
  2150 	if (status != eap_status_ok)
       
  2151 	{
       
  2152 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2153 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2154 	}
       
  2155 
       
  2156 	status = nt_hash.get_master_key(
       
  2157 		&m_password_hash_hash,
       
  2158 		&nt_response,
       
  2159 		&master_key,
       
  2160 		EAP_MSCHAPV2_MASTER_KEY_SIZE);
       
  2161 	if (status != eap_status_ok)
       
  2162 	{
       
  2163 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2164 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2165 	}
       
  2166 
       
  2167 	EAP_TRACE_DATA_DEBUG(
       
  2168 		m_am_tools,
       
  2169 		TRACE_FLAGS_DEFAULT,
       
  2170 		(EAPL("EAP_type_MSCHAPV2: client_send_challenge_response(), master_key"),
       
  2171 		master_key.get_data(),
       
  2172 		master_key.get_data_length()));
       
  2173 
       
  2174 	eap_variable_data_c asymmetric_start_key(m_am_tools);
       
  2175 
       
  2176 	if (asymmetric_start_key.get_is_valid() == false)
       
  2177 	{
       
  2178 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2179 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2180 	}
       
  2181 
       
  2182 
       
  2183 #if defined(USE_FAST_EAP_TYPE)
       
  2184 	if (m_use_EAP_FAST_full_key == true)
       
  2185 	{
       
  2186 		eap_variable_data_c session_key_2(m_am_tools);
       
  2187 
       
  2188 		if (session_key_2.get_is_valid() == false)
       
  2189 		{
       
  2190 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2191 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2192 		}
       
  2193 
       
  2194 		status = nt_hash.get_asymmetric_start_key(
       
  2195 			&master_key,
       
  2196 			&asymmetric_start_key,
       
  2197 			EAP_MSCHAPV2_MASTER_KEY_SIZE,
       
  2198 			false,
       
  2199 			false);
       
  2200 		if (status != eap_status_ok)
       
  2201 		{
       
  2202 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2203 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2204 		}
       
  2205 
       
  2206 		EAP_TRACE_DATA_DEBUG(
       
  2207 			m_am_tools,
       
  2208 			TRACE_FLAGS_DEFAULT,
       
  2209 			(EAPL("EAP_type_MSCHAPV2: client_send_challenge_response(), asymmetric_start_key_1"),
       
  2210 			asymmetric_start_key.get_data(),
       
  2211 			asymmetric_start_key.get_data_length()));
       
  2212 
       
  2213 		status = key->set_copy_of_buffer(&asymmetric_start_key);
       
  2214 		if (status != eap_status_ok)
       
  2215 		{
       
  2216 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2217 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2218 		}
       
  2219 
       
  2220 		status = nt_hash.get_asymmetric_start_key(
       
  2221 			&master_key,
       
  2222 			&asymmetric_start_key,
       
  2223 			EAP_MSCHAPV2_MASTER_KEY_SIZE,
       
  2224 			true,
       
  2225 			false);
       
  2226 		if (status != eap_status_ok)
       
  2227 		{
       
  2228 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2229 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2230 		}
       
  2231 
       
  2232 		EAP_TRACE_DATA_DEBUG(
       
  2233 			m_am_tools,
       
  2234 			TRACE_FLAGS_DEFAULT,
       
  2235 			(EAPL("EAP_type_MSCHAPV2: client_send_challenge_response(), asymmetric_start_key_2"),
       
  2236 			asymmetric_start_key.get_data(),
       
  2237 			asymmetric_start_key.get_data_length()));
       
  2238 
       
  2239 		status = key->add_data(&asymmetric_start_key);
       
  2240 		if (status != eap_status_ok)
       
  2241 		{
       
  2242 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2243 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2244 		}
       
  2245 
       
  2246 	}
       
  2247 	else
       
  2248 #endif //#if defined(USE_FAST_EAP_TYPE)
       
  2249 	{
       
  2250 		status = nt_hash.get_asymmetric_start_key(
       
  2251 			&master_key,
       
  2252 			&asymmetric_start_key,
       
  2253 			EAP_MSCHAPV2_MASTER_KEY_SIZE,
       
  2254 			true,
       
  2255 			false);
       
  2256 		if (status != eap_status_ok)
       
  2257 		{
       
  2258 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2259 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2260 		}
       
  2261 
       
  2262 		EAP_TRACE_DATA_DEBUG(
       
  2263 			m_am_tools,
       
  2264 			TRACE_FLAGS_DEFAULT,
       
  2265 			(EAPL("EAP_type_MSCHAPV2: client_send_challenge_response(), asymmetric_start_key_2"),
       
  2266 			asymmetric_start_key.get_data(),
       
  2267 			asymmetric_start_key.get_data_length()));
       
  2268 
       
  2269 		status = key->set_copy_of_buffer(&asymmetric_start_key);
       
  2270 		if (status != eap_status_ok)
       
  2271 		{
       
  2272 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2273 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2274 		}
       
  2275 	}
       
  2276 
       
  2277 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2278 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2279 }
       
  2280 
       
  2281 // End of File