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