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_lib.c Source File

ws_pae_lib.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 "ns_types.h"
00021 #include "ns_list.h"
00022 #include "ns_trace.h"
00023 #include "nsdynmemLIB.h"
00024 #include "fhss_config.h "
00025 #include "NWK_INTERFACE/Include/protocol.h"
00026 #include "6LoWPAN/ws/ws_config.h"
00027 #include "Security/kmp/kmp_addr.h"
00028 #include "Security/kmp/kmp_api.h"
00029 #include "Security/protocols/sec_prot_certs.h"
00030 #include "Security/protocols/sec_prot_keys.h"
00031 #include "6LoWPAN/ws/ws_pae_timers.h"
00032 #include "6LoWPAN/ws/ws_pae_lib.h"
00033 
00034 #ifdef HAVE_WS
00035 
00036 #define TRACE_GROUP "wspl"
00037 
00038 void ws_pae_lib_kmp_list_init(kmp_list_t *kmp_list)
00039 {
00040     ns_list_init(kmp_list);
00041 }
00042 
00043 kmp_entry_t *ws_pae_lib_kmp_list_add(kmp_list_t *kmp_list, kmp_api_t *kmp)
00044 {
00045     // Already in list
00046     kmp_entry_t *entry = ws_pae_lib_kmp_list_entry_get(kmp_list, kmp);
00047     if (entry) {
00048         return entry;
00049     }
00050 
00051     entry = ns_dyn_mem_alloc(sizeof(kmp_entry_t));
00052     if (!entry) {
00053         return NULL;
00054     }
00055     entry->kmp = kmp;
00056     entry->timer_running = false;
00057 
00058     ns_list_add_to_end(kmp_list, entry);
00059 
00060     return entry;
00061 }
00062 
00063 int8_t ws_pae_lib_kmp_list_delete(kmp_list_t *kmp_list, kmp_api_t *kmp)
00064 {
00065     kmp_entry_t *entry = ws_pae_lib_kmp_list_entry_get(kmp_list, kmp);
00066 
00067     if (entry) {
00068         ns_list_remove(kmp_list, entry);
00069         kmp_api_delete(entry->kmp);
00070         ns_dyn_mem_free(entry);
00071         return 0;
00072     }
00073 
00074     return -1;
00075 }
00076 
00077 kmp_api_t *ws_pae_lib_kmp_list_type_get(kmp_list_t *kmp_list, kmp_type_e type)
00078 {
00079     kmp_api_t *kmp = NULL;
00080 
00081     ns_list_foreach(kmp_entry_t, cur, kmp_list) {
00082         // If kmp type matches
00083         if (kmp_api_type_get(cur->kmp) == type) {
00084             /* If receiving of messages has not been disabled for the kmp (kmp is not
00085                in terminating phase) prioritizes that kmp */
00086             if (!kmp_api_receive_disable(cur->kmp)) {
00087                 return cur->kmp;
00088             }
00089             // Otherwise returns any kmp that matches
00090             kmp = cur->kmp;
00091         }
00092     }
00093     return kmp;
00094 }
00095 
00096 kmp_api_t *ws_pae_lib_kmp_list_instance_id_get(kmp_list_t *kmp_list, uint8_t instance_id)
00097 {
00098     ns_list_foreach(kmp_entry_t, cur, kmp_list) {
00099         if (kmp_api_instance_id_get(cur->kmp) == instance_id) {
00100             return cur->kmp;
00101         }
00102     }
00103 
00104     return NULL;
00105 }
00106 
00107 void ws_pae_lib_kmp_list_free(kmp_list_t *kmp_list)
00108 {
00109     ns_list_foreach_safe(kmp_entry_t, cur, kmp_list) {
00110         kmp_api_delete(cur->kmp);
00111         ns_dyn_mem_free(cur);
00112     }
00113 }
00114 
00115 kmp_entry_t *ws_pae_lib_kmp_list_entry_get(kmp_list_t *kmp_list, kmp_api_t *kmp)
00116 {
00117     ns_list_foreach(kmp_entry_t, cur, kmp_list) {
00118         if (cur->kmp == kmp) {
00119             return cur;
00120         }
00121     }
00122 
00123     return 0;
00124 }
00125 
00126 void ws_pae_lib_kmp_timer_start(kmp_list_t *kmp_list, kmp_entry_t *entry)
00127 {
00128     if (ns_list_get_first(kmp_list) != entry) {
00129         ns_list_remove(kmp_list, entry);
00130         ns_list_add_to_start(kmp_list, entry);
00131     }
00132     entry->timer_running = true;
00133 }
00134 
00135 void ws_pae_lib_kmp_timer_stop(kmp_list_t *kmp_list, kmp_entry_t *entry)
00136 {
00137     if (ns_list_get_last(kmp_list) != entry) {
00138         ns_list_remove(kmp_list, entry);
00139         ns_list_add_to_end(kmp_list, entry);
00140     }
00141     entry->timer_running = false;
00142 }
00143 
00144 bool ws_pae_lib_kmp_timer_update(kmp_list_t *kmp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout)
00145 {
00146     if (ns_list_is_empty(kmp_list)) {
00147         return false;
00148     }
00149 
00150     bool timer_running = false;
00151 
00152     ns_list_foreach_safe(kmp_entry_t, entry, kmp_list) {
00153         if (entry->timer_running) {
00154             timeout(entry->kmp, ticks);
00155             timer_running = true;
00156         } else {
00157             break;
00158         }
00159     }
00160 
00161     return timer_running;
00162 }
00163 
00164 void ws_pae_lib_supp_list_init(supp_list_t *supp_list)
00165 {
00166     ns_list_init(supp_list);
00167 }
00168 
00169 supp_entry_t *ws_pae_lib_supp_list_add(supp_list_t *supp_list, const kmp_addr_t *addr)
00170 {
00171     supp_entry_t *entry = ns_dyn_mem_alloc(sizeof(supp_entry_t));
00172 
00173     if (!entry) {
00174         return NULL;
00175     }
00176 
00177     ws_pae_lib_supp_init(entry);
00178     memset(&entry->addr, 0, sizeof(kmp_addr_t));
00179     entry->addr.type = KMP_ADDR_EUI_64_AND_IP;
00180     kmp_address_copy(&entry->addr, addr);
00181 
00182     ns_list_add_to_end(supp_list, entry);
00183 
00184     return entry;
00185 }
00186 
00187 int8_t ws_pae_lib_supp_list_remove(supp_list_t *supp_list, supp_entry_t *supp)
00188 {
00189     ns_list_remove(supp_list, supp);
00190 
00191     ws_pae_lib_supp_delete(supp);
00192 
00193     ns_dyn_mem_free(supp);
00194     return 0;
00195 }
00196 
00197 supp_entry_t *ws_pae_lib_supp_list_entry_eui_64_get(const supp_list_t *supp_list, const uint8_t *eui_64)
00198 {
00199     ns_list_foreach(supp_entry_t, cur, supp_list) {
00200         if (memcmp(cur->addr.eui_64, eui_64, 8) == 0) {
00201             return cur;
00202         }
00203     }
00204 
00205     return 0;
00206 }
00207 
00208 void ws_pae_lib_supp_list_delete(supp_list_t *supp_list)
00209 {
00210     ns_list_foreach_safe(supp_entry_t, entry, supp_list) {
00211         ws_pae_lib_supp_list_remove(supp_list, entry);
00212     }
00213 }
00214 
00215 bool ws_pae_lib_supp_list_timer_update(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout)
00216 {
00217     bool timer_running = false;
00218 
00219     ns_list_foreach_safe(supp_entry_t, entry, active_supp_list) {
00220         bool running = ws_pae_lib_supp_timer_update(entry, ticks, timeout);
00221         if (running) {
00222             timer_running = true;
00223         } else {
00224             ws_pae_lib_supp_list_to_inactive(active_supp_list, inactive_supp_list, entry);
00225         }
00226     }
00227 
00228     return timer_running;
00229 }
00230 
00231 void ws_pae_lib_supp_list_slow_timer_update(supp_list_t *supp_list, timer_settings_t *timer_settings, uint16_t seconds)
00232 {
00233     ns_list_foreach(supp_entry_t, entry, supp_list) {
00234         if (sec_prot_keys_pmk_lifetime_decrement(&entry->sec_keys, timer_settings->pmk_lifetime, seconds)) {
00235             tr_info("PMK and PTK expired, eui-64: %s, system time: %"PRIu32"", trace_array(entry->addr.eui_64, 8), protocol_core_monotonic_time / 10);
00236         }
00237         if (sec_prot_keys_ptk_lifetime_decrement(&entry->sec_keys, timer_settings->ptk_lifetime, seconds)) {
00238             tr_info("PTK expired, eui-64: %s, system time: %"PRIu32"", trace_array(entry->addr.eui_64, 8), protocol_core_monotonic_time / 10);
00239         }
00240     }
00241 
00242 }
00243 
00244 void ws_pae_lib_supp_init(supp_entry_t *entry)
00245 {
00246     ws_pae_lib_kmp_list_init(&entry->kmp_list);
00247     memset(&entry->addr, 0, sizeof(kmp_addr_t));
00248     memset(&entry->sec_keys, 0, sizeof(sec_prot_keys_t));
00249     entry->ticks = 0;
00250     entry->retry_ticks = 0;
00251     entry->active = true;
00252     entry->access_revoked = false;
00253 }
00254 
00255 void ws_pae_lib_supp_delete(supp_entry_t *entry)
00256 {
00257     ws_pae_lib_kmp_list_free(&entry->kmp_list);
00258 }
00259 
00260 bool ws_pae_lib_supp_timer_update(supp_entry_t *entry, uint16_t ticks, ws_pae_lib_kmp_timer_timeout timeout)
00261 {
00262     // Updates KMP timers and calls timeout callback
00263     bool keep_timer_running = ws_pae_lib_kmp_timer_update(&entry->kmp_list, ticks, timeout);
00264 
00265     // If KMPs are not active updates supplicant timer
00266     if (!keep_timer_running) {
00267         if (entry->ticks > ticks) {
00268             keep_timer_running = true;
00269             entry->ticks -= ticks;
00270         } else {
00271             entry->ticks = 0;
00272             entry->retry_ticks = 0;
00273         }
00274     }
00275 
00276     // Updates retry timer
00277     if (entry->retry_ticks > ticks) {
00278         entry->retry_ticks -= ticks;
00279     } else {
00280         if (entry->retry_ticks > 0) {
00281             tr_info("EAP-TLS max ongoing delay timeout eui-64: %s", trace_array(entry->addr.eui_64, 8));
00282         }
00283         entry->retry_ticks = 0;
00284     }
00285 
00286     return keep_timer_running;
00287 }
00288 
00289 void ws_pae_lib_supp_timer_ticks_set(supp_entry_t *entry, uint32_t ticks)
00290 {
00291     entry->ticks = ticks;
00292 }
00293 
00294 void ws_pae_lib_supp_list_to_active(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, supp_entry_t *entry)
00295 {
00296     if (entry->active) {
00297         return;
00298     }
00299 
00300     tr_debug("PAE: to active, eui-64: %s", trace_array(entry->addr.eui_64, 8));
00301 
00302     ns_list_remove(inactive_supp_list, entry);
00303     ns_list_add_to_start(active_supp_list, entry);
00304 
00305     entry->active = true;
00306     entry->ticks = 0;
00307 
00308     // Adds relay address data
00309     entry->addr.type = KMP_ADDR_EUI_64_AND_IP;
00310 }
00311 
00312 void ws_pae_lib_supp_list_to_inactive(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, supp_entry_t *entry)
00313 {
00314     if (!entry->active) {
00315         return;
00316     }
00317 
00318     tr_debug("PAE: to inactive, eui-64: %s", trace_array(entry->addr.eui_64, 8));
00319 
00320     if (entry->access_revoked) {
00321         tr_info("Access revoked; deleted, eui-64: %s", trace_array(entry->addr.eui_64, 8));
00322         ws_pae_lib_supp_list_remove(active_supp_list, entry);
00323         return;
00324     }
00325 
00326     ns_list_remove(active_supp_list, entry);
00327     ns_list_add_to_start(inactive_supp_list, entry);
00328 
00329     entry->active = false;
00330     entry->ticks = 0;
00331 
00332     // Removes relay address data
00333     entry->addr.type = KMP_ADDR_EUI_64;
00334     entry->addr.port = 0;
00335     memset(entry->addr.relay_address, 0, 16);
00336 }
00337 
00338 void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, uint16_t max_number, uint8_t max_purge)
00339 {
00340     uint16_t active_supp = ns_list_count(active_supp_list);
00341     uint16_t inactive_supp = ns_list_count(inactive_supp_list);
00342 
00343     if (active_supp + inactive_supp > max_number) {
00344         uint16_t remove_count = active_supp + inactive_supp - max_number;
00345         if (max_purge > 0 && remove_count > max_purge) {
00346             remove_count = max_purge;
00347         }
00348 
00349         // Remove entries from inactive list
00350         ns_list_foreach_safe(supp_entry_t, entry, inactive_supp_list) {
00351             if (remove_count > 0) {
00352                 tr_info("Inactive supplicant removed, eui-64: %s", trace_array(kmp_address_eui_64_get(&entry->addr), 8));
00353                 ws_pae_lib_supp_list_remove(inactive_supp_list, entry);
00354                 remove_count--;
00355             } else {
00356                 break;
00357             }
00358         }
00359     }
00360 }
00361 
00362 uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type)
00363 {
00364     uint16_t kmp_count = 0;
00365 
00366     ns_list_foreach(supp_entry_t, entry, supp_list) {
00367         ns_list_foreach(kmp_entry_t, kmp_entry, &entry->kmp_list) {
00368             if (kmp_api_type_get(kmp_entry->kmp) == type) {
00369                 kmp_count++;
00370             }
00371         }
00372     }
00373 
00374     return kmp_count;
00375 }
00376 
00377 supp_entry_t *ws_pae_lib_supp_list_entry_retry_timer_get(supp_list_t *supp_list)
00378 {
00379     supp_entry_t *retry_supp = NULL;
00380 
00381     ns_list_foreach(supp_entry_t, entry, supp_list) {
00382         // Finds entry with shortest timeout i.e. oldest one
00383         if (entry->retry_ticks > 0) {
00384             if (!retry_supp || retry_supp->retry_ticks > entry->retry_ticks) {
00385                 retry_supp = entry;
00386             }
00387         }
00388     }
00389 
00390     return retry_supp;
00391 }
00392 
00393 #endif /* HAVE_WS */