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
00144
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