eapol: Use handshake_state to store state

Remove the keys and other data from struct eapol_sm, update device.c,
netdev.c and wsc.c to use the handshake_state object instead of
eapol_sm.  This also gets rid of eapol_cancel and the ifindex parameter
in some of the eapol functions where sm->handshake->ifindex can be
used instead.
This commit is contained in:
Andrew Zaborowski 2016-11-02 23:46:19 +01:00 committed by Denis Kenzior
parent 061dad2ff5
commit e32ffc4d98
6 changed files with 255 additions and 682 deletions

View File

@ -34,7 +34,7 @@
#include "src/common.h"
#include "src/util.h"
#include "src/ie.h"
#include "src/eapol.h"
#include "src/handshake.h"
#include "src/wiphy.h"
#include "src/scan.h"
#include "src/netdev.h"
@ -677,7 +677,7 @@ void device_connect_network(struct device *device, struct network *network,
enum security security = network_get_security(network);
struct wiphy *wiphy = device->wiphy;
struct l_dbus *dbus = dbus_get_bus();
struct eapol_sm *sm = NULL;
struct handshake_state *hs = NULL;
bool add_mde = false;
uint8_t *mde;
@ -718,31 +718,27 @@ void device_connect_network(struct device *device, struct network *network,
} else if (info.group_management_cipher != 0)
info.mfpc = true;
sm = eapol_sm_new();
eapol_sm_set_authenticator_address(sm, bss->addr);
eapol_sm_set_supplicant_address(sm,
netdev_get_address(device->netdev));
hs = handshake_state_new(netdev_get_ifindex(device->netdev));
ssid = network_get_ssid(network);
eapol_sm_set_ssid(sm, (void *) ssid, strlen(ssid));
handshake_state_set_ssid(hs, (void *) ssid, strlen(ssid));
/* RSN takes priority */
if (bss->rsne) {
ie_build_rsne(&info, rsne_buf);
eapol_sm_set_ap_rsn(sm, bss->rsne);
eapol_sm_set_own_rsn(sm, rsne_buf);
handshake_state_set_ap_rsn(hs, bss->rsne);
handshake_state_set_own_rsn(hs, rsne_buf);
} else {
ie_build_wpa(&info, rsne_buf);
eapol_sm_set_ap_wpa(sm, bss->wpa);
eapol_sm_set_own_wpa(sm, rsne_buf);
handshake_state_set_ap_wpa(hs, bss->wpa);
handshake_state_set_own_wpa(hs, rsne_buf);
}
if (security == SECURITY_PSK)
eapol_sm_set_pmk(sm, network_get_psk(network));
handshake_state_set_pmk(hs, network_get_psk(network));
else
eapol_sm_set_8021x_config(sm,
network_get_settings(network));
handshake_state_set_8021x_config(hs,
network_get_settings(network));
if (info.akm_suites & (IE_RSN_AKM_SUITE_FT_OVER_8021X |
IE_RSN_AKM_SUITE_FT_USING_PSK |
@ -762,18 +758,18 @@ void device_connect_network(struct device *device, struct network *network,
mde[1] = 3;
memcpy(mde + 2, bss->mde, 3);
if (sm)
eapol_sm_set_mde(sm, mde);
if (hs)
handshake_state_set_mde(hs, mde);
} else
mde = NULL;
device->connect_pending = l_dbus_message_ref(message);
if (netdev_connect(device->netdev, bss, sm, mde,
if (netdev_connect(device->netdev, bss, hs, mde,
device_netdev_event,
device_connect_cb, device) < 0) {
if (sm)
eapol_sm_free(sm);
if (hs)
handshake_state_free(hs);
l_free(mde);

File diff suppressed because it is too large Load Diff

View File

@ -48,6 +48,7 @@ enum eapol_key_descriptor_version {
};
struct eapol_sm;
struct handshake_state;
struct eapol_header {
uint8_t protocol_version;
@ -108,22 +109,6 @@ typedef int (*eapol_tx_packet_func_t)(uint32_t ifindex, const uint8_t *aa,
const uint8_t *spa,
const struct eapol_frame *ef,
void *user_data);
typedef bool (*eapol_get_nonce_func_t)(uint8_t nonce[]);
typedef void (*eapol_install_tk_func_t)(uint32_t ifindex, const uint8_t *aa,
const uint8_t *tk, uint32_t cipher,
void *user_data);
typedef void (*eapol_install_gtk_func_t)(uint32_t ifindex, uint8_t key_index,
const uint8_t *gtk, uint8_t gtk_len,
const uint8_t *rsc, uint8_t rsc_len,
uint32_t cipher, void *user_data);
typedef void (*eapol_install_igtk_func_t)(uint32_t ifindex, uint8_t key_index,
const uint8_t *igtk, uint8_t igtk_len,
const uint8_t *ipn, uint8_t ipn_len,
uint32_t cipher, void *user_data);
typedef void (*eapol_deauthenticate_func_t)(uint32_t ifindex, const uint8_t *aa,
const uint8_t *spa,
uint16_t reason_code,
void *user_data);
typedef void (*eapol_rekey_offload_func_t)(uint32_t ifindex,
const uint8_t *kek,
const uint8_t *kck,
@ -132,6 +117,10 @@ typedef void (*eapol_rekey_offload_func_t)(uint32_t ifindex,
typedef void (*eapol_sm_event_func_t)(unsigned int event,
const void *event_data,
void *user_data);
typedef void (*eapol_deauthenticate_func_t)(uint32_t ifindex, const uint8_t *aa,
const uint8_t *spa,
uint16_t reason_code,
void *user_data);
bool eapol_calculate_mic(const uint8_t *kck, const struct eapol_key *frame,
uint8_t *mic);
@ -176,47 +165,23 @@ void __eapol_rx_packet(uint32_t ifindex, const uint8_t *aa,
void __eapol_set_tx_packet_func(eapol_tx_packet_func_t func);
void __eapol_set_tx_user_data(void *user_data);
void __eapol_set_get_nonce_func(eapol_get_nonce_func_t func);
void __eapol_set_install_tk_func(eapol_install_tk_func_t func);
void __eapol_set_install_gtk_func(eapol_install_gtk_func_t func);
void __eapol_set_install_igtk_func(eapol_install_igtk_func_t func);
void __eapol_set_deauthenticate_func(eapol_deauthenticate_func_t func);
void __eapol_set_rekey_offload_func(eapol_rekey_offload_func_t func);
void __eapol_update_replay_counter(uint32_t ifindex, const uint8_t *spa,
const uint8_t *aa, uint64_t replay_counter);
struct eapol_sm *eapol_sm_new();
struct eapol_sm *eapol_sm_new(struct handshake_state *hs);
void eapol_sm_free(struct eapol_sm *sm);
void eapol_sm_set_protocol_version(struct eapol_sm *sm,
enum eapol_protocol_version protocol_version);
void eapol_sm_set_supplicant_address(struct eapol_sm *sm, const uint8_t *spa);
void eapol_sm_set_authenticator_address(struct eapol_sm *sm, const uint8_t *aa);
void eapol_sm_set_pmk(struct eapol_sm *sm, const uint8_t *pmk);
void eapol_sm_set_8021x_config(struct eapol_sm *sm,
struct l_settings *settings);
void eapol_sm_set_use_eapol_start(struct eapol_sm *sm, bool enabled);
void eapol_sm_set_ap_rsn(struct eapol_sm *sm, const uint8_t *rsn_ie);
bool eapol_sm_set_own_rsn(struct eapol_sm *sm, const uint8_t *rsn_ie);
void eapol_sm_set_ap_wpa(struct eapol_sm *sm, const uint8_t *wpa_ie);
bool eapol_sm_set_own_wpa(struct eapol_sm *sm, const uint8_t *wpa_ie);
void eapol_sm_set_user_data(struct eapol_sm *sm, void *user_data);
void eapol_sm_set_event_func(struct eapol_sm *sm, eapol_sm_event_func_t func);
void eapol_sm_set_ssid(struct eapol_sm *sm, const uint8_t *ssid,
size_t ssid_len);
void eapol_sm_set_mde(struct eapol_sm *sm, const uint8_t *mde);
void eapol_sm_set_fte(struct eapol_sm *sm, const uint8_t *fte);
void eapol_sm_set_kh_ids(struct eapol_sm *sm, const uint8_t *r0khid,
size_t r0khid_len, const uint8_t *r1khid);
uint32_t eapol_sm_get_pairwise_cipher(struct eapol_sm *sm);
uint32_t eapol_sm_get_group_cipher(struct eapol_sm *sm);
const uint8_t *eapol_sm_get_own_ie(struct eapol_sm *sm, size_t *out_ie_len);
void eapol_register(uint32_t ifindex, struct eapol_sm *sm);
void eapol_register(struct eapol_sm *sm);
void eapol_start(struct eapol_sm *sm);
void eapol_cancel(uint32_t ifindex);
void eapol_pae_open();
void eapol_pae_close();

View File

@ -43,6 +43,7 @@
#include "src/ie.h"
#include "src/mpdu.h"
#include "src/eapol.h"
#include "src/handshake.h"
#include "src/crypto.h"
#include "src/device.h"
#include "src/scan.h"
@ -63,6 +64,7 @@ struct netdev {
netdev_disconnect_cb_t disconnect_cb;
void *user_data;
struct eapol_sm *sm;
struct handshake_state *handshake;
uint8_t remote_addr[ETH_ALEN];
uint32_t pairwise_new_key_cmd_id;
uint32_t pairwise_set_key_cmd_id;
@ -78,7 +80,6 @@ struct netdev {
bool connected : 1;
bool operational : 1;
bool eapol_active : 1;
bool rekey_offload_support : 1;
};
@ -278,9 +279,9 @@ static void netdev_connect_free(struct netdev *netdev)
netdev->sm = NULL;
}
if (netdev->eapol_active) {
eapol_cancel(netdev->index);
netdev->eapol_active = false;
if (netdev->handshake) {
handshake_state_free(netdev->handshake);
netdev->handshake = NULL;
}
netdev->operational = false;
@ -987,7 +988,7 @@ static void netdev_handshake_failed(uint32_t ifindex,
l_error("4-Way Handshake failed for ifindex: %d", ifindex);
netdev->eapol_active = false;
netdev->sm = NULL;
netdev->result = NETDEV_RESULT_HANDSHAKE_FAILED;
msg = netdev_build_cmd_deauthenticate(netdev, reason_code);
@ -1138,17 +1139,17 @@ static void netdev_connect_event(struct l_genl_msg *msg,
* in a non-RSN (12.4.2 vs. 12.4.3).
*/
if (netdev->mde && !netdev->sm && fte)
if (netdev->mde && !netdev->handshake && fte)
goto error;
if (netdev->mde && netdev->sm) {
if (netdev->mde && netdev->handshake) {
struct ie_ft_info ft_info;
uint8_t zeros[32];
if (!fte)
goto error;
eapol_sm_set_fte(netdev->sm, fte);
handshake_state_set_fte(netdev->handshake, fte);
if (ie_parse_fast_bss_transition_from_data(fte,
fte[1] + 2,
@ -1168,19 +1169,19 @@ static void netdev_connect_event(struct l_genl_msg *msg,
memcmp(ft_info.snonce, zeros, 32))
goto error;
eapol_sm_set_kh_ids(netdev->sm, ft_info.r0khid,
ft_info.r0khid_len,
ft_info.r1khid);
handshake_state_set_kh_ids(netdev->handshake,
ft_info.r0khid,
ft_info.r0khid_len,
ft_info.r1khid);
}
}
if (netdev->eapol_active) {
if (netdev->sm) {
/*
* Start processing EAPoL frames now that the state machine
* has all the input data even in FT mode.
*/
eapol_start(netdev->sm);
netdev->sm = NULL;
if (netdev->event_filter)
netdev->event_filter(netdev,
@ -1229,9 +1230,11 @@ static void netdev_cmd_connect_cb(struct l_genl_msg *msg, void *user_data)
* events can be reversed (e.g. connect_event, then PAE data)
* due to scheduling
*/
if (netdev->sm) {
eapol_register(netdev->index, netdev->sm);
netdev->eapol_active = true;
if (netdev->handshake) {
if (!netdev->sm)
netdev->sm = eapol_sm_new(netdev->handshake);
eapol_register(netdev->sm);
}
return;
@ -1242,9 +1245,9 @@ static void netdev_cmd_connect_cb(struct l_genl_msg *msg, void *user_data)
}
static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
struct scan_bss *bss,
struct eapol_sm *sm,
const uint8_t *mde)
struct scan_bss *bss,
struct handshake_state *hs,
const uint8_t *mde)
{
uint32_t auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
struct l_genl_msg *msg;
@ -1263,14 +1266,10 @@ static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
if (bss->capability & IE_BSS_CAP_PRIVACY)
l_genl_msg_append_attr(msg, NL80211_ATTR_PRIVACY, 0, NULL);
if (sm) {
uint32_t cipher;
if (hs) {
uint32_t nl_cipher;
size_t ie_len;
const uint8_t *ie;
cipher = eapol_sm_get_pairwise_cipher(sm);
if (cipher == IE_RSN_CIPHER_SUITE_CCMP)
if (hs->pairwise_cipher == IE_RSN_CIPHER_SUITE_CCMP)
nl_cipher = CRYPTO_CIPHER_CCMP;
else
nl_cipher = CRYPTO_CIPHER_TKIP;
@ -1278,8 +1277,7 @@ static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
l_genl_msg_append_attr(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
4, &nl_cipher);
cipher = eapol_sm_get_group_cipher(sm);
if (cipher == IE_RSN_CIPHER_SUITE_CCMP)
if (hs->group_cipher == IE_RSN_CIPHER_SUITE_CCMP)
nl_cipher = CRYPTO_CIPHER_CCMP;
else
nl_cipher = CRYPTO_CIPHER_TKIP;
@ -1289,10 +1287,9 @@ static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
l_genl_msg_append_attr(msg, NL80211_ATTR_CONTROL_PORT, 0, NULL);
ie = eapol_sm_get_own_ie(sm, &ie_len);
if (ie) {
iov[iov_elems].iov_base = (void *) ie;
iov[iov_elems].iov_len = ie_len;
if (hs->own_ie) {
iov[iov_elems].iov_base = (void *) hs->own_ie;
iov[iov_elems].iov_len = hs->own_ie[1] + 2;
iov_elems += 1;
}
}
@ -1312,8 +1309,8 @@ static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
static int netdev_connect_common(struct netdev *netdev,
struct l_genl_msg *cmd_connect,
struct scan_bss *bss,
struct eapol_sm *sm,
const uint8_t *mde,
struct handshake_state *hs,
struct eapol_sm *sm, const uint8_t *mde,
netdev_event_func_t event_filter,
netdev_connect_cb_t cb, void *user_data)
{
@ -1331,18 +1328,23 @@ static int netdev_connect_common(struct netdev *netdev,
netdev->user_data = user_data;
memcpy(netdev->remote_addr, bss->addr, ETH_ALEN);
netdev->connected = true;
netdev->handshake = hs;
netdev->sm = sm;
if (mde)
netdev->mde = l_memdup(mde, mde[1] + 2);
if (hs) {
handshake_state_set_authenticator_address(hs, bss->addr);
handshake_state_set_supplicant_address(hs, netdev->addr);
}
return 0;
}
int netdev_connect(struct netdev *netdev, struct scan_bss *bss,
struct eapol_sm *sm,
const uint8_t *mde,
struct handshake_state *hs, const uint8_t *mde,
netdev_event_func_t event_filter,
netdev_connect_cb_t cb, void *user_data)
{
@ -1351,16 +1353,16 @@ int netdev_connect(struct netdev *netdev, struct scan_bss *bss,
if (netdev->connected)
return -EISCONN;
cmd_connect = netdev_build_cmd_connect(netdev, bss, sm, mde);
cmd_connect = netdev_build_cmd_connect(netdev, bss, hs, mde);
if (!cmd_connect)
return -EINVAL;
return netdev_connect_common(netdev, cmd_connect, bss, sm, mde,
return netdev_connect_common(netdev, cmd_connect, bss, hs, NULL, mde,
event_filter, cb, user_data);
}
int netdev_connect_wsc(struct netdev *netdev, struct scan_bss *bss,
struct eapol_sm *sm,
struct handshake_state *hs, struct eapol_sm *sm,
netdev_event_func_t event_filter,
netdev_connect_cb_t cb, void *user_data)
{
@ -1394,7 +1396,7 @@ int netdev_connect_wsc(struct netdev *netdev, struct scan_bss *bss,
l_genl_msg_append_attr(cmd_connect, NL80211_ATTR_IE, ie_len, ie);
l_free(ie);
return netdev_connect_common(netdev, cmd_connect, bss, sm, NULL,
return netdev_connect_common(netdev, cmd_connect, bss, hs, sm, NULL,
event_filter, cb, user_data);
error:
@ -1957,9 +1959,10 @@ bool netdev_init(struct l_genl_family *in,
NULL, NULL))
l_error("Registering for MLME notification failed");
__eapol_set_install_tk_func(netdev_set_tk);
__eapol_set_install_gtk_func(netdev_set_gtk);
__eapol_set_install_igtk_func(netdev_set_igtk);
__handshake_set_install_tk_func(netdev_set_tk);
__handshake_set_install_gtk_func(netdev_set_gtk);
__handshake_set_install_igtk_func(netdev_set_igtk);
__eapol_set_deauthenticate_func(netdev_handshake_failed);
__eapol_set_rekey_offload_func(netdev_set_rekey_offload);

View File

@ -24,7 +24,8 @@
struct netdev;
struct scan_bss;
struct eapol_sm *sm;
struct handshake_state;
struct eapol_sm;
enum netdev_result {
NETDEV_RESULT_OK,
@ -73,11 +74,11 @@ const char *netdev_get_name(struct netdev *netdev);
bool netdev_get_is_up(struct netdev *netdev);
int netdev_connect(struct netdev *netdev, struct scan_bss *bss,
struct eapol_sm *sm, const uint8_t *mde,
struct handshake_state *hs, const uint8_t *mde,
netdev_event_func_t event_filter,
netdev_connect_cb_t cb, void *user_data);
int netdev_connect_wsc(struct netdev *netdev, struct scan_bss *bss,
struct eapol_sm *sm,
struct handshake_state *hs, struct eapol_sm *sm,
netdev_event_func_t event_filter,
netdev_connect_cb_t cb, void *user_data);
int netdev_disconnect(struct netdev *netdev,

View File

@ -36,6 +36,7 @@
#include "src/wscutil.h"
#include "src/util.h"
#include "src/wsc.h"
#include "src/handshake.h"
#include "src/eapol.h"
#include "src/eap-wsc.h"
#include "src/crypto.h"
@ -66,6 +67,7 @@ struct wsc {
uint8_t addr[6];
} creds[3];
uint32_t n_creds;
struct l_settings *eap_settings;
bool wsc_association : 1;
};
@ -203,6 +205,9 @@ static void wsc_connect_cb(struct netdev *netdev, enum netdev_result result,
wsc->wsc_association = false;
l_settings_free(wsc->eap_settings);
wsc->eap_settings = NULL;
if (result == NETDEV_RESULT_HANDSHAKE_FAILED && wsc->n_creds > 0) {
wsc_store_credentials(wsc);
wsc_try_credentials(wsc);
@ -390,14 +395,17 @@ static inline enum wsc_rf_band freq_to_rf_band(uint32_t freq)
static void wsc_connect(struct wsc *wsc)
{
struct eapol_sm *sm = eapol_sm_new();
struct handshake_state *hs;
struct eapol_sm *sm;
struct l_settings *settings = l_settings_new();
struct scan_bss *bss = wsc->target;
uint32_t ifindex = netdev_get_ifindex(device_get_netdev(wsc->device));
wsc->target = NULL;
eapol_sm_set_authenticator_address(sm, bss->addr);
eapol_sm_set_supplicant_address(sm, device_get_address(wsc->device));
hs = handshake_state_new(ifindex);
sm = eapol_sm_new(hs);
eapol_sm_set_user_data(sm, wsc);
eapol_sm_set_event_func(sm, wsc_eapol_event);
@ -417,11 +425,12 @@ static void wsc_connect(struct wsc *wsc)
l_settings_set_string(settings, "WSC", "EnrolleeMAC",
util_address_to_string(device_get_address(wsc->device)));
eapol_sm_set_8021x_config(sm, settings);
l_settings_free(settings);
handshake_state_set_8021x_config(hs, settings);
wsc->eap_settings = settings;
eapol_sm_set_use_eapol_start(sm, true);
if (netdev_connect_wsc(device_get_netdev(wsc->device), bss, sm,
if (netdev_connect_wsc(device_get_netdev(wsc->device), bss, hs, sm,
wsc_netdev_event,
wsc_connect_cb, wsc) < 0) {
eapol_sm_free(sm);
@ -769,6 +778,9 @@ static void wsc_free(void *userdata)
dbus_pending_reply(&wsc->pending_cancel,
dbus_error_aborted(wsc->pending_cancel));
if (wsc->eap_settings)
l_settings_free(wsc->eap_settings);
l_free(wsc);
}