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
key_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/key_sec_prot/key_sec_prot.h" 00037 00038 #ifdef HAVE_WS 00039 00040 #define TRACE_GROUP "ksep" 00041 00042 #define KEY_SEC_FINISHED_TIMEOUT 1 // Finishes right away 00043 00044 typedef enum { 00045 KEY_STATE_INIT = SEC_STATE_INIT, 00046 KEY_STATE_CREATE_REQ = SEC_STATE_CREATE_REQ, 00047 KEY_STATE_CREATE_RESP = SEC_STATE_CREATE_RESP, 00048 KEY_STATE_TX_DONE = SEC_STATE_FIRST, 00049 KEY_STATE_INITIAL_KEY_RECEIVED, 00050 KEY_STATE_FINISH = SEC_STATE_FINISH, 00051 KEY_STATE_FINISHED = SEC_STATE_FINISHED 00052 } key_sec_prot_state_e; 00053 00054 typedef struct { 00055 sec_prot_common_t common; /**< Common data */ 00056 } key_sec_prot_int_t; 00057 00058 static uint16_t key_sec_prot_size(void); 00059 static int8_t supp_key_sec_prot_init(sec_prot_t *prot); 00060 static int8_t auth_key_sec_prot_init(sec_prot_t *prot); 00061 00062 static void key_sec_prot_create_request(sec_prot_t *prot, sec_prot_keys_t *sec_keys); 00063 static void key_sec_prot_create_response(sec_prot_t *prot, sec_prot_result_e result); 00064 static void key_sec_prot_delete(sec_prot_t *prot); 00065 static int8_t key_sec_prot_initial_key_send(sec_prot_t *prot, sec_prot_keys_t *sec_keys); 00066 static int8_t key_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size); 00067 static int8_t key_sec_prot_tx_status_ind(sec_prot_t *prot, sec_prot_tx_status_e tx_status); 00068 static void key_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks); 00069 00070 static void supp_key_sec_prot_state_machine(sec_prot_t *prot); 00071 static void auth_key_sec_prot_state_machine(sec_prot_t *prot); 00072 00073 #define key_sec_prot_get(prot) (key_sec_prot_int_t *) &prot->data 00074 00075 int8_t supp_key_sec_prot_register(kmp_service_t *service) 00076 { 00077 if (!service) { 00078 return -1; 00079 } 00080 00081 if (kmp_service_sec_protocol_register(service, IEEE_802_1X_MKA_KEY, key_sec_prot_size, supp_key_sec_prot_init) < 0) { 00082 return -1; 00083 } 00084 00085 if (kmp_service_sec_protocol_register(service, IEEE_802_11_GKH_KEY, key_sec_prot_size, supp_key_sec_prot_init) < 0) { 00086 return -1; 00087 } 00088 00089 return 0; 00090 } 00091 00092 int8_t auth_key_sec_prot_register(kmp_service_t *service) 00093 { 00094 if (!service) { 00095 return -1; 00096 } 00097 00098 if (kmp_service_sec_protocol_register(service, IEEE_802_1X_MKA_KEY, key_sec_prot_size, auth_key_sec_prot_init) < 0) { 00099 return -1; 00100 } 00101 00102 if (kmp_service_sec_protocol_register(service, IEEE_802_11_GKH_KEY, key_sec_prot_size, auth_key_sec_prot_init) < 0) { 00103 return -1; 00104 } 00105 00106 return 0; 00107 } 00108 00109 static uint16_t key_sec_prot_size(void) 00110 { 00111 return sizeof(key_sec_prot_int_t); 00112 } 00113 00114 static int8_t supp_key_sec_prot_init(sec_prot_t *prot) 00115 { 00116 prot->create_req = key_sec_prot_create_request; 00117 prot->tx_status_ind = key_sec_prot_tx_status_ind; 00118 prot->delete = key_sec_prot_delete; 00119 prot->state_machine = supp_key_sec_prot_state_machine; 00120 prot->timer_timeout = key_sec_prot_timer_timeout; 00121 00122 key_sec_prot_int_t *data = key_sec_prot_get(prot); 00123 sec_prot_init(&data->common); 00124 sec_prot_state_set(prot, &data->common, KEY_STATE_INIT); 00125 00126 return 0; 00127 } 00128 00129 static int8_t auth_key_sec_prot_init(sec_prot_t *prot) 00130 { 00131 prot->create_resp = key_sec_prot_create_response; 00132 prot->receive = key_sec_prot_receive; 00133 prot->delete = key_sec_prot_delete; 00134 prot->state_machine = auth_key_sec_prot_state_machine; 00135 prot->timer_timeout = key_sec_prot_timer_timeout; 00136 00137 key_sec_prot_int_t *data = key_sec_prot_get(prot); 00138 sec_prot_init(&data->common); 00139 sec_prot_state_set(prot, &data->common, KEY_STATE_INIT); 00140 00141 return 0; 00142 } 00143 00144 static void key_sec_prot_delete(sec_prot_t *prot) 00145 { 00146 (void) prot; 00147 } 00148 00149 static void key_sec_prot_create_request(sec_prot_t *prot, sec_prot_keys_t *sec_keys) 00150 { 00151 (void) sec_keys; 00152 00153 prot->state_machine_call(prot); 00154 } 00155 00156 static void key_sec_prot_create_response(sec_prot_t *prot, sec_prot_result_e result) 00157 { 00158 key_sec_prot_int_t *data = key_sec_prot_get(prot); 00159 sec_prot_state_set(prot, &data->common, KEY_STATE_CREATE_RESP); 00160 00161 sec_prot_result_set(&data->common, result); 00162 prot->state_machine_call(prot); 00163 } 00164 00165 static int8_t key_sec_prot_initial_key_send(sec_prot_t *prot, sec_prot_keys_t *sec_keys) 00166 { 00167 uint8_t result = 0; 00168 uint16_t kde_len = KDE_GTKL_LEN; 00169 00170 uint8_t *pmk = sec_prot_keys_pmk_get(sec_keys); 00171 uint8_t pmkid[PMKID_LEN]; 00172 if (pmk) { 00173 if (sec_prot_lib_pmkid_generate(prot, pmkid, false) >= 0) { 00174 kde_len += KDE_PMKID_LEN; 00175 } else { 00176 pmk = NULL; 00177 } 00178 } 00179 00180 uint8_t *ptk = sec_prot_keys_ptk_get(sec_keys); 00181 uint8_t ptkid[PTKID_LEN]; 00182 if (ptk) { 00183 if (sec_prot_lib_ptkid_generate(prot, ptkid, false) >= 0) { 00184 kde_len += KDE_PTKID_LEN; 00185 } else { 00186 ptk = NULL; 00187 } 00188 } 00189 00190 uint8_t *kde_start = ns_dyn_mem_temporary_alloc(kde_len); 00191 if (!kde_start) { 00192 return -1; 00193 } 00194 00195 uint8_t *kde_end = kde_start; 00196 00197 if (pmk) { 00198 kde_end = kde_pmkid_write(kde_end, pmkid); 00199 } 00200 00201 if (ptk) { 00202 kde_end = kde_ptkid_write(kde_end, ptkid); 00203 } 00204 00205 uint8_t gtkl = sec_prot_keys_fresh_gtkl_get(sec_keys->gtks); 00206 kde_end = kde_gtkl_write(kde_end, gtkl); 00207 00208 kde_len = kde_end - kde_start; 00209 00210 eapol_pdu_t eapol_pdu; 00211 00212 uint16_t eapol_pdu_size = eapol_pdu_key_frame_init(&eapol_pdu, kde_len, kde_start); 00213 00214 uint8_t *eapol_decoded_data = ns_dyn_mem_temporary_alloc(eapol_pdu_size + prot->header_size); // In future fill with data that defines eapol message 00215 if (!eapol_decoded_data) { 00216 result = -1; 00217 goto initial_key_exit; 00218 } 00219 00220 eapol_pdu.msg.key.key_information.install = false; 00221 eapol_pdu.msg.key.key_information.pairwise_key = false; 00222 eapol_pdu.msg.key.key_information.request = true; 00223 eapol_pdu.msg.key.replay_counter = 0; 00224 eapol_pdu.msg.key.key_length = 0; 00225 eapol_write_pdu_frame(eapol_decoded_data + prot->header_size, &eapol_pdu); 00226 00227 tr_info("Initial EAPOL-Key send, PMKID %s PTKID %s GTKL %x", pmk ? "set" : "not set", ptk ? "set" : "not set", gtkl); 00228 00229 if (prot->send(prot, eapol_decoded_data, eapol_pdu_size + prot->header_size) < 0) { 00230 result = -1; 00231 } 00232 00233 initial_key_exit: 00234 ns_dyn_mem_free(kde_start); 00235 00236 return result; 00237 } 00238 00239 static int8_t key_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size) 00240 { 00241 eapol_pdu_t eapol_pdu; 00242 key_sec_prot_int_t *data = key_sec_prot_get(prot); 00243 sec_prot_result_e result = SEC_RESULT_OK; 00244 00245 tr_info("Initial EAPOL-Key recv, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); 00246 00247 // Decoding is successful 00248 if (eapol_parse_pdu_header(pdu, size, &eapol_pdu)) { 00249 if (eapol_pdu.packet_type != EAPOL_KEY_TYPE) { 00250 tr_info("not EAPOL-Key packet"); 00251 prot->finished(prot); 00252 return -1; 00253 } 00254 00255 uint16_t kde_len; 00256 uint8_t *kde = sec_prot_lib_message_handle(prot->sec_keys->ptk, &kde_len, &eapol_pdu); 00257 if (!kde) { 00258 tr_error("no KDEs"); 00259 prot->finished(prot); 00260 return -1; 00261 } 00262 00263 // Default assumption is that PMK and PTK are not valid 00264 prot->sec_keys->pmk_mismatch = true; 00265 prot->sec_keys->ptk_mismatch = true; 00266 00267 // Checks if supplicant indicates that it has valid PMK 00268 uint8_t remote_keyid[KEYID_LEN]; 00269 if (kde_pmkid_read(kde, kde_len, remote_keyid) >= 0) { 00270 uint8_t pmkid[PMKID_LEN]; 00271 if (sec_prot_lib_pmkid_generate(prot, pmkid, true) >= 0) { 00272 if (memcmp(remote_keyid, pmkid, PMKID_LEN) == 0) { 00273 prot->sec_keys->pmk_mismatch = false; 00274 } 00275 } 00276 } 00277 00278 // Checks if supplicant indicates that it has valid PTK 00279 if (kde_ptkid_read(kde, kde_len, remote_keyid) >= 0) { 00280 uint8_t ptkid[PTKID_LEN]; 00281 if (sec_prot_lib_ptkid_generate(prot, ptkid, true) >= 0) { 00282 if (memcmp(remote_keyid, ptkid, PTKID_LEN) == 0) { 00283 prot->sec_keys->ptk_mismatch = false; 00284 } 00285 } 00286 } 00287 00288 // Get the GTKL that supplicant indicates 00289 uint8_t gtkl; 00290 if (kde_gtkl_read(kde, kde_len, >kl) >= 0) { 00291 prot->sec_keys->gtkl = gtkl; 00292 } else { 00293 tr_error("no GTKL"); 00294 return -1; 00295 } 00296 00297 tr_info("PMK %s PTK %s GTKL %x", prot->sec_keys->pmk_mismatch ? "not live" : "live", prot->sec_keys->ptk_mismatch ? "not live" : "live", gtkl); 00298 00299 ns_dyn_mem_free(kde); 00300 } else { 00301 tr_error("Invalid"); 00302 result = SEC_RESULT_ERROR; 00303 } 00304 00305 sec_prot_result_set(&data->common, result); 00306 prot->state_machine(prot); 00307 00308 if (result != SEC_RESULT_OK) { 00309 return -1; 00310 } 00311 00312 return 0; 00313 } 00314 00315 static int8_t key_sec_prot_tx_status_ind(sec_prot_t *prot, sec_prot_tx_status_e tx_status) 00316 { 00317 key_sec_prot_int_t *data = key_sec_prot_get(prot); 00318 00319 // Indicates TX failure 00320 if (tx_status == SEC_PROT_TX_ERR_TX_NO_ACK) { 00321 sec_prot_result_set(&data->common, KMP_RESULT_ERR_TX_NO_ACK); 00322 } else if (tx_status != SEC_PROT_TX_OK) { 00323 // Indicates other failure 00324 sec_prot_result_set(&data->common, KMP_RESULT_ERR_UNSPEC); 00325 } 00326 prot->state_machine_call(prot); 00327 return 0; 00328 } 00329 00330 static void key_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks) 00331 { 00332 key_sec_prot_int_t *data = key_sec_prot_get(prot); 00333 sec_prot_timer_timeout_handle(prot, &data->common, NULL, ticks); 00334 } 00335 00336 static void supp_key_sec_prot_state_machine(sec_prot_t *prot) 00337 { 00338 key_sec_prot_int_t *data = key_sec_prot_get(prot); 00339 00340 switch (sec_prot_state_get(&data->common)) { 00341 case KEY_STATE_INIT: 00342 tr_info("Initial-key init"); 00343 sec_prot_state_set(prot, &data->common, KEY_STATE_CREATE_REQ); 00344 prot->timer_start(prot); 00345 break; 00346 00347 case KEY_STATE_CREATE_REQ: 00348 // KMP-CREATE.confirm 00349 prot->create_conf(prot, sec_prot_result_get(&data->common)); 00350 00351 // Send initial-key message 00352 if (key_sec_prot_initial_key_send(prot, prot->sec_keys) < 0) { 00353 // Error on sending, ready to be deleted 00354 sec_prot_state_set(prot, &data->common, KEY_STATE_FINISH); 00355 return; 00356 } 00357 00358 // Waits for TX acknowledge 00359 sec_prot_state_set(prot, &data->common, KEY_STATE_TX_DONE); 00360 break; 00361 00362 case KEY_STATE_TX_DONE: 00363 sec_prot_state_set(prot, &data->common, KEY_STATE_FINISH); 00364 break; 00365 00366 case KEY_STATE_FINISH: 00367 // KMP-FINISHED.indication, 00368 prot->finished_ind(prot, sec_prot_result_get(&data->common), 0); 00369 sec_prot_state_set(prot, &data->common, KEY_STATE_FINISHED); 00370 data->common.ticks = KEY_SEC_FINISHED_TIMEOUT; 00371 break; 00372 00373 case KEY_STATE_FINISHED: 00374 tr_info("Initial-key finished"); 00375 prot->timer_stop(prot); 00376 prot->finished(prot); 00377 break; 00378 00379 default: 00380 break; 00381 } 00382 } 00383 00384 static void auth_key_sec_prot_state_machine(sec_prot_t *prot) 00385 { 00386 key_sec_prot_int_t *data = key_sec_prot_get(prot); 00387 00388 switch (sec_prot_state_get(&data->common)) { 00389 case KEY_STATE_INIT: 00390 tr_info("Initial-key init"); 00391 sec_prot_state_set(prot, &data->common, KEY_STATE_INITIAL_KEY_RECEIVED); 00392 prot->timer_start(prot); 00393 break; 00394 00395 case KEY_STATE_INITIAL_KEY_RECEIVED: 00396 if (!sec_prot_result_ok_check(&data->common)) { 00397 // Goes right away to finished 00398 sec_prot_state_set(prot, &data->common, KEY_STATE_FINISHED); 00399 return; 00400 } 00401 00402 // Send KMP-CREATE.indication 00403 prot->create_ind(prot); 00404 sec_prot_state_set(prot, &data->common, KEY_STATE_CREATE_RESP); 00405 break; 00406 00407 case KEY_STATE_CREATE_RESP: 00408 // Goes to finish state right away 00409 sec_prot_state_set(prot, &data->common, KEY_STATE_FINISH); 00410 break; 00411 00412 case KEY_STATE_FINISH: 00413 // KMP-FINISHED.indication, 00414 prot->finished_ind(prot, sec_prot_result_get(&data->common), 0); 00415 sec_prot_state_set(prot, &data->common, KEY_STATE_FINISHED); 00416 data->common.ticks = KEY_SEC_FINISHED_TIMEOUT; 00417 break; 00418 00419 case KEY_STATE_FINISHED: { 00420 tr_info("Initial-key finished, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); 00421 prot->finished(prot); 00422 break; 00423 } 00424 00425 default: 00426 break; 00427 } 00428 } 00429 00430 #endif /* HAVE_WS */ 00431
Generated on Tue Jul 12 2022 13:54:25 by
 1.7.2
 1.7.2