mirror of https://github.com/ARMmbed/mbed-os.git
666 lines
21 KiB
C
666 lines
21 KiB
C
/*
|
|
* Copyright (c) 2016-2019, Arm Limited and affiliates.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "nsconfig.h"
|
|
#include <string.h>
|
|
#include "ns_types.h"
|
|
#include "ns_list.h"
|
|
#include "ns_trace.h"
|
|
#include "nsdynmemLIB.h"
|
|
#include "NWK_INTERFACE/Include/protocol.h"
|
|
#include "Common_Protocols/ipv6_constants.h"
|
|
#include "socket_api.h"
|
|
#include "6LoWPAN/ws/ws_config.h"
|
|
#include "Security/protocols/sec_prot_cfg.h"
|
|
#include "Security/kmp/kmp_addr.h"
|
|
#include "Security/kmp/kmp_api.h"
|
|
#include "Security/kmp/kmp_socket_if.h"
|
|
#include "Security/protocols/sec_prot_certs.h"
|
|
#include "Security/protocols/sec_prot_keys.h"
|
|
#include "Security/protocols/sec_prot.h"
|
|
|
|
#ifdef HAVE_WS
|
|
|
|
#define TRACE_GROUP "kmap"
|
|
|
|
struct kmp_api_s {
|
|
void *app_data_ptr; /**< Opaque pointer for application data */
|
|
kmp_api_create_confirm *create_conf; /**< KMP-CREATE.confirm callback */
|
|
kmp_api_create_indication *create_ind; /**< KMP-CREATE.indication callback */
|
|
kmp_api_finished_indication *finished_ind; /**< KMP-FINISHED.indication callback */
|
|
kmp_api_finished *finished; /**< Finished i.e. ready to be deleted callback */
|
|
kmp_type_e type; /**< KMP type */
|
|
kmp_addr_t *addr; /**< Supplicant EUI-64, Relay IP address, Relay port */
|
|
kmp_service_t *service; /**< KMP service */
|
|
uint8_t instance_identifier; /**< KMP instance identifier, incremented when created, from 0 to 255 */
|
|
bool timer_start_pending : 1; /**< Timer is pending to start */
|
|
bool receive_disable : 1; /**< Receiving disabled, do not route messages anymore */
|
|
sec_prot_t sec_prot; /**< Security protocol interface */
|
|
};
|
|
|
|
typedef struct {
|
|
kmp_type_e type; /**< Security protocol type callback */
|
|
kmp_sec_prot_size *size; /**< Security protocol data size callback */
|
|
kmp_sec_prot_init *init; /**< Security protocol init */
|
|
ns_list_link_t link; /**< Link */
|
|
} kmp_sec_prot_entry_t;
|
|
|
|
typedef NS_LIST_HEAD(kmp_sec_prot_entry_t, link) kmp_sec_prot_list_t;
|
|
|
|
typedef struct {
|
|
uint8_t instance_id; /**< Message interface instance identifier */
|
|
uint8_t header_size; /**< Message interface header size */
|
|
kmp_service_msg_if_send *send; /**< Message interface callback to send KMP frames */
|
|
ns_list_link_t link; /**< Link */
|
|
} kmp_msg_if_entry_t;
|
|
|
|
typedef NS_LIST_HEAD(kmp_msg_if_entry_t, link) kmp_msg_if_list_t;
|
|
|
|
struct kmp_service_s {
|
|
kmp_sec_prot_list_t sec_prot_list; /**< Security protocols list */
|
|
kmp_msg_if_list_t msg_if_list; /**< Message interface list */
|
|
kmp_service_incoming_ind *incoming_ind; /**< Callback to application to indicate incoming KMP frame */
|
|
kmp_service_tx_status_ind *tx_status_ind; /**< Callback to application to indicate TX status */
|
|
kmp_service_addr_get *addr_get; /**< Callback to get addresses related to KMP */
|
|
kmp_service_ip_addr_get *ip_addr_get; /**< Callback to get IP addresses related to KMP */
|
|
kmp_service_api_get *api_get; /**< Callback to get KMP API from a service */
|
|
kmp_service_timer_if_start *timer_start; /**< Callback to start timer */
|
|
kmp_service_timer_if_stop *timer_stop; /**< Callback to stop timer */
|
|
kmp_service_event_if_event_send *event_send; /**< Callback to send event */
|
|
ns_list_link_t link; /**< Link */
|
|
};
|
|
|
|
typedef struct {
|
|
uint8_t kmp_id; /**< Kmp id */
|
|
uint8_t kmp_data; /**< Kmp data e.g. eapol frame */
|
|
} kmp_pdu_t;
|
|
|
|
static NS_LIST_DEFINE(kmp_service_list, kmp_service_t, link);
|
|
|
|
// KMP instance identifier value
|
|
static uint8_t kmp_instance_identifier = 0;
|
|
|
|
static kmp_msg_if_entry_t *kmp_api_msg_if_get(kmp_service_t *service, uint8_t msg_if_instance_id);
|
|
static void kmp_api_sec_prot_create_confirm(sec_prot_t *prot, sec_prot_result_e result);
|
|
static void kmp_api_sec_prot_create_indication(sec_prot_t *prot);
|
|
static void kmp_api_sec_prot_finished_indication(sec_prot_t *prot, sec_prot_result_e result, sec_prot_keys_t *sec_keys);
|
|
static void kmp_api_sec_prot_finished(sec_prot_t *prot);
|
|
static int8_t kmp_sec_prot_send(sec_prot_t *prot, void *pdu, uint16_t size);
|
|
static void kmp_sec_prot_timer_start(sec_prot_t *prot);
|
|
static void kmp_sec_prot_timer_stop(sec_prot_t *prot);
|
|
static void kmp_sec_prot_state_machine_call(sec_prot_t *prot);
|
|
static void kmp_sec_prot_eui64_addr_get(sec_prot_t *prot, uint8_t *local_eui64, uint8_t *remote_eui64);
|
|
static void kmp_sec_prot_ip_addr_get(sec_prot_t *prot, uint8_t *address);
|
|
static sec_prot_t *kmp_sec_prot_by_type_get(sec_prot_t *prot, uint8_t type);
|
|
static void kmp_sec_prot_receive_disable(sec_prot_t *prot);
|
|
|
|
#define kmp_api_get_from_prot(prot) (kmp_api_t *)(((uint8_t *)prot) - offsetof(kmp_api_t, sec_prot));
|
|
|
|
kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type, uint8_t msg_if_instance_id, sec_cfg_t *sec_cfg)
|
|
{
|
|
if (!service) {
|
|
return 0;
|
|
}
|
|
|
|
kmp_sec_prot_entry_t *sec_prot = 0;
|
|
ns_list_foreach(kmp_sec_prot_entry_t, list_entry, &service->sec_prot_list) {
|
|
if (list_entry->type == type) {
|
|
sec_prot = list_entry;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!sec_prot) {
|
|
// Unknown security protocol
|
|
return 0;
|
|
}
|
|
// Size for security protocol internal data
|
|
uint16_t sec_size = sec_prot->size();
|
|
|
|
kmp_msg_if_entry_t *msg_if_entry = kmp_api_msg_if_get(service, msg_if_instance_id);
|
|
if (!msg_if_entry) {
|
|
return 0;
|
|
}
|
|
|
|
kmp_api_t *kmp = ns_dyn_mem_temporary_alloc(sizeof(kmp_api_t) + sec_size);
|
|
if (!kmp) {
|
|
return 0;
|
|
}
|
|
|
|
kmp->type = type;
|
|
kmp->app_data_ptr = 0;
|
|
kmp->create_conf = 0;
|
|
kmp->create_ind = 0;
|
|
kmp->finished_ind = 0;
|
|
kmp->finished = 0;
|
|
kmp->instance_identifier = kmp_instance_identifier++;
|
|
kmp->addr = 0;
|
|
kmp->service = service;
|
|
kmp->timer_start_pending = false;
|
|
kmp->receive_disable = false;
|
|
|
|
memset(&kmp->sec_prot, 0, sec_size + offsetof(sec_prot_t, data));
|
|
|
|
kmp->sec_prot.header_size = msg_if_entry->header_size;
|
|
kmp->sec_prot.receive_peer_hdr_size = msg_if_entry->header_size;
|
|
kmp->sec_prot.create_conf = kmp_api_sec_prot_create_confirm;
|
|
kmp->sec_prot.create_ind = kmp_api_sec_prot_create_indication;
|
|
kmp->sec_prot.finished_ind = kmp_api_sec_prot_finished_indication;
|
|
kmp->sec_prot.finished = kmp_api_sec_prot_finished;
|
|
kmp->sec_prot.send = kmp_sec_prot_send;
|
|
kmp->sec_prot.timer_start = kmp_sec_prot_timer_start;
|
|
kmp->sec_prot.timer_stop = kmp_sec_prot_timer_stop;
|
|
kmp->sec_prot.state_machine_call = kmp_sec_prot_state_machine_call;
|
|
kmp->sec_prot.addr_get = kmp_sec_prot_eui64_addr_get;
|
|
kmp->sec_prot.ip_addr_get = kmp_sec_prot_ip_addr_get;
|
|
kmp->sec_prot.type_get = kmp_sec_prot_by_type_get;
|
|
kmp->sec_prot.receive_disable = kmp_sec_prot_receive_disable;
|
|
kmp->sec_prot.sec_cfg = sec_cfg;
|
|
kmp->sec_prot.msg_if_instance_id = msg_if_instance_id;
|
|
|
|
if (sec_prot->init(&kmp->sec_prot) < 0) {
|
|
ns_dyn_mem_free(kmp);
|
|
return 0;
|
|
}
|
|
|
|
return (kmp_api_t *) kmp;
|
|
}
|
|
|
|
static kmp_msg_if_entry_t *kmp_api_msg_if_get(kmp_service_t *service, uint8_t msg_if_instance_id)
|
|
{
|
|
ns_list_foreach(kmp_msg_if_entry_t, list_entry, &service->msg_if_list) {
|
|
if (list_entry->instance_id == msg_if_instance_id) {
|
|
return list_entry;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int8_t kmp_api_start(kmp_api_t *kmp)
|
|
{
|
|
if (kmp->timer_start_pending) {
|
|
if (kmp->service->timer_start(kmp->service, kmp) < 0) {
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void kmp_api_create_request(kmp_api_t *kmp, kmp_type_e type, kmp_addr_t *addr, kmp_sec_keys_t *sec_keys)
|
|
{
|
|
kmp->type = type;
|
|
kmp->addr = addr;
|
|
kmp->sec_prot.create_req(&kmp->sec_prot, sec_keys);
|
|
}
|
|
|
|
void kmp_api_create_response(kmp_api_t *kmp, kmp_result_e result)
|
|
{
|
|
kmp->sec_prot.create_resp(&kmp->sec_prot, (sec_prot_result_e) result);
|
|
}
|
|
|
|
static void kmp_api_sec_prot_create_confirm(sec_prot_t *prot, sec_prot_result_e result)
|
|
{
|
|
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
|
|
kmp->create_conf((kmp_api_t *)kmp, (kmp_result_e) result);
|
|
}
|
|
|
|
static void kmp_api_sec_prot_create_indication(sec_prot_t *prot)
|
|
{
|
|
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
|
|
kmp->create_ind((kmp_api_t *)kmp, kmp->type, kmp->addr);
|
|
}
|
|
|
|
static void kmp_api_sec_prot_finished_indication(sec_prot_t *prot, sec_prot_result_e result, sec_prot_keys_t *sec_keys)
|
|
{
|
|
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
|
|
kmp->finished_ind((kmp_api_t *)kmp, (kmp_result_e) result, sec_keys);
|
|
}
|
|
|
|
static void kmp_api_sec_prot_finished(sec_prot_t *prot)
|
|
{
|
|
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
|
|
kmp->finished((kmp_api_t *)kmp);
|
|
}
|
|
|
|
static int8_t kmp_sec_prot_send(sec_prot_t *prot, void *pdu, uint16_t size)
|
|
{
|
|
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
|
|
|
|
// Convert from internal initial key type to real type if needed
|
|
kmp_type_e kmp_id = kmp->type;
|
|
if (kmp_id > IEEE_802_1X_INITIAL_KEY) {
|
|
kmp_id -= IEEE_802_1X_INITIAL_KEY;
|
|
} else if (kmp_id == RADIUS_IEEE_802_1X_MKA) {
|
|
kmp_id = IEEE_802_1X_MKA;
|
|
}
|
|
|
|
kmp_msg_if_entry_t *msg_if_entry = kmp_api_msg_if_get(kmp->service, prot->msg_if_instance_id);
|
|
if (!msg_if_entry) {
|
|
return -1;
|
|
}
|
|
|
|
int8_t result = -1;
|
|
|
|
if (msg_if_entry->send) {
|
|
result = msg_if_entry->send(kmp->service, prot->msg_if_instance_id, kmp_id, kmp->addr, pdu, size, kmp->instance_identifier);
|
|
}
|
|
|
|
if (result < 0) {
|
|
ns_dyn_mem_free(pdu);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static void kmp_sec_prot_timer_start(sec_prot_t *prot)
|
|
{
|
|
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
|
|
kmp->timer_start_pending = false;
|
|
if (kmp->service->timer_start(kmp->service, kmp) < 0) {
|
|
kmp->timer_start_pending = true;
|
|
}
|
|
}
|
|
|
|
static void kmp_sec_prot_timer_stop(sec_prot_t *prot)
|
|
{
|
|
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
|
|
kmp->service->timer_stop(kmp->service, kmp);
|
|
kmp->timer_start_pending = false;
|
|
}
|
|
|
|
static void kmp_sec_prot_eui64_addr_get(sec_prot_t *prot, uint8_t *local_eui64, uint8_t *remote_eui64)
|
|
{
|
|
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
|
|
|
|
kmp_addr_t local_addr;
|
|
kmp_address_init(KMP_ADDR_EUI_64, &local_addr, NULL);
|
|
|
|
kmp_addr_t remote_addr;
|
|
kmp_address_init(KMP_ADDR_EUI_64, &remote_addr, NULL);
|
|
|
|
kmp->service->addr_get(kmp->service, kmp, &local_addr, &remote_addr);
|
|
|
|
if (local_eui64) {
|
|
memcpy(local_eui64, local_addr.eui_64, 8);
|
|
}
|
|
if (remote_eui64) {
|
|
memcpy(remote_eui64, remote_addr.eui_64, 8);
|
|
}
|
|
}
|
|
|
|
static void kmp_sec_prot_ip_addr_get(sec_prot_t *prot, uint8_t *address)
|
|
{
|
|
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
|
|
|
|
kmp->service->ip_addr_get(kmp->service, kmp, address);
|
|
}
|
|
|
|
static sec_prot_t *kmp_sec_prot_by_type_get(sec_prot_t *prot, uint8_t type)
|
|
{
|
|
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
|
|
|
|
kmp_type_e kmp_type;
|
|
|
|
switch (type) {
|
|
case SEC_PROT_TYPE_EAP_TLS:
|
|
kmp_type = IEEE_802_1X_MKA;
|
|
break;
|
|
case SEC_PROT_TYPE_RADIUS_EAP_TLS:
|
|
kmp_type = RADIUS_IEEE_802_1X_MKA;
|
|
break;
|
|
case SEC_PROT_TYPE_TLS:
|
|
kmp_type = TLS_PROT;
|
|
break;
|
|
case SEC_PROT_TYPE_RADIUS_CLIENT:
|
|
kmp_type = RADIUS_CLIENT_PROT;
|
|
break;
|
|
default:
|
|
return NULL;
|
|
}
|
|
|
|
kmp_api_t *kmp_by_type = kmp->service->api_get(kmp->service, kmp, kmp_type);
|
|
if (!kmp_by_type) {
|
|
return NULL;
|
|
}
|
|
|
|
return &kmp_by_type->sec_prot;
|
|
}
|
|
|
|
static void kmp_sec_prot_receive_disable(sec_prot_t *prot)
|
|
{
|
|
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
|
|
kmp->receive_disable = true;
|
|
}
|
|
|
|
void kmp_api_delete(kmp_api_t *kmp)
|
|
{
|
|
if (kmp->sec_prot.delete) {
|
|
kmp->sec_prot.delete(&kmp->sec_prot);
|
|
}
|
|
ns_dyn_mem_free(kmp);
|
|
}
|
|
|
|
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)
|
|
{
|
|
if (!kmp) {
|
|
return;
|
|
}
|
|
|
|
kmp->create_conf = create_conf;
|
|
kmp->create_ind = create_ind;
|
|
kmp->finished_ind = finished_ind;
|
|
kmp->finished = finished;
|
|
}
|
|
|
|
kmp_type_e kmp_api_type_get(kmp_api_t *kmp)
|
|
{
|
|
return kmp->type;
|
|
}
|
|
|
|
bool kmp_api_receive_disable(kmp_api_t *kmp)
|
|
{
|
|
return kmp->receive_disable;
|
|
}
|
|
|
|
bool kmp_api_receive_check(kmp_api_t *kmp, const void *pdu, uint16_t size)
|
|
{
|
|
if (kmp->sec_prot.receive_check) {
|
|
int8_t ret = kmp->sec_prot.receive_check(&kmp->sec_prot, pdu, size);
|
|
if (ret >= 0) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
kmp_type_e kmp_api_type_from_id_get(uint8_t kmp_id)
|
|
{
|
|
switch (kmp_id) {
|
|
case IEEE_802_1X_MKA:
|
|
return IEEE_802_1X_MKA;
|
|
case IEEE_802_11_4WH:
|
|
return IEEE_802_11_4WH;
|
|
case IEEE_802_11_GKH:
|
|
return IEEE_802_11_GKH;
|
|
default:
|
|
return KMP_TYPE_NONE;
|
|
}
|
|
}
|
|
|
|
kmp_service_t *kmp_api_service_get(kmp_api_t *kmp)
|
|
{
|
|
return kmp->service;
|
|
}
|
|
|
|
void kmp_api_data_set(kmp_api_t *kmp, void *data)
|
|
{
|
|
kmp->app_data_ptr = data;
|
|
}
|
|
|
|
void *kmp_api_data_get(kmp_api_t *kmp)
|
|
{
|
|
return kmp->app_data_ptr;
|
|
}
|
|
|
|
uint8_t kmp_api_instance_id_get(kmp_api_t *kmp)
|
|
{
|
|
return kmp->instance_identifier;
|
|
}
|
|
|
|
void kmp_api_addr_set(kmp_api_t *kmp, kmp_addr_t *addr)
|
|
{
|
|
kmp->addr = addr;
|
|
}
|
|
|
|
void kmp_api_sec_keys_set(kmp_api_t *kmp, kmp_sec_keys_t *sec_keys)
|
|
{
|
|
kmp->sec_prot.sec_keys = sec_keys;
|
|
}
|
|
|
|
kmp_service_t *kmp_service_create(void)
|
|
{
|
|
kmp_service_t *service = ns_dyn_mem_alloc(sizeof(kmp_service_t));
|
|
if (!service) {
|
|
return NULL;
|
|
}
|
|
|
|
ns_list_init(&service->sec_prot_list);
|
|
ns_list_init(&service->msg_if_list);
|
|
service->incoming_ind = 0;
|
|
service->tx_status_ind = 0;
|
|
service->addr_get = 0;
|
|
service->api_get = 0;
|
|
|
|
ns_list_add_to_start(&kmp_service_list, service);
|
|
|
|
return service;
|
|
}
|
|
|
|
int8_t kmp_service_delete(kmp_service_t *service)
|
|
{
|
|
if (!service) {
|
|
return -1;
|
|
}
|
|
|
|
ns_list_foreach_safe(kmp_service_t, list_entry, &kmp_service_list) {
|
|
if (list_entry == service) {
|
|
ns_list_foreach_safe(kmp_sec_prot_entry_t, sec_list_entry, &list_entry->sec_prot_list) {
|
|
ns_list_remove(&list_entry->sec_prot_list, sec_list_entry);
|
|
ns_dyn_mem_free(sec_list_entry);
|
|
}
|
|
ns_list_foreach_safe(kmp_msg_if_entry_t, msg_if_list_entry, &list_entry->msg_if_list) {
|
|
ns_list_remove(&list_entry->msg_if_list, msg_if_list_entry);
|
|
ns_dyn_mem_free(msg_if_list_entry);
|
|
}
|
|
ns_list_remove(&kmp_service_list, list_entry);
|
|
ns_dyn_mem_free(list_entry);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static void kmp_sec_prot_state_machine_call(sec_prot_t *prot)
|
|
{
|
|
kmp_api_t *kmp = kmp_api_get_from_prot(prot);
|
|
kmp->service->event_send(kmp->service, prot);
|
|
}
|
|
|
|
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_ip_addr_get *ip_addr_get, kmp_service_api_get *api_get)
|
|
{
|
|
if (!service) {
|
|
return -1;
|
|
}
|
|
|
|
service->incoming_ind = incoming_ind;
|
|
service->tx_status_ind = tx_status_ind;
|
|
service->addr_get = addr_get;
|
|
service->ip_addr_get = ip_addr_get;
|
|
service->api_get = api_get;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int8_t kmp_service_msg_if_register(kmp_service_t *service, uint8_t instance_id, kmp_service_msg_if_send *send, uint8_t header_size)
|
|
{
|
|
if (!service) {
|
|
return -1;
|
|
}
|
|
|
|
kmp_msg_if_entry_t *entry = NULL;
|
|
|
|
ns_list_foreach(kmp_msg_if_entry_t, list_entry, &service->msg_if_list) {
|
|
// Message interface already registered
|
|
if (list_entry->instance_id == instance_id) {
|
|
entry = list_entry;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If removing message interface
|
|
if (send == NULL) {
|
|
if (entry != NULL) {
|
|
ns_list_remove(&service->msg_if_list, entry);
|
|
ns_dyn_mem_free(entry);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Allocate new entry if does not exists
|
|
if (entry == NULL) {
|
|
entry = ns_dyn_mem_temporary_alloc(sizeof(kmp_msg_if_entry_t));
|
|
if (entry == NULL) {
|
|
return -1;
|
|
}
|
|
ns_list_add_to_start(&service->msg_if_list, entry);
|
|
}
|
|
|
|
entry->instance_id = instance_id;
|
|
entry->send = send;
|
|
entry->header_size = header_size;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int8_t kmp_service_msg_if_receive(kmp_service_t *service, uint8_t instance_id, kmp_type_e type, const kmp_addr_t *addr, void *pdu, uint16_t size)
|
|
{
|
|
if (!service) {
|
|
return -1;
|
|
}
|
|
|
|
kmp_api_t *kmp = (kmp_api_t *) service->incoming_ind(service, instance_id, type, addr, pdu, size);
|
|
if (!kmp) {
|
|
return -1;
|
|
}
|
|
|
|
// Security protocol has disables message receiving
|
|
if (kmp->receive_disable) {
|
|
return -1;
|
|
}
|
|
|
|
int8_t ret = kmp->sec_prot.receive(&kmp->sec_prot, pdu, size);
|
|
return ret;
|
|
}
|
|
|
|
int8_t kmp_service_tx_status_indication(kmp_service_t *service, kmp_tx_status_e tx_status, uint8_t tx_identifier)
|
|
{
|
|
if (!service || !service->tx_status_ind) {
|
|
return -1;
|
|
}
|
|
|
|
// Application can use the tx_identifier to match the TX status indication to kmp
|
|
kmp_api_t *kmp = (kmp_api_t *) service->tx_status_ind(service, tx_identifier);
|
|
if (!kmp) {
|
|
return -1;
|
|
}
|
|
|
|
// Security protocol has disabled message receiving or tx status indication is not set
|
|
if (kmp->receive_disable || !kmp->sec_prot.tx_status_ind) {
|
|
return -1;
|
|
}
|
|
|
|
sec_prot_tx_status_e sec_prot_tx_status;
|
|
if (tx_status == KMP_TX_OK) {
|
|
sec_prot_tx_status = SEC_PROT_TX_OK;
|
|
} else if (tx_status == KMP_TX_ERR_TX_NO_ACK) {
|
|
sec_prot_tx_status = SEC_PROT_TX_ERR_TX_NO_ACK;
|
|
} else {
|
|
sec_prot_tx_status = SEC_PROT_TX_ERR_UNSPEC;
|
|
}
|
|
|
|
int8_t ret = kmp->sec_prot.tx_status_ind(&kmp->sec_prot, sec_prot_tx_status);
|
|
return ret;
|
|
}
|
|
|
|
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)
|
|
{
|
|
if (!service) {
|
|
return -1;
|
|
}
|
|
|
|
ns_list_foreach(kmp_sec_prot_entry_t, list_entry, &service->sec_prot_list) {
|
|
// Already registered
|
|
if (list_entry->type == type) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
kmp_sec_prot_entry_t *sec_prot = ns_dyn_mem_temporary_alloc(sizeof(kmp_sec_prot_entry_t));
|
|
if (!sec_prot) {
|
|
return -1;
|
|
}
|
|
|
|
sec_prot->type = type;
|
|
sec_prot->size = size;
|
|
sec_prot->init = init;
|
|
|
|
ns_list_add_to_start(&service->sec_prot_list, sec_prot);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int8_t kmp_service_sec_protocol_unregister(kmp_service_t *service, kmp_type_e type)
|
|
{
|
|
ns_list_foreach(kmp_sec_prot_entry_t, list_entry, &service->sec_prot_list) {
|
|
if (list_entry->type == type) {
|
|
ns_list_remove(&service->sec_prot_list, list_entry);
|
|
ns_dyn_mem_free(list_entry);
|
|
return 0;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void kmp_service_timer_if_timeout(kmp_api_t *kmp, uint16_t ticks)
|
|
{
|
|
kmp->sec_prot.timer_timeout(&kmp->sec_prot, ticks);
|
|
}
|
|
|
|
int8_t kmp_service_timer_if_register(kmp_service_t *service, kmp_service_timer_if_start start, kmp_service_timer_if_stop stop)
|
|
{
|
|
if (!service) {
|
|
return -1;
|
|
}
|
|
|
|
service->timer_start = start;
|
|
service->timer_stop = stop;
|
|
return 0;
|
|
}
|
|
|
|
void kmp_service_event_if_event(kmp_service_t *service, void *data)
|
|
{
|
|
(void) service;
|
|
|
|
// For now, only state machine events
|
|
sec_prot_t *prot = data;
|
|
prot->state_machine(prot);
|
|
}
|
|
|
|
int8_t kmp_service_event_if_register(kmp_service_t *service, kmp_service_event_if_event_send send)
|
|
{
|
|
if (!service) {
|
|
return -1;
|
|
}
|
|
|
|
service->event_send = send;
|
|
return 0;
|
|
}
|
|
|
|
#endif /* HAVE_WS */
|
|
|