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


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Apr 24 2014 15:34:35