139beb93cSSam Leffler /* 239beb93cSSam Leffler * TLSv1 server - read handshake message 3*5b9c547cSRui Paulo * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6f05cddf9SRui Paulo * See README for more details. 739beb93cSSam Leffler */ 839beb93cSSam Leffler 939beb93cSSam Leffler #include "includes.h" 1039beb93cSSam Leffler 1139beb93cSSam Leffler #include "common.h" 12e28a4053SRui Paulo #include "crypto/md5.h" 13e28a4053SRui Paulo #include "crypto/sha1.h" 14f05cddf9SRui Paulo #include "crypto/sha256.h" 15e28a4053SRui Paulo #include "crypto/tls.h" 1639beb93cSSam Leffler #include "x509v3.h" 1739beb93cSSam Leffler #include "tlsv1_common.h" 1839beb93cSSam Leffler #include "tlsv1_record.h" 1939beb93cSSam Leffler #include "tlsv1_server.h" 2039beb93cSSam Leffler #include "tlsv1_server_i.h" 2139beb93cSSam Leffler 2239beb93cSSam Leffler 2339beb93cSSam Leffler static int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct, 2439beb93cSSam Leffler const u8 *in_data, size_t *in_len); 2539beb93cSSam Leffler static int tls_process_change_cipher_spec(struct tlsv1_server *conn, 2639beb93cSSam Leffler u8 ct, const u8 *in_data, 2739beb93cSSam Leffler size_t *in_len); 2839beb93cSSam Leffler 2939beb93cSSam Leffler 30*5b9c547cSRui Paulo static int testing_cipher_suite_filter(struct tlsv1_server *conn, u16 suite) 31*5b9c547cSRui Paulo { 32*5b9c547cSRui Paulo #ifdef CONFIG_TESTING_OPTIONS 33*5b9c547cSRui Paulo if ((conn->test_flags & 34*5b9c547cSRui Paulo (TLS_BREAK_SRV_KEY_X_HASH | TLS_BREAK_SRV_KEY_X_SIGNATURE | 35*5b9c547cSRui Paulo TLS_DHE_PRIME_511B | TLS_DHE_PRIME_767B | TLS_DHE_PRIME_15 | 36*5b9c547cSRui Paulo TLS_DHE_PRIME_58B | TLS_DHE_NON_PRIME)) && 37*5b9c547cSRui Paulo suite != TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 && 38*5b9c547cSRui Paulo suite != TLS_DHE_RSA_WITH_AES_256_CBC_SHA && 39*5b9c547cSRui Paulo suite != TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 && 40*5b9c547cSRui Paulo suite != TLS_DHE_RSA_WITH_AES_128_CBC_SHA && 41*5b9c547cSRui Paulo suite != TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) 42*5b9c547cSRui Paulo return 1; 43*5b9c547cSRui Paulo #endif /* CONFIG_TESTING_OPTIONS */ 44*5b9c547cSRui Paulo 45*5b9c547cSRui Paulo return 0; 46*5b9c547cSRui Paulo } 47*5b9c547cSRui Paulo 48*5b9c547cSRui Paulo 4939beb93cSSam Leffler static int tls_process_client_hello(struct tlsv1_server *conn, u8 ct, 5039beb93cSSam Leffler const u8 *in_data, size_t *in_len) 5139beb93cSSam Leffler { 5239beb93cSSam Leffler const u8 *pos, *end, *c; 5339beb93cSSam Leffler size_t left, len, i, j; 5439beb93cSSam Leffler u16 cipher_suite; 5539beb93cSSam Leffler u16 num_suites; 5639beb93cSSam Leffler int compr_null_found; 573157ba21SRui Paulo u16 ext_type, ext_len; 5839beb93cSSam Leffler 5939beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 60*5b9c547cSRui Paulo tlsv1_server_log(conn, "Expected Handshake; received content type 0x%x", 61*5b9c547cSRui Paulo ct); 6239beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 6339beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 6439beb93cSSam Leffler return -1; 6539beb93cSSam Leffler } 6639beb93cSSam Leffler 6739beb93cSSam Leffler pos = in_data; 6839beb93cSSam Leffler left = *in_len; 6939beb93cSSam Leffler 7039beb93cSSam Leffler if (left < 4) 7139beb93cSSam Leffler goto decode_error; 7239beb93cSSam Leffler 7339beb93cSSam Leffler /* HandshakeType msg_type */ 7439beb93cSSam Leffler if (*pos != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) { 75*5b9c547cSRui Paulo tlsv1_server_log(conn, "Received unexpected handshake message %d (expected ClientHello)", 76*5b9c547cSRui Paulo *pos); 7739beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 7839beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 7939beb93cSSam Leffler return -1; 8039beb93cSSam Leffler } 81*5b9c547cSRui Paulo tlsv1_server_log(conn, "Received ClientHello"); 8239beb93cSSam Leffler pos++; 8339beb93cSSam Leffler /* uint24 length */ 8439beb93cSSam Leffler len = WPA_GET_BE24(pos); 8539beb93cSSam Leffler pos += 3; 8639beb93cSSam Leffler left -= 4; 8739beb93cSSam Leffler 8839beb93cSSam Leffler if (len > left) 8939beb93cSSam Leffler goto decode_error; 9039beb93cSSam Leffler 9139beb93cSSam Leffler /* body - ClientHello */ 9239beb93cSSam Leffler 9339beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello", pos, len); 9439beb93cSSam Leffler end = pos + len; 9539beb93cSSam Leffler 9639beb93cSSam Leffler /* ProtocolVersion client_version */ 9739beb93cSSam Leffler if (end - pos < 2) 9839beb93cSSam Leffler goto decode_error; 9939beb93cSSam Leffler conn->client_version = WPA_GET_BE16(pos); 100*5b9c547cSRui Paulo tlsv1_server_log(conn, "Client version %d.%d", 101*5b9c547cSRui Paulo conn->client_version >> 8, 102*5b9c547cSRui Paulo conn->client_version & 0xff); 103f05cddf9SRui Paulo if (conn->client_version < TLS_VERSION_1) { 104*5b9c547cSRui Paulo tlsv1_server_log(conn, "Unexpected protocol version in ClientHello %u.%u", 105f05cddf9SRui Paulo conn->client_version >> 8, 106f05cddf9SRui Paulo conn->client_version & 0xff); 10739beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 10839beb93cSSam Leffler TLS_ALERT_PROTOCOL_VERSION); 10939beb93cSSam Leffler return -1; 11039beb93cSSam Leffler } 11139beb93cSSam Leffler pos += 2; 11239beb93cSSam Leffler 113f05cddf9SRui Paulo if (TLS_VERSION == TLS_VERSION_1) 114f05cddf9SRui Paulo conn->rl.tls_version = TLS_VERSION_1; 115f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 116f05cddf9SRui Paulo else if (conn->client_version >= TLS_VERSION_1_2) 117f05cddf9SRui Paulo conn->rl.tls_version = TLS_VERSION_1_2; 118f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 119f05cddf9SRui Paulo else if (conn->client_version > TLS_VERSION_1_1) 120f05cddf9SRui Paulo conn->rl.tls_version = TLS_VERSION_1_1; 121f05cddf9SRui Paulo else 122f05cddf9SRui Paulo conn->rl.tls_version = conn->client_version; 123*5b9c547cSRui Paulo tlsv1_server_log(conn, "Using TLS v%s", 124f05cddf9SRui Paulo tls_version_str(conn->rl.tls_version)); 125f05cddf9SRui Paulo 12639beb93cSSam Leffler /* Random random */ 12739beb93cSSam Leffler if (end - pos < TLS_RANDOM_LEN) 12839beb93cSSam Leffler goto decode_error; 12939beb93cSSam Leffler 13039beb93cSSam Leffler os_memcpy(conn->client_random, pos, TLS_RANDOM_LEN); 13139beb93cSSam Leffler pos += TLS_RANDOM_LEN; 13239beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random", 13339beb93cSSam Leffler conn->client_random, TLS_RANDOM_LEN); 13439beb93cSSam Leffler 13539beb93cSSam Leffler /* SessionID session_id */ 13639beb93cSSam Leffler if (end - pos < 1) 13739beb93cSSam Leffler goto decode_error; 13839beb93cSSam Leffler if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN) 13939beb93cSSam Leffler goto decode_error; 14039beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: client session_id", pos + 1, *pos); 14139beb93cSSam Leffler pos += 1 + *pos; 14239beb93cSSam Leffler /* TODO: add support for session resumption */ 14339beb93cSSam Leffler 14439beb93cSSam Leffler /* CipherSuite cipher_suites<2..2^16-1> */ 14539beb93cSSam Leffler if (end - pos < 2) 14639beb93cSSam Leffler goto decode_error; 14739beb93cSSam Leffler num_suites = WPA_GET_BE16(pos); 14839beb93cSSam Leffler pos += 2; 14939beb93cSSam Leffler if (end - pos < num_suites) 15039beb93cSSam Leffler goto decode_error; 15139beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: client cipher suites", 15239beb93cSSam Leffler pos, num_suites); 15339beb93cSSam Leffler if (num_suites & 1) 15439beb93cSSam Leffler goto decode_error; 15539beb93cSSam Leffler num_suites /= 2; 15639beb93cSSam Leffler 15739beb93cSSam Leffler cipher_suite = 0; 15839beb93cSSam Leffler for (i = 0; !cipher_suite && i < conn->num_cipher_suites; i++) { 159*5b9c547cSRui Paulo if (testing_cipher_suite_filter(conn, conn->cipher_suites[i])) 160*5b9c547cSRui Paulo continue; 16139beb93cSSam Leffler c = pos; 16239beb93cSSam Leffler for (j = 0; j < num_suites; j++) { 16339beb93cSSam Leffler u16 tmp = WPA_GET_BE16(c); 16439beb93cSSam Leffler c += 2; 16539beb93cSSam Leffler if (!cipher_suite && tmp == conn->cipher_suites[i]) { 16639beb93cSSam Leffler cipher_suite = tmp; 16739beb93cSSam Leffler break; 16839beb93cSSam Leffler } 16939beb93cSSam Leffler } 17039beb93cSSam Leffler } 17139beb93cSSam Leffler pos += num_suites * 2; 17239beb93cSSam Leffler if (!cipher_suite) { 173*5b9c547cSRui Paulo tlsv1_server_log(conn, "No supported cipher suite available"); 17439beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 17539beb93cSSam Leffler TLS_ALERT_ILLEGAL_PARAMETER); 17639beb93cSSam Leffler return -1; 17739beb93cSSam Leffler } 17839beb93cSSam Leffler 17939beb93cSSam Leffler if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) { 18039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for " 18139beb93cSSam Leffler "record layer"); 18239beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 18339beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 18439beb93cSSam Leffler return -1; 18539beb93cSSam Leffler } 18639beb93cSSam Leffler 18739beb93cSSam Leffler conn->cipher_suite = cipher_suite; 18839beb93cSSam Leffler 18939beb93cSSam Leffler /* CompressionMethod compression_methods<1..2^8-1> */ 19039beb93cSSam Leffler if (end - pos < 1) 19139beb93cSSam Leffler goto decode_error; 19239beb93cSSam Leffler num_suites = *pos++; 19339beb93cSSam Leffler if (end - pos < num_suites) 19439beb93cSSam Leffler goto decode_error; 19539beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: client compression_methods", 19639beb93cSSam Leffler pos, num_suites); 19739beb93cSSam Leffler compr_null_found = 0; 19839beb93cSSam Leffler for (i = 0; i < num_suites; i++) { 19939beb93cSSam Leffler if (*pos++ == TLS_COMPRESSION_NULL) 20039beb93cSSam Leffler compr_null_found = 1; 20139beb93cSSam Leffler } 20239beb93cSSam Leffler if (!compr_null_found) { 203*5b9c547cSRui Paulo tlsv1_server_log(conn, "Client does not accept NULL compression"); 20439beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 20539beb93cSSam Leffler TLS_ALERT_ILLEGAL_PARAMETER); 20639beb93cSSam Leffler return -1; 20739beb93cSSam Leffler } 20839beb93cSSam Leffler 20939beb93cSSam Leffler if (end - pos == 1) { 210*5b9c547cSRui Paulo tlsv1_server_log(conn, "Unexpected extra octet in the end of ClientHello: 0x%02x", 211*5b9c547cSRui Paulo *pos); 21239beb93cSSam Leffler goto decode_error; 21339beb93cSSam Leffler } 21439beb93cSSam Leffler 21539beb93cSSam Leffler if (end - pos >= 2) { 21639beb93cSSam Leffler /* Extension client_hello_extension_list<0..2^16-1> */ 21739beb93cSSam Leffler ext_len = WPA_GET_BE16(pos); 21839beb93cSSam Leffler pos += 2; 21939beb93cSSam Leffler 220*5b9c547cSRui Paulo tlsv1_server_log(conn, "%u bytes of ClientHello extensions", 221*5b9c547cSRui Paulo ext_len); 22239beb93cSSam Leffler if (end - pos != ext_len) { 223*5b9c547cSRui Paulo tlsv1_server_log(conn, "Invalid ClientHello extension list length %u (expected %u)", 2243157ba21SRui Paulo ext_len, (unsigned int) (end - pos)); 22539beb93cSSam Leffler goto decode_error; 22639beb93cSSam Leffler } 22739beb93cSSam Leffler 22839beb93cSSam Leffler /* 22939beb93cSSam Leffler * struct { 23039beb93cSSam Leffler * ExtensionType extension_type (0..65535) 23139beb93cSSam Leffler * opaque extension_data<0..2^16-1> 23239beb93cSSam Leffler * } Extension; 23339beb93cSSam Leffler */ 23439beb93cSSam Leffler 23539beb93cSSam Leffler while (pos < end) { 23639beb93cSSam Leffler if (end - pos < 2) { 237*5b9c547cSRui Paulo tlsv1_server_log(conn, "Invalid extension_type field"); 23839beb93cSSam Leffler goto decode_error; 23939beb93cSSam Leffler } 24039beb93cSSam Leffler 24139beb93cSSam Leffler ext_type = WPA_GET_BE16(pos); 24239beb93cSSam Leffler pos += 2; 24339beb93cSSam Leffler 24439beb93cSSam Leffler if (end - pos < 2) { 245*5b9c547cSRui Paulo tlsv1_server_log(conn, "Invalid extension_data length field"); 24639beb93cSSam Leffler goto decode_error; 24739beb93cSSam Leffler } 24839beb93cSSam Leffler 24939beb93cSSam Leffler ext_len = WPA_GET_BE16(pos); 25039beb93cSSam Leffler pos += 2; 25139beb93cSSam Leffler 25239beb93cSSam Leffler if (end - pos < ext_len) { 253*5b9c547cSRui Paulo tlsv1_server_log(conn, "Invalid extension_data field"); 25439beb93cSSam Leffler goto decode_error; 25539beb93cSSam Leffler } 25639beb93cSSam Leffler 257*5b9c547cSRui Paulo tlsv1_server_log(conn, "ClientHello Extension type %u", 258*5b9c547cSRui Paulo ext_type); 25939beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello " 26039beb93cSSam Leffler "Extension data", pos, ext_len); 26139beb93cSSam Leffler 26239beb93cSSam Leffler if (ext_type == TLS_EXT_SESSION_TICKET) { 26339beb93cSSam Leffler os_free(conn->session_ticket); 26439beb93cSSam Leffler conn->session_ticket = os_malloc(ext_len); 26539beb93cSSam Leffler if (conn->session_ticket) { 26639beb93cSSam Leffler os_memcpy(conn->session_ticket, pos, 26739beb93cSSam Leffler ext_len); 26839beb93cSSam Leffler conn->session_ticket_len = ext_len; 26939beb93cSSam Leffler } 27039beb93cSSam Leffler } 27139beb93cSSam Leffler 27239beb93cSSam Leffler pos += ext_len; 27339beb93cSSam Leffler } 27439beb93cSSam Leffler } 27539beb93cSSam Leffler 27639beb93cSSam Leffler *in_len = end - in_data; 27739beb93cSSam Leffler 278*5b9c547cSRui Paulo tlsv1_server_log(conn, "ClientHello OK - proceed to ServerHello"); 27939beb93cSSam Leffler conn->state = SERVER_HELLO; 28039beb93cSSam Leffler 28139beb93cSSam Leffler return 0; 28239beb93cSSam Leffler 28339beb93cSSam Leffler decode_error: 284*5b9c547cSRui Paulo tlsv1_server_log(conn, "Failed to decode ClientHello"); 28539beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 28639beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 28739beb93cSSam Leffler return -1; 28839beb93cSSam Leffler } 28939beb93cSSam Leffler 29039beb93cSSam Leffler 29139beb93cSSam Leffler static int tls_process_certificate(struct tlsv1_server *conn, u8 ct, 29239beb93cSSam Leffler const u8 *in_data, size_t *in_len) 29339beb93cSSam Leffler { 29439beb93cSSam Leffler const u8 *pos, *end; 29539beb93cSSam Leffler size_t left, len, list_len, cert_len, idx; 29639beb93cSSam Leffler u8 type; 29739beb93cSSam Leffler struct x509_certificate *chain = NULL, *last = NULL, *cert; 29839beb93cSSam Leffler int reason; 29939beb93cSSam Leffler 30039beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 301*5b9c547cSRui Paulo tlsv1_server_log(conn, "Expected Handshake; received content type 0x%x", 302*5b9c547cSRui Paulo ct); 30339beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 30439beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 30539beb93cSSam Leffler return -1; 30639beb93cSSam Leffler } 30739beb93cSSam Leffler 30839beb93cSSam Leffler pos = in_data; 30939beb93cSSam Leffler left = *in_len; 31039beb93cSSam Leffler 31139beb93cSSam Leffler if (left < 4) { 312*5b9c547cSRui Paulo tlsv1_server_log(conn, "Too short Certificate message (len=%lu)", 313*5b9c547cSRui Paulo (unsigned long) left); 31439beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 31539beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 31639beb93cSSam Leffler return -1; 31739beb93cSSam Leffler } 31839beb93cSSam Leffler 31939beb93cSSam Leffler type = *pos++; 32039beb93cSSam Leffler len = WPA_GET_BE24(pos); 32139beb93cSSam Leffler pos += 3; 32239beb93cSSam Leffler left -= 4; 32339beb93cSSam Leffler 32439beb93cSSam Leffler if (len > left) { 325*5b9c547cSRui Paulo tlsv1_server_log(conn, "Unexpected Certificate message length (len=%lu != left=%lu)", 32639beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 32739beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 32839beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 32939beb93cSSam Leffler return -1; 33039beb93cSSam Leffler } 33139beb93cSSam Leffler 33239beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) { 33339beb93cSSam Leffler if (conn->verify_peer) { 334*5b9c547cSRui Paulo tlsv1_server_log(conn, "Client did not include Certificate"); 33539beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 33639beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 33739beb93cSSam Leffler return -1; 33839beb93cSSam Leffler } 33939beb93cSSam Leffler 34039beb93cSSam Leffler return tls_process_client_key_exchange(conn, ct, in_data, 34139beb93cSSam Leffler in_len); 34239beb93cSSam Leffler } 34339beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) { 344*5b9c547cSRui Paulo tlsv1_server_log(conn, "Received unexpected handshake message %d (expected Certificate/ClientKeyExchange)", 345*5b9c547cSRui Paulo type); 34639beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 34739beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 34839beb93cSSam Leffler return -1; 34939beb93cSSam Leffler } 35039beb93cSSam Leffler 351*5b9c547cSRui Paulo tlsv1_server_log(conn, "Received Certificate (certificate_list len %lu)", 35239beb93cSSam Leffler (unsigned long) len); 35339beb93cSSam Leffler 35439beb93cSSam Leffler /* 35539beb93cSSam Leffler * opaque ASN.1Cert<2^24-1>; 35639beb93cSSam Leffler * 35739beb93cSSam Leffler * struct { 35839beb93cSSam Leffler * ASN.1Cert certificate_list<1..2^24-1>; 35939beb93cSSam Leffler * } Certificate; 36039beb93cSSam Leffler */ 36139beb93cSSam Leffler 36239beb93cSSam Leffler end = pos + len; 36339beb93cSSam Leffler 36439beb93cSSam Leffler if (end - pos < 3) { 365*5b9c547cSRui Paulo tlsv1_server_log(conn, "Too short Certificate (left=%lu)", 366*5b9c547cSRui Paulo (unsigned long) left); 36739beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 36839beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 36939beb93cSSam Leffler return -1; 37039beb93cSSam Leffler } 37139beb93cSSam Leffler 37239beb93cSSam Leffler list_len = WPA_GET_BE24(pos); 37339beb93cSSam Leffler pos += 3; 37439beb93cSSam Leffler 37539beb93cSSam Leffler if ((size_t) (end - pos) != list_len) { 376*5b9c547cSRui Paulo tlsv1_server_log(conn, "Unexpected certificate_list length (len=%lu left=%lu)", 37739beb93cSSam Leffler (unsigned long) list_len, 37839beb93cSSam Leffler (unsigned long) (end - pos)); 37939beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 38039beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 38139beb93cSSam Leffler return -1; 38239beb93cSSam Leffler } 38339beb93cSSam Leffler 38439beb93cSSam Leffler idx = 0; 38539beb93cSSam Leffler while (pos < end) { 38639beb93cSSam Leffler if (end - pos < 3) { 387*5b9c547cSRui Paulo tlsv1_server_log(conn, "Failed to parse certificate_list"); 38839beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 38939beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 39039beb93cSSam Leffler x509_certificate_chain_free(chain); 39139beb93cSSam Leffler return -1; 39239beb93cSSam Leffler } 39339beb93cSSam Leffler 39439beb93cSSam Leffler cert_len = WPA_GET_BE24(pos); 39539beb93cSSam Leffler pos += 3; 39639beb93cSSam Leffler 39739beb93cSSam Leffler if ((size_t) (end - pos) < cert_len) { 398*5b9c547cSRui Paulo tlsv1_server_log(conn, "Unexpected certificate length (len=%lu left=%lu)", 39939beb93cSSam Leffler (unsigned long) cert_len, 40039beb93cSSam Leffler (unsigned long) (end - pos)); 40139beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 40239beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 40339beb93cSSam Leffler x509_certificate_chain_free(chain); 40439beb93cSSam Leffler return -1; 40539beb93cSSam Leffler } 40639beb93cSSam Leffler 407*5b9c547cSRui Paulo tlsv1_server_log(conn, "Certificate %lu (len %lu)", 40839beb93cSSam Leffler (unsigned long) idx, (unsigned long) cert_len); 40939beb93cSSam Leffler 41039beb93cSSam Leffler if (idx == 0) { 41139beb93cSSam Leffler crypto_public_key_free(conn->client_rsa_key); 41239beb93cSSam Leffler if (tls_parse_cert(pos, cert_len, 41339beb93cSSam Leffler &conn->client_rsa_key)) { 414*5b9c547cSRui Paulo tlsv1_server_log(conn, "Failed to parse the certificate"); 41539beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 41639beb93cSSam Leffler TLS_ALERT_BAD_CERTIFICATE); 41739beb93cSSam Leffler x509_certificate_chain_free(chain); 41839beb93cSSam Leffler return -1; 41939beb93cSSam Leffler } 42039beb93cSSam Leffler } 42139beb93cSSam Leffler 42239beb93cSSam Leffler cert = x509_certificate_parse(pos, cert_len); 42339beb93cSSam Leffler if (cert == NULL) { 424*5b9c547cSRui Paulo tlsv1_server_log(conn, "Failed to parse the certificate"); 42539beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 42639beb93cSSam Leffler TLS_ALERT_BAD_CERTIFICATE); 42739beb93cSSam Leffler x509_certificate_chain_free(chain); 42839beb93cSSam Leffler return -1; 42939beb93cSSam Leffler } 43039beb93cSSam Leffler 43139beb93cSSam Leffler if (last == NULL) 43239beb93cSSam Leffler chain = cert; 43339beb93cSSam Leffler else 43439beb93cSSam Leffler last->next = cert; 43539beb93cSSam Leffler last = cert; 43639beb93cSSam Leffler 43739beb93cSSam Leffler idx++; 43839beb93cSSam Leffler pos += cert_len; 43939beb93cSSam Leffler } 44039beb93cSSam Leffler 44139beb93cSSam Leffler if (x509_certificate_chain_validate(conn->cred->trusted_certs, chain, 442f05cddf9SRui Paulo &reason, 0) < 0) { 44339beb93cSSam Leffler int tls_reason; 444*5b9c547cSRui Paulo tlsv1_server_log(conn, "Server certificate chain validation failed (reason=%d)", 445*5b9c547cSRui Paulo reason); 44639beb93cSSam Leffler switch (reason) { 44739beb93cSSam Leffler case X509_VALIDATE_BAD_CERTIFICATE: 44839beb93cSSam Leffler tls_reason = TLS_ALERT_BAD_CERTIFICATE; 44939beb93cSSam Leffler break; 45039beb93cSSam Leffler case X509_VALIDATE_UNSUPPORTED_CERTIFICATE: 45139beb93cSSam Leffler tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE; 45239beb93cSSam Leffler break; 45339beb93cSSam Leffler case X509_VALIDATE_CERTIFICATE_REVOKED: 45439beb93cSSam Leffler tls_reason = TLS_ALERT_CERTIFICATE_REVOKED; 45539beb93cSSam Leffler break; 45639beb93cSSam Leffler case X509_VALIDATE_CERTIFICATE_EXPIRED: 45739beb93cSSam Leffler tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED; 45839beb93cSSam Leffler break; 45939beb93cSSam Leffler case X509_VALIDATE_CERTIFICATE_UNKNOWN: 46039beb93cSSam Leffler tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN; 46139beb93cSSam Leffler break; 46239beb93cSSam Leffler case X509_VALIDATE_UNKNOWN_CA: 46339beb93cSSam Leffler tls_reason = TLS_ALERT_UNKNOWN_CA; 46439beb93cSSam Leffler break; 46539beb93cSSam Leffler default: 46639beb93cSSam Leffler tls_reason = TLS_ALERT_BAD_CERTIFICATE; 46739beb93cSSam Leffler break; 46839beb93cSSam Leffler } 46939beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason); 47039beb93cSSam Leffler x509_certificate_chain_free(chain); 47139beb93cSSam Leffler return -1; 47239beb93cSSam Leffler } 47339beb93cSSam Leffler 47439beb93cSSam Leffler x509_certificate_chain_free(chain); 47539beb93cSSam Leffler 47639beb93cSSam Leffler *in_len = end - in_data; 47739beb93cSSam Leffler 47839beb93cSSam Leffler conn->state = CLIENT_KEY_EXCHANGE; 47939beb93cSSam Leffler 48039beb93cSSam Leffler return 0; 48139beb93cSSam Leffler } 48239beb93cSSam Leffler 48339beb93cSSam Leffler 48439beb93cSSam Leffler static int tls_process_client_key_exchange_rsa( 48539beb93cSSam Leffler struct tlsv1_server *conn, const u8 *pos, const u8 *end) 48639beb93cSSam Leffler { 48739beb93cSSam Leffler u8 *out; 48839beb93cSSam Leffler size_t outlen, outbuflen; 48939beb93cSSam Leffler u16 encr_len; 49039beb93cSSam Leffler int res; 49139beb93cSSam Leffler int use_random = 0; 49239beb93cSSam Leffler 49339beb93cSSam Leffler if (end - pos < 2) { 49439beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 49539beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 49639beb93cSSam Leffler return -1; 49739beb93cSSam Leffler } 49839beb93cSSam Leffler 49939beb93cSSam Leffler encr_len = WPA_GET_BE16(pos); 50039beb93cSSam Leffler pos += 2; 501f05cddf9SRui Paulo if (pos + encr_len > end) { 502*5b9c547cSRui Paulo tlsv1_server_log(conn, "Invalid ClientKeyExchange format: encr_len=%u left=%u", 503f05cddf9SRui Paulo encr_len, (unsigned int) (end - pos)); 504f05cddf9SRui Paulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 505f05cddf9SRui Paulo TLS_ALERT_DECODE_ERROR); 506f05cddf9SRui Paulo return -1; 507f05cddf9SRui Paulo } 50839beb93cSSam Leffler 50939beb93cSSam Leffler outbuflen = outlen = end - pos; 51039beb93cSSam Leffler out = os_malloc(outlen >= TLS_PRE_MASTER_SECRET_LEN ? 51139beb93cSSam Leffler outlen : TLS_PRE_MASTER_SECRET_LEN); 51239beb93cSSam Leffler if (out == NULL) { 51339beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 51439beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 51539beb93cSSam Leffler return -1; 51639beb93cSSam Leffler } 51739beb93cSSam Leffler 51839beb93cSSam Leffler /* 51939beb93cSSam Leffler * struct { 52039beb93cSSam Leffler * ProtocolVersion client_version; 52139beb93cSSam Leffler * opaque random[46]; 52239beb93cSSam Leffler * } PreMasterSecret; 52339beb93cSSam Leffler * 52439beb93cSSam Leffler * struct { 52539beb93cSSam Leffler * public-key-encrypted PreMasterSecret pre_master_secret; 52639beb93cSSam Leffler * } EncryptedPreMasterSecret; 52739beb93cSSam Leffler */ 52839beb93cSSam Leffler 52939beb93cSSam Leffler /* 53039beb93cSSam Leffler * Note: To avoid Bleichenbacher attack, we do not report decryption or 53139beb93cSSam Leffler * parsing errors from EncryptedPreMasterSecret processing to the 53239beb93cSSam Leffler * client. Instead, a random pre-master secret is used to force the 53339beb93cSSam Leffler * handshake to fail. 53439beb93cSSam Leffler */ 53539beb93cSSam Leffler 53639beb93cSSam Leffler if (crypto_private_key_decrypt_pkcs1_v15(conn->cred->key, 537f05cddf9SRui Paulo pos, encr_len, 53839beb93cSSam Leffler out, &outlen) < 0) { 53939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt " 540f05cddf9SRui Paulo "PreMasterSecret (encr_len=%u outlen=%lu)", 541f05cddf9SRui Paulo encr_len, (unsigned long) outlen); 54239beb93cSSam Leffler use_random = 1; 54339beb93cSSam Leffler } 54439beb93cSSam Leffler 545f05cddf9SRui Paulo if (!use_random && outlen != TLS_PRE_MASTER_SECRET_LEN) { 546*5b9c547cSRui Paulo tlsv1_server_log(conn, "Unexpected PreMasterSecret length %lu", 547*5b9c547cSRui Paulo (unsigned long) outlen); 54839beb93cSSam Leffler use_random = 1; 54939beb93cSSam Leffler } 55039beb93cSSam Leffler 551f05cddf9SRui Paulo if (!use_random && WPA_GET_BE16(out) != conn->client_version) { 552*5b9c547cSRui Paulo tlsv1_server_log(conn, "Client version in ClientKeyExchange does not match with version in ClientHello"); 55339beb93cSSam Leffler use_random = 1; 55439beb93cSSam Leffler } 55539beb93cSSam Leffler 55639beb93cSSam Leffler if (use_random) { 55739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Using random premaster secret " 55839beb93cSSam Leffler "to avoid revealing information about private key"); 55939beb93cSSam Leffler outlen = TLS_PRE_MASTER_SECRET_LEN; 56039beb93cSSam Leffler if (os_get_random(out, outlen)) { 56139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " 56239beb93cSSam Leffler "data"); 56339beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 56439beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 56539beb93cSSam Leffler os_free(out); 56639beb93cSSam Leffler return -1; 56739beb93cSSam Leffler } 56839beb93cSSam Leffler } 56939beb93cSSam Leffler 57039beb93cSSam Leffler res = tlsv1_server_derive_keys(conn, out, outlen); 57139beb93cSSam Leffler 57239beb93cSSam Leffler /* Clear the pre-master secret since it is not needed anymore */ 57339beb93cSSam Leffler os_memset(out, 0, outbuflen); 57439beb93cSSam Leffler os_free(out); 57539beb93cSSam Leffler 57639beb93cSSam Leffler if (res) { 57739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); 57839beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 57939beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 58039beb93cSSam Leffler return -1; 58139beb93cSSam Leffler } 58239beb93cSSam Leffler 58339beb93cSSam Leffler return 0; 58439beb93cSSam Leffler } 58539beb93cSSam Leffler 58639beb93cSSam Leffler 587*5b9c547cSRui Paulo static int tls_process_client_key_exchange_dh( 58839beb93cSSam Leffler struct tlsv1_server *conn, const u8 *pos, const u8 *end) 58939beb93cSSam Leffler { 59039beb93cSSam Leffler const u8 *dh_yc; 59139beb93cSSam Leffler u16 dh_yc_len; 59239beb93cSSam Leffler u8 *shared; 59339beb93cSSam Leffler size_t shared_len; 59439beb93cSSam Leffler int res; 595*5b9c547cSRui Paulo const u8 *dh_p; 596*5b9c547cSRui Paulo size_t dh_p_len; 59739beb93cSSam Leffler 59839beb93cSSam Leffler /* 59939beb93cSSam Leffler * struct { 60039beb93cSSam Leffler * select (PublicValueEncoding) { 60139beb93cSSam Leffler * case implicit: struct { }; 60239beb93cSSam Leffler * case explicit: opaque dh_Yc<1..2^16-1>; 60339beb93cSSam Leffler * } dh_public; 60439beb93cSSam Leffler * } ClientDiffieHellmanPublic; 60539beb93cSSam Leffler */ 60639beb93cSSam Leffler 607*5b9c547cSRui Paulo tlsv1_server_log(conn, "ClientDiffieHellmanPublic received"); 60839beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientDiffieHellmanPublic", 60939beb93cSSam Leffler pos, end - pos); 61039beb93cSSam Leffler 61139beb93cSSam Leffler if (end == pos) { 61239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Implicit public value encoding " 61339beb93cSSam Leffler "not supported"); 61439beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 61539beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 61639beb93cSSam Leffler return -1; 61739beb93cSSam Leffler } 61839beb93cSSam Leffler 61939beb93cSSam Leffler if (end - pos < 3) { 620*5b9c547cSRui Paulo tlsv1_server_log(conn, "Invalid client public value length"); 62139beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 62239beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 62339beb93cSSam Leffler return -1; 62439beb93cSSam Leffler } 62539beb93cSSam Leffler 62639beb93cSSam Leffler dh_yc_len = WPA_GET_BE16(pos); 62739beb93cSSam Leffler dh_yc = pos + 2; 62839beb93cSSam Leffler 629*5b9c547cSRui Paulo if (dh_yc_len > end - dh_yc) { 630*5b9c547cSRui Paulo tlsv1_server_log(conn, "Client public value overflow (length %d)", 631*5b9c547cSRui Paulo dh_yc_len); 63239beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 63339beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 63439beb93cSSam Leffler return -1; 63539beb93cSSam Leffler } 63639beb93cSSam Leffler 63739beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)", 63839beb93cSSam Leffler dh_yc, dh_yc_len); 63939beb93cSSam Leffler 64039beb93cSSam Leffler if (conn->cred == NULL || conn->cred->dh_p == NULL || 64139beb93cSSam Leffler conn->dh_secret == NULL) { 64239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available"); 64339beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 64439beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 64539beb93cSSam Leffler return -1; 64639beb93cSSam Leffler } 64739beb93cSSam Leffler 648*5b9c547cSRui Paulo tlsv1_server_get_dh_p(conn, &dh_p, &dh_p_len); 649*5b9c547cSRui Paulo 650*5b9c547cSRui Paulo shared_len = dh_p_len; 65139beb93cSSam Leffler shared = os_malloc(shared_len); 65239beb93cSSam Leffler if (shared == NULL) { 65339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for " 65439beb93cSSam Leffler "DH"); 65539beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 65639beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 65739beb93cSSam Leffler return -1; 65839beb93cSSam Leffler } 65939beb93cSSam Leffler 66039beb93cSSam Leffler /* shared = Yc^secret mod p */ 66139beb93cSSam Leffler if (crypto_mod_exp(dh_yc, dh_yc_len, conn->dh_secret, 662*5b9c547cSRui Paulo conn->dh_secret_len, dh_p, dh_p_len, 66339beb93cSSam Leffler shared, &shared_len)) { 66439beb93cSSam Leffler os_free(shared); 66539beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 66639beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 66739beb93cSSam Leffler return -1; 66839beb93cSSam Leffler } 66939beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange", 67039beb93cSSam Leffler shared, shared_len); 67139beb93cSSam Leffler 67239beb93cSSam Leffler os_memset(conn->dh_secret, 0, conn->dh_secret_len); 67339beb93cSSam Leffler os_free(conn->dh_secret); 67439beb93cSSam Leffler conn->dh_secret = NULL; 67539beb93cSSam Leffler 67639beb93cSSam Leffler res = tlsv1_server_derive_keys(conn, shared, shared_len); 67739beb93cSSam Leffler 67839beb93cSSam Leffler /* Clear the pre-master secret since it is not needed anymore */ 67939beb93cSSam Leffler os_memset(shared, 0, shared_len); 68039beb93cSSam Leffler os_free(shared); 68139beb93cSSam Leffler 68239beb93cSSam Leffler if (res) { 68339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); 68439beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 68539beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 68639beb93cSSam Leffler return -1; 68739beb93cSSam Leffler } 68839beb93cSSam Leffler 68939beb93cSSam Leffler return 0; 69039beb93cSSam Leffler } 69139beb93cSSam Leffler 69239beb93cSSam Leffler 69339beb93cSSam Leffler static int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct, 69439beb93cSSam Leffler const u8 *in_data, size_t *in_len) 69539beb93cSSam Leffler { 69639beb93cSSam Leffler const u8 *pos, *end; 69739beb93cSSam Leffler size_t left, len; 69839beb93cSSam Leffler u8 type; 69939beb93cSSam Leffler tls_key_exchange keyx; 70039beb93cSSam Leffler const struct tls_cipher_suite *suite; 70139beb93cSSam Leffler 70239beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 703*5b9c547cSRui Paulo tlsv1_server_log(conn, "Expected Handshake; received content type 0x%x", 704*5b9c547cSRui Paulo ct); 70539beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 70639beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 70739beb93cSSam Leffler return -1; 70839beb93cSSam Leffler } 70939beb93cSSam Leffler 71039beb93cSSam Leffler pos = in_data; 71139beb93cSSam Leffler left = *in_len; 71239beb93cSSam Leffler 71339beb93cSSam Leffler if (left < 4) { 714*5b9c547cSRui Paulo tlsv1_server_log(conn, "Too short ClientKeyExchange (Left=%lu)", 715*5b9c547cSRui Paulo (unsigned long) left); 71639beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 71739beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 71839beb93cSSam Leffler return -1; 71939beb93cSSam Leffler } 72039beb93cSSam Leffler 72139beb93cSSam Leffler type = *pos++; 72239beb93cSSam Leffler len = WPA_GET_BE24(pos); 72339beb93cSSam Leffler pos += 3; 72439beb93cSSam Leffler left -= 4; 72539beb93cSSam Leffler 72639beb93cSSam Leffler if (len > left) { 727*5b9c547cSRui Paulo tlsv1_server_log(conn, "Mismatch in ClientKeyExchange length (len=%lu != left=%lu)", 72839beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 72939beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 73039beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 73139beb93cSSam Leffler return -1; 73239beb93cSSam Leffler } 73339beb93cSSam Leffler 73439beb93cSSam Leffler end = pos + len; 73539beb93cSSam Leffler 73639beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) { 737*5b9c547cSRui Paulo tlsv1_server_log(conn, "Received unexpected handshake message %d (expected ClientKeyExchange)", 738*5b9c547cSRui Paulo type); 73939beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 74039beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 74139beb93cSSam Leffler return -1; 74239beb93cSSam Leffler } 74339beb93cSSam Leffler 744*5b9c547cSRui Paulo tlsv1_server_log(conn, "Received ClientKeyExchange"); 74539beb93cSSam Leffler 74639beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: ClientKeyExchange", pos, len); 74739beb93cSSam Leffler 74839beb93cSSam Leffler suite = tls_get_cipher_suite(conn->rl.cipher_suite); 74939beb93cSSam Leffler if (suite == NULL) 75039beb93cSSam Leffler keyx = TLS_KEY_X_NULL; 75139beb93cSSam Leffler else 75239beb93cSSam Leffler keyx = suite->key_exchange; 75339beb93cSSam Leffler 754*5b9c547cSRui Paulo if ((keyx == TLS_KEY_X_DH_anon || keyx == TLS_KEY_X_DHE_RSA) && 755*5b9c547cSRui Paulo tls_process_client_key_exchange_dh(conn, pos, end) < 0) 75639beb93cSSam Leffler return -1; 75739beb93cSSam Leffler 758*5b9c547cSRui Paulo if (keyx != TLS_KEY_X_DH_anon && keyx != TLS_KEY_X_DHE_RSA && 75939beb93cSSam Leffler tls_process_client_key_exchange_rsa(conn, pos, end) < 0) 76039beb93cSSam Leffler return -1; 76139beb93cSSam Leffler 76239beb93cSSam Leffler *in_len = end - in_data; 76339beb93cSSam Leffler 76439beb93cSSam Leffler conn->state = CERTIFICATE_VERIFY; 76539beb93cSSam Leffler 76639beb93cSSam Leffler return 0; 76739beb93cSSam Leffler } 76839beb93cSSam Leffler 76939beb93cSSam Leffler 77039beb93cSSam Leffler static int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct, 77139beb93cSSam Leffler const u8 *in_data, size_t *in_len) 77239beb93cSSam Leffler { 77339beb93cSSam Leffler const u8 *pos, *end; 77439beb93cSSam Leffler size_t left, len; 77539beb93cSSam Leffler u8 type; 776*5b9c547cSRui Paulo size_t hlen; 777*5b9c547cSRui Paulo u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos; 778*5b9c547cSRui Paulo u8 alert; 77939beb93cSSam Leffler 78039beb93cSSam Leffler if (ct == TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { 78139beb93cSSam Leffler if (conn->verify_peer) { 782*5b9c547cSRui Paulo tlsv1_server_log(conn, "Client did not include CertificateVerify"); 78339beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 78439beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 78539beb93cSSam Leffler return -1; 78639beb93cSSam Leffler } 78739beb93cSSam Leffler 78839beb93cSSam Leffler return tls_process_change_cipher_spec(conn, ct, in_data, 78939beb93cSSam Leffler in_len); 79039beb93cSSam Leffler } 79139beb93cSSam Leffler 79239beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 793*5b9c547cSRui Paulo tlsv1_server_log(conn, "Expected Handshake; received content type 0x%x", 794*5b9c547cSRui Paulo ct); 79539beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 79639beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 79739beb93cSSam Leffler return -1; 79839beb93cSSam Leffler } 79939beb93cSSam Leffler 80039beb93cSSam Leffler pos = in_data; 80139beb93cSSam Leffler left = *in_len; 80239beb93cSSam Leffler 80339beb93cSSam Leffler if (left < 4) { 804*5b9c547cSRui Paulo tlsv1_server_log(conn, "Too short CertificateVerify message (len=%lu)", 805*5b9c547cSRui Paulo (unsigned long) left); 80639beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 80739beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 80839beb93cSSam Leffler return -1; 80939beb93cSSam Leffler } 81039beb93cSSam Leffler 81139beb93cSSam Leffler type = *pos++; 81239beb93cSSam Leffler len = WPA_GET_BE24(pos); 81339beb93cSSam Leffler pos += 3; 81439beb93cSSam Leffler left -= 4; 81539beb93cSSam Leffler 81639beb93cSSam Leffler if (len > left) { 817*5b9c547cSRui Paulo tlsv1_server_log(conn, "Unexpected CertificateVerify message length (len=%lu != left=%lu)", 81839beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 81939beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 82039beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 82139beb93cSSam Leffler return -1; 82239beb93cSSam Leffler } 82339beb93cSSam Leffler 82439beb93cSSam Leffler end = pos + len; 82539beb93cSSam Leffler 82639beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY) { 827*5b9c547cSRui Paulo tlsv1_server_log(conn, "Received unexpected handshake message %d (expected CertificateVerify)", 828*5b9c547cSRui Paulo type); 82939beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 83039beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 83139beb93cSSam Leffler return -1; 83239beb93cSSam Leffler } 83339beb93cSSam Leffler 834*5b9c547cSRui Paulo tlsv1_server_log(conn, "Received CertificateVerify"); 83539beb93cSSam Leffler 83639beb93cSSam Leffler /* 83739beb93cSSam Leffler * struct { 83839beb93cSSam Leffler * Signature signature; 83939beb93cSSam Leffler * } CertificateVerify; 84039beb93cSSam Leffler */ 84139beb93cSSam Leffler 84239beb93cSSam Leffler hpos = hash; 84339beb93cSSam Leffler 844f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 845f05cddf9SRui Paulo if (conn->rl.tls_version == TLS_VERSION_1_2) { 846f05cddf9SRui Paulo /* 847f05cddf9SRui Paulo * RFC 5246, 4.7: 848f05cddf9SRui Paulo * TLS v1.2 adds explicit indication of the used signature and 849f05cddf9SRui Paulo * hash algorithms. 850f05cddf9SRui Paulo * 851f05cddf9SRui Paulo * struct { 852f05cddf9SRui Paulo * HashAlgorithm hash; 853f05cddf9SRui Paulo * SignatureAlgorithm signature; 854f05cddf9SRui Paulo * } SignatureAndHashAlgorithm; 855f05cddf9SRui Paulo */ 856f05cddf9SRui Paulo if (end - pos < 2) { 857f05cddf9SRui Paulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 858f05cddf9SRui Paulo TLS_ALERT_DECODE_ERROR); 859f05cddf9SRui Paulo return -1; 860f05cddf9SRui Paulo } 861f05cddf9SRui Paulo if (pos[0] != TLS_HASH_ALG_SHA256 || 862f05cddf9SRui Paulo pos[1] != TLS_SIGN_ALG_RSA) { 863f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/" 864f05cddf9SRui Paulo "signature(%u) algorithm", 865f05cddf9SRui Paulo pos[0], pos[1]); 866f05cddf9SRui Paulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 867f05cddf9SRui Paulo TLS_ALERT_INTERNAL_ERROR); 868f05cddf9SRui Paulo return -1; 869f05cddf9SRui Paulo } 870f05cddf9SRui Paulo pos += 2; 871f05cddf9SRui Paulo 872f05cddf9SRui Paulo hlen = SHA256_MAC_LEN; 873f05cddf9SRui Paulo if (conn->verify.sha256_cert == NULL || 874f05cddf9SRui Paulo crypto_hash_finish(conn->verify.sha256_cert, hpos, &hlen) < 875f05cddf9SRui Paulo 0) { 876f05cddf9SRui Paulo conn->verify.sha256_cert = NULL; 877f05cddf9SRui Paulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 878f05cddf9SRui Paulo TLS_ALERT_INTERNAL_ERROR); 879f05cddf9SRui Paulo return -1; 880f05cddf9SRui Paulo } 881f05cddf9SRui Paulo conn->verify.sha256_cert = NULL; 882f05cddf9SRui Paulo } else { 883f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 884f05cddf9SRui Paulo 88539beb93cSSam Leffler hlen = MD5_MAC_LEN; 88639beb93cSSam Leffler if (conn->verify.md5_cert == NULL || 887*5b9c547cSRui Paulo crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) { 88839beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 88939beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 89039beb93cSSam Leffler conn->verify.md5_cert = NULL; 89139beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL); 89239beb93cSSam Leffler conn->verify.sha1_cert = NULL; 89339beb93cSSam Leffler return -1; 89439beb93cSSam Leffler } 89539beb93cSSam Leffler hpos += MD5_MAC_LEN; 89639beb93cSSam Leffler 89739beb93cSSam Leffler conn->verify.md5_cert = NULL; 89839beb93cSSam Leffler hlen = SHA1_MAC_LEN; 89939beb93cSSam Leffler if (conn->verify.sha1_cert == NULL || 90039beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) { 90139beb93cSSam Leffler conn->verify.sha1_cert = NULL; 90239beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 90339beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 90439beb93cSSam Leffler return -1; 90539beb93cSSam Leffler } 90639beb93cSSam Leffler conn->verify.sha1_cert = NULL; 90739beb93cSSam Leffler 90839beb93cSSam Leffler hlen += MD5_MAC_LEN; 90939beb93cSSam Leffler 910f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 911f05cddf9SRui Paulo } 912f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 913f05cddf9SRui Paulo 91439beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen); 91539beb93cSSam Leffler 916*5b9c547cSRui Paulo if (tls_verify_signature(conn->rl.tls_version, conn->client_rsa_key, 917*5b9c547cSRui Paulo hash, hlen, pos, end - pos, &alert) < 0) { 918*5b9c547cSRui Paulo tlsv1_server_log(conn, "Invalid Signature in CertificateVerify"); 919*5b9c547cSRui Paulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); 92039beb93cSSam Leffler return -1; 92139beb93cSSam Leffler } 92239beb93cSSam Leffler 92339beb93cSSam Leffler *in_len = end - in_data; 92439beb93cSSam Leffler 92539beb93cSSam Leffler conn->state = CHANGE_CIPHER_SPEC; 92639beb93cSSam Leffler 92739beb93cSSam Leffler return 0; 92839beb93cSSam Leffler } 92939beb93cSSam Leffler 93039beb93cSSam Leffler 93139beb93cSSam Leffler static int tls_process_change_cipher_spec(struct tlsv1_server *conn, 93239beb93cSSam Leffler u8 ct, const u8 *in_data, 93339beb93cSSam Leffler size_t *in_len) 93439beb93cSSam Leffler { 93539beb93cSSam Leffler const u8 *pos; 93639beb93cSSam Leffler size_t left; 93739beb93cSSam Leffler 93839beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { 939*5b9c547cSRui Paulo tlsv1_server_log(conn, "Expected ChangeCipherSpec; received content type 0x%x", 940*5b9c547cSRui Paulo ct); 94139beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 94239beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 94339beb93cSSam Leffler return -1; 94439beb93cSSam Leffler } 94539beb93cSSam Leffler 94639beb93cSSam Leffler pos = in_data; 94739beb93cSSam Leffler left = *in_len; 94839beb93cSSam Leffler 94939beb93cSSam Leffler if (left < 1) { 950*5b9c547cSRui Paulo tlsv1_server_log(conn, "Too short ChangeCipherSpec"); 95139beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 95239beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 95339beb93cSSam Leffler return -1; 95439beb93cSSam Leffler } 95539beb93cSSam Leffler 95639beb93cSSam Leffler if (*pos != TLS_CHANGE_CIPHER_SPEC) { 957*5b9c547cSRui Paulo tlsv1_server_log(conn, "Expected ChangeCipherSpec; received data 0x%x", 958*5b9c547cSRui Paulo *pos); 95939beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 96039beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 96139beb93cSSam Leffler return -1; 96239beb93cSSam Leffler } 96339beb93cSSam Leffler 964*5b9c547cSRui Paulo tlsv1_server_log(conn, "Received ChangeCipherSpec"); 96539beb93cSSam Leffler if (tlsv1_record_change_read_cipher(&conn->rl) < 0) { 96639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher " 96739beb93cSSam Leffler "for record layer"); 96839beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 96939beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 97039beb93cSSam Leffler return -1; 97139beb93cSSam Leffler } 97239beb93cSSam Leffler 97339beb93cSSam Leffler *in_len = pos + 1 - in_data; 97439beb93cSSam Leffler 97539beb93cSSam Leffler conn->state = CLIENT_FINISHED; 97639beb93cSSam Leffler 97739beb93cSSam Leffler return 0; 97839beb93cSSam Leffler } 97939beb93cSSam Leffler 98039beb93cSSam Leffler 98139beb93cSSam Leffler static int tls_process_client_finished(struct tlsv1_server *conn, u8 ct, 98239beb93cSSam Leffler const u8 *in_data, size_t *in_len) 98339beb93cSSam Leffler { 98439beb93cSSam Leffler const u8 *pos, *end; 98539beb93cSSam Leffler size_t left, len, hlen; 98639beb93cSSam Leffler u8 verify_data[TLS_VERIFY_DATA_LEN]; 98739beb93cSSam Leffler u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; 98839beb93cSSam Leffler 989*5b9c547cSRui Paulo #ifdef CONFIG_TESTING_OPTIONS 990*5b9c547cSRui Paulo if ((conn->test_flags & 991*5b9c547cSRui Paulo (TLS_BREAK_SRV_KEY_X_HASH | TLS_BREAK_SRV_KEY_X_SIGNATURE)) && 992*5b9c547cSRui Paulo !conn->test_failure_reported) { 993*5b9c547cSRui Paulo tlsv1_server_log(conn, "TEST-FAILURE: Client Finished received after invalid ServerKeyExchange"); 994*5b9c547cSRui Paulo conn->test_failure_reported = 1; 995*5b9c547cSRui Paulo } 996*5b9c547cSRui Paulo 997*5b9c547cSRui Paulo if ((conn->test_flags & TLS_DHE_PRIME_15) && 998*5b9c547cSRui Paulo !conn->test_failure_reported) { 999*5b9c547cSRui Paulo tlsv1_server_log(conn, "TEST-FAILURE: Client Finished received after bogus DHE \"prime\" 15"); 1000*5b9c547cSRui Paulo conn->test_failure_reported = 1; 1001*5b9c547cSRui Paulo } 1002*5b9c547cSRui Paulo 1003*5b9c547cSRui Paulo if ((conn->test_flags & TLS_DHE_PRIME_58B) && 1004*5b9c547cSRui Paulo !conn->test_failure_reported) { 1005*5b9c547cSRui Paulo tlsv1_server_log(conn, "TEST-FAILURE: Client Finished received after short 58-bit DHE prime in long container"); 1006*5b9c547cSRui Paulo conn->test_failure_reported = 1; 1007*5b9c547cSRui Paulo } 1008*5b9c547cSRui Paulo 1009*5b9c547cSRui Paulo if ((conn->test_flags & TLS_DHE_PRIME_511B) && 1010*5b9c547cSRui Paulo !conn->test_failure_reported) { 1011*5b9c547cSRui Paulo tlsv1_server_log(conn, "TEST-WARNING: Client Finished received after short 511-bit DHE prime (insecure)"); 1012*5b9c547cSRui Paulo conn->test_failure_reported = 1; 1013*5b9c547cSRui Paulo } 1014*5b9c547cSRui Paulo 1015*5b9c547cSRui Paulo if ((conn->test_flags & TLS_DHE_PRIME_767B) && 1016*5b9c547cSRui Paulo !conn->test_failure_reported) { 1017*5b9c547cSRui Paulo tlsv1_server_log(conn, "TEST-NOTE: Client Finished received after 767-bit DHE prime (relatively insecure)"); 1018*5b9c547cSRui Paulo conn->test_failure_reported = 1; 1019*5b9c547cSRui Paulo } 1020*5b9c547cSRui Paulo 1021*5b9c547cSRui Paulo if ((conn->test_flags & TLS_DHE_NON_PRIME) && 1022*5b9c547cSRui Paulo !conn->test_failure_reported) { 1023*5b9c547cSRui Paulo tlsv1_server_log(conn, "TEST-NOTE: Client Finished received after non-prime claimed as DHE prime"); 1024*5b9c547cSRui Paulo conn->test_failure_reported = 1; 1025*5b9c547cSRui Paulo } 1026*5b9c547cSRui Paulo #endif /* CONFIG_TESTING_OPTIONS */ 1027*5b9c547cSRui Paulo 102839beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 1029*5b9c547cSRui Paulo tlsv1_server_log(conn, "Expected Finished; received content type 0x%x", 1030*5b9c547cSRui Paulo ct); 103139beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 103239beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 103339beb93cSSam Leffler return -1; 103439beb93cSSam Leffler } 103539beb93cSSam Leffler 103639beb93cSSam Leffler pos = in_data; 103739beb93cSSam Leffler left = *in_len; 103839beb93cSSam Leffler 103939beb93cSSam Leffler if (left < 4) { 1040*5b9c547cSRui Paulo tlsv1_server_log(conn, "Too short record (left=%lu) forFinished", 104139beb93cSSam Leffler (unsigned long) left); 104239beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 104339beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 104439beb93cSSam Leffler return -1; 104539beb93cSSam Leffler } 104639beb93cSSam Leffler 104739beb93cSSam Leffler if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) { 104839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received " 104939beb93cSSam Leffler "type 0x%x", pos[0]); 105039beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 105139beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 105239beb93cSSam Leffler return -1; 105339beb93cSSam Leffler } 105439beb93cSSam Leffler 105539beb93cSSam Leffler len = WPA_GET_BE24(pos + 1); 105639beb93cSSam Leffler 105739beb93cSSam Leffler pos += 4; 105839beb93cSSam Leffler left -= 4; 105939beb93cSSam Leffler 106039beb93cSSam Leffler if (len > left) { 1061*5b9c547cSRui Paulo tlsv1_server_log(conn, "Too short buffer for Finished (len=%lu > left=%lu)", 106239beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 106339beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 106439beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 106539beb93cSSam Leffler return -1; 106639beb93cSSam Leffler } 106739beb93cSSam Leffler end = pos + len; 106839beb93cSSam Leffler if (len != TLS_VERIFY_DATA_LEN) { 1069*5b9c547cSRui Paulo tlsv1_server_log(conn, "Unexpected verify_data length in Finished: %lu (expected %d)", 107039beb93cSSam Leffler (unsigned long) len, TLS_VERIFY_DATA_LEN); 107139beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 107239beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 107339beb93cSSam Leffler return -1; 107439beb93cSSam Leffler } 107539beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished", 107639beb93cSSam Leffler pos, TLS_VERIFY_DATA_LEN); 107739beb93cSSam Leffler 1078f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 1079f05cddf9SRui Paulo if (conn->rl.tls_version >= TLS_VERSION_1_2) { 1080f05cddf9SRui Paulo hlen = SHA256_MAC_LEN; 1081f05cddf9SRui Paulo if (conn->verify.sha256_client == NULL || 1082f05cddf9SRui Paulo crypto_hash_finish(conn->verify.sha256_client, hash, &hlen) 1083f05cddf9SRui Paulo < 0) { 1084f05cddf9SRui Paulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 1085f05cddf9SRui Paulo TLS_ALERT_INTERNAL_ERROR); 1086f05cddf9SRui Paulo conn->verify.sha256_client = NULL; 1087f05cddf9SRui Paulo return -1; 1088f05cddf9SRui Paulo } 1089f05cddf9SRui Paulo conn->verify.sha256_client = NULL; 1090f05cddf9SRui Paulo } else { 1091f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 1092f05cddf9SRui Paulo 109339beb93cSSam Leffler hlen = MD5_MAC_LEN; 109439beb93cSSam Leffler if (conn->verify.md5_client == NULL || 109539beb93cSSam Leffler crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) { 109639beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 109739beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 109839beb93cSSam Leffler conn->verify.md5_client = NULL; 109939beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_client, NULL, NULL); 110039beb93cSSam Leffler conn->verify.sha1_client = NULL; 110139beb93cSSam Leffler return -1; 110239beb93cSSam Leffler } 110339beb93cSSam Leffler conn->verify.md5_client = NULL; 110439beb93cSSam Leffler hlen = SHA1_MAC_LEN; 110539beb93cSSam Leffler if (conn->verify.sha1_client == NULL || 110639beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN, 110739beb93cSSam Leffler &hlen) < 0) { 110839beb93cSSam Leffler conn->verify.sha1_client = NULL; 110939beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 111039beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 111139beb93cSSam Leffler return -1; 111239beb93cSSam Leffler } 111339beb93cSSam Leffler conn->verify.sha1_client = NULL; 1114f05cddf9SRui Paulo hlen = MD5_MAC_LEN + SHA1_MAC_LEN; 111539beb93cSSam Leffler 1116f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 1117f05cddf9SRui Paulo } 1118f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 1119f05cddf9SRui Paulo 1120f05cddf9SRui Paulo if (tls_prf(conn->rl.tls_version, 1121f05cddf9SRui Paulo conn->master_secret, TLS_MASTER_SECRET_LEN, 1122f05cddf9SRui Paulo "client finished", hash, hlen, 112339beb93cSSam Leffler verify_data, TLS_VERIFY_DATA_LEN)) { 112439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data"); 112539beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 112639beb93cSSam Leffler TLS_ALERT_DECRYPT_ERROR); 112739beb93cSSam Leffler return -1; 112839beb93cSSam Leffler } 112939beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)", 113039beb93cSSam Leffler verify_data, TLS_VERIFY_DATA_LEN); 113139beb93cSSam Leffler 1132*5b9c547cSRui Paulo if (os_memcmp_const(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) { 1133*5b9c547cSRui Paulo tlsv1_server_log(conn, "Mismatch in verify_data"); 113439beb93cSSam Leffler return -1; 113539beb93cSSam Leffler } 113639beb93cSSam Leffler 1137*5b9c547cSRui Paulo tlsv1_server_log(conn, "Received Finished"); 113839beb93cSSam Leffler 113939beb93cSSam Leffler *in_len = end - in_data; 114039beb93cSSam Leffler 114139beb93cSSam Leffler if (conn->use_session_ticket) { 114239beb93cSSam Leffler /* Abbreviated handshake using session ticket; RFC 4507 */ 1143*5b9c547cSRui Paulo tlsv1_server_log(conn, "Abbreviated handshake completed successfully"); 114439beb93cSSam Leffler conn->state = ESTABLISHED; 114539beb93cSSam Leffler } else { 114639beb93cSSam Leffler /* Full handshake */ 114739beb93cSSam Leffler conn->state = SERVER_CHANGE_CIPHER_SPEC; 114839beb93cSSam Leffler } 114939beb93cSSam Leffler 115039beb93cSSam Leffler return 0; 115139beb93cSSam Leffler } 115239beb93cSSam Leffler 115339beb93cSSam Leffler 115439beb93cSSam Leffler int tlsv1_server_process_handshake(struct tlsv1_server *conn, u8 ct, 115539beb93cSSam Leffler const u8 *buf, size_t *len) 115639beb93cSSam Leffler { 115739beb93cSSam Leffler if (ct == TLS_CONTENT_TYPE_ALERT) { 115839beb93cSSam Leffler if (*len < 2) { 1159*5b9c547cSRui Paulo tlsv1_server_log(conn, "Alert underflow"); 116039beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 116139beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 116239beb93cSSam Leffler return -1; 116339beb93cSSam Leffler } 1164*5b9c547cSRui Paulo tlsv1_server_log(conn, "Received alert %d:%d", buf[0], buf[1]); 116539beb93cSSam Leffler *len = 2; 116639beb93cSSam Leffler conn->state = FAILED; 116739beb93cSSam Leffler return -1; 116839beb93cSSam Leffler } 116939beb93cSSam Leffler 117039beb93cSSam Leffler switch (conn->state) { 117139beb93cSSam Leffler case CLIENT_HELLO: 117239beb93cSSam Leffler if (tls_process_client_hello(conn, ct, buf, len)) 117339beb93cSSam Leffler return -1; 117439beb93cSSam Leffler break; 117539beb93cSSam Leffler case CLIENT_CERTIFICATE: 117639beb93cSSam Leffler if (tls_process_certificate(conn, ct, buf, len)) 117739beb93cSSam Leffler return -1; 117839beb93cSSam Leffler break; 117939beb93cSSam Leffler case CLIENT_KEY_EXCHANGE: 118039beb93cSSam Leffler if (tls_process_client_key_exchange(conn, ct, buf, len)) 118139beb93cSSam Leffler return -1; 118239beb93cSSam Leffler break; 118339beb93cSSam Leffler case CERTIFICATE_VERIFY: 118439beb93cSSam Leffler if (tls_process_certificate_verify(conn, ct, buf, len)) 118539beb93cSSam Leffler return -1; 118639beb93cSSam Leffler break; 118739beb93cSSam Leffler case CHANGE_CIPHER_SPEC: 118839beb93cSSam Leffler if (tls_process_change_cipher_spec(conn, ct, buf, len)) 118939beb93cSSam Leffler return -1; 119039beb93cSSam Leffler break; 119139beb93cSSam Leffler case CLIENT_FINISHED: 119239beb93cSSam Leffler if (tls_process_client_finished(conn, ct, buf, len)) 119339beb93cSSam Leffler return -1; 119439beb93cSSam Leffler break; 119539beb93cSSam Leffler default: 1196*5b9c547cSRui Paulo tlsv1_server_log(conn, "Unexpected state %d while processing received message", 119739beb93cSSam Leffler conn->state); 119839beb93cSSam Leffler return -1; 119939beb93cSSam Leffler } 120039beb93cSSam Leffler 120139beb93cSSam Leffler if (ct == TLS_CONTENT_TYPE_HANDSHAKE) 120239beb93cSSam Leffler tls_verify_hash_add(&conn->verify, buf, *len); 120339beb93cSSam Leffler 120439beb93cSSam Leffler return 0; 120539beb93cSSam Leffler } 1206