18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation. 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license. 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details. 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/tls.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_i.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_tls_common.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_config.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_tls_check_blob(struct eap_sm *sm, const char **name, 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 **data, size_t *data_len) 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_config_blob *blob; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*name == NULL || os_strncmp(*name, "blob://", 7) != 0) 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt blob = eap_get_config_blob(sm, *name + 7); 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (blob == NULL) { 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "%s: Named configuration blob '%s' not " 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "found", __func__, *name + 7); 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *name = NULL; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *data = blob->data; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *data_len = blob->len; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_tls_params_flags(struct tls_connection_params *params, 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *txt) 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (txt == NULL) 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(txt, "tls_allow_md5=1")) 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->flags |= TLS_CONN_ALLOW_SIGN_RSA_MD5; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(txt, "tls_disable_time_checks=1")) 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->flags |= TLS_CONN_DISABLE_TIME_CHECKS; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_tls_params_from_conf1(struct tls_connection_params *params, 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *config) 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ca_cert = (char *) config->ca_cert; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ca_path = (char *) config->ca_path; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->client_cert = (char *) config->client_cert; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->private_key = (char *) config->private_key; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->private_key_passwd = (char *) config->private_key_passwd; 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->dh_file = (char *) config->dh_file; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->subject_match = (char *) config->subject_match; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->altsubject_match = (char *) config->altsubject_match; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->engine = config->engine; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->engine_id = config->engine_id; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->pin = config->pin; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->key_id = config->key_id; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->cert_id = config->cert_id; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ca_cert_id = config->ca_cert_id; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_tls_params_flags(params, config->phase1); 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_tls_params_from_conf2(struct tls_connection_params *params, 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *config) 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ca_cert = (char *) config->ca_cert2; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ca_path = (char *) config->ca_path2; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->client_cert = (char *) config->client_cert2; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->private_key = (char *) config->private_key2; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->private_key_passwd = (char *) config->private_key2_passwd; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->dh_file = (char *) config->dh_file2; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->subject_match = (char *) config->subject_match2; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->altsubject_match = (char *) config->altsubject_match2; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->engine = config->engine2; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->engine_id = config->engine2_id; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->pin = config->pin2; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->key_id = config->key2_id; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->cert_id = config->cert2_id; 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ca_cert_id = config->ca_cert2_id; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_tls_params_flags(params, config->phase2); 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_tls_params_from_conf(struct eap_sm *sm, 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ssl_data *data, 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection_params *params, 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *config, int phase2) 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(params, 0, sizeof(*params)); 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (phase2) { 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLS: using phase2 config options"); 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_tls_params_from_conf2(params, config); 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLS: using phase1 config options"); 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_tls_params_from_conf1(params, config); 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->tls_ia = data->tls_ia; 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Use blob data, if available. Otherwise, leave reference to external 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * file as-is. 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_tls_check_blob(sm, ¶ms->ca_cert, ¶ms->ca_cert_blob, 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ¶ms->ca_cert_blob_len) || 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_tls_check_blob(sm, ¶ms->client_cert, 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ¶ms->client_cert_blob, 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ¶ms->client_cert_blob_len) || 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_tls_check_blob(sm, ¶ms->private_key, 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ¶ms->private_key_blob, 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ¶ms->private_key_blob_len) || 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_tls_check_blob(sm, ¶ms->dh_file, ¶ms->dh_blob, 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ¶ms->dh_blob_len)) { 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: Failed to get configuration blobs"); 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_tls_init_connection(struct eap_sm *sm, 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ssl_data *data, 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *config, 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection_params *params) 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->conn = tls_connection_init(sm->ssl_ctx); 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->conn == NULL) { 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS " 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "connection"); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = tls_connection_set_params(sm->ssl_ctx, data->conn, params); 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED) { 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * At this point with the pkcs11 engine the PIN might be wrong. 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * We reset the PIN in the configuration to be sure to not use 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it again and the calling function must request a new one. 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(config->pin); 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->pin = NULL; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (res == TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED) { 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Failed to load private key"); 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * We do not know exactly but maybe the PIN was wrong, 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * so ask for a new one. 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(config->pin); 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->pin = NULL; 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_request_pin(sm); 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ignore = TRUE; 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_connection_deinit(sm->ssl_ctx, data->conn); 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->conn = NULL; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (res) { 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Failed to set TLS connection " 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "parameters"); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_connection_deinit(sm->ssl_ctx, data->conn); 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->conn = NULL; 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_ssl_init - Initialize shared TLS functionality 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Pointer to the network configuration 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to initialize shared TLS functionality for EAP-TLS, 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-PEAP, EAP-TTLS, and EAP-FAST. 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *config) 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection_params params; 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config == NULL) 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap = sm; 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2 = sm->init_phase2; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_tls_params_from_conf(sm, data, ¶ms, config, data->phase2) < 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_tls_init_connection(sm, data, config, ¶ms) < 0) 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_out_limit = config->fragment_size; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2) { 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Limit the fragment size in the inner TLS authentication 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * since the outer authentication with EAP-PEAP does not yet 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * support fragmentation */ 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_out_limit > 100) 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_out_limit -= 100; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config->phase1 && 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strstr(config->phase1, "include_tls_length=1")) { 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLS: Include TLS Message Length in " 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unfragmented packets"); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->include_tls_length = 1; 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_ssl_deinit - Deinitialize shared TLS functionality 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function deinitializes shared TLS functionality that was initialized 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with eap_peer_tls_ssl_init(). 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_connection_deinit(sm->ssl_ctx, data->conn); 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_input(data); 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_output(data); 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_derive_key - Derive a key based on TLS session data 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @label: Label string for deriving the keys, e.g., "client EAP encryption" 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of the key material to generate (usually 64 for MSK) 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to allocated key on success or %NULL on failure 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function uses TLS-PRF to generate pseudo-random data based on the TLS 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * session data (client/server random and master key). Each key type may use a 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * different label to bind the key usage into the generated material. 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The caller is responsible for freeing the returned buffer. 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *label, size_t len) 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_keys keys; 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rnd = NULL, *out; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out = os_malloc(len); 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (out == NULL) 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* First, try to use TLS library function for PRF, if available. */ 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) == 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return out; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TLS library did not support key generation, so get the needed TLS 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * session parameters and use an internal implementation of TLS PRF to 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * derive the key. 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys.client_random == NULL || keys.server_random == NULL || 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys.master_key == NULL) 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rnd = os_malloc(keys.client_random_len + keys.server_random_len); 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rnd == NULL) 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(rnd, keys.client_random, keys.client_random_len); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(rnd + keys.client_random_len, keys.server_random, 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys.server_random_len); 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_prf(keys.master_key, keys.master_key_len, 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt label, rnd, keys.client_random_len + 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys.server_random_len, out, len)) 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rnd); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return out; 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(out); 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rnd); 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_reassemble_fragment - Reassemble a received fragment 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_data: Next incoming TLS segment 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, 1 if more data is needed for the full message, or 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * -1 on error 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data, 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data) 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t tls_in_len, in_len; 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_in_len = data->tls_in ? wpabuf_len(data->tls_in) : 0; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_len = in_data ? wpabuf_len(in_data) : 0; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_in_len + in_len == 0) { 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No message data received?! */ 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "SSL: Invalid reassembly state: " 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "tls_in_left=%lu tls_in_len=%lu in_len=%lu", 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) data->tls_in_left, 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) tls_in_len, 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) in_len); 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_input(data); 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_in_len + in_len > 65536) { 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Limit length to avoid rogue servers from causing large 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * memory allocations. 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size over " 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "64 kB)"); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_input(data); 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (in_len > data->tls_in_left) { 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Sender is doing something odd - reject message */ 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: more data than TLS message length " 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "indicated"); 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_input(data); 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_resize(&data->tls_in, in_len) < 0) { 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: Could not allocate memory for TLS " 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data"); 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_input(data); 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (in_data) 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(data->tls_in, in_data); 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_in_left -= in_len; 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_in_left > 0) { 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: Need %lu bytes more input " 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data", (unsigned long) data->tls_in_left); 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_data_reassemble - Reassemble TLS data 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_data: Next incoming TLS segment 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @need_more_input: Variable for returning whether more input data is needed 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to reassemble this TLS packet 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to output data, %NULL on error or when more data is needed 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for the full message (in which case, *need_more_input is also set to 1). 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function reassembles TLS fragments. Caller must not free the returned 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * data buffer since an internal pointer to it is maintained. 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const struct wpabuf * eap_peer_tls_data_reassemble( 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ssl_data *data, const struct wpabuf *in_data, 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int *need_more_input) 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *need_more_input = 0; 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_in_left > wpabuf_len(in_data) || data->tls_in) { 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Message has fragments */ 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res = eap_peer_tls_reassemble_fragment(data, in_data); 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) { 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == 1) 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *need_more_input = 1; 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Message is now fully reassembled. */ 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No fragments in this message, so just make a copy of it. */ 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_in_left = 0; 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_in = wpabuf_dup(in_data); 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_in == NULL) 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->tls_in; 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_tls_process_input - Process incoming TLS message 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_data: Message received from the server 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_len: Length of in_data 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @out_data: Buffer for returning a pointer to application data (if available) 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, 1 if more input data is needed, 2 if application data 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * is available, -1 on failure 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data, 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *in_data, size_t in_len, 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **out_data) 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *msg; 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int need_more_input; 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *appl_data; 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf buf; 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&buf, in_data, in_len); 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_peer_tls_data_reassemble(data, &buf, &need_more_input); 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return need_more_input ? 1 : -1; 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Full TLS message reassembled - continue handshake processing */ 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_out) { 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* This should not happen.. */ 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: eap_tls_process_input - pending " 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "tls_out data even though tls_out_len = 0"); 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->tls_out); 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_ASSERT(data->tls_out == NULL); 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt appl_data = NULL; 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_out = tls_connection_handshake(sm->ssl_ctx, data->conn, 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg, &appl_data); 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_input(data); 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (appl_data && 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_connection_established(sm->ssl_ctx, data->conn) && 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !tls_connection_get_failed(sm->ssl_ctx, data->conn)) { 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application data", 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt appl_data); 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *out_data = appl_data; 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 2; 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(appl_data); 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_tls_process_output - Process outgoing TLS message 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peap_version: Version number for EAP-PEAP/TTLS 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @id: EAP identifier for the response 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ret: Return value to use on success 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @out_data: Buffer for returning the allocated output buffer 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: ret (0 or 1) on success, -1 on failure 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type, 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int peap_version, u8 id, int ret, 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **out_data) 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *flags; 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int more_fragments, length_included; 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_out == NULL) 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = wpabuf_len(data->tls_out) - data->tls_out_pos; 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total " 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%lu bytes)", 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(data->tls_out)); 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Limit outgoing message to the configured maximum size. Fragment 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * message if needed. 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len > data->tls_out_limit) { 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt more_fragments = 1; 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = data->tls_out_limit; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments " 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "will follow", (unsigned long) len); 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt more_fragments = 0; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt length_included = data->tls_out_pos == 0 && 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (wpabuf_len(data->tls_out) > data->tls_out_limit || 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->include_tls_length); 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!length_included && 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_type == EAP_TYPE_PEAP && peap_version == 0 && 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !tls_connection_established(data->eap->ssl_ctx, data->conn)) { 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Windows Server 2008 NPS really wants to have the TLS Message 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * length included in phase 0 even for unfragmented frames or 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it will get very confused with Compound MAC calculation and 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Outer TLVs. 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt length_included = 1; 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *out_data = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1 + length_included * 4 + len, 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, id); 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*out_data == NULL) 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags = wpabuf_put(*out_data, 1); 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *flags = peap_version; 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (more_fragments) 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS; 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (length_included) { 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED; 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be32(*out_data, wpabuf_len(data->tls_out)); 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(*out_data, 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head_u8(data->tls_out) + data->tls_out_pos, 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len); 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_out_pos += len; 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!more_fragments) 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_output(data); 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_process_helper - Process TLS handshake message 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peap_version: Version number for EAP-PEAP/TTLS 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @id: EAP identifier for the response 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_data: Message received from the server 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_len: Length of in_data 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @out_data: Buffer for returning a pointer to the response message 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, 1 if more input data is needed, 2 if application data 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * is available, or -1 on failure 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to process TLS handshake messages. It reassembles 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the received fragments and uses a TLS library to process the messages. The 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * response data from the TLS library is fragmented to suitable output messages 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * that the caller can send out. 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * out_data is used to return the response message if the return value of this 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * function is 0, 2, or -1. In case of failure, the message is likely a TLS 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * alarm message. The caller is responsible for freeing the allocated buffer if 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * *out_data is not %NULL. 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called for each received TLS message during the TLS 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handshake after eap_peer_tls_process_init() call and possible processing of 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TLS Flags field. Once the handshake has been completed, i.e., when 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tls_connection_established() returns 1, EAP method specific decrypting of 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the tunneled data is used. 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EapType eap_type, int peap_version, 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id, const u8 *in_data, size_t in_len, 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **out_data) 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *out_data = NULL; 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_out && wpabuf_len(data->tls_out) > 0 && in_len > 0) { 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: Received non-ACK when output " 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "fragments are waiting to be sent out"); 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_out == NULL || wpabuf_len(data->tls_out) == 0) { 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * No more data to send out - expect to receive more data from 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the AS. 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res = eap_tls_process_input(sm, data, in_data, in_len, 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out_data); 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) { 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Input processing failed (res = -1) or more data is 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * needed (res = 1). 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The incoming message has been reassembled and processed. The 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * response was allocated into data->tls_out buffer. 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_out == NULL) { 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * No outgoing fragments remaining from the previous message 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * and no new message generated. This indicates an error in TLS 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * processing. 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_output(data); 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) { 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TLS processing has failed - return error */ 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to " 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "report error"); 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: clean pin if engine used? */ 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_out == NULL || wpabuf_len(data->tls_out) == 0) { 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TLS negotiation should now be complete since all other cases 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * needing more data should have been caught above based on 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the TLS Message Length field. 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: No data to be sent out"); 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->tls_out); 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_out = NULL; 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Send the pending message (in fragments, if needed). */ 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_tls_process_output(data, eap_type, peap_version, id, ret, 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out_data); 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_build_ack - Build a TLS ACK frame 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @id: EAP identifier for the response 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peap_version: Version number for EAP-PEAP/TTLS 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the allocated ACK frame or %NULL on failure 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * eap_peer_tls_build_ack(u8 id, EapType eap_type, 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int peap_version) 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, 1, EAP_CODE_RESPONSE, 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id); 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: Building ACK (type=%d id=%d ver=%d)", 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) eap_type, id, peap_version); 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(resp, peap_version); /* Flags */ 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_reauth_init - Re-initialize shared TLS for session resumption 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data) 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_input(data); 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_output(data); 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tls_connection_shutdown(sm->ssl_ctx, data->conn); 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_status - Get TLS status 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for status information 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buflen: Maximum buffer length 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @verbose: Whether to include verbose status information 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of bytes written to buf. 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_tls_status(struct eap_sm *sm, struct eap_ssl_data *data, 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf, size_t buflen, int verbose) 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char name[128]; 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len = 0, ret; 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_get_cipher(sm->ssl_ctx, data->conn, name, sizeof(name)) == 0) { 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP TLS cipher=%s\n", name); 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_process_init - Initial validation/processing of EAP requests 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ret: Return values from EAP request validation and processing 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @reqData: EAP request to be processed (eapReqData) 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Buffer for returning length of the remaining payload 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @flags: Buffer for returning TLS flags 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to payload after TLS flags and length or %NULL on failure 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function validates the EAP header and processes the optional TLS 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Message Length field. If this is the first fragment of a TLS message, the 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TLS reassembly code is initialized to receive the indicated number of bytes. 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-TLS, EAP-PEAP, EAP-TTLS, and EAP-FAST methods are expected to use this 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * function as the first step in processing received messages. They will need 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to process the flags (apart from Message Length Included) that are returned 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * through the flags pointer and the message payload that will be returned (and 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the length is returned through the len pointer). Return values (ret) are set 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for continuation of EAP method processing. The caller is responsible for 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * setting these to indicate completion (either success or failure) based on 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the authentication result. 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * eap_peer_tls_process_init(struct eap_sm *sm, 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ssl_data *data, 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EapType eap_type, 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData, 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t *len, u8 *flags) 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left; 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int tls_msg_len; 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_get_errors(sm->ssl_ctx)) { 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: TLS errors detected"); 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, reqData, &left); 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) { 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left == 0) { 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: Invalid TLS message: no Flags " 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "octet included"); 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->workaround) { 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: Workaround - assume no Flags " 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "indicates ACK frame"); 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *flags = 0; 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *flags = *pos++; 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left--; 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - " 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Flags 0x%02x", (unsigned long) wpabuf_len(reqData), 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *flags); 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left < 4) { 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: Short frame with TLS " 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "length"); 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_msg_len = WPA_GET_BE32(pos); 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d", 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_msg_len); 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_in_left == 0) { 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_in_total = tls_msg_len; 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_in_left = tls_msg_len; 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->tls_in); 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_in = NULL; 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 4; 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = FALSE; 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = TRUE; 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = left; 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_reset_input - Reset input buffers 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function frees any allocated memory for input buffers and resets input 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * state. 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_peer_tls_reset_input(struct eap_ssl_data *data) 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_in_left = data->tls_in_total = 0; 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->tls_in); 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_in = NULL; 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_reset_output - Reset output buffers 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function frees any allocated memory for output buffers and resets 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * output state. 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_peer_tls_reset_output(struct eap_ssl_data *data) 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_out_pos = 0; 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->tls_out); 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_out = NULL; 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_decrypt - Decrypt received phase 2 TLS message 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_data: Message received from the server 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_decrypted: Buffer for returning a pointer to the decrypted message 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, 1 if more input data is needed, or -1 on failure 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_tls_decrypt(struct eap_sm *sm, struct eap_ssl_data *data, 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data, 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **in_decrypted) 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *msg; 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int need_more_input; 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_peer_tls_data_reassemble(data, in_data, &need_more_input); 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return need_more_input ? 1 : -1; 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->conn, msg); 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_input(data); 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*in_decrypted == NULL) { 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: Failed to decrypt Phase 2 data"); 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_encrypt - Encrypt phase 2 TLS message 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peap_version: Version number for EAP-PEAP/TTLS 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @id: EAP identifier for the response 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_data: Plaintext phase 2 data to encrypt or %NULL to continue fragments 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @out_data: Buffer for returning a pointer to the encrypted response message 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_tls_encrypt(struct eap_sm *sm, struct eap_ssl_data *data, 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EapType eap_type, int peap_version, u8 id, 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data, 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **out_data) 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (in_data) { 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_output(data); 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_out = tls_connection_encrypt(sm->ssl_ctx, data->conn, 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_data); 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_out == NULL) { 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 " 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data (in_len=%lu)", 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(in_data)); 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_output(data); 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_tls_process_output(data, eap_type, peap_version, id, 0, 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out_data); 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_select_phase2_methods - Select phase 2 EAP method 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Pointer to the network configuration 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @prefix: 'phase2' configuration prefix, e.g., "auth=" 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @types: Buffer for returning allocated list of allowed EAP methods 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @num_types: Buffer for returning number of allocated EAP methods 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to parse EAP method list and select allowed methods 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for Phase2 authentication. 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_select_phase2_methods(struct eap_peer_config *config, 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *prefix, 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_type **types, 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t *num_types) 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *start, *pos, *buf; 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_type *methods = NULL, *_methods; 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 method; 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t num_methods = 0, prefix_len; 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config == NULL || config->phase2 == NULL) 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto get_defaults; 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start = buf = os_strdup(config->phase2); 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prefix_len = os_strlen(prefix); 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (start && *start != '\0') { 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int vendor; 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strstr(start, prefix); 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (start != pos && *(pos - 1) != ' ') { 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start = pos + prefix_len; 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start = pos + prefix_len; 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strchr(start, ' '); 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos) 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = '\0'; 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt method = eap_get_phase2_type(start, &vendor); 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE) { 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "TLS: Unsupported Phase2 EAP " 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "method '%s'", start); 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_methods++; 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _methods = os_realloc(methods, 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_methods * sizeof(*methods)); 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (_methods == NULL) { 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(methods); 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods = _methods; 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods[num_methods - 1].vendor = vendor; 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods[num_methods - 1].method = method; 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start = pos; 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtget_defaults: 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (methods == NULL) 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods = eap_get_phase2_types(config, &num_methods); 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (methods == NULL) { 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "TLS: No Phase2 EAP methods available"); 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TLS: Phase2 EAP types", 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) methods, 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_methods * sizeof(struct eap_method_type)); 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *types = methods; 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *num_types = num_methods; 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_phase2_nak - Generate EAP-Nak for Phase 2 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @types: Buffer for returning allocated list of allowed EAP methods 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @num_types: Buffer for returning number of allocated EAP methods 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @hdr: EAP-Request header (and the following EAP type octet) 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @resp: Buffer for returning the EAP-Nak message 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_tls_phase2_nak(struct eap_method_type *types, size_t num_types, 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *hdr, struct wpabuf **resp) 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos = (u8 *) (hdr + 1); 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: add support for expanded Nak */ 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLS: Phase 2 Request: Nak type=%d", *pos); 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TLS: Allowed Phase2 EAP types", 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) types, num_types * sizeof(struct eap_method_type)); 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NAK, num_types, 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, hdr->identifier); 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*resp == NULL) 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < num_types; i++) { 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (types[i].vendor == EAP_VENDOR_IETF && 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt types[i].method < 256) 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(*resp, types[i].method); 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_update_len(*resp); 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1022