2 * wpa_supplicant - IBSS RSN
3 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
18 #include "l2_packet/l2_packet.h"
19 #include "wpa_supplicant_i.h"
22 #include "../hostapd/wpa.h"
26 static void ibss_rsn_free(struct ibss_rsn_peer
*peer
)
28 wpa_auth_sta_deinit(peer
->auth
);
29 wpa_sm_deinit(peer
->supp
);
34 static void supp_set_state(void *ctx
, wpa_states state
)
36 struct ibss_rsn_peer
*peer
= ctx
;
37 peer
->supp_state
= state
;
41 static int supp_ether_send(void *ctx
, const u8
*dest
, u16 proto
, const u8
*buf
,
44 struct ibss_rsn_peer
*peer
= ctx
;
45 struct wpa_supplicant
*wpa_s
= peer
->ibss_rsn
->wpa_s
;
47 wpa_printf(MSG_DEBUG
, "SUPP: %s(dest=" MACSTR
" proto=0x%04x "
49 __func__
, MAC2STR(dest
), proto
, (unsigned long) len
);
52 return l2_packet_send(wpa_s
->l2
, dest
, proto
, buf
, len
);
54 return wpa_drv_send_eapol(wpa_s
, dest
, proto
, buf
, len
);
58 static u8
* supp_alloc_eapol(void *ctx
, u8 type
, const void *data
,
59 u16 data_len
, size_t *msg_len
, void **data_pos
)
61 struct ieee802_1x_hdr
*hdr
;
63 wpa_printf(MSG_DEBUG
, "SUPP: %s(type=%d data_len=%d)",
64 __func__
, type
, data_len
);
66 *msg_len
= sizeof(*hdr
) + data_len
;
67 hdr
= os_malloc(*msg_len
);
73 hdr
->length
= host_to_be16(data_len
);
76 os_memcpy(hdr
+ 1, data
, data_len
);
78 os_memset(hdr
+ 1, 0, data_len
);
87 static int supp_get_beacon_ie(void *ctx
)
89 struct ibss_rsn_peer
*peer
= ctx
;
91 wpa_printf(MSG_DEBUG
, "SUPP: %s", __func__
);
92 /* TODO: get correct RSN IE */
93 return wpa_sm_set_ap_rsn_ie(peer
->supp
,
94 (u8
*) "\x30\x14\x01\x00"
96 "\x01\x00\x00\x0f\xac\x04"
97 "\x01\x00\x00\x0f\xac\x02"
102 static int supp_set_key(void *ctx
, wpa_alg alg
,
103 const u8
*addr
, int key_idx
, int set_tx
,
104 const u8
*seq
, size_t seq_len
,
105 const u8
*key
, size_t key_len
)
107 struct ibss_rsn_peer
*peer
= ctx
;
111 * In IBSS RSN, the pairwise key from the 4-way handshake
112 * initiated by the peer with highest MAC address is used.
114 if (os_memcmp(peer
->ibss_rsn
->wpa_s
->own_addr
, peer
->addr
,
119 wpa_printf(MSG_DEBUG
, "SUPP: %s(alg=%d addr=" MACSTR
" key_idx=%d "
121 __func__
, alg
, MAC2STR(addr
), key_idx
, set_tx
);
122 wpa_hexdump(MSG_DEBUG
, "SUPP: set_key - seq", seq
, seq_len
);
123 wpa_hexdump_key(MSG_DEBUG
, "SUPP: set_key - key", key
, key_len
);
125 return wpa_drv_set_key(peer
->ibss_rsn
->wpa_s
, alg
, addr
, key_idx
,
126 set_tx
, seq
, seq_len
, key
, key_len
);
130 static void * supp_get_network_ctx(void *ctx
)
132 struct ibss_rsn_peer
*peer
= ctx
;
133 return wpa_supplicant_get_ssid(peer
->ibss_rsn
->wpa_s
);
137 static int supp_mlme_setprotection(void *ctx
, const u8
*addr
,
138 int protection_type
, int key_type
)
140 wpa_printf(MSG_DEBUG
, "SUPP: %s(addr=" MACSTR
" protection_type=%d "
142 __func__
, MAC2STR(addr
), protection_type
, key_type
);
147 static void supp_cancel_auth_timeout(void *ctx
)
149 wpa_printf(MSG_DEBUG
, "SUPP: %s", __func__
);
153 int ibss_rsn_supp_init(struct ibss_rsn_peer
*peer
, const u8
*own_addr
,
156 struct wpa_sm_ctx
*ctx
= os_zalloc(sizeof(*ctx
));
161 ctx
->msg_ctx
= peer
->ibss_rsn
->wpa_s
;
162 ctx
->set_state
= supp_set_state
;
163 ctx
->ether_send
= supp_ether_send
;
164 ctx
->get_beacon_ie
= supp_get_beacon_ie
;
165 ctx
->alloc_eapol
= supp_alloc_eapol
;
166 ctx
->set_key
= supp_set_key
;
167 ctx
->get_network_ctx
= supp_get_network_ctx
;
168 ctx
->mlme_setprotection
= supp_mlme_setprotection
;
169 ctx
->cancel_auth_timeout
= supp_cancel_auth_timeout
;
170 peer
->supp
= wpa_sm_init(ctx
);
171 if (peer
->supp
== NULL
) {
172 wpa_printf(MSG_DEBUG
, "SUPP: wpa_sm_init() failed");
176 wpa_sm_set_own_addr(peer
->supp
, own_addr
);
177 wpa_sm_set_param(peer
->supp
, WPA_PARAM_RSN_ENABLED
, 1);
178 wpa_sm_set_param(peer
->supp
, WPA_PARAM_PROTO
, WPA_PROTO_RSN
);
179 wpa_sm_set_param(peer
->supp
, WPA_PARAM_PAIRWISE
, WPA_CIPHER_CCMP
);
180 wpa_sm_set_param(peer
->supp
, WPA_PARAM_GROUP
, WPA_CIPHER_CCMP
);
181 wpa_sm_set_param(peer
->supp
, WPA_PARAM_KEY_MGMT
, WPA_KEY_MGMT_PSK
);
182 wpa_sm_set_pmk(peer
->supp
, psk
, PMK_LEN
);
184 peer
->supp_ie_len
= sizeof(peer
->supp_ie
);
185 if (wpa_sm_set_assoc_wpa_ie_default(peer
->supp
, peer
->supp_ie
,
186 &peer
->supp_ie_len
) < 0) {
187 wpa_printf(MSG_DEBUG
, "SUPP: wpa_sm_set_assoc_wpa_ie_default()"
192 wpa_sm_notify_assoc(peer
->supp
, peer
->addr
);
198 static void auth_logger(void *ctx
, const u8
*addr
, logger_level level
,
202 wpa_printf(MSG_DEBUG
, "AUTH: " MACSTR
" - %s",
205 wpa_printf(MSG_DEBUG
, "AUTH: %s", txt
);
209 static const u8
* auth_get_psk(void *ctx
, const u8
*addr
, const u8
*prev_psk
)
211 struct ibss_rsn
*ibss_rsn
= ctx
;
212 wpa_printf(MSG_DEBUG
, "AUTH: %s (addr=" MACSTR
" prev_psk=%p)",
213 __func__
, MAC2STR(addr
), prev_psk
);
216 return ibss_rsn
->psk
;
220 static int auth_send_eapol(void *ctx
, const u8
*addr
, const u8
*data
,
221 size_t data_len
, int encrypt
)
223 struct ibss_rsn
*ibss_rsn
= ctx
;
224 struct wpa_supplicant
*wpa_s
= ibss_rsn
->wpa_s
;
226 wpa_printf(MSG_DEBUG
, "AUTH: %s(addr=" MACSTR
" data_len=%lu "
228 __func__
, MAC2STR(addr
), (unsigned long) data_len
, encrypt
);
231 return l2_packet_send(wpa_s
->l2
, addr
, ETH_P_EAPOL
, data
,
234 return wpa_drv_send_eapol(wpa_s
, addr
, ETH_P_EAPOL
, data
, data_len
);
238 static int auth_set_key(void *ctx
, int vlan_id
, const char *_alg
,
239 const u8
*addr
, int idx
, u8
*key
,
242 struct ibss_rsn
*ibss_rsn
= ctx
;
246 os_memset(seq
, 0, sizeof(seq
));
247 if (os_strcmp(_alg
, "none") == 0)
249 else if (os_strcmp(_alg
, "WEP") == 0)
251 else if (os_strcmp(_alg
, "TKIP") == 0)
253 else if (os_strcmp(_alg
, "CCMP") == 0)
255 else if (os_strcmp(_alg
, "IGTK") == 0)
262 * In IBSS RSN, the pairwise key from the 4-way handshake
263 * initiated by the peer with highest MAC address is used.
265 if (os_memcmp(ibss_rsn
->wpa_s
->own_addr
, addr
, ETH_ALEN
) < 0)
269 return wpa_drv_set_key(ibss_rsn
->wpa_s
, alg
, addr
, idx
,
270 1, seq
, 6, key
, key_len
);
274 static int ibss_rsn_auth_init_group(struct ibss_rsn
*ibss_rsn
,
277 struct wpa_auth_config conf
;
278 struct wpa_auth_callbacks cb
;
280 wpa_printf(MSG_DEBUG
, "AUTH: Initializing group state machine");
282 os_memset(&conf
, 0, sizeof(conf
));
284 conf
.wpa_key_mgmt
= WPA_KEY_MGMT_PSK
;
285 conf
.wpa_pairwise
= WPA_CIPHER_CCMP
;
286 conf
.rsn_pairwise
= WPA_CIPHER_CCMP
;
287 conf
.wpa_group
= WPA_CIPHER_CCMP
;
288 conf
.eapol_version
= 2;
290 os_memset(&cb
, 0, sizeof(cb
));
292 cb
.logger
= auth_logger
;
293 cb
.send_eapol
= auth_send_eapol
;
294 cb
.get_psk
= auth_get_psk
;
295 cb
.set_key
= auth_set_key
;
297 ibss_rsn
->auth_group
= wpa_init(own_addr
, &conf
, &cb
);
298 if (ibss_rsn
->auth_group
== NULL
) {
299 wpa_printf(MSG_DEBUG
, "AUTH: wpa_init() failed");
307 static int ibss_rsn_auth_init(struct ibss_rsn
*ibss_rsn
,
308 struct ibss_rsn_peer
*peer
)
310 peer
->auth
= wpa_auth_sta_init(ibss_rsn
->auth_group
, peer
->addr
);
311 if (peer
->auth
== NULL
) {
312 wpa_printf(MSG_DEBUG
, "AUTH: wpa_auth_sta_init() failed");
316 /* TODO: get peer RSN IE with Probe Request */
317 if (wpa_validate_wpa_ie(ibss_rsn
->auth_group
, peer
->auth
,
318 (u8
*) "\x30\x14\x01\x00"
320 "\x01\x00\x00\x0f\xac\x04"
321 "\x01\x00\x00\x0f\xac\x02"
322 "\x00\x00", 22, NULL
, 0) !=
324 wpa_printf(MSG_DEBUG
, "AUTH: wpa_validate_wpa_ie() failed");
328 wpa_auth_sm_event(peer
->auth
, WPA_ASSOC
);
330 wpa_auth_sta_associated(ibss_rsn
->auth_group
, peer
->auth
);
336 int ibss_rsn_start(struct ibss_rsn
*ibss_rsn
, const u8
*addr
)
338 struct ibss_rsn_peer
*peer
;
340 wpa_printf(MSG_DEBUG
, "RSN: Starting IBSS Authenticator and "
341 "Supplicant for peer " MACSTR
, MAC2STR(addr
));
343 peer
= os_zalloc(sizeof(*peer
));
347 peer
->ibss_rsn
= ibss_rsn
;
348 os_memcpy(peer
->addr
, addr
, ETH_ALEN
);
350 if (ibss_rsn_supp_init(peer
, ibss_rsn
->wpa_s
->own_addr
, ibss_rsn
->psk
)
356 if (ibss_rsn_auth_init(ibss_rsn
, peer
) < 0) {
361 peer
->next
= ibss_rsn
->peers
;
362 ibss_rsn
->peers
= peer
;
368 struct ibss_rsn
* ibss_rsn_init(struct wpa_supplicant
*wpa_s
)
370 struct ibss_rsn
*ibss_rsn
;
372 ibss_rsn
= os_zalloc(sizeof(*ibss_rsn
));
373 if (ibss_rsn
== NULL
)
375 ibss_rsn
->wpa_s
= wpa_s
;
377 if (ibss_rsn_auth_init_group(ibss_rsn
, wpa_s
->own_addr
) < 0) {
378 ibss_rsn_deinit(ibss_rsn
);
386 void ibss_rsn_deinit(struct ibss_rsn
*ibss_rsn
)
388 struct ibss_rsn_peer
*peer
, *prev
;
390 if (ibss_rsn
== NULL
)
393 peer
= ibss_rsn
->peers
;
400 wpa_deinit(ibss_rsn
->auth_group
);
406 static int ibss_rsn_eapol_dst_supp(const u8
*buf
, size_t len
)
408 const struct ieee802_1x_hdr
*hdr
;
409 const struct wpa_eapol_key
*key
;
413 /* TODO: Support other EAPOL packets than just EAPOL-Key */
415 if (len
< sizeof(*hdr
) + sizeof(*key
))
418 hdr
= (const struct ieee802_1x_hdr
*) buf
;
419 key
= (const struct wpa_eapol_key
*) (hdr
+ 1);
420 plen
= be_to_host16(hdr
->length
);
422 if (hdr
->version
< EAPOL_VERSION
) {
423 /* TODO: backwards compatibility */
425 if (hdr
->type
!= IEEE802_1X_TYPE_EAPOL_KEY
) {
426 wpa_printf(MSG_DEBUG
, "RSN: EAPOL frame (type %u) discarded, "
427 "not a Key frame", hdr
->type
);
430 if (plen
> len
- sizeof(*hdr
) || plen
< sizeof(*key
)) {
431 wpa_printf(MSG_DEBUG
, "RSN: EAPOL frame payload size %lu "
432 "invalid (frame size %lu)",
433 (unsigned long) plen
, (unsigned long) len
);
437 if (key
->type
!= EAPOL_KEY_TYPE_RSN
) {
438 wpa_printf(MSG_DEBUG
, "RSN: EAPOL-Key type (%d) unknown, "
439 "discarded", key
->type
);
443 key_info
= WPA_GET_BE16(key
->key_info
);
445 return !!(key_info
& WPA_KEY_INFO_ACK
);
449 static int ibss_rsn_process_rx_eapol(struct ibss_rsn
*ibss_rsn
,
450 struct ibss_rsn_peer
*peer
,
451 const u8
*buf
, size_t len
)
456 supp
= ibss_rsn_eapol_dst_supp(buf
, len
);
460 tmp
= os_malloc(len
);
463 os_memcpy(tmp
, buf
, len
);
465 wpa_printf(MSG_DEBUG
, "RSN: IBSS RX EAPOL for Supplicant");
466 wpa_sm_rx_eapol(peer
->supp
, peer
->addr
, tmp
, len
);
468 wpa_printf(MSG_DEBUG
, "RSN: IBSS RX EAPOL for Authenticator");
469 wpa_receive(ibss_rsn
->auth_group
, peer
->auth
, tmp
, len
);
477 int ibss_rsn_rx_eapol(struct ibss_rsn
*ibss_rsn
, const u8
*src_addr
,
478 const u8
*buf
, size_t len
)
480 struct ibss_rsn_peer
*peer
;
482 for (peer
= ibss_rsn
->peers
; peer
; peer
= peer
->next
) {
483 if (os_memcmp(src_addr
, peer
->addr
, ETH_ALEN
) == 0)
484 return ibss_rsn_process_rx_eapol(ibss_rsn
, peer
,
488 if (ibss_rsn_eapol_dst_supp(buf
, len
) > 0) {
490 * Create new IBSS peer based on an EAPOL message from the peer
493 if (ibss_rsn_start(ibss_rsn
, src_addr
) < 0)
495 return ibss_rsn_process_rx_eapol(ibss_rsn
, ibss_rsn
->peers
,
503 void ibss_rsn_set_psk(struct ibss_rsn
*ibss_rsn
, const u8
*psk
)
505 os_memcpy(ibss_rsn
->psk
, psk
, PMK_LEN
);