2 * WPA Supplicant - Mesh RSN routines
3 * Copyright (c) 2013-2014, cozybit, Inc. All rights reserved.
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
9 #include "utils/includes.h"
11 #include "utils/common.h"
12 #include "utils/eloop.h"
13 #include "crypto/sha256.h"
14 #include "crypto/random.h"
15 #include "crypto/aes.h"
16 #include "crypto/aes_siv.h"
17 #include "rsn_supp/wpa.h"
18 #include "ap/hostapd.h"
19 #include "ap/wpa_auth.h"
20 #include "ap/sta_info.h"
21 #include "ap/ieee802_11.h"
22 #include "wpa_supplicant_i.h"
24 #include "wpas_glue.h"
28 #define MESH_AUTH_TIMEOUT 10
29 #define MESH_AUTH_RETRY 3
31 void mesh_auth_timer(void *eloop_ctx
, void *user_data
)
33 struct wpa_supplicant
*wpa_s
= eloop_ctx
;
34 struct sta_info
*sta
= user_data
;
35 struct hostapd_data
*hapd
;
37 if (sta
->sae
->state
!= SAE_ACCEPTED
) {
38 wpa_printf(MSG_DEBUG
, "AUTH: Re-authenticate with " MACSTR
40 MAC2STR(sta
->addr
), sta
->sae_auth_retry
);
41 wpa_msg(wpa_s
, MSG_INFO
, MESH_SAE_AUTH_FAILURE
"addr=" MACSTR
,
43 if (sta
->sae_auth_retry
< MESH_AUTH_RETRY
) {
44 mesh_rsn_auth_sae_sta(wpa_s
, sta
);
46 hapd
= wpa_s
->ifmsh
->bss
[0];
48 if (sta
->sae_auth_retry
> MESH_AUTH_RETRY
) {
49 ap_free_sta(hapd
, sta
);
53 /* block the STA if exceeded the number of attempts */
54 wpa_mesh_set_plink_state(wpa_s
, sta
, PLINK_BLOCKED
);
55 sta
->sae
->state
= SAE_NOTHING
;
56 wpa_msg(wpa_s
, MSG_INFO
, MESH_SAE_AUTH_BLOCKED
"addr="
57 MACSTR
" duration=%d",
59 hapd
->conf
->ap_max_inactivity
);
61 sta
->sae_auth_retry
++;
66 static void auth_logger(void *ctx
, const u8
*addr
, logger_level level
,
70 wpa_printf(MSG_DEBUG
, "AUTH: " MACSTR
" - %s",
73 wpa_printf(MSG_DEBUG
, "AUTH: %s", txt
);
77 static const u8
*auth_get_psk(void *ctx
, const u8
*addr
,
78 const u8
*p2p_dev_addr
, const u8
*prev_psk
,
81 struct mesh_rsn
*mesh_rsn
= ctx
;
82 struct hostapd_data
*hapd
= mesh_rsn
->wpa_s
->ifmsh
->bss
[0];
83 struct sta_info
*sta
= ap_get_sta(hapd
, addr
);
87 wpa_printf(MSG_DEBUG
, "AUTH: %s (addr=" MACSTR
" prev_psk=%p)",
88 __func__
, MAC2STR(addr
), prev_psk
);
90 if (sta
&& sta
->auth_alg
== WLAN_AUTH_SAE
) {
91 if (!sta
->sae
|| prev_psk
)
100 static int auth_set_key(void *ctx
, int vlan_id
, enum wpa_alg alg
,
101 const u8
*addr
, int idx
, u8
*key
, size_t key_len
)
103 struct mesh_rsn
*mesh_rsn
= ctx
;
106 os_memset(seq
, 0, sizeof(seq
));
109 wpa_printf(MSG_DEBUG
, "AUTH: %s(alg=%d addr=" MACSTR
111 __func__
, alg
, MAC2STR(addr
), idx
);
113 wpa_printf(MSG_DEBUG
, "AUTH: %s(alg=%d key_idx=%d)",
116 wpa_hexdump_key(MSG_DEBUG
, "AUTH: set_key - key", key
, key_len
);
118 return wpa_drv_set_key(mesh_rsn
->wpa_s
, alg
, addr
, idx
,
119 1, seq
, 6, key
, key_len
);
123 static int auth_start_ampe(void *ctx
, const u8
*addr
)
125 struct mesh_rsn
*mesh_rsn
= ctx
;
126 struct hostapd_data
*hapd
;
127 struct sta_info
*sta
;
129 if (mesh_rsn
->wpa_s
->current_ssid
->mode
!= WPAS_MODE_MESH
)
132 hapd
= mesh_rsn
->wpa_s
->ifmsh
->bss
[0];
133 sta
= ap_get_sta(hapd
, addr
);
135 eloop_cancel_timeout(mesh_auth_timer
, mesh_rsn
->wpa_s
, sta
);
137 mesh_mpm_auth_peer(mesh_rsn
->wpa_s
, addr
);
142 static int __mesh_rsn_auth_init(struct mesh_rsn
*rsn
, const u8
*addr
,
143 enum mfp_options ieee80211w
, int ocv
)
145 struct wpa_auth_config conf
;
146 static const struct wpa_auth_callbacks cb
= {
147 .logger
= auth_logger
,
148 .get_psk
= auth_get_psk
,
149 .set_key
= auth_set_key
,
150 .start_ampe
= auth_start_ampe
,
154 wpa_printf(MSG_DEBUG
, "AUTH: Initializing group state machine");
156 os_memset(&conf
, 0, sizeof(conf
));
157 conf
.wpa
= WPA_PROTO_RSN
;
158 conf
.wpa_key_mgmt
= WPA_KEY_MGMT_SAE
;
159 conf
.wpa_pairwise
= rsn
->pairwise_cipher
;
160 conf
.rsn_pairwise
= rsn
->pairwise_cipher
;
161 conf
.wpa_group
= rsn
->group_cipher
;
162 conf
.eapol_version
= 0;
163 conf
.wpa_group_rekey
= -1;
164 conf
.wpa_group_update_count
= 4;
165 conf
.wpa_pairwise_update_count
= 4;
166 #ifdef CONFIG_IEEE80211W
167 conf
.ieee80211w
= ieee80211w
;
168 if (ieee80211w
!= NO_MGMT_FRAME_PROTECTION
)
169 conf
.group_mgmt_cipher
= rsn
->mgmt_group_cipher
;
170 #endif /* CONFIG_IEEE80211W */
173 #endif /* CONFIG_OCV */
175 rsn
->auth
= wpa_init(addr
, &conf
, &cb
, rsn
);
176 if (rsn
->auth
== NULL
) {
177 wpa_printf(MSG_DEBUG
, "AUTH: wpa_init() failed");
181 /* TODO: support rekeying */
182 rsn
->mgtk_len
= wpa_cipher_key_len(conf
.wpa_group
);
183 if (random_get_bytes(rsn
->mgtk
, rsn
->mgtk_len
) < 0)
185 rsn
->mgtk_key_id
= 1;
187 #ifdef CONFIG_IEEE80211W
188 if (ieee80211w
!= NO_MGMT_FRAME_PROTECTION
) {
189 rsn
->igtk_len
= wpa_cipher_key_len(conf
.group_mgmt_cipher
);
190 if (random_get_bytes(rsn
->igtk
, rsn
->igtk_len
) < 0)
192 rsn
->igtk_key_id
= 4;
195 wpa_hexdump_key(MSG_DEBUG
, "mesh: Own TX IGTK",
196 rsn
->igtk
, rsn
->igtk_len
);
197 wpa_drv_set_key(rsn
->wpa_s
,
198 wpa_cipher_to_alg(rsn
->mgmt_group_cipher
), NULL
,
200 seq
, sizeof(seq
), rsn
->igtk
, rsn
->igtk_len
);
202 #endif /* CONFIG_IEEE80211W */
204 /* group privacy / data frames */
205 wpa_hexdump_key(MSG_DEBUG
, "mesh: Own TX MGTK",
206 rsn
->mgtk
, rsn
->mgtk_len
);
207 wpa_drv_set_key(rsn
->wpa_s
, wpa_cipher_to_alg(rsn
->group_cipher
), NULL
,
208 rsn
->mgtk_key_id
, 1, seq
, sizeof(seq
),
209 rsn
->mgtk
, rsn
->mgtk_len
);
215 static void mesh_rsn_deinit(struct mesh_rsn
*rsn
)
217 os_memset(rsn
->mgtk
, 0, sizeof(rsn
->mgtk
));
219 os_memset(rsn
->igtk
, 0, sizeof(rsn
->igtk
));
222 wpa_deinit(rsn
->auth
);
226 struct mesh_rsn
*mesh_rsn_auth_init(struct wpa_supplicant
*wpa_s
,
227 struct mesh_conf
*conf
)
229 struct mesh_rsn
*mesh_rsn
;
230 struct hostapd_data
*bss
= wpa_s
->ifmsh
->bss
[0];
233 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
234 struct external_pmksa_cache
*entry
;
235 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
237 mesh_rsn
= os_zalloc(sizeof(*mesh_rsn
));
238 if (mesh_rsn
== NULL
)
240 mesh_rsn
->wpa_s
= wpa_s
;
241 mesh_rsn
->pairwise_cipher
= conf
->pairwise_cipher
;
242 mesh_rsn
->group_cipher
= conf
->group_cipher
;
243 mesh_rsn
->mgmt_group_cipher
= conf
->mgmt_group_cipher
;
245 if (__mesh_rsn_auth_init(mesh_rsn
, wpa_s
->own_addr
,
246 conf
->ieee80211w
, conf
->ocv
) < 0) {
247 mesh_rsn_deinit(mesh_rsn
);
252 bss
->wpa_auth
= mesh_rsn
->auth
;
254 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
255 while ((entry
= dl_list_last(&wpa_s
->mesh_external_pmksa_cache
,
256 struct external_pmksa_cache
,
260 ret
= wpa_auth_pmksa_add_entry(bss
->wpa_auth
,
262 dl_list_del(&entry
->list
);
268 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
270 ie
= wpa_auth_get_wpa_ie(mesh_rsn
->auth
, &ie_len
);
271 conf
->rsn_ie
= (u8
*) ie
;
272 conf
->rsn_ie_len
= ie_len
;
274 wpa_supplicant_rsn_supp_set_config(wpa_s
, wpa_s
->current_ssid
);
280 static int index_within_array(const int *array
, int idx
)
284 for (i
= 0; i
< idx
; i
++) {
293 static int mesh_rsn_sae_group(struct wpa_supplicant
*wpa_s
,
294 struct sae_data
*sae
)
296 int *groups
= wpa_s
->ifmsh
->bss
[0]->conf
->sae_groups
;
298 /* Configuration may have changed, so validate current index */
299 if (!index_within_array(groups
, wpa_s
->mesh_rsn
->sae_group_index
))
303 int group
= groups
[wpa_s
->mesh_rsn
->sae_group_index
];
307 if (sae_set_group(sae
, group
) == 0) {
308 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Selected SAE group %d",
312 wpa_s
->mesh_rsn
->sae_group_index
++;
319 static int mesh_rsn_build_sae_commit(struct wpa_supplicant
*wpa_s
,
320 struct wpa_ssid
*ssid
,
321 struct sta_info
*sta
)
323 const char *password
;
325 password
= ssid
->sae_password
;
327 password
= ssid
->passphrase
;
329 wpa_msg(wpa_s
, MSG_DEBUG
, "SAE: No password available");
333 if (mesh_rsn_sae_group(wpa_s
, sta
->sae
) < 0) {
334 wpa_msg(wpa_s
, MSG_DEBUG
, "SAE: Failed to select group");
338 if (sta
->sae
->tmp
&& !sta
->sae
->tmp
->pw_id
&& ssid
->sae_password_id
) {
339 sta
->sae
->tmp
->pw_id
= os_strdup(ssid
->sae_password_id
);
340 if (!sta
->sae
->tmp
->pw_id
)
343 return sae_prepare_commit(wpa_s
->own_addr
, sta
->addr
,
344 (u8
*) password
, os_strlen(password
),
345 ssid
->sae_password_id
,
350 /* initiate new SAE authentication with sta */
351 int mesh_rsn_auth_sae_sta(struct wpa_supplicant
*wpa_s
,
352 struct sta_info
*sta
)
354 struct hostapd_data
*hapd
= wpa_s
->ifmsh
->bss
[0];
355 struct wpa_ssid
*ssid
= wpa_s
->current_ssid
;
356 struct rsn_pmksa_cache_entry
*pmksa
;
361 wpa_msg(wpa_s
, MSG_DEBUG
,
362 "AUTH: No current_ssid known to initiate new SAE");
367 sta
->sae
= os_zalloc(sizeof(*sta
->sae
));
368 if (sta
->sae
== NULL
)
372 pmksa
= wpa_auth_pmksa_get(hapd
->wpa_auth
, sta
->addr
, NULL
);
375 sta
->wpa_sm
= wpa_auth_sta_init(hapd
->wpa_auth
,
378 wpa_printf(MSG_ERROR
,
379 "mesh: Failed to initialize RSN state machine");
383 wpa_printf(MSG_DEBUG
,
384 "AUTH: Mesh PMKSA cache entry found for " MACSTR
385 " - try to use PMKSA caching instead of new SAE authentication",
387 wpa_auth_pmksa_set_to_sm(pmksa
, sta
->wpa_sm
, hapd
->wpa_auth
,
388 sta
->sae
->pmkid
, sta
->sae
->pmk
);
389 sae_accept_sta(hapd
, sta
);
390 sta
->mesh_sae_pmksa_caching
= 1;
393 sta
->mesh_sae_pmksa_caching
= 0;
395 if (mesh_rsn_build_sae_commit(wpa_s
, ssid
, sta
))
398 wpa_msg(wpa_s
, MSG_DEBUG
,
399 "AUTH: started authentication with SAE peer: " MACSTR
,
402 ret
= auth_sae_init_committed(hapd
, sta
);
406 eloop_cancel_timeout(mesh_auth_timer
, wpa_s
, sta
);
407 rnd
= rand() % MESH_AUTH_TIMEOUT
;
408 eloop_register_timeout(MESH_AUTH_TIMEOUT
+ rnd
, 0, mesh_auth_timer
,
414 void mesh_rsn_get_pmkid(struct mesh_rsn
*rsn
, struct sta_info
*sta
, u8
*pmkid
)
416 os_memcpy(pmkid
, sta
->sae
->pmkid
, SAE_PMKID_LEN
);
421 mesh_rsn_derive_aek(struct mesh_rsn
*rsn
, struct sta_info
*sta
)
423 u8
*myaddr
= rsn
->wpa_s
->own_addr
;
424 u8
*peer
= sta
->addr
;
426 u8 context
[RSN_SELECTOR_LEN
+ 2 * ETH_ALEN
], *ptr
= context
;
429 * AEK = KDF-Hash-256(PMK, "AEK Derivation", Selected AKM Suite ||
430 * min(localMAC, peerMAC) || max(localMAC, peerMAC))
432 /* Selected AKM Suite: SAE */
433 RSN_SELECTOR_PUT(ptr
, RSN_AUTH_KEY_MGMT_SAE
);
434 ptr
+= RSN_SELECTOR_LEN
;
436 if (os_memcmp(myaddr
, peer
, ETH_ALEN
) < 0) {
443 os_memcpy(ptr
, addr1
, ETH_ALEN
);
445 os_memcpy(ptr
, addr2
, ETH_ALEN
);
447 sha256_prf(sta
->sae
->pmk
, sizeof(sta
->sae
->pmk
), "AEK Derivation",
448 context
, sizeof(context
), sta
->aek
, sizeof(sta
->aek
));
452 /* derive mesh temporal key from pmk */
453 int mesh_rsn_derive_mtk(struct wpa_supplicant
*wpa_s
, struct sta_info
*sta
)
457 u8
*myaddr
= wpa_s
->own_addr
;
458 u8
*peer
= sta
->addr
;
459 u8 context
[2 * WPA_NONCE_LEN
+ 2 * 2 + RSN_SELECTOR_LEN
+ 2 * ETH_ALEN
];
462 * MTK = KDF-Hash-Length(PMK, "Temporal Key Derivation", min(localNonce,
463 * peerNonce) || max(localNonce, peerNonce) || min(localLinkID,
464 * peerLinkID) || max(localLinkID, peerLinkID) || Selected AKM Suite ||
465 * min(localMAC, peerMAC) || max(localMAC, peerMAC))
468 if (os_memcmp(sta
->my_nonce
, sta
->peer_nonce
, WPA_NONCE_LEN
) < 0) {
470 max
= sta
->peer_nonce
;
472 min
= sta
->peer_nonce
;
475 os_memcpy(ptr
, min
, WPA_NONCE_LEN
);
476 ptr
+= WPA_NONCE_LEN
;
477 os_memcpy(ptr
, max
, WPA_NONCE_LEN
);
478 ptr
+= WPA_NONCE_LEN
;
480 if (sta
->my_lid
< sta
->peer_lid
) {
481 WPA_PUT_LE16(ptr
, sta
->my_lid
);
483 WPA_PUT_LE16(ptr
, sta
->peer_lid
);
486 WPA_PUT_LE16(ptr
, sta
->peer_lid
);
488 WPA_PUT_LE16(ptr
, sta
->my_lid
);
492 /* Selected AKM Suite: SAE */
493 RSN_SELECTOR_PUT(ptr
, RSN_AUTH_KEY_MGMT_SAE
);
494 ptr
+= RSN_SELECTOR_LEN
;
496 if (os_memcmp(myaddr
, peer
, ETH_ALEN
) < 0) {
503 os_memcpy(ptr
, min
, ETH_ALEN
);
505 os_memcpy(ptr
, max
, ETH_ALEN
);
507 sta
->mtk_len
= wpa_cipher_key_len(wpa_s
->mesh_rsn
->pairwise_cipher
);
508 sha256_prf(sta
->sae
->pmk
, SAE_PMK_LEN
,
509 "Temporal Key Derivation", context
, sizeof(context
),
510 sta
->mtk
, sta
->mtk_len
);
515 void mesh_rsn_init_ampe_sta(struct wpa_supplicant
*wpa_s
, struct sta_info
*sta
)
517 if (random_get_bytes(sta
->my_nonce
, WPA_NONCE_LEN
) < 0) {
518 wpa_printf(MSG_INFO
, "mesh: Failed to derive random nonce");
519 /* TODO: How to handle this more cleanly? */
521 os_memset(sta
->peer_nonce
, 0, WPA_NONCE_LEN
);
522 mesh_rsn_derive_aek(wpa_s
->mesh_rsn
, sta
);
526 /* insert AMPE and encrypted MIC at @ie.
527 * @mesh_rsn: mesh RSN context
528 * @sta: STA we're sending to
529 * @cat: pointer to category code in frame header.
530 * @buf: wpabuf to add encrypted AMPE and MIC to.
532 int mesh_rsn_protect_frame(struct mesh_rsn
*rsn
, struct sta_info
*sta
,
533 const u8
*cat
, struct wpabuf
*buf
)
535 struct ieee80211_ampe_ie
*ampe
;
536 u8
const *ie
= wpabuf_head_u8(buf
) + wpabuf_len(buf
);
537 u8
*ampe_ie
, *pos
, *mic_payload
;
538 const u8
*aad
[] = { rsn
->wpa_s
->own_addr
, sta
->addr
, cat
};
539 const size_t aad_len
[] = { ETH_ALEN
, ETH_ALEN
, ie
- cat
};
544 if (cat
[1] == PLINK_OPEN
)
545 len
+= rsn
->mgtk_len
+ WPA_KEY_RSC_LEN
+ 4;
546 #ifdef CONFIG_IEEE80211W
547 if (cat
[1] == PLINK_OPEN
&& rsn
->igtk_len
)
548 len
+= 2 + 6 + rsn
->igtk_len
;
549 #endif /* CONFIG_IEEE80211W */
551 if (2 + AES_BLOCK_SIZE
+ 2 + len
> wpabuf_tailroom(buf
)) {
552 wpa_printf(MSG_ERROR
, "protect frame: buffer too small");
556 ampe_ie
= os_zalloc(2 + len
);
558 wpa_printf(MSG_ERROR
, "protect frame: out of memory");
563 ampe_ie
[0] = WLAN_EID_AMPE
;
565 ampe
= (struct ieee80211_ampe_ie
*) (ampe_ie
+ 2);
567 RSN_SELECTOR_PUT(ampe
->selected_pairwise_suite
,
568 RSN_CIPHER_SUITE_CCMP
);
569 os_memcpy(ampe
->local_nonce
, sta
->my_nonce
, WPA_NONCE_LEN
);
570 os_memcpy(ampe
->peer_nonce
, sta
->peer_nonce
, WPA_NONCE_LEN
);
572 pos
= (u8
*) (ampe
+ 1);
573 if (cat
[1] != PLINK_OPEN
)
576 /* TODO: Key Replay Counter[8] optionally for
577 * Mesh Group Key Inform/Acknowledge frames */
579 /* TODO: static mgtk for now since we don't support rekeying! */
582 * MGTK[variable] || Key RSC[8] || GTKExpirationTime[4]
584 os_memcpy(pos
, rsn
->mgtk
, rsn
->mgtk_len
);
585 pos
+= rsn
->mgtk_len
;
586 wpa_drv_get_seqnum(rsn
->wpa_s
, NULL
, rsn
->mgtk_key_id
, pos
);
587 pos
+= WPA_KEY_RSC_LEN
;
588 /* Use fixed GTKExpirationTime for now */
589 WPA_PUT_LE32(pos
, 0xffffffff);
592 #ifdef CONFIG_IEEE80211W
594 * IGTKdata[variable]:
595 * Key ID[2], IPN[6], IGTK[variable]
598 WPA_PUT_LE16(pos
, rsn
->igtk_key_id
);
600 wpa_drv_get_seqnum(rsn
->wpa_s
, NULL
, rsn
->igtk_key_id
, pos
);
602 os_memcpy(pos
, rsn
->igtk
, rsn
->igtk_len
);
604 #endif /* CONFIG_IEEE80211W */
607 wpa_hexdump_key(MSG_DEBUG
, "mesh: Plaintext AMPE element",
611 wpabuf_put_u8(buf
, WLAN_EID_MIC
);
612 wpabuf_put_u8(buf
, AES_BLOCK_SIZE
);
613 /* MIC field is output ciphertext */
615 /* encrypt after MIC */
616 mic_payload
= wpabuf_put(buf
, 2 + len
+ AES_BLOCK_SIZE
);
618 if (aes_siv_encrypt(sta
->aek
, sizeof(sta
->aek
), ampe_ie
, 2 + len
, 3,
619 aad
, aad_len
, mic_payload
)) {
620 wpa_printf(MSG_ERROR
, "protect frame: failed to encrypt");
630 int mesh_rsn_process_ampe(struct wpa_supplicant
*wpa_s
, struct sta_info
*sta
,
631 struct ieee802_11_elems
*elems
, const u8
*cat
,
632 const u8
*chosen_pmk
,
633 const u8
*start
, size_t elems_len
)
636 struct ieee80211_ampe_ie
*ampe
;
637 u8 null_nonce
[WPA_NONCE_LEN
] = {};
640 u8
*ampe_buf
, *crypt
= NULL
, *pos
, *end
;
642 const u8
*aad
[] = { sta
->addr
, wpa_s
->own_addr
, cat
};
643 const size_t aad_len
[] = { ETH_ALEN
, ETH_ALEN
,
644 (elems
->mic
- 2) - cat
};
648 struct hostapd_data
*hapd
= wpa_s
->ifmsh
->bss
[0];
650 if (!wpa_auth_pmksa_get(hapd
->wpa_auth
, sta
->addr
, NULL
)) {
652 "Mesh RSN: SAE is not prepared yet");
655 mesh_rsn_auth_sae_sta(wpa_s
, sta
);
658 if (chosen_pmk
&& os_memcmp(chosen_pmk
, sta
->sae
->pmkid
, PMKID_LEN
)) {
659 wpa_msg(wpa_s
, MSG_DEBUG
,
660 "Mesh RSN: Invalid PMKID (Chosen PMK did not match calculated PMKID)");
664 if (!elems
->mic
|| elems
->mic_len
< AES_BLOCK_SIZE
) {
665 wpa_msg(wpa_s
, MSG_DEBUG
, "Mesh RSN: missing mic ie");
669 ampe_buf
= (u8
*) elems
->mic
+ elems
->mic_len
;
670 if ((int) elems_len
< ampe_buf
- start
)
673 crypt_len
= elems_len
- (elems
->mic
- start
);
674 if (crypt_len
< 2 + AES_BLOCK_SIZE
) {
675 wpa_msg(wpa_s
, MSG_DEBUG
, "Mesh RSN: missing ampe ie");
679 /* crypt is modified by siv_decrypt */
680 crypt
= os_zalloc(crypt_len
);
682 wpa_printf(MSG_ERROR
, "Mesh RSN: out of memory");
687 os_memcpy(crypt
, elems
->mic
, crypt_len
);
689 if (aes_siv_decrypt(sta
->aek
, sizeof(sta
->aek
), crypt
, crypt_len
, 3,
690 aad
, aad_len
, ampe_buf
)) {
691 wpa_printf(MSG_ERROR
, "Mesh RSN: frame verification failed!");
696 crypt_len
-= AES_BLOCK_SIZE
;
697 wpa_hexdump_key(MSG_DEBUG
, "mesh: Decrypted AMPE element",
698 ampe_buf
, crypt_len
);
700 ampe_eid
= *ampe_buf
++;
701 ampe_ie_len
= *ampe_buf
++;
703 if (ampe_eid
!= WLAN_EID_AMPE
||
704 (size_t) 2 + ampe_ie_len
> crypt_len
||
705 ampe_ie_len
< sizeof(struct ieee80211_ampe_ie
)) {
706 wpa_msg(wpa_s
, MSG_DEBUG
, "Mesh RSN: invalid ampe ie");
711 ampe
= (struct ieee80211_ampe_ie
*) ampe_buf
;
712 pos
= (u8
*) (ampe
+ 1);
713 end
= ampe_buf
+ ampe_ie_len
;
714 if (os_memcmp(ampe
->peer_nonce
, null_nonce
, WPA_NONCE_LEN
) != 0 &&
715 os_memcmp(ampe
->peer_nonce
, sta
->my_nonce
, WPA_NONCE_LEN
) != 0) {
716 wpa_msg(wpa_s
, MSG_DEBUG
, "Mesh RSN: invalid peer nonce");
720 os_memcpy(sta
->peer_nonce
, ampe
->local_nonce
,
721 sizeof(ampe
->local_nonce
));
723 /* TODO: Key Replay Counter[8] in Mesh Group Key Inform/Acknowledge
727 * GTKdata shall not be included in Mesh Peering Confirm. While the
728 * standard does not state the same about IGTKdata, that same constraint
729 * needs to apply for it. It makes no sense to include the keys in Mesh
730 * Peering Close frames either, so while the standard does not seem to
731 * have a shall statement for these, they are described without
732 * mentioning GTKdata.
734 * An earlier implementation used to add GTKdata to both Mesh Peering
735 * Open and Mesh Peering Confirm frames, so ignore the possibly present
736 * GTKdata frame without rejecting the frame as a backwards
737 * compatibility mechanism.
739 if (cat
[1] != PLINK_OPEN
) {
741 wpa_hexdump_key(MSG_DEBUG
,
742 "mesh: Ignore unexpected GTKdata(etc.) fields in the end of AMPE element in Mesh Peering Confirm/Close",
750 * MGTK[variable] || Key RSC[8] || GTKExpirationTime[4]
752 sta
->mgtk_key_id
= 1; /* FIX: Where to get Key ID? */
753 key_len
= wpa_cipher_key_len(wpa_s
->mesh_rsn
->group_cipher
);
754 if ((int) key_len
+ WPA_KEY_RSC_LEN
+ 4 > end
- pos
) {
755 wpa_dbg(wpa_s
, MSG_DEBUG
, "mesh: Truncated AMPE element");
759 sta
->mgtk_len
= key_len
;
760 os_memcpy(sta
->mgtk
, pos
, sta
->mgtk_len
);
761 wpa_hexdump_key(MSG_DEBUG
, "mesh: GTKdata - MGTK",
762 sta
->mgtk
, sta
->mgtk_len
);
763 pos
+= sta
->mgtk_len
;
764 wpa_hexdump(MSG_DEBUG
, "mesh: GTKdata - MGTK - Key RSC",
765 pos
, WPA_KEY_RSC_LEN
);
766 os_memcpy(sta
->mgtk_rsc
, pos
, sizeof(sta
->mgtk_rsc
));
767 pos
+= WPA_KEY_RSC_LEN
;
768 wpa_printf(MSG_DEBUG
,
769 "mesh: GTKdata - MGTK - GTKExpirationTime: %u seconds",
773 #ifdef CONFIG_IEEE80211W
775 * IGTKdata[variable]:
776 * Key ID[2], IPN[6], IGTK[variable]
778 key_len
= wpa_cipher_key_len(wpa_s
->mesh_rsn
->mgmt_group_cipher
);
779 if (end
- pos
>= (int) (2 + 6 + key_len
)) {
780 sta
->igtk_key_id
= WPA_GET_LE16(pos
);
781 wpa_printf(MSG_DEBUG
, "mesh: IGTKdata - Key ID %u",
784 os_memcpy(sta
->igtk_rsc
, pos
, sizeof(sta
->igtk_rsc
));
785 wpa_hexdump(MSG_DEBUG
, "mesh: IGTKdata - IPN",
786 sta
->igtk_rsc
, sizeof(sta
->igtk_rsc
));
788 os_memcpy(sta
->igtk
, pos
, key_len
);
789 sta
->igtk_len
= key_len
;
790 wpa_hexdump_key(MSG_DEBUG
, "mesh: IGTKdata - IGTK",
791 sta
->igtk
, sta
->igtk_len
);
793 #endif /* CONFIG_IEEE80211W */