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
,
79 size_t *psk_len
, int *vlan_id
)
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
);
89 wpa_printf(MSG_DEBUG
, "AUTH: %s (addr=" MACSTR
" prev_psk=%p)",
90 __func__
, MAC2STR(addr
), prev_psk
);
92 if (sta
&& sta
->auth_alg
== WLAN_AUTH_SAE
) {
93 if (!sta
->sae
|| prev_psk
)
102 static int auth_set_key(void *ctx
, int vlan_id
, enum wpa_alg alg
,
103 const u8
*addr
, int idx
, u8
*key
, size_t key_len
)
105 struct mesh_rsn
*mesh_rsn
= ctx
;
108 os_memset(seq
, 0, sizeof(seq
));
111 wpa_printf(MSG_DEBUG
, "AUTH: %s(alg=%d addr=" MACSTR
113 __func__
, alg
, MAC2STR(addr
), idx
);
115 wpa_printf(MSG_DEBUG
, "AUTH: %s(alg=%d key_idx=%d)",
118 wpa_hexdump_key(MSG_DEBUG
, "AUTH: set_key - key", key
, key_len
);
120 return wpa_drv_set_key(mesh_rsn
->wpa_s
, alg
, addr
, idx
,
121 1, seq
, 6, key
, key_len
);
125 static int auth_start_ampe(void *ctx
, const u8
*addr
)
127 struct mesh_rsn
*mesh_rsn
= ctx
;
128 struct hostapd_data
*hapd
;
129 struct sta_info
*sta
;
131 if (mesh_rsn
->wpa_s
->current_ssid
->mode
!= WPAS_MODE_MESH
)
134 hapd
= mesh_rsn
->wpa_s
->ifmsh
->bss
[0];
135 sta
= ap_get_sta(hapd
, addr
);
137 eloop_cancel_timeout(mesh_auth_timer
, mesh_rsn
->wpa_s
, sta
);
139 mesh_mpm_auth_peer(mesh_rsn
->wpa_s
, addr
);
144 static int __mesh_rsn_auth_init(struct mesh_rsn
*rsn
, const u8
*addr
,
145 enum mfp_options ieee80211w
, int ocv
)
147 struct wpa_auth_config conf
;
148 static const struct wpa_auth_callbacks cb
= {
149 .logger
= auth_logger
,
150 .get_psk
= auth_get_psk
,
151 .set_key
= auth_set_key
,
152 .start_ampe
= auth_start_ampe
,
156 wpa_printf(MSG_DEBUG
, "AUTH: Initializing group state machine");
158 os_memset(&conf
, 0, sizeof(conf
));
159 conf
.wpa
= WPA_PROTO_RSN
;
160 conf
.wpa_key_mgmt
= WPA_KEY_MGMT_SAE
;
161 conf
.wpa_pairwise
= rsn
->pairwise_cipher
;
162 conf
.rsn_pairwise
= rsn
->pairwise_cipher
;
163 conf
.wpa_group
= rsn
->group_cipher
;
164 conf
.eapol_version
= 0;
165 conf
.wpa_group_rekey
= -1;
166 conf
.wpa_group_update_count
= 4;
167 conf
.wpa_pairwise_update_count
= 4;
168 #ifdef CONFIG_IEEE80211W
169 conf
.ieee80211w
= ieee80211w
;
170 if (ieee80211w
!= NO_MGMT_FRAME_PROTECTION
)
171 conf
.group_mgmt_cipher
= rsn
->mgmt_group_cipher
;
172 #endif /* CONFIG_IEEE80211W */
175 #endif /* CONFIG_OCV */
177 rsn
->auth
= wpa_init(addr
, &conf
, &cb
, rsn
);
178 if (rsn
->auth
== NULL
) {
179 wpa_printf(MSG_DEBUG
, "AUTH: wpa_init() failed");
183 /* TODO: support rekeying */
184 rsn
->mgtk_len
= wpa_cipher_key_len(conf
.wpa_group
);
185 if (random_get_bytes(rsn
->mgtk
, rsn
->mgtk_len
) < 0)
187 rsn
->mgtk_key_id
= 1;
189 #ifdef CONFIG_IEEE80211W
190 if (ieee80211w
!= NO_MGMT_FRAME_PROTECTION
) {
191 rsn
->igtk_len
= wpa_cipher_key_len(conf
.group_mgmt_cipher
);
192 if (random_get_bytes(rsn
->igtk
, rsn
->igtk_len
) < 0)
194 rsn
->igtk_key_id
= 4;
197 wpa_hexdump_key(MSG_DEBUG
, "mesh: Own TX IGTK",
198 rsn
->igtk
, rsn
->igtk_len
);
199 wpa_drv_set_key(rsn
->wpa_s
,
200 wpa_cipher_to_alg(rsn
->mgmt_group_cipher
), NULL
,
202 seq
, sizeof(seq
), rsn
->igtk
, rsn
->igtk_len
);
204 #endif /* CONFIG_IEEE80211W */
206 /* group privacy / data frames */
207 wpa_hexdump_key(MSG_DEBUG
, "mesh: Own TX MGTK",
208 rsn
->mgtk
, rsn
->mgtk_len
);
209 wpa_drv_set_key(rsn
->wpa_s
, wpa_cipher_to_alg(rsn
->group_cipher
), NULL
,
210 rsn
->mgtk_key_id
, 1, seq
, sizeof(seq
),
211 rsn
->mgtk
, rsn
->mgtk_len
);
217 static void mesh_rsn_deinit(struct mesh_rsn
*rsn
)
219 os_memset(rsn
->mgtk
, 0, sizeof(rsn
->mgtk
));
221 os_memset(rsn
->igtk
, 0, sizeof(rsn
->igtk
));
224 wpa_deinit(rsn
->auth
);
228 struct mesh_rsn
*mesh_rsn_auth_init(struct wpa_supplicant
*wpa_s
,
229 struct mesh_conf
*conf
)
231 struct mesh_rsn
*mesh_rsn
;
232 struct hostapd_data
*bss
= wpa_s
->ifmsh
->bss
[0];
235 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
236 struct external_pmksa_cache
*entry
;
237 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
239 mesh_rsn
= os_zalloc(sizeof(*mesh_rsn
));
240 if (mesh_rsn
== NULL
)
242 mesh_rsn
->wpa_s
= wpa_s
;
243 mesh_rsn
->pairwise_cipher
= conf
->pairwise_cipher
;
244 mesh_rsn
->group_cipher
= conf
->group_cipher
;
245 mesh_rsn
->mgmt_group_cipher
= conf
->mgmt_group_cipher
;
247 if (__mesh_rsn_auth_init(mesh_rsn
, wpa_s
->own_addr
,
248 conf
->ieee80211w
, conf
->ocv
) < 0) {
249 mesh_rsn_deinit(mesh_rsn
);
254 bss
->wpa_auth
= mesh_rsn
->auth
;
256 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
257 while ((entry
= dl_list_last(&wpa_s
->mesh_external_pmksa_cache
,
258 struct external_pmksa_cache
,
262 ret
= wpa_auth_pmksa_add_entry(bss
->wpa_auth
,
264 dl_list_del(&entry
->list
);
270 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
272 ie
= wpa_auth_get_wpa_ie(mesh_rsn
->auth
, &ie_len
);
273 conf
->rsn_ie
= (u8
*) ie
;
274 conf
->rsn_ie_len
= ie_len
;
276 wpa_supplicant_rsn_supp_set_config(wpa_s
, wpa_s
->current_ssid
);
282 static int index_within_array(const int *array
, int idx
)
286 for (i
= 0; i
< idx
; i
++) {
295 static int mesh_rsn_sae_group(struct wpa_supplicant
*wpa_s
,
296 struct sae_data
*sae
)
298 int *groups
= wpa_s
->ifmsh
->bss
[0]->conf
->sae_groups
;
300 /* Configuration may have changed, so validate current index */
301 if (!index_within_array(groups
, wpa_s
->mesh_rsn
->sae_group_index
))
305 int group
= groups
[wpa_s
->mesh_rsn
->sae_group_index
];
309 if (sae_set_group(sae
, group
) == 0) {
310 wpa_dbg(wpa_s
, MSG_DEBUG
, "SME: Selected SAE group %d",
314 wpa_s
->mesh_rsn
->sae_group_index
++;
321 static int mesh_rsn_build_sae_commit(struct wpa_supplicant
*wpa_s
,
322 struct wpa_ssid
*ssid
,
323 struct sta_info
*sta
)
325 const char *password
;
327 password
= ssid
->sae_password
;
329 password
= ssid
->passphrase
;
331 wpa_msg(wpa_s
, MSG_DEBUG
, "SAE: No password available");
335 if (mesh_rsn_sae_group(wpa_s
, sta
->sae
) < 0) {
336 wpa_msg(wpa_s
, MSG_DEBUG
, "SAE: Failed to select group");
340 if (sta
->sae
->tmp
&& !sta
->sae
->tmp
->pw_id
&& ssid
->sae_password_id
) {
341 sta
->sae
->tmp
->pw_id
= os_strdup(ssid
->sae_password_id
);
342 if (!sta
->sae
->tmp
->pw_id
)
345 return sae_prepare_commit(wpa_s
->own_addr
, sta
->addr
,
346 (u8
*) password
, os_strlen(password
),
347 ssid
->sae_password_id
,
352 /* initiate new SAE authentication with sta */
353 int mesh_rsn_auth_sae_sta(struct wpa_supplicant
*wpa_s
,
354 struct sta_info
*sta
)
356 struct hostapd_data
*hapd
= wpa_s
->ifmsh
->bss
[0];
357 struct wpa_ssid
*ssid
= wpa_s
->current_ssid
;
358 struct rsn_pmksa_cache_entry
*pmksa
;
363 wpa_msg(wpa_s
, MSG_DEBUG
,
364 "AUTH: No current_ssid known to initiate new SAE");
369 sta
->sae
= os_zalloc(sizeof(*sta
->sae
));
370 if (sta
->sae
== NULL
)
374 pmksa
= wpa_auth_pmksa_get(hapd
->wpa_auth
, sta
->addr
, NULL
);
377 sta
->wpa_sm
= wpa_auth_sta_init(hapd
->wpa_auth
,
380 wpa_printf(MSG_ERROR
,
381 "mesh: Failed to initialize RSN state machine");
385 wpa_printf(MSG_DEBUG
,
386 "AUTH: Mesh PMKSA cache entry found for " MACSTR
387 " - try to use PMKSA caching instead of new SAE authentication",
389 wpa_auth_pmksa_set_to_sm(pmksa
, sta
->wpa_sm
, hapd
->wpa_auth
,
390 sta
->sae
->pmkid
, sta
->sae
->pmk
);
391 sae_accept_sta(hapd
, sta
);
392 sta
->mesh_sae_pmksa_caching
= 1;
395 sta
->mesh_sae_pmksa_caching
= 0;
397 if (mesh_rsn_build_sae_commit(wpa_s
, ssid
, sta
))
400 wpa_msg(wpa_s
, MSG_DEBUG
,
401 "AUTH: started authentication with SAE peer: " MACSTR
,
404 ret
= auth_sae_init_committed(hapd
, sta
);
408 eloop_cancel_timeout(mesh_auth_timer
, wpa_s
, sta
);
409 rnd
= rand() % MESH_AUTH_TIMEOUT
;
410 eloop_register_timeout(MESH_AUTH_TIMEOUT
+ rnd
, 0, mesh_auth_timer
,
416 void mesh_rsn_get_pmkid(struct mesh_rsn
*rsn
, struct sta_info
*sta
, u8
*pmkid
)
418 os_memcpy(pmkid
, sta
->sae
->pmkid
, SAE_PMKID_LEN
);
423 mesh_rsn_derive_aek(struct mesh_rsn
*rsn
, struct sta_info
*sta
)
425 u8
*myaddr
= rsn
->wpa_s
->own_addr
;
426 u8
*peer
= sta
->addr
;
428 u8 context
[RSN_SELECTOR_LEN
+ 2 * ETH_ALEN
], *ptr
= context
;
431 * AEK = KDF-Hash-256(PMK, "AEK Derivation", Selected AKM Suite ||
432 * min(localMAC, peerMAC) || max(localMAC, peerMAC))
434 /* Selected AKM Suite: SAE */
435 RSN_SELECTOR_PUT(ptr
, RSN_AUTH_KEY_MGMT_SAE
);
436 ptr
+= RSN_SELECTOR_LEN
;
438 if (os_memcmp(myaddr
, peer
, ETH_ALEN
) < 0) {
445 os_memcpy(ptr
, addr1
, ETH_ALEN
);
447 os_memcpy(ptr
, addr2
, ETH_ALEN
);
449 sha256_prf(sta
->sae
->pmk
, sizeof(sta
->sae
->pmk
), "AEK Derivation",
450 context
, sizeof(context
), sta
->aek
, sizeof(sta
->aek
));
454 /* derive mesh temporal key from pmk */
455 int mesh_rsn_derive_mtk(struct wpa_supplicant
*wpa_s
, struct sta_info
*sta
)
459 u8
*myaddr
= wpa_s
->own_addr
;
460 u8
*peer
= sta
->addr
;
461 u8 context
[2 * WPA_NONCE_LEN
+ 2 * 2 + RSN_SELECTOR_LEN
+ 2 * ETH_ALEN
];
464 * MTK = KDF-Hash-Length(PMK, "Temporal Key Derivation", min(localNonce,
465 * peerNonce) || max(localNonce, peerNonce) || min(localLinkID,
466 * peerLinkID) || max(localLinkID, peerLinkID) || Selected AKM Suite ||
467 * min(localMAC, peerMAC) || max(localMAC, peerMAC))
470 if (os_memcmp(sta
->my_nonce
, sta
->peer_nonce
, WPA_NONCE_LEN
) < 0) {
472 max
= sta
->peer_nonce
;
474 min
= sta
->peer_nonce
;
477 os_memcpy(ptr
, min
, WPA_NONCE_LEN
);
478 ptr
+= WPA_NONCE_LEN
;
479 os_memcpy(ptr
, max
, WPA_NONCE_LEN
);
480 ptr
+= WPA_NONCE_LEN
;
482 if (sta
->my_lid
< sta
->peer_lid
) {
483 WPA_PUT_LE16(ptr
, sta
->my_lid
);
485 WPA_PUT_LE16(ptr
, sta
->peer_lid
);
488 WPA_PUT_LE16(ptr
, sta
->peer_lid
);
490 WPA_PUT_LE16(ptr
, sta
->my_lid
);
494 /* Selected AKM Suite: SAE */
495 RSN_SELECTOR_PUT(ptr
, RSN_AUTH_KEY_MGMT_SAE
);
496 ptr
+= RSN_SELECTOR_LEN
;
498 if (os_memcmp(myaddr
, peer
, ETH_ALEN
) < 0) {
505 os_memcpy(ptr
, min
, ETH_ALEN
);
507 os_memcpy(ptr
, max
, ETH_ALEN
);
509 sta
->mtk_len
= wpa_cipher_key_len(wpa_s
->mesh_rsn
->pairwise_cipher
);
510 sha256_prf(sta
->sae
->pmk
, SAE_PMK_LEN
,
511 "Temporal Key Derivation", context
, sizeof(context
),
512 sta
->mtk
, sta
->mtk_len
);
517 void mesh_rsn_init_ampe_sta(struct wpa_supplicant
*wpa_s
, struct sta_info
*sta
)
519 if (random_get_bytes(sta
->my_nonce
, WPA_NONCE_LEN
) < 0) {
520 wpa_printf(MSG_INFO
, "mesh: Failed to derive random nonce");
521 /* TODO: How to handle this more cleanly? */
523 os_memset(sta
->peer_nonce
, 0, WPA_NONCE_LEN
);
524 mesh_rsn_derive_aek(wpa_s
->mesh_rsn
, sta
);
528 /* insert AMPE and encrypted MIC at @ie.
529 * @mesh_rsn: mesh RSN context
530 * @sta: STA we're sending to
531 * @cat: pointer to category code in frame header.
532 * @buf: wpabuf to add encrypted AMPE and MIC to.
534 int mesh_rsn_protect_frame(struct mesh_rsn
*rsn
, struct sta_info
*sta
,
535 const u8
*cat
, struct wpabuf
*buf
)
537 struct ieee80211_ampe_ie
*ampe
;
538 u8
const *ie
= wpabuf_head_u8(buf
) + wpabuf_len(buf
);
539 u8
*ampe_ie
, *pos
, *mic_payload
;
540 const u8
*aad
[] = { rsn
->wpa_s
->own_addr
, sta
->addr
, cat
};
541 const size_t aad_len
[] = { ETH_ALEN
, ETH_ALEN
, ie
- cat
};
546 if (cat
[1] == PLINK_OPEN
)
547 len
+= rsn
->mgtk_len
+ WPA_KEY_RSC_LEN
+ 4;
548 #ifdef CONFIG_IEEE80211W
549 if (cat
[1] == PLINK_OPEN
&& rsn
->igtk_len
)
550 len
+= 2 + 6 + rsn
->igtk_len
;
551 #endif /* CONFIG_IEEE80211W */
553 if (2 + AES_BLOCK_SIZE
+ 2 + len
> wpabuf_tailroom(buf
)) {
554 wpa_printf(MSG_ERROR
, "protect frame: buffer too small");
558 ampe_ie
= os_zalloc(2 + len
);
560 wpa_printf(MSG_ERROR
, "protect frame: out of memory");
565 ampe_ie
[0] = WLAN_EID_AMPE
;
567 ampe
= (struct ieee80211_ampe_ie
*) (ampe_ie
+ 2);
569 RSN_SELECTOR_PUT(ampe
->selected_pairwise_suite
,
570 RSN_CIPHER_SUITE_CCMP
);
571 os_memcpy(ampe
->local_nonce
, sta
->my_nonce
, WPA_NONCE_LEN
);
572 os_memcpy(ampe
->peer_nonce
, sta
->peer_nonce
, WPA_NONCE_LEN
);
574 pos
= (u8
*) (ampe
+ 1);
575 if (cat
[1] != PLINK_OPEN
)
578 /* TODO: Key Replay Counter[8] optionally for
579 * Mesh Group Key Inform/Acknowledge frames */
581 /* TODO: static mgtk for now since we don't support rekeying! */
584 * MGTK[variable] || Key RSC[8] || GTKExpirationTime[4]
586 os_memcpy(pos
, rsn
->mgtk
, rsn
->mgtk_len
);
587 pos
+= rsn
->mgtk_len
;
588 wpa_drv_get_seqnum(rsn
->wpa_s
, NULL
, rsn
->mgtk_key_id
, pos
);
589 pos
+= WPA_KEY_RSC_LEN
;
590 /* Use fixed GTKExpirationTime for now */
591 WPA_PUT_LE32(pos
, 0xffffffff);
594 #ifdef CONFIG_IEEE80211W
596 * IGTKdata[variable]:
597 * Key ID[2], IPN[6], IGTK[variable]
600 WPA_PUT_LE16(pos
, rsn
->igtk_key_id
);
602 wpa_drv_get_seqnum(rsn
->wpa_s
, NULL
, rsn
->igtk_key_id
, pos
);
604 os_memcpy(pos
, rsn
->igtk
, rsn
->igtk_len
);
606 #endif /* CONFIG_IEEE80211W */
609 wpa_hexdump_key(MSG_DEBUG
, "mesh: Plaintext AMPE element",
613 wpabuf_put_u8(buf
, WLAN_EID_MIC
);
614 wpabuf_put_u8(buf
, AES_BLOCK_SIZE
);
615 /* MIC field is output ciphertext */
617 /* encrypt after MIC */
618 mic_payload
= wpabuf_put(buf
, 2 + len
+ AES_BLOCK_SIZE
);
620 if (aes_siv_encrypt(sta
->aek
, sizeof(sta
->aek
), ampe_ie
, 2 + len
, 3,
621 aad
, aad_len
, mic_payload
)) {
622 wpa_printf(MSG_ERROR
, "protect frame: failed to encrypt");
632 int mesh_rsn_process_ampe(struct wpa_supplicant
*wpa_s
, struct sta_info
*sta
,
633 struct ieee802_11_elems
*elems
, const u8
*cat
,
634 const u8
*chosen_pmk
,
635 const u8
*start
, size_t elems_len
)
638 struct ieee80211_ampe_ie
*ampe
;
639 u8 null_nonce
[WPA_NONCE_LEN
] = {};
642 u8
*ampe_buf
, *crypt
= NULL
, *pos
, *end
;
644 const u8
*aad
[] = { sta
->addr
, wpa_s
->own_addr
, cat
};
645 const size_t aad_len
[] = { ETH_ALEN
, ETH_ALEN
,
646 elems
->mic
? (elems
->mic
- 2) - cat
: 0 };
650 struct hostapd_data
*hapd
= wpa_s
->ifmsh
->bss
[0];
652 if (!wpa_auth_pmksa_get(hapd
->wpa_auth
, sta
->addr
, NULL
)) {
654 "Mesh RSN: SAE is not prepared yet");
657 mesh_rsn_auth_sae_sta(wpa_s
, sta
);
662 os_memcmp(chosen_pmk
, sta
->sae
->pmkid
, PMKID_LEN
) != 0)) {
663 wpa_msg(wpa_s
, MSG_DEBUG
,
664 "Mesh RSN: Invalid PMKID (Chosen PMK did not match calculated PMKID)");
668 if (!elems
->mic
|| elems
->mic_len
< AES_BLOCK_SIZE
) {
669 wpa_msg(wpa_s
, MSG_DEBUG
, "Mesh RSN: missing mic ie");
673 ampe_buf
= (u8
*) elems
->mic
+ elems
->mic_len
;
674 if ((int) elems_len
< ampe_buf
- start
)
677 crypt_len
= elems_len
- (elems
->mic
- start
);
678 if (crypt_len
< 2 + AES_BLOCK_SIZE
) {
679 wpa_msg(wpa_s
, MSG_DEBUG
, "Mesh RSN: missing ampe ie");
683 /* crypt is modified by siv_decrypt */
684 crypt
= os_zalloc(crypt_len
);
686 wpa_printf(MSG_ERROR
, "Mesh RSN: out of memory");
691 os_memcpy(crypt
, elems
->mic
, crypt_len
);
693 if (aes_siv_decrypt(sta
->aek
, sizeof(sta
->aek
), crypt
, crypt_len
, 3,
694 aad
, aad_len
, ampe_buf
)) {
695 wpa_printf(MSG_ERROR
, "Mesh RSN: frame verification failed!");
700 crypt_len
-= AES_BLOCK_SIZE
;
701 wpa_hexdump_key(MSG_DEBUG
, "mesh: Decrypted AMPE element",
702 ampe_buf
, crypt_len
);
704 ampe_eid
= *ampe_buf
++;
705 ampe_ie_len
= *ampe_buf
++;
707 if (ampe_eid
!= WLAN_EID_AMPE
||
708 (size_t) 2 + ampe_ie_len
> crypt_len
||
709 ampe_ie_len
< sizeof(struct ieee80211_ampe_ie
)) {
710 wpa_msg(wpa_s
, MSG_DEBUG
, "Mesh RSN: invalid ampe ie");
715 ampe
= (struct ieee80211_ampe_ie
*) ampe_buf
;
716 pos
= (u8
*) (ampe
+ 1);
717 end
= ampe_buf
+ ampe_ie_len
;
718 if (os_memcmp(ampe
->peer_nonce
, null_nonce
, WPA_NONCE_LEN
) != 0 &&
719 os_memcmp(ampe
->peer_nonce
, sta
->my_nonce
, WPA_NONCE_LEN
) != 0) {
720 wpa_msg(wpa_s
, MSG_DEBUG
, "Mesh RSN: invalid peer nonce");
724 os_memcpy(sta
->peer_nonce
, ampe
->local_nonce
,
725 sizeof(ampe
->local_nonce
));
727 /* TODO: Key Replay Counter[8] in Mesh Group Key Inform/Acknowledge
731 * GTKdata shall not be included in Mesh Peering Confirm. While the
732 * standard does not state the same about IGTKdata, that same constraint
733 * needs to apply for it. It makes no sense to include the keys in Mesh
734 * Peering Close frames either, so while the standard does not seem to
735 * have a shall statement for these, they are described without
736 * mentioning GTKdata.
738 * An earlier implementation used to add GTKdata to both Mesh Peering
739 * Open and Mesh Peering Confirm frames, so ignore the possibly present
740 * GTKdata frame without rejecting the frame as a backwards
741 * compatibility mechanism.
743 if (cat
[1] != PLINK_OPEN
) {
745 wpa_hexdump_key(MSG_DEBUG
,
746 "mesh: Ignore unexpected GTKdata(etc.) fields in the end of AMPE element in Mesh Peering Confirm/Close",
754 * MGTK[variable] || Key RSC[8] || GTKExpirationTime[4]
756 sta
->mgtk_key_id
= 1; /* FIX: Where to get Key ID? */
757 key_len
= wpa_cipher_key_len(wpa_s
->mesh_rsn
->group_cipher
);
758 if ((int) key_len
+ WPA_KEY_RSC_LEN
+ 4 > end
- pos
) {
759 wpa_dbg(wpa_s
, MSG_DEBUG
, "mesh: Truncated AMPE element");
763 sta
->mgtk_len
= key_len
;
764 os_memcpy(sta
->mgtk
, pos
, sta
->mgtk_len
);
765 wpa_hexdump_key(MSG_DEBUG
, "mesh: GTKdata - MGTK",
766 sta
->mgtk
, sta
->mgtk_len
);
767 pos
+= sta
->mgtk_len
;
768 wpa_hexdump(MSG_DEBUG
, "mesh: GTKdata - MGTK - Key RSC",
769 pos
, WPA_KEY_RSC_LEN
);
770 os_memcpy(sta
->mgtk_rsc
, pos
, sizeof(sta
->mgtk_rsc
));
771 pos
+= WPA_KEY_RSC_LEN
;
772 wpa_printf(MSG_DEBUG
,
773 "mesh: GTKdata - MGTK - GTKExpirationTime: %u seconds",
777 #ifdef CONFIG_IEEE80211W
779 * IGTKdata[variable]:
780 * Key ID[2], IPN[6], IGTK[variable]
782 key_len
= wpa_cipher_key_len(wpa_s
->mesh_rsn
->mgmt_group_cipher
);
783 if (end
- pos
>= (int) (2 + 6 + key_len
)) {
784 sta
->igtk_key_id
= WPA_GET_LE16(pos
);
785 wpa_printf(MSG_DEBUG
, "mesh: IGTKdata - Key ID %u",
788 os_memcpy(sta
->igtk_rsc
, pos
, sizeof(sta
->igtk_rsc
));
789 wpa_hexdump(MSG_DEBUG
, "mesh: IGTKdata - IPN",
790 sta
->igtk_rsc
, sizeof(sta
->igtk_rsc
));
792 os_memcpy(sta
->igtk
, pos
, key_len
);
793 sta
->igtk_len
= key_len
;
794 wpa_hexdump_key(MSG_DEBUG
, "mesh: IGTKdata - IGTK",
795 sta
->igtk
, sta
->igtk_len
);
797 #endif /* CONFIG_IEEE80211W */