eap_tls.c

Go to the documentation of this file.
00001 
00016 #include "includes.h"
00017 
00018 #include "common.h"
00019 #include "eap_i.h"
00020 #include "eap_tls_common.h"
00021 #include "tls.h"
00022 
00023 
00024 static void eap_tls_reset(struct eap_sm *sm, void *priv);
00025 
00026 
00027 struct eap_tls_data {
00028         struct eap_ssl_data ssl;
00029         enum { START, CONTINUE, SUCCESS, FAILURE } state;
00030         int established;
00031 };
00032 
00033 
00034 static const char * eap_tls_state_txt(int state)
00035 {
00036         switch (state) {
00037         case START:
00038                 return "START";
00039         case CONTINUE:
00040                 return "CONTINUE";
00041         case SUCCESS:
00042                 return "SUCCESS";
00043         case FAILURE:
00044                 return "FAILURE";
00045         default:
00046                 return "Unknown?!";
00047         }
00048 }
00049 
00050 
00051 static void eap_tls_state(struct eap_tls_data *data, int state)
00052 {
00053         wpa_printf(MSG_DEBUG, "EAP-TLS: %s -> %s",
00054                    eap_tls_state_txt(data->state),
00055                    eap_tls_state_txt(state));
00056         data->state = state;
00057 }
00058 
00059 
00060 static void * eap_tls_init(struct eap_sm *sm)
00061 {
00062         struct eap_tls_data *data;
00063 
00064         data = os_zalloc(sizeof(*data));
00065         if (data == NULL)
00066                 return NULL;
00067         data->state = START;
00068 
00069         if (eap_server_tls_ssl_init(sm, &data->ssl, 1)) {
00070                 wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
00071                 eap_tls_reset(sm, data);
00072                 return NULL;
00073         }
00074 
00075         return data;
00076 }
00077 
00078 
00079 static void eap_tls_reset(struct eap_sm *sm, void *priv)
00080 {
00081         struct eap_tls_data *data = priv;
00082         if (data == NULL)
00083                 return;
00084         eap_server_tls_ssl_deinit(sm, &data->ssl);
00085         os_free(data);
00086 }
00087 
00088 
00089 static struct wpabuf * eap_tls_build_start(struct eap_sm *sm,
00090                                            struct eap_tls_data *data, u8 id)
00091 {
00092         struct wpabuf *req;
00093 
00094         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLS, 1, EAP_CODE_REQUEST,
00095                             id);
00096         if (req == NULL) {
00097                 wpa_printf(MSG_ERROR, "EAP-TLS: Failed to allocate memory for "
00098                            "request");
00099                 eap_tls_state(data, FAILURE);
00100                 return NULL;
00101         }
00102 
00103         wpabuf_put_u8(req, EAP_TLS_FLAGS_START);
00104 
00105         eap_tls_state(data, CONTINUE);
00106 
00107         return req;
00108 }
00109 
00110 
00111 static struct wpabuf * eap_tls_buildReq(struct eap_sm *sm, void *priv, u8 id)
00112 {
00113         struct eap_tls_data *data = priv;
00114         struct wpabuf *res;
00115 
00116         if (data->ssl.state == FRAG_ACK) {
00117                 return eap_server_tls_build_ack(id, EAP_TYPE_TLS, 0);
00118         }
00119 
00120         if (data->ssl.state == WAIT_FRAG_ACK) {
00121                 res = eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TLS, 0,
00122                                                id);
00123                 goto check_established;
00124         }
00125 
00126         switch (data->state) {
00127         case START:
00128                 return eap_tls_build_start(sm, data, id);
00129         case CONTINUE:
00130                 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn))
00131                         data->established = 1;
00132                 break;
00133         default:
00134                 wpa_printf(MSG_DEBUG, "EAP-TLS: %s - unexpected state %d",
00135                            __func__, data->state);
00136                 return NULL;
00137         }
00138 
00139         res = eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TLS, 0, id);
00140 
00141 check_established:
00142         if (data->established && data->ssl.state != WAIT_FRAG_ACK) {
00143                 /* TLS handshake has been completed and there are no more
00144                  * fragments waiting to be sent out. */
00145                 wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
00146                 eap_tls_state(data, SUCCESS);
00147         }
00148 
00149         return res;
00150 }
00151 
00152 
00153 static Boolean eap_tls_check(struct eap_sm *sm, void *priv,
00154                              struct wpabuf *respData)
00155 {
00156         const u8 *pos;
00157         size_t len;
00158 
00159         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLS, respData, &len);
00160         if (pos == NULL || len < 1) {
00161                 wpa_printf(MSG_INFO, "EAP-TLS: Invalid frame");
00162                 return TRUE;
00163         }
00164 
00165         return FALSE;
00166 }
00167 
00168 
00169 static void eap_tls_process_msg(struct eap_sm *sm, void *priv,
00170                                 const struct wpabuf *respData)
00171 {
00172         struct eap_tls_data *data = priv;
00173         if (data->state == SUCCESS && wpabuf_len(data->ssl.in_buf) == 0) {
00174                 wpa_printf(MSG_DEBUG, "EAP-TLS: Client acknowledged final TLS "
00175                            "handshake message");
00176                 return;
00177         }
00178         if (eap_server_tls_phase1(sm, &data->ssl) < 0)
00179                 eap_tls_state(data, FAILURE);
00180 }
00181 
00182 
00183 static void eap_tls_process(struct eap_sm *sm, void *priv,
00184                             struct wpabuf *respData)
00185 {
00186         struct eap_tls_data *data = priv;
00187         if (eap_server_tls_process(sm, &data->ssl, respData, data,
00188                                    EAP_TYPE_TLS, NULL, eap_tls_process_msg) <
00189             0)
00190                 eap_tls_state(data, FAILURE);
00191 }
00192 
00193 
00194 static Boolean eap_tls_isDone(struct eap_sm *sm, void *priv)
00195 {
00196         struct eap_tls_data *data = priv;
00197         return data->state == SUCCESS || data->state == FAILURE;
00198 }
00199 
00200 
00201 static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len)
00202 {
00203         struct eap_tls_data *data = priv;
00204         u8 *eapKeyData;
00205 
00206         if (data->state != SUCCESS)
00207                 return NULL;
00208 
00209         eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
00210                                                "client EAP encryption",
00211                                                EAP_TLS_KEY_LEN);
00212         if (eapKeyData) {
00213                 *len = EAP_TLS_KEY_LEN;
00214                 wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived key",
00215                             eapKeyData, EAP_TLS_KEY_LEN);
00216         } else {
00217                 wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive key");
00218         }
00219 
00220         return eapKeyData;
00221 }
00222 
00223 
00224 static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
00225 {
00226         struct eap_tls_data *data = priv;
00227         u8 *eapKeyData, *emsk;
00228 
00229         if (data->state != SUCCESS)
00230                 return NULL;
00231 
00232         eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
00233                                                "client EAP encryption",
00234                                                EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
00235         if (eapKeyData) {
00236                 emsk = os_malloc(EAP_EMSK_LEN);
00237                 if (emsk)
00238                         os_memcpy(emsk, eapKeyData + EAP_TLS_KEY_LEN,
00239                                   EAP_EMSK_LEN);
00240                 os_free(eapKeyData);
00241         } else
00242                 emsk = NULL;
00243 
00244         if (emsk) {
00245                 *len = EAP_EMSK_LEN;
00246                 wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived EMSK",
00247                             emsk, EAP_EMSK_LEN);
00248         } else {
00249                 wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive EMSK");
00250         }
00251 
00252         return emsk;
00253 }
00254 
00255 
00256 static Boolean eap_tls_isSuccess(struct eap_sm *sm, void *priv)
00257 {
00258         struct eap_tls_data *data = priv;
00259         return data->state == SUCCESS;
00260 }
00261 
00262 
00263 int eap_server_tls_register(void)
00264 {
00265         struct eap_method *eap;
00266         int ret;
00267 
00268         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
00269                                       EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS");
00270         if (eap == NULL)
00271                 return -1;
00272 
00273         eap->init = eap_tls_init;
00274         eap->reset = eap_tls_reset;
00275         eap->buildReq = eap_tls_buildReq;
00276         eap->check = eap_tls_check;
00277         eap->process = eap_tls_process;
00278         eap->isDone = eap_tls_isDone;
00279         eap->getKey = eap_tls_getKey;
00280         eap->isSuccess = eap_tls_isSuccess;
00281         eap->get_emsk = eap_tls_get_emsk;
00282 
00283         ret = eap_server_method_register(eap);
00284         if (ret)
00285                 eap_server_method_free(eap);
00286         return ret;
00287 }
00288 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on Sat Nov 21 23:16:52 2009 for hostapd by  doxygen 1.6.1