Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sec_prot_keys.c Source File

sec_prot_keys.c

00001 /*
00002  * Copyright (c) 2016-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 "NWK_INTERFACE/Include/protocol.h"
00025 #include "Common_Protocols/ipv6_constants.h"
00026 #include "socket_api.h"
00027 #include "6LoWPAN/ws/ws_config.h"
00028 #include "Security/kmp/kmp_addr.h"
00029 #include "Security/kmp/kmp_api.h"
00030 #include "Security/PANA/pana_eap_header.h"
00031 #include "Security/eapol/eapol_helper.h"
00032 #include "Security/protocols/sec_prot_certs.h"
00033 #include "Security/protocols/sec_prot_keys.h"
00034 #include "Security/protocols/sec_prot.h"
00035 #include "Security/protocols/sec_prot_lib.h"
00036 
00037 #ifdef HAVE_WS
00038 
00039 #define TRACE_GROUP "spke"
00040 
00041 sec_prot_keys_t *sec_prot_keys_create(sec_prot_gtk_keys_t *gtks, const sec_prot_certs_t *certs)
00042 {
00043     sec_prot_keys_t *sec_keys = ns_dyn_mem_alloc(sizeof(sec_prot_keys_t));
00044     if (!sec_keys) {
00045         return NULL;
00046     }
00047 
00048     sec_prot_keys_init(sec_keys, gtks, certs);
00049 
00050     return sec_keys;
00051 }
00052 
00053 void sec_prot_keys_init(sec_prot_keys_t *sec_keys, sec_prot_gtk_keys_t *gtks, const sec_prot_certs_t *certs)
00054 {
00055     memset(sec_keys, 0, sizeof(sec_prot_keys_t));
00056     sec_keys->pmk_lifetime = PMK_LIFETIME_INSTALL;
00057     sec_keys->ptk_lifetime = PTK_LIFETIME_INSTALL;
00058     sec_keys->pmk_key_replay_cnt = 0;
00059     sec_keys->gtks = gtks;
00060     sec_keys->certs = certs;
00061     sec_keys->gtkl = 0;
00062     sec_keys->gtk_set_index = -1;
00063     sec_keys->pmk_set = false;
00064     sec_keys->ptk_set = false;
00065     sec_keys->pmk_key_replay_cnt_set = false;
00066     sec_keys->updated = false;
00067     sec_keys->ptk_eui_64_set = false;
00068     sec_keys->pmk_mismatch = false;
00069     sec_keys->ptk_mismatch = false;
00070 }
00071 
00072 void sec_prot_keys_delete(sec_prot_keys_t *sec_keys)
00073 {
00074     ns_dyn_mem_free(sec_keys);
00075 }
00076 
00077 sec_prot_gtk_keys_t *sec_prot_keys_gtks_create(void)
00078 {
00079     sec_prot_gtk_keys_t *gtks = ns_dyn_mem_alloc(sizeof(sec_prot_gtk_keys_t));
00080     if (!gtks) {
00081         return NULL;
00082     }
00083 
00084     sec_prot_keys_gtks_init(gtks);
00085 
00086     return gtks;
00087 }
00088 
00089 void sec_prot_keys_gtks_init(sec_prot_gtk_keys_t *gtks)
00090 {
00091     memset(gtks, 0, sizeof(sec_prot_gtk_keys_t));
00092     gtks->updated = false;
00093 }
00094 
00095 void sec_prot_keys_gtks_delete(sec_prot_gtk_keys_t *gtks)
00096 {
00097     ns_dyn_mem_free(gtks);
00098 }
00099 
00100 void sec_prot_keys_pmk_write(sec_prot_keys_t *sec_keys, uint8_t *pmk)
00101 {
00102     memcpy(sec_keys->pmk, pmk, PMK_LEN);
00103     sec_keys->pmk_key_replay_cnt = 0;
00104     sec_keys->pmk_key_replay_cnt_set = false;
00105     sec_keys->pmk_lifetime = PMK_LIFETIME_INSTALL;
00106     sec_keys->pmk_set = true;
00107     sec_keys->updated = true;
00108 }
00109 
00110 void sec_prot_keys_pmk_delete(sec_prot_keys_t *sec_keys)
00111 {
00112     memset(sec_keys->pmk, 0, PMK_LEN);
00113     sec_keys->pmk_key_replay_cnt = 0;
00114     sec_keys->pmk_key_replay_cnt_set = false;
00115     sec_keys->pmk_lifetime = PMK_LIFETIME_INSTALL;
00116     sec_keys->pmk_set = false;
00117     sec_keys->updated = true;
00118 }
00119 
00120 uint8_t *sec_prot_keys_pmk_get(sec_prot_keys_t *sec_keys)
00121 {
00122     if (!sec_keys->pmk_set) {
00123         return NULL;
00124     }
00125 
00126     return sec_keys->pmk;
00127 }
00128 
00129 uint64_t sec_prot_keys_pmk_replay_cnt_get(sec_prot_keys_t *sec_keys)
00130 {
00131     return sec_keys->pmk_key_replay_cnt;
00132 }
00133 
00134 void sec_prot_keys_pmk_replay_cnt_set(sec_prot_keys_t *sec_keys, uint64_t counter)
00135 {
00136     sec_keys->pmk_key_replay_cnt_set = true;
00137     sec_keys->pmk_key_replay_cnt = counter;
00138 }
00139 
00140 void sec_prot_keys_pmk_replay_cnt_increment(sec_prot_keys_t *sec_keys)
00141 {
00142     // Start from zero i.e. does not increment on first call
00143     if (!sec_keys->pmk_key_replay_cnt_set) {
00144         sec_keys->pmk_key_replay_cnt_set = true;
00145         return;
00146     }
00147     sec_keys->pmk_key_replay_cnt++;
00148 }
00149 
00150 bool sec_prot_keys_pmk_replay_cnt_compare(uint64_t received_counter, sec_prot_keys_t *sec_keys)
00151 {
00152     // If previous value is set must be greater
00153     if (sec_keys->pmk_key_replay_cnt_set && received_counter > sec_keys->pmk_key_replay_cnt) {
00154         return true;
00155     } else if (!sec_keys->pmk_key_replay_cnt_set && received_counter >= sec_keys->pmk_key_replay_cnt) {
00156         // Otherwise allows also same value e.g. zero
00157         return true;
00158     }
00159 
00160     return false;
00161 }
00162 
00163 void sec_prot_keys_pmk_mismatch_set(sec_prot_keys_t *sec_keys)
00164 {
00165     sec_keys->pmk_mismatch = true;
00166 }
00167 
00168 void sec_prot_keys_pmk_mismatch_reset(sec_prot_keys_t *sec_keys)
00169 {
00170     sec_keys->pmk_mismatch = false;
00171 }
00172 
00173 bool sec_prot_keys_pmk_mismatch_is_set(sec_prot_keys_t *sec_keys)
00174 {
00175     return sec_keys->pmk_mismatch;
00176 }
00177 
00178 bool sec_prot_keys_pmk_lifetime_decrement(sec_prot_keys_t *sec_keys, uint32_t default_lifetime, uint8_t seconds)
00179 {
00180     if (!sec_keys->pmk_set) {
00181         return false;
00182     }
00183 
00184     if (sec_keys->pmk_lifetime == PMK_LIFETIME_INSTALL) {
00185         sec_keys->pmk_lifetime = default_lifetime;
00186     }
00187 
00188     if (sec_keys->pmk_lifetime > seconds) {
00189         sec_keys->pmk_lifetime -= seconds;
00190     } else {
00191         if (sec_keys->pmk_lifetime > 0) {
00192             sec_keys->pmk_lifetime = 0;
00193             sec_prot_keys_ptk_delete(sec_keys);
00194             sec_prot_keys_pmk_delete(sec_keys);
00195             return true;
00196         }
00197     }
00198     return false;
00199 }
00200 
00201 void sec_prot_keys_ptk_write(sec_prot_keys_t *sec_keys, uint8_t *ptk)
00202 {
00203     memcpy(sec_keys->ptk, ptk, PTK_LEN);
00204     sec_keys->ptk_lifetime = PTK_LIFETIME_INSTALL;
00205     sec_keys->ptk_set = true;
00206     sec_keys->updated = true;
00207 }
00208 
00209 void sec_prot_keys_ptk_delete(sec_prot_keys_t *sec_keys)
00210 {
00211     memset(sec_keys->ptk, 0, PTK_LEN);
00212     sec_keys->ptk_lifetime = PTK_LIFETIME_INSTALL;
00213     sec_keys->ptk_set = false;
00214     sec_keys->updated = true;
00215 }
00216 
00217 uint8_t *sec_prot_keys_ptk_get(sec_prot_keys_t *sec_keys)
00218 {
00219     if (!sec_keys->ptk_set) {
00220         return NULL;
00221     }
00222 
00223     return sec_keys->ptk;
00224 }
00225 
00226 void sec_prot_keys_ptk_mismatch_set(sec_prot_keys_t *sec_keys)
00227 {
00228     sec_keys->ptk_mismatch = true;
00229 }
00230 
00231 void sec_prot_keys_ptk_mismatch_reset(sec_prot_keys_t *sec_keys)
00232 {
00233     sec_keys->ptk_mismatch = false;
00234 }
00235 
00236 bool sec_prot_keys_ptk_mismatch_is_set(sec_prot_keys_t *sec_keys)
00237 {
00238     return sec_keys->ptk_mismatch;
00239 }
00240 
00241 void sec_prot_keys_ptk_eui_64_write(sec_prot_keys_t *sec_keys, const uint8_t *eui_64)
00242 {
00243     memcpy(sec_keys->ptk_eui_64, eui_64, 8);
00244     sec_keys->ptk_eui_64_set = true;
00245     sec_keys->updated = true;
00246 }
00247 
00248 uint8_t *sec_prot_keys_ptk_eui_64_get(sec_prot_keys_t *sec_keys)
00249 {
00250     if (!sec_keys->ptk_eui_64_set) {
00251         return NULL;
00252     }
00253 
00254     return sec_keys->ptk_eui_64;
00255 }
00256 
00257 void sec_prot_keys_ptk_eui_64_delete(sec_prot_keys_t *sec_keys)
00258 {
00259     memset(sec_keys->ptk_eui_64, 0, 8);
00260     sec_keys->ptk_eui_64_set = false;
00261     sec_keys->updated = true;
00262 }
00263 
00264 bool sec_prot_keys_ptk_lifetime_decrement(sec_prot_keys_t *sec_keys, uint32_t default_lifetime, uint8_t seconds)
00265 {
00266     if (!sec_keys->ptk_set) {
00267         return false;
00268     }
00269 
00270     if (sec_keys->ptk_lifetime == PTK_LIFETIME_INSTALL) {
00271         sec_keys->ptk_lifetime = default_lifetime;
00272     }
00273 
00274     if (sec_keys->ptk_lifetime > seconds) {
00275         sec_keys->ptk_lifetime -= seconds;
00276     } else {
00277         if (sec_keys->ptk_lifetime > 0) {
00278             sec_prot_keys_ptk_delete(sec_keys);
00279             sec_keys->ptk_lifetime = 0;
00280             return true;
00281         }
00282     }
00283     return false;
00284 }
00285 
00286 bool sec_prot_keys_are_updated(sec_prot_keys_t *sec_keys)
00287 {
00288     return sec_keys->updated;
00289 }
00290 
00291 void sec_prot_keys_updated_reset(sec_prot_keys_t *sec_keys)
00292 {
00293     sec_keys->updated = false;
00294 }
00295 
00296 uint8_t sec_prot_keys_fresh_gtkl_get(sec_prot_gtk_keys_t *gtks)
00297 {
00298     uint8_t gtkl = 0;
00299 
00300     for (uint8_t i = 0; i < GTK_NUM; i++) {
00301         if (sec_prot_keys_gtk_status_is_live(gtks, i)) {
00302             gtkl |= 1 << i;
00303         }
00304     }
00305 
00306     return gtkl;
00307 }
00308 
00309 void sec_prot_keys_gtkl_set(sec_prot_keys_t *sec_keys, uint8_t gtkl)
00310 {
00311     sec_keys->gtkl = gtkl;
00312 }
00313 
00314 bool sec_prot_keys_gtkl_gtk_is_live(sec_prot_keys_t *sec_keys, uint8_t index)
00315 {
00316     if (index >= GTK_NUM) {
00317         return false;
00318     }
00319 
00320     if (sec_keys->gtkl & (1 << index)) {
00321         return true;
00322     }
00323 
00324     return false;
00325 }
00326 
00327 int8_t sec_prot_keys_gtkl_gtk_live_set(sec_prot_keys_t *sec_keys, uint8_t index)
00328 {
00329     if (index >= GTK_NUM) {
00330         return -1;
00331     }
00332 
00333     sec_keys->gtkl |= (1 << index);
00334 
00335     return 0;
00336 }
00337 
00338 int8_t sec_prot_keys_gtk_insert_index_set(sec_prot_keys_t *sec_keys, uint8_t index)
00339 {
00340     if (index >= GTK_NUM || !sec_keys->gtks->gtk[index].set) {
00341         return -1;
00342     }
00343 
00344     sec_keys->gtk_set_index = index;
00345     return 0;
00346 }
00347 
00348 int8_t sec_prot_keys_gtk_insert_index_get(sec_prot_keys_t *sec_keys)
00349 {
00350     return sec_keys->gtk_set_index;
00351 }
00352 
00353 void sec_prot_keys_gtk_insert_index_clear(sec_prot_keys_t *sec_keys)
00354 {
00355     sec_keys->gtk_set_index = -1;
00356 }
00357 
00358 void sec_prot_keys_gtkl_from_gtk_insert_index_set(sec_prot_keys_t *sec_keys)
00359 {
00360     if (sec_keys->gtk_set_index >= 0) {
00361         sec_prot_keys_gtkl_gtk_live_set(sec_keys, sec_keys->gtk_set_index);
00362         sec_prot_keys_gtk_insert_index_clear(sec_keys);
00363     }
00364 }
00365 
00366 int8_t sec_prot_keys_gtk_insert_index_from_gtkl_get(sec_prot_keys_t *sec_keys)
00367 {
00368     // Get currently active key index
00369     int8_t active_index = sec_prot_keys_gtk_status_active_get(sec_keys->gtks);
00370 
00371     if (active_index >= 0 && !sec_prot_keys_gtkl_gtk_is_live(sec_keys, active_index)) {
00372         // If currently active key is not live on remote, inserts it
00373         sec_prot_keys_gtk_insert_index_set(sec_keys, active_index);
00374         return active_index;
00375     }
00376 
00377     // Checks all keys
00378     for (uint8_t i = 0; i < GTK_NUM; i++) {
00379         if (sec_prot_keys_gtk_status_is_live(sec_keys->gtks, i)) {
00380             // If key is live, but not indicated on GTKL inserts it
00381             if (!sec_prot_keys_gtkl_gtk_is_live(sec_keys, i)) {
00382                 sec_prot_keys_gtk_insert_index_set(sec_keys, i);
00383                 return i;
00384             }
00385         }
00386     }
00387 
00388     return -1;
00389 }
00390 
00391 uint8_t *sec_prot_keys_get_gtk_to_insert(sec_prot_keys_t *sec_keys, uint8_t *index)
00392 {
00393     if (sec_keys->gtk_set_index >= 0 && sec_keys->gtks->gtk[sec_keys->gtk_set_index].set) {
00394         *index = sec_keys->gtk_set_index;
00395         return sec_keys->gtks->gtk[sec_keys->gtk_set_index].key;
00396     } else {
00397         return NULL;
00398     }
00399 }
00400 
00401 int8_t sec_prot_keys_gtk_set(sec_prot_gtk_keys_t *gtks, uint8_t index, uint8_t *gtk, uint32_t lifetime)
00402 {
00403     if (!gtk || index >= GTK_NUM) {
00404         return -1;
00405     }
00406 
00407     // If same GTK is given again, do not update
00408     if (gtks->gtk[index].set && memcmp(gtks->gtk[index].key, gtk, GTK_LEN) == 0) {
00409         return -1;
00410     }
00411 
00412     sec_prot_keys_gtk_clear(gtks, index);
00413     uint8_t install_order = sec_prot_keys_gtk_install_order_last_get(gtks);
00414 
00415     gtks->gtk[index].set = true;
00416     gtks->gtk[index].lifetime = lifetime;
00417     gtks->gtk[index].status = GTK_STATUS_NEW;
00418     gtks->gtk[index].install_order = install_order;
00419     memcpy(gtks->gtk[index].key, gtk, GTK_LEN);
00420 
00421     gtks->updated = true;
00422 
00423     return 0;
00424 }
00425 
00426 int8_t sec_prot_keys_gtk_clear(sec_prot_gtk_keys_t *gtks, uint8_t index)
00427 {
00428     if (!gtks || index >= GTK_NUM) {
00429         return -1;
00430     }
00431 
00432     gtks->gtk[index].set = false;
00433     gtks->gtk[index].lifetime = 0;   // Should be provided by authenticator
00434     gtks->gtk[index].status = GTK_STATUS_NEW;
00435     memset(gtks->gtk[index].key, 0, GTK_LEN);
00436 
00437     sec_prot_keys_gtk_install_order_update(gtks);
00438 
00439     return 0;
00440 }
00441 
00442 bool sec_prot_keys_gtk_is_set(sec_prot_gtk_keys_t *gtks, uint8_t index)
00443 {
00444     if (index >= GTK_NUM || !gtks->gtk[index].set) {
00445         return false;
00446     }
00447 
00448     return true;
00449 }
00450 
00451 uint8_t *sec_prot_keys_gtk_get(sec_prot_gtk_keys_t *gtks, uint8_t index)
00452 {
00453     if (index >= GTK_NUM || !gtks->gtk[index].set) {
00454         return NULL;
00455     }
00456 
00457     return gtks->gtk[index].key;
00458 }
00459 
00460 uint32_t sec_prot_keys_gtk_lifetime_get(sec_prot_gtk_keys_t *gtks, uint8_t index)
00461 {
00462     if (index >= GTK_NUM || !gtks->gtk[index].set) {
00463         return 0;
00464     }
00465 
00466     return gtks->gtk[index].lifetime;
00467 }
00468 
00469 uint32_t sec_prot_keys_gtk_lifetime_decrement(sec_prot_gtk_keys_t *gtks, uint8_t index, uint16_t seconds)
00470 {
00471     if (gtks->gtk[index].lifetime > seconds) {
00472         gtks->gtk[index].lifetime -= seconds;
00473     } else {
00474         gtks->gtk[index].lifetime = 0;
00475     }
00476 
00477     return gtks->gtk[index].lifetime;
00478 }
00479 
00480 bool sec_prot_keys_gtks_are_updated(sec_prot_gtk_keys_t *gtks)
00481 {
00482     return gtks->updated;
00483 }
00484 
00485 void sec_prot_keys_gtks_updated_set(sec_prot_gtk_keys_t *gtks)
00486 {
00487     gtks->updated = true;
00488 }
00489 
00490 void sec_prot_keys_gtks_updated_reset(sec_prot_gtk_keys_t *gtks)
00491 {
00492     gtks->updated = false;
00493 }
00494 
00495 void sec_prot_keys_gtk_status_fresh_set(sec_prot_gtk_keys_t *gtks, uint8_t index)
00496 {
00497     if (index >= GTK_NUM || !gtks->gtk[index].set) {
00498         return;
00499     }
00500 
00501     // Active key remains as active, old keys are never reused
00502     if (gtks->gtk[index].status < GTK_STATUS_FRESH) {
00503         gtks->gtk[index].status = GTK_STATUS_FRESH;
00504     }
00505 }
00506 
00507 void sec_prot_keys_gtk_status_all_fresh_set(sec_prot_gtk_keys_t *gtks)
00508 {
00509     for (uint8_t i = 0; i < GTK_NUM; i++) {
00510         sec_prot_keys_gtk_status_fresh_set(gtks, i);
00511     }
00512 }
00513 
00514 int8_t sec_prot_keys_gtk_status_active_set(sec_prot_gtk_keys_t *gtks, uint8_t index)
00515 {
00516     if (index >= GTK_NUM || !gtks->gtk[index].set) {
00517         return -1;
00518     }
00519 
00520     // If key is valid to be taken into use sets it active
00521     if (gtks->gtk[index].status == GTK_STATUS_FRESH) {
00522         // Sets previously active key old
00523         for (uint8_t i = 0; i < GTK_NUM; i++) {
00524             // Sets previously active key old
00525             if (gtks->gtk[i].status == GTK_STATUS_ACTIVE) {
00526                 gtks->gtk[i].status = GTK_STATUS_OLD;
00527             }
00528         }
00529         gtks->gtk[index].status = GTK_STATUS_ACTIVE;
00530         return 0;
00531     }
00532 
00533     return -1;
00534 }
00535 
00536 int8_t sec_prot_keys_gtk_status_active_get(sec_prot_gtk_keys_t *gtks)
00537 {
00538     for (uint8_t i = 0; i < GTK_NUM; i++) {
00539         if (gtks->gtk[i].status == GTK_STATUS_ACTIVE) {
00540             return i;
00541         }
00542     }
00543 
00544     return -1;
00545 }
00546 
00547 bool sec_prot_keys_gtk_status_is_live(sec_prot_gtk_keys_t *gtks, uint8_t index)
00548 {
00549     if (index >= GTK_NUM || !gtks->gtk[index].set) {
00550         return false;
00551     }
00552 
00553     if (gtks->gtk[index].status == GTK_STATUS_FRESH || gtks->gtk[index].status == GTK_STATUS_ACTIVE) {
00554         return true;
00555     }
00556 
00557     return false;
00558 }
00559 
00560 void sec_prot_keys_gtk_status_new_set(sec_prot_gtk_keys_t *gtks, uint8_t index)
00561 {
00562     if (index >= GTK_NUM || !gtks->gtk[index].set) {
00563         return;
00564     }
00565 
00566     gtks->gtk[index].status = GTK_STATUS_NEW;
00567 }
00568 
00569 void sec_prot_keys_gtks_hash_generate(sec_prot_gtk_keys_t *gtks, uint8_t *gtkhash)
00570 {
00571     memset(gtkhash, 0, GTK_ALL_HASHES_LEN);
00572 
00573     uint8_t *gtk_hash_ptr = gtkhash;
00574 
00575     for (uint8_t i = 0; i < GTK_NUM; i++) {
00576         if (sec_prot_keys_gtk_is_set(gtks, i)) {
00577             uint8_t *gtk = sec_prot_keys_gtk_get(gtks, i);
00578             sec_prot_lib_gtkhash_generate(gtk, gtk_hash_ptr);
00579         }
00580         gtk_hash_ptr += GTK_HASH_LEN;
00581     }
00582 }
00583 
00584 void sec_prot_keys_gtk_hash_generate(uint8_t *gtk, uint8_t *gtk_hash)
00585 {
00586     sec_prot_lib_gtkhash_generate(gtk, gtk_hash);
00587 }
00588 
00589 gtk_mismatch_e sec_prot_keys_gtks_hash_update(sec_prot_gtk_keys_t *gtks, uint8_t *gtkhash)
00590 {
00591     uint8_t *gtk_hash_ptr = gtkhash;
00592 
00593     gtk_mismatch_e mismatch = GTK_NO_MISMATCH;
00594 
00595     for (uint8_t i = 0; i < GTK_NUM; i++, gtk_hash_ptr += 8) {
00596         // If hash is not set, stop using the key
00597         if (sec_prot_keys_gtk_hash_empty(gtk_hash_ptr)) {
00598             if (sec_prot_keys_gtk_is_set(gtks, i)) {
00599                 uint32_t lifetime = sec_prot_keys_gtk_lifetime_get(gtks, i);
00600                 if (lifetime > GTK_EXPIRE_MISMATCH_TIME) {
00601                     tr_info("GTK mismatch %i expired time, lifetime: %"PRIu32"", i, lifetime);
00602                     if (mismatch < GTK_LIFETIME_MISMATCH) {
00603                         mismatch = GTK_LIFETIME_MISMATCH;
00604                     }
00605                 }
00606                 sec_prot_keys_gtk_clear(gtks, i);
00607             }
00608         } else {
00609             // Check is hash matches to existing key
00610             uint8_t gtk_hash[8];
00611             uint8_t *gtk = sec_prot_keys_gtk_get(gtks, i);
00612             if (!gtk) {
00613                 // Hash set but GTK is not known, set mismatch
00614                 tr_info("GTK mismatch: %i", i);
00615                 if (mismatch < GTK_HASH_MISMATCH) {
00616                     mismatch = GTK_HASH_MISMATCH;
00617                 }
00618                 continue;
00619             }
00620 
00621             sec_prot_lib_gtkhash_generate(gtk, gtk_hash);
00622 
00623             if (memcmp(gtk_hash, gtk_hash_ptr, 8) == 0) {
00624                 // Key is fresh (or active, if old do not change state)
00625                 sec_prot_keys_gtk_status_fresh_set(gtks, i);
00626             } else {
00627                 // Hash does not match, set mismatch and delete key
00628                 tr_info("GTK mismatch: %i", i);
00629                 if (mismatch < GTK_HASH_MISMATCH) {
00630                     mismatch = GTK_HASH_MISMATCH;
00631                 }
00632                 sec_prot_keys_gtk_clear(gtks, i);
00633             }
00634         }
00635     }
00636 
00637     return mismatch;
00638 }
00639 
00640 bool sec_prot_keys_gtk_hash_empty(uint8_t *gtkhash)
00641 {
00642     const uint8_t empty_hash[GTK_HASH_LEN] = {0};
00643     if (memcmp(gtkhash, empty_hash, GTK_HASH_LEN) == 0) {
00644         return true;
00645     } else {
00646         return false;
00647     }
00648 }
00649 
00650 int8_t sec_prot_keys_gtk_install_order_last_get(sec_prot_gtk_keys_t *gtks)
00651 {
00652     int8_t install_order = -1;
00653 
00654     // Gets the last key index
00655     for (uint8_t i = 0; i < GTK_NUM; i++) {
00656         if (sec_prot_keys_gtk_is_set(gtks, i)) {
00657             if (gtks->gtk[i].install_order > install_order) {
00658                 install_order = gtks->gtk[i].install_order;
00659             }
00660         }
00661     }
00662 
00663     return install_order + 1;
00664 }
00665 
00666 int8_t sec_prot_keys_gtk_install_order_last_index_get(sec_prot_gtk_keys_t *gtks)
00667 {
00668     int8_t install_order = -1;
00669     int8_t index = -1;
00670 
00671     // Gets the last key index
00672     for (uint8_t i = 0; i < GTK_NUM; i++) {
00673         if (sec_prot_keys_gtk_is_set(gtks, i)) {
00674             if (gtks->gtk[i].install_order > install_order) {
00675                 install_order = gtks->gtk[i].install_order;
00676                 index = i;
00677             }
00678         }
00679     }
00680 
00681     return index;
00682 }
00683 
00684 uint32_t sec_prot_keys_gtk_install_order_last_lifetime_get(sec_prot_gtk_keys_t *gtks)
00685 {
00686     uint32_t lifetime = 0;
00687     int8_t install_order = -1;
00688 
00689     // Gets the last key index
00690     for (uint8_t i = 0; i < GTK_NUM; i++) {
00691         if (sec_prot_keys_gtk_is_set(gtks, i)) {
00692             if (gtks->gtk[i].install_order > install_order) {
00693                 install_order = gtks->gtk[i].install_order;
00694                 lifetime = gtks->gtk[i].lifetime;
00695             }
00696         }
00697     }
00698 
00699     return lifetime;
00700 }
00701 
00702 int8_t sec_prot_keys_gtk_install_order_first_index_get(sec_prot_gtk_keys_t *gtks)
00703 {
00704     // Gets the first key index
00705     for (uint8_t i = 0; i < GTK_NUM; i++) {
00706         if (sec_prot_keys_gtk_is_set(gtks, i)) {
00707             if (gtks->gtk[i].install_order == GTK_INSTALL_ORDER_FIRST) {
00708                 return i;
00709             }
00710         }
00711     }
00712 
00713     return -1;
00714 }
00715 
00716 int8_t sec_prot_keys_gtk_install_order_second_index_get(sec_prot_gtk_keys_t *gtks)
00717 {
00718     // Gets the first key index
00719     for (uint8_t i = 0; i < GTK_NUM; i++) {
00720         if (sec_prot_keys_gtk_is_set(gtks, i)) {
00721             if (gtks->gtk[i].install_order == GTK_INSTALL_ORDER_SECOND) {
00722                 return i;
00723             }
00724         }
00725     }
00726 
00727     return -1;
00728 }
00729 
00730 void sec_prot_keys_gtk_install_order_update(sec_prot_gtk_keys_t *gtks)
00731 {
00732     int8_t ordered_indexes[4] = {-1, -1, -1, -1};
00733 
00734     // Creates table of ordered indexes
00735     for (uint8_t i = 0; i < GTK_NUM; i++) {
00736         if (sec_prot_keys_gtk_is_set(gtks, i)) {
00737             ordered_indexes[gtks->gtk[i].install_order] = i;
00738         }
00739     }
00740 
00741     // Updates indexes of the GTKs
00742     uint8_t new_install_order = 0;
00743     for (uint8_t i = 0; i < GTK_NUM; i++) {
00744         if (ordered_indexes[i] >= 0) {
00745             gtks->gtk[ordered_indexes[i]].install_order = new_install_order++;
00746         }
00747     }
00748 }
00749 
00750 int8_t sec_prot_keys_gtk_install_index_get(sec_prot_gtk_keys_t *gtks)
00751 {
00752     // Gets the index of the last key to be installed
00753     int8_t install_index = sec_prot_keys_gtk_install_order_last_index_get(gtks);
00754     if (install_index < 0) {
00755         install_index = 0;
00756     }
00757 
00758     // Checks if there is free index, and available uses that for new GTK
00759     for (uint8_t ctr = 0, i = install_index; ctr < GTK_NUM; ctr++) {
00760         if (!sec_prot_keys_gtk_is_set(gtks, i)) {
00761             install_index = i;
00762             break;
00763         }
00764         i++;
00765         if (i >= GTK_NUM) {
00766             i = 0;
00767         }
00768     }
00769 
00770     return install_index;
00771 }
00772 
00773 uint8_t sec_prot_keys_gtk_count(sec_prot_gtk_keys_t *gtks)
00774 {
00775     uint8_t count = 0;
00776 
00777     for (uint8_t i = 0; i < GTK_NUM; i++) {
00778         if (sec_prot_keys_gtk_is_set(gtks, i)) {
00779             count++;
00780         }
00781     }
00782 
00783     return count;
00784 }
00785 
00786 #endif /* HAVE_WS */