Squashed 'features/nanostack/sal-stack-nanostack/' changes from c473148..0824752

0824752 Merge branch 'release_internal' into release_external
f598339 Merge branch 'master' into release_internal
678e0fd Removed unicast RX flag set. it was affecting that we remove neighbor too early.
a4317fc Corrected coding style
cd2848e Added support for calculating the length of the TLS send message buffer
f255931 Removed UDP echo msg data print and added source address print.
adcca3d RPL dio config advertisment update
6db1f31 Merge pull request #2198 from ARMmbed/IOTTHD-3691
ad244d1 MAC: changed CCA and TX fail trace level to debug
496074a RPL parent select update:
32e22d3 MAC: Added trace to when CCA fails and packet TX is canceled
47b2e03 Corrected GKH initiation on supplicant
c83423a PAE controller now removes keys from MAC on stop (ifdown)
a6f98b7 Flagged extended key usage call with mbedTLS flags
0675a89 Added dynamic setting to enable certificate validation
ff531d3 Added IDevID and LDevID certificate validation
b30635f Merge pull request #2191 from ARMmbed/IOTTHD-3693
88019ec Updated message generated traces
ea15b0e Remove all instances when domain is disbaled and clear EAPOL relay.
dce25d3 Corrected security protocols init and security message routing
7b39e25 Do not trig Renew again after RPL parent registration done state.
3cad7bd DHCPv6 renew and transaction id update
c5b6df3 DHCPv6 client update
dea0d53 DHCPv6 client API update
5eaad10 Added missing address active flag init.
34c751b Corrected triggering of next GTK handshake on authenticator
4fad826 Corrected export keys callback parameters
26c10a6 SW MAC / 802.15.4 Frame counter per key support Update
b62b120 Added robustness on DAO-ACK handling
dfcebef Added support for new certificate modification functions
fd4b2e9 WS ARO handler update
e2d46b9 wi-sun neagtive ARO missing ACK update
443f03f Merge pull request #2181 from ARMmbed/IOTTHD-3530_2
f36da31 MAC: Update frame counter for asynch frames
3260fa1 Merge pull request #2177 from ARMmbed/IOTTHD-3530
f18052a MAC: Initialize frame counter with 0xffffffff
5453e5b MAC: Do not increment framecounter if security param init fails
5bd19c4 MAC: Do not update framecounter for fhss channel retry

git-subtree-dir: features/nanostack/sal-stack-nanostack
git-subtree-split: 082475205bb4eedfbbf5c0c824f2ccf8a73b37ed
pull/11639/head
Jarkko Paso 2019-10-07 13:00:48 +03:00
parent 396dae52ab
commit 3e6cb31659
54 changed files with 1172 additions and 185 deletions

View File

@ -217,6 +217,16 @@ void dhcp_service_update_server_address(uint32_t msg_tr_id, uint8_t *server_addr
*/
void dhcp_service_req_remove(uint32_t msg_tr_id);
/**
* \brief Stops transactions for a messages (retransmissions).
*
* Clears off sending retransmissions for a particular message transaction by finding it via its message class pointer.
*
* \param msg_class_ptr The message class pointer.
*
*/
void dhcp_service_req_remove_all(void *msg_class_ptr);
/**
* \brief Timer tick function for retransmissions.
*

View File

@ -97,6 +97,14 @@ extern int ns_sw_mac_phy_statistics_start(struct mac_api_s *mac_api, struct phy_
*/
extern uint32_t ns_sw_mac_read_current_timestamp(struct mac_api_s *mac_api);
/**
* @brief Enable or disable Frame counter per security key. SW MAC must be create before enable this feature!
* @param mac_api MAC instance.
* @param enable_feature True will allocate frame counter table for devices / key False will clear mode and free counter table.
* @return 0 on success, -1 on fail.
*/
extern int8_t ns_sw_mac_enable_frame_counter_per_key(struct mac_api_s *mac_api, bool enable_feature);
#ifdef __cplusplus
}
#endif

View File

@ -140,4 +140,26 @@ int ws_bbr_node_access_revoke_start(int8_t interface_id);
*/
int ws_bbr_eapol_node_limit_set(int8_t interface_id, uint16_t limit);
/**
* Extended certificate validation
*/
#define BBR_CRT_EXT_VALID_NONE 0x00 /**< Do not make extended validations */
#define BBR_CRT_EXT_VALID_WISUN 0x01 /**< Validate Wi-SUN specific fields */
/**
* Sets extended certificate validation setting
*
* Sets extended certificate validation setting on border router. Function can be used
* to set which fields on client certificate are validated.
*
* \param interface_id Network interface ID
* \param validation Extended Certificate validation setting
* BBR_CRT_EXT_VALID_NONE Do not make extended validations
* BBR_CRT_EXT_VALID_WISUN Validate Wi-SUN specific fields
*
* \return 0 Validation setting was set
* \return <0 Setting set failed
*/
int ws_bbr_ext_certificate_validation_set(int8_t interface_id, uint8_t validation);
#endif /* WS_BBR_API_H_ */

View File

@ -349,12 +349,12 @@ int8_t mac_helper_security_default_recv_key_set(protocol_interface_info_entry_t
return 0;
}
int8_t mac_helper_security_auto_request_key_index_set(protocol_interface_info_entry_t *interface, uint8_t id)
int8_t mac_helper_security_auto_request_key_index_set(protocol_interface_info_entry_t *interface, uint8_t key_attibute_index, uint8_t id)
{
if (id == 0) {
return -1;
}
interface->mac_parameters->mac_default_key_attribute_id = key_attibute_index;
mac_helper_pib_8bit_set(interface, macAutoRequestKeyIndex, id);
return 0;
}
@ -442,13 +442,11 @@ void mac_helper_security_key_swap_next_to_default(protocol_interface_info_entry_
interface->mac_parameters->mac_prev_key_index = interface->mac_parameters->mac_default_key_index;
interface->mac_parameters->mac_prev_key_attribute_id = interface->mac_parameters->mac_default_key_attribute_id;
interface->mac_parameters->mac_default_key_index = interface->mac_parameters->mac_next_key_index;
interface->mac_parameters->mac_default_key_attribute_id = interface->mac_parameters->mac_next_key_attribute_id;
mac_helper_security_auto_request_key_index_set(interface, interface->mac_parameters->mac_next_key_attribute_id, interface->mac_parameters->mac_next_key_index);
interface->mac_parameters->mac_next_key_index = 0;
interface->mac_parameters->mac_next_key_attribute_id = prev_attribute;
mac_helper_pib_8bit_set(interface, macAutoRequestKeyIndex, interface->mac_parameters->mac_default_key_index);
}
void mac_helper_security_key_clean(protocol_interface_info_entry_t *interface)
@ -841,7 +839,7 @@ int8_t mac_helper_link_frame_counter_read(int8_t interface_id, uint32_t *seq_ptr
}
mlme_get_t get_req;
get_req.attr = macFrameCounter;
get_req.attr_index = 0;
get_req.attr_index = cur->mac_parameters->mac_default_key_attribute_id;
cur->mac_api->mlme_req(cur->mac_api, MLME_GET, &get_req);
*seq_ptr = cur->mac_parameters->security_frame_counter;
@ -858,7 +856,7 @@ int8_t mac_helper_link_frame_counter_set(int8_t interface_id, uint32_t seq_ptr)
}
mlme_set_t set_req;
set_req.attr = macFrameCounter;
set_req.attr_index = 0;
set_req.attr_index = cur->mac_parameters->mac_default_key_attribute_id;
set_req.value_pointer = &seq_ptr;
set_req.value_size = 4;
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req);

View File

@ -69,7 +69,7 @@ int8_t mac_helper_security_default_key_set(struct protocol_interface_info_entry
int8_t mac_helper_security_default_recv_key_set(struct protocol_interface_info_entry *interface, const uint8_t *key, uint8_t id, uint8_t keyid_mode);
int8_t mac_helper_security_auto_request_key_index_set(struct protocol_interface_info_entry *interface, uint8_t id);
int8_t mac_helper_security_auto_request_key_index_set(struct protocol_interface_info_entry *interface, uint8_t key_attibute_index, uint8_t id);
int8_t mac_helper_security_next_key_set(struct protocol_interface_info_entry *interface, uint8_t *key, uint8_t id, uint8_t keyid_mode);

View File

@ -636,3 +636,18 @@ int ws_bbr_eapol_node_limit_set(int8_t interface_id, uint16_t limit)
return -1;
#endif
}
int ws_bbr_ext_certificate_validation_set(int8_t interface_id, uint8_t validation)
{
(void) interface_id;
#ifdef HAVE_WS_BORDER_ROUTER
bool enabled = false;
if (validation & BBR_CRT_EXT_VALID_WISUN) {
enabled = true;
}
return ws_pae_controller_ext_certificate_validation_set(interface_id, enabled);
#else
(void) validation;
return -1;
#endif
}

View File

