139beb93cSSam Leffler /* 239beb93cSSam Leffler * TLSv1 client - read handshake message 3780fb4a2SCy 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 30780fb4a2SCy Schubert static int tls_version_disabled(struct tlsv1_client *conn, u16 ver) 31780fb4a2SCy Schubert { 32780fb4a2SCy Schubert return (((conn->flags & TLS_CONN_DISABLE_TLSv1_0) && 33780fb4a2SCy Schubert ver == TLS_VERSION_1) || 34780fb4a2SCy Schubert ((conn->flags & TLS_CONN_DISABLE_TLSv1_1) && 35780fb4a2SCy Schubert ver == TLS_VERSION_1_1) || 36780fb4a2SCy Schubert ((conn->flags & TLS_CONN_DISABLE_TLSv1_2) && 37780fb4a2SCy Schubert ver == TLS_VERSION_1_2)); 38780fb4a2SCy Schubert } 39780fb4a2SCy Schubert 40780fb4a2SCy Schubert 41780fb4a2SCy Schubert static int tls_process_server_hello_extensions(struct tlsv1_client *conn, 42780fb4a2SCy Schubert const u8 *pos, size_t len) 43780fb4a2SCy Schubert { 44780fb4a2SCy Schubert const u8 *end = pos + len; 45780fb4a2SCy Schubert 46780fb4a2SCy Schubert wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello extensions", 47780fb4a2SCy Schubert pos, len); 48780fb4a2SCy Schubert while (pos < end) { 49780fb4a2SCy Schubert u16 ext, elen; 50780fb4a2SCy Schubert 51780fb4a2SCy Schubert if (end - pos < 4) { 52780fb4a2SCy Schubert wpa_printf(MSG_INFO, "TLSv1: Truncated ServerHello extension header"); 53780fb4a2SCy Schubert return -1; 54780fb4a2SCy Schubert } 55780fb4a2SCy Schubert 56780fb4a2SCy Schubert ext = WPA_GET_BE16(pos); 57780fb4a2SCy Schubert pos += 2; 58780fb4a2SCy Schubert elen = WPA_GET_BE16(pos); 59780fb4a2SCy Schubert pos += 2; 60780fb4a2SCy Schubert 61780fb4a2SCy Schubert if (elen > end - pos) { 62780fb4a2SCy Schubert wpa_printf(MSG_INFO, "TLSv1: Truncated ServerHello extension"); 63780fb4a2SCy Schubert return -1; 64780fb4a2SCy Schubert } 65780fb4a2SCy Schubert 66780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, "TLSv1: ServerHello ExtensionType %u", 67780fb4a2SCy Schubert ext); 68780fb4a2SCy Schubert wpa_hexdump(MSG_DEBUG, "TLSv1: ServerHello extension data", 69780fb4a2SCy Schubert pos, elen); 70780fb4a2SCy Schubert 71780fb4a2SCy Schubert pos += elen; 72780fb4a2SCy Schubert } 73780fb4a2SCy Schubert 74780fb4a2SCy Schubert return 0; 75780fb4a2SCy Schubert } 76780fb4a2SCy Schubert 77780fb4a2SCy 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); 127780fb4a2SCy Schubert if (!tls_version_ok(tls_version) || 128780fb4a2SCy 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 217780fb4a2SCy Schubert if (end - pos >= 2) { 218780fb4a2SCy Schubert u16 ext_len; 219780fb4a2SCy Schubert 220780fb4a2SCy Schubert ext_len = WPA_GET_BE16(pos); 221780fb4a2SCy Schubert pos += 2; 222780fb4a2SCy Schubert if (end - pos < ext_len) { 223780fb4a2SCy Schubert wpa_printf(MSG_INFO, 224780fb4a2SCy Schubert "TLSv1: Invalid ServerHello extension length: %u (left: %u)", 225780fb4a2SCy Schubert ext_len, (unsigned int) (end - pos)); 226780fb4a2SCy Schubert goto decode_error; 227780fb4a2SCy Schubert } 228780fb4a2SCy Schubert 229780fb4a2SCy Schubert if (tls_process_server_hello_extensions(conn, pos, ext_len)) 230780fb4a2SCy Schubert goto decode_error; 231780fb4a2SCy Schubert pos += ext_len; 232780fb4a2SCy Schubert } 233780fb4a2SCy 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 279780fb4a2SCy Schubert static void tls_peer_cert_event(struct tlsv1_client *conn, int depth, 280780fb4a2SCy Schubert struct x509_certificate *cert) 281780fb4a2SCy Schubert { 282780fb4a2SCy Schubert union tls_event_data ev; 283780fb4a2SCy Schubert struct wpabuf *cert_buf = NULL; 284780fb4a2SCy Schubert #ifdef CONFIG_SHA256 285780fb4a2SCy Schubert u8 hash[32]; 286780fb4a2SCy Schubert #endif /* CONFIG_SHA256 */ 287780fb4a2SCy Schubert char subject[128]; 288780fb4a2SCy Schubert 289780fb4a2SCy Schubert if (!conn->event_cb) 290780fb4a2SCy Schubert return; 291780fb4a2SCy Schubert 292780fb4a2SCy Schubert os_memset(&ev, 0, sizeof(ev)); 293780fb4a2SCy Schubert if (conn->cred->cert_probe || conn->cert_in_cb) { 294780fb4a2SCy Schubert cert_buf = wpabuf_alloc_copy(cert->cert_start, 295780fb4a2SCy Schubert cert->cert_len); 296780fb4a2SCy Schubert ev.peer_cert.cert = cert_buf; 297780fb4a2SCy Schubert } 298780fb4a2SCy Schubert #ifdef CONFIG_SHA256 299780fb4a2SCy Schubert if (cert_buf) { 300780fb4a2SCy Schubert const u8 *addr[1]; 301780fb4a2SCy Schubert size_t len[1]; 302780fb4a2SCy Schubert addr[0] = wpabuf_head(cert_buf); 303780fb4a2SCy Schubert len[0] = wpabuf_len(cert_buf); 304780fb4a2SCy Schubert if (sha256_vector(1, addr, len, hash) == 0) { 305780fb4a2SCy Schubert ev.peer_cert.hash = hash; 306780fb4a2SCy Schubert ev.peer_cert.hash_len = sizeof(hash); 307780fb4a2SCy Schubert } 308780fb4a2SCy Schubert } 309780fb4a2SCy Schubert #endif /* CONFIG_SHA256 */ 310780fb4a2SCy Schubert 311780fb4a2SCy Schubert ev.peer_cert.depth = depth; 312780fb4a2SCy Schubert x509_name_string(&cert->subject, subject, sizeof(subject)); 313780fb4a2SCy Schubert ev.peer_cert.subject = subject; 314780fb4a2SCy Schubert 315780fb4a2SCy Schubert conn->event_cb(conn->cb_ctx, TLS_PEER_CERTIFICATE, &ev); 316780fb4a2SCy Schubert wpabuf_free(cert_buf); 317780fb4a2SCy Schubert } 318780fb4a2SCy Schubert 319780fb4a2SCy Schubert 320780fb4a2SCy Schubert static void tls_cert_chain_failure_event(struct tlsv1_client *conn, int depth, 321780fb4a2SCy Schubert struct x509_certificate *cert, 322780fb4a2SCy Schubert enum tls_fail_reason reason, 323780fb4a2SCy Schubert const char *reason_txt) 324780fb4a2SCy Schubert { 325780fb4a2SCy Schubert struct wpabuf *cert_buf = NULL; 326780fb4a2SCy Schubert union tls_event_data ev; 327780fb4a2SCy Schubert char subject[128]; 328780fb4a2SCy Schubert 329780fb4a2SCy Schubert if (!conn->event_cb || !cert) 330780fb4a2SCy Schubert return; 331780fb4a2SCy Schubert 332780fb4a2SCy Schubert os_memset(&ev, 0, sizeof(ev)); 333780fb4a2SCy Schubert ev.cert_fail.depth = depth; 334780fb4a2SCy Schubert x509_name_string(&cert->subject, subject, sizeof(subject)); 335780fb4a2SCy Schubert ev.peer_cert.subject = subject; 336780fb4a2SCy Schubert ev.cert_fail.reason = reason; 337780fb4a2SCy Schubert ev.cert_fail.reason_txt = reason_txt; 338780fb4a2SCy Schubert cert_buf = wpabuf_alloc_copy(cert->cert_start, 339780fb4a2SCy Schubert cert->cert_len); 340780fb4a2SCy Schubert ev.cert_fail.cert = cert_buf; 341780fb4a2SCy Schubert conn->event_cb(conn->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev); 342780fb4a2SCy Schubert wpabuf_free(cert_buf); 343780fb4a2SCy Schubert } 344780fb4a2SCy Schubert 345780fb4a2SCy 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 489780fb4a2SCy Schubert tls_peer_cert_event(conn, idx, cert); 490780fb4a2SCy 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 501780fb4a2SCy Schubert if (conn->cred && conn->cred->server_cert_only && chain) { 502780fb4a2SCy Schubert u8 hash[SHA256_MAC_LEN]; 503780fb4a2SCy Schubert char buf[128]; 504780fb4a2SCy Schubert 505780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 506780fb4a2SCy Schubert "TLSv1: Validate server certificate hash"); 507780fb4a2SCy Schubert x509_name_string(&chain->subject, buf, sizeof(buf)); 508780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, "TLSv1: 0: %s", buf); 509780fb4a2SCy Schubert if (sha256_vector(1, &chain->cert_start, &chain->cert_len, 510780fb4a2SCy Schubert hash) < 0 || 511780fb4a2SCy Schubert os_memcmp(conn->cred->srv_cert_hash, hash, 512780fb4a2SCy Schubert SHA256_MAC_LEN) != 0) { 513780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 514780fb4a2SCy Schubert "TLSv1: Server certificate hash mismatch"); 515780fb4a2SCy Schubert wpa_hexdump(MSG_MSGDUMP, "TLSv1: SHA256 hash", 516780fb4a2SCy Schubert hash, SHA256_MAC_LEN); 517780fb4a2SCy Schubert if (conn->event_cb) { 518780fb4a2SCy Schubert union tls_event_data ev; 519780fb4a2SCy Schubert 520780fb4a2SCy Schubert os_memset(&ev, 0, sizeof(ev)); 521780fb4a2SCy Schubert ev.cert_fail.reason = TLS_FAIL_UNSPECIFIED; 522780fb4a2SCy Schubert ev.cert_fail.reason_txt = 523780fb4a2SCy Schubert "Server certificate mismatch"; 524780fb4a2SCy Schubert ev.cert_fail.subject = buf; 525780fb4a2SCy Schubert conn->event_cb(conn->cb_ctx, 526780fb4a2SCy Schubert TLS_CERT_CHAIN_FAILURE, &ev); 527780fb4a2SCy Schubert } 528780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 529780fb4a2SCy Schubert TLS_ALERT_BAD_CERTIFICATE); 530780fb4a2SCy Schubert x509_certificate_chain_free(chain); 531780fb4a2SCy Schubert return -1; 532780fb4a2SCy Schubert } 533780fb4a2SCy Schubert } else if (conn->cred && conn->cred->cert_probe) { 534780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 535780fb4a2SCy Schubert "TLSv1: Reject server certificate on probe-only rune"); 536780fb4a2SCy Schubert if (conn->event_cb) { 537780fb4a2SCy Schubert union tls_event_data ev; 538780fb4a2SCy Schubert char buf[128]; 539780fb4a2SCy Schubert 540780fb4a2SCy Schubert os_memset(&ev, 0, sizeof(ev)); 541780fb4a2SCy Schubert ev.cert_fail.reason = TLS_FAIL_SERVER_CHAIN_PROBE; 542780fb4a2SCy Schubert ev.cert_fail.reason_txt = 543780fb4a2SCy Schubert "Server certificate chain probe"; 544780fb4a2SCy Schubert if (chain) { 545780fb4a2SCy Schubert x509_name_string(&chain->subject, buf, 546780fb4a2SCy Schubert sizeof(buf)); 547780fb4a2SCy Schubert ev.cert_fail.subject = buf; 548780fb4a2SCy Schubert } 549780fb4a2SCy Schubert conn->event_cb(conn->cb_ctx, TLS_CERT_CHAIN_FAILURE, 550780fb4a2SCy Schubert &ev); 551780fb4a2SCy Schubert } 552780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 553780fb4a2SCy Schubert TLS_ALERT_BAD_CERTIFICATE); 554780fb4a2SCy Schubert x509_certificate_chain_free(chain); 555780fb4a2SCy Schubert return -1; 556780fb4a2SCy Schubert } else if (conn->cred && conn->cred->ca_cert_verify && 557780fb4a2SCy Schubert x509_certificate_chain_validate( 558780fb4a2SCy Schubert conn->cred->trusted_certs, chain, &reason, 559780fb4a2SCy 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; 567780fb4a2SCy Schubert tls_cert_chain_failure_event( 568780fb4a2SCy Schubert conn, 0, chain, TLS_FAIL_BAD_CERTIFICATE, 569780fb4a2SCy 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; 576780fb4a2SCy Schubert tls_cert_chain_failure_event( 577780fb4a2SCy Schubert conn, 0, chain, TLS_FAIL_REVOKED, 578780fb4a2SCy Schubert "certificate revoked"); 57939beb93cSSam Leffler break; 58039beb93cSSam Leffler case X509_VALIDATE_CERTIFICATE_EXPIRED: 58139beb93cSSam Leffler tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED; 582780fb4a2SCy Schubert tls_cert_chain_failure_event( 583780fb4a2SCy Schubert conn, 0, chain, TLS_FAIL_EXPIRED, 584780fb4a2SCy 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; 591780fb4a2SCy Schubert tls_cert_chain_failure_event( 592780fb4a2SCy Schubert conn, 0, chain, TLS_FAIL_UNTRUSTED, 593780fb4a2SCy 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 604780fb4a2SCy Schubert if (conn->cred && !conn->cred->server_cert_only && chain && 605780fb4a2SCy Schubert (chain->extensions_present & X509_EXT_EXT_KEY_USAGE) && 606780fb4a2SCy Schubert !(chain->ext_key_usage & 607780fb4a2SCy Schubert (X509_EXT_KEY_USAGE_ANY | X509_EXT_KEY_USAGE_SERVER_AUTH))) { 608780fb4a2SCy Schubert tls_cert_chain_failure_event( 609780fb4a2SCy Schubert conn, 0, chain, TLS_FAIL_BAD_CERTIFICATE, 610780fb4a2SCy Schubert "certificate not allowed for server authentication"); 611780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 612780fb4a2SCy Schubert TLS_ALERT_BAD_CERTIFICATE); 61339beb93cSSam Leffler x509_certificate_chain_free(chain); 614780fb4a2SCy Schubert return -1; 615780fb4a2SCy Schubert } 616780fb4a2SCy Schubert 617780fb4a2SCy Schubert if (conn->flags & TLS_CONN_REQUEST_OCSP) { 618780fb4a2SCy Schubert x509_certificate_chain_free(conn->server_cert); 619780fb4a2SCy Schubert conn->server_cert = chain; 620780fb4a2SCy Schubert } else { 621780fb4a2SCy Schubert x509_certificate_chain_free(chain); 622780fb4a2SCy 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 } 688*85732ac8SCy Schubert conn->dh_p = os_memdup(pos, conn->dh_p_len); 68939beb93cSSam Leffler if (conn->dh_p == NULL) 69039beb93cSSam Leffler goto fail; 69139beb93cSSam Leffler pos += conn->dh_p_len; 69239beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: DH p (prime)", 69339beb93cSSam Leffler conn->dh_p, conn->dh_p_len); 69439beb93cSSam Leffler 69539beb93cSSam Leffler if (end - pos < 3) 69639beb93cSSam Leffler goto fail; 6975b9c547cSRui Paulo val = WPA_GET_BE16(pos); 69839beb93cSSam Leffler pos += 2; 6995b9c547cSRui Paulo if (val == 0 || val > (size_t) (end - pos)) 70039beb93cSSam Leffler goto fail; 7015b9c547cSRui Paulo conn->dh_g_len = val; 702*85732ac8SCy Schubert conn->dh_g = os_memdup(pos, conn->dh_g_len); 70339beb93cSSam Leffler if (conn->dh_g == NULL) 70439beb93cSSam Leffler goto fail; 70539beb93cSSam Leffler pos += conn->dh_g_len; 70639beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: DH g (generator)", 70739beb93cSSam Leffler conn->dh_g, conn->dh_g_len); 70839beb93cSSam Leffler if (conn->dh_g_len == 1 && conn->dh_g[0] < 2) 70939beb93cSSam Leffler goto fail; 71039beb93cSSam Leffler 71139beb93cSSam Leffler if (end - pos < 3) 71239beb93cSSam Leffler goto fail; 7135b9c547cSRui Paulo val = WPA_GET_BE16(pos); 71439beb93cSSam Leffler pos += 2; 7155b9c547cSRui Paulo if (val == 0 || val > (size_t) (end - pos)) 71639beb93cSSam Leffler goto fail; 7175b9c547cSRui Paulo conn->dh_ys_len = val; 718*85732ac8SCy Schubert conn->dh_ys = os_memdup(pos, conn->dh_ys_len); 71939beb93cSSam Leffler if (conn->dh_ys == NULL) 72039beb93cSSam Leffler goto fail; 72139beb93cSSam Leffler pos += conn->dh_ys_len; 72239beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)", 72339beb93cSSam Leffler conn->dh_ys, conn->dh_ys_len); 7245b9c547cSRui Paulo server_params_end = pos; 7255b9c547cSRui Paulo 7265b9c547cSRui Paulo if (key_exchange == TLS_KEY_X_DHE_RSA) { 727780fb4a2SCy Schubert u8 hash[64]; 7285b9c547cSRui Paulo int hlen; 7295b9c547cSRui Paulo 7305b9c547cSRui Paulo if (conn->rl.tls_version == TLS_VERSION_1_2) { 7315b9c547cSRui Paulo #ifdef CONFIG_TLSV12 7325b9c547cSRui Paulo /* 7335b9c547cSRui Paulo * RFC 5246, 4.7: 7345b9c547cSRui Paulo * TLS v1.2 adds explicit indication of the used 7355b9c547cSRui Paulo * signature and hash algorithms. 7365b9c547cSRui Paulo * 7375b9c547cSRui Paulo * struct { 7385b9c547cSRui Paulo * HashAlgorithm hash; 7395b9c547cSRui Paulo * SignatureAlgorithm signature; 7405b9c547cSRui Paulo * } SignatureAndHashAlgorithm; 7415b9c547cSRui Paulo */ 7425b9c547cSRui Paulo if (end - pos < 2) 7435b9c547cSRui Paulo goto fail; 744780fb4a2SCy Schubert if ((pos[0] != TLS_HASH_ALG_SHA256 && 745780fb4a2SCy Schubert pos[0] != TLS_HASH_ALG_SHA384 && 746780fb4a2SCy Schubert pos[0] != TLS_HASH_ALG_SHA512) || 7475b9c547cSRui Paulo pos[1] != TLS_SIGN_ALG_RSA) { 7485b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/signature(%u) algorithm", 7495b9c547cSRui Paulo pos[0], pos[1]); 7505b9c547cSRui Paulo goto fail; 7515b9c547cSRui Paulo } 7525b9c547cSRui Paulo 7535b9c547cSRui Paulo hlen = tlsv12_key_x_server_params_hash( 754780fb4a2SCy Schubert conn->rl.tls_version, pos[0], 755780fb4a2SCy Schubert conn->client_random, 7565b9c547cSRui Paulo conn->server_random, server_params, 7575b9c547cSRui Paulo server_params_end - server_params, hash); 758780fb4a2SCy Schubert pos += 2; 7595b9c547cSRui Paulo #else /* CONFIG_TLSV12 */ 7605b9c547cSRui Paulo goto fail; 7615b9c547cSRui Paulo #endif /* CONFIG_TLSV12 */ 7625b9c547cSRui Paulo } else { 7635b9c547cSRui Paulo hlen = tls_key_x_server_params_hash( 7645b9c547cSRui Paulo conn->rl.tls_version, conn->client_random, 7655b9c547cSRui Paulo conn->server_random, server_params, 7665b9c547cSRui Paulo server_params_end - server_params, hash); 7675b9c547cSRui Paulo } 7685b9c547cSRui Paulo 7695b9c547cSRui Paulo if (hlen < 0) 7705b9c547cSRui Paulo goto fail; 7715b9c547cSRui Paulo wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerKeyExchange hash", 7725b9c547cSRui Paulo hash, hlen); 7735b9c547cSRui Paulo 7745b9c547cSRui Paulo if (tls_verify_signature(conn->rl.tls_version, 7755b9c547cSRui Paulo conn->server_rsa_key, 7765b9c547cSRui Paulo hash, hlen, pos, end - pos, 7775b9c547cSRui Paulo &alert) < 0) 7785b9c547cSRui Paulo goto fail; 7795b9c547cSRui Paulo } 78039beb93cSSam Leffler 78139beb93cSSam Leffler return 0; 78239beb93cSSam Leffler 78339beb93cSSam Leffler fail: 78439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Processing DH params failed"); 78539beb93cSSam Leffler tlsv1_client_free_dh(conn); 78639beb93cSSam Leffler return -1; 78739beb93cSSam Leffler } 78839beb93cSSam Leffler 78939beb93cSSam Leffler 790780fb4a2SCy Schubert static enum tls_ocsp_result 791780fb4a2SCy Schubert tls_process_certificate_status_ocsp_response(struct tlsv1_client *conn, 792780fb4a2SCy Schubert const u8 *pos, size_t len) 793780fb4a2SCy Schubert { 794780fb4a2SCy Schubert const u8 *end = pos + len; 795780fb4a2SCy Schubert u32 ocsp_resp_len; 796780fb4a2SCy Schubert 797780fb4a2SCy Schubert /* opaque OCSPResponse<1..2^24-1>; */ 798780fb4a2SCy Schubert if (end - pos < 3) { 799780fb4a2SCy Schubert wpa_printf(MSG_INFO, "TLSv1: Too short OCSPResponse"); 800780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 801780fb4a2SCy Schubert return TLS_OCSP_INVALID; 802780fb4a2SCy Schubert } 803780fb4a2SCy Schubert ocsp_resp_len = WPA_GET_BE24(pos); 804780fb4a2SCy Schubert pos += 3; 805780fb4a2SCy Schubert if (end - pos < ocsp_resp_len) { 806780fb4a2SCy Schubert wpa_printf(MSG_INFO, "TLSv1: Truncated OCSPResponse"); 807780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 808780fb4a2SCy Schubert return TLS_OCSP_INVALID; 809780fb4a2SCy Schubert } 810780fb4a2SCy Schubert 811780fb4a2SCy Schubert return tls_process_ocsp_response(conn, pos, ocsp_resp_len); 812780fb4a2SCy Schubert } 813780fb4a2SCy Schubert 814780fb4a2SCy Schubert 815780fb4a2SCy Schubert static int tls_process_certificate_status(struct tlsv1_client *conn, u8 ct, 816780fb4a2SCy Schubert const u8 *in_data, size_t *in_len) 817780fb4a2SCy Schubert { 818780fb4a2SCy Schubert const u8 *pos, *end; 819780fb4a2SCy Schubert size_t left, len; 820780fb4a2SCy Schubert u8 type, status_type; 821780fb4a2SCy Schubert enum tls_ocsp_result res; 822780fb4a2SCy Schubert struct x509_certificate *cert; 823780fb4a2SCy Schubert int depth; 824780fb4a2SCy Schubert 825780fb4a2SCy Schubert if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 826780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 827780fb4a2SCy Schubert "TLSv1: Expected Handshake; received content type 0x%x", 828780fb4a2SCy Schubert ct); 829780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 830780fb4a2SCy Schubert TLS_ALERT_UNEXPECTED_MESSAGE); 831780fb4a2SCy Schubert return -1; 832780fb4a2SCy Schubert } 833780fb4a2SCy Schubert 834780fb4a2SCy Schubert pos = in_data; 835780fb4a2SCy Schubert left = *in_len; 836780fb4a2SCy Schubert 837780fb4a2SCy Schubert if (left < 4) { 838780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 839780fb4a2SCy Schubert "TLSv1: Too short CertificateStatus (left=%lu)", 840780fb4a2SCy Schubert (unsigned long) left); 841780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 842780fb4a2SCy Schubert return -1; 843780fb4a2SCy Schubert } 844780fb4a2SCy Schubert 845780fb4a2SCy Schubert type = *pos++; 846780fb4a2SCy Schubert len = WPA_GET_BE24(pos); 847780fb4a2SCy Schubert pos += 3; 848780fb4a2SCy Schubert left -= 4; 849780fb4a2SCy Schubert 850780fb4a2SCy Schubert if (len > left) { 851780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 852780fb4a2SCy Schubert "TLSv1: Mismatch in CertificateStatus length (len=%lu != left=%lu)", 853780fb4a2SCy Schubert (unsigned long) len, (unsigned long) left); 854780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 855780fb4a2SCy Schubert return -1; 856780fb4a2SCy Schubert } 857780fb4a2SCy Schubert 858780fb4a2SCy Schubert end = pos + len; 859780fb4a2SCy Schubert 860780fb4a2SCy Schubert if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS) { 861780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 862780fb4a2SCy Schubert "TLSv1: Received unexpected handshake message %d (expected CertificateStatus)", 863780fb4a2SCy Schubert type); 864780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 865780fb4a2SCy Schubert TLS_ALERT_UNEXPECTED_MESSAGE); 866780fb4a2SCy Schubert return -1; 867780fb4a2SCy Schubert } 868780fb4a2SCy Schubert 869780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateStatus"); 870780fb4a2SCy Schubert 871780fb4a2SCy Schubert /* 872780fb4a2SCy Schubert * struct { 873780fb4a2SCy Schubert * CertificateStatusType status_type; 874780fb4a2SCy Schubert * select (status_type) { 875780fb4a2SCy Schubert * case ocsp: OCSPResponse; 876780fb4a2SCy Schubert * case ocsp_multi: OCSPResponseList; 877780fb4a2SCy Schubert * } response; 878780fb4a2SCy Schubert * } CertificateStatus; 879780fb4a2SCy Schubert */ 880780fb4a2SCy Schubert if (end - pos < 1) { 881780fb4a2SCy Schubert wpa_printf(MSG_INFO, "TLSv1: Too short CertificateStatus"); 882780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 883780fb4a2SCy Schubert return -1; 884780fb4a2SCy Schubert } 885780fb4a2SCy Schubert status_type = *pos++; 886780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, "TLSv1: CertificateStatus status_type %u", 887780fb4a2SCy Schubert status_type); 888780fb4a2SCy Schubert 889780fb4a2SCy Schubert if (status_type == 1 /* ocsp */) { 890780fb4a2SCy Schubert res = tls_process_certificate_status_ocsp_response( 891780fb4a2SCy Schubert conn, pos, end - pos); 892780fb4a2SCy Schubert } else if (status_type == 2 /* ocsp_multi */) { 893780fb4a2SCy Schubert int good = 0, revoked = 0; 894780fb4a2SCy Schubert u32 resp_len; 895780fb4a2SCy Schubert 896780fb4a2SCy Schubert res = TLS_OCSP_NO_RESPONSE; 897780fb4a2SCy Schubert 898780fb4a2SCy Schubert /* 899780fb4a2SCy Schubert * opaque OCSPResponse<0..2^24-1>; 900780fb4a2SCy Schubert * 901780fb4a2SCy Schubert * struct { 902780fb4a2SCy Schubert * OCSPResponse ocsp_response_list<1..2^24-1>; 903780fb4a2SCy Schubert * } OCSPResponseList; 904780fb4a2SCy Schubert */ 905780fb4a2SCy Schubert if (end - pos < 3) { 906780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 907780fb4a2SCy Schubert "TLSv1: Truncated OCSPResponseList"); 908780fb4a2SCy Schubert res = TLS_OCSP_INVALID; 909780fb4a2SCy Schubert goto done; 910780fb4a2SCy Schubert } 911780fb4a2SCy Schubert resp_len = WPA_GET_BE24(pos); 912780fb4a2SCy Schubert pos += 3; 913780fb4a2SCy Schubert if (end - pos < resp_len) { 914780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 915780fb4a2SCy Schubert "TLSv1: Truncated OCSPResponseList(len=%u)", 916780fb4a2SCy Schubert resp_len); 917780fb4a2SCy Schubert res = TLS_OCSP_INVALID; 918780fb4a2SCy Schubert goto done; 919780fb4a2SCy Schubert } 920780fb4a2SCy Schubert end = pos + resp_len; 921780fb4a2SCy Schubert 922780fb4a2SCy Schubert while (end - pos >= 3) { 923780fb4a2SCy Schubert resp_len = WPA_GET_BE24(pos); 924780fb4a2SCy Schubert pos += 3; 925780fb4a2SCy Schubert if (resp_len > end - pos) { 926780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 927780fb4a2SCy Schubert "TLSv1: Truncated OCSPResponse(len=%u; left=%d) in ocsp_multi", 928780fb4a2SCy Schubert resp_len, (int) (end - pos)); 929780fb4a2SCy Schubert res = TLS_OCSP_INVALID; 930780fb4a2SCy Schubert break; 931780fb4a2SCy Schubert } 932780fb4a2SCy Schubert if (!resp_len) 933780fb4a2SCy Schubert continue; /* Skip an empty response */ 934780fb4a2SCy Schubert res = tls_process_certificate_status_ocsp_response( 935780fb4a2SCy Schubert conn, pos - 3, resp_len + 3); 936780fb4a2SCy Schubert if (res == TLS_OCSP_REVOKED) 937780fb4a2SCy Schubert revoked++; 938780fb4a2SCy Schubert else if (res == TLS_OCSP_GOOD) 939780fb4a2SCy Schubert good++; 940780fb4a2SCy Schubert pos += resp_len; 941780fb4a2SCy Schubert } 942780fb4a2SCy Schubert 943780fb4a2SCy Schubert if (revoked) 944780fb4a2SCy Schubert res = TLS_OCSP_REVOKED; 945780fb4a2SCy Schubert else if (good) 946780fb4a2SCy Schubert res = TLS_OCSP_GOOD; 947780fb4a2SCy Schubert } else { 948780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 949780fb4a2SCy Schubert "TLSv1: Ignore unsupported CertificateStatus"); 950780fb4a2SCy Schubert goto skip; 951780fb4a2SCy Schubert } 952780fb4a2SCy Schubert 953780fb4a2SCy Schubert done: 954780fb4a2SCy Schubert if (res == TLS_OCSP_REVOKED) { 955780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 956780fb4a2SCy Schubert TLS_ALERT_CERTIFICATE_REVOKED); 957780fb4a2SCy Schubert for (cert = conn->server_cert, depth = 0; cert; 958780fb4a2SCy Schubert cert = cert->next, depth++) { 959780fb4a2SCy Schubert if (cert->ocsp_revoked) { 960780fb4a2SCy Schubert tls_cert_chain_failure_event( 961780fb4a2SCy Schubert conn, depth, cert, TLS_FAIL_REVOKED, 962780fb4a2SCy Schubert "certificate revoked"); 963780fb4a2SCy Schubert } 964780fb4a2SCy Schubert } 965780fb4a2SCy Schubert return -1; 966780fb4a2SCy Schubert } 967780fb4a2SCy Schubert 968780fb4a2SCy Schubert if (conn->flags & TLS_CONN_REQUIRE_OCSP_ALL) { 969780fb4a2SCy Schubert /* 970780fb4a2SCy Schubert * Verify that each certificate on the chain that is not part 971780fb4a2SCy Schubert * of the trusted certificates has a good status. If not, 972780fb4a2SCy Schubert * terminate handshake. 973780fb4a2SCy Schubert */ 974780fb4a2SCy Schubert for (cert = conn->server_cert, depth = 0; cert; 975780fb4a2SCy Schubert cert = cert->next, depth++) { 976780fb4a2SCy Schubert if (!cert->ocsp_good) { 977780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 978780fb4a2SCy Schubert TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE); 979780fb4a2SCy Schubert tls_cert_chain_failure_event( 980780fb4a2SCy Schubert conn, depth, cert, 981780fb4a2SCy Schubert TLS_FAIL_UNSPECIFIED, 982780fb4a2SCy Schubert "bad certificate status response"); 983780fb4a2SCy Schubert return -1; 984780fb4a2SCy Schubert } 985780fb4a2SCy Schubert if (cert->issuer_trusted) 986780fb4a2SCy Schubert break; 987780fb4a2SCy Schubert } 988780fb4a2SCy Schubert } 989780fb4a2SCy Schubert 990780fb4a2SCy Schubert if ((conn->flags & TLS_CONN_REQUIRE_OCSP) && res != TLS_OCSP_GOOD) { 991780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 992780fb4a2SCy Schubert res == TLS_OCSP_INVALID ? TLS_ALERT_DECODE_ERROR : 993780fb4a2SCy Schubert TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE); 994780fb4a2SCy Schubert if (conn->server_cert) 995780fb4a2SCy Schubert tls_cert_chain_failure_event( 996780fb4a2SCy Schubert conn, 0, conn->server_cert, 997780fb4a2SCy Schubert TLS_FAIL_UNSPECIFIED, 998780fb4a2SCy Schubert "bad certificate status response"); 999780fb4a2SCy Schubert return -1; 1000780fb4a2SCy Schubert } 1001780fb4a2SCy Schubert 1002780fb4a2SCy Schubert conn->ocsp_resp_received = 1; 1003780fb4a2SCy Schubert 1004780fb4a2SCy Schubert skip: 1005780fb4a2SCy Schubert *in_len = end - in_data; 1006780fb4a2SCy Schubert 1007780fb4a2SCy Schubert conn->state = SERVER_KEY_EXCHANGE; 1008780fb4a2SCy Schubert 1009780fb4a2SCy Schubert return 0; 1010780fb4a2SCy Schubert } 1011780fb4a2SCy Schubert 1012780fb4a2SCy Schubert 101339beb93cSSam Leffler static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct, 101439beb93cSSam Leffler const u8 *in_data, size_t *in_len) 101539beb93cSSam Leffler { 101639beb93cSSam Leffler const u8 *pos, *end; 101739beb93cSSam Leffler size_t left, len; 101839beb93cSSam Leffler u8 type; 101939beb93cSSam Leffler const struct tls_cipher_suite *suite; 102039beb93cSSam Leffler 102139beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 102239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " 102339beb93cSSam Leffler "received content type 0x%x", ct); 102439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 102539beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 102639beb93cSSam Leffler return -1; 102739beb93cSSam Leffler } 102839beb93cSSam Leffler 102939beb93cSSam Leffler pos = in_data; 103039beb93cSSam Leffler left = *in_len; 103139beb93cSSam Leffler 103239beb93cSSam Leffler if (left < 4) { 103339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerKeyExchange " 103439beb93cSSam Leffler "(Left=%lu)", (unsigned long) left); 103539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 103639beb93cSSam Leffler return -1; 103739beb93cSSam Leffler } 103839beb93cSSam Leffler 103939beb93cSSam Leffler type = *pos++; 104039beb93cSSam Leffler len = WPA_GET_BE24(pos); 104139beb93cSSam Leffler pos += 3; 104239beb93cSSam Leffler left -= 4; 104339beb93cSSam Leffler 104439beb93cSSam Leffler if (len > left) { 104539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerKeyExchange " 104639beb93cSSam Leffler "length (len=%lu != left=%lu)", 104739beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 104839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 104939beb93cSSam Leffler return -1; 105039beb93cSSam Leffler } 105139beb93cSSam Leffler 105239beb93cSSam Leffler end = pos + len; 105339beb93cSSam Leffler 1054780fb4a2SCy Schubert if ((conn->flags & TLS_CONN_REQUEST_OCSP) && 1055780fb4a2SCy Schubert type == TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS) 1056780fb4a2SCy Schubert return tls_process_certificate_status(conn, ct, in_data, 1057780fb4a2SCy Schubert in_len); 105839beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) 105939beb93cSSam Leffler return tls_process_certificate_request(conn, ct, in_data, 106039beb93cSSam Leffler in_len); 106139beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) 106239beb93cSSam Leffler return tls_process_server_hello_done(conn, ct, in_data, 106339beb93cSSam Leffler in_len); 106439beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) { 106539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " 106639beb93cSSam Leffler "message %d (expected ServerKeyExchange/" 1067780fb4a2SCy Schubert "CertificateRequest/ServerHelloDone%s)", type, 1068780fb4a2SCy Schubert (conn->flags & TLS_CONN_REQUEST_OCSP) ? 1069780fb4a2SCy Schubert "/CertificateStatus" : ""); 107039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 107139beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 107239beb93cSSam Leffler return -1; 107339beb93cSSam Leffler } 107439beb93cSSam Leffler 107539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received ServerKeyExchange"); 107639beb93cSSam Leffler 107739beb93cSSam Leffler if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) { 107839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not allowed " 107939beb93cSSam Leffler "with the selected cipher suite"); 108039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 108139beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 108239beb93cSSam Leffler return -1; 108339beb93cSSam Leffler } 108439beb93cSSam Leffler 108539beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: ServerKeyExchange", pos, len); 108639beb93cSSam Leffler suite = tls_get_cipher_suite(conn->rl.cipher_suite); 10875b9c547cSRui Paulo if (suite && (suite->key_exchange == TLS_KEY_X_DH_anon || 10885b9c547cSRui Paulo suite->key_exchange == TLS_KEY_X_DHE_RSA)) { 10895b9c547cSRui Paulo if (tlsv1_process_diffie_hellman(conn, pos, len, 10905b9c547cSRui Paulo suite->key_exchange) < 0) { 109139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 109239beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 109339beb93cSSam Leffler return -1; 109439beb93cSSam Leffler } 109539beb93cSSam Leffler } else { 109639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: UnexpectedServerKeyExchange"); 109739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 109839beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 109939beb93cSSam Leffler return -1; 110039beb93cSSam Leffler } 110139beb93cSSam Leffler 110239beb93cSSam Leffler *in_len = end - in_data; 110339beb93cSSam Leffler 110439beb93cSSam Leffler conn->state = SERVER_CERTIFICATE_REQUEST; 110539beb93cSSam Leffler 110639beb93cSSam Leffler return 0; 110739beb93cSSam Leffler } 110839beb93cSSam Leffler 110939beb93cSSam Leffler 111039beb93cSSam Leffler static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct, 111139beb93cSSam Leffler const u8 *in_data, size_t *in_len) 111239beb93cSSam Leffler { 111339beb93cSSam Leffler const u8 *pos, *end; 111439beb93cSSam Leffler size_t left, len; 111539beb93cSSam Leffler u8 type; 111639beb93cSSam Leffler 111739beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 111839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " 111939beb93cSSam Leffler "received content type 0x%x", ct); 112039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 112139beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 112239beb93cSSam Leffler return -1; 112339beb93cSSam Leffler } 112439beb93cSSam Leffler 112539beb93cSSam Leffler pos = in_data; 112639beb93cSSam Leffler left = *in_len; 112739beb93cSSam Leffler 112839beb93cSSam Leffler if (left < 4) { 112939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateRequest " 113039beb93cSSam Leffler "(left=%lu)", (unsigned long) left); 113139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 113239beb93cSSam Leffler return -1; 113339beb93cSSam Leffler } 113439beb93cSSam Leffler 113539beb93cSSam Leffler type = *pos++; 113639beb93cSSam Leffler len = WPA_GET_BE24(pos); 113739beb93cSSam Leffler pos += 3; 113839beb93cSSam Leffler left -= 4; 113939beb93cSSam Leffler 114039beb93cSSam Leffler if (len > left) { 114139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in CertificateRequest " 114239beb93cSSam Leffler "length (len=%lu != left=%lu)", 114339beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 114439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 114539beb93cSSam Leffler return -1; 114639beb93cSSam Leffler } 114739beb93cSSam Leffler 114839beb93cSSam Leffler end = pos + len; 114939beb93cSSam Leffler 115039beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) 115139beb93cSSam Leffler return tls_process_server_hello_done(conn, ct, in_data, 115239beb93cSSam Leffler in_len); 115339beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) { 115439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " 115539beb93cSSam Leffler "message %d (expected CertificateRequest/" 115639beb93cSSam Leffler "ServerHelloDone)", type); 115739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 115839beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 115939beb93cSSam Leffler return -1; 116039beb93cSSam Leffler } 116139beb93cSSam Leffler 116239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateRequest"); 116339beb93cSSam Leffler 116439beb93cSSam Leffler conn->certificate_requested = 1; 116539beb93cSSam Leffler 116639beb93cSSam Leffler *in_len = end - in_data; 116739beb93cSSam Leffler 116839beb93cSSam Leffler conn->state = SERVER_HELLO_DONE; 116939beb93cSSam Leffler 117039beb93cSSam Leffler return 0; 117139beb93cSSam Leffler } 117239beb93cSSam Leffler 117339beb93cSSam Leffler 117439beb93cSSam Leffler static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct, 117539beb93cSSam Leffler const u8 *in_data, size_t *in_len) 117639beb93cSSam Leffler { 117739beb93cSSam Leffler const u8 *pos, *end; 117839beb93cSSam Leffler size_t left, len; 117939beb93cSSam Leffler u8 type; 118039beb93cSSam Leffler 118139beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 118239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " 118339beb93cSSam Leffler "received content type 0x%x", ct); 118439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 118539beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 118639beb93cSSam Leffler return -1; 118739beb93cSSam Leffler } 118839beb93cSSam Leffler 118939beb93cSSam Leffler pos = in_data; 119039beb93cSSam Leffler left = *in_len; 119139beb93cSSam Leffler 119239beb93cSSam Leffler if (left < 4) { 119339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerHelloDone " 119439beb93cSSam Leffler "(left=%lu)", (unsigned long) left); 119539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 119639beb93cSSam Leffler return -1; 119739beb93cSSam Leffler } 119839beb93cSSam Leffler 119939beb93cSSam Leffler type = *pos++; 120039beb93cSSam Leffler len = WPA_GET_BE24(pos); 120139beb93cSSam Leffler pos += 3; 120239beb93cSSam Leffler left -= 4; 120339beb93cSSam Leffler 120439beb93cSSam Leffler if (len > left) { 120539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerHelloDone " 120639beb93cSSam Leffler "length (len=%lu != left=%lu)", 120739beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 120839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 120939beb93cSSam Leffler return -1; 121039beb93cSSam Leffler } 121139beb93cSSam Leffler end = pos + len; 121239beb93cSSam Leffler 121339beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) { 121439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " 121539beb93cSSam Leffler "message %d (expected ServerHelloDone)", type); 121639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 121739beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 121839beb93cSSam Leffler return -1; 121939beb93cSSam Leffler } 122039beb93cSSam Leffler 122139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHelloDone"); 122239beb93cSSam Leffler 1223780fb4a2SCy Schubert if ((conn->flags & TLS_CONN_REQUIRE_OCSP) && 1224780fb4a2SCy Schubert !conn->ocsp_resp_received) { 1225780fb4a2SCy Schubert wpa_printf(MSG_INFO, 1226780fb4a2SCy Schubert "TLSv1: No OCSP response received - reject handshake"); 1227780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 1228780fb4a2SCy Schubert TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE); 1229780fb4a2SCy Schubert return -1; 1230780fb4a2SCy Schubert } 1231780fb4a2SCy Schubert 123239beb93cSSam Leffler *in_len = end - in_data; 123339beb93cSSam Leffler 123439beb93cSSam Leffler conn->state = CLIENT_KEY_EXCHANGE; 123539beb93cSSam Leffler 123639beb93cSSam Leffler return 0; 123739beb93cSSam Leffler } 123839beb93cSSam Leffler 123939beb93cSSam Leffler 124039beb93cSSam Leffler static int tls_process_server_change_cipher_spec(struct tlsv1_client *conn, 124139beb93cSSam Leffler u8 ct, const u8 *in_data, 124239beb93cSSam Leffler size_t *in_len) 124339beb93cSSam Leffler { 124439beb93cSSam Leffler const u8 *pos; 124539beb93cSSam Leffler size_t left; 124639beb93cSSam Leffler 124739beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { 124839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " 124939beb93cSSam Leffler "received content type 0x%x", ct); 125039beb93cSSam Leffler if (conn->use_session_ticket) { 125139beb93cSSam Leffler int res; 125239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Server may have " 125339beb93cSSam Leffler "rejected SessionTicket"); 125439beb93cSSam Leffler conn->use_session_ticket = 0; 125539beb93cSSam Leffler 125639beb93cSSam Leffler /* Notify upper layers that SessionTicket failed */ 125739beb93cSSam Leffler res = conn->session_ticket_cb( 125839beb93cSSam Leffler conn->session_ticket_cb_ctx, NULL, 0, NULL, 125939beb93cSSam Leffler NULL, NULL); 126039beb93cSSam Leffler if (res < 0) { 126139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket " 126239beb93cSSam Leffler "callback indicated failure"); 126339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 126439beb93cSSam Leffler TLS_ALERT_HANDSHAKE_FAILURE); 126539beb93cSSam Leffler return -1; 126639beb93cSSam Leffler } 126739beb93cSSam Leffler 126839beb93cSSam Leffler conn->state = SERVER_CERTIFICATE; 126939beb93cSSam Leffler return tls_process_certificate(conn, ct, in_data, 127039beb93cSSam Leffler in_len); 127139beb93cSSam Leffler } 127239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 127339beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 127439beb93cSSam Leffler return -1; 127539beb93cSSam Leffler } 127639beb93cSSam Leffler 127739beb93cSSam Leffler pos = in_data; 127839beb93cSSam Leffler left = *in_len; 127939beb93cSSam Leffler 128039beb93cSSam Leffler if (left < 1) { 128139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec"); 128239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 128339beb93cSSam Leffler return -1; 128439beb93cSSam Leffler } 128539beb93cSSam Leffler 128639beb93cSSam Leffler if (*pos != TLS_CHANGE_CIPHER_SPEC) { 128739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " 128839beb93cSSam Leffler "received data 0x%x", *pos); 128939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 129039beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 129139beb93cSSam Leffler return -1; 129239beb93cSSam Leffler } 129339beb93cSSam Leffler 129439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec"); 129539beb93cSSam Leffler if (tlsv1_record_change_read_cipher(&conn->rl) < 0) { 129639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher " 129739beb93cSSam Leffler "for record layer"); 129839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 129939beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 130039beb93cSSam Leffler return -1; 130139beb93cSSam Leffler } 130239beb93cSSam Leffler 130339beb93cSSam Leffler *in_len = pos + 1 - in_data; 130439beb93cSSam Leffler 130539beb93cSSam Leffler conn->state = SERVER_FINISHED; 130639beb93cSSam Leffler 130739beb93cSSam Leffler return 0; 130839beb93cSSam Leffler } 130939beb93cSSam Leffler 131039beb93cSSam Leffler 131139beb93cSSam Leffler static int tls_process_server_finished(struct tlsv1_client *conn, u8 ct, 131239beb93cSSam Leffler const u8 *in_data, size_t *in_len) 131339beb93cSSam Leffler { 131439beb93cSSam Leffler const u8 *pos, *end; 131539beb93cSSam Leffler size_t left, len, hlen; 131639beb93cSSam Leffler u8 verify_data[TLS_VERIFY_DATA_LEN]; 131739beb93cSSam Leffler u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; 131839beb93cSSam Leffler 131939beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 132039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; " 132139beb93cSSam Leffler "received content type 0x%x", ct); 132239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 132339beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 132439beb93cSSam Leffler return -1; 132539beb93cSSam Leffler } 132639beb93cSSam Leffler 132739beb93cSSam Leffler pos = in_data; 132839beb93cSSam Leffler left = *in_len; 132939beb93cSSam Leffler 133039beb93cSSam Leffler if (left < 4) { 133139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for " 133239beb93cSSam Leffler "Finished", 133339beb93cSSam Leffler (unsigned long) left); 133439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 133539beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 133639beb93cSSam Leffler return -1; 133739beb93cSSam Leffler } 133839beb93cSSam Leffler 133939beb93cSSam Leffler if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) { 134039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received " 134139beb93cSSam Leffler "type 0x%x", pos[0]); 134239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 134339beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 134439beb93cSSam Leffler return -1; 134539beb93cSSam Leffler } 134639beb93cSSam Leffler 134739beb93cSSam Leffler len = WPA_GET_BE24(pos + 1); 134839beb93cSSam Leffler 134939beb93cSSam Leffler pos += 4; 135039beb93cSSam Leffler left -= 4; 135139beb93cSSam Leffler 135239beb93cSSam Leffler if (len > left) { 135339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished " 135439beb93cSSam Leffler "(len=%lu > left=%lu)", 135539beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 135639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 135739beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 135839beb93cSSam Leffler return -1; 135939beb93cSSam Leffler } 136039beb93cSSam Leffler end = pos + len; 136139beb93cSSam Leffler if (len != TLS_VERIFY_DATA_LEN) { 136239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length " 136339beb93cSSam Leffler "in Finished: %lu (expected %d)", 136439beb93cSSam Leffler (unsigned long) len, TLS_VERIFY_DATA_LEN); 136539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 136639beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 136739beb93cSSam Leffler return -1; 136839beb93cSSam Leffler } 136939beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished", 137039beb93cSSam Leffler pos, TLS_VERIFY_DATA_LEN); 137139beb93cSSam Leffler 1372f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 1373f05cddf9SRui Paulo if (conn->rl.tls_version >= TLS_VERSION_1_2) { 1374f05cddf9SRui Paulo hlen = SHA256_MAC_LEN; 1375f05cddf9SRui Paulo if (conn->verify.sha256_server == NULL || 1376f05cddf9SRui Paulo crypto_hash_finish(conn->verify.sha256_server, hash, &hlen) 1377f05cddf9SRui Paulo < 0) { 1378f05cddf9SRui Paulo tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 1379f05cddf9SRui Paulo TLS_ALERT_INTERNAL_ERROR); 1380f05cddf9SRui Paulo conn->verify.sha256_server = NULL; 1381f05cddf9SRui Paulo return -1; 1382f05cddf9SRui Paulo } 1383f05cddf9SRui Paulo conn->verify.sha256_server = NULL; 1384f05cddf9SRui Paulo } else { 1385f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 1386f05cddf9SRui Paulo 138739beb93cSSam Leffler hlen = MD5_MAC_LEN; 138839beb93cSSam Leffler if (conn->verify.md5_server == NULL || 138939beb93cSSam Leffler crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) { 139039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 139139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 139239beb93cSSam Leffler conn->verify.md5_server = NULL; 139339beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_server, NULL, NULL); 139439beb93cSSam Leffler conn->verify.sha1_server = NULL; 139539beb93cSSam Leffler return -1; 139639beb93cSSam Leffler } 139739beb93cSSam Leffler conn->verify.md5_server = NULL; 139839beb93cSSam Leffler hlen = SHA1_MAC_LEN; 139939beb93cSSam Leffler if (conn->verify.sha1_server == NULL || 140039beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN, 140139beb93cSSam Leffler &hlen) < 0) { 140239beb93cSSam Leffler conn->verify.sha1_server = NULL; 140339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 140439beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 140539beb93cSSam Leffler return -1; 140639beb93cSSam Leffler } 140739beb93cSSam Leffler conn->verify.sha1_server = NULL; 1408f05cddf9SRui Paulo hlen = MD5_MAC_LEN + SHA1_MAC_LEN; 140939beb93cSSam Leffler 1410f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 1411f05cddf9SRui Paulo } 1412f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 1413f05cddf9SRui Paulo 1414f05cddf9SRui Paulo if (tls_prf(conn->rl.tls_version, 1415f05cddf9SRui Paulo conn->master_secret, TLS_MASTER_SECRET_LEN, 1416f05cddf9SRui Paulo "server finished", hash, hlen, 141739beb93cSSam Leffler verify_data, TLS_VERIFY_DATA_LEN)) { 141839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data"); 141939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 142039beb93cSSam Leffler TLS_ALERT_DECRYPT_ERROR); 142139beb93cSSam Leffler return -1; 142239beb93cSSam Leffler } 142339beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)", 142439beb93cSSam Leffler verify_data, TLS_VERIFY_DATA_LEN); 142539beb93cSSam Leffler 14265b9c547cSRui Paulo if (os_memcmp_const(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) { 142739beb93cSSam Leffler wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data"); 14285b9c547cSRui Paulo tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 14295b9c547cSRui Paulo TLS_ALERT_DECRYPT_ERROR); 143039beb93cSSam Leffler return -1; 143139beb93cSSam Leffler } 143239beb93cSSam Leffler 143339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received Finished"); 143439beb93cSSam Leffler 143539beb93cSSam Leffler *in_len = end - in_data; 143639beb93cSSam Leffler 143739beb93cSSam Leffler conn->state = (conn->session_resumed || conn->use_session_ticket) ? 143839beb93cSSam Leffler CHANGE_CIPHER_SPEC : ACK_FINISHED; 143939beb93cSSam Leffler 144039beb93cSSam Leffler return 0; 144139beb93cSSam Leffler } 144239beb93cSSam Leffler 144339beb93cSSam Leffler 144439beb93cSSam Leffler static int tls_process_application_data(struct tlsv1_client *conn, u8 ct, 144539beb93cSSam Leffler const u8 *in_data, size_t *in_len, 144639beb93cSSam Leffler u8 **out_data, size_t *out_len) 144739beb93cSSam Leffler { 144839beb93cSSam Leffler const u8 *pos; 144939beb93cSSam Leffler size_t left; 145039beb93cSSam Leffler 145139beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) { 145239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Application Data; " 145339beb93cSSam Leffler "received content type 0x%x", ct); 145439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 145539beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 145639beb93cSSam Leffler return -1; 145739beb93cSSam Leffler } 145839beb93cSSam Leffler 145939beb93cSSam Leffler pos = in_data; 146039beb93cSSam Leffler left = *in_len; 146139beb93cSSam Leffler 146239beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: Application Data included in Handshake", 146339beb93cSSam Leffler pos, left); 146439beb93cSSam Leffler 146539beb93cSSam Leffler *out_data = os_malloc(left); 146639beb93cSSam Leffler if (*out_data) { 146739beb93cSSam Leffler os_memcpy(*out_data, pos, left); 146839beb93cSSam Leffler *out_len = left; 146939beb93cSSam Leffler } 147039beb93cSSam Leffler 147139beb93cSSam Leffler return 0; 147239beb93cSSam Leffler } 147339beb93cSSam Leffler 147439beb93cSSam Leffler 147539beb93cSSam Leffler int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct, 147639beb93cSSam Leffler const u8 *buf, size_t *len, 147739beb93cSSam Leffler u8 **out_data, size_t *out_len) 147839beb93cSSam Leffler { 147939beb93cSSam Leffler if (ct == TLS_CONTENT_TYPE_ALERT) { 148039beb93cSSam Leffler if (*len < 2) { 148139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow"); 148239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 148339beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 148439beb93cSSam Leffler return -1; 148539beb93cSSam Leffler } 148639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d", 148739beb93cSSam Leffler buf[0], buf[1]); 148839beb93cSSam Leffler *len = 2; 148939beb93cSSam Leffler conn->state = FAILED; 149039beb93cSSam Leffler return -1; 149139beb93cSSam Leffler } 149239beb93cSSam Leffler 149339beb93cSSam Leffler if (ct == TLS_CONTENT_TYPE_HANDSHAKE && *len >= 4 && 149439beb93cSSam Leffler buf[0] == TLS_HANDSHAKE_TYPE_HELLO_REQUEST) { 149539beb93cSSam Leffler size_t hr_len = WPA_GET_BE24(buf + 1); 149639beb93cSSam Leffler if (hr_len > *len - 4) { 149739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: HelloRequest underflow"); 149839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 149939beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 150039beb93cSSam Leffler return -1; 150139beb93cSSam Leffler } 150239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Ignored HelloRequest"); 150339beb93cSSam Leffler *len = 4 + hr_len; 150439beb93cSSam Leffler return 0; 150539beb93cSSam Leffler } 150639beb93cSSam Leffler 150739beb93cSSam Leffler switch (conn->state) { 150839beb93cSSam Leffler case SERVER_HELLO: 150939beb93cSSam Leffler if (tls_process_server_hello(conn, ct, buf, len)) 151039beb93cSSam Leffler return -1; 151139beb93cSSam Leffler break; 151239beb93cSSam Leffler case SERVER_CERTIFICATE: 151339beb93cSSam Leffler if (tls_process_certificate(conn, ct, buf, len)) 151439beb93cSSam Leffler return -1; 151539beb93cSSam Leffler break; 151639beb93cSSam Leffler case SERVER_KEY_EXCHANGE: 151739beb93cSSam Leffler if (tls_process_server_key_exchange(conn, ct, buf, len)) 151839beb93cSSam Leffler return -1; 151939beb93cSSam Leffler break; 152039beb93cSSam Leffler case SERVER_CERTIFICATE_REQUEST: 152139beb93cSSam Leffler if (tls_process_certificate_request(conn, ct, buf, len)) 152239beb93cSSam Leffler return -1; 152339beb93cSSam Leffler break; 152439beb93cSSam Leffler case SERVER_HELLO_DONE: 152539beb93cSSam Leffler if (tls_process_server_hello_done(conn, ct, buf, len)) 152639beb93cSSam Leffler return -1; 152739beb93cSSam Leffler break; 152839beb93cSSam Leffler case SERVER_CHANGE_CIPHER_SPEC: 152939beb93cSSam Leffler if (tls_process_server_change_cipher_spec(conn, ct, buf, len)) 153039beb93cSSam Leffler return -1; 153139beb93cSSam Leffler break; 153239beb93cSSam Leffler case SERVER_FINISHED: 153339beb93cSSam Leffler if (tls_process_server_finished(conn, ct, buf, len)) 153439beb93cSSam Leffler return -1; 153539beb93cSSam Leffler break; 153639beb93cSSam Leffler case ACK_FINISHED: 153739beb93cSSam Leffler if (out_data && 153839beb93cSSam Leffler tls_process_application_data(conn, ct, buf, len, out_data, 153939beb93cSSam Leffler out_len)) 154039beb93cSSam Leffler return -1; 154139beb93cSSam Leffler break; 154239beb93cSSam Leffler default: 154339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d " 154439beb93cSSam Leffler "while processing received message", 154539beb93cSSam Leffler conn->state); 154639beb93cSSam Leffler return -1; 154739beb93cSSam Leffler } 154839beb93cSSam Leffler 154939beb93cSSam Leffler if (ct == TLS_CONTENT_TYPE_HANDSHAKE) 155039beb93cSSam Leffler tls_verify_hash_add(&conn->verify, buf, *len); 155139beb93cSSam Leffler 155239beb93cSSam Leffler return 0; 155339beb93cSSam Leffler } 1554