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