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