Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
ws_pae_auth.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 "6LoWPAN/ws/ws_config.h" 00032 #include "Security/kmp/kmp_addr.h" 00033 #include "Security/kmp/kmp_api.h" 00034 #include "Security/kmp/kmp_socket_if.h" 00035 #include "Security/protocols/sec_prot_certs.h" 00036 #include "Security/protocols/sec_prot_keys.h" 00037 #include "Security/protocols/key_sec_prot/key_sec_prot.h" 00038 #include "Security/protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.h" 00039 #include "Security/protocols/tls_sec_prot/tls_sec_prot.h" 00040 #include "Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.h" 00041 #include "Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.h" 00042 #include "6LoWPAN/ws/ws_pae_controller.h" 00043 #include "6LoWPAN/ws/ws_pae_timers.h" 00044 #include "6LoWPAN/ws/ws_pae_auth.h" 00045 #include "6LoWPAN/ws/ws_pae_lib.h" 00046 00047 #ifdef HAVE_WS 00048 #ifdef HAVE_PAE_AUTH 00049 00050 #define TRACE_GROUP "wspa" 00051 00052 #define PAE_TASKLET_INIT 1 00053 #define PAE_TASKLET_EVENT 2 00054 #define PAE_TASKLET_TIMER 3 00055 00056 // Wait for for supplicant to indicate activity (e.g. to send a message) 00057 #define WAIT_FOR_AUTHENTICATION_TICKS 5 * 60 * 10 // 5 minutes 00058 00059 // Maximum number of simultaneous EAP-TLS negotiations 00060 #define MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS 3 00061 00062 /* If EAP-TLS is delayed due to simultaneous negotiations limit, defines how 00063 long to wait for previous negotiation to complete */ 00064 #define EAP_TLS_NEGOTIATION_TRIGGER_TIMEOUT 60 * 10 // 60 seconds 00065 00066 // Default for maximum number of supplicants 00067 #define SUPPLICANT_MAX_NUMBER 1000 00068 00069 /* Default for number of supplicants to purge per garbage collect call from 00070 nanostack monitor */ 00071 #define SUPPLICANT_NUMBER_TO_PURGE 5 00072 00073 typedef struct { 00074 ns_list_link_t link; /**< Link */ 00075 kmp_service_t *kmp_service; /**< KMP service */ 00076 protocol_interface_info_entry_t *interface_ptr; /**< Interface pointer */ 00077 ws_pae_auth_gtk_hash_set *hash_set; /**< GTK hash set callback */ 00078 ws_pae_auth_nw_key_insert *nw_key_insert; /**< Key insert callback */ 00079 ws_pae_auth_nw_key_index_set *nw_key_index_set; /**< Key index set callback */ 00080 supp_list_t active_supp_list; /**< List of active supplicants */ 00081 supp_list_t inactive_supp_list; /**< List of inactive supplicants */ 00082 arm_event_storage_t *timer; /**< Timer */ 00083 sec_prot_gtk_keys_t *gtks; /**< GTKs */ 00084 sec_prot_gtk_keys_t *next_gtks; /**< Next GTKs */ 00085 const sec_prot_certs_t *certs; /**< Certificates */ 00086 timer_settings_t *timer_settings; /**< Timer settings */ 00087 uint16_t supp_max_number; /**< Max number of stored supplicants */ 00088 uint16_t slow_timer_seconds; /**< Slow timer seconds */ 00089 bool timer_running : 1; /**< Timer is running */ 00090 bool gtk_new_inst_req_exp : 1; /**< GTK new install required timer expired */ 00091 bool gtk_new_act_time_exp: 1; /**< GTK new activation time expired */ 00092 } pae_auth_t; 00093 00094 static int8_t ws_pae_auth_network_keys_from_gtks_set(pae_auth_t *pae_auth); 00095 static int8_t ws_pae_auth_active_gtk_set(pae_auth_t *pae_auth, uint8_t index); 00096 static int8_t ws_pae_auth_network_key_index_set(pae_auth_t *pae_auth, uint8_t index); 00097 static void ws_pae_auth_free(pae_auth_t *pae_auth); 00098 static pae_auth_t *ws_pae_auth_get(protocol_interface_info_entry_t *interface_ptr); 00099 static pae_auth_t *ws_pae_auth_by_kmp_service_get(kmp_service_t *service); 00100 static int8_t ws_pae_auth_event_send(kmp_service_t *service, void *data); 00101 static void ws_pae_auth_tasklet_handler(arm_event_s *event); 00102 static void ws_pae_auth_gtk_key_insert(pae_auth_t *pae_auth); 00103 static int8_t ws_pae_auth_new_gtk_activate(pae_auth_t *pae_auth); 00104 static int8_t ws_pae_auth_timer_if_start(kmp_service_t *service, kmp_api_t *kmp); 00105 static int8_t ws_pae_auth_timer_if_stop(kmp_service_t *service, kmp_api_t *kmp); 00106 static int8_t ws_pae_auth_timer_start(pae_auth_t *pae_auth); 00107 static int8_t ws_pae_auth_timer_stop(pae_auth_t *pae_auth); 00108 static bool ws_pae_auth_timer_running(pae_auth_t *pae_auth); 00109 static void ws_pae_auth_kmp_service_addr_get(kmp_service_t *service, kmp_api_t *kmp, kmp_addr_t *local_addr, kmp_addr_t *remote_addr); 00110 static kmp_api_t *ws_pae_auth_kmp_service_api_get(kmp_service_t *service, kmp_api_t *kmp, kmp_type_e type); 00111 static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, kmp_type_e type, const kmp_addr_t *addr); 00112 static void ws_pae_auth_kmp_api_create_confirm(kmp_api_t *kmp, kmp_result_e result); 00113 static void ws_pae_auth_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e type, kmp_addr_t *addr); 00114 static void ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys); 00115 static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *supp_entry); 00116 static kmp_type_e ws_pae_auth_next_protocol_get(supp_entry_t *supp_entry); 00117 static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, supp_entry_t *supp_entry); 00118 static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp); 00119 00120 static int8_t tasklet_id = -1; 00121 static NS_LIST_DEFINE(pae_auth_list, pae_auth_t, link); 00122 00123 int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, timer_settings_t *timer_settings) 00124 { 00125 if (!interface_ptr || !gtks || !certs) { 00126 return -1; 00127 } 00128 00129 if (ws_pae_auth_get(interface_ptr) != NULL) { 00130 return 0; 00131 } 00132 00133 pae_auth_t *pae_auth = ns_dyn_mem_alloc(sizeof(pae_auth_t)); 00134 if (!pae_auth) { 00135 return -1; 00136 } 00137 00138 pae_auth->interface_ptr = interface_ptr; 00139 ws_pae_lib_supp_list_init(&pae_auth->active_supp_list); 00140 ws_pae_lib_supp_list_init(&pae_auth->inactive_supp_list); 00141 pae_auth->timer = NULL; 00142 00143 pae_auth->hash_set = NULL; 00144 pae_auth->nw_key_insert = NULL; 00145 pae_auth->nw_key_index_set = NULL; 00146 00147 pae_auth->gtks = gtks; 00148 pae_auth->next_gtks = next_gtks; 00149 pae_auth->certs = certs; 00150 pae_auth->timer_settings = timer_settings; 00151 pae_auth->supp_max_number = SUPPLICANT_MAX_NUMBER; 00152 00153 pae_auth->slow_timer_seconds = 0; 00154 pae_auth->gtk_new_inst_req_exp = false; 00155 pae_auth->gtk_new_act_time_exp = false; 00156 00157 pae_auth->kmp_service = kmp_service_create(); 00158 if (!pae_auth->kmp_service) { 00159 goto error; 00160 } 00161 00162 if (kmp_service_cb_register(pae_auth->kmp_service, ws_pae_auth_kmp_incoming_ind, NULL, ws_pae_auth_kmp_service_addr_get, ws_pae_auth_kmp_service_api_get)) { 00163 goto error; 00164 } 00165 00166 if (kmp_service_event_if_register(pae_auth->kmp_service, ws_pae_auth_event_send)) { 00167 goto error; 00168 } 00169 00170 if (kmp_service_timer_if_register(pae_auth->kmp_service, ws_pae_auth_timer_if_start, ws_pae_auth_timer_if_stop)) { 00171 goto error; 00172 } 00173 00174 if (auth_key_sec_prot_register(pae_auth->kmp_service) < 0) { 00175 goto error; 00176 } 00177 00178 if (auth_eap_tls_sec_prot_register(pae_auth->kmp_service) < 0) { 00179 goto error; 00180 } 00181 00182 if (server_tls_sec_prot_register(pae_auth->kmp_service) < 0) { 00183 goto error; 00184 } 00185 00186 if (auth_fwh_sec_prot_register(pae_auth->kmp_service) < 0) { 00187 goto error; 00188 } 00189 00190 if (auth_gkh_sec_prot_register(pae_auth->kmp_service) < 0) { 00191 goto error; 00192 } 00193 00194 if (tasklet_id < 0) { 00195 tasklet_id = eventOS_event_handler_create(ws_pae_auth_tasklet_handler, PAE_TASKLET_INIT); 00196 if (tasklet_id < 0) { 00197 goto error; 00198 } 00199 } 00200 00201 if (ws_pae_auth_timer_stop(pae_auth) < 0) { 00202 goto error; 00203 } 00204 00205 ns_list_add_to_end(&pae_auth_list, pae_auth); 00206 00207 return 0; 00208 00209 error: 00210 ws_pae_auth_free(pae_auth); 00211 00212 return -1; 00213 } 00214 00215 int8_t ws_pae_auth_timing_adjust(uint8_t timing) 00216 { 00217 auth_gkh_sec_prot_timing_adjust(timing); 00218 auth_fwh_sec_prot_timing_adjust(timing); 00219 auth_eap_tls_sec_prot_timing_adjust(timing); 00220 return 0; 00221 } 00222 00223 int8_t ws_pae_auth_addresses_set(protocol_interface_info_entry_t *interface_ptr, uint16_t local_port, const uint8_t *remote_addr, uint16_t remote_port) 00224 { 00225 if (!interface_ptr || !remote_addr) { 00226 return -1; 00227 } 00228 00229 pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr); 00230 if (!pae_auth) { 00231 return -1; 00232 } 00233 if (!pae_auth->kmp_service) { 00234 return -1; 00235 } 00236 00237 if (kmp_socket_if_register(pae_auth->kmp_service, local_port, remote_addr, remote_port) < 0) { 00238 return -1; 00239 } 00240 00241 return 0; 00242 } 00243 00244 int8_t ws_pae_auth_delete(protocol_interface_info_entry_t *interface_ptr) 00245 { 00246 if (!interface_ptr) { 00247 return -1; 00248 } 00249 00250 pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr); 00251 if (!pae_auth) { 00252 return -1; 00253 } 00254 00255 ws_pae_auth_free(pae_auth); 00256 return 0; 00257 } 00258 00259 void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set) 00260 { 00261 if (!interface_ptr) { 00262 return; 00263 } 00264 00265 pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr); 00266 if (!pae_auth) { 00267 return; 00268 } 00269 00270 pae_auth->hash_set = hash_set; 00271 pae_auth->nw_key_insert = nw_key_insert; 00272 pae_auth->nw_key_index_set = nw_key_index_set; 00273 } 00274 00275 void ws_pae_auth_start(protocol_interface_info_entry_t *interface_ptr) 00276 { 00277 if (!interface_ptr) { 00278 return; 00279 } 00280 00281 pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr); 00282 if (!pae_auth) { 00283 return; 00284 } 00285 00286 // Checks if there is predefined active key 00287 int8_t index = sec_prot_keys_gtk_status_active_get(pae_auth->gtks); 00288 if (index < 0) { 00289 // If there is no key, inserts a new one 00290 ws_pae_auth_gtk_key_insert(pae_auth); 00291 index = sec_prot_keys_gtk_install_order_first_index_get(pae_auth->gtks); 00292 ws_pae_auth_active_gtk_set(pae_auth, index); 00293 } else { 00294 ws_pae_auth_active_gtk_set(pae_auth, index); 00295 } 00296 00297 // Inserts keys and updates GTK hash on stack 00298 ws_pae_auth_network_keys_from_gtks_set(pae_auth); 00299 00300 // Sets active key index 00301 ws_pae_auth_network_key_index_set(pae_auth, index); 00302 } 00303 00304 void ws_pae_auth_gtks_updated(protocol_interface_info_entry_t *interface_ptr) 00305 { 00306 if (!interface_ptr) { 00307 return; 00308 } 00309 00310 pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr); 00311 if (!pae_auth) { 00312 return; 00313 } 00314 00315 ws_pae_auth_network_keys_from_gtks_set(pae_auth); 00316 } 00317 00318 int8_t ws_pae_auth_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index) 00319 { 00320 if (!interface_ptr) { 00321 return -1; 00322 } 00323 00324 pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr); 00325 if (!pae_auth) { 00326 return -1; 00327 } 00328 00329 ws_pae_auth_active_gtk_set(pae_auth, index); 00330 ws_pae_auth_network_key_index_set(pae_auth, index); 00331 return 0; 00332 } 00333 00334 int8_t ws_pae_auth_node_keys_remove(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64) 00335 { 00336 if (!interface_ptr) { 00337 return -1; 00338 } 00339 00340 pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr); 00341 if (!pae_auth) { 00342 return -1; 00343 } 00344 00345 // Checks if supplicant is active 00346 supp_entry_t *supp = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->active_supp_list, eui_64); 00347 00348 if (supp) { 00349 // Deletes keys and marks as revoked 00350 sec_prot_keys_pmk_delete(&supp->sec_keys); 00351 sec_prot_keys_ptk_delete(&supp->sec_keys); 00352 supp->access_revoked = true; 00353 tr_info("Access revoked; keys removed, eui-64: %s", trace_array(supp->addr.eui_64, 8)); 00354 return 0; 00355 } 00356 00357 // Checks if supplicant is inactive 00358 supp = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->inactive_supp_list, eui_64); 00359 if (supp) { 00360 // Deletes supplicant 00361 tr_info("Access revoked; deleted, eui-64: %s", trace_array(supp->addr.eui_64, 8)); 00362 ws_pae_lib_supp_list_remove(&pae_auth->inactive_supp_list, supp); 00363 return 0; 00364 } 00365 00366 return -1; 00367 } 00368 00369 int8_t ws_pae_auth_node_access_revoke_start(protocol_interface_info_entry_t *interface_ptr) 00370 { 00371 if (!interface_ptr) { 00372 return -1; 00373 } 00374 00375 pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr); 00376 if (!pae_auth) { 00377 return -1; 00378 } 00379 00380 // Gets active GTK 00381 int8_t active_index = sec_prot_keys_gtk_status_active_get(pae_auth->gtks); 00382 00383 if (active_index >= 0) { 00384 // As default removes other keys than active 00385 int8_t not_removed_index = active_index; 00386 00387 uint32_t revocation_lifetime = ws_pae_timers_gtk_revocation_lifetime_get(pae_auth->timer_settings); 00388 00389 uint32_t active_lifetime = sec_prot_keys_gtk_lifetime_get(pae_auth->gtks, active_index); 00390 00391 // If active GTK lifetime is larger than revocation lifetime decrements active GTK lifetime 00392 if (active_lifetime > revocation_lifetime) { 00393 sec_prot_keys_gtk_lifetime_decrement(pae_auth->gtks, active_index, active_lifetime - revocation_lifetime); 00394 tr_info("Access revocation start, GTK active index: %i, revoked lifetime: %"PRIu32"", active_index, revocation_lifetime); 00395 } else { 00396 // Otherwise decrements lifetime of the GTK to be installed after the active one 00397 int8_t second_index = sec_prot_keys_gtk_install_order_second_index_get(pae_auth->gtks); 00398 if (second_index >= 0) { 00399 // Second GTK revocation lifetime is the active GTK lifetime added with revocation time 00400 uint32_t second_revocation_lifetime = active_lifetime + revocation_lifetime; 00401 00402 uint32_t second_lifetime = sec_prot_keys_gtk_lifetime_get(pae_auth->gtks, second_index); 00403 if (second_lifetime > second_revocation_lifetime) { 00404 sec_prot_keys_gtk_lifetime_decrement(pae_auth->gtks, second_index, second_lifetime - second_revocation_lifetime); 00405 tr_info("Access revocation start, GTK second active index: %i, revoked lifetime: %"PRIu32"", second_index, second_revocation_lifetime); 00406 } 00407 // Removes other keys than active and GTK to be installed next 00408 not_removed_index = second_index; 00409 } 00410 } 00411 00412 // Deletes other GTKs 00413 int8_t last_index = sec_prot_keys_gtk_install_order_last_index_get(pae_auth->gtks); 00414 while (last_index >= 0 && last_index != not_removed_index) { 00415 tr_info("Access revocation GTK clear index: %i", last_index); 00416 sec_prot_keys_gtk_clear(pae_auth->gtks, last_index); 00417 last_index = sec_prot_keys_gtk_install_order_last_index_get(pae_auth->gtks); 00418 } 00419 } 00420 00421 // Adds new GTK 00422 ws_pae_auth_gtk_key_insert(pae_auth); 00423 ws_pae_auth_network_keys_from_gtks_set(pae_auth); 00424 00425 return 0; 00426 } 00427 00428 int8_t ws_pae_auth_node_limit_set(protocol_interface_info_entry_t *interface_ptr, uint16_t limit) 00429 { 00430 if (!interface_ptr) { 00431 return -1; 00432 } 00433 00434 pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr); 00435 if (!pae_auth) { 00436 return -1; 00437 } 00438 00439 pae_auth->supp_max_number = limit; 00440 00441 return 0; 00442 } 00443 00444 void ws_pae_auth_forced_gc(protocol_interface_info_entry_t *interface_ptr) 00445 { 00446 if (!interface_ptr) { 00447 return; 00448 } 00449 00450 pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr); 00451 if (!pae_auth) { 00452 return; 00453 } 00454 00455 /* Purge in maximum five entries from supplicant list (starting from oldest one) 00456 per call to the function (called by nanostack monitor) */ 00457 ws_pae_lib_supp_list_purge(&pae_auth->active_supp_list, &pae_auth->inactive_supp_list, 0, SUPPLICANT_NUMBER_TO_PURGE); 00458 } 00459 00460 static int8_t ws_pae_auth_network_keys_from_gtks_set(pae_auth_t *pae_auth) 00461 { 00462 // Authenticator keys are always fresh 00463 sec_prot_keys_gtk_status_all_fresh_set(pae_auth->gtks); 00464 00465 if (pae_auth->hash_set) { 00466 uint8_t gtk_hash[32]; 00467 sec_prot_keys_gtks_hash_generate(pae_auth->gtks, gtk_hash); 00468 pae_auth->hash_set(pae_auth->interface_ptr, gtk_hash); 00469 } 00470 00471 if (pae_auth->nw_key_insert) { 00472 pae_auth->nw_key_insert(pae_auth->interface_ptr, pae_auth->gtks); 00473 } 00474 00475 return 0; 00476 } 00477 00478 static int8_t ws_pae_auth_active_gtk_set(pae_auth_t *pae_auth, uint8_t index) 00479 { 00480 return sec_prot_keys_gtk_status_active_set(pae_auth->gtks, index); 00481 } 00482 00483 static int8_t ws_pae_auth_gtk_clear(pae_auth_t *pae_auth, uint8_t index) 00484 { 00485 return sec_prot_keys_gtk_clear(pae_auth->gtks, index); 00486 } 00487 00488 static int8_t ws_pae_auth_network_key_index_set(pae_auth_t *pae_auth, uint8_t index) 00489 { 00490 if (pae_auth->nw_key_index_set) { 00491 pae_auth->nw_key_index_set(pae_auth->interface_ptr, index); 00492 } 00493 00494 return 0; 00495 } 00496 00497 static void ws_pae_auth_free(pae_auth_t *pae_auth) 00498 { 00499 if (!pae_auth) { 00500 return; 00501 } 00502 00503 ws_pae_lib_supp_list_delete(&pae_auth->active_supp_list); 00504 ws_pae_lib_supp_list_delete(&pae_auth->inactive_supp_list); 00505 00506 kmp_socket_if_unregister(pae_auth->kmp_service); 00507 00508 kmp_service_delete(pae_auth->kmp_service); 00509 00510 ns_list_remove(&pae_auth_list, pae_auth); 00511 ns_dyn_mem_free(pae_auth); 00512 } 00513 00514 static pae_auth_t *ws_pae_auth_get(protocol_interface_info_entry_t *interface_ptr) 00515 { 00516 ns_list_foreach(pae_auth_t, entry, &pae_auth_list) { 00517 if (entry->interface_ptr == interface_ptr) { 00518 return entry; 00519 } 00520 } 00521 00522 return NULL; 00523 } 00524 00525 static pae_auth_t *ws_pae_auth_by_kmp_service_get(kmp_service_t *service) 00526 { 00527 ns_list_foreach(pae_auth_t, entry, &pae_auth_list) { 00528 if (entry->kmp_service == service) { 00529 return entry; 00530 } 00531 } 00532 00533 return NULL; 00534 } 00535 00536 static int8_t ws_pae_auth_event_send(kmp_service_t *service, void *data) 00537 { 00538 pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service); 00539 if (!pae_auth) { 00540 return -1; 00541 } 00542 00543 arm_event_s event = { 00544 .receiver = tasklet_id, 00545 .sender = 0, 00546 .event_id = pae_auth->interface_ptr->id, 00547 .data_ptr = data, 00548 .event_type = PAE_TASKLET_EVENT, 00549 .priority = ARM_LIB_LOW_PRIORITY_EVENT, 00550 }; 00551 00552 if (eventOS_event_send(&event) != 0) { 00553 return -1; 00554 } 00555 00556 return 0; 00557 } 00558 00559 static void ws_pae_auth_tasklet_handler(arm_event_s *event) 00560 { 00561 if (event->event_type == PAE_TASKLET_INIT) { 00562 00563 } else if (event->event_type == PAE_TASKLET_EVENT) { 00564 pae_auth_t *pae_auth = NULL; 00565 00566 ns_list_foreach(pae_auth_t, entry, &pae_auth_list) { 00567 if (entry->interface_ptr->id == event->event_id) { 00568 pae_auth = entry; 00569 break; 00570 } 00571 } 00572 00573 if (pae_auth) { 00574 kmp_service_event_if_event(pae_auth->kmp_service, event->data_ptr); 00575 } 00576 } 00577 } 00578 00579 void ws_pae_auth_fast_timer(uint16_t ticks) 00580 { 00581 ns_list_foreach(pae_auth_t, pae_auth, &pae_auth_list) { 00582 if (!ws_pae_auth_timer_running(pae_auth)) { 00583 continue; 00584 } 00585 00586 // Updates KMP timers 00587 bool running = ws_pae_lib_supp_list_timer_update(&pae_auth->active_supp_list, &pae_auth->inactive_supp_list, ticks, kmp_service_timer_if_timeout); 00588 if (!running) { 00589 ws_pae_auth_timer_stop(pae_auth); 00590 } 00591 } 00592 } 00593 00594 void ws_pae_auth_slow_timer(uint16_t seconds) 00595 { 00596 ns_list_foreach(pae_auth_t, pae_auth, &pae_auth_list) { 00597 00598 // Gets index of currently active GTK 00599 int8_t active_index = sec_prot_keys_gtk_status_active_get(pae_auth->gtks); 00600 00601 for (uint8_t i = 0; i < GTK_NUM; i++) { 00602 if (!sec_prot_keys_gtk_is_set(pae_auth->gtks, i)) { 00603 continue; 00604 } 00605 uint32_t timer_seconds = sec_prot_keys_gtk_lifetime_decrement(pae_auth->gtks, i, seconds); 00606 if (active_index == i) { 00607 if (!pae_auth->gtk_new_inst_req_exp) { 00608 pae_auth->gtk_new_inst_req_exp = ws_pae_timers_gtk_new_install_required(pae_auth->timer_settings, timer_seconds); 00609 if (pae_auth->gtk_new_inst_req_exp) { 00610 int8_t second_index = sec_prot_keys_gtk_install_order_second_index_get(pae_auth->gtks); 00611 if (second_index < 0) { 00612 tr_info("GTK new install required active index: %i, time: %"PRIu32", system time: %"PRIu32"", active_index, timer_seconds, protocol_core_monotonic_time / 10); 00613 ws_pae_auth_gtk_key_insert(pae_auth); 00614 ws_pae_auth_network_keys_from_gtks_set(pae_auth); 00615 } else { 00616 tr_info("GTK new install already done; second index: %i, time: %"PRIu32", system time: %"PRIu32"", second_index, timer_seconds, protocol_core_monotonic_time / 10); 00617 } 00618 } 00619 } 00620 00621 if (!pae_auth->gtk_new_act_time_exp) { 00622 pae_auth->gtk_new_act_time_exp = ws_pae_timers_gtk_new_activation_time(pae_auth->timer_settings, timer_seconds); 00623 if (pae_auth->gtk_new_act_time_exp) { 00624 int8_t new_active_index = ws_pae_auth_new_gtk_activate(pae_auth); 00625 tr_info("GTK new activation time active index: %i, time: %"PRIu32", new index: %i, system time: %"PRIu32"", active_index, timer_seconds, new_active_index, protocol_core_monotonic_time / 10); 00626 if (new_active_index >= 0) { 00627 ws_pae_auth_network_key_index_set(pae_auth, new_active_index); 00628 } 00629 pae_auth->gtk_new_inst_req_exp = false; 00630 pae_auth->gtk_new_act_time_exp = false; 00631 } 00632 } 00633 } 00634 00635 if (timer_seconds == 0) { 00636 tr_info("GTK expired index: %i, system time: %"PRIu32"", i, protocol_core_monotonic_time / 10); 00637 ws_pae_auth_gtk_clear(pae_auth, i); 00638 ws_pae_auth_network_keys_from_gtks_set(pae_auth); 00639 } 00640 } 00641 00642 pae_auth->slow_timer_seconds += seconds; 00643 if (pae_auth->slow_timer_seconds > 60) { 00644 ws_pae_lib_supp_list_slow_timer_update(&pae_auth->active_supp_list, pae_auth->timer_settings, pae_auth->slow_timer_seconds); 00645 ws_pae_lib_supp_list_slow_timer_update(&pae_auth->inactive_supp_list, pae_auth->timer_settings, pae_auth->slow_timer_seconds); 00646 pae_auth->slow_timer_seconds = 0; 00647 } 00648 } 00649 } 00650 00651 static void ws_pae_auth_gtk_key_insert(pae_auth_t *pae_auth) 00652 { 00653 // Gets index to install the key 00654 uint8_t install_index = sec_prot_keys_gtk_install_index_get(pae_auth->gtks); 00655 00656 // Key to install 00657 uint8_t gtk_value[GTK_LEN]; 00658 00659 // Checks if next GTK values are set and gets first GTK to install 00660 int8_t next_gtk_index = sec_prot_keys_gtk_install_order_first_index_get(pae_auth->next_gtks); 00661 if (next_gtk_index >= 0) { 00662 // Gets GTK value 00663 uint8_t *gtk = sec_prot_keys_gtk_get(pae_auth->next_gtks, next_gtk_index); 00664 memcpy(gtk_value, gtk, GTK_LEN); 00665 // Sets same key back to next GTKs but as the last key to be installed 00666 sec_prot_keys_gtk_clear(pae_auth->next_gtks, next_gtk_index); 00667 sec_prot_keys_gtk_set(pae_auth->next_gtks, next_gtk_index, gtk_value, 0); 00668 } else { 00669 randLIB_get_n_bytes_random(gtk_value, GTK_LEN); 00670 } 00671 00672 // Gets latest installed key lifetime and adds GTK expire offset to it 00673 uint32_t lifetime = pae_auth->timer_settings->gtk_expire_offset; 00674 int8_t last_index = sec_prot_keys_gtk_install_order_last_index_get(pae_auth->gtks); 00675 if (last_index >= 0) { 00676 lifetime += sec_prot_keys_gtk_lifetime_get(pae_auth->gtks, last_index); 00677 } 00678 00679 // Installs the new key 00680 sec_prot_keys_gtk_clear(pae_auth->gtks, install_index); 00681 sec_prot_keys_gtk_set(pae_auth->gtks, install_index, gtk_value, lifetime); 00682 00683 // Authenticator keys are always fresh 00684 sec_prot_keys_gtk_status_all_fresh_set(pae_auth->gtks); 00685 00686 tr_info("GTK install new index: %i, lifetime: %"PRIu32" system time: %"PRIu32"", install_index, lifetime, protocol_core_monotonic_time / 10); 00687 } 00688 00689 static int8_t ws_pae_auth_new_gtk_activate(pae_auth_t *pae_auth) 00690 { 00691 int8_t new_active_index = sec_prot_keys_gtk_install_order_second_index_get(pae_auth->gtks); 00692 if (new_active_index >= 0) { 00693 ws_pae_auth_active_gtk_set(pae_auth, new_active_index); 00694 } 00695 00696 return new_active_index; 00697 } 00698 00699 static int8_t ws_pae_auth_timer_if_start(kmp_service_t *service, kmp_api_t *kmp) 00700 { 00701 pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service); 00702 if (!pae_auth) { 00703 return -1; 00704 } 00705 00706 if (ws_pae_auth_timer_start(pae_auth) < 0) { 00707 return -1; 00708 } 00709 00710 supp_entry_t *supp_entry = kmp_api_data_get(kmp); 00711 if (!supp_entry) { 00712 return -1; 00713 } 00714 00715 kmp_entry_t *entry = ws_pae_lib_kmp_list_entry_get(&supp_entry->kmp_list, kmp); 00716 if (!entry) { 00717 return -1; 00718 } 00719 00720 ws_pae_lib_supp_list_to_active(&pae_auth->active_supp_list, &pae_auth->inactive_supp_list, supp_entry); 00721 00722 ws_pae_lib_kmp_timer_start(&supp_entry->kmp_list, entry); 00723 return 0; 00724 } 00725 00726 static int8_t ws_pae_auth_timer_if_stop(kmp_service_t *service, kmp_api_t *kmp) 00727 { 00728 (void) service; 00729 00730 supp_entry_t *supp_entry = kmp_api_data_get(kmp); 00731 00732 kmp_entry_t *entry = ws_pae_lib_kmp_list_entry_get(&supp_entry->kmp_list, kmp); 00733 if (!entry) { 00734 return -1; 00735 } 00736 00737 ws_pae_lib_kmp_timer_stop(&supp_entry->kmp_list, entry); 00738 return 0; 00739 } 00740 00741 static int8_t ws_pae_auth_timer_start(pae_auth_t *pae_auth) 00742 { 00743 pae_auth->timer_running = true; 00744 return 0; 00745 } 00746 00747 static int8_t ws_pae_auth_timer_stop(pae_auth_t *pae_auth) 00748 { 00749 pae_auth->timer_running = false; 00750 return 0; 00751 } 00752 00753 static bool ws_pae_auth_timer_running(pae_auth_t *pae_auth) 00754 { 00755 return pae_auth->timer_running; 00756 } 00757 00758 static void ws_pae_auth_kmp_service_addr_get(kmp_service_t *service, kmp_api_t *kmp, kmp_addr_t *local_addr, kmp_addr_t *remote_addr) 00759 { 00760 pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service); 00761 if (!pae_auth) { 00762 return; 00763 } 00764 00765 // Get own EUI-64 00766 link_layer_address_s mac_params; 00767 if (arm_nwk_mac_address_read(pae_auth->interface_ptr->id, &mac_params) >= 0) { 00768 kmp_address_eui_64_set(local_addr, mac_params.mac_long); 00769 } 00770 00771 // Get supplicant address 00772 supp_entry_t *entry = kmp_api_data_get(kmp); 00773 if (entry) { 00774 kmp_address_copy(remote_addr, &entry->addr); 00775 } 00776 } 00777 00778 static kmp_api_t *ws_pae_auth_kmp_service_api_get(kmp_service_t *service, kmp_api_t *kmp, kmp_type_e type) 00779 { 00780 (void) service; 00781 00782 supp_entry_t *supp_entry = kmp_api_data_get(kmp); 00783 if (!supp_entry) { 00784 return NULL; 00785 } 00786 00787 return ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, type); 00788 } 00789 00790 static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, kmp_type_e type, const kmp_addr_t *addr) 00791 { 00792 pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service); 00793 if (!pae_auth) { 00794 return NULL; 00795 } 00796 00797 // Find supplicant from list of active supplicants 00798 supp_entry_t *supp_entry = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->active_supp_list, kmp_address_eui_64_get(addr)); 00799 00800 if (!supp_entry) { 00801 // Find supplicant from list of inactive supplicants 00802 supp_entry = ws_pae_lib_supp_list_entry_eui_64_get(&pae_auth->inactive_supp_list, kmp_address_eui_64_get(addr)); 00803 if (supp_entry) { 00804 // Move supplicant to active list 00805 ws_pae_lib_supp_list_to_active(&pae_auth->active_supp_list, &pae_auth->inactive_supp_list, supp_entry); 00806 } 00807 } 00808 00809 // If does not exists add it to list 00810 if (!supp_entry) { 00811 // Checks if maximum number of supplicants is reached and purge supplicant list (starting from oldest one) 00812 ws_pae_lib_supp_list_purge(&pae_auth->active_supp_list, &pae_auth->inactive_supp_list, pae_auth->supp_max_number, 0); 00813 00814 supp_entry = ws_pae_lib_supp_list_add(&pae_auth->active_supp_list, addr); 00815 if (!supp_entry) { 00816 return 0; 00817 } 00818 sec_prot_keys_init(&supp_entry->sec_keys, pae_auth->gtks, pae_auth->certs); 00819 // Fixes the address of the supplicant to keys 00820 sec_prot_keys_ptk_eui_64_write(&supp_entry->sec_keys, kmp_address_eui_64_get(addr)); 00821 } else { 00822 // Updates relay address 00823 kmp_address_copy(&supp_entry->addr, addr); 00824 } 00825 00826 // Increases waiting time for supplicant authentication 00827 ws_pae_lib_supp_timer_ticks_set(supp_entry, WAIT_FOR_AUTHENTICATION_TICKS); 00828 00829 // Get KMP for supplicant 00830 kmp_api_t *kmp = ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, type); 00831 if (kmp) { 00832 return kmp; 00833 } 00834 00835 // Create a new KMP for initial eapol-key 00836 kmp = kmp_api_create(service, type + IEEE_802_1X_INITIAL_KEY); 00837 00838 if (!kmp) { 00839 return 0; 00840 } 00841 00842 kmp_api_data_set(kmp, supp_entry); 00843 // Sets address to KMP 00844 kmp_api_addr_set(kmp, &supp_entry->addr); 00845 00846 // Sets security keys to KMP 00847 kmp_api_sec_keys_set(kmp, &supp_entry->sec_keys); 00848 00849 if (ws_pae_lib_kmp_list_add(&supp_entry->kmp_list, kmp) == NULL) { 00850 kmp_api_delete(kmp); 00851 return 0; 00852 } 00853 00854 kmp_api_cb_register(kmp, 00855 ws_pae_auth_kmp_api_create_confirm, 00856 ws_pae_auth_kmp_api_create_indication, 00857 ws_pae_auth_kmp_api_finished_indication, 00858 ws_pae_auth_kmp_api_finished); 00859 00860 if (kmp_api_start(kmp) < 0) { 00861 ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, kmp); 00862 return 0; 00863 } 00864 00865 return kmp; 00866 } 00867 00868 static void ws_pae_auth_kmp_api_create_confirm(kmp_api_t *kmp, kmp_result_e result) 00869 { 00870 (void) kmp; 00871 (void) result; 00872 // If KMP-CREATE.request has failed, authentication error, just stop for now 00873 } 00874 00875 static void ws_pae_auth_kmp_api_create_indication(kmp_api_t *kmp, kmp_type_e type, kmp_addr_t *addr) 00876 { 00877 (void) type; 00878 (void) addr; 00879 // For now, accept every KMP-CREATE.indication 00880 kmp_api_create_response(kmp, KMP_RESULT_OK); 00881 } 00882 00883 static void ws_pae_auth_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e result, kmp_sec_keys_t *sec_keys) 00884 { 00885 (void) sec_keys; 00886 00887 // For now, just ignore if not ok 00888 if (result != KMP_RESULT_OK) { 00889 return; 00890 } 00891 00892 supp_entry_t *supp_entry = kmp_api_data_get(kmp); 00893 if (!supp_entry) { 00894 // Should not be possible 00895 return; 00896 } 00897 kmp_service_t *service = kmp_api_service_get(kmp); 00898 pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service); 00899 if (!pae_auth) { 00900 // Should not be possible 00901 return; 00902 } 00903 00904 ws_pae_auth_next_kmp_trigger(pae_auth, supp_entry); 00905 } 00906 00907 static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *supp_entry) 00908 { 00909 // Disables KMP retry timer 00910 supp_entry->retry_ticks = 0; 00911 00912 // Get next protocol based on what keys supplicant has 00913 kmp_type_e next_type = ws_pae_auth_next_protocol_get(supp_entry); 00914 00915 if (next_type == KMP_TYPE_NONE) { 00916 // All done 00917 return; 00918 } else { 00919 00920 kmp_api_t *api = ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, next_type); 00921 if (api != NULL) { 00922 /* For other types than GTK, only one ongoing negotiation at the same time, 00923 for GTK there can be previous terminating and the new one for next key index */ 00924 if (next_type != IEEE_802_11_GKH) { 00925 tr_info("KMP already ongoing; ignored, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8)); 00926 return; 00927 } 00928 } 00929 } 00930 00931 // Increases waiting time for supplicant authentication 00932 ws_pae_lib_supp_timer_ticks_set(supp_entry, WAIT_FOR_AUTHENTICATION_TICKS); 00933 00934 if (next_type == IEEE_802_1X_MKA) { 00935 /* For EAP-TLS, limits the number of ongoing negotiations. If limit 00936 is reached, authenticator does not initiate EAP-TLS right away. 00937 If previous EAP-TLS negotiation completes before negotiation 00938 trigger timeout, authenticator initiates EAP-TLS towards 00939 supplicant. Otherwise supplicant must re-send initial EAPOL-Key 00940 to try again using its trickle schedule */ 00941 uint16_t ongoing_eap_tls_cnt = ws_pae_lib_supp_list_kmp_count(&pae_auth->active_supp_list, IEEE_802_1X_MKA); 00942 if (ongoing_eap_tls_cnt >= MAX_SIMULTANEOUS_EAP_TLS_NEGOTIATIONS) { 00943 supp_entry->retry_ticks = EAP_TLS_NEGOTIATION_TRIGGER_TIMEOUT; 00944 tr_info("EAP-TLS max ongoing reached, count %i, delayed: eui-64: %s", ongoing_eap_tls_cnt, trace_array(supp_entry->addr.eui_64, 8)); 00945 return; 00946 } 00947 } 00948 00949 // Create new instance 00950 kmp_api_t *new_kmp = ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, next_type, supp_entry); 00951 if (!new_kmp) { 00952 return; 00953 } 00954 00955 // For EAP-TLS create also TLS in addition to EAP-TLS 00956 if (next_type == IEEE_802_1X_MKA) { 00957 if (ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, TLS_PROT) != NULL) { 00958 // TLS already exists, wait for it to be deleted 00959 ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, new_kmp); 00960 return; 00961 } 00962 // Create TLS instance */ 00963 if (ws_pae_auth_kmp_create_and_start(pae_auth->kmp_service, TLS_PROT, supp_entry) == NULL) { 00964 ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, new_kmp); 00965 return; 00966 } 00967 } 00968 00969 kmp_api_create_request(new_kmp, next_type, &supp_entry->addr, &supp_entry->sec_keys); 00970 } 00971 00972 static kmp_type_e ws_pae_auth_next_protocol_get(supp_entry_t *supp_entry) 00973 { 00974 kmp_type_e next_type = KMP_TYPE_NONE; 00975 sec_prot_keys_t *sec_keys = &supp_entry->sec_keys; 00976 00977 // Supplicant has indicated that PMK is not valid 00978 if (sec_keys->pmk_mismatch) { 00979 sec_keys->ptk_mismatch = true; 00980 // start EAP-TLS towards supplicant 00981 next_type = IEEE_802_1X_MKA; 00982 tr_info("PAE start EAP-TLS, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8)); 00983 } else if (sec_keys->ptk_mismatch) { 00984 // start 4WH towards supplicant 00985 next_type = IEEE_802_11_4WH; 00986 tr_info("PAE start 4WH, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8)); 00987 } 00988 00989 int8_t gtk_index = -1; 00990 if (next_type != IEEE_802_1X_MKA) { 00991 // Checks if GTK needs to be inserted 00992 gtk_index = sec_prot_keys_gtk_insert_index_from_gtkl_get(sec_keys); 00993 00994 // For 4WH insert always a key, in case no other then active 00995 if (next_type == IEEE_802_11_4WH && gtk_index < 0) { 00996 gtk_index = sec_prot_keys_gtk_status_active_get(sec_keys->gtks); 00997 } 00998 } 00999 01000 if (gtk_index >= 0) { 01001 if (next_type == KMP_TYPE_NONE && gtk_index >= 0) { 01002 // Update just GTK 01003 next_type = IEEE_802_11_GKH; 01004 tr_info("PAE start GKH, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8)); 01005 } 01006 01007 tr_info("PAE update GTK index: %i, eui-64: %s", gtk_index, trace_array(supp_entry->addr.eui_64, 8)); 01008 } 01009 01010 if (next_type == KMP_TYPE_NONE) { 01011 tr_info("PAE authenticated, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8)); 01012 } 01013 01014 return next_type; 01015 } 01016 01017 01018 static kmp_api_t *ws_pae_auth_kmp_create_and_start(kmp_service_t *service, kmp_type_e type, supp_entry_t *supp_entry) 01019 { 01020 // Create KMP instance for new authentication 01021 kmp_api_t *kmp = kmp_api_create(service, type); 01022 01023 if (!kmp) { 01024 return NULL; 01025 } 01026 01027 if (ws_pae_lib_kmp_list_add(&supp_entry->kmp_list, kmp) == NULL) { 01028 kmp_api_delete(kmp); 01029 return NULL; 01030 } 01031 01032 kmp_api_cb_register(kmp, 01033 ws_pae_auth_kmp_api_create_confirm, 01034 ws_pae_auth_kmp_api_create_indication, 01035 ws_pae_auth_kmp_api_finished_indication, 01036 ws_pae_auth_kmp_api_finished); 01037 01038 kmp_api_data_set(kmp, supp_entry); 01039 01040 if (kmp_api_start(kmp) < 0) { 01041 ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, kmp); 01042 return NULL; 01043 } 01044 01045 return kmp; 01046 } 01047 01048 static void ws_pae_auth_kmp_api_finished(kmp_api_t *kmp) 01049 { 01050 supp_entry_t *supp_entry = kmp_api_data_get(kmp); 01051 if (!supp_entry) { 01052 // Should not be possible 01053 return; 01054 } 01055 01056 pae_auth_t *pae_auth = NULL; 01057 supp_entry_t *retry_supp = NULL; 01058 // When EAP-TLS completes check if there are other supplicants that have requested it lately 01059 if (kmp_api_type_get(kmp) == IEEE_802_1X_MKA) { 01060 kmp_service_t *service = kmp_api_service_get(kmp); 01061 pae_auth = ws_pae_auth_by_kmp_service_get(service); 01062 if (pae_auth) { 01063 retry_supp = ws_pae_lib_supp_list_entry_retry_timer_get(&pae_auth->active_supp_list); 01064 } 01065 } 01066 01067 // Delete KMP 01068 ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, kmp); 01069 01070 if (retry_supp) { 01071 tr_info("PAE next KMP trigger, eui-64: %s", trace_array(retry_supp->addr.eui_64, 8)); 01072 ws_pae_auth_next_kmp_trigger(pae_auth, retry_supp); 01073 } 01074 01075 } 01076 01077 #endif /* HAVE_PAE_AUTH */ 01078 #endif /* HAVE_WS */ 01079
Generated on Tue Jul 12 2022 13:55:04 by
1.7.2