139beb93cSSam Leffler /* 239beb93cSSam Leffler * TLSv1 client - read handshake message 3*780fb4a2SCy Schubert * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6f05cddf9SRui Paulo * See README for more details. 739beb93cSSam Leffler */ 839beb93cSSam Leffler 939beb93cSSam Leffler #include "includes.h" 1039beb93cSSam Leffler 1139beb93cSSam Leffler #include "common.h" 12e28a4053SRui Paulo #include "crypto/md5.h" 13e28a4053SRui Paulo #include "crypto/sha1.h" 14f05cddf9SRui Paulo #include "crypto/sha256.h" 15e28a4053SRui Paulo #include "crypto/tls.h" 1639beb93cSSam Leffler #include "x509v3.h" 1739beb93cSSam Leffler #include "tlsv1_common.h" 1839beb93cSSam Leffler #include "tlsv1_record.h" 1939beb93cSSam Leffler #include "tlsv1_client.h" 2039beb93cSSam Leffler #include "tlsv1_client_i.h" 2139beb93cSSam Leffler 2239beb93cSSam Leffler static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct, 2339beb93cSSam Leffler const u8 *in_data, size_t *in_len); 2439beb93cSSam Leffler static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct, 2539beb93cSSam Leffler const u8 *in_data, size_t *in_len); 2639beb93cSSam Leffler static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct, 2739beb93cSSam Leffler const u8 *in_data, size_t *in_len); 2839beb93cSSam Leffler 2939beb93cSSam Leffler 30*780fb4a2SCy Schubert static int tls_version_disabled(struct tlsv1_client *conn, u16 ver) 31*780fb4a2SCy Schubert { 32*780fb4a2SCy Schubert return (((conn->flags & TLS_CONN_DISABLE_TLSv1_0) && 33*780fb4a2SCy Schubert ver == TLS_VERSION_1) || 34*780fb4a2SCy Schubert ((conn->flags & TLS_CONN_DISABLE_TLSv1_1) && 35*780fb4a2SCy Schubert ver == TLS_VERSION_1_1) || 36*780fb4a2SCy Schubert ((conn->flags & TLS_CONN_DISABLE_TLSv1_2) && 37*780fb4a2SCy Schubert ver == TLS_VERSION_1_2)); 38*780fb4a2SCy Schubert } 39*780fb4a2SCy Schubert 40*780fb4a2SCy Schubert 41*780fb4a2SCy Schubert static int tls_process_server_hello_extensions(struct tlsv1_client *conn, 42*780fb4a2SCy Schubert const u8 *pos, size_t len) 43*780fb4a2SCy Schubert { 44*780fb4a2SCy Schubert const u8 *end = pos + len; 45*780fb4a2SCy Schubert 46*780fb4a2SCy Schubert wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello extensions", 47*780fb4a2SCy Schubert pos, len); 48*780fb4a2SCy Schubert while (pos < end) { 49*780fb4a2SCy Schubert u16 ext, elen; 50*780fb4a2SCy Schubert 51*780fb4a2SCy Schubert if (end - pos < 4) { 52*780fb4a2SCy Schubert wpa_printf(MSG_INFO, "TLSv1: Truncated ServerHello extension header"); 53*780fb4a2SCy Schubert return -1; 54*780fb4a2SCy Schubert } 55*780fb4a2SCy Schubert 56*780fb4a2SCy Schubert ext = WPA_GET_BE16(pos); 57*780fb4a2SCy Schubert pos += 2; 58*780fb4a2SCy Schubert elen = WPA_GET_BE16(pos); 59*780fb4a2SCy Schubert pos += 2; 60*780fb4a2SCy Schubert 61*780fb4a2SCy Schubert if (elen > end - pos) { 62*780fb4a2SCy Schubert wpa_printf(MSG_INFO, "TLSv1: Truncated ServerHello extension"); 63*780fb4a2SCy Schubert return -1; 64*780fb4a2SCy Schubert } 65*780fb4a2SCy Schubert 66*780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, "TLSv1: ServerHello ExtensionType %u", 67*780fb4a2SCy Schubert ext); 68*780fb4a2SCy Schubert wpa_hexdump(MSG_DEBUG, "TLSv1: ServerHello extension data", 69*780fb4a2SCy Schubert pos, elen); 70*780fb4a2SCy Schubert 71*780fb4a2SCy Schubert pos += elen; 72*780fb4a2SCy Schubert } 73*780fb4a2SCy Schubert 74*780fb4a2SCy Schubert return 0; 75*780fb4a2SCy Schubert } 76*780fb4a2SCy Schubert 77*780fb4a2SCy Schubert 7839beb93cSSam Leffler static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct, 7939beb93cSSam Leffler const u8 *in_data, size_t *in_len) 8039beb93cSSam Leffler { 8139beb93cSSam Leffler const u8 *pos, *end; 8239beb93cSSam Leffler size_t left, len, i; 8339beb93cSSam Leffler u16 cipher_suite; 84f05cddf9SRui Paulo u16 tls_version; 8539beb93cSSam Leffler 8639beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 8739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " 8839beb93cSSam Leffler "received content type 0x%x", ct); 8939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 9039beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 9139beb93cSSam Leffler return -1; 9239beb93cSSam Leffler } 9339beb93cSSam Leffler 9439beb93cSSam Leffler pos = in_data; 9539beb93cSSam Leffler left = *in_len; 9639beb93cSSam Leffler 9739beb93cSSam Leffler if (left < 4) 9839beb93cSSam Leffler goto decode_error; 9939beb93cSSam Leffler 10039beb93cSSam Leffler /* HandshakeType msg_type */ 10139beb93cSSam Leffler if (*pos != TLS_HANDSHAKE_TYPE_SERVER_HELLO) { 10239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " 10339beb93cSSam Leffler "message %d (expected ServerHello)", *pos); 10439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 10539beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 10639beb93cSSam Leffler return -1; 10739beb93cSSam Leffler } 10839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHello"); 10939beb93cSSam Leffler pos++; 11039beb93cSSam Leffler /* uint24 length */ 11139beb93cSSam Leffler len = WPA_GET_BE24(pos); 11239beb93cSSam Leffler pos += 3; 11339beb93cSSam Leffler left -= 4; 11439beb93cSSam Leffler 11539beb93cSSam Leffler if (len > left) 11639beb93cSSam Leffler goto decode_error; 11739beb93cSSam Leffler 11839beb93cSSam Leffler /* body - ServerHello */ 11939beb93cSSam Leffler 12039beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello", pos, len); 12139beb93cSSam Leffler end = pos + len; 12239beb93cSSam Leffler 12339beb93cSSam Leffler /* ProtocolVersion server_version */ 12439beb93cSSam Leffler if (end - pos < 2) 12539beb93cSSam Leffler goto decode_error; 126f05cddf9SRui Paulo tls_version = WPA_GET_BE16(pos); 127*780fb4a2SCy Schubert if (!tls_version_ok(tls_version) || 128*780fb4a2SCy Schubert tls_version_disabled(conn, tls_version)) { 12939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in " 130f05cddf9SRui Paulo "ServerHello %u.%u", pos[0], pos[1]); 13139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 13239beb93cSSam Leffler TLS_ALERT_PROTOCOL_VERSION); 13339beb93cSSam Leffler return -1; 13439beb93cSSam Leffler } 13539beb93cSSam Leffler pos += 2; 13639beb93cSSam Leffler 137f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "TLSv1: Using TLS v%s", 138f05cddf9SRui Paulo tls_version_str(tls_version)); 139f05cddf9SRui Paulo conn->rl.tls_version = tls_version; 140f05cddf9SRui Paulo 14139beb93cSSam Leffler /* Random random */ 14239beb93cSSam Leffler if (end - pos < TLS_RANDOM_LEN) 14339beb93cSSam Leffler goto decode_error; 14439beb93cSSam Leffler 14539beb93cSSam Leffler os_memcpy(conn->server_random, pos, TLS_RANDOM_LEN); 14639beb93cSSam Leffler pos += TLS_RANDOM_LEN; 14739beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random", 14839beb93cSSam Leffler conn->server_random, TLS_RANDOM_LEN); 14939beb93cSSam Leffler 15039beb93cSSam Leffler /* SessionID session_id */ 15139beb93cSSam Leffler if (end - pos < 1) 15239beb93cSSam Leffler goto decode_error; 15339beb93cSSam Leffler if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN) 15439beb93cSSam Leffler goto decode_error; 15539beb93cSSam Leffler if (conn->session_id_len && conn->session_id_len == *pos && 15639beb93cSSam Leffler os_memcmp(conn->session_id, pos + 1, conn->session_id_len) == 0) { 15739beb93cSSam Leffler pos += 1 + conn->session_id_len; 15839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Resuming old session"); 15939beb93cSSam Leffler conn->session_resumed = 1; 16039beb93cSSam Leffler } else { 16139beb93cSSam Leffler conn->session_id_len = *pos; 16239beb93cSSam Leffler pos++; 16339beb93cSSam Leffler os_memcpy(conn->session_id, pos, conn->session_id_len); 16439beb93cSSam Leffler pos += conn->session_id_len; 16539beb93cSSam Leffler } 16639beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id", 16739beb93cSSam Leffler conn->session_id, conn->session_id_len); 16839beb93cSSam Leffler 16939beb93cSSam Leffler /* CipherSuite cipher_suite */ 17039beb93cSSam Leffler if (end - pos < 2) 17139beb93cSSam Leffler goto decode_error; 17239beb93cSSam Leffler cipher_suite = WPA_GET_BE16(pos); 17339beb93cSSam Leffler pos += 2; 17439beb93cSSam Leffler for (i = 0; i < conn->num_cipher_suites; i++) { 17539beb93cSSam Leffler if (cipher_suite == conn->cipher_suites[i]) 17639beb93cSSam Leffler break; 17739beb93cSSam Leffler } 17839beb93cSSam Leffler if (i == conn->num_cipher_suites) { 17939beb93cSSam Leffler wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected " 18039beb93cSSam Leffler "cipher suite 0x%04x", cipher_suite); 18139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 18239beb93cSSam Leffler TLS_ALERT_ILLEGAL_PARAMETER); 18339beb93cSSam Leffler return -1; 18439beb93cSSam Leffler } 18539beb93cSSam Leffler 18639beb93cSSam Leffler if (conn->session_resumed && cipher_suite != conn->prev_cipher_suite) { 18739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Server selected a different " 18839beb93cSSam Leffler "cipher suite for a resumed connection (0x%04x != " 18939beb93cSSam Leffler "0x%04x)", cipher_suite, conn->prev_cipher_suite); 19039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 19139beb93cSSam Leffler TLS_ALERT_ILLEGAL_PARAMETER); 19239beb93cSSam Leffler return -1; 19339beb93cSSam Leffler } 19439beb93cSSam Leffler 19539beb93cSSam Leffler if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) { 19639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for " 19739beb93cSSam Leffler "record layer"); 19839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 19939beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 20039beb93cSSam Leffler return -1; 20139beb93cSSam Leffler } 20239beb93cSSam Leffler 20339beb93cSSam Leffler conn->prev_cipher_suite = cipher_suite; 20439beb93cSSam Leffler 20539beb93cSSam Leffler /* CompressionMethod compression_method */ 20639beb93cSSam Leffler if (end - pos < 1) 20739beb93cSSam Leffler goto decode_error; 20839beb93cSSam Leffler if (*pos != TLS_COMPRESSION_NULL) { 20939beb93cSSam Leffler wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected " 21039beb93cSSam Leffler "compression 0x%02x", *pos); 21139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 21239beb93cSSam Leffler TLS_ALERT_ILLEGAL_PARAMETER); 21339beb93cSSam Leffler return -1; 21439beb93cSSam Leffler } 21539beb93cSSam Leffler pos++; 21639beb93cSSam Leffler 217*780fb4a2SCy Schubert if (end - pos >= 2) { 218*780fb4a2SCy Schubert u16 ext_len; 219*780fb4a2SCy Schubert 220*780fb4a2SCy Schubert ext_len = WPA_GET_BE16(pos); 221*780fb4a2SCy Schubert pos += 2; 222*780fb4a2SCy Schubert if (end - pos < ext_len) { 223*780fb4a2SCy Schubert wpa_printf(MSG_INFO, 224*780fb4a2SCy Schubert "TLSv1: Invalid ServerHello extension length: %u (left: %u)", 225*780fb4a2SCy Schubert ext_len, (unsigned int) (end - pos)); 226*780fb4a2SCy Schubert goto decode_error; 227*780fb4a2SCy Schubert } 228*780fb4a2SCy Schubert 229*780fb4a2SCy Schubert if (tls_process_server_hello_extensions(conn, pos, ext_len)) 230*780fb4a2SCy Schubert goto decode_error; 231*780fb4a2SCy Schubert pos += ext_len; 232*780fb4a2SCy Schubert } 233*780fb4a2SCy Schubert 23439beb93cSSam Leffler if (end != pos) { 23539beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: Unexpected extra data in the " 23639beb93cSSam Leffler "end of ServerHello", pos, end - pos); 23739beb93cSSam Leffler goto decode_error; 23839beb93cSSam Leffler } 23939beb93cSSam Leffler 24039beb93cSSam Leffler if (conn->session_ticket_included && conn->session_ticket_cb) { 24139beb93cSSam Leffler /* TODO: include SessionTicket extension if one was included in 24239beb93cSSam Leffler * ServerHello */ 24339beb93cSSam Leffler int res = conn->session_ticket_cb( 24439beb93cSSam Leffler conn->session_ticket_cb_ctx, NULL, 0, 24539beb93cSSam Leffler conn->client_random, conn->server_random, 24639beb93cSSam Leffler conn->master_secret); 24739beb93cSSam Leffler if (res < 0) { 24839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback " 24939beb93cSSam Leffler "indicated failure"); 25039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 25139beb93cSSam Leffler TLS_ALERT_HANDSHAKE_FAILURE); 25239beb93cSSam Leffler return -1; 25339beb93cSSam Leffler } 25439beb93cSSam Leffler conn->use_session_ticket = !!res; 25539beb93cSSam Leffler } 25639beb93cSSam Leffler 25739beb93cSSam Leffler if ((conn->session_resumed || conn->use_session_ticket) && 25839beb93cSSam Leffler tls_derive_keys(conn, NULL, 0)) { 25939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); 26039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 26139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 26239beb93cSSam Leffler return -1; 26339beb93cSSam Leffler } 26439beb93cSSam Leffler 26539beb93cSSam Leffler *in_len = end - in_data; 26639beb93cSSam Leffler 26739beb93cSSam Leffler conn->state = (conn->session_resumed || conn->use_session_ticket) ? 26839beb93cSSam Leffler SERVER_CHANGE_CIPHER_SPEC : SERVER_CERTIFICATE; 26939beb93cSSam Leffler 27039beb93cSSam Leffler return 0; 27139beb93cSSam Leffler 27239beb93cSSam Leffler decode_error: 27339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ServerHello"); 27439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 27539beb93cSSam Leffler return -1; 27639beb93cSSam Leffler } 27739beb93cSSam Leffler 27839beb93cSSam Leffler 279*780fb4a2SCy Schubert static void tls_peer_cert_event(struct tlsv1_client *conn, int depth, 280*780fb4a2SCy Schubert struct x509_certificate *cert) 281*780fb4a2SCy Schubert { 282*780fb4a2SCy Schubert union tls_event_data ev; 283*780fb4a2SCy Schubert struct wpabuf *cert_buf = NULL; 284*780fb4a2SCy Schubert #ifdef CONFIG_SHA256 285*780fb4a2SCy Schubert u8 hash[32]; 286*780fb4a2SCy Schubert #endif /* CONFIG_SHA256 */ 287*780fb4a2SCy Schubert char subject[128]; 288*780fb4a2SCy Schubert 289*780fb4a2SCy Schubert if (!conn->event_cb) 290*780fb4a2SCy Schubert return; 291*780fb4a2SCy Schubert 292*780fb4a2SCy Schubert os_memset(&ev, 0, sizeof(ev)); 293*780fb4a2SCy Schubert if (conn->cred->cert_probe || conn->cert_in_cb) { 294*780fb4a2SCy Schubert cert_buf = wpabuf_alloc_copy(cert->cert_start, 295*780fb4a2SCy Schubert cert->cert_len); 296*780fb4a2SCy Schubert ev.peer_cert.cert = cert_buf; 297*780fb4a2SCy Schubert } 298*780fb4a2SCy Schubert #ifdef CONFIG_SHA256 299*780fb4a2SCy Schubert if (cert_buf) { 300*780fb4a2SCy Schubert const u8 *addr[1]; 301*780fb4a2SCy Schubert size_t len[1]; 302*780fb4a2SCy Schubert addr[0] = wpabuf_head(cert_buf); 303*780fb4a2SCy Schubert len[0] = wpabuf_len(cert_buf); 304*780fb4a2SCy Schubert if (sha256_vector(1, addr, len, hash) == 0) { 305*780fb4a2SCy Schubert ev.peer_cert.hash = hash; 306*780fb4a2SCy Schubert ev.peer_cert.hash_len = sizeof(hash); 307*780fb4a2SCy Schubert } 308*780fb4a2SCy Schubert } 309*780fb4a2SCy Schubert #endif /* CONFIG_SHA256 */ 310*780fb4a2SCy Schubert 311*780fb4a2SCy Schubert ev.peer_cert.depth = depth; 312*780fb4a2SCy Schubert x509_name_string(&cert->subject, subject, sizeof(subject)); 313*780fb4a2SCy Schubert ev.peer_cert.subject = subject; 314*780fb4a2SCy Schubert 315*780fb4a2SCy Schubert conn->event_cb(conn->cb_ctx, TLS_PEER_CERTIFICATE, &ev); 316*780fb4a2SCy Schubert wpabuf_free(cert_buf); 317*780fb4a2SCy Schubert } 318*780fb4a2SCy Schubert 319*780fb4a2SCy Schubert 320*780fb4a2SCy Schubert static void tls_cert_chain_failure_event(struct tlsv1_client *conn, int depth, 321*780fb4a2SCy Schubert struct x509_certificate *cert, 322*780fb4a2SCy Schubert enum tls_fail_reason reason, 323*780fb4a2SCy Schubert const char *reason_txt) 324*780fb4a2SCy Schubert { 325*780fb4a2SCy Schubert struct wpabuf *cert_buf = NULL; 326*780fb4a2SCy Schubert union tls_event_data ev; 327*780fb4a2SCy Schubert char subject[128]; 328*780fb4a2SCy Schubert 329*780fb4a2SCy Schubert if (!conn->event_cb || !cert) 330*780fb4a2SCy Schubert return; 331*780fb4a2SCy Schubert 332*780fb4a2SCy Schubert os_memset(&ev, 0, sizeof(ev)); 333*780fb4a2SCy Schubert ev.cert_fail.depth = depth; 334*780fb4a2SCy Schubert x509_name_string(&cert->subject, subject, sizeof(subject)); 335*780fb4a2SCy Schubert ev.peer_cert.subject = subject; 336*780fb4a2SCy Schubert ev.cert_fail.reason = reason; 337*780fb4a2SCy Schubert ev.cert_fail.reason_txt = reason_txt; 338*780fb4a2SCy Schubert cert_buf = wpabuf_alloc_copy(cert->cert_start, 339*780fb4a2SCy Schubert cert->cert_len); 340*780fb4a2SCy Schubert ev.cert_fail.cert = cert_buf; 341*780fb4a2SCy Schubert conn->event_cb(conn->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev); 342*780fb4a2SCy Schubert wpabuf_free(cert_buf); 343*780fb4a2SCy Schubert } 344*780fb4a2SCy Schubert 345*780fb4a2SCy Schubert 34639beb93cSSam Leffler static int tls_process_certificate(struct tlsv1_client *conn, u8 ct, 34739beb93cSSam Leffler const u8 *in_data, size_t *in_len) 34839beb93cSSam Leffler { 34939beb93cSSam Leffler const u8 *pos, *end; 35039beb93cSSam Leffler size_t left, len, list_len, cert_len, idx; 35139beb93cSSam Leffler u8 type; 35239beb93cSSam Leffler struct x509_certificate *chain = NULL, *last = NULL, *cert; 35339beb93cSSam Leffler int reason; 35439beb93cSSam Leffler 35539beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 35639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " 35739beb93cSSam Leffler "received content type 0x%x", ct); 35839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 35939beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 36039beb93cSSam Leffler return -1; 36139beb93cSSam Leffler } 36239beb93cSSam Leffler 36339beb93cSSam Leffler pos = in_data; 36439beb93cSSam Leffler left = *in_len; 36539beb93cSSam Leffler 36639beb93cSSam Leffler if (left < 4) { 36739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message " 36839beb93cSSam Leffler "(len=%lu)", (unsigned long) left); 36939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 37039beb93cSSam Leffler return -1; 37139beb93cSSam Leffler } 37239beb93cSSam Leffler 37339beb93cSSam Leffler type = *pos++; 37439beb93cSSam Leffler len = WPA_GET_BE24(pos); 37539beb93cSSam Leffler pos += 3; 37639beb93cSSam Leffler left -= 4; 37739beb93cSSam Leffler 37839beb93cSSam Leffler if (len > left) { 37939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message " 38039beb93cSSam Leffler "length (len=%lu != left=%lu)", 38139beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 38239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 38339beb93cSSam Leffler return -1; 38439beb93cSSam Leffler } 38539beb93cSSam Leffler 38639beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) 38739beb93cSSam Leffler return tls_process_server_key_exchange(conn, ct, in_data, 38839beb93cSSam Leffler in_len); 38939beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) 39039beb93cSSam Leffler return tls_process_certificate_request(conn, ct, in_data, 39139beb93cSSam Leffler in_len); 39239beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) 39339beb93cSSam Leffler return tls_process_server_hello_done(conn, ct, in_data, 39439beb93cSSam Leffler in_len); 39539beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) { 39639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " 39739beb93cSSam Leffler "message %d (expected Certificate/" 39839beb93cSSam Leffler "ServerKeyExchange/CertificateRequest/" 39939beb93cSSam Leffler "ServerHelloDone)", type); 40039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 40139beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 40239beb93cSSam Leffler return -1; 40339beb93cSSam Leffler } 40439beb93cSSam Leffler 40539beb93cSSam Leffler wpa_printf(MSG_DEBUG, 40639beb93cSSam Leffler "TLSv1: Received Certificate (certificate_list len %lu)", 40739beb93cSSam Leffler (unsigned long) len); 40839beb93cSSam Leffler 40939beb93cSSam Leffler /* 41039beb93cSSam Leffler * opaque ASN.1Cert<2^24-1>; 41139beb93cSSam Leffler * 41239beb93cSSam Leffler * struct { 41339beb93cSSam Leffler * ASN.1Cert certificate_list<1..2^24-1>; 41439beb93cSSam Leffler * } Certificate; 41539beb93cSSam Leffler */ 41639beb93cSSam Leffler 41739beb93cSSam Leffler end = pos + len; 41839beb93cSSam Leffler 41939beb93cSSam Leffler if (end - pos < 3) { 42039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate " 42139beb93cSSam Leffler "(left=%lu)", (unsigned long) left); 42239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 42339beb93cSSam Leffler return -1; 42439beb93cSSam Leffler } 42539beb93cSSam Leffler 42639beb93cSSam Leffler list_len = WPA_GET_BE24(pos); 42739beb93cSSam Leffler pos += 3; 42839beb93cSSam Leffler 42939beb93cSSam Leffler if ((size_t) (end - pos) != list_len) { 43039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list " 43139beb93cSSam Leffler "length (len=%lu left=%lu)", 43239beb93cSSam Leffler (unsigned long) list_len, 43339beb93cSSam Leffler (unsigned long) (end - pos)); 43439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 43539beb93cSSam Leffler return -1; 43639beb93cSSam Leffler } 43739beb93cSSam Leffler 43839beb93cSSam Leffler idx = 0; 43939beb93cSSam Leffler while (pos < end) { 44039beb93cSSam Leffler if (end - pos < 3) { 44139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " 44239beb93cSSam Leffler "certificate_list"); 44339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 44439beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 44539beb93cSSam Leffler x509_certificate_chain_free(chain); 44639beb93cSSam Leffler return -1; 44739beb93cSSam Leffler } 44839beb93cSSam Leffler 44939beb93cSSam Leffler cert_len = WPA_GET_BE24(pos); 45039beb93cSSam Leffler pos += 3; 45139beb93cSSam Leffler 45239beb93cSSam Leffler if ((size_t) (end - pos) < cert_len) { 45339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate " 45439beb93cSSam Leffler "length (len=%lu left=%lu)", 45539beb93cSSam Leffler (unsigned long) cert_len, 45639beb93cSSam Leffler (unsigned long) (end - pos)); 45739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 45839beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 45939beb93cSSam Leffler x509_certificate_chain_free(chain); 46039beb93cSSam Leffler return -1; 46139beb93cSSam Leffler } 46239beb93cSSam Leffler 46339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)", 46439beb93cSSam Leffler (unsigned long) idx, (unsigned long) cert_len); 46539beb93cSSam Leffler 46639beb93cSSam Leffler if (idx == 0) { 46739beb93cSSam Leffler crypto_public_key_free(conn->server_rsa_key); 46839beb93cSSam Leffler if (tls_parse_cert(pos, cert_len, 46939beb93cSSam Leffler &conn->server_rsa_key)) { 47039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " 47139beb93cSSam Leffler "the certificate"); 47239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 47339beb93cSSam Leffler TLS_ALERT_BAD_CERTIFICATE); 47439beb93cSSam Leffler x509_certificate_chain_free(chain); 47539beb93cSSam Leffler return -1; 47639beb93cSSam Leffler } 47739beb93cSSam Leffler } 47839beb93cSSam Leffler 47939beb93cSSam Leffler cert = x509_certificate_parse(pos, cert_len); 48039beb93cSSam Leffler if (cert == NULL) { 48139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " 48239beb93cSSam Leffler "the certificate"); 48339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 48439beb93cSSam Leffler TLS_ALERT_BAD_CERTIFICATE); 48539beb93cSSam Leffler x509_certificate_chain_free(chain); 48639beb93cSSam Leffler return -1; 48739beb93cSSam Leffler } 48839beb93cSSam Leffler 489*780fb4a2SCy Schubert tls_peer_cert_event(conn, idx, cert); 490*780fb4a2SCy Schubert 49139beb93cSSam Leffler if (last == NULL) 49239beb93cSSam Leffler chain = cert; 49339beb93cSSam Leffler else 49439beb93cSSam Leffler last->next = cert; 49539beb93cSSam Leffler last = cert; 49639beb93cSSam Leffler 49739beb93cSSam Leffler idx++; 49839beb93cSSam Leffler pos += cert_len; 49939beb93cSSam Leffler } 50039beb93cSSam Leffler 501*780fb4a2SCy Schubert if (conn->cred && conn->cred->server_cert_only && chain) { 502*780fb4a2SCy Schubert u8 hash[SHA256_MAC_LEN]; 503*780fb4a2SCy Schubert char buf[128]; 504*780fb4a2SCy Schubert 505*780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 506*780fb4a2SCy Schubert "TLSv1: Validate server certificate hash"); 507*780fb4a2SCy Schubert x509_name_string(&chain->subject, buf, sizeof(buf)); 508*780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, "TLSv1: 0: %s", buf); 509*780fb4a2SCy Schubert if (sha256_vector(1, &chain->cert_start, &chain->cert_len, 510*780fb4a2SCy Schubert hash) < 0 || 511*780fb4a2SCy Schubert os_memcmp(conn->cred->srv_cert_hash, hash, 512*780fb4a2SCy Schubert SHA256_MAC_LEN) != 0) { 513*780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 514*780fb4a2SCy Schubert "TLSv1: Server certificate hash mismatch"); 515*780fb4a2SCy Schubert wpa_hexdump(MSG_MSGDUMP, "TLSv1: SHA256 hash", 516*780fb4a2SCy Schubert hash, SHA256_MAC_LEN); 517*780fb4a2SCy Schubert if (conn->event_cb) { 518*780fb4a2SCy Schubert union tls_event_data ev; 519*780fb4a2SCy Schubert 520*780fb4a2SCy Schubert os_memset(&ev, 0, sizeof(ev)); 521*780fb4a2SCy Schubert ev.cert_fail.reason = TLS_FAIL_UNSPECIFIED; 522*780fb4a2SCy Schubert ev.cert_fail.reason_txt = 523*780fb4a2SCy Schubert "Server certificate mismatch"; 524*780fb4a2SCy Schubert ev.cert_fail.subject = buf; 525*780fb4a2SCy Schubert conn->event_cb(conn->cb_ctx, 526*780fb4a2SCy Schubert TLS_CERT_CHAIN_FAILURE, &ev); 527*780fb4a2SCy Schubert } 528*780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 529*780fb4a2SCy Schubert TLS_ALERT_BAD_CERTIFICATE); 530*780fb4a2SCy Schubert x509_certificate_chain_free(chain); 531*780fb4a2SCy Schubert return -1; 532*780fb4a2SCy Schubert } 533*780fb4a2SCy Schubert } else if (conn->cred && conn->cred->cert_probe) { 534*780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 535*780fb4a2SCy Schubert "TLSv1: Reject server certificate on probe-only rune"); 536*780fb4a2SCy Schubert if (conn->event_cb) { 537*780fb4a2SCy Schubert union tls_event_data ev; 538*780fb4a2SCy Schubert char buf[128]; 539*780fb4a2SCy Schubert 540*780fb4a2SCy Schubert os_memset(&ev, 0, sizeof(ev)); 541*780fb4a2SCy Schubert ev.cert_fail.reason = TLS_FAIL_SERVER_CHAIN_PROBE; 542*780fb4a2SCy Schubert ev.cert_fail.reason_txt = 543*780fb4a2SCy Schubert "Server certificate chain probe"; 544*780fb4a2SCy Schubert if (chain) { 545*780fb4a2SCy Schubert x509_name_string(&chain->subject, buf, 546*780fb4a2SCy Schubert sizeof(buf)); 547*780fb4a2SCy Schubert ev.cert_fail.subject = buf; 548*780fb4a2SCy Schubert } 549*780fb4a2SCy Schubert conn->event_cb(conn->cb_ctx, TLS_CERT_CHAIN_FAILURE, 550*780fb4a2SCy Schubert &ev); 551*780fb4a2SCy Schubert } 552*780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 553*780fb4a2SCy Schubert TLS_ALERT_BAD_CERTIFICATE); 554*780fb4a2SCy Schubert x509_certificate_chain_free(chain); 555*780fb4a2SCy Schubert return -1; 556*780fb4a2SCy Schubert } else if (conn->cred && conn->cred->ca_cert_verify && 557*780fb4a2SCy Schubert x509_certificate_chain_validate( 558*780fb4a2SCy Schubert conn->cred->trusted_certs, chain, &reason, 559*780fb4a2SCy Schubert !!(conn->flags & TLS_CONN_DISABLE_TIME_CHECKS)) 560f05cddf9SRui Paulo < 0) { 56139beb93cSSam Leffler int tls_reason; 56239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain " 56339beb93cSSam Leffler "validation failed (reason=%d)", reason); 56439beb93cSSam Leffler switch (reason) { 56539beb93cSSam Leffler case X509_VALIDATE_BAD_CERTIFICATE: 56639beb93cSSam Leffler tls_reason = TLS_ALERT_BAD_CERTIFICATE; 567*780fb4a2SCy Schubert tls_cert_chain_failure_event( 568*780fb4a2SCy Schubert conn, 0, chain, TLS_FAIL_BAD_CERTIFICATE, 569*780fb4a2SCy Schubert "bad certificate"); 57039beb93cSSam Leffler break; 57139beb93cSSam Leffler case X509_VALIDATE_UNSUPPORTED_CERTIFICATE: 57239beb93cSSam Leffler tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE; 57339beb93cSSam Leffler break; 57439beb93cSSam Leffler case X509_VALIDATE_CERTIFICATE_REVOKED: 57539beb93cSSam Leffler tls_reason = TLS_ALERT_CERTIFICATE_REVOKED; 576*780fb4a2SCy Schubert tls_cert_chain_failure_event( 577*780fb4a2SCy Schubert conn, 0, chain, TLS_FAIL_REVOKED, 578*780fb4a2SCy Schubert "certificate revoked"); 57939beb93cSSam Leffler break; 58039beb93cSSam Leffler case X509_VALIDATE_CERTIFICATE_EXPIRED: 58139beb93cSSam Leffler tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED; 582*780fb4a2SCy Schubert tls_cert_chain_failure_event( 583*780fb4a2SCy Schubert conn, 0, chain, TLS_FAIL_EXPIRED, 584*780fb4a2SCy Schubert "certificate has expired or is not yet valid"); 58539beb93cSSam Leffler break; 58639beb93cSSam Leffler case X509_VALIDATE_CERTIFICATE_UNKNOWN: 58739beb93cSSam Leffler tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN; 58839beb93cSSam Leffler break; 58939beb93cSSam Leffler case X509_VALIDATE_UNKNOWN_CA: 59039beb93cSSam Leffler tls_reason = TLS_ALERT_UNKNOWN_CA; 591*780fb4a2SCy Schubert tls_cert_chain_failure_event( 592*780fb4a2SCy Schubert conn, 0, chain, TLS_FAIL_UNTRUSTED, 593*780fb4a2SCy Schubert "unknown CA"); 59439beb93cSSam Leffler break; 59539beb93cSSam Leffler default: 59639beb93cSSam Leffler tls_reason = TLS_ALERT_BAD_CERTIFICATE; 59739beb93cSSam Leffler break; 59839beb93cSSam Leffler } 59939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason); 60039beb93cSSam Leffler x509_certificate_chain_free(chain); 60139beb93cSSam Leffler return -1; 60239beb93cSSam Leffler } 60339beb93cSSam Leffler 604*780fb4a2SCy Schubert if (conn->cred && !conn->cred->server_cert_only && chain && 605*780fb4a2SCy Schubert (chain->extensions_present & X509_EXT_EXT_KEY_USAGE) && 606*780fb4a2SCy Schubert !(chain->ext_key_usage & 607*780fb4a2SCy Schubert (X509_EXT_KEY_USAGE_ANY | X509_EXT_KEY_USAGE_SERVER_AUTH))) { 608*780fb4a2SCy Schubert tls_cert_chain_failure_event( 609*780fb4a2SCy Schubert conn, 0, chain, TLS_FAIL_BAD_CERTIFICATE, 610*780fb4a2SCy Schubert "certificate not allowed for server authentication"); 611*780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 612*780fb4a2SCy Schubert TLS_ALERT_BAD_CERTIFICATE); 61339beb93cSSam Leffler x509_certificate_chain_free(chain); 614*780fb4a2SCy Schubert return -1; 615*780fb4a2SCy Schubert } 616*780fb4a2SCy Schubert 617*780fb4a2SCy Schubert if (conn->flags & TLS_CONN_REQUEST_OCSP) { 618*780fb4a2SCy Schubert x509_certificate_chain_free(conn->server_cert); 619*780fb4a2SCy Schubert conn->server_cert = chain; 620*780fb4a2SCy Schubert } else { 621*780fb4a2SCy Schubert x509_certificate_chain_free(chain); 622*780fb4a2SCy Schubert } 62339beb93cSSam Leffler 62439beb93cSSam Leffler *in_len = end - in_data; 62539beb93cSSam Leffler 62639beb93cSSam Leffler conn->state = SERVER_KEY_EXCHANGE; 62739beb93cSSam Leffler 62839beb93cSSam Leffler return 0; 62939beb93cSSam Leffler } 63039beb93cSSam Leffler 63139beb93cSSam Leffler 6325b9c547cSRui Paulo static unsigned int count_bits(const u8 *val, size_t len) 63339beb93cSSam Leffler { 6345b9c547cSRui Paulo size_t i; 6355b9c547cSRui Paulo unsigned int bits; 6365b9c547cSRui Paulo u8 tmp; 6375b9c547cSRui Paulo 6385b9c547cSRui Paulo for (i = 0; i < len; i++) { 6395b9c547cSRui Paulo if (val[i]) 6405b9c547cSRui Paulo break; 6415b9c547cSRui Paulo } 6425b9c547cSRui Paulo if (i == len) 6435b9c547cSRui Paulo return 0; 6445b9c547cSRui Paulo 6455b9c547cSRui Paulo bits = (len - i - 1) * 8; 6465b9c547cSRui Paulo tmp = val[i]; 6475b9c547cSRui Paulo while (tmp) { 6485b9c547cSRui Paulo bits++; 6495b9c547cSRui Paulo tmp >>= 1; 6505b9c547cSRui Paulo } 6515b9c547cSRui Paulo 6525b9c547cSRui Paulo return bits; 6535b9c547cSRui Paulo } 6545b9c547cSRui Paulo 6555b9c547cSRui Paulo 6565b9c547cSRui Paulo static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn, 6575b9c547cSRui Paulo const u8 *buf, size_t len, 6585b9c547cSRui Paulo tls_key_exchange key_exchange) 6595b9c547cSRui Paulo { 6605b9c547cSRui Paulo const u8 *pos, *end, *server_params, *server_params_end; 6615b9c547cSRui Paulo u8 alert; 6625b9c547cSRui Paulo unsigned int bits; 6635b9c547cSRui Paulo u16 val; 66439beb93cSSam Leffler 66539beb93cSSam Leffler tlsv1_client_free_dh(conn); 66639beb93cSSam Leffler 66739beb93cSSam Leffler pos = buf; 66839beb93cSSam Leffler end = buf + len; 66939beb93cSSam Leffler 67039beb93cSSam Leffler if (end - pos < 3) 67139beb93cSSam Leffler goto fail; 6725b9c547cSRui Paulo server_params = pos; 6735b9c547cSRui Paulo val = WPA_GET_BE16(pos); 67439beb93cSSam Leffler pos += 2; 6755b9c547cSRui Paulo if (val == 0 || val > (size_t) (end - pos)) { 6765b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "TLSv1: Invalid dh_p length %u", val); 6775b9c547cSRui Paulo goto fail; 6785b9c547cSRui Paulo } 6795b9c547cSRui Paulo conn->dh_p_len = val; 6805b9c547cSRui Paulo bits = count_bits(pos, conn->dh_p_len); 6815b9c547cSRui Paulo if (bits < 768) { 6825b9c547cSRui Paulo wpa_printf(MSG_INFO, "TLSv1: Reject under 768-bit DH prime (insecure; only %u bits)", 6835b9c547cSRui Paulo bits); 6845b9c547cSRui Paulo wpa_hexdump(MSG_DEBUG, "TLSv1: Rejected DH prime", 6855b9c547cSRui Paulo pos, conn->dh_p_len); 68639beb93cSSam Leffler goto fail; 68739beb93cSSam Leffler } 68839beb93cSSam Leffler conn->dh_p = os_malloc(conn->dh_p_len); 68939beb93cSSam Leffler if (conn->dh_p == NULL) 69039beb93cSSam Leffler goto fail; 69139beb93cSSam Leffler os_memcpy(conn->dh_p, pos, conn->dh_p_len); 69239beb93cSSam Leffler pos += conn->dh_p_len; 69339beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: DH p (prime)", 69439beb93cSSam Leffler conn->dh_p, conn->dh_p_len); 69539beb93cSSam Leffler 69639beb93cSSam Leffler if (end - pos < 3) 69739beb93cSSam Leffler goto fail; 6985b9c547cSRui Paulo val = WPA_GET_BE16(pos); 69939beb93cSSam Leffler pos += 2; 7005b9c547cSRui Paulo if (val == 0 || val > (size_t) (end - pos)) 70139beb93cSSam Leffler goto fail; 7025b9c547cSRui Paulo conn->dh_g_len = val; 70339beb93cSSam Leffler conn->dh_g = os_malloc(conn->dh_g_len); 70439beb93cSSam Leffler if (conn->dh_g == NULL) 70539beb93cSSam Leffler goto fail; 70639beb93cSSam Leffler os_memcpy(conn->dh_g, pos, conn->dh_g_len); 70739beb93cSSam Leffler pos += conn->dh_g_len; 70839beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: DH g (generator)", 70939beb93cSSam Leffler conn->dh_g, conn->dh_g_len); 71039beb93cSSam Leffler if (conn->dh_g_len == 1 && conn->dh_g[0] < 2) 71139beb93cSSam Leffler goto fail; 71239beb93cSSam Leffler 71339beb93cSSam Leffler if (end - pos < 3) 71439beb93cSSam Leffler goto fail; 7155b9c547cSRui Paulo val = WPA_GET_BE16(pos); 71639beb93cSSam Leffler pos += 2; 7175b9c547cSRui Paulo if (val == 0 || val > (size_t) (end - pos)) 71839beb93cSSam Leffler goto fail; 7195b9c547cSRui Paulo conn->dh_ys_len = val; 72039beb93cSSam Leffler conn->dh_ys = os_malloc(conn->dh_ys_len); 72139beb93cSSam Leffler if (conn->dh_ys == NULL) 72239beb93cSSam Leffler goto fail; 72339beb93cSSam Leffler os_memcpy(conn->dh_ys, pos, conn->dh_ys_len); 72439beb93cSSam Leffler pos += conn->dh_ys_len; 72539beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)", 72639beb93cSSam Leffler conn->dh_ys, conn->dh_ys_len); 7275b9c547cSRui Paulo server_params_end = pos; 7285b9c547cSRui Paulo 7295b9c547cSRui Paulo if (key_exchange == TLS_KEY_X_DHE_RSA) { 730*780fb4a2SCy Schubert u8 hash[64]; 7315b9c547cSRui Paulo int hlen; 7325b9c547cSRui Paulo 7335b9c547cSRui Paulo if (conn->rl.tls_version == TLS_VERSION_1_2) { 7345b9c547cSRui Paulo #ifdef CONFIG_TLSV12 7355b9c547cSRui Paulo /* 7365b9c547cSRui Paulo * RFC 5246, 4.7: 7375b9c547cSRui Paulo * TLS v1.2 adds explicit indication of the used 7385b9c547cSRui Paulo * signature and hash algorithms. 7395b9c547cSRui Paulo * 7405b9c547cSRui Paulo * struct { 7415b9c547cSRui Paulo * HashAlgorithm hash; 7425b9c547cSRui Paulo * SignatureAlgorithm signature; 7435b9c547cSRui Paulo * } SignatureAndHashAlgorithm; 7445b9c547cSRui Paulo */ 7455b9c547cSRui Paulo if (end - pos < 2) 7465b9c547cSRui Paulo goto fail; 747*780fb4a2SCy Schubert if ((pos[0] != TLS_HASH_ALG_SHA256 && 748*780fb4a2SCy Schubert pos[0] != TLS_HASH_ALG_SHA384 && 749*780fb4a2SCy Schubert pos[0] != TLS_HASH_ALG_SHA512) || 7505b9c547cSRui Paulo pos[1] != TLS_SIGN_ALG_RSA) { 7515b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/signature(%u) algorithm", 7525b9c547cSRui Paulo pos[0], pos[1]); 7535b9c547cSRui Paulo goto fail; 7545b9c547cSRui Paulo } 7555b9c547cSRui Paulo 7565b9c547cSRui Paulo hlen = tlsv12_key_x_server_params_hash( 757*780fb4a2SCy Schubert conn->rl.tls_version, pos[0], 758*780fb4a2SCy Schubert conn->client_random, 7595b9c547cSRui Paulo conn->server_random, server_params, 7605b9c547cSRui Paulo server_params_end - server_params, hash); 761*780fb4a2SCy Schubert pos += 2; 7625b9c547cSRui Paulo #else /* CONFIG_TLSV12 */ 7635b9c547cSRui Paulo goto fail; 7645b9c547cSRui Paulo #endif /* CONFIG_TLSV12 */ 7655b9c547cSRui Paulo } else { 7665b9c547cSRui Paulo hlen = tls_key_x_server_params_hash( 7675b9c547cSRui Paulo conn->rl.tls_version, conn->client_random, 7685b9c547cSRui Paulo conn->server_random, server_params, 7695b9c547cSRui Paulo server_params_end - server_params, hash); 7705b9c547cSRui Paulo } 7715b9c547cSRui Paulo 7725b9c547cSRui Paulo if (hlen < 0) 7735b9c547cSRui Paulo goto fail; 7745b9c547cSRui Paulo wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerKeyExchange hash", 7755b9c547cSRui Paulo hash, hlen); 7765b9c547cSRui Paulo 7775b9c547cSRui Paulo if (tls_verify_signature(conn->rl.tls_version, 7785b9c547cSRui Paulo conn->server_rsa_key, 7795b9c547cSRui Paulo hash, hlen, pos, end - pos, 7805b9c547cSRui Paulo &alert) < 0) 7815b9c547cSRui Paulo goto fail; 7825b9c547cSRui Paulo } 78339beb93cSSam Leffler 78439beb93cSSam Leffler return 0; 78539beb93cSSam Leffler 78639beb93cSSam Leffler fail: 78739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Processing DH params failed"); 78839beb93cSSam Leffler tlsv1_client_free_dh(conn); 78939beb93cSSam Leffler return -1; 79039beb93cSSam Leffler } 79139beb93cSSam Leffler 79239beb93cSSam Leffler 793*780fb4a2SCy Schubert static enum tls_ocsp_result 794*780fb4a2SCy Schubert tls_process_certificate_status_ocsp_response(struct tlsv1_client *conn, 795*780fb4a2SCy Schubert const u8 *pos, size_t len) 796*780fb4a2SCy Schubert { 797*780fb4a2SCy Schubert const u8 *end = pos + len; 798*780fb4a2SCy Schubert u32 ocsp_resp_len; 799*780fb4a2SCy Schubert 800*780fb4a2SCy Schubert /* opaque OCSPResponse<1..2^24-1>; */ 801*780fb4a2SCy Schubert if (end - pos < 3) { 802*780fb4a2SCy Schubert wpa_printf(MSG_INFO, "TLSv1: Too short OCSPResponse"); 803*780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 804*780fb4a2SCy Schubert return TLS_OCSP_INVALID; 805*780fb4a2SCy Schubert } 806*780fb4a2SCy Schubert ocsp_resp_len = WPA_GET_BE24(pos); 807*780fb4a2SCy Schubert pos += 3; 808*780fb4a2SCy Schubert if (end - pos < ocsp_resp_len) { 809*780fb4a2SCy Schubert wpa_printf(MSG_INFO, "TLSv1: Truncated OCSPResponse"); 810*780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 811*780fb4a2SCy Schubert return TLS_OCSP_INVALID; 812*780fb4a2SCy Schubert } 813*780fb4a2SCy Schubert 814*780fb4a2SCy Schubert return tls_process_ocsp_response(conn, pos, ocsp_resp_len); 815*780fb4a2SCy Schubert } 816*780fb4a2SCy Schubert 817*780fb4a2SCy Schubert 818*780fb4a2SCy Schubert static int tls_process_certificate_status(struct tlsv1_client *conn, u8 ct, 819*780fb4a2SCy Schubert const u8 *in_data, size_t *in_len) 820*780fb4a2SCy Schubert { 821*780fb4a2SCy Schubert const u8 *pos, *end; 822*780fb4a2SCy Schubert size_t left, len; 823*780fb4a2SCy Schubert u8 type, status_type; 824*780fb4a2SCy Schubert enum tls_ocsp_result res; 825*780fb4a2SCy Schubert struct x509_certificate *cert; 826*780fb4a2SCy Schubert int depth; 827*780fb4a2SCy Schubert 828*780fb4a2SCy Schubert if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 829*780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 830*780fb4a2SCy Schubert "TLSv1: Expected Handshake; received content type 0x%x", 831*780fb4a2SCy Schubert ct); 832*780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 833*780fb4a2SCy Schubert TLS_ALERT_UNEXPECTED_MESSAGE); 834*780fb4a2SCy Schubert return -1; 835*780fb4a2SCy Schubert } 836*780fb4a2SCy Schubert 837*780fb4a2SCy Schubert pos = in_data; 838*780fb4a2SCy Schubert left = *in_len; 839*780fb4a2SCy Schubert 840*780fb4a2SCy Schubert if (left < 4) { 841*780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 842*780fb4a2SCy Schubert "TLSv1: Too short CertificateStatus (left=%lu)", 843*780fb4a2SCy Schubert (unsigned long) left); 844*780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 845*780fb4a2SCy Schubert return -1; 846*780fb4a2SCy Schubert } 847*780fb4a2SCy Schubert 848*780fb4a2SCy Schubert type = *pos++; 849*780fb4a2SCy Schubert len = WPA_GET_BE24(pos); 850*780fb4a2SCy Schubert pos += 3; 851*780fb4a2SCy Schubert left -= 4; 852*780fb4a2SCy Schubert 853*780fb4a2SCy Schubert if (len > left) { 854*780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 855*780fb4a2SCy Schubert "TLSv1: Mismatch in CertificateStatus length (len=%lu != left=%lu)", 856*780fb4a2SCy Schubert (unsigned long) len, (unsigned long) left); 857*780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 858*780fb4a2SCy Schubert return -1; 859*780fb4a2SCy Schubert } 860*780fb4a2SCy Schubert 861*780fb4a2SCy Schubert end = pos + len; 862*780fb4a2SCy Schubert 863*780fb4a2SCy Schubert if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS) { 864*780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 865*780fb4a2SCy Schubert "TLSv1: Received unexpected handshake message %d (expected CertificateStatus)", 866*780fb4a2SCy Schubert type); 867*780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 868*780fb4a2SCy Schubert TLS_ALERT_UNEXPECTED_MESSAGE); 869*780fb4a2SCy Schubert return -1; 870*780fb4a2SCy Schubert } 871*780fb4a2SCy Schubert 872*780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateStatus"); 873*780fb4a2SCy Schubert 874*780fb4a2SCy Schubert /* 875*780fb4a2SCy Schubert * struct { 876*780fb4a2SCy Schubert * CertificateStatusType status_type; 877*780fb4a2SCy Schubert * select (status_type) { 878*780fb4a2SCy Schubert * case ocsp: OCSPResponse; 879*780fb4a2SCy Schubert * case ocsp_multi: OCSPResponseList; 880*780fb4a2SCy Schubert * } response; 881*780fb4a2SCy Schubert * } CertificateStatus; 882*780fb4a2SCy Schubert */ 883*780fb4a2SCy Schubert if (end - pos < 1) { 884*780fb4a2SCy Schubert wpa_printf(MSG_INFO, "TLSv1: Too short CertificateStatus"); 885*780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 886*780fb4a2SCy Schubert return -1; 887*780fb4a2SCy Schubert } 888*780fb4a2SCy Schubert status_type = *pos++; 889*780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, "TLSv1: CertificateStatus status_type %u", 890*780fb4a2SCy Schubert status_type); 891*780fb4a2SCy Schubert 892*780fb4a2SCy Schubert if (status_type == 1 /* ocsp */) { 893*780fb4a2SCy Schubert res = tls_process_certificate_status_ocsp_response( 894*780fb4a2SCy Schubert conn, pos, end - pos); 895*780fb4a2SCy Schubert } else if (status_type == 2 /* ocsp_multi */) { 896*780fb4a2SCy Schubert int good = 0, revoked = 0; 897*780fb4a2SCy Schubert u32 resp_len; 898*780fb4a2SCy Schubert 899*780fb4a2SCy Schubert res = TLS_OCSP_NO_RESPONSE; 900*780fb4a2SCy Schubert 901*780fb4a2SCy Schubert /* 902*780fb4a2SCy Schubert * opaque OCSPResponse<0..2^24-1>; 903*780fb4a2SCy Schubert * 904*780fb4a2SCy Schubert * struct { 905*780fb4a2SCy Schubert * OCSPResponse ocsp_response_list<1..2^24-1>; 906*780fb4a2SCy Schubert * } OCSPResponseList; 907*780fb4a2SCy Schubert */ 908*780fb4a2SCy Schubert if (end - pos < 3) { 909*780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 910*780fb4a2SCy Schubert "TLSv1: Truncated OCSPResponseList"); 911*780fb4a2SCy Schubert res = TLS_OCSP_INVALID; 912*780fb4a2SCy Schubert goto done; 913*780fb4a2SCy Schubert } 914*780fb4a2SCy Schubert resp_len = WPA_GET_BE24(pos); 915*780fb4a2SCy Schubert pos += 3; 916*780fb4a2SCy Schubert if (end - pos < resp_len) { 917*780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 918*780fb4a2SCy Schubert "TLSv1: Truncated OCSPResponseList(len=%u)", 919*780fb4a2SCy Schubert resp_len); 920*780fb4a2SCy Schubert res = TLS_OCSP_INVALID; 921*780fb4a2SCy Schubert goto done; 922*780fb4a2SCy Schubert } 923*780fb4a2SCy Schubert end = pos + resp_len; 924*780fb4a2SCy Schubert 925*780fb4a2SCy Schubert while (end - pos >= 3) { 926*780fb4a2SCy Schubert resp_len = WPA_GET_BE24(pos); 927*780fb4a2SCy Schubert pos += 3; 928*780fb4a2SCy Schubert if (resp_len > end - pos) { 929*780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 930*780fb4a2SCy Schubert "TLSv1: Truncated OCSPResponse(len=%u; left=%d) in ocsp_multi", 931*780fb4a2SCy Schubert resp_len, (int) (end - pos)); 932*780fb4a2SCy Schubert res = TLS_OCSP_INVALID; 933*780fb4a2SCy Schubert break; 934*780fb4a2SCy Schubert } 935*780fb4a2SCy Schubert if (!resp_len) 936*780fb4a2SCy Schubert continue; /* Skip an empty response */ 937*780fb4a2SCy Schubert res = tls_process_certificate_status_ocsp_response( 938*780fb4a2SCy Schubert conn, pos - 3, resp_len + 3); 939*780fb4a2SCy Schubert if (res == TLS_OCSP_REVOKED) 940*780fb4a2SCy Schubert revoked++; 941*780fb4a2SCy Schubert else if (res == TLS_OCSP_GOOD) 942*780fb4a2SCy Schubert good++; 943*780fb4a2SCy Schubert pos += resp_len; 944*780fb4a2SCy Schubert } 945*780fb4a2SCy Schubert 946*780fb4a2SCy Schubert if (revoked) 947*780fb4a2SCy Schubert res = TLS_OCSP_REVOKED; 948*780fb4a2SCy Schubert else if (good) 949*780fb4a2SCy Schubert res = TLS_OCSP_GOOD; 950*780fb4a2SCy Schubert } else { 951*780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 952*780fb4a2SCy Schubert "TLSv1: Ignore unsupported CertificateStatus"); 953*780fb4a2SCy Schubert goto skip; 954*780fb4a2SCy Schubert } 955*780fb4a2SCy Schubert 956*780fb4a2SCy Schubert done: 957*780fb4a2SCy Schubert if (res == TLS_OCSP_REVOKED) { 958*780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 959*780fb4a2SCy Schubert TLS_ALERT_CERTIFICATE_REVOKED); 960*780fb4a2SCy Schubert for (cert = conn->server_cert, depth = 0; cert; 961*780fb4a2SCy Schubert cert = cert->next, depth++) { 962*780fb4a2SCy Schubert if (cert->ocsp_revoked) { 963*780fb4a2SCy Schubert tls_cert_chain_failure_event( 964*780fb4a2SCy Schubert conn, depth, cert, TLS_FAIL_REVOKED, 965*780fb4a2SCy Schubert "certificate revoked"); 966*780fb4a2SCy Schubert } 967*780fb4a2SCy Schubert } 968*780fb4a2SCy Schubert return -1; 969*780fb4a2SCy Schubert } 970*780fb4a2SCy Schubert 971*780fb4a2SCy Schubert if (conn->flags & TLS_CONN_REQUIRE_OCSP_ALL) { 972*780fb4a2SCy Schubert /* 973*780fb4a2SCy Schubert * Verify that each certificate on the chain that is not part 974*780fb4a2SCy Schubert * of the trusted certificates has a good status. If not, 975*780fb4a2SCy Schubert * terminate handshake. 976*780fb4a2SCy Schubert */ 977*780fb4a2SCy Schubert for (cert = conn->server_cert, depth = 0; cert; 978*780fb4a2SCy Schubert cert = cert->next, depth++) { 979*780fb4a2SCy Schubert if (!cert->ocsp_good) { 980*780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 981*780fb4a2SCy Schubert TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE); 982*780fb4a2SCy Schubert tls_cert_chain_failure_event( 983*780fb4a2SCy Schubert conn, depth, cert, 984*780fb4a2SCy Schubert TLS_FAIL_UNSPECIFIED, 985*780fb4a2SCy Schubert "bad certificate status response"); 986*780fb4a2SCy Schubert return -1; 987*780fb4a2SCy Schubert } 988*780fb4a2SCy Schubert if (cert->issuer_trusted) 989*780fb4a2SCy Schubert break; 990*780fb4a2SCy Schubert } 991*780fb4a2SCy Schubert } 992*780fb4a2SCy Schubert 993*780fb4a2SCy Schubert if ((conn->flags & TLS_CONN_REQUIRE_OCSP) && res != TLS_OCSP_GOOD) { 994*780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 995*780fb4a2SCy Schubert res == TLS_OCSP_INVALID ? TLS_ALERT_DECODE_ERROR : 996*780fb4a2SCy Schubert TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE); 997*780fb4a2SCy Schubert if (conn->server_cert) 998*780fb4a2SCy Schubert tls_cert_chain_failure_event( 999*780fb4a2SCy Schubert conn, 0, conn->server_cert, 1000*780fb4a2SCy Schubert TLS_FAIL_UNSPECIFIED, 1001*780fb4a2SCy Schubert "bad certificate status response"); 1002*780fb4a2SCy Schubert return -1; 1003*780fb4a2SCy Schubert } 1004*780fb4a2SCy Schubert 1005*780fb4a2SCy Schubert conn->ocsp_resp_received = 1; 1006*780fb4a2SCy Schubert 1007*780fb4a2SCy Schubert skip: 1008*780fb4a2SCy Schubert *in_len = end - in_data; 1009*780fb4a2SCy Schubert 1010*780fb4a2SCy Schubert conn->state = SERVER_KEY_EXCHANGE; 1011*780fb4a2SCy Schubert 1012*780fb4a2SCy Schubert return 0; 1013*780fb4a2SCy Schubert } 1014*780fb4a2SCy Schubert 1015*780fb4a2SCy Schubert 101639beb93cSSam Leffler static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct, 101739beb93cSSam Leffler const u8 *in_data, size_t *in_len) 101839beb93cSSam Leffler { 101939beb93cSSam Leffler const u8 *pos, *end; 102039beb93cSSam Leffler size_t left, len; 102139beb93cSSam Leffler u8 type; 102239beb93cSSam Leffler const struct tls_cipher_suite *suite; 102339beb93cSSam Leffler 102439beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 102539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " 102639beb93cSSam Leffler "received content type 0x%x", ct); 102739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 102839beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 102939beb93cSSam Leffler return -1; 103039beb93cSSam Leffler } 103139beb93cSSam Leffler 103239beb93cSSam Leffler pos = in_data; 103339beb93cSSam Leffler left = *in_len; 103439beb93cSSam Leffler 103539beb93cSSam Leffler if (left < 4) { 103639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerKeyExchange " 103739beb93cSSam Leffler "(Left=%lu)", (unsigned long) left); 103839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 103939beb93cSSam Leffler return -1; 104039beb93cSSam Leffler } 104139beb93cSSam Leffler 104239beb93cSSam Leffler type = *pos++; 104339beb93cSSam Leffler len = WPA_GET_BE24(pos); 104439beb93cSSam Leffler pos += 3; 104539beb93cSSam Leffler left -= 4; 104639beb93cSSam Leffler 104739beb93cSSam Leffler if (len > left) { 104839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerKeyExchange " 104939beb93cSSam Leffler "length (len=%lu != left=%lu)", 105039beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 105139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 105239beb93cSSam Leffler return -1; 105339beb93cSSam Leffler } 105439beb93cSSam Leffler 105539beb93cSSam Leffler end = pos + len; 105639beb93cSSam Leffler 1057*780fb4a2SCy Schubert if ((conn->flags & TLS_CONN_REQUEST_OCSP) && 1058*780fb4a2SCy Schubert type == TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS) 1059*780fb4a2SCy Schubert return tls_process_certificate_status(conn, ct, in_data, 1060*780fb4a2SCy Schubert in_len); 106139beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) 106239beb93cSSam Leffler return tls_process_certificate_request(conn, ct, in_data, 106339beb93cSSam Leffler in_len); 106439beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) 106539beb93cSSam Leffler return tls_process_server_hello_done(conn, ct, in_data, 106639beb93cSSam Leffler in_len); 106739beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) { 106839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " 106939beb93cSSam Leffler "message %d (expected ServerKeyExchange/" 1070*780fb4a2SCy Schubert "CertificateRequest/ServerHelloDone%s)", type, 1071*780fb4a2SCy Schubert (conn->flags & TLS_CONN_REQUEST_OCSP) ? 1072*780fb4a2SCy Schubert "/CertificateStatus" : ""); 107339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 107439beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 107539beb93cSSam Leffler return -1; 107639beb93cSSam Leffler } 107739beb93cSSam Leffler 107839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received ServerKeyExchange"); 107939beb93cSSam Leffler 108039beb93cSSam Leffler if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) { 108139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not allowed " 108239beb93cSSam Leffler "with the selected cipher suite"); 108339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 108439beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 108539beb93cSSam Leffler return -1; 108639beb93cSSam Leffler } 108739beb93cSSam Leffler 108839beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: ServerKeyExchange", pos, len); 108939beb93cSSam Leffler suite = tls_get_cipher_suite(conn->rl.cipher_suite); 10905b9c547cSRui Paulo if (suite && (suite->key_exchange == TLS_KEY_X_DH_anon || 10915b9c547cSRui Paulo suite->key_exchange == TLS_KEY_X_DHE_RSA)) { 10925b9c547cSRui Paulo if (tlsv1_process_diffie_hellman(conn, pos, len, 10935b9c547cSRui Paulo suite->key_exchange) < 0) { 109439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 109539beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 109639beb93cSSam Leffler return -1; 109739beb93cSSam Leffler } 109839beb93cSSam Leffler } else { 109939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: UnexpectedServerKeyExchange"); 110039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 110139beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 110239beb93cSSam Leffler return -1; 110339beb93cSSam Leffler } 110439beb93cSSam Leffler 110539beb93cSSam Leffler *in_len = end - in_data; 110639beb93cSSam Leffler 110739beb93cSSam Leffler conn->state = SERVER_CERTIFICATE_REQUEST; 110839beb93cSSam Leffler 110939beb93cSSam Leffler return 0; 111039beb93cSSam Leffler } 111139beb93cSSam Leffler 111239beb93cSSam Leffler 111339beb93cSSam Leffler static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct, 111439beb93cSSam Leffler const u8 *in_data, size_t *in_len) 111539beb93cSSam Leffler { 111639beb93cSSam Leffler const u8 *pos, *end; 111739beb93cSSam Leffler size_t left, len; 111839beb93cSSam Leffler u8 type; 111939beb93cSSam Leffler 112039beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 112139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " 112239beb93cSSam Leffler "received content type 0x%x", ct); 112339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 112439beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 112539beb93cSSam Leffler return -1; 112639beb93cSSam Leffler } 112739beb93cSSam Leffler 112839beb93cSSam Leffler pos = in_data; 112939beb93cSSam Leffler left = *in_len; 113039beb93cSSam Leffler 113139beb93cSSam Leffler if (left < 4) { 113239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateRequest " 113339beb93cSSam Leffler "(left=%lu)", (unsigned long) left); 113439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 113539beb93cSSam Leffler return -1; 113639beb93cSSam Leffler } 113739beb93cSSam Leffler 113839beb93cSSam Leffler type = *pos++; 113939beb93cSSam Leffler len = WPA_GET_BE24(pos); 114039beb93cSSam Leffler pos += 3; 114139beb93cSSam Leffler left -= 4; 114239beb93cSSam Leffler 114339beb93cSSam Leffler if (len > left) { 114439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in CertificateRequest " 114539beb93cSSam Leffler "length (len=%lu != left=%lu)", 114639beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 114739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 114839beb93cSSam Leffler return -1; 114939beb93cSSam Leffler } 115039beb93cSSam Leffler 115139beb93cSSam Leffler end = pos + len; 115239beb93cSSam Leffler 115339beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) 115439beb93cSSam Leffler return tls_process_server_hello_done(conn, ct, in_data, 115539beb93cSSam Leffler in_len); 115639beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) { 115739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " 115839beb93cSSam Leffler "message %d (expected CertificateRequest/" 115939beb93cSSam Leffler "ServerHelloDone)", type); 116039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 116139beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 116239beb93cSSam Leffler return -1; 116339beb93cSSam Leffler } 116439beb93cSSam Leffler 116539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateRequest"); 116639beb93cSSam Leffler 116739beb93cSSam Leffler conn->certificate_requested = 1; 116839beb93cSSam Leffler 116939beb93cSSam Leffler *in_len = end - in_data; 117039beb93cSSam Leffler 117139beb93cSSam Leffler conn->state = SERVER_HELLO_DONE; 117239beb93cSSam Leffler 117339beb93cSSam Leffler return 0; 117439beb93cSSam Leffler } 117539beb93cSSam Leffler 117639beb93cSSam Leffler 117739beb93cSSam Leffler static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct, 117839beb93cSSam Leffler const u8 *in_data, size_t *in_len) 117939beb93cSSam Leffler { 118039beb93cSSam Leffler const u8 *pos, *end; 118139beb93cSSam Leffler size_t left, len; 118239beb93cSSam Leffler u8 type; 118339beb93cSSam Leffler 118439beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 118539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " 118639beb93cSSam Leffler "received content type 0x%x", ct); 118739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 118839beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 118939beb93cSSam Leffler return -1; 119039beb93cSSam Leffler } 119139beb93cSSam Leffler 119239beb93cSSam Leffler pos = in_data; 119339beb93cSSam Leffler left = *in_len; 119439beb93cSSam Leffler 119539beb93cSSam Leffler if (left < 4) { 119639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerHelloDone " 119739beb93cSSam Leffler "(left=%lu)", (unsigned long) left); 119839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 119939beb93cSSam Leffler return -1; 120039beb93cSSam Leffler } 120139beb93cSSam Leffler 120239beb93cSSam Leffler type = *pos++; 120339beb93cSSam Leffler len = WPA_GET_BE24(pos); 120439beb93cSSam Leffler pos += 3; 120539beb93cSSam Leffler left -= 4; 120639beb93cSSam Leffler 120739beb93cSSam Leffler if (len > left) { 120839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerHelloDone " 120939beb93cSSam Leffler "length (len=%lu != left=%lu)", 121039beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 121139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 121239beb93cSSam Leffler return -1; 121339beb93cSSam Leffler } 121439beb93cSSam Leffler end = pos + len; 121539beb93cSSam Leffler 121639beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) { 121739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " 121839beb93cSSam Leffler "message %d (expected ServerHelloDone)", type); 121939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 122039beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 122139beb93cSSam Leffler return -1; 122239beb93cSSam Leffler } 122339beb93cSSam Leffler 122439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHelloDone"); 122539beb93cSSam Leffler 1226*780fb4a2SCy Schubert if ((conn->flags & TLS_CONN_REQUIRE_OCSP) && 1227*780fb4a2SCy Schubert !conn->ocsp_resp_received) { 1228*780fb4a2SCy Schubert wpa_printf(MSG_INFO, 1229*780fb4a2SCy Schubert "TLSv1: No OCSP response received - reject handshake"); 1230*780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 1231*780fb4a2SCy Schubert TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE); 1232*780fb4a2SCy Schubert return -1; 1233*780fb4a2SCy Schubert } 1234*780fb4a2SCy Schubert 123539beb93cSSam Leffler *in_len = end - in_data; 123639beb93cSSam Leffler 123739beb93cSSam Leffler conn->state = CLIENT_KEY_EXCHANGE; 123839beb93cSSam Leffler 123939beb93cSSam Leffler return 0; 124039beb93cSSam Leffler } 124139beb93cSSam Leffler 124239beb93cSSam Leffler 124339beb93cSSam Leffler static int tls_process_server_change_cipher_spec(struct tlsv1_client *conn, 124439beb93cSSam Leffler u8 ct, const u8 *in_data, 124539beb93cSSam Leffler size_t *in_len) 124639beb93cSSam Leffler { 124739beb93cSSam Leffler const u8 *pos; 124839beb93cSSam Leffler size_t left; 124939beb93cSSam Leffler 125039beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { 125139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " 125239beb93cSSam Leffler "received content type 0x%x", ct); 125339beb93cSSam Leffler if (conn->use_session_ticket) { 125439beb93cSSam Leffler int res; 125539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Server may have " 125639beb93cSSam Leffler "rejected SessionTicket"); 125739beb93cSSam Leffler conn->use_session_ticket = 0; 125839beb93cSSam Leffler 125939beb93cSSam Leffler /* Notify upper layers that SessionTicket failed */ 126039beb93cSSam Leffler res = conn->session_ticket_cb( 126139beb93cSSam Leffler conn->session_ticket_cb_ctx, NULL, 0, NULL, 126239beb93cSSam Leffler NULL, NULL); 126339beb93cSSam Leffler if (res < 0) { 126439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket " 126539beb93cSSam Leffler "callback indicated failure"); 126639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 126739beb93cSSam Leffler TLS_ALERT_HANDSHAKE_FAILURE); 126839beb93cSSam Leffler return -1; 126939beb93cSSam Leffler } 127039beb93cSSam Leffler 127139beb93cSSam Leffler conn->state = SERVER_CERTIFICATE; 127239beb93cSSam Leffler return tls_process_certificate(conn, ct, in_data, 127339beb93cSSam Leffler in_len); 127439beb93cSSam Leffler } 127539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 127639beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 127739beb93cSSam Leffler return -1; 127839beb93cSSam Leffler } 127939beb93cSSam Leffler 128039beb93cSSam Leffler pos = in_data; 128139beb93cSSam Leffler left = *in_len; 128239beb93cSSam Leffler 128339beb93cSSam Leffler if (left < 1) { 128439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec"); 128539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 128639beb93cSSam Leffler return -1; 128739beb93cSSam Leffler } 128839beb93cSSam Leffler 128939beb93cSSam Leffler if (*pos != TLS_CHANGE_CIPHER_SPEC) { 129039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " 129139beb93cSSam Leffler "received data 0x%x", *pos); 129239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 129339beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 129439beb93cSSam Leffler return -1; 129539beb93cSSam Leffler } 129639beb93cSSam Leffler 129739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec"); 129839beb93cSSam Leffler if (tlsv1_record_change_read_cipher(&conn->rl) < 0) { 129939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher " 130039beb93cSSam Leffler "for record layer"); 130139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 130239beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 130339beb93cSSam Leffler return -1; 130439beb93cSSam Leffler } 130539beb93cSSam Leffler 130639beb93cSSam Leffler *in_len = pos + 1 - in_data; 130739beb93cSSam Leffler 130839beb93cSSam Leffler conn->state = SERVER_FINISHED; 130939beb93cSSam Leffler 131039beb93cSSam Leffler return 0; 131139beb93cSSam Leffler } 131239beb93cSSam Leffler 131339beb93cSSam Leffler 131439beb93cSSam Leffler static int tls_process_server_finished(struct tlsv1_client *conn, u8 ct, 131539beb93cSSam Leffler const u8 *in_data, size_t *in_len) 131639beb93cSSam Leffler { 131739beb93cSSam Leffler const u8 *pos, *end; 131839beb93cSSam Leffler size_t left, len, hlen; 131939beb93cSSam Leffler u8 verify_data[TLS_VERIFY_DATA_LEN]; 132039beb93cSSam Leffler u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; 132139beb93cSSam Leffler 132239beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 132339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; " 132439beb93cSSam Leffler "received content type 0x%x", ct); 132539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 132639beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 132739beb93cSSam Leffler return -1; 132839beb93cSSam Leffler } 132939beb93cSSam Leffler 133039beb93cSSam Leffler pos = in_data; 133139beb93cSSam Leffler left = *in_len; 133239beb93cSSam Leffler 133339beb93cSSam Leffler if (left < 4) { 133439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for " 133539beb93cSSam Leffler "Finished", 133639beb93cSSam Leffler (unsigned long) left); 133739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 133839beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 133939beb93cSSam Leffler return -1; 134039beb93cSSam Leffler } 134139beb93cSSam Leffler 134239beb93cSSam Leffler if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) { 134339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received " 134439beb93cSSam Leffler "type 0x%x", pos[0]); 134539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 134639beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 134739beb93cSSam Leffler return -1; 134839beb93cSSam Leffler } 134939beb93cSSam Leffler 135039beb93cSSam Leffler len = WPA_GET_BE24(pos + 1); 135139beb93cSSam Leffler 135239beb93cSSam Leffler pos += 4; 135339beb93cSSam Leffler left -= 4; 135439beb93cSSam Leffler 135539beb93cSSam Leffler if (len > left) { 135639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished " 135739beb93cSSam Leffler "(len=%lu > left=%lu)", 135839beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 135939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 136039beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 136139beb93cSSam Leffler return -1; 136239beb93cSSam Leffler } 136339beb93cSSam Leffler end = pos + len; 136439beb93cSSam Leffler if (len != TLS_VERIFY_DATA_LEN) { 136539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length " 136639beb93cSSam Leffler "in Finished: %lu (expected %d)", 136739beb93cSSam Leffler (unsigned long) len, TLS_VERIFY_DATA_LEN); 136839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 136939beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 137039beb93cSSam Leffler return -1; 137139beb93cSSam Leffler } 137239beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished", 137339beb93cSSam Leffler pos, TLS_VERIFY_DATA_LEN); 137439beb93cSSam Leffler 1375f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 1376f05cddf9SRui Paulo if (conn->rl.tls_version >= TLS_VERSION_1_2) { 1377f05cddf9SRui Paulo hlen = SHA256_MAC_LEN; 1378f05cddf9SRui Paulo if (conn->verify.sha256_server == NULL || 1379f05cddf9SRui Paulo crypto_hash_finish(conn->verify.sha256_server, hash, &hlen) 1380f05cddf9SRui Paulo < 0) { 1381f05cddf9SRui Paulo tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 1382f05cddf9SRui Paulo TLS_ALERT_INTERNAL_ERROR); 1383f05cddf9SRui Paulo conn->verify.sha256_server = NULL; 1384f05cddf9SRui Paulo return -1; 1385f05cddf9SRui Paulo } 1386f05cddf9SRui Paulo conn->verify.sha256_server = NULL; 1387f05cddf9SRui Paulo } else { 1388f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 1389f05cddf9SRui Paulo 139039beb93cSSam Leffler hlen = MD5_MAC_LEN; 139139beb93cSSam Leffler if (conn->verify.md5_server == NULL || 139239beb93cSSam Leffler crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) { 139339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 139439beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 139539beb93cSSam Leffler conn->verify.md5_server = NULL; 139639beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_server, NULL, NULL); 139739beb93cSSam Leffler conn->verify.sha1_server = NULL; 139839beb93cSSam Leffler return -1; 139939beb93cSSam Leffler } 140039beb93cSSam Leffler conn->verify.md5_server = NULL; 140139beb93cSSam Leffler hlen = SHA1_MAC_LEN; 140239beb93cSSam Leffler if (conn->verify.sha1_server == NULL || 140339beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN, 140439beb93cSSam Leffler &hlen) < 0) { 140539beb93cSSam Leffler conn->verify.sha1_server = NULL; 140639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 140739beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 140839beb93cSSam Leffler return -1; 140939beb93cSSam Leffler } 141039beb93cSSam Leffler conn->verify.sha1_server = NULL; 1411f05cddf9SRui Paulo hlen = MD5_MAC_LEN + SHA1_MAC_LEN; 141239beb93cSSam Leffler 1413f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 1414f05cddf9SRui Paulo } 1415f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 1416f05cddf9SRui Paulo 1417f05cddf9SRui Paulo if (tls_prf(conn->rl.tls_version, 1418f05cddf9SRui Paulo conn->master_secret, TLS_MASTER_SECRET_LEN, 1419f05cddf9SRui Paulo "server finished", hash, hlen, 142039beb93cSSam Leffler verify_data, TLS_VERIFY_DATA_LEN)) { 142139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data"); 142239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 142339beb93cSSam Leffler TLS_ALERT_DECRYPT_ERROR); 142439beb93cSSam Leffler return -1; 142539beb93cSSam Leffler } 142639beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)", 142739beb93cSSam Leffler verify_data, TLS_VERIFY_DATA_LEN); 142839beb93cSSam Leffler 14295b9c547cSRui Paulo if (os_memcmp_const(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) { 143039beb93cSSam Leffler wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data"); 14315b9c547cSRui Paulo tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 14325b9c547cSRui Paulo TLS_ALERT_DECRYPT_ERROR); 143339beb93cSSam Leffler return -1; 143439beb93cSSam Leffler } 143539beb93cSSam Leffler 143639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received Finished"); 143739beb93cSSam Leffler 143839beb93cSSam Leffler *in_len = end - in_data; 143939beb93cSSam Leffler 144039beb93cSSam Leffler conn->state = (conn->session_resumed || conn->use_session_ticket) ? 144139beb93cSSam Leffler CHANGE_CIPHER_SPEC : ACK_FINISHED; 144239beb93cSSam Leffler 144339beb93cSSam Leffler return 0; 144439beb93cSSam Leffler } 144539beb93cSSam Leffler 144639beb93cSSam Leffler 144739beb93cSSam Leffler static int tls_process_application_data(struct tlsv1_client *conn, u8 ct, 144839beb93cSSam Leffler const u8 *in_data, size_t *in_len, 144939beb93cSSam Leffler u8 **out_data, size_t *out_len) 145039beb93cSSam Leffler { 145139beb93cSSam Leffler const u8 *pos; 145239beb93cSSam Leffler size_t left; 145339beb93cSSam Leffler 145439beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) { 145539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Application Data; " 145639beb93cSSam Leffler "received content type 0x%x", ct); 145739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 145839beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 145939beb93cSSam Leffler return -1; 146039beb93cSSam Leffler } 146139beb93cSSam Leffler 146239beb93cSSam Leffler pos = in_data; 146339beb93cSSam Leffler left = *in_len; 146439beb93cSSam Leffler 146539beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: Application Data included in Handshake", 146639beb93cSSam Leffler pos, left); 146739beb93cSSam Leffler 146839beb93cSSam Leffler *out_data = os_malloc(left); 146939beb93cSSam Leffler if (*out_data) { 147039beb93cSSam Leffler os_memcpy(*out_data, pos, left); 147139beb93cSSam Leffler *out_len = left; 147239beb93cSSam Leffler } 147339beb93cSSam Leffler 147439beb93cSSam Leffler return 0; 147539beb93cSSam Leffler } 147639beb93cSSam Leffler 147739beb93cSSam Leffler 147839beb93cSSam Leffler int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct, 147939beb93cSSam Leffler const u8 *buf, size_t *len, 148039beb93cSSam Leffler u8 **out_data, size_t *out_len) 148139beb93cSSam Leffler { 148239beb93cSSam Leffler if (ct == TLS_CONTENT_TYPE_ALERT) { 148339beb93cSSam Leffler if (*len < 2) { 148439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow"); 148539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 148639beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 148739beb93cSSam Leffler return -1; 148839beb93cSSam Leffler } 148939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d", 149039beb93cSSam Leffler buf[0], buf[1]); 149139beb93cSSam Leffler *len = 2; 149239beb93cSSam Leffler conn->state = FAILED; 149339beb93cSSam Leffler return -1; 149439beb93cSSam Leffler } 149539beb93cSSam Leffler 149639beb93cSSam Leffler if (ct == TLS_CONTENT_TYPE_HANDSHAKE && *len >= 4 && 149739beb93cSSam Leffler buf[0] == TLS_HANDSHAKE_TYPE_HELLO_REQUEST) { 149839beb93cSSam Leffler size_t hr_len = WPA_GET_BE24(buf + 1); 149939beb93cSSam Leffler if (hr_len > *len - 4) { 150039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: HelloRequest underflow"); 150139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 150239beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 150339beb93cSSam Leffler return -1; 150439beb93cSSam Leffler } 150539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Ignored HelloRequest"); 150639beb93cSSam Leffler *len = 4 + hr_len; 150739beb93cSSam Leffler return 0; 150839beb93cSSam Leffler } 150939beb93cSSam Leffler 151039beb93cSSam Leffler switch (conn->state) { 151139beb93cSSam Leffler case SERVER_HELLO: 151239beb93cSSam Leffler if (tls_process_server_hello(conn, ct, buf, len)) 151339beb93cSSam Leffler return -1; 151439beb93cSSam Leffler break; 151539beb93cSSam Leffler case SERVER_CERTIFICATE: 151639beb93cSSam Leffler if (tls_process_certificate(conn, ct, buf, len)) 151739beb93cSSam Leffler return -1; 151839beb93cSSam Leffler break; 151939beb93cSSam Leffler case SERVER_KEY_EXCHANGE: 152039beb93cSSam Leffler if (tls_process_server_key_exchange(conn, ct, buf, len)) 152139beb93cSSam Leffler return -1; 152239beb93cSSam Leffler break; 152339beb93cSSam Leffler case SERVER_CERTIFICATE_REQUEST: 152439beb93cSSam Leffler if (tls_process_certificate_request(conn, ct, buf, len)) 152539beb93cSSam Leffler return -1; 152639beb93cSSam Leffler break; 152739beb93cSSam Leffler case SERVER_HELLO_DONE: 152839beb93cSSam Leffler if (tls_process_server_hello_done(conn, ct, buf, len)) 152939beb93cSSam Leffler return -1; 153039beb93cSSam Leffler break; 153139beb93cSSam Leffler case SERVER_CHANGE_CIPHER_SPEC: 153239beb93cSSam Leffler if (tls_process_server_change_cipher_spec(conn, ct, buf, len)) 153339beb93cSSam Leffler return -1; 153439beb93cSSam Leffler break; 153539beb93cSSam Leffler case SERVER_FINISHED: 153639beb93cSSam Leffler if (tls_process_server_finished(conn, ct, buf, len)) 153739beb93cSSam Leffler return -1; 153839beb93cSSam Leffler break; 153939beb93cSSam Leffler case ACK_FINISHED: 154039beb93cSSam Leffler if (out_data && 154139beb93cSSam Leffler tls_process_application_data(conn, ct, buf, len, out_data, 154239beb93cSSam Leffler out_len)) 154339beb93cSSam Leffler return -1; 154439beb93cSSam Leffler break; 154539beb93cSSam Leffler default: 154639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d " 154739beb93cSSam Leffler "while processing received message", 154839beb93cSSam Leffler conn->state); 154939beb93cSSam Leffler return -1; 155039beb93cSSam Leffler } 155139beb93cSSam Leffler 155239beb93cSSam Leffler if (ct == TLS_CONTENT_TYPE_HANDSHAKE) 155339beb93cSSam Leffler tls_verify_hash_add(&conn->verify, buf, *len); 155439beb93cSSam Leffler 155539beb93cSSam Leffler return 0; 155639beb93cSSam Leffler } 1557