mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-12-19 18:22:32 +01:00
eapol: Handle the Group Key Handshake
This commit is contained in:
parent
1795105c60
commit
a8c0f20510
131
src/eapol.c
131
src/eapol.c
@ -369,6 +369,50 @@ bool eapol_verify_ptk_4_of_4(const struct eapol_key *ek)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool eapol_verify_gtk_1_of_2(const struct eapol_key *ek, bool is_wpa)
|
||||
{
|
||||
uint16_t key_len;
|
||||
|
||||
if (ek->key_type)
|
||||
return false;
|
||||
if (ek->smk_message)
|
||||
return false;
|
||||
if (ek->request)
|
||||
return false;
|
||||
if (ek->error)
|
||||
return false;
|
||||
|
||||
if (!ek->key_ack)
|
||||
return false;
|
||||
|
||||
if (!ek->key_mic)
|
||||
return false;
|
||||
|
||||
if (!ek->secure)
|
||||
return false;
|
||||
|
||||
/* Must be encrypted when GTK is present but reserved in WPA */
|
||||
if (!ek->encrypted_key_data && !is_wpa)
|
||||
return false;
|
||||
|
||||
key_len = L_BE16_TO_CPU(ek->key_length);
|
||||
if (key_len == 0)
|
||||
return false;
|
||||
|
||||
VERIFY_IS_ZERO(ek->reserved);
|
||||
|
||||
/* 0 (Version 2) or random (Version 1) */
|
||||
if (ek->key_descriptor_version ==
|
||||
EAPOL_KEY_DESCRIPTOR_VERSION_HMAC_SHA1_AES)
|
||||
VERIFY_IS_ZERO(ek->eapol_key_iv);
|
||||
|
||||
/* Key ID shall not be 0 */
|
||||
if (is_wpa && !ek->wpa_key_id)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct eapol_key *eapol_create_common(
|
||||
enum eapol_protocol_version protocol,
|
||||
enum eapol_key_descriptor_version version,
|
||||
@ -376,7 +420,8 @@ static struct eapol_key *eapol_create_common(
|
||||
uint64_t key_replay_counter,
|
||||
const uint8_t snonce[],
|
||||
size_t extra_len,
|
||||
const uint8_t *extra_data)
|
||||
const uint8_t *extra_data,
|
||||
int key_type)
|
||||
{
|
||||
size_t to_alloc = sizeof(struct eapol_key);
|
||||
struct eapol_key *out_frame = l_malloc(to_alloc + extra_len);
|
||||
@ -388,7 +433,7 @@ static struct eapol_key *eapol_create_common(
|
||||
out_frame->packet_len = L_CPU_TO_BE16(to_alloc + extra_len - 4);
|
||||
out_frame->descriptor_type = EAPOL_DESCRIPTOR_TYPE_80211;
|
||||
out_frame->key_descriptor_version = version;
|
||||
out_frame->key_type = true;
|
||||
out_frame->key_type = key_type;
|
||||
out_frame->install = false;
|
||||
out_frame->key_ack = false;
|
||||
out_frame->key_mic = true;
|
||||
@ -415,7 +460,7 @@ struct eapol_key *eapol_create_ptk_2_of_4(
|
||||
const uint8_t *extra_data)
|
||||
{
|
||||
return eapol_create_common(protocol, version, false, key_replay_counter,
|
||||
snonce, extra_len, extra_data);
|
||||
snonce, extra_len, extra_data, 1);
|
||||
}
|
||||
|
||||
struct eapol_key *eapol_create_ptk_4_of_4(
|
||||
@ -427,7 +472,20 @@ struct eapol_key *eapol_create_ptk_4_of_4(
|
||||
|
||||
memset(snonce, 0, sizeof(snonce));
|
||||
return eapol_create_common(protocol, version, true, key_replay_counter,
|
||||
snonce, 0, NULL);
|
||||
snonce, 0, NULL, 1);
|
||||
}
|
||||
|
||||
static struct eapol_key *eapol_create_gtk_2_of_2(
|
||||
enum eapol_protocol_version protocol,
|
||||
enum eapol_key_descriptor_version version,
|
||||
uint64_t key_replay_counter)
|
||||
{
|
||||
uint8_t snonce[32];
|
||||
|
||||
memset(snonce, 0, sizeof(snonce));
|
||||
return eapol_create_common(protocol, version, true,
|
||||
key_replay_counter, snonce, 0, NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
struct eapol_sm {
|
||||
@ -860,6 +918,61 @@ fail:
|
||||
l_free(step4);
|
||||
}
|
||||
|
||||
static void eapol_handle_gtk_1_of_2(uint32_t ifindex,
|
||||
struct eapol_sm *sm,
|
||||
const struct eapol_key *ek,
|
||||
const uint8_t *decrypted_key_data,
|
||||
size_t decrypted_key_data_size,
|
||||
void *user_data)
|
||||
{
|
||||
struct crypto_ptk *ptk = (struct crypto_ptk *) sm->ptk;
|
||||
struct eapol_key *step2;
|
||||
uint8_t mic[16];
|
||||
const uint8_t *gtk;
|
||||
size_t gtk_len;
|
||||
uint8_t gtk_key_index;
|
||||
|
||||
if (!eapol_verify_gtk_1_of_2(ek, sm->wpa_ie)) {
|
||||
handshake_failed(ifindex, sm, MPDU_REASON_CODE_UNSPECIFIED);
|
||||
return;
|
||||
}
|
||||
|
||||
gtk = eapol_find_gtk_kde(decrypted_key_data,
|
||||
decrypted_key_data_size,
|
||||
>k_len);
|
||||
|
||||
if (!gtk || gtk_len < 8)
|
||||
return;
|
||||
|
||||
gtk_key_index = util_bit_field(gtk[0], 0, 2);
|
||||
gtk += 2;
|
||||
gtk_len -= 2;
|
||||
|
||||
step2 = eapol_create_gtk_2_of_2(protocol_version,
|
||||
ek->key_descriptor_version,
|
||||
sm->replay_counter);
|
||||
|
||||
/*
|
||||
* 802.11-2012, Section 11.6.7.3, step b):
|
||||
* Verifies that the MIC is valid, i.e., it uses the KCK that is
|
||||
* part of the PTK to verify that there is no data integrity error.
|
||||
*/
|
||||
ptk = (struct crypto_ptk *) sm->ptk;
|
||||
|
||||
if (!eapol_calculate_mic(ptk->kck, step2, mic))
|
||||
goto done;
|
||||
|
||||
memcpy(step2->key_mic_data, mic, sizeof(mic));
|
||||
tx_packet(ifindex, sm->aa, sm->spa, step2, user_data);
|
||||
|
||||
if (install_gtk)
|
||||
install_gtk(sm->ifindex, gtk_key_index, gtk, gtk_len,
|
||||
ek->key_rsc, 6, sm->ap_ie, sm->user_data);
|
||||
|
||||
done:
|
||||
l_free(step2);
|
||||
}
|
||||
|
||||
static struct eapol_sm *eapol_find_sm(uint32_t ifindex,
|
||||
const uint8_t *spa,
|
||||
const uint8_t *aa)
|
||||
@ -947,10 +1060,16 @@ void __eapol_rx_packet(uint32_t ifindex, const uint8_t *spa, const uint8_t *aa,
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: Handle Group Key Handshake */
|
||||
if (ek->key_type == 0)
|
||||
/* Check if this is the group key handshake */
|
||||
if (ek->key_type == 0) {
|
||||
if (!ek->key_mic || !ek->secure)
|
||||
goto done;
|
||||
|
||||
eapol_handle_gtk_1_of_2(ifindex, sm, ek, decrypted_key_data,
|
||||
decrypted_key_data_len, user_data);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* If no MIC, then assume packet 1, otherwise packet 3 */
|
||||
if (!ek->key_mic)
|
||||
eapol_handle_ptk_1_of_4(ifindex, sm, ek, user_data);
|
||||
|
@ -64,7 +64,7 @@ struct eapol_key {
|
||||
uint8_t reserved2:2;
|
||||
uint8_t key_descriptor_version:3;
|
||||
bool key_type:1;
|
||||
uint8_t reserved1:2;
|
||||
uint8_t wpa_key_id:2; /* Bits 4-5 reserved in RSN, Key ID in WPA */
|
||||
bool install:1;
|
||||
bool key_ack:1;
|
||||
#elif defined (__BIG_ENDIAN_BITFIELD)
|
||||
@ -77,7 +77,7 @@ struct eapol_key {
|
||||
bool key_mic:1;
|
||||
bool key_ack:1;
|
||||
bool install:1;
|
||||
uint8_t reserved1:2;
|
||||
uint8_t wpa_key_id:2; /* Bits 4-5 reserved in RSN, Key ID in WPA */
|
||||
bool key_type:1;
|
||||
uint8_t key_descriptor_version:3;
|
||||
#else
|
||||
@ -125,6 +125,7 @@ bool eapol_verify_ptk_1_of_4(const struct eapol_key *ek);
|
||||
bool eapol_verify_ptk_2_of_4(const struct eapol_key *ek);
|
||||
bool eapol_verify_ptk_3_of_4(const struct eapol_key *ek);
|
||||
bool eapol_verify_ptk_4_of_4(const struct eapol_key *ek);
|
||||
bool eapol_verify_gtk_1_of_2(const struct eapol_key *ek, bool is_wpa);
|
||||
|
||||
struct eapol_key *eapol_create_ptk_2_of_4(
|
||||
enum eapol_protocol_version protocol,
|
||||
|
Loading…
Reference in New Issue
Block a user