@ -1371,7 +1371,7 @@ static void ws_bootstrap_neighbor_table_clean(struct protocol_interface_info_ent
//Read current timestamp
uint32_t time_from_last_unicast_shedule = ws_time_from_last_unicast_traffic(current_time_stamp, ws_neighbor);
if (time_from_last_unicast_shedule > WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT || !ws_neighbor->unicast_data_rx) {
if (time_from_last_unicast_shedule > WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT) {
//Accept only Enough Old Device
if (!neighbor_entry_ptr) {
//Accept first compare
@ -1581,6 +1581,10 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode)
return -2;
}
if (ns_sw_mac_enable_frame_counter_per_key(cur->mac_api, true)) {
return -1;
}
if (!etx_storage_list_allocate(cur->id, buffer.device_decription_table_size)) {
return -1;
}
@ -1940,6 +1944,9 @@ static void ws_dhcp_client_global_adress_cb(int8_t interface, uint8_t dhcp_addr[
if (cur) {
rpl_control_register_address(cur, prefix);
}
} else {
//Delete dhcpv6 client
dhcp_client_global_address_delete(interface, dhcp_addr, prefix);
}
}
@ -2055,6 +2062,9 @@ static void ws_bootstrap_rpl_activate(protocol_interface_info_entry_t *cur)
// If i am router I Do this
rpl_control_force_leaf(protocol_6lowpan_rpl_domain, leaf);
rpl_control_request_parent_link_confirmation(true);
rpl_control_set_dio_multicast_min_config_advertisment_count(WS_MIN_DIO_MULTICAST_CONFIG_ADVERTISMENT_COUNT);
rpl_control_set_dao_retry_count(WS_MAX_DAO_RETRIES);
rpl_control_set_initial_dao_ack_wait(WS_MAX_DAO_INITIAL_TIMEOUT);
cur->ws_info->rpl_state = 0xff; // Set invalid state and learn from event
}
@ -2107,7 +2117,9 @@ static void ws_bootstrap_start_discovery(protocol_interface_info_entry_t *cur)
ws_bootstrap_neighbor_list_clean(cur);
// Clear RPL information
rpl_control_remove_domain_from_interface(cur);
rpl_control_free_domain_instances_from_interface(cur);
// Clear EAPOL relay address
ws_eapol_relay_delete(cur);
// Clear ip stack from old information
ws_bootstrap_ip_stack_reset(cur);
@ -2169,7 +2181,7 @@ static void ws_bootstrap_nw_key_clear(protocol_interface_info_entry_t *cur, uint
static void ws_bootstrap_nw_key_index_set(protocol_interface_info_entry_t *cur, uint8_t index)
{
// Set send key
mac_helper_security_auto_request_key_index_set(cur, index + 1);
mac_helper_security_auto_request_key_index_set(cur, index, index + 1);
}
static void ws_bootstrap_nw_frame_counter_set(protocol_interface_info_entry_t *cur, uint32_t counter)

View File

@ -31,6 +31,8 @@
#include "Service_Libs/etx/etx.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
#include "Service_Libs/blacklist/blacklist.h"
#include "RPL/rpl_protocol.h"
#include "RPL/rpl_control.h"
#include "ws_management_api.h"
#include "mac_api.h"
@ -404,6 +406,13 @@ bool ws_common_allow_child_registration(protocol_interface_info_entry_t *interfa
return true;
}
//Verify that we have Selected Parent
if (interface->bootsrap_mode != ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER && !rpl_control_parent_candidate_list_size(interface, true)) {
tr_info("Do not accept new ARO child: no selected parent");
return false;
}
ns_list_foreach_safe(mac_neighbor_table_entry_t, cur, &mac_neighbor_info(interface)->neighbour_list) {
if (ipv6_neighbour_has_registered_by_eui64(&interface->ipv6_neighbour_cache, cur->mac64)) {

View File

@ -133,4 +133,12 @@ extern uint8_t DEVICE_MIN_SENS;
#define FRAME_COUNTER_INCREMENT 1000 // How much frame counter is incremented on start up
#define FRAME_COUNTER_STORE_THRESHOLD 800 // How much frame counter must increment before it is stored
/*
* RPL Configuration parameters
*/
#define WS_MAX_DAO_RETRIES 3 // With 40s, 80s, 160s, 320s, 640s
#define WS_MAX_DAO_INITIAL_TIMEOUT 400 // With 40s initial value exponentially increasing
#define WS_MIN_DIO_MULTICAST_CONFIG_ADVERTISMENT_COUNT 10 // Define 10 multicast advertisment when learn config or learn config update
#endif /* WS_CONFIG_H_ */

View File

@ -919,12 +919,12 @@ static void ws_pae_auth_next_kmp_trigger(pae_auth_t *pae_auth, supp_entry_t *sup
kmp_api_t *api = ws_pae_lib_kmp_list_type_get(&supp_entry->kmp_list, next_type);
if (api != NULL) {
/* For other types than GTK, only one ongoing negotiation at the same time,
for GTK there can be previous terminating and the new one for next key index */
if (next_type != IEEE_802_11_GKH) {
tr_info("KMP already ongoing; ignored, eui-64: %s", trace_array(supp_entry->addr.eui_64, 8));
return;
}
// Delete KMP
ws_pae_lib_kmp_list_delete(&supp_entry->kmp_list, api);
}
}

View File

@ -100,6 +100,7 @@ typedef struct {
typedef struct {
uint16_t node_limit; /**< Max number of stored supplicants */
bool node_limit_set : 1; /**< Node limit set */
bool ext_cert_valid_enabled : 1; /**< Extended certificate validation enabled */
} pae_controller_config_t;
static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr);
@ -126,7 +127,8 @@ static NS_LIST_DEFINE(pae_controller_list, pae_controller_t, link);
pae_controller_config_t pae_controller_config = {
.node_limit = 0,
.node_limit_set = false
.node_limit_set = false,
.ext_cert_valid_enabled = false
};
#if !defined(HAVE_PAE_SUPP) && !defined(HAVE_PAE_AUTH)
@ -482,9 +484,12 @@ static void ws_pae_controller_nw_key_index_check_and_set(protocol_interface_info
controller->gtk_index = index;
uint32_t frame_counter = ws_pae_controller_frame_counter_get(&controller->stored_frame_counter, index, controller->nw_key[index].hash);
controller->nw_frame_counter_set(interface_ptr, frame_counter);
if (frame_counter) {
controller->nw_frame_counter_set(interface_ptr, frame_counter);
}
tr_info("NW frame counter set: %"PRIu32"", frame_counter);
ws_pae_controller_frame_counter_write(controller, index, controller->nw_key[index].hash, frame_counter);
}
// Do not update PAN version for initial key index set
@ -511,9 +516,12 @@ static void ws_pae_controller_active_nw_key_set(protocol_interface_info_entry_t
// If index has changed and the key for the index is fresh get frame counter
if (controller->gtk_index != index && controller->nw_key[index].fresh) {
uint32_t frame_counter = ws_pae_controller_frame_counter_get(&controller->stored_frame_counter, index, controller->nw_key[index].hash);
controller->nw_frame_counter_set(cur, frame_counter);
if (frame_counter) {
controller->nw_frame_counter_set(cur, frame_counter);
}
tr_info("NW frame counter set: %"PRIu32"", frame_counter);
ws_pae_controller_frame_counter_write(controller, index, controller->nw_key[index].hash, frame_counter);
}
controller->gtk_index = index;
@ -586,6 +594,7 @@ static void ws_pae_controller_data_init(pae_controller_t *controller)
sec_prot_keys_gtks_init(&controller->gtks);
sec_prot_keys_gtks_init(&controller->next_gtks);
sec_prot_certs_init(&controller->certs);
sec_prot_certs_ext_certificate_validation_set(&controller->certs, pae_controller_config.ext_cert_valid_enabled);
ws_pae_timers_settings_init(&controller->timer_settings);
}
@ -695,6 +704,9 @@ int8_t ws_pae_controller_stop(protocol_interface_info_entry_t *interface_ptr)
// Stores frame counter
ws_pae_controller_frame_counter_store(controller);
// Removes network keys from PAE controller and MAC
ws_pae_controller_nw_keys_remove(interface_ptr);
// If PAE has been initialized, deletes it
if (controller->pae_delete) {
controller->pae_delete(interface_ptr);
@ -764,6 +776,46 @@ int8_t ws_pae_controller_certificate_chain_set(const arm_certificate_chain_entry
}
}
}
// Updates the length of own certificates
entry->certs.own_cert_chain_len = sec_prot_certs_cert_chain_entry_len_get(&entry->certs.own_cert_chain);
}
return 0;
}
int8_t ws_pae_controller_own_certificate_add(const arm_certificate_entry_s *cert)
{
if (!cert) {
return -1;
}
int8_t ret = -1;
ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
for (uint8_t i = 0; i < SEC_PROT_CERT_CHAIN_DEPTH; i++) {
if (entry->certs.own_cert_chain.cert[i] == NULL) {
sec_prot_certs_cert_set(&entry->certs.own_cert_chain, i, (uint8_t *) cert->cert, cert->cert_len);
// Set private key if set for the certificate that is added
if (cert->key && cert->key_len > 0) {
sec_prot_certs_priv_key_set(&entry->certs.own_cert_chain, (uint8_t *) cert->key, cert->key_len);
}
ret = 0;
break;
}
}
// Updates the length of own certificates
entry->certs.own_cert_chain_len = sec_prot_certs_cert_chain_entry_len_get(&entry->certs.own_cert_chain);
}
return ret;
}
int8_t ws_pae_controller_own_certificates_remove(void)
{
ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
sec_prot_certs_chain_entry_init(&entry->certs.own_cert_chain);
entry->certs.own_cert_chain_len = 0;
}
return 0;
@ -816,6 +868,15 @@ int8_t ws_pae_controller_trusted_certificate_remove(const arm_certificate_entry_
return ret;
}
int8_t ws_pae_controller_trusted_certificates_remove(void)
{
ns_list_foreach(pae_controller_t, entry, &pae_controller_list) {
sec_prot_certs_chain_list_delete(&entry->certs.trusted_cert_chain_list);
}
return 0;
}
int8_t ws_pae_controller_certificate_revocation_list_add(const arm_cert_revocation_list_entry_s *crl)
{
if (!crl) {
@ -1051,6 +1112,26 @@ int8_t ws_pae_controller_node_limit_set(int8_t interface_id, uint16_t limit)
#endif
}
int8_t ws_pae_controller_ext_certificate_validation_set(int8_t interface_id, bool enabled)
{
#ifdef HAVE_PAE_AUTH
pae_controller_config.ext_cert_valid_enabled = enabled;
pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
if (!controller) {
return -1;
}
sec_prot_certs_ext_certificate_validation_set(&controller->certs, enabled);
return 0;
#else
(void) interface_id;
(void) enabled;
return -1;
#endif
}
void ws_pae_controller_forced_gc(bool full_gc)
{
/* Purge only when on critical limit since node limit should handle limiting

View File

@ -158,6 +158,26 @@ int8_t ws_pae_controller_timing_adjust(uint8_t timing);
*/
int8_t ws_pae_controller_certificate_chain_set(const arm_certificate_chain_entry_s *chain);
/**
* ws_pae_controller_own_certificate_add add own certificate to certificate chain
*
* \param cert own certificate
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_controller_own_certificate_add(const arm_certificate_entry_s *cert);
/**
* ws_pae_controller_own_certificates_remove removes own certificates
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_controller_own_certificates_remove(void);
/**
* ws_pae_controller_trusted_certificate_add add trusted certificate
*
@ -180,6 +200,15 @@ int8_t ws_pae_controller_trusted_certificate_add(const arm_certificate_entry_s *
*/
int8_t ws_pae_controller_trusted_certificate_remove(const arm_certificate_entry_s *cert);
/**
* ws_pae_controller_trusted_certificates_remove removes trusted certificates
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_controller_trusted_certificates_remove(void);
/**
* ws_pae_controller_certificate_revocation_list_add add certification revocation list
*
@ -338,6 +367,18 @@ int8_t ws_pae_controller_node_access_revoke_start(int8_t interface_id);
*/
int8_t ws_pae_controller_node_limit_set(int8_t interface_id, uint16_t limit);
/**
* ws_pae_controller_ext_certificate_validation_set enable or disable extended certificate validation
*
* \param interface_ptr interface
* \param enabled true to enable extended validation, false to disable
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_controller_ext_certificate_validation_set(int8_t interface_id, bool enabled);
/**
* ws_pae_controller_active_key_update update active key (test interface)
*

View File

@ -76,13 +76,21 @@ int8_t ws_pae_lib_kmp_list_delete(kmp_list_t *kmp_list, kmp_api_t *kmp)
kmp_api_t *ws_pae_lib_kmp_list_type_get(kmp_list_t *kmp_list, kmp_type_e type)
{
kmp_api_t *kmp = NULL;
ns_list_foreach(kmp_entry_t, cur, kmp_list) {
// If kmp type matches
if (kmp_api_type_get(cur->kmp) == type) {
return cur->kmp;
/* If receiving of messages has not been disabled for the kmp (kmp is not
in terminating phase) prioritizes that kmp */
if (!kmp_api_receive_disable(cur->kmp)) {
return cur->kmp;
}
// Otherwise returns any kmp that matches
kmp = cur->kmp;
}
}
return 0;
return kmp;
}
void ws_pae_lib_kmp_list_free(kmp_list_t *kmp_list)

View File

