139beb93cSSam Leffler /* 239beb93cSSam Leffler * TLSv1 client - write handshake message 3*780fb4a2SCy 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; 50*780fb4a2SCy Schubert u8 *ext_start; 51*780fb4a2SCy Schubert u16 tls_version = TLS_VERSION; 5239beb93cSSam Leffler 53*780fb4a2SCy Schubert /* Pick the highest locally enabled TLS version */ 54*780fb4a2SCy Schubert #ifdef CONFIG_TLSV12 55*780fb4a2SCy Schubert if ((conn->flags & TLS_CONN_DISABLE_TLSv1_2) && 56*780fb4a2SCy Schubert tls_version == TLS_VERSION_1_2) 57*780fb4a2SCy Schubert tls_version = TLS_VERSION_1_1; 58*780fb4a2SCy Schubert #endif /* CONFIG_TLSV12 */ 59*780fb4a2SCy Schubert #ifdef CONFIG_TLSV11 60*780fb4a2SCy Schubert if ((conn->flags & TLS_CONN_DISABLE_TLSv1_1) && 61*780fb4a2SCy Schubert tls_version == TLS_VERSION_1_1) 62*780fb4a2SCy Schubert tls_version = TLS_VERSION_1; 63*780fb4a2SCy Schubert #endif /* CONFIG_TLSV11 */ 64*780fb4a2SCy Schubert if ((conn->flags & TLS_CONN_DISABLE_TLSv1_0) && 65*780fb4a2SCy Schubert tls_version == TLS_VERSION_1) { 66*780fb4a2SCy Schubert wpa_printf(MSG_INFO, "TLSv1: No TLS version allowed"); 67*780fb4a2SCy Schubert return NULL; 68*780fb4a2SCy Schubert } 69*780fb4a2SCy Schubert 70*780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello (ver %s)", 71*780fb4a2SCy Schubert tls_version_str(tls_version)); 7239beb93cSSam Leffler *out_len = 0; 7339beb93cSSam Leffler 7439beb93cSSam Leffler os_get_time(&now); 7539beb93cSSam Leffler WPA_PUT_BE32(conn->client_random, now.sec); 76f05cddf9SRui Paulo if (random_get_bytes(conn->client_random + 4, TLS_RANDOM_LEN - 4)) { 7739beb93cSSam Leffler wpa_printf(MSG_ERROR, "TLSv1: Could not generate " 7839beb93cSSam Leffler "client_random"); 7939beb93cSSam Leffler return NULL; 8039beb93cSSam Leffler } 8139beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random", 8239beb93cSSam Leffler conn->client_random, TLS_RANDOM_LEN); 8339beb93cSSam Leffler 84*780fb4a2SCy Schubert len = 150 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len; 8539beb93cSSam Leffler hello = os_malloc(len); 8639beb93cSSam Leffler if (hello == NULL) 8739beb93cSSam Leffler return NULL; 8839beb93cSSam Leffler end = hello + len; 8939beb93cSSam Leffler 9039beb93cSSam Leffler rhdr = hello; 9139beb93cSSam Leffler pos = rhdr + TLS_RECORD_HEADER_LEN; 9239beb93cSSam Leffler 9339beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 9439beb93cSSam Leffler 9539beb93cSSam Leffler /* Handshake */ 9639beb93cSSam Leffler hs_start = pos; 9739beb93cSSam Leffler /* HandshakeType msg_type */ 9839beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_HELLO; 9939beb93cSSam Leffler /* uint24 length (to be filled) */ 10039beb93cSSam Leffler hs_length = pos; 10139beb93cSSam Leffler pos += 3; 10239beb93cSSam Leffler /* body - ClientHello */ 10339beb93cSSam Leffler /* ProtocolVersion client_version */ 104*780fb4a2SCy Schubert WPA_PUT_BE16(pos, tls_version); 10539beb93cSSam Leffler pos += 2; 10639beb93cSSam Leffler /* Random random: uint32 gmt_unix_time, opaque random_bytes */ 10739beb93cSSam Leffler os_memcpy(pos, conn->client_random, TLS_RANDOM_LEN); 10839beb93cSSam Leffler pos += TLS_RANDOM_LEN; 10939beb93cSSam Leffler /* SessionID session_id */ 11039beb93cSSam Leffler *pos++ = conn->session_id_len; 11139beb93cSSam Leffler os_memcpy(pos, conn->session_id, conn->session_id_len); 11239beb93cSSam Leffler pos += conn->session_id_len; 11339beb93cSSam Leffler /* CipherSuite cipher_suites<2..2^16-1> */ 11439beb93cSSam Leffler WPA_PUT_BE16(pos, 2 * conn->num_cipher_suites); 11539beb93cSSam Leffler pos += 2; 11639beb93cSSam Leffler for (i = 0; i < conn->num_cipher_suites; i++) { 11739beb93cSSam Leffler WPA_PUT_BE16(pos, conn->cipher_suites[i]); 11839beb93cSSam Leffler pos += 2; 11939beb93cSSam Leffler } 12039beb93cSSam Leffler /* CompressionMethod compression_methods<1..2^8-1> */ 12139beb93cSSam Leffler *pos++ = 1; 12239beb93cSSam Leffler *pos++ = TLS_COMPRESSION_NULL; 12339beb93cSSam Leffler 124*780fb4a2SCy Schubert /* Extension */ 125*780fb4a2SCy Schubert ext_start = pos; 126*780fb4a2SCy Schubert pos += 2; 127*780fb4a2SCy Schubert 128*780fb4a2SCy Schubert #ifdef CONFIG_TLSV12 129*780fb4a2SCy Schubert if (conn->rl.tls_version >= TLS_VERSION_1_2) { 130*780fb4a2SCy Schubert /* 131*780fb4a2SCy Schubert * Add signature_algorithms extension since we support only 132*780fb4a2SCy Schubert * SHA256 (and not the default SHA1) with TLSv1.2. 133*780fb4a2SCy Schubert */ 134*780fb4a2SCy Schubert /* ExtensionsType extension_type = signature_algorithms(13) */ 135*780fb4a2SCy Schubert WPA_PUT_BE16(pos, TLS_EXT_SIGNATURE_ALGORITHMS); 136*780fb4a2SCy Schubert pos += 2; 137*780fb4a2SCy Schubert /* opaque extension_data<0..2^16-1> length */ 138*780fb4a2SCy Schubert WPA_PUT_BE16(pos, 8); 139*780fb4a2SCy Schubert pos += 2; 140*780fb4a2SCy Schubert /* supported_signature_algorithms<2..2^16-2> length */ 141*780fb4a2SCy Schubert WPA_PUT_BE16(pos, 6); 142*780fb4a2SCy Schubert pos += 2; 143*780fb4a2SCy Schubert /* supported_signature_algorithms */ 144*780fb4a2SCy Schubert *pos++ = TLS_HASH_ALG_SHA512; 145*780fb4a2SCy Schubert *pos++ = TLS_SIGN_ALG_RSA; 146*780fb4a2SCy Schubert *pos++ = TLS_HASH_ALG_SHA384; 147*780fb4a2SCy Schubert *pos++ = TLS_SIGN_ALG_RSA; 148*780fb4a2SCy Schubert *pos++ = TLS_HASH_ALG_SHA256; 149*780fb4a2SCy Schubert *pos++ = TLS_SIGN_ALG_RSA; 150*780fb4a2SCy Schubert } 151*780fb4a2SCy Schubert #endif /* CONFIG_TLSV12 */ 152*780fb4a2SCy Schubert 15339beb93cSSam Leffler if (conn->client_hello_ext) { 15439beb93cSSam Leffler os_memcpy(pos, conn->client_hello_ext, 15539beb93cSSam Leffler conn->client_hello_ext_len); 15639beb93cSSam Leffler pos += conn->client_hello_ext_len; 15739beb93cSSam Leffler } 15839beb93cSSam Leffler 159*780fb4a2SCy Schubert if (conn->flags & TLS_CONN_REQUEST_OCSP) { 160*780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 161*780fb4a2SCy Schubert "TLSv1: Add status_request extension for OCSP stapling"); 162*780fb4a2SCy Schubert /* ExtensionsType extension_type = status_request(5) */ 163*780fb4a2SCy Schubert WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST); 164*780fb4a2SCy Schubert pos += 2; 165*780fb4a2SCy Schubert /* opaque extension_data<0..2^16-1> length */ 166*780fb4a2SCy Schubert WPA_PUT_BE16(pos, 5); 167*780fb4a2SCy Schubert pos += 2; 168*780fb4a2SCy Schubert 169*780fb4a2SCy Schubert /* 170*780fb4a2SCy Schubert * RFC 6066, 8: 171*780fb4a2SCy Schubert * struct { 172*780fb4a2SCy Schubert * CertificateStatusType status_type; 173*780fb4a2SCy Schubert * select (status_type) { 174*780fb4a2SCy Schubert * case ocsp: OCSPStatusRequest; 175*780fb4a2SCy Schubert * } request; 176*780fb4a2SCy Schubert * } CertificateStatusRequest; 177*780fb4a2SCy Schubert * 178*780fb4a2SCy Schubert * enum { ocsp(1), (255) } CertificateStatusType; 179*780fb4a2SCy Schubert */ 180*780fb4a2SCy Schubert *pos++ = 1; /* status_type = ocsp(1) */ 181*780fb4a2SCy Schubert 182*780fb4a2SCy Schubert /* 183*780fb4a2SCy Schubert * struct { 184*780fb4a2SCy Schubert * ResponderID responder_id_list<0..2^16-1>; 185*780fb4a2SCy Schubert * Extensions request_extensions; 186*780fb4a2SCy Schubert * } OCSPStatusRequest; 187*780fb4a2SCy Schubert * 188*780fb4a2SCy Schubert * opaque ResponderID<1..2^16-1>; 189*780fb4a2SCy Schubert * opaque Extensions<0..2^16-1>; 190*780fb4a2SCy Schubert */ 191*780fb4a2SCy Schubert WPA_PUT_BE16(pos, 0); /* responder_id_list(empty) */ 192*780fb4a2SCy Schubert pos += 2; 193*780fb4a2SCy Schubert WPA_PUT_BE16(pos, 0); /* request_extensions(empty) */ 194*780fb4a2SCy Schubert pos += 2; 195*780fb4a2SCy Schubert 196*780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, 197*780fb4a2SCy Schubert "TLSv1: Add status_request_v2 extension for OCSP stapling"); 198*780fb4a2SCy Schubert /* ExtensionsType extension_type = status_request_v2(17) */ 199*780fb4a2SCy Schubert WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST_V2); 200*780fb4a2SCy Schubert pos += 2; 201*780fb4a2SCy Schubert /* opaque extension_data<0..2^16-1> length */ 202*780fb4a2SCy Schubert WPA_PUT_BE16(pos, 7); 203*780fb4a2SCy Schubert pos += 2; 204*780fb4a2SCy Schubert 205*780fb4a2SCy Schubert /* 206*780fb4a2SCy Schubert * RFC 6961, 2.2: 207*780fb4a2SCy Schubert * struct { 208*780fb4a2SCy Schubert * CertificateStatusType status_type; 209*780fb4a2SCy Schubert * uint16 request_length; 210*780fb4a2SCy Schubert * select (status_type) { 211*780fb4a2SCy Schubert * case ocsp: OCSPStatusRequest; 212*780fb4a2SCy Schubert * case ocsp_multi: OCSPStatusRequest; 213*780fb4a2SCy Schubert * } request; 214*780fb4a2SCy Schubert * } CertificateStatusRequestItemV2; 215*780fb4a2SCy Schubert * 216*780fb4a2SCy Schubert * enum { ocsp(1), ocsp_multi(2), (255) } CertificateStatusType; 217*780fb4a2SCy Schubert * 218*780fb4a2SCy Schubert * struct { 219*780fb4a2SCy Schubert * CertificateStatusRequestItemV2 220*780fb4a2SCy Schubert * certificate_status_req_list<1..2^16-1>; 221*780fb4a2SCy Schubert * } CertificateStatusRequestListV2; 222*780fb4a2SCy Schubert */ 223*780fb4a2SCy Schubert 224*780fb4a2SCy Schubert /* certificate_status_req_list<1..2^16-1> */ 225*780fb4a2SCy Schubert WPA_PUT_BE16(pos, 5); 226*780fb4a2SCy Schubert pos += 2; 227*780fb4a2SCy Schubert 228*780fb4a2SCy Schubert /* CertificateStatusRequestItemV2 */ 229*780fb4a2SCy Schubert *pos++ = 2; /* status_type = ocsp_multi(2) */ 230*780fb4a2SCy Schubert /* OCSPStatusRequest as shown above for v1 */ 231*780fb4a2SCy Schubert WPA_PUT_BE16(pos, 0); /* responder_id_list(empty) */ 232*780fb4a2SCy Schubert pos += 2; 233*780fb4a2SCy Schubert WPA_PUT_BE16(pos, 0); /* request_extensions(empty) */ 234*780fb4a2SCy Schubert pos += 2; 235*780fb4a2SCy Schubert } 236*780fb4a2SCy Schubert 237*780fb4a2SCy Schubert if (pos == ext_start + 2) 238*780fb4a2SCy Schubert pos -= 2; /* no extensions */ 239*780fb4a2SCy Schubert else 240*780fb4a2SCy Schubert WPA_PUT_BE16(ext_start, pos - ext_start - 2); 241*780fb4a2SCy Schubert 24239beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 24339beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 24439beb93cSSam Leffler 24539beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 246f05cddf9SRui Paulo rhdr, end - rhdr, hs_start, pos - hs_start, 247f05cddf9SRui Paulo out_len) < 0) { 24839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record"); 24939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 25039beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 25139beb93cSSam Leffler os_free(hello); 25239beb93cSSam Leffler return NULL; 25339beb93cSSam Leffler } 25439beb93cSSam Leffler 25539beb93cSSam Leffler conn->state = SERVER_HELLO; 25639beb93cSSam Leffler 25739beb93cSSam Leffler return hello; 25839beb93cSSam Leffler } 25939beb93cSSam Leffler 26039beb93cSSam Leffler 26139beb93cSSam Leffler static int tls_write_client_certificate(struct tlsv1_client *conn, 26239beb93cSSam Leffler u8 **msgpos, u8 *end) 26339beb93cSSam Leffler { 26439beb93cSSam Leffler u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start; 26539beb93cSSam Leffler size_t rlen; 26639beb93cSSam Leffler struct x509_certificate *cert; 26739beb93cSSam Leffler 26839beb93cSSam Leffler pos = *msgpos; 269*780fb4a2SCy Schubert if (TLS_RECORD_HEADER_LEN + 1 + 3 + 3 > end - pos) { 270*780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 271*780fb4a2SCy Schubert TLS_ALERT_INTERNAL_ERROR); 272*780fb4a2SCy Schubert return -1; 273*780fb4a2SCy Schubert } 27439beb93cSSam Leffler 27539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate"); 27639beb93cSSam Leffler rhdr = pos; 27739beb93cSSam Leffler pos += TLS_RECORD_HEADER_LEN; 27839beb93cSSam Leffler 27939beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 28039beb93cSSam Leffler 28139beb93cSSam Leffler /* Handshake */ 28239beb93cSSam Leffler hs_start = pos; 28339beb93cSSam Leffler /* HandshakeType msg_type */ 28439beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE; 28539beb93cSSam Leffler /* uint24 length (to be filled) */ 28639beb93cSSam Leffler hs_length = pos; 28739beb93cSSam Leffler pos += 3; 28839beb93cSSam Leffler /* body - Certificate */ 28939beb93cSSam Leffler /* uint24 length (to be filled) */ 29039beb93cSSam Leffler cert_start = pos; 29139beb93cSSam Leffler pos += 3; 29239beb93cSSam Leffler cert = conn->cred ? conn->cred->cert : NULL; 29339beb93cSSam Leffler while (cert) { 294*780fb4a2SCy Schubert if (3 + cert->cert_len > (size_t) (end - pos)) { 29539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space " 29639beb93cSSam Leffler "for Certificate (cert_len=%lu left=%lu)", 29739beb93cSSam Leffler (unsigned long) cert->cert_len, 29839beb93cSSam Leffler (unsigned long) (end - pos)); 29939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 30039beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 30139beb93cSSam Leffler return -1; 30239beb93cSSam Leffler } 30339beb93cSSam Leffler WPA_PUT_BE24(pos, cert->cert_len); 30439beb93cSSam Leffler pos += 3; 30539beb93cSSam Leffler os_memcpy(pos, cert->cert_start, cert->cert_len); 30639beb93cSSam Leffler pos += cert->cert_len; 30739beb93cSSam Leffler 30839beb93cSSam Leffler if (x509_certificate_self_signed(cert)) 30939beb93cSSam Leffler break; 31039beb93cSSam Leffler cert = x509_certificate_get_subject(conn->cred->trusted_certs, 31139beb93cSSam Leffler &cert->issuer); 31239beb93cSSam Leffler } 31339beb93cSSam Leffler if (conn->cred == NULL || cert == conn->cred->cert || cert == NULL) { 31439beb93cSSam Leffler /* 31539beb93cSSam Leffler * Client was not configured with all the needed certificates 31639beb93cSSam Leffler * to form a full certificate chain. The server may fail to 31739beb93cSSam Leffler * validate the chain unless it is configured with all the 31839beb93cSSam Leffler * missing CA certificates. 31939beb93cSSam Leffler */ 32039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Full client certificate chain " 32139beb93cSSam Leffler "not configured - validation may fail"); 32239beb93cSSam Leffler } 32339beb93cSSam Leffler WPA_PUT_BE24(cert_start, pos - cert_start - 3); 32439beb93cSSam Leffler 32539beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 32639beb93cSSam Leffler 32739beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 328f05cddf9SRui Paulo rhdr, end - rhdr, hs_start, pos - hs_start, 329f05cddf9SRui Paulo &rlen) < 0) { 33039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); 33139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 33239beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 33339beb93cSSam Leffler return -1; 33439beb93cSSam Leffler } 33539beb93cSSam Leffler pos = rhdr + rlen; 33639beb93cSSam Leffler 33739beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 33839beb93cSSam Leffler 33939beb93cSSam Leffler *msgpos = pos; 34039beb93cSSam Leffler 34139beb93cSSam Leffler return 0; 34239beb93cSSam Leffler } 34339beb93cSSam Leffler 34439beb93cSSam Leffler 3455b9c547cSRui Paulo static int tlsv1_key_x_dh(struct tlsv1_client *conn, u8 **pos, u8 *end) 34639beb93cSSam Leffler { 34739beb93cSSam Leffler /* ClientDiffieHellmanPublic */ 34839beb93cSSam Leffler u8 *csecret, *csecret_start, *dh_yc, *shared; 34939beb93cSSam Leffler size_t csecret_len, dh_yc_len, shared_len; 35039beb93cSSam Leffler 35139beb93cSSam Leffler csecret_len = conn->dh_p_len; 35239beb93cSSam Leffler csecret = os_malloc(csecret_len); 35339beb93cSSam Leffler if (csecret == NULL) { 35439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " 35539beb93cSSam Leffler "memory for Yc (Diffie-Hellman)"); 35639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 35739beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 35839beb93cSSam Leffler return -1; 35939beb93cSSam Leffler } 360f05cddf9SRui Paulo if (random_get_bytes(csecret, csecret_len)) { 36139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " 36239beb93cSSam Leffler "data for Diffie-Hellman"); 36339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 36439beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 36539beb93cSSam Leffler os_free(csecret); 36639beb93cSSam Leffler return -1; 36739beb93cSSam Leffler } 36839beb93cSSam Leffler 36939beb93cSSam Leffler if (os_memcmp(csecret, conn->dh_p, csecret_len) > 0) 37039beb93cSSam Leffler csecret[0] = 0; /* make sure Yc < p */ 37139beb93cSSam Leffler 37239beb93cSSam Leffler csecret_start = csecret; 37339beb93cSSam Leffler while (csecret_len > 1 && *csecret_start == 0) { 37439beb93cSSam Leffler csecret_start++; 37539beb93cSSam Leffler csecret_len--; 37639beb93cSSam Leffler } 37739beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH client's secret value", 37839beb93cSSam Leffler csecret_start, csecret_len); 37939beb93cSSam Leffler 38039beb93cSSam Leffler /* Yc = g^csecret mod p */ 38139beb93cSSam Leffler dh_yc_len = conn->dh_p_len; 38239beb93cSSam Leffler dh_yc = os_malloc(dh_yc_len); 38339beb93cSSam Leffler if (dh_yc == NULL) { 38439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " 38539beb93cSSam Leffler "memory for Diffie-Hellman"); 38639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 38739beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 38839beb93cSSam Leffler os_free(csecret); 38939beb93cSSam Leffler return -1; 39039beb93cSSam Leffler } 39139beb93cSSam Leffler if (crypto_mod_exp(conn->dh_g, conn->dh_g_len, 39239beb93cSSam Leffler csecret_start, csecret_len, 39339beb93cSSam Leffler conn->dh_p, conn->dh_p_len, 39439beb93cSSam Leffler dh_yc, &dh_yc_len)) { 39539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 39639beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 39739beb93cSSam Leffler os_free(csecret); 39839beb93cSSam Leffler os_free(dh_yc); 39939beb93cSSam Leffler return -1; 40039beb93cSSam Leffler } 40139beb93cSSam Leffler 40239beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)", 40339beb93cSSam Leffler dh_yc, dh_yc_len); 40439beb93cSSam Leffler 405*780fb4a2SCy Schubert if (end - *pos < 2) { 406*780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 407*780fb4a2SCy Schubert TLS_ALERT_INTERNAL_ERROR); 408*780fb4a2SCy Schubert os_free(csecret); 409*780fb4a2SCy Schubert os_free(dh_yc); 410*780fb4a2SCy Schubert return -1; 411*780fb4a2SCy Schubert } 41239beb93cSSam Leffler WPA_PUT_BE16(*pos, dh_yc_len); 41339beb93cSSam Leffler *pos += 2; 414*780fb4a2SCy Schubert if (dh_yc_len > (size_t) (end - *pos)) { 41539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Not enough room in the " 41639beb93cSSam Leffler "message buffer for Yc"); 41739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 41839beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 41939beb93cSSam Leffler os_free(csecret); 42039beb93cSSam Leffler os_free(dh_yc); 42139beb93cSSam Leffler return -1; 42239beb93cSSam Leffler } 42339beb93cSSam Leffler os_memcpy(*pos, dh_yc, dh_yc_len); 42439beb93cSSam Leffler *pos += dh_yc_len; 42539beb93cSSam Leffler os_free(dh_yc); 42639beb93cSSam Leffler 42739beb93cSSam Leffler shared_len = conn->dh_p_len; 42839beb93cSSam Leffler shared = os_malloc(shared_len); 42939beb93cSSam Leffler if (shared == NULL) { 43039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for " 43139beb93cSSam Leffler "DH"); 43239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 43339beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 43439beb93cSSam Leffler os_free(csecret); 43539beb93cSSam Leffler return -1; 43639beb93cSSam Leffler } 43739beb93cSSam Leffler 43839beb93cSSam Leffler /* shared = Ys^csecret mod p */ 43939beb93cSSam Leffler if (crypto_mod_exp(conn->dh_ys, conn->dh_ys_len, 44039beb93cSSam Leffler csecret_start, csecret_len, 44139beb93cSSam Leffler conn->dh_p, conn->dh_p_len, 44239beb93cSSam Leffler shared, &shared_len)) { 44339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 44439beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 44539beb93cSSam Leffler os_free(csecret); 44639beb93cSSam Leffler os_free(shared); 44739beb93cSSam Leffler return -1; 44839beb93cSSam Leffler } 44939beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange", 45039beb93cSSam Leffler shared, shared_len); 45139beb93cSSam Leffler 45239beb93cSSam Leffler os_memset(csecret_start, 0, csecret_len); 45339beb93cSSam Leffler os_free(csecret); 45439beb93cSSam Leffler if (tls_derive_keys(conn, shared, shared_len)) { 45539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); 45639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 45739beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 45839beb93cSSam Leffler os_free(shared); 45939beb93cSSam Leffler return -1; 46039beb93cSSam Leffler } 46139beb93cSSam Leffler os_memset(shared, 0, shared_len); 46239beb93cSSam Leffler os_free(shared); 46339beb93cSSam Leffler tlsv1_client_free_dh(conn); 46439beb93cSSam Leffler return 0; 46539beb93cSSam Leffler } 46639beb93cSSam Leffler 46739beb93cSSam Leffler 46839beb93cSSam Leffler static int tlsv1_key_x_rsa(struct tlsv1_client *conn, u8 **pos, u8 *end) 46939beb93cSSam Leffler { 47039beb93cSSam Leffler u8 pre_master_secret[TLS_PRE_MASTER_SECRET_LEN]; 47139beb93cSSam Leffler size_t clen; 47239beb93cSSam Leffler int res; 47339beb93cSSam Leffler 47439beb93cSSam Leffler if (tls_derive_pre_master_secret(pre_master_secret) < 0 || 47539beb93cSSam Leffler tls_derive_keys(conn, pre_master_secret, 47639beb93cSSam Leffler TLS_PRE_MASTER_SECRET_LEN)) { 47739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); 47839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 47939beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 48039beb93cSSam Leffler return -1; 48139beb93cSSam Leffler } 48239beb93cSSam Leffler 48339beb93cSSam Leffler /* EncryptedPreMasterSecret */ 48439beb93cSSam Leffler if (conn->server_rsa_key == NULL) { 48539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: No server RSA key to " 48639beb93cSSam Leffler "use for encrypting pre-master secret"); 48739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 48839beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 48939beb93cSSam Leffler return -1; 49039beb93cSSam Leffler } 49139beb93cSSam Leffler 49239beb93cSSam Leffler /* RSA encrypted value is encoded with PKCS #1 v1.5 block type 2. */ 49339beb93cSSam Leffler *pos += 2; 49439beb93cSSam Leffler clen = end - *pos; 49539beb93cSSam Leffler res = crypto_public_key_encrypt_pkcs1_v15( 49639beb93cSSam Leffler conn->server_rsa_key, 49739beb93cSSam Leffler pre_master_secret, TLS_PRE_MASTER_SECRET_LEN, 49839beb93cSSam Leffler *pos, &clen); 49939beb93cSSam Leffler os_memset(pre_master_secret, 0, TLS_PRE_MASTER_SECRET_LEN); 50039beb93cSSam Leffler if (res < 0) { 50139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: RSA encryption failed"); 50239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 50339beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 50439beb93cSSam Leffler return -1; 50539beb93cSSam Leffler } 50639beb93cSSam Leffler WPA_PUT_BE16(*pos - 2, clen); 50739beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: Encrypted pre_master_secret", 50839beb93cSSam Leffler *pos, clen); 50939beb93cSSam Leffler *pos += clen; 51039beb93cSSam Leffler 51139beb93cSSam Leffler return 0; 51239beb93cSSam Leffler } 51339beb93cSSam Leffler 51439beb93cSSam Leffler 51539beb93cSSam Leffler static int tls_write_client_key_exchange(struct tlsv1_client *conn, 51639beb93cSSam Leffler u8 **msgpos, u8 *end) 51739beb93cSSam Leffler { 51839beb93cSSam Leffler u8 *pos, *rhdr, *hs_start, *hs_length; 51939beb93cSSam Leffler size_t rlen; 52039beb93cSSam Leffler tls_key_exchange keyx; 52139beb93cSSam Leffler const struct tls_cipher_suite *suite; 52239beb93cSSam Leffler 52339beb93cSSam Leffler suite = tls_get_cipher_suite(conn->rl.cipher_suite); 52439beb93cSSam Leffler if (suite == NULL) 52539beb93cSSam Leffler keyx = TLS_KEY_X_NULL; 52639beb93cSSam Leffler else 52739beb93cSSam Leffler keyx = suite->key_exchange; 52839beb93cSSam Leffler 52939beb93cSSam Leffler pos = *msgpos; 53039beb93cSSam Leffler 53139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send ClientKeyExchange"); 53239beb93cSSam Leffler 53339beb93cSSam Leffler rhdr = pos; 53439beb93cSSam Leffler pos += TLS_RECORD_HEADER_LEN; 53539beb93cSSam Leffler 53639beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 53739beb93cSSam Leffler 53839beb93cSSam Leffler /* Handshake */ 53939beb93cSSam Leffler hs_start = pos; 54039beb93cSSam Leffler /* HandshakeType msg_type */ 54139beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE; 54239beb93cSSam Leffler /* uint24 length (to be filled) */ 54339beb93cSSam Leffler hs_length = pos; 54439beb93cSSam Leffler pos += 3; 54539beb93cSSam Leffler /* body - ClientKeyExchange */ 5465b9c547cSRui Paulo if (keyx == TLS_KEY_X_DH_anon || keyx == TLS_KEY_X_DHE_RSA) { 5475b9c547cSRui Paulo if (tlsv1_key_x_dh(conn, &pos, end) < 0) 54839beb93cSSam Leffler return -1; 54939beb93cSSam Leffler } else { 55039beb93cSSam Leffler if (tlsv1_key_x_rsa(conn, &pos, end) < 0) 55139beb93cSSam Leffler return -1; 55239beb93cSSam Leffler } 55339beb93cSSam Leffler 55439beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 55539beb93cSSam Leffler 55639beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 557f05cddf9SRui Paulo rhdr, end - rhdr, hs_start, pos - hs_start, 558f05cddf9SRui Paulo &rlen) < 0) { 55939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); 56039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 56139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 56239beb93cSSam Leffler return -1; 56339beb93cSSam Leffler } 56439beb93cSSam Leffler pos = rhdr + rlen; 56539beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 56639beb93cSSam Leffler 56739beb93cSSam Leffler *msgpos = pos; 56839beb93cSSam Leffler 56939beb93cSSam Leffler return 0; 57039beb93cSSam Leffler } 57139beb93cSSam Leffler 57239beb93cSSam Leffler 57339beb93cSSam Leffler static int tls_write_client_certificate_verify(struct tlsv1_client *conn, 57439beb93cSSam Leffler u8 **msgpos, u8 *end) 57539beb93cSSam Leffler { 57639beb93cSSam Leffler u8 *pos, *rhdr, *hs_start, *hs_length, *signed_start; 57739beb93cSSam Leffler size_t rlen, hlen, clen; 578f05cddf9SRui Paulo u8 hash[100], *hpos; 57939beb93cSSam Leffler 58039beb93cSSam Leffler pos = *msgpos; 58139beb93cSSam Leffler 58239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateVerify"); 58339beb93cSSam Leffler rhdr = pos; 58439beb93cSSam Leffler pos += TLS_RECORD_HEADER_LEN; 58539beb93cSSam Leffler 58639beb93cSSam Leffler /* Handshake */ 58739beb93cSSam Leffler hs_start = pos; 58839beb93cSSam Leffler /* HandshakeType msg_type */ 58939beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY; 59039beb93cSSam Leffler /* uint24 length (to be filled) */ 59139beb93cSSam Leffler hs_length = pos; 59239beb93cSSam Leffler pos += 3; 59339beb93cSSam Leffler 59439beb93cSSam Leffler /* 59539beb93cSSam Leffler * RFC 2246: 7.4.3 and 7.4.8: 59639beb93cSSam Leffler * Signature signature 59739beb93cSSam Leffler * 59839beb93cSSam Leffler * RSA: 59939beb93cSSam Leffler * digitally-signed struct { 60039beb93cSSam Leffler * opaque md5_hash[16]; 60139beb93cSSam Leffler * opaque sha_hash[20]; 60239beb93cSSam Leffler * }; 60339beb93cSSam Leffler * 60439beb93cSSam Leffler * DSA: 60539beb93cSSam Leffler * digitally-signed struct { 60639beb93cSSam Leffler * opaque sha_hash[20]; 60739beb93cSSam Leffler * }; 60839beb93cSSam Leffler * 60939beb93cSSam Leffler * The hash values are calculated over all handshake messages sent or 61039beb93cSSam Leffler * received starting at ClientHello up to, but not including, this 61139beb93cSSam Leffler * CertificateVerify message, including the type and length fields of 61239beb93cSSam Leffler * the handshake messages. 61339beb93cSSam Leffler */ 61439beb93cSSam Leffler 61539beb93cSSam Leffler hpos = hash; 61639beb93cSSam Leffler 617f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 618f05cddf9SRui Paulo if (conn->rl.tls_version == TLS_VERSION_1_2) { 619f05cddf9SRui Paulo hlen = SHA256_MAC_LEN; 620f05cddf9SRui Paulo if (conn->verify.sha256_cert == NULL || 621f05cddf9SRui Paulo crypto_hash_finish(conn->verify.sha256_cert, hpos, &hlen) < 622f05cddf9SRui Paulo 0) { 623f05cddf9SRui Paulo conn->verify.sha256_cert = NULL; 624f05cddf9SRui Paulo tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 625f05cddf9SRui Paulo TLS_ALERT_INTERNAL_ERROR); 626f05cddf9SRui Paulo return -1; 627f05cddf9SRui Paulo } 628f05cddf9SRui Paulo conn->verify.sha256_cert = NULL; 629f05cddf9SRui Paulo 630f05cddf9SRui Paulo /* 631f05cddf9SRui Paulo * RFC 3447, A.2.4 RSASSA-PKCS1-v1_5 632f05cddf9SRui Paulo * 633f05cddf9SRui Paulo * DigestInfo ::= SEQUENCE { 634f05cddf9SRui Paulo * digestAlgorithm DigestAlgorithm, 635f05cddf9SRui Paulo * digest OCTET STRING 636f05cddf9SRui Paulo * } 637f05cddf9SRui Paulo * 638f05cddf9SRui Paulo * SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11} 639f05cddf9SRui Paulo * 640f05cddf9SRui Paulo * DER encoded DigestInfo for SHA256 per RFC 3447: 641f05cddf9SRui Paulo * 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || 642f05cddf9SRui Paulo * H 643f05cddf9SRui Paulo */ 644f05cddf9SRui Paulo os_memmove(hash + 19, hash, hlen); 645f05cddf9SRui Paulo hlen += 19; 646f05cddf9SRui Paulo os_memcpy(hash, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65" 647f05cddf9SRui Paulo "\x03\x04\x02\x01\x05\x00\x04\x20", 19); 648f05cddf9SRui Paulo } else { 649f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 650f05cddf9SRui Paulo 65139beb93cSSam Leffler hlen = MD5_MAC_LEN; 65239beb93cSSam Leffler if (conn->verify.md5_cert == NULL || 6535b9c547cSRui Paulo crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) { 65439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 65539beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 65639beb93cSSam Leffler conn->verify.md5_cert = NULL; 65739beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL); 65839beb93cSSam Leffler conn->verify.sha1_cert = NULL; 65939beb93cSSam Leffler return -1; 66039beb93cSSam Leffler } 66139beb93cSSam Leffler hpos += MD5_MAC_LEN; 66239beb93cSSam Leffler 66339beb93cSSam Leffler conn->verify.md5_cert = NULL; 66439beb93cSSam Leffler hlen = SHA1_MAC_LEN; 66539beb93cSSam Leffler if (conn->verify.sha1_cert == NULL || 66639beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) { 66739beb93cSSam Leffler conn->verify.sha1_cert = NULL; 66839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 66939beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 67039beb93cSSam Leffler return -1; 67139beb93cSSam Leffler } 67239beb93cSSam Leffler conn->verify.sha1_cert = NULL; 67339beb93cSSam Leffler 67439beb93cSSam Leffler hlen += MD5_MAC_LEN; 67539beb93cSSam Leffler 676f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 677f05cddf9SRui Paulo } 678f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 679f05cddf9SRui Paulo 68039beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen); 68139beb93cSSam Leffler 682f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 683f05cddf9SRui Paulo if (conn->rl.tls_version >= TLS_VERSION_1_2) { 684f05cddf9SRui Paulo /* 685f05cddf9SRui Paulo * RFC 5246, 4.7: 686f05cddf9SRui Paulo * TLS v1.2 adds explicit indication of the used signature and 687f05cddf9SRui Paulo * hash algorithms. 688f05cddf9SRui Paulo * 689f05cddf9SRui Paulo * struct { 690f05cddf9SRui Paulo * HashAlgorithm hash; 691f05cddf9SRui Paulo * SignatureAlgorithm signature; 692f05cddf9SRui Paulo * } SignatureAndHashAlgorithm; 693f05cddf9SRui Paulo */ 694f05cddf9SRui Paulo *pos++ = TLS_HASH_ALG_SHA256; 695f05cddf9SRui Paulo *pos++ = TLS_SIGN_ALG_RSA; 696f05cddf9SRui Paulo } 697f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 698f05cddf9SRui Paulo 69939beb93cSSam Leffler /* 70039beb93cSSam Leffler * RFC 2246, 4.7: 70139beb93cSSam Leffler * In digital signing, one-way hash functions are used as input for a 70239beb93cSSam Leffler * signing algorithm. A digitally-signed element is encoded as an 70339beb93cSSam Leffler * opaque vector <0..2^16-1>, where the length is specified by the 70439beb93cSSam Leffler * signing algorithm and key. 70539beb93cSSam Leffler * 70639beb93cSSam Leffler * In RSA signing, a 36-byte structure of two hashes (one SHA and one 70739beb93cSSam Leffler * MD5) is signed (encrypted with the private key). It is encoded with 70839beb93cSSam Leffler * PKCS #1 block type 0 or type 1 as described in [PKCS1]. 70939beb93cSSam Leffler */ 71039beb93cSSam Leffler signed_start = pos; /* length to be filled */ 71139beb93cSSam Leffler pos += 2; 71239beb93cSSam Leffler clen = end - pos; 71339beb93cSSam Leffler if (conn->cred == NULL || 71439beb93cSSam Leffler crypto_private_key_sign_pkcs1(conn->cred->key, hash, hlen, 71539beb93cSSam Leffler pos, &clen) < 0) { 71639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to sign hash (PKCS #1)"); 71739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 71839beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 71939beb93cSSam Leffler return -1; 72039beb93cSSam Leffler } 72139beb93cSSam Leffler WPA_PUT_BE16(signed_start, clen); 72239beb93cSSam Leffler 72339beb93cSSam Leffler pos += clen; 72439beb93cSSam Leffler 72539beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 72639beb93cSSam Leffler 72739beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 728f05cddf9SRui Paulo rhdr, end - rhdr, hs_start, pos - hs_start, 729f05cddf9SRui Paulo &rlen) < 0) { 73039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); 73139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 73239beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 73339beb93cSSam Leffler return -1; 73439beb93cSSam Leffler } 73539beb93cSSam Leffler pos = rhdr + rlen; 73639beb93cSSam Leffler 73739beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 73839beb93cSSam Leffler 73939beb93cSSam Leffler *msgpos = pos; 74039beb93cSSam Leffler 74139beb93cSSam Leffler return 0; 74239beb93cSSam Leffler } 74339beb93cSSam Leffler 74439beb93cSSam Leffler 74539beb93cSSam Leffler static int tls_write_client_change_cipher_spec(struct tlsv1_client *conn, 74639beb93cSSam Leffler u8 **msgpos, u8 *end) 74739beb93cSSam Leffler { 74839beb93cSSam Leffler size_t rlen; 749f05cddf9SRui Paulo u8 payload[1]; 75039beb93cSSam Leffler 75139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec"); 752f05cddf9SRui Paulo 753f05cddf9SRui Paulo payload[0] = TLS_CHANGE_CIPHER_SPEC; 754f05cddf9SRui Paulo 75539beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC, 756f05cddf9SRui Paulo *msgpos, end - *msgpos, payload, sizeof(payload), 757f05cddf9SRui Paulo &rlen) < 0) { 75839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); 75939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 76039beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 76139beb93cSSam Leffler return -1; 76239beb93cSSam Leffler } 76339beb93cSSam Leffler 76439beb93cSSam Leffler if (tlsv1_record_change_write_cipher(&conn->rl) < 0) { 76539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for " 76639beb93cSSam Leffler "record layer"); 76739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 76839beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 76939beb93cSSam Leffler return -1; 77039beb93cSSam Leffler } 77139beb93cSSam Leffler 772f05cddf9SRui Paulo *msgpos += rlen; 77339beb93cSSam Leffler 77439beb93cSSam Leffler return 0; 77539beb93cSSam Leffler } 77639beb93cSSam Leffler 77739beb93cSSam Leffler 77839beb93cSSam Leffler static int tls_write_client_finished(struct tlsv1_client *conn, 77939beb93cSSam Leffler u8 **msgpos, u8 *end) 78039beb93cSSam Leffler { 781f05cddf9SRui Paulo u8 *pos, *hs_start; 78239beb93cSSam Leffler size_t rlen, hlen; 783f05cddf9SRui Paulo u8 verify_data[1 + 3 + TLS_VERIFY_DATA_LEN]; 78439beb93cSSam Leffler u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; 78539beb93cSSam Leffler 78639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send Finished"); 78739beb93cSSam Leffler 78839beb93cSSam Leffler /* Encrypted Handshake Message: Finished */ 78939beb93cSSam Leffler 790f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 791f05cddf9SRui Paulo if (conn->rl.tls_version >= TLS_VERSION_1_2) { 792f05cddf9SRui Paulo hlen = SHA256_MAC_LEN; 793f05cddf9SRui Paulo if (conn->verify.sha256_client == NULL || 794f05cddf9SRui Paulo crypto_hash_finish(conn->verify.sha256_client, hash, &hlen) 795f05cddf9SRui Paulo < 0) { 796f05cddf9SRui Paulo tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 797f05cddf9SRui Paulo TLS_ALERT_INTERNAL_ERROR); 798f05cddf9SRui Paulo conn->verify.sha256_client = NULL; 799f05cddf9SRui Paulo return -1; 800f05cddf9SRui Paulo } 801f05cddf9SRui Paulo conn->verify.sha256_client = NULL; 802f05cddf9SRui Paulo } else { 803f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 804f05cddf9SRui Paulo 80539beb93cSSam Leffler hlen = MD5_MAC_LEN; 80639beb93cSSam Leffler if (conn->verify.md5_client == NULL || 80739beb93cSSam Leffler crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) { 80839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 80939beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 81039beb93cSSam Leffler conn->verify.md5_client = NULL; 81139beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_client, NULL, NULL); 81239beb93cSSam Leffler conn->verify.sha1_client = NULL; 81339beb93cSSam Leffler return -1; 81439beb93cSSam Leffler } 81539beb93cSSam Leffler conn->verify.md5_client = NULL; 81639beb93cSSam Leffler hlen = SHA1_MAC_LEN; 81739beb93cSSam Leffler if (conn->verify.sha1_client == NULL || 81839beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN, 81939beb93cSSam Leffler &hlen) < 0) { 82039beb93cSSam Leffler conn->verify.sha1_client = NULL; 82139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 82239beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 82339beb93cSSam Leffler return -1; 82439beb93cSSam Leffler } 82539beb93cSSam Leffler conn->verify.sha1_client = NULL; 826f05cddf9SRui Paulo hlen = MD5_MAC_LEN + SHA1_MAC_LEN; 82739beb93cSSam Leffler 828f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 829f05cddf9SRui Paulo } 830f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 831f05cddf9SRui Paulo 832f05cddf9SRui Paulo if (tls_prf(conn->rl.tls_version, 833f05cddf9SRui Paulo conn->master_secret, TLS_MASTER_SECRET_LEN, 834f05cddf9SRui Paulo "client finished", hash, hlen, 835f05cddf9SRui Paulo verify_data + 1 + 3, TLS_VERIFY_DATA_LEN)) { 83639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); 83739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 83839beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 83939beb93cSSam Leffler return -1; 84039beb93cSSam Leffler } 84139beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)", 842f05cddf9SRui Paulo verify_data + 1 + 3, TLS_VERIFY_DATA_LEN); 84339beb93cSSam Leffler 84439beb93cSSam Leffler /* Handshake */ 845f05cddf9SRui Paulo pos = hs_start = verify_data; 84639beb93cSSam Leffler /* HandshakeType msg_type */ 84739beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_FINISHED; 848f05cddf9SRui Paulo /* uint24 length */ 849f05cddf9SRui Paulo WPA_PUT_BE24(pos, TLS_VERIFY_DATA_LEN); 85039beb93cSSam Leffler pos += 3; 851f05cddf9SRui Paulo pos += TLS_VERIFY_DATA_LEN; /* verify_data already in place */ 85239beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 85339beb93cSSam Leffler 85439beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 855f05cddf9SRui Paulo *msgpos, end - *msgpos, hs_start, pos - hs_start, 856f05cddf9SRui Paulo &rlen) < 0) { 85739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); 85839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 85939beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 86039beb93cSSam Leffler return -1; 86139beb93cSSam Leffler } 86239beb93cSSam Leffler 863f05cddf9SRui Paulo *msgpos += rlen; 86439beb93cSSam Leffler 86539beb93cSSam Leffler return 0; 86639beb93cSSam Leffler } 86739beb93cSSam Leffler 86839beb93cSSam Leffler 86939beb93cSSam Leffler static u8 * tls_send_client_key_exchange(struct tlsv1_client *conn, 87039beb93cSSam Leffler size_t *out_len) 87139beb93cSSam Leffler { 87239beb93cSSam Leffler u8 *msg, *end, *pos; 87339beb93cSSam Leffler size_t msglen; 87439beb93cSSam Leffler 87539beb93cSSam Leffler *out_len = 0; 87639beb93cSSam Leffler 877f05cddf9SRui Paulo msglen = 2000; 87839beb93cSSam Leffler if (conn->certificate_requested) 87939beb93cSSam Leffler msglen += tls_client_cert_chain_der_len(conn); 88039beb93cSSam Leffler 88139beb93cSSam Leffler msg = os_malloc(msglen); 88239beb93cSSam Leffler if (msg == NULL) 88339beb93cSSam Leffler return NULL; 88439beb93cSSam Leffler 88539beb93cSSam Leffler pos = msg; 88639beb93cSSam Leffler end = msg + msglen; 88739beb93cSSam Leffler 88839beb93cSSam Leffler if (conn->certificate_requested) { 88939beb93cSSam Leffler if (tls_write_client_certificate(conn, &pos, end) < 0) { 89039beb93cSSam Leffler os_free(msg); 89139beb93cSSam Leffler return NULL; 89239beb93cSSam Leffler } 89339beb93cSSam Leffler } 89439beb93cSSam Leffler 89539beb93cSSam Leffler if (tls_write_client_key_exchange(conn, &pos, end) < 0 || 89639beb93cSSam Leffler (conn->certificate_requested && conn->cred && conn->cred->key && 89739beb93cSSam Leffler tls_write_client_certificate_verify(conn, &pos, end) < 0) || 89839beb93cSSam Leffler tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || 89939beb93cSSam Leffler tls_write_client_finished(conn, &pos, end) < 0) { 90039beb93cSSam Leffler os_free(msg); 90139beb93cSSam Leffler return NULL; 90239beb93cSSam Leffler } 90339beb93cSSam Leffler 90439beb93cSSam Leffler *out_len = pos - msg; 90539beb93cSSam Leffler 90639beb93cSSam Leffler conn->state = SERVER_CHANGE_CIPHER_SPEC; 90739beb93cSSam Leffler 90839beb93cSSam Leffler return msg; 90939beb93cSSam Leffler } 91039beb93cSSam Leffler 91139beb93cSSam Leffler 91239beb93cSSam Leffler static u8 * tls_send_change_cipher_spec(struct tlsv1_client *conn, 91339beb93cSSam Leffler size_t *out_len) 91439beb93cSSam Leffler { 91539beb93cSSam Leffler u8 *msg, *end, *pos; 91639beb93cSSam Leffler 91739beb93cSSam Leffler *out_len = 0; 91839beb93cSSam Leffler 91939beb93cSSam Leffler msg = os_malloc(1000); 92039beb93cSSam Leffler if (msg == NULL) 92139beb93cSSam Leffler return NULL; 92239beb93cSSam Leffler 92339beb93cSSam Leffler pos = msg; 92439beb93cSSam Leffler end = msg + 1000; 92539beb93cSSam Leffler 92639beb93cSSam Leffler if (tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || 92739beb93cSSam Leffler tls_write_client_finished(conn, &pos, end) < 0) { 92839beb93cSSam Leffler os_free(msg); 92939beb93cSSam Leffler return NULL; 93039beb93cSSam Leffler } 93139beb93cSSam Leffler 93239beb93cSSam Leffler *out_len = pos - msg; 93339beb93cSSam Leffler 93439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Session resumption completed " 93539beb93cSSam Leffler "successfully"); 936*780fb4a2SCy Schubert if (!conn->session_resumed && conn->use_session_ticket) 937*780fb4a2SCy Schubert conn->session_resumed = 1; 93839beb93cSSam Leffler conn->state = ESTABLISHED; 93939beb93cSSam Leffler 94039beb93cSSam Leffler return msg; 94139beb93cSSam Leffler } 94239beb93cSSam Leffler 94339beb93cSSam Leffler 94439beb93cSSam Leffler u8 * tlsv1_client_handshake_write(struct tlsv1_client *conn, size_t *out_len, 94539beb93cSSam Leffler int no_appl_data) 94639beb93cSSam Leffler { 94739beb93cSSam Leffler switch (conn->state) { 94839beb93cSSam Leffler case CLIENT_KEY_EXCHANGE: 94939beb93cSSam Leffler return tls_send_client_key_exchange(conn, out_len); 95039beb93cSSam Leffler case CHANGE_CIPHER_SPEC: 95139beb93cSSam Leffler return tls_send_change_cipher_spec(conn, out_len); 95239beb93cSSam Leffler case ACK_FINISHED: 95339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed " 95439beb93cSSam Leffler "successfully"); 95539beb93cSSam Leffler conn->state = ESTABLISHED; 95639beb93cSSam Leffler *out_len = 0; 95739beb93cSSam Leffler if (no_appl_data) { 95839beb93cSSam Leffler /* Need to return something to get final TLS ACK. */ 95939beb93cSSam Leffler return os_malloc(1); 96039beb93cSSam Leffler } 96139beb93cSSam Leffler return NULL; 96239beb93cSSam Leffler default: 96339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while " 96439beb93cSSam Leffler "generating reply", conn->state); 96539beb93cSSam Leffler return NULL; 96639beb93cSSam Leffler } 96739beb93cSSam Leffler } 96839beb93cSSam Leffler 96939beb93cSSam Leffler 97039beb93cSSam Leffler u8 * tlsv1_client_send_alert(struct tlsv1_client *conn, u8 level, 97139beb93cSSam Leffler u8 description, size_t *out_len) 97239beb93cSSam Leffler { 97339beb93cSSam Leffler u8 *alert, *pos, *length; 97439beb93cSSam Leffler 97539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description); 97639beb93cSSam Leffler *out_len = 0; 97739beb93cSSam Leffler 97839beb93cSSam Leffler alert = os_malloc(10); 97939beb93cSSam Leffler if (alert == NULL) 98039beb93cSSam Leffler return NULL; 98139beb93cSSam Leffler 98239beb93cSSam Leffler pos = alert; 98339beb93cSSam Leffler 98439beb93cSSam Leffler /* TLSPlaintext */ 98539beb93cSSam Leffler /* ContentType type */ 98639beb93cSSam Leffler *pos++ = TLS_CONTENT_TYPE_ALERT; 98739beb93cSSam Leffler /* ProtocolVersion version */ 988f05cddf9SRui Paulo WPA_PUT_BE16(pos, conn->rl.tls_version ? conn->rl.tls_version : 989f05cddf9SRui Paulo TLS_VERSION); 99039beb93cSSam Leffler pos += 2; 99139beb93cSSam Leffler /* uint16 length (to be filled) */ 99239beb93cSSam Leffler length = pos; 99339beb93cSSam Leffler pos += 2; 99439beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 99539beb93cSSam Leffler 99639beb93cSSam Leffler /* Alert */ 99739beb93cSSam Leffler /* AlertLevel level */ 99839beb93cSSam Leffler *pos++ = level; 99939beb93cSSam Leffler /* AlertDescription description */ 100039beb93cSSam Leffler *pos++ = description; 100139beb93cSSam Leffler 100239beb93cSSam Leffler WPA_PUT_BE16(length, pos - length - 2); 100339beb93cSSam Leffler *out_len = pos - alert; 100439beb93cSSam Leffler 100539beb93cSSam Leffler return alert; 100639beb93cSSam Leffler } 1007