Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers supp_fwh_sec_prot.c Source File

supp_fwh_sec_prot.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 "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/PANA/pana_eap_header.h"
00030 #include "Security/eapol/eapol_helper.h"
00031 #include "Security/eapol/kde_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 #include "Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.h"
00037 #include "Service_Libs/hmac/hmac_sha1.h"
00038 #include "Service_Libs/nist_aes_kw/nist_aes_kw.h"
00039 
00040 #ifdef HAVE_WS
00041 
00042 #define TRACE_GROUP "sfwh"
00043 
00044 typedef enum {
00045     FWH_STATE_INIT = SEC_STATE_INIT,
00046     FWH_STATE_CREATE_RESP = SEC_STATE_CREATE_RESP,
00047     FWH_STATE_CREATE_IND = SEC_STATE_CREATE_IND,
00048     FWH_STATE_MESSAGE_1 = SEC_STATE_FIRST,
00049     FWH_STATE_MESSAGE_3,
00050     FWH_STATE_MESSAGE_3_RETRY_WAIT,
00051     FWH_STATE_CREATE_RESP_SUPP_RETRY,
00052     FWH_STATE_FINISH = SEC_STATE_FINISH,
00053     FWH_STATE_FINISHED = SEC_STATE_FINISHED
00054 } fwh_sec_prot_state_e;
00055 
00056 typedef enum {
00057     FWH_MESSAGE_UNKNOWN = 0,
00058     FWH_MESSAGE_1,
00059     FWH_MESSAGE_2,
00060     FWH_MESSAGE_3,
00061     FWH_MESSAGE_4
00062 } fwh_sec_prot_msg_e;
00063 
00064 #define KEY_INFO_INSTALL              0x01
00065 #define KEY_INFO_KEY_ACK              0x02
00066 #define KEY_INFO_KEY_MIC              0x04
00067 #define KEY_INFO_SECURED_KEY_FRAME    0x08
00068 
00069 typedef struct {
00070     sec_prot_common_t             common;                      /**< Common data */
00071     eapol_pdu_t                   recv_eapol_pdu;              /**< Received EAPOL PDU */
00072     fwh_sec_prot_msg_e            recv_msg;                    /**< Received message */
00073     uint8_t                       snonce[EAPOL_KEY_NONCE_LEN]; /**< Supplicant nonce */
00074     uint8_t                       anonce[EAPOL_KEY_NONCE_LEN]; /**< Authenticator nonce */
00075     uint8_t                       new_ptk[PTK_LEN];            /**< PTK (384 bits) */
00076     uint8_t                       remote_eui64[8];             /**< Remote EUI-64 used to calculate PTK */
00077     void                          *recv_pdu;                   /**< received pdu */
00078     uint16_t                      recv_size;                   /**< received pdu size */
00079     uint64_t                      recv_replay_cnt;             /**< received replay counter */
00080     bool                          msg3_received : 1;           /**< Valid Message 3 has been received */
00081     bool                          msg3_retry_wait : 1;         /**< Waiting for Message 3 retry */
00082     bool                          recv_replay_cnt_set : 1;     /**< received replay counter set */
00083 } fwh_sec_prot_int_t;
00084 
00085 #define FWH_RETRY_TIMEOUT_SMALL 300*10 // retry timeout for small network
00086 #define FWH_RETRY_TIMEOUT_LARGE 720*10 // retry timeout for large network
00087 
00088 static uint16_t retry_timeout = FWH_RETRY_TIMEOUT_SMALL;
00089 
00090 static uint16_t supp_fwh_sec_prot_size(void);
00091 static int8_t supp_fwh_sec_prot_init(sec_prot_t *prot);
00092 
00093 static void supp_fwh_sec_prot_create_response(sec_prot_t *prot, sec_prot_result_e result);
00094 static void supp_fwh_sec_prot_delete(sec_prot_t *prot);
00095 static int8_t supp_fwh_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size);
00096 static fwh_sec_prot_msg_e supp_fwh_sec_prot_message_get(sec_prot_t *prot, eapol_pdu_t *eapol_pdu);
00097 static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot);
00098 
00099 static int8_t supp_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_e msg);
00100 static void supp_fwh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks);
00101 
00102 static int8_t supp_fwh_sec_prot_ptk_generate(sec_prot_t *prot, sec_prot_keys_t *sec_keys);
00103 static int8_t supp_fwh_sec_prot_mic_validate(sec_prot_t *prot);
00104 
00105 static void supp_fwh_sec_prot_recv_replay_counter_store(sec_prot_t *prot);
00106 static bool supp_fwh_sec_prot_recv_replay_cnt_compare(uint64_t received_counter, sec_prot_t *prot);
00107 static void supp_fwh_sec_prot_anonce_store(sec_prot_t *prot);
00108 static int8_t supp_fwh_sec_prot_anonce_validate(sec_prot_t *prot);
00109 static void supp_fwh_sec_prot_security_replay_counter_update(sec_prot_t *prot);
00110 
00111 static int8_t supp_fwh_kde_handle(sec_prot_t *prot);
00112 
00113 #define fwh_sec_prot_get(prot) (fwh_sec_prot_int_t *) &prot->data
00114 
00115 int8_t supp_fwh_sec_prot_register(kmp_service_t *service)
00116 {
00117     if (!service) {
00118         return -1;
00119     }
00120 
00121     if (kmp_service_sec_protocol_register(service, IEEE_802_11_4WH, supp_fwh_sec_prot_size, supp_fwh_sec_prot_init) < 0) {
00122         return -1;
00123     }
00124 
00125     return 0;
00126 }
00127 int8_t supp_fwh_sec_prot_timing_adjust(uint8_t timing)
00128 {
00129     if (timing < 16) {
00130         retry_timeout = FWH_RETRY_TIMEOUT_SMALL;
00131     } else {
00132         retry_timeout = FWH_RETRY_TIMEOUT_LARGE;
00133     }
00134     return 0;
00135 }
00136 
00137 static uint16_t supp_fwh_sec_prot_size(void)
00138 {
00139     return sizeof(fwh_sec_prot_int_t);
00140 }
00141 
00142 static int8_t supp_fwh_sec_prot_init(sec_prot_t *prot)
00143 {
00144     prot->create_req = 0;
00145     prot->create_resp = supp_fwh_sec_prot_create_response;
00146     prot->receive = supp_fwh_sec_prot_receive;
00147     prot->delete = supp_fwh_sec_prot_delete;
00148     prot->state_machine = supp_fwh_sec_prot_state_machine;
00149     prot->timer_timeout = supp_fwh_sec_prot_timer_timeout;
00150 
00151     fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
00152     sec_prot_init(&data->common);
00153     sec_prot_state_set(prot, &data->common, FWH_STATE_INIT);
00154 
00155     data->common.ticks = retry_timeout;
00156     data->msg3_received = false;
00157     data->msg3_retry_wait = false;
00158     data->recv_replay_cnt = 0;
00159     data->recv_replay_cnt_set = false;
00160 
00161     uint8_t eui64[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
00162     sec_prot_lib_nonce_init(data->snonce, eui64, 1000);
00163 
00164     return 0;
00165 }
00166 
00167 static void supp_fwh_sec_prot_delete(sec_prot_t *prot)
00168 {
00169     // No op at the moment
00170     (void) prot;
00171 }
00172 
00173 static void supp_fwh_sec_prot_create_response(sec_prot_t *prot, sec_prot_result_e result)
00174 {
00175     fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
00176 
00177     // Call state machine
00178     sec_prot_result_set(&data->common, result);
00179     prot->state_machine_call(prot);
00180 }
00181 
00182 static int8_t supp_fwh_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size)
00183 {
00184     fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
00185     int8_t ret_val = -1;
00186 
00187     // Decoding is successful
00188     if (eapol_parse_pdu_header(pdu, size, &data->recv_eapol_pdu)) {
00189         // Get message
00190         data->recv_msg = supp_fwh_sec_prot_message_get(prot, &data->recv_eapol_pdu);
00191         if (data->recv_msg != FWH_MESSAGE_UNKNOWN) {
00192             tr_info("4WH: recv %s", data->recv_msg == FWH_MESSAGE_1 ? "Message 1" : "Message 3");
00193 
00194             // Call state machine
00195             data->recv_pdu = pdu;
00196             data->recv_size = size;
00197             prot->state_machine(prot);
00198         } else {
00199             tr_error("4WH: recv error");
00200         }
00201         ret_val = 0;
00202     } else {
00203         tr_error("4WH: recv error");
00204     }
00205 
00206     memset(&data->recv_eapol_pdu, 0, sizeof(eapol_pdu_t));
00207     data->recv_msg = FWH_MESSAGE_UNKNOWN;
00208     data->recv_pdu = 0;
00209     data->recv_size = 0;
00210 
00211     return ret_val;
00212 }
00213 
00214 static fwh_sec_prot_msg_e supp_fwh_sec_prot_message_get(sec_prot_t *prot, eapol_pdu_t *eapol_pdu)
00215 {
00216     fwh_sec_prot_msg_e msg = FWH_MESSAGE_UNKNOWN;
00217 
00218     if (!eapol_pdu->msg.key.key_information.pairwise_key) {
00219         // This is mismatch between KMP ID indicating 802.11/4WH and key type
00220         return FWH_MESSAGE_UNKNOWN;
00221     }
00222 
00223     uint8_t key_mask = eapol_pdu_key_mask_get(eapol_pdu);
00224 
00225     switch (key_mask) {
00226         // Message 1
00227         case KEY_INFO_KEY_ACK:
00228             /* Must have valid replay counter, both larger for PMK and larger that is used on
00229              * the four way handshake session (note: PMK replay counter is not updated for Message 1
00230              * but session specific counter is)
00231              */
00232             if (sec_prot_keys_pmk_replay_cnt_compare(eapol_pdu->msg.key.replay_counter, prot->sec_keys) &&
00233                     supp_fwh_sec_prot_recv_replay_cnt_compare(eapol_pdu->msg.key.replay_counter, prot)) {
00234                 msg = FWH_MESSAGE_1;
00235             } else {
00236                 tr_error("4WH: invalid replay counter %"PRId64, eapol_pdu->msg.key.replay_counter);
00237             }
00238             break;
00239         // Message 3
00240         case KEY_INFO_INSTALL | KEY_INFO_KEY_ACK | KEY_INFO_KEY_MIC | KEY_INFO_SECURED_KEY_FRAME:
00241             // Must have valid replay counter
00242             if (sec_prot_keys_pmk_replay_cnt_compare(eapol_pdu->msg.key.replay_counter, prot->sec_keys)) {
00243                 if (eapol_pdu->msg.key.key_information.encrypted_key_data) {
00244                     // This should include the GTK KDE, Lifetime KDE and GTKL KDE.
00245                     // At least some of them should be present
00246                     msg = FWH_MESSAGE_3;
00247                 }
00248             } else {
00249                 tr_error("4WH: invalid replay counter %"PRId64, eapol_pdu->msg.key.replay_counter);
00250             }
00251             break;
00252         default:
00253             break;
00254     }
00255 
00256     return msg;
00257 }
00258 
00259 static int8_t supp_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_e msg)
00260 {
00261     fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
00262 
00263     eapol_pdu_t eapol_pdu;
00264     uint16_t eapol_pdu_size = eapol_pdu_key_frame_init(&eapol_pdu, 0, NULL);
00265 
00266     eapol_pdu.msg.key.key_information.pairwise_key = true;
00267 
00268     switch (msg) {
00269         case FWH_MESSAGE_2:
00270             eapol_pdu.msg.key.replay_counter = data->recv_replay_cnt;
00271             eapol_pdu.msg.key.key_information.key_mic = true;
00272             eapol_pdu.msg.key.key_length = 0;
00273             eapol_pdu.msg.key.key_nonce = data->snonce;
00274             break;
00275         case FWH_MESSAGE_4:
00276             eapol_pdu.msg.key.replay_counter = data->recv_replay_cnt;
00277             eapol_pdu.msg.key.key_information.key_mic = true;
00278             eapol_pdu.msg.key.key_information.secured_key_frame = true;
00279             eapol_pdu.msg.key.key_length = 0;
00280             break;
00281         default:
00282             break;
00283     }
00284 
00285     uint8_t *eapol_pdu_frame = sec_prot_lib_message_build(data->new_ptk, 0, 0, &eapol_pdu, eapol_pdu_size, prot->header_size);
00286 
00287     if (eapol_pdu_frame == NULL) {
00288         return -1;
00289     }
00290 
00291     tr_info("4WH: send %s", msg == FWH_MESSAGE_2 ? "Message 2" : "Message 4");
00292 
00293     if (prot->send(prot, eapol_pdu_frame, eapol_pdu_size + prot->header_size) < 0) {
00294         return -1;
00295     }
00296 
00297     return 0;
00298 }
00299 
00300 static void supp_fwh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks)
00301 {
00302     fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
00303     sec_prot_timer_timeout_handle(prot, &data->common, NULL, ticks);
00304 }
00305 
00306 static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot)
00307 {
00308     fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
00309 
00310     // 4WH supplicant state machine
00311     switch (sec_prot_state_get(&data->common)) {
00312         case FWH_STATE_INIT:
00313             tr_info("4WH: init");
00314             prot->timer_start(prot);
00315             sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_1);
00316             break;
00317 
00318         // Wait 4WH message 1 (starts handshake on supplicant)
00319         case FWH_STATE_MESSAGE_1:
00320             if (data->recv_msg != FWH_MESSAGE_1) {
00321                 return;
00322             }
00323 
00324             // PMKID must be valid
00325             if (supp_fwh_kde_handle(prot) < 0) {
00326                 return;
00327             }
00328 
00329             // Set default timeout for the total maximum length of the negotiation
00330             sec_prot_default_timeout_set(&data->common);
00331 
00332             tr_info("4WH: start");
00333 
00334             // Store authenticator nonce for check when 4WH Message 3 is received
00335             supp_fwh_sec_prot_anonce_store(prot);
00336             sec_prot_lib_nonce_generate(data->snonce);
00337             if (supp_fwh_sec_prot_ptk_generate(prot, prot->sec_keys) < 0) {
00338                 return;
00339             }
00340 
00341             supp_fwh_sec_prot_recv_replay_counter_store(prot);
00342 
00343             // Send KMP-CREATE.indication
00344             prot->create_ind(prot);
00345             sec_prot_state_set(prot, &data->common, FWH_STATE_CREATE_RESP);
00346             break;
00347 
00348         // Wait KMP-CREATE.response
00349         case FWH_STATE_CREATE_RESP:
00350             if (sec_prot_result_ok_check(&data->common)) {
00351                 // Send 4WH message 2
00352                 supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_2);
00353                 data->common.ticks = retry_timeout;
00354                 sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_3);
00355             } else {
00356                 // Ready to be deleted
00357                 sec_prot_state_set(prot, &data->common, FWH_STATE_FINISHED);
00358             }
00359             break;
00360 
00361         // Wait 4WH message 3 (message 2 has been sent)
00362         case FWH_STATE_MESSAGE_3:
00363             if (data->recv_msg == FWH_MESSAGE_1) {
00364 
00365                 // PMKID must be valid
00366                 if (supp_fwh_kde_handle(prot) < 0) {
00367                     return;
00368                 }
00369 
00370                 // Store authenticator nonce for check when 4WH Message 3 is received
00371                 supp_fwh_sec_prot_anonce_store(prot);
00372                 sec_prot_lib_nonce_generate(data->snonce);
00373                 if (supp_fwh_sec_prot_ptk_generate(prot, prot->sec_keys) < 0) {
00374                     return;
00375                 }
00376 
00377                 supp_fwh_sec_prot_recv_replay_counter_store(prot);
00378 
00379                 // Send 4WH message 2
00380                 supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_2);
00381                 data->common.ticks = retry_timeout;
00382                 return;
00383             } else if (data->recv_msg != FWH_MESSAGE_3) {
00384                 return;
00385             }
00386 
00387             // MIC must be valid
00388             if (supp_fwh_sec_prot_mic_validate(prot) < 0) {
00389                 return;
00390             }
00391 
00392             // Nonce must match to 4WH Message 1
00393             if (supp_fwh_sec_prot_anonce_validate(prot) < 0) {
00394                 return;
00395             }
00396 
00397             // Must have at least GTKL
00398             if (supp_fwh_kde_handle(prot) < 0) {
00399                 return;
00400             }
00401 
00402             supp_fwh_sec_prot_recv_replay_counter_store(prot);
00403             supp_fwh_sec_prot_security_replay_counter_update(prot);
00404             data->msg3_received = true;
00405 
00406             // Sends 4WH Message 4
00407             supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_4);
00408             data->common.ticks = retry_timeout;
00409             sec_prot_state_set(prot, &data->common, FWH_STATE_FINISH);
00410             break;
00411 
00412         case FWH_STATE_FINISH:
00413             if (data->msg3_retry_wait) {
00414                 tr_info("4WH: Message 3 retry timeout");
00415                 sec_prot_state_set(prot, &data->common, FWH_STATE_FINISHED);
00416                 return;
00417             }
00418 
00419             // If Message 3 has been received updates key data and waits for Message 3 retry
00420             if (data->msg3_received) {
00421                 data->msg3_retry_wait = true;
00422 
00423                 tr_info("4WH: finish, wait Message 3 retry");
00424 
00425                 sec_prot_keys_ptk_write(prot->sec_keys, data->new_ptk);
00426                 sec_prot_keys_ptk_eui_64_write(prot->sec_keys, data->remote_eui64);
00427 
00428                 data->common.ticks = 60 * 10; // 60 seconds
00429                 // KMP-FINISHED.indication
00430                 prot->finished_ind(prot, sec_prot_result_get(&data->common), prot->sec_keys);
00431                 sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_3_RETRY_WAIT);
00432             } else {
00433                 tr_info("4WH: finish");
00434                 // KMP-FINISHED.indication
00435                 prot->finished_ind(prot, sec_prot_result_get(&data->common), prot->sec_keys);
00436                 sec_prot_state_set(prot, &data->common, FWH_STATE_FINISHED);
00437             }
00438             break;
00439 
00440         case FWH_STATE_MESSAGE_3_RETRY_WAIT:
00441             if (sec_prot_result_timeout_check(&data->common)) {
00442                 tr_info("4WH: Message 3 retry timeout");
00443                 sec_prot_state_set(prot, &data->common, FWH_STATE_FINISHED);
00444             } else {
00445                 if (data->recv_msg != FWH_MESSAGE_3) {
00446                     return;
00447                 }
00448 
00449                 // MIC must be valid
00450                 if (supp_fwh_sec_prot_mic_validate(prot) < 0) {
00451                     return;
00452                 }
00453 
00454                 // Nonce must match to 4WH Message 1
00455                 if (supp_fwh_sec_prot_anonce_validate(prot) < 0) {
00456                     return;
00457                 }
00458 
00459                 // Must have at least GTKL
00460                 if (supp_fwh_kde_handle(prot) < 0) {
00461                     return;
00462                 }
00463 
00464                 supp_fwh_sec_prot_recv_replay_counter_store(prot);
00465                 supp_fwh_sec_prot_security_replay_counter_update(prot);
00466 
00467                 tr_info("4WH: send Message 4 again");
00468 
00469                 supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_4);
00470             }
00471             break;
00472 
00473         case FWH_STATE_FINISHED:
00474             tr_info("4WH: finished");
00475             prot->timer_stop(prot);
00476             prot->finished(prot);
00477             break;
00478 
00479         default:
00480             break;
00481     }
00482 }
00483 
00484 static int8_t supp_fwh_sec_prot_ptk_generate(sec_prot_t *prot, sec_prot_keys_t *sec_keys)
00485 {
00486     fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
00487 
00488     uint8_t local_eui64[8];
00489     prot->addr_get(prot, local_eui64, data->remote_eui64);
00490 
00491     uint8_t *remote_nonce = data->recv_eapol_pdu.msg.key.key_nonce;
00492     if (!remote_nonce) {
00493         tr_error("No ANonce");
00494         return -1;
00495     }
00496 
00497     uint8_t *pmk = sec_prot_keys_pmk_get(sec_keys);
00498     sec_prot_lib_ptk_calc(pmk, local_eui64, data->remote_eui64, data->snonce, remote_nonce, data->new_ptk);
00499 
00500     return 0;
00501 }
00502 
00503 static int8_t supp_fwh_sec_prot_mic_validate(sec_prot_t *prot)
00504 {
00505     fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
00506     return sec_prot_lib_mic_validate(data->new_ptk, data->recv_eapol_pdu.msg.key.key_mic, data->recv_pdu, data->recv_size);
00507 }
00508 
00509 static void supp_fwh_sec_prot_recv_replay_counter_store(sec_prot_t *prot)
00510 {
00511     fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
00512     data->recv_replay_cnt = data->recv_eapol_pdu.msg.key.replay_counter;
00513     data->recv_replay_cnt_set = true;
00514 }
00515 
00516 static bool supp_fwh_sec_prot_recv_replay_cnt_compare(uint64_t received_counter, sec_prot_t *prot)
00517 {
00518     fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
00519     // If previous value is set must be greater
00520     if (data->recv_replay_cnt_set && received_counter > data->recv_replay_cnt) {
00521         return true;
00522     } else if (!data->recv_replay_cnt_set && received_counter >= data->recv_replay_cnt) {
00523         // Otherwise allows also same value e.g. zero
00524         return true;
00525     }
00526 
00527     return false;
00528 }
00529 
00530 static void supp_fwh_sec_prot_anonce_store(sec_prot_t *prot)
00531 {
00532     fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
00533     memcpy(data->anonce, data->recv_eapol_pdu.msg.key.key_nonce, EAPOL_KEY_NONCE_LEN);
00534 }
00535 
00536 static int8_t supp_fwh_sec_prot_anonce_validate(sec_prot_t *prot)
00537 {
00538     fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
00539     if (memcmp(data->anonce, data->recv_eapol_pdu.msg.key.key_nonce, EAPOL_KEY_NONCE_LEN) != 0) {
00540         tr_error("ANonce invalid");
00541         return -1;
00542     }
00543     return 0;
00544 }
00545 
00546 static void supp_fwh_sec_prot_security_replay_counter_update(sec_prot_t *prot)
00547 {
00548     fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
00549     sec_prot_keys_pmk_replay_cnt_set(prot->sec_keys, data->recv_eapol_pdu.msg.key.replay_counter);
00550 }
00551 
00552 static int8_t supp_fwh_kde_handle(sec_prot_t *prot)
00553 {
00554     fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
00555 
00556     uint16_t kde_len;
00557     uint8_t *kde = sec_prot_lib_message_handle(data->new_ptk, &kde_len, &data->recv_eapol_pdu);
00558     if (!kde) {
00559         return -1;
00560     }
00561 
00562     switch (data->recv_msg) {
00563         case FWH_MESSAGE_1: {
00564             uint8_t recv_pmkid[PMKID_LEN];
00565             uint8_t calc_pmkid[PMKID_LEN];
00566             if (kde_pmkid_read(kde, kde_len, recv_pmkid) < 0) {
00567                 goto error;
00568             }
00569             if (sec_prot_lib_pmkid_generate(prot, calc_pmkid, false) < 0) {
00570                 goto error;
00571             }
00572             if (memcmp(recv_pmkid, calc_pmkid, PMKID_LEN) != 0) {
00573                 goto error;
00574             }
00575         }
00576         break;
00577 
00578         case FWH_MESSAGE_3:
00579             // If a valid new GTK value present, insert it
00580             if (sec_prot_lib_gtk_read(kde, kde_len, prot->sec_keys) < 0) {
00581                 goto error;
00582             }
00583             break;
00584 
00585         default:
00586             break;
00587     }
00588 
00589     ns_dyn_mem_free(kde);
00590     return 0;
00591 
00592 error:
00593     tr_error("Invalid KDEs");
00594     ns_dyn_mem_free(kde);
00595     return -1;
00596 }
00597 
00598 #endif /* HAVE_WS */