3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-11-26 10:39:23 +01:00

eapol: refactor eapol_find_kde and add install_igtk

This commit is contained in:
Rahul Rahul 2016-10-25 14:45:16 -07:00 committed by Denis Kenzior
parent 318d3a2d35
commit c16ae02056
2 changed files with 98 additions and 9 deletions

View File

@ -47,6 +47,7 @@ struct l_queue *state_machines;
eapol_get_nonce_func_t get_nonce = NULL; eapol_get_nonce_func_t get_nonce = NULL;
eapol_install_tk_func_t install_tk = NULL; eapol_install_tk_func_t install_tk = NULL;
eapol_install_gtk_func_t install_gtk = NULL; eapol_install_gtk_func_t install_gtk = NULL;
eapol_install_igtk_func_t install_igtk = NULL;
eapol_deauthenticate_func_t deauthenticate = NULL; eapol_deauthenticate_func_t deauthenticate = NULL;
eapol_rekey_offload_func_t rekey_offload = NULL; eapol_rekey_offload_func_t rekey_offload = NULL;
@ -722,6 +723,7 @@ struct eapol_sm {
uint8_t *own_ie; uint8_t *own_ie;
enum ie_rsn_cipher_suite pairwise_cipher; enum ie_rsn_cipher_suite pairwise_cipher;
enum ie_rsn_cipher_suite group_cipher; enum ie_rsn_cipher_suite group_cipher;
enum ie_rsn_cipher_suite group_management_cipher;
enum ie_rsn_akm_suite akm_suite; enum ie_rsn_akm_suite akm_suite;
uint8_t pmk[32]; uint8_t pmk[32];
uint64_t replay_counter; uint64_t replay_counter;
@ -739,6 +741,7 @@ struct eapol_sm {
bool have_pmk:1; bool have_pmk:1;
bool started:1; bool started:1;
bool use_eapol_start:1; bool use_eapol_start:1;
bool mfpc:1;
struct eap_state *eap; struct eap_state *eap;
struct eapol_buffer *early_frame; struct eapol_buffer *early_frame;
}; };
@ -836,7 +839,9 @@ static bool eapol_sm_setup_own_ciphers(struct eapol_sm *sm,
sm->akm_suite = info->akm_suites; sm->akm_suite = info->akm_suites;
sm->pairwise_cipher = info->pairwise_ciphers; sm->pairwise_cipher = info->pairwise_ciphers;
sm->group_cipher = info->group_cipher; sm->group_cipher = info->group_cipher;
sm->group_management_cipher = info->group_management_cipher;
sm->mfpc = info->mfpc;
return true; return true;
} }
@ -1015,12 +1020,12 @@ static void eapol_handle_ptk_1_of_4(uint32_t ifindex, struct eapol_sm *sm,
sm->timeout = NULL; sm->timeout = NULL;
} }
static const uint8_t *eapol_find_gtk_kde(const uint8_t *data, size_t data_len, static const uint8_t *eapol_find_kde(const uint8_t *data, size_t data_len,
size_t *out_gtk_len) size_t *out_len,
const unsigned char *oui)
{ {
static const unsigned char gtk_oui[] = { 0x00, 0x0f, 0xac, 0x01 };
struct ie_tlv_iter iter; struct ie_tlv_iter iter;
const uint8_t *gtk; const uint8_t *result;
unsigned int len; unsigned int len;
ie_tlv_iter_init(&iter, data, data_len); ie_tlv_iter_init(&iter, data, data_len);
@ -1034,19 +1039,38 @@ static const uint8_t *eapol_find_gtk_kde(const uint8_t *data, size_t data_len,
return NULL; return NULL;
/* Check OUI */ /* Check OUI */
gtk = ie_tlv_iter_get_data(&iter); result = ie_tlv_iter_get_data(&iter);
if (memcmp(gtk, gtk_oui, 4)) if (memcmp(result, oui, 4))
continue; continue;
if (out_gtk_len) if (out_len)
*out_gtk_len = len - 4; *out_len = len - 4;
return gtk + 4; return result + 4;
} }
return NULL; return NULL;
} }
static const uint8_t *eapol_find_gtk_kde(const uint8_t *data, size_t data_len,
size_t *out_gtk_len)
{
static const unsigned char gtk_oui[] = { 0x00, 0x0f, 0xac, 0x01 };
return eapol_find_kde(data, data_len,
out_gtk_len, gtk_oui);
}
static const uint8_t *eapol_find_igtk_kde(const uint8_t *data, size_t data_len,
size_t *out_igtk_len)
{
static const unsigned char igtk_oui[] = { 0x00, 0x0f, 0xac, 0x09 };
return eapol_find_kde(data, data_len,
out_igtk_len, igtk_oui);
}
static const uint8_t *eapol_find_rsne(const uint8_t *data, size_t data_len, static const uint8_t *eapol_find_rsne(const uint8_t *data, size_t data_len,
const uint8_t **optional) const uint8_t **optional)
{ {
@ -1194,9 +1218,12 @@ static void eapol_handle_ptk_3_of_4(uint32_t ifindex,
uint8_t mic[16]; uint8_t mic[16];
const uint8_t *gtk; const uint8_t *gtk;
size_t gtk_len; size_t gtk_len;
const uint8_t *igtk;
size_t igtk_len;
const uint8_t *rsne; const uint8_t *rsne;
const uint8_t *optional_rsne = NULL; const uint8_t *optional_rsne = NULL;
uint8_t gtk_key_index; uint8_t gtk_key_index;
uint8_t igtk_key_index;
enum ie_rsn_cipher_suite pairwise = sm->pairwise_cipher; enum ie_rsn_cipher_suite pairwise = sm->pairwise_cipher;
if (!eapol_verify_ptk_3_of_4(ek, sm->wpa_ie)) { if (!eapol_verify_ptk_3_of_4(ek, sm->wpa_ie)) {
@ -1319,6 +1346,22 @@ static void eapol_handle_ptk_3_of_4(uint32_t ifindex,
} else } else
gtk = NULL; gtk = NULL;
if (sm->mfpc) {
igtk = eapol_find_igtk_kde(decrypted_key_data,
decrypted_key_data_size,
&igtk_len);
if (!igtk || igtk_len < 8) {
handshake_failed(ifindex, sm,
MPDU_REASON_CODE_UNSPECIFIED);
return;
}
igtk_key_index = util_bit_field(igtk[0], 0, 2);
igtk += 2;
igtk_len -= 2;
} else
igtk = NULL;
step4 = eapol_create_ptk_4_of_4(sm->protocol_version, step4 = eapol_create_ptk_4_of_4(sm->protocol_version,
ek->key_descriptor_version, ek->key_descriptor_version,
sm->replay_counter, sm->wpa_ie); sm->replay_counter, sm->wpa_ie);
@ -1351,6 +1394,16 @@ static void eapol_handle_ptk_3_of_4(uint32_t ifindex,
ek->key_rsc, 6, cipher, sm->user_data); ek->key_rsc, 6, cipher, sm->user_data);
} }
if (igtk && install_igtk) {
uint32_t cipher =
ie_rsn_cipher_suite_to_cipher(
sm->group_management_cipher);
install_igtk(sm->ifindex, igtk_key_index, igtk + 6,
igtk_len - 6, igtk, 6, cipher,
sm->user_data);
}
if (rekey_offload) if (rekey_offload)
rekey_offload(sm->ifindex, ptk->kek, ptk->kck, rekey_offload(sm->ifindex, ptk->kek, ptk->kck,
sm->replay_counter, sm->user_data); sm->replay_counter, sm->user_data);
@ -1371,6 +1424,9 @@ static void eapol_handle_gtk_1_of_2(uint32_t ifindex,
const uint8_t *gtk; const uint8_t *gtk;
size_t gtk_len; size_t gtk_len;
uint8_t gtk_key_index; uint8_t gtk_key_index;
const uint8_t *igtk;
size_t igtk_len;
uint8_t igtk_key_index;
if (!eapol_verify_gtk_1_of_2(ek, sm->wpa_ie)) { if (!eapol_verify_gtk_1_of_2(ek, sm->wpa_ie)) {
handshake_failed(ifindex, sm, MPDU_REASON_CODE_UNSPECIFIED); handshake_failed(ifindex, sm, MPDU_REASON_CODE_UNSPECIFIED);
@ -1399,6 +1455,19 @@ static void eapol_handle_gtk_1_of_2(uint32_t ifindex,
} else } else
gtk_key_index = ek->wpa_key_id; gtk_key_index = ek->wpa_key_id;
if (sm->mfpc) {
igtk = eapol_find_igtk_kde(decrypted_key_data,
decrypted_key_data_size,
&igtk_len);
if (!igtk || igtk_len < 8)
return;
igtk_key_index = util_bit_field(igtk[0], 0, 2);
igtk += 2;
igtk_len -= 2;
} else
igtk = NULL;
step2 = eapol_create_gtk_2_of_2(sm->protocol_version, step2 = eapol_create_gtk_2_of_2(sm->protocol_version,
ek->key_descriptor_version, ek->key_descriptor_version,
sm->replay_counter, sm->wpa_ie, sm->replay_counter, sm->wpa_ie,
@ -1425,6 +1494,16 @@ static void eapol_handle_gtk_1_of_2(uint32_t ifindex,
ek->key_rsc, 6, cipher, sm->user_data); ek->key_rsc, 6, cipher, sm->user_data);
} }
if (igtk && install_igtk) {
uint32_t cipher =
ie_rsn_cipher_suite_to_cipher(
sm->group_management_cipher);
install_igtk(sm->ifindex, igtk_key_index, igtk + 6,
igtk_len - 6, igtk, 6, cipher,
sm->user_data);
}
done: done:
l_free(step2); l_free(step2);
} }
@ -1782,6 +1861,11 @@ void __eapol_set_install_gtk_func(eapol_install_gtk_func_t func)
install_gtk = func; install_gtk = func;
} }
void __eapol_set_install_igtk_func(eapol_install_igtk_func_t func)
{
install_igtk = func;
}
void __eapol_set_deauthenticate_func(eapol_deauthenticate_func_t func) void __eapol_set_deauthenticate_func(eapol_deauthenticate_func_t func)
{ {
deauthenticate = func; deauthenticate = func;

View File

@ -116,6 +116,10 @@ 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 *gtk, uint8_t gtk_len,
const uint8_t *rsc, uint8_t rsc_len, const uint8_t *rsc, uint8_t rsc_len,
uint32_t cipher, void *user_data); 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, typedef void (*eapol_deauthenticate_func_t)(uint32_t ifindex, const uint8_t *aa,
const uint8_t *spa, const uint8_t *spa,
uint16_t reason_code, uint16_t reason_code,
@ -175,6 +179,7 @@ void __eapol_set_tx_user_data(void *user_data);
void __eapol_set_get_nonce_func(eapol_get_nonce_func_t func); 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_tk_func(eapol_install_tk_func_t func);
void __eapol_set_install_gtk_func(eapol_install_gtk_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_deauthenticate_func(eapol_deauthenticate_func_t func);
void __eapol_set_rekey_offload_func(eapol_rekey_offload_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, void __eapol_update_replay_counter(uint32_t ifindex, const uint8_t *spa,