Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers kmp_api.c Source File

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