Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
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 */
Generated on Tue Jul 12 2022 13:54:54 by
