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