Skip to content

Commit

Permalink
Added ignoring of incoming security messages and improved EAP-TLS sta…
Browse files Browse the repository at this point in the history
…rtup

If supplicant authentication is not ongoing (during bootstrap or re-authentication),
supplicant now ignores incoming security protocol messages.

This results that e.g. if initial EAPOL-key message results mac TX failure, but
authenticator has received the message (ack is lost), and authenticator starts
EAP-TLS after the supplicant has returned to discover state, supplicant does not start
EAP-TLS negotiation.

Improved authenticator functionality on EAP-TLS identity request state. If supplicant
has not received or has ignored the EAP-TLS identity request (e.g. because of mac
TX failure) and authenticator receives initial EAPOL-key message from supplicant,
authenticator now re-sends the the EAP-TLS identity request right away.
  • Loading branch information
Mika Leppänen committed Jan 10, 2020
1 parent 7350634 commit d8dd18d
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 5 deletions.
14 changes: 14 additions & 0 deletions source/6LoWPAN/ws/ws_pae_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,20 @@ void ws_pae_lib_supp_timer_ticks_set(supp_entry_t *entry, uint32_t ticks)
entry->ticks = ticks;
}

void ws_pae_lib_supp_timer_ticks_add(supp_entry_t *entry, uint32_t ticks)
{
entry->ticks += ticks;
}

bool ws_pae_lib_supp_timer_is_running(supp_entry_t *entry)
{
if (entry->ticks == 0) {
return false;
}

return true;
}

