$search
00001 /* 00002 * EAP peer method: 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 "crypto/tls.h" 00019 #include "eap_i.h" 00020 #include "eap_tls_common.h" 00021 #include "eap_config.h" 00022 00023 00024 static void eap_tls_deinit(struct eap_sm *sm, void *priv); 00025 00026 00027 struct eap_tls_data { 00028 struct eap_ssl_data ssl; 00029 u8 *key_data; 00030 }; 00031 00032 00033 static void * eap_tls_init(struct eap_sm *sm) 00034 { 00035 struct eap_tls_data *data; 00036 struct eap_peer_config *config = eap_get_config(sm); 00037 if (config == NULL || 00038 ((sm->init_phase2 ? config->private_key2 : config->private_key) 00039 == NULL && 00040 (sm->init_phase2 ? config->engine2 : config->engine) == 0)) { 00041 wpa_printf(MSG_INFO, "EAP-TLS: Private key not configured"); 00042 return NULL; 00043 } 00044 00045 data = os_zalloc(sizeof(*data)); 00046 if (data == NULL) 00047 return NULL; 00048 00049 if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) { 00050 wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); 00051 eap_tls_deinit(sm, data); 00052 if (config->engine) { 00053 wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting Smartcard " 00054 "PIN"); 00055 eap_sm_request_pin(sm); 00056 sm->ignore = TRUE; 00057 } else if (config->private_key && !config->private_key_passwd) 00058 { 00059 wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting private " 00060 "key passphrase"); 00061 eap_sm_request_passphrase(sm); 00062 sm->ignore = TRUE; 00063 } 00064 return NULL; 00065 } 00066 00067 return data; 00068 } 00069 00070 00071 static void eap_tls_deinit(struct eap_sm *sm, void *priv) 00072 { 00073 struct eap_tls_data *data = priv; 00074 if (data == NULL) 00075 return; 00076 eap_peer_tls_ssl_deinit(sm, &data->ssl); 00077 os_free(data->key_data); 00078 os_free(data); 00079 } 00080 00081 00082 static struct wpabuf * eap_tls_failure(struct eap_sm *sm, 00083 struct eap_tls_data *data, 00084 struct eap_method_ret *ret, int res, 00085 struct wpabuf *resp, u8 id) 00086 { 00087 wpa_printf(MSG_DEBUG, "EAP-TLS: TLS processing failed"); 00088 00089 ret->methodState = METHOD_DONE; 00090 ret->decision = DECISION_FAIL; 00091 00092 if (res == -1) { 00093 struct eap_peer_config *config = eap_get_config(sm); 00094 if (config) { 00095 /* 00096 * The TLS handshake failed. So better forget the old 00097 * PIN. It may be wrong, we cannot be sure but trying 00098 * the wrong one again might block it on the card--so 00099 * better ask the user again. 00100 */ 00101 os_free(config->pin); 00102 config->pin = NULL; 00103 } 00104 } 00105 00106 if (resp) { 00107 /* 00108 * This is likely an alert message, so send it instead of just 00109 * ACKing the error. 00110 */ 00111 return resp; 00112 } 00113 00114 return eap_peer_tls_build_ack(id, EAP_TYPE_TLS, 0); 00115 } 00116 00117 00118 static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, 00119 struct eap_method_ret *ret) 00120 { 00121 wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); 00122 00123 ret->methodState = METHOD_DONE; 00124 ret->decision = DECISION_UNCOND_SUCC; 00125 00126 os_free(data->key_data); 00127 data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, 00128 "client EAP encryption", 00129 EAP_TLS_KEY_LEN + 00130 EAP_EMSK_LEN); 00131 if (data->key_data) { 00132 wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key", 00133 data->key_data, EAP_TLS_KEY_LEN); 00134 wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived EMSK", 00135 data->key_data + EAP_TLS_KEY_LEN, 00136 EAP_EMSK_LEN); 00137 } else { 00138 wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key"); 00139 } 00140 } 00141 00142 00143 static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, 00144 struct eap_method_ret *ret, 00145 const struct wpabuf *reqData) 00146 { 00147 size_t left; 00148 int res; 00149 struct wpabuf *resp; 00150 u8 flags, id; 00151 const u8 *pos; 00152 struct eap_tls_data *data = priv; 00153 00154 pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TLS, ret, 00155 reqData, &left, &flags); 00156 if (pos == NULL) 00157 return NULL; 00158 id = eap_get_id(reqData); 00159 00160 if (flags & EAP_TLS_FLAGS_START) { 00161 wpa_printf(MSG_DEBUG, "EAP-TLS: Start"); 00162 left = 0; /* make sure that this frame is empty, even though it 00163 * should always be, anyway */ 00164 } 00165 00166 resp = NULL; 00167 res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TLS, 0, id, 00168 pos, left, &resp); 00169 00170 if (res < 0) { 00171 return eap_tls_failure(sm, data, ret, res, resp, id); 00172 } 00173 00174 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) 00175 eap_tls_success(sm, data, ret); 00176 00177 if (res == 1) { 00178 wpabuf_free(resp); 00179 return eap_peer_tls_build_ack(id, EAP_TYPE_TLS, 0); 00180 } 00181 00182 return resp; 00183 } 00184 00185 00186 static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv) 00187 { 00188 struct eap_tls_data *data = priv; 00189 return tls_connection_established(sm->ssl_ctx, data->ssl.conn); 00190 } 00191 00192 00193 static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv) 00194 { 00195 } 00196 00197 00198 static void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv) 00199 { 00200 struct eap_tls_data *data = priv; 00201 os_free(data->key_data); 00202 data->key_data = NULL; 00203 if (eap_peer_tls_reauth_init(sm, &data->ssl)) { 00204 os_free(data); 00205 return NULL; 00206 } 00207 return priv; 00208 } 00209 00210 00211 static int eap_tls_get_status(struct eap_sm *sm, void *priv, char *buf, 00212 size_t buflen, int verbose) 00213 { 00214 struct eap_tls_data *data = priv; 00215 return eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); 00216 } 00217 00218 00219 static Boolean eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv) 00220 { 00221 struct eap_tls_data *data = priv; 00222 return data->key_data != NULL; 00223 } 00224 00225 00226 static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len) 00227 { 00228 struct eap_tls_data *data = priv; 00229 u8 *key; 00230 00231 if (data->key_data == NULL) 00232 return NULL; 00233 00234 key = os_malloc(EAP_TLS_KEY_LEN); 00235 if (key == NULL) 00236 return NULL; 00237 00238 *len = EAP_TLS_KEY_LEN; 00239 os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); 00240 00241 return key; 00242 } 00243 00244 00245 static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 00246 { 00247 struct eap_tls_data *data = priv; 00248 u8 *key; 00249 00250 if (data->key_data == NULL) 00251 return NULL; 00252 00253 key = os_malloc(EAP_EMSK_LEN); 00254 if (key == NULL) 00255 return NULL; 00256 00257 *len = EAP_EMSK_LEN; 00258 os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN); 00259 00260 return key; 00261 } 00262 00263 00264 int eap_peer_tls_register(void) 00265 { 00266 struct eap_method *eap; 00267 int ret; 00268 00269 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 00270 EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS"); 00271 if (eap == NULL) 00272 return -1; 00273 00274 eap->init = eap_tls_init; 00275 eap->deinit = eap_tls_deinit; 00276 eap->process = eap_tls_process; 00277 eap->isKeyAvailable = eap_tls_isKeyAvailable; 00278 eap->getKey = eap_tls_getKey; 00279 eap->get_status = eap_tls_get_status; 00280 eap->has_reauth_data = eap_tls_has_reauth_data; 00281 eap->deinit_for_reauth = eap_tls_deinit_for_reauth; 00282 eap->init_for_reauth = eap_tls_init_for_reauth; 00283 eap->get_emsk = eap_tls_get_emsk; 00284 00285 ret = eap_peer_method_register(eap); 00286 if (ret) 00287 eap_peer_method_free(eap); 00288 return ret; 00289 }