mbed-mesh-api: Add new Wi-SUN certificate API

Add new API for setting Wi-SUN:
-Setting own/trusted certificates
-Removing own/trusted certificates
pull/11181/head
Arto Kinnunen 2019-08-08 16:40:46 +03:00
parent c0f3cb7568
commit 774162dd83
4 changed files with 340 additions and 13 deletions

View File

@ -50,7 +50,7 @@ public:
* \return MESH_ERROR_NONE on success.
* \return MESH_ERROR_UNKNOWN in case of failure.
* */
mesh_error_t network_name_set(char *network_name);
mesh_error_t set_network_name(char *network_name);
/**
* \brief Set Wi-SUN network regulatory domain, operating class and operating mode.
@ -61,13 +61,68 @@ public:
*
* Function overwrites parameters defined by Mbed OS configuration.
*
* \param regulatory_domain Values defined in Wi-SUN PHY-specification
* \param operating_class Values defined in Wi-SUN PHY-specification
* \param operating_mode Values defined in Wi-SUN PHY-specification
* \param regulatory_domain Values defined in Wi-SUN PHY-specification. Use 0xff to use leave parameter unchanged.
* \param operating_class Values defined in Wi-SUN PHY-specification. Use 0xff to use leave parameter unchanged.
* \param operating_mode Values defined in Wi-SUN PHY-specification. Use 0xff to use leave parameter unchanged.
* \return MESH_ERROR_NONE on success.
* \return MESH_ERROR_UNKNOWN in case of failure.
* */
mesh_error_t network_regulatory_domain_set(uint8_t regulatory_domain = 0xff, uint8_t operating_class = 0xff, uint8_t operating_mode = 0xff);
mesh_error_t set_network_regulatory_domain(uint8_t regulatory_domain = 0xff, uint8_t operating_class = 0xff, uint8_t operating_mode = 0xff);
/**
* \brief Set own certificate and private key reference to the Wi-SUN network.
*
* Function can be called several times if intermediate certificates are used. Then each call to the function
* adds a certificate reference to own certificate chain. Certificates are in bottom up order i.e. the top certificate is given last.
*
* Function must be called before connecting the device i.e before first call to connect() method.
* Function will not copy certificate or key, therefore addresses must remain valid.
*
* \param cert Certificate address.
* \param cert_len Certificate length in bytes.
* \param cert_key Certificate key address.
* \param cert_key_len Certificate key length in bytes.
* \return MESH_ERROR_NONE on success.
* \return MESH_ERROR_STATE if method is called after calling connect().
* \return MESH_ERROR_MEMORY in case of memory allocation failure.
* */
mesh_error_t set_own_certificate(uint8_t *cert, uint16_t cert_len, uint8_t *cert_key = NULL, uint16_t cert_key_len = 0);
/**
* \brief Remove own certificates from the Wi-SUN network.
*
* Function must be called before connecting the device i.e before first call to connect() method.
*
* \return MESH_ERROR_NONE on success.
* \return MESH_ERROR_STATE if method is called after calling connect().
* */
mesh_error_t remove_own_certificates(void);
/**
* \brief Set trusted certificate reference to the Wi-SUN network.
*
* Function can be called several times. Certificates are in bottom up order i.e. the top certificate is given last.
*
* Function must be called before connecting the device i.e before first call to connect() method.
* Function will not copy certificate, therefore addresses must remain valid.
*
* \param cert Certificate address.
* \param cert_len Certificate length in bytes.
* \return MESH_ERROR_NONE on success.
* \return MESH_ERROR_STATE if method is called after calling connect().
* \return MESH_ERROR_MEMORY in case of memory allocation failure.
* */
mesh_error_t set_trusted_certificate(uint8_t *cert, uint16_t cert_len);
/**
* \brief Remove trusted certificates from the Wi-SUN network.
*
* Function must be called before connecting the device i.e before first call to connect() method.
*
* \return MESH_ERROR_NONE on success.
* \return MESH_ERROR_STATE if method is called after calling connect().
* */
mesh_error_t remove_trusted_certificates(void);
/**
* \brief Get router IP address

View File

@ -171,11 +171,11 @@ bool WisunInterface::getRouterIpAddress(char *address, int8_t len)
return _interface->get_gateway(address, len);
}
mesh_error_t WisunInterface::network_name_set(char *network_name)
mesh_error_t WisunInterface::set_network_name(char *network_name)
{
mesh_error_t ret_val = MESH_ERROR_NONE;
int status = wisun_tasklet_network_name_set(get_interface_id(), network_name);
int status = wisun_tasklet_set_network_name(get_interface_id(), network_name);
if (status != 0) {
ret_val = MESH_ERROR_UNKNOWN;
}
@ -183,11 +183,11 @@ mesh_error_t WisunInterface::network_name_set(char *network_name)
return ret_val;
}
mesh_error_t WisunInterface::network_regulatory_domain_set(uint8_t regulatory_domain, uint8_t operating_class, uint8_t operating_mode)
mesh_error_t WisunInterface::set_network_regulatory_domain(uint8_t regulatory_domain, uint8_t operating_class, uint8_t operating_mode)
{
mesh_error_t ret_val = MESH_ERROR_NONE;
int status = wisun_tasklet_regulatory_domain_set(get_interface_id(), regulatory_domain, operating_class, operating_mode);
int status = wisun_tasklet_set_regulatory_domain(get_interface_id(), regulatory_domain, operating_class, operating_mode);
if (status != 0) {
ret_val = MESH_ERROR_UNKNOWN;
}
@ -195,6 +195,58 @@ mesh_error_t WisunInterface::network_regulatory_domain_set(uint8_t regulatory_do
return ret_val;
}
mesh_error_t WisunInterface::set_own_certificate(uint8_t *cert, uint16_t cert_len, uint8_t *cert_key, uint16_t cert_key_len)
{
mesh_error_t ret_val = MESH_ERROR_NONE;
int status = wisun_tasklet_set_own_certificate(cert, cert_len, cert_key, cert_key_len);
if (status == -1) {
ret_val = MESH_ERROR_MEMORY;
} else if (status == -2) {
ret_val = MESH_ERROR_STATE;
}
return ret_val;
}
mesh_error_t WisunInterface::remove_own_certificates(void)
{
mesh_error_t ret_val = MESH_ERROR_NONE;
int status = wisun_tasklet_remove_own_certificates();
if (status == -1) {
ret_val = MESH_ERROR_MEMORY;
} else if (status == -2) {
ret_val = MESH_ERROR_STATE;
}
return ret_val;
}
mesh_error_t WisunInterface::set_trusted_certificate(uint8_t *cert, uint16_t cert_len)
{
mesh_error_t ret_val = MESH_ERROR_NONE;
int status = wisun_tasklet_set_trusted_certificate(cert, cert_len);
if (status == -1) {
ret_val = MESH_ERROR_MEMORY;
} else if (status == -2) {
ret_val = MESH_ERROR_STATE;
}
return ret_val;
}
mesh_error_t WisunInterface::remove_trusted_certificates(void)
{
mesh_error_t ret_val = MESH_ERROR_NONE;
int status = wisun_tasklet_remove_trusted_certificates();
if (status == -1) {
ret_val = MESH_ERROR_MEMORY;
} else if (status == -2) {
ret_val = MESH_ERROR_STATE;
}
return ret_val;
}
#define WISUN 0x2345
#if MBED_CONF_NSAPI_DEFAULT_MESH_TYPE == WISUN && DEVICE_802_15_4_PHY
MBED_WEAK MeshInterface *MeshInterface::get_target_default_instance()

View File

@ -64,6 +64,9 @@ void wisun_tasklet_init(void);
*
* \param device_id registered physical device
* \return interface ID that can be used to communication with this interface
* \return -1 in case of MAC initialization fails
* \return -2 in case of error in parameters
* \return -3 in case of memory allocation error
*/
int8_t wisun_tasklet_network_init(int8_t device_id);
@ -84,7 +87,7 @@ int8_t wisun_tasklet_disconnect(bool send_cb);
* \return 0 if network name stored successfully
* \return < 0 in case of errors
*/
int wisun_tasklet_network_name_set(int8_t nwk_interface_id, char *network_name_ptr);
int wisun_tasklet_set_network_name(int8_t nwk_interface_id, char *network_name_ptr);
/*
* \brief Set Wi-SUN network regulatory domain
@ -96,7 +99,45 @@ int wisun_tasklet_network_name_set(int8_t nwk_interface_id, char *network_name_p
* \return 0 if regulatory domain is set successfully.
* \return < 0 in case of errors
*/
int wisun_tasklet_regulatory_domain_set(int8_t nwk_interface_id, uint8_t regulatory_domain, uint8_t operating_class, uint8_t operating_mode);
int wisun_tasklet_set_regulatory_domain(int8_t nwk_interface_id, uint8_t regulatory_domain, uint8_t operating_class, uint8_t operating_mode);
/*
* \brief Set own certificate to Wi-SUN network
*
* \param cert to use for networking
* \param cert_len
* \param cert_key
* \param cert_key_len
* \return 0 if certificate stored successfully
* \return < 0 in case of errors
*/
int wisun_tasklet_set_own_certificate(uint8_t *cert, uint16_t cert_len, uint8_t *cert_key, uint16_t cert_key_len);
/*
* \brief Remove own certificate from Wi-SUN network
*
* \return 0 if certificates removed successfully
* \return < 0 in case of errors
*/
int wisun_tasklet_remove_own_certificates(void);
/*
* \brief Set trusted certificate to Wi-SUN network
*
* \param cert to use for networking
* \param cert_len
* \return 0 if certificate stored successfully
* \return < 0 in case of errors
*/
int wisun_tasklet_set_trusted_certificate(uint8_t *cert, uint16_t cert_len);
/*
* \brief Remove trusted certificate from Wi-SUN network
*
* \return 0 if certificates removed successfully
* \return < 0 in case of errors
*/
int wisun_tasklet_remove_trusted_certificates(void);
#ifdef __cplusplus
}

