TDLS: Move TPK M1 sending to a separate function

Now all there TPK handshake messages are sent in similar functions
and are easier to find from the source code.
This commit is contained in:
Jouni Malinen 2011-01-26 16:38:50 +02:00 committed by Jouni Malinen
parent 2e1d335e44
commit a4c3e4b194

View file

@ -800,6 +800,183 @@ static int wpa_tdls_send_smk_error(struct wpa_sm *sm, const u8 *dst,
}
static int wpa_tdls_send_tpk_m1(struct wpa_sm *sm,
struct wpa_tdls_peer *peer)
{
size_t buf_len;
struct wpa_tdls_timeoutie timeoutie;
u16 rsn_capab;
struct wpa_tdls_ftie *ftie;
u8 *rbuf, *pos, *count_pos;
u16 count;
struct rsn_ie_hdr *hdr;
if (!wpa_tdls_get_privacy(sm)) {
wpa_printf(MSG_DEBUG, "TDLS: No security used on the link");
peer->rsnie_i_len = 0;
goto skip_rsnie;
}
/*
* TPK Handshake Message 1:
* FTIE: ANonce=0, SNonce=nonce MIC=0, DataKDs=(RSNIE_I,
* Timeout Interval IE))
*/
/* Filling RSN IE */
hdr = (struct rsn_ie_hdr *) peer->rsnie_i;
hdr->elem_id = WLAN_EID_RSN;
WPA_PUT_LE16(hdr->version, RSN_VERSION);
pos = (u8 *) (hdr + 1);
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
pos += RSN_SELECTOR_LEN;
count_pos = pos;
pos += 2;
count = 0;
/*
* AES-CCMP is the default Encryption preferred for TDLS, so
* RSN IE is filled only with CCMP CIPHER
* Note: TKIP is not used to encrypt TDLS link.
*
* Regardless of the cipher used on the AP connection, select CCMP
* here.
*/
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
pos += RSN_SELECTOR_LEN;
count++;
WPA_PUT_LE16(count_pos, count);
WPA_PUT_LE16(pos, 1);
pos += 2;
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
pos += RSN_SELECTOR_LEN;
rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
#ifdef CONFIG_TDLS_TESTING
if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) {
wpa_printf(MSG_DEBUG, "TDLS: Use alternative RSN IE for "
"testing");
rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
}
#endif /* CONFIG_TDLS_TESTING */
WPA_PUT_LE16(pos, rsn_capab);
pos += 2;
#ifdef CONFIG_TDLS_TESTING
if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) {
/* Number of PMKIDs */
*pos++ = 0x00;
*pos++ = 0x00;
}
#endif /* CONFIG_TDLS_TESTING */
hdr->len = (pos - peer->rsnie_i) - 2;
peer->rsnie_i_len = pos - peer->rsnie_i;
wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake",
peer->rsnie_i, peer->rsnie_i_len);
skip_rsnie:
buf_len = 0;
if (wpa_tdls_get_privacy(sm))
buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
sizeof(struct wpa_tdls_timeoutie);
#ifdef CONFIG_TDLS_TESTING
if (wpa_tdls_get_privacy(sm) &&
(tdls_testing & TDLS_TESTING_LONG_FRAME))
buf_len += 170;
if (tdls_testing & TDLS_TESTING_DIFF_BSSID)
buf_len += sizeof(struct wpa_tdls_lnkid);
#endif /* CONFIG_TDLS_TESTING */
rbuf = os_zalloc(buf_len + 1);
if (rbuf == NULL) {
wpa_tdls_peer_free(sm, peer);
return -1;
}
pos = rbuf;
if (!wpa_tdls_get_privacy(sm))
goto skip_ies;
/* Initiator RSN IE */
pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len);
ftie = (struct wpa_tdls_ftie *) pos;
ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
if (os_get_random(peer->inonce, WPA_NONCE_LEN)) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: Failed to get random data for INonce");
os_free(rbuf);
wpa_tdls_peer_free(sm, peer);
return -1;
}
os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, "TDLS: INonce for TPK handshake",
ftie->Snonce, WPA_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK Handshake M1",
(u8 *) ftie, sizeof(struct wpa_tdls_ftie));
pos = (u8 *) (ftie + 1);
#ifdef CONFIG_TDLS_TESTING
if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
"FTIE");
ftie->ie_len += 170;
*pos++ = 255; /* FTIE subelem */
*pos++ = 168; /* FTIE subelem length */
pos += 168;
}
#endif /* CONFIG_TDLS_TESTING */
/* Lifetime */
peer->lifetime = TPK_LIFETIME;
#ifdef CONFIG_TDLS_TESTING
if (tdls_testing & TDLS_TESTING_SHORT_LIFETIME) {
wpa_printf(MSG_DEBUG, "TDLS: Testing - use short TPK "
"lifetime");
peer->lifetime = 301;
}
#endif /* CONFIG_TDLS_TESTING */
pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
sizeof(timeoutie), peer->lifetime);
wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime);
skip_ies:
#ifdef CONFIG_TDLS_TESTING
if (tdls_testing & TDLS_TESTING_DIFF_BSSID) {
wpa_printf(MSG_DEBUG, "TDLS: Testing - use incorrect BSSID in "
"Link Identifier");
struct wpa_tdls_lnkid *l = (struct wpa_tdls_lnkid *) pos;
l->ie_type = WLAN_EID_LINK_ID;
l->ie_len = 3 * ETH_ALEN;
os_memcpy(l->bssid, sm->bssid, ETH_ALEN);
l->bssid[5] ^= 0x01;
os_memcpy(l->init_sta, sm->own_addr, ETH_ALEN);
os_memcpy(l->resp_sta, addr, ETH_ALEN);
pos += sizeof(*l);
}
#endif /* CONFIG_TDLS_TESTING */
wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Request / TPK "
"Handshake Message 1 (peer " MACSTR ")",
MAC2STR(peer->addr));
wpa_tdls_smk_send(sm, peer->addr, WLAN_TDLS_SETUP_REQUEST, 0, 0,
rbuf, pos - rbuf);
os_free(rbuf);
return 0;
}
static int wpa_tdls_send_tpk_m2(struct wpa_sm *sm,
const unsigned char *src_addr, u8 dtoken,
struct wpa_tdls_lnkid *lnkid,
@ -1532,14 +1709,7 @@ static u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs)
*/
int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr)
{
u16 buf_len;
struct wpa_tdls_ftie *ftie;
u8 *rbuf, *pos, *count_pos;
u16 count;
struct rsn_ie_hdr *hdr;
struct wpa_tdls_peer *peer;
struct wpa_tdls_timeoutie timeoutie;
u16 rsn_capab;
/* Find existing entry and if found, use that instead of adding
* a new one */
@ -1562,168 +1732,7 @@ int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr)
peer->initiator = 1;
if (!wpa_tdls_get_privacy(sm)) {
wpa_printf(MSG_DEBUG, "TDLS: No security used on the link");
peer->rsnie_i_len = 0;
goto skip_rsnie;
}
/*
* TPK Handshake Message 1:
* FTIE: ANonce=0, SNonce=nonce MIC=0, DataKDs=(RSNIE_I,
* Timeout Interval IE))
*/
/* Filling RSN IE */
hdr = (struct rsn_ie_hdr *) peer->rsnie_i;
hdr->elem_id = WLAN_EID_RSN;
WPA_PUT_LE16(hdr->version, RSN_VERSION);
pos = (u8 *) (hdr + 1);
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
pos += RSN_SELECTOR_LEN;
count_pos = pos;
pos += 2;
count = 0;
/*
* AES-CCMP is the default Encryption preferred for TDLS, so
* RSN IE is filled only with CCMP CIPHER
* Note: TKIP is not used to encrypt TDLS link.
*
* Regardless of the cipher used on the AP connection, select CCMP
* here.
*/
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
pos += RSN_SELECTOR_LEN;
count++;
WPA_PUT_LE16(count_pos, count);
WPA_PUT_LE16(pos, 1);
pos += 2;
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
pos += RSN_SELECTOR_LEN;
rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
#ifdef CONFIG_TDLS_TESTING
if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) {
wpa_printf(MSG_DEBUG, "TDLS: Use alternative RSN IE for "
"testing");
rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
}
#endif /* CONFIG_TDLS_TESTING */
WPA_PUT_LE16(pos, rsn_capab);
pos += 2;
#ifdef CONFIG_TDLS_TESTING
if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) {
/* Number of PMKIDs */
*pos++ = 0x00;
*pos++ = 0x00;
}
#endif /* CONFIG_TDLS_TESTING */
hdr->len = (pos - peer->rsnie_i) - 2;
peer->rsnie_i_len = pos - peer->rsnie_i;
wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake",
peer->rsnie_i, peer->rsnie_i_len);
skip_rsnie:
buf_len = 0;
if (wpa_tdls_get_privacy(sm))
buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
sizeof(struct wpa_tdls_timeoutie);
#ifdef CONFIG_TDLS_TESTING
if (wpa_tdls_get_privacy(sm) &&
(tdls_testing & TDLS_TESTING_LONG_FRAME))
buf_len += 170;
if (tdls_testing & TDLS_TESTING_DIFF_BSSID)
buf_len += sizeof(struct wpa_tdls_lnkid);
#endif /* CONFIG_TDLS_TESTING */
rbuf = os_zalloc(buf_len + 1);
if (rbuf == NULL) {
wpa_tdls_peer_free(sm, peer);
return -1;
}
pos = rbuf;
if (!wpa_tdls_get_privacy(sm))
goto skip_ies;
/* Initiator RSN IE */
pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len);
ftie = (struct wpa_tdls_ftie *) pos;
ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
if (os_get_random(peer->inonce, WPA_NONCE_LEN)) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: Failed to get random data for INonce");
os_free(rbuf);
wpa_tdls_peer_free(sm, peer);
return -1;
}
os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, "TDLS: INonce for TPK handshake",
ftie->Snonce, WPA_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK Handshake M1",
(u8 *) ftie, sizeof(struct wpa_tdls_ftie));
pos = (u8 *) (ftie + 1);
#ifdef CONFIG_TDLS_TESTING
if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
"FTIE");
ftie->ie_len += 170;
*pos++ = 255; /* FTIE subelem */
*pos++ = 168; /* FTIE subelem length */
pos += 168;
}
#endif /* CONFIG_TDLS_TESTING */
/* Lifetime */
peer->lifetime = TPK_LIFETIME;
#ifdef CONFIG_TDLS_TESTING
if (tdls_testing & TDLS_TESTING_SHORT_LIFETIME) {
wpa_printf(MSG_DEBUG, "TDLS: Testing - use short TPK "
"lifetime");
peer->lifetime = 301;
}
#endif /* CONFIG_TDLS_TESTING */
pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
sizeof(timeoutie), peer->lifetime);
wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime);
skip_ies:
#ifdef CONFIG_TDLS_TESTING
if (tdls_testing & TDLS_TESTING_DIFF_BSSID) {
wpa_printf(MSG_DEBUG, "TDLS: Testing - use incorrect BSSID in "
"Link Identifier");
struct wpa_tdls_lnkid *l = (struct wpa_tdls_lnkid *) pos;
l->ie_type = WLAN_EID_LINK_ID;
l->ie_len = 3 * ETH_ALEN;
os_memcpy(l->bssid, sm->bssid, ETH_ALEN);
l->bssid[5] ^= 0x01;
os_memcpy(l->init_sta, sm->own_addr, ETH_ALEN);
os_memcpy(l->resp_sta, addr, ETH_ALEN);
pos += sizeof(*l);
}
#endif /* CONFIG_TDLS_TESTING */
wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Request / TPK "
"Handshake Message 1 (peer " MACSTR ")", MAC2STR(addr));
wpa_tdls_smk_send(sm, addr, WLAN_TDLS_SETUP_REQUEST, 0, 0,
rbuf, pos - rbuf);
os_free(rbuf);
return 0;
return wpa_tdls_send_tpk_m1(sm, peer);
}