wlan_bearer/wlanengine/wlan_common/wlanengine_common_3.1/src/core_sub_operation_wpa_connect.cpp
changeset 0 c40eb8fe8501
child 3 6524e815f76f
equal deleted inserted replaced
-1:000000000000 0:c40eb8fe8501
       
     1 /*
       
     2 * Copyright (c) 2005-2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  State machine for connecting to a WPA network
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "core_sub_operation_wpa_connect.h"
       
    20 #include "core_sub_operation_connect.h"
       
    21 #include "core_server.h"
       
    22 #include "core_tools.h"
       
    23 #include "core_tools_parser.h"
       
    24 #include "core_ap_data.h"
       
    25 #include "core_frame_rsn_ie.h"
       
    26 #include "core_frame_wpa_ie.h"
       
    27 #include "core_frame_wapi_ie.h"
       
    28 #include "am_debug.h"
       
    29 
       
    30 // ======== MEMBER FUNCTIONS ========
       
    31 
       
    32 // ---------------------------------------------------------------------------
       
    33 // ---------------------------------------------------------------------------
       
    34 //
       
    35 core_sub_operation_wpa_connect_c::core_sub_operation_wpa_connect_c(
       
    36     u32_t request_id,
       
    37     core_server_c* server,
       
    38     abs_core_driverif_c* drivers,
       
    39     abs_core_server_callback_c* adaptation,
       
    40     bool_t& is_connected,
       
    41     core_management_status_e& connect_status,
       
    42     const core_ssid_s& ssid,
       
    43     core_ap_data_c& ap_data,
       
    44     bool_t& is_cached_sa_used,
       
    45     core_type_list_c<core_frame_dot11_ie_c>& assoc_ie_list,
       
    46     core_frame_assoc_resp_c** assoc_resp ) :
       
    47     core_operation_base_c( core_operation_unspecified, request_id, server, drivers, adaptation,
       
    48         core_base_flag_drivers_needed ),
       
    49     abs_wlan_eapol_callback_interface_c(),
       
    50     is_connected_m( is_connected ),
       
    51     is_cached_sa_used_m( is_cached_sa_used ),
       
    52     connect_status_m( connect_status ),
       
    53     ssid_m( ssid ),
       
    54     ap_data_m( ap_data ),
       
    55     current_bssid_m( ZERO_MAC_ADDR ),
       
    56     pmkid_length_m( 0 ),
       
    57     sent_ie_m( NULL ),
       
    58     auth_algorithm_m( core_authentication_mode_open ),
       
    59     eapol_auth_type_m( wlan_eapol_if_eapol_key_authentication_type_none ),
       
    60     assoc_ie_list_m( assoc_ie_list ),
       
    61     assoc_resp_m( assoc_resp ),
       
    62     is_key_caching_used_m( false_t )
       
    63     {
       
    64     DEBUG( "core_sub_operation_wpa_connect_c::core_sub_operation_wpa_connect_c()" );
       
    65     }
       
    66 
       
    67 // ---------------------------------------------------------------------------
       
    68 // ---------------------------------------------------------------------------
       
    69 //
       
    70 core_sub_operation_wpa_connect_c::~core_sub_operation_wpa_connect_c()
       
    71     {
       
    72     DEBUG( "core_sub_operation_wpa_connect_c::~core_sub_operation_wpa_connect_c()" );
       
    73 
       
    74     /**
       
    75      * Ownership of sent_ie_m has been transferred to assoc_ie_list_m,
       
    76      * no need delete it.
       
    77      */
       
    78     sent_ie_m = NULL;
       
    79 
       
    80     server_m->set_eapol_handler( NULL );
       
    81     server_m->unregister_event_handler( this );
       
    82     assoc_resp_m = NULL;
       
    83     }
       
    84 
       
    85 // ---------------------------------------------------------------------------
       
    86 // ---------------------------------------------------------------------------
       
    87 //
       
    88 core_error_e core_sub_operation_wpa_connect_c::next_state()
       
    89     {
       
    90     DEBUG( "core_sub_operation_wpa_connect_c::next_state()" );
       
    91 
       
    92     switch ( operation_state_m )
       
    93         {
       
    94         case core_state_init:
       
    95             {
       
    96             DEBUG( "core_sub_operation_wpa_connect_c::next_state() - marking is_eapol_authentication_started as true" );
       
    97             server_m->get_connection_data()->set_eapol_authentication_started(
       
    98                 true_t );
       
    99             server_m->get_connection_data()->set_eapol_auth_bssid(
       
   100                 ZERO_MAC_ADDR );
       
   101 
       
   102             eapol_auth_type_m = core_tools_c::eap_authentication_type(
       
   103                 server_m->get_connection_data()->iap_data(),
       
   104                 ap_data_m );
       
   105             current_bssid_m = ap_data_m.bssid();
       
   106 
       
   107             server_m->set_eapol_handler( this );
       
   108 
       
   109             server_m->get_eapol_instance().clear_stored_frame();
       
   110 
       
   111             /**
       
   112              * If roaming to a WPA2-EAP AP without a cached PMKSA, attempt
       
   113              * to use proactive key caching if not previously done so.
       
   114              */
       
   115             if( !is_key_caching_used_m &&
       
   116                 !is_cached_sa_used_m &&              
       
   117                 server_m->get_connection_data()->current_ap_data() &&
       
   118                 eapol_auth_type_m == wlan_eapol_if_eapol_key_authentication_type_rsna_eap )
       
   119                 {
       
   120                 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - attempting to use proactive key caching" );
       
   121 
       
   122                 is_cached_sa_used_m = true_t;
       
   123                 is_key_caching_used_m = true_t;
       
   124                 }
       
   125             else if( is_key_caching_used_m )
       
   126                 {
       
   127                 is_cached_sa_used_m = false_t;
       
   128                 is_key_caching_used_m = false_t;                
       
   129                 }
       
   130 
       
   131             // update_wlan_database_reference_values must be sent before start_authentication and start_reassociation.
       
   132             u32_t reference[2] = {
       
   133                 3, // ELan
       
   134                 server_m->get_connection_data()->iap_data().id() };
       
   135             core_error_e ret = server_m->get_eapol_instance().update_wlan_database_reference_values(
       
   136                 reinterpret_cast<u8_t*>( reference ), 2*sizeof( u32_t ) );
       
   137 
       
   138             if( is_cached_sa_used_m )
       
   139                 {
       
   140                 if( eapol_auth_type_m == wlan_eapol_if_eapol_key_authentication_type_wpx_fast_roam )
       
   141                     {
       
   142                     DEBUG( "core_sub_operation_wpa_connect_c::next_state() - starting a WPX fast-roam reassociation" );
       
   143 
       
   144                     core_error_e ret = server_m->get_wpx_adaptation_instance().handle_fast_roam_start_reassociation(
       
   145                         ap_data_m,
       
   146                         assoc_ie_list_m );
       
   147                     DEBUG1( "core_sub_operation_wpa_connect_c::next_state() - handle_fast_roam_start_reassociation returned with %u",
       
   148                         ret );
       
   149                     /*
       
   150                      *  State machine will move forward from here by:
       
   151                      * - complete_start_wpx_fast_roam_reassociation() 
       
   152                      *     -> core_state_do_connect
       
   153                      * - Error message (start_wpx_fast_roam_reassociation) 
       
   154                      *     -> core_state_init (with is_cached_sa_used_m = false_t)
       
   155                      */
       
   156                     }
       
   157                 else
       
   158                     {
       
   159                     DEBUG( "core_sub_operation_wpa_connect_c::next_state() - starting a reassociation" );
       
   160                     
       
   161                     operation_state_m = core_state_do_connect;
       
   162                     
       
   163                     core_mac_address_s previous_bssid( ZERO_MAC_ADDR );
       
   164                     if( server_m->get_connection_data()->current_ap_data() )
       
   165                         {
       
   166                         previous_bssid = server_m->get_connection_data()->current_ap_data()->bssid();
       
   167                         }
       
   168 
       
   169                     network_id_c previous_ap(
       
   170                         &previous_bssid.addr[0],
       
   171                         MAC_ADDR_LEN,
       
   172                         &server_m->own_mac_addr().addr[0],
       
   173                         MAC_ADDR_LEN,
       
   174                         server_m->get_eapol_instance().ethernet_type() );
       
   175     
       
   176                     network_id_c new_ap(
       
   177                         &current_bssid_m.addr[0],
       
   178                         MAC_ADDR_LEN,
       
   179                         &server_m->own_mac_addr().addr[0],
       
   180                         MAC_ADDR_LEN,
       
   181                         server_m->get_eapol_instance().ethernet_type() );
       
   182                     
       
   183                     ret = server_m->get_eapol_instance().start_reassociation(
       
   184                         &previous_ap, &new_ap, eapol_auth_type_m );
       
   185                     DEBUG1( "core_sub_operation_wpa_connect_c::next_state() - start_reassociation returned with %u",
       
   186                         ret );
       
   187                     /*
       
   188                      *  State machine will move forward from here by:
       
   189                      * - reassociate(), when reassociation is possible 
       
   190                      *     -> core_state_do_connect
       
   191                      * - Error message (start_reassociation), when start_reassociation is not possible 
       
   192                      *     -> core_state_start_authentication_needed
       
   193                      */
       
   194                     }
       
   195                 }
       
   196             else
       
   197                 {
       
   198                 // Full authentication is needed.
       
   199                 operation_state_m = core_state_start_authentication_needed;
       
   200                 return next_state();
       
   201                 }
       
   202             break;
       
   203             }
       
   204         case core_state_start_authentication_needed:
       
   205             {
       
   206             DEBUG( "core_sub_operation_wpa_connect_c::next_state() - starting a full authentication" );
       
   207 
       
   208             operation_state_m = core_state_do_connect;
       
   209 
       
   210             network_id_c network_id(
       
   211                 &current_bssid_m.addr[0],
       
   212                 MAC_ADDR_LEN,
       
   213                 &server_m->own_mac_addr().addr[0],
       
   214                 MAC_ADDR_LEN,
       
   215                 server_m->get_eapol_instance().ethernet_type() );
       
   216 
       
   217             core_error_e ret = server_m->get_eapol_instance().start_authentication(
       
   218                 const_cast<u8_t*>( &ssid_m.ssid[0] ), ssid_m.length,
       
   219                 eapol_auth_type_m,
       
   220                 const_cast<u8_t*>( &server_m->get_connection_data()->iap_data().psk_key().key_data[0] ),
       
   221                 server_m->get_connection_data()->iap_data().psk_key().key_length,
       
   222                 server_m->get_connection_data()->iap_data().is_psk_overridden(),
       
   223                 &network_id );
       
   224             DEBUG1( "core_sub_operation_wpa_connect_c::next_state() - start_authentication returned with %u",
       
   225                 ret );
       
   226             
       
   227             break;
       
   228             }
       
   229         case core_state_do_connect:
       
   230             {
       
   231             core_key_management_e key_management( core_key_management_eap );
       
   232             core_encryption_mode_e encryption_mode( core_encryption_mode_wpa );
       
   233             bool_t is_pairwise_key_invalidated( true_t );
       
   234             
       
   235             switch ( eapol_auth_type_m )
       
   236                 {
       
   237                 case wlan_eapol_if_eapol_key_authentication_type_rsna_eap:
       
   238                     /** Falls through on purpose. */
       
   239                 case wlan_eapol_if_eapol_key_authentication_type_wpa_eap:
       
   240                     {
       
   241                     DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using key management core_key_management_eap" );
       
   242                     DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using encryption mode core_encryption_mode_wpa" );
       
   243                     key_management = core_key_management_eap;
       
   244                     encryption_mode = core_encryption_mode_wpa;                    
       
   245                     break;
       
   246                     }
       
   247                 case wlan_eapol_if_eapol_key_authentication_type_wfa_sc:
       
   248                     {
       
   249                     DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using key management core_key_management_eap" );
       
   250                     key_management = core_key_management_eap;
       
   251 
       
   252                     if ( ap_data_m.is_privacy_enabled() )
       
   253                         {
       
   254                         DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using encryption mode core_encryption_mode_wpa" );
       
   255                         encryption_mode = core_encryption_mode_wpa;
       
   256                         }
       
   257                     else
       
   258                         {
       
   259                         DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using encryption mode core_encryption_mode_disabled" );
       
   260                         encryption_mode = core_encryption_mode_disabled;
       
   261                         }
       
   262                     break;
       
   263                     }
       
   264                 case wlan_eapol_if_eapol_key_authentication_type_rsna_psk:
       
   265                     /** Falls through on purpose. */
       
   266                 case wlan_eapol_if_eapol_key_authentication_type_wpa_psk:
       
   267                     {
       
   268                     DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using key management core_key_management_preshared" );
       
   269                     DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using encryption mode core_encryption_mode_wpa" );
       
   270                     key_management = core_key_management_preshared;
       
   271                     encryption_mode = core_encryption_mode_wpa;
       
   272                     break;
       
   273                     }
       
   274                 case wlan_eapol_if_eapol_key_authentication_type_802_1x:
       
   275                     {
       
   276                     DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using key management core_key_management_eap" );
       
   277                     DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using encryption mode core_encryption_mode_802dot1x" );
       
   278                     key_management = core_key_management_eap;
       
   279                     encryption_mode = core_encryption_mode_802dot1x;
       
   280                     break;
       
   281                     }
       
   282                 case wlan_eapol_if_eapol_key_authentication_type_wpx_fast_roam:
       
   283                     {
       
   284                     DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using key management wlan_eapol_if_eapol_key_authentication_type_wpx_fast_roam" );
       
   285                     DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using encryption mode core_encryption_mode_802dot1x" );
       
   286                     key_management = core_key_management_wpx_fast_roam;
       
   287                     encryption_mode = core_encryption_mode_802dot1x;
       
   288                     if( is_cached_sa_used_m )
       
   289                         {
       
   290                         is_pairwise_key_invalidated = false_t;
       
   291                         }
       
   292                     break;
       
   293                     }
       
   294                 case wlan_eapol_if_eapol_key_authentication_type_wapi:
       
   295                     {
       
   296                     DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using key management core_key_management_wapi_certificate" );
       
   297                     DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using encryption mode core_security_mode_wapi" );
       
   298                     key_management = core_key_management_wapi_certificate;
       
   299                     encryption_mode = core_encryption_mode_wpi;
       
   300                     break;                    
       
   301                     }
       
   302                 case wlan_eapol_if_eapol_key_authentication_type_wapi_psk:
       
   303                     {
       
   304                     DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using key management core_key_management_wapi_psk" );
       
   305                     DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using encryption mode core_security_mode_wapi" );
       
   306                     key_management = core_key_management_wapi_psk;
       
   307                     encryption_mode = core_encryption_mode_wpi;
       
   308                     break;                    
       
   309                     }
       
   310                 default:
       
   311                     {
       
   312                     DEBUG( "core_sub_operation_wpa_connect_c::next_state() - unknown authentication type" );
       
   313                     ASSERT( false_t );
       
   314                     }
       
   315                 }
       
   316             
       
   317             operation_state_m = core_state_req_connect;
       
   318 
       
   319             if( ap_data_m.is_rsn_ie_present() )
       
   320                 {
       
   321                 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - generating RSN IE" );
       
   322 
       
   323                 sent_ie_m = core_frame_rsn_ie_c::instance(
       
   324                     server_m->get_wpx_adaptation_instance(),
       
   325                     ap_data_m.best_group_cipher(),
       
   326                     ap_data_m.best_pairwise_cipher(),
       
   327                     key_management,
       
   328                     pmkid_length_m,
       
   329                     &pmkid_data_m[0] );
       
   330                 }
       
   331             else if( ap_data_m.is_wpa_ie_present() )
       
   332                 {
       
   333                 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - generating WPA IE" );
       
   334 
       
   335                 sent_ie_m = core_frame_wpa_ie_c::instance(
       
   336                     server_m->get_wpx_adaptation_instance(),
       
   337                     ap_data_m.best_group_cipher(),
       
   338                     ap_data_m.best_pairwise_cipher(),
       
   339                     key_management );
       
   340                 }
       
   341             else if( ap_data_m.is_wapi_ie_present() )
       
   342                 {
       
   343                 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - generating WAPI IE" );
       
   344 
       
   345                 sent_ie_m = core_frame_wapi_ie_c::instance(
       
   346                     ap_data_m.best_group_cipher(),
       
   347                     ap_data_m.best_pairwise_cipher(),
       
   348                     key_management,
       
   349                     0,
       
   350                     pmkid_length_m,
       
   351                     &pmkid_data_m[0] );
       
   352                 }
       
   353             
       
   354             if( sent_ie_m &&
       
   355                 eapol_auth_type_m != wlan_eapol_if_eapol_key_authentication_type_wfa_sc )
       
   356                 {
       
   357                 assoc_ie_list_m.append(
       
   358                     sent_ie_m,
       
   359                     sent_ie_m->element_id() );
       
   360                 }
       
   361 
       
   362             DEBUG( "core_sub_operation_wpa_connect_c::next_state() - marking is_eapol_connecting as true" );
       
   363             server_m->get_connection_data()->set_eapol_connecting(
       
   364                 true_t );
       
   365 
       
   366             core_operation_base_c* operation = new core_sub_operation_connect_c(
       
   367                 request_id_m,
       
   368                 server_m,
       
   369                 drivers_m,
       
   370                 adaptation_m,
       
   371                 is_connected_m,
       
   372                 connect_status_m,
       
   373                 ssid_m,
       
   374                 ap_data_m,
       
   375                 auth_algorithm_m,
       
   376                 server_m->get_wpx_adaptation_instance().encryption_mode(
       
   377                     ap_data_m, encryption_mode ),
       
   378                 core_tools_c::cipher_key_type(
       
   379                     ap_data_m.best_pairwise_cipher() ),
       
   380                 assoc_ie_list_m,
       
   381                 assoc_resp_m,
       
   382                 is_pairwise_key_invalidated,
       
   383                 true_t );
       
   384 
       
   385             return run_sub_operation( operation );
       
   386             }
       
   387         case core_state_req_connect:
       
   388             {
       
   389             DEBUG( "core_sub_operation_wpa_connect_c::next_state() - connection success" );
       
   390 
       
   391             operation_state_m = core_state_req_state_notification;
       
   392 
       
   393             network_id_c network(
       
   394                 &current_bssid_m.addr[0],
       
   395                 MAC_ADDR_LEN,
       
   396                 &server_m->own_mac_addr().addr[0],
       
   397                 MAC_ADDR_LEN,
       
   398                 server_m->get_eapol_instance().ethernet_type() );
       
   399 
       
   400             const core_frame_dot11_ie_c* ie = NULL;
       
   401             if( ap_data_m.is_rsn_ie_present() )
       
   402                 {
       
   403                 ie = ap_data_m.rsn_ie();
       
   404                 }
       
   405             else if( ap_data_m.is_wpa_ie_present() )
       
   406                 {
       
   407                 ie = ap_data_m.wpa_ie();
       
   408                 }
       
   409             else if( ap_data_m.is_wapi_ie_present() )
       
   410                 {
       
   411                 ie = ap_data_m.wapi_ie();
       
   412                 }
       
   413 
       
   414             core_frame_dot11_ie_c * recv_ie = NULL;
       
   415             core_frame_dot11_ie_c * sent_ie = NULL;
       
   416 
       
   417             if ( sent_ie_m )
       
   418                 {
       
   419                 sent_ie = sent_ie_m;
       
   420                 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - sent IE: " );
       
   421                 DEBUG_BUFFER( sent_ie_m->data_length(), sent_ie_m->data() );
       
   422                 }
       
   423     
       
   424             if ( ie )
       
   425                 {
       
   426                 recv_ie = core_frame_dot11_ie_c::instance( ie->data_length(), ie->data() );
       
   427 
       
   428                 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - received IE: " );
       
   429                 DEBUG_BUFFER( ie->data_length(), ie->data() );
       
   430                 }
       
   431 
       
   432             DEBUG( "core_sub_operation_wpa_connect_c::next_state() - marking is_eapol_connecting as false" );
       
   433             server_m->get_connection_data()->set_eapol_connecting(
       
   434                 false_t );
       
   435             server_m->get_connection_data()->set_eapol_auth_bssid(
       
   436                 current_bssid_m );
       
   437 
       
   438             /**
       
   439              * WPX fast-roam reassociation is handled differently, EAPOL indication will
       
   440              * move the state machine forward.
       
   441              */
       
   442             if ( is_cached_sa_used_m &&
       
   443                  eapol_auth_type_m == wlan_eapol_if_eapol_key_authentication_type_wpx_fast_roam )
       
   444                 {
       
   445                 server_m->get_wpx_adaptation_instance().handle_fast_roam_reassoc_resp(
       
   446                     assoc_resp_m ? *assoc_resp_m : NULL );
       
   447 
       
   448                 delete recv_ie;
       
   449                 recv_ie = NULL;
       
   450                 delete ie;
       
   451                 ie = NULL;
       
   452                 return core_error_request_pending;
       
   453                 }
       
   454 
       
   455             u8_t * temp_recv_ie( NULL );
       
   456             u32_t temp_recv_ie_length( 0 );
       
   457             u8_t * temp_sent_ie( NULL );
       
   458             u32_t temp_sent_ie_length( 0 );
       
   459             
       
   460             if ( recv_ie )
       
   461                 {
       
   462                 temp_recv_ie = const_cast<u8_t*>( recv_ie->data() );
       
   463                 temp_recv_ie_length = recv_ie->data_length();
       
   464                 }
       
   465             if ( sent_ie_m )
       
   466                 {
       
   467                 temp_sent_ie = const_cast<u8_t*>( sent_ie->data() );
       
   468                 temp_sent_ie_length = sent_ie->data_length();
       
   469                 }
       
   470                 
       
   471             if ( is_cached_sa_used_m )                 
       
   472                 {
       
   473                 server_m->get_eapol_instance().complete_reassociation(
       
   474                     wlan_eapol_if_eapol_wlan_authentication_state_association_ok,
       
   475                     &network,
       
   476                     temp_recv_ie, temp_recv_ie_length,
       
   477                     temp_sent_ie, temp_sent_ie_length,
       
   478                     core_tools_c::eapol_cipher( ap_data_m.best_pairwise_cipher() ),
       
   479                     core_tools_c::eapol_cipher( ap_data_m.best_group_cipher() ) );
       
   480                 }
       
   481             else
       
   482                 {
       
   483                 server_m->get_eapol_instance().complete_association(                
       
   484                     wlan_eapol_if_eapol_wlan_authentication_state_association_ok,
       
   485                     &network,
       
   486                     temp_recv_ie, temp_recv_ie_length,
       
   487                     temp_sent_ie, temp_sent_ie_length,
       
   488                     core_tools_c::eapol_cipher( ap_data_m.best_pairwise_cipher() ),
       
   489                     core_tools_c::eapol_cipher( ap_data_m.best_group_cipher() ) );
       
   490                 }
       
   491 
       
   492             delete recv_ie;
       
   493             recv_ie = NULL;
       
   494             delete ie;
       
   495             ie = NULL;
       
   496             
       
   497             // Send EAPOL frame after timer. This will allow new EAPOL frames to come from queue.
       
   498             return asynch_goto( core_state_process_eapol_frame, CORE_TIMER_IMMEDIATELY );
       
   499             }
       
   500         case core_state_process_eapol_frame:
       
   501             {
       
   502             operation_state_m = core_state_req_state_notification;
       
   503             
       
   504             server_m->get_eapol_instance().process_stored_frame();
       
   505             server_m->register_event_handler( this );
       
   506 
       
   507             break;
       
   508             }
       
   509         case core_state_req_state_notification:
       
   510             {
       
   511             server_m->unregister_event_handler( this );
       
   512 
       
   513             DEBUG( "core_sub_operation_wpa_connect_c::next_state() - authentication success" );
       
   514 
       
   515             return core_error_ok;
       
   516             }
       
   517         case core_state_req_connect_failed:
       
   518             {
       
   519             DEBUG( "core_sub_operation_wpa_connect_c::next_state() - connection failed" );
       
   520 
       
   521             DEBUG( "core_sub_operation_wpa_connect_c::next_state() - marking is_eapol_authentication_started as false" );
       
   522             server_m->get_connection_data()->set_eapol_authentication_started(
       
   523                 false_t );
       
   524             DEBUG( "core_sub_operation_wpa_connect_c::next_state() - marking is_eapol_connecting as false" );
       
   525             server_m->get_connection_data()->set_eapol_connecting(
       
   526                 false_t );
       
   527 
       
   528             /** The connection attempt failed, we are no longer connected. */
       
   529             is_connected_m = false_t;
       
   530 
       
   531             /**
       
   532              * WPX fast-roam reassociation is handled differently, EAPOL indication will
       
   533              * move the state machine forward.
       
   534              * 
       
   535              * This completion should be before clearing eapol_handler. 
       
   536              * Otherwise we don't get error message.
       
   537              */
       
   538             if ( is_cached_sa_used_m &&
       
   539                  eapol_auth_type_m == wlan_eapol_if_eapol_key_authentication_type_wpx_fast_roam )
       
   540                 {
       
   541                 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - calling EAPOL complete_fast_roam_reassociation (this_ap_failed)" );
       
   542                 server_m->get_wpx_adaptation_instance().handle_fast_roam_reassoc_resp( NULL );
       
   543 
       
   544                 return core_error_request_pending;
       
   545                 }
       
   546 
       
   547             /**
       
   548              * We already know the connection has failed so don't process the failure
       
   549              * indication from EAPOL.
       
   550              */
       
   551             server_m->set_eapol_handler( NULL );
       
   552 
       
   553             wlan_eapol_if_eapol_wlan_authentication_state_e eapol_reason(
       
   554                 wlan_eapol_if_eapol_wlan_authentication_state_this_ap_failed );
       
   555 
       
   556             if ( connect_status_m == core_management_status_auth_algo_not_supported )
       
   557                 {
       
   558                 eapol_reason = wlan_eapol_if_eapol_wlan_authentication_state_802_11_auth_algorithm_not_supported;
       
   559                 }
       
   560             else if ( failure_reason_m == core_error_timeout )
       
   561                 {
       
   562                 eapol_reason = wlan_eapol_if_eapol_wlan_authentication_state_no_response;
       
   563                 }
       
   564 
       
   565             network_id_c network(
       
   566                 &current_bssid_m.addr[0],
       
   567                 MAC_ADDR_LEN,
       
   568                 &server_m->own_mac_addr().addr[0],
       
   569                 MAC_ADDR_LEN,
       
   570                 server_m->get_eapol_instance().ethernet_type() );
       
   571 
       
   572             if ( is_cached_sa_used_m )
       
   573                 {
       
   574                 DEBUG1( "core_sub_operation_wpa_connect_c::next_state() - calling EAPOL complete_reassociation with code %u",
       
   575                     eapol_reason );
       
   576 
       
   577                 server_m->get_eapol_instance().complete_reassociation(
       
   578                     eapol_reason,
       
   579                     &network,
       
   580                     NULL, 0,
       
   581                     NULL, 0,
       
   582                     wlan_eapol_if_rsna_cipher_none,
       
   583                     wlan_eapol_if_rsna_cipher_none );
       
   584                 }
       
   585             else
       
   586                 {
       
   587                 DEBUG1( "core_sub_operation_wpa_connect_c::next_state() - calling EAPOL complete_association with code %u",
       
   588                     eapol_reason );
       
   589 
       
   590                 server_m->get_eapol_instance().complete_association(
       
   591                     eapol_reason,
       
   592                     &network,
       
   593                     NULL, 0,
       
   594                     NULL, 0,
       
   595                     wlan_eapol_if_rsna_cipher_none,
       
   596                     wlan_eapol_if_rsna_cipher_none );
       
   597                 }
       
   598 
       
   599             return cancel();
       
   600             }
       
   601         case core_state_req_association_failed:
       
   602             {
       
   603             DEBUG( "core_sub_operation_wpa_connect_c::next_state() - association, reassociation or WPX fast-roam reassociation failed" );
       
   604             
       
   605             server_m->set_eapol_handler( NULL );
       
   606 
       
   607             return cancel();
       
   608             }
       
   609         case core_state_bss_lost:
       
   610             {
       
   611             DEBUG( "core_sub_operation_wpa_connect_c::next_state() - authentication failed due to BSS lost" );
       
   612 
       
   613             /** The connection attempt failed, we are no longer connected. */
       
   614             is_connected_m = false_t;
       
   615             
       
   616             return core_error_timeout;
       
   617             }
       
   618         case core_state_user_cancel:
       
   619             {
       
   620             DEBUG( "core_sub_operation_wpa_connect_c::next_state() - pending request has been completed, proceeding with user cancel" );
       
   621 
       
   622             network_id_c network(
       
   623                 &current_bssid_m.addr[0],
       
   624                 MAC_ADDR_LEN,
       
   625                 &server_m->own_mac_addr().addr[0],
       
   626                 MAC_ADDR_LEN,
       
   627                 server_m->get_eapol_instance().ethernet_type() );
       
   628 
       
   629             DEBUG6( "core_sub_operation_wpa_connect_c::next_state() - EAPOL disassociation from BSSID %02X:%02X:%02X:%02X:%02X:%02X",
       
   630                 current_bssid_m.addr[0], current_bssid_m.addr[1], current_bssid_m.addr[2],
       
   631                 current_bssid_m.addr[3], current_bssid_m.addr[4], current_bssid_m.addr[5] );
       
   632 
       
   633             server_m->get_eapol_instance().disassociation( &network );
       
   634 
       
   635             /** The connection attempt failed, we are no longer connected. */
       
   636             is_connected_m = false_t;            
       
   637 
       
   638             return core_error_cancel;
       
   639             }
       
   640         default:
       
   641             {
       
   642             ASSERT( false_t );
       
   643             }
       
   644         }
       
   645 
       
   646     return core_error_request_pending;
       
   647     }
       
   648 
       
   649 // ---------------------------------------------------------------------------
       
   650 // ---------------------------------------------------------------------------
       
   651 //
       
   652 core_error_e core_sub_operation_wpa_connect_c::cancel()
       
   653     {
       
   654     DEBUG( "core_sub_operation_wpa_connect_c::cancel()" );
       
   655 
       
   656     switch( operation_state_m )
       
   657         {
       
   658         case core_state_req_connect:
       
   659             {
       
   660             return goto_state( core_state_req_connect_failed );
       
   661             }
       
   662         case core_state_req_state_notification:
       
   663             {
       
   664             if( server_m->get_connection_data()->is_eapol_require_immediate_reconnect() ||
       
   665                 ( is_key_caching_used_m &&
       
   666                   failure_reason_m == core_error_eapol_auth_start_timeout ) )
       
   667                 {
       
   668                 DEBUG( "core_sub_operation_wpa_connect_c::cancel() - re-attempting authentication" );
       
   669                 server_m->get_connection_data()->set_eapol_require_immediate_reconnect( false_t );
       
   670                 assoc_ie_list_m.clear();
       
   671 
       
   672                 return asynch_goto( core_state_init, 100000 ); // 100 ms delay before new connect
       
   673                 }
       
   674 
       
   675             /** The connection attempt failed, we are no longer connected. */
       
   676             is_connected_m = false_t;            
       
   677 
       
   678             return failure_reason_m;
       
   679             }
       
   680         default:
       
   681             {
       
   682             return failure_reason_m;
       
   683             }
       
   684         }
       
   685     }
       
   686 
       
   687 // ---------------------------------------------------------------------------
       
   688 // ---------------------------------------------------------------------------
       
   689 //
       
   690 void core_sub_operation_wpa_connect_c::user_cancel(
       
   691     bool_t /* do_graceful_cancel */ )
       
   692     {
       
   693     DEBUG( "core_sub_operation_wpa_connect_c::user_cancel()" );
       
   694 
       
   695     /**
       
   696      * Do not handle any EAPOL indications that might occur during our
       
   697      * transition to core_state_user_cancel state.
       
   698      */
       
   699     DEBUG( "core_sub_operation_wpa_connect_c::next_state() - marking is_eapol_authenticating as false" );
       
   700     server_m->get_connection_data()->set_eapol_authenticating(
       
   701         false_t );
       
   702     DEBUG( "core_sub_operation_wpa_connect_c::next_state() - marking is_eapol_authentication_started as false" );
       
   703     server_m->get_connection_data()->set_eapol_authentication_started(
       
   704         false_t );
       
   705     
       
   706     /**
       
   707      * If we are waiting for an EAPOL indication, we'll have to schedule
       
   708      * our own timer to proceed.
       
   709      */
       
   710     if( operation_state_m == core_state_req_state_notification )
       
   711         {
       
   712         asynch_goto( core_state_user_cancel, CORE_TIMER_IMMEDIATELY );
       
   713 
       
   714         return;
       
   715         }
       
   716 
       
   717     /**
       
   718      * Otherwise we'll just wait for the pending request complete
       
   719      * before continuing.
       
   720      */    
       
   721     operation_state_m = core_state_user_cancel;
       
   722     }
       
   723 
       
   724 // ---------------------------------------------------------------------------
       
   725 // ---------------------------------------------------------------------------
       
   726 //
       
   727 core_error_e core_sub_operation_wpa_connect_c::packet_send(
       
   728     network_id_c * send_network_id,
       
   729     u8_t * packet_data,
       
   730     u32_t packet_data_length,
       
   731     bool_t send_unencrypted )
       
   732     {
       
   733     DEBUG( "core_sub_operation_wpa_connect_c::packet_send()" );    
       
   734 
       
   735     server_m->send_data_frame(
       
   736         ap_data_m,
       
   737         core_frame_type_ethernet,
       
   738         static_cast<u16_t>( packet_data_length ),
       
   739         packet_data,
       
   740         core_access_class_voice,
       
   741         send_network_id->destination(),
       
   742         send_unencrypted );
       
   743 
       
   744     return core_error_ok;
       
   745     }
       
   746 
       
   747 // ---------------------------------------------------------------------------
       
   748 // ---------------------------------------------------------------------------
       
   749 //
       
   750 core_error_e core_sub_operation_wpa_connect_c::associate(
       
   751     wlan_eapol_if_eapol_key_authentication_mode_e authentication_mode )
       
   752     {
       
   753     DEBUG( "core_sub_operation_wpa_connect_c::associate()" );
       
   754 
       
   755     auth_algorithm_m = server_m->get_wpx_adaptation_instance().authentication_algorithm(
       
   756         eapol_auth_type_m,
       
   757         authentication_mode );
       
   758 
       
   759     next_state();
       
   760 
       
   761     return core_error_ok;
       
   762     }
       
   763 
       
   764 // ---------------------------------------------------------------------------
       
   765 // ---------------------------------------------------------------------------
       
   766 //
       
   767 core_error_e core_sub_operation_wpa_connect_c::disassociate(
       
   768     network_id_c * /*receive_network_id*/,
       
   769     const bool_t /* self_disassociation */ )
       
   770     {
       
   771     DEBUG( "core_sub_operation_wpa_connect_c::disassociate()" );
       
   772     
       
   773     return core_error_ok;
       
   774     }
       
   775 
       
   776 // ---------------------------------------------------------------------------
       
   777 // ---------------------------------------------------------------------------
       
   778 //
       
   779 core_error_e core_sub_operation_wpa_connect_c::packet_data_session_key(
       
   780     network_id_c * send_network_id,
       
   781     session_key_c * key )
       
   782     {
       
   783     DEBUG( "core_sub_operation_wpa_connect_c::packet_data_session_key()" );
       
   784     ASSERT ( key != NULL );
       
   785     ASSERT ( send_network_id != NULL );
       
   786 
       
   787     core_mac_address_s mac( BROADCAST_MAC_ADDR );
       
   788 
       
   789     if ( key->eapol_key_type == wlan_eapol_if_eapol_key_type_unicast )
       
   790         {
       
   791         mac = send_network_id->destination();
       
   792         }
       
   793 
       
   794     core_cipher_key_type_e type =
       
   795         core_tools_c::cipher_key_type(
       
   796             key->eapol_key_type,
       
   797             ap_data_m.best_pairwise_cipher(),
       
   798             ap_data_m.best_group_cipher() );
       
   799 
       
   800     ASSERT( drivers_m );
       
   801     drivers_m->add_cipher_key(
       
   802         type,
       
   803         static_cast<u8_t>( key->key_index ),
       
   804         static_cast<u16_t>( key->key_length ),
       
   805         key->key,
       
   806         mac,
       
   807         true_t );
       
   808 
       
   809     return core_error_ok;
       
   810     }
       
   811 
       
   812 // ---------------------------------------------------------------------------
       
   813 // ---------------------------------------------------------------------------
       
   814 //	    
       
   815 void core_sub_operation_wpa_connect_c::state_notification(
       
   816     state_notification_c * /*state*/ )
       
   817     {
       
   818     DEBUG( "core_sub_operation_wpa_connect_c::state_notification()" );
       
   819     }
       
   820 
       
   821 // ---------------------------------------------------------------------------
       
   822 // ---------------------------------------------------------------------------
       
   823 //	    
       
   824 core_error_e core_sub_operation_wpa_connect_c::reassociate(
       
   825     network_id_c * /* send_network_id */,
       
   826     const wlan_eapol_if_eapol_key_authentication_type_e /* authentication_type */,
       
   827     u8_t * PMKID,
       
   828     u32_t PMKID_length )
       
   829     {
       
   830     DEBUG( "core_sub_operation_wpa_connect_c::reassociate()" );
       
   831 
       
   832     if( PMKID )
       
   833         {
       
   834         pmkid_length_m = PMKID_length;
       
   835         core_tools_c::copy(
       
   836             &pmkid_data_m[0],
       
   837             PMKID,
       
   838             pmkid_length_m );
       
   839         }
       
   840 
       
   841     DEBUG( "core_sub_operation_wpa_connect_c::reassociate() - using open authentication algorithm" );
       
   842     auth_algorithm_m = core_authentication_mode_open;
       
   843 
       
   844     next_state();
       
   845 
       
   846     return core_error_ok;
       
   847     }
       
   848 
       
   849 // ---------------------------------------------------------------------------
       
   850 // ---------------------------------------------------------------------------
       
   851 //
       
   852 core_error_e core_sub_operation_wpa_connect_c::complete_check_pmksa_cache(
       
   853     core_type_list_c<network_id_c> & /* network_id_list */ )
       
   854     {
       
   855     DEBUG( "core_sub_operation_wpa_connect_c::complete_check_pmksa_cache()" );
       
   856     return core_error_ok;
       
   857     }
       
   858 
       
   859 // ---------------------------------------------------------------------------
       
   860 // ---------------------------------------------------------------------------
       
   861 //
       
   862 core_error_e core_sub_operation_wpa_connect_c::complete_start_wpx_fast_roam_reassociation(
       
   863     network_id_c * /* receive_network_id */,
       
   864     u8_t * reassociation_request_ie,
       
   865     u32_t reassociation_request_ie_length )
       
   866     {
       
   867     DEBUG( "core_sub_operation_wpa_connect_c::complete_start_wpx_fast_roam_reassociation()" );
       
   868     
       
   869     // Generate a WPX fast-roam IE and append it to assoc_ie_list.
       
   870     // Actually this could be done with core_wpx_frame_fast_roam_req_ie_c::instance() to make sure it's size is correct.
       
   871     core_frame_dot11_ie_c* ie = core_frame_dot11_ie_c::instance(
       
   872         reassociation_request_ie_length,
       
   873         reassociation_request_ie,
       
   874         true_t );
       
   875     if ( !ie )
       
   876         {
       
   877         DEBUG( "core_sub_operation_wpa_connect_c::complete_start_wpx_fast_roam_reassociation() - unable to generate a dot11 IE" );
       
   878         is_cached_sa_used_m = false_t;
       
   879         //asynch_goto( core_state_init, CORE_TIMER_IMMEDIATELY );
       
   880         return core_error_no_memory;
       
   881         }
       
   882 
       
   883     assoc_ie_list_m.append(
       
   884         ie,
       
   885         ie->element_id() );
       
   886 
       
   887     if( eapol_auth_type_m == wlan_eapol_if_eapol_key_authentication_type_wpx_fast_roam &&
       
   888         is_cached_sa_used_m )
       
   889         {
       
   890         server_m->get_connection_data()->set_eapol_authenticating(
       
   891             true_t ); 
       
   892         }
       
   893 
       
   894     asynch_goto( core_state_do_connect, CORE_TIMER_IMMEDIATELY );
       
   895     return core_error_ok;
       
   896     }
       
   897 
       
   898 
       
   899 // ---------------------------------------------------------------------------
       
   900 // ---------------------------------------------------------------------------
       
   901 //
       
   902 core_error_e core_sub_operation_wpa_connect_c::new_protected_setup_credentials(
       
   903     core_type_list_c< protected_setup_credential_c > & /* credential_list */ )
       
   904     {
       
   905     DEBUG( "core_sub_operation_wpa_connect_c::new_protected_setup_credentials()" );
       
   906     
       
   907     ASSERT( false_t );
       
   908     
       
   909     return core_error_ok;
       
   910     }
       
   911 
       
   912 
       
   913 // ---------------------------------------------------------------------------
       
   914 // ---------------------------------------------------------------------------
       
   915 //
       
   916 void core_sub_operation_wpa_connect_c::handle_error(
       
   917     wlan_eapol_if_error_e errorcode,
       
   918     wlan_eapol_if_message_type_function_e function )
       
   919     {
       
   920     DEBUG3( "core_sub_operation_wpa_connect_c::handle_error() - Received error message: errorcode=%i, function=%i (operation_state_m=%i)", 
       
   921         errorcode, 
       
   922         function, 
       
   923         operation_state_m );
       
   924     
       
   925     if ( errorcode != wlan_eapol_if_error_ok 
       
   926         && errorcode != wlan_eapol_if_error_pending_request )
       
   927         {
       
   928         if ( function == wlan_eapol_if_message_type_function_start_reassociation )
       
   929             {
       
   930             // Full authentication is needed.
       
   931             is_cached_sa_used_m = false_t;
       
   932             asynch_goto( core_state_start_authentication_needed, CORE_TIMER_IMMEDIATELY );
       
   933             }
       
   934         else if ( function == wlan_eapol_if_message_type_function_start_wpx_fast_roam_reassociation )
       
   935             {
       
   936             is_cached_sa_used_m = false_t;
       
   937 
       
   938             asynch_goto( core_state_init, CORE_TIMER_IMMEDIATELY );
       
   939             }
       
   940         else if ( function == wlan_eapol_if_message_type_function_complete_association
       
   941                || function == wlan_eapol_if_message_type_function_complete_reassociation
       
   942                || function == wlan_eapol_if_message_type_function_complete_wpx_fast_roam_reassociation  )
       
   943             {
       
   944             DEBUG( "core_sub_operation_wpa_connect_c::handle_error() - (WPX fast-roam) (re-)association failed" );
       
   945             asynch_goto( core_state_req_association_failed, CORE_TIMER_IMMEDIATELY );
       
   946             }
       
   947         /*else if ( function == wlan_eapol_if_message_type_function_start_authentication )
       
   948             {
       
   949             }*/
       
   950         else
       
   951             {
       
   952             DEBUG( "core_sub_operation_wpa_connect_c::handle_error() - Error ignored." );
       
   953             }
       
   954         }
       
   955     }
       
   956 
       
   957 
       
   958 // ---------------------------------------------------------------------------
       
   959 // ---------------------------------------------------------------------------
       
   960 //
       
   961 bool_t core_sub_operation_wpa_connect_c::notify(
       
   962     core_am_indication_e indication )
       
   963     {
       
   964     if ( operation_state_m == core_state_req_state_notification &&
       
   965          ( indication == core_am_indication_wlan_media_disconnect ||
       
   966            indication == core_am_indication_wlan_beacon_lost ||
       
   967            indication == core_am_indication_wlan_power_mode_failure ||
       
   968            indication == core_am_indication_wlan_tx_fail ) )
       
   969         {
       
   970         server_m->unregister_event_handler( this );
       
   971 
       
   972         if ( indication == core_am_indication_wlan_media_disconnect )
       
   973             {
       
   974             DEBUG( "core_sub_operation_wpa_connect_c::notify() - AP has disconnected us during authentication, notifying EAPOL" );
       
   975             }
       
   976         else
       
   977             {
       
   978             DEBUG( "core_sub_operation_wpa_connect_c::notify() - connection to the AP has been lost, notifying EAPOL" );
       
   979             }
       
   980 
       
   981         network_id_c network(
       
   982             &current_bssid_m.addr[0],
       
   983             MAC_ADDR_LEN,
       
   984             &server_m->own_mac_addr().addr[0],
       
   985             MAC_ADDR_LEN,
       
   986             server_m->get_eapol_instance().ethernet_type() );
       
   987 
       
   988         DEBUG6( "core_sub_operation_wpa_connect_c::notify() - EAPOL disassociation from BSSID %02X:%02X:%02X:%02X:%02X:%02X",
       
   989             current_bssid_m.addr[0], current_bssid_m.addr[1], current_bssid_m.addr[2],
       
   990             current_bssid_m.addr[3], current_bssid_m.addr[4], current_bssid_m.addr[5] );
       
   991 
       
   992         server_m->get_eapol_instance().disassociation( &network );
       
   993 
       
   994         if ( indication != core_am_indication_wlan_media_disconnect )
       
   995             {
       
   996             DEBUG( "core_sub_operation_wpa_connect_c::notify() - marking is_eapol_authenticating as false" );
       
   997             server_m->get_connection_data()->set_eapol_authenticating(
       
   998                 false_t );
       
   999             DEBUG( "core_sub_operation_wpa_connect_c::notify() - marking is_eapol_authentication_started as false" );
       
  1000             server_m->get_connection_data()->set_eapol_authentication_started(
       
  1001                 false_t );
       
  1002 
       
  1003             asynch_goto( core_state_bss_lost );
       
  1004 
       
  1005             return true_t;
       
  1006             }
       
  1007 
       
  1008         /**
       
  1009          * EAPOL indication will move the state machine forward.
       
  1010          */
       
  1011 
       
  1012         return true_t;
       
  1013         }
       
  1014 
       
  1015     return false_t;
       
  1016     }