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_gkh_sec_prot.c
00001 /* 00002 * Copyright (c) 2018-2019, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "nsconfig.h" 00019 #include <string.h> 00020 #include "ns_types.h" 00021 #include "ns_list.h" 00022 #include "ns_trace.h" 00023 #include "nsdynmemLIB.h" 00024 #include "fhss_config.h " 00025 #include "NWK_INTERFACE/Include/protocol.h" 00026 #include "6LoWPAN/ws/ws_config.h" 00027 #include "Security/kmp/kmp_addr.h" 00028 #include "Security/kmp/kmp_api.h" 00029 #include "Security/PANA/pana_eap_header.h" 00030 #include "Security/eapol/eapol_helper.h" 00031 #include "Security/protocols/sec_prot_certs.h" 00032 #include "Security/protocols/sec_prot_keys.h" 00033 #include "Security/protocols/sec_prot.h" 00034 #include "Security/protocols/sec_prot_lib.h" 00035 #include "Security/protocols/gkh_sec_prot/supp_gkh_sec_prot.h" 00036 00037 #ifdef HAVE_WS 00038 00039 #define TRACE_GROUP "sgkh" 00040 00041 typedef enum { 00042 GKH_STATE_INIT = SEC_STATE_INIT, 00043 GKH_STATE_CREATE_RESP = SEC_STATE_CREATE_RESP, 00044 GKH_STATE_CREATE_IND = SEC_STATE_CREATE_IND, 00045 GKH_STATE_MESSAGE_1 = SEC_STATE_FIRST, 00046 GKH_STATE_FINISH = SEC_STATE_FINISH, 00047 GKH_STATE_FINISHED = SEC_STATE_FINISHED 00048 } gkh_sec_prot_state_e; 00049 00050 typedef enum { 00051 GKH_MESSAGE_UNKNOWN = 0, 00052 GKH_MESSAGE_1, 00053 GKH_MESSAGE_2 00054 } gkh_sec_prot_msg_e; 00055 00056 typedef struct { 00057 sec_prot_common_t common; /**< Common data */ 00058 eapol_pdu_t recv_eapol_pdu; /**< Received EAPOL PDU */ 00059 void *recv_pdu; /**< Received pdu */ 00060 uint16_t recv_size; /**< Received pdu size */ 00061 } gkh_sec_prot_int_t; 00062 00063 static uint16_t supp_gkh_sec_prot_size(void); 00064 static int8_t supp_gkh_sec_prot_init(sec_prot_t *prot); 00065 00066 static void supp_gkh_sec_prot_create_response(sec_prot_t *prot, sec_prot_result_e result); 00067 static void supp_gkh_sec_prot_delete(sec_prot_t *prot); 00068 static int8_t supp_gkh_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size); 00069 static gkh_sec_prot_msg_e supp_gkh_sec_prot_message_get(eapol_pdu_t *eapol_pdu, sec_prot_keys_t *sec_keys); 00070 static void supp_gkh_sec_prot_state_machine(sec_prot_t *prot); 00071 00072 static int8_t supp_gkh_sec_prot_message_send(sec_prot_t *prot, gkh_sec_prot_msg_e msg); 00073 static void supp_gkh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks); 00074 static int8_t supp_gkh_sec_prot_mic_validate(sec_prot_t *prot); 00075 static void supp_gkh_sec_prot_security_replay_counter_update(sec_prot_t *prot); 00076 static int8_t supp_gkh_kde_handle(sec_prot_t *prot); 00077 00078 #define gkh_sec_prot_get(prot) (gkh_sec_prot_int_t *) &prot->data 00079 00080 int8_t supp_gkh_sec_prot_register(kmp_service_t *service) 00081 { 00082 if (!service) { 00083 return -1; 00084 } 00085 00086 if (kmp_service_sec_protocol_register(service, IEEE_802_11_GKH, supp_gkh_sec_prot_size, supp_gkh_sec_prot_init) < 0) { 00087 return -1; 00088 } 00089 00090 return 0; 00091 } 00092 00093 static uint16_t supp_gkh_sec_prot_size(void) 00094 { 00095 return sizeof(gkh_sec_prot_int_t); 00096 } 00097 00098 static int8_t supp_gkh_sec_prot_init(sec_prot_t *prot) 00099 { 00100 prot->create_req = 0; 00101 prot->create_resp = supp_gkh_sec_prot_create_response; 00102 prot->receive = supp_gkh_sec_prot_receive; 00103 prot->delete = supp_gkh_sec_prot_delete; 00104 prot->state_machine = supp_gkh_sec_prot_state_machine; 00105 prot->timer_timeout = supp_gkh_sec_prot_timer_timeout; 00106 00107 gkh_sec_prot_int_t *data = gkh_sec_prot_get(prot); 00108 sec_prot_init(&data->common); 00109 sec_prot_state_set(prot, &data->common, GKH_STATE_INIT); 00110 00111 return 0; 00112 } 00113 00114 static void supp_gkh_sec_prot_delete(sec_prot_t *prot) 00115 { 00116 // No op at the moment 00117 (void) prot; 00118 } 00119 00120 static void supp_gkh_sec_prot_create_response(sec_prot_t *prot, sec_prot_result_e result) 00121 { 00122 gkh_sec_prot_int_t *data = gkh_sec_prot_get(prot); 00123 00124 // Call state machine 00125 sec_prot_result_set(&data->common, result); 00126 prot->state_machine_call(prot); 00127 } 00128 00129 static int8_t supp_gkh_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size) 00130 { 00131 gkh_sec_prot_int_t *data = gkh_sec_prot_get(prot); 00132 int8_t ret_val = -1; 00133 00134 // Decoding is successful 00135 if (eapol_parse_pdu_header(pdu, size, &data->recv_eapol_pdu)) { 00136 // Get message 00137 if (supp_gkh_sec_prot_message_get(&data->recv_eapol_pdu, prot->sec_keys) != GKH_MESSAGE_UNKNOWN) { 00138 tr_info("GKH: recv Message 1"); 00139 00140 // Call state machine 00141 data->recv_pdu = pdu; 00142 data->recv_size = size; 00143 prot->state_machine(prot); 00144 } else { 00145 tr_error("GKH: recv error"); 00146 } 00147 ret_val = 0; 00148 } else { 00149 tr_error("GKH: recv error"); 00150 } 00151 00152 memset(&data->recv_eapol_pdu, 0, sizeof(eapol_pdu_t)); 00153 data->recv_pdu = 0; 00154 data->recv_size = 0; 00155 00156 return ret_val; 00157 } 00158 00159 static gkh_sec_prot_msg_e supp_gkh_sec_prot_message_get(eapol_pdu_t *eapol_pdu, sec_prot_keys_t *sec_keys) 00160 { 00161 gkh_sec_prot_msg_e msg = GKH_MESSAGE_UNKNOWN; 00162 00163 if (eapol_pdu->msg.key.key_information.pairwise_key) { 00164 // This is mismatch between KMP ID indicating 802.11/GKH and key type 00165 return GKH_MESSAGE_UNKNOWN; 00166 } 00167 00168 uint8_t key_mask = eapol_pdu_key_mask_get(eapol_pdu); 00169 00170 switch (key_mask) { 00171 case KEY_INFO_KEY_ACK | KEY_INFO_KEY_MIC | KEY_INFO_SECURED_KEY_FRAME: 00172 // Must have valid replay counter 00173 if (sec_prot_keys_pmk_replay_cnt_compare(eapol_pdu->msg.key.replay_counter, sec_keys)) { 00174 if (eapol_pdu->msg.key.key_information.encrypted_key_data) { 00175 // This should include the GTK KDE, Lifetime KDE and GTKL KDE. 00176 msg = GKH_MESSAGE_1; 00177 } 00178 } else { 00179 tr_error("GKH: invalid replay counter %"PRId64, eapol_pdu->msg.key.replay_counter); 00180 } 00181 break; 00182 default: 00183 break; 00184 } 00185 00186 return msg; 00187 } 00188 00189 static int8_t supp_gkh_sec_prot_message_send(sec_prot_t *prot, gkh_sec_prot_msg_e msg) 00190 { 00191 eapol_pdu_t eapol_pdu; 00192 uint16_t eapol_pdu_size = eapol_pdu_key_frame_init(&eapol_pdu, 0, NULL); 00193 00194 switch (msg) { 00195 case GKH_MESSAGE_2: 00196 eapol_pdu.msg.key.replay_counter = sec_prot_keys_pmk_replay_cnt_get(prot->sec_keys); 00197 eapol_pdu.msg.key.key_information.key_mic = true; 00198 eapol_pdu.msg.key.key_information.secured_key_frame = true; 00199 eapol_pdu.msg.key.key_length = 0; 00200 break; 00201 default: 00202 break; 00203 } 00204 00205 uint8_t *eapol_pdu_frame = sec_prot_lib_message_build(prot->sec_keys->ptk, NULL, 0, &eapol_pdu, eapol_pdu_size, prot->header_size); 00206 00207 if (eapol_pdu_frame == NULL) { 00208 return -1; 00209 } 00210 00211 tr_info("GKH: send Message 2"); 00212 00213 if (prot->send(prot, eapol_pdu_frame, eapol_pdu_size + prot->header_size) < 0) { 00214 return -1; 00215 } 00216 00217 return 0; 00218 } 00219 00220 static void supp_gkh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks) 00221 { 00222 gkh_sec_prot_int_t *data = gkh_sec_prot_get(prot); 00223 sec_prot_timer_timeout_handle(prot, &data->common, NULL, ticks); 00224 } 00225 00226 static void supp_gkh_sec_prot_state_machine(sec_prot_t *prot) 00227 { 00228 gkh_sec_prot_int_t *data = gkh_sec_prot_get(prot); 00229 00230 // GKH supplicant state machine 00231 switch (sec_prot_state_get(&data->common)) { 00232 case GKH_STATE_INIT: 00233 tr_info("GKH init"); 00234 sec_prot_state_set(prot, &data->common, GKH_STATE_MESSAGE_1); 00235 prot->timer_start(prot); 00236 break; 00237 00238 // Wait GKH message 1 (starts handshake on supplicant) 00239 case GKH_STATE_MESSAGE_1: 00240 if (supp_gkh_sec_prot_mic_validate(prot) < 0) { 00241 return; 00242 } 00243 00244 if (supp_gkh_kde_handle(prot) < 0) { 00245 return; 00246 } 00247 00248 // Set default timeout for the total maximum length of the negotiation 00249 sec_prot_default_timeout_set(&data->common); 00250 00251 supp_gkh_sec_prot_security_replay_counter_update(prot); 00252 00253 tr_info("GKH start"); 00254 00255 // Send KMP-CREATE.indication 00256 prot->create_ind(prot); 00257 sec_prot_state_set(prot, &data->common, GKH_STATE_CREATE_RESP); 00258 break; 00259 00260 // Wait KMP-CREATE.response 00261 case GKH_STATE_CREATE_RESP: 00262 if (sec_prot_result_ok_check(&data->common)) { 00263 // Send GKH message 2 00264 supp_gkh_sec_prot_message_send(prot, GKH_MESSAGE_2); 00265 sec_prot_state_set(prot, &data->common, GKH_STATE_FINISH); 00266 } else { 00267 // Ready to be deleted 00268 sec_prot_state_set(prot, &data->common, GKH_STATE_FINISHED); 00269 } 00270 break; 00271 00272 case GKH_STATE_FINISH: 00273 tr_info("GKH finish"); 00274 00275 // KMP-FINISHED.indication, 00276 prot->finished_ind(prot, sec_prot_result_get(&data->common), prot->sec_keys); 00277 sec_prot_state_set(prot, &data->common, GKH_STATE_FINISHED); 00278 break; 00279 00280 case GKH_STATE_FINISHED: 00281 tr_info("GKH finished"); 00282 prot->timer_stop(prot); 00283 prot->finished(prot); 00284 break; 00285 00286 default: 00287 break; 00288 } 00289 } 00290 00291 static int8_t supp_gkh_sec_prot_mic_validate(sec_prot_t *prot) 00292 { 00293 gkh_sec_prot_int_t *data = gkh_sec_prot_get(prot); 00294 return sec_prot_lib_mic_validate(prot->sec_keys->ptk, data->recv_eapol_pdu.msg.key.key_mic, data->recv_pdu, data->recv_size); 00295 } 00296 00297 static void supp_gkh_sec_prot_security_replay_counter_update(sec_prot_t *prot) 00298 { 00299 gkh_sec_prot_int_t *data = gkh_sec_prot_get(prot); 00300 sec_prot_keys_pmk_replay_cnt_set(prot->sec_keys, data->recv_eapol_pdu.msg.key.replay_counter); 00301 } 00302 00303 static int8_t supp_gkh_kde_handle(sec_prot_t *prot) 00304 { 00305 gkh_sec_prot_int_t *data = gkh_sec_prot_get(prot); 00306 00307 uint16_t kde_len; 00308 uint8_t *kde = sec_prot_lib_message_handle(prot->sec_keys->ptk, &kde_len, &data->recv_eapol_pdu); 00309 if (!kde) { 00310 return -1; 00311 } 00312 00313 // If a valid new GTK value present, insert it 00314 int8_t ret = sec_prot_lib_gtk_read(kde, kde_len, prot->sec_keys); 00315 00316 ns_dyn_mem_free(kde); 00317 00318 return ret; 00319 } 00320 00321 #endif /* HAVE_WS */ 00322
Generated on Tue Jul 12 2022 13:54:54 by
