139beb93cSSam Leffler /* 239beb93cSSam Leffler * TLSv1 client - read handshake message 3*f05cddf9SRui Paulo * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 5*f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6*f05cddf9SRui 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" 14*f05cddf9SRui 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 3039beb93cSSam Leffler static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct, 3139beb93cSSam Leffler const u8 *in_data, size_t *in_len) 3239beb93cSSam Leffler { 3339beb93cSSam Leffler const u8 *pos, *end; 3439beb93cSSam Leffler size_t left, len, i; 3539beb93cSSam Leffler u16 cipher_suite; 36*f05cddf9SRui Paulo u16 tls_version; 3739beb93cSSam Leffler 3839beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 3939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " 4039beb93cSSam Leffler "received content type 0x%x", ct); 4139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 4239beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 4339beb93cSSam Leffler return -1; 4439beb93cSSam Leffler } 4539beb93cSSam Leffler 4639beb93cSSam Leffler pos = in_data; 4739beb93cSSam Leffler left = *in_len; 4839beb93cSSam Leffler 4939beb93cSSam Leffler if (left < 4) 5039beb93cSSam Leffler goto decode_error; 5139beb93cSSam Leffler 5239beb93cSSam Leffler /* HandshakeType msg_type */ 5339beb93cSSam Leffler if (*pos != TLS_HANDSHAKE_TYPE_SERVER_HELLO) { 5439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " 5539beb93cSSam Leffler "message %d (expected ServerHello)", *pos); 5639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 5739beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 5839beb93cSSam Leffler return -1; 5939beb93cSSam Leffler } 6039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHello"); 6139beb93cSSam Leffler pos++; 6239beb93cSSam Leffler /* uint24 length */ 6339beb93cSSam Leffler len = WPA_GET_BE24(pos); 6439beb93cSSam Leffler pos += 3; 6539beb93cSSam Leffler left -= 4; 6639beb93cSSam Leffler 6739beb93cSSam Leffler if (len > left) 6839beb93cSSam Leffler goto decode_error; 6939beb93cSSam Leffler 7039beb93cSSam Leffler /* body - ServerHello */ 7139beb93cSSam Leffler 7239beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello", pos, len); 7339beb93cSSam Leffler end = pos + len; 7439beb93cSSam Leffler 7539beb93cSSam Leffler /* ProtocolVersion server_version */ 7639beb93cSSam Leffler if (end - pos < 2) 7739beb93cSSam Leffler goto decode_error; 78*f05cddf9SRui Paulo tls_version = WPA_GET_BE16(pos); 79*f05cddf9SRui Paulo if (!tls_version_ok(tls_version)) { 8039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in " 81*f05cddf9SRui Paulo "ServerHello %u.%u", pos[0], pos[1]); 8239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 8339beb93cSSam Leffler TLS_ALERT_PROTOCOL_VERSION); 8439beb93cSSam Leffler return -1; 8539beb93cSSam Leffler } 8639beb93cSSam Leffler pos += 2; 8739beb93cSSam Leffler 88*f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "TLSv1: Using TLS v%s", 89*f05cddf9SRui Paulo tls_version_str(tls_version)); 90*f05cddf9SRui Paulo conn->rl.tls_version = tls_version; 91*f05cddf9SRui Paulo 9239beb93cSSam Leffler /* Random random */ 9339beb93cSSam Leffler if (end - pos < TLS_RANDOM_LEN) 9439beb93cSSam Leffler goto decode_error; 9539beb93cSSam Leffler 9639beb93cSSam Leffler os_memcpy(conn->server_random, pos, TLS_RANDOM_LEN); 9739beb93cSSam Leffler pos += TLS_RANDOM_LEN; 9839beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random", 9939beb93cSSam Leffler conn->server_random, TLS_RANDOM_LEN); 10039beb93cSSam Leffler 10139beb93cSSam Leffler /* SessionID session_id */ 10239beb93cSSam Leffler if (end - pos < 1) 10339beb93cSSam Leffler goto decode_error; 10439beb93cSSam Leffler if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN) 10539beb93cSSam Leffler goto decode_error; 10639beb93cSSam Leffler if (conn->session_id_len && conn->session_id_len == *pos && 10739beb93cSSam Leffler os_memcmp(conn->session_id, pos + 1, conn->session_id_len) == 0) { 10839beb93cSSam Leffler pos += 1 + conn->session_id_len; 10939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Resuming old session"); 11039beb93cSSam Leffler conn->session_resumed = 1; 11139beb93cSSam Leffler } else { 11239beb93cSSam Leffler conn->session_id_len = *pos; 11339beb93cSSam Leffler pos++; 11439beb93cSSam Leffler os_memcpy(conn->session_id, pos, conn->session_id_len); 11539beb93cSSam Leffler pos += conn->session_id_len; 11639beb93cSSam Leffler } 11739beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id", 11839beb93cSSam Leffler conn->session_id, conn->session_id_len); 11939beb93cSSam Leffler 12039beb93cSSam Leffler /* CipherSuite cipher_suite */ 12139beb93cSSam Leffler if (end - pos < 2) 12239beb93cSSam Leffler goto decode_error; 12339beb93cSSam Leffler cipher_suite = WPA_GET_BE16(pos); 12439beb93cSSam Leffler pos += 2; 12539beb93cSSam Leffler for (i = 0; i < conn->num_cipher_suites; i++) { 12639beb93cSSam Leffler if (cipher_suite == conn->cipher_suites[i]) 12739beb93cSSam Leffler break; 12839beb93cSSam Leffler } 12939beb93cSSam Leffler if (i == conn->num_cipher_suites) { 13039beb93cSSam Leffler wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected " 13139beb93cSSam Leffler "cipher suite 0x%04x", cipher_suite); 13239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 13339beb93cSSam Leffler TLS_ALERT_ILLEGAL_PARAMETER); 13439beb93cSSam Leffler return -1; 13539beb93cSSam Leffler } 13639beb93cSSam Leffler 13739beb93cSSam Leffler if (conn->session_resumed && cipher_suite != conn->prev_cipher_suite) { 13839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Server selected a different " 13939beb93cSSam Leffler "cipher suite for a resumed connection (0x%04x != " 14039beb93cSSam Leffler "0x%04x)", cipher_suite, conn->prev_cipher_suite); 14139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 14239beb93cSSam Leffler TLS_ALERT_ILLEGAL_PARAMETER); 14339beb93cSSam Leffler return -1; 14439beb93cSSam Leffler } 14539beb93cSSam Leffler 14639beb93cSSam Leffler if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) { 14739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for " 14839beb93cSSam Leffler "record layer"); 14939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 15039beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 15139beb93cSSam Leffler return -1; 15239beb93cSSam Leffler } 15339beb93cSSam Leffler 15439beb93cSSam Leffler conn->prev_cipher_suite = cipher_suite; 15539beb93cSSam Leffler 15639beb93cSSam Leffler /* CompressionMethod compression_method */ 15739beb93cSSam Leffler if (end - pos < 1) 15839beb93cSSam Leffler goto decode_error; 15939beb93cSSam Leffler if (*pos != TLS_COMPRESSION_NULL) { 16039beb93cSSam Leffler wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected " 16139beb93cSSam Leffler "compression 0x%02x", *pos); 16239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 16339beb93cSSam Leffler TLS_ALERT_ILLEGAL_PARAMETER); 16439beb93cSSam Leffler return -1; 16539beb93cSSam Leffler } 16639beb93cSSam Leffler pos++; 16739beb93cSSam Leffler 16839beb93cSSam Leffler if (end != pos) { 16939beb93cSSam Leffler /* TODO: ServerHello extensions */ 17039beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: Unexpected extra data in the " 17139beb93cSSam Leffler "end of ServerHello", pos, end - pos); 17239beb93cSSam Leffler goto decode_error; 17339beb93cSSam Leffler } 17439beb93cSSam Leffler 17539beb93cSSam Leffler if (conn->session_ticket_included && conn->session_ticket_cb) { 17639beb93cSSam Leffler /* TODO: include SessionTicket extension if one was included in 17739beb93cSSam Leffler * ServerHello */ 17839beb93cSSam Leffler int res = conn->session_ticket_cb( 17939beb93cSSam Leffler conn->session_ticket_cb_ctx, NULL, 0, 18039beb93cSSam Leffler conn->client_random, conn->server_random, 18139beb93cSSam Leffler conn->master_secret); 18239beb93cSSam Leffler if (res < 0) { 18339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback " 18439beb93cSSam Leffler "indicated failure"); 18539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 18639beb93cSSam Leffler TLS_ALERT_HANDSHAKE_FAILURE); 18739beb93cSSam Leffler return -1; 18839beb93cSSam Leffler } 18939beb93cSSam Leffler conn->use_session_ticket = !!res; 19039beb93cSSam Leffler } 19139beb93cSSam Leffler 19239beb93cSSam Leffler if ((conn->session_resumed || conn->use_session_ticket) && 19339beb93cSSam Leffler tls_derive_keys(conn, NULL, 0)) { 19439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); 19539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 19639beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 19739beb93cSSam Leffler return -1; 19839beb93cSSam Leffler } 19939beb93cSSam Leffler 20039beb93cSSam Leffler *in_len = end - in_data; 20139beb93cSSam Leffler 20239beb93cSSam Leffler conn->state = (conn->session_resumed || conn->use_session_ticket) ? 20339beb93cSSam Leffler SERVER_CHANGE_CIPHER_SPEC : SERVER_CERTIFICATE; 20439beb93cSSam Leffler 20539beb93cSSam Leffler return 0; 20639beb93cSSam Leffler 20739beb93cSSam Leffler decode_error: 20839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ServerHello"); 20939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 21039beb93cSSam Leffler return -1; 21139beb93cSSam Leffler } 21239beb93cSSam Leffler 21339beb93cSSam Leffler 21439beb93cSSam Leffler static int tls_process_certificate(struct tlsv1_client *conn, u8 ct, 21539beb93cSSam Leffler const u8 *in_data, size_t *in_len) 21639beb93cSSam Leffler { 21739beb93cSSam Leffler const u8 *pos, *end; 21839beb93cSSam Leffler size_t left, len, list_len, cert_len, idx; 21939beb93cSSam Leffler u8 type; 22039beb93cSSam Leffler struct x509_certificate *chain = NULL, *last = NULL, *cert; 22139beb93cSSam Leffler int reason; 22239beb93cSSam Leffler 22339beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 22439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " 22539beb93cSSam Leffler "received content type 0x%x", ct); 22639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 22739beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 22839beb93cSSam Leffler return -1; 22939beb93cSSam Leffler } 23039beb93cSSam Leffler 23139beb93cSSam Leffler pos = in_data; 23239beb93cSSam Leffler left = *in_len; 23339beb93cSSam Leffler 23439beb93cSSam Leffler if (left < 4) { 23539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message " 23639beb93cSSam Leffler "(len=%lu)", (unsigned long) left); 23739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 23839beb93cSSam Leffler return -1; 23939beb93cSSam Leffler } 24039beb93cSSam Leffler 24139beb93cSSam Leffler type = *pos++; 24239beb93cSSam Leffler len = WPA_GET_BE24(pos); 24339beb93cSSam Leffler pos += 3; 24439beb93cSSam Leffler left -= 4; 24539beb93cSSam Leffler 24639beb93cSSam Leffler if (len > left) { 24739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message " 24839beb93cSSam Leffler "length (len=%lu != left=%lu)", 24939beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 25039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 25139beb93cSSam Leffler return -1; 25239beb93cSSam Leffler } 25339beb93cSSam Leffler 25439beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) 25539beb93cSSam Leffler return tls_process_server_key_exchange(conn, ct, in_data, 25639beb93cSSam Leffler in_len); 25739beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) 25839beb93cSSam Leffler return tls_process_certificate_request(conn, ct, in_data, 25939beb93cSSam Leffler in_len); 26039beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) 26139beb93cSSam Leffler return tls_process_server_hello_done(conn, ct, in_data, 26239beb93cSSam Leffler in_len); 26339beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) { 26439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " 26539beb93cSSam Leffler "message %d (expected Certificate/" 26639beb93cSSam Leffler "ServerKeyExchange/CertificateRequest/" 26739beb93cSSam Leffler "ServerHelloDone)", type); 26839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 26939beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 27039beb93cSSam Leffler return -1; 27139beb93cSSam Leffler } 27239beb93cSSam Leffler 27339beb93cSSam Leffler wpa_printf(MSG_DEBUG, 27439beb93cSSam Leffler "TLSv1: Received Certificate (certificate_list len %lu)", 27539beb93cSSam Leffler (unsigned long) len); 27639beb93cSSam Leffler 27739beb93cSSam Leffler /* 27839beb93cSSam Leffler * opaque ASN.1Cert<2^24-1>; 27939beb93cSSam Leffler * 28039beb93cSSam Leffler * struct { 28139beb93cSSam Leffler * ASN.1Cert certificate_list<1..2^24-1>; 28239beb93cSSam Leffler * } Certificate; 28339beb93cSSam Leffler */ 28439beb93cSSam Leffler 28539beb93cSSam Leffler end = pos + len; 28639beb93cSSam Leffler 28739beb93cSSam Leffler if (end - pos < 3) { 28839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate " 28939beb93cSSam Leffler "(left=%lu)", (unsigned long) left); 29039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 29139beb93cSSam Leffler return -1; 29239beb93cSSam Leffler } 29339beb93cSSam Leffler 29439beb93cSSam Leffler list_len = WPA_GET_BE24(pos); 29539beb93cSSam Leffler pos += 3; 29639beb93cSSam Leffler 29739beb93cSSam Leffler if ((size_t) (end - pos) != list_len) { 29839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list " 29939beb93cSSam Leffler "length (len=%lu left=%lu)", 30039beb93cSSam Leffler (unsigned long) list_len, 30139beb93cSSam Leffler (unsigned long) (end - pos)); 30239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 30339beb93cSSam Leffler return -1; 30439beb93cSSam Leffler } 30539beb93cSSam Leffler 30639beb93cSSam Leffler idx = 0; 30739beb93cSSam Leffler while (pos < end) { 30839beb93cSSam Leffler if (end - pos < 3) { 30939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " 31039beb93cSSam Leffler "certificate_list"); 31139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 31239beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 31339beb93cSSam Leffler x509_certificate_chain_free(chain); 31439beb93cSSam Leffler return -1; 31539beb93cSSam Leffler } 31639beb93cSSam Leffler 31739beb93cSSam Leffler cert_len = WPA_GET_BE24(pos); 31839beb93cSSam Leffler pos += 3; 31939beb93cSSam Leffler 32039beb93cSSam Leffler if ((size_t) (end - pos) < cert_len) { 32139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate " 32239beb93cSSam Leffler "length (len=%lu left=%lu)", 32339beb93cSSam Leffler (unsigned long) cert_len, 32439beb93cSSam Leffler (unsigned long) (end - pos)); 32539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 32639beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 32739beb93cSSam Leffler x509_certificate_chain_free(chain); 32839beb93cSSam Leffler return -1; 32939beb93cSSam Leffler } 33039beb93cSSam Leffler 33139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)", 33239beb93cSSam Leffler (unsigned long) idx, (unsigned long) cert_len); 33339beb93cSSam Leffler 33439beb93cSSam Leffler if (idx == 0) { 33539beb93cSSam Leffler crypto_public_key_free(conn->server_rsa_key); 33639beb93cSSam Leffler if (tls_parse_cert(pos, cert_len, 33739beb93cSSam Leffler &conn->server_rsa_key)) { 33839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " 33939beb93cSSam Leffler "the certificate"); 34039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 34139beb93cSSam Leffler TLS_ALERT_BAD_CERTIFICATE); 34239beb93cSSam Leffler x509_certificate_chain_free(chain); 34339beb93cSSam Leffler return -1; 34439beb93cSSam Leffler } 34539beb93cSSam Leffler } 34639beb93cSSam Leffler 34739beb93cSSam Leffler cert = x509_certificate_parse(pos, cert_len); 34839beb93cSSam Leffler if (cert == NULL) { 34939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " 35039beb93cSSam Leffler "the certificate"); 35139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 35239beb93cSSam Leffler TLS_ALERT_BAD_CERTIFICATE); 35339beb93cSSam Leffler x509_certificate_chain_free(chain); 35439beb93cSSam Leffler return -1; 35539beb93cSSam Leffler } 35639beb93cSSam Leffler 35739beb93cSSam Leffler if (last == NULL) 35839beb93cSSam Leffler chain = cert; 35939beb93cSSam Leffler else 36039beb93cSSam Leffler last->next = cert; 36139beb93cSSam Leffler last = cert; 36239beb93cSSam Leffler 36339beb93cSSam Leffler idx++; 36439beb93cSSam Leffler pos += cert_len; 36539beb93cSSam Leffler } 36639beb93cSSam Leffler 36739beb93cSSam Leffler if (conn->cred && 36839beb93cSSam Leffler x509_certificate_chain_validate(conn->cred->trusted_certs, chain, 369*f05cddf9SRui Paulo &reason, conn->disable_time_checks) 370*f05cddf9SRui Paulo < 0) { 37139beb93cSSam Leffler int tls_reason; 37239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain " 37339beb93cSSam Leffler "validation failed (reason=%d)", reason); 37439beb93cSSam Leffler switch (reason) { 37539beb93cSSam Leffler case X509_VALIDATE_BAD_CERTIFICATE: 37639beb93cSSam Leffler tls_reason = TLS_ALERT_BAD_CERTIFICATE; 37739beb93cSSam Leffler break; 37839beb93cSSam Leffler case X509_VALIDATE_UNSUPPORTED_CERTIFICATE: 37939beb93cSSam Leffler tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE; 38039beb93cSSam Leffler break; 38139beb93cSSam Leffler case X509_VALIDATE_CERTIFICATE_REVOKED: 38239beb93cSSam Leffler tls_reason = TLS_ALERT_CERTIFICATE_REVOKED; 38339beb93cSSam Leffler break; 38439beb93cSSam Leffler case X509_VALIDATE_CERTIFICATE_EXPIRED: 38539beb93cSSam Leffler tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED; 38639beb93cSSam Leffler break; 38739beb93cSSam Leffler case X509_VALIDATE_CERTIFICATE_UNKNOWN: 38839beb93cSSam Leffler tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN; 38939beb93cSSam Leffler break; 39039beb93cSSam Leffler case X509_VALIDATE_UNKNOWN_CA: 39139beb93cSSam Leffler tls_reason = TLS_ALERT_UNKNOWN_CA; 39239beb93cSSam Leffler break; 39339beb93cSSam Leffler default: 39439beb93cSSam Leffler tls_reason = TLS_ALERT_BAD_CERTIFICATE; 39539beb93cSSam Leffler break; 39639beb93cSSam Leffler } 39739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason); 39839beb93cSSam Leffler x509_certificate_chain_free(chain); 39939beb93cSSam Leffler return -1; 40039beb93cSSam Leffler } 40139beb93cSSam Leffler 40239beb93cSSam Leffler x509_certificate_chain_free(chain); 40339beb93cSSam Leffler 40439beb93cSSam Leffler *in_len = end - in_data; 40539beb93cSSam Leffler 40639beb93cSSam Leffler conn->state = SERVER_KEY_EXCHANGE; 40739beb93cSSam Leffler 40839beb93cSSam Leffler return 0; 40939beb93cSSam Leffler } 41039beb93cSSam Leffler 41139beb93cSSam Leffler 41239beb93cSSam Leffler static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn, 41339beb93cSSam Leffler const u8 *buf, size_t len) 41439beb93cSSam Leffler { 41539beb93cSSam Leffler const u8 *pos, *end; 41639beb93cSSam Leffler 41739beb93cSSam Leffler tlsv1_client_free_dh(conn); 41839beb93cSSam Leffler 41939beb93cSSam Leffler pos = buf; 42039beb93cSSam Leffler end = buf + len; 42139beb93cSSam Leffler 42239beb93cSSam Leffler if (end - pos < 3) 42339beb93cSSam Leffler goto fail; 42439beb93cSSam Leffler conn->dh_p_len = WPA_GET_BE16(pos); 42539beb93cSSam Leffler pos += 2; 42639beb93cSSam Leffler if (conn->dh_p_len == 0 || end - pos < (int) conn->dh_p_len) { 42739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Invalid dh_p length %lu", 42839beb93cSSam Leffler (unsigned long) conn->dh_p_len); 42939beb93cSSam Leffler goto fail; 43039beb93cSSam Leffler } 43139beb93cSSam Leffler conn->dh_p = os_malloc(conn->dh_p_len); 43239beb93cSSam Leffler if (conn->dh_p == NULL) 43339beb93cSSam Leffler goto fail; 43439beb93cSSam Leffler os_memcpy(conn->dh_p, pos, conn->dh_p_len); 43539beb93cSSam Leffler pos += conn->dh_p_len; 43639beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: DH p (prime)", 43739beb93cSSam Leffler conn->dh_p, conn->dh_p_len); 43839beb93cSSam Leffler 43939beb93cSSam Leffler if (end - pos < 3) 44039beb93cSSam Leffler goto fail; 44139beb93cSSam Leffler conn->dh_g_len = WPA_GET_BE16(pos); 44239beb93cSSam Leffler pos += 2; 44339beb93cSSam Leffler if (conn->dh_g_len == 0 || end - pos < (int) conn->dh_g_len) 44439beb93cSSam Leffler goto fail; 44539beb93cSSam Leffler conn->dh_g = os_malloc(conn->dh_g_len); 44639beb93cSSam Leffler if (conn->dh_g == NULL) 44739beb93cSSam Leffler goto fail; 44839beb93cSSam Leffler os_memcpy(conn->dh_g, pos, conn->dh_g_len); 44939beb93cSSam Leffler pos += conn->dh_g_len; 45039beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: DH g (generator)", 45139beb93cSSam Leffler conn->dh_g, conn->dh_g_len); 45239beb93cSSam Leffler if (conn->dh_g_len == 1 && conn->dh_g[0] < 2) 45339beb93cSSam Leffler goto fail; 45439beb93cSSam Leffler 45539beb93cSSam Leffler if (end - pos < 3) 45639beb93cSSam Leffler goto fail; 45739beb93cSSam Leffler conn->dh_ys_len = WPA_GET_BE16(pos); 45839beb93cSSam Leffler pos += 2; 45939beb93cSSam Leffler if (conn->dh_ys_len == 0 || end - pos < (int) conn->dh_ys_len) 46039beb93cSSam Leffler goto fail; 46139beb93cSSam Leffler conn->dh_ys = os_malloc(conn->dh_ys_len); 46239beb93cSSam Leffler if (conn->dh_ys == NULL) 46339beb93cSSam Leffler goto fail; 46439beb93cSSam Leffler os_memcpy(conn->dh_ys, pos, conn->dh_ys_len); 46539beb93cSSam Leffler pos += conn->dh_ys_len; 46639beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)", 46739beb93cSSam Leffler conn->dh_ys, conn->dh_ys_len); 46839beb93cSSam Leffler 46939beb93cSSam Leffler return 0; 47039beb93cSSam Leffler 47139beb93cSSam Leffler fail: 47239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Processing DH params failed"); 47339beb93cSSam Leffler tlsv1_client_free_dh(conn); 47439beb93cSSam Leffler return -1; 47539beb93cSSam Leffler } 47639beb93cSSam Leffler 47739beb93cSSam Leffler 47839beb93cSSam Leffler static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct, 47939beb93cSSam Leffler const u8 *in_data, size_t *in_len) 48039beb93cSSam Leffler { 48139beb93cSSam Leffler const u8 *pos, *end; 48239beb93cSSam Leffler size_t left, len; 48339beb93cSSam Leffler u8 type; 48439beb93cSSam Leffler const struct tls_cipher_suite *suite; 48539beb93cSSam Leffler 48639beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 48739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " 48839beb93cSSam Leffler "received content type 0x%x", ct); 48939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 49039beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 49139beb93cSSam Leffler return -1; 49239beb93cSSam Leffler } 49339beb93cSSam Leffler 49439beb93cSSam Leffler pos = in_data; 49539beb93cSSam Leffler left = *in_len; 49639beb93cSSam Leffler 49739beb93cSSam Leffler if (left < 4) { 49839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerKeyExchange " 49939beb93cSSam Leffler "(Left=%lu)", (unsigned long) left); 50039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 50139beb93cSSam Leffler return -1; 50239beb93cSSam Leffler } 50339beb93cSSam Leffler 50439beb93cSSam Leffler type = *pos++; 50539beb93cSSam Leffler len = WPA_GET_BE24(pos); 50639beb93cSSam Leffler pos += 3; 50739beb93cSSam Leffler left -= 4; 50839beb93cSSam Leffler 50939beb93cSSam Leffler if (len > left) { 51039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerKeyExchange " 51139beb93cSSam Leffler "length (len=%lu != left=%lu)", 51239beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 51339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 51439beb93cSSam Leffler return -1; 51539beb93cSSam Leffler } 51639beb93cSSam Leffler 51739beb93cSSam Leffler end = pos + len; 51839beb93cSSam Leffler 51939beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) 52039beb93cSSam Leffler return tls_process_certificate_request(conn, ct, in_data, 52139beb93cSSam Leffler in_len); 52239beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) 52339beb93cSSam Leffler return tls_process_server_hello_done(conn, ct, in_data, 52439beb93cSSam Leffler in_len); 52539beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) { 52639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " 52739beb93cSSam Leffler "message %d (expected ServerKeyExchange/" 52839beb93cSSam Leffler "CertificateRequest/ServerHelloDone)", type); 52939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 53039beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 53139beb93cSSam Leffler return -1; 53239beb93cSSam Leffler } 53339beb93cSSam Leffler 53439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received ServerKeyExchange"); 53539beb93cSSam Leffler 53639beb93cSSam Leffler if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) { 53739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not allowed " 53839beb93cSSam Leffler "with the selected cipher suite"); 53939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 54039beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 54139beb93cSSam Leffler return -1; 54239beb93cSSam Leffler } 54339beb93cSSam Leffler 54439beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: ServerKeyExchange", pos, len); 54539beb93cSSam Leffler suite = tls_get_cipher_suite(conn->rl.cipher_suite); 54639beb93cSSam Leffler if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) { 54739beb93cSSam Leffler if (tlsv1_process_diffie_hellman(conn, pos, len) < 0) { 54839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 54939beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 55039beb93cSSam Leffler return -1; 55139beb93cSSam Leffler } 55239beb93cSSam Leffler } else { 55339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: UnexpectedServerKeyExchange"); 55439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 55539beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 55639beb93cSSam Leffler return -1; 55739beb93cSSam Leffler } 55839beb93cSSam Leffler 55939beb93cSSam Leffler *in_len = end - in_data; 56039beb93cSSam Leffler 56139beb93cSSam Leffler conn->state = SERVER_CERTIFICATE_REQUEST; 56239beb93cSSam Leffler 56339beb93cSSam Leffler return 0; 56439beb93cSSam Leffler } 56539beb93cSSam Leffler 56639beb93cSSam Leffler 56739beb93cSSam Leffler static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct, 56839beb93cSSam Leffler const u8 *in_data, size_t *in_len) 56939beb93cSSam Leffler { 57039beb93cSSam Leffler const u8 *pos, *end; 57139beb93cSSam Leffler size_t left, len; 57239beb93cSSam Leffler u8 type; 57339beb93cSSam Leffler 57439beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 57539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " 57639beb93cSSam Leffler "received content type 0x%x", ct); 57739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 57839beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 57939beb93cSSam Leffler return -1; 58039beb93cSSam Leffler } 58139beb93cSSam Leffler 58239beb93cSSam Leffler pos = in_data; 58339beb93cSSam Leffler left = *in_len; 58439beb93cSSam Leffler 58539beb93cSSam Leffler if (left < 4) { 58639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateRequest " 58739beb93cSSam Leffler "(left=%lu)", (unsigned long) left); 58839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 58939beb93cSSam Leffler return -1; 59039beb93cSSam Leffler } 59139beb93cSSam Leffler 59239beb93cSSam Leffler type = *pos++; 59339beb93cSSam Leffler len = WPA_GET_BE24(pos); 59439beb93cSSam Leffler pos += 3; 59539beb93cSSam Leffler left -= 4; 59639beb93cSSam Leffler 59739beb93cSSam Leffler if (len > left) { 59839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in CertificateRequest " 59939beb93cSSam Leffler "length (len=%lu != left=%lu)", 60039beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 60139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 60239beb93cSSam Leffler return -1; 60339beb93cSSam Leffler } 60439beb93cSSam Leffler 60539beb93cSSam Leffler end = pos + len; 60639beb93cSSam Leffler 60739beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) 60839beb93cSSam Leffler return tls_process_server_hello_done(conn, ct, in_data, 60939beb93cSSam Leffler in_len); 61039beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) { 61139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " 61239beb93cSSam Leffler "message %d (expected CertificateRequest/" 61339beb93cSSam Leffler "ServerHelloDone)", type); 61439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 61539beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 61639beb93cSSam Leffler return -1; 61739beb93cSSam Leffler } 61839beb93cSSam Leffler 61939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateRequest"); 62039beb93cSSam Leffler 62139beb93cSSam Leffler conn->certificate_requested = 1; 62239beb93cSSam Leffler 62339beb93cSSam Leffler *in_len = end - in_data; 62439beb93cSSam Leffler 62539beb93cSSam Leffler conn->state = SERVER_HELLO_DONE; 62639beb93cSSam Leffler 62739beb93cSSam Leffler return 0; 62839beb93cSSam Leffler } 62939beb93cSSam Leffler 63039beb93cSSam Leffler 63139beb93cSSam Leffler static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct, 63239beb93cSSam Leffler const u8 *in_data, size_t *in_len) 63339beb93cSSam Leffler { 63439beb93cSSam Leffler const u8 *pos, *end; 63539beb93cSSam Leffler size_t left, len; 63639beb93cSSam Leffler u8 type; 63739beb93cSSam Leffler 63839beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 63939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " 64039beb93cSSam Leffler "received content type 0x%x", ct); 64139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 64239beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 64339beb93cSSam Leffler return -1; 64439beb93cSSam Leffler } 64539beb93cSSam Leffler 64639beb93cSSam Leffler pos = in_data; 64739beb93cSSam Leffler left = *in_len; 64839beb93cSSam Leffler 64939beb93cSSam Leffler if (left < 4) { 65039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerHelloDone " 65139beb93cSSam Leffler "(left=%lu)", (unsigned long) left); 65239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 65339beb93cSSam Leffler return -1; 65439beb93cSSam Leffler } 65539beb93cSSam Leffler 65639beb93cSSam Leffler type = *pos++; 65739beb93cSSam Leffler len = WPA_GET_BE24(pos); 65839beb93cSSam Leffler pos += 3; 65939beb93cSSam Leffler left -= 4; 66039beb93cSSam Leffler 66139beb93cSSam Leffler if (len > left) { 66239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerHelloDone " 66339beb93cSSam Leffler "length (len=%lu != left=%lu)", 66439beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 66539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 66639beb93cSSam Leffler return -1; 66739beb93cSSam Leffler } 66839beb93cSSam Leffler end = pos + len; 66939beb93cSSam Leffler 67039beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) { 67139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " 67239beb93cSSam Leffler "message %d (expected ServerHelloDone)", type); 67339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 67439beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 67539beb93cSSam Leffler return -1; 67639beb93cSSam Leffler } 67739beb93cSSam Leffler 67839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHelloDone"); 67939beb93cSSam Leffler 68039beb93cSSam Leffler *in_len = end - in_data; 68139beb93cSSam Leffler 68239beb93cSSam Leffler conn->state = CLIENT_KEY_EXCHANGE; 68339beb93cSSam Leffler 68439beb93cSSam Leffler return 0; 68539beb93cSSam Leffler } 68639beb93cSSam Leffler 68739beb93cSSam Leffler 68839beb93cSSam Leffler static int tls_process_server_change_cipher_spec(struct tlsv1_client *conn, 68939beb93cSSam Leffler u8 ct, const u8 *in_data, 69039beb93cSSam Leffler size_t *in_len) 69139beb93cSSam Leffler { 69239beb93cSSam Leffler const u8 *pos; 69339beb93cSSam Leffler size_t left; 69439beb93cSSam Leffler 69539beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { 69639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " 69739beb93cSSam Leffler "received content type 0x%x", ct); 69839beb93cSSam Leffler if (conn->use_session_ticket) { 69939beb93cSSam Leffler int res; 70039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Server may have " 70139beb93cSSam Leffler "rejected SessionTicket"); 70239beb93cSSam Leffler conn->use_session_ticket = 0; 70339beb93cSSam Leffler 70439beb93cSSam Leffler /* Notify upper layers that SessionTicket failed */ 70539beb93cSSam Leffler res = conn->session_ticket_cb( 70639beb93cSSam Leffler conn->session_ticket_cb_ctx, NULL, 0, NULL, 70739beb93cSSam Leffler NULL, NULL); 70839beb93cSSam Leffler if (res < 0) { 70939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket " 71039beb93cSSam Leffler "callback indicated failure"); 71139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 71239beb93cSSam Leffler TLS_ALERT_HANDSHAKE_FAILURE); 71339beb93cSSam Leffler return -1; 71439beb93cSSam Leffler } 71539beb93cSSam Leffler 71639beb93cSSam Leffler conn->state = SERVER_CERTIFICATE; 71739beb93cSSam Leffler return tls_process_certificate(conn, ct, in_data, 71839beb93cSSam Leffler in_len); 71939beb93cSSam Leffler } 72039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 72139beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 72239beb93cSSam Leffler return -1; 72339beb93cSSam Leffler } 72439beb93cSSam Leffler 72539beb93cSSam Leffler pos = in_data; 72639beb93cSSam Leffler left = *in_len; 72739beb93cSSam Leffler 72839beb93cSSam Leffler if (left < 1) { 72939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec"); 73039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); 73139beb93cSSam Leffler return -1; 73239beb93cSSam Leffler } 73339beb93cSSam Leffler 73439beb93cSSam Leffler if (*pos != TLS_CHANGE_CIPHER_SPEC) { 73539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " 73639beb93cSSam Leffler "received data 0x%x", *pos); 73739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 73839beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 73939beb93cSSam Leffler return -1; 74039beb93cSSam Leffler } 74139beb93cSSam Leffler 74239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec"); 74339beb93cSSam Leffler if (tlsv1_record_change_read_cipher(&conn->rl) < 0) { 74439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher " 74539beb93cSSam Leffler "for record layer"); 74639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 74739beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 74839beb93cSSam Leffler return -1; 74939beb93cSSam Leffler } 75039beb93cSSam Leffler 75139beb93cSSam Leffler *in_len = pos + 1 - in_data; 75239beb93cSSam Leffler 75339beb93cSSam Leffler conn->state = SERVER_FINISHED; 75439beb93cSSam Leffler 75539beb93cSSam Leffler return 0; 75639beb93cSSam Leffler } 75739beb93cSSam Leffler 75839beb93cSSam Leffler 75939beb93cSSam Leffler static int tls_process_server_finished(struct tlsv1_client *conn, u8 ct, 76039beb93cSSam Leffler const u8 *in_data, size_t *in_len) 76139beb93cSSam Leffler { 76239beb93cSSam Leffler const u8 *pos, *end; 76339beb93cSSam Leffler size_t left, len, hlen; 76439beb93cSSam Leffler u8 verify_data[TLS_VERIFY_DATA_LEN]; 76539beb93cSSam Leffler u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; 76639beb93cSSam Leffler 76739beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 76839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; " 76939beb93cSSam Leffler "received content type 0x%x", ct); 77039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 77139beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 77239beb93cSSam Leffler return -1; 77339beb93cSSam Leffler } 77439beb93cSSam Leffler 77539beb93cSSam Leffler pos = in_data; 77639beb93cSSam Leffler left = *in_len; 77739beb93cSSam Leffler 77839beb93cSSam Leffler if (left < 4) { 77939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for " 78039beb93cSSam Leffler "Finished", 78139beb93cSSam Leffler (unsigned long) left); 78239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 78339beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 78439beb93cSSam Leffler return -1; 78539beb93cSSam Leffler } 78639beb93cSSam Leffler 78739beb93cSSam Leffler if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) { 78839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received " 78939beb93cSSam Leffler "type 0x%x", pos[0]); 79039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 79139beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 79239beb93cSSam Leffler return -1; 79339beb93cSSam Leffler } 79439beb93cSSam Leffler 79539beb93cSSam Leffler len = WPA_GET_BE24(pos + 1); 79639beb93cSSam Leffler 79739beb93cSSam Leffler pos += 4; 79839beb93cSSam Leffler left -= 4; 79939beb93cSSam Leffler 80039beb93cSSam Leffler if (len > left) { 80139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished " 80239beb93cSSam Leffler "(len=%lu > left=%lu)", 80339beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 80439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 80539beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 80639beb93cSSam Leffler return -1; 80739beb93cSSam Leffler } 80839beb93cSSam Leffler end = pos + len; 80939beb93cSSam Leffler if (len != TLS_VERIFY_DATA_LEN) { 81039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length " 81139beb93cSSam Leffler "in Finished: %lu (expected %d)", 81239beb93cSSam Leffler (unsigned long) len, TLS_VERIFY_DATA_LEN); 81339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 81439beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 81539beb93cSSam Leffler return -1; 81639beb93cSSam Leffler } 81739beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished", 81839beb93cSSam Leffler pos, TLS_VERIFY_DATA_LEN); 81939beb93cSSam Leffler 820*f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 821*f05cddf9SRui Paulo if (conn->rl.tls_version >= TLS_VERSION_1_2) { 822*f05cddf9SRui Paulo hlen = SHA256_MAC_LEN; 823*f05cddf9SRui Paulo if (conn->verify.sha256_server == NULL || 824*f05cddf9SRui Paulo crypto_hash_finish(conn->verify.sha256_server, hash, &hlen) 825*f05cddf9SRui Paulo < 0) { 826*f05cddf9SRui Paulo tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 827*f05cddf9SRui Paulo TLS_ALERT_INTERNAL_ERROR); 828*f05cddf9SRui Paulo conn->verify.sha256_server = NULL; 829*f05cddf9SRui Paulo return -1; 830*f05cddf9SRui Paulo } 831*f05cddf9SRui Paulo conn->verify.sha256_server = NULL; 832*f05cddf9SRui Paulo } else { 833*f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 834*f05cddf9SRui Paulo 83539beb93cSSam Leffler hlen = MD5_MAC_LEN; 83639beb93cSSam Leffler if (conn->verify.md5_server == NULL || 83739beb93cSSam Leffler crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) { 83839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 83939beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 84039beb93cSSam Leffler conn->verify.md5_server = NULL; 84139beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_server, NULL, NULL); 84239beb93cSSam Leffler conn->verify.sha1_server = NULL; 84339beb93cSSam Leffler return -1; 84439beb93cSSam Leffler } 84539beb93cSSam Leffler conn->verify.md5_server = NULL; 84639beb93cSSam Leffler hlen = SHA1_MAC_LEN; 84739beb93cSSam Leffler if (conn->verify.sha1_server == NULL || 84839beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN, 84939beb93cSSam Leffler &hlen) < 0) { 85039beb93cSSam Leffler conn->verify.sha1_server = NULL; 85139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 85239beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 85339beb93cSSam Leffler return -1; 85439beb93cSSam Leffler } 85539beb93cSSam Leffler conn->verify.sha1_server = NULL; 856*f05cddf9SRui Paulo hlen = MD5_MAC_LEN + SHA1_MAC_LEN; 85739beb93cSSam Leffler 858*f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 859*f05cddf9SRui Paulo } 860*f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 861*f05cddf9SRui Paulo 862*f05cddf9SRui Paulo if (tls_prf(conn->rl.tls_version, 863*f05cddf9SRui Paulo conn->master_secret, TLS_MASTER_SECRET_LEN, 864*f05cddf9SRui Paulo "server finished", hash, hlen, 86539beb93cSSam Leffler verify_data, TLS_VERIFY_DATA_LEN)) { 86639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data"); 86739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 86839beb93cSSam Leffler TLS_ALERT_DECRYPT_ERROR); 86939beb93cSSam Leffler return -1; 87039beb93cSSam Leffler } 87139beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)", 87239beb93cSSam Leffler verify_data, TLS_VERIFY_DATA_LEN); 87339beb93cSSam Leffler 87439beb93cSSam Leffler if (os_memcmp(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) { 87539beb93cSSam Leffler wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data"); 87639beb93cSSam Leffler return -1; 87739beb93cSSam Leffler } 87839beb93cSSam Leffler 87939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received Finished"); 88039beb93cSSam Leffler 88139beb93cSSam Leffler *in_len = end - in_data; 88239beb93cSSam Leffler 88339beb93cSSam Leffler conn->state = (conn->session_resumed || conn->use_session_ticket) ? 88439beb93cSSam Leffler CHANGE_CIPHER_SPEC : ACK_FINISHED; 88539beb93cSSam Leffler 88639beb93cSSam Leffler return 0; 88739beb93cSSam Leffler } 88839beb93cSSam Leffler 88939beb93cSSam Leffler 89039beb93cSSam Leffler static int tls_process_application_data(struct tlsv1_client *conn, u8 ct, 89139beb93cSSam Leffler const u8 *in_data, size_t *in_len, 89239beb93cSSam Leffler u8 **out_data, size_t *out_len) 89339beb93cSSam Leffler { 89439beb93cSSam Leffler const u8 *pos; 89539beb93cSSam Leffler size_t left; 89639beb93cSSam Leffler 89739beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) { 89839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Application Data; " 89939beb93cSSam Leffler "received content type 0x%x", ct); 90039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 90139beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 90239beb93cSSam Leffler return -1; 90339beb93cSSam Leffler } 90439beb93cSSam Leffler 90539beb93cSSam Leffler pos = in_data; 90639beb93cSSam Leffler left = *in_len; 90739beb93cSSam Leffler 90839beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: Application Data included in Handshake", 90939beb93cSSam Leffler pos, left); 91039beb93cSSam Leffler 91139beb93cSSam Leffler *out_data = os_malloc(left); 91239beb93cSSam Leffler if (*out_data) { 91339beb93cSSam Leffler os_memcpy(*out_data, pos, left); 91439beb93cSSam Leffler *out_len = left; 91539beb93cSSam Leffler } 91639beb93cSSam Leffler 91739beb93cSSam Leffler return 0; 91839beb93cSSam Leffler } 91939beb93cSSam Leffler 92039beb93cSSam Leffler 92139beb93cSSam Leffler int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct, 92239beb93cSSam Leffler const u8 *buf, size_t *len, 92339beb93cSSam Leffler u8 **out_data, size_t *out_len) 92439beb93cSSam Leffler { 92539beb93cSSam Leffler if (ct == TLS_CONTENT_TYPE_ALERT) { 92639beb93cSSam Leffler if (*len < 2) { 92739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow"); 92839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 92939beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 93039beb93cSSam Leffler return -1; 93139beb93cSSam Leffler } 93239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d", 93339beb93cSSam Leffler buf[0], buf[1]); 93439beb93cSSam Leffler *len = 2; 93539beb93cSSam Leffler conn->state = FAILED; 93639beb93cSSam Leffler return -1; 93739beb93cSSam Leffler } 93839beb93cSSam Leffler 93939beb93cSSam Leffler if (ct == TLS_CONTENT_TYPE_HANDSHAKE && *len >= 4 && 94039beb93cSSam Leffler buf[0] == TLS_HANDSHAKE_TYPE_HELLO_REQUEST) { 94139beb93cSSam Leffler size_t hr_len = WPA_GET_BE24(buf + 1); 94239beb93cSSam Leffler if (hr_len > *len - 4) { 94339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: HelloRequest underflow"); 94439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 94539beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 94639beb93cSSam Leffler return -1; 94739beb93cSSam Leffler } 94839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Ignored HelloRequest"); 94939beb93cSSam Leffler *len = 4 + hr_len; 95039beb93cSSam Leffler return 0; 95139beb93cSSam Leffler } 95239beb93cSSam Leffler 95339beb93cSSam Leffler switch (conn->state) { 95439beb93cSSam Leffler case SERVER_HELLO: 95539beb93cSSam Leffler if (tls_process_server_hello(conn, ct, buf, len)) 95639beb93cSSam Leffler return -1; 95739beb93cSSam Leffler break; 95839beb93cSSam Leffler case SERVER_CERTIFICATE: 95939beb93cSSam Leffler if (tls_process_certificate(conn, ct, buf, len)) 96039beb93cSSam Leffler return -1; 96139beb93cSSam Leffler break; 96239beb93cSSam Leffler case SERVER_KEY_EXCHANGE: 96339beb93cSSam Leffler if (tls_process_server_key_exchange(conn, ct, buf, len)) 96439beb93cSSam Leffler return -1; 96539beb93cSSam Leffler break; 96639beb93cSSam Leffler case SERVER_CERTIFICATE_REQUEST: 96739beb93cSSam Leffler if (tls_process_certificate_request(conn, ct, buf, len)) 96839beb93cSSam Leffler return -1; 96939beb93cSSam Leffler break; 97039beb93cSSam Leffler case SERVER_HELLO_DONE: 97139beb93cSSam Leffler if (tls_process_server_hello_done(conn, ct, buf, len)) 97239beb93cSSam Leffler return -1; 97339beb93cSSam Leffler break; 97439beb93cSSam Leffler case SERVER_CHANGE_CIPHER_SPEC: 97539beb93cSSam Leffler if (tls_process_server_change_cipher_spec(conn, ct, buf, len)) 97639beb93cSSam Leffler return -1; 97739beb93cSSam Leffler break; 97839beb93cSSam Leffler case SERVER_FINISHED: 97939beb93cSSam Leffler if (tls_process_server_finished(conn, ct, buf, len)) 98039beb93cSSam Leffler return -1; 98139beb93cSSam Leffler break; 98239beb93cSSam Leffler case ACK_FINISHED: 98339beb93cSSam Leffler if (out_data && 98439beb93cSSam Leffler tls_process_application_data(conn, ct, buf, len, out_data, 98539beb93cSSam Leffler out_len)) 98639beb93cSSam Leffler return -1; 98739beb93cSSam Leffler break; 98839beb93cSSam Leffler default: 98939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d " 99039beb93cSSam Leffler "while processing received message", 99139beb93cSSam Leffler conn->state); 99239beb93cSSam Leffler return -1; 99339beb93cSSam Leffler } 99439beb93cSSam Leffler 99539beb93cSSam Leffler if (ct == TLS_CONTENT_TYPE_HANDSHAKE) 99639beb93cSSam Leffler tls_verify_hash_add(&conn->verify, buf, *len); 99739beb93cSSam Leffler 99839beb93cSSam Leffler return 0; 99939beb93cSSam Leffler } 1000