@ -588,6 +588,7 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se
pae_supp->timer_running = false;
pae_supp->new_br_eui_64_set = false;
pae_supp->new_br_eui_64_fresh = false;
pae_supp->entry_address_active = false;
ws_pae_lib_supp_init(&pae_supp->entry);
@ -1010,7 +1011,13 @@ static kmp_api_t *ws_pae_supp_kmp_incoming_ind(kmp_service_t *service, kmp_type_
// Check if ongoing
kmp_api_t *kmp = ws_pae_lib_kmp_list_type_get(&pae_supp->entry.kmp_list, type);
if (kmp) {
/* If kmp receiving is enabled or it is not GKH, routes message to existing KMP.
For GKH creates an instance to handle message. If message is not valid (e.g. repeated
message counter), GKH ignores message and waits for timeout. All further messages
are routed to that instance. If valid message arrives, GKH instance handles the
message, replies to authenticator and terminates. */
if (kmp && (!kmp_api_receive_disable(kmp) || type != IEEE_802_11_GKH)) {
return kmp;
}

View File

@ -1388,6 +1388,9 @@ static void icmpv6_aro_cb(buffer_t *buf, uint8_t status)
ll_address[8] ^= 2;
}
rpl_control_address_register_done(buf->interface, ll_address, status);
if (status != SOCKET_TX_DONE) {
ws_common_aro_failure(buf->interface, ll_address);
}
}
buffer_t *icmpv6_build_ns(protocol_interface_info_entry_t *cur, const uint8_t target_addr[16], const uint8_t *prompting_src_addr, bool unicast, bool unspecified_source, const aro_t *aro)
@ -1603,8 +1606,6 @@ buffer_t *icmpv6_build_na(protocol_interface_info_entry_t *cur, bool solicited,
uint8_t *ptr;
uint8_t flags;
tr_debug("Build NA");
/* Check if ARO response and status == success, then sending can be omitted with flag */
if (aro && cur->ipv6_neighbour_cache.omit_na_aro_success && aro->status == ARO_SUCCESS) {
tr_debug("Omit NA ARO success");
@ -1712,6 +1713,8 @@ buffer_t *icmpv6_build_na(protocol_interface_info_entry_t *cur, bool solicited,
buf->info = (buffer_info_t)(B_DIR_DOWN | B_FROM_ICMP | B_TO_ICMP);
buf->interface = cur;
tr_debug("Build NA");
return (buf);
}

View File

@ -146,12 +146,7 @@ buffer_t *udp_up(buffer_t *buf)
if (buf->dst_sa.port == UDP_PORT_ECHO && buf->src_sa.port != UDP_PORT_ECHO) {
protocol_interface_info_entry_t *cur;
tr_debug("UDP echo msg [%"PRIi16"]: %s%s",
buffer_data_length(buf),
trace_array(
buffer_data_pointer(buf),
(buffer_data_length(buf) > 64 ? 64 : buffer_data_length(buf))),
(buffer_data_length(buf) > 64 ? "..." : ""));
tr_debug("UDP echo msg from %s", trace_ipv6(buf->src_sa.address));
cur = buf->interface;

View File

@ -111,7 +111,7 @@ void dhcp_client_delete(int8_t interface)
if (srv_data_ptr != NULL) {
tr_debug("Free DHCPv6 Client\n");
memcpy(temporary_address, srv_data_ptr->iaNontemporalAddress.addressPrefix, 16);
dhcp_service_req_remove(srv_data_ptr->transActionId);// remove all pending retransmissions
dhcp_service_req_remove_all(srv_data_ptr);// remove all pending retransmissions
libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
addr_delete(cur, temporary_address);
@ -144,13 +144,18 @@ int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uin
dhcpv6_client_server_data_t *srv_data_ptr = NULL;
(void)instance_id;
srv_data_ptr = ptr;
//Validate that started TR ID class is still at list
srv_data_ptr = libdhcpv6_nonTemporal_validate_class_pointer(ptr);
if (srv_data_ptr == NULL) {
tr_error("server data not found");
goto error_exit;
}
//Clear Active Transaction state
srv_data_ptr->transActionId = 0;
// Validate message
if (msg_name != DHCPV6_REPLY_TYPE) {
tr_error("invalid response");
@ -158,7 +163,7 @@ int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uin
}
if (libdhcpv6_reply_message_option_validate(&clientId, &serverId, &dhcp_ia_non_temporal_params, msg_ptr, msg_len) != 0) {
tr_error("Sol Not include all Options");
tr_error("Reply Not include all Options");
goto error_exit;
}
@ -330,7 +335,7 @@ int dhcp_client_server_address_update(int8_t interface, uint8_t *prefix, uint8_t
}
memcpy(srv_data_ptr->server_address, server_address, 16);
if (!srv_data_ptr->iaNonTemporalStructValid) {
if (srv_data_ptr->transActionId) {
dhcp_service_update_server_address(srv_data_ptr->transActionId, server_address);
}
return 0;
@ -357,7 +362,7 @@ void dhcp_client_global_address_delete(int8_t interface, uint8_t *dhcp_addr, uin
return;
}
dhcp_service_req_remove(srv_data_ptr->transActionId);// remove all pending retransmissions
dhcp_service_req_remove_all(srv_data_ptr);// remove all pending retransmissions
if (dhcp_client.one_instance_interface) {
addr_deprecate(cur, srv_data_ptr->iaNontemporalAddress.addressPrefix);
} else {
@ -384,7 +389,7 @@ void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t
return;
}
if (reason == ADDR_CALLBACK_INVALIDATED) {
dhcp_service_req_remove(srv_data_ptr->transActionId);//stop retransmissions of renew
dhcp_service_req_remove_all(srv_data_ptr);// remove all pending retransmissions
libdhcvp6_nontemporalAddress_server_data_free(srv_data_ptr);
tr_warn("Dhcp address lost");
return;
@ -394,6 +399,12 @@ void dhcpv6_renew(protocol_interface_info_entry_t *interface, if_address_entry_t
return;
}
if (srv_data_ptr->transActionId) {
//Do not trig new Renew process
tr_warn("Do not trig new pending renew request");
return;
}
payload_len = libdhcpv6_address_request_message_len(srv_data_ptr->clientLinkIdType, srv_data_ptr->serverLinkType, 0, !dhcp_client.no_address_hint);
payload_ptr = ns_dyn_mem_temporary_alloc(payload_len);
if (payload_ptr == NULL) {

View File

@ -148,24 +148,19 @@ typedef struct mac_mcps_data_conf_fail_s {
typedef struct protocol_interface_rf_mac_setup {
int8_t mac_interface_id;
bool macUpState;
bool macUpState: 1;
bool shortAdressValid: 1; //Define Dynamic src address to mac16 when it is true
bool beaconSrcAddressModeLong: 1; //This force beacon src to mac64 otherwise shortAdressValid will define type
bool secFrameCounterPerKey: 1;
bool mac_extension_enabled: 1;
bool mac_ack_tx_active: 1;
bool mac_frame_pending: 1;
uint16_t mac_short_address;
uint16_t pan_id;
uint8_t mac64[8];
uint16_t coord_short_address;
uint8_t coord_long_address[8];
/* MAC Capability Information */
bool macCapRxOnIdle: 1;
bool macCapCordinator: 1;
bool macCapAssocationPermit: 1;
bool macCapBatteryPowered: 1;
bool macCapSecrutityCapability: 1;
bool macProminousMode: 1;
bool macGTSPermit: 1;
bool mac_security_enabled: 1;
@ -173,7 +168,6 @@ typedef struct protocol_interface_rf_mac_setup {
bool mac_security_bypass_unknow_device: 1;
/* Load balancing need this feature */
bool macAcceptAnyBeacon: 1;
/* TX process Flag */
bool macTxProcessActive: 1;
bool macTxRequestAck: 1;
@ -188,6 +182,12 @@ typedef struct protocol_interface_rf_mac_setup {
bool scan_active: 1;
bool rf_csma_extension_supported: 1;
bool ack_tx_possible: 1;
uint16_t mac_short_address;
uint16_t pan_id;
uint8_t mac64[8];
uint16_t coord_short_address;
uint8_t coord_long_address[8];
/* CSMA Params */
unsigned macMinBE: 4;
unsigned macMaxBE: 4;
@ -200,7 +200,6 @@ typedef struct protocol_interface_rf_mac_setup {
uint8_t scan_duration; //Needed???
mac_scan_type_t scan_type;
uint8_t mac_channel;
//uint8_t cca_failure;
@ -253,6 +252,7 @@ typedef struct protocol_interface_rf_mac_setup {
struct mlme_device_descriptor_s *device_description_table;
uint8_t device_description_table_size;
struct mlme_key_descriptor_s *key_description_table;
void *key_device_frame_counter_list_buffer;
uint8_t key_description_table_size;
uint8_t key_lookup_list_size;
uint8_t key_usage_list_size;

View File

@ -90,6 +90,14 @@ uint32_t mac_mcps_sap_get_phy_timestamp(protocol_interface_rf_mac_setup_s *rf_ma
return timestamp;
}
static bool mac_data_counter_too_small(uint32_t current_counter, uint32_t packet_counter)
{
if ((current_counter - packet_counter) >= 2) {
return true;
}
return false;
}
static bool mac_data_request_confirmation_finnish(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_pre_build_frame_t *buffer)
{
if (!buffer->asynch_request) {
@ -583,10 +591,14 @@ static uint8_t mac_data_interface_decrypt_packet(mac_pre_parsed_frame_t *b, mlme
return MLME_UNAVAILABLE_KEY;
}
if (b->neigh_info && neighbour_validation.frameCounter < b->neigh_info->FrameCounter) {
tr_debug("MLME_COUNTER_ERROR");
return MLME_COUNTER_ERROR;
if (b->neigh_info) {
uint32_t min_accepted_frame_counter = mac_mib_key_device_frame_counter_get(key_description, b->neigh_info, device_descriptor_handle);
if (neighbour_validation.frameCounter < min_accepted_frame_counter) {
tr_debug("MLME_COUNTER_ERROR");
return MLME_COUNTER_ERROR;
}
}
}
key = key_description->Key;
@ -620,10 +632,15 @@ static uint8_t mac_data_interface_decrypt_packet(mac_pre_parsed_frame_t *b, mlme
//Update key device and key description tables
if (!security_by_pass) {
b->neigh_info->FrameCounter = neighbour_validation.frameCounter + 1;
mac_sec_mib_key_device_frame_counter_set(key_description, b->neigh_info, neighbour_validation.frameCounter + 1, device_descriptor_handle);
if (!key_device_description) {
// Black list old used keys by this device
mac_sec_mib_device_description_blacklist(rf_mac_setup, device_descriptor_handle);
if (!rf_mac_setup->secFrameCounterPerKey) {
// Black list old used keys by this device
mac_sec_mib_device_description_blacklist(rf_mac_setup, device_descriptor_handle);
}
key_device_description = mac_sec_mib_key_device_description_list_update(key_description);
if (key_device_description) {
tr_debug("Set new device user %u for key", device_descriptor_handle);
@ -1199,6 +1216,7 @@ mac_pre_build_frame_t *mcps_sap_prebuild_frame_buffer_get(uint16_t payload_size)
return NULL;
}
memset(buffer, 0, sizeof(mac_pre_build_frame_t));
buffer->aux_header.frameCounter = 0xffffffff;
if (payload_size) {
//Mac interlnal payload allocate
buffer->mac_payload = ns_dyn_mem_temporary_alloc(payload_size);
@ -1229,7 +1247,7 @@ void mcps_sap_prebuild_frame_buffer_free(mac_pre_build_frame_t *buffer)
}
static bool mac_frame_security_parameters_init(ccm_globals_t *ccm_ptr, protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer)
static mlme_key_descriptor_t *mac_frame_security_key_get(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer)
{
/* Encrypt the packet payload if AES encyption bit is set */
mlme_security_t key_source;
@ -1237,13 +1255,13 @@ static bool mac_frame_security_parameters_init(ccm_globals_t *ccm_ptr, protocol_
key_source.KeyIndex = buffer->aux_header.KeyIndex;
key_source.SecurityLevel = buffer->aux_header.securityLevel;
memcpy(key_source.Keysource, buffer->aux_header.Keysource, 8);
mlme_key_descriptor_t *key_description = mac_sec_key_description_get(rf_ptr, &key_source, buffer->fcf_dsn.DstAddrMode, buffer->DstAddr, buffer->DstPANId);
return mac_sec_key_description_get(rf_ptr, &key_source, buffer->fcf_dsn.DstAddrMode, buffer->DstAddr, buffer->DstPANId);
}
if (!key_description) {
buffer->status = MLME_UNAVAILABLE_KEY;
return false;
}
static bool mac_frame_security_parameters_init(ccm_globals_t *ccm_ptr, protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *buffer, mlme_key_descriptor_t *key_description)
{
/* Encrypt the packet payload if AES encyption bit is set */
mlme_device_descriptor_t *device_description;
uint8_t *nonce_ext_64_ptr;
@ -1298,6 +1316,7 @@ static void mac_common_data_confirmation_handle(protocol_interface_rf_mac_setup_
timer_mac_stop(rf_mac_setup);
if (m_event == MAC_CCA_FAIL) {
sw_mac_stats_update(rf_mac_setup, STAT_MAC_TX_CCA_FAIL, 0);
tr_debug("MAC CCA fail");
/* CCA fail */
//rf_mac_setup->cca_failure++;
buf->status = MLME_BUSY_CHAN;
@ -1305,7 +1324,7 @@ static void mac_common_data_confirmation_handle(protocol_interface_rf_mac_setup_
sw_mac_stats_update(rf_mac_setup, STAT_MAC_TX_COUNT, buf->mac_payload_length);
if (m_event == MAC_TX_FAIL) {
sw_mac_stats_update(rf_mac_setup, STAT_MAC_TX_FAIL, 0);
tr_error("MAC tx fail");
tr_debug("MAC tx fail");
buf->status = MLME_TX_NO_ACK;
} else if (m_event == MAC_TX_DONE) {
if (mac_is_ack_request_set(buf) == false) {
@ -1517,16 +1536,31 @@ static int8_t mcps_generic_packet_build(protocol_interface_rf_mac_setup_s *rf_pt
mac_header_information_elements_preparation(buffer);
mcps_generic_sequence_number_allocate(rf_ptr, buffer);
mlme_key_descriptor_t *key_desc;
if (buffer->fcf_dsn.securityEnabled) {
bool increment_framecounter = false;
//Remember to update security counter here!
buffer->aux_header.frameCounter = mac_mlme_framecounter_get(rf_ptr);
if (!mac_frame_security_parameters_init(&ccm_ptr, rf_ptr, buffer)) {
key_desc = mac_frame_security_key_get(rf_ptr, buffer);
if (!key_desc) {
buffer->status = MLME_UNAVAILABLE_KEY;
return -2;
}
//GET Counter
uint32_t new_frameCounter = mac_sec_mib_key_outgoing_frame_counter_get(rf_ptr, key_desc);
// If buffer frame counter is set, this is FHSS channel retry, update frame counter only if something was sent after failure
if ((buffer->aux_header.frameCounter == 0xffffffff) || buffer->asynch_request || mac_data_counter_too_small(new_frameCounter, buffer->aux_header.frameCounter)) {
buffer->aux_header.frameCounter = new_frameCounter;
increment_framecounter = true;
}
if (!mac_frame_security_parameters_init(&ccm_ptr, rf_ptr, buffer, key_desc)) {
return -2;
}
//Increment security counter
mac_mlme_framecounter_increment(rf_ptr);
if (increment_framecounter) {
mac_sec_mib_key_outgoing_frame_counter_increment(rf_ptr, key_desc);
}
}
//Calculate Payload length here with IE extension
@ -1559,7 +1593,9 @@ static int8_t mcps_generic_packet_build(protocol_interface_rf_mac_setup_s *rf_pt
tr_debug("Too Long %u, %u pa %u header %u mic %u", frame_length, mac_payload_length, buffer->mac_header_length_with_security, buffer->security_mic_len, dev_driver->phy_MTU);
buffer->status = MLME_FRAME_TOO_LONG;
//decrement security counter
mac_mlme_framecounter_decrement(rf_ptr);
if (buffer->fcf_dsn.securityEnabled) {
mac_sec_mib_key_outgoing_frame_counter_decrement(rf_ptr, key_desc);
}
return -1;
}
@ -1673,19 +1709,24 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, bool in
ccm_globals_t ccm_ptr;
mac_pre_build_frame_t *buffer = &rf_ptr->enhanced_ack_buffer;
mlme_key_descriptor_t *key_desc;
if (buffer->fcf_dsn.securityEnabled) {
//Remember to update security counter here!
if (init_build) {
buffer->aux_header.frameCounter = mac_mlme_framecounter_get(rf_ptr);
key_desc = mac_frame_security_key_get(rf_ptr, buffer);
if (!key_desc) {
buffer->status = MLME_UNAVAILABLE_KEY;
return -2;
}
if (!mac_frame_security_parameters_init(&ccm_ptr, rf_ptr, buffer)) {
if (init_build) {
buffer->aux_header.frameCounter = mac_sec_mib_key_outgoing_frame_counter_get(rf_ptr, key_desc);
}
if (!mac_frame_security_parameters_init(&ccm_ptr, rf_ptr, buffer, key_desc)) {
return -2;
}
if (init_build) {
//Increment security counter
mac_mlme_framecounter_increment(rf_ptr);
mac_sec_mib_key_outgoing_frame_counter_increment(rf_ptr, key_desc);
}
}
@ -1709,7 +1750,7 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, bool in
if (buffer->fcf_dsn.securityEnabled) {
//decrement security counter
mac_mlme_framecounter_decrement(rf_ptr);
mac_sec_mib_key_outgoing_frame_counter_decrement(rf_ptr, key_desc);
ccm_free(&ccm_ptr);
}
return -1;
@ -1770,7 +1811,14 @@ static int8_t mcps_generic_packet_rebuild(protocol_interface_rf_mac_setup_s *rf_
}
if (buffer->fcf_dsn.securityEnabled) {
if (!mac_frame_security_parameters_init(&ccm_ptr, rf_ptr, buffer)) {
mlme_key_descriptor_t *key_desc = mac_frame_security_key_get(rf_ptr, buffer);
if (!key_desc) {
buffer->status = MLME_UNAVAILABLE_KEY;
return -2;
}
if (!mac_frame_security_parameters_init(&ccm_ptr, rf_ptr, buffer, key_desc)) {
return -2;
}
}
@ -2318,3 +2366,17 @@ int mcps_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage)
return -1;
}
void mcps_pending_packet_counter_update_check(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_pre_build_frame_t *buffer)
{
if (buffer->fcf_dsn.securityEnabled) {
mlme_key_descriptor_t *key_desc = mac_frame_security_key_get(rf_mac_setup, buffer);
if (key_desc) {
uint32_t current_counter = mac_sec_mib_key_outgoing_frame_counter_get(rf_mac_setup, key_desc);
if (mac_data_counter_too_small(current_counter, buffer->aux_header.frameCounter)) {
buffer->aux_header.frameCounter = current_counter;
mac_sec_mib_key_outgoing_frame_counter_increment(rf_mac_setup, key_desc);
}
}
}
}

View File

@ -140,4 +140,6 @@ int mcps_packet_ingress_rate_limit_by_memory(uint8_t free_heap_percentage);
uint32_t mac_mcps_sap_get_phy_timestamp(struct protocol_interface_rf_mac_setup *rf_mac_setup);
void mcps_pending_packet_counter_update_check(struct protocol_interface_rf_mac_setup *rf_mac_setup, mac_pre_build_frame_t *buffer);
#endif /* MAC_IEEE802_15_4_MAC_MCPS_SAP_H_ */

View File

@ -606,15 +606,21 @@ static int8_t mac_mlme_8bit_set(protocol_interface_rf_mac_setup_s *rf_mac_setup,
return 0;
}
static int8_t mac_mlme_32bit_set(protocol_interface_rf_mac_setup_s *rf_mac_setup, mlme_attr_t attribute, uint32_t value)
static int8_t mac_mlme_32bit_set(protocol_interface_rf_mac_setup_s *rf_mac_setup, mlme_attr_t attribute, uint8_t index, uint32_t value)
{
(void)rf_mac_setup;
(void) value;
switch (attribute) {
case macFrameCounter:
platform_enter_critical();
rf_mac_setup->security_frame_counter = value;
platform_exit_critical();
if (rf_mac_setup->secFrameCounterPerKey) {
mlme_key_descriptor_t *key_desc = mac_sec_key_description_get_by_attribute(rf_mac_setup, index);
if (!key_desc) {
return -1;
}
mac_sec_mib_key_outgoing_frame_counter_set(rf_mac_setup, key_desc, value);
} else {
mac_sec_mib_key_outgoing_frame_counter_set(rf_mac_setup, NULL, value);
}
break;
default:
@ -718,7 +724,7 @@ static int8_t mac_mlme_handle_set_values(protocol_interface_rf_mac_setup_s *rf_m
return mac_mlme_16bit_set(rf_mac_setup, set_req->attr, *pu16);
} else if (set_req->value_size == 4) {
const uint32_t *pu32 = set_req->value_pointer;
return mac_mlme_32bit_set(rf_mac_setup, set_req->attr, *pu32);
return mac_mlme_32bit_set(rf_mac_setup, set_req->attr, set_req->attr_index, *pu32);
}
return -1;
}
@ -787,30 +793,6 @@ int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const m
}
}
uint32_t mac_mlme_framecounter_get(struct protocol_interface_rf_mac_setup *rf_mac_setup)
{
uint32_t value;
platform_enter_critical();
value = rf_mac_setup->security_frame_counter;
platform_exit_critical();
return value;
}
void mac_mlme_framecounter_increment(struct protocol_interface_rf_mac_setup *rf_mac_setup)
{
platform_enter_critical();
rf_mac_setup->security_frame_counter++;
platform_exit_critical();
}
void mac_mlme_framecounter_decrement(struct protocol_interface_rf_mac_setup *rf_mac_setup)
{
platform_enter_critical();
rf_mac_setup->security_frame_counter--;
platform_exit_critical();
}
int8_t mac_mlme_get_req(struct protocol_interface_rf_mac_setup *rf_mac_setup, mlme_get_conf_t *get_req)
{
if (!get_req || !rf_mac_setup) {
@ -833,9 +815,16 @@ int8_t mac_mlme_get_req(struct protocol_interface_rf_mac_setup *rf_mac_setup, ml
break;
case macFrameCounter:
platform_enter_critical();
get_req->value_pointer = &rf_mac_setup->security_frame_counter;
platform_exit_critical();
if (rf_mac_setup->secFrameCounterPerKey) {
mlme_key_descriptor_t *key_desc = mac_sec_key_description_get_by_attribute(rf_mac_setup, get_req->attr_index);
if (!key_desc) {
return -1;
}
get_req->value_pointer = &key_desc->KeyFrameCounter;
} else {
get_req->value_pointer = &rf_mac_setup->security_frame_counter;
}
get_req->value_size = 4;
break;
@ -1344,8 +1333,6 @@ int mac_mlme_beacon_notify(protocol_interface_rf_mac_setup_s *rf_mac_setup, mlme
mac->mlme_ind_cb(mac, MLME_BEACON_NOTIFY, data);
}
tr_debug("Beacon Notify: %s", trace_array(data->beacon_data, data->beacon_data_length));
if (rf_mac_setup->mac_mlme_scan_resp) {
mlme_scan_conf_t *conf = rf_mac_setup->mac_mlme_scan_resp;
update_beacon = add_or_update_beacon(conf, data, rf_mac_setup->fhss_api);

View File

@ -65,11 +65,6 @@ int8_t mac_mlme_get_req(struct protocol_interface_rf_mac_setup *rf_mac_setup, st
void mac_extended_mac_set(struct protocol_interface_rf_mac_setup *rf_mac_setup, const uint8_t *mac64);
uint32_t mac_mlme_framecounter_get(struct protocol_interface_rf_mac_setup *rf_mac_setup);
void mac_mlme_framecounter_increment(struct protocol_interface_rf_mac_setup *rf_mac_setup);
void mac_mlme_framecounter_decrement(struct protocol_interface_rf_mac_setup *rf_mac_setup);
/**
* MLME Poll Request
*

View File

@ -387,14 +387,6 @@ static void mac_sap_no_ack_cb(protocol_interface_rf_mac_setup_s *rf_ptr)
}
}
static bool mac_data_counter_too_small(uint32_t current_counter, uint32_t packet_counter)
{
if ((current_counter - packet_counter) >= 2) {
return true;
}
return false;
}
static bool mac_data_asynch_channel_switch(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *active_buf)
{
@ -420,13 +412,7 @@ static void mac_data_ack_tx_finish(protocol_interface_rf_mac_setup_s *rf_ptr)
}
if (rf_ptr->active_pd_data_request) {
if (rf_ptr->active_pd_data_request->fcf_dsn.securityEnabled) {
uint32_t current_counter = mac_mlme_framecounter_get(rf_ptr);
if (mac_data_counter_too_small(current_counter, rf_ptr->active_pd_data_request->aux_header.frameCounter)) {
rf_ptr->active_pd_data_request->aux_header.frameCounter = current_counter;
mac_mlme_framecounter_increment(rf_ptr);
}
}
mcps_pending_packet_counter_update_check(rf_ptr, rf_ptr->active_pd_data_request);
//GEN TX failure
mac_sap_cca_fail_cb(rf_ptr);
}

View File

@ -19,6 +19,7 @@
#include "ns_types.h"
#include "ns_trace.h"
#include "nsdynmemLIB.h"
#include "platform/arm_hal_interrupt.h"
#include "mac_api.h"
#include "sw_mac.h"
#include "mac_common_defines.h"
@ -78,6 +79,42 @@ static mlme_key_id_lookup_descriptor_t *mac_sec_mib_key_lookup_table_allocate(ui
return table_ptr;
}
static int mac_sec_mib_frame_counter_key_buffer_allocate(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint16_t list_size, uint16_t device_count)
{
rf_mac_setup->key_device_frame_counter_list_buffer = ns_dyn_mem_alloc(sizeof(uint32_t) * list_size * device_count);
if (!rf_mac_setup->key_device_frame_counter_list_buffer) {
return -1;
}
memset(rf_mac_setup->key_device_frame_counter_list_buffer, 0, (sizeof(uint32_t) * list_size * device_count));
rf_mac_setup->secFrameCounterPerKey = true;
mlme_key_descriptor_t *key_descriptor_list = rf_mac_setup->key_description_table;
uint32_t *frame_counter_pointer = rf_mac_setup->key_device_frame_counter_list_buffer;
for (uint8_t i = 0; i < rf_mac_setup->key_description_table_size; i++) {
key_descriptor_list->KeyDeviceFrameCouterList = frame_counter_pointer;
key_descriptor_list->KeyFrameCounterPerKey = true;
key_descriptor_list->KeyFrameCounter = 0;
//Update Pointers
key_descriptor_list++;
frame_counter_pointer += device_count;
}
return 0;
}
static void mac_sec_mib_frame_counter_key_buffer_free(protocol_interface_rf_mac_setup_s *rf_mac_setup)
{
mlme_key_descriptor_t *key_descriptor_list = rf_mac_setup->key_description_table;
for (uint8_t i = 0; i < rf_mac_setup->key_description_table_size; i++) {
key_descriptor_list->KeyDeviceFrameCouterList = NULL;
key_descriptor_list->KeyFrameCounterPerKey = false;
//Update Pointers
key_descriptor_list++;
}
ns_dyn_mem_free(rf_mac_setup->key_device_frame_counter_list_buffer);
rf_mac_setup->key_device_frame_counter_list_buffer = NULL;
rf_mac_setup->secFrameCounterPerKey = false;
}
static mlme_device_descriptor_t *mac_sec_mib_device_description_get_by_mac16(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint16_t mac16)
{
@ -134,6 +171,11 @@ static void mac_sec_mib_key_device_description_remove_from_list(mlme_key_descrip
if (removed_entry) {
key_descpription_table->KeyDeviceListEntries--;
//Clear Also frame counter per key if it its enabled
if (key_descpription_table->KeyFrameCounterPerKey) {
//SET frame counter to 0
mac_sec_mib_key_device_frame_counter_set(key_descpription_table, NULL, 0, device_descriptor_handle);
}
}
}
@ -234,7 +276,6 @@ int8_t mac_sec_mib_device_description_set(uint8_t atribute_index, mlme_device_de
//validate index to list size
if (!rf_mac_setup || !device_descriptor || atribute_index >= rf_mac_setup->device_description_table_size) {
tr_debug("Too many Devices");
return -1;
}
@ -302,6 +343,17 @@ int8_t mac_sec_mib_key_description_set(uint8_t atribute_index, mlme_key_descript
memcpy(key_ptr->KeyUsageList, key_descriptor->KeyUsageList, sizeof(mlme_key_usage_descriptor_t) * key_ptr->KeyUsageListEntries);
}
if (key_ptr->KeyFrameCounterPerKey) {
key_ptr->KeyFrameCounter = 0;
if (key_ptr->KeyDeviceListEntries == 0) {
//Clear all frame counters from old possible user's
uint32_t *counter_ptr = key_ptr->KeyDeviceFrameCouterList;
for (int i = 0; i < rf_mac_setup->device_description_table_size; i++) {
*counter_ptr++ = 0;
}
}
}
return 0;
}
@ -414,6 +466,17 @@ mlme_key_descriptor_t *mac_sec_key_description_get(protocol_interface_rf_mac_set
return NULL;
}
mlme_key_descriptor_t *mac_sec_key_description_get_by_attribute(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint8_t atribute_index)
{
//validate index to list size
if (atribute_index >= rf_mac_setup->key_description_table_size) {
return NULL;
}
return rf_mac_setup->key_description_table + atribute_index;
}
int8_t mac_sec_mib_init(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_description_storage_size_t *storage_sizes)
{
@ -434,16 +497,102 @@ int8_t mac_sec_mib_init(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_des
return 0;
}
int8_t mac_sec_mib_frame_counter_per_key_set(protocol_interface_rf_mac_setup_s *rf_mac_setup, bool enabled)
{
if (enabled) {
if (rf_mac_setup->key_device_frame_counter_list_buffer) {
return 0;
}
return mac_sec_mib_frame_counter_key_buffer_allocate(rf_mac_setup, rf_mac_setup->key_description_table_size, rf_mac_setup->device_description_table_size);
}
//Clear Key Descriptors
//Free current list
mac_sec_mib_frame_counter_key_buffer_free(rf_mac_setup);
return 0;
}
void mac_sec_mib_deinit(protocol_interface_rf_mac_setup_s *rf_mac_setup)
{
if (!rf_mac_setup) {
return;
}
mac_sec_mib_frame_counter_key_buffer_free(rf_mac_setup);
mac_sec_mib_device_description_table_deinit(rf_mac_setup);
mac_sec_mib_key_description_table_deinit(rf_mac_setup);
}
uint32_t mac_sec_mib_key_outgoing_frame_counter_get(protocol_interface_rf_mac_setup_s *rf_mac_setup, mlme_key_descriptor_t *key_descpription)
{
uint32_t value;
platform_enter_critical();
if (key_descpription && key_descpription->KeyFrameCounterPerKey) {
value = key_descpription->KeyFrameCounter;
} else {
value = rf_mac_setup->security_frame_counter;
}
platform_exit_critical();
return value;
}
void mac_sec_mib_key_outgoing_frame_counter_set(protocol_interface_rf_mac_setup_s *rf_mac_setup, mlme_key_descriptor_t *key_descpription, uint32_t value)
{
platform_enter_critical();
if (key_descpription && key_descpription->KeyFrameCounterPerKey) {
key_descpription->KeyFrameCounter = value;
} else {
rf_mac_setup->security_frame_counter = value;
}
platform_exit_critical();
}
void mac_sec_mib_key_outgoing_frame_counter_increment(struct protocol_interface_rf_mac_setup *rf_mac_setup, mlme_key_descriptor_t *key_descpription)
{
platform_enter_critical();
if (key_descpription && key_descpription->KeyFrameCounterPerKey) {
key_descpription->KeyFrameCounter++;
} else {
rf_mac_setup->security_frame_counter++;
}
platform_exit_critical();
}
void mac_sec_mib_key_outgoing_frame_counter_decrement(struct protocol_interface_rf_mac_setup *rf_mac_setup, mlme_key_descriptor_t *key_descpription)
{
platform_enter_critical();
if (key_descpription && key_descpription->KeyFrameCounterPerKey) {
key_descpription->KeyFrameCounter--;
} else {
rf_mac_setup->security_frame_counter--;
}
platform_exit_critical();
}
void mac_sec_mib_key_device_frame_counter_set(mlme_key_descriptor_t *key_descpription_table, mlme_device_descriptor_t *device_info, uint32_t frame_counter, uint8_t attribute_index)
{
if (key_descpription_table->KeyFrameCounterPerKey) {
uint32_t *counter_ptr = key_descpription_table->KeyDeviceFrameCouterList + attribute_index;
*counter_ptr = frame_counter;
} else {
device_info->FrameCounter = frame_counter;
}
}
uint32_t mac_mib_key_device_frame_counter_get(mlme_key_descriptor_t *key_descpription_table, mlme_device_descriptor_t *device_info, uint8_t attribute_index)
{
if (key_descpription_table->KeyFrameCounterPerKey) {
uint32_t *counter_ptr = key_descpription_table->KeyDeviceFrameCouterList + attribute_index;
return *counter_ptr;
}
return device_info->FrameCounter;
}
//allocate new entry and update entries size
mlme_key_device_descriptor_t *mac_sec_mib_key_device_description_list_update(mlme_key_descriptor_t *key_descpription_table)
{
@ -477,7 +626,6 @@ mlme_key_device_descriptor_t *mac_sec_mib_key_device_description_discover_from_l
void mac_sec_mib_device_description_blacklist(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint8_t device_handle)
{
if (!rf_mac_setup) {
return;
}
@ -485,7 +633,6 @@ void mac_sec_mib_device_description_blacklist(protocol_interface_rf_mac_setup_s
for (uint8_t i = 0; i < rf_mac_setup->key_description_table_size; i++) {
descriptor = mac_sec_mib_key_device_description_discover_from_list(&rf_mac_setup->key_description_table[i], device_handle);
if (descriptor) {
tr_debug("Black listed device %u", device_handle);
descriptor->Blacklisted = true;
}

View File

@ -25,21 +25,26 @@ struct mac_description_storage_size_s;
typedef struct mlme_key_descriptor_s {
mlme_key_id_lookup_descriptor_t *KeyIdLookupList;
uint8_t KeyIdLookupListEntries;
mlme_key_device_descriptor_t *KeyDeviceList;
mlme_key_usage_descriptor_t *KeyUsageList;
uint32_t *KeyDeviceFrameCouterList;
uint32_t KeyFrameCounter;
uint8_t Key[16];
uint8_t KeyDeviceListSize;
uint8_t KeyDeviceListEntries;
mlme_key_usage_descriptor_t *KeyUsageList;
uint8_t KeyIdLookupListEntries;
uint8_t KeyUsageListEntries;
uint8_t KeyUsageListSize;
uint8_t Key[16];
bool unique_key_descriptor;
bool unique_key_descriptor: 1;
bool KeyFrameCounterPerKey: 1;
} mlme_key_descriptor_t;
int8_t mac_sec_mib_init(struct protocol_interface_rf_mac_setup *rf_mac_setup, struct mac_description_storage_size_s *storage_sizes);
void mac_sec_mib_deinit(struct protocol_interface_rf_mac_setup *rf_mac_setup);
int8_t mac_sec_mib_frame_counter_per_key_set(struct protocol_interface_rf_mac_setup *rf_mac_setup, bool enabled);
int8_t mac_sec_mib_device_description_set(uint8_t atribute_index, mlme_device_descriptor_t *device_descriptor, struct protocol_interface_rf_mac_setup *rf_mac_setup);
int8_t mac_sec_mib_key_description_set(uint8_t atribute_index, mlme_key_descriptor_entry_t *key_descriptor, struct protocol_interface_rf_mac_setup *rf_mac_setup);
@ -52,10 +57,24 @@ uint8_t mac_mib_device_descption_attribute_get_by_descriptor(struct protocol_int
mlme_key_descriptor_t *mac_sec_key_description_get(struct protocol_interface_rf_mac_setup *rf_mac_setup, mlme_security_t *key_source, uint8_t address_mode, uint8_t *address_ptr, uint16_t pan_id);
mlme_key_descriptor_t *mac_sec_key_description_get_by_attribute(struct protocol_interface_rf_mac_setup *rf_mac_setup, uint8_t atribute_index);
mlme_key_device_descriptor_t *mac_sec_mib_key_device_description_list_update(mlme_key_descriptor_t *key_descpription_table);
mlme_key_device_descriptor_t *mac_sec_mib_key_device_description_discover_from_list(mlme_key_descriptor_t *key_descpription_table, uint8_t device_descriptor_handle);
void mac_sec_mib_device_description_blacklist(struct protocol_interface_rf_mac_setup *rf_mac_setup, uint8_t device_handle);
void mac_sec_mib_key_device_frame_counter_set(mlme_key_descriptor_t *key_descpription_table, mlme_device_descriptor_t *device_info, uint32_t frame_counter, uint8_t attribute_index);
uint32_t mac_mib_key_device_frame_counter_get(mlme_key_descriptor_t *key_descpription_table, mlme_device_descriptor_t *device_info, uint8_t attribute_index);
uint32_t mac_sec_mib_key_outgoing_frame_counter_get(struct protocol_interface_rf_mac_setup *rf_mac_setup, mlme_key_descriptor_t *key_descpription);
void mac_sec_mib_key_outgoing_frame_counter_set(struct protocol_interface_rf_mac_setup *rf_mac_setup, mlme_key_descriptor_t *key_descpription, uint32_t value);
void mac_sec_mib_key_outgoing_frame_counter_increment(struct protocol_interface_rf_mac_setup *rf_mac_setup, mlme_key_descriptor_t *key_descpription);
void mac_sec_mib_key_outgoing_frame_counter_decrement(struct protocol_interface_rf_mac_setup *rf_mac_setup, mlme_key_descriptor_t *key_descpription);
#endif /* MAC_SECURITY_MIB_H_ */

View File

@ -25,6 +25,7 @@
#include "MAC/IEEE802_15_4/mac_defines.h"
#include "MAC/IEEE802_15_4/mac_mcps_sap.h"
#include "MAC/IEEE802_15_4/mac_pd_sap.h"
#include "MAC/IEEE802_15_4/mac_security_mib.h"
#include "MAC/rf_driver_storage.h"
#include "MAC/virtual_rf/virtual_rf_defines.h"
#include "mac_fhss_callbacks.h"
@ -123,6 +124,14 @@ mac_api_t *ns_sw_mac_create(int8_t rf_driver_id, mac_description_storage_size_t
return this;
}
int8_t ns_sw_mac_enable_frame_counter_per_key(struct mac_api_s *mac_api_s, bool enable_feature)
{
if (!mac_api_s || mac_api_s != mac_store.mac_api) {
return -1;
}
return mac_sec_mib_frame_counter_per_key_set(mac_store.setup, enable_feature);
}
int8_t ns_sw_mac_virtual_client_register(mac_api_t *api, int8_t virtual_driver_id)
{
if (!api || api != mac_store.mac_api) {

View File

@ -176,6 +176,21 @@ void rpl_control_request_parent_link_confirmation(bool requested)
rpl_policy_set_parent_confirmation_request(requested);
}
void rpl_control_set_dio_multicast_min_config_advertisment_count(uint8_t min_count)
{
rpl_policy_set_dio_multicast_config_advertisment_min_count(min_count);
}
void rpl_control_set_dao_retry_count(uint8_t count)
{
rpl_policy_set_dao_retry_count(count);
}
void rpl_control_set_initial_dao_ack_wait(uint16_t timeout_in_ms)
{
rpl_policy_set_initial_dao_ack_wait(timeout_in_ms);
}
/* Send address registration to either specified address, or to non-registered address */
void rpl_control_register_address(protocol_interface_info_entry_t *interface, const uint8_t addr[16])
{
@ -340,16 +355,24 @@ void rpl_control_delete_domain(rpl_domain_t *domain)
rpl_free(domain, sizeof * domain);
}
static void rpl_control_remove_interface_from_domain(protocol_interface_info_entry_t *cur, rpl_domain_t *domain)
static void rpl_control_remove_interface_from_domain(protocol_interface_info_entry_t *cur, rpl_domain_t *domain, bool free_instances)
{
ns_list_foreach(rpl_instance_t, instance, &domain->instances) {
rpl_instance_remove_interface(instance, cur->id);
}
ns_list_foreach(if_address_entry_t, addr, &cur->ip_addresses) {
if (!addr_is_ipv6_link_local(addr->address)) {
rpl_control_unpublish_address(domain, addr->address);
}
}
if (free_instances) {
ns_list_foreach_safe(rpl_instance_t, instance, &domain->instances) {
rpl_delete_instance(instance);
}
}
if (domain->non_storing_downstream_interface == cur->id) {
domain->non_storing_downstream_interface = -1;
}
@ -374,7 +397,16 @@ void rpl_control_set_domain_on_interface(protocol_interface_info_entry_t *cur, r
void rpl_control_remove_domain_from_interface(protocol_interface_info_entry_t *cur)
{
if (cur->rpl_domain) {
rpl_control_remove_interface_from_domain(cur, cur->rpl_domain);
rpl_control_remove_interface_from_domain(cur, cur->rpl_domain, false);
addr_delete_group(cur, ADDR_LINK_LOCAL_ALL_RPL_NODES);
cur->rpl_domain = NULL;
}
}
void rpl_control_free_domain_instances_from_interface(protocol_interface_info_entry_t *cur)
{
if (cur->rpl_domain) {
rpl_control_remove_interface_from_domain(cur, cur->rpl_domain, true);
addr_delete_group(cur, ADDR_LINK_LOCAL_ALL_RPL_NODES);
cur->rpl_domain = NULL;
}
@ -1368,6 +1400,7 @@ void rpl_control_transmit_dis(rpl_domain_t *domain, protocol_interface_info_entr
buffer_data_end_set(buf, ptr);
rpl_control_transmit(domain, cur, ICMPV6_CODE_RPL_DIS, buf, dst);
tr_info("Transmit DIS");
}
#ifdef HAVE_RPL_DAO_HANDLING

View File

@ -145,6 +145,7 @@ rpl_domain_t *rpl_control_create_domain(void);
void rpl_control_delete_domain(rpl_domain_t *domain);
void rpl_control_set_domain_on_interface(struct protocol_interface_info_entry *cur, rpl_domain_t *domain, bool downstream);
void rpl_control_remove_domain_from_interface(struct protocol_interface_info_entry *cur);
void rpl_control_free_domain_instances_from_interface(struct protocol_interface_info_entry *cur);
void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, rpl_new_parent_callback_t new_parent_add, void *cb_handle);
/* Target publishing */
@ -156,6 +157,9 @@ uint16_t rpl_control_parent_candidate_list_size(struct protocol_interface_info_e
void rpl_control_neighbor_delete(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16]);
/* Parent link confirmation API extension */
void rpl_control_request_parent_link_confirmation(bool requested);
void rpl_control_set_dio_multicast_min_config_advertisment_count(uint8_t min_count);
void rpl_control_set_dao_retry_count(uint8_t count);
void rpl_control_set_initial_dao_ack_wait(uint16_t timeout_in_ms);
void rpl_control_register_address(struct protocol_interface_info_entry *interface, const uint8_t addr[16]);
void rpl_control_address_register_done(struct protocol_interface_info_entry *interface, const uint8_t ll_addr[16], uint8_t status);
@ -178,6 +182,7 @@ uint16_t rpl_control_current_rank(const struct rpl_instance *instance);
#define rpl_control_fast_timer(ticks) ((void) 0)
#define rpl_control_slow_timer(seconds) ((void) 0)
#define rpl_control_remove_domain_from_interface(cur) ((void) 0)
#define rpl_control_free_domain_instances_from_interface(cur) ((void) 0)
#define rpl_control_register_address(interface, addr) ((void) 0)
#define rpl_control_address_register_done(interface, ll_addr, status) ((void) 0)

View File

@ -712,6 +712,21 @@ void rpl_instance_send_dao_update(rpl_instance_t *instance)
return;
}
if (rpl_policy_dao_retry_count() > 0 && instance->dao_attempt >= rpl_policy_dao_retry_count()) {
// Check if recovery logic is started
// after half the retries are done we remove the primary parent
tr_info("DAO remove primary parent");
rpl_neighbour_t *neighbour = ns_list_get_first(&instance->candidate_neighbours);
if (neighbour) {
rpl_delete_neighbour(instance, neighbour);
}
// Set parameters to restart
instance->dao_in_transit = false;
instance->dao_attempt = 0;
instance->dao_retry_timer = 0;
instance->delay_dao_timer = 0;
return;
}
/* Which parent this DAO will be for if storing */
rpl_neighbour_t *parent = NULL;
@ -847,6 +862,15 @@ void rpl_instance_send_dao_update(rpl_instance_t *instance)
cur = NULL;
}
if (instance->dao_attempt > 0) {
// Start informing problem in routing. This will cause us to select secondary routes when sending the DAO
tr_info("DAO reachability problem");
protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_rpl_domain(instance->domain, -1);
if (interface) {
ipv6_neighbour_reachability_problem(dst, interface->id);
}
}
bool need_ack = rpl_control_transmit_dao(instance->domain, cur, instance, instance->id, instance->dao_sequence, dodag->id, opts, ptr - opts, dst);
ns_dyn_mem_free(opts);
@ -1859,7 +1883,7 @@ void rpl_instance_address_registration_done(protocol_interface_info_entry_t *int
if (status == SOCKET_TX_DONE) {
/* State_timer is 1/10 s. Set renewal to 75-85% of lifetime */
if_address_entry_t *address = rpl_interface_addr_get(interface, dao_target->prefix);
if (address) {
if (address && address->source != ADDR_SOURCE_DHCP) {
address->state_timer = (address->preferred_lifetime * randLIB_get_random_in_range(75, 85) / 10);
}
neighbour->confirmed = true;

View File

@ -35,6 +35,11 @@
#define TRACE_GROUP "RPLy"
static bool rpl_policy_parent_confirmation_req = false;
static int8_t rpl_policy_dao_retry_count_conf = 0;
static int16_t rpl_policy_dao_initial_timeout_conf = 20; // Default is 2 seconds 100ms ticks
static uint16_t rpl_policy_dio_validity_period_hysteresis = 0x0180; //Fixed Point 1.5
static uint8_t rpl_policy_multicast_config_min_advertisment_count = 0;
/* TODO - application API to control when to join new instances / DODAGs
*
@ -105,6 +110,11 @@ bool rpl_policy_request_dao_acks(const rpl_domain_t *domain, uint8_t mop)
return true;
}
void rpl_policy_set_initial_dao_ack_wait(uint16_t timeout_in_ms)
{
rpl_policy_dao_initial_timeout_conf = timeout_in_ms;
}
uint16_t rpl_policy_initial_dao_ack_wait(const rpl_domain_t *domain, uint8_t mop)
{
(void)mop;
@ -120,7 +130,18 @@ uint16_t rpl_policy_initial_dao_ack_wait(const rpl_domain_t *domain, uint8_t mop
}
}
return 20; /* *100ms ticks = 2s */
return rpl_policy_dao_initial_timeout_conf;
}
void rpl_policy_set_dao_retry_count(uint8_t count)
{
rpl_policy_dao_retry_count_conf = count;
}
int8_t rpl_policy_dao_retry_count()
{
return rpl_policy_dao_retry_count_conf;
}
/* Given the next-hop address from a source routing header, which interface,
@ -192,6 +213,20 @@ uint16_t rpl_policy_etx_hysteresis(rpl_domain_t *domain)
return 0x0080; /* 8.8 fixed-point, so 0.5 */
}
uint16_t rpl_policy_dio_validity_period(rpl_domain_t *domain)
{
(void)domain;
return rpl_policy_dio_validity_period_hysteresis; /* Fixed Point */
}
void rpl_policy_set_dio_validity_period(rpl_domain_t *domain, uint16_t fixed_point)
{
(void)domain;
rpl_policy_dio_validity_period_hysteresis = fixed_point; /* Fixed Point */
}
uint16_t rpl_policy_etx_change_parent_selection_delay(rpl_domain_t *domain)
{
(void)domain;
@ -331,6 +366,16 @@ bool rpl_policy_parent_confirmation_requested(void)
return rpl_policy_parent_confirmation_req;
}
uint8_t rpl_policy_dio_multicast_config_advertisment_min_count(void)
{
return rpl_policy_multicast_config_min_advertisment_count;
}
void rpl_policy_set_dio_multicast_config_advertisment_min_count(uint8_t min_count)
{
rpl_policy_multicast_config_min_advertisment_count = min_count;
}
#ifdef RPL_STRUCTURES_H_
#error "rpl_structures.h should not be included by rpl_policy.c"

View File

@ -27,11 +27,20 @@ bool rpl_policy_join_config(rpl_domain_t *domain, const rpl_dodag_conf_t *conf,
bool rpl_policy_request_dao_acks(const rpl_domain_t *domain, uint8_t mop);
uint16_t rpl_policy_initial_dao_ack_wait(const rpl_domain_t *domain, uint8_t mop);
void rpl_policy_set_initial_dao_ack_wait(uint16_t timeout_in_ms);
void rpl_policy_set_dao_retry_count(uint8_t count);
int8_t rpl_policy_dao_retry_count();
int8_t rpl_policy_srh_next_hop_interface(rpl_domain_t *domain, int8_t if_id, const uint8_t *next_hop);
uint16_t rpl_policy_modify_downward_cost_to_root_neighbour(rpl_domain_t *domain, int8_t if_id, const uint8_t *next_hop, uint16_t cost);
uint16_t rpl_policy_parent_selection_period(rpl_domain_t *domain);
uint16_t rpl_policy_etx_hysteresis(rpl_domain_t *domain);
//Return Fixed point multiple which base 1.0 is 0x0100
uint16_t rpl_policy_dio_validity_period(rpl_domain_t *domain);
//Fixed point must 1.0 is 0x0100
void rpl_policy_set_dio_validity_period(rpl_domain_t *domain, uint16_t fixed_point);
uint16_t rpl_policy_etx_change_parent_selection_delay(rpl_domain_t *domain);
uint16_t rpl_policy_dio_parent_selection_delay(rpl_domain_t *domain);
@ -56,5 +65,7 @@ uint16_t rpl_policy_mrhof_parent_switch_threshold(const rpl_domain_t *domain);
uint16_t rpl_policy_mrhof_max_rank_stretch_for_extra_parents(const rpl_domain_t *domain);
bool rpl_policy_parent_confirmation_requested(void);
void rpl_policy_set_parent_confirmation_request(bool confirmation_requested);
uint8_t rpl_policy_dio_multicast_config_advertisment_min_count(void);
void rpl_policy_set_dio_multicast_config_advertisment_min_count(uint8_t min_count);
#endif /* RPL_POLICY_H_ */

View File

@ -90,6 +90,7 @@ struct rpl_dodag {
bool leaf: 1; /* We are a leaf in this DODAG (by policy) */
bool have_config: 1; /* We have the config */
bool used: 1; /* We have ever been a member of this DODAG? */
uint8_t new_config_advertisment_count; /* We have advertiment new config at multicasti DIO */
NS_LIST_HEAD(rpl_dodag_version_t, link) versions; /* List of DODAG versions (newest first) */
prefix_list_t prefixes; /* Prefixes advertised in DIO PIOs */
rpl_dio_route_list_t routes; /* Routes advertised in DIO RIOs*/

View File

@ -635,6 +635,7 @@ rpl_dodag_t *rpl_create_dodag(rpl_instance_t *instance, const uint8_t *dodagid,
dodag->have_config = false;
dodag->used = false;
dodag->g_mop_prf = g_mop_prf;
dodag->new_config_advertisment_count = 0;
// Default timer parameters and trickle start should never normally
// be used - we would set the parameters from the DODAG Config and start
// as we join a version. But initialising here catches odd cases where
@ -728,6 +729,7 @@ bool rpl_dodag_update_config(rpl_dodag_t *dodag, const rpl_dodag_conf_t *conf, c
/* They've changed the timing parameters for our currently-in-use trickle timer! */
tr_warn("Trickle parameters changed");
trickle_start(&dodag->instance->dio_timer, &dodag->dio_timer_params);
dodag->new_config_advertisment_count = 0;
}
dodag->instance->of = rpl_objective_lookup(conf->objective_code_point);
/* We could be a leaf of an unknown OCP. Still need an OF to choose parents */
@ -1355,6 +1357,11 @@ static void trace_info_print(const char *fmt, ...)
va_end(ap);
}
static uint32_t rpl_dio_imax_time_calculate(uint16_t Imax, uint16_t fixed_point)
{
return (((uint32_t)Imax * fixed_point) / 0x0100);
}
void rpl_instance_run_parent_selection(rpl_instance_t *instance)
{
@ -1438,6 +1445,15 @@ void rpl_instance_run_parent_selection(rpl_instance_t *instance)
if (preferred_parent) {
// Always stop repair if we find a parent
rpl_instance_set_local_repair(instance, false);
//Validate time from last DIO
uint32_t time_between_parent = protocol_core_monotonic_time - preferred_parent->dio_timestamp;
uint32_t accepted_time = rpl_dio_imax_time_calculate(instance->current_dodag_version->dodag->dio_timer_params.Imax, rpl_policy_dio_validity_period(instance->domain));
if (accepted_time < time_between_parent) {
rpl_control_transmit_dis(instance->domain, NULL, RPL_SOLINFO_PRED_INSTANCEID, instance->id, NULL, 0, preferred_parent->ll_address);
}
} else if (original_preferred) {
// Only start repair if we just lost a parent
rpl_instance_set_local_repair(instance, true);
@ -1533,7 +1549,15 @@ void rpl_instance_dio_trigger(rpl_instance_t *instance, protocol_interface_info_
}
// Always send config in unicasts (as required), never in multicasts (optional)
rpl_dodag_conf_t *conf = addr ? &dodag->config : NULL;
rpl_dodag_conf_t *conf;
if (addr) {
conf = &dodag->config;
} else if (dodag->new_config_advertisment_count < rpl_policy_dio_multicast_config_advertisment_min_count()) {
conf = &dodag->config;
dodag->new_config_advertisment_count++;
} else {
conf = NULL;
}
rpl_control_transmit_dio(instance->domain, cur, instance->id, dodag_version->number, rank, dodag->g_mop_prf, instance->dtsn, dodag, dodag->id, conf, addr);
@ -1921,7 +1945,7 @@ bool rpl_upward_accept_prefix_update(const rpl_dodag_t *dodag_info, const rpl_ne
//Calculate Time between from last dio from parent and this neighbour
//neighbour dio_timestamp >= pref_parent's, because it's a newly-received message
uint32_t time_between_parent = neighbour->dio_timestamp - pref_parent->dio_timestamp;
uint32_t accepted_time = (uint32_t)dodag_info->dio_timer_params.Imax * 2;
uint32_t accepted_time = rpl_dio_imax_time_calculate(dodag_info->dio_timer_params.Imax, 0x0200);
//Accept prefix Update If Time from last DIO is more than 2 x Max
if (accepted_time < time_between_parent) {
return true;

View File

@ -314,6 +314,11 @@ 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;
}
kmp_type_e kmp_api_type_from_id_get(uint8_t kmp_id)
{
switch (kmp_id) {

View File

@ -152,6 +152,16 @@ void kmp_api_delete(kmp_api_t *kmp);
*/
kmp_type_e kmp_api_type_get(kmp_api_t *kmp);
/**
* kmp_api_type_get get receive disabled status
*
* \param kmp instance
*
* \return true/false true when receiving has been disabled
*
*/
bool kmp_api_receive_disable(kmp_api_t *kmp);
/**
* kmp_api_type_from_id_get get KMP type from KMP id
*

View File

@ -98,7 +98,7 @@ static int8_t auth_eap_tls_sec_prot_message_handle(sec_prot_t *prot);
static int8_t auth_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_code, uint8_t eap_type, uint8_t tls_state);
static void auth_eap_tls_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks);
static void auth_eap_tls_sec_prot_init_tls(sec_prot_t *prot);
static int8_t auth_eap_tls_sec_prot_init_tls(sec_prot_t *prot);
static void auth_eap_tls_sec_prot_delete_tls(sec_prot_t *prot);
static void auth_eap_tls_sec_prot_seq_id_update(sec_prot_t *prot);
@ -348,16 +348,16 @@ static int8_t auth_eap_tls_sec_prot_tls_send(sec_prot_t *tls_prot, void *pdu, ui
return 0;
}
static void auth_eap_tls_sec_prot_init_tls(sec_prot_t *prot)
static int8_t auth_eap_tls_sec_prot_init_tls(sec_prot_t *prot)
{
eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
if (data->tls_prot) {
return;
return 0;
}
data->tls_prot = prot->type_get(prot, SEC_PROT_TYPE_TLS);
if (!data->tls_prot) {
return;
return -1;
}
data->tls_prot->header_size = TLS_HEAD_LEN;
@ -369,6 +369,8 @@ static void auth_eap_tls_sec_prot_init_tls(sec_prot_t *prot)
data->tls_prot->send = auth_eap_tls_sec_prot_tls_send;
data->tls_ongoing = true;
return 0;
}
static void auth_eap_tls_sec_prot_delete_tls(sec_prot_t *prot)
@ -388,14 +390,17 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
// EAP-TLS authenticator state machine
switch (sec_prot_state_get(&data->common)) {
case EAP_TLS_STATE_INIT:
tr_info("EAP-TLS init");
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_CREATE_REQ);
prot->timer_start(prot);
break;
// Wait KMP-CREATE.request
case EAP_TLS_STATE_CREATE_REQ:
tr_info("EAP-TLS start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
prot->timer_start(prot);
// Set default timeout for the total maximum length of the negotiation
sec_prot_default_timeout_set(&data->common);
// KMP-CREATE.confirm
prot->create_conf(prot, SEC_RESULT_OK);
@ -469,8 +474,11 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
// All fragments received for a message
if (result == EAP_TLS_MSG_RECEIVE_DONE) {
auth_eap_tls_sec_prot_init_tls(prot);
// Initialize TLS protocol
if (auth_eap_tls_sec_prot_init_tls(prot) < 0) {
tr_error("TLS init failed");
return;
}
if (data->tls_ongoing) {
// Call TLS
data->tls_prot->receive(data->tls_prot, data->tls_recv.data, data->tls_recv.total_len);
@ -538,12 +546,14 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_FINISHED);
break;
case EAP_TLS_STATE_FINISHED:
case EAP_TLS_STATE_FINISHED: {
uint8_t *remote_eui_64 = sec_prot_remote_eui_64_addr_get(prot);
tr_info("EAP-TLS finished, eui-64: %s", remote_eui_64 ? trace_array(sec_prot_remote_eui_64_addr_get(prot), 8) : "not set");
auth_eap_tls_sec_prot_delete_tls(prot);
prot->timer_stop(prot);
prot->finished(prot);
break;
}
default:
break;
}

View File

@ -59,6 +59,23 @@ int8_t eap_tls_sec_prot_lib_message_allocate(tls_data_t *data, uint8_t head_len,
return 0;
}
int8_t eap_tls_sec_prot_lib_message_realloc(tls_data_t *data, uint8_t head_len, uint16_t new_len)
{
tls_data_t new_tls_send;
eap_tls_sec_prot_lib_message_init(&new_tls_send);
if (eap_tls_sec_prot_lib_message_allocate(&new_tls_send, head_len, new_len) < 0) {
return -1;
}
memcpy(new_tls_send.data + head_len, data->data + head_len, data->handled_len);
new_tls_send.handled_len = data->handled_len;
eap_tls_sec_prot_lib_message_free(data);
*data = new_tls_send;
return 0;
}
void eap_tls_sec_prot_lib_message_free(tls_data_t *data)
{
ns_dyn_mem_free(data->data);

View File

@ -72,6 +72,19 @@ extern const uint8_t eap_msg_trace[4][10];
*/
int8_t eap_tls_sec_prot_lib_message_allocate(tls_data_t *data, uint8_t head_len, uint16_t len);
/**
* eap_tls_sec_prot_lib_message_realloc allocates larger message buffer and copies existing data to it
*
* \param data data buffer which length is increased
* \param head_len header length
* \param new_len new length for the buffer
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t eap_tls_sec_prot_lib_message_realloc(tls_data_t *data, uint8_t head_len, uint16_t new_len);
/**
* eap_tls_sec_prot_lib_message_free free message buffer
*

View File

@ -90,7 +90,7 @@ static int8_t supp_eap_tls_sec_prot_message_handle(sec_prot_t *prot);
static int8_t supp_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_code, uint8_t eap_type, uint8_t tls_state);
static void supp_eap_tls_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks);
static void supp_eap_tls_sec_prot_init_tls(sec_prot_t *prot);
static int8_t supp_eap_tls_sec_prot_init_tls(sec_prot_t *prot);
static void supp_eap_tls_sec_prot_delete_tls(sec_prot_t *prot);
static void supp_eap_tls_sec_prot_seq_id_update(sec_prot_t *prot);
@ -360,16 +360,16 @@ static int8_t supp_eap_tls_sec_prot_tls_send(sec_prot_t *tls_prot, void *pdu, ui
return 0;
}
static void supp_eap_tls_sec_prot_init_tls(sec_prot_t *prot)
static int8_t supp_eap_tls_sec_prot_init_tls(sec_prot_t *prot)
{
eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);
if (data->tls_prot) {
return;
return 0;
}
data->tls_prot = prot->type_get(prot, SEC_PROT_TYPE_TLS);
if (!data->tls_prot) {
return;
return -1;
}
data->tls_prot->header_size = TLS_HEAD_LEN;
@ -381,6 +381,8 @@ static void supp_eap_tls_sec_prot_init_tls(sec_prot_t *prot)
data->tls_prot->send = supp_eap_tls_sec_prot_tls_send;
data->tls_ongoing = true;
return 0;
}
static void supp_eap_tls_sec_prot_delete_tls(sec_prot_t *prot)
@ -400,7 +402,9 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
// EAP-TLS supplicant state machine
switch (sec_prot_state_get(&data->common)) {
case EAP_TLS_STATE_INIT:
tr_info("EAP-TLS init");
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_REQUEST_ID);
prot->timer_start(prot);
break;
// Wait EAP request, Identity (starts handshake on supplicant)
@ -411,13 +415,14 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
return;
}
// Set default timeout for the total maximum length of the negotiation
sec_prot_default_timeout_set(&data->common);
// Store sequence ID
supp_eap_tls_sec_prot_seq_id_update(prot);
tr_info("EAP-TLS start");
prot->timer_start(prot);
// Send KMP-CREATE.indication
prot->create_ind(prot);
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_CREATE_RESP);
@ -459,7 +464,10 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
data->common.ticks = retry_timeout;
// Initialize TLS protocol
supp_eap_tls_sec_prot_init_tls(prot);
if (supp_eap_tls_sec_prot_init_tls(prot) < 0) {
tr_error("TLS init failed");
return;
}
// Request TLS to start (send client hello)
data->tls_prot->create_req(data->tls_prot, prot->sec_keys);
break;
@ -523,6 +531,7 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot)
break;
case EAP_TLS_STATE_FINISHED:
tr_info("EAP-TLS finished");
supp_eap_tls_sec_prot_delete_tls(prot);
prot->timer_stop(prot);
prot->finished(prot);

View File

@ -341,6 +341,7 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot)
// 4WH authenticator state machine
switch (sec_prot_state_get(&data->common)) {
case FWH_STATE_INIT:
tr_info("4WH: init");
prot->timer_start(prot);
sec_prot_state_set(prot, &data->common, FWH_STATE_CREATE_REQ);
break;
@ -349,6 +350,9 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot)
case FWH_STATE_CREATE_REQ:
tr_info("4WH: start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
// Set default timeout for the total maximum length of the negotiation
sec_prot_default_timeout_set(&data->common);
uint8_t *pmk = sec_prot_keys_pmk_get(prot->sec_keys);
if (!pmk) { // If PMK is not set fails
prot->create_conf(prot, SEC_RESULT_ERROR);
@ -429,10 +433,13 @@ static void auth_fwh_sec_prot_state_machine(sec_prot_t *prot)
sec_prot_state_set(prot, &data->common, FWH_STATE_FINISHED);
break;
case FWH_STATE_FINISHED:
case FWH_STATE_FINISHED: {
uint8_t *remote_eui_64 = sec_prot_remote_eui_64_addr_get(prot);
tr_info("4WH: finished, eui-64: %s", remote_eui_64 ? trace_array(sec_prot_remote_eui_64_addr_get(prot), 8) : "not set");
prot->timer_stop(prot);
prot->finished(prot);
break;
}
default:
break;

View File

@ -310,6 +310,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot)
// 4WH supplicant state machine
switch (sec_prot_state_get(&data->common)) {
case FWH_STATE_INIT:
tr_info("4WH: init");
prot->timer_start(prot);
sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_1);
break;
@ -325,6 +326,9 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot)
return;
}
// Set default timeout for the total maximum length of the negotiation
sec_prot_default_timeout_set(&data->common);
tr_info("4WH: start");
// Store authenticator nonce for check when 4WH Message 3 is received
@ -467,6 +471,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot)
break;
case FWH_STATE_FINISHED:
tr_info("4WH: finished");
prot->timer_stop(prot);
prot->finished(prot);
break;

View File

@ -293,14 +293,17 @@ static void auth_gkh_sec_prot_state_machine(sec_prot_t *prot)
// GKH authenticator state machine
switch (sec_prot_state_get(&data->common)) {
case GKH_STATE_INIT:
tr_info("GKH init");
sec_prot_state_set(prot, &data->common, GKH_STATE_CREATE_REQ);
prot->timer_start(prot);
break;
// Wait KMP-CREATE.request
case GKH_STATE_CREATE_REQ:
tr_info("GKH start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
prot->timer_start(prot);
// Set default timeout for the total maximum length of the negotiation
sec_prot_default_timeout_set(&data->common);
// KMP-CREATE.confirm
prot->create_conf(prot, SEC_RESULT_OK);
@ -340,10 +343,13 @@ static void auth_gkh_sec_prot_state_machine(sec_prot_t *prot)
sec_prot_state_set(prot, &data->common, GKH_STATE_FINISHED);
break;
case GKH_STATE_FINISHED:
case GKH_STATE_FINISHED: {
uint8_t *remote_eui_64 = sec_prot_remote_eui_64_addr_get(prot);
tr_info("GKH finished, eui-64: %s", remote_eui_64 ? trace_array(sec_prot_remote_eui_64_addr_get(prot), 8) : "not set");
prot->timer_stop(prot);
prot->finished(prot);
break;
}
default:
break;

View File

@ -230,7 +230,9 @@ static void supp_gkh_sec_prot_state_machine(sec_prot_t *prot)
// GKH supplicant state machine
switch (sec_prot_state_get(&data->common)) {
case GKH_STATE_INIT:
tr_info("GKH init");
sec_prot_state_set(prot, &data->common, GKH_STATE_MESSAGE_1);
prot->timer_start(prot);
break;
// Wait GKH message 1 (starts handshake on supplicant)
@ -243,11 +245,12 @@ static void supp_gkh_sec_prot_state_machine(sec_prot_t *prot)
return;
}
// Set default timeout for the total maximum length of the negotiation
sec_prot_default_timeout_set(&data->common);
supp_gkh_sec_prot_security_replay_counter_update(prot);
tr_debug("GKH start");
prot->timer_start(prot);
tr_info("GKH start");
// Send KMP-CREATE.indication
prot->create_ind(prot);
@ -267,7 +270,7 @@ static void supp_gkh_sec_prot_state_machine(sec_prot_t *prot)
break;
case GKH_STATE_FINISH:
tr_debug("GKH finish");
tr_info("GKH finish");
// KMP-FINISHED.indication,
prot->finished_ind(prot, sec_prot_result_get(&data->common), prot->sec_keys);
@ -275,6 +278,7 @@ static void supp_gkh_sec_prot_state_machine(sec_prot_t *prot)
break;
case GKH_STATE_FINISHED:
tr_info("GKH finished");
prot->timer_stop(prot);
prot->finished(prot);
break;

View File

@ -32,6 +32,10 @@
#define TRACE_GROUP "spce"
// Length for PEM coded certificate's begin and end certificate text strings
#define SEC_PROT_CERT_PEM_HEADER_FOOTER_LEN 52
#define SEC_PROT_CERT_PEM_HEADER_STR "-----BEGIN CERTIFICATE-----"
int8_t sec_prot_certs_init(sec_prot_certs_t *certs)
{
if (!certs) {
@ -41,6 +45,8 @@ int8_t sec_prot_certs_init(sec_prot_certs_t *certs)
sec_prot_certs_chain_entry_init(&certs->own_cert_chain);
ns_list_init(&certs->trusted_cert_chain_list);
ns_list_init(&certs->cert_revocat_lists);
certs->own_cert_chain_len = 0;
certs->ext_cert_valid_enabled = false;
return 0;
}
@ -56,6 +62,27 @@ void sec_prot_certs_delete(sec_prot_certs_t *certs)
sec_prot_certs_revocat_lists_delete(&certs->cert_revocat_lists);
}
int8_t sec_prot_certs_ext_certificate_validation_set(sec_prot_certs_t *certs, bool enabled)
{
if (!certs) {
return -1;
}
certs->ext_cert_valid_enabled = enabled;
return 0;
}
bool sec_prot_certs_ext_certificate_validation_get(const sec_prot_certs_t *certs)
{
return certs->ext_cert_valid_enabled;
}
uint16_t sec_prot_certs_own_cert_chain_len_get(const sec_prot_certs_t *certs)
{
return certs->own_cert_chain_len;
}
cert_chain_entry_t *sec_prot_certs_chain_entry_create(void)
{
cert_chain_entry_t *entry = ns_dyn_mem_alloc(sizeof(cert_chain_entry_t));
@ -98,6 +125,28 @@ uint8_t *sec_prot_certs_cert_get(const cert_chain_entry_t *entry, uint8_t index,
return entry->cert[index];
}
uint16_t sec_prot_certs_cert_chain_entry_len_get(const cert_chain_entry_t *entry)
{
uint16_t chain_length = 0;
for (uint8_t index = 0; index < SEC_PROT_CERT_CHAIN_DEPTH; index++) {
if (entry->cert[index]) {
uint16_t cert_length = entry->cert_len[index];
// Checks if certificate is in PEM base64 format
if (cert_length > SEC_PROT_CERT_PEM_HEADER_FOOTER_LEN &&
entry->cert[index][cert_length - 1] == '\0' &&
strstr((const char *)entry->cert[index], SEC_PROT_CERT_PEM_HEADER_STR) != NULL) {
cert_length -= SEC_PROT_CERT_PEM_HEADER_FOOTER_LEN;
/* 4 base64 chars encode 3 bytes (ignores line endings and possible paddings in the
calculation i.e they are counted to length) */
chain_length += (cert_length / 4) * 3;
} else {
chain_length += cert_length;
}
}
}
return chain_length;
}
int8_t sec_prot_certs_priv_key_set(cert_chain_entry_t *entry, uint8_t *key, uint8_t key_len)
{
if (!entry) {

View File

@ -58,6 +58,8 @@ typedef struct {
cert_chain_entry_t own_cert_chain; /**< Own certificate chain */
cert_chain_list_t trusted_cert_chain_list; /**< Trusted certificate chain lists */
cert_revocat_lists_t cert_revocat_lists; /**< Certificate Revocation Lists */
uint16_t own_cert_chain_len; /**< Own certificate chain certificates length */
bool ext_cert_valid_enabled : 1; /**< Extended certificate validation enabled */
} sec_prot_certs_t;
/**
@ -78,6 +80,37 @@ int8_t sec_prot_certs_init(sec_prot_certs_t *certs);
*/
void sec_prot_certs_delete(sec_prot_certs_t *certs);
/**
* sec_prot_certs_ext_certificate_validation_set enable or disable extended certificate validation
*
* \param certs certificate information
* \param enabled true to enable extended validation, false to disable
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t sec_prot_certs_ext_certificate_validation_set(sec_prot_certs_t *certs, bool enabled);
/**
* sec_prot_certs_ext_certificate_validation_get get extended certificate validation setting
*
* \param certs certificate information
*
* \return true/false enabled or not
*
*/
bool sec_prot_certs_ext_certificate_validation_get(const sec_prot_certs_t *certs);
/**
* sec_prot_certs_own_cert_chain_len_get get length of own certificate chain
*
* \param certs certificate information
*
* \return length of all the certificates in the own certificate chain
*/
uint16_t sec_prot_certs_own_cert_chain_len_get(const sec_prot_certs_t *certs);
/**
* sec_prot_certs_chain_entry_create allocate memory for certificate chain entry
*
@ -123,6 +156,15 @@ int8_t sec_prot_certs_cert_set(cert_chain_entry_t *entry, uint8_t index, uint8_t
*/
uint8_t *sec_prot_certs_cert_get(const cert_chain_entry_t *entry, uint8_t index, uint16_t *cert_len);
/**
* sec_prot_certs_cert_chain_entry_len_get get length of certificate chain on cert chain entry
*
* \param entry certificate chain entry
*
* \return total length of all the certificates in the entry
*/
uint16_t sec_prot_certs_cert_chain_entry_len_get(const cert_chain_entry_t *entry);
/**
* sec_prot_certs_priv_key_set set certificate (chain) private key
*

View File

@ -48,7 +48,7 @@ void sec_prot_init(sec_prot_common_t *data)
{
data->state = SEC_STATE_INIT;
data->result = SEC_RESULT_OK;
data->ticks = SEC_TOTAL_TIMEOUT;
data->ticks = SEC_INIT_TIMEOUT;
data->trickle_running = false;
}
@ -73,10 +73,14 @@ void sec_prot_timer_timeout_handle(sec_prot_t *prot, sec_prot_common_t *data, co
if (data->ticks > ticks) {
data->ticks -= ticks;
} else {
tr_debug("prot timeout");
tr_debug("prot timeout, state: %i", data->state);
data->ticks = 0;
sec_prot_result_set(data, SEC_RESULT_TIMEOUT);
sec_prot_state_set(prot, data, SEC_STATE_FINISH);
if (data->state == SEC_STATE_INIT) {
sec_prot_state_set(prot, data, SEC_STATE_FINISHED);
} else {
sec_prot_state_set(prot, data, SEC_STATE_FINISH);
}
}
}
@ -167,6 +171,11 @@ bool sec_prot_result_ok_check(sec_prot_common_t *data)
return false;
}
void sec_prot_default_timeout_set(sec_prot_common_t *data)
{
data->ticks = SEC_TOTAL_TIMEOUT;
}
void sec_prot_lib_nonce_generate(uint8_t *nonce)
{
// Use randlib

View File

@ -32,6 +32,7 @@
#define FWH_NONCE_LENGTH 32
#define EUI64_LEN 8
#define SEC_TOTAL_TIMEOUT 30 * 60 * 10 // 30 minutes
#define SEC_INIT_TIMEOUT 60 * 10 // 60 seconds
#define SEC_FINISHED_TIMEOUT 5 * 10 // 5 seconds
@ -295,4 +296,12 @@ bool sec_prot_result_timeout_check(sec_prot_common_t *data);
*/
bool sec_prot_result_ok_check(sec_prot_common_t *data);
/**
* sec_prot_default_timeout_set sets default timeout for protocol
*
* \param data common data
*
*/
void sec_prot_default_timeout_set(sec_prot_common_t *data);
#endif /* SEC_PROT_LIB_H_ */

View File

@ -104,6 +104,8 @@ static bool tls_sec_prot_queue_check(sec_prot_t *prot);
static bool tls_sec_prot_queue_process(sec_prot_t *prot);
static void tls_sec_prot_queue_remove(sec_prot_t *prot);
static uint16_t tls_sec_prot_send_buffer_size_get(sec_prot_t *prot);
#define tls_sec_prot_get(prot) (tls_sec_prot_int_t *) &prot->data
static NS_LIST_DEFINE(tls_sec_prot_queue, tls_sec_prot_queue_t, link);
@ -292,15 +294,17 @@ static void client_tls_sec_prot_state_machine(sec_prot_t *prot)
switch (sec_prot_state_get(&data->common)) {
case TLS_STATE_INIT:
tr_debug("TLS: init");
sec_prot_state_set(prot, &data->common, TLS_STATE_CREATE_REQ);
prot->timer_start(prot);
// Set default timeout for the total maximum length of the negotiation
sec_prot_default_timeout_set(&data->common);
break;
// Wait KMP-CREATE.request
case TLS_STATE_CREATE_REQ:
tr_debug("TLS: start");
prot->timer_start(prot);
prot->create_conf(prot, SEC_RESULT_OK);
sec_prot_state_set(prot, &data->common, TLS_STATE_CONFIGURE);
@ -383,15 +387,17 @@ static void server_tls_sec_prot_state_machine(sec_prot_t *prot)
switch (sec_prot_state_get(&data->common)) {
case TLS_STATE_INIT:
tr_debug("TLS: init");
sec_prot_state_set(prot, &data->common, TLS_STATE_CLIENT_HELLO);
prot->timer_start(prot);
// Set default timeout for the total maximum length of the negotiation
sec_prot_default_timeout_set(&data->common);
break;
// Wait EAP request, Identity (starts handshake on supplicant)
case TLS_STATE_CLIENT_HELLO:
tr_debug("TLS: start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
prot->timer_start(prot);
client_hello = true;
sec_prot_state_set(prot, &data->common, TLS_STATE_CREATE_RESP);
@ -494,12 +500,23 @@ static int16_t tls_sec_prot_tls_send(void *handle, const void *buf, size_t len)
tls_sec_prot_int_t *data = tls_sec_prot_get(prot);
if (!data->tls_send.data) {
eap_tls_sec_prot_lib_message_allocate(&data->tls_send, prot->header_size, TLS_SEC_PROT_BUFFER_SIZE);
uint16_t buffer_len = tls_sec_prot_send_buffer_size_get(prot);
eap_tls_sec_prot_lib_message_allocate(&data->tls_send, prot->header_size, buffer_len);
}
if (!data->tls_send.data) {
return -1;
}
/* If send buffer is too small for the TLS payload, re-allocates */
uint16_t new_len = prot->header_size + data->tls_send.handled_len + len;
if (new_len > data->tls_send.total_len) {
tr_error("TLS send buffer size too small: %i < %i, allocating new: %i", data->tls_send.total_len, new_len, data->tls_send.total_len + TLS_SEC_PROT_SEND_BUFFER_SIZE_INCREMENT);
if (eap_tls_sec_prot_lib_message_realloc(&data->tls_send, prot->header_size,
data->tls_send.total_len + TLS_SEC_PROT_SEND_BUFFER_SIZE_INCREMENT) < 0) {
return -1;
}
}
memcpy(data->tls_send.data + prot->header_size + data->tls_send.handled_len, buf, len);
data->tls_send.handled_len += len;
@ -685,4 +702,9 @@ static void tls_sec_prot_queue_remove(sec_prot_t *prot)
}
}
static uint16_t tls_sec_prot_send_buffer_size_get(sec_prot_t *prot)
{
return TLS_SEC_PROT_SEND_BUFFER_SIZE + sec_prot_certs_own_cert_chain_len_get(prot->sec_keys->certs);
}
#endif /* HAVE_WS */

View File

@ -23,7 +23,13 @@
*
*/
#define TLS_SEC_PROT_BUFFER_SIZE 1200 // Send buffer size (maximum size for a TLS data for a flight)
/* TLS send buffer size not including certificates. This should include e.g. on
* server: server hello, server key exchange, certificate request and server
* hello done. */
#define TLS_SEC_PROT_SEND_BUFFER_SIZE 500
/* TLS send buffer size increment if it is detected that buffer is too small */
#define TLS_SEC_PROT_SEND_BUFFER_SIZE_INCREMENT 1000
/**
* client_tls_sec_prot_register register client TLS protocol to KMP service

View File

@ -49,6 +49,7 @@
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/ssl_ciphersuites.h"
#include "mbedtls/debug.h"
#include "mbedtls/oid.h"
#include "mbedtls/ssl_internal.h"
@ -57,7 +58,9 @@
#define TLS_HANDSHAKE_TIMEOUT_MIN 25000
#define TLS_HANDSHAKE_TIMEOUT_MAX 201000
//#define TLS_SEC_PROT_LIB_TLS_DEBUG // Enable mbed TLS debug traces
//#define TLS_SEC_PROT_LIB_TLS_DEBUG // Enable mbed TLS debug traces
typedef int tls_sec_prot_lib_crt_verify_cb(tls_security_t *sec, mbedtls_x509_crt *crt, uint32_t *flags);
struct tls_security_s {
mbedtls_ssl_config conf; /**< mbed TLS SSL configuration */
@ -71,6 +74,8 @@ struct tls_security_s {
mbedtls_x509_crt owncert; /**< Own certificate(s) */
mbedtls_pk_context pkey; /**< Private key for own certificate */
void *handle; /**< Handle provided in callbacks (defined by library user) */
bool ext_cert_valid : 1; /**< Extended certificate validation enabled */
tls_sec_prot_lib_crt_verify_cb *crt_verify; /**< Verify function for client/server certificate */
tls_sec_prot_lib_send *send; /**< Send callback */
tls_sec_prot_lib_receive *receive; /**< Receive callback */
tls_sec_prot_lib_export_keys *export_keys; /**< Export keys callback */
@ -85,23 +90,42 @@ static int tls_sec_prot_lib_ssl_send(void *ctx, const unsigned char *buf, size_t
static int tls_sec_prot_lib_ssl_recv(void *ctx, unsigned char *buf, size_t len);
static int tls_sec_prot_lib_ssl_export_keys(void *p_expkey, const unsigned char *ms,
const unsigned char *kb, size_t maclen, size_t keylen,
size_t ivlen, unsigned char client_random[32],
unsigned char server_random[32],
size_t ivlen, const unsigned char client_random[32],
const unsigned char server_random[32],
mbedtls_tls_prf_types tls_prf_type);
static int tls_sec_prot_lib_x509_crt_verify(void *ctx, mbedtls_x509_crt *crt, int certificate_depth, uint32_t *flags);
static int8_t tls_sec_prot_lib_subject_alternative_name_validate(mbedtls_x509_crt *crt);
static int8_t tls_sec_prot_lib_extended_key_usage_validate(mbedtls_x509_crt *crt);
#ifdef HAVE_PAE_AUTH
static int tls_sec_prot_lib_x509_crt_idevid_ldevid_verify(tls_security_t *sec, mbedtls_x509_crt *crt, uint32_t *flags);
#endif
#ifdef HAVE_PAE_SUPP
static int tls_sec_prot_lib_x509_crt_server_verify(tls_security_t *sec, mbedtls_x509_crt *crt, uint32_t *flags);
#endif
#ifdef TLS_SEC_PROT_LIB_TLS_DEBUG
static void tls_sec_prot_lib_debug(void *ctx, int level, const char *file, int line, const char *string);
#endif
#ifdef MBEDTLS_PLATFORM_MEMORY
// Disable for now
//#define TLS_SEC_PROT_LIB_USE_MBEDTLS_PLATFORM_MEMORY
#endif
#ifdef TLS_SEC_PROT_LIB_USE_MBEDTLS_PLATFORM_MEMORY
static void *tls_sec_prot_lib_mem_calloc(size_t count, size_t size);
static void tls_sec_prot_lib_mem_free(void *ptr);
#endif
#if defined(HAVE_PAE_AUTH) && defined(HAVE_PAE_SUPP)
#define is_server_is_set (is_server == true)
#define is_server_is_not_set (is_server == false)
#elif defined(HAVE_PAE_AUTH)
#define is_server_is_set true
#define is_server_is_not_set false
#elif defined(HAVE_PAE_SUPP)
#define is_server_is_set false
#define is_server_is_not_set true
#endif
int8_t tls_sec_prot_lib_init(tls_security_t *sec)
{
const char *pers = "ws_tls";
@ -110,7 +134,6 @@ int8_t tls_sec_prot_lib_init(tls_security_t *sec)
mbedtls_platform_set_calloc_free(tls_sec_prot_lib_mem_calloc, tls_sec_prot_lib_mem_free);
#endif
mbedtls_ssl_init(&sec->ssl);
mbedtls_ssl_config_init(&sec->conf);
mbedtls_ctr_drbg_init(&sec->ctr_drbg);
@ -269,21 +292,37 @@ static int tls_sec_prot_lib_configure_certificates(tls_security_t *sec, const se
// Certificate verify required on both client and server
mbedtls_ssl_conf_authmode(&sec->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
// Get extended certificate validation setting
sec->ext_cert_valid = sec_prot_certs_ext_certificate_validation_get(certs);
return 0;
}
int8_t tls_sec_prot_lib_connect(tls_security_t *sec, bool is_server, const sec_prot_certs_t *certs)
{
#if !defined(HAVE_PAE_SUPP) || !defined(HAVE_PAE_AUTH)
(void) is_server;
#endif
if (!sec) {
return -1;
}
int endpoint = MBEDTLS_SSL_IS_CLIENT;
if (is_server) {
endpoint = MBEDTLS_SSL_IS_SERVER;
#ifdef HAVE_PAE_SUPP
if (is_server_is_not_set) {
sec->crt_verify = tls_sec_prot_lib_x509_crt_server_verify;
}
#endif
#ifdef HAVE_PAE_AUTH
if (is_server_is_set) {
sec->crt_verify = tls_sec_prot_lib_x509_crt_idevid_ldevid_verify;
}
#endif
if ((mbedtls_ssl_config_defaults(&sec->conf, endpoint, MBEDTLS_SSL_TRANSPORT_STREAM, 0)) != 0) {
if ((mbedtls_ssl_config_defaults(&sec->conf,
is_server_is_set ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM, 0)) != 0) {
tr_error("config defaults fail");
return -1;
}
@ -331,8 +370,11 @@ int8_t tls_sec_prot_lib_connect(tls_security_t *sec, bool is_server, const sec_p
mbedtls_ssl_conf_min_version(&sec->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MAJOR_VERSION_3);
mbedtls_ssl_conf_max_version(&sec->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MAJOR_VERSION_3);
// Set certificate verify callback
mbedtls_ssl_set_verify(&sec->ssl, tls_sec_prot_lib_x509_crt_verify, sec);
#ifdef MBEDTLS_ECP_RESTARTABLE
if (endpoint == MBEDTLS_SSL_IS_SERVER) {
if (is_server_is_set) {
// Temporary to enable non blocking ECC */
sec->ssl.handshake->ecrs_enabled = 1;
}
@ -405,8 +447,8 @@ static int tls_sec_prot_lib_ssl_recv(void *ctx, unsigned char *buf, size_t len)
static int tls_sec_prot_lib_ssl_export_keys(void *p_expkey, const unsigned char *ms,
const unsigned char *kb, size_t maclen, size_t keylen,
size_t ivlen, unsigned char client_random[32],
unsigned char server_random[32],
size_t ivlen, const unsigned char client_random[32],
const unsigned char server_random[32],
mbedtls_tls_prf_types tls_prf_type)
{
(void) kb;
@ -433,6 +475,109 @@ static int tls_sec_prot_lib_ssl_export_keys(void *p_expkey, const unsigned char
return 0;
}
static int tls_sec_prot_lib_x509_crt_verify(void *ctx, mbedtls_x509_crt *crt, int certificate_depth, uint32_t *flags)
{
tls_security_t *sec = (tls_security_t *) ctx;
/* MD/PK forced by configuration flags and dynamic settings but traced also here
to prevent invalid configurations/certificates */
if (crt->sig_md != MBEDTLS_MD_SHA256) {
tr_error("Invalid signature md algorithm");
}
if (crt->sig_pk != MBEDTLS_PK_ECDSA) {
tr_error("Invalid signature pk algorithm");
}
// Verify client/server certificate of the chain
if (certificate_depth == 0) {
return sec->crt_verify(sec, crt, flags);
}
// No further checks for intermediate and root certificates at the moment
return 0;
}
static int8_t tls_sec_prot_lib_subject_alternative_name_validate(mbedtls_x509_crt *crt)
{
mbedtls_asn1_sequence *seq = &crt->subject_alt_names;
int8_t result = -1;
while (seq) {
mbedtls_x509_subject_alternative_name san;
int ret_value = mbedtls_x509_parse_subject_alt_name((mbedtls_x509_buf *)&seq->buf, &san);
if (ret_value == 0 && san.type == MBEDTLS_X509_SAN_OTHER_NAME) {
// id-on-hardwareModuleName must be present (1.3.6.1.5.5.7.8.4)
if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &san.san.other_name.value.hardware_module_name.oid)) {
// Traces hardwareModuleName (1.3.6.1.4.1.<enteprise number>.<model,version,etc.>)
char buffer[30];
ret_value = mbedtls_oid_get_numeric_string(buffer, sizeof(buffer), &san.san.other_name.value.hardware_module_name.oid);
if (ret_value != MBEDTLS_ERR_OID_BUF_TOO_SMALL) {
tr_info("id-on-hardwareModuleName %s", buffer);
}
// Traces serial number as hex string
mbedtls_x509_buf *val = &san.san.other_name.value.hardware_module_name.val;
if (val->p) {
tr_info("id-on-hardwareModuleName hwSerialNum %s", trace_array(val->p, val->len));
}
result = 0;
}
} else {
tr_debug("Ignored subject alt name: %i", san.type);
}
seq = seq->next;
}
return result;
}
static int8_t tls_sec_prot_lib_extended_key_usage_validate(mbedtls_x509_crt *crt)
{
#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE)
// Extended key usage must be present
if (mbedtls_x509_crt_check_extended_key_usage(crt, MBEDTLS_OID_WISUN_FAN, sizeof(MBEDTLS_OID_WISUN_FAN) - 1) != 0) {
tr_error("invalid extended key usage");
return -1; // FAIL
}
#endif
return 0;
}
#ifdef HAVE_PAE_AUTH
static int tls_sec_prot_lib_x509_crt_idevid_ldevid_verify(tls_security_t *sec, mbedtls_x509_crt *crt, uint32_t *flags)
{
// For both IDevID and LDevId both subject alternative name or extended key usage must be valid
if (tls_sec_prot_lib_subject_alternative_name_validate(crt) < 0 ||
tls_sec_prot_lib_extended_key_usage_validate(crt) < 0) {
tr_error("invalid cert");
if (sec->ext_cert_valid) {
*flags |= MBEDTLS_X509_BADCERT_OTHER;
return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;
}
}
return 0;
}
#endif
#ifdef HAVE_PAE_SUPP
static int tls_sec_prot_lib_x509_crt_server_verify(tls_security_t *sec, mbedtls_x509_crt *crt, uint32_t *flags)
{
int8_t sane_res = tls_sec_prot_lib_subject_alternative_name_validate(crt);
int8_t ext_key_res = tls_sec_prot_lib_extended_key_usage_validate(crt);
// If either subject alternative name or extended key usage is present
if (sane_res >= 0 || ext_key_res >= 0) {
// Then both subject alternative name and extended key usage must be valid
if (sane_res < 0 || ext_key_res < 0) {
tr_error("invalid cert");
if (sec->ext_cert_valid) {
*flags |= MBEDTLS_X509_BADCERT_OTHER;
return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;
}
}
}
return 0;
}
#endif
static int tls_sec_lib_entropy_poll(void *ctx, unsigned char *output, size_t len, size_t *olen)
{
(void)ctx;
@ -518,4 +663,3 @@ uint16_t tls_sec_prot_lib_size(void)
}
#endif /* WS_MBEDTLS_SECURITY_ENABLED */
#endif /* HAVE_WS */

View File

@ -679,6 +679,7 @@ void dhcp_service_delete(uint16_t instance)
int dhcp_service_send_resp(uint32_t msg_tr_id, uint8_t options, uint8_t *msg_ptr, uint16_t msg_len)
{
tr_debug("Send DHCPv6 response");
msg_tr_t *msg_tr_ptr;
server_instance_t *srv_instance;
msg_tr_ptr = dhcp_tr_find(msg_tr_id);
@ -706,6 +707,7 @@ int dhcp_service_send_resp(uint32_t msg_tr_id, uint8_t options, uint8_t *msg_ptr
}
uint32_t dhcp_service_send_req(uint16_t instance_id, uint8_t options, void *ptr, const uint8_t addr[static 16], uint8_t *msg_ptr, uint16_t msg_len, dhcp_service_receive_resp_cb *receive_resp_cb)
{
tr_debug("Send DHCPv6 request");
msg_tr_t *msg_tr_ptr;
server_instance_t *srv_ptr;
srv_ptr = dhcp_service_client_find(instance_id);
@ -767,6 +769,17 @@ void dhcp_service_req_remove(uint32_t msg_tr_id)
return;
}
void dhcp_service_req_remove_all(void *msg_class_ptr)
{
if (dhcp_service) {
ns_list_foreach_safe(msg_tr_t, cur_ptr, &dhcp_service->tr_list) {
if (cur_ptr->client_obj_ptr == msg_class_ptr) {
dhcp_tr_delete(cur_ptr);
}
}
}
}
void dhcp_service_send_message(msg_tr_t *msg_tr_ptr)
{
int8_t retval;
@ -930,4 +943,9 @@ bool dhcp_service_timer_tick(uint16_t ticks)
return false;
}
void dhcp_service_req_remove_all(void *msg_class_ptr)
{
(void)msg_class_ptr;
}
#endif

View File

@ -217,6 +217,17 @@ dhcpv6_client_server_data_t *libdhcpv6_nonTemporal_entry_get_by_prefix(int8_t in
return NULL;
}
dhcpv6_client_server_data_t *libdhcpv6_nonTemporal_validate_class_pointer(void *class_ptr)
{
ns_list_foreach(dhcpv6_client_server_data_t, cur, &dhcpv6_client_nonTemporal_list) {
if (cur == class_ptr) {
return cur;
}
}
return NULL;
}
uint16_t libdhcpv6_duid_option_size(uint16_t linkType)
{
uint16_t length = 8; // Type & Length header part *2

View File

@ -235,6 +235,7 @@ dhcpv6_client_server_data_t *libdhcpv6_nonTemporal_entry_get_by_iaid(uint32_t ia
dhcpv6_client_server_data_t *libdhcpv6_nonTemporal_entry_get_by_transactionId(uint32_t txId);
dhcpv6_client_server_data_t *libdhcpv6_nonTemporal_entry_get_by_prefix(int8_t interfaceId, uint8_t *prefix);
dhcpv6_client_server_data_t *libdhcpv6_nonTemporal_entry_get_by_instance(uint8_t instanceId);
dhcpv6_client_server_data_t *libdhcpv6_nonTemporal_validate_class_pointer(void *class_ptr);
uint8_t libdhcpv6_nonTemporal_entry_get_unique_instance_id(void);

View File

@ -988,18 +988,30 @@ int8_t arm_network_trusted_certificate_remove(const arm_certificate_entry_s *cer
int8_t arm_network_trusted_certificates_remove(void)
{
#ifdef HAVE_WS
return ws_pae_controller_trusted_certificates_remove();
#else
return -1;
#endif
}
int8_t arm_network_own_certificate_add(const arm_certificate_entry_s *cert)
{
#ifdef HAVE_WS
return ws_pae_controller_own_certificate_add(cert);
#else
(void) cert;
return -1;
#endif
}
extern int8_t arm_network_own_certificates_remove(void)
{
#ifdef HAVE_WS
return ws_pae_controller_own_certificates_remove();
#else
return -1;
#endif
}
int8_t arm_network_certificate_revocation_list_add(const arm_cert_revocation_list_entry_s *crl)