eap_server_tls_common.c revision 281806
1214501Srpaulo/* 2214501Srpaulo * EAP-TLS/PEAP/TTLS/FAST server common functions 3214501Srpaulo * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> 4214501Srpaulo * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7214501Srpaulo */ 8214501Srpaulo 9214501Srpaulo#include "includes.h" 10214501Srpaulo 11214501Srpaulo#include "common.h" 12214501Srpaulo#include "crypto/sha1.h" 13214501Srpaulo#include "crypto/tls.h" 14214501Srpaulo#include "eap_i.h" 15214501Srpaulo#include "eap_tls_common.h" 16214501Srpaulo 17214501Srpaulo 18214501Srpaulostatic void eap_server_tls_free_in_buf(struct eap_ssl_data *data); 19214501Srpaulo 20214501Srpaulo 21252726Srpaulostruct wpabuf * eap_tls_msg_alloc(EapType type, size_t payload_len, 22252726Srpaulo u8 code, u8 identifier) 23252726Srpaulo{ 24252726Srpaulo if (type == EAP_UNAUTH_TLS_TYPE) 25252726Srpaulo return eap_msg_alloc(EAP_VENDOR_UNAUTH_TLS, 26252726Srpaulo EAP_VENDOR_TYPE_UNAUTH_TLS, payload_len, 27252726Srpaulo code, identifier); 28281806Srpaulo else if (type == EAP_WFA_UNAUTH_TLS_TYPE) 29281806Srpaulo return eap_msg_alloc(EAP_VENDOR_WFA_NEW, 30281806Srpaulo EAP_VENDOR_WFA_UNAUTH_TLS, payload_len, 31281806Srpaulo code, identifier); 32252726Srpaulo return eap_msg_alloc(EAP_VENDOR_IETF, type, payload_len, code, 33252726Srpaulo identifier); 34252726Srpaulo} 35252726Srpaulo 36252726Srpaulo 37281806Srpaulo#ifdef CONFIG_TLS_INTERNAL 38281806Srpaulostatic void eap_server_tls_log_cb(void *ctx, const char *msg) 39281806Srpaulo{ 40281806Srpaulo struct eap_sm *sm = ctx; 41281806Srpaulo eap_log_msg(sm, "TLS: %s", msg); 42281806Srpaulo} 43281806Srpaulo#endif /* CONFIG_TLS_INTERNAL */ 44281806Srpaulo 45281806Srpaulo 46214501Srpauloint eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, 47214501Srpaulo int verify_peer) 48214501Srpaulo{ 49281806Srpaulo if (sm->ssl_ctx == NULL) { 50281806Srpaulo wpa_printf(MSG_ERROR, "TLS context not initialized - cannot use TLS-based EAP method"); 51281806Srpaulo return -1; 52281806Srpaulo } 53281806Srpaulo 54214501Srpaulo data->eap = sm; 55214501Srpaulo data->phase2 = sm->init_phase2; 56214501Srpaulo 57214501Srpaulo data->conn = tls_connection_init(sm->ssl_ctx); 58214501Srpaulo if (data->conn == NULL) { 59214501Srpaulo wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS " 60214501Srpaulo "connection"); 61214501Srpaulo return -1; 62214501Srpaulo } 63214501Srpaulo 64281806Srpaulo#ifdef CONFIG_TLS_INTERNAL 65281806Srpaulo tls_connection_set_log_cb(data->conn, eap_server_tls_log_cb, sm); 66281806Srpaulo#ifdef CONFIG_TESTING_OPTIONS 67281806Srpaulo tls_connection_set_test_flags(data->conn, sm->tls_test_flags); 68281806Srpaulo#endif /* CONFIG_TESTING_OPTIONS */ 69281806Srpaulo#endif /* CONFIG_TLS_INTERNAL */ 70281806Srpaulo 71214501Srpaulo if (tls_connection_set_verify(sm->ssl_ctx, data->conn, verify_peer)) { 72214501Srpaulo wpa_printf(MSG_INFO, "SSL: Failed to configure verification " 73214501Srpaulo "of TLS peer certificate"); 74214501Srpaulo tls_connection_deinit(sm->ssl_ctx, data->conn); 75214501Srpaulo data->conn = NULL; 76214501Srpaulo return -1; 77214501Srpaulo } 78214501Srpaulo 79252726Srpaulo data->tls_out_limit = sm->fragment_size > 0 ? sm->fragment_size : 1398; 80214501Srpaulo if (data->phase2) { 81214501Srpaulo /* Limit the fragment size in the inner TLS authentication 82214501Srpaulo * since the outer authentication with EAP-PEAP does not yet 83214501Srpaulo * support fragmentation */ 84214501Srpaulo if (data->tls_out_limit > 100) 85214501Srpaulo data->tls_out_limit -= 100; 86214501Srpaulo } 87214501Srpaulo return 0; 88214501Srpaulo} 89214501Srpaulo 90214501Srpaulo 91214501Srpaulovoid eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) 92214501Srpaulo{ 93214501Srpaulo tls_connection_deinit(sm->ssl_ctx, data->conn); 94214501Srpaulo eap_server_tls_free_in_buf(data); 95214501Srpaulo wpabuf_free(data->tls_out); 96214501Srpaulo data->tls_out = NULL; 97214501Srpaulo} 98214501Srpaulo 99214501Srpaulo 100214501Srpaulou8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, 101214501Srpaulo char *label, size_t len) 102214501Srpaulo{ 103214501Srpaulo struct tls_keys keys; 104214501Srpaulo u8 *rnd = NULL, *out; 105214501Srpaulo 106214501Srpaulo out = os_malloc(len); 107214501Srpaulo if (out == NULL) 108214501Srpaulo return NULL; 109214501Srpaulo 110214501Srpaulo if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) == 111214501Srpaulo 0) 112214501Srpaulo return out; 113214501Srpaulo 114214501Srpaulo if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) 115214501Srpaulo goto fail; 116214501Srpaulo 117214501Srpaulo if (keys.client_random == NULL || keys.server_random == NULL || 118214501Srpaulo keys.master_key == NULL) 119214501Srpaulo goto fail; 120214501Srpaulo 121214501Srpaulo rnd = os_malloc(keys.client_random_len + keys.server_random_len); 122214501Srpaulo if (rnd == NULL) 123214501Srpaulo goto fail; 124214501Srpaulo os_memcpy(rnd, keys.client_random, keys.client_random_len); 125214501Srpaulo os_memcpy(rnd + keys.client_random_len, keys.server_random, 126214501Srpaulo keys.server_random_len); 127214501Srpaulo 128252726Srpaulo if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len, 129252726Srpaulo label, rnd, keys.client_random_len + 130252726Srpaulo keys.server_random_len, out, len)) 131214501Srpaulo goto fail; 132214501Srpaulo 133214501Srpaulo os_free(rnd); 134214501Srpaulo return out; 135214501Srpaulo 136214501Srpaulofail: 137214501Srpaulo os_free(out); 138214501Srpaulo os_free(rnd); 139214501Srpaulo return NULL; 140214501Srpaulo} 141214501Srpaulo 142214501Srpaulo 143281806Srpaulo/** 144281806Srpaulo * eap_server_tls_derive_session_id - Derive a Session-Id based on TLS data 145281806Srpaulo * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 146281806Srpaulo * @data: Data for TLS processing 147281806Srpaulo * @eap_type: EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST) 148281806Srpaulo * @len: Pointer to length of the session ID generated 149281806Srpaulo * Returns: Pointer to allocated Session-Id on success or %NULL on failure 150281806Srpaulo * 151281806Srpaulo * This function derive the Session-Id based on the TLS session data 152281806Srpaulo * (client/server random and method type). 153281806Srpaulo * 154281806Srpaulo * The caller is responsible for freeing the returned buffer. 155281806Srpaulo */ 156281806Srpaulou8 * eap_server_tls_derive_session_id(struct eap_sm *sm, 157281806Srpaulo struct eap_ssl_data *data, u8 eap_type, 158281806Srpaulo size_t *len) 159281806Srpaulo{ 160281806Srpaulo struct tls_keys keys; 161281806Srpaulo u8 *out; 162281806Srpaulo 163281806Srpaulo if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) 164281806Srpaulo return NULL; 165281806Srpaulo 166281806Srpaulo if (keys.client_random == NULL || keys.server_random == NULL) 167281806Srpaulo return NULL; 168281806Srpaulo 169281806Srpaulo *len = 1 + keys.client_random_len + keys.server_random_len; 170281806Srpaulo out = os_malloc(*len); 171281806Srpaulo if (out == NULL) 172281806Srpaulo return NULL; 173281806Srpaulo 174281806Srpaulo /* Session-Id = EAP type || client.random || server.random */ 175281806Srpaulo out[0] = eap_type; 176281806Srpaulo os_memcpy(out + 1, keys.client_random, keys.client_random_len); 177281806Srpaulo os_memcpy(out + 1 + keys.client_random_len, keys.server_random, 178281806Srpaulo keys.server_random_len); 179281806Srpaulo 180281806Srpaulo return out; 181281806Srpaulo} 182281806Srpaulo 183281806Srpaulo 184214501Srpaulostruct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data, 185214501Srpaulo int eap_type, int version, u8 id) 186214501Srpaulo{ 187214501Srpaulo struct wpabuf *req; 188214501Srpaulo u8 flags; 189214501Srpaulo size_t send_len, plen; 190214501Srpaulo 191214501Srpaulo wpa_printf(MSG_DEBUG, "SSL: Generating Request"); 192214501Srpaulo if (data->tls_out == NULL) { 193214501Srpaulo wpa_printf(MSG_ERROR, "SSL: tls_out NULL in %s", __func__); 194214501Srpaulo return NULL; 195214501Srpaulo } 196214501Srpaulo 197214501Srpaulo flags = version; 198214501Srpaulo send_len = wpabuf_len(data->tls_out) - data->tls_out_pos; 199214501Srpaulo if (1 + send_len > data->tls_out_limit) { 200214501Srpaulo send_len = data->tls_out_limit - 1; 201214501Srpaulo flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS; 202214501Srpaulo if (data->tls_out_pos == 0) { 203214501Srpaulo flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED; 204214501Srpaulo send_len -= 4; 205214501Srpaulo } 206214501Srpaulo } 207214501Srpaulo 208214501Srpaulo plen = 1 + send_len; 209214501Srpaulo if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) 210214501Srpaulo plen += 4; 211214501Srpaulo 212252726Srpaulo req = eap_tls_msg_alloc(eap_type, plen, EAP_CODE_REQUEST, id); 213214501Srpaulo if (req == NULL) 214214501Srpaulo return NULL; 215214501Srpaulo 216214501Srpaulo wpabuf_put_u8(req, flags); /* Flags */ 217214501Srpaulo if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) 218214501Srpaulo wpabuf_put_be32(req, wpabuf_len(data->tls_out)); 219214501Srpaulo 220214501Srpaulo wpabuf_put_data(req, wpabuf_head_u8(data->tls_out) + data->tls_out_pos, 221214501Srpaulo send_len); 222214501Srpaulo data->tls_out_pos += send_len; 223214501Srpaulo 224214501Srpaulo if (data->tls_out_pos == wpabuf_len(data->tls_out)) { 225214501Srpaulo wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes " 226214501Srpaulo "(message sent completely)", 227214501Srpaulo (unsigned long) send_len); 228214501Srpaulo wpabuf_free(data->tls_out); 229214501Srpaulo data->tls_out = NULL; 230214501Srpaulo data->tls_out_pos = 0; 231214501Srpaulo data->state = MSG; 232214501Srpaulo } else { 233214501Srpaulo wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes " 234214501Srpaulo "(%lu more to send)", (unsigned long) send_len, 235214501Srpaulo (unsigned long) wpabuf_len(data->tls_out) - 236214501Srpaulo data->tls_out_pos); 237214501Srpaulo data->state = WAIT_FRAG_ACK; 238214501Srpaulo } 239214501Srpaulo 240214501Srpaulo return req; 241214501Srpaulo} 242214501Srpaulo 243214501Srpaulo 244214501Srpaulostruct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version) 245214501Srpaulo{ 246214501Srpaulo struct wpabuf *req; 247214501Srpaulo 248252726Srpaulo req = eap_tls_msg_alloc(eap_type, 1, EAP_CODE_REQUEST, id); 249214501Srpaulo if (req == NULL) 250214501Srpaulo return NULL; 251214501Srpaulo wpa_printf(MSG_DEBUG, "SSL: Building ACK"); 252214501Srpaulo wpabuf_put_u8(req, version); /* Flags */ 253214501Srpaulo return req; 254214501Srpaulo} 255214501Srpaulo 256214501Srpaulo 257214501Srpaulostatic int eap_server_tls_process_cont(struct eap_ssl_data *data, 258214501Srpaulo const u8 *buf, size_t len) 259214501Srpaulo{ 260214501Srpaulo /* Process continuation of a pending message */ 261214501Srpaulo if (len > wpabuf_tailroom(data->tls_in)) { 262214501Srpaulo wpa_printf(MSG_DEBUG, "SSL: Fragment overflow"); 263214501Srpaulo return -1; 264214501Srpaulo } 265214501Srpaulo 266214501Srpaulo wpabuf_put_data(data->tls_in, buf, len); 267214501Srpaulo wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes, waiting for %lu " 268214501Srpaulo "bytes more", (unsigned long) len, 269214501Srpaulo (unsigned long) wpabuf_tailroom(data->tls_in)); 270214501Srpaulo 271214501Srpaulo return 0; 272214501Srpaulo} 273214501Srpaulo 274214501Srpaulo 275214501Srpaulostatic int eap_server_tls_process_fragment(struct eap_ssl_data *data, 276214501Srpaulo u8 flags, u32 message_length, 277214501Srpaulo const u8 *buf, size_t len) 278214501Srpaulo{ 279214501Srpaulo /* Process a fragment that is not the last one of the message */ 280214501Srpaulo if (data->tls_in == NULL && !(flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)) { 281214501Srpaulo wpa_printf(MSG_DEBUG, "SSL: No Message Length field in a " 282214501Srpaulo "fragmented packet"); 283214501Srpaulo return -1; 284214501Srpaulo } 285214501Srpaulo 286214501Srpaulo if (data->tls_in == NULL) { 287214501Srpaulo /* First fragment of the message */ 288214501Srpaulo 289214501Srpaulo /* Limit length to avoid rogue peers from causing large 290214501Srpaulo * memory allocations. */ 291214501Srpaulo if (message_length > 65536) { 292214501Srpaulo wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size" 293214501Srpaulo " over 64 kB)"); 294214501Srpaulo return -1; 295214501Srpaulo } 296214501Srpaulo 297243419Scperciva if (len > message_length) { 298243419Scperciva wpa_printf(MSG_INFO, "SSL: Too much data (%d bytes) in " 299243419Scperciva "first fragment of frame (TLS Message " 300243419Scperciva "Length %d bytes)", 301243419Scperciva (int) len, (int) message_length); 302243419Scperciva return -1; 303243419Scperciva } 304243419Scperciva 305214501Srpaulo data->tls_in = wpabuf_alloc(message_length); 306214501Srpaulo if (data->tls_in == NULL) { 307214501Srpaulo wpa_printf(MSG_DEBUG, "SSL: No memory for message"); 308214501Srpaulo return -1; 309214501Srpaulo } 310214501Srpaulo wpabuf_put_data(data->tls_in, buf, len); 311214501Srpaulo wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes in first " 312214501Srpaulo "fragment, waiting for %lu bytes more", 313214501Srpaulo (unsigned long) len, 314214501Srpaulo (unsigned long) wpabuf_tailroom(data->tls_in)); 315214501Srpaulo } 316214501Srpaulo 317214501Srpaulo return 0; 318214501Srpaulo} 319214501Srpaulo 320214501Srpaulo 321214501Srpauloint eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data) 322214501Srpaulo{ 323214501Srpaulo if (data->tls_out) { 324214501Srpaulo /* This should not happen.. */ 325214501Srpaulo wpa_printf(MSG_INFO, "SSL: pending tls_out data when " 326214501Srpaulo "processing new message"); 327214501Srpaulo wpabuf_free(data->tls_out); 328214501Srpaulo WPA_ASSERT(data->tls_out == NULL); 329214501Srpaulo } 330214501Srpaulo 331214501Srpaulo data->tls_out = tls_connection_server_handshake(sm->ssl_ctx, 332214501Srpaulo data->conn, 333214501Srpaulo data->tls_in, NULL); 334214501Srpaulo if (data->tls_out == NULL) { 335214501Srpaulo wpa_printf(MSG_INFO, "SSL: TLS processing failed"); 336214501Srpaulo return -1; 337214501Srpaulo } 338214501Srpaulo if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) { 339214501Srpaulo /* TLS processing has failed - return error */ 340214501Srpaulo wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to " 341214501Srpaulo "report error"); 342214501Srpaulo return -1; 343214501Srpaulo } 344214501Srpaulo 345214501Srpaulo return 0; 346214501Srpaulo} 347214501Srpaulo 348214501Srpaulo 349214501Srpaulostatic int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags, 350214501Srpaulo const u8 **pos, size_t *left) 351214501Srpaulo{ 352214501Srpaulo unsigned int tls_msg_len = 0; 353214501Srpaulo const u8 *end = *pos + *left; 354214501Srpaulo 355214501Srpaulo if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { 356214501Srpaulo if (*left < 4) { 357214501Srpaulo wpa_printf(MSG_INFO, "SSL: Short frame with TLS " 358214501Srpaulo "length"); 359214501Srpaulo return -1; 360214501Srpaulo } 361214501Srpaulo tls_msg_len = WPA_GET_BE32(*pos); 362214501Srpaulo wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d", 363214501Srpaulo tls_msg_len); 364214501Srpaulo *pos += 4; 365214501Srpaulo *left -= 4; 366252726Srpaulo 367252726Srpaulo if (*left > tls_msg_len) { 368252726Srpaulo wpa_printf(MSG_INFO, "SSL: TLS Message Length (%d " 369252726Srpaulo "bytes) smaller than this fragment (%d " 370252726Srpaulo "bytes)", (int) tls_msg_len, (int) *left); 371252726Srpaulo return -1; 372252726Srpaulo } 373214501Srpaulo } 374214501Srpaulo 375214501Srpaulo wpa_printf(MSG_DEBUG, "SSL: Received packet: Flags 0x%x " 376214501Srpaulo "Message Length %u", flags, tls_msg_len); 377214501Srpaulo 378214501Srpaulo if (data->state == WAIT_FRAG_ACK) { 379214501Srpaulo if (*left != 0) { 380214501Srpaulo wpa_printf(MSG_DEBUG, "SSL: Unexpected payload in " 381214501Srpaulo "WAIT_FRAG_ACK state"); 382214501Srpaulo return -1; 383214501Srpaulo } 384214501Srpaulo wpa_printf(MSG_DEBUG, "SSL: Fragment acknowledged"); 385214501Srpaulo return 1; 386214501Srpaulo } 387214501Srpaulo 388214501Srpaulo if (data->tls_in && 389214501Srpaulo eap_server_tls_process_cont(data, *pos, end - *pos) < 0) 390214501Srpaulo return -1; 391214501Srpaulo 392214501Srpaulo if (flags & EAP_TLS_FLAGS_MORE_FRAGMENTS) { 393214501Srpaulo if (eap_server_tls_process_fragment(data, flags, tls_msg_len, 394214501Srpaulo *pos, end - *pos) < 0) 395214501Srpaulo return -1; 396214501Srpaulo 397214501Srpaulo data->state = FRAG_ACK; 398214501Srpaulo return 1; 399214501Srpaulo } 400214501Srpaulo 401214501Srpaulo if (data->state == FRAG_ACK) { 402214501Srpaulo wpa_printf(MSG_DEBUG, "SSL: All fragments received"); 403214501Srpaulo data->state = MSG; 404214501Srpaulo } 405214501Srpaulo 406214501Srpaulo if (data->tls_in == NULL) { 407214501Srpaulo /* Wrap unfragmented messages as wpabuf without extra copy */ 408214501Srpaulo wpabuf_set(&data->tmpbuf, *pos, end - *pos); 409214501Srpaulo data->tls_in = &data->tmpbuf; 410214501Srpaulo } 411214501Srpaulo 412214501Srpaulo return 0; 413214501Srpaulo} 414214501Srpaulo 415214501Srpaulo 416214501Srpaulostatic void eap_server_tls_free_in_buf(struct eap_ssl_data *data) 417214501Srpaulo{ 418214501Srpaulo if (data->tls_in != &data->tmpbuf) 419214501Srpaulo wpabuf_free(data->tls_in); 420214501Srpaulo data->tls_in = NULL; 421214501Srpaulo} 422214501Srpaulo 423214501Srpaulo 424214501Srpaulostruct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm, 425214501Srpaulo struct eap_ssl_data *data, 426214501Srpaulo const struct wpabuf *plain) 427214501Srpaulo{ 428214501Srpaulo struct wpabuf *buf; 429214501Srpaulo 430214501Srpaulo buf = tls_connection_encrypt(sm->ssl_ctx, data->conn, 431214501Srpaulo plain); 432214501Srpaulo if (buf == NULL) { 433214501Srpaulo wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data"); 434214501Srpaulo return NULL; 435214501Srpaulo } 436214501Srpaulo 437214501Srpaulo return buf; 438214501Srpaulo} 439214501Srpaulo 440214501Srpaulo 441214501Srpauloint eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data, 442214501Srpaulo struct wpabuf *respData, void *priv, int eap_type, 443214501Srpaulo int (*proc_version)(struct eap_sm *sm, void *priv, 444214501Srpaulo int peer_version), 445214501Srpaulo void (*proc_msg)(struct eap_sm *sm, void *priv, 446214501Srpaulo const struct wpabuf *respData)) 447214501Srpaulo{ 448214501Srpaulo const u8 *pos; 449214501Srpaulo u8 flags; 450214501Srpaulo size_t left; 451214501Srpaulo int ret, res = 0; 452214501Srpaulo 453252726Srpaulo if (eap_type == EAP_UNAUTH_TLS_TYPE) 454252726Srpaulo pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS, 455252726Srpaulo EAP_VENDOR_TYPE_UNAUTH_TLS, respData, 456252726Srpaulo &left); 457281806Srpaulo else if (eap_type == EAP_WFA_UNAUTH_TLS_TYPE) 458281806Srpaulo pos = eap_hdr_validate(EAP_VENDOR_WFA_NEW, 459281806Srpaulo EAP_VENDOR_WFA_UNAUTH_TLS, respData, 460281806Srpaulo &left); 461252726Srpaulo else 462252726Srpaulo pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, respData, 463252726Srpaulo &left); 464214501Srpaulo if (pos == NULL || left < 1) 465214501Srpaulo return 0; /* Should not happen - frame already validated */ 466214501Srpaulo flags = *pos++; 467214501Srpaulo left--; 468214501Srpaulo wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - Flags 0x%02x", 469214501Srpaulo (unsigned long) wpabuf_len(respData), flags); 470214501Srpaulo 471214501Srpaulo if (proc_version && 472214501Srpaulo proc_version(sm, priv, flags & EAP_TLS_VERSION_MASK) < 0) 473214501Srpaulo return -1; 474214501Srpaulo 475214501Srpaulo ret = eap_server_tls_reassemble(data, flags, &pos, &left); 476214501Srpaulo if (ret < 0) { 477214501Srpaulo res = -1; 478214501Srpaulo goto done; 479214501Srpaulo } else if (ret == 1) 480214501Srpaulo return 0; 481214501Srpaulo 482214501Srpaulo if (proc_msg) 483214501Srpaulo proc_msg(sm, priv, respData); 484214501Srpaulo 485214501Srpaulo if (tls_connection_get_write_alerts(sm->ssl_ctx, data->conn) > 1) { 486214501Srpaulo wpa_printf(MSG_INFO, "SSL: Locally detected fatal error in " 487214501Srpaulo "TLS processing"); 488214501Srpaulo res = -1; 489214501Srpaulo } 490214501Srpaulo 491214501Srpaulodone: 492214501Srpaulo eap_server_tls_free_in_buf(data); 493214501Srpaulo 494214501Srpaulo return res; 495214501Srpaulo} 496