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
17346981Scy#define NO_EAP_METHOD_ERROR (-1)
18346981Scy
19189251Ssam/* RFC 4137 - EAP Peer state machine */
20189251Ssam
21189251Ssamtypedef enum {
22189251Ssam	DECISION_FAIL, DECISION_COND_SUCC, DECISION_UNCOND_SUCC
23189251Ssam} EapDecision;
24189251Ssam
25189251Ssamtypedef enum {
26189251Ssam	METHOD_NONE, METHOD_INIT, METHOD_CONT, METHOD_MAY_CONT, METHOD_DONE
27189251Ssam} EapMethodState;
28189251Ssam
29189251Ssam/**
30189251Ssam * struct eap_method_ret - EAP return values from struct eap_method::process()
31189251Ssam *
32189251Ssam * These structure contains OUT variables for the interface between peer state
33189251Ssam * machine and methods (RFC 4137, Sect. 4.2). eapRespData will be returned as
34189251Ssam * the return value of struct eap_method::process() so it is not included in
35189251Ssam * this structure.
36189251Ssam */
37189251Ssamstruct eap_method_ret {
38189251Ssam	/**
39189251Ssam	 * ignore - Whether method decided to drop the current packed (OUT)
40189251Ssam	 */
41189251Ssam	Boolean ignore;
42189251Ssam
43189251Ssam	/**
44189251Ssam	 * methodState - Method-specific state (IN/OUT)
45189251Ssam	 */
46189251Ssam	EapMethodState methodState;
47189251Ssam
48189251Ssam	/**
49189251Ssam	 * decision - Authentication decision (OUT)
50189251Ssam	 */
51189251Ssam	EapDecision decision;
52189251Ssam
53189251Ssam	/**
54189251Ssam	 * allowNotifications - Whether method allows notifications (OUT)
55189251Ssam	 */
56189251Ssam	Boolean allowNotifications;
57189251Ssam};
58189251Ssam
59189251Ssam
60189251Ssam/**
61189251Ssam * struct eap_method - EAP method interface
62189251Ssam * This structure defines the EAP method interface. Each method will need to
63189251Ssam * register its own EAP type, EAP name, and set of function pointers for method
64189251Ssam * specific operations. This interface is based on section 4.4 of RFC 4137.
65189251Ssam */
66189251Ssamstruct eap_method {
67189251Ssam	/**
68189251Ssam	 * vendor - EAP Vendor-ID (EAP_VENDOR_*) (0 = IETF)
69189251Ssam	 */
70189251Ssam	int vendor;
71189251Ssam
72189251Ssam	/**
73189251Ssam	 * method - EAP type number (EAP_TYPE_*)
74189251Ssam	 */
75189251Ssam	EapType method;
76189251Ssam
77189251Ssam	/**
78189251Ssam	 * name - Name of the method (e.g., "TLS")
79189251Ssam	 */
80189251Ssam	const char *name;
81189251Ssam
82189251Ssam	/**
83189251Ssam	 * init - Initialize an EAP method
84189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
85189251Ssam	 * Returns: Pointer to allocated private data, or %NULL on failure
86189251Ssam	 *
87189251Ssam	 * This function is used to initialize the EAP method explicitly
88189251Ssam	 * instead of using METHOD_INIT state as specific in RFC 4137. The
89189251Ssam	 * method is expected to initialize it method-specific state and return
90189251Ssam	 * a pointer that will be used as the priv argument to other calls.
91189251Ssam	 */
92189251Ssam	void * (*init)(struct eap_sm *sm);
93189251Ssam
94189251Ssam	/**
95189251Ssam	 * deinit - Deinitialize an EAP method
96189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
97189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
98189251Ssam	 *
99189251Ssam	 * Deinitialize the EAP method and free any allocated private data.
100189251Ssam	 */
101189251Ssam	void (*deinit)(struct eap_sm *sm, void *priv);
102189251Ssam
103189251Ssam	/**
104189251Ssam	 * process - Process an EAP request
105189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
106189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
107189251Ssam	 * @ret: Return values from EAP request validation and processing
108189251Ssam	 * @reqData: EAP request to be processed (eapReqData)
109189251Ssam	 * Returns: Pointer to allocated EAP response packet (eapRespData)
110189251Ssam	 *
111189251Ssam	 * This function is a combination of m.check(), m.process(), and
112189251Ssam	 * m.buildResp() procedures defined in section 4.4 of RFC 4137 In other
113189251Ssam	 * words, this function validates the incoming request, processes it,
114189251Ssam	 * and build a response packet. m.check() and m.process() return values
115189251Ssam	 * are returned through struct eap_method_ret *ret variable. Caller is
116189251Ssam	 * responsible for freeing the returned EAP response packet.
117189251Ssam	 */
118189251Ssam	struct wpabuf * (*process)(struct eap_sm *sm, void *priv,
119189251Ssam				   struct eap_method_ret *ret,
120189251Ssam				   const struct wpabuf *reqData);
121189251Ssam
122189251Ssam	/**
123189251Ssam	 * isKeyAvailable - Find out whether EAP method has keying material
124189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
125189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
126189251Ssam	 * Returns: %TRUE if key material (eapKeyData) is available
127189251Ssam	 */
128189251Ssam	Boolean (*isKeyAvailable)(struct eap_sm *sm, void *priv);
129189251Ssam
130189251Ssam	/**
131189251Ssam	 * getKey - Get EAP method specific keying material (eapKeyData)
132189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
133189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
134189251Ssam	 * @len: Pointer to variable to store key length (eapKeyDataLen)
135189251Ssam	 * Returns: Keying material (eapKeyData) or %NULL if not available
136189251Ssam	 *
137189251Ssam	 * This function can be used to get the keying material from the EAP
138189251Ssam	 * method. The key may already be stored in the method-specific private
139189251Ssam	 * data or this function may derive the key.
140189251Ssam	 */
141189251Ssam	u8 * (*getKey)(struct eap_sm *sm, void *priv, size_t *len);
142189251Ssam
143189251Ssam	/**
144189251Ssam	 * get_status - Get EAP method status
145189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
146189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
147189251Ssam	 * @buf: Buffer for status information
148189251Ssam	 * @buflen: Maximum buffer length
149189251Ssam	 * @verbose: Whether to include verbose status information
150189251Ssam	 * Returns: Number of bytes written to buf
151189251Ssam	 *
152189251Ssam	 * Query EAP method for status information. This function fills in a
153189251Ssam	 * text area with current status information from the EAP method. If
154189251Ssam	 * the buffer (buf) is not large enough, status information will be
155189251Ssam	 * truncated to fit the buffer.
156189251Ssam	 */
157189251Ssam	int (*get_status)(struct eap_sm *sm, void *priv, char *buf,
158189251Ssam			  size_t buflen, int verbose);
159189251Ssam
160189251Ssam	/**
161189251Ssam	 * has_reauth_data - Whether method is ready for fast reauthentication
162189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
163189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
164189251Ssam	 * Returns: %TRUE or %FALSE based on whether fast reauthentication is
165189251Ssam	 * possible
166189251Ssam	 *
167189251Ssam	 * This function is an optional handler that only EAP methods
168189251Ssam	 * supporting fast re-authentication need to implement.
169189251Ssam	 */
170189251Ssam	Boolean (*has_reauth_data)(struct eap_sm *sm, void *priv);
171189251Ssam
172189251Ssam	/**
173189251Ssam	 * deinit_for_reauth - Release data that is not needed for fast re-auth
174189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
175189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
176189251Ssam	 *
177189251Ssam	 * This function is an optional handler that only EAP methods
178189251Ssam	 * supporting fast re-authentication need to implement. This is called
179189251Ssam	 * when authentication has been completed and EAP state machine is
180189251Ssam	 * requesting that enough state information is maintained for fast
181189251Ssam	 * re-authentication
182189251Ssam	 */
183189251Ssam	void (*deinit_for_reauth)(struct eap_sm *sm, void *priv);
184189251Ssam
185189251Ssam	/**
186189251Ssam	 * init_for_reauth - Prepare for start of fast re-authentication
187189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
188189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
189189251Ssam	 *
190189251Ssam	 * This function is an optional handler that only EAP methods
191189251Ssam	 * supporting fast re-authentication need to implement. This is called
192189251Ssam	 * when EAP authentication is started and EAP state machine is
193189251Ssam	 * requesting fast re-authentication to be used.
194189251Ssam	 */
195189251Ssam	void * (*init_for_reauth)(struct eap_sm *sm, void *priv);
196189251Ssam
197189251Ssam	/**
198189251Ssam	 * get_identity - Get method specific identity for re-authentication
199189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
200189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
201189251Ssam	 * @len: Length of the returned identity
202189251Ssam	 * Returns: Pointer to the method specific identity or %NULL if default
203189251Ssam	 * identity is to be used
204189251Ssam	 *
205189251Ssam	 * This function is an optional handler that only EAP methods
206189251Ssam	 * that use method specific identity need to implement.
207189251Ssam	 */
208189251Ssam	const u8 * (*get_identity)(struct eap_sm *sm, void *priv, size_t *len);
209189251Ssam
210189251Ssam	/**
211346981Scy	 * get_error_code - Get the latest EAP method error code
212346981Scy	 * @priv: Pointer to private EAP method data from eap_method::init()
213346981Scy	 * Returns: An int for the EAP method specific error code if exists or
214346981Scy	 * NO_EAP_METHOD_ERROR otherwise.
215346981Scy	 *
216346981Scy	 * This method is an optional handler that only EAP methods that need to
217346981Scy	 * report their error code need to implement.
218346981Scy	 */
219346981Scy	int (*get_error_code)(void *priv);
220346981Scy
221346981Scy	/**
222189251Ssam	 * free - Free EAP method data
223189251Ssam	 * @method: Pointer to the method data registered with
224189251Ssam	 * eap_peer_method_register().
225189251Ssam	 *
226189251Ssam	 * This function will be called when the EAP method is being
227189251Ssam	 * unregistered. If the EAP method allocated resources during
228189251Ssam	 * registration (e.g., allocated struct eap_method), they should be
229189251Ssam	 * freed in this function. No other method functions will be called
230189251Ssam	 * after this call. If this function is not defined (i.e., function
231189251Ssam	 * pointer is %NULL), a default handler is used to release the method
232189251Ssam	 * data with free(method). This is suitable for most cases.
233189251Ssam	 */
234189251Ssam	void (*free)(struct eap_method *method);
235189251Ssam
236189251Ssam#define EAP_PEER_METHOD_INTERFACE_VERSION 1
237189251Ssam	/**
238189251Ssam	 * version - Version of the EAP peer method interface
239189251Ssam	 *
240189251Ssam	 * The EAP peer method implementation should set this variable to
241189251Ssam	 * EAP_PEER_METHOD_INTERFACE_VERSION. This is used to verify that the
242189251Ssam	 * EAP method is using supported API version when using dynamically
243189251Ssam	 * loadable EAP methods.
244189251Ssam	 */
245189251Ssam	int version;
246189251Ssam
247189251Ssam	/**
248189251Ssam	 * next - Pointer to the next EAP method
249189251Ssam	 *
250189251Ssam	 * This variable is used internally in the EAP method registration code
251189251Ssam	 * to create a linked list of registered EAP methods.
252189251Ssam	 */
253189251Ssam	struct eap_method *next;
254189251Ssam
255189251Ssam#ifdef CONFIG_DYNAMIC_EAP_METHODS
256189251Ssam	/**
257189251Ssam	 * dl_handle - Handle for the dynamic library
258189251Ssam	 *
259189251Ssam	 * This variable is used internally in the EAP method registration code
260189251Ssam	 * to store a handle for the dynamic library. If the method is linked
261189251Ssam	 * in statically, this is %NULL.
262189251Ssam	 */
263189251Ssam	void *dl_handle;
264189251Ssam#endif /* CONFIG_DYNAMIC_EAP_METHODS */
265189251Ssam
266189251Ssam	/**
267189251Ssam	 * get_emsk - Get EAP method specific keying extended material (EMSK)
268189251Ssam	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
269189251Ssam	 * @priv: Pointer to private EAP method data from eap_method::init()
270189251Ssam	 * @len: Pointer to a variable to store EMSK length
271189251Ssam	 * Returns: EMSK or %NULL if not available
272189251Ssam	 *
273189251Ssam	 * This function can be used to get the extended keying material from
274189251Ssam	 * the EAP method. The key may already be stored in the method-specific
275189251Ssam	 * private data or this function may derive the key.
276189251Ssam	 */
277189251Ssam	u8 * (*get_emsk)(struct eap_sm *sm, void *priv, size_t *len);
278281806Srpaulo
279281806Srpaulo	/**
280281806Srpaulo	 * getSessionId - Get EAP method specific Session-Id
281281806Srpaulo	 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
282281806Srpaulo	 * @priv: Pointer to private EAP method data from eap_method::init()
283281806Srpaulo	 * @len: Pointer to a variable to store Session-Id length
284281806Srpaulo	 * Returns: Session-Id or %NULL if not available
285281806Srpaulo	 *
286281806Srpaulo	 * This function can be used to get the Session-Id from the EAP method.
287281806Srpaulo	 * The Session-Id may already be stored in the method-specific private
288281806Srpaulo	 * data or this function may derive the Session-Id.
289281806Srpaulo	 */
290281806Srpaulo	u8 * (*getSessionId)(struct eap_sm *sm, void *priv, size_t *len);
291189251Ssam};
292189251Ssam
293189251Ssam
294281806Srpaulostruct eap_erp_key {
295281806Srpaulo	struct dl_list list;
296281806Srpaulo	size_t rRK_len;
297281806Srpaulo	size_t rIK_len;
298281806Srpaulo	u8 rRK[ERP_MAX_KEY_LEN];
299281806Srpaulo	u8 rIK[ERP_MAX_KEY_LEN];
300281806Srpaulo	u32 next_seq;
301281806Srpaulo	char keyname_nai[];
302281806Srpaulo};
303281806Srpaulo
304189251Ssam/**
305189251Ssam * struct eap_sm - EAP state machine data
306189251Ssam */
307189251Ssamstruct eap_sm {
308189251Ssam	enum {
309189251Ssam		EAP_INITIALIZE, EAP_DISABLED, EAP_IDLE, EAP_RECEIVED,
310189251Ssam		EAP_GET_METHOD, EAP_METHOD, EAP_SEND_RESPONSE, EAP_DISCARD,
311189251Ssam		EAP_IDENTITY, EAP_NOTIFICATION, EAP_RETRANSMIT, EAP_SUCCESS,
312189251Ssam		EAP_FAILURE
313189251Ssam	} EAP_state;
314189251Ssam	/* Long-term local variables */
315189251Ssam	EapType selectedMethod;
316189251Ssam	EapMethodState methodState;
317189251Ssam	int lastId;
318189251Ssam	struct wpabuf *lastRespData;
319189251Ssam	EapDecision decision;
320189251Ssam	/* Short-term local variables */
321189251Ssam	Boolean rxReq;
322189251Ssam	Boolean rxSuccess;
323189251Ssam	Boolean rxFailure;
324189251Ssam	int reqId;
325189251Ssam	EapType reqMethod;
326189251Ssam	int reqVendor;
327189251Ssam	u32 reqVendorMethod;
328189251Ssam	Boolean ignore;
329189251Ssam	/* Constants */
330189251Ssam	int ClientTimeout;
331189251Ssam
332189251Ssam	/* Miscellaneous variables */
333189251Ssam	Boolean allowNotifications; /* peer state machine <-> methods */
334189251Ssam	struct wpabuf *eapRespData; /* peer to lower layer */
335189251Ssam	Boolean eapKeyAvailable; /* peer to lower layer */
336189251Ssam	u8 *eapKeyData; /* peer to lower layer */
337189251Ssam	size_t eapKeyDataLen; /* peer to lower layer */
338281806Srpaulo	u8 *eapSessionId; /* peer to lower layer */
339281806Srpaulo	size_t eapSessionIdLen; /* peer to lower layer */
340189251Ssam	const struct eap_method *m; /* selected EAP method */
341189251Ssam	/* not defined in RFC 4137 */
342189251Ssam	Boolean changed;
343189251Ssam	void *eapol_ctx;
344289549Srpaulo	const struct eapol_callbacks *eapol_cb;
345189251Ssam	void *eap_method_priv;
346189251Ssam	int init_phase2;
347189251Ssam	int fast_reauth;
348281806Srpaulo	Boolean reauthInit; /* send EAP-Identity/Re-auth */
349281806Srpaulo	u32 erp_seq;
350189251Ssam
351189251Ssam	Boolean rxResp /* LEAP only */;
352189251Ssam	Boolean leap_done;
353189251Ssam	Boolean peap_done;
354289549Srpaulo	u8 req_sha1[20]; /* SHA1() of the current EAP packet */
355289549Srpaulo	u8 last_sha1[20]; /* SHA1() of the previously received EAP packet; used
356289549Srpaulo			   * in duplicate request detection. */
357189251Ssam
358189251Ssam	void *msg_ctx;
359189251Ssam	void *scard_ctx;
360189251Ssam	void *ssl_ctx;
361252726Srpaulo	void *ssl_ctx2;
362189251Ssam
363189251Ssam	unsigned int workaround;
364189251Ssam
365189251Ssam	/* Optional challenges generated in Phase 1 (EAP-FAST) */
366189251Ssam	u8 *peer_challenge, *auth_challenge;
367189251Ssam
368189251Ssam	int num_rounds;
369189251Ssam	int force_disabled;
370189251Ssam
371189251Ssam	struct wps_context *wps;
372189251Ssam
373189251Ssam	int prev_failure;
374281806Srpaulo	struct eap_peer_config *last_config;
375252726Srpaulo
376252726Srpaulo	struct ext_password_data *ext_pw;
377252726Srpaulo	struct wpabuf *ext_pw_buf;
378281806Srpaulo
379281806Srpaulo	int external_sim;
380281806Srpaulo
381281806Srpaulo	unsigned int expected_failure:1;
382337817Scy	unsigned int ext_cert_check:1;
383337817Scy	unsigned int waiting_ext_cert_check:1;
384281806Srpaulo
385281806Srpaulo	struct dl_list erp_keys; /* struct eap_erp_key */
386189251Ssam};
387189251Ssam
388189251Ssamconst u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len);
389189251Ssamconst u8 * eap_get_config_password(struct eap_sm *sm, size_t *len);
390189251Ssamconst u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash);
391189251Ssamconst u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len);
392189251Ssamconst u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len);
393189251Ssamvoid eap_clear_config_otp(struct eap_sm *sm);
394189251Ssamconst char * eap_get_config_phase1(struct eap_sm *sm);
395189251Ssamconst char * eap_get_config_phase2(struct eap_sm *sm);
396252726Srpauloint eap_get_config_fragment_size(struct eap_sm *sm);
397189251Ssamstruct eap_peer_config * eap_get_config(struct eap_sm *sm);
398189251Ssamvoid eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob);
399189251Ssamconst struct wpa_config_blob *
400189251Ssameap_get_config_blob(struct eap_sm *sm, const char *name);
401189251Ssamvoid eap_notify_pending(struct eap_sm *sm);
402189251Ssamint eap_allowed_method(struct eap_sm *sm, int vendor, u32 method);
403189251Ssam
404189251Ssam#endif /* EAP_I_H */
405