The Android Open Source Project | 845e012 | 2009-03-03 19:31:34 -0800 | [diff] [blame] | 1 | /* |
| 2 | * EAP peer state machines internal structures (RFC 4137) |
| 3 | * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> |
| 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify |
| 6 | * it under the terms of the GNU General Public License version 2 as |
| 7 | * published by the Free Software Foundation. |
| 8 | * |
| 9 | * Alternatively, this software may be distributed under the terms of BSD |
| 10 | * license. |
| 11 | * |
| 12 | * See README and COPYING for more details. |
| 13 | */ |
| 14 | |
| 15 | #ifndef EAP_I_H |
| 16 | #define EAP_I_H |
| 17 | |
| 18 | #include "eap.h" |
| 19 | |
| 20 | /* RFC 4137 - EAP Peer state machine */ |
| 21 | |
| 22 | typedef enum { |
| 23 | DECISION_FAIL, DECISION_COND_SUCC, DECISION_UNCOND_SUCC |
| 24 | } EapDecision; |
| 25 | |
| 26 | typedef enum { |
| 27 | METHOD_NONE, METHOD_INIT, METHOD_CONT, METHOD_MAY_CONT, METHOD_DONE |
| 28 | } EapMethodState; |
| 29 | |
| 30 | /** |
| 31 | * struct eap_method_ret - EAP return values from struct eap_method::process() |
| 32 | * |
| 33 | * These structure contains OUT variables for the interface between peer state |
| 34 | * machine and methods (RFC 4137, Sect. 4.2). eapRespData will be returned as |
| 35 | * the return value of struct eap_method::process() so it is not included in |
| 36 | * this structure. |
| 37 | */ |
| 38 | struct eap_method_ret { |
| 39 | /** |
| 40 | * ignore - Whether method decided to drop the current packed (OUT) |
| 41 | */ |
| 42 | Boolean ignore; |
| 43 | |
| 44 | /** |
| 45 | * methodState - Method-specific state (IN/OUT) |
| 46 | */ |
| 47 | EapMethodState methodState; |
| 48 | |
| 49 | /** |
| 50 | * decision - Authentication decision (OUT) |
| 51 | */ |
| 52 | EapDecision decision; |
| 53 | |
| 54 | /** |
| 55 | * allowNotifications - Whether method allows notifications (OUT) |
| 56 | */ |
| 57 | Boolean allowNotifications; |
| 58 | }; |
| 59 | |
| 60 | |
| 61 | /** |
| 62 | * struct eap_method - EAP method interface |
| 63 | * This structure defines the EAP method interface. Each method will need to |
| 64 | * register its own EAP type, EAP name, and set of function pointers for method |
| 65 | * specific operations. This interface is based on section 4.4 of RFC 4137. |
| 66 | */ |
| 67 | struct eap_method { |
| 68 | /** |
| 69 | * vendor - EAP Vendor-ID (EAP_VENDOR_*) (0 = IETF) |
| 70 | */ |
| 71 | int vendor; |
| 72 | |
| 73 | /** |
| 74 | * method - EAP type number (EAP_TYPE_*) |
| 75 | */ |
| 76 | EapType method; |
| 77 | |
| 78 | /** |
| 79 | * name - Name of the method (e.g., "TLS") |
| 80 | */ |
| 81 | const char *name; |
| 82 | |
| 83 | /** |
| 84 | * init - Initialize an EAP method |
| 85 | * @sm: Pointer to EAP state machine allocated with eap_sm_init() |
| 86 | * Returns: Pointer to allocated private data, or %NULL on failure |
| 87 | * |
| 88 | * This function is used to initialize the EAP method explicitly |
| 89 | * instead of using METHOD_INIT state as specific in RFC 4137. The |
| 90 | * method is expected to initialize it method-specific state and return |
| 91 | * a pointer that will be used as the priv argument to other calls. |
| 92 | */ |
| 93 | void * (*init)(struct eap_sm *sm); |
| 94 | |
| 95 | /** |
| 96 | * deinit - Deinitialize an EAP method |
| 97 | * @sm: Pointer to EAP state machine allocated with eap_sm_init() |
| 98 | * @priv: Pointer to private EAP method data from eap_method::init() |
| 99 | * |
| 100 | * Deinitialize the EAP method and free any allocated private data. |
| 101 | */ |
| 102 | void (*deinit)(struct eap_sm *sm, void *priv); |
| 103 | |
| 104 | /** |
| 105 | * process - Process an EAP request |
| 106 | * @sm: Pointer to EAP state machine allocated with eap_sm_init() |
| 107 | * @priv: Pointer to private EAP method data from eap_method::init() |
| 108 | * @ret: Return values from EAP request validation and processing |
| 109 | * @reqData: EAP request to be processed (eapReqData) |
| 110 | * @reqDataLen: Length of the EAP request |
| 111 | * @respDataLen: Length of the returned EAP response |
| 112 | * Returns: Pointer to allocated EAP response packet (eapRespData) |
| 113 | * |
| 114 | * This function is a combination of m.check(), m.process(), and |
| 115 | * m.buildResp() procedures defined in section 4.4 of RFC 4137 In other |
| 116 | * words, this function validates the incoming request, processes it, |
| 117 | * and build a response packet. m.check() and m.process() return values |
| 118 | * are returned through struct eap_method_ret *ret variable. Caller is |
| 119 | * responsible for freeing the returned EAP response packet. |
| 120 | */ |
| 121 | u8 * (*process)(struct eap_sm *sm, void *priv, |
| 122 | struct eap_method_ret *ret, |
| 123 | const u8 *reqData, size_t reqDataLen, |
| 124 | size_t *respDataLen); |
| 125 | |
| 126 | /** |
| 127 | * isKeyAvailable - Find out whether EAP method has keying material |
| 128 | * @sm: Pointer to EAP state machine allocated with eap_sm_init() |
| 129 | * @priv: Pointer to private EAP method data from eap_method::init() |
| 130 | * Returns: %TRUE if key material (eapKeyData) is available |
| 131 | */ |
| 132 | Boolean (*isKeyAvailable)(struct eap_sm *sm, void *priv); |
| 133 | |
| 134 | /** |
| 135 | * getKey - Get EAP method specific keying material (eapKeyData) |
| 136 | * @sm: Pointer to EAP state machine allocated with eap_sm_init() |
| 137 | * @priv: Pointer to private EAP method data from eap_method::init() |
| 138 | * @len: Pointer to variable to store key length (eapKeyDataLen) |
| 139 | * Returns: Keying material (eapKeyData) or %NULL if not available |
| 140 | * |
| 141 | * This function can be used to get the keying material from the EAP |
| 142 | * method. The key may already be stored in the method-specific private |
| 143 | * data or this function may derive the key. |
| 144 | */ |
| 145 | u8 * (*getKey)(struct eap_sm *sm, void *priv, size_t *len); |
| 146 | |
| 147 | /** |
| 148 | * get_status - Get EAP method status |
| 149 | * @sm: Pointer to EAP state machine allocated with eap_sm_init() |
| 150 | * @priv: Pointer to private EAP method data from eap_method::init() |
| 151 | * @buf: Buffer for status information |
| 152 | * @buflen: Maximum buffer length |
| 153 | * @verbose: Whether to include verbose status information |
| 154 | * Returns: Number of bytes written to buf |
| 155 | * |
| 156 | * Query EAP method for status information. This function fills in a |
| 157 | * text area with current status information from the EAP method. If |
| 158 | * the buffer (buf) is not large enough, status information will be |
| 159 | * truncated to fit the buffer. |
| 160 | */ |
| 161 | int (*get_status)(struct eap_sm *sm, void *priv, char *buf, |
| 162 | size_t buflen, int verbose); |
| 163 | |
| 164 | /** |
| 165 | * has_reauth_data - Whether method is ready for fast reauthentication |
| 166 | * @sm: Pointer to EAP state machine allocated with eap_sm_init() |
| 167 | * @priv: Pointer to private EAP method data from eap_method::init() |
| 168 | * Returns: %TRUE or %FALSE based on whether fast reauthentication is |
| 169 | * possible |
| 170 | * |
| 171 | * This function is an optional handler that only EAP methods |
| 172 | * supporting fast re-authentication need to implement. |
| 173 | */ |
| 174 | Boolean (*has_reauth_data)(struct eap_sm *sm, void *priv); |
| 175 | |
| 176 | /** |
| 177 | * deinit_for_reauth - Release data that is not needed for fast re-auth |
| 178 | * @sm: Pointer to EAP state machine allocated with eap_sm_init() |
| 179 | * @priv: Pointer to private EAP method data from eap_method::init() |
| 180 | * |
| 181 | * This function is an optional handler that only EAP methods |
| 182 | * supporting fast re-authentication need to implement. This is called |
| 183 | * when authentication has been completed and EAP state machine is |
| 184 | * requesting that enough state information is maintained for fast |
| 185 | * re-authentication |
| 186 | */ |
| 187 | void (*deinit_for_reauth)(struct eap_sm *sm, void *priv); |
| 188 | |
| 189 | /** |
| 190 | * init_for_reauth - Prepare for start of fast re-authentication |
| 191 | * @sm: Pointer to EAP state machine allocated with eap_sm_init() |
| 192 | * @priv: Pointer to private EAP method data from eap_method::init() |
| 193 | * |
| 194 | * This function is an optional handler that only EAP methods |
| 195 | * supporting fast re-authentication need to implement. This is called |
| 196 | * when EAP authentication is started and EAP state machine is |
| 197 | * requesting fast re-authentication to be used. |
| 198 | */ |
| 199 | void * (*init_for_reauth)(struct eap_sm *sm, void *priv); |
| 200 | |
| 201 | /** |
| 202 | * get_identity - Get method specific identity for re-authentication |
| 203 | * @sm: Pointer to EAP state machine allocated with eap_sm_init() |
| 204 | * @priv: Pointer to private EAP method data from eap_method::init() |
| 205 | * @len: Length of the returned identity |
| 206 | * Returns: Pointer to the method specific identity or %NULL if default |
| 207 | * identity is to be used |
| 208 | * |
| 209 | * This function is an optional handler that only EAP methods |
| 210 | * that use method specific identity need to implement. |
| 211 | */ |
| 212 | const u8 * (*get_identity)(struct eap_sm *sm, void *priv, size_t *len); |
| 213 | |
| 214 | /** |
| 215 | * free - Free EAP method data |
| 216 | * @method: Pointer to the method data registered with |
| 217 | * eap_peer_method_register(). |
| 218 | * |
| 219 | * This function will be called when the EAP method is being |
| 220 | * unregistered. If the EAP method allocated resources during |
| 221 | * registration (e.g., allocated struct eap_method), they should be |
| 222 | * freed in this function. No other method functions will be called |
| 223 | * after this call. If this function is not defined (i.e., function |
| 224 | * pointer is %NULL), a default handler is used to release the method |
| 225 | * data with free(method). This is suitable for most cases. |
| 226 | */ |
| 227 | void (*free)(struct eap_method *method); |
| 228 | |
| 229 | #define EAP_PEER_METHOD_INTERFACE_VERSION 1 |
| 230 | /** |
| 231 | * version - Version of the EAP peer method interface |
| 232 | * |
| 233 | * The EAP peer method implementation should set this variable to |
| 234 | * EAP_PEER_METHOD_INTERFACE_VERSION. This is used to verify that the |
| 235 | * EAP method is using supported API version when using dynamically |
| 236 | * loadable EAP methods. |
| 237 | */ |
| 238 | int version; |
| 239 | |
| 240 | /** |
| 241 | * next - Pointer to the next EAP method |
| 242 | * |
| 243 | * This variable is used internally in the EAP method registration code |
| 244 | * to create a linked list of registered EAP methods. |
| 245 | */ |
| 246 | struct eap_method *next; |
| 247 | |
| 248 | #ifdef CONFIG_DYNAMIC_EAP_METHODS |
| 249 | /** |
| 250 | * dl_handle - Handle for the dynamic library |
| 251 | * |
| 252 | * This variable is used internally in the EAP method registration code |
| 253 | * to store a handle for the dynamic library. If the method is linked |
| 254 | * in statically, this is %NULL. |
| 255 | */ |
| 256 | void *dl_handle; |
| 257 | #endif /* CONFIG_DYNAMIC_EAP_METHODS */ |
| 258 | |
| 259 | /** |
| 260 | * get_emsk - Get EAP method specific keying extended material (EMSK) |
| 261 | * @sm: Pointer to EAP state machine allocated with eap_sm_init() |
| 262 | * @priv: Pointer to private EAP method data from eap_method::init() |
| 263 | * @len: Pointer to a variable to store EMSK length |
| 264 | * Returns: EMSK or %NULL if not available |
| 265 | * |
| 266 | * This function can be used to get the extended keying material from |
| 267 | * the EAP method. The key may already be stored in the method-specific |
| 268 | * private data or this function may derive the key. |
| 269 | */ |
| 270 | u8 * (*get_emsk)(struct eap_sm *sm, void *priv, size_t *len); |
| 271 | }; |
| 272 | |
| 273 | |
| 274 | /** |
| 275 | * struct eap_sm - EAP state machine data |
| 276 | */ |
| 277 | struct eap_sm { |
| 278 | enum { |
| 279 | EAP_INITIALIZE, EAP_DISABLED, EAP_IDLE, EAP_RECEIVED, |
| 280 | EAP_GET_METHOD, EAP_METHOD, EAP_SEND_RESPONSE, EAP_DISCARD, |
| 281 | EAP_IDENTITY, EAP_NOTIFICATION, EAP_RETRANSMIT, EAP_SUCCESS, |
| 282 | EAP_FAILURE |
| 283 | } EAP_state; |
| 284 | /* Long-term local variables */ |
| 285 | EapType selectedMethod; |
| 286 | EapMethodState methodState; |
| 287 | int lastId; |
| 288 | u8 *lastRespData; |
| 289 | size_t lastRespDataLen; |
| 290 | EapDecision decision; |
| 291 | /* Short-term local variables */ |
| 292 | Boolean rxReq; |
| 293 | Boolean rxSuccess; |
| 294 | Boolean rxFailure; |
| 295 | int reqId; |
| 296 | EapType reqMethod; |
| 297 | int reqVendor; |
| 298 | u32 reqVendorMethod; |
| 299 | Boolean ignore; |
| 300 | /* Constants */ |
| 301 | int ClientTimeout; |
| 302 | |
| 303 | /* Miscellaneous variables */ |
| 304 | Boolean allowNotifications; /* peer state machine <-> methods */ |
| 305 | u8 *eapRespData; /* peer to lower layer */ |
| 306 | size_t eapRespDataLen; /* peer to lower layer */ |
| 307 | Boolean eapKeyAvailable; /* peer to lower layer */ |
| 308 | u8 *eapKeyData; /* peer to lower layer */ |
| 309 | size_t eapKeyDataLen; /* peer to lower layer */ |
| 310 | const struct eap_method *m; /* selected EAP method */ |
| 311 | /* not defined in RFC 4137 */ |
| 312 | Boolean changed; |
| 313 | void *eapol_ctx; |
| 314 | struct eapol_callbacks *eapol_cb; |
| 315 | void *eap_method_priv; |
| 316 | int init_phase2; |
| 317 | int fast_reauth; |
| 318 | |
| 319 | Boolean rxResp /* LEAP only */; |
| 320 | Boolean leap_done; |
| 321 | Boolean peap_done; |
| 322 | u8 req_md5[16]; /* MD5() of the current EAP packet */ |
| 323 | u8 last_md5[16]; /* MD5() of the previously received EAP packet; used |
| 324 | * in duplicate request detection. */ |
| 325 | |
| 326 | void *msg_ctx; |
| 327 | void *scard_ctx; |
| 328 | void *ssl_ctx; |
| 329 | |
| 330 | unsigned int workaround; |
| 331 | |
| 332 | /* Optional challenges generated in Phase 1 (EAP-FAST) */ |
| 333 | u8 *peer_challenge, *auth_challenge; |
| 334 | int mschapv2_full_key; /* Request full MSCHAPv2 key */ |
| 335 | |
| 336 | int num_rounds; |
| 337 | int force_disabled; |
| 338 | }; |
| 339 | |
| 340 | const u8 * eap_hdr_validate(int vendor, EapType eap_type, |
| 341 | const u8 *msg, size_t msglen, size_t *plen); |
| 342 | const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len); |
| 343 | const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len); |
| 344 | const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len); |
| 345 | const u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len); |
| 346 | void eap_clear_config_otp(struct eap_sm *sm); |
| 347 | struct wpa_ssid * eap_get_config(struct eap_sm *sm); |
| 348 | void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob); |
| 349 | const struct wpa_config_blob * |
| 350 | eap_get_config_blob(struct eap_sm *sm, const char *name); |
| 351 | struct eap_hdr * eap_msg_alloc(int vendor, EapType type, size_t *len, |
| 352 | size_t payload_len, u8 code, u8 identifier, |
| 353 | u8 **payload); |
| 354 | void eap_notify_pending(struct eap_sm *sm); |
| 355 | |
| 356 | #endif /* EAP_I_H */ |