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
kmp_api.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/kmp/kmp_socket_if.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 00035 #ifdef HAVE_WS 00036 00037 #define TRACE_GROUP "kmap" 00038 00039 struct kmp_api_s { 00040 void *app_data_ptr; /**< Opaque pointer for application data */ 00041 kmp_api_create_confirm *create_conf; /**< KMP-CREATE.confirm callback */ 00042 kmp_api_create_indication *create_ind; /**< KMP-CREATE.indication callback */ 00043 kmp_api_finished_indication *finished_ind; /**< KMP-FINISHED.indication callback */ 00044 kmp_api_finished *finished; /**< Finished i.e. ready to be deleted callback */ 00045 kmp_type_e type; /**< KMP type */ 00046 kmp_addr_t *addr; /**< Supplicant EUI-64, Relay IP address, Relay port */ 00047 kmp_service_t *service; /**< KMP service */ 00048 uint8_t instance_identifier; /**< KMP instance identifier, incremented when created, from 0 to 255 */ 00049 bool timer_start_pending : 1; /**< Timer is pending to start */ 00050 bool receive_disable : 1; /**< Receiving disabled, do not route messages anymore */ 00051 sec_prot_t sec_prot; /**< Security protocol interface */ 00052 }; 00053 00054 typedef struct { 00055 kmp_type_e type; /**< Security protocol type callback */ 00056 kmp_sec_prot_size *size; /**< Security protocol data size callback */ 00057 kmp_sec_prot_init *init; /**< Security protocol init */ 00058 ns_list_link_t link; /**< Link */ 00059 } kmp_sec_prot_entry_t; 00060 00061 typedef NS_LIST_HEAD (kmp_sec_prot_entry_t, link) kmp_sec_prot_list_t; 00062 00063 struct kmp_service_s { 00064 kmp_sec_prot_list_t sec_prot_list; /**< Security protocols list */ 00065 kmp_service_incoming_ind *incoming_ind; /**< Callback to application to indicate incoming KMP frame */ 00066 kmp_service_tx_status_ind *tx_status_ind; /**< Callback to application to indicate TX status */ 00067 kmp_service_addr_get *addr_get; /**< Callback to get addresses related to KMP */ 00068 kmp_service_api_get *api_get; /**< Callback to get KMP API from a service */ 00069 kmp_service_msg_if_send *send; /**< Callback to send KMP frames */ 00070 kmp_service_timer_if_start *timer_start; /**< Callback to start timer */ 00071 kmp_service_timer_if_stop *timer_stop; /**< Callback to stop timer */ 00072 kmp_service_event_if_event_send *event_send; /**< Callback to send event */ 00073 uint8_t header_size; /**< Header size */ 00074 ns_list_link_t link; /**< Link */ 00075 }; 00076 00077 typedef struct { 00078 uint8_t kmp_id; /**< Kmp id */ 00079 uint8_t kmp_data; /**< Kmp data e.g. eapol frame */ 00080 } kmp_pdu_t; 00081 00082 static NS_LIST_DEFINE(kmp_service_list, kmp_service_t, link); 00083 00084 // KMP instance identifier value 00085 static uint8_t kmp_instance_identifier = 0; 00086 00087 static void kmp_api_sec_prot_create_confirm(sec_prot_t *prot, sec_prot_result_e result); 00088 static void kmp_api_sec_prot_create_indication(sec_prot_t *prot); 00089 static void kmp_api_sec_prot_finished_indication(sec_prot_t *prot, sec_prot_result_e result, sec_prot_keys_t *sec_keys); 00090 static void kmp_api_sec_prot_finished(sec_prot_t *prot); 00091 static int8_t kmp_sec_prot_send(sec_prot_t *prot, void *pdu, uint16_t size); 00092 static void kmp_sec_prot_timer_start(sec_prot_t *prot); 00093 static void kmp_sec_prot_timer_stop(sec_prot_t *prot); 00094 static void kmp_sec_prot_state_machine_call(sec_prot_t *prot); 00095 static void kmp_sec_prot_eui64_addr_get(sec_prot_t *prot, uint8_t *local_eui64, uint8_t *remote_eui64); 00096 static sec_prot_t *kmp_sec_prot_by_type_get(sec_prot_t *prot, uint8_t type); 00097 static void kmp_sec_prot_receive_disable(sec_prot_t *prot); 00098 00099 #define kmp_api_get_from_prot(prot) (kmp_api_t *)(((uint8_t *)prot) - offsetof(kmp_api_t, sec_prot)); 00100 00101 kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type) 00102 { 00103 if (!service) { 00104 return 0; 00105 } 00106 00107 kmp_sec_prot_entry_t *sec_prot = 0; 00108 ns_list_foreach(kmp_sec_prot_entry_t, list_entry, &service->sec_prot_list) { 00109 if (list_entry->type == type) { 00110 sec_prot = list_entry; 00111 break; 00112 } 00113 } 00114 00115 if (!sec_prot) { 00116 // Unknown security protocol 00117 return 0; 00118 } 00119 // Size for security protocol internal data 00120 uint16_t sec_size = sec_prot->size(); 00121 00122 kmp_api_t *kmp = ns_dyn_mem_temporary_alloc(sizeof(kmp_api_t) + sec_size); 00123 if (!kmp) { 00124 return 0; 00125 } 00126 00127 kmp->type = type; 00128 kmp->app_data_ptr = 0; 00129 kmp->create_conf = 0; 00130 kmp->create_ind = 0; 00131 kmp->finished_ind = 0; 00132 kmp->finished = 0; 00133 kmp->instance_identifier = kmp_instance_identifier++; 00134 kmp->addr = 0; 00135 kmp->service = service; 00136 kmp->timer_start_pending = false; 00137 kmp->receive_disable = false; 00138 00139 memset(&kmp->sec_prot, 0, sec_size); 00140 00141 kmp->sec_prot.header_size = service->header_size; 00142 kmp->sec_prot.create_conf = kmp_api_sec_prot_create_confirm; 00143 kmp->sec_prot.create_ind = kmp_api_sec_prot_create_indication; 00144 kmp->sec_prot.finished_ind = kmp_api_sec_prot_finished_indication; 00145 kmp->sec_prot.finished = kmp_api_sec_prot_finished; 00146 kmp->sec_prot.send = kmp_sec_prot_send; 00147 kmp->sec_prot.timer_start = kmp_sec_prot_timer_start; 00148 kmp->sec_prot.timer_stop = kmp_sec_prot_timer_stop; 00149 kmp->sec_prot.state_machine_call = kmp_sec_prot_state_machine_call; 00150 kmp->sec_prot.addr_get = kmp_sec_prot_eui64_addr_get; 00151 kmp->sec_prot.type_get = kmp_sec_prot_by_type_get; 00152 kmp->sec_prot.receive_disable = kmp_sec_prot_receive_disable; 00153 00154 if (sec_prot->init(&kmp->sec_prot) < 0) { 00155 ns_dyn_mem_free(kmp); 00156 return 0; 00157 } 00158 00159 return (kmp_api_t *) kmp; 00160 } 00161 00162 int8_t kmp_api_start(kmp_api_t *kmp) 00163 { 00164 if (kmp->timer_start_pending) { 00165 if (kmp->service->timer_start(kmp->service, kmp) < 0) { 00166 return -1; 00167 } 00168 } 00169 return 0; 00170 } 00171 00172 void kmp_api_create_request(kmp_api_t *kmp, kmp_type_e type, kmp_addr_t *addr, kmp_sec_keys_t *sec_keys) 00173 { 00174 kmp->type = type; 00175 kmp->addr = addr; 00176 kmp->sec_prot.create_req(&kmp->sec_prot, sec_keys); 00177 } 00178 00179 void kmp_api_create_response(kmp_api_t *kmp, kmp_result_e result) 00180 { 00181 kmp->sec_prot.create_resp(&kmp->sec_prot, (sec_prot_result_e) result); 00182 } 00183 00184 static void kmp_api_sec_prot_create_confirm(sec_prot_t *prot, sec_prot_result_e result) 00185 { 00186 kmp_api_t *kmp = kmp_api_get_from_prot(prot); 00187 kmp->create_conf((kmp_api_t *)kmp, (kmp_result_e) result); 00188 } 00189 00190 static void kmp_api_sec_prot_create_indication(sec_prot_t *prot) 00191 { 00192 kmp_api_t *kmp = kmp_api_get_from_prot(prot); 00193 kmp->create_ind((kmp_api_t *)kmp, kmp->type, kmp->addr); 00194 } 00195 00196 static void kmp_api_sec_prot_finished_indication(sec_prot_t *prot, sec_prot_result_e result, sec_prot_keys_t *sec_keys) 00197 { 00198 kmp_api_t *kmp = kmp_api_get_from_prot(prot); 00199 kmp->finished_ind((kmp_api_t *)kmp, (kmp_result_e) result, sec_keys); 00200 } 00201 00202 static void kmp_api_sec_prot_finished(sec_prot_t *prot) 00203 { 00204 kmp_api_t *kmp = kmp_api_get_from_prot(prot); 00205 kmp->finished((kmp_api_t *)kmp); 00206 } 00207 00208 static int8_t kmp_sec_prot_send(sec_prot_t *prot, void *pdu, uint16_t size) 00209 { 00210 kmp_api_t *kmp = kmp_api_get_from_prot(prot); 00211 00212 // Convert from internal initial key type to real type if needed 00213 kmp_type_e kmp_id = kmp->type; 00214 if (kmp_id > IEEE_802_1X_INITIAL_KEY) { 00215 kmp_id -= IEEE_802_1X_INITIAL_KEY; 00216 } 00217 00218 int8_t result = -1; 00219 00220 if (kmp->service->send) { 00221 result = kmp->service->send(kmp->service, kmp_id, kmp->addr, pdu, size, kmp->instance_identifier); 00222 } 00223 00224 if (result < 0) { 00225 ns_dyn_mem_free(pdu); 00226 } 00227 00228 return result; 00229 } 00230 00231 static void kmp_sec_prot_timer_start(sec_prot_t *prot) 00232 { 00233 kmp_api_t *kmp = kmp_api_get_from_prot(prot); 00234 kmp->timer_start_pending = false; 00235 if (kmp->service->timer_start(kmp->service, kmp) < 0) { 00236 kmp->timer_start_pending = true; 00237 } 00238 } 00239 00240 static void kmp_sec_prot_timer_stop(sec_prot_t *prot) 00241 { 00242 kmp_api_t *kmp = kmp_api_get_from_prot(prot); 00243 kmp->service->timer_stop(kmp->service, kmp); 00244 kmp->timer_start_pending = false; 00245 } 00246 00247 static void kmp_sec_prot_eui64_addr_get(sec_prot_t *prot, uint8_t *local_eui64, uint8_t *remote_eui64) 00248 { 00249 kmp_api_t *kmp = kmp_api_get_from_prot(prot); 00250 00251 kmp_addr_t local_addr; 00252 kmp_address_init(KMP_ADDR_EUI_64, &local_addr, NULL); 00253 00254 kmp_addr_t remote_addr; 00255 kmp_address_init(KMP_ADDR_EUI_64, &remote_addr, NULL); 00256 00257 kmp->service->addr_get(kmp->service, kmp, &local_addr, &remote_addr); 00258 00259 if (local_eui64) { 00260 memcpy(local_eui64, local_addr.eui_64, 8); 00261 } 00262 if (remote_eui64) { 00263 memcpy(remote_eui64, remote_addr.eui_64, 8); 00264 } 00265 } 00266 00267 static sec_prot_t *kmp_sec_prot_by_type_get(sec_prot_t *prot, uint8_t type) 00268 { 00269 kmp_api_t *kmp = kmp_api_get_from_prot(prot); 00270 00271 kmp_type_e kmp_type; 00272 00273 switch (type) { 00274 case SEC_PROT_TYPE_EAP_TLS: 00275 kmp_type = IEEE_802_1X_MKA; 00276 break; 00277 case SEC_PROT_TYPE_TLS: 00278 kmp_type = TLS_PROT; 00279 break; 00280 default: 00281 return NULL; 00282 } 00283 00284 kmp_api_t *kmp_by_type = kmp->service->api_get(kmp->service, kmp, kmp_type); 00285 if (!kmp_by_type) { 00286 return NULL; 00287 } 00288 00289 return &kmp_by_type->sec_prot; 00290 } 00291 00292 static void kmp_sec_prot_receive_disable(sec_prot_t *prot) 00293 { 00294 kmp_api_t *kmp = kmp_api_get_from_prot(prot); 00295 kmp->receive_disable = true; 00296 } 00297 00298 void kmp_api_delete(kmp_api_t *kmp) 00299 { 00300 if (kmp->sec_prot.delete) { 00301 kmp->sec_prot.delete(&kmp->sec_prot); 00302 } 00303 ns_dyn_mem_free(kmp); 00304 } 00305 00306 void kmp_api_cb_register(kmp_api_t *kmp, kmp_api_create_confirm *create_conf, kmp_api_create_indication *create_ind, kmp_api_finished_indication *finished_ind, kmp_api_finished *finished) 00307 { 00308 if (!kmp) { 00309 return; 00310 } 00311 00312 kmp->create_conf = create_conf; 00313 kmp->create_ind = create_ind; 00314 kmp->finished_ind = finished_ind; 00315 kmp->finished = finished; 00316 } 00317 00318 kmp_type_e kmp_api_type_get(kmp_api_t *kmp) 00319 { 00320 return kmp->type; 00321 } 00322 00323 bool kmp_api_receive_disable(kmp_api_t *kmp) 00324 { 00325 return kmp->receive_disable; 00326 } 00327 00328 kmp_type_e kmp_api_type_from_id_get(uint8_t kmp_id) 00329 { 00330 switch (kmp_id) { 00331 case IEEE_802_1X_MKA: 00332 return IEEE_802_1X_MKA; 00333 case IEEE_802_11_4WH: 00334 return IEEE_802_11_4WH; 00335 case IEEE_802_11_GKH: 00336 return IEEE_802_11_GKH; 00337 default: 00338 return KMP_TYPE_NONE; 00339 } 00340 } 00341 00342 kmp_service_t *kmp_api_service_get(kmp_api_t *kmp) 00343 { 00344 return kmp->service; 00345 } 00346 00347 void kmp_api_data_set(kmp_api_t *kmp, void *data) 00348 { 00349 kmp->app_data_ptr = data; 00350 } 00351 00352 void *kmp_api_data_get(kmp_api_t *kmp) 00353 { 00354 return kmp->app_data_ptr; 00355 } 00356 00357 uint8_t kmp_api_instance_id_get(kmp_api_t *kmp) 00358 { 00359 return kmp->instance_identifier; 00360 } 00361 00362 void kmp_api_addr_set(kmp_api_t *kmp, kmp_addr_t *addr) 00363 { 00364 kmp->addr = addr; 00365 } 00366 00367 void kmp_api_sec_keys_set(kmp_api_t *kmp, kmp_sec_keys_t *sec_keys) 00368 { 00369 kmp->sec_prot.sec_keys = sec_keys; 00370 } 00371 00372 kmp_service_t *kmp_service_create(void) 00373 { 00374 kmp_service_t *service = ns_dyn_mem_alloc(sizeof(kmp_service_t)); 00375 if (!service) { 00376 return NULL; 00377 } 00378 00379 ns_list_init(&service->sec_prot_list); 00380 service->incoming_ind = 0; 00381 service->tx_status_ind = 0; 00382 service->addr_get = 0; 00383 service->api_get = 0; 00384 service->send = 0; 00385 service->header_size = 0; 00386 00387 ns_list_add_to_start(&kmp_service_list, service); 00388 00389 return service; 00390 } 00391 00392 int8_t kmp_service_delete(kmp_service_t *service) 00393 { 00394 if (!service) { 00395 return -1; 00396 } 00397 00398 ns_list_foreach_safe(kmp_service_t, list_entry, &kmp_service_list) { 00399 if (list_entry == service) { 00400 ns_list_foreach_safe(kmp_sec_prot_entry_t, sec_list_entry, &list_entry->sec_prot_list) { 00401 ns_list_remove(&list_entry->sec_prot_list, sec_list_entry); 00402 ns_dyn_mem_free(sec_list_entry); 00403 } 00404 00405 ns_list_remove(&kmp_service_list, list_entry); 00406 ns_dyn_mem_free(list_entry); 00407 return 0; 00408 } 00409 } 00410 00411 return -1; 00412 } 00413 00414 static void kmp_sec_prot_state_machine_call(sec_prot_t *prot) 00415 { 00416 kmp_api_t *kmp = kmp_api_get_from_prot(prot); 00417 kmp->service->event_send(kmp->service, prot); 00418 } 00419 00420 int8_t kmp_service_cb_register(kmp_service_t *service, kmp_service_incoming_ind *incoming_ind, kmp_service_tx_status_ind *tx_status_ind, kmp_service_addr_get *addr_get, kmp_service_api_get *api_get) 00421 { 00422 if (!service) { 00423 return -1; 00424 } 00425 00426 service->incoming_ind = incoming_ind; 00427 service->tx_status_ind = tx_status_ind; 00428 service->addr_get = addr_get; 00429 service->api_get = api_get; 00430 00431 return 0; 00432 } 00433 00434 int8_t kmp_service_msg_if_register(kmp_service_t *service, kmp_service_msg_if_send *send, uint8_t header_size) 00435 { 00436 if (!service) { 00437 return -1; 00438 } 00439 00440 service->send = send; 00441 service->header_size = header_size; 00442 00443 return 0; 00444 } 00445 00446 int8_t kmp_service_msg_if_receive(kmp_service_t *service, kmp_type_e type, const kmp_addr_t *addr, void *pdu, uint16_t size) 00447 { 00448 if (!service) { 00449 return -1; 00450 } 00451 00452 kmp_api_t *kmp = (kmp_api_t *) service->incoming_ind(service, type, addr); 00453 if (!kmp) { 00454 return -1; 00455 } 00456 00457 // Security protocol has disables message receiving 00458 if (kmp->receive_disable) { 00459 return -1; 00460 } 00461 00462 int8_t ret = kmp->sec_prot.receive(&kmp->sec_prot, pdu, size); 00463 return ret; 00464 } 00465 00466 int8_t kmp_service_tx_status_indication(kmp_service_t *service, kmp_tx_status_e tx_status, uint8_t tx_identifier) 00467 { 00468 if (!service || !service->tx_status_ind) { 00469 return -1; 00470 } 00471 00472 // Application can use the tx_identifier to match the TX status indication to kmp 00473 kmp_api_t *kmp = (kmp_api_t *) service->tx_status_ind(service, tx_identifier); 00474 if (!kmp) { 00475 return -1; 00476 } 00477 00478 // Security protocol has disabled message receiving or tx status indication is not set 00479 if (kmp->receive_disable || !kmp->sec_prot.tx_status_ind) { 00480 return -1; 00481 } 00482 00483 sec_prot_tx_status_e sec_prot_tx_status; 00484 if (tx_status == KMP_TX_OK) { 00485 sec_prot_tx_status = SEC_PROT_TX_OK; 00486 } else if (tx_status == KMP_TX_ERR_TX_NO_ACK) { 00487 sec_prot_tx_status = SEC_PROT_TX_ERR_TX_NO_ACK; 00488 } else { 00489 sec_prot_tx_status = SEC_PROT_TX_ERR_UNSPEC; 00490 } 00491 00492 int8_t ret = kmp->sec_prot.tx_status_ind(&kmp->sec_prot, sec_prot_tx_status); 00493 return ret; 00494 } 00495 00496 int8_t kmp_service_sec_protocol_register(kmp_service_t *service, kmp_type_e type, kmp_sec_prot_size *size, kmp_sec_prot_init *init) 00497 { 00498 if (!service) { 00499 return -1; 00500 } 00501 00502 ns_list_foreach(kmp_sec_prot_entry_t, list_entry, &service->sec_prot_list) { 00503 // Already registered 00504 if (list_entry->type == type) { 00505 return -1; 00506 } 00507 } 00508 00509 kmp_sec_prot_entry_t *sec_prot = ns_dyn_mem_temporary_alloc(sizeof(kmp_sec_prot_entry_t)); 00510 if (!sec_prot) { 00511 return -1; 00512 } 00513 00514 sec_prot->type = type; 00515 sec_prot->size = size; 00516 sec_prot->init = init; 00517 00518 ns_list_add_to_start(&service->sec_prot_list, sec_prot); 00519 00520 return 0; 00521 } 00522 00523 int8_t kmp_service_sec_protocol_unregister(kmp_service_t *service, kmp_type_e type) 00524 { 00525 ns_list_foreach(kmp_sec_prot_entry_t, list_entry, &service->sec_prot_list) { 00526 if (list_entry->type == type) { 00527 ns_list_remove(&service->sec_prot_list, list_entry); 00528 ns_dyn_mem_free(list_entry); 00529 return 0; 00530 } 00531 } 00532 return -1; 00533 } 00534 00535 void kmp_service_timer_if_timeout(kmp_api_t *kmp, uint16_t ticks) 00536 { 00537 kmp->sec_prot.timer_timeout(&kmp->sec_prot, ticks); 00538 } 00539 00540 int8_t kmp_service_timer_if_register(kmp_service_t *service, kmp_service_timer_if_start start, kmp_service_timer_if_stop stop) 00541 { 00542 if (!service) { 00543 return -1; 00544 } 00545 00546 service->timer_start = start; 00547 service->timer_stop = stop; 00548 return 0; 00549 } 00550 00551 void kmp_service_event_if_event(kmp_service_t *service, void *data) 00552 { 00553 (void) service; 00554 00555 // For now, only state machine events 00556 sec_prot_t *prot = data; 00557 prot->state_machine(prot); 00558 } 00559 00560 int8_t kmp_service_event_if_register(kmp_service_t *service, kmp_service_event_if_event_send send) 00561 { 00562 if (!service) { 00563 return -1; 00564 } 00565 00566 service->event_send = send; 00567 return 0; 00568 } 00569 00570 #endif /* HAVE_WS */ 00571
Generated on Tue Jul 12 2022 13:54:25 by
