00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
00143
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 }