1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/*
2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Test program for combined WPA authenticator/supplicant
3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify
6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as
7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation.
8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license.
11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details.
13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h"
16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h"
18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eloop.h"
19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "ieee802_11_defs.h"
20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "config.h"
21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "wpa.h"
22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "wpa_ie.h"
23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "../hostapd/wpa.h"
24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtextern int wpa_debug_level;
27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtextern int wpa_debug_show_keys;
28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct wpa {
31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 auth_addr[ETH_ALEN];
32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 supp_addr[ETH_ALEN];
33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 psk[PMK_LEN];
34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* from authenticator */
36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 auth_eapol_dst[ETH_ALEN];
37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 *auth_eapol;
38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t auth_eapol_len;
39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* from supplicant */
41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 *supp_eapol;
42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t supp_eapol_len;
43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_sm *supp;
45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_authenticator *auth_group;
46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_state_machine *auth;
47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_ssid ssid;
49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 supp_ie[80];
50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t supp_ie_len;
51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpa_ssid * supp_get_ssid(void *ctx)
55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa *wpa = ctx;
57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return &wpa->ssid;
59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int supp_get_bssid(void *ctx, u8 *bssid)
63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa *wpa = ctx;
65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(bssid, wpa->auth_addr, ETH_ALEN);
67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void supp_set_state(void *ctx, wpa_states state)
72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "SUPP: %s(state=%d)", __func__, state);
74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void auth_eapol_rx(void *eloop_data, void *user_ctx)
78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa *wpa = eloop_data;
80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "AUTH: RX EAPOL frame");
82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_receive(wpa->auth_group, wpa->auth, wpa->supp_eapol,
83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    wpa->supp_eapol_len);
84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int supp_ether_send(void *ctx, const u8 *dest, u16 proto, const u8 *buf,
88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   size_t len)
89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa *wpa = ctx;
91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "SUPP: %s(dest=" MACSTR " proto=0x%04x "
93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "len=%lu)",
94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   __func__, MAC2STR(dest), proto, (unsigned long) len);
95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(wpa->supp_eapol);
97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa->supp_eapol = os_malloc(len);
98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wpa->supp_eapol == NULL)
99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(wpa->supp_eapol, buf, len);
101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa->supp_eapol_len = len;
102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eloop_register_timeout(0, 0, auth_eapol_rx, wpa, NULL);
103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic u8 * supp_alloc_eapol(void *ctx, u8 type, const void *data,
109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			     u16 data_len, size_t *msg_len, void **data_pos)
110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct ieee802_1x_hdr *hdr;
112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "SUPP: %s(type=%d data_len=%d)",
114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   __func__, type, data_len);
115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*msg_len = sizeof(*hdr) + data_len;
117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hdr = os_malloc(*msg_len);
118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (hdr == NULL)
119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hdr->version = 2;
122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hdr->type = type;
123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hdr->length = host_to_be16(data_len);
124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (data)
126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(hdr + 1, data, data_len);
127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	else
128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memset(hdr + 1, 0, data_len);
129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (data_pos)
131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*data_pos = hdr + 1;
132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return (u8 *) hdr;
134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int supp_get_beacon_ie(void *ctx)
138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa *wpa = ctx;
140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	const u8 *ie;
141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t ielen;
142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ie = wpa_auth_get_wpa_ie(wpa->auth_group, &ielen);
146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ie == NULL || ielen < 1)
147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ie[0] == WLAN_EID_RSN)
149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return wpa_sm_set_ap_rsn_ie(wpa->supp, ie, 2 + ie[1]);
150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return wpa_sm_set_ap_wpa_ie(wpa->supp, ie, 2 + ie[1]);
151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int supp_set_key(void *ctx, wpa_alg alg,
155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			const u8 *addr, int key_idx, int set_tx,
156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			const u8 *seq, size_t seq_len,
157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			const u8 *key, size_t key_len)
158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "SUPP: %s(alg=%d addr=" MACSTR " key_idx=%d "
160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "set_tx=%d)",
161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   __func__, alg, MAC2STR(addr), key_idx, set_tx);
162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "SUPP: set_key - seq", seq, seq_len);
163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "SUPP: set_key - key", key, key_len);
164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int supp_mlme_setprotection(void *ctx, const u8 *addr,
169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   int protection_type, int key_type)
170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "SUPP: %s(addr=" MACSTR " protection_type=%d "
172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "key_type=%d)",
173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   __func__, MAC2STR(addr), protection_type, key_type);
174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void supp_cancel_scan(void *ctx)
179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void supp_cancel_auth_timeout(void *ctx)
185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int supp_init(struct wpa *wpa)
191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_sm_ctx *ctx = os_zalloc(sizeof(*ctx));
193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ctx == NULL)
194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctx->ctx = wpa;
197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctx->set_state = supp_set_state;
198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctx->get_ssid = supp_get_ssid;
199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctx->get_bssid = supp_get_bssid;
200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctx->ether_send = supp_ether_send;
201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctx->get_beacon_ie = supp_get_beacon_ie;
202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctx->alloc_eapol = supp_alloc_eapol;
203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctx->set_key = supp_set_key;
204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctx->mlme_setprotection = supp_mlme_setprotection;
205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctx->cancel_scan = supp_cancel_scan;
206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctx->cancel_auth_timeout = supp_cancel_auth_timeout;
207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa->supp = wpa_sm_init(ctx);
208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wpa->supp == NULL) {
209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed");
210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_sm_set_own_addr(wpa->supp, wpa->supp_addr);
214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_sm_set_param(wpa->supp, WPA_PARAM_RSN_ENABLED, 1);
215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_sm_set_param(wpa->supp, WPA_PARAM_PROTO, WPA_PROTO_RSN);
216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_sm_set_param(wpa->supp, WPA_PARAM_PAIRWISE, WPA_CIPHER_CCMP);
217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_sm_set_param(wpa->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP);
218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_sm_set_param(wpa->supp, WPA_PARAM_KEY_MGMT, WPA_KEY_MGMT_PSK);
219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_sm_set_pmk(wpa->supp, wpa->psk, PMK_LEN);
220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa->supp_ie_len = sizeof(wpa->supp_ie);
222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wpa_sm_set_assoc_wpa_ie_default(wpa->supp, wpa->supp_ie,
223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					    &wpa->supp_ie_len) < 0) {
224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_set_assoc_wpa_ie_default()"
225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   " failed");
226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_sm_notify_assoc(wpa->supp, wpa->auth_addr);
230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void auth_logger(void *ctx, const u8 *addr, logger_level level,
236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			const char *txt)
237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (addr)
239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "AUTH: " MACSTR " - %s",
240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   MAC2STR(addr), txt);
241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	else
242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "AUTH: %s", txt);
243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void supp_eapol_rx(void *eloop_data, void *user_ctx)
247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa *wpa = eloop_data;
249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "SUPP: RX EAPOL frame");
251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_sm_rx_eapol(wpa->supp, wpa->auth_addr, wpa->auth_eapol,
252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa->auth_eapol_len);
253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int auth_send_eapol(void *ctx, const u8 *addr, const u8 *data,
257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   size_t data_len, int encrypt)
258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa *wpa = ctx;
260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "AUTH: %s(addr=" MACSTR " data_len=%lu "
262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "encrypt=%d)",
263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   __func__, MAC2STR(addr), (unsigned long) data_len, encrypt);
264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(wpa->auth_eapol);
266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa->auth_eapol = os_malloc(data_len);
267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wpa->auth_eapol == NULL)
268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(wpa->auth_eapol_dst, addr, ETH_ALEN);
270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(wpa->auth_eapol, data, data_len);
271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa->auth_eapol_len = data_len;
272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eloop_register_timeout(0, 0, supp_eapol_rx, wpa, NULL);
273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic const u8 * auth_get_psk(void *ctx, const u8 *addr, const u8 *prev_psk)
279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa *wpa = ctx;
281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "AUTH: %s (addr=" MACSTR " prev_psk=%p)",
282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   __func__, MAC2STR(addr), prev_psk);
283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (prev_psk)
284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return wpa->psk;
286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int auth_init_group(struct wpa *wpa)
290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_auth_config conf;
292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_auth_callbacks cb;
293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "AUTH: Initializing group state machine");
295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&conf, 0, sizeof(conf));
297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	conf.wpa = 2;
298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	conf.wpa_key_mgmt = WPA_KEY_MGMT_PSK;
299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	conf.wpa_pairwise = WPA_CIPHER_CCMP;
300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	conf.rsn_pairwise = WPA_CIPHER_CCMP;
301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	conf.wpa_group = WPA_CIPHER_CCMP;
302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	conf.eapol_version = 2;
303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&cb, 0, sizeof(cb));
305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	cb.ctx = wpa;
306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	cb.logger = auth_logger;
307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	cb.send_eapol = auth_send_eapol;
308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	cb.get_psk = auth_get_psk;
309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa->auth_group = wpa_init(wpa->auth_addr, &conf, &cb);
311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wpa->auth_group == NULL) {
312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "AUTH: wpa_init() failed");
313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int auth_init(struct wpa *wpa)
321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa->auth = wpa_auth_sta_init(wpa->auth_group, wpa->supp_addr);
323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wpa->auth == NULL) {
324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "AUTH: wpa_auth_sta_init() failed");
325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wpa_validate_wpa_ie(wpa->auth_group, wpa->auth, wpa->supp_ie,
329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				wpa->supp_ie_len, NULL, 0) != WPA_IE_OK) {
330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "AUTH: wpa_validate_wpa_ie() failed");
331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_auth_sm_event(wpa->auth, WPA_ASSOC);
335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_auth_sta_associated(wpa->auth_group, wpa->auth);
337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void deinit(struct wpa *wpa)
343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_auth_sta_deinit(wpa->auth);
345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_sm_deinit(wpa->supp);
346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_deinit(wpa->auth_group);
347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(wpa->auth_eapol);
348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa->auth_eapol = NULL;
349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(wpa->supp_eapol);
350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa->supp_eapol = NULL;
351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint main(int argc, char *argv[])
355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa wpa;
357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (os_program_init())
359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&wpa, 0, sizeof(wpa));
362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(wpa.auth_addr, 0x12, ETH_ALEN);
363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(wpa.supp_addr, 0x32, ETH_ALEN);
364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(wpa.psk, 0x44, PMK_LEN);
365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_debug_level = 0;
367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_debug_show_keys = 1;
368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (eloop_init(&wpa)) {
370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (auth_init_group(&wpa) < 0)
375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (supp_init(&wpa) < 0)
378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (auth_init(&wpa) < 0)
381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "Starting eloop");
384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eloop_run();
385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "eloop done");
386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	deinit(&wpa);
388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	eloop_destroy();
390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_program_deinit();
392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
395