summaryrefslogtreecommitdiff
path: root/src/eap_peer/eap_tls_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/eap_peer/eap_tls_common.c')
-rw-r--r--src/eap_peer/eap_tls_common.c137
1 files changed, 55 insertions, 82 deletions
diff --git a/src/eap_peer/eap_tls_common.c b/src/eap_peer/eap_tls_common.c
index 8710781618eff..af2b7541d7016 100644
--- a/src/eap_peer/eap_tls_common.c
+++ b/src/eap_peer/eap_tls_common.c
@@ -68,6 +68,10 @@ static void eap_tls_params_flags(struct tls_connection_params *params,
params->flags |= TLS_CONN_DISABLE_SESSION_TICKET;
if (os_strstr(txt, "tls_disable_session_ticket=0"))
params->flags &= ~TLS_CONN_DISABLE_SESSION_TICKET;
+ if (os_strstr(txt, "tls_disable_tlsv1_0=1"))
+ params->flags |= TLS_CONN_DISABLE_TLSv1_0;
+ if (os_strstr(txt, "tls_disable_tlsv1_0=0"))
+ params->flags &= ~TLS_CONN_DISABLE_TLSv1_0;
if (os_strstr(txt, "tls_disable_tlsv1_1=1"))
params->flags |= TLS_CONN_DISABLE_TLSv1_1;
if (os_strstr(txt, "tls_disable_tlsv1_1=0"))
@@ -196,28 +200,25 @@ static int eap_tls_init_connection(struct eap_sm *sm,
}
res = tls_connection_set_params(data->ssl_ctx, data->conn, params);
- if (res == TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED) {
+ if (res == TLS_SET_PARAMS_ENGINE_PRV_BAD_PIN) {
/*
- * At this point with the pkcs11 engine the PIN might be wrong.
- * We reset the PIN in the configuration to be sure to not use
- * it again and the calling function must request a new one.
+ * At this point with the pkcs11 engine the PIN is wrong. We
+ * reset the PIN in the configuration to be sure to not use it
+ * again and the calling function must request a new one.
*/
+ wpa_printf(MSG_INFO,
+ "TLS: Bad PIN provided, requesting a new one");
os_free(config->pin);
config->pin = NULL;
+ eap_sm_request_pin(sm);
+ sm->ignore = TRUE;
+ } else if (res == TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED) {
+ wpa_printf(MSG_INFO, "TLS: Failed to initialize engine");
} else if (res == TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED) {
wpa_printf(MSG_INFO, "TLS: Failed to load private key");
- /*
- * We do not know exactly but maybe the PIN was wrong,
- * so ask for a new one.
- */
- os_free(config->pin);
- config->pin = NULL;
- eap_sm_request_pin(sm);
sm->ignore = TRUE;
- tls_connection_deinit(data->ssl_ctx, data->conn);
- data->conn = NULL;
- return -1;
- } else if (res) {
+ }
+ if (res) {
wpa_printf(MSG_INFO, "TLS: Failed to set TLS connection "
"parameters");
tls_connection_deinit(data->ssl_ctx, data->conn);
@@ -313,53 +314,19 @@ void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
const char *label, size_t len)
{
-#ifndef CONFIG_FIPS
- struct tls_keys keys;
-#endif /* CONFIG_FIPS */
- u8 *rnd = NULL, *out;
+ u8 *out;
out = os_malloc(len);
if (out == NULL)
return NULL;
- /* First, try to use TLS library function for PRF, if available. */
- if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, out, len)
- == 0)
- return out;
-
-#ifndef CONFIG_FIPS
- /*
- * TLS library did not support key generation, so get the needed TLS
- * session parameters and use an internal implementation of TLS PRF to
- * derive the key.
- */
- if (tls_connection_get_keys(data->ssl_ctx, data->conn, &keys))
- goto fail;
-
- if (keys.client_random == NULL || keys.server_random == NULL ||
- keys.master_key == NULL)
- goto fail;
-
- rnd = os_malloc(keys.client_random_len + keys.server_random_len);
- if (rnd == NULL)
- goto fail;
- os_memcpy(rnd, keys.client_random, keys.client_random_len);
- os_memcpy(rnd + keys.client_random_len, keys.server_random,
- keys.server_random_len);
-
- if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len,
- label, rnd, keys.client_random_len +
- keys.server_random_len, out, len))
- goto fail;
+ if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, 0,
+ out, len)) {
+ os_free(out);
+ return NULL;
+ }
- os_free(rnd);
return out;
-
-fail:
-#endif /* CONFIG_FIPS */
- os_free(out);
- os_free(rnd);
- return NULL;
}
@@ -380,10 +347,10 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
struct eap_ssl_data *data, u8 eap_type,
size_t *len)
{
- struct tls_keys keys;
+ struct tls_random keys;
u8 *out;
- if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
+ if (tls_connection_get_random(sm->ssl_ctx, data->conn, &keys))
return NULL;
if (keys.client_random == NULL || keys.server_random == NULL)
@@ -514,22 +481,19 @@ static const struct wpabuf * eap_peer_tls_data_reassemble(
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
* @data: Data for TLS processing
* @in_data: Message received from the server
- * @in_len: Length of in_data
* @out_data: Buffer for returning a pointer to application data (if available)
* Returns: 0 on success, 1 if more input data is needed, 2 if application data
* is available, -1 on failure
*/
static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data,
- const u8 *in_data, size_t in_len,
+ const struct wpabuf *in_data,
struct wpabuf **out_data)
{
const struct wpabuf *msg;
int need_more_input;
struct wpabuf *appl_data;
- struct wpabuf buf;
- wpabuf_set(&buf, in_data, in_len);
- msg = eap_peer_tls_data_reassemble(data, &buf, &need_more_input);
+ msg = eap_peer_tls_data_reassemble(data, in_data, &need_more_input);
if (msg == NULL)
return need_more_input ? 1 : -1;
@@ -649,7 +613,6 @@ static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type,
* @peap_version: Version number for EAP-PEAP/TTLS
* @id: EAP identifier for the response
* @in_data: Message received from the server
- * @in_len: Length of in_data
* @out_data: Buffer for returning a pointer to the response message
* Returns: 0 on success, 1 if more input data is needed, 2 if application data
* is available, or -1 on failure
@@ -672,14 +635,15 @@ static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type,
*/
int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
EapType eap_type, int peap_version,
- u8 id, const u8 *in_data, size_t in_len,
+ u8 id, const struct wpabuf *in_data,
struct wpabuf **out_data)
{
int ret = 0;
*out_data = NULL;
- if (data->tls_out && wpabuf_len(data->tls_out) > 0 && in_len > 0) {
+ if (data->tls_out && wpabuf_len(data->tls_out) > 0 &&
+ wpabuf_len(in_data) > 0) {
wpa_printf(MSG_DEBUG, "SSL: Received non-ACK when output "
"fragments are waiting to be sent out");
return -1;
@@ -690,8 +654,7 @@ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
* No more data to send out - expect to receive more data from
* the AS.
*/
- int res = eap_tls_process_input(sm, data, in_data, in_len,
- out_data);
+ int res = eap_tls_process_input(sm, data, in_data, out_data);
if (res) {
/*
* Input processing failed (res = -1) or more data is
@@ -719,12 +682,18 @@ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
if (tls_connection_get_failed(data->ssl_ctx, data->conn)) {
/* TLS processing has failed - return error */
wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to "
- "report error");
+ "report error (len=%u)",
+ (unsigned int) wpabuf_len(data->tls_out));
ret = -1;
/* TODO: clean pin if engine used? */
+ if (wpabuf_len(data->tls_out) == 0) {
+ wpabuf_free(data->tls_out);
+ data->tls_out = NULL;
+ return -1;
+ }
}
- if (data->tls_out == NULL || wpabuf_len(data->tls_out) == 0) {
+ if (wpabuf_len(data->tls_out) == 0) {
/*
* TLS negotiation should now be complete since all other cases
* needing more data should have been caught above based on
@@ -790,20 +759,24 @@ int eap_peer_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data)
int eap_peer_tls_status(struct eap_sm *sm, struct eap_ssl_data *data,
char *buf, size_t buflen, int verbose)
{
- char name[128];
+ char version[20], name[128];
int len = 0, ret;
- if (tls_get_cipher(data->ssl_ctx, data->conn, name, sizeof(name)) == 0)
- {
- ret = os_snprintf(buf + len, buflen - len,
- "EAP TLS cipher=%s\n"
- "tls_session_reused=%d\n",
- name, tls_connection_resumed(data->ssl_ctx,
- data->conn));
- if (os_snprintf_error(buflen - len, ret))
- return len;
- len += ret;
- }
+ if (tls_get_version(data->ssl_ctx, data->conn, version,
+ sizeof(version)) < 0)
+ version[0] = '\0';
+ if (tls_get_cipher(data->ssl_ctx, data->conn, name, sizeof(name)) < 0)
+ name[0] = '\0';
+
+ ret = os_snprintf(buf + len, buflen - len,
+ "eap_tls_version=%s\n"
+ "EAP TLS cipher=%s\n"
+ "tls_session_reused=%d\n",
+ version, name,
+ tls_connection_resumed(data->ssl_ctx, data->conn));
+ if (os_snprintf_error(buflen - len, ret))
+ return len;
+ len += ret;
return len;
}
@@ -1032,7 +1005,7 @@ int eap_peer_select_phase2_methods(struct eap_peer_config *config,
{
char *start, *pos, *buf;
struct eap_method_type *methods = NULL, *_methods;
- u8 method;
+ u32 method;
size_t num_methods = 0, prefix_len;
if (config == NULL || config->phase2 == NULL)