View File

@ -27,6 +27,8 @@
#include "multicast_api.h"
#include "mac_api.h"
#include "sw_mac.h"
#include "ns_list.h"
#include "net_interface.h"
#include "ws_management_api.h" //ws_management_node_init
#ifdef MBED_CONF_MBED_MESH_API_CERTIFICATE_HEADER
#if !defined(MBED_CONF_MBED_MESH_API_ROOT_CERTIFICATE) || !defined(MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE) || \
@ -75,10 +77,24 @@ typedef struct {
uint8_t rd_operating_mode;
} wisun_network_settings_t;
typedef struct {
arm_certificate_entry_s arm_cert_entry;
ns_list_link_t link; /*!< List link entry */
} wisun_certificate_entry_t;
typedef NS_LIST_HEAD(wisun_certificate_entry_t, link) cert_list_t;
typedef struct {
cert_list_t own_certificates_list;
cert_list_t trusted_certificates_list;
bool remove_own_certificates: 1;
bool remove_trusted_certificates: 1;
} wisun_certificates_t;
#define WS_NA 0xff // Not applicable value
/* Tasklet data */
static wisun_tasklet_data_str_t *wisun_tasklet_data_ptr = NULL;
static wisun_certificates_t *wisun_certificates_ptr = NULL;
static wisun_network_settings_t wisun_settings_str = {NULL, WS_NA, WS_NA, WS_NA};
static mac_api_t *mac_api = NULL;
@ -89,6 +105,9 @@ static void wisun_tasklet_main(arm_event_s *event);
static void wisun_tasklet_network_state_changed(mesh_connection_status_t status);
static void wisun_tasklet_parse_network_event(arm_event_s *event);
static void wisun_tasklet_configure_and_connect_to_network(void);
static void wisun_tasklet_clear_stored_certificates(void) ;
static int wisun_tasklet_store_certificate_data(const uint8_t *cert, uint16_t cert_len, const uint8_t *cert_key, uint16_t cert_key_len, bool remove_own, bool remove_trusted, bool trusted_cert);
static int wisun_tasklet_add_stored_certificates(void) ;
/*
* \brief A function which will be eventually called by NanoStack OS when ever the OS has an event to deliver.
@ -221,6 +240,11 @@ static void wisun_tasklet_configure_and_connect_to_network(void)
wisun_tasklet_data_ptr->operating_mode,
wisun_tasklet_data_ptr->operating_mode_extension);
if (wisun_tasklet_add_stored_certificates() != 0) {
tr_error("Can't set Wi-SUN certificates");
return;
}
status = ws_management_node_init(wisun_tasklet_data_ptr->network_interface_id,
MBED_CONF_MBED_MESH_API_WISUN_REGULATORY_DOMAIN,
wisun_settings_str.network_name,
@ -278,6 +302,118 @@ static void wisun_tasklet_network_state_changed(mesh_connection_status_t status)
}
}
static int wisun_tasklet_store_certificate_data(const uint8_t *cert, uint16_t cert_len, const uint8_t *cert_key, uint16_t cert_key_len, bool remove_own, bool remove_trusted, bool trusted_cert)
{
if (wisun_certificates_ptr == NULL) {
wisun_certificates_ptr = (wisun_certificates_t *)ns_dyn_mem_alloc(sizeof(wisun_certificates_t));
if (!wisun_certificates_ptr) {
return -1;
}
ns_list_init(&wisun_certificates_ptr->own_certificates_list);
ns_list_init(&wisun_certificates_ptr->trusted_certificates_list);
wisun_certificates_ptr->remove_own_certificates = false;
wisun_certificates_ptr->remove_trusted_certificates = false;
}
if (remove_own) {
wisun_certificates_ptr->remove_own_certificates = true;
return 0;
}
if (remove_trusted) {
wisun_certificates_ptr->remove_trusted_certificates = true;
return 0;
}
wisun_certificate_entry_t *ws_cert_entry_store = (wisun_certificate_entry_t *)ns_dyn_mem_alloc(sizeof(wisun_certificate_entry_t));
if (!ws_cert_entry_store) {
wisun_tasklet_clear_stored_certificates();
return -1;
}
ws_cert_entry_store->arm_cert_entry.cert = cert;
ws_cert_entry_store->arm_cert_entry.cert_len = cert_len;
if (cert_key) {
ws_cert_entry_store->arm_cert_entry.key = cert_key;
ws_cert_entry_store->arm_cert_entry.key_len = cert_key_len;
} else {
ws_cert_entry_store->arm_cert_entry.key = NULL;
ws_cert_entry_store->arm_cert_entry.key_len = 0;
}
if (trusted_cert) {
ns_list_add_to_end(&wisun_certificates_ptr->trusted_certificates_list, ws_cert_entry_store);
} else {
ns_list_add_to_end(&wisun_certificates_ptr->own_certificates_list, ws_cert_entry_store);
}
return 0;
}
static void wisun_tasklet_clear_stored_certificates(void)
{
if (!wisun_certificates_ptr) {
return;
}
ns_list_foreach_safe(wisun_certificate_entry_t, trusted_cert_entry, &wisun_certificates_ptr->trusted_certificates_list) {
ns_list_remove(&wisun_certificates_ptr->trusted_certificates_list, trusted_cert_entry);
ns_dyn_mem_free(trusted_cert_entry);
}
ns_list_foreach_safe(wisun_certificate_entry_t, own_cert_entry, &wisun_certificates_ptr->own_certificates_list) {
ns_list_remove(&wisun_certificates_ptr->own_certificates_list, own_cert_entry);
ns_dyn_mem_free(own_cert_entry);
}
ns_dyn_mem_free(wisun_certificates_ptr);
wisun_certificates_ptr = NULL;
}
static int wisun_tasklet_add_stored_certificates(void)
{
int8_t status = 0;
if (wisun_certificates_ptr == NULL) {
// certificates not updated
return 0;
}
if (wisun_certificates_ptr->remove_own_certificates) {
status = arm_network_own_certificates_remove();
if (status != 0) {
goto CERTIFICATE_SET_END;
}
}
if (wisun_certificates_ptr->remove_trusted_certificates) {
status = arm_network_trusted_certificates_remove();
if (status != 0) {
goto CERTIFICATE_SET_END;
}
}
ns_list_foreach(wisun_certificate_entry_t, cert_entry, &wisun_certificates_ptr->trusted_certificates_list) {
status = arm_network_trusted_certificate_add(&cert_entry->arm_cert_entry);
if (status != 0) {
goto CERTIFICATE_SET_END;
}
}
ns_list_foreach(wisun_certificate_entry_t, cert_entry, &wisun_certificates_ptr->own_certificates_list) {
status = arm_network_own_certificate_add(&cert_entry->arm_cert_entry);
if (status != 0) {
goto CERTIFICATE_SET_END;
}
}
CERTIFICATE_SET_END:
wisun_tasklet_clear_stored_certificates();
return status;
}
/* Public functions */
int8_t wisun_tasklet_get_router_ip_address(char *address, int8_t len)
{
@ -378,7 +514,7 @@ int8_t wisun_tasklet_network_init(int8_t device_id)
return arm_nwk_interface_lowpan_init(mac_api, INTERFACE_NAME);
}
int wisun_tasklet_network_name_set(int8_t nwk_interface_id, char *network_name_ptr)
int wisun_tasklet_set_network_name(int8_t nwk_interface_id, char *network_name_ptr)
{
if (!network_name_ptr || strlen(network_name_ptr) > 32) {
return -1;
@ -401,7 +537,7 @@ int wisun_tasklet_network_name_set(int8_t nwk_interface_id, char *network_name_p
return 0;
}
int wisun_tasklet_regulatory_domain_set(int8_t nwk_interface_id, uint8_t regulatory_domain, uint8_t operating_class, uint8_t operating_mode)
int wisun_tasklet_set_regulatory_domain(int8_t nwk_interface_id, uint8_t regulatory_domain, uint8_t operating_class, uint8_t operating_mode)
{
int status = 0;
@ -415,3 +551,46 @@ int wisun_tasklet_regulatory_domain_set(int8_t nwk_interface_id, uint8_t regulat
return status;
}
int wisun_tasklet_set_own_certificate(uint8_t *cert, uint16_t cert_len, uint8_t *cert_key, uint16_t cert_key_len)
{
if (wisun_tasklet_data_ptr) {
// this API can be only used before first connect()
tr_err("Already connected");
return -2;
}
return wisun_tasklet_store_certificate_data(cert, cert_len, cert_key, cert_key_len, false, false, false);
}
int wisun_tasklet_remove_own_certificates(void)
{
if (wisun_tasklet_data_ptr) {
// this API can be only used before first connect()
tr_err("Already connected");
return -2;
}
return wisun_tasklet_store_certificate_data(NULL, 0, NULL, 0, true, false, false);
}
int wisun_tasklet_remove_trusted_certificates(void)
{
if (wisun_tasklet_data_ptr) {
// this API can be only used before first connect()
tr_err("Already connected");
return -2;
}
return wisun_tasklet_store_certificate_data(NULL, 0, NULL, 0, false, true, false);
}
int wisun_tasklet_set_trusted_certificate(uint8_t *cert, uint16_t cert_len)
{
if (wisun_tasklet_data_ptr) {
// this API can be only used before first connect()
tr_err("Already connected");
return -2;
}
return wisun_tasklet_store_certificate_data(cert, cert_len, NULL, 0, false, false, true);
}