Merge pull request #14046 from mikaleppanen/mbedos_5_15_corr_cert_add

[mbed-os-5.15] Corrected Wi-SUN certificate add and remove functions on Wi-SUN interface
pull/14147/head
Martin Kojtal 2021-01-25 08:49:55 +00:00 committed by GitHub
commit 46a045b7e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 110 additions and 66 deletions

View File

@ -424,7 +424,16 @@ public:
* \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.
* adds a certificate reference to own certificate chain. Certificates are in bottom up order i.e. own certificate
* is given first and the top certificate is given last.
*
* PEM formatted certificates must use either "\n" or "\r\n" as line separator. PEM formatted certificates
* must be NUL terminated and the NUL terminator is counted to certificate length.
*
* It is possible to add multiple PEM certificates concatenated together in one call set_own_certificate(). In that
* case certificates are in bottom up order i.e. own certificate is given first and the top certificate is given
* last. NUL terminator is added after the last concatenated certificate and the NUL terminator is counted to
* total concatenated certificate length.
*
* Function must be called before connecting the device i.e before call to connect() method.
* Function will not copy certificate or key, therefore addresses must remain valid.
@ -452,7 +461,14 @@ public:
/**
* \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 can be called several times. Each call to the function adds a trusted certificate to Wi-SUN.
*
* PEM formatted certificates must use either "\n" or "\r\n" as line separator. PEM formatted certificates
* must be NUL terminated and the NUL terminator is counted to certificate length.
*
* It is possible to add multiple PEM certificates concatenated together in one call set_trusted_certificate().
* NUL terminator is added after the last concatenated certificate and the NUL terminator is counted to
* total concatenated certificate length.
*
* Function must be called before connecting the device i.e before call to connect() method.
* Function will not copy certificate, therefore addresses must remain valid.

View File

@ -70,6 +70,7 @@ typedef struct {
net_6lowpan_mode_e operating_mode;
net_6lowpan_mode_extension_e operating_mode_extension;
int8_t network_interface_id;
bool configured_and_connected;
} wisun_tasklet_data_str_t;
typedef struct {
@ -81,8 +82,6 @@ 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;
/* Tasklet data */
@ -106,9 +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) ;
static void wisun_tasklet_clear_stored_certificates(int8_t clear_trusted, int8_t clear_own);
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 trusted_cert);
static int wisun_tasklet_add_stored_certificates(int8_t *trusted_set, int8_t *own_set);
static void wisun_tasklet_statistics_do_start(void);
/*
@ -230,6 +229,11 @@ static void wisun_tasklet_parse_network_event(arm_event_s *event)
static void wisun_tasklet_configure_and_connect_to_network(void)
{
int status;
if (wisun_tasklet_data_ptr->configured_and_connected) {
return;
}
fhss_timer_t *fhss_timer_ptr = &fhss_functions;
if (MBED_CONF_MBED_MESH_API_WISUN_DEVICE_TYPE == MESH_DEVICE_TYPE_WISUN_BORDER_ROUTER) {
@ -245,7 +249,9 @@ 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) {
int8_t trusted_set = false;
int8_t own_set = false;
if (wisun_tasklet_add_stored_certificates(&trusted_set, &own_set) != 0) {
tr_error("Can't set Wi-SUN certificates");
return;
}
@ -277,38 +283,41 @@ static void wisun_tasklet_configure_and_connect_to_network(void)
}
#if defined(MBED_CONF_MBED_MESH_API_CERTIFICATE_HEADER)
arm_certificate_entry_s trusted_cert = {
.cert = MBED_CONF_MBED_MESH_API_ROOT_CERTIFICATE,
.key = NULL,
.cert_len = 0,
.key_len = 0
};
if (!trusted_set) {
arm_certificate_entry_s trusted_cert = {
.cert = MBED_CONF_MBED_MESH_API_ROOT_CERTIFICATE,
.key = NULL,
.cert_len = 0,
.key_len = 0
};
#ifdef MBED_CONF_MBED_MESH_API_ROOT_CERTIFICATE_LEN
trusted_cert.cert_len = MBED_CONF_MBED_MESH_API_ROOT_CERTIFICATE_LEN;
trusted_cert.cert_len = MBED_CONF_MBED_MESH_API_ROOT_CERTIFICATE_LEN;
#else
trusted_cert.cert_len = strlen((const char *) MBED_CONF_MBED_MESH_API_ROOT_CERTIFICATE) + 1;
trusted_cert.cert_len = strlen((const char *) MBED_CONF_MBED_MESH_API_ROOT_CERTIFICATE) + 1;
#endif
arm_network_trusted_certificates_remove();
arm_network_trusted_certificate_add((const arm_certificate_entry_s *)&trusted_cert);
arm_certificate_entry_s own_cert = {
.cert = MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE,
.key = MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE_KEY,
.cert_len = 0,
.key_len = 0
};
arm_network_trusted_certificates_remove();
arm_network_trusted_certificate_add((const arm_certificate_entry_s *)&trusted_cert);
}
if (!own_set) {
arm_certificate_entry_s own_cert = {
.cert = MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE,
.key = MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE_KEY,
.cert_len = 0,
.key_len = 0
};
#ifdef MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE_LEN
own_cert.cert_len = MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE_LEN;
own_cert.cert_len = MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE_LEN;
#else
own_cert.cert_len = strlen((const char *) MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE) + 1;
own_cert.cert_len = strlen((const char *) MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE) + 1;
#endif
#ifdef MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE_KEY_LEN
own_cert.key_len = MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE_KEY_LEN;
own_cert.key_len = MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE_KEY_LEN;
#else
own_cert.key_len = strlen((const char *) MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE_KEY) + 1;
own_cert.key_len = strlen((const char *) MBED_CONF_MBED_MESH_API_OWN_CERTIFICATE_KEY) + 1;
#endif
arm_network_own_certificates_remove();
arm_network_own_certificate_add((const arm_certificate_entry_s *)&own_cert);
arm_network_own_certificates_remove();
arm_network_own_certificate_add((const arm_certificate_entry_s *)&own_cert);
}
#endif
if (statistics_started) {
@ -317,6 +326,7 @@ static void wisun_tasklet_configure_and_connect_to_network(void)
status = arm_nwk_interface_up(wisun_tasklet_data_ptr->network_interface_id);
if (status >= 0) {
wisun_tasklet_data_ptr->configured_and_connected = true;
wisun_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_STARTED;
tr_info("Start Wi-SUN Bootstrap");
wisun_tasklet_network_state_changed(MESH_BOOTSTRAP_STARTED);
@ -325,6 +335,7 @@ static void wisun_tasklet_configure_and_connect_to_network(void)
tr_err("Bootstrap start failed, %d", status);
wisun_tasklet_network_state_changed(MESH_BOOTSTRAP_START_FAILED);
}
}
/*
@ -337,7 +348,7 @@ 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)
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 trusted_cert)
{
if (wisun_certificates_ptr == NULL) {
wisun_certificates_ptr = (wisun_certificates_t *)ns_dyn_mem_alloc(sizeof(wisun_certificates_t));
@ -346,23 +357,11 @@ static int wisun_tasklet_store_certificate_data(const uint8_t *cert, uint16_t ce
}
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();
wisun_tasklet_clear_stored_certificates(true, true);
return -1;
}
@ -386,27 +385,33 @@ static int wisun_tasklet_store_certificate_data(const uint8_t *cert, uint16_t ce
return 0;
}
static void wisun_tasklet_clear_stored_certificates(void)
static void wisun_tasklet_clear_stored_certificates(int8_t clear_trusted, int8_t clear_own)
{
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);
if (clear_trusted) {
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);
if (clear_own) {
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;
if (ns_list_is_empty(&wisun_certificates_ptr->trusted_certificates_list) && ns_list_is_empty(&wisun_certificates_ptr->own_certificates_list)) {
ns_dyn_mem_free(wisun_certificates_ptr);
wisun_certificates_ptr = NULL;
}
}
static int wisun_tasklet_add_stored_certificates(void)
static int wisun_tasklet_add_stored_certificates(int8_t *trusted_set, int8_t *own_set)
{
int8_t status = 0;
@ -415,15 +420,15 @@ static int wisun_tasklet_add_stored_certificates(void)
return 0;
}
if (wisun_certificates_ptr->remove_own_certificates) {
status = arm_network_own_certificates_remove();
if (!ns_list_is_empty(&wisun_certificates_ptr->trusted_certificates_list)) {
status = arm_network_trusted_certificates_remove();
if (status != 0) {
goto CERTIFICATE_SET_END;
}
}
if (wisun_certificates_ptr->remove_trusted_certificates) {
status = arm_network_trusted_certificates_remove();
if (!ns_list_is_empty(&wisun_certificates_ptr->own_certificates_list)) {
status = arm_network_own_certificates_remove();
if (status != 0) {
goto CERTIFICATE_SET_END;
}
@ -434,6 +439,7 @@ static int wisun_tasklet_add_stored_certificates(void)
if (status != 0) {
goto CERTIFICATE_SET_END;
}
*trusted_set = true;
}
ns_list_foreach(wisun_certificate_entry_t, cert_entry, &wisun_certificates_ptr->own_certificates_list) {
@ -441,10 +447,11 @@ static int wisun_tasklet_add_stored_certificates(void)
if (status != 0) {
goto CERTIFICATE_SET_END;
}
*own_set = true;
}
CERTIFICATE_SET_END:
wisun_tasklet_clear_stored_certificates();
wisun_tasklet_clear_stored_certificates(true, true);
return status;
}
@ -480,6 +487,7 @@ int8_t wisun_tasklet_connect(mesh_interface_cb callback, int8_t nwk_interface_id
wisun_tasklet_data_ptr->mesh_api_cb = callback;
wisun_tasklet_data_ptr->network_interface_id = nwk_interface_id;
wisun_tasklet_data_ptr->tasklet_state = TASKLET_STATE_INITIALIZED;
wisun_tasklet_data_ptr->configured_and_connected = false;
if (re_connecting == false) {
wisun_tasklet_data_ptr->tasklet = eventOS_event_handler_create(&wisun_tasklet_main,
@ -508,6 +516,7 @@ int8_t wisun_tasklet_disconnect(bool send_cb)
wisun_tasklet_network_state_changed(MESH_DISCONNECTED);
}
}
wisun_tasklet_data_ptr->configured_and_connected = false;
wisun_tasklet_data_ptr->mesh_api_cb = NULL;
}
return status;
@ -521,6 +530,7 @@ void wisun_tasklet_init(void)
memset(wisun_tasklet_data_ptr, 0, sizeof(wisun_tasklet_data_str_t));
wisun_tasklet_data_ptr->tasklet_state = TASKLET_STATE_CREATED;
wisun_tasklet_data_ptr->network_interface_id = INVALID_INTERFACE_ID;
wisun_tasklet_data_ptr->configured_and_connected = false;
}
}
@ -541,7 +551,7 @@ int8_t wisun_tasklet_network_init(int8_t device_id)
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 && wisun_tasklet_data_ptr->network_interface_id != INVALID_INTERFACE_ID) {
if (wisun_tasklet_data_ptr && wisun_tasklet_data_ptr->network_interface_id != INVALID_INTERFACE_ID && wisun_tasklet_data_ptr->configured_and_connected) {
// interface already active write certificates to stack.
arm_certificate_entry_s arm_cert_entry;
arm_cert_entry.cert = cert;
@ -551,22 +561,40 @@ int wisun_tasklet_set_own_certificate(uint8_t *cert, uint16_t cert_len, uint8_t
return arm_network_own_certificate_add(&arm_cert_entry);
}
// Stack is inactive store the certificates and activate when connect() called
return wisun_tasklet_store_certificate_data(cert, cert_len, cert_key, cert_key_len, false, false, false);
return wisun_tasklet_store_certificate_data(cert, cert_len, cert_key, cert_key_len, false);
}
int wisun_tasklet_remove_own_certificates(void)
{
return wisun_tasklet_store_certificate_data(NULL, 0, NULL, 0, true, false, false);
if (wisun_tasklet_data_ptr && wisun_tasklet_data_ptr->network_interface_id != INVALID_INTERFACE_ID && wisun_tasklet_data_ptr->configured_and_connected) {
int8_t status = arm_network_own_certificates_remove();
if (status != 0) {
return -1;
}
return 0;
}
wisun_tasklet_clear_stored_certificates(false, true);
return 0;
}
int wisun_tasklet_remove_trusted_certificates(void)
{
return wisun_tasklet_store_certificate_data(NULL, 0, NULL, 0, false, true, false);
if (wisun_tasklet_data_ptr && wisun_tasklet_data_ptr->network_interface_id != INVALID_INTERFACE_ID && wisun_tasklet_data_ptr->configured_and_connected) {
int8_t status = arm_network_trusted_certificates_remove();
if (status != 0) {
return -1;
}
return 0;
}
wisun_tasklet_clear_stored_certificates(true, false);
return 0;
}
int wisun_tasklet_set_trusted_certificate(uint8_t *cert, uint16_t cert_len)
{
if (wisun_tasklet_data_ptr && wisun_tasklet_data_ptr->network_interface_id != INVALID_INTERFACE_ID) {
if (wisun_tasklet_data_ptr && wisun_tasklet_data_ptr->network_interface_id != INVALID_INTERFACE_ID && wisun_tasklet_data_ptr->configured_and_connected) {
// interface already active write certificates to stack.
arm_certificate_entry_s arm_cert_entry;
arm_cert_entry.cert = cert;
@ -576,7 +604,7 @@ int wisun_tasklet_set_trusted_certificate(uint8_t *cert, uint16_t cert_len)
return arm_network_trusted_certificate_add(&arm_cert_entry);
}
// Stack is inactive store the certificates and activate when connect() called
return wisun_tasklet_store_certificate_data(cert, cert_len, NULL, 0, false, false, true);
return wisun_tasklet_store_certificate_data(cert, cert_len, NULL, 0, true);
}
int wisun_tasklet_statistics_start(void)