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

ws_pae_controller.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 "ns_address.h"
00026 #include "NWK_INTERFACE/Include/protocol.h"
00027 #include "6LoWPAN/ws/ws_config.h"
00028 #include "6LoWPAN/ws/ws_pae_controller.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_supp.h"
00033 #include "6LoWPAN/ws/ws_pae_auth.h"
00034 #include "6LoWPAN/ws/ws_pae_nvm_store.h"
00035 #include "6LoWPAN/ws/ws_pae_nvm_data.h"
00036 #include "mbedtls/sha256.h"
00037 
00038 #ifdef HAVE_WS
00039 
00040 #define TRACE_GROUP "wspc"
00041 
00042 typedef int8_t ws_pae_delete(protocol_interface_info_entry_t *interface_ptr);
00043 typedef void ws_pae_timer(uint16_t ticks);
00044 typedef int8_t ws_pae_br_addr_write(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64);
00045 typedef int8_t ws_pae_br_addr_read(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64);
00046 typedef void ws_pae_gtks_updated(protocol_interface_info_entry_t *interface_ptr);
00047 typedef int8_t ws_pae_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash);
00048 typedef int8_t ws_pae_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
00049 
00050 typedef struct {
00051     uint8_t gtk[GTK_LEN];                                            /**< GTK key */
00052     bool set : 1;                                                    /**< Key has been set */
00053     bool installed : 1;                                              /**< Key has been installed on MAC */
00054 } nw_key_t;
00055 
00056 typedef struct {
00057     ns_list_link_t link;                                             /**< Link */
00058     uint8_t target_eui_64[8];                                        /**< EAPOL target */
00059     uint16_t target_pan_id;                                          /**< EAPOL target PAN ID */
00060     uint8_t br_eui_64[8];                                            /**< Border router EUI-64 */
00061     sec_prot_gtk_keys_t gtks;                                        /**< GTKs */
00062     sec_prot_gtk_keys_t next_gtks;                                   /**< Next GTKs */
00063     int8_t gtk_index;                                                /**< GTK index */
00064     uint8_t gtkhash[32];                                             /**< GTK hashes */
00065     sec_prot_certs_t certs;                                          /**< Certificates */
00066     nw_key_t nw_key[GTK_NUM];                                        /**< Currently active network keys (on MAC) */
00067     char *network_name;                                              /**< Network name for GAK generation */
00068     uint16_t frame_cnt_store_timer;                                  /**< Timer for storing frame counter value */
00069     frame_counters_t frame_counters;                                 /**< Frame counters */
00070     timer_settings_t timer_settings;                                 /**< Timer settings */
00071     protocol_interface_info_entry_t *interface_ptr;                  /**< List link entry */
00072     ws_pae_controller_auth_completed *auth_completed;                /**< Authentication completed callback, continue bootstrap */
00073     ws_pae_controller_nw_key_set *nw_key_set;                        /**< Key set callback */
00074     ws_pae_controller_nw_key_clear *nw_key_clear;                    /**< Key clear callback */
00075     ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set;  /**< Send key index set callback */
00076     ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set;    /**< Frame counter set callback */
00077     ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read;  /**< Frame counter read callback */
00078     ws_pae_controller_pan_ver_increment *pan_ver_increment;          /**< PAN version increment callback */
00079     ws_pae_delete *pae_delete;                                       /**< PAE delete callback */
00080     ws_pae_timer *pae_fast_timer;                                    /**< PAE fast timer callback */
00081     ws_pae_timer *pae_slow_timer;                                    /**< PAE slow timer callback */
00082     ws_pae_br_addr_write *pae_br_addr_write;                         /**< PAE Border router EUI-64 write callback */
00083     ws_pae_br_addr_read *pae_br_addr_read;                           /**< PAE Border router EUI-64 read callback */
00084     ws_pae_gtks_updated *pae_gtks_updated;                           /**< PAE GTKs updated */
00085     ws_pae_gtk_hash_update *pae_gtk_hash_update;                     /**< PAE GTK HASH update */
00086     ws_pae_nw_key_index_update *pae_nw_key_index_update;             /**< PAE NW key index update */
00087     nvm_tlv_entry_t *pae_nvm_buffer;                                 /**< Buffer For PAE NVM write operation*/
00088     bool gtks_set : 1;                                               /**< GTKs are set */
00089     bool gtkhash_set : 1;                                            /**< GTK hashes are set */
00090     bool key_index_set : 1;                                          /**< NW key index is set */
00091 } pae_controller_t;
00092 
00093 typedef struct {
00094     uint16_t node_limit;                                             /**< Max number of stored supplicants */
00095     bool node_limit_set : 1;                                         /**< Node limit set */
00096     bool ext_cert_valid_enabled : 1;                                 /**< Extended certificate validation enabled */
00097 } pae_controller_config_t;
00098 
00099 static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr);
00100 static void ws_pae_controller_frame_counter_timer(uint16_t seconds, pae_controller_t *entry);
00101 static void ws_pae_controller_frame_counter_timer_trigger(uint16_t seconds, pae_controller_t *entry);
00102 static void ws_pae_controller_frame_counter_store(pae_controller_t *entry, bool use_threshold);
00103 static void ws_pae_controller_nvm_frame_counter_write(nvm_tlv_entry_t *tlv_entry);
00104 static int8_t ws_pae_controller_nvm_frame_counter_read(frame_counters_t *counters);
00105 static pae_controller_t *ws_pae_controller_get_or_create(int8_t interface_id);
00106 static void ws_pae_controller_gtk_hash_set(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash);
00107 static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks);
00108 static void ws_pae_controller_active_nw_key_clear(nw_key_t *nw_key);
00109 static void ws_pae_controller_active_nw_key_set(protocol_interface_info_entry_t *cur, uint8_t index);
00110 static int8_t ws_pae_controller_gak_from_gtk(uint8_t *gak, uint8_t *gtk, char *network_name);
00111 static void ws_pae_controller_nw_key_index_check_and_set(protocol_interface_info_entry_t *interface_ptr, uint8_t index);
00112 static void ws_pae_controller_data_init(pae_controller_t *controller);
00113 static void ws_pae_controller_frame_counter_read(pae_controller_t *controller);
00114 static void ws_pae_controller_frame_counter_reset(frame_counters_t *frame_counters);
00115 
00116 static const char *FRAME_COUNTER_FILE = FRAME_COUNTER_FILE_NAME;
00117 
00118 static NS_LIST_DEFINE(pae_controller_list, pae_controller_t, link);
00119 
00120 pae_controller_config_t pae_controller_config = {
00121     .node_limit = 0,
00122     .node_limit_set = false,
00123     .ext_cert_valid_enabled = false
00124 };
00125 
00126 #if !defined(HAVE_PAE_SUPP) && !defined(HAVE_PAE_AUTH)
00127 
00128 static void ws_pae_controller_test_keys_set(sec_prot_gtk_keys_t *gtks)
00129 {
00130     uint8_t gtk[GTK_LEN];
00131 
00132     // Test data
00133     for (int i = 0; i < GTK_LEN; i++) {
00134         gtk[i] = 0xcf - i;
00135     }
00136 
00137     sec_prot_keys_gtk_set(gtks, 0, gtk, GTK_DEFAULT_LIFETIME);
00138 }
00139 
00140 #else
00141 
00142 #define ws_pae_controller_test_keys_set(gtks);
00143 
00144 #endif
00145 
00146 int8_t ws_pae_controller_authenticate(protocol_interface_info_entry_t *interface_ptr)
00147 {
00148     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
00149     if (!controller) {
00150         return -1;
00151     }
00152 
00153 #ifdef HAVE_PAE_SUPP
00154     // In case test keys are set uses those and does not initiate authentication
00155     if (controller->gtks_set) {
00156         if (sec_prot_keys_gtks_are_updated(&controller->gtks)) {
00157             ws_pae_controller_nw_key_check_and_insert(controller->interface_ptr, &controller->gtks);
00158             sec_prot_keys_gtks_updated_reset(&controller->gtks);
00159             ws_pae_supp_gtks_set(controller->interface_ptr, &controller->gtks);
00160         }
00161         controller->auth_completed(interface_ptr, AUTH_RESULT_OK, NULL);
00162         return 0;
00163     }
00164 
00165     if (ws_pae_supp_authenticate(controller->interface_ptr, controller->target_pan_id, controller->target_eui_64) < 0) {
00166         controller->auth_completed(interface_ptr, AUTH_RESULT_ERR_UNSPEC, controller->target_eui_64);
00167     }
00168 
00169 #else
00170     ws_pae_controller_test_keys_set(&controller->gtks);
00171     ws_pae_controller_nw_key_check_and_insert(interface_ptr, &controller->gtks);
00172     ws_pae_controller_nw_key_index_check_and_set(interface_ptr, 0);
00173 
00174     controller->auth_completed(interface_ptr, AUTH_RESULT_OK);
00175 #endif
00176 
00177     return 0;
00178 }
00179 
00180 int8_t ws_pae_controller_bootstrap_done(protocol_interface_info_entry_t *interface_ptr)
00181 {
00182     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
00183     if (!controller) {
00184         return -1;
00185     }
00186 
00187 #ifdef HAVE_PAE_SUPP
00188     // RPL parent is known, remove EAPOL target that what was set using the authenticate call */
00189     ws_pae_supp_eapol_target_remove(interface_ptr);
00190 
00191     /* Trigger GTK hash update to supplicant, so it can check whether keys have been updated
00192        during bootstrap. Does nothing if GTKs are up to date. */
00193     ws_pae_supp_gtk_hash_update(interface_ptr, controller->gtkhash);
00194 #endif
00195 
00196     return 0;
00197 }
00198 
00199 int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *interface_ptr, uint16_t local_port, const uint8_t *remote_addr, uint16_t remote_port)
00200 {
00201     (void) local_port;
00202     (void) remote_port;
00203 
00204     if (!interface_ptr || !remote_addr) {
00205         return -1;
00206     }
00207 
00208     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
00209     if (!controller) {
00210         return -1;
00211     }
00212 
00213 #ifdef HAVE_PAE_AUTH
00214     if (sec_prot_keys_gtks_are_updated(&controller->gtks)) {
00215         ws_pae_auth_gtks_updated(interface_ptr);
00216         if (controller->gtk_index >= 0) {
00217             controller->pae_nw_key_index_update(interface_ptr, controller->gtk_index);
00218         }
00219         sec_prot_keys_gtks_updated_reset(&controller->gtks);
00220     }
00221 #else
00222     ws_pae_controller_test_keys_set(&controller->gtks);
00223     ws_pae_controller_nw_key_check_and_insert(interface_ptr, &controller->gtks);
00224     ws_pae_controller_nw_key_index_check_and_set(interface_ptr, 0);
00225 #endif
00226 
00227     if (ws_pae_auth_addresses_set(interface_ptr, local_port, remote_addr, remote_port) < 0) {
00228         return -1;
00229     }
00230 
00231     if (pae_controller_config.node_limit_set) {
00232         ws_pae_auth_node_limit_set(controller->interface_ptr, pae_controller_config.node_limit);
00233     }
00234 
00235     ws_pae_auth_cb_register(interface_ptr, ws_pae_controller_gtk_hash_set, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_nw_key_index_check_and_set);
00236 
00237     ws_pae_auth_start(interface_ptr);
00238 
00239     return 0;
00240 }
00241 
00242 int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment)
00243 {
00244     if (!interface_ptr) {
00245         return -1;
00246     }
00247 
00248     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
00249     if (!controller) {
00250         return -1;
00251     }
00252 
00253     controller->auth_completed = completed;
00254     controller->nw_key_set = nw_key_set;
00255     controller->nw_key_clear = nw_key_clear;
00256     controller->nw_send_key_index_set = nw_send_key_index_set;
00257     controller->nw_frame_counter_set = nw_frame_counter_set;
00258     controller->nw_frame_counter_read = nw_frame_counter_read;
00259     controller->pan_ver_increment = pan_ver_increment;
00260 
00261     return 0;
00262 }
00263 
00264 int8_t ws_pae_controller_set_target(protocol_interface_info_entry_t *interface_ptr, uint16_t target_pan_id, uint8_t *target_eui_64)
00265 {
00266     if (!interface_ptr) {
00267         return -1;
00268     }
00269 
00270     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
00271     if (!controller) {
00272         return -1;
00273     }
00274 
00275     controller->target_pan_id = target_pan_id;
00276     memcpy(controller->target_eui_64, target_eui_64, 8);
00277 
00278     return 0;
00279 }
00280 
00281 int8_t ws_pae_controller_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name)
00282 {
00283     (void) pan_id;
00284     (void) network_name;
00285 
00286     if (!interface_ptr) {
00287         return -1;
00288     }
00289 
00290     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
00291     if (!controller) {
00292         return -1;
00293     }
00294 
00295     controller->network_name = network_name;
00296 
00297     return ws_pae_supp_nw_info_set(interface_ptr, pan_id, network_name);
00298 }
00299 
00300 int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface_ptr)
00301 {
00302     if (!interface_ptr) {
00303         return -1;
00304     }
00305 
00306     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
00307     if (!controller) {
00308         return -1;
00309     }
00310 
00311     return ws_pae_supp_nw_key_valid(interface_ptr);
00312 }
00313 
00314 static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks)
00315 {
00316     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
00317     if (!controller) {
00318         return -1;
00319     }
00320 
00321     int8_t ret = -1;
00322 
00323     // Adds, removes and updates network keys to MAC based on new GTKs
00324     nw_key_t *nw_key = controller->nw_key;
00325     for (uint8_t i = 0; i < GTK_NUM; i++) {
00326         // Gets GTK for the index (new, modified or none)
00327         uint8_t *gtk = sec_prot_keys_gtk_get(gtks, i);
00328 
00329         // If network key is set and GTK key is not set or not the same, removes network key
00330         if (nw_key[i].set && (!gtk || memcmp(nw_key[i].gtk, gtk, GTK_LEN) != 0)) {
00331             // Removes key from MAC if installed
00332             if (nw_key[i].installed) {
00333                 controller->nw_key_clear(interface_ptr, i);
00334             }
00335             nw_key[i].installed = false;
00336             nw_key[i].set = false;
00337             tr_info("NW key remove: %i", i);
00338         }
00339 
00340         // If GTK key is not set, continues to next GTK
00341         if (!gtk) {
00342             continue;
00343         }
00344 
00345         // Network key is set and installed, all done
00346         if (nw_key[i].set && nw_key[i].installed) {
00347             continue;
00348         }
00349 
00350         // If network key is not set, stores the new GTK key to network key
00351         if (!nw_key[i].set) {
00352             nw_key[i].set = true;
00353             nw_key[i].installed = false;
00354             memcpy(nw_key[i].gtk, gtk, GTK_LEN);
00355         }
00356 
00357         // If network key has not been installed, installs it and updates frame counter as needed
00358         if (!nw_key[i].installed) {
00359             uint8_t gtkhash[GTK_HASH_LEN];
00360             sec_prot_keys_gtk_hash_generate(gtk, gtkhash);
00361             tr_info("NW key set: %i, hash: %s", i, trace_array(gtkhash, 8));
00362             uint8_t gak[GTK_LEN];
00363             if (ws_pae_controller_gak_from_gtk(gak, gtk, controller->network_name) >= 0) {
00364                 // Install the new network key derived from GTK and network name (GAK) to MAC
00365                 controller->nw_key_set(interface_ptr, i, i, gak);
00366                 tr_info("NW: %s", controller->network_name);
00367                 tr_info("NW: %s", trace_array((uint8_t *)controller->network_name, 20));
00368                 tr_info("GTK: %s", trace_array(gtk, 16));
00369                 tr_info("GAK: %s", trace_array(gak, 16));
00370                 nw_key[i].installed = true;
00371                 ret = 0;
00372             } else {
00373                 tr_error("GAK generation failed network name: %s", controller->network_name);
00374                 continue;
00375             }
00376 
00377             // If frame counter value has been stored for the network key, updates the frame counter if needed
00378             if (controller->frame_counters.counter[i].set &&
00379                     memcmp(gtk, controller->frame_counters.counter[i].gtk, GTK_LEN) == 0) {
00380                 // Read current counter from MAC
00381                 uint32_t curr_frame_counter;
00382                 controller->nw_frame_counter_read(controller->interface_ptr, &curr_frame_counter, i);
00383                 // If stored frame counter is greater than MAC counter
00384                 if (controller->frame_counters.counter[i].frame_counter > curr_frame_counter) {
00385                     tr_debug("Frame counter set: %i, stored %"PRIu32" current: %"PRIu32"", i, controller->frame_counters.counter[i].frame_counter, curr_frame_counter);
00386                     curr_frame_counter = controller->frame_counters.counter[i].frame_counter;
00387                     // Updates MAC frame counter
00388                     controller->nw_frame_counter_set(controller->interface_ptr, curr_frame_counter, i);
00389                 }
00390             }
00391             /* Trigger storing of frame counters; there is 5 seconds delay to give time for the
00392                other keys to be inserted, so that frame counters for several keys are updated on
00393                a same time. */
00394             ws_pae_controller_frame_counter_timer_trigger(FRAME_COUNTER_STORE_TRIGGER, controller);
00395         }
00396     }
00397 
00398     return ret;
00399 }
00400 
00401 static void ws_pae_controller_active_nw_key_clear(nw_key_t *nw_key)
00402 {
00403     memset(nw_key, 0, sizeof(nw_key_t));
00404     nw_key->set = false;
00405     nw_key->installed = false;
00406 }
00407 
00408 static int8_t ws_pae_controller_gak_from_gtk(uint8_t *gak, uint8_t *gtk, char *network_name)
00409 {
00410 #if defined(HAVE_PAE_SUPP) || defined(HAVE_PAE_AUTH)
00411     uint8_t network_name_len = strlen(network_name);
00412     if (network_name_len == 0) {
00413         return -1;
00414     }
00415 
00416     uint8_t input[network_name_len + GTK_LEN];
00417     memcpy(input, network_name, network_name_len);
00418     memcpy(input + network_name_len, gtk, GTK_LEN);
00419 
00420     int8_t ret_val = 0;
00421 
00422     mbedtls_sha256_context ctx;
00423 
00424     mbedtls_sha256_init(&ctx);
00425 
00426     if (mbedtls_sha256_starts_ret(&ctx, 0) != 0) {
00427         ret_val = -1;
00428         goto error;
00429     }
00430 
00431     if (mbedtls_sha256_update_ret(&ctx, input, network_name_len + GTK_LEN) != 0) {
00432         ret_val = -1;
00433         goto error;
00434     }
00435 
00436     uint8_t output[32];
00437 
00438     if (mbedtls_sha256_finish_ret(&ctx, output) != 0) {
00439         ret_val = -1;
00440         goto error;
00441     }
00442 
00443     memcpy(gak, &output[0], 16);
00444 
00445 error:
00446     mbedtls_sha256_free(&ctx);
00447 
00448     return ret_val;
00449 #else
00450     (void) network_name;
00451     memcpy(gak, gtk, 16);
00452     return 0;
00453 #endif
00454 }
00455 
00456 int8_t ws_pae_controller_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index)
00457 {
00458     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
00459     if (!controller) {
00460         return -1;
00461     }
00462 
00463     if (controller->pae_nw_key_index_update) {
00464         controller->pae_nw_key_index_update(interface_ptr, index);
00465     }
00466 
00467     return 0;
00468 }
00469 
00470 void ws_pae_controller_nw_keys_remove(protocol_interface_info_entry_t *interface_ptr)
00471 {
00472     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
00473     if (!controller) {
00474         return;
00475     }
00476 
00477     tr_info("NW keys remove");
00478 
00479     nw_key_t *nw_key = controller->nw_key;
00480     for (uint8_t i = 0; i < GTK_NUM; i++) {
00481         // Deletes the key if it is set
00482         if (nw_key[i].set) {
00483             tr_info("NW key remove: %i", i);
00484             if (nw_key[i].installed) {
00485                 controller->nw_key_clear(interface_ptr, i);
00486             }
00487             nw_key[i].set = false;
00488             nw_key[i].installed = false;
00489         }
00490     }
00491 }
00492 
00493 static void ws_pae_controller_nw_key_index_check_and_set(protocol_interface_info_entry_t *interface_ptr, uint8_t index)
00494 {
00495     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
00496     if (!controller) {
00497         return;
00498     }
00499 
00500     if (controller->nw_send_key_index_set) {
00501         tr_info("NW send key index set: %i", index + 1);
00502         controller->nw_send_key_index_set(interface_ptr, index);
00503         controller->gtk_index = index;
00504     }
00505 
00506     // Do not update PAN version for initial key index set
00507     if (controller->key_index_set) {
00508         if (controller->pan_ver_increment) {
00509             controller->pan_ver_increment(interface_ptr);
00510         }
00511     } else {
00512         controller->key_index_set = true;
00513     }
00514 }
00515 
00516 static void ws_pae_controller_active_nw_key_set(protocol_interface_info_entry_t *cur, uint8_t index)
00517 {
00518     pae_controller_t *controller = ws_pae_controller_get(cur);
00519     if (!controller) {
00520         return;
00521     }
00522 
00523     if (controller->nw_send_key_index_set) {
00524         /* Checks if frame counters needs to be stored for the new GTK that is taken into
00525            use; this is the last check that stored counters are in sync before activating key */
00526         ws_pae_controller_frame_counter_store(controller, true);
00527         // Activates key on MAC
00528         controller->nw_send_key_index_set(controller->interface_ptr, index);
00529         tr_info("NW send key index set: %i", index + 1);
00530         controller->gtk_index = index;
00531     }
00532 }
00533 
00534 int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr)
00535 {
00536     if (!interface_ptr) {
00537         return -1;
00538     }
00539 
00540     if (ws_pae_controller_get(interface_ptr) != NULL) {
00541         return 0;
00542     }
00543 
00544     pae_controller_t *controller = ns_dyn_mem_alloc(sizeof(pae_controller_t));
00545     void *pae_nvm_buffer = ws_pae_buffer_allocate();
00546 
00547     if (!controller || !pae_nvm_buffer) {
00548         ns_dyn_mem_free(controller);
00549         ns_dyn_mem_free(pae_nvm_buffer);
00550         return -1;
00551     }
00552 
00553     controller->interface_ptr = interface_ptr;
00554     controller->auth_completed = NULL;
00555     controller->nw_key_set = NULL;
00556     controller->nw_key_clear = NULL;
00557     controller->nw_send_key_index_set = NULL;
00558     controller->nw_frame_counter_set = NULL;
00559     controller->pan_ver_increment = NULL;
00560     controller->pae_nvm_buffer = pae_nvm_buffer;
00561 
00562     ws_pae_controller_data_init(controller);
00563 
00564     ns_list_add_to_end(&pae_controller_list, controller);
00565 
00566     return 0;
00567 }
00568 
00569 static void ws_pae_controller_data_init(pae_controller_t *controller)
00570 {
00571     memset(controller->target_eui_64, 0, 8);
00572     memset(controller->br_eui_64, 0, 8);
00573     memset(controller->gtkhash, 0, 32);
00574 
00575     ws_pae_controller_active_nw_key_clear(&controller->nw_key[0]);
00576     ws_pae_controller_active_nw_key_clear(&controller->nw_key[1]);
00577     ws_pae_controller_active_nw_key_clear(&controller->nw_key[2]);
00578     ws_pae_controller_active_nw_key_clear(&controller->nw_key[3]);
00579 
00580     controller->target_pan_id = 0xffff;
00581     controller->pae_delete = NULL;
00582     controller->pae_fast_timer = NULL;
00583     controller->pae_slow_timer = NULL;
00584     controller->pae_br_addr_write = NULL;
00585     controller->pae_br_addr_read = NULL;
00586     controller->pae_gtks_updated = NULL;
00587     controller->pae_gtk_hash_update = NULL;
00588     controller->pae_nw_key_index_update = NULL;
00589     controller->gtks_set = false;
00590     controller->gtkhash_set = false;
00591     controller->key_index_set = false;
00592     controller->gtk_index = -1;
00593     controller->network_name = NULL;
00594     controller->frame_cnt_store_timer = FRAME_COUNTER_STORE_INTERVAL;
00595     ws_pae_controller_frame_counter_reset(&controller->frame_counters);
00596     sec_prot_keys_gtks_init(&controller->gtks);
00597     sec_prot_keys_gtks_init(&controller->next_gtks);
00598     sec_prot_certs_init(&controller->certs);
00599     sec_prot_certs_ext_certificate_validation_set(&controller->certs, pae_controller_config.ext_cert_valid_enabled);
00600     ws_pae_timers_settings_init(&controller->timer_settings);
00601 }
00602 
00603 static void ws_pae_controller_frame_counter_read(pae_controller_t *controller)
00604 {
00605     // Read frame counters
00606     if (ws_pae_controller_nvm_frame_counter_read(&controller->frame_counters) >= 0) {
00607         bool updated = false;
00608         // Checks frame counters
00609         for (uint8_t index = 0; index < GTK_NUM; index++) {
00610             if (controller->frame_counters.counter[index].set) {
00611                 // Increments frame counters
00612                 controller->frame_counters.counter[index].frame_counter += FRAME_COUNTER_INCREMENT;
00613 
00614                 tr_info("Read frame counter: index %i value %"PRIu32"", index, controller->frame_counters.counter[index].frame_counter);
00615 
00616                 updated = true;
00617             }
00618         }
00619         if (updated) {
00620             // Writes incremented frame counters
00621             ws_pae_nvm_store_frame_counter_tlv_create(controller->pae_nvm_buffer, &controller->frame_counters);
00622             ws_pae_controller_nvm_frame_counter_write(controller->pae_nvm_buffer);
00623             //ws_pae_controller_frame_counter_write(controller, &controller->frame_counters);
00624         }
00625     }
00626 }
00627 
00628 static void ws_pae_controller_frame_counter_reset(frame_counters_t *frame_counters)
00629 {
00630     for (uint8_t index = 0; index < GTK_NUM; index++) {
00631         memset(frame_counters->counter[index].gtk, 0, GTK_LEN);
00632         frame_counters->counter[index].frame_counter = 0;
00633         frame_counters->counter[index].set = false;
00634     }
00635 }
00636 
00637 int8_t ws_pae_controller_supp_init(protocol_interface_info_entry_t *interface_ptr)
00638 {
00639     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
00640     if (!controller) {
00641         return -1;
00642     }
00643 
00644     if (ws_pae_supp_init(controller->interface_ptr, &controller->certs, &controller->timer_settings) < 0) {
00645         return -1;
00646     }
00647 
00648     controller->pae_delete = ws_pae_supp_delete;
00649     controller->pae_fast_timer = ws_pae_supp_fast_timer;
00650     controller->pae_slow_timer = ws_pae_supp_slow_timer;
00651     controller->pae_br_addr_write = ws_pae_supp_border_router_addr_write;
00652     controller->pae_br_addr_read = ws_pae_supp_border_router_addr_read;
00653     controller->pae_gtk_hash_update = ws_pae_supp_gtk_hash_update;
00654     controller->pae_nw_key_index_update = ws_pae_supp_nw_key_index_update;
00655 
00656     ws_pae_supp_cb_register(controller->interface_ptr, controller->auth_completed, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_active_nw_key_set);
00657 
00658     ws_pae_controller_frame_counter_read(controller);
00659 
00660     return 0;
00661 }
00662 
00663 int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_ptr)
00664 {
00665     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
00666     if (!controller) {
00667         return -1;
00668     }
00669 
00670     if (ws_pae_auth_init(controller->interface_ptr, &controller->gtks, &controller->next_gtks, &controller->certs, &controller->timer_settings) < 0) {
00671         return -1;
00672     }
00673 
00674     controller->pae_delete = ws_pae_auth_delete;
00675     controller->pae_fast_timer = ws_pae_auth_fast_timer;
00676     controller->pae_slow_timer = ws_pae_auth_slow_timer;
00677     controller->pae_gtks_updated = ws_pae_auth_gtks_updated;
00678     controller->pae_nw_key_index_update = ws_pae_auth_nw_key_index_update;
00679 
00680     ws_pae_controller_frame_counter_read(controller);
00681 
00682     return 0;
00683 }
00684 
00685 int8_t ws_pae_controller_stop(protocol_interface_info_entry_t *interface_ptr)
00686 {
00687     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
00688     if (!controller) {
00689         return -1;
00690     }
00691 
00692     // Stores frame counter
00693     ws_pae_controller_frame_counter_store(controller, false);
00694 
00695     // Removes network keys from PAE controller and MAC
00696     ws_pae_controller_nw_keys_remove(interface_ptr);
00697 
00698     // If PAE has been initialized, deletes it
00699     if (controller->pae_delete) {
00700         controller->pae_delete(interface_ptr);
00701     }
00702 
00703     // Free data
00704     sec_prot_certs_delete(&controller->certs);
00705 
00706     // Init controller data
00707     ws_pae_controller_data_init(controller);
00708 
00709     return 0;
00710 }
00711 
00712 int8_t ws_pae_controller_delete(protocol_interface_info_entry_t *interface_ptr)
00713 {
00714     if (!interface_ptr) {
00715         return -1;
00716     }
00717 
00718     ws_pae_controller_stop(interface_ptr);
00719 
00720     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
00721     if (!controller) {
00722         return -1;
00723     }
00724 
00725     ns_list_remove(&pae_controller_list, controller);
00726     ns_dyn_mem_free(controller->pae_nvm_buffer);
00727     ns_dyn_mem_free(controller);
00728 
00729     return 0;
00730 }
00731 
00732 int8_t ws_pae_controller_timing_adjust(uint8_t timing)
00733 {
00734     ws_pae_supp_timing_adjust(timing);
00735     ws_pae_auth_timing_adjust(timing);
00736     return 0;
00737 }
00738 
00739 int8_t ws_pae_controller_certificate_chain_set(const arm_certificate_chain_entry_s *new_chain)
00740 {
00741     if (!new_chain) {
00742         return -1;
00743     }
00744 
00745     ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
00746         // Delete previous information
00747         sec_prot_certs_delete(&entry->certs);
00748 
00749         // Adds a trusted certificate from index 0
00750         if (new_chain->cert_chain[0]) {
00751             cert_chain_entry_t *root_ca_chain = sec_prot_certs_chain_entry_create();
00752             sec_prot_certs_cert_set(root_ca_chain, 0, (uint8_t *) new_chain->cert_chain[0], new_chain->cert_len[0]);
00753             sec_prot_certs_chain_list_add(&entry->certs.trusted_cert_chain_list, root_ca_chain);
00754         }
00755 
00756         // Adds own certificate chain from indexes 1 to 3
00757         for (uint8_t i = 1; i < SEC_PROT_CERT_CHAIN_DEPTH; i++) {
00758             if (new_chain->cert_chain[i]) {
00759                 sec_prot_certs_cert_set(&entry->certs.own_cert_chain, i - 1, (uint8_t *) new_chain->cert_chain[i], new_chain->cert_len[i]);
00760                 if (new_chain->key_chain[i]) {
00761                     // Will be the key from top certificate in chain after all certificates are added
00762                     uint8_t key_len = strlen((char *) new_chain->key_chain[i]) + 1;
00763                     sec_prot_certs_priv_key_set(&entry->certs.own_cert_chain, (uint8_t *) new_chain->key_chain[i], key_len);
00764                 }
00765             }
00766         }
00767 
00768         // Updates the length of own certificates
00769         entry->certs.own_cert_chain_len = sec_prot_certs_cert_chain_entry_len_get(&entry->certs.own_cert_chain);
00770     }
00771 
00772     return 0;
00773 }
00774 
00775 int8_t ws_pae_controller_own_certificate_add(const arm_certificate_entry_s *cert)
00776 {
00777     if (!cert) {
00778         return -1;
00779     }
00780 
00781     int8_t ret = -1;
00782 
00783     ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
00784         for (uint8_t i = 0; i < SEC_PROT_CERT_CHAIN_DEPTH; i++) {
00785             if (entry->certs.own_cert_chain.cert[i] == NULL) {
00786                 sec_prot_certs_cert_set(&entry->certs.own_cert_chain, i, (uint8_t *) cert->cert, cert->cert_len);
00787                 // Set private key if set for the certificate that is added
00788                 if (cert->key && cert->key_len > 0) {
00789                     sec_prot_certs_priv_key_set(&entry->certs.own_cert_chain, (uint8_t *) cert->key, cert->key_len);
00790                 }
00791                 ret = 0;
00792                 break;
00793             }
00794         }
00795         // Updates the length of own certificates
00796         entry->certs.own_cert_chain_len = sec_prot_certs_cert_chain_entry_len_get(&entry->certs.own_cert_chain);
00797     }
00798 
00799     return ret;
00800 }
00801 
00802 int8_t ws_pae_controller_own_certificates_remove(void)
00803 {
00804     ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
00805         sec_prot_certs_chain_entry_init(&entry->certs.own_cert_chain);
00806         entry->certs.own_cert_chain_len = 0;
00807     }
00808 
00809     return 0;
00810 }
00811 
00812 int8_t ws_pae_controller_trusted_certificate_add(const arm_certificate_entry_s *cert)
00813 {
00814     if (!cert) {
00815         return -1;
00816     }
00817 
00818     int8_t ret = -1;
00819 
00820     ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
00821         cert_chain_entry_t *trusted_cert = sec_prot_certs_chain_entry_create();
00822         sec_prot_certs_cert_set(trusted_cert, 0, (uint8_t *) cert->cert, cert->cert_len);
00823 
00824         if (sec_prot_certs_chain_list_entry_find(&entry->certs.trusted_cert_chain_list, trusted_cert)) {
00825             sec_prot_certs_chain_entry_delete(trusted_cert);
00826             continue;
00827         }
00828         sec_prot_certs_chain_list_add(&entry->certs.trusted_cert_chain_list, trusted_cert);
00829         ret = 0;
00830     }
00831 
00832     return ret;
00833 }
00834 
00835 int8_t ws_pae_controller_trusted_certificate_remove(const arm_certificate_entry_s *cert)
00836 {
00837     if (!cert) {
00838         return -1;
00839     }
00840 
00841     int8_t ret = -1;
00842 
00843     cert_chain_entry_t *trusted_cert = sec_prot_certs_chain_entry_create();
00844     sec_prot_certs_cert_set(trusted_cert, 0, (uint8_t *) cert->cert, cert->cert_len);
00845 
00846     ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
00847         cert_chain_entry_t *removed_cert = sec_prot_certs_chain_list_entry_find(&entry->certs.trusted_cert_chain_list, trusted_cert);
00848         if (removed_cert) {
00849             sec_prot_certs_chain_list_entry_delete(&entry->certs.trusted_cert_chain_list, removed_cert);
00850             ret = 0;
00851         }
00852     }
00853 
00854     sec_prot_certs_chain_entry_delete(trusted_cert);
00855 
00856     return ret;
00857 }
00858 
00859 int8_t ws_pae_controller_trusted_certificates_remove(void)
00860 {
00861     ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
00862         sec_prot_certs_chain_list_delete(&entry->certs.trusted_cert_chain_list);
00863     }
00864 
00865     return 0;
00866 }
00867 
00868 int8_t ws_pae_controller_certificate_revocation_list_add(const arm_cert_revocation_list_entry_s *crl)
00869 {
00870     if (!crl) {
00871         return -1;
00872     }
00873 
00874     int8_t ret = -1;
00875 
00876     ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
00877         cert_revocat_list_entry_t *cert_revoc_list = sec_prot_certs_revocat_list_entry_create();
00878         sec_prot_certs_revocat_list_set(cert_revoc_list, crl->crl, crl->crl_len);
00879 
00880         if (sec_prot_certs_revocat_lists_entry_find(&entry->certs.cert_revocat_lists, cert_revoc_list)) {
00881             sec_prot_certs_revocat_list_entry_delete(cert_revoc_list);
00882             continue;
00883         }
00884 
00885         sec_prot_certs_revocat_lists_add(&entry->certs.cert_revocat_lists, cert_revoc_list);
00886         ret = 0;
00887     }
00888 
00889     return ret;
00890 }
00891 
00892 int8_t ws_pae_controller_certificate_revocation_list_remove(const arm_cert_revocation_list_entry_s *crl)
00893 {
00894     if (!crl) {
00895         return -1;
00896     }
00897 
00898     int8_t ret = -1;
00899 
00900     cert_revocat_list_entry_t *cert_revoc_list = sec_prot_certs_revocat_list_entry_create();
00901     sec_prot_certs_revocat_list_set(cert_revoc_list, crl->crl, crl->crl_len);
00902 
00903     ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
00904         cert_revocat_list_entry_t *removed_cert_revoc_list = sec_prot_certs_revocat_lists_entry_find(&entry->certs.cert_revocat_lists, cert_revoc_list);
00905         if (removed_cert_revoc_list) {
00906             sec_prot_certs_revocat_lists_entry_delete(&entry->certs.cert_revocat_lists, removed_cert_revoc_list);
00907             ret = 0;
00908         }
00909     }
00910 
00911     sec_prot_certs_revocat_list_entry_delete(cert_revoc_list);
00912 
00913     return ret;
00914 }
00915 
00916 int8_t ws_pae_controller_border_router_addr_write(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64)
00917 {
00918     if (!eui_64) {
00919         return -1;
00920     }
00921 
00922     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
00923     if (!controller) {
00924         return -1;
00925     }
00926 
00927     if (controller->pae_br_addr_write) {
00928         return controller->pae_br_addr_write(interface_ptr, eui_64);
00929     } else {
00930         memcpy(controller->br_eui_64, eui_64, 8);
00931     }
00932 
00933     return 0;
00934 }
00935 
00936 int8_t ws_pae_controller_border_router_addr_read(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64)
00937 {
00938     if (!eui_64) {
00939         return -1;
00940     }
00941 
00942     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
00943     if (!controller) {
00944         return -1;
00945     }
00946 
00947     if (controller->pae_br_addr_read) {
00948         return controller->pae_br_addr_read(interface_ptr, eui_64);
00949     } else {
00950         memcpy(eui_64, controller->br_eui_64, 8);
00951     }
00952 
00953     return 0;
00954 }
00955 
00956 int8_t ws_pae_controller_gtk_update(int8_t interface_id, uint8_t *gtk[GTK_NUM])
00957 {
00958     if (!gtk) {
00959         return -1;
00960     }
00961 
00962     pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
00963     if (!controller) {
00964         return -1;
00965     }
00966 
00967     // Removes keys set as not used
00968     for (uint8_t i = 0; i < GTK_NUM; i++) {
00969         if (!gtk[i]) {
00970             sec_prot_keys_gtk_clear(&controller->gtks, i);
00971         }
00972     }
00973 
00974     // Inserts new keys
00975     for (uint8_t i = 0; i < GTK_NUM; i++) {
00976         if (gtk[i]) {
00977             uint32_t lifetime = sec_prot_keys_gtk_install_order_last_lifetime_get(&controller->gtks);
00978             lifetime += controller->timer_settings.gtk_expire_offset;
00979             if (sec_prot_keys_gtk_set(&controller->gtks, i, gtk[i], lifetime) >= 0) {
00980                 controller->gtks_set = true;
00981                 tr_info("GTK set index: %i, lifetime %"PRIu32", system time: %"PRIu32"", i, lifetime, protocol_core_monotonic_time / 10);
00982             }
00983         }
00984     }
00985 
00986     // Notifies PAE authenticator that GTKs have been updated */
00987     if (controller->pae_gtks_updated) {
00988         controller->pae_gtks_updated(controller->interface_ptr);
00989     }
00990 
00991     return 0;
00992 }
00993 
00994 int8_t ws_pae_controller_next_gtk_update(int8_t interface_id, uint8_t *gtk[GTK_NUM])
00995 {
00996     if (!gtk) {
00997         return -1;
00998     }
00999 
01000     pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
01001     if (!controller) {
01002         return -1;
01003     }
01004 
01005     // Inserts new keys and removed keys set as not used
01006     for (uint8_t i = 0; i < GTK_NUM; i++) {
01007         if (gtk[i]) {
01008             sec_prot_keys_gtk_set(&controller->next_gtks, i, gtk[i], 0);
01009         } else {
01010             sec_prot_keys_gtk_clear(&controller->next_gtks, i);
01011         }
01012     }
01013 
01014     return 0;
01015 }
01016 
01017 int8_t ws_pae_controller_active_key_update(int8_t interface_id, uint8_t index)
01018 {
01019     pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
01020     if (!controller) {
01021         return -1;
01022     }
01023 
01024     controller->gtk_index = index;
01025 
01026     if (controller->pae_nw_key_index_update) {
01027         controller->pae_nw_key_index_update(controller->interface_ptr, index);
01028     }
01029 
01030     return 0;
01031 }
01032 
01033 int8_t ws_pae_controller_key_lifetime_update(int8_t interface_id, uint32_t gtk_lifetime, uint32_t pmk_lifetime, uint32_t ptk_lifetime)
01034 {
01035     pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
01036     if (!controller) {
01037         return -1;
01038     }
01039 
01040     ws_pae_timers_lifetime_set(&controller->timer_settings, gtk_lifetime, pmk_lifetime, ptk_lifetime);
01041 
01042     return 0;
01043 }
01044 
01045 int8_t ws_pae_controller_gtk_time_settings_update(int8_t interface_id, uint8_t revocat_lifetime_reduct, uint8_t new_activation_time, uint8_t new_install_req, uint32_t max_mismatch)
01046 {
01047     pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
01048     if (!controller) {
01049         return -1;
01050     }
01051 
01052     ws_pae_timers_gtk_time_settings_set(&controller->timer_settings, revocat_lifetime_reduct, new_activation_time, new_install_req, max_mismatch);
01053 
01054     return 0;
01055 }
01056 
01057 int8_t ws_pae_controller_node_keys_remove(int8_t interface_id, uint8_t *eui_64)
01058 {
01059 #ifndef HAVE_PAE_AUTH
01060     (void) eui_64;
01061 #endif
01062 
01063     pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
01064     if (!controller) {
01065         return -1;
01066     }
01067 
01068     return ws_pae_auth_node_keys_remove(controller->interface_ptr, eui_64);
01069 }
01070 
01071 int8_t ws_pae_controller_node_access_revoke_start(int8_t interface_id)
01072 {
01073     pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
01074     if (!controller) {
01075         return -1;
01076     }
01077 
01078     ws_pae_auth_node_access_revoke_start(controller->interface_ptr);
01079 
01080     return -1;
01081 }
01082 
01083 int8_t ws_pae_controller_node_limit_set(int8_t interface_id, uint16_t limit)
01084 {
01085 #ifdef HAVE_PAE_AUTH
01086     pae_controller_config.node_limit = limit;
01087     pae_controller_config.node_limit_set = true;
01088 
01089     pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
01090     if (!controller) {
01091         return -1;
01092     }
01093 
01094     ws_pae_auth_node_limit_set(controller->interface_ptr, limit);
01095 
01096     return 0;
01097 #else
01098     (void) interface_id;
01099     (void) limit;
01100     return -1;
01101 #endif
01102 }
01103 
01104 int8_t ws_pae_controller_ext_certificate_validation_set(int8_t interface_id, bool enabled)
01105 {
01106 #ifdef HAVE_PAE_AUTH
01107     pae_controller_config.ext_cert_valid_enabled = enabled;
01108 
01109     pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
01110     if (!controller) {
01111         return -1;
01112     }
01113 
01114     sec_prot_certs_ext_certificate_validation_set(&controller->certs, enabled);
01115 
01116     return 0;
01117 #else
01118     (void) interface_id;
01119     (void) enabled;
01120     return -1;
01121 #endif
01122 }
01123 
01124 void ws_pae_controller_forced_gc(bool full_gc)
01125 {
01126     /* Purge only when on critical limit since node limit should handle limiting
01127        of entries in normal case */
01128     if (!full_gc) {
01129         return;
01130     }
01131 
01132     // Purge authenticators for each interface
01133     ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
01134         ws_pae_auth_forced_gc(entry->interface_ptr);
01135     }
01136 }
01137 
01138 static void ws_pae_controller_gtk_hash_set(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash)
01139 {
01140     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
01141     if (!controller) {
01142         return;
01143     }
01144 
01145     memcpy(controller->gtkhash, gtkhash, 32);
01146 
01147     tr_info("GTK hash set %s %s %s %s",
01148             trace_array(&gtkhash[0], 8),
01149             trace_array(&gtkhash[8], 8),
01150             trace_array(&gtkhash[16], 8),
01151             trace_array(&gtkhash[24], 8));
01152 
01153     // Do not update PAN version for initial hash set
01154     if (controller->gtkhash_set) {
01155         if (controller->pan_ver_increment) {
01156             controller->pan_ver_increment(interface_ptr);
01157         }
01158     } else {
01159         controller->gtkhash_set = true;
01160     }
01161 }
01162 
01163 uint8_t *ws_pae_controller_gtk_hash_ptr_get(protocol_interface_info_entry_t *interface_ptr)
01164 {
01165     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
01166     if (!controller) {
01167         return NULL;
01168     }
01169 
01170     return controller->gtkhash;
01171 }
01172 
01173 int8_t ws_pae_controller_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash)
01174 {
01175     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
01176     if (!controller) {
01177         return -1;
01178     }
01179 
01180     memcpy(controller->gtkhash, gtkhash, 32);
01181 
01182     if (controller->pae_gtk_hash_update) {
01183         return controller->pae_gtk_hash_update(interface_ptr, gtkhash);
01184     }
01185 
01186     return 0;
01187 }
01188 
01189 void ws_pae_controller_fast_timer(uint16_t ticks)
01190 {
01191     ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
01192         if (entry->pae_fast_timer) {
01193             entry->pae_fast_timer(ticks);
01194         }
01195     }
01196 }
01197 
01198 void ws_pae_controller_slow_timer(uint16_t seconds)
01199 {
01200     ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
01201         if (entry->pae_slow_timer) {
01202             entry->pae_slow_timer(seconds);
01203         }
01204         ws_pae_controller_frame_counter_timer(seconds, entry);
01205     }
01206 }
01207 
01208 static void ws_pae_controller_frame_counter_timer(uint16_t seconds, pae_controller_t *entry)
01209 {
01210     if (entry->frame_cnt_store_timer > seconds) {
01211         entry->frame_cnt_store_timer -= seconds;
01212     } else {
01213         entry->frame_cnt_store_timer = FRAME_COUNTER_STORE_INTERVAL;
01214         ws_pae_controller_frame_counter_store(entry, true);
01215     }
01216 }
01217 
01218 static void ws_pae_controller_frame_counter_timer_trigger(uint16_t seconds, pae_controller_t *entry)
01219 {
01220     if (entry->frame_cnt_store_timer > seconds) {
01221         entry->frame_cnt_store_timer = seconds;
01222     }
01223 }
01224 
01225 static void ws_pae_controller_frame_counter_store(pae_controller_t *entry, bool use_threshold)
01226 {
01227     bool update_needed = false;
01228 
01229     for (int i = 0; i < GTK_NUM; i++) {
01230         /* If network key is set, checks if frame counter needs to be updated to NVM
01231          * Note! The frame counters for non-installed keys (previous frame counters) are not changed.
01232          *       This is because GTKs are removed e.g. if PAN configuration is not heard/cannot be
01233          *       de-crypted during a bootstrap. If BR later installs previous keys using 4WH/GKH, the
01234          *       frame counters will be still valid.
01235          */
01236         if (entry->nw_key[i].installed) {
01237             // Reads frame counter for the key
01238             uint32_t curr_frame_counter;
01239             entry->nw_frame_counter_read(entry->interface_ptr, &curr_frame_counter, i);
01240 
01241             // If frame counter for the network key has already been stored
01242             if (entry->frame_counters.counter[i].set &&
01243                     memcmp(entry->nw_key[i].gtk, entry->frame_counters.counter[i].gtk, GTK_LEN) == 0) {
01244                 // If threshold check is disabled or frame counter has advanced for the threshold value, stores the new value
01245                 if (!use_threshold ||
01246                         curr_frame_counter > entry->frame_counters.counter[i].frame_counter + FRAME_COUNTER_STORE_THRESHOLD) {
01247                     entry->frame_counters.counter[i].frame_counter = curr_frame_counter;
01248                     update_needed = true;
01249                     tr_debug("Stored updated frame counter: index %i value %"PRIu32"", i, curr_frame_counter);
01250                 }
01251             } else {
01252                 // For new or modified network keys, stores the frame counter value
01253                 entry->frame_counters.counter[i].set = true;
01254                 memcpy(entry->frame_counters.counter[i].gtk, entry->nw_key[i].gtk, GTK_LEN);
01255                 entry->frame_counters.counter[i].frame_counter = curr_frame_counter;
01256                 update_needed = true;
01257                 tr_debug("Stored new frame counter: index %i value %"PRIu32"", i, curr_frame_counter);
01258             }
01259         }
01260     }
01261 
01262     if (update_needed) {
01263         tr_debug("Write frame counters: system time %"PRIu32"", protocol_core_monotonic_time / 10);
01264         // Writes modified frame counters
01265         ws_pae_nvm_store_frame_counter_tlv_create(entry->pae_nvm_buffer, &entry->frame_counters);
01266         ws_pae_controller_nvm_frame_counter_write(entry->pae_nvm_buffer);
01267     }
01268 }
01269 
01270 static int8_t ws_pae_controller_nvm_frame_counter_read(frame_counters_t *counters)
01271 {
01272     nvm_tlv_list_t tlv_list;
01273     ns_list_init(&tlv_list);
01274 
01275     if (ws_pae_nvm_store_tlv_file_read(FRAME_COUNTER_FILE, &tlv_list) < 0) {
01276         return -1;
01277     }
01278 
01279     int8_t result = -1;
01280     ns_list_foreach_safe(nvm_tlv_entry_t, entry, &tlv_list) {
01281         if (ws_pae_nvm_store_frame_counter_tlv_read(entry, counters) >= 0) {
01282             result = 0;
01283         }
01284         ns_list_remove(&tlv_list, entry);
01285         ns_dyn_mem_free(entry);
01286     }
01287 
01288     return result;
01289 }
01290 
01291 static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr)
01292 {
01293     ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
01294         if (entry->interface_ptr == interface_ptr) {
01295             return entry;
01296         }
01297     }
01298 
01299     return NULL;
01300 }
01301 
01302 static pae_controller_t *ws_pae_controller_get_or_create(int8_t interface_id)
01303 {
01304     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
01305     if (!cur) {
01306         return NULL;
01307     }
01308 
01309     pae_controller_t *controller = ws_pae_controller_get(cur);
01310 
01311     if (!controller) {
01312         if (ws_pae_controller_init(cur) < 0) {
01313             return NULL;
01314         }
01315         controller = ws_pae_controller_get(cur);
01316     }
01317 
01318     return controller;
01319 }
01320 
01321 nvm_tlv_entry_t *ws_pae_controller_nvm_tlv_get(protocol_interface_info_entry_t *interface_ptr)
01322 {
01323     pae_controller_t *controller = ws_pae_controller_get(interface_ptr);
01324     if (!controller) {
01325         return NULL;
01326     }
01327 
01328     return controller->pae_nvm_buffer;
01329 }
01330 
01331 static void ws_pae_controller_nvm_frame_counter_write(nvm_tlv_entry_t *tlv_entry)
01332 {
01333     nvm_tlv_list_t tlv_list;
01334     ns_list_init(&tlv_list);
01335     ns_list_add_to_end(&tlv_list, tlv_entry);
01336     ws_pae_nvm_store_tlv_file_write(FRAME_COUNTER_FILE, &tlv_list);
01337 
01338 }
01339 
01340 #endif /* HAVE_WS */
01341