mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-12-22 13:02:44 +01:00
eapol: IP Allocation KDE support
Support IP allocation during the 4-Way Handshake as defined in the P2P spec. This is the supplicant side implementation. The API requires the user to set hs->support_ip_allocation true before eapol_start(). On HANDSHAKE_EVENT_COMPLETE, if this same flag is still set, we've received the IP lease, the netmask and the authenticator's IP from the authenticator and there's no need to start DHCP. If the flag is cleared, the user needs to use DHCP.
This commit is contained in:
parent
4fa4cc5867
commit
ddf111d2c4
76
src/eapol.c
76
src/eapol.c
@ -1088,7 +1088,7 @@ static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm,
|
||||
const uint8_t *kck;
|
||||
struct eapol_key *step2;
|
||||
uint8_t mic[MIC_MAXLEN];
|
||||
uint8_t *ies;
|
||||
uint8_t ies[512];
|
||||
size_t ies_len;
|
||||
const uint8_t *own_ie = sm->handshake->supplicant_ie;
|
||||
const uint8_t *pmkid;
|
||||
@ -1199,8 +1199,6 @@ static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm,
|
||||
* Rebuild the RSNE to include the PMKR1Name and append
|
||||
* MDE + FTE.
|
||||
*/
|
||||
ies = alloca(512);
|
||||
|
||||
rsn_info.num_pmkids = 1;
|
||||
rsn_info.pmkids = sm->handshake->pmk_r1_name;
|
||||
|
||||
@ -1214,7 +1212,16 @@ static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm,
|
||||
ies_len += fte[1] + 2;
|
||||
} else {
|
||||
ies_len = own_ie[1] + 2;
|
||||
ies = (uint8_t *) own_ie;
|
||||
memcpy(ies, own_ie, ies_len);
|
||||
}
|
||||
|
||||
if (sm->handshake->support_ip_allocation) {
|
||||
/* Wi-Fi P2P Technical Specification v1.7 Table 58 */
|
||||
ies[ies_len++] = IE_TYPE_VENDOR_SPECIFIC;
|
||||
ies[ies_len++] = 4 + 1;
|
||||
l_put_be32(HANDSHAKE_KDE_IP_ADDRESS_REQ, ies + ies_len);
|
||||
ies_len += 4;
|
||||
ies[ies_len++] = 0x01;
|
||||
}
|
||||
|
||||
step2 = eapol_create_ptk_2_of_4(sm->protocol_version,
|
||||
@ -1381,7 +1388,8 @@ static const uint8_t *eapol_find_rsne(const uint8_t *data, size_t data_len,
|
||||
return first;
|
||||
}
|
||||
|
||||
static const uint8_t *eapol_find_osen(const uint8_t *data, size_t data_len)
|
||||
static const uint8_t *eapol_find_wfa_kde(const uint8_t *data, size_t data_len,
|
||||
uint8_t oi_type)
|
||||
{
|
||||
struct ie_tlv_iter iter;
|
||||
|
||||
@ -1389,7 +1397,7 @@ static const uint8_t *eapol_find_osen(const uint8_t *data, size_t data_len)
|
||||
|
||||
while (ie_tlv_iter_next(&iter)) {
|
||||
if (ie_tlv_iter_get_tag(&iter) == IE_TYPE_VENDOR_SPECIFIC) {
|
||||
if (!is_ie_wfa_ie(iter.data, iter.len, IE_WFA_OI_OSEN))
|
||||
if (!is_ie_wfa_ie(iter.data, iter.len, oi_type))
|
||||
continue;
|
||||
} else
|
||||
continue;
|
||||
@ -1474,6 +1482,28 @@ static const uint8_t *eapol_find_wpa_ie(const uint8_t *data, size_t data_len)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool eapol_check_ip_mask(const uint8_t *mask,
|
||||
const uint8_t *ip1, const uint8_t *ip2)
|
||||
{
|
||||
uint32_t mask_uint = l_get_be32(mask);
|
||||
uint32_t ip1_uint = l_get_be32(ip1);
|
||||
uint32_t ip2_uint = l_get_be32(ip2);
|
||||
|
||||
return
|
||||
/* Check IPs are in the same subnet */
|
||||
((ip1_uint ^ ip2_uint) & mask_uint) == 0 &&
|
||||
/* Check IPs are different */
|
||||
ip1_uint != ip2_uint &&
|
||||
/* Check IPs are not subnet addresses */
|
||||
(ip1_uint & ~mask_uint) != 0 &&
|
||||
(ip2_uint & ~mask_uint) != 0 &&
|
||||
/* Check IPs are not broadcast addresses */
|
||||
(ip1_uint | mask_uint) != 0xffffffff &&
|
||||
(ip2_uint | mask_uint) != 0xffffffff &&
|
||||
/* Check the 1s are at the start of the mask */
|
||||
(uint32_t) (mask_uint << __builtin_popcountl(mask_uint)) == 0;
|
||||
}
|
||||
|
||||
static void eapol_handle_ptk_3_of_4(struct eapol_sm *sm,
|
||||
const struct eapol_key *ek,
|
||||
const uint8_t *decrypted_key_data,
|
||||
@ -1520,8 +1550,9 @@ static void eapol_handle_ptk_3_of_4(struct eapol_sm *sm,
|
||||
rsne = eapol_find_wpa_ie(decrypted_key_data,
|
||||
decrypted_key_data_size);
|
||||
else if (sm->handshake->osen_ie)
|
||||
rsne = eapol_find_osen(decrypted_key_data,
|
||||
decrypted_key_data_size);
|
||||
rsne = eapol_find_wfa_kde(decrypted_key_data,
|
||||
decrypted_key_data_size,
|
||||
IE_WFA_OI_OSEN);
|
||||
else
|
||||
rsne = eapol_find_rsne(decrypted_key_data,
|
||||
decrypted_key_data_size,
|
||||
@ -1667,6 +1698,35 @@ static void eapol_handle_ptk_3_of_4(struct eapol_sm *sm,
|
||||
} else
|
||||
igtk = NULL;
|
||||
|
||||
if (sm->handshake->support_ip_allocation) {
|
||||
const uint8_t *ip_alloc_kde =
|
||||
eapol_find_wfa_kde(decrypted_key_data,
|
||||
decrypted_key_data_size,
|
||||
HANDSHAKE_KDE_IP_ADDRESS_ALLOC & 255);
|
||||
|
||||
if (ip_alloc_kde &&
|
||||
(ip_alloc_kde[1] < 16 ||
|
||||
!eapol_check_ip_mask(ip_alloc_kde + 10,
|
||||
ip_alloc_kde + 6,
|
||||
ip_alloc_kde + 14))) {
|
||||
l_debug("Invalid IP Allocation KDE in frame 3/4");
|
||||
handshake_failed(sm, MMPDU_REASON_CODE_INVALID_IE);
|
||||
return;
|
||||
}
|
||||
|
||||
sm->handshake->support_ip_allocation = ip_alloc_kde != NULL;
|
||||
|
||||
if (ip_alloc_kde) {
|
||||
sm->handshake->client_ip_addr =
|
||||
l_get_be32(ip_alloc_kde + 6);
|
||||
sm->handshake->subnet_mask =
|
||||
l_get_be32(ip_alloc_kde + 10);
|
||||
sm->handshake->go_ip_addr =
|
||||
l_get_be32(ip_alloc_kde + 14);
|
||||
} else
|
||||
l_debug("Authenticator ignored our IP Address Request");
|
||||
}
|
||||
|
||||
retransmit:
|
||||
/*
|
||||
* 802.11-2016, Section 12.7.6.4:
|
||||
|
@ -28,8 +28,8 @@
|
||||
struct handshake_state;
|
||||
enum crypto_cipher;
|
||||
|
||||
/* 802.11-2016 Table 12-6 in section 12.7.2 */
|
||||
enum handshake_kde {
|
||||
/* 802.11-2016 Table 12-6 in section 12.7.2 */
|
||||
HANDSHAKE_KDE_GTK = 0x000fac01,
|
||||
HANDSHAKE_KDE_MAC_ADDRESS = 0x000fac03,
|
||||
HANDSHAKE_KDE_PMKID = 0x000fac04,
|
||||
@ -41,6 +41,9 @@ enum handshake_kde {
|
||||
HANDSHAKE_KDE_KEY_ID = 0x000fac0a,
|
||||
HANDSHAKE_KDE_MULTIBAND_GTK = 0x000fac0b,
|
||||
HANDSHAKE_KDE_MULTIBAND_KEY_ID = 0x000fac0c,
|
||||
/* Wi-Fi P2P Technical Specification v1.7 4.2.8 */
|
||||
HANDSHAKE_KDE_IP_ADDRESS_REQ = 0x506f9a04,
|
||||
HANDSHAKE_KDE_IP_ADDRESS_ALLOC = 0x506f9a05,
|
||||
};
|
||||
|
||||
enum handshake_event {
|
||||
@ -124,6 +127,10 @@ struct handshake_state {
|
||||
uint8_t proto_version : 2;
|
||||
unsigned int gtk_index;
|
||||
struct erp_cache_entry *erp_cache;
|
||||
bool support_ip_allocation : 1;
|
||||
uint32_t client_ip_addr;
|
||||
uint32_t subnet_mask;
|
||||
uint32_t go_ip_addr;
|
||||
void *user_data;
|
||||
|
||||
void (*free)(struct handshake_state *s);
|
||||
|
Loading…
Reference in New Issue
Block a user