18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions 334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt * Copyright (c) 2004-2013, 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 1961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic struct wpabuf * eap_tls_msg_alloc(EapType type, size_t payload_len, 2061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 code, u8 identifier) 2161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{ 2261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (type == EAP_UNAUTH_TLS_TYPE) 2361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return eap_msg_alloc(EAP_VENDOR_UNAUTH_TLS, 2461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt EAP_VENDOR_TYPE_UNAUTH_TLS, payload_len, 2561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt code, identifier); 26f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (type == EAP_WFA_UNAUTH_TLS_TYPE) 27f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return eap_msg_alloc(EAP_VENDOR_WFA_NEW, 28f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt EAP_VENDOR_WFA_UNAUTH_TLS, payload_len, 29f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt code, identifier); 3061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return eap_msg_alloc(EAP_VENDOR_IETF, type, payload_len, code, 3161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt identifier); 3261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 3361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 3461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_tls_check_blob(struct eap_sm *sm, const char **name, 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 **data, size_t *data_len) 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_config_blob *blob; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*name == NULL || os_strncmp(*name, "blob://", 7) != 0) 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt blob = eap_get_config_blob(sm, *name + 7); 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (blob == NULL) { 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "%s: Named configuration blob '%s' not " 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "found", __func__, *name + 7); 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *name = NULL; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *data = blob->data; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *data_len = blob->len; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_tls_params_flags(struct tls_connection_params *params, 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *txt) 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (txt == NULL) 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(txt, "tls_allow_md5=1")) 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->flags |= TLS_CONN_ALLOW_SIGN_RSA_MD5; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(txt, "tls_disable_time_checks=1")) 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->flags |= TLS_CONN_DISABLE_TIME_CHECKS; 6761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (os_strstr(txt, "tls_disable_session_ticket=1")) 6861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt params->flags |= TLS_CONN_DISABLE_SESSION_TICKET; 6961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (os_strstr(txt, "tls_disable_session_ticket=0")) 7061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt params->flags &= ~TLS_CONN_DISABLE_SESSION_TICKET; 7113ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt if (os_strstr(txt, "tls_disable_tlsv1_1=1")) 7213ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt params->flags |= TLS_CONN_DISABLE_TLSv1_1; 7313ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt if (os_strstr(txt, "tls_disable_tlsv1_1=0")) 7413ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt params->flags &= ~TLS_CONN_DISABLE_TLSv1_1; 7513ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt if (os_strstr(txt, "tls_disable_tlsv1_2=1")) 7613ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt params->flags |= TLS_CONN_DISABLE_TLSv1_2; 7713ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt if (os_strstr(txt, "tls_disable_tlsv1_2=0")) 7813ca8d8ea51a1aa5e24c6c956473a11b0c7daed4Dmitry Shmidt params->flags &= ~TLS_CONN_DISABLE_TLSv1_2; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_tls_params_from_conf1(struct tls_connection_params *params, 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *config) 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ca_cert = (char *) config->ca_cert; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ca_path = (char *) config->ca_path; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->client_cert = (char *) config->client_cert; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->private_key = (char *) config->private_key; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->private_key_passwd = (char *) config->private_key_passwd; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->dh_file = (char *) config->dh_file; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->subject_match = (char *) config->subject_match; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->altsubject_match = (char *) config->altsubject_match; 93051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt params->suffix_match = config->domain_suffix_match; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->engine = config->engine; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->engine_id = config->engine_id; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->pin = config->pin; 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->key_id = config->key_id; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->cert_id = config->cert_id; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ca_cert_id = config->ca_cert_id; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_tls_params_flags(params, config->phase1); 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_tls_params_from_conf2(struct tls_connection_params *params, 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *config) 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ca_cert = (char *) config->ca_cert2; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ca_path = (char *) config->ca_path2; 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->client_cert = (char *) config->client_cert2; 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->private_key = (char *) config->private_key2; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->private_key_passwd = (char *) config->private_key2_passwd; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->dh_file = (char *) config->dh_file2; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->subject_match = (char *) config->subject_match2; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->altsubject_match = (char *) config->altsubject_match2; 115051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt params->suffix_match = config->domain_suffix_match2; 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->engine = config->engine2; 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->engine_id = config->engine2_id; 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->pin = config->pin2; 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->key_id = config->key2_id; 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->cert_id = config->cert2_id; 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ca_cert_id = config->ca_cert2_id; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_tls_params_flags(params, config->phase2); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_tls_params_from_conf(struct eap_sm *sm, 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ssl_data *data, 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection_params *params, 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *config, int phase2) 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(params, 0, sizeof(*params)); 13261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (sm->workaround && data->eap_type != EAP_TYPE_FAST) { 13361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 13461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Some deployed authentication servers seem to be unable to 13561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * handle the TLS Session Ticket extension (they are supposed 13661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * to ignore unrecognized TLS extensions, but end up rejecting 13761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * the ClientHello instead). As a workaround, disable use of 13861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * TLS Sesson Ticket extension for EAP-TLS, EAP-PEAP, and 13961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * EAP-TTLS (EAP-FAST uses session ticket, so any server that 14061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * supports EAP-FAST does not need this workaround). 14161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 14261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt params->flags |= TLS_CONN_DISABLE_SESSION_TICKET; 14361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (phase2) { 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLS: using phase2 config options"); 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_tls_params_from_conf2(params, config); 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLS: using phase1 config options"); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_tls_params_from_conf1(params, config); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Use blob data, if available. Otherwise, leave reference to external 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * file as-is. 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_tls_check_blob(sm, ¶ms->ca_cert, ¶ms->ca_cert_blob, 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ¶ms->ca_cert_blob_len) || 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_tls_check_blob(sm, ¶ms->client_cert, 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ¶ms->client_cert_blob, 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ¶ms->client_cert_blob_len) || 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_tls_check_blob(sm, ¶ms->private_key, 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ¶ms->private_key_blob, 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ¶ms->private_key_blob_len) || 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_tls_check_blob(sm, ¶ms->dh_file, ¶ms->dh_blob, 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ¶ms->dh_blob_len)) { 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: Failed to get configuration blobs"); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_tls_init_connection(struct eap_sm *sm, 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ssl_data *data, 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *config, 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection_params *params) 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (config->ocsp) 18234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt params->flags |= TLS_CONN_REQUEST_OCSP; 18334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (config->ocsp == 2) 18434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt params->flags |= TLS_CONN_REQUIRE_OCSP; 18504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data->conn = tls_connection_init(data->ssl_ctx); 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->conn == NULL) { 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS " 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "connection"); 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt res = tls_connection_set_params(data->ssl_ctx, data->conn, params); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED) { 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * At this point with the pkcs11 engine the PIN might be wrong. 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * We reset the PIN in the configuration to be sure to not use 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it again and the calling function must request a new one. 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(config->pin); 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->pin = NULL; 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (res == TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED) { 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Failed to load private key"); 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * We do not know exactly but maybe the PIN was wrong, 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * so ask for a new one. 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(config->pin); 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->pin = NULL; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_request_pin(sm); 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->ignore = TRUE; 21104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt tls_connection_deinit(data->ssl_ctx, data->conn); 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->conn = NULL; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (res) { 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Failed to set TLS connection " 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "parameters"); 21704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt tls_connection_deinit(data->ssl_ctx, data->conn); 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->conn = NULL; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_ssl_init - Initialize shared TLS functionality 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Pointer to the network configuration 23161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * @eap_type: EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST) 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to initialize shared TLS functionality for EAP-TLS, 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-PEAP, EAP-TTLS, and EAP-FAST. 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, 23861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct eap_peer_config *config, u8 eap_type) 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection_params params; 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config == NULL) 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap = sm; 24661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt data->eap_type = eap_type; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2 = sm->init_phase2; 24804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 : 24904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sm->ssl_ctx; 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_tls_params_from_conf(sm, data, ¶ms, config, data->phase2) < 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_tls_init_connection(sm, data, config, ¶ms) < 0) 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_out_limit = config->fragment_size; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->phase2) { 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Limit the fragment size in the inner TLS authentication 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * since the outer authentication with EAP-PEAP does not yet 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * support fragmentation */ 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_out_limit > 100) 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_out_limit -= 100; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config->phase1 && 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strstr(config->phase1, "include_tls_length=1")) { 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLS: Include TLS Message Length in " 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unfragmented packets"); 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->include_tls_length = 1; 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_ssl_deinit - Deinitialize shared TLS functionality 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function deinitializes shared TLS functionality that was initialized 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with eap_peer_tls_ssl_init(). 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 28704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt tls_connection_deinit(data->ssl_ctx, data->conn); 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_input(data); 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_output(data); 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_derive_key - Derive a key based on TLS session data 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @label: Label string for deriving the keys, e.g., "client EAP encryption" 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of the key material to generate (usually 64 for MSK) 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to allocated key on success or %NULL on failure 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function uses TLS-PRF to generate pseudo-random data based on the TLS 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * session data (client/server random and master key). Each key type may use a 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * different label to bind the key usage into the generated material. 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The caller is responsible for freeing the returned buffer. 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *label, size_t len) 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 31061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifndef CONFIG_FIPS 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_keys keys; 31261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_FIPS */ 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rnd = NULL, *out; 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out = os_malloc(len); 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (out == NULL) 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* First, try to use TLS library function for PRF, if available. */ 32004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, out, len) 32104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt == 0) 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return out; 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifndef CONFIG_FIPS 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TLS library did not support key generation, so get the needed TLS 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * session parameters and use an internal implementation of TLS PRF to 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * derive the key. 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 33004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (tls_connection_get_keys(data->ssl_ctx, data->conn, &keys)) 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keys.client_random == NULL || keys.server_random == NULL || 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys.master_key == NULL) 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rnd = os_malloc(keys.client_random_len + keys.server_random_len); 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rnd == NULL) 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(rnd, keys.client_random, keys.client_random_len); 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(rnd + keys.client_random_len, keys.server_random, 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys.server_random_len); 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len, 3451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt label, rnd, keys.client_random_len + 3461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt keys.server_random_len, out, len)) 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rnd); 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return out; 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 35361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_FIPS */ 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(out); 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rnd); 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 361f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * eap_peer_tls_derive_session_id - Derive a Session-Id based on TLS data 362f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 363f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * @data: Data for TLS processing 364f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * @eap_type: EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST) 365f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * @len: Pointer to length of the session ID generated 366f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * Returns: Pointer to allocated Session-Id on success or %NULL on failure 367f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * 368f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * This function derive the Session-Id based on the TLS session data 369f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * (client/server random and method type). 370f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * 371f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * The caller is responsible for freeing the returned buffer. 372f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt */ 373f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtu8 * eap_peer_tls_derive_session_id(struct eap_sm *sm, 374f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct eap_ssl_data *data, u8 eap_type, 375f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt size_t *len) 376f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt{ 377f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct tls_keys keys; 378f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt u8 *out; 379f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 380f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt /* 381f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * TLS library did not support session ID generation, 382f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * so get the needed TLS session parameters 383f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt */ 384f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) 385f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return NULL; 386f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 387f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (keys.client_random == NULL || keys.server_random == NULL || 388f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt keys.master_key == NULL) 389f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return NULL; 390f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 391f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt *len = 1 + keys.client_random_len + keys.server_random_len; 392f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt out = os_malloc(*len); 393f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (out == NULL) 394f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return NULL; 395f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 396f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt /* Session-Id = EAP type || client.random || server.random */ 397f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt out[0] = eap_type; 398f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_memcpy(out + 1, keys.client_random, keys.client_random_len); 399f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_memcpy(out + 1 + keys.client_random_len, keys.server_random, 400f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt keys.server_random_len); 401f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 402f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return out; 403f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt} 404f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 405f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 406f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt/** 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_reassemble_fragment - Reassemble a received fragment 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_data: Next incoming TLS segment 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, 1 if more data is needed for the full message, or 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * -1 on error 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data, 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data) 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t tls_in_len, in_len; 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_in_len = data->tls_in ? wpabuf_len(data->tls_in) : 0; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_len = in_data ? wpabuf_len(in_data) : 0; 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_in_len + in_len == 0) { 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No message data received?! */ 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "SSL: Invalid reassembly state: " 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "tls_in_left=%lu tls_in_len=%lu in_len=%lu", 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) data->tls_in_left, 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) tls_in_len, 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) in_len); 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_input(data); 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_in_len + in_len > 65536) { 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Limit length to avoid rogue servers from causing large 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * memory allocations. 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size over " 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "64 kB)"); 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_input(data); 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (in_len > data->tls_in_left) { 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Sender is doing something odd - reject message */ 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: more data than TLS message length " 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "indicated"); 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_input(data); 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_resize(&data->tls_in, in_len) < 0) { 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: Could not allocate memory for TLS " 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data"); 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_input(data); 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (in_data) 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(data->tls_in, in_data); 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_in_left -= in_len; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_in_left > 0) { 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: Need %lu bytes more input " 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data", (unsigned long) data->tls_in_left); 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_data_reassemble - Reassemble TLS data 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_data: Next incoming TLS segment 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @need_more_input: Variable for returning whether more input data is needed 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to reassemble this TLS packet 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to output data, %NULL on error or when more data is needed 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for the full message (in which case, *need_more_input is also set to 1). 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function reassembles TLS fragments. Caller must not free the returned 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * data buffer since an internal pointer to it is maintained. 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const struct wpabuf * eap_peer_tls_data_reassemble( 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ssl_data *data, const struct wpabuf *in_data, 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int *need_more_input) 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *need_more_input = 0; 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_in_left > wpabuf_len(in_data) || data->tls_in) { 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Message has fragments */ 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res = eap_peer_tls_reassemble_fragment(data, in_data); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) { 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == 1) 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *need_more_input = 1; 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Message is now fully reassembled. */ 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No fragments in this message, so just make a copy of it. */ 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_in_left = 0; 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_in = wpabuf_dup(in_data); 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_in == NULL) 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->tls_in; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_tls_process_input - Process incoming TLS message 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_data: Message received from the server 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_len: Length of in_data 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @out_data: Buffer for returning a pointer to application data (if available) 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, 1 if more input data is needed, 2 if application data 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * is available, -1 on failure 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data, 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *in_data, size_t in_len, 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **out_data) 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *msg; 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int need_more_input; 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *appl_data; 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf buf; 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&buf, in_data, in_len); 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_peer_tls_data_reassemble(data, &buf, &need_more_input); 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return need_more_input ? 1 : -1; 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Full TLS message reassembled - continue handshake processing */ 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_out) { 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* This should not happen.. */ 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: eap_tls_process_input - pending " 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "tls_out data even though tls_out_len = 0"); 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->tls_out); 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_ASSERT(data->tls_out == NULL); 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt appl_data = NULL; 54404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data->tls_out = tls_connection_handshake(data->ssl_ctx, data->conn, 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg, &appl_data); 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_input(data); 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (appl_data && 55004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt tls_connection_established(data->ssl_ctx, data->conn) && 55104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt !tls_connection_get_failed(data->ssl_ctx, data->conn)) { 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application data", 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt appl_data); 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *out_data = appl_data; 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 2; 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(appl_data); 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_tls_process_output - Process outgoing TLS message 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peap_version: Version number for EAP-PEAP/TTLS 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @id: EAP identifier for the response 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ret: Return value to use on success 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @out_data: Buffer for returning the allocated output buffer 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: ret (0 or 1) on success, -1 on failure 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type, 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int peap_version, u8 id, int ret, 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **out_data) 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *flags; 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int more_fragments, length_included; 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_out == NULL) 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = wpabuf_len(data->tls_out) - data->tls_out_pos; 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total " 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%lu bytes)", 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(data->tls_out)); 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Limit outgoing message to the configured maximum size. Fragment 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * message if needed. 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len > data->tls_out_limit) { 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt more_fragments = 1; 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = data->tls_out_limit; 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments " 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "will follow", (unsigned long) len); 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt more_fragments = 0; 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt length_included = data->tls_out_pos == 0 && 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (wpabuf_len(data->tls_out) > data->tls_out_limit || 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->include_tls_length); 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!length_included && 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_type == EAP_TYPE_PEAP && peap_version == 0 && 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !tls_connection_established(data->eap->ssl_ctx, data->conn)) { 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Windows Server 2008 NPS really wants to have the TLS Message 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * length included in phase 0 even for unfragmented frames or 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it will get very confused with Compound MAC calculation and 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Outer TLVs. 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt length_included = 1; 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt *out_data = eap_tls_msg_alloc(eap_type, 1 + length_included * 4 + len, 61861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt EAP_CODE_RESPONSE, id); 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*out_data == NULL) 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags = wpabuf_put(*out_data, 1); 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *flags = peap_version; 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (more_fragments) 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS; 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (length_included) { 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED; 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be32(*out_data, wpabuf_len(data->tls_out)); 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(*out_data, 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head_u8(data->tls_out) + data->tls_out_pos, 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len); 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_out_pos += len; 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!more_fragments) 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_output(data); 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_process_helper - Process TLS handshake message 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peap_version: Version number for EAP-PEAP/TTLS 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @id: EAP identifier for the response 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_data: Message received from the server 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_len: Length of in_data 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @out_data: Buffer for returning a pointer to the response message 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, 1 if more input data is needed, 2 if application data 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * is available, or -1 on failure 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to process TLS handshake messages. It reassembles 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the received fragments and uses a TLS library to process the messages. The 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * response data from the TLS library is fragmented to suitable output messages 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * that the caller can send out. 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * out_data is used to return the response message if the return value of this 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * function is 0, 2, or -1. In case of failure, the message is likely a TLS 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * alarm message. The caller is responsible for freeing the allocated buffer if 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * *out_data is not %NULL. 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called for each received TLS message during the TLS 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handshake after eap_peer_tls_process_init() call and possible processing of 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TLS Flags field. Once the handshake has been completed, i.e., when 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tls_connection_established() returns 1, EAP method specific decrypting of 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the tunneled data is used. 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EapType eap_type, int peap_version, 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id, const u8 *in_data, size_t in_len, 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **out_data) 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *out_data = NULL; 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_out && wpabuf_len(data->tls_out) > 0 && in_len > 0) { 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: Received non-ACK when output " 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "fragments are waiting to be sent out"); 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_out == NULL || wpabuf_len(data->tls_out) == 0) { 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * No more data to send out - expect to receive more data from 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the AS. 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res = eap_tls_process_input(sm, data, in_data, in_len, 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out_data); 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) { 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Input processing failed (res = -1) or more data is 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * needed (res = 1). 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The incoming message has been reassembled and processed. The 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * response was allocated into data->tls_out buffer. 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_out == NULL) { 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * No outgoing fragments remaining from the previous message 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * and no new message generated. This indicates an error in TLS 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * processing. 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_output(data); 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 71804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (tls_connection_get_failed(data->ssl_ctx, data->conn)) { 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TLS processing has failed - return error */ 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to " 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "report error"); 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: clean pin if engine used? */ 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_out == NULL || wpabuf_len(data->tls_out) == 0) { 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TLS negotiation should now be complete since all other cases 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * needing more data should have been caught above based on 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the TLS Message Length field. 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: No data to be sent out"); 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->tls_out); 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_out = NULL; 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Send the pending message (in fragments, if needed). */ 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_tls_process_output(data, eap_type, peap_version, id, ret, 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out_data); 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_build_ack - Build a TLS ACK frame 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @id: EAP identifier for the response 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peap_version: Version number for EAP-PEAP/TTLS 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the allocated ACK frame or %NULL on failure 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * eap_peer_tls_build_ack(u8 id, EapType eap_type, 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int peap_version) 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 75661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt resp = eap_tls_msg_alloc(eap_type, 1, EAP_CODE_RESPONSE, id); 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: Building ACK (type=%d id=%d ver=%d)", 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) eap_type, id, peap_version); 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(resp, peap_version); /* Flags */ 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_reauth_init - Re-initialize shared TLS for session resumption 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data) 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_input(data); 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_output(data); 77604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return tls_connection_shutdown(data->ssl_ctx, data->conn); 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_status - Get TLS status 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for status information 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buflen: Maximum buffer length 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @verbose: Whether to include verbose status information 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of bytes written to buf. 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_tls_status(struct eap_sm *sm, struct eap_ssl_data *data, 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf, size_t buflen, int verbose) 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char name[128]; 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len = 0, ret; 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 79504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (tls_get_cipher(data->ssl_ctx, data->conn, name, sizeof(name)) == 0) 79604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt { 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf + len, buflen - len, 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP TLS cipher=%s\n", name); 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (size_t) ret >= buflen - len) 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += ret; 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_process_init - Initial validation/processing of EAP requests 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ret: Return values from EAP request validation and processing 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @reqData: EAP request to be processed (eapReqData) 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Buffer for returning length of the remaining payload 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @flags: Buffer for returning TLS flags 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to payload after TLS flags and length or %NULL on failure 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function validates the EAP header and processes the optional TLS 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Message Length field. If this is the first fragment of a TLS message, the 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TLS reassembly code is initialized to receive the indicated number of bytes. 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-TLS, EAP-PEAP, EAP-TTLS, and EAP-FAST methods are expected to use this 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * function as the first step in processing received messages. They will need 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to process the flags (apart from Message Length Included) that are returned 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * through the flags pointer and the message payload that will be returned (and 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the length is returned through the len pointer). Return values (ret) are set 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for continuation of EAP method processing. The caller is responsible for 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * setting these to indicate completion (either success or failure) based on 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the authentication result. 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst u8 * eap_peer_tls_process_init(struct eap_sm *sm, 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_ssl_data *data, 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EapType eap_type, 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData, 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t *len, u8 *flags) 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left; 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int tls_msg_len; 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 84304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (tls_get_errors(data->ssl_ctx)) { 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: TLS errors detected"); 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 84961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (eap_type == EAP_UNAUTH_TLS_TYPE) 85061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS, 85161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt EAP_VENDOR_TYPE_UNAUTH_TLS, reqData, 85261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt &left); 853f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt else if (eap_type == EAP_WFA_UNAUTH_TLS_TYPE) 854f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_WFA_NEW, 855f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt EAP_VENDOR_WFA_UNAUTH_TLS, reqData, 856f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt &left); 85761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt else 85861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, reqData, 85961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt &left); 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) { 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left == 0) { 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: Invalid TLS message: no Flags " 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "octet included"); 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->workaround) { 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: Workaround - assume no Flags " 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "indicates ACK frame"); 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *flags = 0; 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *flags = *pos++; 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left--; 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - " 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Flags 0x%02x", (unsigned long) wpabuf_len(reqData), 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *flags); 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left < 4) { 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: Short frame with TLS " 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "length"); 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_msg_len = WPA_GET_BE32(pos); 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d", 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_msg_len); 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_in_left == 0) { 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_in_total = tls_msg_len; 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_in_left = tls_msg_len; 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->tls_in); 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_in = NULL; 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 4; 900d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 901d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (left > tls_msg_len) { 902d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_printf(MSG_INFO, "SSL: TLS Message Length (%d " 903d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt "bytes) smaller than this fragment (%d " 904d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt "bytes)", (int) tls_msg_len, (int) left); 905d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt ret->ignore = TRUE; 906d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return NULL; 907d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = FALSE; 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = TRUE; 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = left; 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_reset_input - Reset input buffers 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function frees any allocated memory for input buffers and resets input 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * state. 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_peer_tls_reset_input(struct eap_ssl_data *data) 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_in_left = data->tls_in_total = 0; 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->tls_in); 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_in = NULL; 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_reset_output - Reset output buffers 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function frees any allocated memory for output buffers and resets 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * output state. 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_peer_tls_reset_output(struct eap_ssl_data *data) 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_out_pos = 0; 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->tls_out); 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tls_out = NULL; 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_decrypt - Decrypt received phase 2 TLS message 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_data: Message received from the server 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_decrypted: Buffer for returning a pointer to the decrypted message 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, 1 if more input data is needed, or -1 on failure 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_tls_decrypt(struct eap_sm *sm, struct eap_ssl_data *data, 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data, 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **in_decrypted) 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *msg; 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int need_more_input; 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_peer_tls_data_reassemble(data, in_data, &need_more_input); 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return need_more_input ? 1 : -1; 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 96904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *in_decrypted = tls_connection_decrypt(data->ssl_ctx, data->conn, msg); 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_input(data); 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*in_decrypted == NULL) { 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: Failed to decrypt Phase 2 data"); 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_encrypt - Encrypt phase 2 TLS message 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data for TLS processing 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peap_version: Version number for EAP-PEAP/TTLS 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @id: EAP identifier for the response 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_data: Plaintext phase 2 data to encrypt or %NULL to continue fragments 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @out_data: Buffer for returning a pointer to the encrypted response message 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_tls_encrypt(struct eap_sm *sm, struct eap_ssl_data *data, 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EapType eap_type, int peap_version, u8 id, 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data, 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **out_data) 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (in_data) { 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_output(data); 99704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data->tls_out = tls_connection_encrypt(data->ssl_ctx, 99804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data->conn, in_data); 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tls_out == NULL) { 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 " 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data (in_len=%lu)", 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(in_data)); 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_tls_reset_output(data); 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_tls_process_output(data, eap_type, peap_version, id, 0, 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out_data); 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_select_phase2_methods - Select phase 2 EAP method 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @config: Pointer to the network configuration 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @prefix: 'phase2' configuration prefix, e.g., "auth=" 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @types: Buffer for returning allocated list of allowed EAP methods 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @num_types: Buffer for returning number of allocated EAP methods 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to parse EAP method list and select allowed methods 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for Phase2 authentication. 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_select_phase2_methods(struct eap_peer_config *config, 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *prefix, 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_type **types, 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t *num_types) 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *start, *pos, *buf; 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_type *methods = NULL, *_methods; 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 method; 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t num_methods = 0, prefix_len; 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config == NULL || config->phase2 == NULL) 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto get_defaults; 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start = buf = os_strdup(config->phase2); 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prefix_len = os_strlen(prefix); 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (start && *start != '\0') { 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int vendor; 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strstr(start, prefix); 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (start != pos && *(pos - 1) != ' ') { 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start = pos + prefix_len; 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start = pos + prefix_len; 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strchr(start, ' '); 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos) 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = '\0'; 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt method = eap_get_phase2_type(start, &vendor); 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE) { 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "TLS: Unsupported Phase2 EAP " 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "method '%s'", start); 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_methods++; 106361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt _methods = os_realloc_array(methods, num_methods, 106461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sizeof(*methods)); 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (_methods == NULL) { 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(methods); 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods = _methods; 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods[num_methods - 1].vendor = vendor; 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods[num_methods - 1].method = method; 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start = pos; 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtget_defaults: 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (methods == NULL) 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods = eap_get_phase2_types(config, &num_methods); 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (methods == NULL) { 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "TLS: No Phase2 EAP methods available"); 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TLS: Phase2 EAP types", 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) methods, 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_methods * sizeof(struct eap_method_type)); 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *types = methods; 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *num_types = num_methods; 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_tls_phase2_nak - Generate EAP-Nak for Phase 2 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @types: Buffer for returning allocated list of allowed EAP methods 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @num_types: Buffer for returning number of allocated EAP methods 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @hdr: EAP-Request header (and the following EAP type octet) 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @resp: Buffer for returning the EAP-Nak message 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_tls_phase2_nak(struct eap_method_type *types, size_t num_types, 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_hdr *hdr, struct wpabuf **resp) 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos = (u8 *) (hdr + 1); 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: add support for expanded Nak */ 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLS: Phase 2 Request: Nak type=%d", *pos); 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TLS: Allowed Phase2 EAP types", 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) types, num_types * sizeof(struct eap_method_type)); 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NAK, num_types, 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, hdr->identifier); 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*resp == NULL) 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < num_types; i++) { 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (types[i].vendor == EAP_VENDOR_IETF && 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt types[i].method < 256) 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(*resp, types[i].method); 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_update_len(*resp); 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1132