Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ws_pae_supp.c Source File

ws_pae_supp.c

00001 /*
00002  * Copyright (c) 2018-2019, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include "nsconfig.h"
00019 #include <string.h>
00020 #include <randLIB.h>
00021 #include "ns_types.h"
00022 #include "ns_list.h"
00023 #include "ns_trace.h"
00024 #include "nsdynmemLIB.h"
00025 #include "fhss_config.h "
00026 #include "eventOS_event.h"
00027 #include "eventOS_scheduler.h"
00028 #include "eventOS_event_timer.h"
00029 #include "ns_address.h"
00030 #include "NWK_INTERFACE/Include/protocol.h"
00031 #include "RPL/rpl_protocol.h"
00032 #include "RPL/rpl_control.h"
00033 #include "RPL/rpl_data.h"
00034 #include "6LoWPAN/ws/ws_config.h"
00035 #include "Security/kmp/kmp_addr.h"
00036 #include "Security/kmp/kmp_api.h"
00037 #include "Security/protocols/sec_prot_certs.h"
00038 #include "Security/protocols/sec_prot_keys.h"
00039 #include "Security/protocols/key_sec_prot/key_sec_prot.h"
00040 #include "Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.h"
00041 #include "Security/protocols/tls_sec_prot/tls_sec_prot.h"
00042 #include "Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.h"
00043 #include "Security/protocols/gkh_sec_prot/supp_gkh_sec_prot.h"
00044 #include "6LoWPAN/ws/ws_pae_controller.h"
00045 #include "6LoWPAN/ws/ws_pae_timers.h"
00046 #include "6LoWPAN/ws/ws_pae_supp.h"
00047 #include "6LoWPAN/ws/ws_pae_lib.h"
00048 #include "6LoWPAN/ws/ws_pae_nvm_store.h"
00049 #include "6LoWPAN/ws/ws_pae_nvm_data.h"
00050 #include "6LoWPAN/MAC/mpx_api.h"
00051 #include "6LoWPAN/ws/ws_eapol_pdu.h"
00052 #include "Security/kmp/kmp_eapol_pdu_if.h"
00053 
00054 #ifdef HAVE_WS
00055 #ifdef HAVE_PAE_SUPP
00056 
00057 #define TRACE_GROUP "wsps"
00058 
00059 #define PAE_TASKLET_INIT                       1
00060 #define PAE_TASKLET_EVENT                      2
00061 #define PAE_TASKLET_TIMER                      3
00062 
00063 // Wait for for authenticator to continue with authentication (e.g. after EAP-TLS to initiate 4WH)
00064 #define WAIT_FOR_AUTHENTICATION_TICKS          30 * 10      // 30 seconds
00065 
00066 // Wait for re-authentication after GTK update
00067 #define WAIT_FOR_REAUTHENTICATION_TICKS        120 * 10     // 120 seconds
00068 
00069 // How many times in maximum stored keys are used for authentication
00070 #define STORED_KEYS_MAXIMUM_USE_COUNT          1
00071 
00072 // Delay for sending the initial EAPOL-Key
00073 #define INITIAL_KEY_TIMER_MIN                  3
00074 #define INITIAL_KEY_TIMER_MAX                  30
00075 
00076 typedef struct {
00077     char network_name[33];                                 /**< Network name for keys */
00078     sec_prot_gtk_keys_t *gtks;                             /**< Link to GTKs */
00079     uint16_t new_pan_id;                                   /**< new PAN ID indicated by bootstrap */
00080     uint16_t key_pan_id;                                   /**< PAN ID for keys */
00081     bool updated : 1;                                      /**< Network info has been updated */
00082 } sec_prot_keys_nw_info_t;
00083 
00084 typedef struct {
00085     ns_list_link_t link;                                   /**< Link */
00086     kmp_service_t *kmp_service;                            /**< KMP service */
00087     protocol_interface_info_entry_t *interface_ptr;        /**< Interface */
00088     ws_pae_supp_auth_completed *auth_completed;            /**< Authentication completed callback, continue bootstrap */
00089     ws_pae_supp_nw_key_insert *nw_key_insert;              /**< Key insert callback */
00090     ws_pae_supp_nw_key_index_set *nw_key_index_set;        /**< Key index set callback */
00091     supp_entry_t entry;                                    /**< Supplicant data */
00092     kmp_addr_t target_addr;                                /**< EAPOL target (parent) address */
00093     uint16_t initial_key_timer;                            /**< Timer to trigger initial EAPOL-Key */
00094     trickle_t auth_trickle_timer;                          /**< Trickle timer for re-sending initial EAPOL-key or for GTK mismatch */
00095     trickle_params_t auth_trickle_params;                  /**< Trickle parameters for initial EAPOL-key or for GTK mismatch */
00096     sec_prot_gtk_keys_t gtks;                              /**< GTKs */
00097     uint8_t new_br_eui_64[8];                              /**< Border router EUI-64 indicated by bootstrap */
00098     sec_prot_keys_nw_info_t sec_keys_nw_info;              /**< Security keys network information */
00099     timer_settings_t *timer_settings;                      /**< Timer settings */
00100     uint8_t nw_keys_used_cnt;                              /**< How many times bootstrap has been tried with current keys */
00101     bool auth_trickle_running : 1;                         /**< Initial EAPOL-Key Trickle timer running */
00102     bool auth_requested : 1;                               /**< Authentication has been requested by the bootstrap */
00103     bool timer_running : 1;                                /**< Timer is running */
00104     bool new_br_eui_64_set : 1;                            /**< Border router address has been set */
00105     bool new_br_eui_64_fresh : 1;                          /**< Border router address is fresh (set during this authentication attempt) */
00106     bool entry_address_active: 1;
00107 } pae_supp_t;
00108 
00109 
00110 #define TRICKLE_IMIN_180_SECS   180
00111 
00112 static trickle_params_t initial_eapol_key_trickle_params = {
00113     .Imin = TRICKLE_IMIN_180_SECS,          /* 180 second; ticks are 1 second */
00114     .Imax = TRICKLE_IMIN_180_SECS << 1,     /* 360 second */
00115                                   .k = 0,   /* infinity - no consistency checking */
00116                                   .TimerExpirations = 3
00117 };
00118 
00119 static void ws_pae_supp_free(pae_supp_t *pae_supp);
00120 static void ws_pae_supp_authenticate_response(pae_supp_t *pae_supp, auth_result_e result);
00121 static int8_t ws_pae_supp_initial_key_send(pae_supp_t *pae_supp);
00122 static void ws_pae_supp_nvm_update(pae_supp_t *pae_supp);
00123 static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan_id);
00124 static int8_t ws_pae_supp_nvm_nw_info_write(pae_supp_t *pae_supp);
00125 static int8_t ws_pae_supp_nvm_keys_write(pae_supp_t *pae_supp);
00126 static pae_supp_t *ws_pae_supp_get(protocol_interface_info_entry_t *interface_ptr);
00127 static int8_t ws_pae_supp_event_send(kmp_service_t *service, void *data);
00128 static void ws_pae_supp_tasklet_handler(arm_event_s *event);
00129 static int8_t ws_pae_supp_timer_if_start(kmp_service_t *service, kmp_api_t *kmp);
00130 static int8_t ws_pae_supp_timer_if_stop(kmp_service_t *service, kmp_api_t *kmp);
00131 static int8_t ws_pae_supp_timer_start(pae_supp_t *pae_supp);
00132 static int8_t ws_pae_supp_timer_stop(pae_supp_t *pae_supp);
00133 static bool ws_pae_supp_timer_running(pae_supp_t *pae_supp);
00134 static void ws_pae_supp_kmp_service_addr_get(kmp_service_t *service, kmp_api_t *kmp, kmp_addr_t *local_addr, kmp_addr_t *remote_addr);
00135 static kmp_api_t *ws_pae_supp_kmp_service_api_get(kmp_service_t *service, kmp_api_t *kmp, kmp_type_e type);
00136 static kmp_api_t *ws_pae_supp_kmp_incoming_ind(kmp_service_t *service, kmp_type_e type, const kmp_addr_t *addr);
00137 static kmp_api_t *ws_pae_supp_kmp_tx_status_ind(kmp_service_t *service, uint8_t instance_id);
00138 static kmp_api_t *ws_pae_supp_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, pae_supp_t *pae_supp);
00139 static int8_t ws_pae_supp_eapol_pdu_address_check(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64);
00140 static int8_t ws_pae_supp_parent_eui_64_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64);
00141 
00142 static void ws_pae_supp_kmp_api_create_confirm(kmp_api_t *kmp, kmp_result_e result);
00143 static void ws_pae_supp_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e type, kmp_addr_t *addr);
00144 static void ws_pae_supp_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys);
00145 static void ws_pae_supp_kmp_api_finished(kmp_api_t *kmp);
00146 
00147 
00148 static const eapol_pdu_recv_cb_data_t eapol_pdu_recv_cb_data = {
00149     .priority = EAPOL_PDU_RECV_HIGH_PRIORITY,
00150     .addr_check = ws_pae_supp_eapol_pdu_address_check,
00151     .receive = kmp_eapol_pdu_if_receive
00152 };
00153 
00154 static const char *NW_INFO_FILE = NW_INFO_FILE_NAME;
00155 static const char *KEYS_FILE = KEYS_FILE_NAME;
00156 
00157 static int8_t tasklet_id = -1;
00158 static NS_LIST_DEFINE(pae_supp_list, pae_supp_t, link);
00159 
00160 static void ws_pae_supp_address_set(pae_supp_t *pae_supp, kmp_addr_t *address)
00161 {
00162     if (address) {
00163         // Sets target address in use
00164         pae_supp->entry.addr = *address;
00165         pae_supp->entry_address_active = true;
00166     } else {
00167         pae_supp->entry_address_active = false;
00168     }
00169 }
00170 
00171 static bool ws_pae_supp_address_is_set(pae_supp_t *pae_supp)
00172 {
00173     return pae_supp->entry_address_active;
00174 }
00175 
00176 int8_t ws_pae_supp_authenticate(protocol_interface_info_entry_t *interface_ptr, uint16_t dest_pan_id, uint8_t *dest_eui_64)
00177 {
00178     pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
00179     if (!pae_supp) {
00180         return -1;
00181     }
00182 
00183     if (ws_pae_supp_nw_keys_valid_check(pae_supp, dest_pan_id) >= 0) {
00184         pae_supp->auth_completed(interface_ptr, AUTH_RESULT_OK, NULL);
00185         return 0;
00186     }
00187 
00188     // Delete GTKs
00189     sec_prot_keys_gtks_init(pae_supp->sec_keys_nw_info.gtks);
00190 
00191     /* PAN ID has changed, delete key data associated with border router
00192        i.e PMK, PTK, EA-IE data (border router EUI-64) */
00193     if (pae_supp->sec_keys_nw_info.key_pan_id != 0xFFFF && pae_supp->sec_keys_nw_info.key_pan_id != dest_pan_id) {
00194         sec_prot_keys_pmk_delete(&pae_supp->entry.sec_keys);
00195         sec_prot_keys_ptk_delete(&pae_supp->entry.sec_keys);
00196         sec_prot_keys_ptk_eui_64_delete(&pae_supp->entry.sec_keys);
00197     }
00198 
00199     pae_supp->sec_keys_nw_info.key_pan_id = dest_pan_id;
00200 
00201     // Prepare to receive new border router address
00202     pae_supp->new_br_eui_64_fresh = false;
00203 
00204     // Stores target/parent address
00205     kmp_address_init(KMP_ADDR_EUI_64, &pae_supp->target_addr, dest_eui_64);
00206     // Sets target address in use
00207     ws_pae_supp_address_set(pae_supp, &pae_supp->target_addr);
00208 
00209     pae_supp->auth_requested = true;
00210 
00211     // Randomizes the sending of initial EAPOL-Key messsage
00212     pae_supp->initial_key_timer = randLIB_get_random_in_range(INITIAL_KEY_TIMER_MIN, INITIAL_KEY_TIMER_MAX);
00213 
00214     // Starts supplicant timer
00215     ws_pae_supp_timer_start(pae_supp);
00216 
00217     tr_debug("PAE active, timer %i", pae_supp->initial_key_timer);
00218 
00219     return 1;
00220 }
00221 
00222 int8_t ws_pae_supp_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name)
00223 {
00224     pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
00225     if (!pae_supp) {
00226         return -1;
00227     }
00228 
00229     // PAN ID has been modified
00230     if (pan_id != 0xffff && pan_id != pae_supp->sec_keys_nw_info.new_pan_id) {
00231         pae_supp->sec_keys_nw_info.new_pan_id = pan_id;
00232         pae_supp->sec_keys_nw_info.updated = true;
00233     }
00234 
00235     // Network name has been modified
00236     if (network_name && strncmp(pae_supp->sec_keys_nw_info.network_name, network_name, 33) != 0) {
00237         strncpy(pae_supp->sec_keys_nw_info.network_name, network_name, 32);
00238         pae_supp->sec_keys_nw_info.updated = true;
00239     }
00240 
00241 
00242     return 0;
00243 }
00244 
00245 int8_t ws_pae_supp_border_router_addr_write(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64)
00246 {
00247     pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
00248     if (!pae_supp) {
00249         return -1;
00250     }
00251 
00252     memcpy(pae_supp->new_br_eui_64, eui_64, 8);
00253     pae_supp->new_br_eui_64_set = true;
00254     pae_supp->new_br_eui_64_fresh = true;
00255 
00256     return 0;
00257 }
00258 
00259 int8_t ws_pae_supp_border_router_addr_read(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64)
00260 {
00261     pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
00262     if (!pae_supp) {
00263         return -1;
00264     }
00265 
00266     uint8_t *br_eui_64 = sec_prot_keys_ptk_eui_64_get(&pae_supp->entry.sec_keys);
00267     if (!br_eui_64) {
00268         return -1;
00269     }
00270 
00271     memcpy(eui_64, br_eui_64, 8);
00272 
00273     return 0;
00274 }
00275 
00276 int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr)
00277 {
00278     pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
00279     if (!pae_supp) {
00280         return -1;
00281     }
00282 
00283     tr_info("NW key valid");
00284 
00285     // Stored keys are valid
00286     pae_supp->nw_keys_used_cnt = 0;
00287 
00288     // Update NVM if data has been changed
00289     ws_pae_supp_nvm_update(pae_supp);
00290 
00291     return 0;
00292 }
00293 
00294 int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash)
00295 {
00296     pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
00297     if (!pae_supp) {
00298         return -1;
00299     }
00300 
00301     // Check GTK hashes and initiate EAPOL procedure if mismatch is detected */
00302     gtk_mismatch_e mismatch = sec_prot_keys_gtks_hash_update(&pae_supp->gtks, gtkhash);
00303     if (mismatch > GTK_NO_MISMATCH) {
00304         tr_info("GTK hash update %s %s %s %s",
00305                 trace_array(&gtkhash[0], 8),
00306                 trace_array(&gtkhash[8], 8),
00307                 trace_array(&gtkhash[16], 8),
00308                 trace_array(&gtkhash[24], 8));
00309 
00310         // Mismatch, initiate EAPOL
00311         if (!pae_supp->auth_trickle_running) {
00312             uint8_t timer_expirations = 3;
00313             // For GTK lifetime mismatch send only once
00314             if (mismatch == GTK_LIFETIME_MISMATCH) {
00315                 timer_expirations = 1;
00316             }
00317 
00318             pae_supp->auth_trickle_params.Imin = pae_supp->timer_settings->gtk_request_imin;
00319             pae_supp->auth_trickle_params.Imax = pae_supp->timer_settings->gtk_request_imax;
00320             pae_supp->auth_trickle_params.k = 0;
00321             pae_supp->auth_trickle_params.TimerExpirations = timer_expirations;
00322 
00323             // Starts trickle
00324             trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params);
00325             pae_supp->auth_trickle_running = true;
00326 
00327             // Starts supplicant timer
00328             ws_pae_supp_timer_start(pae_supp);
00329 
00330             tr_info("GTK update start imin: %i, imax: %i, max mismatch: %i, tr time: %i", pae_supp->timer_settings->gtk_request_imin, pae_supp->timer_settings->gtk_request_imax, pae_supp->timer_settings->gtk_max_mismatch, pae_supp->auth_trickle_timer.t);
00331         } else {
00332             // If trickle is already running, set inconsistent heard to speed up the trickle
00333             trickle_inconsistent_heard(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params);
00334         }
00335     }
00336 
00337     // Modify keys
00338     pae_supp->nw_key_insert(pae_supp->interface_ptr, pae_supp->sec_keys_nw_info.gtks);
00339 
00340     return 0;
00341 }
00342 
00343 int8_t ws_pae_supp_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index)
00344 {
00345     pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
00346     if (!pae_supp) {
00347         return -1;
00348     }
00349 
00350     if (sec_prot_keys_gtk_status_active_set(&pae_supp->gtks, index) >= 0) {
00351         pae_supp->nw_key_index_set(interface_ptr, index);
00352     } else {
00353         tr_info("NW send key index: %i, no changes", index + 1);
00354     }
00355 
00356     return 0;
00357 }
00358 
00359 int8_t ws_pae_supp_gtks_set(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks)
00360 {
00361     pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
00362     if (!pae_supp) {
00363         return -1;
00364     }
00365 
00366     pae_supp->gtks = *gtks;
00367 
00368     return 0;
00369 }
00370 
00371 int8_t ws_pae_supp_eapol_target_remove(protocol_interface_info_entry_t *interface_ptr)
00372 {
00373     pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
00374     if (!pae_supp) {
00375         return -1;
00376     }
00377 
00378     // Sets target/parent address to null
00379     ws_pae_supp_address_set(pae_supp, NULL);
00380 
00381     return 0;
00382 }
00383 
00384 static void ws_pae_supp_nvm_update(pae_supp_t *pae_supp)
00385 {
00386     // Check if NW info or GTKs have been changed
00387     if (pae_supp->sec_keys_nw_info.updated || sec_prot_keys_gtks_are_updated(pae_supp->sec_keys_nw_info.gtks)) {
00388         ws_pae_supp_nvm_nw_info_write(pae_supp);
00389         pae_supp->sec_keys_nw_info.updated = false;
00390         sec_prot_keys_gtks_updated_reset(pae_supp->sec_keys_nw_info.gtks);
00391     }
00392 
00393     // Check if pairwise security keys have been changed
00394     if (sec_prot_keys_are_updated(&pae_supp->entry.sec_keys)) {
00395         ws_pae_supp_nvm_keys_write(pae_supp);
00396         sec_prot_keys_updated_reset(&pae_supp->entry.sec_keys);
00397     }
00398 }
00399 
00400 static int8_t ws_pae_supp_nvm_nw_info_write(pae_supp_t *pae_supp)
00401 {
00402     nvm_tlv_entry_t *tlv_entry = ws_pae_controller_nvm_tlv_get(pae_supp->interface_ptr);
00403     if (!tlv_entry) {
00404         return -1;
00405     }
00406 
00407     nvm_tlv_list_t tlv_list;
00408     ns_list_init(&tlv_list);
00409 
00410     ws_pae_nvm_store_nw_info_tlv_create(tlv_entry, pae_supp->sec_keys_nw_info.key_pan_id,
00411                                         pae_supp->sec_keys_nw_info.network_name,
00412                                         &pae_supp->gtks);
00413     ns_list_add_to_end(&tlv_list, tlv_entry);
00414 
00415     ws_pae_nvm_store_tlv_file_write(NW_INFO_FILE, &tlv_list);
00416 
00417     return 0;
00418 }
00419 
00420 static int8_t ws_pae_supp_nvm_nw_info_read(pae_supp_t *pae_supp)
00421 {
00422     nvm_tlv_list_t tlv_list;
00423     ns_list_init(&tlv_list);
00424 
00425     ws_pae_nvm_store_tlv_file_read(NW_INFO_FILE, &tlv_list);
00426 
00427     ns_list_foreach_safe(nvm_tlv_entry_t, entry, &tlv_list) {
00428         ws_pae_nvm_store_nw_info_tlv_read(entry, &pae_supp->sec_keys_nw_info.key_pan_id,
00429                                           pae_supp->sec_keys_nw_info.network_name,
00430                                           &pae_supp->gtks);
00431         ns_list_remove(&tlv_list, entry);
00432         ns_dyn_mem_free(entry);
00433     }
00434 
00435     return 0;
00436 }
00437 
00438 static int8_t ws_pae_supp_nvm_keys_write(pae_supp_t *pae_supp)
00439 {
00440     nvm_tlv_entry_t *tlv_entry = ws_pae_controller_nvm_tlv_get(pae_supp->interface_ptr);
00441     if (!tlv_entry) {
00442         return -1;
00443     }
00444 
00445     nvm_tlv_list_t tlv_list;
00446     ns_list_init(&tlv_list);
00447 
00448     ws_pae_nvm_store_keys_tlv_create(tlv_entry, &pae_supp->entry.sec_keys);
00449     ns_list_add_to_end(&tlv_list, tlv_entry);
00450 
00451     ws_pae_nvm_store_tlv_file_write(KEYS_FILE, &tlv_list);
00452 
00453     return 0;
00454 }
00455 
00456 static int8_t ws_pae_supp_nvm_keys_read(pae_supp_t *pae_supp)
00457 {
00458     nvm_tlv_list_t tlv_list;
00459     ns_list_init(&tlv_list);
00460 
00461     ws_pae_nvm_store_tlv_file_read(KEYS_FILE, &tlv_list);
00462 
00463     ns_list_foreach_safe(nvm_tlv_entry_t, entry, &tlv_list) {
00464         ws_pae_nvm_store_keys_tlv_read(entry, &pae_supp->entry.sec_keys);
00465         ns_list_remove(&tlv_list, entry);
00466         ns_dyn_mem_free(entry);
00467     }
00468 
00469     return 0;
00470 }
00471 
00472 static void ws_pae_supp_authenticate_response(pae_supp_t *pae_supp, auth_result_e result)
00473 {
00474     pae_supp->auth_trickle_running = false;
00475     if (pae_supp->auth_requested && pae_supp->auth_completed) {
00476         pae_supp->auth_requested = false;
00477         uint8_t *target_eui_64 = NULL;
00478         if (result != AUTH_RESULT_OK) {
00479             target_eui_64 = pae_supp->target_addr.eui_64;
00480         }
00481         pae_supp->auth_completed(pae_supp->interface_ptr, result, target_eui_64);
00482     }
00483 }
00484 
00485 static int8_t ws_pae_supp_initial_key_send(pae_supp_t *pae_supp)
00486 {
00487     if (!pae_supp->auth_requested) {
00488         // If not making initial authentication updates target (RPL parent) for each EAPOL-key message
00489         uint8_t parent_eui_64[8];
00490         if (ws_pae_supp_parent_eui_64_get(pae_supp->interface_ptr, parent_eui_64) >= 0) {
00491             // Stores target/parent address
00492             kmp_address_init(KMP_ADDR_EUI_64, &pae_supp->target_addr, parent_eui_64);
00493             // Sets parent address in use
00494             ws_pae_supp_address_set(pae_supp, &pae_supp->target_addr);
00495         } else if (ws_pae_supp_address_is_set(pae_supp)) {
00496             /* If there is no RPL parent but there is target address from initial authentication
00497                bootstrap, tries to use it. This can happen if BR updates keys after EAPOL authentication
00498                but before bootstrap is completed and RPL parent is known */
00499             tr_info("EAPOL initial auth target used");
00500         } else {
00501             // No target, failure
00502             return -1;
00503         }
00504 
00505         ws_pae_lib_supp_timer_ticks_set(&pae_supp->entry, WAIT_FOR_REAUTHENTICATION_TICKS);
00506         tr_info("PAE wait for auth seconds: %i", WAIT_FOR_REAUTHENTICATION_TICKS / 10);
00507     }
00508 
00509     kmp_api_t *kmp = ws_pae_supp_kmp_create_and_start(pae_supp->kmp_service, IEEE_802_1X_MKA_KEY, pae_supp);
00510     if (!kmp) {
00511         return -1;
00512     }
00513 
00514     tr_info("EAPOL target: %s", trace_array(kmp_address_eui_64_get(&pae_supp->entry.addr), 8));
00515 
00516     kmp_api_create_request(kmp, IEEE_802_1X_MKA_KEY, &pae_supp->entry.addr, &pae_supp->entry.sec_keys);
00517 
00518     return 0;
00519 }
00520 
00521 static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan_id)
00522 {
00523     // Checks how many times authentication has been tried with current network keys
00524     if (pae_supp->nw_keys_used_cnt >= STORED_KEYS_MAXIMUM_USE_COUNT) {
00525         tr_debug("Keys not valid, delete GTKs");
00526 
00527         // Delete GTKs
00528         sec_prot_keys_gtks_init(pae_supp->sec_keys_nw_info.gtks);
00529         sec_prot_keys_gtks_updated_set(pae_supp->sec_keys_nw_info.gtks);
00530         ws_pae_supp_nvm_update(pae_supp);
00531 
00532         pae_supp->nw_keys_used_cnt = 0;
00533         return -1;
00534     }
00535 
00536     /* Checks if keys match to PAN ID and that needed keys exists (PMK, PTK and a GTK),
00537        and calls inserts function that will update the network keys as needed */
00538     if ((pan_id == pae_supp->sec_keys_nw_info.key_pan_id) &&
00539             (sec_prot_keys_gtk_count(pae_supp->sec_keys_nw_info.gtks) > 0) &&
00540             (sec_prot_keys_pmk_get(&pae_supp->entry.sec_keys) != NULL) &&
00541             (sec_prot_keys_ptk_get(&pae_supp->entry.sec_keys) != NULL)) {
00542         tr_debug("Existing keys used, counter %i", pae_supp->nw_keys_used_cnt);
00543         if (pae_supp->nw_key_insert(pae_supp->interface_ptr, pae_supp->sec_keys_nw_info.gtks) >= 0) {
00544             tr_debug("Keys inserted");
00545         }
00546         pae_supp->nw_keys_used_cnt++;
00547         return 0;
00548     } else {
00549         pae_supp->nw_keys_used_cnt = 0;
00550         return -1;
00551     }
00552 }
00553 
00554 static void ws_pae_supp_keys_nw_info_init(sec_prot_keys_nw_info_t *sec_keys_nw_info, sec_prot_gtk_keys_t *gtks)
00555 {
00556     if (!sec_keys_nw_info) {
00557         return;
00558     }
00559 
00560     memset(sec_keys_nw_info, 0, sizeof(sec_prot_keys_nw_info_t));
00561 
00562     sec_keys_nw_info->gtks = gtks;
00563     sec_keys_nw_info->new_pan_id = 0xFFFF;
00564     sec_keys_nw_info->key_pan_id = 0xFFFF;
00565     sec_keys_nw_info->updated = false;
00566 }
00567 
00568 void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_supp_auth_completed *completed, ws_pae_supp_nw_key_insert *nw_key_insert, ws_pae_supp_nw_key_index_set *nw_key_index_set)
00569 {
00570     pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
00571     if (!pae_supp) {
00572         return;
00573     }
00574 
00575     pae_supp->auth_completed = completed;
00576     pae_supp->nw_key_insert = nw_key_insert;
00577     pae_supp->nw_key_index_set = nw_key_index_set;
00578 }
00579 
00580 int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const sec_prot_certs_t *certs, timer_settings_t *timer_settings)
00581 {
00582     if (!interface_ptr) {
00583         return -1;
00584     }
00585 
00586     if (ws_pae_supp_get(interface_ptr) != NULL) {
00587         return 0;
00588     }
00589 
00590     pae_supp_t *pae_supp = ns_dyn_mem_alloc(sizeof(pae_supp_t));
00591     if (!pae_supp) {
00592         return -1;
00593     }
00594 
00595     pae_supp->interface_ptr = interface_ptr;
00596     pae_supp->auth_completed = NULL;
00597     pae_supp->nw_key_insert = NULL;
00598     pae_supp->nw_key_index_set = NULL;
00599     pae_supp->initial_key_timer = 0;
00600     pae_supp->nw_keys_used_cnt = 0;
00601     pae_supp->timer_settings = timer_settings;
00602     pae_supp->auth_trickle_running = false;
00603     pae_supp->auth_requested = false;
00604     pae_supp->timer_running = false;
00605     pae_supp->new_br_eui_64_set = false;
00606     pae_supp->new_br_eui_64_fresh = false;
00607     pae_supp->entry_address_active = false;
00608 
00609     ws_pae_lib_supp_init(&pae_supp->entry);
00610 
00611     ws_pae_supp_keys_nw_info_init(&pae_supp->sec_keys_nw_info, &pae_supp->gtks);
00612 
00613     kmp_address_init(KMP_ADDR_EUI_64, &pae_supp->target_addr, 0);
00614 
00615     sec_prot_keys_gtks_init(&pae_supp->gtks);
00616     sec_prot_keys_init(&pae_supp->entry.sec_keys, &pae_supp->gtks, certs);
00617     memset(pae_supp->new_br_eui_64, 0, 8);
00618 
00619     pae_supp->kmp_service = kmp_service_create();
00620     if (!pae_supp->kmp_service) {
00621         goto error;
00622     }
00623 
00624     if (kmp_service_cb_register(pae_supp->kmp_service, ws_pae_supp_kmp_incoming_ind, ws_pae_supp_kmp_tx_status_ind, ws_pae_supp_kmp_service_addr_get, ws_pae_supp_kmp_service_api_get) < 0) {
00625         goto error;
00626     }
00627 
00628     if (kmp_service_event_if_register(pae_supp->kmp_service, ws_pae_supp_event_send)) {
00629         goto error;
00630     }
00631 
00632     if (kmp_service_timer_if_register(pae_supp->kmp_service, ws_pae_supp_timer_if_start, ws_pae_supp_timer_if_stop)) {
00633         goto error;
00634     }
00635 
00636     if (kmp_eapol_pdu_if_register(pae_supp->kmp_service, interface_ptr) < 0) {
00637         goto error;
00638     }
00639 
00640     if (ws_eapol_pdu_cb_register(interface_ptr, &eapol_pdu_recv_cb_data) < 0) {
00641         goto error;
00642     }
00643 
00644     if (supp_key_sec_prot_register(pae_supp->kmp_service) < 0) {
00645         goto error;
00646     }
00647 
00648     if (supp_eap_tls_sec_prot_register(pae_supp->kmp_service) < 0) {
00649         goto error;
00650     }
00651 
00652     if (client_tls_sec_prot_register(pae_supp->kmp_service) < 0) {
00653         goto error;
00654     }
00655 
00656     if (supp_fwh_sec_prot_register(pae_supp->kmp_service) < 0) {
00657         goto error;
00658     }
00659 
00660     if (supp_gkh_sec_prot_register(pae_supp->kmp_service) < 0) {
00661         goto error;
00662     }
00663 
00664     if (tasklet_id < 0) {
00665         tasklet_id = eventOS_event_handler_create(ws_pae_supp_tasklet_handler, PAE_TASKLET_INIT);
00666         if (tasklet_id < 0) {
00667             goto error;
00668         }
00669     }
00670 
00671     if (ws_pae_supp_timer_stop(pae_supp) < 0) {
00672         goto error;
00673     }
00674 
00675     ws_pae_supp_nvm_nw_info_read(pae_supp);
00676     ws_pae_supp_nvm_keys_read(pae_supp);
00677 
00678     ns_list_add_to_end(&pae_supp_list, pae_supp);
00679 
00680     return 0;
00681 
00682 error:
00683     ws_pae_supp_free(pae_supp);
00684 
00685     return -1;
00686 }
00687 
00688 int8_t ws_pae_supp_delete(protocol_interface_info_entry_t *interface_ptr)
00689 {
00690     if (!interface_ptr) {
00691         return -1;
00692     }
00693 
00694     pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
00695     if (!pae_supp) {
00696         return -1;
00697     }
00698 
00699     ws_pae_supp_free(pae_supp);
00700     return 0;
00701 }
00702 
00703 int8_t ws_pae_supp_timing_adjust(uint8_t timing)
00704 {
00705     supp_fwh_sec_prot_timing_adjust(timing);
00706     supp_eap_sec_prot_timing_adjust(timing);
00707     return 0;
00708 }
00709 
00710 static void ws_pae_supp_free(pae_supp_t *pae_supp)
00711 {
00712     if (!pae_supp) {
00713         return;
00714     }
00715 
00716     ws_pae_lib_supp_delete(&pae_supp->entry);
00717 
00718     kmp_eapol_pdu_if_unregister(pae_supp->kmp_service);
00719 
00720     ws_eapol_pdu_cb_unregister(pae_supp->interface_ptr, &eapol_pdu_recv_cb_data);
00721 
00722     kmp_service_delete(pae_supp->kmp_service);
00723 
00724     ns_list_remove(&pae_supp_list, pae_supp);
00725     ns_dyn_mem_free(pae_supp);
00726 }
00727 
00728 static pae_supp_t *ws_pae_supp_get(protocol_interface_info_entry_t *interface_ptr)
00729 {
00730     ns_list_foreach(pae_supp_t, entry, &pae_supp_list) {
00731         if (entry->interface_ptr == interface_ptr) {
00732             return entry;
00733         }
00734     }
00735 
00736     return NULL;
00737 }
00738 
00739 static pae_supp_t *ws_pae_supp_by_kmp_service_get(kmp_service_t *service)
00740 {
00741     ns_list_foreach(pae_supp_t, entry, &pae_supp_list) {
00742         if (entry->kmp_service == service) {
00743             return entry;
00744         }
00745     }
00746 
00747     return NULL;
00748 }
00749 
00750 static int8_t ws_pae_supp_event_send(kmp_service_t *service, void *data)
00751 {
00752     pae_supp_t *pae_supp = ws_pae_supp_by_kmp_service_get(service);
00753     if (!pae_supp) {
00754         return -1;
00755     }
00756 
00757     arm_event_s event = {
00758         .receiver = tasklet_id,
00759         .sender = 0,
00760         .event_id = pae_supp->interface_ptr->id,
00761         .data_ptr = data,
00762         .event_type = PAE_TASKLET_EVENT,
00763         .priority = ARM_LIB_LOW_PRIORITY_EVENT,
00764     };
00765 
00766     if (eventOS_event_send(&event) != 0) {
00767         return -1;
00768     }
00769 
00770     return 0;
00771 }
00772 
00773 static void ws_pae_supp_tasklet_handler(arm_event_s *event)
00774 {
00775     if (event->event_type == PAE_TASKLET_INIT) {
00776 
00777     } else if (event->event_type == PAE_TASKLET_EVENT) {
00778         pae_supp_t *pae_supp = NULL;
00779 
00780         ns_list_foreach(pae_supp_t, entry, &pae_supp_list) {
00781             if (entry->interface_ptr->id == event->event_id) {
00782                 pae_supp = entry;
00783                 break;
00784             }
00785         }
00786 
00787         if (pae_supp) {
00788             kmp_service_event_if_event(pae_supp->kmp_service, event->data_ptr);
00789         }
00790     }
00791 }
00792 
00793 void ws_pae_supp_fast_timer(uint16_t ticks)
00794 {
00795     ns_list_foreach(pae_supp_t, pae_supp, &pae_supp_list) {
00796         if (!ws_pae_supp_timer_running(pae_supp)) {
00797             continue;
00798         }
00799 
00800         // Updates KMP timers and supplicant authentication ongoing timer
00801         bool running = ws_pae_lib_supp_timer_update(&pae_supp->entry, ticks, kmp_service_timer_if_timeout);
00802 
00803         // Checks whether timer needs to be active
00804         if (!pae_supp->initial_key_timer && !pae_supp->auth_trickle_running && !running) {
00805             tr_debug("PAE idle");
00806             // If not already completed, restart bootstrap
00807             ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_UNSPEC);
00808 
00809             ws_pae_supp_timer_stop(pae_supp);
00810         }
00811     }
00812 }
00813 
00814 void ws_pae_supp_slow_timer(uint16_t seconds)
00815 {
00816     ns_list_foreach(pae_supp_t, pae_supp, &pae_supp_list) {
00817 
00818         // Checks whether initial EAPOL-Key message needs to be re-send or new GTK request to be sent
00819         if (pae_supp->auth_trickle_running) {
00820             if (trickle_timer(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params, seconds)) {
00821                 if (ws_pae_supp_initial_key_send(pae_supp) < 0) {
00822                     tr_info("EAPOL-Key send failed");
00823                 }
00824             }
00825             // Maximum number of trickle expires, authentication fails
00826             if (!trickle_running(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params)) {
00827                 ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_UNSPEC);
00828             }
00829         }
00830 
00831         // Decrements GTK lifetimes
00832         for (uint8_t i = 0; i < GTK_NUM; i++) {
00833             if (!sec_prot_keys_gtk_is_set(&pae_supp->gtks, i)) {
00834                 continue;
00835             }
00836             sec_prot_keys_gtk_lifetime_decrement(&pae_supp->gtks, i, seconds);
00837         }
00838 
00839         if (pae_supp->initial_key_timer > 0) {
00840             if (pae_supp->initial_key_timer > seconds) {
00841                 pae_supp->initial_key_timer -= seconds;
00842             } else {
00843                 pae_supp->initial_key_timer = 0;
00844 
00845                 // Sends initial EAPOL-Key message
00846                 if (ws_pae_supp_initial_key_send(pae_supp) < 0) {
00847                     tr_info("EAPOL-Key send failed");
00848                 }
00849 
00850                 // Starts trickle
00851                 pae_supp->auth_trickle_params = initial_eapol_key_trickle_params;
00852                 trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params);
00853                 pae_supp->auth_trickle_running = true;
00854             }
00855         }
00856     }
00857 }
00858 
00859 static int8_t ws_pae_supp_timer_if_start(kmp_service_t *service, kmp_api_t *kmp)
00860 {
00861     pae_supp_t *pae_supp = ws_pae_supp_by_kmp_service_get(service);
00862     if (!pae_supp) {
00863         return -1;
00864     }
00865 
00866     if (ws_pae_supp_timer_start(pae_supp) < 0) {
00867         return -1;
00868     }
00869 
00870     kmp_entry_t *entry = kmp_api_data_get(kmp);
00871     if (!entry) {
00872         return -1;
00873     }
00874     ws_pae_lib_kmp_timer_start(&pae_supp->entry.kmp_list, entry);
00875     return 0;
00876 }
00877 
00878 static int8_t ws_pae_supp_timer_if_stop(kmp_service_t *service, kmp_api_t *kmp)
00879 {
00880     pae_supp_t *pae_supp = ws_pae_supp_by_kmp_service_get(service);
00881     if (!pae_supp) {
00882         return -1;
00883     }
00884 
00885     kmp_entry_t *entry = kmp_api_data_get(kmp);
00886     if (!entry) {
00887         return -1;
00888     }
00889     ws_pae_lib_kmp_timer_stop(&pae_supp->entry.kmp_list, entry);
00890     return 0;
00891 }
00892 
00893 static int8_t ws_pae_supp_timer_start(pae_supp_t *pae_supp)
00894 {
00895     pae_supp->timer_running = true;
00896     return 0;
00897 }
00898 
00899 static int8_t ws_pae_supp_timer_stop(pae_supp_t *pae_supp)
00900 {
00901     pae_supp->timer_running = false;
00902     return 0;
00903 }
00904 
00905 static bool ws_pae_supp_timer_running(pae_supp_t *pae_supp)
00906 {
00907     return pae_supp->timer_running;
00908 }
00909 
00910 static int8_t ws_pae_supp_eapol_pdu_address_check(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64)
00911 {
00912     pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
00913     if (!pae_supp) {
00914         return -1;
00915     }
00916 
00917     // Message from EAPOL target node, route to self
00918     if (pae_supp->entry_address_active) {
00919         if (memcmp(eui_64, pae_supp->entry.addr.eui_64, 8) == 0) {
00920             return 0;
00921         }
00922     }
00923 
00924     // Get parent
00925     uint8_t parent_eui_64[8];
00926     if (ws_pae_supp_parent_eui_64_get(interface_ptr, parent_eui_64) < 0) {
00927         return -1;
00928     }
00929 
00930     // Message from RPL parent, route to self
00931     if (memcmp(parent_eui_64, eui_64, 8) == 0) {
00932         return 0;
00933     }
00934 
00935     return -1;
00936 }
00937 
00938 static int8_t ws_pae_supp_parent_eui_64_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64)
00939 {
00940     rpl_dodag_info_t dodag_info;
00941     if (!interface_ptr->rpl_domain) {
00942         return -1;
00943     }
00944     struct rpl_instance *instance = rpl_control_enumerate_instances(interface_ptr->rpl_domain, NULL);
00945     if (instance && rpl_control_read_dodag_info(instance, &dodag_info)) {
00946         // Get parent
00947         const uint8_t *parent_ll_addr = rpl_control_preferred_parent_addr(instance, false);
00948         if (parent_ll_addr) {
00949             memcpy(eui_64, &parent_ll_addr[8], 8);
00950             eui_64[0] |= 0x02;
00951             return 0;
00952         }
00953     }
00954 
00955     return -1;
00956 }
00957 
00958 static void ws_pae_supp_kmp_service_addr_get(kmp_service_t *service, kmp_api_t *kmp, kmp_addr_t *local_addr, kmp_addr_t *remote_addr)
00959 {
00960     (void) kmp;
00961 
00962     pae_supp_t *pae_supp = ws_pae_supp_by_kmp_service_get(service);
00963     if (!pae_supp) {
00964         return;
00965     }
00966 
00967     // Get own EUI-64
00968     link_layer_address_s mac_params;
00969     if (arm_nwk_mac_address_read(pae_supp->interface_ptr->id, &mac_params) >= 0) {
00970         kmp_address_eui_64_set(local_addr, mac_params.mac_long);
00971     }
00972 
00973     // BR address has been received during authentication attempt
00974     if (pae_supp->new_br_eui_64_fresh) {
00975         kmp_address_eui_64_set(remote_addr, pae_supp->new_br_eui_64);
00976     } else {
00977         uint8_t *eui_64 = sec_prot_keys_ptk_eui_64_get(&pae_supp->entry.sec_keys);
00978         // BR address is set on security keys (confirmed using 4WH)
00979         if (eui_64) {
00980             kmp_address_eui_64_set(remote_addr, eui_64);
00981         } else {
00982             // For initial EAPOL key, if BR address has been received during previous attempt, generate PMKID using it
00983             if (pae_supp->new_br_eui_64_set && kmp_api_type_get(kmp) >= IEEE_802_1X_INITIAL_KEY) {
00984                 kmp_address_eui_64_set(remote_addr, pae_supp->new_br_eui_64);
00985             } else {
00986                 memset(remote_addr, 0, sizeof(kmp_addr_t));
00987                 tr_error("No border router EUI-64");
00988             }
00989         }
00990     }
00991 }
00992 
00993 static kmp_api_t *ws_pae_supp_kmp_service_api_get(kmp_service_t *service, kmp_api_t *kmp, kmp_type_e type)
00994 {
00995     (void) kmp;
00996 
00997     pae_supp_t *pae_supp = ws_pae_supp_by_kmp_service_get(service);
00998     if (!pae_supp) {
00999         return NULL;
01000     }
01001 
01002     return ws_pae_lib_kmp_list_type_get(&pae_supp->entry.kmp_list, type);
01003 }
01004 
01005 static kmp_api_t *ws_pae_supp_kmp_incoming_ind(kmp_service_t *service, kmp_type_e type, const kmp_addr_t *addr)
01006 {
01007     // Should be MKA, 4WH or GKH and never initial EAPOL-key for supplicant
01008     if (type > IEEE_802_1X_INITIAL_KEY) {
01009         return NULL;
01010     }
01011 
01012     pae_supp_t *pae_supp = ws_pae_supp_by_kmp_service_get(service);
01013     if (!pae_supp) {
01014         return NULL;
01015     }
01016 
01017     if (!pae_supp->entry_address_active) {
01018         // Does no longer wait for authentication, ignores message
01019         return NULL;
01020     }
01021 
01022     // No longer runs trickle timer for re-sending initial EAPOL-key
01023     pae_supp->auth_trickle_running = false;
01024 
01025     // Updates parent address
01026     kmp_address_copy(&pae_supp->entry.addr, addr);
01027 
01028     // Check if ongoing
01029     kmp_api_t *kmp = ws_pae_lib_kmp_list_type_get(&pae_supp->entry.kmp_list, type);
01030     /* If kmp receiving is enabled or it is not GKH, routes message to existing KMP.
01031 
01032        For GKH creates an instance to handle message. If message is not valid (e.g. repeated
01033        message counter), GKH ignores message and waits for timeout. All further messages
01034        are routed to that instance. If valid message arrives, GKH instance handles the
01035        message, replies to authenticator and terminates. */
01036     if (kmp && (!kmp_api_receive_disable(kmp) || type != IEEE_802_11_GKH)) {
01037         return kmp;
01038     }
01039 
01040     // Create new instance
01041     kmp = ws_pae_supp_kmp_create_and_start(service, type, pae_supp);
01042 
01043     // For EAP-TLS create also TLS in addition to EAP-TLS
01044     if (type == IEEE_802_1X_MKA) {
01045         if (ws_pae_lib_kmp_list_type_get(&pae_supp->entry.kmp_list, TLS_PROT) != NULL) {
01046             // TLS already exists, wait for it to be deleted
01047             ws_pae_lib_kmp_list_delete(&pae_supp->entry.kmp_list, kmp);
01048             return NULL;
01049         }
01050         // Create TLS instance */
01051         if (ws_pae_supp_kmp_create_and_start(service, TLS_PROT, pae_supp) == NULL) {
01052             ws_pae_lib_kmp_list_delete(&pae_supp->entry.kmp_list, kmp);
01053             return NULL;
01054         }
01055     }
01056 
01057     return kmp;
01058 }
01059 
01060 static kmp_api_t *ws_pae_supp_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, pae_supp_t *pae_supp)
01061 {
01062     // Create new instance
01063     kmp_api_t *kmp = kmp_api_create(service, type);
01064     if (!kmp) {
01065         return NULL;
01066     }
01067 
01068     // Updates parent address
01069     kmp_api_addr_set(kmp, &pae_supp->entry.addr);
01070 
01071     // Sets security keys to KMP
01072     kmp_api_sec_keys_set(kmp, &pae_supp->entry.sec_keys);
01073 
01074     kmp_api_cb_register(
01075         kmp, ws_pae_supp_kmp_api_create_confirm,
01076         ws_pae_supp_kmp_api_create_indication,
01077         ws_pae_supp_kmp_api_finished_indication,
01078         ws_pae_supp_kmp_api_finished);
01079 
01080     kmp_entry_t *kmp_entry = ws_pae_lib_kmp_list_add(&pae_supp->entry.kmp_list, kmp);
01081     if (!kmp_entry) {
01082         kmp_api_delete(kmp);
01083         return NULL;
01084     }
01085 
01086     kmp_api_data_set(kmp, kmp_entry);
01087 
01088     if (kmp_api_start(kmp) < 0) {
01089         ws_pae_lib_kmp_list_delete(&pae_supp->entry.kmp_list, kmp);
01090         return NULL;
01091     }
01092 
01093     return kmp;
01094 }
01095 
01096 static void ws_pae_supp_kmp_api_create_confirm(kmp_api_t *kmp, kmp_result_e result)
01097 {
01098     kmp_service_t *service = kmp_api_service_get(kmp);
01099     pae_supp_t *pae_supp = ws_pae_supp_by_kmp_service_get(service);
01100     if (!pae_supp) {
01101         return;
01102     }
01103 
01104     // KMP-CREATE.request has failed, authentication error
01105     if (result != KMP_RESULT_OK) {
01106         ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_UNSPEC);
01107     }
01108 }
01109 
01110 static void ws_pae_supp_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e type, kmp_addr_t *addr)
01111 {
01112     (void) addr;
01113     (void) type;
01114 
01115     // For now, accept every KMP-CREATE.indication
01116     kmp_api_create_response(kmp, KMP_RESULT_OK);
01117 }
01118 
01119 static void ws_pae_supp_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys)
01120 {
01121     kmp_service_t *service = kmp_api_service_get(kmp);
01122     pae_supp_t *pae_supp = ws_pae_supp_by_kmp_service_get(service);
01123     if (!pae_supp) {
01124         return;
01125     }
01126 
01127     kmp_type_e type = kmp_api_type_get(kmp);
01128 
01129     // Whenever EAP-TLS, 4WH or GKH completes increase timer for wait for authentication
01130     if (type < IEEE_802_1X_INITIAL_KEY && result == KMP_RESULT_OK) {
01131         ws_pae_lib_supp_timer_ticks_set(&pae_supp->entry, WAIT_FOR_AUTHENTICATION_TICKS);
01132     }
01133 
01134     /* When 4WH or GKH completes inserts keys and indicates authentication completed
01135        (if not alredy indicated) */
01136     if ((type == IEEE_802_11_4WH || type == IEEE_802_11_GKH) && result == KMP_RESULT_OK) {
01137         if (sec_keys) {
01138             sec_prot_keys_t *keys = sec_keys;
01139             pae_supp->nw_key_insert(pae_supp->interface_ptr, keys->gtks);
01140         }
01141 
01142         ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_OK);
01143     }
01144 
01145     /* If initial EAPOL-key message sending fails to tx no acknowledge, indicates failure so
01146        that bootstrap can decide if EAPOL target should be changed */
01147     else if (type > IEEE_802_1X_INITIAL_KEY && result == KMP_RESULT_ERR_TX_NO_ACK) {
01148         tr_info("Initial EAPOL-Key TX failure, target: %s", trace_array(kmp_address_eui_64_get(&pae_supp->entry.addr), 8));
01149         ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_TX_NO_ACK);
01150     }
01151 
01152 }
01153 
01154 static void ws_pae_supp_kmp_api_finished(kmp_api_t *kmp)
01155 {
01156     kmp_service_t *service = kmp_api_service_get(kmp);
01157     pae_supp_t *pae_supp = ws_pae_supp_by_kmp_service_get(service);
01158     if (!pae_supp) {
01159         return;
01160     }
01161 
01162     // Delete KMP
01163     ws_pae_lib_kmp_list_delete(&pae_supp->entry.kmp_list, kmp);
01164 }
01165 
01166 static kmp_api_t *ws_pae_supp_kmp_tx_status_ind(kmp_service_t *service, uint8_t instance_id)
01167 {
01168     pae_supp_t *pae_supp = ws_pae_supp_by_kmp_service_get(service);
01169     if (!pae_supp) {
01170         return NULL;
01171     }
01172 
01173     kmp_api_t *kmp = ws_pae_lib_kmp_list_instance_id_get(&pae_supp->entry.kmp_list, instance_id);
01174     if (!kmp) {
01175         return NULL;
01176     }
01177 
01178     return kmp;
01179 }
01180 
01181 #endif /* HAVE_PAE_SUPP */
01182 #endif /* HAVE_WS */
01183