diff options
Diffstat (limited to 'contrib/wpa_supplicant/eap_tls.c')
-rw-r--r-- | contrib/wpa_supplicant/eap_tls.c | 183 |
1 files changed, 119 insertions, 64 deletions
diff --git a/contrib/wpa_supplicant/eap_tls.c b/contrib/wpa_supplicant/eap_tls.c index d1452df..03fcd89 100644 --- a/contrib/wpa_supplicant/eap_tls.c +++ b/contrib/wpa_supplicant/eap_tls.c @@ -1,6 +1,6 @@ /* - * WPA Supplicant / EAP-TLS (RFC 2716) - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> + * EAP peer method: EAP-TLS (RFC 2716) + * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> * * 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 @@ -12,14 +12,11 @@ * See README and COPYING for more details. */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> +#include "includes.h" #include "common.h" #include "eap_i.h" #include "eap_tls_common.h" -#include "wpa_supplicant.h" #include "config_ssid.h" #include "tls.h" @@ -44,10 +41,9 @@ static void * eap_tls_init(struct eap_sm *sm) return NULL; } - data = malloc(sizeof(*data)); + data = os_zalloc(sizeof(*data)); if (data == NULL) return NULL; - memset(data, 0, sizeof(*data)); if (eap_tls_ssl_init(sm, &data->ssl, config)) { wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); @@ -55,13 +51,13 @@ static void * eap_tls_init(struct eap_sm *sm) if (config->engine) { wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting Smartcard " "PIN"); - eap_sm_request_pin(sm, config); + eap_sm_request_pin(sm); sm->ignore = TRUE; } else if (config->private_key && !config->private_key_passwd) { wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting private " "key passphrase"); - eap_sm_request_passphrase(sm, config); + eap_sm_request_passphrase(sm); sm->ignore = TRUE; } return NULL; @@ -77,8 +73,67 @@ static void eap_tls_deinit(struct eap_sm *sm, void *priv) if (data == NULL) return; eap_tls_ssl_deinit(sm, &data->ssl); - free(data->key_data); - free(data); + os_free(data->key_data); + os_free(data); +} + + +static u8 * eap_tls_failure(struct eap_sm *sm, struct eap_tls_data *data, + struct eap_method_ret *ret, int res, u8 *resp, + u8 id, size_t *respDataLen) +{ + wpa_printf(MSG_DEBUG, "EAP-TLS: TLS processing failed"); + + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + + if (res == -1) { + struct wpa_ssid *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 + * ACKing the error. + */ + return resp; + } + + return eap_tls_build_ack(&data->ssl, respDataLen, id, EAP_TYPE_TLS, 0); +} + + +static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, + struct eap_method_ret *ret) +{ + wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); + + ret->methodState = METHOD_DONE; + ret->decision = DECISION_UNCOND_SUCC; + + os_free(data->key_data); + data->key_data = eap_tls_derive_key(sm, &data->ssl, + "client EAP encryption", + EAP_TLS_KEY_LEN + EAP_EMSK_LEN); + if (data->key_data) { + wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key", + data->key_data, EAP_TLS_KEY_LEN); + wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived EMSK", + data->key_data + EAP_TLS_KEY_LEN, + EAP_EMSK_LEN); + } else { + wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key"); + } } @@ -87,7 +142,6 @@ static u8 * eap_tls_process(struct eap_sm *sm, void *priv, const u8 *reqData, size_t reqDataLen, size_t *respDataLen) { - struct wpa_ssid *config = eap_get_config(sm); const struct eap_hdr *req; size_t left; int res; @@ -113,48 +167,18 @@ static u8 * eap_tls_process(struct eap_sm *sm, void *priv, left, &resp, respDataLen); if (res < 0) { - wpa_printf(MSG_DEBUG, "EAP-TLS: TLS processing failed"); - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - if (resp) { - /* This is likely an alert message, so send it instead - * of just ACKing the error. */ - return resp; - } - return eap_tls_build_ack(&data->ssl, respDataLen, id, - EAP_TYPE_TLS, 0); + return eap_tls_failure(sm, data, ret, res, resp, id, + respDataLen); } - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - free(data->key_data); - data->key_data = eap_tls_derive_key(sm, &data->ssl, - "client EAP encryption", - EAP_TLS_KEY_LEN); - if (data->key_data) { - wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key", - data->key_data, EAP_TLS_KEY_LEN); - } else { - wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive key"); - } - } + if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) + eap_tls_success(sm, data, ret); if (res == 1) { return eap_tls_build_ack(&data->ssl, respDataLen, id, EAP_TYPE_TLS, 0); } - if (res == -1) { - /* The TLS handshake failed. So better forget the old PIN. - * It may be wrong, we can't be sure but trying the wrong one - * again might block it on the card - so better ask the user - * again */ - free(config->pin); - config->pin = NULL; - } - return resp; } @@ -174,10 +198,10 @@ 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; - free(data->key_data); + os_free(data->key_data); data->key_data = NULL; if (eap_tls_reauth_init(sm, &data->ssl)) { - free(data); + os_free(data); return NULL; } return priv; @@ -207,28 +231,59 @@ static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len) if (data->key_data == NULL) return NULL; - key = malloc(EAP_TLS_KEY_LEN); + key = os_malloc(EAP_TLS_KEY_LEN); if (key == NULL) return NULL; *len = EAP_TLS_KEY_LEN; - memcpy(key, data->key_data, EAP_TLS_KEY_LEN); + os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); return key; } -const struct eap_method eap_method_tls = +static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) { - .method = EAP_TYPE_TLS, - .name = "TLS", - .init = eap_tls_init, - .deinit = eap_tls_deinit, - .process = eap_tls_process, - .isKeyAvailable = eap_tls_isKeyAvailable, - .getKey = eap_tls_getKey, - .get_status = eap_tls_get_status, - .has_reauth_data = eap_tls_has_reauth_data, - .deinit_for_reauth = eap_tls_deinit_for_reauth, - .init_for_reauth = eap_tls_init_for_reauth, -}; + struct eap_tls_data *data = priv; + u8 *key; + + if (data->key_data == NULL) + return NULL; + + key = os_malloc(EAP_EMSK_LEN); + if (key == NULL) + return NULL; + + *len = EAP_EMSK_LEN; + os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN); + + return key; +} + + +int eap_peer_tls_register(void) +{ + struct eap_method *eap; + int ret; + + eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, + EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS"); + if (eap == NULL) + return -1; + + eap->init = eap_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; +} |