eap_i.h revision 281806
1189251Ssam/*
2189251Ssam * EAP peer state machines internal structures (RFC 4137)
3281806Srpaulo * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
4189251Ssam *
5252726Srpaulo * This software may be distributed under the terms of the BSD license.
6252726Srpaulo * See README for more details.
7189251Ssam */
8189251Ssam
9189251Ssam#ifndef EAP_I_H
10189251Ssam#define EAP_I_H
11189251Ssam
12189251Ssam#include "wpabuf.h"
13281806Srpaulo#include "utils/list.h"
14189251Ssam#include "eap_peer/eap.h"
15189251Ssam#include "eap_common/eap_common.h"
16189251Ssam
17189251Ssam/* RFC 4137 - EAP Peer state machine */
18189251Ssam
19189251Ssamtypedef enum {
20189251Ssam	DECISION_FAIL, DECISION_COND_SUCC, DECISION_UNCOND_SUCC
21189251Ssam} EapDecision;
22189251Ssam
23189251Ssamtypedef enum {
24189251Ssam	METHOD_NONE, METHOD_INIT, METHOD_CONT, METHOD_MAY_CONT, METHOD_DONE
25189251Ssam} EapMethodState;
26189251Ssam
27189251Ssam/**
28189251Ssam * struct eap_method_ret - EAP return values from struct eap_method::process()
29189251Ssam *
30189251Ssam * These structure contains OUT variables for the interface between peer state
31189251Ssam * machine and methods (RFC 4137, Sect. 4.2). eapRespData will be returned as
32189251Ssam * the return value of struct eap_method::process() so it is not included in
33189251Ssam * this structure.
34189251Ssam */
35189251Ssamstruct eap_method_ret {
36189251Ssam	/**
37189251Ssam	 * ignore - Whether method decided to drop the current packed (OUT)
38189251Ssam	 */
39189251Ssam	Boolean ignore;
40189251Ssam
41189251Ssam	/**
42189251Ssam	 * methodState - Method-specific state (IN/OUT)
43189251Ssam	 */
44189251Ssam	EapMethodState methodState;
45189251Ssam
46189251Ssam	/**
47189251Ssam	 * decision - Authentication decision (OUT)
48189251Ssam	 */
49189251Ssam	EapDecision decision;
50189251Ssam
51189251Ssam	/**
52189251Ssam	 * allowNotifications - Whether method allows notifications (OUT)
53189251Ssam	 */
54189251Ssam	Boolean allowNotifications;
55189251Ssam};
56189251Ssam
57189251Ssam
58189251Ssam/**
59189251Ssam * struct eap_method - EAP method interface
60189251Ssam * This structure defines the EAP method interface. Each method will need to
61189251Ssam * register its own EAP type, EAP name, and set of function pointers for method
62189251Ssam * specific operations. This interface is based on section 4.4 of RFC 4137.
63189251Ssam */
64189251Ssamstruct eap_method {
65189251Ssam	/**
66189251Ssam	 * vendor - EAP Vendor-ID (EAP_VENDOR_*) (0 = IETF)
67189251Ssam	 */
68189251Ssam	int vendor;
69189251Ssam
70189251Ssam	/**
71189251Ssam	 * method - EAP type number (EAP_TYPE_*)
72189251Ssam	 */
73189251Ssam	EapType method;
74189251Ssam
75189251Ssam	/**
76189251Ssam	 * name - Name of the method (e.g., "TLS")
77189251Ssam	 */
78189251Ssam	const char *name;
79189251Ssam
80189251Ssam	/**
81189251Ssam	 * init - Initialize an EAP method
82189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
83189251Ssam	 * Returns: Pointer to allocated private data, or %NULL on failure
84189251Ssam	 *
85189251Ssam	 * This function is used to initialize the EAP method explicitly
86189251Ssam	 * instead of using METHOD_INIT state as specific in RFC 4137. The
87189251Ssam	 * method is expected to initialize it method-specific state and return
88189251Ssam	 * a pointer that will be used as the priv argument to other calls.
89189251Ssam	 */
90189251Ssam	void * (*init)(struct eap_sm *sm);
91189251Ssam
92189251Ssam	/**
93189251Ssam	 * deinit - Deinitialize an EAP method
94189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
95189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
96189251Ssam	 *
97189251Ssam	 * Deinitialize the EAP method and free any allocated private data.
98189251Ssam	 */
99189251Ssam	void (*deinit)(struct eap_sm *sm, void *priv);
100189251Ssam
101189251Ssam	/**
102189251Ssam	 * process - Process an EAP request
103189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
104189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
105189251Ssam	 * @ret: Return values from EAP request validation and processing
106189251Ssam	 * @reqData: EAP request to be processed (eapReqData)
107189251Ssam	 * Returns: Pointer to allocated EAP response packet (eapRespData)
108189251Ssam	 *
109189251Ssam	 * This function is a combination of m.check(), m.process(), and
110189251Ssam	 * m.buildResp() procedures defined in section 4.4 of RFC 4137 In other
111189251Ssam	 * words, this function validates the incoming request, processes it,
112189251Ssam	 * and build a response packet. m.check() and m.process() return values
113189251Ssam	 * are returned through struct eap_method_ret *ret variable. Caller is
114189251Ssam	 * responsible for freeing the returned EAP response packet.
115189251Ssam	 */
116189251Ssam	struct wpabuf * (*process)(struct eap_sm *sm, void *priv,
117189251Ssam				   struct eap_method_ret *ret,
118189251Ssam				   const struct wpabuf *reqData);
119189251Ssam
120189251Ssam	/**
121189251Ssam	 * isKeyAvailable - Find out whether EAP method has keying material
122189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
123189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
124189251Ssam	 * Returns: %TRUE if key material (eapKeyData) is available
125189251Ssam	 */
126189251Ssam	Boolean (*isKeyAvailable)(struct eap_sm *sm, void *priv);
127189251Ssam
128189251Ssam	/**
129189251Ssam	 * getKey - Get EAP method specific keying material (eapKeyData)
130189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
131189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
132189251Ssam	 * @len: Pointer to variable to store key length (eapKeyDataLen)
133189251Ssam	 * Returns: Keying material (eapKeyData) or %NULL if not available
134189251Ssam	 *
135189251Ssam	 * This function can be used to get the keying material from the EAP
136189251Ssam	 * method. The key may already be stored in the method-specific private
137189251Ssam	 * data or this function may derive the key.
138189251Ssam	 */
139189251Ssam	u8 * (*getKey)(struct eap_sm *sm, void *priv, size_t *len);
140189251Ssam
141189251Ssam	/**
142189251Ssam	 * get_status - Get EAP method status
143189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
144189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
145189251Ssam	 * @buf: Buffer for status information
146189251Ssam	 * @buflen: Maximum buffer length
147189251Ssam	 * @verbose: Whether to include verbose status information
148189251Ssam	 * Returns: Number of bytes written to buf
149189251Ssam	 *
150189251Ssam	 * Query EAP method for status information. This function fills in a
151189251Ssam	 * text area with current status information from the EAP method. If
152189251Ssam	 * the buffer (buf) is not large enough, status information will be
153189251Ssam	 * truncated to fit the buffer.
154189251Ssam	 */
155189251Ssam	int (*get_status)(struct eap_sm *sm, void *priv, char *buf,
156189251Ssam			  size_t buflen, int verbose);
157189251Ssam
158189251Ssam	/**
159189251Ssam	 * has_reauth_data - Whether method is ready for fast reauthentication
160189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
161189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
162189251Ssam	 * Returns: %TRUE or %FALSE based on whether fast reauthentication is
163189251Ssam	 * possible
164189251Ssam	 *
165189251Ssam	 * This function is an optional handler that only EAP methods
166189251Ssam	 * supporting fast re-authentication need to implement.
167189251Ssam	 */
168189251Ssam	Boolean (*has_reauth_data)(struct eap_sm *sm, void *priv);
169189251Ssam
170189251Ssam	/**
171189251Ssam	 * deinit_for_reauth - Release data that is not needed for fast re-auth
172189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
173189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
174189251Ssam	 *
175189251Ssam	 * This function is an optional handler that only EAP methods
176189251Ssam	 * supporting fast re-authentication need to implement. This is called
177189251Ssam	 * when authentication has been completed and EAP state machine is
178189251Ssam	 * requesting that enough state information is maintained for fast
179189251Ssam	 * re-authentication
180189251Ssam	 */
181189251Ssam	void (*deinit_for_reauth)(struct eap_sm *sm, void *priv);
182189251Ssam
183189251Ssam	/**
184189251Ssam	 * init_for_reauth - Prepare for start of fast re-authentication
185189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
186189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
187189251Ssam	 *
188189251Ssam	 * This function is an optional handler that only EAP methods
189189251Ssam	 * supporting fast re-authentication need to implement. This is called
190189251Ssam	 * when EAP authentication is started and EAP state machine is
191189251Ssam	 * requesting fast re-authentication to be used.
192189251Ssam	 */
193189251Ssam	void * (*init_for_reauth)(struct eap_sm *sm, void *priv);
194189251Ssam
195189251Ssam	/**
196189251Ssam	 * get_identity - Get method specific identity for re-authentication
197189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
198189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
199189251Ssam	 * @len: Length of the returned identity
200189251Ssam	 * Returns: Pointer to the method specific identity or %NULL if default
201189251Ssam	 * identity is to be used
202189251Ssam	 *
203189251Ssam	 * This function is an optional handler that only EAP methods
204189251Ssam	 * that use method specific identity need to implement.
205189251Ssam	 */
206189251Ssam	const u8 * (*get_identity)(struct eap_sm *sm, void *priv, size_t *len);
207189251Ssam
208189251Ssam	/**
209189251Ssam	 * free - Free EAP method data
210189251Ssam	 * @method: Pointer to the method data registered with
211189251Ssam	 * eap_peer_method_register().
212189251Ssam	 *
213189251Ssam	 * This function will be called when the EAP method is being
214189251Ssam	 * unregistered. If the EAP method allocated resources during
215189251Ssam	 * registration (e.g., allocated struct eap_method), they should be
216189251Ssam	 * freed in this function. No other method functions will be called
217189251Ssam	 * after this call. If this function is not defined (i.e., function
218189251Ssam	 * pointer is %NULL), a default handler is used to release the method
219189251Ssam	 * data with free(method). This is suitable for most cases.
220189251Ssam	 */
221189251Ssam	void (*free)(struct eap_method *method);
222189251Ssam
223189251Ssam#define EAP_PEER_METHOD_INTERFACE_VERSION 1
224189251Ssam	/**
225189251Ssam	 * version - Version of the EAP peer method interface
226189251Ssam	 *
227189251Ssam	 * The EAP peer method implementation should set this variable to
228189251Ssam	 * EAP_PEER_METHOD_INTERFACE_VERSION. This is used to verify that the
229189251Ssam	 * EAP method is using supported API version when using dynamically
230189251Ssam	 * loadable EAP methods.
231189251Ssam	 */
232189251Ssam	int version;
233189251Ssam
234189251Ssam	/**
235189251Ssam	 * next - Pointer to the next EAP method
236189251Ssam	 *
237189251Ssam	 * This variable is used internally in the EAP method registration code
238189251Ssam	 * to create a linked list of registered EAP methods.
239189251Ssam	 */
240189251Ssam	struct eap_method *next;
241189251Ssam
242189251Ssam#ifdef CONFIG_DYNAMIC_EAP_METHODS
243189251Ssam	/**
244189251Ssam	 * dl_handle - Handle for the dynamic library
245189251Ssam	 *
246189251Ssam	 * This variable is used internally in the EAP method registration code
247189251Ssam	 * to store a handle for the dynamic library. If the method is linked
248189251Ssam	 * in statically, this is %NULL.
249189251Ssam	 */
250189251Ssam	void *dl_handle;
251189251Ssam#endif /* CONFIG_DYNAMIC_EAP_METHODS */
252189251Ssam
253189251Ssam	/**
254189251Ssam	 * get_emsk - Get EAP method specific keying extended material (EMSK)
255189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
256189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
257189251Ssam	 * @len: Pointer to a variable to store EMSK length
258189251Ssam	 * Returns: EMSK or %NULL if not available
259189251Ssam	 *
260189251Ssam	 * This function can be used to get the extended keying material from
261189251Ssam	 * the EAP method. The key may already be stored in the method-specific
262189251Ssam	 * private data or this function may derive the key.
263189251Ssam	 */
264189251Ssam	u8 * (*get_emsk)(struct eap_sm *sm, void *priv, size_t *len);
265281806Srpaulo
266281806Srpaulo	/**
267281806Srpaulo	 * getSessionId - Get EAP method specific Session-Id
268281806Srpaulo	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
269281806Srpaulo	 * @priv: Pointer to private EAP method data from eap_method::init()
270281806Srpaulo	 * @len: Pointer to a variable to store Session-Id length
271281806Srpaulo	 * Returns: Session-Id or %NULL if not available
272281806Srpaulo	 *
273281806Srpaulo	 * This function can be used to get the Session-Id from the EAP method.
274281806Srpaulo	 * The Session-Id may already be stored in the method-specific private
275281806Srpaulo	 * data or this function may derive the Session-Id.
276281806Srpaulo	 */
277281806Srpaulo	u8 * (*getSessionId)(struct eap_sm *sm, void *priv, size_t *len);
278189251Ssam};
279189251Ssam
280189251Ssam
281281806Srpaulostruct eap_erp_key {
282281806Srpaulo	struct dl_list list;
283281806Srpaulo	size_t rRK_len;
284281806Srpaulo	size_t rIK_len;
285281806Srpaulo	u8 rRK[ERP_MAX_KEY_LEN];
286281806Srpaulo	u8 rIK[ERP_MAX_KEY_LEN];
287281806Srpaulo	u32 next_seq;
288281806Srpaulo	char keyname_nai[];
289281806Srpaulo};
290281806Srpaulo
291189251Ssam/**
292189251Ssam * struct eap_sm - EAP state machine data
293189251Ssam */
294189251Ssamstruct eap_sm {
295189251Ssam	enum {
296189251Ssam		EAP_INITIALIZE, EAP_DISABLED, EAP_IDLE, EAP_RECEIVED,
297189251Ssam		EAP_GET_METHOD, EAP_METHOD, EAP_SEND_RESPONSE, EAP_DISCARD,
298189251Ssam		EAP_IDENTITY, EAP_NOTIFICATION, EAP_RETRANSMIT, EAP_SUCCESS,
299189251Ssam		EAP_FAILURE
300189251Ssam	} EAP_state;
301189251Ssam	/* Long-term local variables */
302189251Ssam	EapType selectedMethod;
303189251Ssam	EapMethodState methodState;
304189251Ssam	int lastId;
305189251Ssam	struct wpabuf *lastRespData;
306189251Ssam	EapDecision decision;
307189251Ssam	/* Short-term local variables */
308189251Ssam	Boolean rxReq;
309189251Ssam	Boolean rxSuccess;
310189251Ssam	Boolean rxFailure;
311189251Ssam	int reqId;
312189251Ssam	EapType reqMethod;
313189251Ssam	int reqVendor;
314189251Ssam	u32 reqVendorMethod;
315189251Ssam	Boolean ignore;
316189251Ssam	/* Constants */
317189251Ssam	int ClientTimeout;
318189251Ssam
319189251Ssam	/* Miscellaneous variables */
320189251Ssam	Boolean allowNotifications; /* peer state machine <-> methods */
321189251Ssam	struct wpabuf *eapRespData; /* peer to lower layer */
322189251Ssam	Boolean eapKeyAvailable; /* peer to lower layer */
323189251Ssam	u8 *eapKeyData; /* peer to lower layer */
324189251Ssam	size_t eapKeyDataLen; /* peer to lower layer */
325281806Srpaulo	u8 *eapSessionId; /* peer to lower layer */
326281806Srpaulo	size_t eapSessionIdLen; /* peer to lower layer */
327189251Ssam	const struct eap_method *m; /* selected EAP method */
328189251Ssam	/* not defined in RFC 4137 */
329189251Ssam	Boolean changed;
330189251Ssam	void *eapol_ctx;
331189251Ssam	struct eapol_callbacks *eapol_cb;
332189251Ssam	void *eap_method_priv;
333189251Ssam	int init_phase2;
334189251Ssam	int fast_reauth;
335281806Srpaulo	Boolean reauthInit; /* send EAP-Identity/Re-auth */
336281806Srpaulo	u32 erp_seq;
337189251Ssam
338189251Ssam	Boolean rxResp /* LEAP only */;
339189251Ssam	Boolean leap_done;
340189251Ssam	Boolean peap_done;
341189251Ssam	u8 req_md5[16]; /* MD5() of the current EAP packet */
342189251Ssam	u8 last_md5[16]; /* MD5() of the previously received EAP packet; used
343189251Ssam			  * in duplicate request detection. */
344189251Ssam
345189251Ssam	void *msg_ctx;
346189251Ssam	void *scard_ctx;
347189251Ssam	void *ssl_ctx;
348252726Srpaulo	void *ssl_ctx2;
349189251Ssam
350189251Ssam	unsigned int workaround;
351189251Ssam
352189251Ssam	/* Optional challenges generated in Phase 1 (EAP-FAST) */
353189251Ssam	u8 *peer_challenge, *auth_challenge;
354189251Ssam
355189251Ssam	int num_rounds;
356189251Ssam	int force_disabled;
357189251Ssam
358189251Ssam	struct wps_context *wps;
359189251Ssam
360189251Ssam	int prev_failure;
361281806Srpaulo	struct eap_peer_config *last_config;
362252726Srpaulo
363252726Srpaulo	struct ext_password_data *ext_pw;
364252726Srpaulo	struct wpabuf *ext_pw_buf;
365281806Srpaulo
366281806Srpaulo	int external_sim;
367281806Srpaulo
368281806Srpaulo	unsigned int expected_failure:1;
369281806Srpaulo
370281806Srpaulo	struct dl_list erp_keys; /* struct eap_erp_key */
371189251Ssam};
372189251Ssam
373189251Ssamconst u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len);
374189251Ssamconst u8 * eap_get_config_password(struct eap_sm *sm, size_t *len);
375189251Ssamconst u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash);
376189251Ssamconst u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len);
377189251Ssamconst u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len);
378189251Ssamvoid eap_clear_config_otp(struct eap_sm *sm);
379189251Ssamconst char * eap_get_config_phase1(struct eap_sm *sm);
380189251Ssamconst char * eap_get_config_phase2(struct eap_sm *sm);
381252726Srpauloint eap_get_config_fragment_size(struct eap_sm *sm);
382189251Ssamstruct eap_peer_config * eap_get_config(struct eap_sm *sm);
383189251Ssamvoid eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob);
384189251Ssamconst struct wpa_config_blob *
385189251Ssameap_get_config_blob(struct eap_sm *sm, const char *name);
386189251Ssamvoid eap_notify_pending(struct eap_sm *sm);
387189251Ssamint eap_allowed_method(struct eap_sm *sm, int vendor, u32 method);
388189251Ssam
389189251Ssam#endif /* EAP_I_H */
390