139beb93cSSam Leffler /* 239beb93cSSam Leffler * TLSv1 client - write handshake message 3780fb4a2SCy Schubert * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6f05cddf9SRui Paulo * See README for more details. 739beb93cSSam Leffler */ 839beb93cSSam Leffler 939beb93cSSam Leffler #include "includes.h" 1039beb93cSSam Leffler 1139beb93cSSam Leffler #include "common.h" 12e28a4053SRui Paulo #include "crypto/md5.h" 13e28a4053SRui Paulo #include "crypto/sha1.h" 14f05cddf9SRui Paulo #include "crypto/sha256.h" 15e28a4053SRui Paulo #include "crypto/tls.h" 16f05cddf9SRui Paulo #include "crypto/random.h" 1739beb93cSSam Leffler #include "x509v3.h" 1839beb93cSSam Leffler #include "tlsv1_common.h" 1939beb93cSSam Leffler #include "tlsv1_record.h" 2039beb93cSSam Leffler #include "tlsv1_client.h" 2139beb93cSSam Leffler #include "tlsv1_client_i.h" 2239beb93cSSam Leffler 2339beb93cSSam Leffler 2439beb93cSSam Leffler static size_t tls_client_cert_chain_der_len(struct tlsv1_client *conn) 2539beb93cSSam Leffler { 2639beb93cSSam Leffler size_t len = 0; 2739beb93cSSam Leffler struct x509_certificate *cert; 2839beb93cSSam Leffler 2939beb93cSSam Leffler if (conn->cred == NULL) 3039beb93cSSam Leffler return 0; 3139beb93cSSam Leffler 3239beb93cSSam Leffler cert = conn->cred->cert; 3339beb93cSSam Leffler while (cert) { 3439beb93cSSam Leffler len += 3 + cert->cert_len; 3539beb93cSSam Leffler if (x509_certificate_self_signed(cert)) 3639beb93cSSam Leffler break; 3739beb93cSSam Leffler cert = x509_certificate_get_subject(conn->cred->trusted_certs, 3839beb93cSSam Leffler &cert->issuer); 3939beb93cSSam Leffler } 4039beb93cSSam Leffler 4139beb93cSSam Leffler return len; 4239beb93cSSam Leffler } 4339beb93cSSam Leffler 4439beb93cSSam Leffler 4539beb93cSSam Leffler u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len) 4639beb93cSSam Leffler { 4739beb93cSSam Leffler u8 *hello, *end, *pos, *hs_length, *hs_start, *rhdr; 4839beb93cSSam Leffler struct os_time now; 4939beb93cSSam Leffler size_t len, i; 50780fb4a2SCy Schubert u8 *ext_start; 51780fb4a2SCy Schubert u16 tls_version = TLS_VERSION; 5239beb93cSSam Leffler 53780fb4a2SCy Schubert /* Pick the highest locally enabled TLS version */ 54780fb4a2SCy Schubert #ifdef CONFIG_TLSV12 55780fb4a2SCy Schubert if ((conn->flags & TLS_CONN_DISABLE_TLSv1_2) && 56780fb4a2SCy Schubert tls_version == TLS_VERSION_1_2) 57780fb4a2SCy Schubert tls_version = TLS_VERSION_1_1; 58780fb4a2SCy Schubert #endif /* CONFIG_TLSV12 */ 59780fb4a2SCy Schubert #ifdef CONFIG_TLSV11 60780fb4a2SCy Schubert if ((conn->flags & TLS_CONN_DISABLE_TLSv1_1) && 61780fb4a2SCy Schubert tls_version == TLS_VERSION_1_1) 62780fb4a2SCy Schubert tls_version = TLS_VERSION_1; 63780fb4a2SCy Schubert #endif /* CONFIG_TLSV11 */ 64780fb4a2SCy Schubert if ((conn->flags & TLS_CONN_DISABLE_TLSv1_0) && 65780fb4a2SCy Schubert tls_version == TLS_VERSION_1) { 66780fb4a2SCy Schubert wpa_printf(MSG_INFO, "TLSv1: No TLS version allowed"); 67780fb4a2SCy Schubert return NULL; 68780fb4a2SCy Schubert } 69780fb4a2SCy Schubert 70780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello (ver %s)", 71780fb4a2SCy Schubert tls_version_str(tls_version)); 7239beb93cSSam Leffler *out_len = 0; 7339beb93cSSam Leffler 7439beb93cSSam Leffler os_get_time(&now); 75*4bc52338SCy Schubert #ifdef TEST_FUZZ 76*4bc52338SCy Schubert now.sec = 0xfffefdfc; 77*4bc52338SCy Schubert #endif /* TEST_FUZZ */ 7839beb93cSSam Leffler WPA_PUT_BE32(conn->client_random, now.sec); 79f05cddf9SRui Paulo if (random_get_bytes(conn->client_random + 4, TLS_RANDOM_LEN - 4)) { 8039beb93cSSam Leffler wpa_printf(MSG_ERROR, "TLSv1: Could not generate " 8139beb93cSSam Leffler "client_random"); 8239beb93cSSam Leffler return NULL; 8339beb93cSSam Leffler } 8439beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random", 8539beb93cSSam Leffler conn->client_random, TLS_RANDOM_LEN); 8639beb93cSSam Leffler 87780fb4a2SCy Schubert len = 150 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len; 8839beb93cSSam Leffler hello = os_malloc(len); 8939beb93cSSam Leffler if (hello == NULL) 9039beb93cSSam Leffler return NULL; 9139beb93cSSam Leffler end = hello + len; 9239beb93cSSam Leffler 9339beb93cSSam Leffler rhdr = hello; 9439beb93cSSam Leffler pos = rhdr + TLS_RECORD_HEADER_LEN; 9539beb93cSSam Leffler 9639beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 9739beb93cSSam Leffler 9839beb93cSSam Leffler /* Handshake */ 9939beb93cSSam Leffler hs_start = pos; 10039beb93cSSam Leffler /* HandshakeType msg_type */ 10139beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_HELLO; 10239beb93cSSam Leffler /* uint24 length (to be filled) */ 10339beb93cSSam Leffler hs_length = pos; 10439beb93cSSam Leffler pos += 3; 10539beb93cSSam Leffler /* body - ClientHello */ 10639beb93cSSam Leffler /* ProtocolVersion client_version */ 107780fb4a2SCy Schubert WPA_PUT_BE16(pos, tls_version); 10839beb93cSSam Leffler pos += 2; 10939beb93cSSam Leffler /* Random random: uint32 gmt_unix_time, opaque random_bytes */ 11039beb93cSSam Leffler os_memcpy(pos, conn->client_random, TLS_RANDOM_LEN); 11139beb93cSSam Leffler pos += TLS_RANDOM_LEN; 11239beb93cSSam Leffler /* SessionID session_id */ 11339beb93cSSam Leffler *pos++ = conn->session_id_len; 11439beb93cSSam Leffler os_memcpy(pos, conn->session_id, conn->session_id_len); 11539beb93cSSam Leffler pos += conn->session_id_len; 11639beb93cSSam Leffler /* CipherSuite cipher_suites<2..2^16-1> */ 11739beb93cSSam Leffler WPA_PUT_BE16(pos, 2 * conn->num_cipher_suites); 11839beb93cSSam Leffler pos += 2; 11939beb93cSSam Leffler for (i = 0; i < conn->num_cipher_suites; i++) { 12039beb93cSSam Leffler WPA_PUT_BE16(pos, conn->cipher_suites[i]); 12139beb93cSSam Leffler pos += 2; 12239beb93cSSam Leffler } 12339beb93cSSam Leffler /* CompressionMethod compression_methods<1..2^8-1> */ 12439beb93cSSam Leffler *pos++ = 1; 12539beb93cSSam Leffler *pos++ = TLS_COMPRESSION_NULL; 12639beb93cSSam Leffler 127780fb4a2SCy Schubert /* Extension */ 128780fb4a2SCy Schubert ext_start = pos; 129780fb4a2SCy Schubert pos += 2; 130780fb4a2SCy Schubert 131780fb4a2SCy Schubert #ifdef CONFIG_TLSV12 132780fb4a2SCy Schubert if (conn->rl.tls_version >= TLS_VERSION_1_2) { 133780fb4a2SCy Schubert /* 134780fb4a2SCy Schubert * Add signature_algorithms extension since we support only 135780fb4a2SCy Schubert * SHA256 (and not the default SHA1) with TLSv1.2. 136780fb4a2SCy Schubert */ 137780fb4a2SCy Schubert /* ExtensionsType extension_type = signature_algorithms(13) */ 138780fb4a2SCy Schubert WPA_PUT_BE16(pos, TLS_EXT_SIGNATURE_ALGORITHMS); 139780fb4a2SCy Schubert pos += 2; 140780fb4a2SCy Schubert /* opaque extension_data<0..2^16-1> length */ 141780fb4a2SCy Schubert WPA_PUT_BE16(pos, 8); 142780fb4a2SCy Schubert pos += 2; 143780fb4a2SCy Schubert /* supported_signature_algorithms<2..2^16-2> length */ 144780fb4a2SCy Schubert WPA_PUT_BE16(pos, 6); 145780fb4a2SCy Schubert pos += 2; 146780fb4a2SCy Schubert /* supported_signature_algorithms */ 147780fb4a2SCy Schubert *pos++ = TLS_HASH_ALG_SHA512; 148780fb4a2SCy Schubert *pos++ = TLS_SIGN_ALG_RSA; 149780fb4a2SCy Schubert *pos++ = TLS_HASH_ALG_SHA384; 150780fb4a2SCy Schubert *pos++ = TLS_SIGN_ALG_RSA; 151780fb4a2SCy Schubert *pos++ = TLS_HASH_ALG_SHA256; 152780fb4a2SCy Schubert *pos++ = TLS_SIGN_ALG_RSA; 153780fb4a2SCy Schubert } 154780fb4a2SCy Schubert #endif /* CONFIG_TLSV12 */ 155780fb4a2SCy Schubert 15639beb93cSSam Leffler if (conn->client_hello_ext) { 15739beb93cSSam Leffler os_memcpy(pos, conn->client_hello_ext, 15839beb93cSSam Leffler conn->client_hello_ext_len); 15939beb93cSSam Leffler pos += conn->client_hello_ext_len; 16039beb93cSSam Leffler } 16139beb93cSSam Leffler 162780fb4a2SCy Schubert if (conn->flags & TLS_CONN_REQUEST_OCSP) { 163780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 164780fb4a2SCy Schubert "TLSv1: Add status_request extension for OCSP stapling"); 165780fb4a2SCy Schubert /* ExtensionsType extension_type = status_request(5) */ 166780fb4a2SCy Schubert WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST); 167780fb4a2SCy Schubert pos += 2; 168780fb4a2SCy Schubert /* opaque extension_data<0..2^16-1> length */ 169780fb4a2SCy Schubert WPA_PUT_BE16(pos, 5); 170780fb4a2SCy Schubert pos += 2; 171780fb4a2SCy Schubert 172780fb4a2SCy Schubert /* 173780fb4a2SCy Schubert * RFC 6066, 8: 174780fb4a2SCy Schubert * struct { 175780fb4a2SCy Schubert * CertificateStatusType status_type; 176780fb4a2SCy Schubert * select (status_type) { 177780fb4a2SCy Schubert * case ocsp: OCSPStatusRequest; 178780fb4a2SCy Schubert * } request; 179780fb4a2SCy Schubert * } CertificateStatusRequest; 180780fb4a2SCy Schubert * 181780fb4a2SCy Schubert * enum { ocsp(1), (255) } CertificateStatusType; 182780fb4a2SCy Schubert */ 183780fb4a2SCy Schubert *pos++ = 1; /* status_type = ocsp(1) */ 184780fb4a2SCy Schubert 185780fb4a2SCy Schubert /* 186780fb4a2SCy Schubert * struct { 187780fb4a2SCy Schubert * ResponderID responder_id_list<0..2^16-1>; 188780fb4a2SCy Schubert * Extensions request_extensions; 189780fb4a2SCy Schubert * } OCSPStatusRequest; 190780fb4a2SCy Schubert * 191780fb4a2SCy Schubert * opaque ResponderID<1..2^16-1>; 192780fb4a2SCy Schubert * opaque Extensions<0..2^16-1>; 193780fb4a2SCy Schubert */ 194780fb4a2SCy Schubert WPA_PUT_BE16(pos, 0); /* responder_id_list(empty) */ 195780fb4a2SCy Schubert pos += 2; 196780fb4a2SCy Schubert WPA_PUT_BE16(pos, 0); /* request_extensions(empty) */ 197780fb4a2SCy Schubert pos += 2; 198780fb4a2SCy Schubert 199780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 200780fb4a2SCy Schubert "TLSv1: Add status_request_v2 extension for OCSP stapling"); 201780fb4a2SCy Schubert /* ExtensionsType extension_type = status_request_v2(17) */ 202780fb4a2SCy Schubert WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST_V2); 203780fb4a2SCy Schubert pos += 2; 204780fb4a2SCy Schubert /* opaque extension_data<0..2^16-1> length */ 205780fb4a2SCy Schubert WPA_PUT_BE16(pos, 7); 206780fb4a2SCy Schubert pos += 2; 207780fb4a2SCy Schubert 208780fb4a2SCy Schubert /* 209780fb4a2SCy Schubert * RFC 6961, 2.2: 210780fb4a2SCy Schubert * struct { 211780fb4a2SCy Schubert * CertificateStatusType status_type; 212780fb4a2SCy Schubert * uint16 request_length; 213780fb4a2SCy Schubert * select (status_type) { 214780fb4a2SCy Schubert * case ocsp: OCSPStatusRequest; 215780fb4a2SCy Schubert * case ocsp_multi: OCSPStatusRequest; 216780fb4a2SCy Schubert * } request; 217780fb4a2SCy Schubert * } CertificateStatusRequestItemV2; 218780fb4a2SCy Schubert * 219780fb4a2SCy Schubert * enum { ocsp(1), ocsp_multi(2), (255) } CertificateStatusType; 220780fb4a2SCy Schubert * 221780fb4a2SCy Schubert * struct { 222780fb4a2SCy Schubert * CertificateStatusRequestItemV2 223780fb4a2SCy Schubert * certificate_status_req_list<1..2^16-1>; 224780fb4a2SCy Schubert * } CertificateStatusRequestListV2; 225780fb4a2SCy Schubert */ 226780fb4a2SCy Schubert 227780fb4a2SCy Schubert /* certificate_status_req_list<1..2^16-1> */ 228780fb4a2SCy Schubert WPA_PUT_BE16(pos, 5); 229780fb4a2SCy Schubert pos += 2; 230780fb4a2SCy Schubert 231780fb4a2SCy Schubert /* CertificateStatusRequestItemV2 */ 232780fb4a2SCy Schubert *pos++ = 2; /* status_type = ocsp_multi(2) */ 233780fb4a2SCy Schubert /* OCSPStatusRequest as shown above for v1 */ 234780fb4a2SCy Schubert WPA_PUT_BE16(pos, 0); /* responder_id_list(empty) */ 235780fb4a2SCy Schubert pos += 2; 236780fb4a2SCy Schubert WPA_PUT_BE16(pos, 0); /* request_extensions(empty) */ 237780fb4a2SCy Schubert pos += 2; 238780fb4a2SCy Schubert } 239780fb4a2SCy Schubert 240780fb4a2SCy Schubert if (pos == ext_start + 2) 241780fb4a2SCy Schubert pos -= 2; /* no extensions */ 242780fb4a2SCy Schubert else 243780fb4a2SCy Schubert WPA_PUT_BE16(ext_start, pos - ext_start - 2); 244780fb4a2SCy Schubert 24539beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 24639beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 24739beb93cSSam Leffler 24839beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 249f05cddf9SRui Paulo rhdr, end - rhdr, hs_start, pos - hs_start, 250f05cddf9SRui Paulo out_len) < 0) { 25139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record"); 25239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 25339beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 25439beb93cSSam Leffler os_free(hello); 25539beb93cSSam Leffler return NULL; 25639beb93cSSam Leffler } 25739beb93cSSam Leffler 25839beb93cSSam Leffler conn->state = SERVER_HELLO; 25939beb93cSSam Leffler 26039beb93cSSam Leffler return hello; 26139beb93cSSam Leffler } 26239beb93cSSam Leffler 26339beb93cSSam Leffler 26439beb93cSSam Leffler static int tls_write_client_certificate(struct tlsv1_client *conn, 26539beb93cSSam Leffler u8 **msgpos, u8 *end) 26639beb93cSSam Leffler { 26739beb93cSSam Leffler u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start; 26839beb93cSSam Leffler size_t rlen; 26939beb93cSSam Leffler struct x509_certificate *cert; 27039beb93cSSam Leffler 27139beb93cSSam Leffler pos = *msgpos; 272780fb4a2SCy Schubert if (TLS_RECORD_HEADER_LEN + 1 + 3 + 3 > end - pos) { 273780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 274780fb4a2SCy Schubert TLS_ALERT_INTERNAL_ERROR); 275780fb4a2SCy Schubert return -1; 276780fb4a2SCy Schubert } 27739beb93cSSam Leffler 27839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate"); 27939beb93cSSam Leffler rhdr = pos; 28039beb93cSSam Leffler pos += TLS_RECORD_HEADER_LEN; 28139beb93cSSam Leffler 28239beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 28339beb93cSSam Leffler 28439beb93cSSam Leffler /* Handshake */ 28539beb93cSSam Leffler hs_start = pos; 28639beb93cSSam Leffler /* HandshakeType msg_type */ 28739beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE; 28839beb93cSSam Leffler /* uint24 length (to be filled) */ 28939beb93cSSam Leffler hs_length = pos; 29039beb93cSSam Leffler pos += 3; 29139beb93cSSam Leffler /* body - Certificate */ 29239beb93cSSam Leffler /* uint24 length (to be filled) */ 29339beb93cSSam Leffler cert_start = pos; 29439beb93cSSam Leffler pos += 3; 29539beb93cSSam Leffler cert = conn->cred ? conn->cred->cert : NULL; 29639beb93cSSam Leffler while (cert) { 297780fb4a2SCy Schubert if (3 + cert->cert_len > (size_t) (end - pos)) { 29839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space " 29939beb93cSSam Leffler "for Certificate (cert_len=%lu left=%lu)", 30039beb93cSSam Leffler (unsigned long) cert->cert_len, 30139beb93cSSam Leffler (unsigned long) (end - pos)); 30239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 30339beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 30439beb93cSSam Leffler return -1; 30539beb93cSSam Leffler } 30639beb93cSSam Leffler WPA_PUT_BE24(pos, cert->cert_len); 30739beb93cSSam Leffler pos += 3; 30839beb93cSSam Leffler os_memcpy(pos, cert->cert_start, cert->cert_len); 30939beb93cSSam Leffler pos += cert->cert_len; 31039beb93cSSam Leffler 31139beb93cSSam Leffler if (x509_certificate_self_signed(cert)) 31239beb93cSSam Leffler break; 31339beb93cSSam Leffler cert = x509_certificate_get_subject(conn->cred->trusted_certs, 31439beb93cSSam Leffler &cert->issuer); 31539beb93cSSam Leffler } 31639beb93cSSam Leffler if (conn->cred == NULL || cert == conn->cred->cert || cert == NULL) { 31739beb93cSSam Leffler /* 31839beb93cSSam Leffler * Client was not configured with all the needed certificates 31939beb93cSSam Leffler * to form a full certificate chain. The server may fail to 32039beb93cSSam Leffler * validate the chain unless it is configured with all the 32139beb93cSSam Leffler * missing CA certificates. 32239beb93cSSam Leffler */ 32339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Full client certificate chain " 32439beb93cSSam Leffler "not configured - validation may fail"); 32539beb93cSSam Leffler } 32639beb93cSSam Leffler WPA_PUT_BE24(cert_start, pos - cert_start - 3); 32739beb93cSSam Leffler 32839beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 32939beb93cSSam Leffler 33039beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 331f05cddf9SRui Paulo rhdr, end - rhdr, hs_start, pos - hs_start, 332f05cddf9SRui Paulo &rlen) < 0) { 33339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); 33439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 33539beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 33639beb93cSSam Leffler return -1; 33739beb93cSSam Leffler } 33839beb93cSSam Leffler pos = rhdr + rlen; 33939beb93cSSam Leffler 34039beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 34139beb93cSSam Leffler 34239beb93cSSam Leffler *msgpos = pos; 34339beb93cSSam Leffler 34439beb93cSSam Leffler return 0; 34539beb93cSSam Leffler } 34639beb93cSSam Leffler 34739beb93cSSam Leffler 3485b9c547cSRui Paulo static int tlsv1_key_x_dh(struct tlsv1_client *conn, u8 **pos, u8 *end) 34939beb93cSSam Leffler { 35039beb93cSSam Leffler /* ClientDiffieHellmanPublic */ 35139beb93cSSam Leffler u8 *csecret, *csecret_start, *dh_yc, *shared; 35239beb93cSSam Leffler size_t csecret_len, dh_yc_len, shared_len; 35339beb93cSSam Leffler 35439beb93cSSam Leffler csecret_len = conn->dh_p_len; 35539beb93cSSam Leffler csecret = os_malloc(csecret_len); 35639beb93cSSam Leffler if (csecret == NULL) { 35739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " 35839beb93cSSam Leffler "memory for Yc (Diffie-Hellman)"); 35939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 36039beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 36139beb93cSSam Leffler return -1; 36239beb93cSSam Leffler } 363f05cddf9SRui Paulo if (random_get_bytes(csecret, csecret_len)) { 36439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " 36539beb93cSSam Leffler "data for Diffie-Hellman"); 36639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 36739beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 36839beb93cSSam Leffler os_free(csecret); 36939beb93cSSam Leffler return -1; 37039beb93cSSam Leffler } 37139beb93cSSam Leffler 37239beb93cSSam Leffler if (os_memcmp(csecret, conn->dh_p, csecret_len) > 0) 37339beb93cSSam Leffler csecret[0] = 0; /* make sure Yc < p */ 37439beb93cSSam Leffler 37539beb93cSSam Leffler csecret_start = csecret; 37639beb93cSSam Leffler while (csecret_len > 1 && *csecret_start == 0) { 37739beb93cSSam Leffler csecret_start++; 37839beb93cSSam Leffler csecret_len--; 37939beb93cSSam Leffler } 38039beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH client's secret value", 38139beb93cSSam Leffler csecret_start, csecret_len); 38239beb93cSSam Leffler 38339beb93cSSam Leffler /* Yc = g^csecret mod p */ 38439beb93cSSam Leffler dh_yc_len = conn->dh_p_len; 38539beb93cSSam Leffler dh_yc = os_malloc(dh_yc_len); 38639beb93cSSam Leffler if (dh_yc == NULL) { 38739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " 38839beb93cSSam Leffler "memory for Diffie-Hellman"); 38939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 39039beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 39139beb93cSSam Leffler os_free(csecret); 39239beb93cSSam Leffler return -1; 39339beb93cSSam Leffler } 39439beb93cSSam Leffler if (crypto_mod_exp(conn->dh_g, conn->dh_g_len, 39539beb93cSSam Leffler csecret_start, csecret_len, 39639beb93cSSam Leffler conn->dh_p, conn->dh_p_len, 39739beb93cSSam Leffler dh_yc, &dh_yc_len)) { 39839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 39939beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 40039beb93cSSam Leffler os_free(csecret); 40139beb93cSSam Leffler os_free(dh_yc); 40239beb93cSSam Leffler return -1; 40339beb93cSSam Leffler } 40439beb93cSSam Leffler 40539beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)", 40639beb93cSSam Leffler dh_yc, dh_yc_len); 40739beb93cSSam Leffler 408780fb4a2SCy Schubert if (end - *pos < 2) { 409780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 410780fb4a2SCy Schubert TLS_ALERT_INTERNAL_ERROR); 411780fb4a2SCy Schubert os_free(csecret); 412780fb4a2SCy Schubert os_free(dh_yc); 413780fb4a2SCy Schubert return -1; 414780fb4a2SCy Schubert } 41539beb93cSSam Leffler WPA_PUT_BE16(*pos, dh_yc_len); 41639beb93cSSam Leffler *pos += 2; 417780fb4a2SCy Schubert if (dh_yc_len > (size_t) (end - *pos)) { 41839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Not enough room in the " 41939beb93cSSam Leffler "message buffer for Yc"); 42039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 42139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 42239beb93cSSam Leffler os_free(csecret); 42339beb93cSSam Leffler os_free(dh_yc); 42439beb93cSSam Leffler return -1; 42539beb93cSSam Leffler } 42639beb93cSSam Leffler os_memcpy(*pos, dh_yc, dh_yc_len); 42739beb93cSSam Leffler *pos += dh_yc_len; 42839beb93cSSam Leffler os_free(dh_yc); 42939beb93cSSam Leffler 43039beb93cSSam Leffler shared_len = conn->dh_p_len; 43139beb93cSSam Leffler shared = os_malloc(shared_len); 43239beb93cSSam Leffler if (shared == NULL) { 43339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for " 43439beb93cSSam Leffler "DH"); 43539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 43639beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 43739beb93cSSam Leffler os_free(csecret); 43839beb93cSSam Leffler return -1; 43939beb93cSSam Leffler } 44039beb93cSSam Leffler 44139beb93cSSam Leffler /* shared = Ys^csecret mod p */ 44239beb93cSSam Leffler if (crypto_mod_exp(conn->dh_ys, conn->dh_ys_len, 44339beb93cSSam Leffler csecret_start, csecret_len, 44439beb93cSSam Leffler conn->dh_p, conn->dh_p_len, 44539beb93cSSam Leffler shared, &shared_len)) { 44639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 44739beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 44839beb93cSSam Leffler os_free(csecret); 44939beb93cSSam Leffler os_free(shared); 45039beb93cSSam Leffler return -1; 45139beb93cSSam Leffler } 45239beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange", 45339beb93cSSam Leffler shared, shared_len); 45439beb93cSSam Leffler 45539beb93cSSam Leffler os_memset(csecret_start, 0, csecret_len); 45639beb93cSSam Leffler os_free(csecret); 45739beb93cSSam Leffler if (tls_derive_keys(conn, shared, shared_len)) { 45839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); 45939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 46039beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 46139beb93cSSam Leffler os_free(shared); 46239beb93cSSam Leffler return -1; 46339beb93cSSam Leffler } 46439beb93cSSam Leffler os_memset(shared, 0, shared_len); 46539beb93cSSam Leffler os_free(shared); 46639beb93cSSam Leffler tlsv1_client_free_dh(conn); 46739beb93cSSam Leffler return 0; 46839beb93cSSam Leffler } 46939beb93cSSam Leffler 47039beb93cSSam Leffler 47139beb93cSSam Leffler static int tlsv1_key_x_rsa(struct tlsv1_client *conn, u8 **pos, u8 *end) 47239beb93cSSam Leffler { 47339beb93cSSam Leffler u8 pre_master_secret[TLS_PRE_MASTER_SECRET_LEN]; 47439beb93cSSam Leffler size_t clen; 47539beb93cSSam Leffler int res; 47639beb93cSSam Leffler 47739beb93cSSam Leffler if (tls_derive_pre_master_secret(pre_master_secret) < 0 || 47839beb93cSSam Leffler tls_derive_keys(conn, pre_master_secret, 47939beb93cSSam Leffler TLS_PRE_MASTER_SECRET_LEN)) { 48039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); 48139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 48239beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 48339beb93cSSam Leffler return -1; 48439beb93cSSam Leffler } 48539beb93cSSam Leffler 48639beb93cSSam Leffler /* EncryptedPreMasterSecret */ 48739beb93cSSam Leffler if (conn->server_rsa_key == NULL) { 48839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: No server RSA key to " 48939beb93cSSam Leffler "use for encrypting pre-master secret"); 49039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 49139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 49239beb93cSSam Leffler return -1; 49339beb93cSSam Leffler } 49439beb93cSSam Leffler 49539beb93cSSam Leffler /* RSA encrypted value is encoded with PKCS #1 v1.5 block type 2. */ 49639beb93cSSam Leffler *pos += 2; 49739beb93cSSam Leffler clen = end - *pos; 49839beb93cSSam Leffler res = crypto_public_key_encrypt_pkcs1_v15( 49939beb93cSSam Leffler conn->server_rsa_key, 50039beb93cSSam Leffler pre_master_secret, TLS_PRE_MASTER_SECRET_LEN, 50139beb93cSSam Leffler *pos, &clen); 50239beb93cSSam Leffler os_memset(pre_master_secret, 0, TLS_PRE_MASTER_SECRET_LEN); 50339beb93cSSam Leffler if (res < 0) { 50439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: RSA encryption failed"); 50539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 50639beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 50739beb93cSSam Leffler return -1; 50839beb93cSSam Leffler } 50939beb93cSSam Leffler WPA_PUT_BE16(*pos - 2, clen); 51039beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: Encrypted pre_master_secret", 51139beb93cSSam Leffler *pos, clen); 51239beb93cSSam Leffler *pos += clen; 51339beb93cSSam Leffler 51439beb93cSSam Leffler return 0; 51539beb93cSSam Leffler } 51639beb93cSSam Leffler 51739beb93cSSam Leffler 51839beb93cSSam Leffler static int tls_write_client_key_exchange(struct tlsv1_client *conn, 51939beb93cSSam Leffler u8 **msgpos, u8 *end) 52039beb93cSSam Leffler { 52139beb93cSSam Leffler u8 *pos, *rhdr, *hs_start, *hs_length; 52239beb93cSSam Leffler size_t rlen; 52339beb93cSSam Leffler tls_key_exchange keyx; 52439beb93cSSam Leffler const struct tls_cipher_suite *suite; 52539beb93cSSam Leffler 52639beb93cSSam Leffler suite = tls_get_cipher_suite(conn->rl.cipher_suite); 52739beb93cSSam Leffler if (suite == NULL) 52839beb93cSSam Leffler keyx = TLS_KEY_X_NULL; 52939beb93cSSam Leffler else 53039beb93cSSam Leffler keyx = suite->key_exchange; 53139beb93cSSam Leffler 53239beb93cSSam Leffler pos = *msgpos; 53339beb93cSSam Leffler 53439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send ClientKeyExchange"); 53539beb93cSSam Leffler 53639beb93cSSam Leffler rhdr = pos; 53739beb93cSSam Leffler pos += TLS_RECORD_HEADER_LEN; 53839beb93cSSam Leffler 53939beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 54039beb93cSSam Leffler 54139beb93cSSam Leffler /* Handshake */ 54239beb93cSSam Leffler hs_start = pos; 54339beb93cSSam Leffler /* HandshakeType msg_type */ 54439beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE; 54539beb93cSSam Leffler /* uint24 length (to be filled) */ 54639beb93cSSam Leffler hs_length = pos; 54739beb93cSSam Leffler pos += 3; 54839beb93cSSam Leffler /* body - ClientKeyExchange */ 5495b9c547cSRui Paulo if (keyx == TLS_KEY_X_DH_anon || keyx == TLS_KEY_X_DHE_RSA) { 5505b9c547cSRui Paulo if (tlsv1_key_x_dh(conn, &pos, end) < 0) 55139beb93cSSam Leffler return -1; 55239beb93cSSam Leffler } else { 55339beb93cSSam Leffler if (tlsv1_key_x_rsa(conn, &pos, end) < 0) 55439beb93cSSam Leffler return -1; 55539beb93cSSam Leffler } 55639beb93cSSam Leffler 55739beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 55839beb93cSSam Leffler 55939beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 560f05cddf9SRui Paulo rhdr, end - rhdr, hs_start, pos - hs_start, 561f05cddf9SRui Paulo &rlen) < 0) { 56239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); 56339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 56439beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 56539beb93cSSam Leffler return -1; 56639beb93cSSam Leffler } 56739beb93cSSam Leffler pos = rhdr + rlen; 56839beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 56939beb93cSSam Leffler 57039beb93cSSam Leffler *msgpos = pos; 57139beb93cSSam Leffler 57239beb93cSSam Leffler return 0; 57339beb93cSSam Leffler } 57439beb93cSSam Leffler 57539beb93cSSam Leffler 57639beb93cSSam Leffler static int tls_write_client_certificate_verify(struct tlsv1_client *conn, 57739beb93cSSam Leffler u8 **msgpos, u8 *end) 57839beb93cSSam Leffler { 57939beb93cSSam Leffler u8 *pos, *rhdr, *hs_start, *hs_length, *signed_start; 58039beb93cSSam Leffler size_t rlen, hlen, clen; 581f05cddf9SRui Paulo u8 hash[100], *hpos; 58239beb93cSSam Leffler 58339beb93cSSam Leffler pos = *msgpos; 58439beb93cSSam Leffler 58539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateVerify"); 58639beb93cSSam Leffler rhdr = pos; 58739beb93cSSam Leffler pos += TLS_RECORD_HEADER_LEN; 58839beb93cSSam Leffler 58939beb93cSSam Leffler /* Handshake */ 59039beb93cSSam Leffler hs_start = pos; 59139beb93cSSam Leffler /* HandshakeType msg_type */ 59239beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY; 59339beb93cSSam Leffler /* uint24 length (to be filled) */ 59439beb93cSSam Leffler hs_length = pos; 59539beb93cSSam Leffler pos += 3; 59639beb93cSSam Leffler 59739beb93cSSam Leffler /* 59839beb93cSSam Leffler * RFC 2246: 7.4.3 and 7.4.8: 59939beb93cSSam Leffler * Signature signature 60039beb93cSSam Leffler * 60139beb93cSSam Leffler * RSA: 60239beb93cSSam Leffler * digitally-signed struct { 60339beb93cSSam Leffler * opaque md5_hash[16]; 60439beb93cSSam Leffler * opaque sha_hash[20]; 60539beb93cSSam Leffler * }; 60639beb93cSSam Leffler * 60739beb93cSSam Leffler * DSA: 60839beb93cSSam Leffler * digitally-signed struct { 60939beb93cSSam Leffler * opaque sha_hash[20]; 61039beb93cSSam Leffler * }; 61139beb93cSSam Leffler * 61239beb93cSSam Leffler * The hash values are calculated over all handshake messages sent or 61339beb93cSSam Leffler * received starting at ClientHello up to, but not including, this 61439beb93cSSam Leffler * CertificateVerify message, including the type and length fields of 61539beb93cSSam Leffler * the handshake messages. 61639beb93cSSam Leffler */ 61739beb93cSSam Leffler 61839beb93cSSam Leffler hpos = hash; 61939beb93cSSam Leffler 620f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 621f05cddf9SRui Paulo if (conn->rl.tls_version == TLS_VERSION_1_2) { 622f05cddf9SRui Paulo hlen = SHA256_MAC_LEN; 623f05cddf9SRui Paulo if (conn->verify.sha256_cert == NULL || 624f05cddf9SRui Paulo crypto_hash_finish(conn->verify.sha256_cert, hpos, &hlen) < 625f05cddf9SRui Paulo 0) { 626f05cddf9SRui Paulo conn->verify.sha256_cert = NULL; 627f05cddf9SRui Paulo tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 628f05cddf9SRui Paulo TLS_ALERT_INTERNAL_ERROR); 629f05cddf9SRui Paulo return -1; 630f05cddf9SRui Paulo } 631f05cddf9SRui Paulo conn->verify.sha256_cert = NULL; 632f05cddf9SRui Paulo 633f05cddf9SRui Paulo /* 634f05cddf9SRui Paulo * RFC 3447, A.2.4 RSASSA-PKCS1-v1_5 635f05cddf9SRui Paulo * 636f05cddf9SRui Paulo * DigestInfo ::= SEQUENCE { 637f05cddf9SRui Paulo * digestAlgorithm DigestAlgorithm, 638f05cddf9SRui Paulo * digest OCTET STRING 639f05cddf9SRui Paulo * } 640f05cddf9SRui Paulo * 641f05cddf9SRui Paulo * SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11} 642f05cddf9SRui Paulo * 643f05cddf9SRui Paulo * DER encoded DigestInfo for SHA256 per RFC 3447: 644f05cddf9SRui Paulo * 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || 645f05cddf9SRui Paulo * H 646f05cddf9SRui Paulo */ 647f05cddf9SRui Paulo os_memmove(hash + 19, hash, hlen); 648f05cddf9SRui Paulo hlen += 19; 649f05cddf9SRui Paulo os_memcpy(hash, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65" 650f05cddf9SRui Paulo "\x03\x04\x02\x01\x05\x00\x04\x20", 19); 651f05cddf9SRui Paulo } else { 652f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 653f05cddf9SRui Paulo 65439beb93cSSam Leffler hlen = MD5_MAC_LEN; 65539beb93cSSam Leffler if (conn->verify.md5_cert == NULL || 6565b9c547cSRui Paulo crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) { 65739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 65839beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 65939beb93cSSam Leffler conn->verify.md5_cert = NULL; 66039beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL); 66139beb93cSSam Leffler conn->verify.sha1_cert = NULL; 66239beb93cSSam Leffler return -1; 66339beb93cSSam Leffler } 66439beb93cSSam Leffler hpos += MD5_MAC_LEN; 66539beb93cSSam Leffler 66639beb93cSSam Leffler conn->verify.md5_cert = NULL; 66739beb93cSSam Leffler hlen = SHA1_MAC_LEN; 66839beb93cSSam Leffler if (conn->verify.sha1_cert == NULL || 66939beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) { 67039beb93cSSam Leffler conn->verify.sha1_cert = NULL; 67139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 67239beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 67339beb93cSSam Leffler return -1; 67439beb93cSSam Leffler } 67539beb93cSSam Leffler conn->verify.sha1_cert = NULL; 67639beb93cSSam Leffler 67739beb93cSSam Leffler hlen += MD5_MAC_LEN; 67839beb93cSSam Leffler 679f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 680f05cddf9SRui Paulo } 681f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 682f05cddf9SRui Paulo 68339beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen); 68439beb93cSSam Leffler 685f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 686f05cddf9SRui Paulo if (conn->rl.tls_version >= TLS_VERSION_1_2) { 687f05cddf9SRui Paulo /* 688f05cddf9SRui Paulo * RFC 5246, 4.7: 689f05cddf9SRui Paulo * TLS v1.2 adds explicit indication of the used signature and 690f05cddf9SRui Paulo * hash algorithms. 691f05cddf9SRui Paulo * 692f05cddf9SRui Paulo * struct { 693f05cddf9SRui Paulo * HashAlgorithm hash; 694f05cddf9SRui Paulo * SignatureAlgorithm signature; 695f05cddf9SRui Paulo * } SignatureAndHashAlgorithm; 696f05cddf9SRui Paulo */ 697f05cddf9SRui Paulo *pos++ = TLS_HASH_ALG_SHA256; 698f05cddf9SRui Paulo *pos++ = TLS_SIGN_ALG_RSA; 699f05cddf9SRui Paulo } 700f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 701f05cddf9SRui Paulo 70239beb93cSSam Leffler /* 70339beb93cSSam Leffler * RFC 2246, 4.7: 70439beb93cSSam Leffler * In digital signing, one-way hash functions are used as input for a 70539beb93cSSam Leffler * signing algorithm. A digitally-signed element is encoded as an 70639beb93cSSam Leffler * opaque vector <0..2^16-1>, where the length is specified by the 70739beb93cSSam Leffler * signing algorithm and key. 70839beb93cSSam Leffler * 70939beb93cSSam Leffler * In RSA signing, a 36-byte structure of two hashes (one SHA and one 71039beb93cSSam Leffler * MD5) is signed (encrypted with the private key). It is encoded with 71139beb93cSSam Leffler * PKCS #1 block type 0 or type 1 as described in [PKCS1]. 71239beb93cSSam Leffler */ 71339beb93cSSam Leffler signed_start = pos; /* length to be filled */ 71439beb93cSSam Leffler pos += 2; 71539beb93cSSam Leffler clen = end - pos; 71639beb93cSSam Leffler if (conn->cred == NULL || 71739beb93cSSam Leffler crypto_private_key_sign_pkcs1(conn->cred->key, hash, hlen, 71839beb93cSSam Leffler pos, &clen) < 0) { 71939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to sign hash (PKCS #1)"); 72039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 72139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 72239beb93cSSam Leffler return -1; 72339beb93cSSam Leffler } 72439beb93cSSam Leffler WPA_PUT_BE16(signed_start, clen); 72539beb93cSSam Leffler 72639beb93cSSam Leffler pos += clen; 72739beb93cSSam Leffler 72839beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 72939beb93cSSam Leffler 73039beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 731f05cddf9SRui Paulo rhdr, end - rhdr, hs_start, pos - hs_start, 732f05cddf9SRui Paulo &rlen) < 0) { 73339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); 73439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 73539beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 73639beb93cSSam Leffler return -1; 73739beb93cSSam Leffler } 73839beb93cSSam Leffler pos = rhdr + rlen; 73939beb93cSSam Leffler 74039beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 74139beb93cSSam Leffler 74239beb93cSSam Leffler *msgpos = pos; 74339beb93cSSam Leffler 74439beb93cSSam Leffler return 0; 74539beb93cSSam Leffler } 74639beb93cSSam Leffler 74739beb93cSSam Leffler 74839beb93cSSam Leffler static int tls_write_client_change_cipher_spec(struct tlsv1_client *conn, 74939beb93cSSam Leffler u8 **msgpos, u8 *end) 75039beb93cSSam Leffler { 75139beb93cSSam Leffler size_t rlen; 752f05cddf9SRui Paulo u8 payload[1]; 75339beb93cSSam Leffler 75439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec"); 755f05cddf9SRui Paulo 756f05cddf9SRui Paulo payload[0] = TLS_CHANGE_CIPHER_SPEC; 757f05cddf9SRui Paulo 75839beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC, 759f05cddf9SRui Paulo *msgpos, end - *msgpos, payload, sizeof(payload), 760f05cddf9SRui Paulo &rlen) < 0) { 76139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); 76239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 76339beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 76439beb93cSSam Leffler return -1; 76539beb93cSSam Leffler } 76639beb93cSSam Leffler 76739beb93cSSam Leffler if (tlsv1_record_change_write_cipher(&conn->rl) < 0) { 76839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for " 76939beb93cSSam Leffler "record layer"); 77039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 77139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 77239beb93cSSam Leffler return -1; 77339beb93cSSam Leffler } 77439beb93cSSam Leffler 775f05cddf9SRui Paulo *msgpos += rlen; 77639beb93cSSam Leffler 77739beb93cSSam Leffler return 0; 77839beb93cSSam Leffler } 77939beb93cSSam Leffler 78039beb93cSSam Leffler 78139beb93cSSam Leffler static int tls_write_client_finished(struct tlsv1_client *conn, 78239beb93cSSam Leffler u8 **msgpos, u8 *end) 78339beb93cSSam Leffler { 784f05cddf9SRui Paulo u8 *pos, *hs_start; 78539beb93cSSam Leffler size_t rlen, hlen; 786f05cddf9SRui Paulo u8 verify_data[1 + 3 + TLS_VERIFY_DATA_LEN]; 78739beb93cSSam Leffler u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; 78839beb93cSSam Leffler 78939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send Finished"); 79039beb93cSSam Leffler 79139beb93cSSam Leffler /* Encrypted Handshake Message: Finished */ 79239beb93cSSam Leffler 793f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 794f05cddf9SRui Paulo if (conn->rl.tls_version >= TLS_VERSION_1_2) { 795f05cddf9SRui Paulo hlen = SHA256_MAC_LEN; 796f05cddf9SRui Paulo if (conn->verify.sha256_client == NULL || 797f05cddf9SRui Paulo crypto_hash_finish(conn->verify.sha256_client, hash, &hlen) 798f05cddf9SRui Paulo < 0) { 799f05cddf9SRui Paulo tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 800f05cddf9SRui Paulo TLS_ALERT_INTERNAL_ERROR); 801f05cddf9SRui Paulo conn->verify.sha256_client = NULL; 802f05cddf9SRui Paulo return -1; 803f05cddf9SRui Paulo } 804f05cddf9SRui Paulo conn->verify.sha256_client = NULL; 805f05cddf9SRui Paulo } else { 806f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 807f05cddf9SRui Paulo 80839beb93cSSam Leffler hlen = MD5_MAC_LEN; 80939beb93cSSam Leffler if (conn->verify.md5_client == NULL || 81039beb93cSSam Leffler crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) { 81139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 81239beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 81339beb93cSSam Leffler conn->verify.md5_client = NULL; 81439beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_client, NULL, NULL); 81539beb93cSSam Leffler conn->verify.sha1_client = NULL; 81639beb93cSSam Leffler return -1; 81739beb93cSSam Leffler } 81839beb93cSSam Leffler conn->verify.md5_client = NULL; 81939beb93cSSam Leffler hlen = SHA1_MAC_LEN; 82039beb93cSSam Leffler if (conn->verify.sha1_client == NULL || 82139beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN, 82239beb93cSSam Leffler &hlen) < 0) { 82339beb93cSSam Leffler conn->verify.sha1_client = NULL; 82439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 82539beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 82639beb93cSSam Leffler return -1; 82739beb93cSSam Leffler } 82839beb93cSSam Leffler conn->verify.sha1_client = NULL; 829f05cddf9SRui Paulo hlen = MD5_MAC_LEN + SHA1_MAC_LEN; 83039beb93cSSam Leffler 831f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 832f05cddf9SRui Paulo } 833f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 834f05cddf9SRui Paulo 835f05cddf9SRui Paulo if (tls_prf(conn->rl.tls_version, 836f05cddf9SRui Paulo conn->master_secret, TLS_MASTER_SECRET_LEN, 837f05cddf9SRui Paulo "client finished", hash, hlen, 838f05cddf9SRui Paulo verify_data + 1 + 3, TLS_VERIFY_DATA_LEN)) { 83939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); 84039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 84139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 84239beb93cSSam Leffler return -1; 84339beb93cSSam Leffler } 84439beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)", 845f05cddf9SRui Paulo verify_data + 1 + 3, TLS_VERIFY_DATA_LEN); 84639beb93cSSam Leffler 84739beb93cSSam Leffler /* Handshake */ 848f05cddf9SRui Paulo pos = hs_start = verify_data; 84939beb93cSSam Leffler /* HandshakeType msg_type */ 85039beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_FINISHED; 851f05cddf9SRui Paulo /* uint24 length */ 852f05cddf9SRui Paulo WPA_PUT_BE24(pos, TLS_VERIFY_DATA_LEN); 85339beb93cSSam Leffler pos += 3; 854f05cddf9SRui Paulo pos += TLS_VERIFY_DATA_LEN; /* verify_data already in place */ 85539beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 85639beb93cSSam Leffler 85739beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 858f05cddf9SRui Paulo *msgpos, end - *msgpos, hs_start, pos - hs_start, 859f05cddf9SRui Paulo &rlen) < 0) { 86039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); 86139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 86239beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 86339beb93cSSam Leffler return -1; 86439beb93cSSam Leffler } 86539beb93cSSam Leffler 866f05cddf9SRui Paulo *msgpos += rlen; 86739beb93cSSam Leffler 86839beb93cSSam Leffler return 0; 86939beb93cSSam Leffler } 87039beb93cSSam Leffler 87139beb93cSSam Leffler 87239beb93cSSam Leffler static u8 * tls_send_client_key_exchange(struct tlsv1_client *conn, 87339beb93cSSam Leffler size_t *out_len) 87439beb93cSSam Leffler { 87539beb93cSSam Leffler u8 *msg, *end, *pos; 87639beb93cSSam Leffler size_t msglen; 87739beb93cSSam Leffler 87839beb93cSSam Leffler *out_len = 0; 87939beb93cSSam Leffler 880f05cddf9SRui Paulo msglen = 2000; 88139beb93cSSam Leffler if (conn->certificate_requested) 88239beb93cSSam Leffler msglen += tls_client_cert_chain_der_len(conn); 88339beb93cSSam Leffler 88439beb93cSSam Leffler msg = os_malloc(msglen); 88539beb93cSSam Leffler if (msg == NULL) 88639beb93cSSam Leffler return NULL; 88739beb93cSSam Leffler 88839beb93cSSam Leffler pos = msg; 88939beb93cSSam Leffler end = msg + msglen; 89039beb93cSSam Leffler 89139beb93cSSam Leffler if (conn->certificate_requested) { 89239beb93cSSam Leffler if (tls_write_client_certificate(conn, &pos, end) < 0) { 89339beb93cSSam Leffler os_free(msg); 89439beb93cSSam Leffler return NULL; 89539beb93cSSam Leffler } 89639beb93cSSam Leffler } 89739beb93cSSam Leffler 89839beb93cSSam Leffler if (tls_write_client_key_exchange(conn, &pos, end) < 0 || 89939beb93cSSam Leffler (conn->certificate_requested && conn->cred && conn->cred->key && 90039beb93cSSam Leffler tls_write_client_certificate_verify(conn, &pos, end) < 0) || 90139beb93cSSam Leffler tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || 90239beb93cSSam Leffler tls_write_client_finished(conn, &pos, end) < 0) { 90339beb93cSSam Leffler os_free(msg); 90439beb93cSSam Leffler return NULL; 90539beb93cSSam Leffler } 90639beb93cSSam Leffler 90739beb93cSSam Leffler *out_len = pos - msg; 90839beb93cSSam Leffler 90939beb93cSSam Leffler conn->state = SERVER_CHANGE_CIPHER_SPEC; 91039beb93cSSam Leffler 91139beb93cSSam Leffler return msg; 91239beb93cSSam Leffler } 91339beb93cSSam Leffler 91439beb93cSSam Leffler 91539beb93cSSam Leffler static u8 * tls_send_change_cipher_spec(struct tlsv1_client *conn, 91639beb93cSSam Leffler size_t *out_len) 91739beb93cSSam Leffler { 91839beb93cSSam Leffler u8 *msg, *end, *pos; 91939beb93cSSam Leffler 92039beb93cSSam Leffler *out_len = 0; 92139beb93cSSam Leffler 92239beb93cSSam Leffler msg = os_malloc(1000); 92339beb93cSSam Leffler if (msg == NULL) 92439beb93cSSam Leffler return NULL; 92539beb93cSSam Leffler 92639beb93cSSam Leffler pos = msg; 92739beb93cSSam Leffler end = msg + 1000; 92839beb93cSSam Leffler 92939beb93cSSam Leffler if (tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || 93039beb93cSSam Leffler tls_write_client_finished(conn, &pos, end) < 0) { 93139beb93cSSam Leffler os_free(msg); 93239beb93cSSam Leffler return NULL; 93339beb93cSSam Leffler } 93439beb93cSSam Leffler 93539beb93cSSam Leffler *out_len = pos - msg; 93639beb93cSSam Leffler 93739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Session resumption completed " 93839beb93cSSam Leffler "successfully"); 939780fb4a2SCy Schubert if (!conn->session_resumed && conn->use_session_ticket) 940780fb4a2SCy Schubert conn->session_resumed = 1; 94139beb93cSSam Leffler conn->state = ESTABLISHED; 94239beb93cSSam Leffler 94339beb93cSSam Leffler return msg; 94439beb93cSSam Leffler } 94539beb93cSSam Leffler 94639beb93cSSam Leffler 94739beb93cSSam Leffler u8 * tlsv1_client_handshake_write(struct tlsv1_client *conn, size_t *out_len, 94839beb93cSSam Leffler int no_appl_data) 94939beb93cSSam Leffler { 95039beb93cSSam Leffler switch (conn->state) { 95139beb93cSSam Leffler case CLIENT_KEY_EXCHANGE: 95239beb93cSSam Leffler return tls_send_client_key_exchange(conn, out_len); 95339beb93cSSam Leffler case CHANGE_CIPHER_SPEC: 95439beb93cSSam Leffler return tls_send_change_cipher_spec(conn, out_len); 95539beb93cSSam Leffler case ACK_FINISHED: 95639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed " 95739beb93cSSam Leffler "successfully"); 95839beb93cSSam Leffler conn->state = ESTABLISHED; 95939beb93cSSam Leffler *out_len = 0; 96039beb93cSSam Leffler if (no_appl_data) { 96139beb93cSSam Leffler /* Need to return something to get final TLS ACK. */ 96239beb93cSSam Leffler return os_malloc(1); 96339beb93cSSam Leffler } 96439beb93cSSam Leffler return NULL; 96539beb93cSSam Leffler default: 96639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while " 96739beb93cSSam Leffler "generating reply", conn->state); 96839beb93cSSam Leffler return NULL; 96939beb93cSSam Leffler } 97039beb93cSSam Leffler } 97139beb93cSSam Leffler 97239beb93cSSam Leffler 97339beb93cSSam Leffler u8 * tlsv1_client_send_alert(struct tlsv1_client *conn, u8 level, 97439beb93cSSam Leffler u8 description, size_t *out_len) 97539beb93cSSam Leffler { 97639beb93cSSam Leffler u8 *alert, *pos, *length; 97739beb93cSSam Leffler 97839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description); 97939beb93cSSam Leffler *out_len = 0; 98039beb93cSSam Leffler 98139beb93cSSam Leffler alert = os_malloc(10); 98239beb93cSSam Leffler if (alert == NULL) 98339beb93cSSam Leffler return NULL; 98439beb93cSSam Leffler 98539beb93cSSam Leffler pos = alert; 98639beb93cSSam Leffler 98739beb93cSSam Leffler /* TLSPlaintext */ 98839beb93cSSam Leffler /* ContentType type */ 98939beb93cSSam Leffler *pos++ = TLS_CONTENT_TYPE_ALERT; 99039beb93cSSam Leffler /* ProtocolVersion version */ 991f05cddf9SRui Paulo WPA_PUT_BE16(pos, conn->rl.tls_version ? conn->rl.tls_version : 992f05cddf9SRui Paulo TLS_VERSION); 99339beb93cSSam Leffler pos += 2; 99439beb93cSSam Leffler /* uint16 length (to be filled) */ 99539beb93cSSam Leffler length = pos; 99639beb93cSSam Leffler pos += 2; 99739beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 99839beb93cSSam Leffler 99939beb93cSSam Leffler /* Alert */ 100039beb93cSSam Leffler /* AlertLevel level */ 100139beb93cSSam Leffler *pos++ = level; 100239beb93cSSam Leffler /* AlertDescription description */ 100339beb93cSSam Leffler *pos++ = description; 100439beb93cSSam Leffler 100539beb93cSSam Leffler WPA_PUT_BE16(length, pos - length - 2); 100639beb93cSSam Leffler *out_len = pos - alert; 100739beb93cSSam Leffler 100839beb93cSSam Leffler return alert; 100939beb93cSSam Leffler } 1010