eapol/eapol_framework/eapol_common/core/eapol_key_state_client.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 49 
       
    23 	#undef EAP_FILE_NUMBER_DATE 
       
    24 	#define EAP_FILE_NUMBER_DATE 1127594498 
       
    25 #endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
       
    26 
       
    27 
       
    28 
       
    29 #include "eap_am_memory.h"
       
    30 #include "eapol_key_state.h"
       
    31 #include "eapol_key_header.h"
       
    32 #include "eap_crypto_api.h"
       
    33 #include "abs_eap_am_mutex.h"
       
    34 #include "eap_state_notification.h"
       
    35 #include "eap_automatic_variable.h"
       
    36 #include "eapol_rsna_key_data_gtk_header.h"
       
    37 #include "eap_buffer.h"
       
    38 #include "eapol_rsna_key_data_payloads.h"
       
    39 #include "abs_eapol_key_state.h"
       
    40 #include "eapol_rc4_key_header.h"
       
    41 #include "eapol_key_state_string.h"
       
    42 
       
    43 //--------------------------------------------------
       
    44 //
       
    45 eap_status_e eapol_key_state_c::create_4_way_handshake_message_2(
       
    46 	eap_buf_chain_wr_c * const sent_packet,
       
    47 	const u32_t eapol_header_offset,
       
    48 	u32_t * const data_length,
       
    49 	u32_t * const buffer_length,
       
    50 	const u64_t received_key_replay_counter,
       
    51 	const eapol_protocol_version_e received_eapol_version,
       
    52 	const eapol_key_descriptor_type_e received_key_descriptor_type)
       
    53 {
       
    54 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
    55 	eap_status_e status = eap_status_process_general_error;
       
    56 
       
    57 	EAP_TRACE_DEBUG(
       
    58 		m_am_tools, 
       
    59 		TRACE_FLAGS_DEFAULT, 
       
    60 		(EAPL("EAPOL_KEY: %s: eapol_key_state_c::create_4_way_handshake_message_2()\n"),
       
    61 		(m_is_client == true ? "client": "server")));
       
    62 
       
    63 	// Only client (Supplicant) could create 4-Way Handshake message 2.
       
    64 	EAP_ASSERT_ALWAYS(m_is_client == true);
       
    65 
       
    66 	if (sent_packet == 0
       
    67 		|| sent_packet->get_is_valid() == false)
       
    68 	{
       
    69 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
    70 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
    71 	}
       
    72 
       
    73 	if (m_SNonce.get_is_valid_data() == false
       
    74 		|| m_SNonce.get_data_length() != eapol_RSNA_key_header_c::EAPOL_RSNA_KEY_NONCE_SIZE)
       
    75 	{
       
    76 		EAP_TRACE_ERROR(
       
    77 			m_am_tools,
       
    78 			TRACE_FLAGS_EAPOL_KEY_DATA_ERROR,
       
    79 			(EAPL("ERROR: EAPOL_KEY: eapol_key_state_c::create_4_way_handshake_message_2(): ")
       
    80 			 EAPL("m_SNonce is missing or corrupted.\n")));
       
    81 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
    82 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
    83 	}
       
    84 
       
    85 	if (m_supplicant_RSNA_IE.get_is_valid_data() == false
       
    86 		|| m_supplicant_RSNA_IE.get_data_length() == 0ul
       
    87 		|| m_supplicant_RSNA_IE.get_data_length()
       
    88 		> eapol_RSNA_key_header_c::EAPOL_RSNA_KEY_DATA_MAXIMUM_RSN_IE_SIZE)
       
    89 	{
       
    90 		EAP_TRACE_ERROR(
       
    91 			m_am_tools,
       
    92 			TRACE_FLAGS_EAPOL_KEY_DATA_ERROR,
       
    93 			(EAPL("ERROR: EAPOL_KEY: eapol_key_state_c::create_4_way_handshake_message_2(): ")
       
    94 			 EAPL("m_supplicant_RSNA_IE is missing or corrupted.\n")));
       
    95 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
    96 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
    97 	}
       
    98 
       
    99 
       
   100 	u32_t eapol_key_data_length
       
   101 		= eapol_RSNA_key_header_c::get_header_length()
       
   102 		+ m_supplicant_RSNA_IE.get_data_length();
       
   103 
       
   104 	*buffer_length
       
   105 		= eapol_header_offset
       
   106 		+ eapol_key_data_length;
       
   107 
       
   108 	status = sent_packet->set_buffer_length(
       
   109 		*buffer_length);
       
   110 	if (status != eap_status_ok)
       
   111 	{
       
   112 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   113 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   114 	}
       
   115 	sent_packet->set_data_length(
       
   116 		sent_packet->get_buffer_length());
       
   117 
       
   118 	eapol_RSNA_key_header_c eapol_key_message(
       
   119 		m_am_tools,
       
   120 		get_is_RSNA(),
       
   121 		get_is_WPXM(),
       
   122 		sent_packet->get_data_offset(eapol_header_offset, eapol_key_data_length),
       
   123 		sent_packet->get_data_length());
       
   124 
       
   125 	if (eapol_key_message.get_is_valid() == false)
       
   126 	{
       
   127 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   128 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   129 	}
       
   130 
       
   131 
       
   132 	status = eapol_key_message.reset_header(
       
   133 		0ul,
       
   134 		m_authentication_type,
       
   135 		m_eapol_pairwise_cipher,
       
   136 		received_key_replay_counter,
       
   137 		true, // Pairwise key type bit is on.
       
   138 		false, // Install bit is NOT set.
       
   139 		false, // Key Ack bit is NOT set.
       
   140 		true, // Key MIC bit is on.
       
   141 		false, // Secure bit is NOT set.
       
   142 		false, // Error bit is NOT set.
       
   143 		false, // Request bit is NOT set.
       
   144 		false, // STAKey bit is NOT set.
       
   145 		false, // Encrypted Key Data bit is NOT set.
       
   146 		received_eapol_version,
       
   147 		received_key_descriptor_type);
       
   148 	if (status != eap_status_ok)
       
   149 	{
       
   150 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   151 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   152 	}
       
   153 
       
   154 
       
   155 	{
       
   156 		// Add SNonce.
       
   157 		u8_t * const nonce_field = eapol_key_message.get_key_NONCE();
       
   158 		if (nonce_field == 0
       
   159 			|| m_SNonce.get_data_length() != eapol_RSNA_key_header_c::EAPOL_RSNA_KEY_NONCE_SIZE)
       
   160 		{
       
   161 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   162 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   163 		}
       
   164 		m_am_tools->memmove(
       
   165 			nonce_field,
       
   166 			m_SNonce.get_data(eapol_RSNA_key_header_c::EAPOL_RSNA_KEY_NONCE_SIZE),
       
   167 			eapol_RSNA_key_header_c::EAPOL_RSNA_KEY_NONCE_SIZE);
       
   168 	}
       
   169 
       
   170 
       
   171 	u32_t total_key_data_length(0ul);
       
   172 
       
   173 	status = add_RSN_IE_payload(
       
   174 		&eapol_key_message,
       
   175 		&m_supplicant_RSNA_IE,
       
   176 		&total_key_data_length);
       
   177 	if (status != eap_status_ok)
       
   178 	{
       
   179 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   180 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   181 	}
       
   182 
       
   183 	if (total_key_data_length > 0xffff)
       
   184 	{
       
   185 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   186 		return EAP_STATUS_RETURN(m_am_tools, eap_status_too_long_message);
       
   187 	}
       
   188 
       
   189 	status = eapol_key_message.set_key_data_length(
       
   190 		static_cast<u16_t>(total_key_data_length));
       
   191 	if (status != eap_status_ok)
       
   192 	{
       
   193 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   194 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   195 	}
       
   196 
       
   197 	*data_length
       
   198 		= eapol_key_message.get_header_length()
       
   199 		+ eapol_key_message.get_key_data_length();
       
   200 
       
   201 	status = eapol_key_message.set_eapol_packet_body_length(
       
   202 		static_cast<u16_t>(*data_length - eapol_header_base_c::get_header_length()));
       
   203 	if (status != eap_status_ok)
       
   204 	{
       
   205 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   206 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   207 	}
       
   208 
       
   209 	const eap_variable_data_c * confirmation_key = &m_confirmation_KCK;
       
   210 #if defined(EAP_USE_WPXM)
       
   211 	if (get_is_WPXM() == true)
       
   212 	{
       
   213 		confirmation_key = &m_WPXM_WPXK1;
       
   214 	}
       
   215 #endif //#if defined(EAP_USE_WPXM)
       
   216 
       
   217 	status = create_key_mic(
       
   218 		&eapol_key_message,
       
   219 		confirmation_key);
       
   220 	if (status != eap_status_ok)
       
   221 	{
       
   222 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   223 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   224 	}
       
   225 
       
   226 #if defined(USE_EAPOL_KEY_TEST_FAILURES)
       
   227 	if (m_create_key_failure == eapol_key_state_wait_4_way_handshake_message_1)
       
   228 	{
       
   229 		m_create_key_failure = eapol_key_state_wait_4_way_handshake_message_3;
       
   230 
       
   231 		status = eapol_key_message.zero_key_MIC(m_am_tools);
       
   232 		if (status != eap_status_ok)
       
   233 		{
       
   234 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   235 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   236 		}
       
   237 
       
   238 		EAP_TRACE_DEBUG(
       
   239 			m_am_tools, 
       
   240 			TRACE_FLAGS_DEFAULT, 
       
   241 			(EAPL("WARNING: EAPOL_KEY: %s: error generated in eapol_key_state_c::create_4_way_handshake_message_2()\n"),
       
   242 			 (m_is_client == true ? "client": "server")));
       
   243 	}
       
   244 #endif //#if defined(USE_EAPOL_KEY_TEST_FAILURES)
       
   245 
       
   246 	sent_packet->set_data_length(
       
   247 		eapol_header_offset + *data_length);
       
   248 
       
   249 	TRACE_EAPOL_KEY_MESSAGE(
       
   250 		"Send 4-Way Handshake Message 2",
       
   251 		&eapol_key_message);
       
   252 
       
   253 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   254 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   255 }
       
   256 
       
   257 //--------------------------------------------------
       
   258 
       
   259 //
       
   260 eap_status_e eapol_key_state_c::create_4_way_handshake_message_4(
       
   261 	eap_buf_chain_wr_c * const sent_packet,
       
   262 	const u32_t eapol_header_offset,
       
   263 	u32_t * const data_length,
       
   264 	u32_t * const buffer_length,
       
   265 	const u64_t received_key_replay_counter,
       
   266 	const bool received_secure_bit,
       
   267 	const eapol_protocol_version_e received_eapol_version,
       
   268 	const eapol_key_descriptor_type_e received_key_descriptor_type)
       
   269 {
       
   270 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   271 	eap_status_e status = eap_status_process_general_error;
       
   272 
       
   273 	EAP_TRACE_DEBUG(
       
   274 		m_am_tools, 
       
   275 		TRACE_FLAGS_DEFAULT, 
       
   276 		(EAPL("EAPOL_KEY: %s: eapol_key_state_c::create_4_way_handshake_message_4()\n"),
       
   277 		(m_is_client == true ? "client": "server")));
       
   278 
       
   279 	// Only client (Supplicant) could create 4-Way Handshake message 4.
       
   280 	EAP_ASSERT_ALWAYS(m_is_client == true);
       
   281 
       
   282 	if (sent_packet == 0
       
   283 		|| sent_packet->get_is_valid() == false)
       
   284 	{
       
   285 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   286 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   287 	}
       
   288 
       
   289 	u32_t eapol_key_data_length
       
   290 		= eapol_RSNA_key_header_c::get_header_length();
       
   291 
       
   292 	*buffer_length
       
   293 		= eapol_header_offset
       
   294 		+ eapol_key_data_length;
       
   295 
       
   296 	status = sent_packet->set_buffer_length(
       
   297 		*buffer_length);
       
   298 	if (status != eap_status_ok)
       
   299 	{
       
   300 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   301 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   302 	}
       
   303 	sent_packet->set_data_length(
       
   304 		sent_packet->get_buffer_length());
       
   305 
       
   306 	eapol_RSNA_key_header_c eapol_key_message(
       
   307 		m_am_tools,
       
   308 		get_is_RSNA(),
       
   309 		get_is_WPXM(),
       
   310 		sent_packet->get_data_offset(eapol_header_offset, eapol_key_data_length),
       
   311 		sent_packet->get_data_length());
       
   312 
       
   313 	if (eapol_key_message.get_is_valid() == false)
       
   314 	{
       
   315 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   316 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   317 	}
       
   318 
       
   319 
       
   320 	bool secure_bit = received_secure_bit; // Secure bit is the same as in the received WPA 4-Way Handshake message 3.
       
   321 
       
   322 	if (get_is_RSNA() == true)
       
   323 	{
       
   324 		secure_bit = true; // Secure bit is on in RSNA.
       
   325 	}
       
   326 
       
   327 	status = eapol_key_message.reset_header(
       
   328 		0ul,
       
   329 		m_authentication_type,
       
   330 		m_eapol_pairwise_cipher,
       
   331 		received_key_replay_counter,
       
   332 		true, // Pairwise key type bit is on.
       
   333 		false, // Install bit is NOT set.
       
   334 		false, // Key Ack bit is NOT set.
       
   335 		true, // Key MIC bit is on.
       
   336 		secure_bit,
       
   337 		false, // Error bit is NOT set.
       
   338 		false, // Request bit is NOT set.
       
   339 		false, // STAKey bit is NOT set.
       
   340 		false, // Encrypted Key Data bit is NOT set.
       
   341 		received_eapol_version,
       
   342 		received_key_descriptor_type);
       
   343 	if (status != eap_status_ok)
       
   344 	{
       
   345 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   346 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   347 	}
       
   348 
       
   349 	status = eapol_key_message.set_key_data_length(0ul);
       
   350 	if (status != eap_status_ok)
       
   351 	{
       
   352 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   353 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   354 	}
       
   355 
       
   356 	*data_length
       
   357 		= eapol_key_message.get_header_length()
       
   358 		+ eapol_key_message.get_key_data_length();
       
   359 
       
   360 	status = eapol_key_message.set_eapol_packet_body_length(
       
   361 		static_cast<u16_t>(*data_length - eapol_header_base_c::get_header_length()));
       
   362 	if (status != eap_status_ok)
       
   363 	{
       
   364 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   365 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   366 	}
       
   367 
       
   368 	status = create_key_mic(
       
   369 		&eapol_key_message,
       
   370 		&m_confirmation_KCK);
       
   371 	if (status != eap_status_ok)
       
   372 	{
       
   373 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   374 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   375 	}
       
   376 
       
   377 #if defined(USE_EAPOL_KEY_TEST_FAILURES)
       
   378 	if (m_create_key_failure == eapol_key_state_wait_4_way_handshake_message_3)
       
   379 	{
       
   380 		m_create_key_failure = eapol_key_state_4_way_handshake_successfull;
       
   381 
       
   382 		status = eapol_key_message.zero_key_MIC(m_am_tools);
       
   383 		if (status != eap_status_ok)
       
   384 		{
       
   385 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   386 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   387 		}
       
   388 
       
   389 		EAP_TRACE_ERROR(
       
   390 			m_am_tools, 
       
   391 			TRACE_FLAGS_DEFAULT, 
       
   392 			(EAPL("WARNING: EAPOL_KEY: %s: error generated in eapol_key_state_c::create_4_way_handshake_message_4()\n"),
       
   393 			 (m_is_client == true ? "client": "server")));
       
   394 	}
       
   395 #endif //#if defined(USE_EAPOL_KEY_TEST_FAILURES)
       
   396 
       
   397 	sent_packet->set_data_length(
       
   398 		eapol_header_offset + *data_length);
       
   399 
       
   400 	TRACE_EAPOL_KEY_MESSAGE(
       
   401 		"Send 4-Way Handshake Message 4",
       
   402 		&eapol_key_message);
       
   403 
       
   404 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   405 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   406 }
       
   407 
       
   408 //--------------------------------------------------
       
   409 
       
   410 //
       
   411 eap_status_e eapol_key_state_c::process_4_way_handshake_message_1(
       
   412 	const eap_am_network_id_c * const receive_network_id,
       
   413 	eapol_RSNA_key_header_c * const eapol_key_message,
       
   414 	const u32_t /* packet_length */)
       
   415 {
       
   416 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   417 	EAP_UNREFERENCED_PARAMETER(receive_network_id);
       
   418 
       
   419 	eap_status_e status = eap_status_process_general_error;
       
   420 
       
   421 	eapol_key_state_string_c state_string;
       
   422 
       
   423 	EAP_TRACE_DEBUG(
       
   424 		m_am_tools, 
       
   425 		TRACE_FLAGS_DEFAULT, 
       
   426 		(EAPL("EAPOL_KEY: %s: eapol_key_state_c::process_4_way_handshake_message_1(): eapol_key_descriptor_type = %s = 0x%02x\n"),
       
   427 		(m_is_client == true ? "client": "server"),
       
   428 		state_string.get_eapol_key_descriptor_type_string(eapol_key_message->get_key_descriptor_type()),
       
   429 		eapol_key_message->get_key_descriptor_type()));
       
   430 
       
   431 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eapol_key_state_c::process_4_way_handshake_message_1()");
       
   432 
       
   433 	// Only client (supplicant) could receive 4-Way Handshake message 1.
       
   434 	EAP_ASSERT_ALWAYS(m_is_client == true);
       
   435 
       
   436 	if (m_eapol_key_handshake_type == eapol_key_handshake_type_none)
       
   437 	{
       
   438 		// 4-Way Handshake started again.
       
   439 		m_eapol_key_handshake_type = eapol_key_handshake_type_4_way_handshake;
       
   440 		set_eapol_key_state(eapol_key_state_wait_4_way_handshake_message_1);
       
   441 
       
   442 		EAP_TRACE_ALWAYS(
       
   443 			m_am_tools,
       
   444 			TRACE_FLAGS_DEFAULT,
       
   445 			(EAPL("EAPOL_KEY: %s: process_4_way_handshake_message_1(): 4-Way Handshake restarted.\n"),
       
   446 			(m_is_client == true ? "client": "server")));
       
   447 	}
       
   448 
       
   449 	if (get_eapol_key_state() != eapol_key_state_wait_4_way_handshake_message_1
       
   450 		&& get_eapol_key_state() != eapol_key_state_wait_4_way_handshake_message_3
       
   451 		&& get_eapol_key_state() != eapol_key_state_4_way_handshake_successfull
       
   452 		&& get_eapol_key_state() != eapol_key_state_preauthenticated
       
   453 #if defined(EAP_USE_WPXM)
       
   454 		&& get_eapol_key_state() != eapol_key_state_wpxm_reassociation_finished_successfull
       
   455 #endif //#if defined(EAP_USE_WPXM)
       
   456 		)
       
   457 	{
       
   458 		EAP_TRACE_ERROR(
       
   459 			m_am_tools,
       
   460 			TRACE_FLAGS_DEFAULT,
       
   461 			(EAPL("WARNING: EAPOL_KEY: %s: process_4_way_handshake_message_1(): wrong state %s\n"),
       
   462 			(m_is_client == true ? "client": "server"),
       
   463 			state_string.get_eapol_key_state_string(get_eapol_key_state())));
       
   464 
       
   465 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   466 		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
       
   467 	}
       
   468 
       
   469 	// Some APs seems to behave incorrectly and
       
   470 	// fills the IV field with non-zero stuff. For this reason don't verify the field to be 0.
       
   471 
       
   472 	status = verify_field_is_zero(
       
   473 		eapol_key_message->get_key_RSC(),
       
   474 		eapol_RSNA_key_header_c::EAPOL_RSNA_KEY_RSC_SIZE);
       
   475 	if (status != eap_status_ok)
       
   476 	{
       
   477 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   478 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   479 	}
       
   480 
       
   481 	/**
       
   482 	 * @{ In 802.11i D3.0 this field is Key ID instead of STA MAC address. }
       
   483 	 */
       
   484 	status = verify_field_is_zero(
       
   485 		eapol_key_message->get_key_STA_MAC_address(),
       
   486 		eapol_RSNA_key_header_c::EAPOL_RSNA_KEY_STA_MAC_ADDRESS_SIZE);
       
   487 	if (status != eap_status_ok)
       
   488 	{
       
   489 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   490 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   491 	}
       
   492 
       
   493 	if (m_allow_non_zero_mic_and_reserved_in_message_1 == false)
       
   494 	{
       
   495 		status = verify_field_is_zero(
       
   496 			eapol_key_message->get_key_reserved(),
       
   497 			eapol_RSNA_key_header_c::EAPOL_RSNA_KEY_RESERVED_SIZE);
       
   498 		if (status != eap_status_ok)
       
   499 		{
       
   500 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   501 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   502 		}
       
   503 
       
   504 		status = verify_field_is_zero(
       
   505 			eapol_key_message->get_key_MIC(),
       
   506 			eapol_RSNA_key_header_c::EAPOL_RSNA_KEY_MIC_SIZE);
       
   507 		if (status != eap_status_ok)
       
   508 		{
       
   509 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   510 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   511 		}
       
   512 	}
       
   513 
       
   514 	// Save ANonce.
       
   515 	const u8_t * const ANonce = eapol_key_message->get_key_NONCE();
       
   516 	if (ANonce == 0)
       
   517 	{
       
   518 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   519 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
   520 	}
       
   521 
       
   522 	status = m_ANonce.set_copy_of_buffer(
       
   523 		ANonce,
       
   524 		eapol_RSNA_key_header_c::EAPOL_RSNA_KEY_NONCE_SIZE);
       
   525 	if (status != eap_status_ok)
       
   526 	{
       
   527 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   528 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   529 	}
       
   530 
       
   531 
       
   532 	if (get_is_RSNA() == true)
       
   533 	{
       
   534 		u32_t received_buffer_length = eapol_key_message->get_key_data_length();
       
   535 
       
   536 		if (m_allow_missing_PMKID_in_message_1 == false
       
   537 			&& received_buffer_length == 0u)
       
   538 		{
       
   539 			// No payload in this packet.
       
   540 			return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
   541 		}
       
   542 		
       
   543 		if (received_buffer_length > 0u)
       
   544 		{
       
   545 			if (received_buffer_length > eapol_key_message->get_header_buffer_length()
       
   546 				|| eapol_key_message->get_key_data(received_buffer_length) == 0)
       
   547 			{
       
   548 				// Not enough payload in this packet.
       
   549 				return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
   550 			}
       
   551 
       
   552 			eapol_rsna_key_data_payloads_c key_data_payloads(
       
   553 				m_am_tools,
       
   554 				get_is_RSNA(),
       
   555 				get_is_WPXM());
       
   556 
       
   557 			eapol_rsna_key_data_header_c key_data(
       
   558 				m_am_tools,
       
   559 				get_is_RSNA(),
       
   560 				get_is_WPXM(),
       
   561 				eapol_key_message->get_key_data(received_buffer_length),
       
   562 				received_buffer_length);
       
   563 			if (key_data.get_is_valid() == false)
       
   564 			{
       
   565 				EAP_TRACE_ERROR(
       
   566 					m_am_tools, 
       
   567 					TRACE_FLAGS_EAPOL_KEY_DATA_ERROR, 
       
   568 					(EAPL("ERROR: EAPOL_KEY: No EAPOL-Key data payloads.\n")));
       
   569 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   570 				return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   571 			}
       
   572 
       
   573 			status = key_data.check_header();
       
   574 			if (status != eap_status_ok)
       
   575 			{
       
   576 				EAP_TRACE_ERROR(
       
   577 					m_am_tools, 
       
   578 					TRACE_FLAGS_EAPOL_KEY_DATA_ERROR, 
       
   579 					(EAPL("ERROR: EAPOL_KEY: EAPOL-Key data payload header corrupted.\n")));
       
   580 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   581 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   582 			}
       
   583 
       
   584 			status = parse_key_data(
       
   585 				eapol_key_message->get_key_descriptor_type(),
       
   586 				&key_data,
       
   587 				&received_buffer_length,
       
   588 				&key_data_payloads,
       
   589 				eapol_key_state_wait_4_way_handshake_message_1,
       
   590 				eapol_key_message->get_key_information_key_descriptor_version());
       
   591 			if (status != eap_status_ok)
       
   592 			{
       
   593 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   594 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   595 			}
       
   596 
       
   597 			eapol_rsna_key_data_payloads_c::eapol_rsna_key_data_payload_status_e PMKID_existence(
       
   598 				eapol_rsna_key_data_payloads_c::eapol_rsna_key_data_payload_status_must_be);
       
   599 
       
   600 			if (m_allow_missing_PMKID_in_message_1 == true)
       
   601 			{
       
   602 				PMKID_existence = eapol_rsna_key_data_payloads_c::eapol_rsna_key_data_payload_status_optional;
       
   603 			}
       
   604 
       
   605 			// Check the valid payload is included.
       
   606 			if (false == key_data_payloads.check_payloads(
       
   607 				eapol_rsna_key_data_payloads_c::eapol_rsna_key_data_payload_status_must_not_be, // key_id_and_group_key
       
   608 				eapol_rsna_key_data_payloads_c::eapol_rsna_key_data_payload_status_must_not_be, // STAKey
       
   609 				PMKID_existence, // PMKID
       
   610 				eapol_rsna_key_data_payloads_c::eapol_rsna_key_data_payload_status_must_not_be // One or more RSN IE
       
   611 				))
       
   612 			{
       
   613 				// Not correct EAPOL Key Data payloads are included.
       
   614 				EAP_TRACE_ERROR(
       
   615 					m_am_tools, 
       
   616 					TRACE_FLAGS_EAPOL_KEY_DATA_ERROR, 
       
   617 					(EAPL("ERROR: EAPOL_KEY: eapol_key_state_c::process_4_way_handshake_message_1(): ")
       
   618 					 EAPL("Not correct EAPOL Key Data payloads are included.\n")));
       
   619 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   620 				return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
   621 			}
       
   622 
       
   623 			if (key_data_payloads.get_PMKID()->get_is_valid_data() == true)
       
   624 			{
       
   625 				// We do have the expected PMKID, save it.
       
   626 				status = get_received_PMKID()->set_copy_of_buffer(key_data_payloads.get_PMKID());
       
   627 				if (status != eap_status_ok)
       
   628 				{
       
   629 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   630 					return EAP_STATUS_RETURN(m_am_tools, status);
       
   631 				}
       
   632 			}
       
   633 			else
       
   634 			{
       
   635 				// We do not get mandatory PMKID.
       
   636 				// Access point is broken and cached PMKSA is not used.
       
   637 				EAP_TRACE_DEBUG(
       
   638 					m_am_tools, 
       
   639 					TRACE_FLAGS_DEFAULT, 
       
   640 					(EAPL("WARNING: EAPOL_KEY: eapol_key_state_c::process_4_way_handshake_message_1(): ")
       
   641 					 EAPL("Not correct EAPOL Key Data payloads are included, mandatory PMKID is missing.\n")));
       
   642 			}
       
   643 		}
       
   644 		else
       
   645 		{
       
   646 			EAP_TRACE_DEBUG(
       
   647 				m_am_tools, 
       
   648 				TRACE_FLAGS_DEFAULT, 
       
   649 				(EAPL("WARNING: EAPOL_KEY: eapol_key_state_c::process_4_way_handshake_message_1(): ")
       
   650 				 EAPL("Not correct EAPOL Key Data payloads are included, mandatory PMKID is missing.\n")));
       
   651 		}
       
   652 	}
       
   653 
       
   654 #if defined(EAP_USE_WPXM)
       
   655 	if (get_is_WPXM() == true)
       
   656 	{
       
   657 		EAP_TRACE_DEBUG(
       
   658 			m_am_tools, 
       
   659 			TRACE_FLAGS_DEFAULT, 
       
   660 			(EAPL("EAPOL_KEY: eapol_key_state_c::process_4_way_handshake_message_1(): ")
       
   661 			 EAPL("m_WPXM_WPXC=%d.\n"),
       
   662 			 m_WPXM_WPXC));
       
   663 
       
   664 		status = derive_WPXM_WPXK1_WPXK2();
       
   665 		if (status != eap_status_ok)
       
   666 		{
       
   667 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   668 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   669 		}
       
   670 
       
   671 		status = derive_WPXM_PTK(eapol_key_constant_wpxm_initial_wpxc_counter_value);
       
   672 	}
       
   673 	else
       
   674 #endif //#if defined(EAP_USE_WPXM)
       
   675 	{
       
   676 		status = derive_PTK();
       
   677 	}
       
   678 
       
   679 	if (status != eap_status_ok)
       
   680 	{
       
   681 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   682 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   683 	}
       
   684 
       
   685 	eap_buf_chain_wr_c sent_packet(
       
   686 		eap_write_buffer,
       
   687 		m_am_tools);
       
   688 
       
   689 	if (sent_packet.get_is_valid() == false)
       
   690 	{
       
   691 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   692 	}
       
   693 
       
   694 	u32_t send_data_length = 0ul;
       
   695 	u32_t send_buffer_length = 0ul;
       
   696 
       
   697 	status = create_4_way_handshake_message_2(
       
   698 		&sent_packet,
       
   699 		m_eapol_header_offset,
       
   700 		&send_data_length,
       
   701 		&send_buffer_length,
       
   702 		eapol_key_message->get_key_replay_counter(),
       
   703 		eapol_key_message->get_eapol_protocol_version(),
       
   704 		eapol_key_message->get_key_descriptor_type());
       
   705 	if (status != eap_status_ok)
       
   706 	{
       
   707 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   708 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   709 	}
       
   710 
       
   711 	status = packet_send(
       
   712 		&m_send_network_id,
       
   713 		&sent_packet,
       
   714 		m_eapol_header_offset,
       
   715 		send_data_length,
       
   716 		send_buffer_length);
       
   717 	if (status != eap_status_ok)
       
   718 	{
       
   719 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   720 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   721 	}
       
   722 
       
   723 	cancel_4_way_handshake_start_timeout();
       
   724 
       
   725 	set_eapol_key_state(eapol_key_state_wait_4_way_handshake_message_3);
       
   726 
       
   727 	m_eapol_key_handshake_type = eapol_key_handshake_type_4_way_handshake;
       
   728 
       
   729 	set_key_reply_counter(eapol_key_message->get_key_replay_counter());
       
   730 
       
   731 	status = init_handshake_timeout(m_handshake_timeout);
       
   732 	if (status != eap_status_ok)
       
   733 	{
       
   734 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   735 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   736 	}
       
   737 
       
   738 	{
       
   739 		// This is notification to eapol_core_c object.
       
   740 		// 4-Way Handshake started successfully.
       
   741 		eap_state_notification_c * notification = new eap_state_notification_c(
       
   742 			m_am_tools,
       
   743 			&m_send_network_id,
       
   744 			m_is_client,
       
   745 			eap_state_notification_generic,
       
   746 			eap_protocol_layer_eapol_key,
       
   747 			eapol_key_handshake_type_4_way_handshake,
       
   748 			eapol_key_state_4_way_handshake_running,
       
   749 			eapol_key_state_4_way_handshake_running,
       
   750 			0ul,
       
   751 			false);
       
   752 		if (notification == 0)
       
   753 		{
       
   754 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   755 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   756 		}
       
   757 		m_key_state_partner->state_notification(notification);
       
   758 
       
   759 		delete notification;
       
   760 	}
       
   761 
       
   762 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   763 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   764 }
       
   765 
       
   766 //--------------------------------------------------
       
   767 
       
   768 //
       
   769 eap_status_e eapol_key_state_c::process_4_way_handshake_message_3_payloads_a(
       
   770 	const eap_am_network_id_c * const receive_network_id,
       
   771 	eapol_RSNA_key_header_c * const eapol_key_message,
       
   772 	const u32_t packet_length,
       
   773 	bool * const group_key_received)
       
   774 {
       
   775 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   776 	EAP_UNREFERENCED_PARAMETER(receive_network_id);
       
   777 
       
   778 	eap_status_e status = eap_status_process_general_error;
       
   779 
       
   780 	// Only client (supplicant) could receive 4-Way Handshake message 3.
       
   781 	EAP_ASSERT_ALWAYS(m_is_client == true);
       
   782 
       
   783 
       
   784 	{
       
   785 		u32_t received_buffer_length = eapol_key_message->get_key_data_length();
       
   786 
       
   787 		if (received_buffer_length > eapol_key_message->get_header_buffer_length()
       
   788 			|| eapol_key_message->get_key_data(received_buffer_length) == 0)
       
   789 		{
       
   790 			// Not enough payload in this packet.
       
   791 			return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
   792 		}
       
   793 
       
   794 		eapol_rsna_key_data_payloads_c key_data_payloads(
       
   795 			m_am_tools,
       
   796 			get_is_RSNA(),
       
   797 			get_is_WPXM());
       
   798 
       
   799 		eapol_rsna_key_data_header_c key_data(
       
   800 			m_am_tools,
       
   801 			get_is_RSNA(),
       
   802 			get_is_WPXM(),
       
   803 			eapol_key_message->get_key_data(received_buffer_length),
       
   804 			packet_length);
       
   805 		if (key_data.get_is_valid() == false)
       
   806 		{
       
   807 			EAP_TRACE_ERROR(
       
   808 				m_am_tools, 
       
   809 				TRACE_FLAGS_EAPOL_KEY_DATA_ERROR, 
       
   810 				(EAPL("ERROR: EAPOL_KEY: No EAPOL-Key data payloads.\n")));
       
   811 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   812 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   813 		}
       
   814 
       
   815 		status = key_data.check_header();
       
   816 		if (status != eap_status_ok)
       
   817 		{
       
   818 			EAP_TRACE_ERROR(
       
   819 				m_am_tools, 
       
   820 				TRACE_FLAGS_EAPOL_KEY_DATA_ERROR, 
       
   821 				(EAPL("ERROR: EAPOL_KEY: EAPOL-Key data payload header corrupted.\n")));
       
   822 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   823 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   824 		}
       
   825 
       
   826 		status = parse_key_data(
       
   827 			eapol_key_message->get_key_descriptor_type(),
       
   828 			&key_data,
       
   829 			&received_buffer_length,
       
   830 			&key_data_payloads,
       
   831 			eapol_key_state_wait_4_way_handshake_message_3,
       
   832 			eapol_key_message->get_key_information_key_descriptor_version());
       
   833 		if (status != eap_status_ok)
       
   834 		{
       
   835 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   836 			return EAP_STATUS_RETURN(m_am_tools, status);
       
   837 		}
       
   838 
       
   839 		// Check the valid payload is included.
       
   840 		if (false == key_data_payloads.check_payloads(
       
   841 			eapol_rsna_key_data_payloads_c::eapol_rsna_key_data_payload_status_optional, // key_id_and_group_key
       
   842 			eapol_rsna_key_data_payloads_c::eapol_rsna_key_data_payload_status_must_not_be, // STAKey
       
   843 			eapol_rsna_key_data_payloads_c::eapol_rsna_key_data_payload_status_must_not_be, // PMKID
       
   844 			eapol_rsna_key_data_payloads_c::eapol_rsna_key_data_payload_status_must_be // One or more RSN IE
       
   845 			))
       
   846 		{
       
   847 			// Not correct EAPOL Key Data payloads are included.
       
   848 			EAP_TRACE_ERROR(
       
   849 				m_am_tools, 
       
   850 				TRACE_FLAGS_EAPOL_KEY_DATA_ERROR, 
       
   851 				(EAPL("ERROR: EAPOL_KEY: eapol_key_state_c::process_4_way_handshake_message_3_payloads_a(): ")
       
   852 				 EAPL("Not correct EAPOL Key Data payloads are included.\n")));
       
   853 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   854 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
   855 		}
       
   856 
       
   857 		// We do have the expected RSN IE, compare it.
       
   858 		if (get_authenticator_RSNA_IE()->compare(
       
   859 				key_data_payloads.get_RSN_IE()->get_object(0ul)) != 0)
       
   860 		{
       
   861 			// Illegal RSN IE.
       
   862 			EAP_TRACE_ERROR(
       
   863 				m_am_tools, 
       
   864 				TRACE_FLAGS_EAPOL_KEY_DATA_ERROR, 
       
   865 				(EAPL("ERROR: EAPOL_KEY: eapol_key_state_c::process_4_way_handshake_message_3_payloads_a(): ")
       
   866 				 EAPL("Not correct RSN IE received.\n")));
       
   867 
       
   868 			EAP_TRACE_DATA_DEBUG(
       
   869 				m_am_tools,
       
   870 				TRACE_FLAGS_EAPOL_KEY_DATA_ERROR,
       
   871 				(EAPL("   Local RSN IE"),
       
   872 				get_authenticator_RSNA_IE()->get_data(
       
   873 					get_authenticator_RSNA_IE()->get_data_length()),
       
   874 				get_authenticator_RSNA_IE()->get_data_length()));
       
   875 
       
   876 			EAP_TRACE_DATA_DEBUG(
       
   877 				m_am_tools,
       
   878 				TRACE_FLAGS_EAPOL_KEY_DATA_ERROR,
       
   879 				(EAPL("Received RSN IE"),
       
   880 				key_data_payloads.get_RSN_IE()->get_object(0ul)->get_data(
       
   881 					key_data_payloads.get_RSN_IE()->get_object(0ul)->get_data_length()),
       
   882 				key_data_payloads.get_RSN_IE()->get_object(0ul)->get_data_length()));
       
   883 
       
   884 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   885 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
   886 		}
       
   887 
       
   888 		// Check the optional second RSN IE.
       
   889 		if (key_data_payloads.get_RSN_IE()->get_object_count() > 1ul
       
   890 			&& key_data_payloads.get_RSN_IE()->get_object(1ul) != 0
       
   891 			&& key_data_payloads.get_RSN_IE()->get_object(1ul)->get_is_valid_data() == true)
       
   892 		{
       
   893 			// If a second RSN IE is provided in the message, the Supplicant shall use
       
   894 			// the unicast cipher suite specified in the second RSN IE or deauthenticate.
       
   895 			status = get_unicast_cipher_suite_RSNA_IE()->set_copy_of_buffer(
       
   896 				key_data_payloads.get_RSN_IE()->get_object(1ul));
       
   897 			if (status != eap_status_ok)
       
   898 			{
       
   899 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   900 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   901 			}
       
   902 		}
       
   903 
       
   904 
       
   905 		if (get_is_RSNA() == true
       
   906 			|| (get_is_WPXM() == true
       
   907 				&& eapol_key_message->get_key_descriptor_type() == eapol_key_descriptor_type_RSNA))
       
   908 		{
       
   909 			if (m_eapol_group_cipher != eapol_RSNA_key_header_c::eapol_RSNA_cipher_none
       
   910 			&& key_data_payloads.get_group_key()->get_is_valid_data() == true)
       
   911 			{
       
   912 				// We do have the expected GTK, save it.
       
   913 				status = m_group_GTK.set_copy_of_buffer(
       
   914 					key_data_payloads.get_group_key());
       
   915 				if (status != eap_status_ok)
       
   916 				{
       
   917 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   918 					return EAP_STATUS_RETURN(m_am_tools, status);
       
   919 				}
       
   920 
       
   921 				m_group_GTK_ID = key_data_payloads.get_group_key_id();
       
   922 				m_group_GTK_Tx_bit = key_data_payloads.get_group_key_tx();
       
   923 
       
   924 				*group_key_received = true;
       
   925 			}
       
   926 			else if (m_eapol_group_cipher != eapol_RSNA_key_header_c::eapol_RSNA_cipher_none
       
   927 				&& key_data_payloads.get_group_key()->get_is_valid_data() == false
       
   928 				&& eapol_key_message->get_key_descriptor_type() == eapol_key_descriptor_type_RSNA)
       
   929 			{
       
   930 				// ERROR, required GTK is missing.
       
   931 				EAP_TRACE_ERROR(
       
   932 					m_am_tools, 
       
   933 					TRACE_FLAGS_EAPOL_KEY_DATA_ERROR, 
       
   934 					(EAPL("ERROR: EAPOL_KEY: eapol_key_state_c::process_4_way_handshake_message_3_payloads_a(): ")
       
   935 					 EAPL("Required GTK is missing.\n")));
       
   936 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   937 				return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
   938 			}
       
   939 			else if (m_eapol_group_cipher == eapol_RSNA_key_header_c::eapol_RSNA_cipher_none
       
   940 				&& key_data_payloads.get_group_key()->get_is_valid_data() == true)
       
   941 			{
       
   942 				// ERROR, unexpected GTK received.
       
   943 				EAP_TRACE_ERROR(
       
   944 					m_am_tools, 
       
   945 					TRACE_FLAGS_EAPOL_KEY_DATA_ERROR, 
       
   946 					(EAPL("ERROR: EAPOL_KEY: eapol_key_state_c::process_4_way_handshake_message_3_payloads_a(): ")
       
   947 					 EAPL("Unexpected GTK received.\n")));
       
   948 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   949 				return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
   950 			}
       
   951 		}
       
   952 	}
       
   953 
       
   954 
       
   955 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   956 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   957 }
       
   958 
       
   959 //--------------------------------------------------
       
   960 
       
   961 //
       
   962 eap_status_e eapol_key_state_c::process_4_way_handshake_message_3_payloads_b(
       
   963 	const eap_am_network_id_c * const receive_network_id,
       
   964 	eapol_RSNA_key_header_c * const eapol_key_message,
       
   965 	const u32_t /* packet_length */,
       
   966 	const bool group_key_received)
       
   967 {
       
   968 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   969 	EAP_UNREFERENCED_PARAMETER(receive_network_id);
       
   970 
       
   971 	eap_status_e status = eap_status_process_general_error;
       
   972 
       
   973 	// Only client (supplicant) could receive 4-Way Handshake message 3.
       
   974 	EAP_ASSERT_ALWAYS(m_is_client == true);
       
   975 
       
   976 	{
       
   977 		eap_buf_chain_wr_c sent_packet(
       
   978 			eap_write_buffer,
       
   979 			m_am_tools);
       
   980 
       
   981 		if (sent_packet.get_is_valid() == false)
       
   982 		{
       
   983 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   984 		}
       
   985 
       
   986 		u32_t send_data_length = 0ul;
       
   987 		u32_t send_buffer_length = 0ul;
       
   988 
       
   989 		status = create_4_way_handshake_message_4(
       
   990 			&sent_packet,
       
   991 			m_eapol_header_offset,
       
   992 			&send_data_length,
       
   993 			&send_buffer_length,
       
   994 			eapol_key_message->get_key_replay_counter(),
       
   995 			eapol_key_message->get_key_information_secure(),
       
   996 			eapol_key_message->get_eapol_protocol_version(),
       
   997 			eapol_key_message->get_key_descriptor_type());
       
   998 		if (status != eap_status_ok)
       
   999 		{
       
  1000 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1001 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1002 		}
       
  1003 
       
  1004 		status = packet_send(
       
  1005 			&m_send_network_id,
       
  1006 			&sent_packet,
       
  1007 			m_eapol_header_offset,
       
  1008 			send_data_length,
       
  1009 			send_buffer_length);
       
  1010 		if (status != eap_status_ok)
       
  1011 		{
       
  1012 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1013 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1014 		}
       
  1015 	}
       
  1016 
       
  1017 	if (get_eapol_key_state() == eapol_key_state_wait_4_way_handshake_message_3)
       
  1018 	{
       
  1019 		// We set the keys only on the first received 4-Way Handshake Message 3.
       
  1020 
       
  1021 		status = packet_data_session_key(
       
  1022 			&m_temporal_TK,
       
  1023 			eapol_key_type_unicast,
       
  1024 			0ul,
       
  1025 			false,
       
  1026 			eapol_key_message->get_key_RSC(),
       
  1027 			eapol_RSNA_key_header_c::EAPOL_RSNA_KEY_RSC_SIZE);
       
  1028 		if (status != eap_status_ok)
       
  1029 		{
       
  1030 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1031 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1032 		}
       
  1033 
       
  1034 
       
  1035 		{
       
  1036 			// This notification to eapol_core_c object.
       
  1037 			// 4-Way Handshake finished successfully.
       
  1038 			eap_state_notification_c * notification = new eap_state_notification_c(
       
  1039 				m_am_tools,
       
  1040 				&m_send_network_id,
       
  1041 				m_is_client,
       
  1042 				eap_state_notification_generic,
       
  1043 				eap_protocol_layer_eapol_key,
       
  1044 				eapol_key_handshake_type_4_way_handshake,
       
  1045 				get_eapol_key_state(),
       
  1046 				eapol_key_state_4_way_handshake_successfull,
       
  1047 				0ul,
       
  1048 				false);
       
  1049 			if (notification == 0)
       
  1050 			{
       
  1051 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1052 				return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1053 			}
       
  1054 			m_key_state_partner->state_notification(notification);
       
  1055 
       
  1056 			delete notification;
       
  1057 		}
       
  1058 
       
  1059 
       
  1060 		if ((get_is_RSNA() == true
       
  1061 				&& m_eapol_group_cipher != eapol_RSNA_key_header_c::eapol_RSNA_cipher_none)
       
  1062 			|| (get_is_WPXM() == true
       
  1063 					&& eapol_key_message->get_key_descriptor_type() == eapol_key_descriptor_type_RSNA))
       
  1064 		{
       
  1065 			if (group_key_received == true)
       
  1066 			{
       
  1067 				// We do have the expected GTK, pass it to lower layers.
       
  1068 				status = packet_data_session_key(
       
  1069 					&m_group_GTK,
       
  1070 					eapol_key_type_broadcast,
       
  1071 					m_group_GTK_ID,
       
  1072 					m_group_GTK_Tx_bit,
       
  1073 					eapol_key_message->get_key_RSC(),
       
  1074 					eapol_RSNA_key_header_c::EAPOL_RSNA_KEY_RSC_SIZE);
       
  1075 				if (status != eap_status_ok)
       
  1076 				{
       
  1077 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1078 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1079 				}
       
  1080 
       
  1081 				{
       
  1082 					// This notification to eapol_core_c object.
       
  1083 					// Group Key Handshake finished successfully.
       
  1084 					eap_state_notification_c * notification = new eap_state_notification_c(
       
  1085 						m_am_tools,
       
  1086 						&m_send_network_id,
       
  1087 						m_is_client,
       
  1088 						eap_state_notification_generic,
       
  1089 						eap_protocol_layer_eapol_key,
       
  1090 						eapol_key_handshake_type_group_key_handshake,
       
  1091 						get_eapol_key_state(),
       
  1092 						eapol_key_state_group_key_handshake_successfull,
       
  1093 						0ul,
       
  1094 						false);
       
  1095 					if (notification == 0)
       
  1096 					{
       
  1097 						EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1098 						return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1099 					}
       
  1100 					m_key_state_partner->state_notification(notification);
       
  1101 
       
  1102 					delete notification;
       
  1103 				}
       
  1104 			}
       
  1105 			else
       
  1106 			{
       
  1107 				// ERROR, no GTK received.
       
  1108 				EAP_TRACE_ERROR(
       
  1109 					m_am_tools, 
       
  1110 					TRACE_FLAGS_EAPOL_KEY_DATA_ERROR, 
       
  1111 					(EAPL("ERROR: EAPOL_KEY: eapol_key_state_c::process_4_way_handshake_message_3_payloads_b(): ")
       
  1112 					 EAPL("No GTK received.\n")));
       
  1113 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1114 				return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1115 			}
       
  1116 		}
       
  1117 	}
       
  1118 	else
       
  1119 	{
       
  1120 		eapol_key_state_string_c state_string;
       
  1121 
       
  1122 		EAP_TRACE_DEBUG(
       
  1123 			m_am_tools, 
       
  1124 			TRACE_FLAGS_DEFAULT, 
       
  1125 			(EAPL("WARNING: EAPOL_KEY: eapol_key_state_c::process_4_way_handshake_message_3_payloads_b(): ")
       
  1126 			 EAPL("No keys are set on state %d=%s.\n"),
       
  1127 			 get_eapol_key_state(),
       
  1128 			 state_string.get_eapol_key_state_string(get_eapol_key_state())));
       
  1129 	}
       
  1130 
       
  1131 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1132 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1133 }
       
  1134 
       
  1135 //--------------------------------------------------
       
  1136 
       
  1137 //
       
  1138 eap_status_e eapol_key_state_c::process_4_way_handshake_message_3(
       
  1139 	const eap_am_network_id_c * const receive_network_id,
       
  1140 	eapol_RSNA_key_header_c * const eapol_key_message,
       
  1141 	const u32_t packet_length)
       
  1142 {
       
  1143 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1144 	EAP_UNREFERENCED_PARAMETER(receive_network_id);
       
  1145 
       
  1146 	eap_status_e status = eap_status_process_general_error;
       
  1147 
       
  1148 	eapol_key_state_string_c state_string;
       
  1149 
       
  1150 	EAP_TRACE_DEBUG(
       
  1151 		m_am_tools, 
       
  1152 		TRACE_FLAGS_DEFAULT, 
       
  1153 		(EAPL("EAPOL_KEY: %s: eapol_key_state_c::process_4_way_handshake_message_3(): eapol_key_descriptor_type = %s = 0x%02x\n"),
       
  1154 		(m_is_client == true ? "client": "server"),
       
  1155 		state_string.get_eapol_key_descriptor_type_string(eapol_key_message->get_key_descriptor_type()),
       
  1156 		eapol_key_message->get_key_descriptor_type()));
       
  1157 
       
  1158 	EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eapol_key_state_c::process_4_way_handshake_message_3()");
       
  1159 
       
  1160 	// Only client (supplicant) could receive 4-Way Handshake message 3.
       
  1161 	EAP_ASSERT_ALWAYS(m_is_client == true);
       
  1162 
       
  1163 	// NOTE, this could be re-transmitted message.
       
  1164 	// Authenticator did not get the 4-Way Handshake message 4.
       
  1165 	if (m_eapol_key_handshake_type != eapol_key_handshake_type_4_way_handshake
       
  1166 		&& m_eapol_key_handshake_type != eapol_key_handshake_type_group_key_handshake)
       
  1167 	{
       
  1168 		eapol_key_state_string_c state_string;
       
  1169 		EAP_TRACE_ERROR(
       
  1170 			m_am_tools,
       
  1171 			TRACE_FLAGS_DEFAULT,
       
  1172 			(EAPL("WARNING: EAPOL_KEY: %s: process_4_way_handshake_message_3(): wrong handshake type %s\n"),
       
  1173 			(m_is_client == true ? "client": "server"),
       
  1174 			state_string.get_eapol_key_handshake_type_string(m_eapol_key_handshake_type)));
       
  1175 
       
  1176 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1177 		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
       
  1178 	}
       
  1179 
       
  1180 	if (get_eapol_key_state() != eapol_key_state_wait_4_way_handshake_message_3
       
  1181 		&& get_eapol_key_state() != eapol_key_state_4_way_handshake_successfull
       
  1182 #if defined(EAP_USE_WPXM)
       
  1183 		&& get_eapol_key_state() != eapol_key_state_wpxm_reassociation_finished_successfull
       
  1184 #endif //#if defined(EAP_USE_WPXM)
       
  1185 		)
       
  1186 	{
       
  1187 		EAP_TRACE_ERROR(
       
  1188 			m_am_tools,
       
  1189 			TRACE_FLAGS_DEFAULT,
       
  1190 			(EAPL("WARNING: EAPOL_KEY: %s: process_4_way_handshake_message_3(): wrong state %s\n"),
       
  1191 			(m_is_client == true ? "client": "server"),
       
  1192 			state_string.get_eapol_key_state_string(get_eapol_key_state())));
       
  1193 
       
  1194 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1195 		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
       
  1196 	}
       
  1197 
       
  1198 	// We do have the expected ANonce, compare it.
       
  1199 	if (m_am_tools->memcmp(
       
  1200 			get_ANonce()->get_data(
       
  1201 				get_ANonce()->get_data_length()),
       
  1202 			eapol_key_message->get_key_NONCE(),
       
  1203 			get_ANonce()->get_data_length()) != 0)
       
  1204 	{
       
  1205 		// Illegal ANonce.
       
  1206 		EAP_TRACE_ERROR(
       
  1207 			m_am_tools, 
       
  1208 			TRACE_FLAGS_EAPOL_KEY_DATA_ERROR, 
       
  1209 			(EAPL("ERROR: EAPOL_KEY: eapol_key_state_c::process_4_way_handshake_message_3(): ")
       
  1210 			 EAPL("Not correct ANonce received.\n")));
       
  1211 		EAP_TRACE_DATA_DEBUG(
       
  1212 			m_am_tools,
       
  1213 			TRACE_FLAGS_EAPOL_KEY_DATA_ERROR,
       
  1214 			(EAPL("Local ANonce   "),
       
  1215 			get_ANonce()->get_data(
       
  1216 				get_ANonce()->get_data_length()),
       
  1217 			get_ANonce()->get_data_length()));
       
  1218 		EAP_TRACE_DATA_DEBUG(
       
  1219 			m_am_tools,
       
  1220 			TRACE_FLAGS_EAPOL_KEY_DATA_ERROR,
       
  1221 			(EAPL("Received ANonce"),
       
  1222 			eapol_key_message->get_key_NONCE(),
       
  1223 			get_ANonce()->get_data_length()));
       
  1224 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1225 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1226 	}
       
  1227 
       
  1228 	u32_t received_data_length = eapol_key_message->get_key_data_length();
       
  1229 
       
  1230 	if (received_data_length == 0u)
       
  1231 	{
       
  1232 		// No payload in this packet.
       
  1233 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  1234 	}
       
  1235 
       
  1236 	if (received_data_length > eapol_key_message->get_header_buffer_length()
       
  1237 			|| eapol_key_message->get_key_data(received_data_length) == 0)
       
  1238 	{
       
  1239 		// Not enough payload in this packet.
       
  1240 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  1241 	}
       
  1242 
       
  1243 	if (m_eapol_pairwise_cipher
       
  1244 			 == eapol_RSNA_key_header_c::eapol_RSNA_cipher_TKIP)
       
  1245 	{
       
  1246 		status = m_EAPOL_key_IV.set_copy_of_buffer(
       
  1247 			eapol_key_message->get_EAPOL_key_IV(),
       
  1248 			eapol_RSNA_key_header_c::EAPOL_RSNA_EAPOL_KEY_IV_SIZE);
       
  1249 		if (status != eap_status_ok)
       
  1250 		{
       
  1251 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1252 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1253 		}
       
  1254 	}
       
  1255 	else
       
  1256 	{
       
  1257 		if (m_allow_non_zero_mic_and_reserved_in_message_1 == false)
       
  1258 		{
       
  1259 			status = verify_field_is_zero(
       
  1260 				eapol_key_message->get_EAPOL_key_IV(),
       
  1261 				eapol_RSNA_key_header_c::EAPOL_RSNA_EAPOL_KEY_IV_SIZE);
       
  1262 			if (status != eap_status_ok)
       
  1263 			{
       
  1264 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1265 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1266 			}
       
  1267 		}
       
  1268 	}
       
  1269 
       
  1270 	status = verify_field_is_zero(
       
  1271 		eapol_key_message->get_key_STA_MAC_address(),
       
  1272 		eapol_RSNA_key_header_c::EAPOL_RSNA_KEY_STA_MAC_ADDRESS_SIZE);
       
  1273 	if (status != eap_status_ok)
       
  1274 	{
       
  1275 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1276 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1277 	}
       
  1278 
       
  1279 	status = verify_field_is_zero(
       
  1280 		eapol_key_message->get_key_reserved(),
       
  1281 		eapol_RSNA_key_header_c::EAPOL_RSNA_KEY_RESERVED_SIZE);
       
  1282 	if (status != eap_status_ok)
       
  1283 	{
       
  1284 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1285 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1286 	}
       
  1287 
       
  1288 
       
  1289 	status = verify_key_mic(
       
  1290 		eapol_key_message,
       
  1291 		&m_confirmation_KCK);
       
  1292 	if (status != eap_status_ok)
       
  1293 	{
       
  1294 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1295 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1296 	}
       
  1297 
       
  1298 
       
  1299 	if ((get_is_RSNA() == true
       
  1300 			|| get_is_WPXM() == true)
       
  1301 		&& eapol_key_message->get_key_information_encrypted_key_data() == true)
       
  1302 	{
       
  1303 		status = decrypt_key_data(eapol_key_message);
       
  1304 		if (status != eap_status_ok)
       
  1305 		{
       
  1306 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1307 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1308 		}
       
  1309 
       
  1310 		// Decryption may change data length.
       
  1311 		received_data_length = eapol_key_message->get_key_data_length();
       
  1312 
       
  1313 		if (received_data_length > eapol_key_message->get_header_buffer_length()
       
  1314 			|| eapol_key_message->get_key_data(received_data_length) == 0)
       
  1315 		{
       
  1316 			// Not enough payload in this packet.
       
  1317 			return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  1318 		}
       
  1319 	}
       
  1320 
       
  1321 
       
  1322 	// This split of process_4_way_handshake_message_3_payloads() function
       
  1323 	// is fix internal compiler error.
       
  1324 	bool group_key_received(false);
       
  1325 
       
  1326 	status = process_4_way_handshake_message_3_payloads_a(
       
  1327 		receive_network_id,
       
  1328 		eapol_key_message,
       
  1329 		packet_length,
       
  1330 		&group_key_received);
       
  1331 	if (status != eap_status_ok)
       
  1332 	{
       
  1333 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1334 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1335 	}
       
  1336 
       
  1337 	status = process_4_way_handshake_message_3_payloads_b(
       
  1338 		receive_network_id,
       
  1339 		eapol_key_message,
       
  1340 		packet_length,
       
  1341 		group_key_received);
       
  1342 	if (status != eap_status_ok)
       
  1343 	{
       
  1344 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1345 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1346 	}
       
  1347 
       
  1348 
       
  1349 	if (get_eapol_key_state() == eapol_key_state_wait_4_way_handshake_message_3)
       
  1350 	{
       
  1351 		if (get_is_RSNA() == true
       
  1352 			|| (get_is_WPXM() == true
       
  1353 					&& eapol_key_message->get_key_descriptor_type() == eapol_key_descriptor_type_RSNA))
       
  1354 		{
       
  1355 			if (m_indicate_pmkid_to_lower_layer == true)
       
  1356 			{
       
  1357 				// In some platforms lower layers uses PMKID.
       
  1358 				status = create_PMKID();
       
  1359 				if (status != eap_status_ok)
       
  1360 				{
       
  1361 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1362 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1363 				}
       
  1364 
       
  1365 				status = packet_data_session_key(
       
  1366 					&m_PMKID,
       
  1367 					eapol_key_type_pmkid,
       
  1368 					0ul,
       
  1369 					false,
       
  1370 					0,
       
  1371 					0ul);
       
  1372 				if (status != eap_status_ok)
       
  1373 				{
       
  1374 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1375 					return EAP_STATUS_RETURN(m_am_tools, status);
       
  1376 				}
       
  1377 			}
       
  1378 
       
  1379 
       
  1380 			{
       
  1381 				// This notification to eapol_core_c object.
       
  1382 				// 802.11i authentication finished successfully.
       
  1383 				eap_state_notification_c * notification = new eap_state_notification_c(
       
  1384 					m_am_tools,
       
  1385 					&m_send_network_id,
       
  1386 					m_is_client,
       
  1387 					eap_state_notification_generic,
       
  1388 					eap_protocol_layer_eapol_key,
       
  1389 					eapol_key_handshake_type_802_11i_handshake,
       
  1390 					get_eapol_key_state(),
       
  1391 					eapol_key_state_802_11i_authentication_finished_successfull,
       
  1392 					0ul,
       
  1393 					false);
       
  1394 				if (notification == 0)
       
  1395 				{
       
  1396 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1397 					return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1398 				}
       
  1399 				m_key_state_partner->state_notification(notification);
       
  1400 
       
  1401 				delete notification;
       
  1402 			}
       
  1403 
       
  1404 			cancel_handshake_timeout();
       
  1405 		}
       
  1406 		else
       
  1407 		{
       
  1408 			// Note the WPA version always does separate Group Key Handshake.
       
  1409 			// Authentication is successfull after the Group Key Handshake
       
  1410 			// Finishes successfully.
       
  1411 		}
       
  1412 
       
  1413 		set_eapol_key_state(eapol_key_state_4_way_handshake_successfull);
       
  1414 
       
  1415 		// A new Group Key Handshake can happen at any time.
       
  1416 		m_eapol_key_handshake_type = eapol_key_handshake_type_group_key_handshake;
       
  1417 
       
  1418 		set_key_reply_counter(eapol_key_message->get_key_replay_counter());
       
  1419 
       
  1420 
       
  1421 		EAP_TRACE_ALWAYS(
       
  1422 			m_am_tools,
       
  1423 			TRACE_FLAGS_DEFAULT,
       
  1424 			(EAPL("EAPOL_KEY: %s: 4-Way Handshake SUCCESS\n"),
       
  1425 			(m_is_client == true ? "client": "server")));
       
  1426 	}
       
  1427 	else
       
  1428 	{
       
  1429 		eapol_key_state_string_c state_string;
       
  1430 
       
  1431 		EAP_TRACE_DEBUG(
       
  1432 			m_am_tools, 
       
  1433 			TRACE_FLAGS_DEFAULT, 
       
  1434 			(EAPL("WARNING: EAPOL_KEY: eapol_key_state_c::process_4_way_handshake_message_3(): ")
       
  1435 			 EAPL("No keys are set on state %d=%s.\n"),
       
  1436 			 get_eapol_key_state(),
       
  1437 			 state_string.get_eapol_key_state_string(get_eapol_key_state())));
       
  1438 	}
       
  1439 
       
  1440 
       
  1441 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1442 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1443 }
       
  1444 
       
  1445 //--------------------------------------------------
       
  1446 
       
  1447 //
       
  1448 eap_status_e eapol_key_state_c::create_eapol_key_handshake_message_0(
       
  1449 	const bool true_when_4_way_handshake, ///< With false initiates Group Key Handshake.
       
  1450 	eap_buf_chain_wr_c * const sent_packet,
       
  1451 	const u32_t eapol_header_offset,
       
  1452 	u32_t * const data_length,
       
  1453 	u32_t * const buffer_length,
       
  1454 	const u64_t received_key_replay_counter,
       
  1455 	const eapol_protocol_version_e received_eapol_version)
       
  1456 {
       
  1457 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1458 	eap_status_e status = eap_status_process_general_error;
       
  1459 
       
  1460 	EAP_TRACE_DEBUG(
       
  1461 		m_am_tools, 
       
  1462 		TRACE_FLAGS_DEFAULT, 
       
  1463 		(EAPL("EAPOL_KEY: %s: eapol_key_state_c::create_eapol_key_handshake_message_0()\n"),
       
  1464 		(m_is_client == true ? "client": "server")));
       
  1465 
       
  1466 	// Only client (Supplicant) could create 4-Way or Group Key Handshake message 0.
       
  1467 	EAP_ASSERT_ALWAYS(m_is_client == true);
       
  1468 
       
  1469 	u32_t eapol_key_data_length
       
  1470 		= eapol_RSNA_key_header_c::get_header_length();
       
  1471 
       
  1472 	*buffer_length
       
  1473 		= eapol_header_offset
       
  1474 		+ eapol_key_data_length;
       
  1475 
       
  1476 	status = sent_packet->set_buffer_length(
       
  1477 		*buffer_length);
       
  1478 	if (status != eap_status_ok)
       
  1479 	{
       
  1480 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1481 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1482 	}
       
  1483 	sent_packet->set_data_length(
       
  1484 		sent_packet->get_buffer_length());
       
  1485 
       
  1486 	eapol_RSNA_key_header_c eapol_key_message(
       
  1487 		m_am_tools,
       
  1488 		get_is_RSNA(),
       
  1489 		get_is_WPXM(),
       
  1490 		sent_packet->get_data_offset(eapol_header_offset, eapol_key_data_length),
       
  1491 		sent_packet->get_data_length());
       
  1492 
       
  1493 	if (eapol_key_message.get_is_valid() == false)
       
  1494 	{
       
  1495 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1496 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1497 	}
       
  1498 
       
  1499 
       
  1500 	status = eapol_key_message.reset_header(
       
  1501 		0ul,
       
  1502 		m_authentication_type,
       
  1503 		m_eapol_pairwise_cipher,
       
  1504 		received_key_replay_counter,
       
  1505 		true_when_4_way_handshake,
       
  1506 		false, // Install bit is NOT set.
       
  1507 		false, // Key Ack bit is NOT set.
       
  1508 		true, // Key MIC bit is set on
       
  1509 		false, // Secure bit is NOT set.
       
  1510 		false, // Error bit is NOT set.
       
  1511 		true, // Request bit is set on.
       
  1512 		false, // STAKey bit is NOT set.
       
  1513 		false, // Encrypted Key Data bit is NOT set.
       
  1514 		received_eapol_version,
       
  1515 #if defined(EAP_USE_WPXM)
       
  1516 		m_EAPOL_WPXM_key_descriptor_type
       
  1517 #else
       
  1518 		eapol_key_descriptor_type_RSNA
       
  1519 #endif //#if defined(EAP_USE_WPXM)
       
  1520 		);
       
  1521 	if (status != eap_status_ok)
       
  1522 	{
       
  1523 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1524 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1525 	}
       
  1526 
       
  1527 	status = eapol_key_message.set_key_data_length(0ul);
       
  1528 	if (status != eap_status_ok)
       
  1529 	{
       
  1530 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1531 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1532 	}
       
  1533 
       
  1534 	*data_length
       
  1535 		= eapol_key_message.get_header_length()
       
  1536 		+ eapol_key_message.get_key_data_length();
       
  1537 
       
  1538 	status = eapol_key_message.set_eapol_packet_body_length(
       
  1539 		static_cast<u16_t>(*data_length - eapol_header_base_c::get_header_length()));
       
  1540 	if (status != eap_status_ok)
       
  1541 	{
       
  1542 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1543 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1544 	}
       
  1545 
       
  1546 	sent_packet->set_data_length(
       
  1547 		eapol_header_offset + *data_length);
       
  1548 
       
  1549 	if (true_when_4_way_handshake == true)
       
  1550 	{
       
  1551 		TRACE_EAPOL_KEY_MESSAGE(
       
  1552 			"Send 4-Way Handshake Message 0",
       
  1553 			&eapol_key_message);
       
  1554 	}
       
  1555 	else
       
  1556 	{
       
  1557 		status = create_key_mic(
       
  1558 			&eapol_key_message,
       
  1559 			&m_confirmation_KCK);
       
  1560 		if (status != eap_status_ok)
       
  1561 		{
       
  1562 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1563 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1564 		}
       
  1565 
       
  1566 		TRACE_EAPOL_KEY_MESSAGE(
       
  1567 			"Send Group Key Handshake Message 0",
       
  1568 			&eapol_key_message);
       
  1569 	}
       
  1570 
       
  1571 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1572 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1573 }
       
  1574 
       
  1575 //--------------------------------------------------
       
  1576 
       
  1577 //
       
  1578 eap_status_e eapol_key_state_c::create_group_key_handshake_message_2(
       
  1579 	eap_buf_chain_wr_c * const sent_packet,
       
  1580 	const u32_t eapol_header_offset,
       
  1581 	u32_t * const data_length,
       
  1582 	u32_t * const buffer_length,
       
  1583 	const u64_t received_key_replay_counter,
       
  1584 	const eapol_protocol_version_e received_eapol_version,
       
  1585 	const eapol_key_descriptor_type_e received_key_descriptor_type)
       
  1586 {
       
  1587 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1588 	eap_status_e status = eap_status_process_general_error;
       
  1589 
       
  1590 	EAP_TRACE_DEBUG(
       
  1591 		m_am_tools, 
       
  1592 		TRACE_FLAGS_DEFAULT, 
       
  1593 		(EAPL("EAPOL_KEY: %s: eapol_key_state_c::create_group_key_handshake_message_2()\n"),
       
  1594 		(m_is_client == true ? "client": "server")));
       
  1595 
       
  1596 	// Only client (Supplicant) could create Group Key Handshake message 2.
       
  1597 	EAP_ASSERT_ALWAYS(m_is_client == true);
       
  1598 
       
  1599 	if (sent_packet == 0
       
  1600 		|| sent_packet->get_is_valid() == false)
       
  1601 	{
       
  1602 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1603 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1604 	}
       
  1605 
       
  1606 	u32_t eapol_key_data_length
       
  1607 		= eapol_RSNA_key_header_c::get_header_length();
       
  1608 
       
  1609 	*buffer_length
       
  1610 		= eapol_header_offset
       
  1611 		+ eapol_key_data_length;
       
  1612 
       
  1613 	status = sent_packet->set_buffer_length(
       
  1614 		*buffer_length);
       
  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 	sent_packet->set_data_length(
       
  1621 		sent_packet->get_buffer_length());
       
  1622 
       
  1623 	eapol_RSNA_key_header_c eapol_key_message(
       
  1624 		m_am_tools,
       
  1625 		get_is_RSNA(),
       
  1626 		get_is_WPXM(),
       
  1627 		sent_packet->get_data_offset(eapol_header_offset, eapol_key_data_length),
       
  1628 		sent_packet->get_data_length());
       
  1629 
       
  1630 	if (eapol_key_message.get_is_valid() == false)
       
  1631 	{
       
  1632 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1633 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1634 	}
       
  1635 
       
  1636 
       
  1637 	status = eapol_key_message.reset_header(
       
  1638 		m_group_GTK_ID,
       
  1639 		m_authentication_type,
       
  1640 		m_eapol_pairwise_cipher,
       
  1641 		received_key_replay_counter,
       
  1642 		false, // Pairwise key type bit NOT set.
       
  1643 		false, // Install bit is NOT set.
       
  1644 		false, // Key Ack bit is NOT set.
       
  1645 		true, // Key MIC bit is on.
       
  1646 		true, // Secure bit is on.
       
  1647 		false, // Error bit is NOT set.
       
  1648 		false, // Request bit is NOT set.
       
  1649 		false, // STAKey bit is NOT set.
       
  1650 		false, // Encrypted Key Data bit is NOT set.
       
  1651 		received_eapol_version,
       
  1652 		received_key_descriptor_type);
       
  1653 	if (status != eap_status_ok)
       
  1654 	{
       
  1655 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1656 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1657 	}
       
  1658 
       
  1659 	status = eapol_key_message.set_key_data_length(0ul);
       
  1660 	if (status != eap_status_ok)
       
  1661 	{
       
  1662 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1663 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1664 	}
       
  1665 
       
  1666 	*data_length
       
  1667 		= eapol_key_message.get_header_length()
       
  1668 		+ eapol_key_message.get_key_data_length();
       
  1669 
       
  1670 	status = eapol_key_message.set_eapol_packet_body_length(
       
  1671 		static_cast<u16_t>(*data_length - eapol_header_base_c::get_header_length()));
       
  1672 	if (status != eap_status_ok)
       
  1673 	{
       
  1674 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1675 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1676 	}
       
  1677 
       
  1678 	status = create_key_mic(
       
  1679 		&eapol_key_message,
       
  1680 		&m_confirmation_KCK);
       
  1681 	if (status != eap_status_ok)
       
  1682 	{
       
  1683 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1684 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1685 	}
       
  1686 
       
  1687 #if defined(USE_EAPOL_KEY_TEST_FAILURES)
       
  1688 	if (m_create_key_failure == eapol_key_state_4_way_handshake_successfull)
       
  1689 	{
       
  1690 		m_create_key_failure = eapol_key_state_group_key_handshake_successfull;
       
  1691 
       
  1692 		status = eapol_key_message.zero_key_MIC(m_am_tools);
       
  1693 		if (status != eap_status_ok)
       
  1694 		{
       
  1695 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1696 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1697 		}
       
  1698 
       
  1699 		EAP_TRACE_DEBUG(
       
  1700 			m_am_tools, 
       
  1701 			TRACE_FLAGS_DEFAULT, 
       
  1702 			(EAPL("WARNING: EAPOL_KEY: %s: error generated in eapol_key_state_c::create_group_key_handshake_message_2()\n"),
       
  1703 			 (m_is_client == true ? "client": "server")));
       
  1704 	}
       
  1705 #endif //#if defined(USE_EAPOL_KEY_TEST_FAILURES)
       
  1706 
       
  1707 	sent_packet->set_data_length(
       
  1708 		eapol_header_offset + *data_length);
       
  1709 
       
  1710 	TRACE_EAPOL_KEY_MESSAGE(
       
  1711 		"Send Group Key Handshake Message 2",
       
  1712 		&eapol_key_message);
       
  1713 
       
  1714 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1715 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1716 }
       
  1717 
       
  1718 //--------------------------------------------------
       
  1719 
       
  1720 //
       
  1721 eap_status_e eapol_key_state_c::process_group_key_handshake_message_1(
       
  1722 	const eap_am_network_id_c * const receive_network_id,
       
  1723 	eapol_RSNA_key_header_c * const eapol_key_message,
       
  1724 	const u32_t packet_length)
       
  1725 {
       
  1726 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1727 	EAP_UNREFERENCED_PARAMETER(receive_network_id);
       
  1728 
       
  1729 	eap_status_e status = eap_status_process_general_error;
       
  1730 
       
  1731 	EAP_TRACE_DEBUG(
       
  1732 		m_am_tools, 
       
  1733 		TRACE_FLAGS_DEFAULT, 
       
  1734 		(EAPL("EAPOL_KEY: %s: eapol_key_state_c::process_group_key_handshake_message_1()\n"),
       
  1735 		(m_is_client == true ? "client": "server")));
       
  1736 
       
  1737 	// Only client (supplicant) could receive Group Key Handshake message 1.
       
  1738 	EAP_ASSERT_ALWAYS(m_is_client == true);
       
  1739 
       
  1740 	if (get_eapol_key_state() == eapol_key_state_4_way_handshake_successfull
       
  1741 		|| get_eapol_key_state() == eapol_key_state_group_key_handshake_successfull
       
  1742 #if defined(EAP_USE_WPXM)
       
  1743 		|| get_eapol_key_state() == eapol_key_state_wpxm_reassociation_finished_successfull
       
  1744 #endif //#if defined(EAP_USE_WPXM)
       
  1745 		)
       
  1746 	{
       
  1747 		// At this point we know the 4-Way handshake or Group key handshake was successfull.
       
  1748 		m_eapol_key_handshake_type = eapol_key_handshake_type_group_key_handshake;
       
  1749 	}
       
  1750 
       
  1751 	if (m_eapol_key_handshake_type != eapol_key_handshake_type_none
       
  1752 		&& m_eapol_key_handshake_type != eapol_key_handshake_type_group_key_handshake)
       
  1753 	{
       
  1754 		eapol_key_state_string_c state_string;
       
  1755 		EAP_TRACE_ERROR(
       
  1756 			m_am_tools,
       
  1757 			TRACE_FLAGS_DEFAULT,
       
  1758 			(EAPL("WARNING: EAPOL_KEY: %s: start_group_key_handshake(): wrong handshake type %s\n"),
       
  1759 			(m_is_client == true ? "client": "server"),
       
  1760 			state_string.get_eapol_key_handshake_type_string(m_eapol_key_handshake_type)));
       
  1761 
       
  1762 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1763 		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
       
  1764 	}
       
  1765 
       
  1766 	if (get_eapol_key_state() != eapol_key_state_4_way_handshake_successfull
       
  1767 		&& get_eapol_key_state() != eapol_key_state_group_key_handshake_successfull
       
  1768 		&& get_eapol_key_state() != eapol_key_state_preauthenticated
       
  1769 #if defined(EAP_USE_WPXM)
       
  1770 		&& get_eapol_key_state() != eapol_key_state_wpxm_reassociation_finished_successfull
       
  1771 #endif //#if defined(EAP_USE_WPXM)
       
  1772 		)
       
  1773 	{
       
  1774 		eapol_key_state_string_c state_string;
       
  1775 		EAP_TRACE_ERROR(
       
  1776 			m_am_tools,
       
  1777 			TRACE_FLAGS_DEFAULT,
       
  1778 			(EAPL("WARNING: EAPOL_KEY: %s: process_group_key_handshake_message_1(): wrong state %s\n"),
       
  1779 			(m_is_client == true ? "client": "server"),
       
  1780 			state_string.get_eapol_key_state_string(get_eapol_key_state())));
       
  1781 
       
  1782 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1783 		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
       
  1784 	}
       
  1785 
       
  1786 	u32_t received_data_length = eapol_key_message->get_key_data_length();
       
  1787 
       
  1788 	if (received_data_length == 0u)
       
  1789 	{
       
  1790 		// No payload in this packet.
       
  1791 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  1792 	}
       
  1793 
       
  1794 	if (received_data_length > eapol_key_message->get_header_buffer_length()
       
  1795 		|| eapol_key_message->get_key_data(received_data_length) == 0)
       
  1796 	{
       
  1797 		// Not enough payload in this packet.
       
  1798 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  1799 	}
       
  1800 
       
  1801 
       
  1802 	if (get_is_RSNA() == true)
       
  1803 	{
       
  1804 		if (m_allow_non_zero_mic_and_reserved_in_message_1 == false)
       
  1805 		{
       
  1806 			status = verify_field_is_zero(
       
  1807 				eapol_key_message->get_key_NONCE(),
       
  1808 				eapol_RSNA_key_header_c::EAPOL_RSNA_KEY_NONCE_SIZE);
       
  1809 			if (status != eap_status_ok)
       
  1810 			{
       
  1811 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1812 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1813 			}
       
  1814 		}
       
  1815 	}
       
  1816 	else
       
  1817 	{
       
  1818 		// WPA sends GNonse for debugging purposes.
       
  1819 	}
       
  1820 
       
  1821 
       
  1822 	status = verify_field_is_zero(
       
  1823 		eapol_key_message->get_key_STA_MAC_address(),
       
  1824 		eapol_RSNA_key_header_c::EAPOL_RSNA_KEY_STA_MAC_ADDRESS_SIZE);
       
  1825 	if (status != eap_status_ok)
       
  1826 	{
       
  1827 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1828 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1829 	}
       
  1830 
       
  1831 	status = verify_field_is_zero(
       
  1832 		eapol_key_message->get_key_reserved(),
       
  1833 		eapol_RSNA_key_header_c::EAPOL_RSNA_KEY_RESERVED_SIZE);
       
  1834 	if (status != eap_status_ok)
       
  1835 	{
       
  1836 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1837 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1838 	}
       
  1839 
       
  1840 
       
  1841 	if (m_eapol_group_cipher
       
  1842 			== eapol_RSNA_key_header_c::eapol_RSNA_cipher_CCMP
       
  1843 		|| m_eapol_group_cipher
       
  1844 			== eapol_RSNA_key_header_c::eapol_RSNA_cipher_TKIP
       
  1845 		|| m_eapol_group_cipher
       
  1846 			== eapol_RSNA_key_header_c::eapol_RSNA_cipher_WEP_40
       
  1847 		|| m_eapol_group_cipher
       
  1848 			== eapol_RSNA_key_header_c::eapol_RSNA_cipher_WEP_104)
       
  1849 	{
       
  1850 		status = m_EAPOL_key_IV.set_copy_of_buffer(
       
  1851 			eapol_key_message->get_EAPOL_key_IV(),
       
  1852 			eapol_RSNA_key_header_c::EAPOL_RSNA_EAPOL_KEY_IV_SIZE);
       
  1853 		if (status != eap_status_ok)
       
  1854 		{
       
  1855 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1856 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1857 		}
       
  1858 	}
       
  1859 	else
       
  1860 	{
       
  1861 		status = verify_field_is_zero(
       
  1862 			eapol_key_message->get_EAPOL_key_IV(),
       
  1863 			eapol_RSNA_key_header_c::EAPOL_RSNA_EAPOL_KEY_IV_SIZE);
       
  1864 		if (status != eap_status_ok)
       
  1865 		{
       
  1866 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1867 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1868 		}
       
  1869 	}
       
  1870 
       
  1871 
       
  1872 	status = verify_key_mic(
       
  1873 		eapol_key_message,
       
  1874 		&m_confirmation_KCK);
       
  1875 	if (status != eap_status_ok)
       
  1876 	{
       
  1877 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1878 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1879 	}
       
  1880 
       
  1881 
       
  1882 	status = decrypt_key_data(eapol_key_message);
       
  1883 	if (status != eap_status_ok)
       
  1884 	{
       
  1885 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1886 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1887 	}
       
  1888 
       
  1889 	// Decryption may change data length.
       
  1890 	received_data_length = eapol_key_message->get_key_data_length();
       
  1891 
       
  1892 	if (received_data_length > eapol_key_message->get_header_buffer_length()
       
  1893 		|| eapol_key_message->get_key_data(received_data_length) == 0)
       
  1894 	{
       
  1895 		// Not enough payload in this packet.
       
  1896 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  1897 	}
       
  1898 
       
  1899 
       
  1900 	if (get_is_RSNA() == true)
       
  1901 	{
       
  1902 		eapol_rsna_key_data_payloads_c key_data_payloads(
       
  1903 			m_am_tools,
       
  1904 			get_is_RSNA(),
       
  1905 			get_is_WPXM());
       
  1906 
       
  1907 		eapol_rsna_key_data_header_c key_data(
       
  1908 			m_am_tools,
       
  1909 			get_is_RSNA(),
       
  1910 			get_is_WPXM(),
       
  1911 			eapol_key_message->get_key_data(received_data_length),
       
  1912 			packet_length);
       
  1913 		if (key_data.get_is_valid() == false)
       
  1914 		{
       
  1915 			EAP_TRACE_ERROR(
       
  1916 				m_am_tools, 
       
  1917 				TRACE_FLAGS_EAPOL_KEY_DATA_ERROR, 
       
  1918 				(EAPL("ERROR: EAPOL_KEY: No EAPOL-Key data payloads.\n")));
       
  1919 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1920 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1921 		}
       
  1922 
       
  1923 		status = key_data.check_header();
       
  1924 		if (status != eap_status_ok)
       
  1925 		{
       
  1926 			EAP_TRACE_ERROR(
       
  1927 				m_am_tools, 
       
  1928 				TRACE_FLAGS_EAPOL_KEY_DATA_ERROR, 
       
  1929 				(EAPL("ERROR: EAPOL_KEY: EAPOL-Key data payload header corrupted.\n")));
       
  1930 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1931 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1932 		}
       
  1933 
       
  1934 		status = parse_key_data(
       
  1935 			eapol_key_message->get_key_descriptor_type(),
       
  1936 			&key_data,
       
  1937 			&received_data_length,
       
  1938 			&key_data_payloads,
       
  1939 			eapol_key_state_wait_group_key_handshake_message_1,
       
  1940 			eapol_key_message->get_key_information_key_descriptor_version());
       
  1941 		if (status != eap_status_ok)
       
  1942 		{
       
  1943 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1944 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1945 		}
       
  1946 
       
  1947 		// Check the valid payload is included.
       
  1948 		if (false == key_data_payloads.check_payloads(
       
  1949 			eapol_rsna_key_data_payloads_c::eapol_rsna_key_data_payload_status_must_be, // key_id_and_group_key
       
  1950 			eapol_rsna_key_data_payloads_c::eapol_rsna_key_data_payload_status_must_not_be, // STAKey
       
  1951 			eapol_rsna_key_data_payloads_c::eapol_rsna_key_data_payload_status_must_not_be, // PMKID
       
  1952 			eapol_rsna_key_data_payloads_c::eapol_rsna_key_data_payload_status_must_not_be // One or more RSN IE
       
  1953 			))
       
  1954 		{
       
  1955 			// Not correct EAPOL Key Data payloads are included.
       
  1956 			EAP_TRACE_ERROR(
       
  1957 				m_am_tools, 
       
  1958 				TRACE_FLAGS_EAPOL_KEY_DATA_ERROR, 
       
  1959 				(EAPL("ERROR: EAPOL_KEY: eapol_key_state_c::process_group_key_handshake_message_1(): ")
       
  1960 				 EAPL("Not correct EAPOL Key Data payloads are included.\n")));
       
  1961 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1962 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  1963 		}
       
  1964 
       
  1965 		// We do have the expected GTK, save it.
       
  1966 		status = m_group_GTK.set_copy_of_buffer(
       
  1967 			key_data_payloads.get_group_key());
       
  1968 		if (status != eap_status_ok)
       
  1969 		{
       
  1970 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1971 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1972 		}
       
  1973 
       
  1974 		m_group_GTK_ID = key_data_payloads.get_group_key_id();
       
  1975 		m_group_GTK_Tx_bit = key_data_payloads.get_group_key_tx();
       
  1976 	}
       
  1977 	else
       
  1978 	{
       
  1979 		// WPA
       
  1980 		EAP_UNREFERENCED_PARAMETER(packet_length);
       
  1981 
       
  1982 		// According to Draft 3 the GTK is not encapsulated in any way.
       
  1983 		status = m_group_GTK.set_copy_of_buffer(
       
  1984 			eapol_key_message->get_key_data(received_data_length),
       
  1985 			received_data_length);
       
  1986 		if (status != eap_status_ok)
       
  1987 		{
       
  1988 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1989 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1990 		}
       
  1991 
       
  1992 		m_group_GTK_ID = eapol_key_message->get_key_information_key_index();
       
  1993 	}
       
  1994 
       
  1995 
       
  1996 	eap_buf_chain_wr_c sent_packet(
       
  1997 		eap_write_buffer,
       
  1998 		m_am_tools);
       
  1999 
       
  2000 	if (sent_packet.get_is_valid() == false)
       
  2001 	{
       
  2002 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2003 	}
       
  2004 
       
  2005 	u32_t send_data_length = 0ul;
       
  2006 	u32_t send_buffer_length = 0ul;
       
  2007 
       
  2008 	u64_t reply_counter(eapol_key_message->get_key_replay_counter());
       
  2009 
       
  2010 	if (get_is_WPXM() == true
       
  2011 		&& reply_counter == 0ul)
       
  2012 	{
       
  2013 		// Here we must increase the saved Reply Counter.
       
  2014 		// WPXM seems to work against RSN specification that says
       
  2015 		// every packet must be sent with new Reply Counter.
       
  2016 		// WPXM starts Group Key Handshake with Reply Counter 0 after successfull
       
  2017 		// 4-Way Handshake.
       
  2018 		reply_counter = get_key_reply_counter() + 1ul;
       
  2019 	}
       
  2020 
       
  2021 	status = create_group_key_handshake_message_2(
       
  2022 		&sent_packet,
       
  2023 		m_eapol_header_offset,
       
  2024 		&send_data_length,
       
  2025 		&send_buffer_length,
       
  2026 		reply_counter,
       
  2027 		eapol_key_message->get_eapol_protocol_version(),
       
  2028 		eapol_key_message->get_key_descriptor_type());
       
  2029 	if (status != eap_status_ok)
       
  2030 	{
       
  2031 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2032 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2033 	}
       
  2034 
       
  2035 
       
  2036 	status = packet_send(
       
  2037 		&m_send_network_id,
       
  2038 		&sent_packet,
       
  2039 		m_eapol_header_offset,
       
  2040 		send_data_length,
       
  2041 		send_buffer_length);
       
  2042 	if (status != eap_status_ok)
       
  2043 	{
       
  2044 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2045 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2046 	}
       
  2047 
       
  2048 	if (get_eapol_key_state() == eapol_key_state_4_way_handshake_successfull
       
  2049 		|| get_eapol_key_state() == eapol_key_state_preauthenticated
       
  2050 		|| get_eapol_key_state() == eapol_key_state_group_key_handshake_successfull
       
  2051 #if defined(EAP_USE_WPXM)
       
  2052 		|| get_eapol_key_state() == eapol_key_state_wpxm_reassociation_finished_successfull
       
  2053 #endif //#if defined(EAP_USE_WPXM)
       
  2054 		)
       
  2055 	{
       
  2056 		status = packet_data_session_key(
       
  2057 			&m_group_GTK,
       
  2058 			eapol_key_type_broadcast,
       
  2059 			m_group_GTK_ID,
       
  2060 			m_group_GTK_Tx_bit,
       
  2061 			eapol_key_message->get_key_RSC(),
       
  2062 			eapol_RSNA_key_header_c::EAPOL_RSNA_KEY_RSC_SIZE);
       
  2063 		if (status != eap_status_ok)
       
  2064 		{
       
  2065 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2066 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2067 		}
       
  2068 
       
  2069 		// This is notification to eapol_core_c object.
       
  2070 		// Group Key Handshake finished successfully.
       
  2071 		eap_state_notification_c notification(
       
  2072 			m_am_tools,
       
  2073 			&m_send_network_id,
       
  2074 			m_is_client,
       
  2075 			eap_state_notification_generic,
       
  2076 			eap_protocol_layer_eapol_key,
       
  2077 			eapol_key_handshake_type_group_key_handshake,
       
  2078 			get_eapol_key_state(),
       
  2079 			eapol_key_state_group_key_handshake_successfull,
       
  2080 			0ul,
       
  2081 			false);
       
  2082 		m_key_state_partner->state_notification(&notification);
       
  2083 
       
  2084 		if (get_is_RSNA() == false)
       
  2085 		{
       
  2086 			// Note the WPA version always does separate Group Key Handshake.
       
  2087 			// Authentication is successfull after the Group Key Handshake
       
  2088 			// Finishes successfully.
       
  2089 
       
  2090 			{
       
  2091 				// This notification to eapol_core_c object.
       
  2092 				// WPA authentication finished successfully.
       
  2093 				eap_state_notification_c * notification = new eap_state_notification_c(
       
  2094 					m_am_tools,
       
  2095 					&m_send_network_id,
       
  2096 					m_is_client,
       
  2097 					eap_state_notification_generic,
       
  2098 					eap_protocol_layer_eapol_key,
       
  2099 					eapol_key_handshake_type_802_11i_handshake,
       
  2100 					get_eapol_key_state(),
       
  2101 					eapol_key_state_802_11i_authentication_finished_successfull,
       
  2102 					0ul,
       
  2103 					false);
       
  2104 				if (notification == 0)
       
  2105 				{
       
  2106 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2107 					return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2108 				}
       
  2109 				m_key_state_partner->state_notification(notification);
       
  2110 
       
  2111 				delete notification;
       
  2112 			}
       
  2113 		}
       
  2114 
       
  2115 		set_eapol_key_state(eapol_key_state_group_key_handshake_successfull);
       
  2116 
       
  2117 		m_eapol_key_handshake_type = eapol_key_handshake_type_none;
       
  2118 
       
  2119 		if (get_is_WPXM() == true)
       
  2120 		{
       
  2121 			// Here we must increase the Reply Counter.
       
  2122 			// WPXM seems to work against RSN specification that says
       
  2123 			// every packet must be sent with new Reply Counter.
       
  2124 			// WPXM starts Group Key Handshake with Reply Counter 0 after successfull
       
  2125 			// 4-Way Handshake.
       
  2126 			set_key_reply_counter(get_key_reply_counter() + 1ul);
       
  2127 		}
       
  2128 		else
       
  2129 		{
       
  2130 			set_key_reply_counter(eapol_key_message->get_key_replay_counter());
       
  2131 		}
       
  2132 
       
  2133 		cancel_handshake_timeout();
       
  2134 
       
  2135 		EAP_TRACE_ALWAYS(
       
  2136 			m_am_tools,
       
  2137 			TRACE_FLAGS_DEFAULT,
       
  2138 			(EAPL("EAPOL_KEY: %s: Group Key Handshake SUCCESS\n"),
       
  2139 			(m_is_client == true ? "client": "server")));
       
  2140 	}
       
  2141 	else
       
  2142 	{
       
  2143 		eapol_key_state_string_c state_string;
       
  2144 
       
  2145 		EAP_TRACE_DEBUG(
       
  2146 			m_am_tools, 
       
  2147 			TRACE_FLAGS_DEFAULT, 
       
  2148 			(EAPL("WARNING: EAPOL_KEY: eapol_key_state_c::process_group_key_handshake_message_1(): ")
       
  2149 			 EAPL("No keys are set on state %d=%s.\n"),
       
  2150 			 get_eapol_key_state(),
       
  2151 			 state_string.get_eapol_key_state_string(get_eapol_key_state())));
       
  2152 	}
       
  2153 
       
  2154 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2155 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2156 }
       
  2157 
       
  2158 //--------------------------------------------------
       
  2159 
       
  2160 //
       
  2161 eap_status_e eapol_key_state_c::process_RC4_key_descriptor(
       
  2162 	const eap_am_network_id_c * const receive_network_id,
       
  2163 	eap_general_header_base_c * const packet_data,
       
  2164 	const u32_t packet_length)
       
  2165 {
       
  2166 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2167 	EAP_UNREFERENCED_PARAMETER(receive_network_id);
       
  2168 
       
  2169 	eap_status_e status = eap_status_process_general_error;
       
  2170 
       
  2171 	if (packet_length < eapol_RC4_key_header_c::get_header_length())
       
  2172 	{
       
  2173 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2174 		return EAP_STATUS_RETURN(m_am_tools, eap_status_too_short_message);
       
  2175 	}
       
  2176 
       
  2177 	if (m_eapol_key_handshake_type != eapol_key_handshake_type_dynamic_WEP)
       
  2178 	{
       
  2179 		eapol_key_state_string_c state_string;
       
  2180 		EAP_TRACE_ERROR(
       
  2181 			m_am_tools,
       
  2182 			TRACE_FLAGS_DEFAULT,
       
  2183 			(EAPL("ERROR: EAPOL_KEY: %s: process_RC4_key_descriptor(): wrong handshake type %s\n"),
       
  2184 			(m_is_client == true ? "client": "server"),
       
  2185 			state_string.get_eapol_key_handshake_type_string(m_eapol_key_handshake_type)));
       
  2186 
       
  2187 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2188 		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
       
  2189 	}
       
  2190 
       
  2191 	if (get_eapol_key_state() != eapol_key_state_wait_rc4_key_message)
       
  2192 	{
       
  2193 		eapol_key_state_string_c state_string;
       
  2194 		EAP_TRACE_ERROR(
       
  2195 			m_am_tools,
       
  2196 			TRACE_FLAGS_DEFAULT,
       
  2197 			(EAPL("WARNING: EAPOL_KEY: %s: process_RC4_key_descriptor(): wrong state %s\n"),
       
  2198 			(m_is_client == true ? "client": "server"),
       
  2199 			state_string.get_eapol_key_state_string(get_eapol_key_state())));
       
  2200 
       
  2201 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2202 		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
       
  2203 	}
       
  2204 
       
  2205 	eapol_RC4_key_header_c eapol_key_message(
       
  2206 		m_am_tools,
       
  2207 		packet_data->get_header_buffer(packet_data->get_header_buffer_length()),
       
  2208 		packet_data->get_header_buffer_length());
       
  2209 	if (eapol_key_message.get_is_valid() == false)
       
  2210 	{
       
  2211 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2212 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2213 	}
       
  2214 	else if (eapol_key_message.check_header() != 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 
       
  2221 	// Check the packet length
       
  2222 	u32_t rc4_packet_data_length = eapol_header_base_c::get_header_length()
       
  2223 		+ static_cast<u32_t>(eapol_key_message.get_eapol_packet_body_length());
       
  2224 
       
  2225 	if (eapol_RC4_key_header_c::get_header_length() > packet_length
       
  2226 		|| rc4_packet_data_length > packet_length)
       
  2227 	{
       
  2228 		// ERROR.
       
  2229 		EAP_TRACE_ERROR(
       
  2230 			m_am_tools,
       
  2231 			TRACE_FLAGS_EAPOL_KEY_DATA_ERROR,
       
  2232 			(EAPL("ERROR: EAPOL_KEY: Illegal EAPOL-Key frame length, ")
       
  2233 			EAPL("eapol_key_message.get_header_length() %d, eapol_key_message.get_packet_body_length() %d, packet_length %d\n"),
       
  2234 			eapol_key_message.get_header_length(),
       
  2235 			eapol_key_message.get_eapol_packet_body_length(),
       
  2236 			packet_length));
       
  2237 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2238 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  2239 	}
       
  2240 
       
  2241 	// Get MS-MPPE-Recv-Key and MS-MPPE-Send-Key	
       
  2242 	eap_variable_data_c mppe_recv_key(m_am_tools);
       
  2243 	eap_variable_data_c mppe_send_key(m_am_tools);
       
  2244 
       
  2245 	if (m_pairwise_PMK_WPXK3.get_data_length() == eapol_key_state_mppe_key_length_leap)
       
  2246 	{
       
  2247 		// LEAP only generates 16 bytes PMK. Also with LEAP the receive and send keys are the same.
       
  2248 		status = mppe_recv_key.set_buffer(
       
  2249 			m_pairwise_PMK_WPXK3.get_data(
       
  2250 			eapol_key_state_mppe_key_length_leap),
       
  2251 			eapol_key_state_mppe_key_length_leap,
       
  2252 			false,
       
  2253 			false);
       
  2254 		if (status != eap_status_ok)
       
  2255 		{
       
  2256 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2257 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2258 		}
       
  2259 
       
  2260 		status = mppe_send_key.set_buffer(
       
  2261 			m_pairwise_PMK_WPXK3.get_data(
       
  2262 			eapol_key_state_mppe_key_length_leap),
       
  2263 			eapol_key_state_mppe_key_length_leap,
       
  2264 			false,
       
  2265 			false);
       
  2266 		if (status != eap_status_ok)
       
  2267 		{
       
  2268 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2269 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2270 		}
       
  2271 		
       
  2272 	}
       
  2273 	else if (m_pairwise_PMK_WPXK3.get_data_length() >= 64ul)
       
  2274 	{
       
  2275 		// Usually types generate at least 64 bytes PMK.
       
  2276 		// Recv-Key is the first 32 bytes of master session key and Send-Key is the next 32 bytes.
       
  2277 		status = mppe_recv_key.set_buffer(
       
  2278 			m_pairwise_PMK_WPXK3.get_data(
       
  2279 			eapol_key_state_mppe_key_length),
       
  2280 			eapol_key_state_mppe_key_length,
       
  2281 			false,
       
  2282 			false);
       
  2283 		if (status != eap_status_ok)
       
  2284 		{
       
  2285 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2286 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2287 		}
       
  2288 
       
  2289 		status = mppe_send_key.set_buffer(
       
  2290 			m_pairwise_PMK_WPXK3.get_data_offset(
       
  2291 				eapol_key_state_mppe_key_length,
       
  2292 				eapol_key_state_mppe_key_length),
       
  2293 			eapol_key_state_mppe_key_length,
       
  2294 			false,
       
  2295 			false);
       
  2296 		if (status != eap_status_ok)
       
  2297 		{
       
  2298 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2299 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2300 		}
       
  2301 	}
       
  2302 	else
       
  2303 	{
       
  2304 		EAP_TRACE_ERROR(
       
  2305 			m_am_tools,
       
  2306 			TRACE_FLAGS_EAPOL_KEY_DATA_ERROR,
       
  2307 			(EAPL("ERROR: EAPOL_KEY: Unsupported PMK key length for RC4 EAPOL-key handshake.\n")));
       
  2308 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2309 		return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);	
       
  2310 	}
       
  2311 	
       
  2312 	// Verify the the MD5 signature in Eapol-Key
       
  2313 	crypto_md5_c md5(m_am_tools);
       
  2314 	crypto_hmac_c hmac_md5(m_am_tools, &md5, false);
       
  2315 	if (hmac_md5.get_is_valid() == false)
       
  2316 	{
       
  2317 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2318 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2319 	}
       
  2320 
       
  2321 	if (hmac_md5.get_is_valid() == false)
       
  2322 	{
       
  2323 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2324 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2325 	}
       
  2326 
       
  2327 	// MPPE-Send-Key is used as the signature key.
       
  2328 	if (hmac_md5.hmac_set_key(&mppe_send_key) != eap_status_ok)
       
  2329 	{
       
  2330 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2331 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2332 	}
       
  2333 
       
  2334 	// Save the signature from the packet
       
  2335 	eap_variable_data_c signature(m_am_tools);
       
  2336 	status = signature.set_copy_of_buffer(
       
  2337 		eapol_key_message.get_key_signature(),
       
  2338 		EAPOL_RC4_KEY_SIGNATURE_LENGTH);
       
  2339 	if (status != eap_status_ok)
       
  2340 	{
       
  2341 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2342 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2343 	}
       
  2344 
       
  2345 	// Replace the signature with zeros.
       
  2346 	eapol_key_message.zero_key_signature(m_am_tools);
       
  2347 
       
  2348 	// Send the data to HMAC-MD5 module
       
  2349 	if (hmac_md5.hmac_update(
       
  2350 			eapol_key_message.get_header_buffer(rc4_packet_data_length),
       
  2351 			rc4_packet_data_length)
       
  2352 		!= eap_status_ok)
       
  2353 	{
       
  2354 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);		
       
  2355 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  2356 	}
       
  2357 
       
  2358 	// Get the calculated signature
       
  2359 	u8_t tmp_signature[EAPOL_RC4_KEY_SIGNATURE_LENGTH];
       
  2360 	u32_t length;
       
  2361 	if (hmac_md5.hmac_final(tmp_signature, &length) != eap_status_ok)
       
  2362 	{
       
  2363 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2364 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  2365 	}
       
  2366 	
       
  2367 	// Compare the calculated and original signature
       
  2368 	if (m_am_tools->memcmp(
       
  2369 		tmp_signature,
       
  2370 		signature.get_data(
       
  2371 			EAPOL_RC4_KEY_SIGNATURE_LENGTH),
       
  2372 			EAPOL_RC4_KEY_SIGNATURE_LENGTH) != 0)
       
  2373 	{
       
  2374 		// Signatures did not match. Something's wrong.
       
  2375 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2376 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2377 	}
       
  2378 
       
  2379 	EAP_TRACE_DEBUG(
       
  2380 		m_am_tools,
       
  2381 		TRACE_FLAGS_DEFAULT,
       
  2382 		(EAPL("EAPOL_KEY: EAPOL-Key HMAC-MD5 check passed.\n")));
       
  2383 
       
  2384 	eap_variable_data_c key_out(m_am_tools);
       
  2385 	// Decrypt the RC4 encrypted key
       
  2386 	if (eapol_key_message.get_key() == 0)
       
  2387 	{
       
  2388 		// EAPOL-Key does not contain the key. This means that we should use
       
  2389 		// the first bytes from MS-MPPE-Recv-Key as the key. There is a slight 
       
  2390 		// confusion in draft-congdon-radius-8021x-23.txt regarding this but this is how
       
  2391 		// it works.
       
  2392 		if (eapol_key_message.get_key_length() > 0)
       
  2393 		{
       
  2394 			status = key_out.set_copy_of_buffer(
       
  2395 				mppe_recv_key.get_data(
       
  2396 					eapol_key_message.get_key_length()),
       
  2397 				eapol_key_message.get_key_length());	
       
  2398 			if (status != eap_status_ok)
       
  2399 			{
       
  2400 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2401 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  2402 			}
       
  2403 		} 
       
  2404 		else
       
  2405 		{
       
  2406 			// Key message with no key length?
       
  2407 			// Just ignore the message.
       
  2408 			EAP_TRACE_DEBUG(
       
  2409 				m_am_tools,
       
  2410 				TRACE_FLAGS_DEFAULT,
       
  2411 				(EAPL("EAPOL_KEY: Got empty WEP unicast key message.\n")));
       
  2412 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2413 			return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2414 		}
       
  2415 	} 
       
  2416 	else
       
  2417 	{
       
  2418 		// Set-up RC4 key. Key is the IV and the MS-MPPE-Recv-Key truncated together.
       
  2419 		eap_variable_data_c rc4_key(m_am_tools);
       
  2420 		status = rc4_key.set_copy_of_buffer(eapol_key_message.get_key_IV(), EAPOL_RC4_KEY_IV_LENGTH);
       
  2421 		if (status != eap_status_ok)
       
  2422 		{
       
  2423 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2424 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2425 		}
       
  2426 
       
  2427 		status = rc4_key.add_data(&mppe_recv_key);
       
  2428 		if (status != eap_status_ok)
       
  2429 		{
       
  2430 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2431 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2432 		}
       
  2433 
       
  2434 		// Set-up RC4 module
       
  2435 		crypto_rc4_c rc4(m_am_tools);
       
  2436 		if (rc4.get_is_valid() == false)
       
  2437 		{
       
  2438 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2439 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2440 		}
       
  2441 
       
  2442 		// Set the key for RC4
       
  2443 		if (rc4.set_key(&rc4_key) != eap_status_ok)
       
  2444 		{
       
  2445 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2446 			return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
       
  2447 		}
       
  2448 
       
  2449 		// Decrypt the key to key_out
       
  2450 		status = key_out.set_buffer_length(eapol_key_message.get_key_length());
       
  2451 		if (status != eap_status_ok)
       
  2452 		{
       
  2453 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2454 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2455 		}
       
  2456 		status = rc4.decrypt_data(
       
  2457 			eapol_key_message.get_key(),
       
  2458 			key_out.get_buffer(
       
  2459 				eapol_key_message.get_key_length()),
       
  2460 			eapol_key_message.get_key_length());
       
  2461 		if (status != eap_status_ok)
       
  2462 		{
       
  2463 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2464 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2465 		}
       
  2466 
       
  2467 		status = key_out.set_data_length(eapol_key_message.get_key_length());
       
  2468 		if (status != eap_status_ok)
       
  2469 		{
       
  2470 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2471 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  2472 		}
       
  2473 	}
       
  2474 
       
  2475 	// Find out the key type. At the moment only WEP keys are supported.
       
  2476 	eapol_key_type_e key_type;
       
  2477 	switch (eapol_key_message.get_key_flag())
       
  2478 	{
       
  2479 	case eapol_RC4_key_flag_broadcast:
       
  2480 		EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("EAPOL_KEY: Got WEP broadcast key\n")));
       
  2481 		key_type = eapol_key_type_broadcast;
       
  2482 		m_received_802_1x_keys[eapol_key_type_broadcast] = true;
       
  2483 		break;
       
  2484 	case eapol_RC4_key_flag_unicast:
       
  2485 		EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("EAPOL_KEY: Got WEP unicast key\n")));
       
  2486 		key_type = eapol_key_type_unicast;
       
  2487 		m_received_802_1x_keys[eapol_key_type_unicast] = true;
       
  2488 		break;
       
  2489 	default:
       
  2490 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2491 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
  2492 	}
       
  2493 
       
  2494 	EAP_TRACE_DATA_DEBUG(
       
  2495 		m_am_tools,
       
  2496 		TRACE_FLAGS_DEFAULT,
       
  2497 		(EAPL("RC4 Key"),
       
  2498 		key_out.get_data(key_out.get_data_length()),
       
  2499 		key_out.get_data_length()));
       
  2500 
       
  2501 	status = packet_data_session_key(
       
  2502 		&key_out,
       
  2503 		key_type,
       
  2504 		eapol_key_message.get_key_index(),
       
  2505 		true,
       
  2506 		0,
       
  2507 		0ul);
       
  2508 	if (status != eap_status_ok)
       
  2509 	{
       
  2510 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2511 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2512 	}
       
  2513 
       
  2514 
       
  2515 	{
       
  2516 		bool finished_keys(true);
       
  2517 
       
  2518 		for (u32_t key_type = 0ul; key_type <= eapol_key_type_unicast; key_type++)
       
  2519 		{
       
  2520 			if (m_received_802_1x_keys[key_type] == false)
       
  2521 			{
       
  2522 				// Not all keys are received.
       
  2523 				finished_keys = false;
       
  2524 				break;
       
  2525 			}
       
  2526 		}
       
  2527 
       
  2528 		if (finished_keys == true)
       
  2529 		{
       
  2530 			// This is notification to eapol_core_c object.
       
  2531 			// Dynamic WEP (802.1x) authentication finished successfully.
       
  2532 			eap_state_notification_c * notification = new eap_state_notification_c(
       
  2533 				m_am_tools,
       
  2534 				&m_send_network_id,
       
  2535 				m_is_client,
       
  2536 				eap_state_notification_generic,
       
  2537 				eap_protocol_layer_eapol_key,
       
  2538 				eapol_key_handshake_type_dynamic_WEP,
       
  2539 				get_eapol_key_state(),
       
  2540 				eapol_key_state_802_11i_authentication_finished_successfull,
       
  2541 				0ul,
       
  2542 				false);
       
  2543 			if (notification == 0)
       
  2544 			{
       
  2545 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2546 				return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2547 			}
       
  2548 			m_key_state_partner->state_notification(notification);
       
  2549 
       
  2550 			delete notification;
       
  2551 		}
       
  2552 	}
       
  2553 
       
  2554 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2555 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2556 }
       
  2557 
       
  2558 //--------------------------------------------------
       
  2559 
       
  2560 //
       
  2561 eap_status_e eapol_key_state_c::initialize_4_way_handshake(
       
  2562 	const eap_am_network_id_c * const receive_network_id,
       
  2563 	const eapol_protocol_version_e used_eapol_version)
       
  2564 {
       
  2565 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2566 	EAP_UNREFERENCED_PARAMETER(receive_network_id);
       
  2567 
       
  2568 	eap_status_e status = eap_status_process_general_error;
       
  2569 
       
  2570 	// Only client (supplicant) could call this.
       
  2571 	EAP_ASSERT_ALWAYS(m_is_client == true);
       
  2572 
       
  2573 	EAP_TRACE_DEBUG(
       
  2574 		m_am_tools, 
       
  2575 		TRACE_FLAGS_DEFAULT, 
       
  2576 		(EAPL("EAPOL_KEY: %s: eapol_key_state_c::initialize_4_way_handshake()\n"),
       
  2577 		(m_is_client == true ? "client": "server")));
       
  2578 
       
  2579 	if (m_eapol_key_handshake_type != eapol_key_handshake_type_none
       
  2580 		&& m_eapol_key_handshake_type != eapol_key_handshake_type_group_key_handshake
       
  2581 		&& m_eapol_key_handshake_type != eapol_key_handshake_type_4_way_handshake)
       
  2582 	{
       
  2583 		eapol_key_state_string_c state_string;
       
  2584 		EAP_TRACE_ERROR(
       
  2585 			m_am_tools,
       
  2586 			TRACE_FLAGS_DEFAULT,
       
  2587 			(EAPL("WARNING: EAPOL_KEY: %s: initialize_4_way_handshake(): wrong handshake type %s\n"),
       
  2588 			(m_is_client == true ? "client": "server"),
       
  2589 			state_string.get_eapol_key_handshake_type_string(m_eapol_key_handshake_type)));
       
  2590 
       
  2591 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2592 		return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eap_type_state);
       
  2593 	}
       
  2594 
       
  2595 	eap_buf_chain_wr_c sent_packet(
       
  2596 		eap_write_buffer,
       
  2597 		m_am_tools);
       
  2598 
       
  2599 	if (sent_packet.get_is_valid() == false)
       
  2600 	{
       
  2601 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  2602 	}
       
  2603 
       
  2604 	u32_t send_data_length = 0ul;
       
  2605 	u32_t send_buffer_length = 0ul;
       
  2606 
       
  2607 	status = create_eapol_key_handshake_message_0(
       
  2608 		true,
       
  2609 		&sent_packet,
       
  2610 		m_eapol_header_offset,
       
  2611 		&send_data_length,
       
  2612 		&send_buffer_length,
       
  2613 		m_client_send_key_reply_counter,
       
  2614 		used_eapol_version);
       
  2615 	if (status != eap_status_ok)
       
  2616 	{
       
  2617 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2618 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2619 	}
       
  2620 
       
  2621 	status = packet_send(
       
  2622 		&m_send_network_id,
       
  2623 		&sent_packet,
       
  2624 		m_eapol_header_offset,
       
  2625 		send_data_length,
       
  2626 		send_buffer_length);
       
  2627 	if (status != eap_status_ok)
       
  2628 	{
       
  2629 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2630 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2631 	}
       
  2632 		
       
  2633 	set_eapol_key_state(eapol_key_state_wait_4_way_handshake_message_1);
       
  2634 
       
  2635 	m_eapol_key_handshake_type = eapol_key_handshake_type_4_way_handshake;
       
  2636 
       
  2637 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2638 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2639 }
       
  2640 
       
  2641 //--------------------------------------------------
       
  2642 
       
  2643 
       
  2644 // End.