X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=libeap%2Fsrc%2Feap_peer%2Feap_tls.c;h=66a027a626e0dba5cac6f1673689ccca25d58c69;hb=4f319dde67a76fe0aaf33f6d2788968012584ada;hp=20b2212e1cdc4fff0e6e9cfe7ef2a95f8c5d3f91;hpb=acc2e49c1b52930eb717443fee098d4e7773bd5a;p=mech_eap.git diff --git a/libeap/src/eap_peer/eap_tls.c b/libeap/src/eap_peer/eap_tls.c index 20b2212..66a027a 100644 --- a/libeap/src/eap_peer/eap_tls.c +++ b/libeap/src/eap_peer/eap_tls.c @@ -1,15 +1,9 @@ /* * EAP peer method: EAP-TLS (RFC 2716) - * Copyright (c) 2004-2008, Jouni Malinen + * Copyright (c) 2004-2008, 2012, Jouni Malinen * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. + * This software may be distributed under the terms of the BSD license. + * See README for more details. */ #include "includes.h" @@ -27,6 +21,10 @@ static void eap_tls_deinit(struct eap_sm *sm, void *priv); struct eap_tls_data { struct eap_ssl_data ssl; u8 *key_data; + u8 *session_id; + size_t id_len; + void *ssl_ctx; + u8 eap_type; }; @@ -46,7 +44,10 @@ static void * eap_tls_init(struct eap_sm *sm) if (data == NULL) return NULL; - if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) { + data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 : + sm->ssl_ctx; + + if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_TLS)) { wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); eap_tls_deinit(sm, data); if (config->engine) { @@ -64,8 +65,73 @@ static void * eap_tls_init(struct eap_sm *sm) return NULL; } + data->eap_type = EAP_TYPE_TLS; + + return data; +} + + +#ifdef EAP_UNAUTH_TLS +static void * eap_unauth_tls_init(struct eap_sm *sm) +{ + struct eap_tls_data *data; + struct eap_peer_config *config = eap_get_config(sm); + + data = os_zalloc(sizeof(*data)); + if (data == NULL) + return NULL; + + data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 : + sm->ssl_ctx; + + if (eap_peer_tls_ssl_init(sm, &data->ssl, config, + EAP_UNAUTH_TLS_TYPE)) { + wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); + eap_tls_deinit(sm, data); + return NULL; + } + + data->eap_type = EAP_UNAUTH_TLS_TYPE; + + return data; +} +#endif /* EAP_UNAUTH_TLS */ + + +#ifdef CONFIG_HS20 +static void * eap_wfa_unauth_tls_init(struct eap_sm *sm) +{ + struct eap_tls_data *data; + struct eap_peer_config *config = eap_get_config(sm); + + data = os_zalloc(sizeof(*data)); + if (data == NULL) + return NULL; + + data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 : + sm->ssl_ctx; + + if (eap_peer_tls_ssl_init(sm, &data->ssl, config, + EAP_WFA_UNAUTH_TLS_TYPE)) { + wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); + eap_tls_deinit(sm, data); + return NULL; + } + + data->eap_type = EAP_WFA_UNAUTH_TLS_TYPE; + return data; } +#endif /* CONFIG_HS20 */ + + +static void eap_tls_free_key(struct eap_tls_data *data) +{ + if (data->key_data) { + bin_clear_free(data->key_data, EAP_TLS_KEY_LEN + EAP_EMSK_LEN); + data->key_data = NULL; + } +} static void eap_tls_deinit(struct eap_sm *sm, void *priv) @@ -74,7 +140,8 @@ static void eap_tls_deinit(struct eap_sm *sm, void *priv) if (data == NULL) return; eap_peer_tls_ssl_deinit(sm, &data->ssl); - os_free(data->key_data); + eap_tls_free_key(data); + os_free(data->session_id); os_free(data); } @@ -89,20 +156,6 @@ static struct wpabuf * eap_tls_failure(struct eap_sm *sm, ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; - if (res == -1) { - struct eap_peer_config *config = eap_get_config(sm); - if (config) { - /* - * The TLS handshake failed. So better forget the old - * PIN. It may be wrong, we cannot be sure but trying - * the wrong one again might block it on the card--so - * better ask the user again. - */ - os_free(config->pin); - config->pin = NULL; - } - } - if (resp) { /* * This is likely an alert message, so send it instead of just @@ -111,7 +164,7 @@ static struct wpabuf * eap_tls_failure(struct eap_sm *sm, return resp; } - return eap_peer_tls_build_ack(id, EAP_TYPE_TLS, 0); + return eap_peer_tls_build_ack(id, data->eap_type, 0); } @@ -123,7 +176,7 @@ static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, ret->methodState = METHOD_DONE; ret->decision = DECISION_UNCOND_SUCC; - os_free(data->key_data); + eap_tls_free_key(data); data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, "client EAP encryption", EAP_TLS_KEY_LEN + @@ -137,6 +190,17 @@ static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, } else { wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key"); } + + os_free(data->session_id); + data->session_id = eap_peer_tls_derive_session_id(sm, &data->ssl, + EAP_TYPE_TLS, + &data->id_len); + if (data->session_id) { + wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived Session-Id", + data->session_id, data->id_len); + } else { + wpa_printf(MSG_ERROR, "EAP-TLS: Failed to derive Session-Id"); + } } @@ -150,8 +214,9 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, u8 flags, id; const u8 *pos; struct eap_tls_data *data = priv; + struct wpabuf msg; - pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TLS, ret, + pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret, reqData, &left, &flags); if (pos == NULL) return NULL; @@ -164,19 +229,20 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, } resp = NULL; - res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TLS, 0, id, - pos, left, &resp); + wpabuf_set(&msg, pos, left); + res = eap_peer_tls_process_helper(sm, &data->ssl, data->eap_type, 0, + id, &msg, &resp); if (res < 0) { return eap_tls_failure(sm, data, ret, res, resp, id); } - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) + if (tls_connection_established(data->ssl_ctx, data->ssl.conn)) eap_tls_success(sm, data, ret); if (res == 1) { wpabuf_free(resp); - return eap_peer_tls_build_ack(id, EAP_TYPE_TLS, 0); + return eap_peer_tls_build_ack(id, data->eap_type, 0); } return resp; @@ -186,7 +252,7 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv) { struct eap_tls_data *data = priv; - return tls_connection_established(sm->ssl_ctx, data->ssl.conn); + return tls_connection_established(data->ssl_ctx, data->ssl.conn); } @@ -198,8 +264,9 @@ static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv) static void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv) { struct eap_tls_data *data = priv; - os_free(data->key_data); - data->key_data = NULL; + eap_tls_free_key(data); + os_free(data->session_id); + data->session_id = NULL; if (eap_peer_tls_reauth_init(sm, &data->ssl)) { os_free(data); return NULL; @@ -261,6 +328,25 @@ static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } +static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len) +{ + struct eap_tls_data *data = priv; + u8 *id; + + if (data->session_id == NULL) + return NULL; + + id = os_malloc(data->id_len); + if (id == NULL) + return NULL; + + *len = data->id_len; + os_memcpy(id, data->session_id, data->id_len); + + return id; +} + + int eap_peer_tls_register(void) { struct eap_method *eap; @@ -276,6 +362,69 @@ int eap_peer_tls_register(void) eap->process = eap_tls_process; eap->isKeyAvailable = eap_tls_isKeyAvailable; eap->getKey = eap_tls_getKey; + eap->getSessionId = eap_tls_get_session_id; + eap->get_status = eap_tls_get_status; + eap->has_reauth_data = eap_tls_has_reauth_data; + eap->deinit_for_reauth = eap_tls_deinit_for_reauth; + eap->init_for_reauth = eap_tls_init_for_reauth; + eap->get_emsk = eap_tls_get_emsk; + + ret = eap_peer_method_register(eap); + if (ret) + eap_peer_method_free(eap); + return ret; +} + + +#ifdef EAP_UNAUTH_TLS +int eap_peer_unauth_tls_register(void) +{ + struct eap_method *eap; + int ret; + + eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, + EAP_VENDOR_UNAUTH_TLS, + EAP_VENDOR_TYPE_UNAUTH_TLS, "UNAUTH-TLS"); + if (eap == NULL) + return -1; + + eap->init = eap_unauth_tls_init; + eap->deinit = eap_tls_deinit; + eap->process = eap_tls_process; + eap->isKeyAvailable = eap_tls_isKeyAvailable; + eap->getKey = eap_tls_getKey; + eap->get_status = eap_tls_get_status; + eap->has_reauth_data = eap_tls_has_reauth_data; + eap->deinit_for_reauth = eap_tls_deinit_for_reauth; + eap->init_for_reauth = eap_tls_init_for_reauth; + eap->get_emsk = eap_tls_get_emsk; + + ret = eap_peer_method_register(eap); + if (ret) + eap_peer_method_free(eap); + return ret; +} +#endif /* EAP_UNAUTH_TLS */ + + +#ifdef CONFIG_HS20 +int eap_peer_wfa_unauth_tls_register(void) +{ + struct eap_method *eap; + int ret; + + eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, + EAP_VENDOR_WFA_NEW, + EAP_VENDOR_WFA_UNAUTH_TLS, + "WFA-UNAUTH-TLS"); + if (eap == NULL) + return -1; + + eap->init = eap_wfa_unauth_tls_init; + eap->deinit = eap_tls_deinit; + eap->process = eap_tls_process; + eap->isKeyAvailable = eap_tls_isKeyAvailable; + eap->getKey = eap_tls_getKey; eap->get_status = eap_tls_get_status; eap->has_reauth_data = eap_tls_has_reauth_data; eap->deinit_for_reauth = eap_tls_deinit_for_reauth; @@ -287,3 +436,4 @@ int eap_peer_tls_register(void) eap_peer_method_free(eap); return ret; } +#endif /* CONFIG_HS20 */