1 /*
2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
8  * Sun elects to license this software under the BSD license.
9  * See README for more details.
10  */
11 #ifndef __WPA_IMPL_H
12 #define	__WPA_IMPL_H
13 
14 #pragma ident	"%Z%%M%	%I%	%E% SMI"
15 
16 #include <net/wpa.h>
17 #include <libdladm.h>
18 
19 #ifdef	__cplusplus
20 extern "C" {
21 #endif
22 
23 #define	BIT(n)			(1 << (n))
24 
25 #define	WPA_CIPHER_NONE		BIT(0)
26 #define	WPA_CIPHER_WEP40	BIT(1)
27 #define	WPA_CIPHER_WEP104	BIT(2)
28 #define	WPA_CIPHER_TKIP		BIT(3)
29 #define	WPA_CIPHER_CCMP		BIT(4)
30 
31 #define	WPA_KEY_MGMT_IEEE8021X	BIT(0)
32 #define	WPA_KEY_MGMT_PSK	BIT(1)
33 #define	WPA_KEY_MGMT_NONE	BIT(2)
34 #define	WPA_KEY_MGMT_IEEE8021X_NO_WPA	BIT(3)
35 
36 #define	WPA_PROTO_WPA		BIT(0)
37 #define	WPA_PROTO_RSN		BIT(1)
38 
39 #pragma pack(1)
40 struct ieee802_1x_hdr {
41 	uint8_t		version;
42 	uint8_t		type;
43 	uint16_t	length;
44 	/* followed by length octets of data */
45 };
46 #pragma pack()
47 
48 #define	EAPOL_VERSION	2
49 
50 enum {	IEEE802_1X_TYPE_EAP_PACKET	= 0,
51 	IEEE802_1X_TYPE_EAPOL_START	= 1,
52 	IEEE802_1X_TYPE_EAPOL_LOGOFF	= 2,
53 	IEEE802_1X_TYPE_EAPOL_KEY	= 3,
54 	IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT	= 4
55 };
56 
57 enum {	EAPOL_KEY_TYPE_RC4 = 1,
58 	EAPOL_KEY_TYPE_RSN = 2,
59 	EAPOL_KEY_TYPE_WPA = 254
60 };
61 
62 #define	WPA_NONCE_LEN		32
63 #define	WPA_REPLAY_COUNTER_LEN	8
64 #define	MAX_PSK_LENGTH		64
65 #define	WPA_PMK_LEN		32
66 
67 #pragma pack(1)
68 struct wpa_eapol_key {
69 	uint8_t		type;
70 	uint16_t	key_info;
71 	uint16_t	key_length;
72 	uint8_t		replay_counter[WPA_REPLAY_COUNTER_LEN];
73 	uint8_t		key_nonce[WPA_NONCE_LEN];
74 	uint8_t		key_iv[16];
75 	uint8_t		key_rsc[8];
76 	uint8_t		key_id[8]; /* Reserved in IEEE 802.11i/RSN */
77 	uint8_t		key_mic[16];
78 	uint16_t	key_data_length;
79 	/* followed by key_data_length bytes of key_data */
80 };
81 #pragma pack()
82 
83 #define	WPA_KEY_INFO_TYPE_MASK		(BIT(0) | BIT(1) | BIT(2))
84 #define	WPA_KEY_INFO_TYPE_HMAC_MD5_RC4	BIT(0)
85 #define	WPA_KEY_INFO_TYPE_HMAC_SHA1_AES	BIT(1)
86 #define	WPA_KEY_INFO_KEY_TYPE		BIT(3) /* 1: Pairwise, 0: Group key */
87 /* bit4..5 is used in WPA, but is reserved in IEEE 802.11i/RSN */
88 #define	WPA_KEY_INFO_KEY_INDEX_MASK	(BIT(4) | BIT(5))
89 #define	WPA_KEY_INFO_KEY_INDEX_SHIFT	4
90 #define	WPA_KEY_INFO_INSTALL		BIT(6) /* pairwise */
91 #define	WPA_KEY_INFO_TXRX		BIT(6) /* group */
92 #define	WPA_KEY_INFO_ACK		BIT(7)
93 #define	WPA_KEY_INFO_MIC		BIT(8)
94 #define	WPA_KEY_INFO_SECURE		BIT(9)
95 #define	WPA_KEY_INFO_ERROR		BIT(10)
96 #define	WPA_KEY_INFO_REQUEST		BIT(11)
97 #define	WPA_KEY_INFO_ENCR_KEY_DATA	BIT(12) /* IEEE 802.11i/RSN only */
98 
99 #define	WPA_CAPABILITY_PREAUTH		BIT(0)
100 
101 #define	GENERIC_INFO_ELEM		0xdd
102 #define	RSN_INFO_ELEM			0x30
103 
104 #define	MAX_LOGBUF			4096
105 #define	MAX_SCANRESULTS			64
106 
107 enum {
108 	REASON_UNSPECIFIED			= 1,
109 	REASON_DEAUTH_LEAVING			= 3,
110 	REASON_INVALID_IE			= 13,
111 	REASON_MICHAEL_MIC_FAILURE		= 14,
112 	REASON_4WAY_HANDSHAKE_TIMEOUT		= 15,
113 	REASON_GROUP_KEY_UPDATE_TIMEOUT		= 16,
114 	REASON_IE_IN_4WAY_DIFFERS		= 17,
115 	REASON_GROUP_CIPHER_NOT_VALID		= 18,
116 	REASON_PAIRWISE_CIPHER_NOT_VALID	= 19,
117 	REASON_AKMP_NOT_VALID			= 20,
118 	REASON_UNSUPPORTED_RSN_IE_VERSION	= 21,
119 	REASON_INVALID_RSN_IE_CAPAB		= 22,
120 	REASON_IEEE_802_1X_AUTH_FAILED		= 23,
121 	REASON_CIPHER_SUITE_REJECTED		= 24
122 };
123 
124 /*
125  * wpa_supplicant
126  */
127 #define	PMKID_LEN 			16
128 #define	PMK_LEN				32
129 
130 #define	MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
131 #define	MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
132 
133 struct rsn_pmksa_cache {
134 	struct rsn_pmksa_cache	*next;
135 	uint8_t			pmkid[PMKID_LEN];
136 	uint8_t			pmk[PMK_LEN];
137 	time_t			expiration;
138 	int			akmp; /* WPA_KEY_MGMT_* */
139 	uint8_t			aa[IEEE80211_ADDR_LEN];
140 };
141 
142 struct rsn_pmksa_candidate {
143 	struct rsn_pmksa_candidate *next;
144 	uint8_t			bssid[IEEE80211_ADDR_LEN];
145 };
146 
147 
148 #pragma pack(1)
149 struct wpa_ptk {
150 	uint8_t mic_key[16]; /* EAPOL-Key MIC Key (MK) */
151 	uint8_t encr_key[16]; /* EAPOL-Key Encryption Key (EK) */
152 	uint8_t tk1[16]; /* Temporal Key 1 (TK1) */
153 	union {
154 		uint8_t tk2[16]; /* Temporal Key 2 (TK2) */
155 		struct {
156 			uint8_t tx_mic_key[8];
157 			uint8_t rx_mic_key[8];
158 		} auth;
159 	} u;
160 };
161 #pragma pack()
162 
163 
164 struct wpa_supplicant {
165 	struct l2_packet_data	*l2;
166 	unsigned char		own_addr[IEEE80211_ADDR_LEN];
167 
168 	datalink_id_t		linkid;
169 	char			kname[WPA_STRSIZE];
170 
171 	uint8_t			pmk[PMK_LEN];
172 
173 	uint8_t			snonce[WPA_NONCE_LEN];
174 	uint8_t			anonce[WPA_NONCE_LEN];
175 	/* ANonce from the last 1/4 msg */
176 
177 	struct wpa_ptk		ptk, tptk;
178 	int			ptk_set, tptk_set;
179 	int			renew_snonce;
180 
181 	struct wpa_config	*conf;
182 
183 	uint8_t			request_counter[WPA_REPLAY_COUNTER_LEN];
184 	uint8_t			rx_replay_counter[WPA_REPLAY_COUNTER_LEN];
185 	int			rx_replay_counter_set;
186 
187 	uint8_t			bssid[IEEE80211_ADDR_LEN];
188 	int			reassociate; /* reassociation requested */
189 
190 	uint8_t			*ap_wpa_ie;
191 	size_t			ap_wpa_ie_len;
192 
193 	/*
194 	 * Selected configuration
195 	 * based on Beacon/ProbeResp WPA IE
196 	 */
197 	int			proto;
198 	int 			pairwise_cipher;
199 	int 			group_cipher;
200 	int			key_mgmt;
201 
202 	struct wpa_driver_ops	*driver;
203 
204 	enum {
205 		WPA_DISCONNECTED,
206 		WPA_SCANNING,
207 		WPA_ASSOCIATING,
208 		WPA_ASSOCIATED,
209 		WPA_4WAY_HANDSHAKE,
210 		WPA_GROUP_HANDSHAKE,
211 		WPA_COMPLETED
212 	} wpa_state;
213 
214 	struct rsn_pmksa_cache	*pmksa; /* PMKSA cache */
215 	int	pmksa_count; /* number of entries in PMKSA cache */
216 	struct rsn_pmksa_cache	*cur_pmksa; /* current PMKSA entry */
217 	struct rsn_pmksa_candidate	*pmksa_candidates;
218 
219 	/*
220 	 * number of EAPOL packets received after the
221 	 * previous association event
222 	 */
223 	int			eapol_received;
224 };
225 
226 struct wpa_ie_data {
227 	int	proto;
228 	int	pairwise_cipher;
229 	int	group_cipher;
230 	int	key_mgmt;
231 	int	capabilities;
232 };
233 
234 /* WPA configuration */
235 struct wpa_ssid {
236 	uint8_t	*ssid;
237 	size_t	ssid_len;
238 
239 	uint8_t	bssid[IEEE80211_ADDR_LEN];
240 	int	bssid_set;
241 
242 	uint8_t	psk[PMK_LEN];
243 	int	psk_set;
244 	char	*passphrase;
245 
246 	/* Bitfields of allowed Pairwise/Group Ciphers, WPA_CIPHER_* */
247 	int	pairwise_cipher;
248 	int	group_cipher;
249 
250 	int	key_mgmt;
251 	int	proto; /* Bitfield of allowed protocols (WPA_PROTO_*) */
252 };
253 
254 struct wpa_config {
255 	struct wpa_ssid *ssid; /* global network list */
256 	int eapol_version;
257 	/* int ap_scan; */
258 };
259 
260 struct wpa_config *wpa_config_read(void *);
261 void wpa_config_free(struct wpa_config *);
262 
263 /*
264  * Debugging function - conditional printf and hex dump.
265  * Driver wrappers can use these for debugging purposes.
266  */
267 enum { MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR };
268 
269 void wpa_printf(int, char *, ...);
270 void wpa_hexdump(int, const char *, const uint8_t *, size_t);
271 
272 void wpa_event_handler(void *, wpa_event_type);
273 void wpa_supplicant_rx_eapol(void *, unsigned char *, unsigned char *, size_t);
274 
275 void wpa_supplicant_scan(void *, void *);
276 void wpa_supplicant_req_scan(struct wpa_supplicant *, int, int);
277 
278 void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *, int, int);
279 void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *);
280 void wpa_supplicant_disassociate(struct wpa_supplicant *, int);
281 
282 void pmksa_cache_free(struct wpa_supplicant *);
283 void pmksa_candidate_free(struct wpa_supplicant *);
284 struct rsn_pmksa_cache *pmksa_cache_get(struct wpa_supplicant *,
285     uint8_t *, uint8_t *);
286 
287 int wpa_parse_wpa_ie(struct wpa_supplicant *, uint8_t *,
288 	size_t, struct wpa_ie_data *);
289 int wpa_gen_wpa_ie(struct wpa_supplicant *, uint8_t *);
290 
291 #ifdef __cplusplus
292 }
293 #endif
294 
295 #endif /* __WPA_IMPL_H */
296