/*
* ============================================================================
* Name : ./accesssec/eapol/eapol_framework/wapi_common/src/wapi_core.cpp
* Part of : WAPI / WAPI *** Info from the SWAD
* Description : WAPI authentication
* Version : %version: 131.1.4 % << Don't touch! Updated by Synergy at check-out.
*
* Copyright © 2001-2009 Nokia. All rights reserved.
* This material, including documentation and any related computer
* programs, is protected by copyright controlled by Nokia. All
* rights are reserved. Copying, including reproducing, storing,
* adapting or translating, any or all of this material requires the
* prior written consent of Nokia. This material also contains
* confidential information which may not be disclosed to others
* without the prior written consent of Nokia.
* ============================================================================
* Template version: 4.1.1
*/
// This is enumeration of WAPI source code.
#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
#undef EAP_FILE_NUMBER_ENUM
#define EAP_FILE_NUMBER_ENUM 712
#undef EAP_FILE_NUMBER_DATE
#define EAP_FILE_NUMBER_DATE 1127594498
#endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
#include "eap_am_memory.h"
#include "eap_tools.h"
#include "abs_wapi_core.h"
#include "abs_eap_am_mutex.h"
#include "wapi_core.h"
#include "eap_state_notification.h"
#include "eap_network_id_selector.h"
#include "eap_buffer.h"
#include "eap_automatic_variable.h"
#include "wapi_core_retransmission.h"
#include "wai_protocol_packet_header.h"
#include "wapi_strings.h"
#include "eap_crypto_api.h"
#include "eap_automatic_variable.h"
#include "eapol_session_key.h"
#include "wapi_am_crypto_sms4.h"
#include "asn1_der_type.h"
#include "wapi_asn1_der_parser.h"
#include "wapi_am_base_core.h"
//#define WAPI_SKIP_BKID_TEST // This is for testing.
//--------------------------------------------------
//
EAP_FUNC_EXPORT wapi_core_c::~wapi_core_c()
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::~wapi_core_c(): %s, this = 0x%08x => 0x%08x.\n"),
(m_is_client == true) ? "client": "server",
this,
dynamic_cast<abs_eap_base_timer_c *>(this)));
EAP_ASSERT(m_shutdown_was_called == true);
{
for (u32_t ind = 0ul; ind < WAPI_USKSA_COUNT; ++ind)
{
delete m_USKSA[ind];
m_USKSA[ind] = 0;
} // for()
}
{
for (u32_t ind = 0ul; ind < WAPI_MSKSA_COUNT; ++ind)
{
delete m_MSKSA[ind];
m_MSKSA[ind] = 0;
} // for()
}
delete m_ec_certificate_store;
m_ec_certificate_store = 0;
delete m_am_wapi_core;
m_am_wapi_core = 0;
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
}
//--------------------------------------------------
#if defined(_WIN32) && !defined(__GNUC__)
#pragma warning( disable : 4355 ) // 'this' : used in base member initializer list
#endif
//
EAP_FUNC_EXPORT wapi_core_c::wapi_core_c(
abs_eap_am_tools_c * const tools,
abs_wapi_core_c * const partner,
const bool is_client_when_true,
const eap_am_network_id_c * const receive_network_id)
: m_partner(partner)
, m_ec_certificate_store(0)
, m_am_wapi_core(0)
, m_am_tools(tools)
, m_wapi_header_offset(0u)
, m_MTU(0u)
, m_trailer_length(0u)
, m_receive_network_id(tools)
, m_retransmission(0)
, m_retransmission_time(WAPI_CORE_RETRANSMISSION_TIME)
, m_retransmission_counter(WAPI_CORE_RETRANSMISSION_COUNTER)
, m_session_timeout(WAPI_CORE_SESSION_TIMEOUT)
, m_wapi_core_failure_received_timeout(WAPI_CORE_FAILURE_RECEIVED_TIMEOUT)
, m_remove_session_timeout(WAPI_CORE_REMOVE_SESSION_TIMEOUT)
, m_wapi_state(wapi_core_state_none)
, m_received_wai_message_data(tools, is_client_when_true)
, m_new_payloads(tools, is_client_when_true)
, m_preshared_key_PSK(tools)
, m_BK(tools)
, m_BKID(tools)
, m_USKID(0u)
, m_MSKID(0u)
, m_ae_certificate_challenge(tools)
, m_asue_certificate_challenge(tools)
, m_ae_unicast_challenge(tools)
, m_asue_unicast_challenge(tools)
, m_authentication_identifier(tools)
, m_asue_id(tools)
, m_asu_id(tools)
, m_ae_id(tools)
, m_test_other_asu_id(tools)
, m_own_certificate(tools)
, m_peer_certificate(tools)
, m_ae_certificate(tools)
, m_wapi_ie_asue(tools)
, m_wapi_ie_ae(tools)
, m_unicast_encryption_key_UEK(tools)
, m_unicast_integrity_check_key_UCK(tools)
, m_message_authentication_key_MAK(tools)
, m_key_encryption_key_KEK(tools)
, m_next_unicast_challenge(tools)
, m_multicast_key(tools)
, m_packet_data_number(tools)
, m_key_announcement(tools)
, m_own_private_key_d(tools)
, m_own_public_key_x(tools)
, m_own_public_key_y(tools)
, m_peer_public_key_x(tools)
, m_peer_public_key_y(tools)
, m_result_of_certificate_verification(tools)
, m_server_signature_trusted_by_asue(tools)
, m_server_signature_trusted_by_ae(tools)
, m_reassemble_packet(tools)
, m_authentication_type(eapol_key_authentication_type_none)
, m_wapi_negotiation_state(wapi_negotiation_state_none)
, m_wapi_pairwise_cipher(eapol_RSNA_key_header_c::eapol_RSNA_cipher_none)
, m_wapi_group_cipher(eapol_RSNA_key_header_c::eapol_RSNA_cipher_none)
, m_packet_sequence_number(0u)
, m_fragment_sequence_number(0u)
, m_is_client(is_client_when_true)
, m_is_client_role(is_client_when_true)
, m_is_valid(false)
, m_client_restart_authentication_initiated(false)
, m_marked_removed(false)
, m_shutdown_was_called(false)
, m_do_certificate_validation(false)
#if defined(USE_WAPI_CORE_SERVER)
, m_only_initial_authentication(false)
#endif //#if defined(USE_WAPI_CORE_SERVER)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::wapi_core_c(): %s, this = 0x%08x => 0x%08x, compiled %s %s.\n"),
(m_is_client == true) ? "client": "server",
this,
dynamic_cast<abs_eap_base_timer_c *>(this),
__DATE__,
__TIME__));
eap_status_e status = m_receive_network_id.set_copy_of_network_id(receive_network_id);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return;
}
{
for (u32_t ind = 0ul; ind < WAPI_USKSA_COUNT; ++ind)
{
m_USKSA[ind] = 0;
} // for()
}
{
for (u32_t ind = 0ul; ind < WAPI_MSKSA_COUNT; ++ind)
{
m_MSKSA[ind] = 0;
}
}
{
for (u32_t ind = 0ul; ind < WAPI_USKSA_COUNT; ++ind)
{
m_USKSA[ind] = 0;
wai_usksa_c * const usksa = new wai_usksa_c(m_am_tools);
if (usksa == 0
|| usksa->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
(void) EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
return;
}
m_USKSA[ind] = usksa;
} // for()
}
{
for (u32_t ind = 0ul; ind < WAPI_MSKSA_COUNT; ++ind)
{
m_MSKSA[ind] = 0;
wai_usksa_c * const msksa = new wai_usksa_c(m_am_tools);
if (msksa == 0
|| msksa->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
(void) EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
return;
}
m_MSKSA[ind] = msksa;
} // for()
}
m_am_wapi_core = wapi_am_base_core_c::new_wapi_am_core(
tools,
this,
is_client_when_true,
&m_receive_network_id);
if (m_am_wapi_core == 0
|| m_am_wapi_core->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
(void) EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
return;
}
m_ec_certificate_store = ec_base_certificate_store_c::new_ec_base_certificate_store_c(
tools,
this,
m_am_wapi_core,
is_client_when_true);
if (m_ec_certificate_store == 0
|| m_ec_certificate_store->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
(void) EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
return;
}
status = m_ec_certificate_store->set_receive_network_id(&m_receive_network_id);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
(void) EAP_STATUS_RETURN(m_am_tools, status);
return;
}
set_is_valid();
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::initialize(
const eap_am_network_id_c * const receive_network_id,
const eapol_key_authentication_type_e authentication_type)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
eap_status_e status = m_receive_network_id.set_copy_of_network_id(receive_network_id);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
m_authentication_type = authentication_type;
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::initialize(
const eap_am_network_id_c * const receive_network_id,
const eapol_key_authentication_type_e authentication_type,
const eap_variable_data_c * const wapi_ie_ae,
const eap_variable_data_c * const wapi_ie_asue,
const eapol_RSNA_key_header_c::eapol_RSNA_cipher_e wapi_pairwise_cipher,
const eapol_RSNA_key_header_c::eapol_RSNA_cipher_e wapi_group_cipher)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
eap_status_e status = m_receive_network_id.set_copy_of_network_id(receive_network_id);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
m_authentication_type = authentication_type;
status = m_wapi_ie_ae.set_copy_of_buffer(wapi_ie_ae);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_wapi_ie_asue.set_copy_of_buffer(wapi_ie_asue);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
m_wapi_pairwise_cipher = wapi_pairwise_cipher;
m_wapi_group_cipher = wapi_group_cipher;
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
//
void wapi_core_c::set_wapi_state(wapi_core_state_e wapi_state)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAI: %s: wapi_core_c::set_wapi_state(): State from %s to %s, %s.\n"),
(m_is_client == true) ? "client": "server",
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_core_state_string(wapi_state),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
m_wapi_state = wapi_state;
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT abs_wapi_core_c * wapi_core_c::get_partner()
{
EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
return m_partner;
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT void wapi_core_c::set_partner(abs_wapi_core_c * const partner)
{
EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
m_partner = partner;
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT void wapi_core_c::set_is_valid()
{
m_is_valid = true;
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT bool wapi_core_c::get_is_valid()
{
return m_is_valid;
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT void wapi_core_c::object_increase_reference_count()
{
// This is an empty function to implement here unused interface function.
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT u32_t wapi_core_c::object_decrease_reference_count()
{
return 0u;
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT bool wapi_core_c::get_marked_removed()
{
return m_marked_removed;
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT void wapi_core_c::set_marked_removed()
{
m_marked_removed = true;
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT void wapi_core_c::unset_marked_removed()
{
m_marked_removed = false;
}
//--------------------------------------------------
//
eap_status_e wapi_core_c::initialize_asynchronous_init_remove_wapi_session(
const u32_t remove_session_timeout)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::initialize_asynchronous_init_remove_wapi_session(): %s.\n"),
(m_is_client == true) ? "client": "server"));
eap_status_e status = eap_status_process_general_error;
if (m_is_client_role == false)
{
// Server stops re-transmissions.
// Client can re-transmit until session is removed.
cancel_retransmission();
}
cancel_wapi_failure_timeout();
cancel_session_timeout();
set_marked_removed();
if (remove_session_timeout == 0ul)
{
status = asynchronous_init_remove_wapi_session();
}
else
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
cancel_asynchronous_init_remove_wapi_session();
status = m_partner->set_timer(
this,
WAPI_CORE_REMOVE_SESSION_TIMEOUT_ID,
0,
remove_session_timeout);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: %s: WAPI_CORE_REMOVE_SESSION_TIMEOUT_ID set %d ms, this = 0x%08x.\n"),
(m_is_client == true) ? "client": "server",
remove_session_timeout,
this));
}
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
eap_status_e wapi_core_c::cancel_asynchronous_init_remove_wapi_session()
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
eap_status_e status = m_partner->cancel_timer(
this,
WAPI_CORE_REMOVE_SESSION_TIMEOUT_ID);
EAP_UNREFERENCED_PARAMETER(status); // in release
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: %s: WAPI_CORE_REMOVE_SESSION_TIMEOUT_ID cancelled status %d, this = 0x%08x.\n"),
(m_is_client == true ? "client": "server"),
status,
this));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
}
//--------------------------------------------------
//
eap_status_e wapi_core_c::asynchronous_init_remove_wapi_session()
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::asynchronous_init_remove_wapi_session(): %s.\n"),
(m_is_client == true) ? "client": "server"));
eap_am_network_id_c send_network_id(
m_am_tools,
m_receive_network_id.get_destination_id(),
m_receive_network_id.get_source_id(),
m_receive_network_id.get_type());
eap_status_e status = m_partner->asynchronous_init_remove_wapi_session(
&send_network_id);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
//
eap_status_e wapi_core_c::init_end_of_session(
const abs_eap_state_notification_c * const state)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::init_end_of_session(): %s.\n"),
(m_is_client == true) ? "client": "server"));
eap_status_e status(eap_status_process_general_error);
// Normally we will remove session after authentication ends.
// Remove session only if the stack is not already being deleted
if (m_shutdown_was_called == false)
{
#if defined(USE_WAPI_CORE_SIMULATOR_VERSION) && defined(USE_WAPI_CORE_RESTART_AUTHENTICATION)
// Simulator reuses current session.
status = restart_authentication(
state->get_send_network_id(),
m_is_client);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
#elif defined(USE_WAPI_CORE_SIMULATOR_VERSION)
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::state_notification(): %s, %s, Ignored notification: ")
EAPL("Protocol layer %d, State transition from ")
EAPL("%d=%s to %d=%s, client %d.\n"),
(m_is_client == true) ? "client": "server",
(m_is_tunneled_eap == true) ? "tunneled": "outer most",
state->get_protocol_layer(),
state->get_previous_state(),
state->get_previous_state_string(),
state->get_current_state(),
state->get_current_state_string(),
state->get_is_client()));
#endif //#if defined(USE_WAPI_CORE_SIMULATOR_VERSION)
status = initialize_asynchronous_init_remove_wapi_session(m_remove_session_timeout);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
else
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::state_notification(): %s, Ignored notification: ")
EAPL("Protocol layer %d, State transition from ")
EAPL("%d=%s to %d=%s, client %d when shutdown was called.\n"),
(m_is_client == true) ? "client": "server",
state->get_protocol_layer(),
state->get_previous_state(),
state->get_previous_state_string(),
state->get_current_state(),
state->get_current_state_string(),
state->get_is_client()));
status = eap_status_ok;
}
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
EAP_FUNC_EXPORT void wapi_core_c::state_notification(
const abs_eap_state_notification_c * const state)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
eap_status_string_c status_string;
EAP_UNREFERENCED_PARAMETER(status_string); // in release
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::state_notification(), %s, protocol_layer %d=%s, protocol %d=%s.\n"),
(m_is_client == true) ? "client": "server",
state->get_protocol_layer(),
state->get_protocol_layer_string(),
state->get_protocol(),
state->get_protocol_string()));
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::state_notification(), %s, current_state %d=%s, error %d=%s.\n"),
(m_is_client == true) ? "client": "server",
state->get_current_state(),
state->get_current_state_string(),
state->get_authentication_error(),
status_string.get_status_string(state->get_authentication_error())));
m_partner->state_notification(state);
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT eap_status_e wapi_core_c::initialize_session_timeout(const u32_t session_timeout_ms)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
cancel_session_timeout();
eap_status_e status = m_partner->set_timer(
this,
WAPI_CORE_SESSION_TIMEOUT_ID,
0,
session_timeout_ms);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: %s: WAPI_CORE_SESSION_TIMEOUT_ID set %d ms, this = 0x%08x.\n"),
(m_is_client == true) ? "client": "server",
session_timeout_ms,
this));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::cancel_session_timeout()
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
eap_status_e status = m_partner->cancel_timer(
this,
WAPI_CORE_SESSION_TIMEOUT_ID);
EAP_UNREFERENCED_PARAMETER(status); // in release
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: %s: WAPI_CORE_SESSION_TIMEOUT_ID cancelled status %d, this = 0x%08x.\n"),
(m_is_client == true ? "client": "server"),
status,
this));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
}
//--------------------------------------------------
eap_status_e wapi_core_c::create_BKID(
eap_variable_data_c * const BKID,
const eap_am_network_id_c * const receive_network_id)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::create_BKID(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::create_BKID()");
if (BKID == 0
|| BKID->get_is_valid() == false
|| receive_network_id == 0
|| receive_network_id->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
eap_status_e status(eap_status_process_general_error);
// BKID = KD_HMAC_SHA256(BK, MACAE || MACASUE)
crypto_kd_hmac_sha256_c kd_hmac(m_am_tools);
if (kd_hmac.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
eap_variable_data_c label(m_am_tools);
if (label.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
const eap_variable_data_c * MAC_1 = receive_network_id->get_destination_id();
const eap_variable_data_c * MAC_2 = receive_network_id->get_source_id();
if (m_is_client == true)
{
MAC_1 = receive_network_id->get_source_id();
MAC_2 = receive_network_id->get_destination_id();
}
status = label.set_copy_of_buffer(MAC_1);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = label.add_data(MAC_2);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = kd_hmac.expand_key(
BKID,
WAPI_BKID_LENGTH,
&m_BK,
&label);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
//
eap_status_e wapi_core_c::packet_data_session_key(
eap_variable_data_c * const key, ///< Here is the key.
const eapol_key_type_e key_type, ///< This the type of the key.
const u32_t key_index, ///< This is the index of the key.
const bool key_tx_bit, ///< This is the TX bit of the key.
const u8_t * const key_RSC, ///< This is the RSC counter
const u32_t key_RSC_size ///< This is the size of RSC counter
)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
eapol_session_key_c * eapol_session_key = new eapol_session_key_c(
m_am_tools,
key,
key_type,
key_index,
key_tx_bit,
key_RSC,
key_RSC_size
);
if (eapol_session_key == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
if (eapol_session_key->get_is_valid() == false)
{
delete eapol_session_key;
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
// Here we swap the addresses.
eap_am_network_id_c send_network_id(m_am_tools,
m_receive_network_id.get_destination_id(),
m_receive_network_id.get_source_id(),
m_receive_network_id.get_type());
if (send_network_id.get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
eap_status_e status = m_partner->packet_data_session_key(
&send_network_id,
eapol_session_key);
delete eapol_session_key;
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
eap_status_e wapi_core_c::create_unicast_key(
const eap_variable_data_c * const BK,
const eap_am_network_id_c * const receive_network_id,
const eap_variable_data_c * const ae_challenge,
const eap_variable_data_c * const asue_challenge,
eap_variable_data_c * const unicast_encryption_key_UEK,
eap_variable_data_c * const unicast_integrity_check_key_UCK,
eap_variable_data_c * const message_authentication_key_MAK,
eap_variable_data_c * const key_encryption_key_KEK,
eap_variable_data_c * const challenge_seed)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::create_unicast_key(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::create_unicast_key()");
if (BK == 0
|| BK->get_is_valid_data() == false
|| receive_network_id == 0
|| receive_network_id->get_is_valid() == false
|| ae_challenge == 0
|| ae_challenge->get_is_valid_data() == false
|| asue_challenge == 0
|| asue_challenge->get_is_valid_data() == false
|| unicast_encryption_key_UEK == 0
|| unicast_encryption_key_UEK->get_is_valid() == false
|| unicast_integrity_check_key_UCK == 0
|| unicast_integrity_check_key_UCK->get_is_valid() == false
|| message_authentication_key_MAK == 0
|| message_authentication_key_MAK->get_is_valid() == false
|| key_encryption_key_KEK == 0
|| key_encryption_key_KEK->get_is_valid() == false
|| challenge_seed == 0
|| challenge_seed->get_is_valid() == false
)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
eap_status_e status(eap_status_process_general_error);
// Output (96) = KD-HMAC-SHA256(BK, ADDID||N_AE||N_ASUE||Label, Length);
crypto_kd_hmac_sha256_c kd_hmac(m_am_tools);
if (kd_hmac.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
eap_variable_data_c label(m_am_tools);
if (label.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
const eap_variable_data_c * MAC_1 = receive_network_id->get_destination_id();
const eap_variable_data_c * MAC_2 = receive_network_id->get_source_id();
if (m_is_client == true)
{
MAC_1 = receive_network_id->get_source_id();
MAC_2 = receive_network_id->get_destination_id();
}
status = label.set_copy_of_buffer(MAC_1);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = label.add_data(MAC_2);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = label.add_data(ae_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = label.add_data(asue_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = label.add_data(WAPI_UNICAST_KEY_LABEL, WAPI_UNICAST_KEY_LABEL_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
eap_variable_data_c unicast_key(m_am_tools);
if (unicast_key.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = kd_hmac.expand_key(
&unicast_key,
WAPI_UNICAST_KEY_LENGTH,
BK,
&label);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// {unicast_encryption_key_UEK (16)
// || unicast_integrity_check_key_UCK (16)
// || message_authentication_key_MAK (16)
// || key_encryption_key_KEK (16)
// || Challenge seed (32)}
// = Output (96)
u32_t offset(0ul);
u32_t required_data_length(WAPI_UNICAST_ENCRYPTION_KEY_UEK_LENGTH);
status = unicast_encryption_key_UEK->set_copy_of_buffer(
unicast_key.get_data_offset(offset, required_data_length),
required_data_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
offset += required_data_length;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
required_data_length = WAPI_UNICAST_INTEGRITY_CHECK_KEY_UCK_LENGTH;
status = unicast_integrity_check_key_UCK->set_copy_of_buffer(
unicast_key.get_data_offset(offset, required_data_length),
required_data_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
offset += required_data_length;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
required_data_length = WAPI_MESSAGE_AUTHENTICATION_KEY_MAK_LENGTH;
status = message_authentication_key_MAK->set_copy_of_buffer(
unicast_key.get_data_offset(offset, required_data_length),
required_data_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
offset += required_data_length;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
required_data_length = WAPI_KEY_ENCRYPTION_KEY_KEK_LENGTH;
status = key_encryption_key_KEK->set_copy_of_buffer(
unicast_key.get_data_offset(offset, required_data_length),
required_data_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
offset += required_data_length;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
required_data_length = WAPI_CHALLENGE_SEED_LENGTH;
{
eap_variable_data_c next_challenge(m_am_tools);
if (next_challenge.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
crypto_sha_256_c sha_256(m_am_tools);
if (sha_256.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = sha_256.hash_init();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = sha_256.hash_update(
unicast_key.get_data_offset(offset, required_data_length),
required_data_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
u32_t md_length(sha_256.get_digest_length());
status = challenge_seed->set_buffer_length(md_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = challenge_seed->set_data_length(md_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = sha_256.hash_final(
challenge_seed->get_data(),
&md_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("next challenge_seed"),
challenge_seed->get_data(),
challenge_seed->get_data_length()));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
eap_status_e wapi_core_c::create_MAC(
const wai_message_payloads_c * const payloads,
eap_variable_data_c * const MAC)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::create_MAC(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::create_MAC()");
if (payloads == 0
|| payloads->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
if (MAC == 0
|| MAC->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
eap_status_e status(eap_status_process_general_error);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
crypto_sha_256_c sha_256(m_am_tools);
if (sha_256.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
crypto_hmac_c hmac_sha_256(
m_am_tools,
&sha_256,
false);
if (hmac_sha_256.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: m_message_authentication_key_MAK"),
m_message_authentication_key_MAK.get_data(),
m_message_authentication_key_MAK.get_data_length()));
status = hmac_sha_256.hmac_set_key(&m_message_authentication_key_MAK);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
for (u32_t tlv_index = 0ul; tlv_index < payloads->get_tlv_count(); ++tlv_index)
{
const wai_variable_data_c * tlv = payloads->get_tlv(tlv_index);
if (tlv == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
if (tlv->get_payload_type() != wai_payload_type_message_authentication_code)
{
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: MAC: input data"),
tlv->get_data(tlv->get_data_length()),
tlv->get_data_length()));
status = hmac_sha_256.hmac_update(
tlv->get_data(tlv->get_data_length()),
tlv->get_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
} // for()
status = MAC->set_buffer_length(hmac_sha_256.get_digest_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = MAC->set_data_length(hmac_sha_256.get_digest_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
u32_t md_length(hmac_sha_256.get_digest_length());
status = hmac_sha_256.hmac_final(
MAC->get_data(hmac_sha_256.get_digest_length()),
&md_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = MAC->set_data_length(WAPI_MESSAGE_AUTHENTICATION_CODE_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: MAC"),
MAC->get_data(),
MAC->get_data_length()));
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
eap_status_e wapi_core_c::create_HASH(
const wai_message_payloads_c * const payloads,
const bool hash_all_payloads,
eap_variable_data_c * const HASH)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::create_HASH(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::create_HASH()");
if (payloads == 0
|| payloads->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
if (HASH == 0
|| HASH->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
eap_status_e status(eap_status_process_general_error);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
crypto_sha_256_c sha_256(m_am_tools);
if (sha_256.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = sha_256.hash_init();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
for (u32_t tlv_index = 0ul; tlv_index < payloads->get_tlv_count(); ++tlv_index)
{
const wai_variable_data_c * tlv = payloads->get_tlv(tlv_index);
if (tlv == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
if (hash_all_payloads == true
|| (tlv->get_payload_type() != wai_payload_type_message_authentication_code
&& tlv->get_payload_type() != wai_payload_type_signature_attributes))
{
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: HASH: input data"),
tlv->get_data(tlv->get_data_length()),
tlv->get_data_length()));
status = sha_256.hash_update(
tlv->get_data(tlv->get_data_length()),
tlv->get_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
} // for()
status = HASH->set_buffer_length(sha_256.get_digest_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = HASH->set_data_length(sha_256.get_digest_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
u32_t md_length(sha_256.get_digest_length());
status = sha_256.hash_final(
HASH->get_data(sha_256.get_digest_length()),
&md_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: HASH"),
HASH->get_data(),
HASH->get_data_length()));
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
#if defined(USE_WAPI_CORE_SERVER)
eap_status_e wapi_core_c::encrypt_multicast_key_data(
const eap_variable_data_c * const multicast_key,
const eap_variable_data_c * const key_announcement,
wai_variable_data_c * const key_data)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TODO: WAPI_Core: this = 0x%08x, %s: wapi_core_c::encrypt_multicast_key_data(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::encrypt_multicast_key_data()");
eap_status_e status(eap_status_process_general_error);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: multicast_key"),
multicast_key->get_data(),
multicast_key->get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: m_key_encryption_key_KEK"),
m_key_encryption_key_KEK.get_data(),
m_key_encryption_key_KEK.get_data_length()));
wapi_am_crypto_sms4_c sms4(m_am_tools);
status = sms4.set_key(&m_key_encryption_key_KEK);
if (status != eap_status_ok)
{
return EAP_STATUS_RETURN(m_am_tools, status);
}
eap_variable_data_c encrypted_multicast_key(m_am_tools);
status = encrypted_multicast_key.set_buffer_length(multicast_key->get_data_length());
if (status != eap_status_ok)
{
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = encrypted_multicast_key.set_data_length(encrypted_multicast_key.get_buffer_length());
if (status != eap_status_ok)
{
return EAP_STATUS_RETURN(m_am_tools, status);
}
{
eap_variable_data_c iv_block(m_am_tools);
status = iv_block.set_buffer_length(multicast_key->get_data_length());
if (status != eap_status_ok)
{
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = iv_block.set_data_length(iv_block.get_buffer_length());
if (status != eap_status_ok)
{
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = sms4.ecb_encrypt(
key_announcement->get_data(multicast_key->get_data_length()),
iv_block.get_data(multicast_key->get_data_length()),
multicast_key->get_data_length()/16);
if (status != eap_status_ok)
{
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: iv_block"),
iv_block.get_data(),
iv_block.get_data_length()));
// encrypted_multicast_key = multicast_key XOR iv_block.
const u8_t * const pIV = iv_block.get_data(multicast_key->get_data_length());
const u8_t * const pdata = multicast_key->get_data(multicast_key->get_data_length());
u8_t * const output = encrypted_multicast_key.get_data(multicast_key->get_data_length());
if (pIV == 0
|| pdata == 0
|| output == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
for (u32_t ind = 0u; ind < multicast_key->get_data_length(); ind++)
{
output[ind] = pdata[ind] ^ pIV[ind];
}
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: encrypted_multicast_key"),
encrypted_multicast_key.get_data(),
encrypted_multicast_key.get_data_length()));
status = key_data->create(
wai_payload_type_key_data,
encrypted_multicast_key.get_data(),
encrypted_multicast_key.get_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
#endif //#if defined(USE_WAPI_CORE_SERVER)
//--------------------------------------------------
eap_status_e wapi_core_c::decrypt_multicast_key_data(
const wai_variable_data_c * const key_data,
const eap_variable_data_c * const key_announcement,
eap_variable_data_c * const multicast_key)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TODO: WAPI_Core: this = 0x%08x, %s: wapi_core_c::decrypt_multicast_key_data(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::decrypt_multicast_key_data()");
eap_status_e status(eap_status_process_general_error);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: key_data"),
key_data->get_type_data(key_data->get_type_data_length()),
key_data->get_type_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: m_key_encryption_key_KEK"),
m_key_encryption_key_KEK.get_data(),
m_key_encryption_key_KEK.get_data_length()));
wapi_am_crypto_sms4_c sms4(m_am_tools);
status = sms4.set_key(&m_key_encryption_key_KEK);
if (status != eap_status_ok)
{
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = multicast_key->set_buffer_length(key_data->get_type_data_length());
if (status != eap_status_ok)
{
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = multicast_key->set_data_length(multicast_key->get_buffer_length());
if (status != eap_status_ok)
{
return EAP_STATUS_RETURN(m_am_tools, status);
}
{
eap_variable_data_c iv_block(m_am_tools);
if (iv_block.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = iv_block.set_buffer_length(key_data->get_type_data_length());
if (status != eap_status_ok)
{
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = iv_block.set_data_length(iv_block.get_buffer_length());
if (status != eap_status_ok)
{
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = sms4.ecb_encrypt(
key_announcement->get_data(key_data->get_type_data_length()),
iv_block.get_data(key_data->get_type_data_length()),
key_data->get_type_data_length()/16);
if (status != eap_status_ok)
{
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: iv_block"),
iv_block.get_data(),
iv_block.get_data_length()));
// multicast_key = encrypted_multicast_key XOR iv_block.
const u8_t * const pIV = iv_block.get_data(key_data->get_type_data_length());
const u8_t * const pdata = key_data->get_type_data(key_data->get_type_data_length());
u8_t * const output = multicast_key->get_data(key_data->get_type_data_length());
if (pIV == 0
|| pdata == 0
|| output == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
for (u32_t ind = 0u; ind < key_data->get_type_data_length(); ind++)
{
output[ind] = pdata[ind] ^ pIV[ind];
}
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: multicast_key"),
multicast_key->get_data(),
multicast_key->get_data_length()));
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
eap_status_e wapi_core_c::create_multicast_key(
const eap_variable_data_c * const notification_master_key,
eap_variable_data_c * const multicast_key)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TODO: WAPI_Core: this = 0x%08x, %s: wapi_core_c::create_multicast_key(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::create_multicast_key()");
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: notification_master_key"),
notification_master_key->get_data(),
notification_master_key->get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: m_key_encryption_key_KEK"),
m_key_encryption_key_KEK.get_data(),
m_key_encryption_key_KEK.get_data_length()));
// multicas_key = KD_HMAC_SHA256(notification_master_key, string label)
crypto_kd_hmac_sha256_c kd_hmac(m_am_tools);
if (kd_hmac.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
eap_variable_data_c label(m_am_tools);
if (label.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
eap_status_e status = label.add_data(WAPI_MULTICAST_KEY_EXPANSION_LABEL, WAPI_MULTICAST_KEY_EXPANSION_LABEL_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: label"),
label.get_data(),
label.get_data_length()));
status = kd_hmac.expand_key(
multicast_key,
WAPI_MULTICAST_KEY_LENGTH,
notification_master_key,
&label);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: multicast_key"),
multicast_key->get_data(),
multicast_key->get_data_length()));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
eap_status_e wapi_core_c::create_signature_attributes(
wai_variable_data_c * const data_signature,
const eap_variable_data_c * const signer_id,
const eap_variable_data_c * const signature)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::create_signature_attributes(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::create_signature_attributes()");
eap_status_e status(eap_status_process_general_error);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
wai_variable_data_c data_identity(m_am_tools);
if (data_identity.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_identity.create(
wai_payload_type_identity,
signer_id);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("data_identity"),
data_identity.get_full_tlv_buffer()->get_data(),
data_identity.get_full_tlv_buffer()->get_data_length()));
status = data_signature->create(
wai_payload_type_signature_attributes,
data_identity.get_full_tlv_buffer());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("data_signature"),
data_signature->get_full_tlv_buffer()->get_data(),
data_signature->get_full_tlv_buffer()->get_data_length()));
u8_t hash_algorithm_id(WAI_HASH_ALGORITHM_ID);
u8_t signature_algorithm_id(WAI_SIGNATURE_ALGORITHM_ID);
u8_t signature_parameter_id(WAI_SIGNATURE_PARAMETER_ID);
u16_t signature_parameter_content_length(sizeof(WAPI_ECDH_OID_PARAMETER));
u16_t signature_length(static_cast<u16_t>(signature->get_data_length()));
u16_t signature_algorithm_length(
sizeof(hash_algorithm_id)
+ sizeof(signature_algorithm_id)
+ sizeof(signature_parameter_id)
+ sizeof(signature_parameter_content_length)
+ signature_parameter_content_length);
{
u16_t network_order_signature_algorithm_length(eap_htons(signature_algorithm_length));
status = data_signature->add_data(
wai_payload_type_signature_attributes,
&network_order_signature_algorithm_length,
sizeof(network_order_signature_algorithm_length));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("data_signature"),
data_signature->get_full_tlv_buffer()->get_data(),
data_signature->get_full_tlv_buffer()->get_data_length()));
}
status = data_signature->add_data(
wai_payload_type_signature_attributes,
&hash_algorithm_id,
sizeof(hash_algorithm_id));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("data_signature"),
data_signature->get_full_tlv_buffer()->get_data(),
data_signature->get_full_tlv_buffer()->get_data_length()));
status = data_signature->add_data(
wai_payload_type_signature_attributes,
&signature_algorithm_id,
sizeof(signature_algorithm_id));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("data_signature"),
data_signature->get_full_tlv_buffer()->get_data(),
data_signature->get_full_tlv_buffer()->get_data_length()));
status = data_signature->add_data(
wai_payload_type_signature_attributes,
&signature_parameter_id,
sizeof(signature_parameter_id));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("data_signature"),
data_signature->get_full_tlv_buffer()->get_data(),
data_signature->get_full_tlv_buffer()->get_data_length()));
{
u16_t network_order_signature_parameter_content_length(eap_htons(signature_parameter_content_length));
status = data_signature->add_data(
wai_payload_type_signature_attributes,
&network_order_signature_parameter_content_length,
sizeof(network_order_signature_parameter_content_length));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("data_signature"),
data_signature->get_full_tlv_buffer()->get_data(),
data_signature->get_full_tlv_buffer()->get_data_length()));
}
status = data_signature->add_data(
wai_payload_type_signature_attributes,
WAPI_ECDH_OID_PARAMETER,
sizeof(WAPI_ECDH_OID_PARAMETER));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("data_signature"),
data_signature->get_full_tlv_buffer()->get_data(),
data_signature->get_full_tlv_buffer()->get_data_length()));
{
u16_t network_order_signature_length(eap_htons(signature_length));
status = data_signature->add_data(
wai_payload_type_signature_attributes,
&network_order_signature_length,
sizeof(network_order_signature_length));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("data_signature"),
data_signature->get_full_tlv_buffer()->get_data(),
data_signature->get_full_tlv_buffer()->get_data_length()));
}
status = data_signature->add_data(
wai_payload_type_signature_attributes,
signature);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("data_signature"),
data_signature->get_full_tlv_buffer()->get_data(),
data_signature->get_full_tlv_buffer()->get_data_length()));
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
eap_status_e wapi_core_c::parse_signature_attributes(
const wai_variable_data_c * const data_signature,
eap_variable_data_c * const signer_id,
eap_variable_data_c * const signature)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::parse_signature_attributes(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::parse_signature_attributes()");
eap_status_e status(eap_status_process_general_error);
if (signer_id == 0
|| signer_id->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
u16_t signature_length(0ul);
u16_t signature_algorithm_length(0ul);
u32_t offset(0ul);
u32_t remaining_data(data_signature->get_type_data_length());
if (remaining_data > data_signature->get_full_tlv_buffer()->get_data_length())
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
status = signer_id->reset_start_offset_and_data_length();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
{
// Read the ASN1/DER encoded Identity (Subject name, Issuer name, and Sequence number).
if (data_signature->get_data_length() < (offset+remaining_data))
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
void * const identity_header_begins = data_signature->get_type_data_offset(
offset,
remaining_data);
if (identity_header_begins == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
ec_cs_tlv_header_c identity_header(
m_am_tools,
identity_header_begins,
remaining_data);
if (identity_header.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
eap_variable_data_c input_data(
m_am_tools,
identity_header.get_data(identity_header.get_data_length()),
identity_header.get_data_length(),
false,
false);
if (input_data.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
wapi_asn1_der_parser_c asn1_der_parser(m_am_tools);
if (asn1_der_parser.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = asn1_der_parser.decode(&input_data);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = asn1_der_parser.get_wapi_identity(
signer_id);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
const u32_t used_data_length(identity_header.get_header_length() + identity_header.get_data_length());
offset += used_data_length;
remaining_data -= used_data_length;
}
{
if (data_signature->get_data_length() < (offset+sizeof(u16_t)))
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u16_t * const network_order_signature_algorithm_length =
reinterpret_cast<u16_t *>(data_signature->get_type_data_offset(
offset,
sizeof(*network_order_signature_algorithm_length)));
if (network_order_signature_algorithm_length == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
signature_algorithm_length = eap_read_u16_t_network_order(
network_order_signature_algorithm_length,
sizeof(*network_order_signature_algorithm_length));
offset += sizeof(*network_order_signature_algorithm_length) + signature_algorithm_length;
}
// NOTE, we skip all the Signature algorithm content.
{
if (data_signature->get_data_length() < (offset+sizeof(u16_t)))
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u16_t * const network_order_signature_length = reinterpret_cast<u16_t *>(data_signature->get_type_data_offset(
offset,
sizeof(*network_order_signature_length)));
if (network_order_signature_length == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
signature_length = eap_read_u16_t_network_order(
network_order_signature_length,
sizeof(*network_order_signature_length));
offset += sizeof(*network_order_signature_length);
}
{
if (data_signature->get_data_length() < (offset+signature_length))
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u8_t * const pointer_to_signature = data_signature->get_type_data_offset(
offset,
signature_length);
if (pointer_to_signature == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = signature->set_copy_of_buffer(
pointer_to_signature,
signature_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
offset += signature_length;
}
if (offset != data_signature->get_type_data_length())
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
eap_status_e wapi_core_c::create_result_of_certificate_verification(
wai_variable_data_c * const result_of_certificate_verification,
const eap_variable_data_c * const ae_challenge,
const eap_variable_data_c * const asue_challenge,
const wapi_certificate_result_e asue_certificate_result,
const eap_variable_data_c * const asue_certificate,
const wapi_certificate_result_e ae_certificate_result,
const eap_variable_data_c * const ae_certificate)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::create_result_of_certificate_verification(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::create_result_of_certificate_verification()");
eap_status_e status(eap_status_process_general_error);
if (result_of_certificate_verification == 0
|| result_of_certificate_verification->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
if (ae_challenge == 0
|| ae_challenge->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
if (asue_challenge == 0
|| asue_challenge->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
if (asue_certificate == 0
|| asue_certificate->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
if (ae_certificate == 0
|| ae_certificate->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::create_result_of_certificate_verification(): ae_challenge"),
ae_challenge->get_data(),
ae_challenge->get_data_length()));
status = result_of_certificate_verification->create(
wai_payload_type_result_of_certificate_verification,
ae_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::create_result_of_certificate_verification(): asue_challenge"),
asue_challenge->get_data(),
asue_challenge->get_data_length()));
status = result_of_certificate_verification->add_data(
wai_payload_type_result_of_certificate_verification,
asue_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
{
u8_t verification_result_1(asue_certificate_result);
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::create_result_of_certificate_verification(): verification_result_1"),
&verification_result_1,
sizeof(verification_result_1)));
status = result_of_certificate_verification->add_data(
wai_payload_type_result_of_certificate_verification,
&verification_result_1,
sizeof(verification_result_1));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
{
wai_variable_data_c data_asue_certificate(m_am_tools);
if (data_asue_certificate.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::create_result_of_certificate_verification(): asue_certificate"),
asue_certificate->get_data(),
asue_certificate->get_data_length()));
status = data_asue_certificate.create(
wai_payload_type_certificate,
asue_certificate);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = result_of_certificate_verification->add_data(
wai_payload_type_result_of_certificate_verification,
data_asue_certificate.get_full_tlv_buffer());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
{
u8_t verification_result_2(ae_certificate_result);
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::create_result_of_certificate_verification(): verification_result_2"),
&verification_result_2,
sizeof(verification_result_2)));
status = result_of_certificate_verification->add_data(
wai_payload_type_result_of_certificate_verification,
&verification_result_2,
sizeof(verification_result_2));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
{
wai_variable_data_c data_ae_certificate(m_am_tools);
if (data_ae_certificate.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::create_result_of_certificate_verification(): ae_certificate"),
ae_certificate->get_data(),
ae_certificate->get_data_length()));
status = data_ae_certificate.create(
wai_payload_type_certificate,
ae_certificate);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = result_of_certificate_verification->add_data(
wai_payload_type_result_of_certificate_verification,
data_ae_certificate.get_full_tlv_buffer());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
eap_status_e wapi_core_c::parse_result_of_certificate_verification(
const wai_variable_data_c * const result_of_certificate_verification,
eap_variable_data_c * const ae_challenge,
eap_variable_data_c * const asue_challenge,
wapi_certificate_result_e * const asue_certificate_result,
eap_variable_data_c * const asue_certificate,
wapi_certificate_result_e * const ae_certificate_result,
eap_variable_data_c * const ae_certificate)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::parse_result_of_certificate_verification(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::parse_result_of_certificate_verification()");
eap_status_e status(eap_status_process_general_error);
if (result_of_certificate_verification == 0
|| result_of_certificate_verification->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
if (ae_challenge == 0
|| ae_challenge->get_is_valid() == false
|| asue_challenge == 0
|| asue_challenge->get_is_valid() == false
|| asue_certificate == 0
|| asue_certificate->get_is_valid() == false
|| ae_certificate == 0
|| ae_certificate->get_is_valid() == false
|| asue_certificate_result == 0
|| ae_certificate_result == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
u32_t offset(0ul);
if (result_of_certificate_verification->get_type_data_length() < (offset+WAPI_CHALLENGE_LENGTH))
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
status = ae_challenge->set_copy_of_buffer(
result_of_certificate_verification->get_type_data_offset(offset, WAPI_CHALLENGE_LENGTH),
WAPI_CHALLENGE_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
offset += WAPI_CHALLENGE_LENGTH;
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::parse_result_of_certificate_verification(): ae_challenge"),
ae_challenge->get_data(),
ae_challenge->get_data_length()));
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (result_of_certificate_verification->get_type_data_length() < (offset+WAPI_CHALLENGE_LENGTH))
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
status = asue_challenge->set_copy_of_buffer(
result_of_certificate_verification->get_type_data_offset(offset, WAPI_CHALLENGE_LENGTH),
WAPI_CHALLENGE_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
offset += WAPI_CHALLENGE_LENGTH;
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::parse_result_of_certificate_verification(): asue_challenge"),
asue_challenge->get_data(),
asue_challenge->get_data_length()));
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{
if (result_of_certificate_verification->get_type_data_length() < (offset+sizeof(u8_t)))
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u8_t * const verification_result_1 = result_of_certificate_verification->get_type_data_offset(offset, sizeof(*verification_result_1));
if (verification_result_1 == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
*asue_certificate_result = static_cast<wapi_certificate_result_e>(*verification_result_1);
offset += sizeof(*verification_result_1);
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::parse_result_of_certificate_verification(): verification_result_1"),
verification_result_1,
sizeof(*verification_result_1)));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{
if (result_of_certificate_verification->get_type_data_length() < offset)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
u32_t data_length(result_of_certificate_verification->get_type_data_length() - offset);
if (result_of_certificate_verification->get_type_data_length() < (offset+data_length))
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
ec_cs_tlv_header_c certificate_1(
m_am_tools,
result_of_certificate_verification->get_type_data_offset(offset, data_length),
data_length);
if (certificate_1.get_is_valid() == false
|| certificate_1.check_header() != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = asue_certificate->set_copy_of_buffer(
certificate_1.get_data(certificate_1.get_data_length()),
certificate_1.get_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
offset += (certificate_1.get_header_length() + certificate_1.get_data_length());
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::parse_result_of_certificate_verification(): asue_certificate"),
asue_certificate->get_data(),
asue_certificate->get_data_length()));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{
if (result_of_certificate_verification->get_type_data_length() < (offset+sizeof(u8_t)))
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u8_t * const verification_result_2 = result_of_certificate_verification->get_type_data_offset(offset, sizeof(*verification_result_2));
if (verification_result_2 == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
*ae_certificate_result = static_cast<wapi_certificate_result_e>(*verification_result_2);
offset += sizeof(*verification_result_2);
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::parse_result_of_certificate_verification(): verification_result_2"),
verification_result_2,
sizeof(*verification_result_2)));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{
if (result_of_certificate_verification->get_type_data_length() < offset)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
u32_t data_length(result_of_certificate_verification->get_type_data_length() - offset);
if (result_of_certificate_verification->get_type_data_length() < (offset+data_length))
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
ec_cs_tlv_header_c certificate_2(
m_am_tools,
result_of_certificate_verification->get_type_data_offset(offset, data_length),
data_length);
if (certificate_2.get_is_valid() == false
|| certificate_2.check_header() != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = ae_certificate->set_copy_of_buffer(
certificate_2.get_data(certificate_2.get_data_length()),
certificate_2.get_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
offset += (certificate_2.get_header_length() + certificate_2.get_data_length());
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::parse_result_of_certificate_verification(): ae_certificate"),
ae_certificate->get_data(),
ae_certificate->get_data_length()));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
eap_status_e wapi_core_c::packet_send(
wai_message_c * const new_wai_message_data,
const wai_protocol_subtype_e wapi_subtype)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::packet_send(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::packet_send()");
eap_status_e status(eap_status_process_general_error);
if (new_wai_message_data == 0
|| new_wai_message_data->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Here we swap the addresses.
eap_am_network_id_c send_network_id(m_am_tools,
m_receive_network_id.get_destination_id(),
m_receive_network_id.get_source_id(),
m_receive_network_id.get_type());
if (send_network_id.get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
EAP_ASSERT_ALWAYS(m_MTU > m_trailer_length);
#if defined(USE_WAPI_CORE_SERVER)
if (m_is_client == false)
{
++m_packet_sequence_number;
}
#endif //#if defined(USE_WAPI_CORE_SERVER)
// Both client and server initializes re-transmission.
// Client will process re-transmitted request again.
// Server will re-transmit the packet when timer elapses and no response is received.
init_retransmission(
&send_network_id,
&m_received_wai_message_data,
new_wai_message_data,
m_packet_sequence_number,
wapi_subtype);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
status = packet_fragment(new_wai_message_data, m_packet_sequence_number);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
eap_status_e wapi_core_c::packet_fragment(
wai_message_c * const new_wai_message_data,
const u16_t packet_sequence_number)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::packet_fragment(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::packet_fragment()");
eap_status_e status(eap_status_process_general_error);
if (new_wai_message_data == 0
|| new_wai_message_data->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Here we swap the addresses.
eap_am_network_id_c send_network_id(m_am_tools,
m_receive_network_id.get_destination_id(),
m_receive_network_id.get_source_id(),
m_receive_network_id.get_type());
if (send_network_id.get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
EAP_ASSERT_ALWAYS(m_MTU > m_trailer_length);
wai_protocol_packet_header_c wai(
m_am_tools,
new_wai_message_data->get_wai_message_data()->get_data(),
new_wai_message_data->get_wai_message_data()->get_data_length());
if (wai.get_is_valid() == false)
{
EAP_TRACE_ERROR(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::packet_fragment(): %s, packet buffer corrupted.\n"),
(m_is_client_role == true) ? "client": "server"
));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
}
WAI_PROTOCOL_PACKET_TRACE_HEADER("full packet", &wai, m_is_client);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const u32_t data_length(wai.get_data_length());
const u32_t header_length(wai.get_header_length());
const u32_t FRAGMENT_MULTIPLIER = 8ul;
const u32_t header_remainder_length(header_length % FRAGMENT_MULTIPLIER);
const u32_t data_mtu(m_MTU - header_length - header_remainder_length);
const u32_t data_mtu_8(data_mtu - (data_mtu % FRAGMENT_MULTIPLIER));
u32_t data_fragment_length = (header_remainder_length + data_mtu_8);
const u32_t fragment_count = ((data_length + data_fragment_length - 1) / data_fragment_length);
if (fragment_count == 1ul
&& data_length < data_fragment_length)
{
data_fragment_length = data_length;
}
const u32_t last_data_fragment_length = (data_length - ((fragment_count-1) * data_fragment_length));
const u32_t one_packet_length = (header_length + data_fragment_length);
EAP_UNREFERENCED_PARAMETER(one_packet_length);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::packet_fragment(): packet_sequence_number=%d, m_MTU=%d, packet_length=%d, data_length=%d, fragment_count=%d, data_fragment_length=%d, last_data_fragment_length=%d, one_packet_length=%d\n"),
packet_sequence_number,
m_MTU,
(header_length+data_length),
data_length,
fragment_count,
data_fragment_length,
last_data_fragment_length,
one_packet_length));
EAP_ASSERT(last_data_fragment_length <= data_fragment_length);
u32_t current_fragment_length(data_fragment_length);
for (u32_t frag_ind = 0ul; frag_ind < fragment_count; ++frag_ind)
{
u32_t buffer_size = m_wapi_header_offset + wai.get_header_length() + current_fragment_length + m_trailer_length;
// Creates a fragment.
eap_buf_chain_wr_c wai_packet(
eap_write_buffer,
m_am_tools,
buffer_size);
if (wai_packet.get_is_valid() == false)
{
EAP_TRACE_ERROR(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::packet_fragment(): %s, packet buffer corrupted.\n"),
(m_is_client == true) ? "client": "server"
));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = wai_packet.add_data_to_offset(
m_wapi_header_offset,
wai.get_header_buffer(wai.get_header_length()),
wai.get_header_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = wai_packet.add_data_to_offset(
m_wapi_header_offset+wai.get_header_length(),
wai.get_data_offset(frag_ind * data_fragment_length, current_fragment_length),
current_fragment_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
wai_protocol_packet_header_c wai_fragment_header(
m_am_tools,
wai_packet.get_data_offset(m_wapi_header_offset, wai.get_header_length() + current_fragment_length),
wai.get_header_length() + current_fragment_length);
if (wai_fragment_header.get_is_valid() == false)
{
EAP_TRACE_ERROR(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::packet_fragment(): %s, packet buffer corrupted.\n"),
(m_is_client_role == true) ? "client": "server"
));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
}
status = wai_fragment_header.set_packet_sequence_number(packet_sequence_number);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = wai_fragment_header.set_fragment_sequence_number(static_cast<u8_t>(frag_ind));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = wai_fragment_header.set_length(wai.get_header_length() + current_fragment_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
if ((frag_ind+1ul) < fragment_count)
{
// Not last fragment.
wai_fragment_header.set_flag(wai_fragment_header.get_flag() | wai_protocol_packet_header_c::m_flag_mask_fragment_exists);
}
else
{
// Last fragment.
wai_fragment_header.set_flag(wai_fragment_header.get_flag() & ~wai_protocol_packet_header_c::m_flag_mask_fragment_exists);
}
if ((frag_ind+2ul) == fragment_count)
{
current_fragment_length = last_data_fragment_length;
}
WAI_PROTOCOL_PACKET_TRACE_HEADER("fragment", &wai_fragment_header, m_is_client);
status = packet_send(
&send_network_id,
&wai_packet,
m_wapi_header_offset,
wai_fragment_header.get_length(),
buffer_size);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
eap_status_e wapi_core_c::packet_reassemble(const wai_protocol_packet_header_c * const wai)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::packet_reassemble(): wait fragment number %d, packet fragment number %d, state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
m_fragment_sequence_number,
wai->get_fragment_sequence_number(),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL(" %s: wapi_core_c::packet_reassemble(): sequence number %d, required sequence number %d.\n"),
(m_is_client == true) ? "client": "server",
wai->get_packet_sequence_number(),
m_packet_sequence_number));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::packet_reassemble()");
eap_status_e status(eap_status_process_general_error);
if (wai == 0
|| wai->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
status = wai->check_header();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (wai->get_fragment_sequence_number() != m_fragment_sequence_number)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::packet_reassemble(): fragment sequence number %d != required fragment sequence number %d.\n"),
(m_is_client == true) ? "client": "server",
wai->get_fragment_sequence_number(),
m_fragment_sequence_number));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
wai_protocol_packet_header_c reass_wai(
m_am_tools);
if (wai->get_fragment_sequence_number() == 0u)
{
m_reassemble_packet.reset();
// Add header and data.
status = m_reassemble_packet.set_copy_of_buffer(
wai->get_header_buffer(wai->get_length()),
wai->get_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = reass_wai.set_header_buffer(
m_reassemble_packet.get_data(),
m_reassemble_packet.get_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
else
{
status = reass_wai.set_header_buffer(
m_reassemble_packet.get_data(),
m_reassemble_packet.get_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
if (wai->get_packet_sequence_number() != reass_wai.get_packet_sequence_number())
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::packet_reassemble(): sequence number %d != required sequence number %d.\n"),
(m_is_client == true) ? "client": "server",
wai->get_packet_sequence_number(),
reass_wai.get_packet_sequence_number()));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
if (wai->get_subtype() != reass_wai.get_subtype())
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::packet_reassemble(): sub-type %d != required sub-type %d.\n"),
(m_is_client == true) ? "client": "server",
wai->get_subtype(),
reass_wai.get_subtype()));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
// Add data.
status = m_reassemble_packet.add_data(
wai->get_data(wai->get_data_length()),
wai->get_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = reass_wai.set_header_buffer(
m_reassemble_packet.get_data(),
m_reassemble_packet.get_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = reass_wai.set_length(reass_wai.get_length() + wai->get_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = reass_wai.set_fragment_sequence_number(wai->get_fragment_sequence_number());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
status = reass_wai.set_flag(wai->get_flag());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
++m_fragment_sequence_number;
WAI_PROTOCOL_PACKET_TRACE_HEADER("reassembled packet", &reass_wai, m_is_client_role);
if ((reass_wai.get_flag() & wai_protocol_packet_header_c::m_flag_mask_fragment_exists) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_pending_request);
}
status = m_received_wai_message_data.set_wai_message_data(&m_reassemble_packet);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// This is the last fragment.
m_fragment_sequence_number = 0ul;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::start_authentication()
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::start_authentication(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::start_authentication()");
eap_status_e status(eap_status_process_general_error);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
m_fragment_sequence_number = 0ul;
m_packet_sequence_number = 0ul;
#if defined(USE_WAPI_CORE_SERVER)
if (m_wapi_negotiation_state == wapi_negotiation_state_none
|| m_only_initial_authentication == true)
{
m_wapi_negotiation_state = wapi_negotiation_state_initial_negotiation;
}
else if (m_wapi_negotiation_state == wapi_negotiation_state_initial_negotiation)
{
m_wapi_negotiation_state = wapi_negotiation_state_rekeying;
}
else if (m_wapi_negotiation_state == wapi_negotiation_state_rekeying)
{
// Randomly change to initial negotiation.
crypto_random_c rand(m_am_tools);
if (rand.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
const u32_t MIN_LIMIT = 0ul;
const u32_t MAX_LIMIT = 100ul;
const u32_t SELECTION_LIMIT = MAX_LIMIT/2ul;
if (rand.get_rand_integer(MIN_LIMIT, MAX_LIMIT) <= SELECTION_LIMIT)
{
m_wapi_negotiation_state = wapi_negotiation_state_initial_negotiation;
}
}
if (m_is_client == false
&& (m_wapi_state == wapi_core_state_none
|| m_wapi_state == wapi_core_state_authentication_ok
|| m_wapi_state == wapi_core_state_authentication_failed))
{
if (m_authentication_type == eapol_key_authentication_type_WAI_PSK)
{
set_wapi_state(wapi_core_state_start_unicast_key_negotiation);
status = start_unicast_key_negotiation();
}
else if (m_authentication_type == eapol_key_authentication_type_WAI_certificate)
{
set_wapi_state(wapi_core_state_start_certificate_negotiation);
status = start_certificate_negotiation();
}
else
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_authentication_type);
}
}
else
#endif //#if defined(USE_WAPI_CORE_SERVER)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::start_authentication(): Verify state %s != %s, negotiation state = %s.\n"),
(m_is_client == true) ? "client": "server",
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_core_state_string(wapi_core_state_none),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
status = eap_status_unexpected_message;
(void) EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::allow_authentication()
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::allow_authentication(): state=%s, negotiation_state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::allow_authentication()");
eap_status_e status(eap_status_process_general_error);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
m_fragment_sequence_number = 0ul;
if (m_wapi_negotiation_state == wapi_negotiation_state_none)
{
m_wapi_negotiation_state = wapi_negotiation_state_initial_negotiation;
}
else if (m_wapi_negotiation_state == wapi_negotiation_state_initial_negotiation)
{
m_wapi_negotiation_state = wapi_negotiation_state_rekeying;
}
if (m_wapi_state == wapi_core_state_none)
{
if (m_authentication_type == eapol_key_authentication_type_WAI_PSK)
{
set_wapi_state(wapi_core_state_wait_unicast_key_negotiation_request_message);
status = eap_status_ok;
}
else if (m_authentication_type == eapol_key_authentication_type_WAI_certificate)
{
set_wapi_state(wapi_core_state_wait_authentication_activation_message);
status = eap_status_ok;
}
else
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_authentication_type);
}
}
else
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::allow_authentication(): Verify state %s != %s, negotiation state = %s.\n"),
(m_is_client == true) ? "client": "server",
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_core_state_string(wapi_core_state_none),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::init_bksa_caching_timeout()
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::init_bksa_caching_timeout(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::init_bksa_caching_timeout()");
eap_status_e status(eap_status_process_general_error);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("%s: Removes BKSA cache\n"),
(m_is_client == true ? "client": "server")));
// Now we do not use BKSA cache, clean-up state.
(void) reset();
// Timeout value zero will remove state immediately.
status = set_session_timeout(0ul);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::reset_cached_bksa()
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::reset_cached_bksa(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::reset_cached_bksa()");
eap_status_e status(eap_status_process_general_error);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Now we do not use BKSA cache, clean-up state.
status = reset();
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::read_reassociation_parameters(
const eap_am_network_id_c * const /* receive_network_id */, ///< source includes remote address, destination includes local address.
const eapol_key_authentication_type_e /* required_authentication_type */,
eap_variable_data_c * const /* BKSA */,
const eap_variable_data_c * const /* received_ie */,
const eap_variable_data_c * const /* sent_ie */)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::read_reassociation_parameters(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::read_reassociation_parameters()");
eap_status_e status(eap_status_process_general_error);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Now we do not support cached BKSAs.
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
#if defined(USE_WAPI_CORE_SERVER)
eap_status_e wapi_core_c::increase_u128_t_network_order(
eap_variable_data_c * const u128_t_integer) const
{
u64_t half_integer[2];
half_integer[1ul] = eap_read_u64_t_network_order(
u128_t_integer->get_data(sizeof(u64_t)),
sizeof(u64_t));
half_integer[0ul] = eap_read_u64_t_network_order(
u128_t_integer->get_data_offset(sizeof(u64_t), sizeof(u64_t)),
sizeof(u64_t));
if (half_integer[0ul] == (~0UL))
{
++half_integer[1ul];
}
++half_integer[0ul];
eap_status_e status = eap_write_u64_t_network_order(
u128_t_integer->get_data(sizeof(u64_t)),
sizeof(u64_t),
half_integer[1ul]);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = eap_write_u64_t_network_order(
u128_t_integer->get_data_offset(sizeof(u64_t), sizeof(u64_t)),
sizeof(u64_t),
half_integer[0ul]);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
#endif //#if defined(USE_WAPI_CORE_SERVER)
//--------------------------------------------------
#if defined(USE_WAPI_CORE_SERVER)
eap_status_e wapi_core_c::start_certificate_negotiation()
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::start_certificate_negotiation(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::start_certificate_negotiation()");
eap_status_e status(eap_status_process_general_error);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
m_packet_sequence_number = 0u;
status = m_ec_certificate_store->query_asu_id();
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
#endif //#if defined(USE_WAPI_CORE_SERVER)
//--------------------------------------------------
#if defined(USE_WAPI_CORE_SERVER)
eap_status_e wapi_core_c::start_unicast_key_negotiation()
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::start_unicast_key_negotiation(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::start_unicast_key_negotiation()");
eap_status_e status(eap_status_process_general_error);
if (m_authentication_type != eapol_key_authentication_type_WAI_PSK
&& m_authentication_type != eapol_key_authentication_type_WAI_certificate)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_authentication_type);
}
if (m_wapi_state != wapi_core_state_start_unicast_key_negotiation)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::start_unicast_key_negotiation(): Verify state %s != %s, negotiation state = %s.\n"),
(m_is_client == true) ? "client": "server",
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_core_state_string(wapi_core_state_start_unicast_key_negotiation),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create BKID.
status = create_BKID(&m_BKID, &m_receive_network_id);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create AE challenge.
if (m_wapi_negotiation_state == wapi_negotiation_state_initial_negotiation)
{
crypto_random_c rand(m_am_tools);
if (rand.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = rand.get_rand_bytes(
&m_ae_unicast_challenge,
WAPI_CHALLENGE_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
else
{
status = m_ae_unicast_challenge.set_copy_of_buffer(&m_next_unicast_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create the Unicast Key Negotiation Request message.
wai_message_payloads_c * const payloads = new wai_message_payloads_c(m_am_tools, m_is_client);
eap_automatic_variable_c<wai_message_payloads_c> automatic_payloads(m_am_tools, payloads);
if (payloads == 0
|| payloads->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = payloads->initialise_header();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->get_wai_protocol_packet_header_writable()->set_subtype(wai_protocol_subtype_unicast_key_negotiation_request);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds FLAG to data field.
{
wai_variable_data_c data_flag(m_am_tools);
if (data_flag.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
u8_t flag(wai_data_flag_mask_none);
if (m_wapi_negotiation_state == wapi_negotiation_state_rekeying)
{
flag = wai_data_flag_mask_USK_Rekeying;
}
status = data_flag.create(
wai_payload_type_flag,
&flag,
sizeof(flag));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_flag);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds BKID to data field.
{
wai_variable_data_c data_BKID(m_am_tools);
if (data_BKID.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_BKID.create(
wai_payload_type_bkid,
&m_BKID);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_BKID);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds USKID to data field.
{
wai_variable_data_c data_USKID(m_am_tools);
if (data_USKID.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
if (m_wapi_negotiation_state == wapi_negotiation_state_rekeying)
{
m_USKID = (m_USKID + 1u) % 2;
}
status = data_USKID.create(
wai_payload_type_uskid,
&m_USKID,
sizeof(m_USKID));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_USKID);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds ADDID to data field.
{
wai_variable_data_c data_ADDID(m_am_tools);
if (data_ADDID.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
const eap_variable_data_c * MAC_1 = m_receive_network_id.get_source_id();
const eap_variable_data_c * MAC_2 = m_receive_network_id.get_destination_id();
if (m_is_client == true)
{
MAC_1 = m_receive_network_id.get_destination_id();
MAC_2 = m_receive_network_id.get_source_id();
}
status = data_ADDID.create(
wai_payload_type_addid,
MAC_1);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = data_ADDID.add_data(
wai_payload_type_addid,
MAC_2);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_ADDID);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds AE Challenge to data field.
{
wai_variable_data_c data_AE_challenge(m_am_tools);
if (data_AE_challenge.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_AE_challenge.create(
wai_payload_type_nonce,
&m_ae_unicast_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_AE_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create and send message.
wai_message_c new_wai_message_data(m_am_tools, m_is_client);
if (new_wai_message_data.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->create_wai_tlv_message(&new_wai_message_data, false);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//m_packet_sequence_number = 0u;
//cancel_retransmission();
status = packet_send(
&new_wai_message_data,
payloads->get_wai_protocol_packet_header_writable()->get_subtype());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
set_wapi_state(wapi_core_state_wait_unicast_key_negotiation_response_message);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
#endif //#if defined(USE_WAPI_CORE_SERVER)
//--------------------------------------------------
#if defined(USE_WAPI_CORE_SERVER)
eap_status_e wapi_core_c::start_multicast_key_announcement()
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::start_multicast_key_announcement(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::start_multicast_key_announcement()");
eap_status_e status(eap_status_process_general_error);
if (m_authentication_type != eapol_key_authentication_type_WAI_PSK
&& m_authentication_type != eapol_key_authentication_type_WAI_certificate)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_authentication_type);
}
if (m_wapi_state != wapi_core_state_start_multicast_key_announcement)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::start_multicast_key_announcement(): Verify state %s != %s, negotiation state = %s.\n"),
(m_is_client == true) ? "client": "server",
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_core_state_string(wapi_core_state_start_multicast_key_announcement),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create multicast key.
crypto_random_c rand(m_am_tools);
if (rand.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
eap_variable_data_c notification_master_key(m_am_tools);
if (notification_master_key.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = rand.get_rand_bytes(
¬ification_master_key,
WAPI_NOTIFICATION_MASTER_KEY_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = create_multicast_key(¬ification_master_key, &m_multicast_key);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create the Multicast Key announcement message.
wai_message_payloads_c * const payloads = new wai_message_payloads_c(m_am_tools, m_is_client);
eap_automatic_variable_c<wai_message_payloads_c> automatic_payloads(m_am_tools, payloads);
if (payloads == 0
|| payloads->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = payloads->initialise_header();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->get_wai_protocol_packet_header_writable()->set_subtype(wai_protocol_subtype_multicast_key_announcement);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds FLAG to data field.
{
wai_variable_data_c data_flag(m_am_tools);
if (data_flag.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
u8_t flag(wai_data_flag_mask_none);
status = data_flag.create(
wai_payload_type_flag,
&flag,
sizeof(flag));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_flag);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds MSKID to data field.
{
wai_variable_data_c data_flag(m_am_tools);
if (data_flag.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
if (m_wapi_negotiation_state == wapi_negotiation_state_initial_negotiation)
{
m_MSKID = 0u;
}
else
{
m_MSKID = (m_MSKID + 1u) % 2;
}
status = data_flag.create(
wai_payload_type_mskid_stakeyid,
&m_MSKID,
sizeof(m_MSKID));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_flag);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds USKID to data field.
{
wai_variable_data_c data_USKID(m_am_tools);
if (data_USKID.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_USKID.create(
wai_payload_type_uskid,
&m_USKID,
sizeof(m_USKID));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_USKID);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds ADDID to data field.
{
wai_variable_data_c data_ADDID(m_am_tools);
if (data_ADDID.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
const eap_variable_data_c * MAC_1 = m_receive_network_id.get_source_id();
const eap_variable_data_c * MAC_2 = m_receive_network_id.get_destination_id();
if (m_is_client == true)
{
MAC_1 = m_receive_network_id.get_destination_id();
MAC_2 = m_receive_network_id.get_source_id();
}
status = data_ADDID.create(
wai_payload_type_addid,
MAC_1);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = data_ADDID.add_data(
wai_payload_type_addid,
MAC_2);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_ADDID);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds Data Packet Number to data field.
{
wai_variable_data_c data_packet_number(m_am_tools);
if (data_packet_number.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
if (m_wapi_negotiation_state == wapi_negotiation_state_initial_negotiation)
{
const u8_t TEST_DATA_PACKET_NUMBER[] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
status = m_packet_data_number.set_copy_of_buffer(
TEST_DATA_PACKET_NUMBER,
sizeof(TEST_DATA_PACKET_NUMBER));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
else
{
status = increase_u128_t_network_order(
&m_packet_data_number);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
status = data_packet_number.create(
wai_payload_type_data_sequence_number,
&m_packet_data_number);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_packet_number);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds Key Announcement to data field.
{
wai_variable_data_c key_announcement(m_am_tools);
if (key_announcement.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
if (m_wapi_negotiation_state == wapi_negotiation_state_initial_negotiation)
{
const u8_t TEST_KEY_ANNOUNCEMENT[] =
{
0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36,
};
status = m_key_announcement.set_copy_of_buffer(
TEST_KEY_ANNOUNCEMENT,
sizeof(TEST_KEY_ANNOUNCEMENT));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
else
{
status = increase_u128_t_network_order(
&m_key_announcement);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
status = key_announcement.create(
wai_payload_type_key_announcement_identifier,
&m_key_announcement);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&key_announcement);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds Key Data to data field.
{
wai_variable_data_c key_data(m_am_tools);
if (key_data.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = encrypt_multicast_key_data(¬ification_master_key, &m_key_announcement, &key_data);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&key_data);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds MAC to data field.
{
wai_variable_data_c data_MAC(m_am_tools);
if (data_MAC.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
eap_variable_data_c MAC(m_am_tools);
if (MAC.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = create_MAC(payloads, &MAC);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = MAC.set_data_length(WAPI_MESSAGE_AUTHENTICATION_CODE_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = data_MAC.create(
wai_payload_type_message_authentication_code,
&MAC);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_MAC);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create and send message.
wai_message_c new_wai_message_data(m_am_tools, m_is_client);
if (new_wai_message_data.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->create_wai_tlv_message(&new_wai_message_data, false);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//m_packet_sequence_number = 0u;
//cancel_retransmission();
status = packet_send(
&new_wai_message_data,
payloads->get_wai_protocol_packet_header_writable()->get_subtype());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
set_wapi_state(wapi_core_state_wait_multicast_announcement_response_message);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
#endif //#if defined(USE_WAPI_CORE_SERVER)
//--------------------------------------------------
eap_status_e wapi_core_c::handle_authentication_activation(
const eap_am_network_id_c * const receive_network_id,
const wai_protocol_packet_header_c * const wai)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::handle_authentication_activation(): state=%s, negotiation state = %s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::handle_authentication_activation()");
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
eap_status_e status(eap_status_process_general_error);
if (m_authentication_type != eapol_key_authentication_type_WAI_certificate)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_authentication_type);
}
if (m_wapi_state != wapi_core_state_wait_authentication_activation_message
&& m_wapi_state != wapi_core_state_wait_access_authentication_response_message
&& m_wapi_state != wapi_core_state_authentication_ok)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::handle_authentication_activation(): Verify state %s != %s, negotiation state = %s.\n"),
(m_is_client == true) ? "client": "server",
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_core_state_string(wapi_core_state_wait_authentication_activation_message),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
if (receive_network_id == 0
|| receive_network_id->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
if (wai == 0
|| wai->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
}
status = wai->check_header();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (wai->get_packet_sequence_number() != WAI_FIRST_SEQUENCE_NUMBER)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::handle_authentication_activation(): sequence number %d != required sequence number %d.\n"),
(m_is_client == true) ? "client": "server",
wai->get_packet_sequence_number(),
WAI_FIRST_SEQUENCE_NUMBER));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
m_packet_sequence_number = WAI_FIRST_SEQUENCE_NUMBER;
set_wapi_state(wapi_core_state_process_authentication_activation_message);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (m_authentication_type == eapol_key_authentication_type_WAI_certificate)
{
// Here we swap the addresses.
eap_am_network_id_c send_network_id(m_am_tools,
m_receive_network_id.get_destination_id(),
m_receive_network_id.get_source_id(),
m_receive_network_id.get_type());
if (send_network_id.get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
// This is notification to eapol_core_c object.
// WAI unicast negotiation started successfully.
eap_state_notification_c * notification = new eap_state_notification_c(
m_am_tools,
&send_network_id,
m_is_client,
eap_state_notification_generic,
eap_protocol_layer_wai,
eapol_key_handshake_type_wai_handshake,
eapol_key_state_wapi_authentication_running,
eapol_key_state_wapi_authentication_running,
0ul,
false);
if (notification == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
m_partner->state_notification(notification);
delete notification;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
wai_message_payloads_c parser(
m_am_tools,
m_is_client);
if (parser.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
u32_t padding_length(0ul);
status = parser.parse_wai_payloads(
wai->get_header_buffer(wai->get_header_buffer_length()), ///< This is the start of the message buffer.
wai->get_header_buffer_length(), ///< This is the length of the buffer. This must match with the length of all payloads.
&padding_length ///< Length of possible padding is set to this variable.
);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify BK rekeying flag.
{
wai_variable_data_c * const flag_payload = parser.get_tlv_pointer(wai_payload_type_flag);
if (flag_payload == 0
|| flag_payload->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u8_t * const flag = flag_payload->get_data(sizeof(*flag));
if (flag == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (m_wapi_negotiation_state == wapi_negotiation_state_rekeying)
{
if (((*flag) & wai_data_flag_mask_BK_Rekeying) == 0)
{
m_wapi_negotiation_state = wapi_negotiation_state_initial_negotiation;
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WARNING: WAPI_Core: this = 0x%08x, %s: wapi_core_c::handle_authentication_activation(): changed to %s.\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
}
}
else
{
if (((*flag) & wai_data_flag_mask_BK_Rekeying) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Save Authentication Identifier.
{
wai_variable_data_c * const authentication_identifier = parser.get_tlv_pointer(wai_payload_type_authentication_identifier);
if (authentication_identifier == 0
|| authentication_identifier->get_is_valid_data() == false
|| authentication_identifier->get_data_length() < WAPI_AUTHENTICATION_IDENTIFIER_LENGTH)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (m_wapi_negotiation_state == wapi_negotiation_state_rekeying)
{
// Verify the Authentication Identifier.
if (m_am_tools->memcmp(
m_authentication_identifier.get_data(WAPI_AUTHENTICATION_IDENTIFIER_LENGTH),
authentication_identifier->get_data(WAPI_AUTHENTICATION_IDENTIFIER_LENGTH),
WAPI_AUTHENTICATION_IDENTIFIER_LENGTH) != 0)
{
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: local m_authentication_identifier"),
m_authentication_identifier.get_data(),
m_authentication_identifier.get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: received authentication_identifier"),
authentication_identifier->get_data(WAPI_AUTHENTICATION_IDENTIFIER_LENGTH),
WAPI_AUTHENTICATION_IDENTIFIER_LENGTH));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
else
{
status = m_authentication_identifier.set_copy_of_buffer(
authentication_identifier->get_type_data(WAPI_AUTHENTICATION_IDENTIFIER_LENGTH),
WAPI_AUTHENTICATION_IDENTIFIER_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Save ASU-ID.
{
wai_variable_data_c * const asu_id = parser.get_tlv_pointer(wai_payload_type_identity);
if (asu_id == 0
|| asu_id->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
status = m_asu_id.set_copy_of_buffer(
asu_id->get_type_data(asu_id->get_type_data_length()),
asu_id->get_type_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_asu_id"),
m_asu_id.get_data(),
m_asu_id.get_data_length()));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Save STA_AE certificate.
{
wai_variable_data_c * const sta_ae_certificate = parser.get_tlv_pointer(wai_payload_type_certificate);
if (sta_ae_certificate == 0
|| sta_ae_certificate->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
status = m_peer_certificate.set_copy_of_buffer(
sta_ae_certificate->get_type_data(sta_ae_certificate->get_type_data_length()),
sta_ae_certificate->get_type_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify the ECDH parameter.
{
wai_variable_data_c * const echd_parameter = parser.get_tlv_pointer(wai_payload_type_echd_parameter);
if (echd_parameter == 0
|| echd_parameter->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (sizeof(WAPI_ECDH_OID_PARAMETER) != echd_parameter->get_type_data_length()
|| m_am_tools->memcmp(
WAPI_ECDH_OID_PARAMETER,
echd_parameter->get_type_data(sizeof(WAPI_ECDH_OID_PARAMETER)),
sizeof(WAPI_ECDH_OID_PARAMETER)) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create ASUE challenge.
if (m_asue_certificate_challenge.get_is_valid_data() == false)
{
crypto_random_c rand(m_am_tools);
if (rand.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = rand.get_rand_bytes(
&m_asue_certificate_challenge,
WAPI_CHALLENGE_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Selects own certificate issued by ASU-ID.
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_asu_id"),
m_asu_id.get_data(),
m_asu_id.get_data_length()));
status = m_ec_certificate_store->select_certificate(&m_asu_id);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
eap_status_e wapi_core_c::handle_access_authentication_response(
const eap_am_network_id_c * const receive_network_id,
const wai_protocol_packet_header_c * const wai)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::handle_access_authentication_response(): state=%s, negotiation state = %s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::handle_access_authentication_response()");
if (m_authentication_type != eapol_key_authentication_type_WAI_certificate)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_authentication_type);
}
if (m_wapi_state != wapi_core_state_wait_access_authentication_response_message
&& m_wapi_state != wapi_core_state_wait_unicast_key_negotiation_request_message
&& m_wapi_state != wapi_core_state_wait_unicast_key_negotiation_confirmation_message
&& m_wapi_state != wapi_core_state_authentication_ok)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::handle_access_authentication_response(): Verify state %s != %s, negotiation state = %s.\n"),
(m_is_client == true) ? "client": "server",
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_core_state_string(wapi_core_state_wait_access_authentication_response_message),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
eap_status_e status(eap_status_process_general_error);
if (receive_network_id == 0
|| receive_network_id->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
if (wai == 0
|| wai->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
}
status = wai->check_header();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (wai->get_packet_sequence_number() != (m_packet_sequence_number + 1u))
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::handle_access_authentication_response(): sequence number %d != required sequence number %d.\n"),
(m_is_client == true) ? "client": "server",
wai->get_packet_sequence_number(),
(m_packet_sequence_number + 1u)));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
++m_packet_sequence_number;
set_wapi_state(wapi_core_state_process_access_authentication_response_message);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
wai_message_payloads_c parser(
m_am_tools,
m_is_client);
if (parser.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
u32_t padding_length(0ul);
status = parser.parse_wai_payloads(
wai->get_header_buffer(wai->get_header_buffer_length()), ///< This is the start of the message buffer.
wai->get_header_buffer_length(), ///< This is the length of the buffer. This must match with the length of all payloads.
&padding_length ///< Length of possible padding is set to this variable.
);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify BK rekeying flag.
{
wai_variable_data_c * const flag_payload = parser.get_tlv_pointer(wai_payload_type_flag);
if (flag_payload == 0
|| flag_payload->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u8_t * const pointer_to_flag = flag_payload->get_data(sizeof(*pointer_to_flag));
if (pointer_to_flag == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
m_do_certificate_validation = false;
if (m_wapi_negotiation_state == wapi_negotiation_state_rekeying)
{
if (((*pointer_to_flag) & wai_data_flag_mask_BK_Rekeying) == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (((*pointer_to_flag) & wai_data_flag_mask_Certificate_Validation_Request) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::handle_access_authentication_response(): no certificate validation\n"),
this,
(m_is_client == true ? "client": "server")));
}
else
{
if (((*pointer_to_flag) & wai_data_flag_mask_BK_Rekeying) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::handle_access_authentication_response(): does certificate validation\n"),
this,
(m_is_client == true ? "client": "server")));
m_do_certificate_validation = true;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify AE identity.
{
wai_variable_data_c * const ae_identity = parser.get_tlv_pointer(wai_payload_type_identity);
if (ae_identity == 0
|| ae_identity->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (m_ae_id.compare(
ae_identity->get_type_data(ae_identity->get_type_data_length()),
ae_identity->get_type_data_length()) != 0)
{
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: local m_ae_id"),
m_ae_id.get_data(),
m_ae_id.get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: received AE-ID"),
ae_identity->get_type_data(ae_identity->get_type_data_length()),
ae_identity->get_type_data_length()));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify ASUE identity.
wai_variable_data_c * const asue_identity = ae_identity->get_next_payload_with_same_tlv_type();
if (asue_identity == 0
|| asue_identity->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (m_asue_id.compare(
asue_identity->get_type_data(asue_identity->get_type_data_length()),
asue_identity->get_type_data_length()) != 0)
{
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: local m_asue_id"),
m_asue_id.get_data(),
m_asue_id.get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: received ASUE-ID"),
asue_identity->get_type_data(asue_identity->get_type_data_length()),
asue_identity->get_type_data_length()));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify ASUE challenge.
{
wai_variable_data_c * const asue_challenge = parser.get_tlv_pointer(wai_payload_type_nonce);
if (asue_challenge == 0
|| asue_challenge->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (m_asue_certificate_challenge.compare(
asue_challenge->get_type_data(asue_challenge->get_type_data_length()),
asue_challenge->get_type_data_length()) != 0)
{
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: local m_asue_certificate_challenge"),
m_asue_certificate_challenge.get_data(),
m_asue_certificate_challenge.get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: received ASUE-challenge"),
asue_challenge->get_type_data(asue_challenge->get_type_data_length()),
asue_challenge->get_type_data_length()));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Save AE challenge.
wai_variable_data_c * const ae_challenge = asue_challenge->get_next_payload_with_same_tlv_type();
if (ae_challenge == 0
|| ae_challenge->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
status = m_ae_certificate_challenge.set_copy_of_buffer(ae_challenge->get_data(WAPI_CHALLENGE_LENGTH), WAPI_CHALLENGE_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
wai_variable_data_c * ae_signature_trusted_by_asue = 0;
if (m_do_certificate_validation == true)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::handle_access_authentication_response(): does certificate validation\n"),
this,
(m_is_client == true ? "client": "server")));
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Save result of certificate_verification.
{
wai_variable_data_c * const result_of_certificate_verification = parser.get_tlv_pointer(wai_payload_type_result_of_certificate_verification);
if (result_of_certificate_verification == 0
|| result_of_certificate_verification->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
status = m_result_of_certificate_verification.set_copy_of_buffer(result_of_certificate_verification);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
{
eap_variable_data_c ae_challenge(m_am_tools);
eap_variable_data_c asue_challenge(m_am_tools);
eap_variable_data_c asue_certificate(m_am_tools);
wapi_certificate_result_e asue_certificate_result(wapi_certificate_result_none);
wapi_certificate_result_e ae_certificate_result(wapi_certificate_result_none);
status = parse_result_of_certificate_verification(
&m_result_of_certificate_verification,
&ae_challenge,
&asue_challenge,
&asue_certificate_result,
&asue_certificate,
&ae_certificate_result,
&m_ae_certificate);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// Verify AE-Challenge.
if (m_ae_certificate_challenge.compare(&ae_challenge) != 0)
{
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: local m_ae_certificate_challenge"),
m_ae_certificate_challenge.get_data(),
m_ae_certificate_challenge.get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: received AE-challenge"),
ae_challenge.get_data(),
ae_challenge.get_data_length()));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
// Verify ASUE-Challenge.
if (m_asue_certificate_challenge.compare(&asue_challenge) != 0)
{
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: local m_asue_certificate_challenge"),
m_asue_certificate_challenge.get_data(),
m_asue_certificate_challenge.get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: received ASUE-challenge"),
asue_challenge.get_data(),
asue_challenge.get_data_length()));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
// Verify ASUE-Certificate.
if (m_own_certificate.compare(&asue_certificate) != 0)
{
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: local m_own_certificate"),
m_own_certificate.get_data(),
m_own_certificate.get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: received ASUE-Certificate"),
asue_certificate.get_data(),
asue_certificate.get_data_length()));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (asue_certificate_result != wapi_certificate_result_valid)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAPI_Core: this = 0x%08x, %s: wapi_core_c::handle_access_authentication_response(): asue_certificate_result=%d\n"),
this,
(m_is_client == true ? "client": "server"),
asue_certificate_result));
switch (asue_certificate_result)
{
case wapi_certificate_result_issuer_is_unknown:
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unknown_ca);
case wapi_certificate_result_certificate_is_based_on_an_untrusted_root:
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unknown_ca);
case wapi_certificate_result_certificate_is_not_time_valid:
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_certificate_expired);
case wapi_certificate_result_certificate_have_not_a_valid_signature:
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_certificate);
case wapi_certificate_result_certificate_is_revoked:
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_certificate_revoked);
case wapi_certificate_result_certificate_is_not_valid_for_proposed_usage:
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_certificate);
case wapi_certificate_result_revocation_state_of_the_certificate_is_unknown:
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_certificate);
default:
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure);
}
}
if (ae_certificate_result != wapi_certificate_result_valid)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAPI_Core: this = 0x%08x, %s: wapi_core_c::handle_access_authentication_response(): ae_certificate_result=%d\n"),
this,
(m_is_client == true ? "client": "server"),
ae_certificate_result));
switch (ae_certificate_result)
{
case wapi_certificate_result_issuer_is_unknown:
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unknown_ca);
case wapi_certificate_result_certificate_is_based_on_an_untrusted_root:
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unknown_ca);
case wapi_certificate_result_certificate_is_not_time_valid:
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_certificate_expired);
case wapi_certificate_result_certificate_have_not_a_valid_signature:
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_certificate);
case wapi_certificate_result_certificate_is_revoked:
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_certificate_revoked);
case wapi_certificate_result_certificate_is_not_valid_for_proposed_usage:
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_certificate);
case wapi_certificate_result_revocation_state_of_the_certificate_is_unknown:
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_certificate);
default:
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure);
}
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Save server signature trusted by ASUE.
{
wai_variable_data_c * const server_signature_trusted_by_asue = parser.get_tlv_pointer(wai_payload_type_signature_attributes);
if (server_signature_trusted_by_asue == 0
|| server_signature_trusted_by_asue->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
status = m_server_signature_trusted_by_asue.set_copy_of_buffer(server_signature_trusted_by_asue);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Save server signature trusted by AE.
// NOTE: This is used only when server trusted by ASUE is different than server trusted by AE.
wai_variable_data_c * const server_signature_trusted_by_ae = server_signature_trusted_by_asue->get_next_payload_with_same_tlv_type();
if (server_signature_trusted_by_ae == 0
|| server_signature_trusted_by_ae->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Save Signature of AE. This is always the last signature.
ae_signature_trusted_by_asue = server_signature_trusted_by_ae->get_next_payload_with_same_tlv_type();
if ((ae_signature_trusted_by_asue == 0
|| ae_signature_trusted_by_asue->get_is_valid_data() == false))
{
// Server trusted by AE is the same as server trusted by ASUE.
status = m_server_signature_trusted_by_ae.set_copy_of_buffer(server_signature_trusted_by_asue);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// Signature of AE is always the last signature.
ae_signature_trusted_by_asue = server_signature_trusted_by_ae;
}
else
{
// Server trusted by AE is different than server trusted by ASUE.
status = m_server_signature_trusted_by_ae.set_copy_of_buffer(server_signature_trusted_by_ae);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
}
}
else
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::handle_access_authentication_response(): no certificate validation\n"),
this,
(m_is_client == true ? "client": "server")));
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Save Signature of AE.
ae_signature_trusted_by_asue = parser.get_tlv_pointer(wai_payload_type_signature_attributes);
if (ae_signature_trusted_by_asue == 0
|| ae_signature_trusted_by_asue->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{
wai_variable_data_c * ae_key_data = 0;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Compare ASUE key data.
{
wai_variable_data_c * const asue_key_data = parser.get_tlv_pointer(wai_payload_type_key_data);
if (asue_key_data == 0
|| asue_key_data->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
u32_t offset(0ul);
const u8_t * const point_type = asue_key_data->get_type_data_offset(offset, sizeof(u8_t));
if (point_type == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (*point_type != WAI_EC_POINT_TYPE_NO_COMPRESSION_ID)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
offset += sizeof(*point_type);
const u32_t x_key_element_length((1ul + asue_key_data->get_type_data_length() - sizeof(*point_type)) / 2ul);
const u32_t y_key_element_length(asue_key_data->get_type_data_length() - sizeof(*point_type) - x_key_element_length);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: sizeof(*point_type)=%d, *point_type=0x%02x, get_type_data_length()=%d, x_key_element_length=%d, y_key_element_length=%d\n"),
this,
(m_is_client == true ? "client": "server"),
sizeof(*point_type),
*point_type,
asue_key_data->get_type_data_length(),
x_key_element_length,
y_key_element_length));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_own_public_key_x"),
m_own_public_key_x.get_data(),
m_own_public_key_x.get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("received public_key_x"),
asue_key_data->get_type_data_offset(offset, x_key_element_length),
x_key_element_length));
if (m_own_public_key_x.compare(
asue_key_data->get_type_data_offset(offset, x_key_element_length),
x_key_element_length) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
offset += x_key_element_length;
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_own_public_key_y"),
m_own_public_key_y.get_data(),
m_own_public_key_y.get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("received public_key_y"),
asue_key_data->get_type_data_offset(offset, y_key_element_length),
y_key_element_length));
if (m_own_public_key_y.compare(
asue_key_data->get_type_data_offset(offset, y_key_element_length),
y_key_element_length) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
ae_key_data = asue_key_data->get_next_payload_with_same_tlv_type();
if (asue_key_data == 0
|| asue_key_data->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Save AE key data.
{
u32_t offset(0ul);
const u8_t * const point_type = ae_key_data->get_type_data_offset(offset, sizeof(u8_t));
if (point_type == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (*point_type != WAI_EC_POINT_TYPE_NO_COMPRESSION_ID)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
offset += sizeof(*point_type);
const u32_t x_key_element_length((1ul + ae_key_data->get_type_data_length() - sizeof(*point_type)) / 2ul);
const u32_t y_key_element_length(ae_key_data->get_type_data_length() - sizeof(*point_type) - x_key_element_length);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: sizeof(*point_type)=%d, *point_type=0x%02x, get_type_data_length()=%d, x_key_element_length=%d, y_key_element_length=%d\n"),
this,
(m_is_client == true ? "client": "server"),
sizeof(*point_type),
*point_type,
ae_key_data->get_type_data_length(),
x_key_element_length,
y_key_element_length));
status = m_peer_public_key_x.set_copy_of_buffer(
ae_key_data->get_type_data_offset(offset, x_key_element_length),
x_key_element_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_peer_public_key_x"),
m_peer_public_key_x.get_data(),
m_peer_public_key_x.get_data_length()));
offset += x_key_element_length;
status = m_peer_public_key_y.set_copy_of_buffer(
ae_key_data->get_type_data_offset(offset, y_key_element_length),
y_key_element_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_peer_public_key_y"),
m_peer_public_key_y.get_data(),
m_peer_public_key_y.get_data_length()));
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify Signature of AE.
{
if (ae_signature_trusted_by_asue == 0
|| ae_signature_trusted_by_asue->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
eap_variable_data_c signature_data(m_am_tools);
if (signature_data.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
eap_variable_data_c received_ae_id(m_am_tools);
if (received_ae_id.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = parse_signature_attributes(
ae_signature_trusted_by_asue,
&received_ae_id,
&signature_data);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("received_ae_id"),
received_ae_id.get_data(),
received_ae_id.get_data_length()));
if (received_ae_id.compare(&m_ae_id) != 0)
{
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: local m_ae_id"),
m_ae_id.get_data(),
m_ae_id.get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: received AE-ID"),
received_ae_id.get_data(received_ae_id.get_data_length()),
received_ae_id.get_data_length()));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
eap_variable_data_c HASH(m_am_tools);
if (HASH.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
{
wai_message_payloads_c * const signature_payload = new wai_message_payloads_c(m_am_tools, m_is_client);
eap_automatic_variable_c<wai_message_payloads_c> automatic_signature_payload(m_am_tools, signature_payload);
if (signature_payload == 0
|| signature_payload->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
// Copy all payloads except the last signature.
for (u32_t index = 0ul; (index+1ul) < parser.get_tlv_count(); ++index)
{
const wai_variable_data_c * const payload = parser.get_tlv(index);
if (payload != 0)
{
status = signature_payload->insert_payload(payload);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
}
status = create_HASH(signature_payload, true, &HASH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
status = m_ec_certificate_store->set_ae_certificate(
&m_ae_certificate);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_ec_certificate_store->verify_signature_with_public_key(
&m_ae_id,
&HASH,
&signature_data,
true);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
#if defined(USE_WAPI_CORE_SERVER)
eap_status_e wapi_core_c::handle_access_authentication_request(
const eap_am_network_id_c * const receive_network_id,
const wai_protocol_packet_header_c * const wai)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::handle_access_authentication_request(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::handle_access_authentication_request()");
if (m_authentication_type != eapol_key_authentication_type_WAI_certificate)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_authentication_type);
}
if (m_wapi_state != wapi_core_state_wait_access_authentication_request_message
&& m_wapi_state != wapi_core_state_wait_unicast_key_negotiation_response_message
&& m_wapi_state != wapi_core_state_authentication_ok)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::handle_access_authentication_request(): Verify state %s != %s, negotiation state = %s.\n"),
(m_is_client == true) ? "client": "server",
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_core_state_string(wapi_core_state_wait_multicast_announcement_message),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
eap_status_e status(eap_status_process_general_error);
if (receive_network_id == 0
|| receive_network_id->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
if (wai == 0
|| wai->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
}
status = wai->check_header();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (wai->get_packet_sequence_number() != m_packet_sequence_number)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::handle_access_authentication_request(): sequence number %d != required sequence number %d.\n"),
(m_is_client == true) ? "client": "server",
wai->get_packet_sequence_number(),
m_packet_sequence_number));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
set_wapi_state(wapi_core_state_process_access_authentication_request_message);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
wai_message_payloads_c parser(
m_am_tools,
m_is_client);
if (parser.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
u32_t padding_length(0ul);
status = parser.parse_wai_payloads(
wai->get_header_buffer(wai->get_header_buffer_length()), ///< This is the start of the message buffer.
wai->get_header_buffer_length(), ///< This is the length of the buffer. This must match with the length of all payloads.
&padding_length ///< Length of possible padding is set to this variable.
);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify BK rekeying flag.
{
wai_variable_data_c * const flag_payload = parser.get_tlv_pointer(wai_payload_type_flag);
if (flag_payload == 0
|| flag_payload->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u8_t * const flag = flag_payload->get_data(sizeof(*flag));
if (flag == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
m_do_certificate_validation = false;
if (m_wapi_negotiation_state == wapi_negotiation_state_rekeying)
{
if (((*flag) & wai_data_flag_mask_BK_Rekeying) == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (((*flag) & wai_data_flag_mask_Certificate_Validation_Request) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::handle_access_authentication_request(): no certificate validation\n"),
this,
(m_is_client == true ? "client": "server")));
}
else
{
if (((*flag) & wai_data_flag_mask_BK_Rekeying) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (((*flag) & wai_data_flag_mask_Certificate_Validation_Request) == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::handle_access_authentication_request(): does certificate validation\n"),
this,
(m_is_client == true ? "client": "server")));
m_do_certificate_validation = true;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify the Authentication identifier parameter.
{
wai_variable_data_c * const authentication_identifier = parser.get_tlv_pointer(wai_payload_type_authentication_identifier);
if (authentication_identifier == 0
|| authentication_identifier->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (authentication_identifier->get_type_data_length() != m_authentication_identifier.get_data_length()
|| m_am_tools->memcmp(
m_authentication_identifier.get_data(),
authentication_identifier->get_type_data(authentication_identifier->get_type_data_length()),
authentication_identifier->get_type_data_length()) != 0)
{
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: local m_authentication_identifier"),
m_authentication_identifier.get_data(),
m_authentication_identifier.get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: received Authentication identifier"),
authentication_identifier->get_type_data(authentication_identifier->get_type_data_length()),
authentication_identifier->get_type_data_length()));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify the ECDH parameter.
{
wai_variable_data_c * const echd_parameter = parser.get_tlv_pointer(wai_payload_type_echd_parameter);
if (echd_parameter == 0
|| echd_parameter->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (sizeof(WAPI_ECDH_OID_PARAMETER) != echd_parameter->get_type_data_length()
|| m_am_tools->memcmp(
WAPI_ECDH_OID_PARAMETER,
echd_parameter->get_type_data(sizeof(WAPI_ECDH_OID_PARAMETER)),
sizeof(WAPI_ECDH_OID_PARAMETER)) != 0)
{
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: local ECDH parameter"),
WAPI_ECDH_OID_PARAMETER,
sizeof(WAPI_ECDH_OID_PARAMETER)));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: received ECDH parameter"),
echd_parameter->get_type_data(echd_parameter->get_type_data_length()),
echd_parameter->get_type_data_length()));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify the ID of STA_AE parameter.
{
wai_variable_data_c * const ae_id = parser.get_tlv_pointer(wai_payload_type_identity);
if (ae_id == 0
|| ae_id->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (m_ae_id.get_data_length() != ae_id->get_type_data_length()
|| m_am_tools->memcmp(
ae_id->get_type_data(m_ae_id.get_data_length()),
m_ae_id.get_data(),
m_ae_id.get_data_length()) != 0)
{
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: local m_ae_id"),
m_ae_id.get_data(),
m_ae_id.get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: received AE-ID"),
ae_id->get_type_data(ae_id->get_type_data_length()),
ae_id->get_type_data_length()));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
else
{
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_ae_id"),
m_ae_id.get_data(),
m_ae_id.get_data_length()));
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Save ASUE challenge.
{
wai_variable_data_c * const asue_challenge = parser.get_tlv_pointer(wai_payload_type_nonce);
if (asue_challenge == 0
|| asue_challenge->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
status = m_asue_certificate_challenge.set_copy_of_buffer(
asue_challenge->get_type_data(asue_challenge->get_type_data_length()),
asue_challenge->get_type_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Save ASUE key data.
{
wai_variable_data_c * const asue_key_data = parser.get_tlv_pointer(wai_payload_type_key_data);
if (asue_key_data == 0
|| asue_key_data->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
u32_t offset(0ul);
const u8_t * const point_type = asue_key_data->get_type_data_offset(offset, sizeof(u8_t));
if (point_type == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (*point_type != WAI_EC_POINT_TYPE_NO_COMPRESSION_ID)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
offset += sizeof(*point_type);
const u32_t x_key_element_length((1ul + asue_key_data->get_type_data_length() - sizeof(*point_type)) / 2ul);
const u32_t y_key_element_length(asue_key_data->get_type_data_length() - sizeof(*point_type) - x_key_element_length);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: sizeof(*point_type)=%d, *point_type=0x%02x, get_type_data_length()=%d, x_key_element_length=%d, y_key_element_length=%d\n"),
this,
(m_is_client == true ? "client": "server"),
sizeof(*point_type),
*point_type,
asue_key_data->get_type_data_length(),
x_key_element_length,
y_key_element_length));
status = m_peer_public_key_x.set_copy_of_buffer(
asue_key_data->get_type_data_offset(offset, x_key_element_length),
x_key_element_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_peer_public_key_x"),
m_peer_public_key_x.get_data(),
m_peer_public_key_x.get_data_length()));
offset += x_key_element_length;
status = m_peer_public_key_y.set_copy_of_buffer(
asue_key_data->get_type_data_offset(offset, y_key_element_length),
y_key_element_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_peer_public_key_y"),
m_peer_public_key_y.get_data(),
m_peer_public_key_y.get_data_length()));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Save STA_ASUE certificate.
{
wai_variable_data_c * const sta_asue_certificate = parser.get_tlv_pointer(wai_payload_type_certificate);
if (sta_asue_certificate == 0
|| sta_asue_certificate->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
status = m_peer_certificate.set_copy_of_buffer(
sta_asue_certificate->get_type_data(sta_asue_certificate->get_type_data_length()),
sta_asue_certificate->get_type_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify Signature of ASUE.
{
wai_variable_data_c * const signature_payload = parser.get_tlv_pointer(wai_payload_type_signature_attributes);
if (signature_payload == 0
|| signature_payload->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
eap_variable_data_c signature_data(m_am_tools);
if (signature_data.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = parse_signature_attributes(
signature_payload,
&m_asue_id,
&signature_data);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_asue_id"),
m_asue_id.get_data(),
m_asue_id.get_data_length()));
eap_variable_data_c HASH(m_am_tools);
if (HASH.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = create_HASH(&parser, false, &HASH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_ec_certificate_store->verify_signature_with_public_key(
&m_asue_id,
&HASH,
&signature_data,
false);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
#endif //#if defined(USE_WAPI_CORE_SERVER)
//--------------------------------------------------
eap_status_e wapi_core_c::handle_unicast_key_negotiation_request(
const eap_am_network_id_c * const receive_network_id,
const wai_protocol_packet_header_c * const wai)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::handle_unicast_key_negotiation_request(): state=%s, negotiation state = %s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::handle_unicast_key_negotiation_request()");
eap_status_e status(eap_status_process_general_error);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (m_wapi_state != wapi_core_state_wait_unicast_key_negotiation_request_message
&& m_wapi_state != wapi_core_state_wait_unicast_key_negotiation_confirmation_message
&& m_wapi_state != wapi_core_state_authentication_ok)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::handle_unicast_key_negotiation_request(): Verify state %s != %s, negotiation state = %s.\n"),
(m_is_client == true) ? "client": "server",
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_core_state_string(wapi_core_state_wait_unicast_key_negotiation_request_message),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
if (m_authentication_type != eapol_key_authentication_type_WAI_PSK
&& m_authentication_type != eapol_key_authentication_type_WAI_certificate)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_authentication_type);
}
if (receive_network_id == 0
|| receive_network_id->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
if (wai == 0
|| wai->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
}
status = wai->check_header();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (wai->get_packet_sequence_number() != (m_packet_sequence_number + 1u))
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::handle_unicast_key_negotiation_request(): sequence number %d != required sequence number %d.\n"),
(m_is_client == true) ? "client": "server",
wai->get_packet_sequence_number(),
(m_packet_sequence_number + 1u)));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
++m_packet_sequence_number;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (m_authentication_type == eapol_key_authentication_type_WAI_PSK)
{
// Here we swap the addresses.
eap_am_network_id_c send_network_id(m_am_tools,
m_receive_network_id.get_destination_id(),
m_receive_network_id.get_source_id(),
m_receive_network_id.get_type());
if (send_network_id.get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
// This is notification to eapol_core_c object.
// WAI unicast negotiation started successfully.
eap_state_notification_c * notification = new eap_state_notification_c(
m_am_tools,
&send_network_id,
m_is_client,
eap_state_notification_generic,
eap_protocol_layer_wai,
eapol_key_handshake_type_wai_handshake,
eapol_key_state_wapi_authentication_running,
eapol_key_state_wapi_authentication_running,
0ul,
false);
if (notification == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
m_partner->state_notification(notification);
delete notification;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
status = create_BKID(&m_BKID, receive_network_id);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
wai_message_payloads_c parser(
m_am_tools,
m_is_client);
if (parser.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
u32_t padding_length(0ul);
status = parser.parse_wai_payloads(
wai->get_header_buffer(wai->get_header_buffer_length()), ///< This is the start of the message buffer.
wai->get_header_buffer_length(), ///< This is the length of the buffer. This must match with the length of all payloads.
&padding_length ///< Length of possible padding is set to this variable.
);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify BKID.
{
wai_variable_data_c * const BKID_payload = parser.get_tlv_pointer(wai_payload_type_bkid);
if (BKID_payload == 0
|| BKID_payload->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (m_BKID.compare(
BKID_payload->get_data(BKID_payload->get_data_length()),
BKID_payload->get_data_length()) != 0)
{
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: local m_BKID"),
m_BKID.get_data(),
m_BKID.get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: received BKID"),
BKID_payload->get_data(BKID_payload->get_data_length()),
BKID_payload->get_data_length()));
#if defined(WAPI_SKIP_BKID_TEST)
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WARNING: WAPI_Core: this = 0x%08x, %s: wapi_core_c::handle_unicast_key_negotiation_request(): Skips BKID test.\n"),
this,
(m_is_client == true ? "client": "server")));
#else
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
#endif //#if !defined(WAPI_SKIP_BKID_TEST)
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify USK rekeying flag.
{
wai_variable_data_c * const flag_payload = parser.get_tlv_pointer(wai_payload_type_flag);
if (flag_payload == 0
|| flag_payload->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u8_t * const flag = flag_payload->get_data(sizeof(*flag));
if (flag == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (m_wapi_negotiation_state == wapi_negotiation_state_rekeying)
{
if (((*flag) & wai_data_flag_mask_USK_Rekeying) == 0)
{
m_wapi_negotiation_state = wapi_negotiation_state_initial_negotiation;
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WARNING: WAPI_Core: this = 0x%08x, %s: wapi_core_c::handle_unicast_key_negotiation_request(): change to %s.\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
}
}
else
{
if (((*flag) & wai_data_flag_mask_USK_Rekeying) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify USKID.
{
wai_variable_data_c * const USKID_payload = parser.get_tlv_pointer(wai_payload_type_uskid);
if (USKID_payload == 0
|| USKID_payload->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u8_t * const USKID_pointer = USKID_payload->get_data(sizeof(*USKID_pointer));
if (USKID_pointer == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
u8_t USKID = (*USKID_pointer) & wai_data_uskid_mask_uskid;
if (USKID >= WAPI_USKSA_COUNT
|| m_USKSA[USKID] == 0
|| m_USKSA[USKID]->get_is_valid_data() == true)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
m_USKID = USKID;
m_USKSA[USKID]->set_USKID(m_USKID);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Save AE challenge.
{
wai_variable_data_c * const ae_challenge = parser.get_tlv_pointer(wai_payload_type_nonce);
if (ae_challenge == 0
|| ae_challenge->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (m_wapi_negotiation_state == wapi_negotiation_state_rekeying)
{
// Verify the AE challenge.
if (m_am_tools->memcmp(m_next_unicast_challenge.get_data(WAPI_CHALLENGE_LENGTH), ae_challenge->get_data(WAPI_CHALLENGE_LENGTH), WAPI_CHALLENGE_LENGTH) != 0)
{
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: local m_next_unicast_challenge"),
m_next_unicast_challenge.get_data(),
m_next_unicast_challenge.get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: received AE Challenge"),
ae_challenge->get_data(WAPI_CHALLENGE_LENGTH),
WAPI_CHALLENGE_LENGTH));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
status = m_ae_unicast_challenge.set_copy_of_buffer(ae_challenge->get_data(WAPI_CHALLENGE_LENGTH), WAPI_CHALLENGE_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create ASUE challenge.
{
crypto_random_c rand(m_am_tools);
if (rand.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = rand.get_rand_bytes(
&m_asue_unicast_challenge,
WAPI_CHALLENGE_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create unicast session key.
status = create_unicast_key(
&m_BK,
receive_network_id,
&m_ae_unicast_challenge,
&m_asue_unicast_challenge,
&m_unicast_encryption_key_UEK,
&m_unicast_integrity_check_key_UCK,
&m_message_authentication_key_MAK,
&m_key_encryption_key_KEK,
&m_next_unicast_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create the Unicast Key Negotiation Response message.
wai_message_payloads_c * const payloads = new wai_message_payloads_c(m_am_tools, m_is_client);
// Automatic variable deletes payloads when control returns from this function.
eap_automatic_variable_c<wai_message_payloads_c> automatic_payloads(m_am_tools, payloads);
if (payloads == 0
|| payloads->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = payloads->initialise_header();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->get_wai_protocol_packet_header_writable()->set_subtype(wai_protocol_subtype_unicast_key_negotiation_response);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds FLAG to data field.
{
wai_variable_data_c data_flag(m_am_tools);
if (data_flag.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
u8_t flag(wai_data_flag_mask_none);
if (m_wapi_negotiation_state == wapi_negotiation_state_rekeying)
{
flag = wai_data_flag_mask_USK_Rekeying;
}
status = data_flag.create(
wai_payload_type_flag,
&flag,
sizeof(flag));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_flag);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds BKID to data field.
{
wai_variable_data_c data_BKID(m_am_tools);
if (data_BKID.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_BKID.create(
wai_payload_type_bkid,
&m_BKID);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_BKID);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds USKID to data field.
{
wai_variable_data_c data_USKID(m_am_tools);
if (data_USKID.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_USKID.create(
wai_payload_type_uskid,
&m_USKID,
sizeof(m_USKID));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_USKID);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds ADDID to data field.
{
wai_variable_data_c data_ADDID(m_am_tools);
if (data_ADDID.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
const eap_variable_data_c * MAC_1 = receive_network_id->get_destination_id();
const eap_variable_data_c * MAC_2 = receive_network_id->get_source_id();
if (m_is_client == true)
{
MAC_1 = receive_network_id->get_source_id();
MAC_2 = receive_network_id->get_destination_id();
}
status = data_ADDID.create(
wai_payload_type_addid,
MAC_1);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = data_ADDID.add_data(
wai_payload_type_addid,
MAC_2);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_ADDID);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds ASUE Challenge to data field.
{
wai_variable_data_c data_ASUE_challenge(m_am_tools);
if (data_ASUE_challenge.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_ASUE_challenge.create(
wai_payload_type_nonce,
&m_asue_unicast_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_ASUE_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds AE Challenge to data field.
{
wai_variable_data_c data_AE_challenge(m_am_tools);
if (data_AE_challenge.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_AE_challenge.create(
wai_payload_type_nonce,
&m_ae_unicast_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_AE_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds WIE ASUE to data field.
{
wai_variable_data_c data_WIE_ASUE(m_am_tools);
if (data_WIE_ASUE.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
EAP_ASSERT_TOOLS(m_am_tools, m_wapi_ie_asue.get_is_valid() == true && m_wapi_ie_asue.get_data_length() > 0ul);
status = data_WIE_ASUE.create(
wai_payload_type_wie,
&m_wapi_ie_asue);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_WIE_ASUE);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds MAC to data field.
{
wai_variable_data_c data_MAC(m_am_tools);
if (data_MAC.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
eap_variable_data_c MAC(m_am_tools);
if (MAC.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = create_MAC(payloads, &MAC);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = MAC.set_data_length(WAPI_MESSAGE_AUTHENTICATION_CODE_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = data_MAC.create(
wai_payload_type_message_authentication_code,
&MAC);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_MAC);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create and send message.
{
wai_message_c new_wai_message_data(m_am_tools, m_is_client);
if (new_wai_message_data.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->create_wai_tlv_message(&new_wai_message_data, false);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//cancel_retransmission();
status = packet_send(
&new_wai_message_data,
payloads->get_wai_protocol_packet_header_writable()->get_subtype());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
set_wapi_state(wapi_core_state_wait_unicast_key_negotiation_confirmation_message);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
#if defined(USE_WAPI_CORE_SERVER)
eap_status_e wapi_core_c::handle_unicast_key_negotiation_response(
const eap_am_network_id_c * const receive_network_id,
const wai_protocol_packet_header_c * const wai)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::handle_unicast_key_negotiation_response(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::handle_unicast_key_negotiation_response()");
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (m_wapi_state != wapi_core_state_wait_unicast_key_negotiation_response_message
&& m_wapi_state != wapi_core_state_wait_multicast_announcement_response_message)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::handle_unicast_key_negotiation_response(): Verify state %s != %s, negotiation state = %s.\n"),
(m_is_client == true) ? "client": "server",
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_core_state_string(wapi_core_state_wait_unicast_key_negotiation_response_message),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
if (m_authentication_type != eapol_key_authentication_type_WAI_PSK
&& m_authentication_type != eapol_key_authentication_type_WAI_certificate)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_authentication_type);
}
eap_status_e status(eap_status_process_general_error);
if (receive_network_id == 0
|| receive_network_id->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
if (wai == 0
|| wai->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
}
status = wai->check_header();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (wai->get_packet_sequence_number() != m_packet_sequence_number)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::handle_unicast_key_negotiation_response(): sequence number %d != required sequence number %d.\n"),
(m_is_client == true) ? "client": "server",
wai->get_packet_sequence_number(),
m_packet_sequence_number));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
wai_message_payloads_c parser(
m_am_tools,
m_is_client);
if (parser.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
u32_t padding_length(0ul);
status = parser.parse_wai_payloads(
wai->get_header_buffer(wai->get_header_buffer_length()), ///< This is the start of the message buffer.
wai->get_header_buffer_length(), ///< This is the length of the buffer. This must match with the length of all payloads.
&padding_length ///< Length of possible padding is set to this variable.
);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify BKID.
{
wai_variable_data_c * const BKID_payload = parser.get_tlv_pointer(wai_payload_type_bkid);
if (BKID_payload == 0
|| BKID_payload->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (m_BKID.compare(
BKID_payload->get_data(BKID_payload->get_data_length()),
BKID_payload->get_data_length()) != 0)
{
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: local m_BKID"),
m_BKID.get_data(),
m_BKID.get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: received BKID"),
BKID_payload->get_data(BKID_payload->get_data_length()),
BKID_payload->get_data_length()));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify USK rekeying flag.
{
wai_variable_data_c * const flag_payload = parser.get_tlv_pointer(wai_payload_type_flag);
if (flag_payload == 0
|| flag_payload->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u8_t * const flag = flag_payload->get_data(sizeof(*flag));
if (flag == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (m_wapi_negotiation_state == wapi_negotiation_state_rekeying)
{
if (((*flag) & wai_data_flag_mask_USK_Rekeying) == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
else
{
if (((*flag) & wai_data_flag_mask_USK_Rekeying) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify USKID.
{
wai_variable_data_c * const USKID_payload = parser.get_tlv_pointer(wai_payload_type_uskid);
if (USKID_payload == 0
|| USKID_payload->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u8_t * const USKID_pointer = USKID_payload->get_data(sizeof(*USKID_pointer));
if (USKID_pointer == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
u8_t USKID = (*USKID_pointer) & wai_data_uskid_mask_uskid;
if (USKID >= WAPI_USKSA_COUNT
|| m_USKSA[USKID] == 0
|| m_USKSA[USKID]->get_is_valid_data() == true)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
m_USKID = USKID;
m_USKSA[USKID]->set_USKID(m_USKID);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Save ASUE challenge.
{
wai_variable_data_c * const asue_challenge = parser.get_tlv_pointer(wai_payload_type_nonce);
if (asue_challenge == 0
|| asue_challenge->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
status = m_asue_unicast_challenge.set_copy_of_buffer(asue_challenge->get_data(WAPI_CHALLENGE_LENGTH), WAPI_CHALLENGE_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify AE challenge.
wai_variable_data_c * const ae_challenge = asue_challenge->get_next_payload_with_same_tlv_type();
if (ae_challenge == 0
|| ae_challenge->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (m_ae_unicast_challenge.compare(
ae_challenge->get_data(ae_challenge->get_data_length()),
ae_challenge->get_data_length()) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify WIE_ASUE.
if (m_wapi_negotiation_state == wapi_negotiation_state_initial_negotiation)
{
wai_variable_data_c * const wie_asue = parser.get_tlv_pointer(wai_payload_type_wie);
if (wie_asue == 0
|| wie_asue->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (m_wapi_ie_asue.compare(
wie_asue->get_data(wie_asue->get_data_length()),
wie_asue->get_data_length()) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create unicast session key.
status = create_unicast_key(
&m_BK,
receive_network_id,
&m_ae_unicast_challenge,
&m_asue_unicast_challenge,
&m_unicast_encryption_key_UEK,
&m_unicast_integrity_check_key_UCK,
&m_message_authentication_key_MAK,
&m_key_encryption_key_KEK,
&m_next_unicast_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify MAC.
{
wai_variable_data_c * const received_MAC = parser.get_tlv_pointer(wai_payload_type_message_authentication_code);
if (received_MAC == 0
|| received_MAC->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
eap_variable_data_c local_MAC(m_am_tools);
if (local_MAC.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = create_MAC(&parser, &local_MAC);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = local_MAC.set_data_length(WAPI_MESSAGE_AUTHENTICATION_CODE_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
if (local_MAC.compare(
received_MAC->get_data(received_MAC->get_data_length()),
received_MAC->get_data_length()) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure);
}
else
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAI: %s: wapi_core_c::handle_unicast_key_negotiation_response(): MAC OK.\n"),
(m_is_client == true) ? "client": "server"));
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create the Unicast Key Negotiation Confirmation message.
wai_message_payloads_c * const payloads = new wai_message_payloads_c(m_am_tools, m_is_client);
eap_automatic_variable_c<wai_message_payloads_c> automatic_payloads(m_am_tools, payloads);
if (payloads == 0
|| payloads->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = payloads->initialise_header();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->get_wai_protocol_packet_header_writable()->set_subtype(wai_protocol_subtype_unicast_key_negotiation_confirmation);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds FLAG to data field.
{
wai_variable_data_c data_flag(m_am_tools);
if (data_flag.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
u8_t flag(wai_data_flag_mask_none);
if (m_wapi_negotiation_state == wapi_negotiation_state_rekeying)
{
flag = wai_data_flag_mask_USK_Rekeying;
}
status = data_flag.create(
wai_payload_type_flag,
&flag,
sizeof(flag));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_flag);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds BKID to data field.
{
wai_variable_data_c data_BKID(m_am_tools);
if (data_BKID.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_BKID.create(
wai_payload_type_bkid,
&m_BKID);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_BKID);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds USKID to data field.
{
wai_variable_data_c data_USKID(m_am_tools);
if (data_USKID.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_USKID.create(
wai_payload_type_uskid,
&m_USKID,
sizeof(m_USKID));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_USKID);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds ADDID to data field.
{
wai_variable_data_c data_ADDID(m_am_tools);
if (data_ADDID.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
const eap_variable_data_c * MAC_1 = receive_network_id->get_source_id();
const eap_variable_data_c * MAC_2 = receive_network_id->get_destination_id();
if (m_is_client == true)
{
MAC_1 = receive_network_id->get_destination_id();
MAC_2 = receive_network_id->get_source_id();
}
status = data_ADDID.create(
wai_payload_type_addid,
MAC_1);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = data_ADDID.add_data(
wai_payload_type_addid,
MAC_2);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_ADDID);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds ASUE Challenge to data field.
{
wai_variable_data_c data_ASUE_challenge(m_am_tools);
if (data_ASUE_challenge.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_ASUE_challenge.create(
wai_payload_type_nonce,
&m_asue_unicast_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_ASUE_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds WIE AE to data field.
{
wai_variable_data_c data_WIE_AE(m_am_tools);
if (data_WIE_AE.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_WIE_AE.create(
wai_payload_type_wie,
&m_wapi_ie_ae);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_WIE_AE);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds MAC to data field.
{
wai_variable_data_c data_MAC(m_am_tools);
if (data_MAC.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
eap_variable_data_c MAC(m_am_tools);
if (MAC.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = create_MAC(payloads, &MAC);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = MAC.set_data_length(WAPI_MESSAGE_AUTHENTICATION_CODE_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = data_MAC.create(
wai_payload_type_message_authentication_code,
&MAC);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_MAC);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create and send message.
wai_message_c new_wai_message_data(m_am_tools, m_is_client);
if (new_wai_message_data.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->create_wai_tlv_message(&new_wai_message_data, false);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//cancel_retransmission();
status = packet_send(
&new_wai_message_data,
payloads->get_wai_protocol_packet_header_writable()->get_subtype());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Install unicast session key.
{
eap_variable_data_c unicast_session_key(m_am_tools);
if (unicast_session_key.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = unicast_session_key.set_copy_of_buffer(&m_unicast_encryption_key_UEK);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = unicast_session_key.add_data(&m_unicast_integrity_check_key_UCK);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = packet_data_session_key(
&unicast_session_key,
eapol_key_type_unicast,
m_USKID,
false,
m_packet_data_number.get_data(),
m_packet_data_number.get_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
set_wapi_state(wapi_core_state_start_multicast_key_announcement);
status = start_multicast_key_announcement();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
#endif //#if defined(USE_WAPI_CORE_SERVER)
//--------------------------------------------------
eap_status_e wapi_core_c::handle_unicast_key_negotiation_confirmation(
const eap_am_network_id_c * const receive_network_id,
const wai_protocol_packet_header_c * const wai)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::handle_unicast_key_negotiation_confirmation(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::handle_unicast_key_negotiation_confirmation()");
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (m_wapi_state != wapi_core_state_wait_unicast_key_negotiation_confirmation_message
&& m_wapi_state != wapi_core_state_wait_multicast_announcement_message)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::handle_unicast_key_negotiation_confirmation(): Verify state %s != %s, negotiation state = %s.\n"),
(m_is_client == true) ? "client": "server",
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_core_state_string(wapi_core_state_wait_unicast_key_negotiation_confirmation_message),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
if (m_authentication_type != eapol_key_authentication_type_WAI_PSK
&& m_authentication_type != eapol_key_authentication_type_WAI_certificate)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_authentication_type);
}
eap_status_e status(eap_status_process_general_error);
if (receive_network_id == 0
|| receive_network_id->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
if (wai == 0
|| wai->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
}
status = wai->check_header();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (wai->get_packet_sequence_number() != (m_packet_sequence_number + 1u))
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::handle_unicast_key_negotiation_confirmation(): sequence number %d != required sequence number %d.\n"),
(m_is_client == true) ? "client": "server",
wai->get_packet_sequence_number(),
(m_packet_sequence_number + 1u)));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
++m_packet_sequence_number;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
wai_message_payloads_c parser(
m_am_tools,
m_is_client);
if (parser.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
u32_t padding_length(0ul);
status = parser.parse_wai_payloads(
wai->get_header_buffer(wai->get_header_buffer_length()), ///< This is the start of the message buffer.
wai->get_header_buffer_length(), ///< This is the length of the buffer. This must match with the length of all payloads.
&padding_length ///< Length of possible padding is set to this variable.
);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify BKID.
{
wai_variable_data_c * const BKID_payload = parser.get_tlv_pointer(wai_payload_type_bkid);
if (BKID_payload == 0
|| BKID_payload->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (m_BKID.compare(
BKID_payload->get_data(BKID_payload->get_data_length()),
BKID_payload->get_data_length()) != 0)
{
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: local m_BKID"),
m_BKID.get_data(),
m_BKID.get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: received BKID"),
BKID_payload->get_data(BKID_payload->get_data_length()),
BKID_payload->get_data_length()));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify MAC.
{
wai_variable_data_c * const received_MAC = parser.get_tlv_pointer(wai_payload_type_message_authentication_code);
if (received_MAC == 0
|| received_MAC->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
eap_variable_data_c local_MAC(m_am_tools);
if (local_MAC.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = create_MAC(&parser, &local_MAC);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = local_MAC.set_data_length(WAPI_MESSAGE_AUTHENTICATION_CODE_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
if (local_MAC.compare(
received_MAC->get_data(received_MAC->get_data_length()),
received_MAC->get_data_length()) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure);
}
else
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAI: %s: wapi_core_c::handle_unicast_key_negotiation_confirmation(): MAC OK.\n"),
(m_is_client == true) ? "client": "server"));
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify USK rekeying flag.
{
wai_variable_data_c * const flag_payload = parser.get_tlv_pointer(wai_payload_type_flag);
if (flag_payload == 0
|| flag_payload->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u8_t * const flag = flag_payload->get_data(sizeof(*flag));
if (flag == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (m_wapi_negotiation_state == wapi_negotiation_state_rekeying)
{
if (((*flag) & wai_data_flag_mask_USK_Rekeying) == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
else
{
if (((*flag) & wai_data_flag_mask_USK_Rekeying) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify USKID.
{
wai_variable_data_c * const USKID_payload = parser.get_tlv_pointer(wai_payload_type_uskid);
if (USKID_payload == 0
|| USKID_payload->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u8_t * const USKID_pointer = USKID_payload->get_data(sizeof(*USKID_pointer));
if (USKID_pointer == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
u8_t USKID = (*USKID_pointer) & wai_data_uskid_mask_uskid;
if (USKID >= WAPI_USKSA_COUNT
|| m_USKSA[USKID] == 0
|| m_USKSA[USKID]->get_is_valid_data() == true)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
m_USKID = USKID;
m_USKSA[USKID]->set_USKID(m_USKID);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify ASUE challenge.
{
wai_variable_data_c * const asue_challenge = parser.get_tlv_pointer(wai_payload_type_nonce);
if (asue_challenge == 0
|| asue_challenge->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (m_asue_unicast_challenge.compare(
asue_challenge->get_data(asue_challenge->get_data_length()),
asue_challenge->get_data_length()) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify WIE_AE.
{
wai_variable_data_c * const wie_ae = parser.get_tlv_pointer(wai_payload_type_wie);
if (wie_ae == 0
|| wie_ae->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (m_wapi_ie_ae.compare(
wie_ae->get_data(wie_ae->get_data_length()),
wie_ae->get_data_length()) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Install unicast session key.
{
eap_variable_data_c unicast_session_key(m_am_tools);
if (unicast_session_key.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = unicast_session_key.set_copy_of_buffer(&m_unicast_encryption_key_UEK);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = unicast_session_key.add_data(&m_unicast_integrity_check_key_UCK);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = packet_data_session_key(
&unicast_session_key,
eapol_key_type_unicast,
m_USKID,
false,
m_packet_data_number.get_data(),
m_packet_data_number.get_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (m_wapi_negotiation_state == wapi_negotiation_state_initial_negotiation)
{
set_wapi_state(wapi_core_state_wait_multicast_announcement_message);
}
else if (m_wapi_negotiation_state == wapi_negotiation_state_rekeying)
{
// Here we swap the addresses.
eap_am_network_id_c send_network_id(m_am_tools,
m_receive_network_id.get_destination_id(),
m_receive_network_id.get_source_id(),
m_receive_network_id.get_type());
if (send_network_id.get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
eap_state_notification_c * notification = new eap_state_notification_c(
m_am_tools,
&send_network_id,
m_is_client,
eap_state_notification_generic,
eap_protocol_layer_wai,
eapol_key_handshake_type_wai_handshake,
eapol_key_state_wapi_authentication_running,
eapol_key_state_wapi_authentication_finished_successfull,
0ul,
false);
if (notification == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
state_notification(notification);
delete notification;
set_wapi_state(wapi_core_state_authentication_ok);
}
else
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::handle_unicast_key_negotiation_confirmation(): negotiation state = %s.\n"),
(m_is_client == true) ? "client": "server",
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
eap_status_e wapi_core_c::handle_multicast_key_announcement(
const eap_am_network_id_c * const receive_network_id,
const wai_protocol_packet_header_c * const wai)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::handle_multicast_key_announcement(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::handle_multicast_key_announcement()");
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (m_wapi_state != wapi_core_state_wait_multicast_announcement_message
&& m_wapi_state != wapi_core_state_authentication_ok)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::handle_multicast_key_announcement(): Verify state %s != %s, negotiation state = %s.\n"),
(m_is_client == true) ? "client": "server",
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_core_state_string(wapi_core_state_wait_multicast_announcement_message),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
if (m_authentication_type != eapol_key_authentication_type_WAI_PSK
&& m_authentication_type != eapol_key_authentication_type_WAI_certificate)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_authentication_type);
}
eap_status_e status(eap_status_process_general_error);
if (receive_network_id == 0
|| receive_network_id->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
if (wai == 0
|| wai->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
}
status = wai->check_header();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (wai->get_packet_sequence_number() != (m_packet_sequence_number + 1u))
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::handle_multicast_key_announcement(): sequence number %d != required sequence number %d.\n"),
(m_is_client == true) ? "client": "server",
wai->get_packet_sequence_number(),
(m_packet_sequence_number + 1u)));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
++m_packet_sequence_number;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
wai_message_payloads_c parser(
m_am_tools,
m_is_client);
if (parser.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
u32_t padding_length(0ul);
status = parser.parse_wai_payloads(
wai->get_header_buffer(wai->get_header_buffer_length()), ///< This is the start of the message buffer.
wai->get_header_buffer_length(), ///< This is the length of the buffer. This must match with the length of all payloads.
&padding_length ///< Length of possible padding is set to this variable.
);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify MAC.
{
wai_variable_data_c * const received_MAC = parser.get_tlv_pointer(wai_payload_type_message_authentication_code);
if (received_MAC == 0
|| received_MAC->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
eap_variable_data_c local_MAC(m_am_tools);
if (local_MAC.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = create_MAC(&parser, &local_MAC);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = local_MAC.set_data_length(WAPI_MESSAGE_AUTHENTICATION_CODE_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
if (local_MAC.compare(
received_MAC->get_data(received_MAC->get_data_length()),
received_MAC->get_data_length()) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure);
}
else
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAI: %s: wapi_core_c::handle_multicast_key_announcement(): MAC OK.\n"),
(m_is_client == true) ? "client": "server"));
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify USK rekeying flag.
{
wai_variable_data_c * const flag_payload = parser.get_tlv_pointer(wai_payload_type_flag);
if (flag_payload == 0
|| flag_payload->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u8_t * const flag = flag_payload->get_data(sizeof(*flag));
if (flag == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (((*flag) & wai_data_flag_mask_USK_Rekeying) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify MSKID.
{
wai_variable_data_c * const MSKID_payload = parser.get_tlv_pointer(wai_payload_type_mskid_stakeyid);
if (MSKID_payload == 0
|| MSKID_payload->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u8_t * const MSKID_pointer = MSKID_payload->get_data(sizeof(*MSKID_pointer));
if (MSKID_pointer == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
u8_t MSKID = (*MSKID_pointer) & wai_data_uskid_mask_mskid;
if (MSKID >= WAPI_MSKSA_COUNT
|| m_MSKSA[MSKID] == 0
|| m_MSKSA[MSKID]->get_is_valid_data() == true)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
m_MSKID = MSKID;
m_MSKSA[MSKID]->set_USKID(m_MSKID);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify USKID.
{
wai_variable_data_c * const USKID_payload = parser.get_tlv_pointer(wai_payload_type_uskid);
if (USKID_payload == 0
|| USKID_payload->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u8_t * const USKID_pointer = USKID_payload->get_data(sizeof(*USKID_pointer));
if (USKID_pointer == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
u8_t USKID = (*USKID_pointer) & wai_data_uskid_mask_uskid;
if (USKID >= WAPI_USKSA_COUNT
|| m_USKSA[USKID] == 0
|| m_USKSA[USKID]->get_is_valid_data() == true)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
m_USKID = USKID;
m_USKSA[USKID]->set_USKID(m_USKID);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Read Data Packet Number.
{
wai_variable_data_c * const packet_data_number = parser.get_tlv_pointer(wai_payload_type_data_sequence_number);
if (packet_data_number == 0
|| packet_data_number->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
status = m_packet_data_number.set_copy_of_buffer(
packet_data_number->get_data(packet_data_number->get_data_length()),
packet_data_number->get_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Read Key Announcement.
{
wai_variable_data_c * const key_announcement = parser.get_tlv_pointer(wai_payload_type_key_announcement_identifier);
if (key_announcement == 0
|| key_announcement->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
status = m_key_announcement.set_copy_of_buffer(
key_announcement->get_data(key_announcement->get_data_length()),
key_announcement->get_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Read and decrypt Key Data.
{
wai_variable_data_c * const key_data = parser.get_tlv_pointer(wai_payload_type_key_data);
if (key_data == 0
|| key_data->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
eap_variable_data_c notification_master_key(m_am_tools);
if (notification_master_key.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = decrypt_multicast_key_data(key_data, &m_key_announcement, ¬ification_master_key);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = create_multicast_key(¬ification_master_key, &m_multicast_key);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create the Multicast Key announcement response message.
wai_message_payloads_c * const payloads = new wai_message_payloads_c(m_am_tools, m_is_client);
eap_automatic_variable_c<wai_message_payloads_c> automatic_payloads(m_am_tools, payloads);
if (payloads == 0
|| payloads->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = payloads->initialise_header();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->get_wai_protocol_packet_header_writable()->set_subtype(wai_protocol_subtype_multicast_key_announcement_response);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds FLAG to data field.
{
wai_variable_data_c data_flag(m_am_tools);
if (data_flag.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
u8_t flag(wai_data_flag_mask_none);
status = data_flag.create(
wai_payload_type_flag,
&flag,
sizeof(flag));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_flag);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds MSKID to data field.
{
wai_variable_data_c data_flag(m_am_tools);
if (data_flag.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_flag.create(
wai_payload_type_mskid_stakeyid,
&m_MSKID,
sizeof(m_MSKID));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_flag);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds USKID to data field.
{
wai_variable_data_c data_USKID(m_am_tools);
if (data_USKID.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_USKID.create(
wai_payload_type_uskid,
&m_USKID,
sizeof(m_USKID));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_USKID);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds ADDID to data field.
{
wai_variable_data_c data_ADDID(m_am_tools);
if (data_ADDID.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
const eap_variable_data_c * MAC_1 = receive_network_id->get_destination_id();
const eap_variable_data_c * MAC_2 = receive_network_id->get_source_id();
if (m_is_client == true)
{
MAC_1 = receive_network_id->get_source_id();
MAC_2 = receive_network_id->get_destination_id();
}
status = data_ADDID.create(
wai_payload_type_addid,
MAC_1);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = data_ADDID.add_data(
wai_payload_type_addid,
MAC_2);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_ADDID);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds Key Announcement to data field.
{
wai_variable_data_c key_announcement(m_am_tools);
if (key_announcement.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = key_announcement.create(
wai_payload_type_data_sequence_number,
&m_key_announcement);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&key_announcement);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds MAC to data field.
{
wai_variable_data_c data_MAC(m_am_tools);
if (data_MAC.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
eap_variable_data_c MAC(m_am_tools);
if (MAC.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = create_MAC(payloads, &MAC);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = MAC.set_data_length(WAPI_MESSAGE_AUTHENTICATION_CODE_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = data_MAC.create(
wai_payload_type_message_authentication_code,
&MAC);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_MAC);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create and send message.
wai_message_c new_wai_message_data(m_am_tools, m_is_client);
if (new_wai_message_data.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = payloads->create_wai_tlv_message(&new_wai_message_data, false);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//cancel_retransmission();
status = packet_send(
&new_wai_message_data,
payloads->get_wai_protocol_packet_header_writable()->get_subtype());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Install multicast session key.
status = packet_data_session_key(
&m_multicast_key,
eapol_key_type_broadcast,
m_MSKID,
false,
m_packet_data_number.get_data(),
m_packet_data_number.get_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{
m_wapi_negotiation_state = wapi_negotiation_state_rekeying;
// Here we swap the addresses.
eap_am_network_id_c send_network_id(m_am_tools,
m_receive_network_id.get_destination_id(),
m_receive_network_id.get_source_id(),
m_receive_network_id.get_type());
if (send_network_id.get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
// This notification to eapol_core_c object.
// WAPI authentication finished successfully.
eap_state_notification_c * notification = new eap_state_notification_c(
m_am_tools,
&send_network_id,
m_is_client,
eap_state_notification_generic,
eap_protocol_layer_wai,
eapol_key_handshake_type_wai_handshake,
eapol_key_state_wapi_authentication_running,
eapol_key_state_wapi_authentication_finished_successfull,
0ul,
false);
if (notification == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
state_notification(notification);
delete notification;
}
cancel_session_timeout();
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
set_wapi_state(wapi_core_state_authentication_ok);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
#if defined(USE_WAPI_CORE_SERVER)
eap_status_e wapi_core_c::handle_multicast_key_announcement_response(
const eap_am_network_id_c * const receive_network_id,
const wai_protocol_packet_header_c * const wai)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::handle_multicast_key_announcement_response(): state=%s, negotiation state = %s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::handle_multicast_key_announcement_response()");
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if (m_wapi_state != wapi_core_state_wait_multicast_announcement_response_message
&& m_wapi_state != wapi_core_state_authentication_ok)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::handle_multicast_key_announcement_response(): Verify state %s != %s, negotiation state = %s.\n"),
(m_is_client == true) ? "client": "server",
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_core_state_string(wapi_core_state_wait_multicast_announcement_response_message),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_unexpected_message);
}
if (m_authentication_type != eapol_key_authentication_type_WAI_PSK
&& m_authentication_type != eapol_key_authentication_type_WAI_certificate)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_authentication_type);
}
eap_status_e status(eap_status_process_general_error);
if (receive_network_id == 0
|| receive_network_id->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
if (wai == 0
|| wai->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
}
status = wai->check_header();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
wai_message_payloads_c parser(
m_am_tools,
m_is_client);
if (parser.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
u32_t padding_length(0ul);
status = parser.parse_wai_payloads(
wai->get_header_buffer(wai->get_header_buffer_length()), ///< This is the start of the message buffer.
wai->get_header_buffer_length(), ///< This is the length of the buffer. This must match with the length of all payloads.
&padding_length ///< Length of possible padding is set to this variable.
);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify MAC.
{
wai_variable_data_c * const received_MAC = parser.get_tlv_pointer(wai_payload_type_message_authentication_code);
if (received_MAC == 0
|| received_MAC->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
eap_variable_data_c local_MAC(m_am_tools);
if (local_MAC.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = create_MAC(&parser, &local_MAC);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = local_MAC.set_data_length(WAPI_MESSAGE_AUTHENTICATION_CODE_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
if (local_MAC.compare(
received_MAC->get_data(received_MAC->get_data_length()),
received_MAC->get_data_length()) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure);
}
else
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAI: %s: wapi_core_c::handle_multicast_key_announcement_response(): MAC OK.\n"),
(m_is_client == true) ? "client": "server"));
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify USK rekeying flag.
{
wai_variable_data_c * const flag_payload = parser.get_tlv_pointer(wai_payload_type_flag);
if (flag_payload == 0
|| flag_payload->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u8_t * const flag = flag_payload->get_data(sizeof(*flag));
if (flag == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (((*flag) & wai_data_flag_mask_USK_Rekeying) != 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify MSKID.
{
wai_variable_data_c * const MSKID_payload = parser.get_tlv_pointer(wai_payload_type_mskid_stakeyid);
if (MSKID_payload == 0
|| MSKID_payload->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u8_t * const MSKID_pointer = MSKID_payload->get_data(sizeof(*MSKID_pointer));
if (MSKID_pointer == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
u8_t MSKID = (*MSKID_pointer) & wai_data_uskid_mask_mskid;
if (MSKID != m_MSKID
|| m_MSKSA[MSKID] == 0
|| m_MSKSA[MSKID]->get_is_valid_data() == true)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify USKID.
{
wai_variable_data_c * const USKID_payload = parser.get_tlv_pointer(wai_payload_type_uskid);
if (USKID_payload == 0
|| USKID_payload->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
const u8_t * const USKID_pointer = USKID_payload->get_data(sizeof(*USKID_pointer));
if (USKID_pointer == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
u8_t USKID = (*USKID_pointer) & wai_data_uskid_mask_uskid;
if (USKID >= WAPI_USKSA_COUNT
|| m_USKSA[USKID] == 0
|| m_USKSA[USKID]->get_is_valid_data() == true)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify Key Announcement.
{
wai_variable_data_c * const key_announcement = parser.get_tlv_pointer(wai_payload_type_key_announcement_identifier);
if (key_announcement == 0
|| key_announcement->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
if (m_key_announcement.compare(
key_announcement->get_data(key_announcement->get_data_length()),
key_announcement->get_data_length()) != 0)
{
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: local m_key_announcement"),
m_key_announcement.get_data(),
m_key_announcement.get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: received key_announcement"),
key_announcement->get_data(key_announcement->get_data_length()),
key_announcement->get_data_length()));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Install multicast session key.
status = packet_data_session_key(
&m_multicast_key,
eapol_key_type_broadcast,
m_MSKID,
false,
m_packet_data_number.get_data(),
m_packet_data_number.get_data_length());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{
m_wapi_negotiation_state = wapi_negotiation_state_rekeying;
// Here we swap the addresses.
eap_am_network_id_c send_network_id(m_am_tools,
m_receive_network_id.get_destination_id(),
m_receive_network_id.get_source_id(),
m_receive_network_id.get_type());
if (send_network_id.get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
// This notification to eapol_core_c object.
// WAPI authentication finished successfully.
eap_state_notification_c * notification = new eap_state_notification_c(
m_am_tools,
&send_network_id,
m_is_client,
eap_state_notification_generic,
eap_protocol_layer_wai,
eapol_key_handshake_type_wai_handshake,
eapol_key_state_wapi_authentication_running,
eapol_key_state_wapi_authentication_finished_successfull,
0ul,
false);
if (notification == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
state_notification(notification);
delete notification;
}
cancel_session_timeout();
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
set_wapi_state(wapi_core_state_authentication_ok);
//cancel_retransmission();
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
#endif //#if defined(USE_WAPI_CORE_SERVER)
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::packet_process(
const eap_am_network_id_c * const receive_network_id,
eap_general_header_base_c * const packet_data,
const u32_t packet_length)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAI: %s: wapi_core_c::packet_process(): state = %s, negotiation state = %s.\n"),
(m_is_client == true) ? "client": "server",
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
eap_status_e status(eap_status_process_general_error);
// This automatic variable stores the current packet sequence number.
// If the received packet is illegal the current packet sequence number is restored.
eap_automatic_simple_value_c<u16_t> automatic_packet_sequence_number(
m_am_tools,
&m_packet_sequence_number,
m_packet_sequence_number);
// This automatic variable stores the current WAPI-state.
// If the received packet is illegal the current WAPI-state is restored.
eap_automatic_simple_value_c<wapi_core_state_e> automatic_wapi_state(
m_am_tools,
&m_wapi_state,
m_wapi_state);
if (m_wapi_state == wapi_core_state_none)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAI: %s: wapi_core_c::packet_process(): Verify state %s == %s, negotiation state = %s, drop packet.\n"),
(m_is_client == true) ? "client": "server",
wapi_strings_c::get_wapi_core_state_string(m_wapi_state),
wapi_strings_c::get_wapi_core_state_string(wapi_core_state_none),
wapi_strings_c::get_wapi_negotiation_state_string(m_wapi_negotiation_state)));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
}
if (packet_data == 0
|| packet_data->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
}
if (receive_network_id == 0
|| receive_network_id->get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
if (packet_length < eap_header_base_c::get_header_length())
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_too_short_message);
}
wai_protocol_packet_header_c wai(
m_am_tools,
packet_data->get_header_buffer(packet_length),
packet_length);
if (wai.get_is_valid() == false)
{
EAP_TRACE_ERROR(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("packet_process: %s, packet buffer corrupted.\n"),
(m_is_client_role == true) ? "client": "server"
));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
EAP_TRACE_FLAGS_MESSAGE_DATA|TRACE_TEST_VECTORS,
(EAPL("WAI-packet"),
wai.get_header_buffer(packet_length),
packet_length));
WAI_PROTOCOL_PACKET_TRACE_HEADER("wapi_core_c::packet_process(): ->", &wai, m_is_client_role);
status = wai.check_header();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
if (m_shutdown_was_called == true
&& m_is_client_role == true)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WARNING: WAPI_Core: %s, wapi_core_c::packet_process(): %s packet dropped quietly because shutdown was already called.\n"),
(m_is_client_role == true) ? "client": "server",
wapi_strings_c::get_wai_protocol_subtype_string(wai.get_subtype())));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
}
status = packet_reassemble(&wai);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
wai_protocol_packet_header_c reass_wai(
m_am_tools,
m_reassemble_packet.get_data(),
m_reassemble_packet.get_data_length());
if (reass_wai.get_is_valid() == false)
{
EAP_TRACE_ERROR(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::packet_process(): %s, packet buffer corrupted.\n"),
(m_is_client_role == true) ? "client": "server"
));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
}
if (m_is_client_role == true)
{
status = check_retransmission(&reass_wai);
if (status == eap_status_ok)
{
// OK, re-transmitted an old packet.
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
switch(reass_wai.get_subtype())
{
case wai_protocol_subtype_authentication_activation:
status = handle_authentication_activation(receive_network_id, &reass_wai);
break;
case wai_protocol_subtype_access_authentication_response:
status = handle_access_authentication_response(receive_network_id, &reass_wai);
break;
case wai_protocol_subtype_unicast_key_negotiation_request:
status = handle_unicast_key_negotiation_request(receive_network_id, &reass_wai);
break;
case wai_protocol_subtype_unicast_key_negotiation_confirmation:
status = handle_unicast_key_negotiation_confirmation(receive_network_id, &reass_wai);
break;
case wai_protocol_subtype_multicast_key_announcement:
status = handle_multicast_key_announcement(receive_network_id, &reass_wai);
break;
default:
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAPI_Core: %s, wapi_core_c::packet_process(): Unknown %d=%s packet dropped quietly.\n"),
(m_is_client_role == true) ? "client": "server",
reass_wai.get_subtype(),
wapi_strings_c::get_wai_protocol_subtype_string(reass_wai.get_subtype())));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
};
}
#if defined(USE_WAPI_CORE_SERVER)
else
{
switch(reass_wai.get_subtype())
{
case wai_protocol_subtype_access_authentication_request:
status = handle_access_authentication_request(receive_network_id, &reass_wai);
break;
case wai_protocol_subtype_unicast_key_negotiation_response:
status = handle_unicast_key_negotiation_response(receive_network_id, &reass_wai);
break;
case wai_protocol_subtype_multicast_key_announcement_response:
status = handle_multicast_key_announcement_response(receive_network_id, &reass_wai);
break;
default:
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: WAPI_Core: %s, wapi_core_c::packet_process(): Unknown %d=%s packet dropped quietly.\n"),
(m_is_client_role == true) ? "client": "server",
reass_wai.get_subtype(),
wapi_strings_c::get_wai_protocol_subtype_string(reass_wai.get_subtype())));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
};
}
#endif //#if defined(USE_WAPI_CORE_SERVER)
if (status == eap_status_ok
|| status == eap_status_pending_request)
{
automatic_packet_sequence_number.do_not_restore_variable();
automatic_wapi_state.do_not_restore_variable();
}
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT eap_status_e wapi_core_c::packet_send(
const eap_am_network_id_c * const send_network_id,
eap_buf_chain_wr_c * const sent_packet,
const u32_t header_offset,
const u32_t data_length,
const u32_t buffer_length)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
wai_protocol_packet_header_c wai(
m_am_tools,
sent_packet->get_data_offset(
header_offset, data_length),
data_length);
if (wai.get_is_valid() == false)
{
EAP_TRACE_ERROR(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("packet_send(): %s, packet buffer corrupted.\n"),
(m_is_client_role == true) ? "client": "server"
));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
}
EAP_ASSERT(header_offset < sent_packet->get_data_length());
EAP_ASSERT(data_length <= sent_packet->get_data_length());
EAP_ASSERT(sent_packet->get_data_length() <= buffer_length);
EAP_TRACE_DATA_DEBUG(
m_am_tools,
EAP_TRACE_FLAGS_MESSAGE_DATA|TRACE_TEST_VECTORS,
(EAPL("WAI-packet"),
wai.get_header_buffer(data_length),
data_length));
WAI_PROTOCOL_PACKET_TRACE_HEADER("wapi_core_c::packet_send(): <-", &wai, m_is_client_role);
if (m_shutdown_was_called == true
&& m_is_client_role == true)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WARNING: WAPI_Core: %s, wapi_core_c::packet_send(): %s packet dropped quietly because shutdown was already called.\n"),
(m_is_client_role == true) ? "client": "server",
wapi_strings_c::get_wai_protocol_subtype_string(wai.get_subtype())));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
}
eap_status_e status = m_partner->packet_send(
send_network_id, sent_packet, header_offset, data_length, buffer_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::resend_packet(
const eap_am_network_id_c * const send_network_id,
const wai_message_c * const wai_message_data,
const u32_t retransmission_counter,
const u16_t packet_sequence_number)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_UNREFERENCED_PARAMETER(retransmission_counter); // Only trace uses this.
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("<- WAPI_Core: %s: wapi_core_c::resend_packet(), counter %d.\n"),
(m_is_client_role == true) ? "client": "server",
retransmission_counter
));
// We make a copy because random error test may corrupt the data.
wai_message_c * const copy_packet = wai_message_data->copy();
if (copy_packet == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
// NOTE: send packet directly to partner object.
// This will skip initialization of re-transmission for re-transmitted packet.
eap_status_e status = packet_fragment(
copy_packet,
packet_sequence_number);
delete copy_packet;
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::cancel_retransmission()
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: %s: WAPI_CORE_TIMER_RETRANSMISSION_ID cancelled.\n"),
(m_is_client_role == true ? "client": "server")
));
if (m_is_client_role == false)
{
// Only WAPI-server uses timer to re-transmits WAI-packets.
m_partner->cancel_timer(this, WAPI_CORE_TIMER_RETRANSMISSION_ID);
}
m_retransmission.reset();
}
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::init_retransmission(
const eap_am_network_id_c * const send_network_id,
const wai_message_c * const received_wai_message_data,
const wai_message_c * const new_wai_message_data,
const u16_t packet_sequence_number,
const wai_protocol_subtype_e wapi_subtype
)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
if (m_is_client_role == false)
{
if (m_retransmission_time == 0u
|| m_retransmission_counter == 0u)
{
// No retransmission.
return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
}
}
EAP_ASSERT(send_network_id->get_source() != 0);
EAP_ASSERT(send_network_id->get_destination() != 0);
wapi_core_retransmission_c * retransmission = new wapi_core_retransmission_c(
m_am_tools,
send_network_id,
received_wai_message_data,
new_wai_message_data,
m_retransmission_time,
m_retransmission_counter,
packet_sequence_number,
wapi_subtype);
if (retransmission == 0
|| retransmission->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
eap_status_e status = m_retransmission.add_object_to_begin(
retransmission,
true);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
if (m_is_client_role == false)
{
// Only WAPI-server uses timer to re-transmits WAI-packets.
m_partner->cancel_timer(this, WAPI_CORE_TIMER_RETRANSMISSION_ID);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: %s: WAPI_CORE_TIMER_RETRANSMISSION_ID cancelled.\n"),
(m_is_client_role == true ? "client": "server")
));
}
retransmission = m_retransmission.get_object(0ul);
if (retransmission == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
if (retransmission->get_is_valid() == true)
{
if (m_is_client_role == false)
{
// Only WAPI-server uses timer to re-transmits WAI-packets.
u32_t next_retransmission_time = retransmission->get_next_retransmission_time();
eap_status_e status = m_partner->set_timer(this, WAPI_CORE_TIMER_RETRANSMISSION_ID, 0,
next_retransmission_time);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: %s: WAPI_CORE_TIMER_RETRANSMISSION_ID set %d ms.\n"),
(m_is_client_role == true ? "client": "server"),
next_retransmission_time));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
else
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
}
}
else
{
(void) m_retransmission.remove_object(0ul);
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
}
//--------------------------------------------------
eap_status_e wapi_core_c::check_retransmission(const wai_protocol_packet_header_c * const received_wai)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::check_retransmission(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::check_retransmission()");
EAP_ASSERT(m_is_client == true);
eap_status_e status(eap_status_process_general_error);
if (received_wai == 0
|| received_wai->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
for (u32_t index = 0ul; index < m_retransmission.get_object_count(); ++index)
{
const wapi_core_retransmission_c * const retransmission = m_retransmission.get_object(index);
if (retransmission == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_not_found);
}
const wai_message_c * const message = retransmission->get_wai_received_message_data();
if (message == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_not_found);
}
else
{
wai_protocol_packet_header_c wai(
m_am_tools,
message->get_wai_message_data()->get_data(),
message->get_wai_message_data()->get_data_length());
if (wai.get_is_valid() == false)
{
EAP_TRACE_ERROR(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::packet_fragment(): %s, packet buffer corrupted.\n"),
(m_is_client_role == true) ? "client": "server"
));
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
}
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("%s: wapi_core_c::check_retransmission(): wai.get_version()=%d, received_wai->get_version()=%d\n"),
(m_is_client == true ? "client": "server"),
wai.get_version(),
received_wai->get_version()));
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("%s: wapi_core_c::check_retransmission(): wai.get_type()=%d, received_wai->get_type()=%d\n"),
(m_is_client == true ? "client": "server"),
wai.get_type(),
received_wai->get_type()));
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("%s: wapi_core_c::check_retransmission(): wai.get_subtype()=%d, received_wai->get_subtype()=%d\n"),
(m_is_client == true ? "client": "server"),
wai.get_subtype(),
received_wai->get_subtype()));
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("%s: wapi_core_c::check_retransmission(): wai.get_packet_sequence_number()=%d, received_wai->get_packet_sequence_number()=%d\n"),
(m_is_client == true ? "client": "server"),
wai.get_packet_sequence_number(),
received_wai->get_packet_sequence_number()));
if (wai.get_version() == received_wai->get_version()
&& wai.get_type() == received_wai->get_type()
&& wai.get_subtype() == received_wai->get_subtype()
&& wai.get_packet_sequence_number() == received_wai->get_packet_sequence_number())
{
status = resend_packet(
retransmission->get_send_network_id(),
retransmission->get_wai_message_data(),
retransmission->get_retransmission_counter(),
retransmission->get_packet_sequence_number());
if (status == eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
} // for()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_not_found);
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT eap_status_e wapi_core_c::set_wapi_failure_timeout()
{
eap_status_e status = m_partner->set_timer(
this,
WAPI_CORE_FAILURE_RECEIVED_ID,
0,
m_wapi_core_failure_received_timeout);
if (status != eap_status_ok)
{
EAP_TRACE_ERROR(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: TIMER: %s: WAPI_CORE_FAILURE_RECEIVED_ID failed.\n"),
(m_is_client_role == true ? "client": "server")
));
}
else
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: %s: WAPI_CORE_FAILURE_RECEIVED_ID set %d ms.\n"),
(m_is_client_role == true ? "client": "server"),
m_wapi_core_failure_received_timeout
));
}
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT eap_status_e wapi_core_c::cancel_wapi_failure_timeout()
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: %s: WAPI_CORE_FAILURE_RECEIVED_ID cancelled.\n"),
(m_is_client_role == true ? "client": "server")
));
return m_partner->cancel_timer(
this,
WAPI_CORE_FAILURE_RECEIVED_ID);
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT u32_t wapi_core_c::get_header_offset(
u32_t * const MTU,
u32_t * const trailer_length)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
const u32_t offset = m_partner->get_header_offset(MTU, trailer_length);
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::get_header_offset(): offset=%d, MTU=%d, trailer_length=%d\n"),
offset,
*MTU,
*trailer_length));
return offset;
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT eap_status_e wapi_core_c::configure()
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
#if !defined(USE_EAP_DEBUG_TRACE)
EAP_TRACE_ALWAYS(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::configure(): %s\n"),
((m_is_client == true) ? "client": "server")));
#else
EAP_TRACE_ALWAYS(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::configure(): %s: this = 0x%08x => 0x%08x.\n"),
((m_is_client == true) ? "client": "server"),
this,
dynamic_cast<abs_eap_base_timer_c *>(this)));
#endif
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::configure()");
EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#if defined(USE_EAP_TEST_VECTORS)
{
eap_variable_data_c data(m_am_tools);
eap_status_e status = m_partner->read_configure(
cf_str_EAP_TRACE_only_trace_messages.get_field(),
&data);
if (status == eap_status_ok
&& data.get_data_length() == sizeof(u32_t)
&& data.get_data(data.get_data_length()) != 0)
{
if (*(reinterpret_cast<u32_t *>(data.get_data(data.get_data_length()))) != 0u)
{
// Activate only WAPI message traces.
m_am_tools->set_trace_mask(
eap_am_tools_c::eap_trace_mask_always
| eap_am_tools_c::eap_trace_mask_eap_messages);
}
else
{
// Disable only WAPI message traces.
m_am_tools->set_trace_mask(
m_am_tools->get_trace_mask() & (~eap_am_tools_c::eap_trace_mask_eap_messages));
}
}
else
{
// Disable only WAPI message traces.
m_am_tools->set_trace_mask(
m_am_tools->get_trace_mask() & (~eap_am_tools_c::eap_trace_mask_eap_messages));
}
}
{
eap_variable_data_c data(m_am_tools);
eap_status_e status = m_partner->read_configure(
cf_str_EAP_TRACE_only_test_vectors.get_field(),
&data);
if (status == eap_status_ok
&& data.get_data_length() == sizeof(u32_t)
&& data.get_data(data.get_data_length()) != 0)
{
if (*(reinterpret_cast<u32_t *>(data.get_data(data.get_data_length()))) != 0u)
{
// Activates only WAPI test vector traces.
m_am_tools->set_trace_mask(eap_am_tools_c::eap_trace_mask_test_vectors);
}
}
}
{
eap_variable_data_c data(m_am_tools);
eap_status_e status = m_partner->read_configure(
cf_str_EAP_TRACE_crypto_test_vectors_sha1.get_field(),
&data);
if (status == eap_status_ok
&& data.get_data_length() == sizeof(u32_t)
&& data.get_data(data.get_data_length()) != 0)
{
if (*(reinterpret_cast<u32_t *>(data.get_data(data.get_data_length()))) != 0u)
{
// Activates SHA1 WAPI test vector traces.
m_am_tools->set_trace_mask(m_am_tools->get_trace_mask()
| eap_am_tools_c::eap_trace_mask_crypto_sha1);
}
}
}
{
eap_variable_data_c data(m_am_tools);
eap_status_e status = m_partner->read_configure(
cf_str_EAP_TRACE_crypto_test_vectors_rc4.get_field(),
&data);
if (status == eap_status_ok
&& data.get_data_length() == sizeof(u32_t)
&& data.get_data(data.get_data_length()) != 0)
{
if (*(reinterpret_cast<u32_t *>(data.get_data(data.get_data_length()))) != 0u)
{
// Activates RC4 WAPI test vector traces.
m_am_tools->set_trace_mask(m_am_tools->get_trace_mask()
| eap_am_tools_c::eap_trace_mask_crypto_rc4);
}
}
}
{
eap_variable_data_c data(m_am_tools);
eap_status_e status = m_partner->read_configure(
cf_str_EAP_TRACE_crypto_test_vectors_md4.get_field(),
&data);
if (status == eap_status_ok
&& data.get_data_length() == sizeof(u32_t)
&& data.get_data(data.get_data_length()) != 0)
{
if (*(reinterpret_cast<u32_t *>(data.get_data(data.get_data_length()))) != 0u)
{
// Activates MD4 WAPI test vector traces.
m_am_tools->set_trace_mask(m_am_tools->get_trace_mask()
| eap_am_tools_c::eap_trace_mask_crypto_md4);
}
}
}
{
eap_variable_data_c data(m_am_tools);
eap_status_e status = m_partner->read_configure(
cf_str_EAP_TRACE_crypto_test_vectors_test_random.get_field(),
&data);
if (status == eap_status_ok
&& data.get_data_length() == sizeof(u32_t)
&& data.get_data(data.get_data_length()) != 0)
{
if (*(reinterpret_cast<u32_t *>(data.get_data(data.get_data_length()))) != 0u)
{
// Activates test random generator WAPI test vector traces.
m_am_tools->set_trace_mask(m_am_tools->get_trace_mask()
| eap_am_tools_c::eap_trace_mask_crypto_test_random
| eap_am_tools_c::eap_trace_mask_crypto_sha1);
}
}
}
#endif //#if defined(USE_EAP_TEST_VECTORS)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#if defined(USE_WAPI_CORE_SERVER)
if (m_is_client == false)
{
eap_variable_data_c retransmission_time(m_am_tools);
eap_status_e status = read_configure(
cf_str_WAPI_CORE_retransmission_time.get_field(),
&retransmission_time);
if (status == eap_status_ok
&& retransmission_time.get_is_valid_data() == true)
{
u32_t *retransmission_time_value = reinterpret_cast<u32_t *>(
retransmission_time.get_data(sizeof(u32_t)));
if (retransmission_time_value != 0)
{
m_retransmission_time = *retransmission_time_value;
}
else
{
m_retransmission_time = WAPI_CORE_RETRANSMISSION_TIME;
}
}
else
{
m_retransmission_time = WAPI_CORE_RETRANSMISSION_TIME;
}
}
#endif //#if defined(USE_WAPI_CORE_SERVER)
{
eap_variable_data_c retransmission_counter(m_am_tools);
eap_status_e status = read_configure(
cf_str_WAPI_CORE_retransmission_counter.get_field(),
&retransmission_counter);
if (status == eap_status_ok
&& retransmission_counter.get_is_valid_data() == true)
{
u32_t *retransmission_counter_value = reinterpret_cast<u32_t *>(
retransmission_counter.get_data(sizeof(u32_t)));
if (retransmission_counter_value != 0)
{
m_retransmission_counter = *retransmission_counter_value;
}
else
{
m_retransmission_counter = WAPI_CORE_RETRANSMISSION_COUNTER;
}
}
else
{
m_retransmission_counter = WAPI_CORE_RETRANSMISSION_COUNTER;
}
}
//----------------------------------------------------------
{
eap_variable_data_c session_timeout(m_am_tools);
eap_status_e status = read_configure(
cf_str_WAPI_CORE_session_timeout.get_field(),
&session_timeout);
if (status == eap_status_ok
&& session_timeout.get_is_valid_data() == true)
{
u32_t *handler_timeout = reinterpret_cast<u32_t *>(
session_timeout.get_data(sizeof(u32_t)));
if (handler_timeout != 0)
{
m_session_timeout = *handler_timeout;
}
else
{
m_session_timeout = WAPI_CORE_SESSION_TIMEOUT;
}
}
else
{
m_session_timeout = WAPI_CORE_SESSION_TIMEOUT;
}
}
#if defined(USE_WAPI_CORE_SERVER)
if (m_is_client == false)
{
eap_variable_data_c session_timeout(m_am_tools);
eap_status_e status = read_configure(
cf_str_WAPI_CORE_server_session_timeout.get_field(),
&session_timeout);
if (status == eap_status_ok
&& session_timeout.get_is_valid_data() == true)
{
u32_t *handler_timeout = reinterpret_cast<u32_t *>(
session_timeout.get_data(sizeof(u32_t)));
if (handler_timeout != 0)
{
// This is optional.
m_session_timeout = *handler_timeout;
}
}
}
//----------------------------------------------------------
if (m_is_client == false)
{
eap_variable_data_c only_initial_authentication(m_am_tools);
eap_status_e status = read_configure(
cf_str_WAPI_CORE_server_only_initial_authentication.get_field(),
&only_initial_authentication);
if (status == eap_status_ok
&& only_initial_authentication.get_is_valid_data() == true)
{
u32_t *flag = reinterpret_cast<u32_t *>(
only_initial_authentication.get_data(sizeof(u32_t)));
if (flag != 0)
{
if (*flag == 0)
{
m_only_initial_authentication = false;
}
else
{
m_only_initial_authentication = true;
}
}
}
}
//----------------------------------------------------------
if (m_is_client == false)
{
eap_status_e status = m_partner->read_configure(
cf_str_WAPI_CORE_server_test_other_asu_id.get_field(),
&m_test_other_asu_id);
if (status == eap_status_ok
&& m_test_other_asu_id.get_is_valid_data() == true)
{
// This is optional for testing purposes.
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::configure(): Other ASU ID\n"),
this,
(m_is_client == true ? "client": "server")));
}
}
#endif //#if defined(USE_WAPI_CORE_SERVER)
//----------------------------------------------------------
{
eap_variable_data_c failure_received_timeout(m_am_tools);
eap_status_e status = read_configure(
cf_str_WAPI_CORE_failure_received_timeout.get_field(),
&failure_received_timeout);
if (status == eap_status_ok
&& failure_received_timeout.get_is_valid_data() == true)
{
u32_t *timeout = reinterpret_cast<u32_t *>(
failure_received_timeout.get_data(sizeof(u32_t)));
if (timeout != 0)
{
m_wapi_core_failure_received_timeout = *timeout;
}
}
}
//----------------------------------------------------------
{
eap_status_e status = read_configure(
cf_str_WAPI_CORE_PSK.get_field(),
&m_preshared_key_PSK);
if (status == eap_status_ok)
{
if (m_preshared_key_PSK.get_data_length() == WAPI_BK_LENGTH)
{
status = m_BK.set_copy_of_buffer(&m_preshared_key_PSK);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
else
{
// Create BK from PSK and label.
crypto_kd_hmac_sha256_c kd_hmac(m_am_tools);
if (kd_hmac.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
const eap_variable_data_c label(
m_am_tools,
WAPI_PRESHARED_KEY_LABEL,
WAPI_PRESHARED_KEY_LABEL_LENGTH,
false,
false);
if (label.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = kd_hmac.expand_key(
&m_BK,
WAPI_BK_LENGTH,
&m_preshared_key_PSK,
&label);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
}
}
//----------------------------------------------------------
m_wapi_header_offset = m_partner->get_header_offset(&m_MTU, &m_trailer_length);
// Add session timeout.
initialize_session_timeout(m_session_timeout);
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT eap_status_e wapi_core_c::shutdown()
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
eap_status_e status(eap_status_ok);
#if !defined(USE_EAP_DEBUG_TRACE)
EAP_TRACE_ALWAYS(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::shutdown(): %s: m_shutdown_was_called=%d.\n"),
((m_is_client == true) ? "client": "server"),
m_shutdown_was_called));
#else
EAP_TRACE_ALWAYS(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::shutdown(): %s: this = 0x%08x => 0x%08x, ")
EAPL("m_shutdown_was_called=%d.\n"),
((m_is_client == true) ? "client": "server"),
this,
dynamic_cast<abs_eap_base_timer_c *>(this),
m_shutdown_was_called));
#endif
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::shutdown()");
if (m_shutdown_was_called == true)
{
// Shutdown was already called once.
return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
}
m_shutdown_was_called = true;
cancel_retransmission();
cancel_session_timeout();
cancel_wapi_failure_timeout();
cancel_asynchronous_init_remove_wapi_session();
if (m_partner != 0)
{
cancel_session_timeout();
}
if (m_ec_certificate_store != 0)
{
m_ec_certificate_store->shutdown();
}
if (m_am_wapi_core != 0)
{
m_am_wapi_core->shutdown();
}
#if !defined(USE_EAP_DEBUG_TRACE)
EAP_TRACE_ALWAYS(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::shutdown(): %s: m_shutdown_was_called=%d, status=%d returns.\n"),
((m_is_client == true) ? "client": "server"),
m_shutdown_was_called,
status));
#else
EAP_TRACE_ALWAYS(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::shutdown(): %s: this = 0x%08x => 0x%08x, ")
EAPL("m_shutdown_was_called=%d, status=%d returns.\n"),
((m_is_client == true) ? "client": "server"),
this,
dynamic_cast<abs_eap_base_timer_c *>(this),
m_shutdown_was_called,
status));
#endif
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT eap_status_e wapi_core_c::restart_authentication(
const eap_am_network_id_c * const send_network_id,
const bool is_client_when_true)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
// Here we swap the addresses.
eap_am_network_id_c receive_network_id(m_am_tools,
send_network_id->get_destination_id(),
send_network_id->get_source_id(),
send_network_id->get_type());
eap_status_e status = eap_status_process_general_error;
initialize_session_timeout(m_session_timeout);
if (is_client_when_true == false)
{
status = start_authentication();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
m_client_restart_authentication_initiated = true;
}
else
{
if (m_client_restart_authentication_initiated == true)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
}
status = allow_authentication();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
m_client_restart_authentication_initiated = true;
}
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::read_configure(
const eap_configuration_field_c * const field,
eap_variable_data_c * const data)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
const eap_status_e status = m_partner->read_configure(field, data);
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::write_configure(
const eap_configuration_field_c * const field,
eap_variable_data_c * const data)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
const eap_status_e status = m_partner->write_configure(field, data);
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT eap_status_e wapi_core_c::timer_expired(
const u32_t id, void *data)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_UNREFERENCED_PARAMETER(data); // Only trace uses this.
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: [0x%08x]->wapi_core_c::timer_expired(id 0x%02x, data 0x%08x), %s.\n"),
this,
id,
data,
(m_is_client == true) ? "client": "server"));
EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
eap_status_e status(eap_status_process_general_error);
if (id == WAPI_CORE_TIMER_RETRANSMISSION_ID)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: %s: WAPI_CORE_TIMER_RETRANSMISSION_ID elapsed.\n"),
(m_is_client == true ? "client": "server")
));
if (m_retransmission.get_object_count() > 0ul)
{
wapi_core_retransmission_c * const retransmission = m_retransmission.get_object(0ul);
if (retransmission != 0
&& retransmission->get_is_valid() == true
&& retransmission->get_retransmission_counter() > 0)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: %s, new retransmission, retransmission->get_is_valid()=%d, ")
EAPL("retransmission->get_retransmission_counter()=%d.\n"),
(m_is_client == true) ? "client": "server",
retransmission->get_is_valid(),
retransmission->get_retransmission_counter()));
status = eap_status_ok;
if (retransmission->get_wapi_subtype() == wai_protocol_subtype_unicast_key_negotiation_request
|| retransmission->get_wapi_subtype() == wai_protocol_subtype_multicast_key_announcement)
{
// Also the previous message must be re-transmitted.
if (m_retransmission.get_object_count() > 1ul)
{
wapi_core_retransmission_c * const prev_retransmission = m_retransmission.get_object(1ul);
if (prev_retransmission != 0
&& prev_retransmission->get_is_valid() == true
&& prev_retransmission->get_retransmission_counter() > 0)
{
status = resend_packet(
prev_retransmission->get_send_network_id(),
prev_retransmission->get_wai_message_data(),
prev_retransmission->get_retransmission_counter(),
prev_retransmission->get_packet_sequence_number());
}
}
}
if (status == eap_status_ok)
{
status = resend_packet(
retransmission->get_send_network_id(),
retransmission->get_wai_message_data(),
retransmission->get_retransmission_counter(),
retransmission->get_packet_sequence_number());
}
if (status == eap_status_ok)
{
if (retransmission->get_retransmission_counter() > 0u)
{
// OK, initialize the next time to retransmit.
u32_t next_retransmission_time
= retransmission->get_next_retransmission_time();
status = m_partner->set_timer(
this,
WAPI_CORE_TIMER_RETRANSMISSION_ID,
0,
next_retransmission_time);
if (status != eap_status_ok)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("ERROR: TIMER: %s: WAPI_CORE_TIMER_RETRANSMISSION_ID ")
EAPL("set %d ms, retransmission_counter %d, failed.\n"),
(m_is_client == true ? "client": "server"),
next_retransmission_time,
retransmission->get_retransmission_counter()));
}
else
{
retransmission->get_next_retransmission_counter(); // This decrements the counter.
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: %s: WAPI_CORE_TIMER_RETRANSMISSION_ID ")
EAPL("set %d ms, retransmission_counter %d.\n"),
(m_is_client == true ? "client": "server"),
next_retransmission_time,
retransmission->get_retransmission_counter()));
}
}
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
else
{
status = eap_status_ok;
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
else
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: %s, no retransmission, m_retransmission=0x%08x.\n"),
(m_is_client == true) ? "client": "server",
retransmission));
if (retransmission != 0)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: %s, no retransmission, retransmission->get_is_valid()=%d, ")
EAPL("retransmission->get_retransmission_counter()=%d.\n"),
(m_is_client == true) ? "client": "server",
retransmission->get_is_valid(),
retransmission->get_retransmission_counter()));
}
// No good WAI-Response received to WAI-Requests.
// Terminate the session.
{
eap_am_network_id_c send_network_id(
m_am_tools,
m_receive_network_id.get_destination_id(),
m_receive_network_id.get_source_id(),
m_receive_network_id.get_type());
eap_state_notification_c notification(
m_am_tools,
&send_network_id,
m_is_client,
eap_state_notification_eap,
eap_protocol_layer_eap,
eap_type_none,
eap_state_none,
eap_state_authentication_terminated_unsuccessfully,
0ul,
false);
notification.set_authentication_error(eap_status_authentication_failure);
state_notification(¬ification);
}
status = eap_status_ok;
}
}
else
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: %s, no retransmission, count of m_retransmission=%d.\n"),
(m_is_client == true) ? "client": "server",
m_retransmission.get_object_count()));
}
}
else if (id == WAPI_CORE_SESSION_TIMEOUT_ID)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: %s: WAPI_CORE_SESSION_TIMEOUT_ID elapsed.\n"),
(m_is_client == true ? "client": "server")
));
// we will remove this session immediately.
status = initialize_asynchronous_init_remove_wapi_session(0ul);
{
// Here we swap the addresses.
eap_am_network_id_c send_network_id(m_am_tools,
m_receive_network_id.get_destination_id(),
m_receive_network_id.get_source_id(),
m_receive_network_id.get_type());
if (send_network_id.get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
// This notification to eapol_core_c object.
// WAI authentication terminated unsuccessfully.
eap_state_notification_c * notification = new eap_state_notification_c(
m_am_tools,
&send_network_id,
m_is_client,
eap_state_notification_generic,
eap_protocol_layer_wai,
eapol_key_handshake_type_wai_handshake,
eapol_key_state_wapi_authentication_running,
eapol_key_state_wapi_authentication_terminated_unsuccessfull,
0ul,
false);
if (notification == 0)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
notification->set_authentication_error(eap_status_authentication_failure);
state_notification(notification);
delete notification;
set_wapi_state(wapi_core_state_authentication_failed);
}
return EAP_STATUS_RETURN(m_am_tools, status);
}
else if (id == WAPI_CORE_REMOVE_SESSION_TIMEOUT_ID)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: %s: WAPI_CORE_REMOVE_SESSION_TIMEOUT_ID elapsed.\n"),
(m_is_client == true ? "client": "server")
));
status = asynchronous_init_remove_wapi_session();
}
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT eap_status_e wapi_core_c::timer_delete_data(
const u32_t id, void *data)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_UNREFERENCED_PARAMETER(data); // Only trace uses this.
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: [0x%08x]->wapi_core_c::timer_delete_data(id 0x%02x, data 0x%08x): %s.\n"),
this,
id,
data,
(m_is_client == true) ? "client": "server"
));
EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
if (id == WAPI_CORE_TIMER_RETRANSMISSION_ID)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("TIMER: %s: WAPI_CORE_TIMER_RETRANSMISSION_ID delete data.\n"),
(m_is_client == true ? "client": "server")
));
if (m_retransmission.get_object_count() > 0ul)
{
wapi_core_retransmission_c * const retransmission = m_retransmission.get_object(0ul);
if (retransmission != 0
&& retransmission->get_is_valid() == true
&& retransmission->get_retransmission_counter() > 0)
{
// Do not delete yet.
// cancel_retransmission() will delete m_retransmission.
}
else if (retransmission != 0)
{
(void) m_retransmission.remove_object(0ul);
}
}
}
else if (id == WAPI_CORE_REMOVE_SESSION_TIMEOUT_ID)
{
// Nothing to do.
}
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT eap_status_e wapi_core_c::reset()
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
#if !defined(USE_EAP_DEBUG_TRACE)
EAP_TRACE_ALWAYS(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::reset(): %s.\n"),
((m_is_client == true) ? "client": "server")));
#else
EAP_TRACE_ALWAYS(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("wapi_core_c::reset(): %s: this = 0x%08x => 0x%08x.\n"),
((m_is_client == true) ? "client": "server"),
this,
dynamic_cast<abs_eap_base_timer_c *>(this)));
#endif
eap_status_e status = eap_status_ok;
cancel_retransmission();
cancel_session_timeout();
cancel_wapi_failure_timeout();
cancel_asynchronous_init_remove_wapi_session();
// restart message sequencing
m_packet_sequence_number = 0ul;
// Add session timeout.
initialize_session_timeout(m_session_timeout);
m_wapi_state = wapi_core_state_none;
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT eap_status_e wapi_core_c::set_session_timeout(
const u32_t session_timeout_ms)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
eap_status_e status = initialize_session_timeout(session_timeout_ms);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT eap_status_e wapi_core_c::set_timer(
abs_eap_base_timer_c * const p_initializer,
const u32_t p_id,
void * const p_data,
const u32_t p_time_ms)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
const eap_status_e status = m_partner->set_timer(
p_initializer,
p_id,
p_data,
p_time_ms);
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT eap_status_e wapi_core_c::cancel_timer(
abs_eap_base_timer_c * const p_initializer,
const u32_t p_id)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
const eap_status_e status = m_partner->cancel_timer(
p_initializer,
p_id);
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
//
EAP_FUNC_EXPORT eap_status_e wapi_core_c::cancel_all_timers()
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
const eap_status_e status = m_partner->cancel_all_timers();
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::set_authentication_role(const bool when_true_set_client)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
cancel_retransmission();
cancel_wapi_failure_timeout();
m_is_client_role = when_true_set_client;
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::cancel_authentication_session()
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::cancel_authentication_session(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::cancel_authentication_session()");
cancel_retransmission();
cancel_wapi_failure_timeout();
cancel_session_timeout();
m_fragment_sequence_number = 0ul;
m_packet_sequence_number = 0u;
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::check_bksa_cache(
const eapol_key_authentication_type_e selected_eapol_key_authentication_type,
const eapol_RSNA_key_header_c::eapol_RSNA_cipher_e pairwise_key_cipher_suite,
const eapol_RSNA_key_header_c::eapol_RSNA_cipher_e group_key_cipher_suite)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::check_bksa_cache(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::check_bksa_cache()");
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::complete_query_asu_id(
const eap_variable_data_c * const asn1_der_subject_name,
const eap_variable_data_c * const asn1_der_issuer_name,
const eap_variable_data_c * const asn1_der_sequence_number,
const eap_status_e id_status)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::complete_query_asu_id(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::complete_query_asu_id()");
if (id_status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, id_status);
}
eap_status_e status = m_asu_id.set_copy_of_buffer(asn1_der_subject_name);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_asu_id.add_data(asn1_der_issuer_name);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_asu_id.add_data(asn1_der_sequence_number);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_ec_certificate_store->get_own_certificate();
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::complete_get_own_certificate(
const eap_variable_data_c * const own_certificate)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::complete_get_own_certificate(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::complete_get_own_certificate()");
eap_status_e status(eap_status_not_supported);
#if defined(USE_WAPI_CORE_SERVER)
if (m_is_client == false
&& m_wapi_state == wapi_core_state_start_certificate_negotiation)
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Saves own certificate.
status = m_own_certificate.set_copy_of_buffer(own_certificate);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Reads the ID of STA_AE
status = m_ec_certificate_store->read_id_of_certificate(&m_own_certificate);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
#endif //#if defined(USE_WAPI_CORE_SERVER)
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::complete_select_certificate(
const eap_variable_data_c * const issuer_ID,
const eap_variable_data_c * const certificate_ID,
const eap_variable_data_c * const certificate)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::complete_select_certificate(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::complete_select_certificate()");
eap_status_e status(eap_status_not_supported);
if (issuer_ID == 0
|| issuer_ID->get_is_valid() == false
|| certificate_ID == 0
|| certificate_ID->get_is_valid() == false
|| certificate == 0
|| certificate->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
}
if (m_is_client == true
&& m_wapi_state == wapi_core_state_process_authentication_activation_message)
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Saves own ID.
status = m_asue_id.set_copy_of_buffer(certificate_ID);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_asue_id"),
m_asue_id.get_data(),
m_asue_id.get_data_length()));
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Saves own certificate.
status = m_own_certificate.set_copy_of_buffer(certificate);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Reads the ID of STA_AE
status = m_ec_certificate_store->read_id_of_certificate(&m_peer_certificate);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::complete_read_id_of_certificate(
const eap_variable_data_c * const ID)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::complete_read_id_of_certificate(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::complete_read_id_of_certificate()");
eap_status_e status(eap_status_not_supported);
#if defined(USE_WAPI_CORE_SERVER)
if (m_is_client == false
&& m_wapi_state == wapi_core_state_start_certificate_negotiation)
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Save AE-ID.
status = m_ae_id.set_copy_of_buffer(ID);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_ae_id"),
m_ae_id.get_data(),
m_ae_id.get_data_length()));
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create Authentication Identifier.
if (m_wapi_negotiation_state == wapi_negotiation_state_initial_negotiation)
{
crypto_random_c rand(m_am_tools);
if (rand.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = rand.get_rand_bytes(
&m_authentication_identifier,
WAPI_AUTHENTICATION_IDENTIFIER_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("new local m_authentication_identifier"),
m_authentication_identifier.get_data(),
m_authentication_identifier.get_data_length()));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create the Authentication Activation Packet.
wai_message_payloads_c * const payloads = new wai_message_payloads_c(m_am_tools, m_is_client);
eap_automatic_variable_c<wai_message_payloads_c> automatic_payloads(m_am_tools, payloads);
if (payloads == 0
|| payloads->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = payloads->initialise_header();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->get_wai_protocol_packet_header_writable()->set_subtype(wai_protocol_subtype_authentication_activation);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds FLAG to data field.
{
wai_variable_data_c data_flag(m_am_tools);
if (data_flag.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
u8_t flag(wai_data_flag_mask_none);
if (m_wapi_negotiation_state == wapi_negotiation_state_rekeying)
{
flag = wai_data_flag_mask_BK_Rekeying;
}
status = data_flag.create(
wai_payload_type_flag,
&flag,
sizeof(flag));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_flag);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds Authentication Identifier to data field.
{
wai_variable_data_c data_authentication_identifier(m_am_tools);
if (data_authentication_identifier.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_authentication_identifier.create(
wai_payload_type_authentication_identifier,
&m_authentication_identifier);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_authentication_identifier);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds ID of local ASU to data field.
{
wai_variable_data_c data_id_of_local_asu(m_am_tools);
if (data_id_of_local_asu.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
if (m_test_other_asu_id.get_is_valid_data() == true)
{
status = data_id_of_local_asu.create(
wai_payload_type_identity,
&m_test_other_asu_id);
}
else
{
status = data_id_of_local_asu.create(
wai_payload_type_identity,
&m_asu_id);
}
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_id_of_local_asu);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds STA_AE Certificate to data field.
{
wai_variable_data_c data_certificate(m_am_tools);
if (data_certificate.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_certificate.create(
wai_payload_type_certificate,
&m_own_certificate);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_certificate);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds ECDH parameter to data field.
{
wai_variable_data_c data_ecdh_parameter(m_am_tools);
if (data_ecdh_parameter.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_ecdh_parameter.create(
wai_payload_type_echd_parameter,
WAPI_ECDH_OID_PARAMETER,
sizeof(WAPI_ECDH_OID_PARAMETER));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&data_ecdh_parameter);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create and send message.
wai_message_c new_wai_message_data(m_am_tools, m_is_client);
if (new_wai_message_data.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->create_wai_tlv_message(&new_wai_message_data, false);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//cancel_retransmission();
status = packet_send(
&new_wai_message_data,
payloads->get_wai_protocol_packet_header_writable()->get_subtype());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
set_wapi_state(wapi_core_state_wait_access_authentication_request_message);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
}
else
#endif //#if defined(USE_WAPI_CORE_SERVER)
if (m_is_client == true
&& m_wapi_state == wapi_core_state_process_authentication_activation_message)
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Saves ID of STA_AE.
status = m_ae_id.set_copy_of_buffer(ID);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_ae_id"),
m_ae_id.get_data(),
m_ae_id.get_data_length()));
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Creates ECDH temporary keys.
status = m_ec_certificate_store->create_ecdh_temporary_keys();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::complete_create_signature_with_private_key(
const eap_variable_data_c * const signature,
const eap_status_e signature_status)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::complete_create_signature_with_private_key(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::complete_create_signature_with_private_key()");
if (signature_status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, signature_status);
}
eap_status_e status(eap_status_not_supported);
#if defined(USE_WAPI_CORE_SERVER)
if (m_is_client == false
&& m_wapi_state == wapi_core_state_process_access_authentication_request_message_AE_signature_trusted_by_ASUE)
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds signature of AE trusted by ASUE to data field.
{
wai_variable_data_c data_signature(m_am_tools);
if (data_signature.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_ae_id"),
m_ae_id.get_data(),
m_ae_id.get_data_length()));
status = create_signature_attributes(
&data_signature,
&m_ae_id,
signature);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.add_tlv(&data_signature);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create and send message.
wai_message_c new_wai_message_data(m_am_tools, m_is_client);
if (new_wai_message_data.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.create_wai_tlv_message(&new_wai_message_data, false);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//cancel_retransmission();
status = packet_send(
&new_wai_message_data,
m_new_payloads.get_wai_protocol_packet_header_writable()->get_subtype());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
m_new_payloads.reset();
set_wapi_state(wapi_core_state_start_unicast_key_negotiation);
status = start_unicast_key_negotiation();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
}
else if (m_is_client == false
&& m_wapi_state == wapi_core_state_process_access_authentication_request_message_ASU_signature_trusted_by_AE)
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds signature of server trusted by AE to data field.
status = create_signature_attributes(
&m_server_signature_trusted_by_ae,
&m_asu_id,
signature);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Creates ECDH temporary keys.
status = m_ec_certificate_store->create_ecdh_temporary_keys();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
else if (m_is_client == false
&& m_wapi_state == wapi_core_state_process_access_authentication_request_message)
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds signature of server trusted by ASUE to data field.
status = create_signature_attributes(
&m_server_signature_trusted_by_asue,
&m_asu_id,
signature);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
{
eap_variable_data_c HASH(m_am_tools);
if (HASH.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
wai_message_payloads_c * const payloads = new wai_message_payloads_c(m_am_tools, m_is_client);
eap_automatic_variable_c<wai_message_payloads_c> automatic_payloads(m_am_tools, payloads);
if (payloads == 0
|| payloads->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = payloads->insert_payload(&m_result_of_certificate_verification);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->insert_payload(&m_server_signature_trusted_by_asue);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = create_HASH(payloads, true, &HASH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_asu_id"),
m_asu_id.get_data(),
m_asu_id.get_data_length()));
set_wapi_state(wapi_core_state_process_access_authentication_request_message_ASU_signature_trusted_by_AE);
status = m_ec_certificate_store->create_signature_with_private_key(
&HASH,
&m_asu_id);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
}
else
#endif //#if defined(USE_WAPI_CORE_SERVER)
if (m_is_client == true
&& m_wapi_state == wapi_core_state_process_authentication_activation_message)
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds Signature of ASUE to data field.
{
wai_variable_data_c data_signature(m_am_tools);
if (data_signature.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_asue_id"),
m_asue_id.get_data(),
m_asue_id.get_data_length()));
status = create_signature_attributes(
&data_signature,
&m_asue_id,
signature);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.add_tlv(&data_signature);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create and send message.
wai_message_c new_wai_message_data(m_am_tools, m_is_client);
if (new_wai_message_data.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.create_wai_tlv_message(&new_wai_message_data, false);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = packet_send(
&new_wai_message_data,
m_new_payloads.get_wai_protocol_packet_header_writable()->get_subtype());
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
m_new_payloads.reset();
set_wapi_state(wapi_core_state_wait_access_authentication_response_message);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
}
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::complete_verify_signature_with_public_key(
const eap_status_e verification_status)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::complete_verify_signature_with_public_key(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::complete_verify_signature_with_public_key()");
eap_status_e status(eap_status_not_supported);
#if defined(USE_WAPI_CORE_SERVER)
if (m_is_client == false
&& m_wapi_state == wapi_core_state_process_access_authentication_request_message)
{
if (verification_status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, verification_status);
}
// Create the AE challenge.
if (m_ae_certificate_challenge.get_is_valid_data() == false)
{
crypto_random_c rand(m_am_tools);
if (rand.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = rand.get_rand_bytes(
&m_ae_certificate_challenge,
WAPI_CHALLENGE_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
if (m_do_certificate_validation == true)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::complete_verify_signature_with_public_key(): does certificate validation\n"),
this,
(m_is_client == true ? "client": "server")));
// First we need to create verification results by server (ASU) of both certificates, ASUE certificate and AE certificate.
// Second thing to create are server (ASU) signatures trusted by ASUE and AE.
// Signature trusted by ASUE signs field Authentication Result for certificate in the Certificate Authentication Response packet.
// Signature trusted by AE signs both fields Authentication Result for certificate and Signature trusted by ASUE in the Certificate Authentication Response packet.
// All operations are simulated here without external server (ASU) and without Certificate Authentication Request and Certificate Authentication Response packets.
// Create the result of certificate verification.
status = create_result_of_certificate_verification(
&m_result_of_certificate_verification,
&m_ae_certificate_challenge,
&m_asue_certificate_challenge,
wapi_certificate_result_valid,
&m_peer_certificate, // ASUE certificate
wapi_certificate_result_valid,
&m_own_certificate); // AE certificate
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create Signature of ASU.
{
eap_variable_data_c HASH(m_am_tools);
if (HASH.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
wai_message_payloads_c * const payloads = new wai_message_payloads_c(m_am_tools, m_is_client);
eap_automatic_variable_c<wai_message_payloads_c> automatic_payloads(m_am_tools, payloads);
if (payloads == 0
|| payloads->get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = payloads->initialise_header();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->get_wai_protocol_packet_header_writable()->set_subtype(wai_protocol_subtype_certificate_authentication_response);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = payloads->add_tlv(&m_result_of_certificate_verification);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = create_HASH(payloads, true, &HASH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_asu_id"),
m_asu_id.get_data(),
m_asu_id.get_data_length()));
status = m_ec_certificate_store->create_signature_with_private_key(
&HASH,
&m_asu_id);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
}
else
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::complete_verify_signature_with_public_key(): no certificate validation\n"),
this,
(m_is_client == true ? "client": "server")));
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Creates ECDH temporary keys.
set_wapi_state(wapi_core_state_process_access_authentication_request_message_ASU_signature_trusted_by_AE);
status = m_ec_certificate_store->create_ecdh_temporary_keys();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
}
}
else
#endif //#if defined(USE_WAPI_CORE_SERVER)
if (m_is_client == true
&& m_wapi_state == wapi_core_state_process_access_authentication_response_message)
{
if (verification_status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, verification_status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Verify Signature of ASU.
if (m_do_certificate_validation == true)
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::complete_verify_signature_with_public_key(): does certificate validation\n"),
this,
(m_is_client == true ? "client": "server")));
if (m_server_signature_trusted_by_ae.get_is_valid_data() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_payload);
}
eap_variable_data_c signature_data(m_am_tools);
if (signature_data.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
eap_variable_data_c received_asu_id(m_am_tools);
if (received_asu_id.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = parse_signature_attributes(
&m_server_signature_trusted_by_ae,
&received_asu_id,
&signature_data);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("received_asu_id"),
received_asu_id.get_data(),
received_asu_id.get_data_length()));
eap_variable_data_c HASH(m_am_tools);
if (HASH.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds Multiple Certificate Verification Result to data field.
{
status = m_new_payloads.reset();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.add_tlv(&m_result_of_certificate_verification);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
status = create_HASH(&m_new_payloads, false, &HASH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
set_wapi_state(wapi_core_state_process_access_authentication_response_message_ASU_signature);
status = m_ec_certificate_store->verify_signature_with_public_key(
&m_asu_id,
&HASH,
&signature_data,
false);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
else
{
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::complete_verify_signature_with_public_key(): no certificate validation\n"),
this,
(m_is_client == true ? "client": "server")));
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create temporary ECDH keys.
set_wapi_state(wapi_core_state_process_access_authentication_response_message_ASU_signature);
status = m_ec_certificate_store->create_ecdh(
&m_own_private_key_d,
&m_peer_public_key_x,
&m_peer_public_key_y);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
}
}
else if (m_is_client == true
&& m_wapi_state == wapi_core_state_process_access_authentication_response_message_ASU_signature)
{
if (verification_status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, verification_status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create temporary ECDH keys.
status = m_ec_certificate_store->create_ecdh(
&m_own_private_key_d,
&m_peer_public_key_x,
&m_peer_public_key_y);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
}
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::complete_create_ecdh_temporary_keys(
const eap_variable_data_c * const private_key_d,
const eap_variable_data_c * const public_key_x,
const eap_variable_data_c * const public_key_y)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::complete_create_ecdh_temporary_keys(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::complete_create_ecdh_temporary_keys()");
eap_status_e status(eap_status_not_supported);
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("private_key_d"),
private_key_d->get_data(),
private_key_d->get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("public_key_x"),
public_key_x->get_data(),
public_key_x->get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("public_key_y"),
public_key_y->get_data(),
public_key_y->get_data_length()));
#if defined(USE_WAPI_CORE_SERVER)
if (m_is_client == false
&& m_wapi_state == wapi_core_state_process_access_authentication_request_message_ASU_signature_trusted_by_AE)
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Save ECDH keys.
// We do not use the new keys. Only the first generated keys.
if (m_own_private_key_d.get_is_valid_data() == false
|| m_own_public_key_x.get_is_valid_data() == false
|| m_own_public_key_y.get_is_valid_data() == false)
{
status = m_own_private_key_d.set_copy_of_buffer(private_key_d);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_own_public_key_x.set_copy_of_buffer(public_key_x);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_own_public_key_y.set_copy_of_buffer(public_key_y);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create temporary ECDH keys.
status = m_ec_certificate_store->create_ecdh(
&m_own_private_key_d,
&m_peer_public_key_x,
&m_peer_public_key_y);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
else
#endif //#if defined(USE_WAPI_CORE_SERVER)
if (m_is_client == true
&& m_wapi_state == wapi_core_state_process_authentication_activation_message)
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Save ECDH keys.
// We do not use the new keys. Only the first generated keys.
if (m_own_private_key_d.get_is_valid_data() == false
|| m_own_public_key_x.get_is_valid_data() == false
|| m_own_public_key_y.get_is_valid_data() == false)
{
status = m_own_private_key_d.set_copy_of_buffer(private_key_d);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_own_public_key_x.set_copy_of_buffer(public_key_x);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_own_public_key_y.set_copy_of_buffer(public_key_y);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create the Access Authentication Request Packet.
m_new_payloads.reset();
if (m_new_payloads.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = m_new_payloads.initialise_header();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.get_wai_protocol_packet_header_writable()->set_subtype(wai_protocol_subtype_access_authentication_request);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds FLAG to data field.
{
wai_variable_data_c data_flag(m_am_tools);
if (data_flag.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
u8_t flag(wai_data_flag_mask_none | wai_data_flag_mask_Certificate_Validation_Request);
if (m_wapi_negotiation_state == wapi_negotiation_state_rekeying)
{
flag = wai_data_flag_mask_BK_Rekeying;
}
status = data_flag.create(
wai_payload_type_flag,
&flag,
sizeof(flag));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.add_tlv(&data_flag);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds Authentication Identifier to data field.
{
wai_variable_data_c data_authentication_identifier(m_am_tools);
if (data_authentication_identifier.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_authentication_identifier.create(
wai_payload_type_authentication_identifier,
&m_authentication_identifier);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.add_tlv(&data_authentication_identifier);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds ASUE Challenge to data field.
{
wai_variable_data_c data_ASUE_challenge(m_am_tools);
if (data_ASUE_challenge.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_ASUE_challenge.create(
wai_payload_type_nonce,
&m_asue_certificate_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.add_tlv(&data_ASUE_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds ASUE key data to data field.
{
wai_variable_data_c ASUE_key_data(m_am_tools);
if (ASUE_key_data.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
u8_t ec_point_type(WAI_EC_POINT_TYPE_NO_COMPRESSION_ID);
status = ASUE_key_data.create(
wai_payload_type_key_data,
&ec_point_type,
sizeof(ec_point_type));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = ASUE_key_data.add_data(
wai_payload_type_key_data,
&m_own_public_key_x);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = ASUE_key_data.add_data(
wai_payload_type_key_data,
&m_own_public_key_y);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.add_tlv(&ASUE_key_data);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds ID of STA_AE to data field.
{
wai_variable_data_c data_id_of_ae(m_am_tools);
if (data_id_of_ae.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_ae_id"),
m_ae_id.get_data(),
m_ae_id.get_data_length()));
status = data_id_of_ae.create(
wai_payload_type_identity,
&m_ae_id);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.add_tlv(&data_id_of_ae);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds STA_ASUE Certificate to data field.
{
wai_variable_data_c data_certificate(m_am_tools);
if (data_certificate.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_certificate.create(
wai_payload_type_certificate,
&m_own_certificate);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.add_tlv(&data_certificate);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds ECDH parameter to data field.
{
wai_variable_data_c data_ecdh_parameter(m_am_tools);
if (data_ecdh_parameter.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_ecdh_parameter.create(
wai_payload_type_echd_parameter,
WAPI_ECDH_OID_PARAMETER,
sizeof(WAPI_ECDH_OID_PARAMETER));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.add_tlv(&data_ecdh_parameter);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds optional ASU list trusted by ASUE. We do not add.
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create Signature of ASUE.
{
eap_variable_data_c HASH(m_am_tools);
if (HASH.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = create_HASH(&m_new_payloads, false, &HASH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_asue_id"),
m_asue_id.get_data(),
m_asue_id.get_data_length()));
status = m_ec_certificate_store->create_signature_with_private_key(
&HASH,
&m_asue_id);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
}
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
bool wapi_core_c::compare_issuer_name(const eap_variable_data_c * const asue_id, const eap_variable_data_c * const ae_id)
{
eap_variable_data_c asue_subject_name(m_am_tools);
eap_variable_data_c asue_issuer_name(m_am_tools);
eap_variable_data_c asue_sequence_number(m_am_tools);
if (asue_subject_name.get_is_valid() == false
|| asue_issuer_name.get_is_valid() == false
|| asue_sequence_number.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
(void) EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
return false;
}
{
wapi_asn1_der_parser_c asue(m_am_tools);
if (asue.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
(void) EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
return false;
}
eap_status_e status = asue.decode(asue_id);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
(void) EAP_STATUS_RETURN(m_am_tools, status);
return false;
}
status = asue.get_wapi_identity(
&asue_subject_name,
&asue_issuer_name,
&asue_sequence_number);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
(void) EAP_STATUS_RETURN(m_am_tools, status);
return false;
}
}
eap_variable_data_c ae_subject_name(m_am_tools);
eap_variable_data_c ae_issuer_name(m_am_tools);
eap_variable_data_c ae_sequence_number(m_am_tools);
if (ae_subject_name.get_is_valid() == false
|| ae_issuer_name.get_is_valid() == false
|| ae_sequence_number.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
(void) EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
return false;
}
{
wapi_asn1_der_parser_c ae(m_am_tools);
if (ae.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
(void) EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
return false;
}
eap_status_e status = ae.decode(ae_id);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
(void) EAP_STATUS_RETURN(m_am_tools, status);
return false;
}
status = ae.get_wapi_identity(
&ae_subject_name,
&ae_issuer_name,
&ae_sequence_number);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
(void) EAP_STATUS_RETURN(m_am_tools, status);
return false;
}
}
return asue_issuer_name.compare(&ae_issuer_name) == 0;
}
//--------------------------------------------------
EAP_FUNC_EXPORT eap_status_e wapi_core_c::complete_create_ecdh(
const eap_variable_data_c * const K_AB_x4,
const eap_variable_data_c * const K_AB_y4)
{
EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
EAP_TRACE_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("WAPI_Core: this = 0x%08x, %s: wapi_core_c::complete_create_ecdh(): state=%s\n"),
this,
(m_is_client == true ? "client": "server"),
wapi_strings_c::get_wapi_core_state_string(m_wapi_state)));
EAP_TRACE_RETURN_STRING(m_am_tools, "returns: wapi_core_c::complete_create_ecdh()");
eap_variable_data_c key(m_am_tools);
if (key.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("K_AB_x4"),
K_AB_x4->get_data(),
K_AB_x4->get_data_length()));
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("K_AB_y4"),
K_AB_y4->get_data(),
K_AB_y4->get_data_length()));
eap_status_e status(eap_status_process_general_error);
// Only the x-coordinate is used in key generation.
status = key.set_copy_of_buffer(K_AB_x4);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// BK || Challenge seed = KD_HMAC_SHA256((yxP) abscissa, NONCE_AE || NONCE_ASUE || string label)
crypto_kd_hmac_sha256_c kd_hmac(m_am_tools);
if (kd_hmac.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
eap_variable_data_c label(m_am_tools);
if (label.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = label.set_copy_of_buffer(&m_ae_certificate_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = label.add_data(&m_asue_certificate_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = label.add_data(WAPI_CERTIFICATE_KEY_LABEL, WAPI_CERTIFICATE_KEY_LABEL_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
eap_variable_data_c bk_challenge_seed(m_am_tools);
if (bk_challenge_seed.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = kd_hmac.expand_key(
&bk_challenge_seed,
WAPI_BK_LENGTH + WAPI_CHALLENGE_SEED_LENGTH,
&key,
&label);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_BK.set_copy_of_buffer(
bk_challenge_seed.get_data(WAPI_BK_LENGTH),
WAPI_BK_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
{
eap_variable_data_c next_challenge(m_am_tools);
if (next_challenge.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
crypto_sha_256_c sha_256(m_am_tools);
if (sha_256.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = sha_256.hash_init();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = sha_256.hash_update(
bk_challenge_seed.get_data_offset(WAPI_BK_LENGTH, WAPI_CHALLENGE_SEED_LENGTH),
WAPI_CHALLENGE_SEED_LENGTH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
u32_t md_length(sha_256.get_digest_length());
status = m_authentication_identifier.set_buffer_length(md_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_authentication_identifier.set_data_length(md_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = sha_256.hash_final(
m_authentication_identifier.get_data(),
&md_length);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("next local m_authentication_identifier"),
m_authentication_identifier.get_data(),
m_authentication_identifier.get_data_length()));
}
#if defined(USE_WAPI_CORE_SERVER)
if (m_is_client == false
&& m_wapi_state == wapi_core_state_process_access_authentication_request_message_ASU_signature_trusted_by_AE)
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create the Access Authentication Request Packet.
m_new_payloads.reset();
if (m_new_payloads.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = m_new_payloads.initialise_header();
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.get_wai_protocol_packet_header_writable()->set_subtype(wai_protocol_subtype_access_authentication_response);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds FLAG to data field.
{
wai_variable_data_c data_flag(m_am_tools);
if (data_flag.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
u8_t flag(wai_data_flag_mask_none | wai_data_flag_mask_Optional_Field | wai_data_flag_mask_Certificate_Validation_Request);
if (m_wapi_negotiation_state == wapi_negotiation_state_rekeying)
{
flag = wai_data_flag_mask_BK_Rekeying;
}
status = data_flag.create(
wai_payload_type_flag,
&flag,
sizeof(flag));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.add_tlv(&data_flag);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds ASUE Challenge to data field.
{
wai_variable_data_c data_ASUE_challenge(m_am_tools);
if (data_ASUE_challenge.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_ASUE_challenge.create(
wai_payload_type_nonce,
&m_asue_certificate_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.add_tlv(&data_ASUE_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds AE Challenge to data field.
{
wai_variable_data_c data_AE_challenge(m_am_tools);
if (data_AE_challenge.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = data_AE_challenge.create(
wai_payload_type_nonce,
&m_ae_certificate_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.add_tlv(&data_AE_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds Access Result to data field.
{
wai_variable_data_c data_AE_challenge(m_am_tools);
if (data_AE_challenge.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
wapi_access_result_e result(wapi_access_result_successfull_access);
status = data_AE_challenge.create(
wai_payload_type_access_result,
&result,
sizeof(result));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.add_tlv(&data_AE_challenge);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds ASUE key data to data field.
{
wai_variable_data_c ASUE_key_data(m_am_tools);
if (ASUE_key_data.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
u8_t ec_point_type(WAI_EC_POINT_TYPE_NO_COMPRESSION_ID);
status = ASUE_key_data.create(
wai_payload_type_key_data,
&ec_point_type,
sizeof(ec_point_type));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = ASUE_key_data.add_data(
wai_payload_type_key_data,
&m_peer_public_key_x);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = ASUE_key_data.add_data(
wai_payload_type_key_data,
&m_peer_public_key_y);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.add_tlv(&ASUE_key_data);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds AE key data to data field.
{
wai_variable_data_c ASUE_key_data(m_am_tools);
if (ASUE_key_data.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
u8_t ec_point_type(WAI_EC_POINT_TYPE_NO_COMPRESSION_ID);
status = ASUE_key_data.create(
wai_payload_type_key_data,
&ec_point_type,
sizeof(ec_point_type));
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = ASUE_key_data.add_data(
wai_payload_type_key_data,
&m_own_public_key_x);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = ASUE_key_data.add_data(
wai_payload_type_key_data,
&m_own_public_key_y);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.add_tlv(&ASUE_key_data);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds ID of STA_AE to data field.
{
wai_variable_data_c data_id_of_ae(m_am_tools);
if (data_id_of_ae.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_ae_id"),
m_ae_id.get_data(),
m_ae_id.get_data_length()));
status = data_id_of_ae.create(
wai_payload_type_identity,
&m_ae_id);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.add_tlv(&data_id_of_ae);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds ID of STA_ASUE to data field.
{
wai_variable_data_c data_id_of_asue(m_am_tools);
if (data_id_of_asue.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_asue_id"),
m_asue_id.get_data(),
m_asue_id.get_data_length()));
status = data_id_of_asue.create(
wai_payload_type_identity,
&m_asue_id);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.add_tlv(&data_id_of_asue);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Adds Multiple Certificate Verification Result to data field.
if (m_do_certificate_validation == true)
{
status = m_new_payloads.add_tlv(&m_result_of_certificate_verification);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
status = m_new_payloads.add_tlv(&m_server_signature_trusted_by_asue);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
if (compare_issuer_name(&m_asu_id, &m_ae_id) == false)
{
status = m_new_payloads.add_tlv(&m_server_signature_trusted_by_ae);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Create Signature of AE.
{
eap_variable_data_c HASH(m_am_tools);
if (HASH.get_is_valid() == false)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
}
status = create_HASH(&m_new_payloads, true, &HASH);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
EAP_TRACE_DATA_DEBUG(
m_am_tools,
TRACE_FLAGS_DEFAULT,
(EAPL("m_asue_id"),
m_asue_id.get_data(),
m_asue_id.get_data_length()));
set_wapi_state(wapi_core_state_process_access_authentication_request_message_AE_signature_trusted_by_ASUE);
status = m_ec_certificate_store->create_signature_with_private_key(
&HASH,
&m_ae_id);
if (status != eap_status_ok)
{
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
}
}
else
#endif //#if defined(USE_WAPI_CORE_SERVER)
if (m_is_client == true
&& m_wapi_state == wapi_core_state_process_access_authentication_response_message_ASU_signature)
{
set_wapi_state(wapi_core_state_wait_unicast_key_negotiation_request_message);
}
EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
return EAP_STATUS_RETURN(m_am_tools, status);
}
//--------------------------------------------------
// End.