eap_server_tls_common.c revision 289549
11556Srgrimes/* 21556Srgrimes * EAP-TLS/PEAP/TTLS/FAST server common functions 31556Srgrimes * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> 41556Srgrimes * 51556Srgrimes * This software may be distributed under the terms of the BSD license. 61556Srgrimes * See README for more details. 71556Srgrimes */ 81556Srgrimes 91556Srgrimes#include "includes.h" 101556Srgrimes 111556Srgrimes#include "common.h" 121556Srgrimes#include "crypto/sha1.h" 131556Srgrimes#include "crypto/tls.h" 141556Srgrimes#include "eap_i.h" 151556Srgrimes#include "eap_tls_common.h" 161556Srgrimes 171556Srgrimes 181556Srgrimesstatic void eap_server_tls_free_in_buf(struct eap_ssl_data *data); 191556Srgrimes 201556Srgrimes 211556Srgrimesstruct wpabuf * eap_tls_msg_alloc(EapType type, size_t payload_len, 221556Srgrimes u8 code, u8 identifier) 231556Srgrimes{ 241556Srgrimes if (type == EAP_UNAUTH_TLS_TYPE) 251556Srgrimes return eap_msg_alloc(EAP_VENDOR_UNAUTH_TLS, 261556Srgrimes EAP_VENDOR_TYPE_UNAUTH_TLS, payload_len, 271556Srgrimes code, identifier); 281556Srgrimes else if (type == EAP_WFA_UNAUTH_TLS_TYPE) 291556Srgrimes return eap_msg_alloc(EAP_VENDOR_WFA_NEW, 301556Srgrimes EAP_VENDOR_WFA_UNAUTH_TLS, payload_len, 311556Srgrimes code, identifier); 321556Srgrimes return eap_msg_alloc(EAP_VENDOR_IETF, type, payload_len, code, 331556Srgrimes identifier); 3436150Scharnier} 3536150Scharnier 3636150Scharnier 371556Srgrimes#ifdef CONFIG_TLS_INTERNAL 3899110Sobrienstatic void eap_server_tls_log_cb(void *ctx, const char *msg) 3999110Sobrien{ 401556Srgrimes struct eap_sm *sm = ctx; 41100437Stjr eap_log_msg(sm, "TLS: %s", msg); 4217987Speter} 43102576Skeramida#endif /* CONFIG_TLS_INTERNAL */ 4417987Speter 45153091Sstefanf 4645266Scracauerint eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, 4753891Scracauer int verify_peer, int eap_type) 4817987Speter{ 491556Srgrimes u8 session_ctx[8]; 501556Srgrimes unsigned int flags = 0; 511556Srgrimes 521556Srgrimes if (sm->ssl_ctx == NULL) { 531556Srgrimes wpa_printf(MSG_ERROR, "TLS context not initialized - cannot use TLS-based EAP method"); 541556Srgrimes return -1; 551556Srgrimes } 561556Srgrimes 571556Srgrimes data->eap = sm; 581556Srgrimes data->phase2 = sm->init_phase2; 591556Srgrimes 601556Srgrimes data->conn = tls_connection_init(sm->ssl_ctx); 611556Srgrimes if (data->conn == NULL) { 621556Srgrimes wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS " 631556Srgrimes "connection"); 641556Srgrimes return -1; 651556Srgrimes } 661556Srgrimes 671556Srgrimes#ifdef CONFIG_TLS_INTERNAL 681556Srgrimes tls_connection_set_log_cb(data->conn, eap_server_tls_log_cb, sm); 691556Srgrimes#ifdef CONFIG_TESTING_OPTIONS 7017987Speter tls_connection_set_test_flags(data->conn, sm->tls_test_flags); 711556Srgrimes#endif /* CONFIG_TESTING_OPTIONS */ 7217987Speter#endif /* CONFIG_TLS_INTERNAL */ 731556Srgrimes 7417987Speter if (eap_type != EAP_TYPE_FAST) 751556Srgrimes flags |= TLS_CONN_DISABLE_SESSION_TICKET; 761556Srgrimes os_memcpy(session_ctx, "hostapd", 7); 77201053Sjilles session_ctx[7] = (u8) eap_type; 781556Srgrimes if (tls_connection_set_verify(sm->ssl_ctx, data->conn, verify_peer, 791556Srgrimes flags, session_ctx, 801556Srgrimes sizeof(session_ctx))) { 81193169Sstefanf wpa_printf(MSG_INFO, "SSL: Failed to configure verification " 821556Srgrimes "of TLS peer certificate"); 831556Srgrimes tls_connection_deinit(sm->ssl_ctx, data->conn); 841556Srgrimes data->conn = NULL; 851556Srgrimes return -1; 861556Srgrimes } 8717987Speter 881556Srgrimes data->tls_out_limit = sm->fragment_size > 0 ? sm->fragment_size : 1398; 891556Srgrimes if (data->phase2) { 90149933Sstefanf /* Limit the fragment size in the inner TLS authentication 91149933Sstefanf * since the outer authentication with EAP-PEAP does not yet 9290111Simp * support fragmentation */ 9390111Simp if (data->tls_out_limit > 100) 9490111Simp data->tls_out_limit -= 100; 9590111Simp } 9690111Simp return 0; 9790111Simp} 981556Srgrimes 991556Srgrimes 1001556Srgrimesvoid eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) 1011556Srgrimes{ 1021556Srgrimes tls_connection_deinit(sm->ssl_ctx, data->conn); 1031556Srgrimes eap_server_tls_free_in_buf(data); 1041556Srgrimes wpabuf_free(data->tls_out); 1051556Srgrimes data->tls_out = NULL; 1061556Srgrimes} 1071556Srgrimes 1081556Srgrimes 1091556Srgrimesu8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, 1101556Srgrimes char *label, size_t len) 1111556Srgrimes{ 1121556Srgrimes u8 *out; 1131556Srgrimes 1141556Srgrimes out = os_malloc(len); 1151556Srgrimes if (out == NULL) 1161556Srgrimes return NULL; 1171556Srgrimes 1181556Srgrimes if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, 0, 1191556Srgrimes out, len)) { 1201556Srgrimes os_free(out); 12146684Skris return NULL; 1221556Srgrimes } 1231556Srgrimes 12417987Speter return out; 12590111Simp} 1261556Srgrimes 1271556Srgrimes 1281556Srgrimes/** 1291556Srgrimes * eap_server_tls_derive_session_id - Derive a Session-Id based on TLS data 1301556Srgrimes * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 1311556Srgrimes * @data: Data for TLS processing 1321556Srgrimes * @eap_type: EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST) 1331556Srgrimes * @len: Pointer to length of the session ID generated 1341556Srgrimes * Returns: Pointer to allocated Session-Id on success or %NULL on failure 1351556Srgrimes * 1361556Srgrimes * This function derive the Session-Id based on the TLS session data 1371556Srgrimes * (client/server random and method type). 1381556Srgrimes * 1391556Srgrimes * The caller is responsible for freeing the returned buffer. 1401556Srgrimes */ 1411556Srgrimesu8 * eap_server_tls_derive_session_id(struct eap_sm *sm, 1421556Srgrimes struct eap_ssl_data *data, u8 eap_type, 1431556Srgrimes size_t *len) 1441556Srgrimes{ 1451556Srgrimes struct tls_random keys; 146193169Sstefanf u8 *out; 1471556Srgrimes 1481556Srgrimes if (tls_connection_get_random(sm->ssl_ctx, data->conn, &keys)) 1491556Srgrimes return NULL; 1501556Srgrimes 1511556Srgrimes if (keys.client_random == NULL || keys.server_random == NULL) 1521556Srgrimes return NULL; 1531556Srgrimes 1541556Srgrimes *len = 1 + keys.client_random_len + keys.server_random_len; 1551556Srgrimes out = os_malloc(*len); 1561556Srgrimes if (out == NULL) 157193169Sstefanf return NULL; 15890111Simp 1591556Srgrimes /* Session-Id = EAP type || client.random || server.random */ 1601556Srgrimes out[0] = eap_type; 161194128Sjilles os_memcpy(out + 1, keys.client_random, keys.client_random_len); 1621556Srgrimes os_memcpy(out + 1 + keys.client_random_len, keys.server_random, 163194128Sjilles keys.server_random_len); 164194128Sjilles 1651556Srgrimes return out; 1661556Srgrimes} 1671556Srgrimes 168194128Sjilles 169194128Sjillesstruct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data, 170194128Sjilles int eap_type, int version, u8 id) 171194128Sjilles{ 172194128Sjilles struct wpabuf *req; 173194128Sjilles u8 flags; 1741556Srgrimes size_t send_len, plen; 1751556Srgrimes 1761556Srgrimes wpa_printf(MSG_DEBUG, "SSL: Generating Request"); 1771556Srgrimes if (data->tls_out == NULL) { 178194128Sjilles wpa_printf(MSG_ERROR, "SSL: tls_out NULL in %s", __func__); 179194128Sjilles return NULL; 1801556Srgrimes } 1811556Srgrimes 1821556Srgrimes flags = version; 1831556Srgrimes send_len = wpabuf_len(data->tls_out) - data->tls_out_pos; 1841556Srgrimes if (1 + send_len > data->tls_out_limit) { 1851556Srgrimes send_len = data->tls_out_limit - 1; 1861556Srgrimes flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS; 1871556Srgrimes if (data->tls_out_pos == 0) { 1881556Srgrimes flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED; 18990111Simp send_len -= 4; 19017987Speter } 191149927Sstefanf } 192149927Sstefanf 193149927Sstefanf plen = 1 + send_len; 1941556Srgrimes if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) 1951556Srgrimes plen += 4; 1961556Srgrimes 1971556Srgrimes req = eap_tls_msg_alloc(eap_type, plen, EAP_CODE_REQUEST, id); 1981556Srgrimes if (req == NULL) 19917987Speter return NULL; 2001556Srgrimes 20117987Speter wpabuf_put_u8(req, flags); /* Flags */ 202149802Sstefanf if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) 2031556Srgrimes wpabuf_put_be32(req, wpabuf_len(data->tls_out)); 2041556Srgrimes 205149932Sstefanf wpabuf_put_data(req, wpabuf_head_u8(data->tls_out) + data->tls_out_pos, 2061556Srgrimes send_len); 2071556Srgrimes data->tls_out_pos += send_len; 2081556Srgrimes 2091556Srgrimes if (data->tls_out_pos == wpabuf_len(data->tls_out)) { 2101556Srgrimes wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes " 2111556Srgrimes "(message sent completely)", 21218754Ssteve (unsigned long) send_len); 2131556Srgrimes wpabuf_free(data->tls_out); 21418754Ssteve data->tls_out = NULL; 2151556Srgrimes data->tls_out_pos = 0; 2161556Srgrimes data->state = MSG; 2171556Srgrimes } else { 2181556Srgrimes wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes " 2191556Srgrimes "(%lu more to send)", (unsigned long) send_len, 2201556Srgrimes (unsigned long) wpabuf_len(data->tls_out) - 2211556Srgrimes data->tls_out_pos); 2221556Srgrimes data->state = WAIT_FRAG_ACK; 2231556Srgrimes } 2241556Srgrimes 2251556Srgrimes return req; 2261556Srgrimes} 2271556Srgrimes 2281556Srgrimes 2291556Srgrimesstruct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version) 2301556Srgrimes{ 231149927Sstefanf struct wpabuf *req; 2321556Srgrimes 2331556Srgrimes req = eap_tls_msg_alloc(eap_type, 1, EAP_CODE_REQUEST, id); 2341556Srgrimes if (req == NULL) 2351556Srgrimes return NULL; 2361556Srgrimes wpa_printf(MSG_DEBUG, "SSL: Building ACK"); 2371556Srgrimes wpabuf_put_u8(req, version); /* Flags */ 2381556Srgrimes return req; 2391556Srgrimes} 24020425Ssteve 2411556Srgrimes 24217987Speterstatic int eap_server_tls_process_cont(struct eap_ssl_data *data, 2431556Srgrimes const u8 *buf, size_t len) 24420425Ssteve{ 24520425Ssteve /* Process continuation of a pending message */ 2461556Srgrimes if (len > wpabuf_tailroom(data->tls_in)) { 2471556Srgrimes wpa_printf(MSG_DEBUG, "SSL: Fragment overflow"); 2481556Srgrimes return -1; 2491556Srgrimes } 250149933Sstefanf 2511556Srgrimes wpabuf_put_data(data->tls_in, buf, len); 2521556Srgrimes wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes, waiting for %lu " 253149933Sstefanf "bytes more", (unsigned long) len, 2541556Srgrimes (unsigned long) wpabuf_tailroom(data->tls_in)); 2551556Srgrimes 2561556Srgrimes return 0; 2571556Srgrimes} 2581556Srgrimes 2591556Srgrimes 2601556Srgrimesstatic int eap_server_tls_process_fragment(struct eap_ssl_data *data, 2611556Srgrimes u8 flags, u32 message_length, 2621556Srgrimes const u8 *buf, size_t len) 2631556Srgrimes{ 2641556Srgrimes /* Process a fragment that is not the last one of the message */ 2651556Srgrimes if (data->tls_in == NULL && !(flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)) { 2661556Srgrimes wpa_printf(MSG_DEBUG, "SSL: No Message Length field in a " 2671556Srgrimes "fragmented packet"); 2681556Srgrimes return -1; 269149927Sstefanf } 2701556Srgrimes 2711556Srgrimes if (data->tls_in == NULL) { 2721556Srgrimes /* First fragment of the message */ 273149927Sstefanf 2741556Srgrimes /* Limit length to avoid rogue peers from causing large 2751556Srgrimes * memory allocations. */ 2761556Srgrimes if (message_length > 65536) { 2771556Srgrimes wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size" 2781556Srgrimes " over 64 kB)"); 2791556Srgrimes return -1; 2801556Srgrimes } 2811556Srgrimes 2821556Srgrimes if (len > message_length) { 283149927Sstefanf wpa_printf(MSG_INFO, "SSL: Too much data (%d bytes) in " 2841556Srgrimes "first fragment of frame (TLS Message " 2851556Srgrimes "Length %d bytes)", 2861556Srgrimes (int) len, (int) message_length); 2871556Srgrimes return -1; 2881556Srgrimes } 289149933Sstefanf 29017987Speter data->tls_in = wpabuf_alloc(message_length); 2911556Srgrimes if (data->tls_in == NULL) { 2921556Srgrimes wpa_printf(MSG_DEBUG, "SSL: No memory for message"); 2931556Srgrimes return -1; 2941556Srgrimes } 2951556Srgrimes wpabuf_put_data(data->tls_in, buf, len); 2961556Srgrimes wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes in first " 2971556Srgrimes "fragment, waiting for %lu bytes more", 2981556Srgrimes (unsigned long) len, 2991556Srgrimes (unsigned long) wpabuf_tailroom(data->tls_in)); 3001556Srgrimes } 3011556Srgrimes 3021556Srgrimes return 0; 3031556Srgrimes} 3041556Srgrimes 3051556Srgrimes 3061556Srgrimesint eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data) 3071556Srgrimes{ 3081556Srgrimes if (data->tls_out) { 3091556Srgrimes /* This should not happen.. */ 3101556Srgrimes wpa_printf(MSG_INFO, "SSL: pending tls_out data when " 3111556Srgrimes "processing new message"); 3121556Srgrimes wpabuf_free(data->tls_out); 313149933Sstefanf WPA_ASSERT(data->tls_out == NULL); 3141556Srgrimes } 3151556Srgrimes 3161556Srgrimes data->tls_out = tls_connection_server_handshake(sm->ssl_ctx, 3171556Srgrimes data->conn, 3181556Srgrimes data->tls_in, NULL); 3191556Srgrimes if (data->tls_out == NULL) { 3201556Srgrimes wpa_printf(MSG_INFO, "SSL: TLS processing failed"); 3211556Srgrimes return -1; 3221556Srgrimes } 3231556Srgrimes if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) { 3241556Srgrimes /* TLS processing has failed - return error */ 325149933Sstefanf wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to " 32617987Speter "report error"); 3271556Srgrimes return -1; 3281556Srgrimes } 3291556Srgrimes 3301556Srgrimes return 0; 3311556Srgrimes} 3321556Srgrimes 3331556Srgrimes 3341556Srgrimesstatic int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags, 33517987Speter const u8 **pos, size_t *left) 3361556Srgrimes{ 3371556Srgrimes unsigned int tls_msg_len = 0; 3381556Srgrimes const u8 *end = *pos + *left; 3391556Srgrimes 3401556Srgrimes if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { 3411556Srgrimes if (*left < 4) { 3421556Srgrimes wpa_printf(MSG_INFO, "SSL: Short frame with TLS " 3431556Srgrimes "length"); 3441556Srgrimes return -1; 3451556Srgrimes } 346149933Sstefanf tls_msg_len = WPA_GET_BE32(*pos); 3471556Srgrimes wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d", 3481556Srgrimes tls_msg_len); 3491556Srgrimes *pos += 4; 3501556Srgrimes *left -= 4; 3511556Srgrimes 3521556Srgrimes if (*left > tls_msg_len) { 3531556Srgrimes wpa_printf(MSG_INFO, "SSL: TLS Message Length (%d " 3541556Srgrimes "bytes) smaller than this fragment (%d " 3551556Srgrimes "bytes)", (int) tls_msg_len, (int) *left); 3561556Srgrimes return -1; 3571556Srgrimes } 3581556Srgrimes } 3591556Srgrimes 3601556Srgrimes wpa_printf(MSG_DEBUG, "SSL: Received packet: Flags 0x%x " 3611556Srgrimes "Message Length %u", flags, tls_msg_len); 3621556Srgrimes 3631556Srgrimes if (data->state == WAIT_FRAG_ACK) { 3641556Srgrimes if (*left != 0) { 36590111Simp wpa_printf(MSG_DEBUG, "SSL: Unexpected payload in " 36617987Speter "WAIT_FRAG_ACK state"); 3671556Srgrimes return -1; 3681556Srgrimes } 3691556Srgrimes wpa_printf(MSG_DEBUG, "SSL: Fragment acknowledged"); 3701556Srgrimes return 1; 3711556Srgrimes } 3721556Srgrimes 3731556Srgrimes if (data->tls_in && 37417987Speter eap_server_tls_process_cont(data, *pos, end - *pos) < 0) 375172440Sstefanf return -1; 3761556Srgrimes 3771556Srgrimes if (flags & EAP_TLS_FLAGS_MORE_FRAGMENTS) { 3781556Srgrimes if (eap_server_tls_process_fragment(data, flags, tls_msg_len, 3791556Srgrimes *pos, end - *pos) < 0) 3801556Srgrimes return -1; 3811556Srgrimes 3821556Srgrimes data->state = FRAG_ACK; 3831556Srgrimes return 1; 3841556Srgrimes } 3851556Srgrimes 3861556Srgrimes if (data->state == FRAG_ACK) { 3871556Srgrimes wpa_printf(MSG_DEBUG, "SSL: All fragments received"); 3881556Srgrimes data->state = MSG; 3891556Srgrimes } 3901556Srgrimes 3911556Srgrimes if (data->tls_in == NULL) { 3921556Srgrimes /* Wrap unfragmented messages as wpabuf without extra copy */ 3931556Srgrimes wpabuf_set(&data->tmpbuf, *pos, end - *pos); 3941556Srgrimes data->tls_in = &data->tmpbuf; 3951556Srgrimes } 3961556Srgrimes 3971556Srgrimes return 0; 39890111Simp} 39917987Speter 4001556Srgrimes 4011556Srgrimesstatic void eap_server_tls_free_in_buf(struct eap_ssl_data *data) 4021556Srgrimes{ 4031556Srgrimes if (data->tls_in != &data->tmpbuf) 404194774Sjilles wpabuf_free(data->tls_in); 405194774Sjilles data->tls_in = NULL; 4061556Srgrimes} 4071556Srgrimes 4081556Srgrimes 4091556Srgrimesstruct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm, 410201053Sjilles struct eap_ssl_data *data, 4111556Srgrimes const struct wpabuf *plain) 41245916Scracauer{ 4131556Srgrimes struct wpabuf *buf; 4141556Srgrimes 4151556Srgrimes buf = tls_connection_encrypt(sm->ssl_ctx, data->conn, 4161556Srgrimes plain); 4171556Srgrimes if (buf == NULL) { 4181556Srgrimes wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data"); 4191556Srgrimes return NULL; 4201556Srgrimes } 4211556Srgrimes 4221556Srgrimes return buf; 4231556Srgrimes} 42490111Simp 42517987Speter 42625222Ssteveint eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data, 4271556Srgrimes struct wpabuf *respData, void *priv, int eap_type, 4281556Srgrimes int (*proc_version)(struct eap_sm *sm, void *priv, 42917987Speter int peer_version), 43017987Speter void (*proc_msg)(struct eap_sm *sm, void *priv, 43117987Speter const struct wpabuf *respData)) 43217987Speter{ 43317987Speter const u8 *pos; 43417987Speter u8 flags; 43566612Sbrian size_t left; 43617987Speter int ret, res = 0; 43796922Stjr 4381556Srgrimes if (eap_type == EAP_UNAUTH_TLS_TYPE) 4391556Srgrimes pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS, 44017987Speter EAP_VENDOR_TYPE_UNAUTH_TLS, respData, 44117987Speter &left); 44217987Speter else if (eap_type == EAP_WFA_UNAUTH_TLS_TYPE) 44317987Speter pos = eap_hdr_validate(EAP_VENDOR_WFA_NEW, 444181017Sstefanf EAP_VENDOR_WFA_UNAUTH_TLS, respData, 44517987Speter &left); 44617987Speter else 44717987Speter pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, respData, 4481556Srgrimes &left); 4491556Srgrimes if (pos == NULL || left < 1) 4501556Srgrimes return 0; /* Should not happen - frame already validated */ 4511556Srgrimes flags = *pos++; 4521556Srgrimes left--; 4531556Srgrimes wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - Flags 0x%02x", 4541556Srgrimes (unsigned long) wpabuf_len(respData), flags); 4551556Srgrimes 4561556Srgrimes if (proc_version && 4571556Srgrimes proc_version(sm, priv, flags & EAP_TLS_VERSION_MASK) < 0) 4581556Srgrimes return -1; 4591556Srgrimes 4601556Srgrimes ret = eap_server_tls_reassemble(data, flags, &pos, &left); 4611556Srgrimes if (ret < 0) { 46290111Simp res = -1; 46317987Speter goto done; 4641556Srgrimes } else if (ret == 1) 4651556Srgrimes return 0; 4661556Srgrimes 4671556Srgrimes if (proc_msg) 4681556Srgrimes proc_msg(sm, priv, respData); 4691556Srgrimes 470149802Sstefanf if (tls_connection_get_write_alerts(sm->ssl_ctx, data->conn) > 1) { 4711556Srgrimes wpa_printf(MSG_INFO, "SSL: Locally detected fatal error in " 4721556Srgrimes "TLS processing"); 4731556Srgrimes res = -1; 4741556Srgrimes } 4751556Srgrimes 4761556Srgrimesdone: 4771556Srgrimes eap_server_tls_free_in_buf(data); 4781556Srgrimes 4791556Srgrimes return res; 4801556Srgrimes} 4811556Srgrimes