139beb93cSSam Leffler /* 239beb93cSSam Leffler * TLSv1 server - read handshake message 35b9c547cSRui 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 305b9c547cSRui Paulo static int testing_cipher_suite_filter(struct tlsv1_server *conn, u16 suite) 315b9c547cSRui Paulo { 325b9c547cSRui Paulo #ifdef CONFIG_TESTING_OPTIONS 335b9c547cSRui Paulo if ((conn->test_flags & 345b9c547cSRui Paulo (TLS_BREAK_SRV_KEY_X_HASH | TLS_BREAK_SRV_KEY_X_SIGNATURE | 355b9c547cSRui Paulo TLS_DHE_PRIME_511B | TLS_DHE_PRIME_767B | TLS_DHE_PRIME_15 | 365b9c547cSRui Paulo TLS_DHE_PRIME_58B | TLS_DHE_NON_PRIME)) && 375b9c547cSRui Paulo suite != TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 && 385b9c547cSRui Paulo suite != TLS_DHE_RSA_WITH_AES_256_CBC_SHA && 395b9c547cSRui Paulo suite != TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 && 405b9c547cSRui Paulo suite != TLS_DHE_RSA_WITH_AES_128_CBC_SHA && 415b9c547cSRui Paulo suite != TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) 425b9c547cSRui Paulo return 1; 435b9c547cSRui Paulo #endif /* CONFIG_TESTING_OPTIONS */ 445b9c547cSRui Paulo 455b9c547cSRui Paulo return 0; 465b9c547cSRui Paulo } 475b9c547cSRui Paulo 485b9c547cSRui Paulo 49780fb4a2SCy Schubert static void tls_process_status_request_item(struct tlsv1_server *conn, 50780fb4a2SCy Schubert const u8 *req, size_t req_len) 51780fb4a2SCy Schubert { 52780fb4a2SCy Schubert const u8 *pos, *end; 53780fb4a2SCy Schubert u8 status_type; 54780fb4a2SCy Schubert 55780fb4a2SCy Schubert pos = req; 56780fb4a2SCy Schubert end = req + req_len; 57780fb4a2SCy Schubert 58780fb4a2SCy Schubert /* 59780fb4a2SCy Schubert * RFC 6961, 2.2: 60780fb4a2SCy Schubert * struct { 61780fb4a2SCy Schubert * CertificateStatusType status_type; 62780fb4a2SCy Schubert * uint16 request_length; 63780fb4a2SCy Schubert * select (status_type) { 64780fb4a2SCy Schubert * case ocsp: OCSPStatusRequest; 65780fb4a2SCy Schubert * case ocsp_multi: OCSPStatusRequest; 66780fb4a2SCy Schubert * } request; 67780fb4a2SCy Schubert * } CertificateStatusRequestItemV2; 68780fb4a2SCy Schubert * 69780fb4a2SCy Schubert * enum { ocsp(1), ocsp_multi(2), (255) } CertificateStatusType; 70780fb4a2SCy Schubert */ 71780fb4a2SCy Schubert 72780fb4a2SCy Schubert if (end - pos < 1) 73780fb4a2SCy Schubert return; /* Truncated data */ 74780fb4a2SCy Schubert 75780fb4a2SCy Schubert status_type = *pos++; 76780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, "TLSv1: CertificateStatusType %u", status_type); 77780fb4a2SCy Schubert if (status_type != 1 && status_type != 2) 78780fb4a2SCy Schubert return; /* Unsupported status type */ 79780fb4a2SCy Schubert /* 80780fb4a2SCy Schubert * For now, only OCSP stapling is supported, so ignore the specific 81780fb4a2SCy Schubert * request, if any. 82780fb4a2SCy Schubert */ 83780fb4a2SCy Schubert wpa_hexdump(MSG_DEBUG, "TLSv1: OCSPStatusRequest", pos, end - pos); 84780fb4a2SCy Schubert 85780fb4a2SCy Schubert if (status_type == 2) 86780fb4a2SCy Schubert conn->status_request_multi = 1; 87780fb4a2SCy Schubert } 88780fb4a2SCy Schubert 89780fb4a2SCy Schubert 90780fb4a2SCy Schubert static void tls_process_status_request_v2(struct tlsv1_server *conn, 91780fb4a2SCy Schubert const u8 *ext, size_t ext_len) 92780fb4a2SCy Schubert { 93780fb4a2SCy Schubert const u8 *pos, *end; 94780fb4a2SCy Schubert 95780fb4a2SCy Schubert conn->status_request_v2 = 1; 96780fb4a2SCy Schubert 97780fb4a2SCy Schubert pos = ext; 98780fb4a2SCy Schubert end = ext + ext_len; 99780fb4a2SCy Schubert 100780fb4a2SCy Schubert /* 101780fb4a2SCy Schubert * RFC 6961, 2.2: 102780fb4a2SCy Schubert * struct { 103780fb4a2SCy Schubert * CertificateStatusRequestItemV2 104780fb4a2SCy Schubert * certificate_status_req_list<1..2^16-1>; 105780fb4a2SCy Schubert * } CertificateStatusRequestListV2; 106780fb4a2SCy Schubert */ 107780fb4a2SCy Schubert 108780fb4a2SCy Schubert while (end - pos >= 2) { 109780fb4a2SCy Schubert u16 len; 110780fb4a2SCy Schubert 111780fb4a2SCy Schubert len = WPA_GET_BE16(pos); 112780fb4a2SCy Schubert pos += 2; 113780fb4a2SCy Schubert if (len > end - pos) 114780fb4a2SCy Schubert break; /* Truncated data */ 115780fb4a2SCy Schubert tls_process_status_request_item(conn, pos, len); 116780fb4a2SCy Schubert pos += len; 117780fb4a2SCy Schubert } 118780fb4a2SCy Schubert } 119780fb4a2SCy Schubert 120780fb4a2SCy Schubert 12139beb93cSSam Leffler static int tls_process_client_hello(struct tlsv1_server *conn, u8 ct, 12239beb93cSSam Leffler const u8 *in_data, size_t *in_len) 12339beb93cSSam Leffler { 12439beb93cSSam Leffler const u8 *pos, *end, *c; 12539beb93cSSam Leffler size_t left, len, i, j; 12639beb93cSSam Leffler u16 cipher_suite; 12739beb93cSSam Leffler u16 num_suites; 12839beb93cSSam Leffler int compr_null_found; 1293157ba21SRui Paulo u16 ext_type, ext_len; 13039beb93cSSam Leffler 13139beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 1325b9c547cSRui Paulo tlsv1_server_log(conn, "Expected Handshake; received content type 0x%x", 1335b9c547cSRui Paulo ct); 13439beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 13539beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 13639beb93cSSam Leffler return -1; 13739beb93cSSam Leffler } 13839beb93cSSam Leffler 13939beb93cSSam Leffler pos = in_data; 14039beb93cSSam Leffler left = *in_len; 14139beb93cSSam Leffler 142*4bc52338SCy Schubert if (left < 4) { 143*4bc52338SCy Schubert tlsv1_server_log(conn, 144*4bc52338SCy Schubert "Truncated handshake message (expected ClientHello)"); 14539beb93cSSam Leffler goto decode_error; 146*4bc52338SCy Schubert } 14739beb93cSSam Leffler 14839beb93cSSam Leffler /* HandshakeType msg_type */ 14939beb93cSSam Leffler if (*pos != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) { 1505b9c547cSRui Paulo tlsv1_server_log(conn, "Received unexpected handshake message %d (expected ClientHello)", 1515b9c547cSRui Paulo *pos); 15239beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 15339beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 15439beb93cSSam Leffler return -1; 15539beb93cSSam Leffler } 1565b9c547cSRui Paulo tlsv1_server_log(conn, "Received ClientHello"); 15739beb93cSSam Leffler pos++; 15839beb93cSSam Leffler /* uint24 length */ 15939beb93cSSam Leffler len = WPA_GET_BE24(pos); 16039beb93cSSam Leffler pos += 3; 16139beb93cSSam Leffler left -= 4; 16239beb93cSSam Leffler 163*4bc52338SCy Schubert if (len > left) { 164*4bc52338SCy Schubert tlsv1_server_log(conn, 165*4bc52338SCy Schubert "Truncated ClientHello (len=%d left=%d)", 166*4bc52338SCy Schubert (int) len, (int) left); 16739beb93cSSam Leffler goto decode_error; 168*4bc52338SCy Schubert } 16939beb93cSSam Leffler 17039beb93cSSam Leffler /* body - ClientHello */ 17139beb93cSSam Leffler 17239beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello", pos, len); 17339beb93cSSam Leffler end = pos + len; 17439beb93cSSam Leffler 17539beb93cSSam Leffler /* ProtocolVersion client_version */ 176*4bc52338SCy Schubert if (end - pos < 2) { 177*4bc52338SCy Schubert tlsv1_server_log(conn, "Truncated ClientHello/client_version"); 17839beb93cSSam Leffler goto decode_error; 179*4bc52338SCy Schubert } 18039beb93cSSam Leffler conn->client_version = WPA_GET_BE16(pos); 1815b9c547cSRui Paulo tlsv1_server_log(conn, "Client version %d.%d", 1825b9c547cSRui Paulo conn->client_version >> 8, 1835b9c547cSRui Paulo conn->client_version & 0xff); 184f05cddf9SRui Paulo if (conn->client_version < TLS_VERSION_1) { 1855b9c547cSRui Paulo tlsv1_server_log(conn, "Unexpected protocol version in ClientHello %u.%u", 186f05cddf9SRui Paulo conn->client_version >> 8, 187f05cddf9SRui Paulo conn->client_version & 0xff); 18839beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 18939beb93cSSam Leffler TLS_ALERT_PROTOCOL_VERSION); 19039beb93cSSam Leffler return -1; 19139beb93cSSam Leffler } 19239beb93cSSam Leffler pos += 2; 19339beb93cSSam Leffler 194f05cddf9SRui Paulo if (TLS_VERSION == TLS_VERSION_1) 195f05cddf9SRui Paulo conn->rl.tls_version = TLS_VERSION_1; 196f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 197f05cddf9SRui Paulo else if (conn->client_version >= TLS_VERSION_1_2) 198f05cddf9SRui Paulo conn->rl.tls_version = TLS_VERSION_1_2; 199f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 200f05cddf9SRui Paulo else if (conn->client_version > TLS_VERSION_1_1) 201f05cddf9SRui Paulo conn->rl.tls_version = TLS_VERSION_1_1; 202f05cddf9SRui Paulo else 203f05cddf9SRui Paulo conn->rl.tls_version = conn->client_version; 2045b9c547cSRui Paulo tlsv1_server_log(conn, "Using TLS v%s", 205f05cddf9SRui Paulo tls_version_str(conn->rl.tls_version)); 206f05cddf9SRui Paulo 20739beb93cSSam Leffler /* Random random */ 208*4bc52338SCy Schubert if (end - pos < TLS_RANDOM_LEN) { 209*4bc52338SCy Schubert tlsv1_server_log(conn, "Truncated ClientHello/client_random"); 21039beb93cSSam Leffler goto decode_error; 211*4bc52338SCy Schubert } 21239beb93cSSam Leffler 21339beb93cSSam Leffler os_memcpy(conn->client_random, pos, TLS_RANDOM_LEN); 21439beb93cSSam Leffler pos += TLS_RANDOM_LEN; 21539beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random", 21639beb93cSSam Leffler conn->client_random, TLS_RANDOM_LEN); 21739beb93cSSam Leffler 21839beb93cSSam Leffler /* SessionID session_id */ 219*4bc52338SCy Schubert if (end - pos < 1) { 220*4bc52338SCy Schubert tlsv1_server_log(conn, "Truncated ClientHello/session_id len"); 22139beb93cSSam Leffler goto decode_error; 222*4bc52338SCy Schubert } 223*4bc52338SCy Schubert if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN) { 224*4bc52338SCy Schubert tlsv1_server_log(conn, "Truncated ClientHello/session_id"); 22539beb93cSSam Leffler goto decode_error; 226*4bc52338SCy Schubert } 22739beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: client session_id", pos + 1, *pos); 22839beb93cSSam Leffler pos += 1 + *pos; 22939beb93cSSam Leffler /* TODO: add support for session resumption */ 23039beb93cSSam Leffler 23139beb93cSSam Leffler /* CipherSuite cipher_suites<2..2^16-1> */ 232*4bc52338SCy Schubert if (end - pos < 2) { 233*4bc52338SCy Schubert tlsv1_server_log(conn, 234*4bc52338SCy Schubert "Truncated ClientHello/cipher_suites len"); 23539beb93cSSam Leffler goto decode_error; 236*4bc52338SCy Schubert } 23739beb93cSSam Leffler num_suites = WPA_GET_BE16(pos); 23839beb93cSSam Leffler pos += 2; 239*4bc52338SCy Schubert if (end - pos < num_suites) { 240*4bc52338SCy Schubert tlsv1_server_log(conn, "Truncated ClientHello/cipher_suites"); 24139beb93cSSam Leffler goto decode_error; 242*4bc52338SCy Schubert } 24339beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: client cipher suites", 24439beb93cSSam Leffler pos, num_suites); 245*4bc52338SCy Schubert if (num_suites & 1) { 246*4bc52338SCy Schubert tlsv1_server_log(conn, "Odd len ClientHello/cipher_suites"); 24739beb93cSSam Leffler goto decode_error; 248*4bc52338SCy Schubert } 24939beb93cSSam Leffler num_suites /= 2; 25039beb93cSSam Leffler 25139beb93cSSam Leffler cipher_suite = 0; 25239beb93cSSam Leffler for (i = 0; !cipher_suite && i < conn->num_cipher_suites; i++) { 2535b9c547cSRui Paulo if (testing_cipher_suite_filter(conn, conn->cipher_suites[i])) 2545b9c547cSRui Paulo continue; 25539beb93cSSam Leffler c = pos; 25639beb93cSSam Leffler for (j = 0; j < num_suites; j++) { 25739beb93cSSam Leffler u16 tmp = WPA_GET_BE16(c); 25839beb93cSSam Leffler c += 2; 25939beb93cSSam Leffler if (!cipher_suite && tmp == conn->cipher_suites[i]) { 26039beb93cSSam Leffler cipher_suite = tmp; 26139beb93cSSam Leffler break; 26239beb93cSSam Leffler } 26339beb93cSSam Leffler } 26439beb93cSSam Leffler } 26539beb93cSSam Leffler pos += num_suites * 2; 26639beb93cSSam Leffler if (!cipher_suite) { 2675b9c547cSRui Paulo tlsv1_server_log(conn, "No supported cipher suite available"); 26839beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 26939beb93cSSam Leffler TLS_ALERT_ILLEGAL_PARAMETER); 27039beb93cSSam Leffler return -1; 27139beb93cSSam Leffler } 27239beb93cSSam Leffler 27339beb93cSSam Leffler if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) { 27439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for " 27539beb93cSSam Leffler "record layer"); 27639beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 27739beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 27839beb93cSSam Leffler return -1; 27939beb93cSSam Leffler } 28039beb93cSSam Leffler 28139beb93cSSam Leffler conn->cipher_suite = cipher_suite; 28239beb93cSSam Leffler 28339beb93cSSam Leffler /* CompressionMethod compression_methods<1..2^8-1> */ 284*4bc52338SCy Schubert if (end - pos < 1) { 285*4bc52338SCy Schubert tlsv1_server_log(conn, 286*4bc52338SCy Schubert "Truncated ClientHello/compression_methods len"); 28739beb93cSSam Leffler goto decode_error; 288*4bc52338SCy Schubert } 28939beb93cSSam Leffler num_suites = *pos++; 290*4bc52338SCy Schubert if (end - pos < num_suites) { 291*4bc52338SCy Schubert tlsv1_server_log(conn, 292*4bc52338SCy Schubert "Truncated ClientHello/compression_methods"); 29339beb93cSSam Leffler goto decode_error; 294*4bc52338SCy Schubert } 29539beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: client compression_methods", 29639beb93cSSam Leffler pos, num_suites); 29739beb93cSSam Leffler compr_null_found = 0; 29839beb93cSSam Leffler for (i = 0; i < num_suites; i++) { 29939beb93cSSam Leffler if (*pos++ == TLS_COMPRESSION_NULL) 30039beb93cSSam Leffler compr_null_found = 1; 30139beb93cSSam Leffler } 30239beb93cSSam Leffler if (!compr_null_found) { 3035b9c547cSRui Paulo tlsv1_server_log(conn, "Client does not accept NULL compression"); 30439beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 30539beb93cSSam Leffler TLS_ALERT_ILLEGAL_PARAMETER); 30639beb93cSSam Leffler return -1; 30739beb93cSSam Leffler } 30839beb93cSSam Leffler 30939beb93cSSam Leffler if (end - pos == 1) { 3105b9c547cSRui Paulo tlsv1_server_log(conn, "Unexpected extra octet in the end of ClientHello: 0x%02x", 3115b9c547cSRui Paulo *pos); 31239beb93cSSam Leffler goto decode_error; 31339beb93cSSam Leffler } 31439beb93cSSam Leffler 31539beb93cSSam Leffler if (end - pos >= 2) { 31639beb93cSSam Leffler /* Extension client_hello_extension_list<0..2^16-1> */ 31739beb93cSSam Leffler ext_len = WPA_GET_BE16(pos); 31839beb93cSSam Leffler pos += 2; 31939beb93cSSam Leffler 3205b9c547cSRui Paulo tlsv1_server_log(conn, "%u bytes of ClientHello extensions", 3215b9c547cSRui Paulo ext_len); 32239beb93cSSam Leffler if (end - pos != ext_len) { 3235b9c547cSRui Paulo tlsv1_server_log(conn, "Invalid ClientHello extension list length %u (expected %u)", 3243157ba21SRui Paulo ext_len, (unsigned int) (end - pos)); 32539beb93cSSam Leffler goto decode_error; 32639beb93cSSam Leffler } 32739beb93cSSam Leffler 32839beb93cSSam Leffler /* 32939beb93cSSam Leffler * struct { 33039beb93cSSam Leffler * ExtensionType extension_type (0..65535) 33139beb93cSSam Leffler * opaque extension_data<0..2^16-1> 33239beb93cSSam Leffler * } Extension; 33339beb93cSSam Leffler */ 33439beb93cSSam Leffler 33539beb93cSSam Leffler while (pos < end) { 33639beb93cSSam Leffler if (end - pos < 2) { 3375b9c547cSRui Paulo tlsv1_server_log(conn, "Invalid extension_type field"); 33839beb93cSSam Leffler goto decode_error; 33939beb93cSSam Leffler } 34039beb93cSSam Leffler 34139beb93cSSam Leffler ext_type = WPA_GET_BE16(pos); 34239beb93cSSam Leffler pos += 2; 34339beb93cSSam Leffler 34439beb93cSSam Leffler if (end - pos < 2) { 3455b9c547cSRui Paulo tlsv1_server_log(conn, "Invalid extension_data length field"); 34639beb93cSSam Leffler goto decode_error; 34739beb93cSSam Leffler } 34839beb93cSSam Leffler 34939beb93cSSam Leffler ext_len = WPA_GET_BE16(pos); 35039beb93cSSam Leffler pos += 2; 35139beb93cSSam Leffler 35239beb93cSSam Leffler if (end - pos < ext_len) { 3535b9c547cSRui Paulo tlsv1_server_log(conn, "Invalid extension_data field"); 35439beb93cSSam Leffler goto decode_error; 35539beb93cSSam Leffler } 35639beb93cSSam Leffler 3575b9c547cSRui Paulo tlsv1_server_log(conn, "ClientHello Extension type %u", 3585b9c547cSRui Paulo ext_type); 35939beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello " 36039beb93cSSam Leffler "Extension data", pos, ext_len); 36139beb93cSSam Leffler 36239beb93cSSam Leffler if (ext_type == TLS_EXT_SESSION_TICKET) { 36339beb93cSSam Leffler os_free(conn->session_ticket); 36439beb93cSSam Leffler conn->session_ticket = os_malloc(ext_len); 36539beb93cSSam Leffler if (conn->session_ticket) { 36639beb93cSSam Leffler os_memcpy(conn->session_ticket, pos, 36739beb93cSSam Leffler ext_len); 36839beb93cSSam Leffler conn->session_ticket_len = ext_len; 36939beb93cSSam Leffler } 370780fb4a2SCy Schubert } else if (ext_type == TLS_EXT_STATUS_REQUEST) { 371780fb4a2SCy Schubert conn->status_request = 1; 372780fb4a2SCy Schubert } else if (ext_type == TLS_EXT_STATUS_REQUEST_V2) { 373780fb4a2SCy Schubert tls_process_status_request_v2(conn, pos, 374780fb4a2SCy Schubert ext_len); 37539beb93cSSam Leffler } 37639beb93cSSam Leffler 37739beb93cSSam Leffler pos += ext_len; 37839beb93cSSam Leffler } 37939beb93cSSam Leffler } 38039beb93cSSam Leffler 38139beb93cSSam Leffler *in_len = end - in_data; 38239beb93cSSam Leffler 3835b9c547cSRui Paulo tlsv1_server_log(conn, "ClientHello OK - proceed to ServerHello"); 38439beb93cSSam Leffler conn->state = SERVER_HELLO; 38539beb93cSSam Leffler 38639beb93cSSam Leffler return 0; 38739beb93cSSam Leffler 38839beb93cSSam Leffler decode_error: 3895b9c547cSRui Paulo tlsv1_server_log(conn, "Failed to decode ClientHello"); 39039beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 39139beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 39239beb93cSSam Leffler return -1; 39339beb93cSSam Leffler } 39439beb93cSSam Leffler 39539beb93cSSam Leffler 39639beb93cSSam Leffler static int tls_process_certificate(struct tlsv1_server *conn, u8 ct, 39739beb93cSSam Leffler const u8 *in_data, size_t *in_len) 39839beb93cSSam Leffler { 39939beb93cSSam Leffler const u8 *pos, *end; 40039beb93cSSam Leffler size_t left, len, list_len, cert_len, idx; 40139beb93cSSam Leffler u8 type; 40239beb93cSSam Leffler struct x509_certificate *chain = NULL, *last = NULL, *cert; 40339beb93cSSam Leffler int reason; 40439beb93cSSam Leffler 40539beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 4065b9c547cSRui Paulo tlsv1_server_log(conn, "Expected Handshake; received content type 0x%x", 4075b9c547cSRui Paulo ct); 40839beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 40939beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 41039beb93cSSam Leffler return -1; 41139beb93cSSam Leffler } 41239beb93cSSam Leffler 41339beb93cSSam Leffler pos = in_data; 41439beb93cSSam Leffler left = *in_len; 41539beb93cSSam Leffler 41639beb93cSSam Leffler if (left < 4) { 4175b9c547cSRui Paulo tlsv1_server_log(conn, "Too short Certificate message (len=%lu)", 4185b9c547cSRui Paulo (unsigned long) left); 41939beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 42039beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 42139beb93cSSam Leffler return -1; 42239beb93cSSam Leffler } 42339beb93cSSam Leffler 42439beb93cSSam Leffler type = *pos++; 42539beb93cSSam Leffler len = WPA_GET_BE24(pos); 42639beb93cSSam Leffler pos += 3; 42739beb93cSSam Leffler left -= 4; 42839beb93cSSam Leffler 42939beb93cSSam Leffler if (len > left) { 4305b9c547cSRui Paulo tlsv1_server_log(conn, "Unexpected Certificate message length (len=%lu != left=%lu)", 43139beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 43239beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 43339beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 43439beb93cSSam Leffler return -1; 43539beb93cSSam Leffler } 43639beb93cSSam Leffler 43739beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) { 43839beb93cSSam Leffler if (conn->verify_peer) { 4395b9c547cSRui Paulo tlsv1_server_log(conn, "Client did not include Certificate"); 44039beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 44139beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 44239beb93cSSam Leffler return -1; 44339beb93cSSam Leffler } 44439beb93cSSam Leffler 44539beb93cSSam Leffler return tls_process_client_key_exchange(conn, ct, in_data, 44639beb93cSSam Leffler in_len); 44739beb93cSSam Leffler } 44839beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) { 4495b9c547cSRui Paulo tlsv1_server_log(conn, "Received unexpected handshake message %d (expected Certificate/ClientKeyExchange)", 4505b9c547cSRui Paulo type); 45139beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 45239beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 45339beb93cSSam Leffler return -1; 45439beb93cSSam Leffler } 45539beb93cSSam Leffler 4565b9c547cSRui Paulo tlsv1_server_log(conn, "Received Certificate (certificate_list len %lu)", 45739beb93cSSam Leffler (unsigned long) len); 45839beb93cSSam Leffler 45939beb93cSSam Leffler /* 46039beb93cSSam Leffler * opaque ASN.1Cert<2^24-1>; 46139beb93cSSam Leffler * 46239beb93cSSam Leffler * struct { 46339beb93cSSam Leffler * ASN.1Cert certificate_list<1..2^24-1>; 46439beb93cSSam Leffler * } Certificate; 46539beb93cSSam Leffler */ 46639beb93cSSam Leffler 46739beb93cSSam Leffler end = pos + len; 46839beb93cSSam Leffler 46939beb93cSSam Leffler if (end - pos < 3) { 4705b9c547cSRui Paulo tlsv1_server_log(conn, "Too short Certificate (left=%lu)", 4715b9c547cSRui Paulo (unsigned long) left); 47239beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 47339beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 47439beb93cSSam Leffler return -1; 47539beb93cSSam Leffler } 47639beb93cSSam Leffler 47739beb93cSSam Leffler list_len = WPA_GET_BE24(pos); 47839beb93cSSam Leffler pos += 3; 47939beb93cSSam Leffler 48039beb93cSSam Leffler if ((size_t) (end - pos) != list_len) { 4815b9c547cSRui Paulo tlsv1_server_log(conn, "Unexpected certificate_list length (len=%lu left=%lu)", 48239beb93cSSam Leffler (unsigned long) list_len, 48339beb93cSSam Leffler (unsigned long) (end - pos)); 48439beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 48539beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 48639beb93cSSam Leffler return -1; 48739beb93cSSam Leffler } 48839beb93cSSam Leffler 48939beb93cSSam Leffler idx = 0; 49039beb93cSSam Leffler while (pos < end) { 49139beb93cSSam Leffler if (end - pos < 3) { 4925b9c547cSRui Paulo tlsv1_server_log(conn, "Failed to parse certificate_list"); 49339beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 49439beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 49539beb93cSSam Leffler x509_certificate_chain_free(chain); 49639beb93cSSam Leffler return -1; 49739beb93cSSam Leffler } 49839beb93cSSam Leffler 49939beb93cSSam Leffler cert_len = WPA_GET_BE24(pos); 50039beb93cSSam Leffler pos += 3; 50139beb93cSSam Leffler 50239beb93cSSam Leffler if ((size_t) (end - pos) < cert_len) { 5035b9c547cSRui Paulo tlsv1_server_log(conn, "Unexpected certificate length (len=%lu left=%lu)", 50439beb93cSSam Leffler (unsigned long) cert_len, 50539beb93cSSam Leffler (unsigned long) (end - pos)); 50639beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 50739beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 50839beb93cSSam Leffler x509_certificate_chain_free(chain); 50939beb93cSSam Leffler return -1; 51039beb93cSSam Leffler } 51139beb93cSSam Leffler 5125b9c547cSRui Paulo tlsv1_server_log(conn, "Certificate %lu (len %lu)", 51339beb93cSSam Leffler (unsigned long) idx, (unsigned long) cert_len); 51439beb93cSSam Leffler 51539beb93cSSam Leffler if (idx == 0) { 51639beb93cSSam Leffler crypto_public_key_free(conn->client_rsa_key); 51739beb93cSSam Leffler if (tls_parse_cert(pos, cert_len, 51839beb93cSSam Leffler &conn->client_rsa_key)) { 5195b9c547cSRui Paulo tlsv1_server_log(conn, "Failed to parse the certificate"); 52039beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 52139beb93cSSam Leffler TLS_ALERT_BAD_CERTIFICATE); 52239beb93cSSam Leffler x509_certificate_chain_free(chain); 52339beb93cSSam Leffler return -1; 52439beb93cSSam Leffler } 52539beb93cSSam Leffler } 52639beb93cSSam Leffler 52739beb93cSSam Leffler cert = x509_certificate_parse(pos, cert_len); 52839beb93cSSam Leffler if (cert == NULL) { 5295b9c547cSRui Paulo tlsv1_server_log(conn, "Failed to parse the certificate"); 53039beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 53139beb93cSSam Leffler TLS_ALERT_BAD_CERTIFICATE); 53239beb93cSSam Leffler x509_certificate_chain_free(chain); 53339beb93cSSam Leffler return -1; 53439beb93cSSam Leffler } 53539beb93cSSam Leffler 53639beb93cSSam Leffler if (last == NULL) 53739beb93cSSam Leffler chain = cert; 53839beb93cSSam Leffler else 53939beb93cSSam Leffler last->next = cert; 54039beb93cSSam Leffler last = cert; 54139beb93cSSam Leffler 54239beb93cSSam Leffler idx++; 54339beb93cSSam Leffler pos += cert_len; 54439beb93cSSam Leffler } 54539beb93cSSam Leffler 54639beb93cSSam Leffler if (x509_certificate_chain_validate(conn->cred->trusted_certs, chain, 547f05cddf9SRui Paulo &reason, 0) < 0) { 54839beb93cSSam Leffler int tls_reason; 5495b9c547cSRui Paulo tlsv1_server_log(conn, "Server certificate chain validation failed (reason=%d)", 5505b9c547cSRui Paulo reason); 55139beb93cSSam Leffler switch (reason) { 55239beb93cSSam Leffler case X509_VALIDATE_BAD_CERTIFICATE: 55339beb93cSSam Leffler tls_reason = TLS_ALERT_BAD_CERTIFICATE; 55439beb93cSSam Leffler break; 55539beb93cSSam Leffler case X509_VALIDATE_UNSUPPORTED_CERTIFICATE: 55639beb93cSSam Leffler tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE; 55739beb93cSSam Leffler break; 55839beb93cSSam Leffler case X509_VALIDATE_CERTIFICATE_REVOKED: 55939beb93cSSam Leffler tls_reason = TLS_ALERT_CERTIFICATE_REVOKED; 56039beb93cSSam Leffler break; 56139beb93cSSam Leffler case X509_VALIDATE_CERTIFICATE_EXPIRED: 56239beb93cSSam Leffler tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED; 56339beb93cSSam Leffler break; 56439beb93cSSam Leffler case X509_VALIDATE_CERTIFICATE_UNKNOWN: 56539beb93cSSam Leffler tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN; 56639beb93cSSam Leffler break; 56739beb93cSSam Leffler case X509_VALIDATE_UNKNOWN_CA: 56839beb93cSSam Leffler tls_reason = TLS_ALERT_UNKNOWN_CA; 56939beb93cSSam Leffler break; 57039beb93cSSam Leffler default: 57139beb93cSSam Leffler tls_reason = TLS_ALERT_BAD_CERTIFICATE; 57239beb93cSSam Leffler break; 57339beb93cSSam Leffler } 57439beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason); 57539beb93cSSam Leffler x509_certificate_chain_free(chain); 57639beb93cSSam Leffler return -1; 57739beb93cSSam Leffler } 57839beb93cSSam Leffler 579780fb4a2SCy Schubert if (chain && (chain->extensions_present & X509_EXT_EXT_KEY_USAGE) && 580780fb4a2SCy Schubert !(chain->ext_key_usage & 581780fb4a2SCy Schubert (X509_EXT_KEY_USAGE_ANY | X509_EXT_KEY_USAGE_CLIENT_AUTH))) { 582780fb4a2SCy Schubert tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 583780fb4a2SCy Schubert TLS_ALERT_BAD_CERTIFICATE); 584780fb4a2SCy Schubert x509_certificate_chain_free(chain); 585780fb4a2SCy Schubert return -1; 586780fb4a2SCy Schubert } 587780fb4a2SCy Schubert 58839beb93cSSam Leffler x509_certificate_chain_free(chain); 58939beb93cSSam Leffler 59039beb93cSSam Leffler *in_len = end - in_data; 59139beb93cSSam Leffler 59239beb93cSSam Leffler conn->state = CLIENT_KEY_EXCHANGE; 59339beb93cSSam Leffler 59439beb93cSSam Leffler return 0; 59539beb93cSSam Leffler } 59639beb93cSSam Leffler 59739beb93cSSam Leffler 59839beb93cSSam Leffler static int tls_process_client_key_exchange_rsa( 59939beb93cSSam Leffler struct tlsv1_server *conn, const u8 *pos, const u8 *end) 60039beb93cSSam Leffler { 60139beb93cSSam Leffler u8 *out; 60239beb93cSSam Leffler size_t outlen, outbuflen; 60339beb93cSSam Leffler u16 encr_len; 60439beb93cSSam Leffler int res; 60539beb93cSSam Leffler int use_random = 0; 60639beb93cSSam Leffler 60739beb93cSSam Leffler if (end - pos < 2) { 60839beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 60939beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 61039beb93cSSam Leffler return -1; 61139beb93cSSam Leffler } 61239beb93cSSam Leffler 61339beb93cSSam Leffler encr_len = WPA_GET_BE16(pos); 61439beb93cSSam Leffler pos += 2; 615f05cddf9SRui Paulo if (pos + encr_len > end) { 6165b9c547cSRui Paulo tlsv1_server_log(conn, "Invalid ClientKeyExchange format: encr_len=%u left=%u", 617f05cddf9SRui Paulo encr_len, (unsigned int) (end - pos)); 618f05cddf9SRui Paulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 619f05cddf9SRui Paulo TLS_ALERT_DECODE_ERROR); 620f05cddf9SRui Paulo return -1; 621f05cddf9SRui Paulo } 62239beb93cSSam Leffler 62339beb93cSSam Leffler outbuflen = outlen = end - pos; 62439beb93cSSam Leffler out = os_malloc(outlen >= TLS_PRE_MASTER_SECRET_LEN ? 62539beb93cSSam Leffler outlen : TLS_PRE_MASTER_SECRET_LEN); 62639beb93cSSam Leffler if (out == NULL) { 62739beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 62839beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 62939beb93cSSam Leffler return -1; 63039beb93cSSam Leffler } 63139beb93cSSam Leffler 63239beb93cSSam Leffler /* 63339beb93cSSam Leffler * struct { 63439beb93cSSam Leffler * ProtocolVersion client_version; 63539beb93cSSam Leffler * opaque random[46]; 63639beb93cSSam Leffler * } PreMasterSecret; 63739beb93cSSam Leffler * 63839beb93cSSam Leffler * struct { 63939beb93cSSam Leffler * public-key-encrypted PreMasterSecret pre_master_secret; 64039beb93cSSam Leffler * } EncryptedPreMasterSecret; 64139beb93cSSam Leffler */ 64239beb93cSSam Leffler 64339beb93cSSam Leffler /* 64439beb93cSSam Leffler * Note: To avoid Bleichenbacher attack, we do not report decryption or 64539beb93cSSam Leffler * parsing errors from EncryptedPreMasterSecret processing to the 64639beb93cSSam Leffler * client. Instead, a random pre-master secret is used to force the 64739beb93cSSam Leffler * handshake to fail. 64839beb93cSSam Leffler */ 64939beb93cSSam Leffler 65039beb93cSSam Leffler if (crypto_private_key_decrypt_pkcs1_v15(conn->cred->key, 651f05cddf9SRui Paulo pos, encr_len, 65239beb93cSSam Leffler out, &outlen) < 0) { 65339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt " 654f05cddf9SRui Paulo "PreMasterSecret (encr_len=%u outlen=%lu)", 655f05cddf9SRui Paulo encr_len, (unsigned long) outlen); 65639beb93cSSam Leffler use_random = 1; 65739beb93cSSam Leffler } 65839beb93cSSam Leffler 659f05cddf9SRui Paulo if (!use_random && outlen != TLS_PRE_MASTER_SECRET_LEN) { 6605b9c547cSRui Paulo tlsv1_server_log(conn, "Unexpected PreMasterSecret length %lu", 6615b9c547cSRui Paulo (unsigned long) outlen); 66239beb93cSSam Leffler use_random = 1; 66339beb93cSSam Leffler } 66439beb93cSSam Leffler 665f05cddf9SRui Paulo if (!use_random && WPA_GET_BE16(out) != conn->client_version) { 6665b9c547cSRui Paulo tlsv1_server_log(conn, "Client version in ClientKeyExchange does not match with version in ClientHello"); 66739beb93cSSam Leffler use_random = 1; 66839beb93cSSam Leffler } 66939beb93cSSam Leffler 67039beb93cSSam Leffler if (use_random) { 67139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Using random premaster secret " 67239beb93cSSam Leffler "to avoid revealing information about private key"); 67339beb93cSSam Leffler outlen = TLS_PRE_MASTER_SECRET_LEN; 67439beb93cSSam Leffler if (os_get_random(out, outlen)) { 67539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " 67639beb93cSSam Leffler "data"); 67739beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 67839beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 67939beb93cSSam Leffler os_free(out); 68039beb93cSSam Leffler return -1; 68139beb93cSSam Leffler } 68239beb93cSSam Leffler } 68339beb93cSSam Leffler 68439beb93cSSam Leffler res = tlsv1_server_derive_keys(conn, out, outlen); 68539beb93cSSam Leffler 68639beb93cSSam Leffler /* Clear the pre-master secret since it is not needed anymore */ 68739beb93cSSam Leffler os_memset(out, 0, outbuflen); 68839beb93cSSam Leffler os_free(out); 68939beb93cSSam Leffler 69039beb93cSSam Leffler if (res) { 69139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); 69239beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 69339beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 69439beb93cSSam Leffler return -1; 69539beb93cSSam Leffler } 69639beb93cSSam Leffler 69739beb93cSSam Leffler return 0; 69839beb93cSSam Leffler } 69939beb93cSSam Leffler 70039beb93cSSam Leffler 7015b9c547cSRui Paulo static int tls_process_client_key_exchange_dh( 70239beb93cSSam Leffler struct tlsv1_server *conn, const u8 *pos, const u8 *end) 70339beb93cSSam Leffler { 70439beb93cSSam Leffler const u8 *dh_yc; 70539beb93cSSam Leffler u16 dh_yc_len; 70639beb93cSSam Leffler u8 *shared; 70739beb93cSSam Leffler size_t shared_len; 70839beb93cSSam Leffler int res; 7095b9c547cSRui Paulo const u8 *dh_p; 7105b9c547cSRui Paulo size_t dh_p_len; 71139beb93cSSam Leffler 71239beb93cSSam Leffler /* 71339beb93cSSam Leffler * struct { 71439beb93cSSam Leffler * select (PublicValueEncoding) { 71539beb93cSSam Leffler * case implicit: struct { }; 71639beb93cSSam Leffler * case explicit: opaque dh_Yc<1..2^16-1>; 71739beb93cSSam Leffler * } dh_public; 71839beb93cSSam Leffler * } ClientDiffieHellmanPublic; 71939beb93cSSam Leffler */ 72039beb93cSSam Leffler 7215b9c547cSRui Paulo tlsv1_server_log(conn, "ClientDiffieHellmanPublic received"); 72239beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientDiffieHellmanPublic", 72339beb93cSSam Leffler pos, end - pos); 72439beb93cSSam Leffler 72539beb93cSSam Leffler if (end == pos) { 72639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Implicit public value encoding " 72739beb93cSSam Leffler "not supported"); 72839beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 72939beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 73039beb93cSSam Leffler return -1; 73139beb93cSSam Leffler } 73239beb93cSSam Leffler 73339beb93cSSam Leffler if (end - pos < 3) { 7345b9c547cSRui Paulo tlsv1_server_log(conn, "Invalid client public value length"); 73539beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 73639beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 73739beb93cSSam Leffler return -1; 73839beb93cSSam Leffler } 73939beb93cSSam Leffler 74039beb93cSSam Leffler dh_yc_len = WPA_GET_BE16(pos); 74139beb93cSSam Leffler dh_yc = pos + 2; 74239beb93cSSam Leffler 7435b9c547cSRui Paulo if (dh_yc_len > end - dh_yc) { 7445b9c547cSRui Paulo tlsv1_server_log(conn, "Client public value overflow (length %d)", 7455b9c547cSRui Paulo dh_yc_len); 74639beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 74739beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 74839beb93cSSam Leffler return -1; 74939beb93cSSam Leffler } 75039beb93cSSam Leffler 75139beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)", 75239beb93cSSam Leffler dh_yc, dh_yc_len); 75339beb93cSSam Leffler 75439beb93cSSam Leffler if (conn->cred == NULL || conn->cred->dh_p == NULL || 75539beb93cSSam Leffler conn->dh_secret == NULL) { 75639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available"); 75739beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 75839beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 75939beb93cSSam Leffler return -1; 76039beb93cSSam Leffler } 76139beb93cSSam Leffler 7625b9c547cSRui Paulo tlsv1_server_get_dh_p(conn, &dh_p, &dh_p_len); 7635b9c547cSRui Paulo 7645b9c547cSRui Paulo shared_len = dh_p_len; 76539beb93cSSam Leffler shared = os_malloc(shared_len); 76639beb93cSSam Leffler if (shared == NULL) { 76739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for " 76839beb93cSSam Leffler "DH"); 76939beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 77039beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 77139beb93cSSam Leffler return -1; 77239beb93cSSam Leffler } 77339beb93cSSam Leffler 77439beb93cSSam Leffler /* shared = Yc^secret mod p */ 77539beb93cSSam Leffler if (crypto_mod_exp(dh_yc, dh_yc_len, conn->dh_secret, 7765b9c547cSRui Paulo conn->dh_secret_len, dh_p, dh_p_len, 77739beb93cSSam Leffler shared, &shared_len)) { 77839beb93cSSam Leffler os_free(shared); 77939beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 78039beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 78139beb93cSSam Leffler return -1; 78239beb93cSSam Leffler } 78339beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange", 78439beb93cSSam Leffler shared, shared_len); 78539beb93cSSam Leffler 78639beb93cSSam Leffler os_memset(conn->dh_secret, 0, conn->dh_secret_len); 78739beb93cSSam Leffler os_free(conn->dh_secret); 78839beb93cSSam Leffler conn->dh_secret = NULL; 78939beb93cSSam Leffler 79039beb93cSSam Leffler res = tlsv1_server_derive_keys(conn, shared, shared_len); 79139beb93cSSam Leffler 79239beb93cSSam Leffler /* Clear the pre-master secret since it is not needed anymore */ 79339beb93cSSam Leffler os_memset(shared, 0, shared_len); 79439beb93cSSam Leffler os_free(shared); 79539beb93cSSam Leffler 79639beb93cSSam Leffler if (res) { 79739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); 79839beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 79939beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 80039beb93cSSam Leffler return -1; 80139beb93cSSam Leffler } 80239beb93cSSam Leffler 80339beb93cSSam Leffler return 0; 80439beb93cSSam Leffler } 80539beb93cSSam Leffler 80639beb93cSSam Leffler 80739beb93cSSam Leffler static int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct, 80839beb93cSSam Leffler const u8 *in_data, size_t *in_len) 80939beb93cSSam Leffler { 81039beb93cSSam Leffler const u8 *pos, *end; 81139beb93cSSam Leffler size_t left, len; 81239beb93cSSam Leffler u8 type; 81339beb93cSSam Leffler tls_key_exchange keyx; 81439beb93cSSam Leffler const struct tls_cipher_suite *suite; 81539beb93cSSam Leffler 81639beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 8175b9c547cSRui Paulo tlsv1_server_log(conn, "Expected Handshake; received content type 0x%x", 8185b9c547cSRui Paulo ct); 81939beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 82039beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 82139beb93cSSam Leffler return -1; 82239beb93cSSam Leffler } 82339beb93cSSam Leffler 82439beb93cSSam Leffler pos = in_data; 82539beb93cSSam Leffler left = *in_len; 82639beb93cSSam Leffler 82739beb93cSSam Leffler if (left < 4) { 8285b9c547cSRui Paulo tlsv1_server_log(conn, "Too short ClientKeyExchange (Left=%lu)", 8295b9c547cSRui Paulo (unsigned long) left); 83039beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 83139beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 83239beb93cSSam Leffler return -1; 83339beb93cSSam Leffler } 83439beb93cSSam Leffler 83539beb93cSSam Leffler type = *pos++; 83639beb93cSSam Leffler len = WPA_GET_BE24(pos); 83739beb93cSSam Leffler pos += 3; 83839beb93cSSam Leffler left -= 4; 83939beb93cSSam Leffler 84039beb93cSSam Leffler if (len > left) { 8415b9c547cSRui Paulo tlsv1_server_log(conn, "Mismatch in ClientKeyExchange length (len=%lu != left=%lu)", 84239beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 84339beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 84439beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 84539beb93cSSam Leffler return -1; 84639beb93cSSam Leffler } 84739beb93cSSam Leffler 84839beb93cSSam Leffler end = pos + len; 84939beb93cSSam Leffler 85039beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) { 8515b9c547cSRui Paulo tlsv1_server_log(conn, "Received unexpected handshake message %d (expected ClientKeyExchange)", 8525b9c547cSRui Paulo type); 85339beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 85439beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 85539beb93cSSam Leffler return -1; 85639beb93cSSam Leffler } 85739beb93cSSam Leffler 8585b9c547cSRui Paulo tlsv1_server_log(conn, "Received ClientKeyExchange"); 85939beb93cSSam Leffler 86039beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: ClientKeyExchange", pos, len); 86139beb93cSSam Leffler 86239beb93cSSam Leffler suite = tls_get_cipher_suite(conn->rl.cipher_suite); 86339beb93cSSam Leffler if (suite == NULL) 86439beb93cSSam Leffler keyx = TLS_KEY_X_NULL; 86539beb93cSSam Leffler else 86639beb93cSSam Leffler keyx = suite->key_exchange; 86739beb93cSSam Leffler 8685b9c547cSRui Paulo if ((keyx == TLS_KEY_X_DH_anon || keyx == TLS_KEY_X_DHE_RSA) && 8695b9c547cSRui Paulo tls_process_client_key_exchange_dh(conn, pos, end) < 0) 87039beb93cSSam Leffler return -1; 87139beb93cSSam Leffler 8725b9c547cSRui Paulo if (keyx != TLS_KEY_X_DH_anon && keyx != TLS_KEY_X_DHE_RSA && 87339beb93cSSam Leffler tls_process_client_key_exchange_rsa(conn, pos, end) < 0) 87439beb93cSSam Leffler return -1; 87539beb93cSSam Leffler 87639beb93cSSam Leffler *in_len = end - in_data; 87739beb93cSSam Leffler 87839beb93cSSam Leffler conn->state = CERTIFICATE_VERIFY; 87939beb93cSSam Leffler 88039beb93cSSam Leffler return 0; 88139beb93cSSam Leffler } 88239beb93cSSam Leffler 88339beb93cSSam Leffler 88439beb93cSSam Leffler static int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct, 88539beb93cSSam Leffler const u8 *in_data, size_t *in_len) 88639beb93cSSam Leffler { 88739beb93cSSam Leffler const u8 *pos, *end; 88839beb93cSSam Leffler size_t left, len; 88939beb93cSSam Leffler u8 type; 8905b9c547cSRui Paulo size_t hlen; 8915b9c547cSRui Paulo u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos; 8925b9c547cSRui Paulo u8 alert; 89339beb93cSSam Leffler 89439beb93cSSam Leffler if (ct == TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { 89539beb93cSSam Leffler if (conn->verify_peer) { 8965b9c547cSRui Paulo tlsv1_server_log(conn, "Client did not include CertificateVerify"); 89739beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 89839beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 89939beb93cSSam Leffler return -1; 90039beb93cSSam Leffler } 90139beb93cSSam Leffler 90239beb93cSSam Leffler return tls_process_change_cipher_spec(conn, ct, in_data, 90339beb93cSSam Leffler in_len); 90439beb93cSSam Leffler } 90539beb93cSSam Leffler 90639beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 9075b9c547cSRui Paulo tlsv1_server_log(conn, "Expected Handshake; received content type 0x%x", 9085b9c547cSRui Paulo ct); 90939beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 91039beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 91139beb93cSSam Leffler return -1; 91239beb93cSSam Leffler } 91339beb93cSSam Leffler 91439beb93cSSam Leffler pos = in_data; 91539beb93cSSam Leffler left = *in_len; 91639beb93cSSam Leffler 91739beb93cSSam Leffler if (left < 4) { 9185b9c547cSRui Paulo tlsv1_server_log(conn, "Too short CertificateVerify message (len=%lu)", 9195b9c547cSRui Paulo (unsigned long) left); 92039beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 92139beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 92239beb93cSSam Leffler return -1; 92339beb93cSSam Leffler } 92439beb93cSSam Leffler 92539beb93cSSam Leffler type = *pos++; 92639beb93cSSam Leffler len = WPA_GET_BE24(pos); 92739beb93cSSam Leffler pos += 3; 92839beb93cSSam Leffler left -= 4; 92939beb93cSSam Leffler 93039beb93cSSam Leffler if (len > left) { 9315b9c547cSRui Paulo tlsv1_server_log(conn, "Unexpected CertificateVerify message length (len=%lu != left=%lu)", 93239beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 93339beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 93439beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 93539beb93cSSam Leffler return -1; 93639beb93cSSam Leffler } 93739beb93cSSam Leffler 93839beb93cSSam Leffler end = pos + len; 93939beb93cSSam Leffler 94039beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY) { 9415b9c547cSRui Paulo tlsv1_server_log(conn, "Received unexpected handshake message %d (expected CertificateVerify)", 9425b9c547cSRui Paulo type); 94339beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 94439beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 94539beb93cSSam Leffler return -1; 94639beb93cSSam Leffler } 94739beb93cSSam Leffler 9485b9c547cSRui Paulo tlsv1_server_log(conn, "Received CertificateVerify"); 94939beb93cSSam Leffler 95039beb93cSSam Leffler /* 95139beb93cSSam Leffler * struct { 95239beb93cSSam Leffler * Signature signature; 95339beb93cSSam Leffler * } CertificateVerify; 95439beb93cSSam Leffler */ 95539beb93cSSam Leffler 95639beb93cSSam Leffler hpos = hash; 95739beb93cSSam Leffler 958f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 959f05cddf9SRui Paulo if (conn->rl.tls_version == TLS_VERSION_1_2) { 960f05cddf9SRui Paulo /* 961f05cddf9SRui Paulo * RFC 5246, 4.7: 962f05cddf9SRui Paulo * TLS v1.2 adds explicit indication of the used signature and 963f05cddf9SRui Paulo * hash algorithms. 964f05cddf9SRui Paulo * 965f05cddf9SRui Paulo * struct { 966f05cddf9SRui Paulo * HashAlgorithm hash; 967f05cddf9SRui Paulo * SignatureAlgorithm signature; 968f05cddf9SRui Paulo * } SignatureAndHashAlgorithm; 969f05cddf9SRui Paulo */ 970f05cddf9SRui Paulo if (end - pos < 2) { 971f05cddf9SRui Paulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 972f05cddf9SRui Paulo TLS_ALERT_DECODE_ERROR); 973f05cddf9SRui Paulo return -1; 974f05cddf9SRui Paulo } 975f05cddf9SRui Paulo if (pos[0] != TLS_HASH_ALG_SHA256 || 976f05cddf9SRui Paulo pos[1] != TLS_SIGN_ALG_RSA) { 977f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/" 978f05cddf9SRui Paulo "signature(%u) algorithm", 979f05cddf9SRui Paulo pos[0], pos[1]); 980f05cddf9SRui Paulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 981f05cddf9SRui Paulo TLS_ALERT_INTERNAL_ERROR); 982f05cddf9SRui Paulo return -1; 983f05cddf9SRui Paulo } 984f05cddf9SRui Paulo pos += 2; 985f05cddf9SRui Paulo 986f05cddf9SRui Paulo hlen = SHA256_MAC_LEN; 987f05cddf9SRui Paulo if (conn->verify.sha256_cert == NULL || 988f05cddf9SRui Paulo crypto_hash_finish(conn->verify.sha256_cert, hpos, &hlen) < 989f05cddf9SRui Paulo 0) { 990f05cddf9SRui Paulo conn->verify.sha256_cert = NULL; 991f05cddf9SRui Paulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 992f05cddf9SRui Paulo TLS_ALERT_INTERNAL_ERROR); 993f05cddf9SRui Paulo return -1; 994f05cddf9SRui Paulo } 995f05cddf9SRui Paulo conn->verify.sha256_cert = NULL; 996f05cddf9SRui Paulo } else { 997f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 998f05cddf9SRui Paulo 99939beb93cSSam Leffler hlen = MD5_MAC_LEN; 100039beb93cSSam Leffler if (conn->verify.md5_cert == NULL || 10015b9c547cSRui Paulo crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) { 100239beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 100339beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 100439beb93cSSam Leffler conn->verify.md5_cert = NULL; 100539beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL); 100639beb93cSSam Leffler conn->verify.sha1_cert = NULL; 100739beb93cSSam Leffler return -1; 100839beb93cSSam Leffler } 100939beb93cSSam Leffler hpos += MD5_MAC_LEN; 101039beb93cSSam Leffler 101139beb93cSSam Leffler conn->verify.md5_cert = NULL; 101239beb93cSSam Leffler hlen = SHA1_MAC_LEN; 101339beb93cSSam Leffler if (conn->verify.sha1_cert == NULL || 101439beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) { 101539beb93cSSam Leffler conn->verify.sha1_cert = NULL; 101639beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 101739beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 101839beb93cSSam Leffler return -1; 101939beb93cSSam Leffler } 102039beb93cSSam Leffler conn->verify.sha1_cert = NULL; 102139beb93cSSam Leffler 102239beb93cSSam Leffler hlen += MD5_MAC_LEN; 102339beb93cSSam Leffler 1024f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 1025f05cddf9SRui Paulo } 1026f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 1027f05cddf9SRui Paulo 102839beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen); 102939beb93cSSam Leffler 10305b9c547cSRui Paulo if (tls_verify_signature(conn->rl.tls_version, conn->client_rsa_key, 10315b9c547cSRui Paulo hash, hlen, pos, end - pos, &alert) < 0) { 10325b9c547cSRui Paulo tlsv1_server_log(conn, "Invalid Signature in CertificateVerify"); 10335b9c547cSRui Paulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); 103439beb93cSSam Leffler return -1; 103539beb93cSSam Leffler } 103639beb93cSSam Leffler 103739beb93cSSam Leffler *in_len = end - in_data; 103839beb93cSSam Leffler 103939beb93cSSam Leffler conn->state = CHANGE_CIPHER_SPEC; 104039beb93cSSam Leffler 104139beb93cSSam Leffler return 0; 104239beb93cSSam Leffler } 104339beb93cSSam Leffler 104439beb93cSSam Leffler 104539beb93cSSam Leffler static int tls_process_change_cipher_spec(struct tlsv1_server *conn, 104639beb93cSSam Leffler u8 ct, const u8 *in_data, 104739beb93cSSam Leffler size_t *in_len) 104839beb93cSSam Leffler { 104939beb93cSSam Leffler const u8 *pos; 105039beb93cSSam Leffler size_t left; 105139beb93cSSam Leffler 105239beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { 10535b9c547cSRui Paulo tlsv1_server_log(conn, "Expected ChangeCipherSpec; received content type 0x%x", 10545b9c547cSRui Paulo ct); 105539beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 105639beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 105739beb93cSSam Leffler return -1; 105839beb93cSSam Leffler } 105939beb93cSSam Leffler 106039beb93cSSam Leffler pos = in_data; 106139beb93cSSam Leffler left = *in_len; 106239beb93cSSam Leffler 106339beb93cSSam Leffler if (left < 1) { 10645b9c547cSRui Paulo tlsv1_server_log(conn, "Too short ChangeCipherSpec"); 106539beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 106639beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 106739beb93cSSam Leffler return -1; 106839beb93cSSam Leffler } 106939beb93cSSam Leffler 107039beb93cSSam Leffler if (*pos != TLS_CHANGE_CIPHER_SPEC) { 10715b9c547cSRui Paulo tlsv1_server_log(conn, "Expected ChangeCipherSpec; received data 0x%x", 10725b9c547cSRui Paulo *pos); 107339beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 107439beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 107539beb93cSSam Leffler return -1; 107639beb93cSSam Leffler } 107739beb93cSSam Leffler 10785b9c547cSRui Paulo tlsv1_server_log(conn, "Received ChangeCipherSpec"); 107939beb93cSSam Leffler if (tlsv1_record_change_read_cipher(&conn->rl) < 0) { 108039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher " 108139beb93cSSam Leffler "for record layer"); 108239beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 108339beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 108439beb93cSSam Leffler return -1; 108539beb93cSSam Leffler } 108639beb93cSSam Leffler 108739beb93cSSam Leffler *in_len = pos + 1 - in_data; 108839beb93cSSam Leffler 108939beb93cSSam Leffler conn->state = CLIENT_FINISHED; 109039beb93cSSam Leffler 109139beb93cSSam Leffler return 0; 109239beb93cSSam Leffler } 109339beb93cSSam Leffler 109439beb93cSSam Leffler 109539beb93cSSam Leffler static int tls_process_client_finished(struct tlsv1_server *conn, u8 ct, 109639beb93cSSam Leffler const u8 *in_data, size_t *in_len) 109739beb93cSSam Leffler { 109839beb93cSSam Leffler const u8 *pos, *end; 109939beb93cSSam Leffler size_t left, len, hlen; 110039beb93cSSam Leffler u8 verify_data[TLS_VERIFY_DATA_LEN]; 110139beb93cSSam Leffler u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; 110239beb93cSSam Leffler 11035b9c547cSRui Paulo #ifdef CONFIG_TESTING_OPTIONS 11045b9c547cSRui Paulo if ((conn->test_flags & 11055b9c547cSRui Paulo (TLS_BREAK_SRV_KEY_X_HASH | TLS_BREAK_SRV_KEY_X_SIGNATURE)) && 11065b9c547cSRui Paulo !conn->test_failure_reported) { 11075b9c547cSRui Paulo tlsv1_server_log(conn, "TEST-FAILURE: Client Finished received after invalid ServerKeyExchange"); 11085b9c547cSRui Paulo conn->test_failure_reported = 1; 11095b9c547cSRui Paulo } 11105b9c547cSRui Paulo 11115b9c547cSRui Paulo if ((conn->test_flags & TLS_DHE_PRIME_15) && 11125b9c547cSRui Paulo !conn->test_failure_reported) { 11135b9c547cSRui Paulo tlsv1_server_log(conn, "TEST-FAILURE: Client Finished received after bogus DHE \"prime\" 15"); 11145b9c547cSRui Paulo conn->test_failure_reported = 1; 11155b9c547cSRui Paulo } 11165b9c547cSRui Paulo 11175b9c547cSRui Paulo if ((conn->test_flags & TLS_DHE_PRIME_58B) && 11185b9c547cSRui Paulo !conn->test_failure_reported) { 11195b9c547cSRui Paulo tlsv1_server_log(conn, "TEST-FAILURE: Client Finished received after short 58-bit DHE prime in long container"); 11205b9c547cSRui Paulo conn->test_failure_reported = 1; 11215b9c547cSRui Paulo } 11225b9c547cSRui Paulo 11235b9c547cSRui Paulo if ((conn->test_flags & TLS_DHE_PRIME_511B) && 11245b9c547cSRui Paulo !conn->test_failure_reported) { 11255b9c547cSRui Paulo tlsv1_server_log(conn, "TEST-WARNING: Client Finished received after short 511-bit DHE prime (insecure)"); 11265b9c547cSRui Paulo conn->test_failure_reported = 1; 11275b9c547cSRui Paulo } 11285b9c547cSRui Paulo 11295b9c547cSRui Paulo if ((conn->test_flags & TLS_DHE_PRIME_767B) && 11305b9c547cSRui Paulo !conn->test_failure_reported) { 11315b9c547cSRui Paulo tlsv1_server_log(conn, "TEST-NOTE: Client Finished received after 767-bit DHE prime (relatively insecure)"); 11325b9c547cSRui Paulo conn->test_failure_reported = 1; 11335b9c547cSRui Paulo } 11345b9c547cSRui Paulo 11355b9c547cSRui Paulo if ((conn->test_flags & TLS_DHE_NON_PRIME) && 11365b9c547cSRui Paulo !conn->test_failure_reported) { 11375b9c547cSRui Paulo tlsv1_server_log(conn, "TEST-NOTE: Client Finished received after non-prime claimed as DHE prime"); 11385b9c547cSRui Paulo conn->test_failure_reported = 1; 11395b9c547cSRui Paulo } 11405b9c547cSRui Paulo #endif /* CONFIG_TESTING_OPTIONS */ 11415b9c547cSRui Paulo 114239beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { 11435b9c547cSRui Paulo tlsv1_server_log(conn, "Expected Finished; received content type 0x%x", 11445b9c547cSRui Paulo ct); 114539beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 114639beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 114739beb93cSSam Leffler return -1; 114839beb93cSSam Leffler } 114939beb93cSSam Leffler 115039beb93cSSam Leffler pos = in_data; 115139beb93cSSam Leffler left = *in_len; 115239beb93cSSam Leffler 115339beb93cSSam Leffler if (left < 4) { 11545b9c547cSRui Paulo tlsv1_server_log(conn, "Too short record (left=%lu) forFinished", 115539beb93cSSam Leffler (unsigned long) left); 115639beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 115739beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 115839beb93cSSam Leffler return -1; 115939beb93cSSam Leffler } 116039beb93cSSam Leffler 116139beb93cSSam Leffler if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) { 116239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received " 116339beb93cSSam Leffler "type 0x%x", pos[0]); 116439beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 116539beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE); 116639beb93cSSam Leffler return -1; 116739beb93cSSam Leffler } 116839beb93cSSam Leffler 116939beb93cSSam Leffler len = WPA_GET_BE24(pos + 1); 117039beb93cSSam Leffler 117139beb93cSSam Leffler pos += 4; 117239beb93cSSam Leffler left -= 4; 117339beb93cSSam Leffler 117439beb93cSSam Leffler if (len > left) { 11755b9c547cSRui Paulo tlsv1_server_log(conn, "Too short buffer for Finished (len=%lu > left=%lu)", 117639beb93cSSam Leffler (unsigned long) len, (unsigned long) left); 117739beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 117839beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 117939beb93cSSam Leffler return -1; 118039beb93cSSam Leffler } 118139beb93cSSam Leffler end = pos + len; 118239beb93cSSam Leffler if (len != TLS_VERIFY_DATA_LEN) { 11835b9c547cSRui Paulo tlsv1_server_log(conn, "Unexpected verify_data length in Finished: %lu (expected %d)", 118439beb93cSSam Leffler (unsigned long) len, TLS_VERIFY_DATA_LEN); 118539beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 118639beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 118739beb93cSSam Leffler return -1; 118839beb93cSSam Leffler } 118939beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished", 119039beb93cSSam Leffler pos, TLS_VERIFY_DATA_LEN); 119139beb93cSSam Leffler 1192f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 1193f05cddf9SRui Paulo if (conn->rl.tls_version >= TLS_VERSION_1_2) { 1194f05cddf9SRui Paulo hlen = SHA256_MAC_LEN; 1195f05cddf9SRui Paulo if (conn->verify.sha256_client == NULL || 1196f05cddf9SRui Paulo crypto_hash_finish(conn->verify.sha256_client, hash, &hlen) 1197f05cddf9SRui Paulo < 0) { 1198f05cddf9SRui Paulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 1199f05cddf9SRui Paulo TLS_ALERT_INTERNAL_ERROR); 1200f05cddf9SRui Paulo conn->verify.sha256_client = NULL; 1201f05cddf9SRui Paulo return -1; 1202f05cddf9SRui Paulo } 1203f05cddf9SRui Paulo conn->verify.sha256_client = NULL; 1204f05cddf9SRui Paulo } else { 1205f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 1206f05cddf9SRui Paulo 120739beb93cSSam Leffler hlen = MD5_MAC_LEN; 120839beb93cSSam Leffler if (conn->verify.md5_client == NULL || 120939beb93cSSam Leffler crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) { 121039beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 121139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 121239beb93cSSam Leffler conn->verify.md5_client = NULL; 121339beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_client, NULL, NULL); 121439beb93cSSam Leffler conn->verify.sha1_client = NULL; 121539beb93cSSam Leffler return -1; 121639beb93cSSam Leffler } 121739beb93cSSam Leffler conn->verify.md5_client = NULL; 121839beb93cSSam Leffler hlen = SHA1_MAC_LEN; 121939beb93cSSam Leffler if (conn->verify.sha1_client == NULL || 122039beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN, 122139beb93cSSam Leffler &hlen) < 0) { 122239beb93cSSam Leffler conn->verify.sha1_client = NULL; 122339beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 122439beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 122539beb93cSSam Leffler return -1; 122639beb93cSSam Leffler } 122739beb93cSSam Leffler conn->verify.sha1_client = NULL; 1228f05cddf9SRui Paulo hlen = MD5_MAC_LEN + SHA1_MAC_LEN; 122939beb93cSSam Leffler 1230f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 1231f05cddf9SRui Paulo } 1232f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 1233f05cddf9SRui Paulo 1234f05cddf9SRui Paulo if (tls_prf(conn->rl.tls_version, 1235f05cddf9SRui Paulo conn->master_secret, TLS_MASTER_SECRET_LEN, 1236f05cddf9SRui Paulo "client finished", hash, hlen, 123739beb93cSSam Leffler verify_data, TLS_VERIFY_DATA_LEN)) { 123839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data"); 123939beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 124039beb93cSSam Leffler TLS_ALERT_DECRYPT_ERROR); 124139beb93cSSam Leffler return -1; 124239beb93cSSam Leffler } 124339beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)", 124439beb93cSSam Leffler verify_data, TLS_VERIFY_DATA_LEN); 124539beb93cSSam Leffler 12465b9c547cSRui Paulo if (os_memcmp_const(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) { 12475b9c547cSRui Paulo tlsv1_server_log(conn, "Mismatch in verify_data"); 1248*4bc52338SCy Schubert conn->state = FAILED; 124939beb93cSSam Leffler return -1; 125039beb93cSSam Leffler } 125139beb93cSSam Leffler 12525b9c547cSRui Paulo tlsv1_server_log(conn, "Received Finished"); 125339beb93cSSam Leffler 125439beb93cSSam Leffler *in_len = end - in_data; 125539beb93cSSam Leffler 125639beb93cSSam Leffler if (conn->use_session_ticket) { 125739beb93cSSam Leffler /* Abbreviated handshake using session ticket; RFC 4507 */ 12585b9c547cSRui Paulo tlsv1_server_log(conn, "Abbreviated handshake completed successfully"); 125939beb93cSSam Leffler conn->state = ESTABLISHED; 126039beb93cSSam Leffler } else { 126139beb93cSSam Leffler /* Full handshake */ 126239beb93cSSam Leffler conn->state = SERVER_CHANGE_CIPHER_SPEC; 126339beb93cSSam Leffler } 126439beb93cSSam Leffler 126539beb93cSSam Leffler return 0; 126639beb93cSSam Leffler } 126739beb93cSSam Leffler 126839beb93cSSam Leffler 126939beb93cSSam Leffler int tlsv1_server_process_handshake(struct tlsv1_server *conn, u8 ct, 127039beb93cSSam Leffler const u8 *buf, size_t *len) 127139beb93cSSam Leffler { 127239beb93cSSam Leffler if (ct == TLS_CONTENT_TYPE_ALERT) { 127339beb93cSSam Leffler if (*len < 2) { 12745b9c547cSRui Paulo tlsv1_server_log(conn, "Alert underflow"); 127539beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 127639beb93cSSam Leffler TLS_ALERT_DECODE_ERROR); 127739beb93cSSam Leffler return -1; 127839beb93cSSam Leffler } 12795b9c547cSRui Paulo tlsv1_server_log(conn, "Received alert %d:%d", buf[0], buf[1]); 128039beb93cSSam Leffler *len = 2; 128139beb93cSSam Leffler conn->state = FAILED; 128239beb93cSSam Leffler return -1; 128339beb93cSSam Leffler } 128439beb93cSSam Leffler 128539beb93cSSam Leffler switch (conn->state) { 128639beb93cSSam Leffler case CLIENT_HELLO: 128739beb93cSSam Leffler if (tls_process_client_hello(conn, ct, buf, len)) 128839beb93cSSam Leffler return -1; 128939beb93cSSam Leffler break; 129039beb93cSSam Leffler case CLIENT_CERTIFICATE: 129139beb93cSSam Leffler if (tls_process_certificate(conn, ct, buf, len)) 129239beb93cSSam Leffler return -1; 129339beb93cSSam Leffler break; 129439beb93cSSam Leffler case CLIENT_KEY_EXCHANGE: 129539beb93cSSam Leffler if (tls_process_client_key_exchange(conn, ct, buf, len)) 129639beb93cSSam Leffler return -1; 129739beb93cSSam Leffler break; 129839beb93cSSam Leffler case CERTIFICATE_VERIFY: 129939beb93cSSam Leffler if (tls_process_certificate_verify(conn, ct, buf, len)) 130039beb93cSSam Leffler return -1; 130139beb93cSSam Leffler break; 130239beb93cSSam Leffler case CHANGE_CIPHER_SPEC: 130339beb93cSSam Leffler if (tls_process_change_cipher_spec(conn, ct, buf, len)) 130439beb93cSSam Leffler return -1; 130539beb93cSSam Leffler break; 130639beb93cSSam Leffler case CLIENT_FINISHED: 130739beb93cSSam Leffler if (tls_process_client_finished(conn, ct, buf, len)) 130839beb93cSSam Leffler return -1; 130939beb93cSSam Leffler break; 131039beb93cSSam Leffler default: 13115b9c547cSRui Paulo tlsv1_server_log(conn, "Unexpected state %d while processing received message", 131239beb93cSSam Leffler conn->state); 131339beb93cSSam Leffler return -1; 131439beb93cSSam Leffler } 131539beb93cSSam Leffler 131639beb93cSSam Leffler if (ct == TLS_CONTENT_TYPE_HANDSHAKE) 131739beb93cSSam Leffler tls_verify_hash_add(&conn->verify, buf, *len); 131839beb93cSSam Leffler 131939beb93cSSam Leffler return 0; 132039beb93cSSam Leffler } 1321