void ws_pae_lib_supp_list_to_active(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, supp_entry_t *entry)
{
if (entry->active) {
Expand Down
19 changes: 19 additions & 0 deletions source/6LoWPAN/ws/ws_pae_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,25 @@ void ws_pae_lib_supp_delete(supp_entry_t *entry);
*/
void ws_pae_lib_supp_timer_ticks_set(supp_entry_t *entry, uint32_t ticks);

/**
* ws_pae_lib_supp_timer_ticks_add adds supplicant timer ticks
*
* \param entry supplicant entry
* \param ticks ticks
*
*/
void ws_pae_lib_supp_timer_ticks_add(supp_entry_t *entry, uint32_t ticks);

/**
* ws_pae_lib_supp_timer_is_running checks whether supplicant timer is running
*
* \param entry supplicant entry
*
* \return TRUE timer is running, FALSE timer is not running
*
*/
bool ws_pae_lib_supp_timer_is_running(supp_entry_t *entry);

/**
* ws_pae_lib_supp_list_to_active move supplicant to active supplicants list
*
Expand Down
25 changes: 22 additions & 3 deletions source/6LoWPAN/ws/ws_pae_supp.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@
// Wait for re-authentication after GTK update
#define WAIT_FOR_REAUTHENTICATION_TICKS 120 * 10 // 120 seconds

// Ticks added to wait for authenticator timer when authentication protocol is started (e.g. EAP-TLS)
#define START_AUTHENTICATION_TICKS 5 * 10 // 10 seconds

// How many times in maximum stored keys are used for authentication
#define STORED_KEYS_MAXIMUM_USE_COUNT 1

Expand Down Expand Up @@ -146,6 +149,7 @@ static int8_t ws_pae_supp_event_send(kmp_service_t *service, void *data);
static void ws_pae_supp_tasklet_handler(arm_event_s *event);
static void ws_pae_supp_initial_trickle_timer_start(pae_supp_t *pae_supp);
static void ws_pae_supp_initial_last_interval_trickle_timer_start(pae_supp_t *pae_supp);
static bool ws_pae_supp_authentication_ongoing(pae_supp_t *pae_supp);
static int8_t ws_pae_supp_timer_if_start(kmp_service_t *service, kmp_api_t *kmp);
static int8_t ws_pae_supp_timer_if_stop(kmp_service_t *service, kmp_api_t *kmp);
static int8_t ws_pae_supp_timer_start(pae_supp_t *pae_supp);
Expand Down Expand Up @@ -823,7 +827,7 @@ void ws_pae_supp_fast_timer(uint16_t ticks)
bool running = ws_pae_lib_supp_timer_update(&pae_supp->entry, ticks, kmp_service_timer_if_timeout);

// Checks whether timer needs to be active
if (!pae_supp->initial_key_timer && !pae_supp->auth_trickle_running && !running) {
if (!ws_pae_supp_authentication_ongoing(pae_supp) && !running) {
tr_debug("PAE idle");
// If not already completed, restart bootstrap
ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_UNSPEC);
Expand All @@ -833,6 +837,17 @@ void ws_pae_supp_fast_timer(uint16_t ticks)
}
}

static bool ws_pae_supp_authentication_ongoing(pae_supp_t *pae_supp)
{
/* When either bootstrap initial authentication or re-authentication is ongoing */
if (pae_supp->initial_key_timer || pae_supp->auth_trickle_running ||
ws_pae_lib_supp_timer_is_running(&pae_supp->entry)) {
return true;
}

return false;
}

void ws_pae_supp_slow_timer(uint16_t seconds)
{
ns_list_foreach(pae_supp_t, pae_supp, &pae_supp_list) {
Expand Down Expand Up @@ -1105,7 +1120,9 @@ static kmp_api_t *ws_pae_supp_kmp_incoming_ind(kmp_service_t *service, kmp_type_
return NULL;
}

if (!pae_supp->entry_address_active) {
// If target address is not set or authentication is not ongoing
if (!pae_supp->entry_address_active || !ws_pae_supp_authentication_ongoing(pae_supp)) {
tr_info("Incoming KMP rejected, auth not ongoing, type: %i ", type);
// Does no longer wait for authentication, ignores message
return NULL;
}
Expand All @@ -1131,6 +1148,9 @@ static kmp_api_t *ws_pae_supp_kmp_incoming_ind(kmp_service_t *service, kmp_type_
// Create new instance
kmp = ws_pae_supp_kmp_create_and_start(service, type, pae_supp);

// Adds ticks to wait for authenticator to continue timer
ws_pae_lib_supp_timer_ticks_add(&pae_supp->entry, START_AUTHENTICATION_TICKS);

// For EAP-TLS create also TLS in addition to EAP-TLS
if (type == IEEE_802_1X_MKA) {
if (ws_pae_lib_kmp_list_type_get(&pae_supp->entry.kmp_list, TLS_PROT) != NULL) {
Expand Down Expand Up @@ -1239,7 +1259,6 @@ static void ws_pae_supp_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e
tr_info("Initial EAPOL-Key TX failure, target: %s", trace_array(kmp_address_eui_64_get(&pae_supp->entry.addr), 8));
ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_TX_NO_ACK);
}

}

static void ws_pae_supp_kmp_api_finished(kmp_api_t *kmp)
Expand Down
39 changes: 37 additions & 2 deletions source/Security/protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,24 @@ typedef enum {
EAP_TLS_STATE_FINISHED = SEC_STATE_FINISHED
} eap_tls_sec_prot_state_e;

// Filters initial EAPOL-key re-transmission bursts
#define BURST_FILTER_TIMER_TIMEOUT 5 * 10

// How many times initial EAPOL-key is accepted on wait for identity response state
#define INITIAL_EAPOL_KEY_MAX_COUNT 2

typedef struct {
sec_prot_common_t common; /**< Common data */
sec_prot_t *tls_prot; /**< TLS security protocol */
eapol_pdu_t recv_eapol_pdu; /**< Received EAPOL PDU */
tls_data_t tls_send; /**< EAP-TLS send buffer */
tls_data_t tls_recv; /**< EAP-TLS receive buffer */
uint16_t burst_filt_timer; /**< Burst filter timer */
uint8_t eap_id_seq; /**< EAP sequence */
uint8_t recv_eap_id_seq; /**< Last received EAP sequence */
uint8_t eap_code; /**< Received EAP code */
uint8_t eap_type; /**< Received EAP type */
uint8_t init_key_cnt; /**< How many time initial EAPOL-key has been received */
int8_t tls_result; /**< Result of TLS operation */
bool wait_tls: 1; /**< Wait TLS (ECC calculation) before sending EAP-TLS message */
bool tls_ongoing: 1; /**< TLS handshake is ongoing */
Expand Down Expand Up @@ -151,13 +159,15 @@ static int8_t auth_eap_tls_sec_prot_init(sec_prot_t *prot)
sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_INIT);

data->tls_prot = NULL;
data->burst_filt_timer = BURST_FILTER_TIMER_TIMEOUT;
data->eap_id_seq = 0;
data->recv_eap_id_seq = 0;
data->eap_code = 0;
data->eap_type = 0;
eap_tls_sec_prot_lib_message_init(&data->tls_recv);
eap_tls_sec_prot_lib_message_init(&data->tls_send);
data->tls_result = EAP_TLS_RESULT_ERROR;
data->tls_result = EAP_TLS_RESULT_ERROR;
data->init_key_cnt = 0;
data->wait_tls = false;
data->tls_ongoing = false;
data->send_pending = false;
Expand Down Expand Up @@ -186,13 +196,31 @@ static int8_t auth_eap_tls_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_

// Decoding is successful
if (eapol_parse_pdu_header(pdu, size, &data->recv_eapol_pdu)) {
// Handle only EAP messages (ignore initial EAPOL-key retransmissions)
// Handle EAP messages
if (data->recv_eapol_pdu.packet_type == EAPOL_EAP_TYPE) {
data->eap_code = data->recv_eapol_pdu.msg.eap.eap_code;
data->eap_type = data->recv_eapol_pdu.msg.eap.type;

// Call state machine
prot->state_machine(prot);
} else if (data->recv_eapol_pdu.packet_type == EAPOL_KEY_TYPE &&
sec_prot_state_get(&data->common) == EAP_TLS_STATE_RESPONSE_ID) {
/* If initial EAPOL-key transmission arrives to first EAP-TLS wait state i.e.
* when waiting for identity response, triggers re-transmission of identity
* request. This allows the supplicant to start EAP-TLS right away, if it has
* missed the original identity request.
*/
if (data->burst_filt_timer == 0 && data->init_key_cnt < INITIAL_EAPOL_KEY_MAX_COUNT) {
tr_info("EAP-TLS: initial EAPOL-key recv, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8));
sec_prot_result_set(&data->common, SEC_RESULT_TIMEOUT);
// Call state machine
prot->state_machine(prot);
// Resets trickle timer to give time for supplicant to answer
sec_prot_timer_trickle_start(&data->common, &eap_tls_trickle_params);
data->init_key_cnt++;
}
// Filters repeated initial EAPOL-key messages
data->burst_filt_timer = BURST_FILTER_TIMER_TIMEOUT;
}
ret_val = 0;
}
Expand Down Expand Up @@ -288,6 +316,13 @@ static int8_t auth_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_c
static void auth_eap_tls_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks)
{
eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot);

if (data->burst_filt_timer > ticks) {
data->burst_filt_timer -= ticks;
} else {
data->burst_filt_timer = 0;
}

sec_prot_timer_timeout_handle(prot, &data->common, &eap_tls_trickle_params, ticks);
}

Expand Down

0 comments on commit d8dd18d

Please sign in to comment.