139beb93cSSam Leffler /* 239beb93cSSam Leffler * TLSv1 server - write handshake message 35b9c547cSRui Paulo * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6f05cddf9SRui Paulo * See README for more details. 739beb93cSSam Leffler */ 839beb93cSSam Leffler 939beb93cSSam Leffler #include "includes.h" 1039beb93cSSam Leffler 1139beb93cSSam Leffler #include "common.h" 12e28a4053SRui Paulo #include "crypto/md5.h" 13e28a4053SRui Paulo #include "crypto/sha1.h" 14f05cddf9SRui Paulo #include "crypto/sha256.h" 15e28a4053SRui Paulo #include "crypto/tls.h" 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_server.h" 2139beb93cSSam Leffler #include "tlsv1_server_i.h" 2239beb93cSSam Leffler 2339beb93cSSam Leffler 2439beb93cSSam Leffler static size_t tls_server_cert_chain_der_len(struct tlsv1_server *conn) 2539beb93cSSam Leffler { 2639beb93cSSam Leffler size_t len = 0; 2739beb93cSSam Leffler struct x509_certificate *cert; 2839beb93cSSam Leffler 2939beb93cSSam Leffler cert = conn->cred->cert; 3039beb93cSSam Leffler while (cert) { 3139beb93cSSam Leffler len += 3 + cert->cert_len; 3239beb93cSSam Leffler if (x509_certificate_self_signed(cert)) 3339beb93cSSam Leffler break; 3439beb93cSSam Leffler cert = x509_certificate_get_subject(conn->cred->trusted_certs, 3539beb93cSSam Leffler &cert->issuer); 3639beb93cSSam Leffler } 3739beb93cSSam Leffler 3839beb93cSSam Leffler return len; 3939beb93cSSam Leffler } 4039beb93cSSam Leffler 4139beb93cSSam Leffler 4239beb93cSSam Leffler static int tls_write_server_hello(struct tlsv1_server *conn, 4339beb93cSSam Leffler u8 **msgpos, u8 *end) 4439beb93cSSam Leffler { 45*780fb4a2SCy Schubert u8 *pos, *rhdr, *hs_start, *hs_length, *ext_start; 4639beb93cSSam Leffler struct os_time now; 4739beb93cSSam Leffler size_t rlen; 4839beb93cSSam Leffler 4939beb93cSSam Leffler pos = *msgpos; 5039beb93cSSam Leffler 515b9c547cSRui Paulo tlsv1_server_log(conn, "Send ServerHello"); 5239beb93cSSam Leffler rhdr = pos; 5339beb93cSSam Leffler pos += TLS_RECORD_HEADER_LEN; 5439beb93cSSam Leffler 5539beb93cSSam Leffler os_get_time(&now); 5639beb93cSSam Leffler WPA_PUT_BE32(conn->server_random, now.sec); 57f05cddf9SRui Paulo if (random_get_bytes(conn->server_random + 4, TLS_RANDOM_LEN - 4)) { 5839beb93cSSam Leffler wpa_printf(MSG_ERROR, "TLSv1: Could not generate " 5939beb93cSSam Leffler "server_random"); 6039beb93cSSam Leffler return -1; 6139beb93cSSam Leffler } 6239beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random", 6339beb93cSSam Leffler conn->server_random, TLS_RANDOM_LEN); 6439beb93cSSam Leffler 6539beb93cSSam Leffler conn->session_id_len = TLS_SESSION_ID_MAX_LEN; 66f05cddf9SRui Paulo if (random_get_bytes(conn->session_id, conn->session_id_len)) { 6739beb93cSSam Leffler wpa_printf(MSG_ERROR, "TLSv1: Could not generate " 6839beb93cSSam Leffler "session_id"); 6939beb93cSSam Leffler return -1; 7039beb93cSSam Leffler } 7139beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id", 7239beb93cSSam Leffler conn->session_id, conn->session_id_len); 7339beb93cSSam Leffler 7439beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 7539beb93cSSam Leffler 7639beb93cSSam Leffler /* Handshake */ 7739beb93cSSam Leffler hs_start = pos; 7839beb93cSSam Leffler /* HandshakeType msg_type */ 7939beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO; 8039beb93cSSam Leffler /* uint24 length (to be filled) */ 8139beb93cSSam Leffler hs_length = pos; 8239beb93cSSam Leffler pos += 3; 8339beb93cSSam Leffler /* body - ServerHello */ 8439beb93cSSam Leffler /* ProtocolVersion server_version */ 85f05cddf9SRui Paulo WPA_PUT_BE16(pos, conn->rl.tls_version); 8639beb93cSSam Leffler pos += 2; 8739beb93cSSam Leffler /* Random random: uint32 gmt_unix_time, opaque random_bytes */ 8839beb93cSSam Leffler os_memcpy(pos, conn->server_random, TLS_RANDOM_LEN); 8939beb93cSSam Leffler pos += TLS_RANDOM_LEN; 9039beb93cSSam Leffler /* SessionID session_id */ 9139beb93cSSam Leffler *pos++ = conn->session_id_len; 9239beb93cSSam Leffler os_memcpy(pos, conn->session_id, conn->session_id_len); 9339beb93cSSam Leffler pos += conn->session_id_len; 9439beb93cSSam Leffler /* CipherSuite cipher_suite */ 9539beb93cSSam Leffler WPA_PUT_BE16(pos, conn->cipher_suite); 9639beb93cSSam Leffler pos += 2; 9739beb93cSSam Leffler /* CompressionMethod compression_method */ 9839beb93cSSam Leffler *pos++ = TLS_COMPRESSION_NULL; 9939beb93cSSam Leffler 100*780fb4a2SCy Schubert /* Extension */ 101*780fb4a2SCy Schubert ext_start = pos; 102*780fb4a2SCy Schubert pos += 2; 103*780fb4a2SCy Schubert 104*780fb4a2SCy Schubert if (conn->status_request) { 105*780fb4a2SCy Schubert /* Add a status_request extension with empty extension_data */ 106*780fb4a2SCy Schubert /* ExtensionsType extension_type = status_request(5) */ 107*780fb4a2SCy Schubert WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST); 108*780fb4a2SCy Schubert pos += 2; 109*780fb4a2SCy Schubert /* opaque extension_data<0..2^16-1> length */ 110*780fb4a2SCy Schubert WPA_PUT_BE16(pos, 0); 111*780fb4a2SCy Schubert pos += 2; 112*780fb4a2SCy Schubert } 113*780fb4a2SCy Schubert 114*780fb4a2SCy Schubert if (conn->status_request_v2) { 115*780fb4a2SCy Schubert /* 116*780fb4a2SCy Schubert Add a status_request_v2 extension with empty extension_data 117*780fb4a2SCy Schubert */ 118*780fb4a2SCy Schubert /* ExtensionsType extension_type = status_request_v2(17) */ 119*780fb4a2SCy Schubert WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST_V2); 120*780fb4a2SCy Schubert pos += 2; 121*780fb4a2SCy Schubert /* opaque extension_data<0..2^16-1> length */ 122*780fb4a2SCy Schubert WPA_PUT_BE16(pos, 0); 123*780fb4a2SCy Schubert pos += 2; 124*780fb4a2SCy Schubert } 125*780fb4a2SCy Schubert 12639beb93cSSam Leffler if (conn->session_ticket && conn->session_ticket_cb) { 12739beb93cSSam Leffler int res = conn->session_ticket_cb( 12839beb93cSSam Leffler conn->session_ticket_cb_ctx, 12939beb93cSSam Leffler conn->session_ticket, conn->session_ticket_len, 13039beb93cSSam Leffler conn->client_random, conn->server_random, 13139beb93cSSam Leffler conn->master_secret); 13239beb93cSSam Leffler if (res < 0) { 1335b9c547cSRui Paulo tlsv1_server_log(conn, "SessionTicket callback indicated failure"); 13439beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 13539beb93cSSam Leffler TLS_ALERT_HANDSHAKE_FAILURE); 13639beb93cSSam Leffler return -1; 13739beb93cSSam Leffler } 13839beb93cSSam Leffler conn->use_session_ticket = res; 13939beb93cSSam Leffler 14039beb93cSSam Leffler if (conn->use_session_ticket) { 14139beb93cSSam Leffler if (tlsv1_server_derive_keys(conn, NULL, 0) < 0) { 14239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to " 14339beb93cSSam Leffler "derive keys"); 14439beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 14539beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 14639beb93cSSam Leffler return -1; 14739beb93cSSam Leffler } 14839beb93cSSam Leffler } 14939beb93cSSam Leffler 15039beb93cSSam Leffler /* 15139beb93cSSam Leffler * RFC 4507 specifies that server would include an empty 15239beb93cSSam Leffler * SessionTicket extension in ServerHello and a 15339beb93cSSam Leffler * NewSessionTicket message after the ServerHello. However, 15439beb93cSSam Leffler * EAP-FAST (RFC 4851), i.e., the only user of SessionTicket 15539beb93cSSam Leffler * extension at the moment, does not use such extensions. 15639beb93cSSam Leffler * 15739beb93cSSam Leffler * TODO: Add support for configuring RFC 4507 behavior and make 15839beb93cSSam Leffler * EAP-FAST disable it. 15939beb93cSSam Leffler */ 16039beb93cSSam Leffler } 16139beb93cSSam Leffler 162*780fb4a2SCy Schubert if (pos == ext_start + 2) 163*780fb4a2SCy Schubert pos -= 2; /* no extensions */ 164*780fb4a2SCy Schubert else 165*780fb4a2SCy Schubert WPA_PUT_BE16(ext_start, pos - ext_start - 2); 166*780fb4a2SCy Schubert 16739beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 16839beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 16939beb93cSSam Leffler 17039beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 171f05cddf9SRui Paulo rhdr, end - rhdr, hs_start, pos - hs_start, 172f05cddf9SRui Paulo &rlen) < 0) { 17339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record"); 17439beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 17539beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 17639beb93cSSam Leffler return -1; 17739beb93cSSam Leffler } 17839beb93cSSam Leffler pos = rhdr + rlen; 17939beb93cSSam Leffler 18039beb93cSSam Leffler *msgpos = pos; 18139beb93cSSam Leffler 18239beb93cSSam Leffler return 0; 18339beb93cSSam Leffler } 18439beb93cSSam Leffler 18539beb93cSSam Leffler 18639beb93cSSam Leffler static int tls_write_server_certificate(struct tlsv1_server *conn, 18739beb93cSSam Leffler u8 **msgpos, u8 *end) 18839beb93cSSam Leffler { 18939beb93cSSam Leffler u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start; 19039beb93cSSam Leffler size_t rlen; 19139beb93cSSam Leffler struct x509_certificate *cert; 19239beb93cSSam Leffler const struct tls_cipher_suite *suite; 19339beb93cSSam Leffler 19439beb93cSSam Leffler suite = tls_get_cipher_suite(conn->rl.cipher_suite); 19539beb93cSSam Leffler if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) { 19639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Do not send Certificate when " 19739beb93cSSam Leffler "using anonymous DH"); 19839beb93cSSam Leffler return 0; 19939beb93cSSam Leffler } 20039beb93cSSam Leffler 20139beb93cSSam Leffler pos = *msgpos; 202*780fb4a2SCy Schubert if (TLS_RECORD_HEADER_LEN + 1 + 3 + 3 > end - pos) { 203*780fb4a2SCy Schubert tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 204*780fb4a2SCy Schubert TLS_ALERT_INTERNAL_ERROR); 205*780fb4a2SCy Schubert return -1; 206*780fb4a2SCy Schubert } 20739beb93cSSam Leffler 2085b9c547cSRui Paulo tlsv1_server_log(conn, "Send Certificate"); 20939beb93cSSam Leffler rhdr = pos; 21039beb93cSSam Leffler pos += TLS_RECORD_HEADER_LEN; 21139beb93cSSam Leffler 21239beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 21339beb93cSSam Leffler 21439beb93cSSam Leffler /* Handshake */ 21539beb93cSSam Leffler hs_start = pos; 21639beb93cSSam Leffler /* HandshakeType msg_type */ 21739beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE; 21839beb93cSSam Leffler /* uint24 length (to be filled) */ 21939beb93cSSam Leffler hs_length = pos; 22039beb93cSSam Leffler pos += 3; 22139beb93cSSam Leffler /* body - Certificate */ 22239beb93cSSam Leffler /* uint24 length (to be filled) */ 22339beb93cSSam Leffler cert_start = pos; 22439beb93cSSam Leffler pos += 3; 22539beb93cSSam Leffler cert = conn->cred->cert; 22639beb93cSSam Leffler while (cert) { 227*780fb4a2SCy Schubert if (3 + cert->cert_len > (size_t) (end - pos)) { 22839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space " 22939beb93cSSam Leffler "for Certificate (cert_len=%lu left=%lu)", 23039beb93cSSam Leffler (unsigned long) cert->cert_len, 23139beb93cSSam Leffler (unsigned long) (end - pos)); 23239beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 23339beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 23439beb93cSSam Leffler return -1; 23539beb93cSSam Leffler } 23639beb93cSSam Leffler WPA_PUT_BE24(pos, cert->cert_len); 23739beb93cSSam Leffler pos += 3; 23839beb93cSSam Leffler os_memcpy(pos, cert->cert_start, cert->cert_len); 23939beb93cSSam Leffler pos += cert->cert_len; 24039beb93cSSam Leffler 24139beb93cSSam Leffler if (x509_certificate_self_signed(cert)) 24239beb93cSSam Leffler break; 24339beb93cSSam Leffler cert = x509_certificate_get_subject(conn->cred->trusted_certs, 24439beb93cSSam Leffler &cert->issuer); 24539beb93cSSam Leffler } 24639beb93cSSam Leffler if (cert == conn->cred->cert || cert == NULL) { 24739beb93cSSam Leffler /* 24839beb93cSSam Leffler * Server was not configured with all the needed certificates 24939beb93cSSam Leffler * to form a full certificate chain. The client may fail to 25039beb93cSSam Leffler * validate the chain unless it is configured with all the 25139beb93cSSam Leffler * missing CA certificates. 25239beb93cSSam Leffler */ 25339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Full server certificate chain " 25439beb93cSSam Leffler "not configured - validation may fail"); 25539beb93cSSam Leffler } 25639beb93cSSam Leffler WPA_PUT_BE24(cert_start, pos - cert_start - 3); 25739beb93cSSam Leffler 25839beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 25939beb93cSSam Leffler 26039beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 261f05cddf9SRui Paulo rhdr, end - rhdr, hs_start, pos - hs_start, 262f05cddf9SRui Paulo &rlen) < 0) { 26339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); 26439beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 26539beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 26639beb93cSSam Leffler return -1; 26739beb93cSSam Leffler } 26839beb93cSSam Leffler pos = rhdr + rlen; 26939beb93cSSam Leffler 27039beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 27139beb93cSSam Leffler 27239beb93cSSam Leffler *msgpos = pos; 27339beb93cSSam Leffler 27439beb93cSSam Leffler return 0; 27539beb93cSSam Leffler } 27639beb93cSSam Leffler 27739beb93cSSam Leffler 278*780fb4a2SCy Schubert static int tls_write_server_certificate_status(struct tlsv1_server *conn, 279*780fb4a2SCy Schubert u8 **msgpos, u8 *end, 280*780fb4a2SCy Schubert int ocsp_multi, 281*780fb4a2SCy Schubert char *ocsp_resp, 282*780fb4a2SCy Schubert size_t ocsp_resp_len) 283*780fb4a2SCy Schubert { 284*780fb4a2SCy Schubert u8 *pos, *rhdr, *hs_start, *hs_length; 285*780fb4a2SCy Schubert size_t rlen; 286*780fb4a2SCy Schubert 287*780fb4a2SCy Schubert if (!ocsp_resp) { 288*780fb4a2SCy Schubert /* 289*780fb4a2SCy Schubert * Client did not request certificate status or there is no 290*780fb4a2SCy Schubert * matching response cached. 291*780fb4a2SCy Schubert */ 292*780fb4a2SCy Schubert return 0; 293*780fb4a2SCy Schubert } 294*780fb4a2SCy Schubert 295*780fb4a2SCy Schubert pos = *msgpos; 296*780fb4a2SCy Schubert if (TLS_RECORD_HEADER_LEN + 1 + 3 + 1 + 3 + ocsp_resp_len > 297*780fb4a2SCy Schubert (unsigned int) (end - pos)) { 298*780fb4a2SCy Schubert tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 299*780fb4a2SCy Schubert TLS_ALERT_INTERNAL_ERROR); 300*780fb4a2SCy Schubert return -1; 301*780fb4a2SCy Schubert } 302*780fb4a2SCy Schubert 303*780fb4a2SCy Schubert tlsv1_server_log(conn, "Send CertificateStatus (multi=%d)", ocsp_multi); 304*780fb4a2SCy Schubert rhdr = pos; 305*780fb4a2SCy Schubert pos += TLS_RECORD_HEADER_LEN; 306*780fb4a2SCy Schubert 307*780fb4a2SCy Schubert /* opaque fragment[TLSPlaintext.length] */ 308*780fb4a2SCy Schubert 309*780fb4a2SCy Schubert /* Handshake */ 310*780fb4a2SCy Schubert hs_start = pos; 311*780fb4a2SCy Schubert /* HandshakeType msg_type */ 312*780fb4a2SCy Schubert *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS; 313*780fb4a2SCy Schubert /* uint24 length (to be filled) */ 314*780fb4a2SCy Schubert hs_length = pos; 315*780fb4a2SCy Schubert pos += 3; 316*780fb4a2SCy Schubert 317*780fb4a2SCy Schubert /* body - CertificateStatus 318*780fb4a2SCy Schubert * 319*780fb4a2SCy Schubert * struct { 320*780fb4a2SCy Schubert * CertificateStatusType status_type; 321*780fb4a2SCy Schubert * select (status_type) { 322*780fb4a2SCy Schubert * case ocsp: OCSPResponse; 323*780fb4a2SCy Schubert * case ocsp_multi: OCSPResponseList; 324*780fb4a2SCy Schubert * } response; 325*780fb4a2SCy Schubert * } CertificateStatus; 326*780fb4a2SCy Schubert * 327*780fb4a2SCy Schubert * opaque OCSPResponse<1..2^24-1>; 328*780fb4a2SCy Schubert * 329*780fb4a2SCy Schubert * struct { 330*780fb4a2SCy Schubert * OCSPResponse ocsp_response_list<1..2^24-1>; 331*780fb4a2SCy Schubert * } OCSPResponseList; 332*780fb4a2SCy Schubert */ 333*780fb4a2SCy Schubert 334*780fb4a2SCy Schubert /* CertificateStatusType status_type */ 335*780fb4a2SCy Schubert if (ocsp_multi) 336*780fb4a2SCy Schubert *pos++ = 2; /* ocsp_multi(2) */ 337*780fb4a2SCy Schubert else 338*780fb4a2SCy Schubert *pos++ = 1; /* ocsp(1) */ 339*780fb4a2SCy Schubert /* uint24 length of OCSPResponse */ 340*780fb4a2SCy Schubert WPA_PUT_BE24(pos, ocsp_resp_len); 341*780fb4a2SCy Schubert pos += 3; 342*780fb4a2SCy Schubert os_memcpy(pos, ocsp_resp, ocsp_resp_len); 343*780fb4a2SCy Schubert pos += ocsp_resp_len; 344*780fb4a2SCy Schubert 345*780fb4a2SCy Schubert WPA_PUT_BE24(hs_length, pos - hs_length - 3); 346*780fb4a2SCy Schubert 347*780fb4a2SCy Schubert if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 348*780fb4a2SCy Schubert rhdr, end - rhdr, hs_start, pos - hs_start, 349*780fb4a2SCy Schubert &rlen) < 0) { 350*780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); 351*780fb4a2SCy Schubert tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 352*780fb4a2SCy Schubert TLS_ALERT_INTERNAL_ERROR); 353*780fb4a2SCy Schubert return -1; 354*780fb4a2SCy Schubert } 355*780fb4a2SCy Schubert pos = rhdr + rlen; 356*780fb4a2SCy Schubert 357*780fb4a2SCy Schubert tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 358*780fb4a2SCy Schubert 359*780fb4a2SCy Schubert *msgpos = pos; 360*780fb4a2SCy Schubert 361*780fb4a2SCy Schubert return 0; 362*780fb4a2SCy Schubert } 363*780fb4a2SCy Schubert 364*780fb4a2SCy Schubert 36539beb93cSSam Leffler static int tls_write_server_key_exchange(struct tlsv1_server *conn, 36639beb93cSSam Leffler u8 **msgpos, u8 *end) 36739beb93cSSam Leffler { 36839beb93cSSam Leffler tls_key_exchange keyx; 36939beb93cSSam Leffler const struct tls_cipher_suite *suite; 3705b9c547cSRui Paulo u8 *pos, *rhdr, *hs_start, *hs_length, *server_params; 37139beb93cSSam Leffler size_t rlen; 37239beb93cSSam Leffler u8 *dh_ys; 37339beb93cSSam Leffler size_t dh_ys_len; 3745b9c547cSRui Paulo const u8 *dh_p; 3755b9c547cSRui Paulo size_t dh_p_len; 37639beb93cSSam Leffler 37739beb93cSSam Leffler suite = tls_get_cipher_suite(conn->rl.cipher_suite); 37839beb93cSSam Leffler if (suite == NULL) 37939beb93cSSam Leffler keyx = TLS_KEY_X_NULL; 38039beb93cSSam Leffler else 38139beb93cSSam Leffler keyx = suite->key_exchange; 38239beb93cSSam Leffler 38339beb93cSSam Leffler if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) { 38439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: No ServerKeyExchange needed"); 38539beb93cSSam Leffler return 0; 38639beb93cSSam Leffler } 38739beb93cSSam Leffler 3885b9c547cSRui Paulo if (keyx != TLS_KEY_X_DH_anon && keyx != TLS_KEY_X_DHE_RSA) { 38939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not yet " 39039beb93cSSam Leffler "supported with key exchange type %d", keyx); 39139beb93cSSam Leffler return -1; 39239beb93cSSam Leffler } 39339beb93cSSam Leffler 39439beb93cSSam Leffler if (conn->cred == NULL || conn->cred->dh_p == NULL || 39539beb93cSSam Leffler conn->cred->dh_g == NULL) { 39639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available for " 39739beb93cSSam Leffler "ServerKeyExhcange"); 39839beb93cSSam Leffler return -1; 39939beb93cSSam Leffler } 40039beb93cSSam Leffler 4015b9c547cSRui Paulo tlsv1_server_get_dh_p(conn, &dh_p, &dh_p_len); 4025b9c547cSRui Paulo 40339beb93cSSam Leffler os_free(conn->dh_secret); 4045b9c547cSRui Paulo conn->dh_secret_len = dh_p_len; 40539beb93cSSam Leffler conn->dh_secret = os_malloc(conn->dh_secret_len); 40639beb93cSSam Leffler if (conn->dh_secret == NULL) { 40739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " 40839beb93cSSam Leffler "memory for secret (Diffie-Hellman)"); 40939beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 41039beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 41139beb93cSSam Leffler return -1; 41239beb93cSSam Leffler } 413f05cddf9SRui Paulo if (random_get_bytes(conn->dh_secret, conn->dh_secret_len)) { 41439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " 41539beb93cSSam Leffler "data for Diffie-Hellman"); 41639beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 41739beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 41839beb93cSSam Leffler os_free(conn->dh_secret); 41939beb93cSSam Leffler conn->dh_secret = NULL; 42039beb93cSSam Leffler return -1; 42139beb93cSSam Leffler } 42239beb93cSSam Leffler 4235b9c547cSRui Paulo if (os_memcmp(conn->dh_secret, dh_p, conn->dh_secret_len) > 0) 42439beb93cSSam Leffler conn->dh_secret[0] = 0; /* make sure secret < p */ 42539beb93cSSam Leffler 42639beb93cSSam Leffler pos = conn->dh_secret; 42739beb93cSSam Leffler while (pos + 1 < conn->dh_secret + conn->dh_secret_len && *pos == 0) 42839beb93cSSam Leffler pos++; 42939beb93cSSam Leffler if (pos != conn->dh_secret) { 43039beb93cSSam Leffler os_memmove(conn->dh_secret, pos, 43139beb93cSSam Leffler conn->dh_secret_len - (pos - conn->dh_secret)); 43239beb93cSSam Leffler conn->dh_secret_len -= pos - conn->dh_secret; 43339beb93cSSam Leffler } 43439beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH server's secret value", 43539beb93cSSam Leffler conn->dh_secret, conn->dh_secret_len); 43639beb93cSSam Leffler 43739beb93cSSam Leffler /* Ys = g^secret mod p */ 4385b9c547cSRui Paulo dh_ys_len = dh_p_len; 43939beb93cSSam Leffler dh_ys = os_malloc(dh_ys_len); 44039beb93cSSam Leffler if (dh_ys == NULL) { 44139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate memory for " 44239beb93cSSam Leffler "Diffie-Hellman"); 44339beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 44439beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 44539beb93cSSam Leffler return -1; 44639beb93cSSam Leffler } 44739beb93cSSam Leffler if (crypto_mod_exp(conn->cred->dh_g, conn->cred->dh_g_len, 44839beb93cSSam Leffler conn->dh_secret, conn->dh_secret_len, 4495b9c547cSRui Paulo dh_p, dh_p_len, dh_ys, &dh_ys_len)) { 45039beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 45139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 45239beb93cSSam Leffler os_free(dh_ys); 45339beb93cSSam Leffler return -1; 45439beb93cSSam Leffler } 45539beb93cSSam Leffler 45639beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)", 45739beb93cSSam Leffler dh_ys, dh_ys_len); 45839beb93cSSam Leffler 45939beb93cSSam Leffler /* 46039beb93cSSam Leffler * struct { 46139beb93cSSam Leffler * select (KeyExchangeAlgorithm) { 46239beb93cSSam Leffler * case diffie_hellman: 46339beb93cSSam Leffler * ServerDHParams params; 46439beb93cSSam Leffler * Signature signed_params; 46539beb93cSSam Leffler * case rsa: 46639beb93cSSam Leffler * ServerRSAParams params; 46739beb93cSSam Leffler * Signature signed_params; 46839beb93cSSam Leffler * }; 46939beb93cSSam Leffler * } ServerKeyExchange; 47039beb93cSSam Leffler * 47139beb93cSSam Leffler * struct { 47239beb93cSSam Leffler * opaque dh_p<1..2^16-1>; 47339beb93cSSam Leffler * opaque dh_g<1..2^16-1>; 47439beb93cSSam Leffler * opaque dh_Ys<1..2^16-1>; 47539beb93cSSam Leffler * } ServerDHParams; 47639beb93cSSam Leffler */ 47739beb93cSSam Leffler 47839beb93cSSam Leffler pos = *msgpos; 47939beb93cSSam Leffler 4805b9c547cSRui Paulo tlsv1_server_log(conn, "Send ServerKeyExchange"); 48139beb93cSSam Leffler rhdr = pos; 48239beb93cSSam Leffler pos += TLS_RECORD_HEADER_LEN; 48339beb93cSSam Leffler 48439beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 48539beb93cSSam Leffler 48639beb93cSSam Leffler /* Handshake */ 48739beb93cSSam Leffler hs_start = pos; 48839beb93cSSam Leffler /* HandshakeType msg_type */ 48939beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE; 49039beb93cSSam Leffler /* uint24 length (to be filled) */ 49139beb93cSSam Leffler hs_length = pos; 49239beb93cSSam Leffler pos += 3; 49339beb93cSSam Leffler 49439beb93cSSam Leffler /* body - ServerDHParams */ 4955b9c547cSRui Paulo server_params = pos; 49639beb93cSSam Leffler /* dh_p */ 497*780fb4a2SCy Schubert if (2 + dh_p_len > (size_t) (end - pos)) { 49839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " 49939beb93cSSam Leffler "dh_p"); 50039beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 50139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 50239beb93cSSam Leffler os_free(dh_ys); 50339beb93cSSam Leffler return -1; 50439beb93cSSam Leffler } 5055b9c547cSRui Paulo WPA_PUT_BE16(pos, dh_p_len); 50639beb93cSSam Leffler pos += 2; 5075b9c547cSRui Paulo os_memcpy(pos, dh_p, dh_p_len); 5085b9c547cSRui Paulo pos += dh_p_len; 50939beb93cSSam Leffler 51039beb93cSSam Leffler /* dh_g */ 511*780fb4a2SCy Schubert if (2 + conn->cred->dh_g_len > (size_t) (end - pos)) { 51239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " 51339beb93cSSam Leffler "dh_g"); 51439beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 51539beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 51639beb93cSSam Leffler os_free(dh_ys); 51739beb93cSSam Leffler return -1; 51839beb93cSSam Leffler } 51939beb93cSSam Leffler WPA_PUT_BE16(pos, conn->cred->dh_g_len); 52039beb93cSSam Leffler pos += 2; 52139beb93cSSam Leffler os_memcpy(pos, conn->cred->dh_g, conn->cred->dh_g_len); 52239beb93cSSam Leffler pos += conn->cred->dh_g_len; 52339beb93cSSam Leffler 52439beb93cSSam Leffler /* dh_Ys */ 525*780fb4a2SCy Schubert if (2 + dh_ys_len > (size_t) (end - pos)) { 52639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " 52739beb93cSSam Leffler "dh_Ys"); 52839beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 52939beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 53039beb93cSSam Leffler os_free(dh_ys); 53139beb93cSSam Leffler return -1; 53239beb93cSSam Leffler } 53339beb93cSSam Leffler WPA_PUT_BE16(pos, dh_ys_len); 53439beb93cSSam Leffler pos += 2; 53539beb93cSSam Leffler os_memcpy(pos, dh_ys, dh_ys_len); 53639beb93cSSam Leffler pos += dh_ys_len; 53739beb93cSSam Leffler os_free(dh_ys); 53839beb93cSSam Leffler 5395b9c547cSRui Paulo /* 5405b9c547cSRui Paulo * select (SignatureAlgorithm) 5415b9c547cSRui Paulo * { case anonymous: struct { }; 5425b9c547cSRui Paulo * case rsa: 5435b9c547cSRui Paulo * digitally-signed struct { 5445b9c547cSRui Paulo * opaque md5_hash[16]; 5455b9c547cSRui Paulo * opaque sha_hash[20]; 5465b9c547cSRui Paulo * }; 5475b9c547cSRui Paulo * case dsa: 5485b9c547cSRui Paulo * digitally-signed struct { 5495b9c547cSRui Paulo * opaque sha_hash[20]; 5505b9c547cSRui Paulo * }; 5515b9c547cSRui Paulo * } Signature; 5525b9c547cSRui Paulo * 5535b9c547cSRui Paulo * md5_hash 5545b9c547cSRui Paulo * MD5(ClientHello.random + ServerHello.random + ServerParams); 5555b9c547cSRui Paulo * 5565b9c547cSRui Paulo * sha_hash 5575b9c547cSRui Paulo * SHA(ClientHello.random + ServerHello.random + ServerParams); 5585b9c547cSRui Paulo */ 5595b9c547cSRui Paulo 5605b9c547cSRui Paulo if (keyx == TLS_KEY_X_DHE_RSA) { 5615b9c547cSRui Paulo u8 hash[100]; 5625b9c547cSRui Paulo u8 *signed_start; 5635b9c547cSRui Paulo size_t clen; 5645b9c547cSRui Paulo int hlen; 5655b9c547cSRui Paulo 5665b9c547cSRui Paulo if (conn->rl.tls_version >= TLS_VERSION_1_2) { 5675b9c547cSRui Paulo #ifdef CONFIG_TLSV12 5685b9c547cSRui Paulo hlen = tlsv12_key_x_server_params_hash( 569*780fb4a2SCy Schubert conn->rl.tls_version, TLS_HASH_ALG_SHA256, 570*780fb4a2SCy Schubert conn->client_random, 5715b9c547cSRui Paulo conn->server_random, server_params, 5725b9c547cSRui Paulo pos - server_params, hash + 19); 5735b9c547cSRui Paulo 5745b9c547cSRui Paulo /* 5755b9c547cSRui Paulo * RFC 5246, 4.7: 5765b9c547cSRui Paulo * TLS v1.2 adds explicit indication of the used 5775b9c547cSRui Paulo * signature and hash algorithms. 5785b9c547cSRui Paulo * 5795b9c547cSRui Paulo * struct { 5805b9c547cSRui Paulo * HashAlgorithm hash; 5815b9c547cSRui Paulo * SignatureAlgorithm signature; 5825b9c547cSRui Paulo * } SignatureAndHashAlgorithm; 5835b9c547cSRui Paulo */ 584*780fb4a2SCy Schubert if (hlen < 0 || end - pos < 2) { 5855b9c547cSRui Paulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 5865b9c547cSRui Paulo TLS_ALERT_INTERNAL_ERROR); 5875b9c547cSRui Paulo return -1; 5885b9c547cSRui Paulo } 5895b9c547cSRui Paulo *pos++ = TLS_HASH_ALG_SHA256; 5905b9c547cSRui Paulo *pos++ = TLS_SIGN_ALG_RSA; 5915b9c547cSRui Paulo 5925b9c547cSRui Paulo /* 5935b9c547cSRui Paulo * RFC 3447, A.2.4 RSASSA-PKCS1-v1_5 5945b9c547cSRui Paulo * 5955b9c547cSRui Paulo * DigestInfo ::= SEQUENCE { 5965b9c547cSRui Paulo * digestAlgorithm DigestAlgorithm, 5975b9c547cSRui Paulo * digest OCTET STRING 5985b9c547cSRui Paulo * } 5995b9c547cSRui Paulo * 6005b9c547cSRui Paulo * SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11} 6015b9c547cSRui Paulo * 6025b9c547cSRui Paulo * DER encoded DigestInfo for SHA256 per RFC 3447: 6035b9c547cSRui Paulo * 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 6045b9c547cSRui Paulo * 04 20 || H 6055b9c547cSRui Paulo */ 6065b9c547cSRui Paulo hlen += 19; 6075b9c547cSRui Paulo os_memcpy(hash, 6085b9c547cSRui Paulo "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65" 6095b9c547cSRui Paulo "\x03\x04\x02\x01\x05\x00\x04\x20", 19); 6105b9c547cSRui Paulo 6115b9c547cSRui Paulo #else /* CONFIG_TLSV12 */ 6125b9c547cSRui Paulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 6135b9c547cSRui Paulo TLS_ALERT_INTERNAL_ERROR); 6145b9c547cSRui Paulo return -1; 6155b9c547cSRui Paulo #endif /* CONFIG_TLSV12 */ 6165b9c547cSRui Paulo } else { 6175b9c547cSRui Paulo hlen = tls_key_x_server_params_hash( 6185b9c547cSRui Paulo conn->rl.tls_version, conn->client_random, 6195b9c547cSRui Paulo conn->server_random, server_params, 6205b9c547cSRui Paulo pos - server_params, hash); 6215b9c547cSRui Paulo } 6225b9c547cSRui Paulo 6235b9c547cSRui Paulo if (hlen < 0) { 6245b9c547cSRui Paulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 6255b9c547cSRui Paulo TLS_ALERT_INTERNAL_ERROR); 6265b9c547cSRui Paulo return -1; 6275b9c547cSRui Paulo } 6285b9c547cSRui Paulo 6295b9c547cSRui Paulo wpa_hexdump(MSG_MSGDUMP, "TLS: ServerKeyExchange signed_params hash", 6305b9c547cSRui Paulo hash, hlen); 6315b9c547cSRui Paulo #ifdef CONFIG_TESTING_OPTIONS 6325b9c547cSRui Paulo if (conn->test_flags & TLS_BREAK_SRV_KEY_X_HASH) { 6335b9c547cSRui Paulo tlsv1_server_log(conn, "TESTING: Break ServerKeyExchange signed params hash"); 6345b9c547cSRui Paulo hash[hlen - 1] ^= 0x80; 6355b9c547cSRui Paulo } 6365b9c547cSRui Paulo #endif /* CONFIG_TESTING_OPTIONS */ 6375b9c547cSRui Paulo 6385b9c547cSRui Paulo /* 6395b9c547cSRui Paulo * RFC 2246, 4.7: 6405b9c547cSRui Paulo * In digital signing, one-way hash functions are used as input 6415b9c547cSRui Paulo * for a signing algorithm. A digitally-signed element is 6425b9c547cSRui Paulo * encoded as an opaque vector <0..2^16-1>, where the length is 6435b9c547cSRui Paulo * specified by the signing algorithm and key. 6445b9c547cSRui Paulo * 6455b9c547cSRui Paulo * In RSA signing, a 36-byte structure of two hashes (one SHA 6465b9c547cSRui Paulo * and one MD5) is signed (encrypted with the private key). It 6475b9c547cSRui Paulo * is encoded with PKCS #1 block type 0 or type 1 as described 6485b9c547cSRui Paulo * in [PKCS1]. 6495b9c547cSRui Paulo */ 6505b9c547cSRui Paulo signed_start = pos; /* length to be filled */ 6515b9c547cSRui Paulo pos += 2; 6525b9c547cSRui Paulo clen = end - pos; 6535b9c547cSRui Paulo if (conn->cred == NULL || 6545b9c547cSRui Paulo crypto_private_key_sign_pkcs1(conn->cred->key, hash, hlen, 6555b9c547cSRui Paulo pos, &clen) < 0) { 6565b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "TLSv1: Failed to sign hash (PKCS #1)"); 6575b9c547cSRui Paulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 6585b9c547cSRui Paulo TLS_ALERT_INTERNAL_ERROR); 6595b9c547cSRui Paulo return -1; 6605b9c547cSRui Paulo } 6615b9c547cSRui Paulo WPA_PUT_BE16(signed_start, clen); 6625b9c547cSRui Paulo #ifdef CONFIG_TESTING_OPTIONS 6635b9c547cSRui Paulo if (conn->test_flags & TLS_BREAK_SRV_KEY_X_SIGNATURE) { 6645b9c547cSRui Paulo tlsv1_server_log(conn, "TESTING: Break ServerKeyExchange signed params signature"); 6655b9c547cSRui Paulo pos[clen - 1] ^= 0x80; 6665b9c547cSRui Paulo } 6675b9c547cSRui Paulo #endif /* CONFIG_TESTING_OPTIONS */ 6685b9c547cSRui Paulo 6695b9c547cSRui Paulo pos += clen; 6705b9c547cSRui Paulo } 6715b9c547cSRui Paulo 67239beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 67339beb93cSSam Leffler 67439beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 675f05cddf9SRui Paulo rhdr, end - rhdr, hs_start, pos - hs_start, 676f05cddf9SRui Paulo &rlen) < 0) { 67739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); 67839beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 67939beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 68039beb93cSSam Leffler return -1; 68139beb93cSSam Leffler } 68239beb93cSSam Leffler pos = rhdr + rlen; 68339beb93cSSam Leffler 68439beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 68539beb93cSSam Leffler 68639beb93cSSam Leffler *msgpos = pos; 68739beb93cSSam Leffler 68839beb93cSSam Leffler return 0; 68939beb93cSSam Leffler } 69039beb93cSSam Leffler 69139beb93cSSam Leffler 69239beb93cSSam Leffler static int tls_write_server_certificate_request(struct tlsv1_server *conn, 69339beb93cSSam Leffler u8 **msgpos, u8 *end) 69439beb93cSSam Leffler { 69539beb93cSSam Leffler u8 *pos, *rhdr, *hs_start, *hs_length; 69639beb93cSSam Leffler size_t rlen; 69739beb93cSSam Leffler 69839beb93cSSam Leffler if (!conn->verify_peer) { 69939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: No CertificateRequest needed"); 70039beb93cSSam Leffler return 0; 70139beb93cSSam Leffler } 70239beb93cSSam Leffler 70339beb93cSSam Leffler pos = *msgpos; 70439beb93cSSam Leffler 7055b9c547cSRui Paulo tlsv1_server_log(conn, "Send CertificateRequest"); 70639beb93cSSam Leffler rhdr = pos; 70739beb93cSSam Leffler pos += TLS_RECORD_HEADER_LEN; 70839beb93cSSam Leffler 70939beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 71039beb93cSSam Leffler 71139beb93cSSam Leffler /* Handshake */ 71239beb93cSSam Leffler hs_start = pos; 71339beb93cSSam Leffler /* HandshakeType msg_type */ 71439beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST; 71539beb93cSSam Leffler /* uint24 length (to be filled) */ 71639beb93cSSam Leffler hs_length = pos; 71739beb93cSSam Leffler pos += 3; 71839beb93cSSam Leffler /* body - CertificateRequest */ 71939beb93cSSam Leffler 72039beb93cSSam Leffler /* 72139beb93cSSam Leffler * enum { 72239beb93cSSam Leffler * rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4), 72339beb93cSSam Leffler * (255) 72439beb93cSSam Leffler * } ClientCertificateType; 72539beb93cSSam Leffler * ClientCertificateType certificate_types<1..2^8-1> 72639beb93cSSam Leffler */ 72739beb93cSSam Leffler *pos++ = 1; 72839beb93cSSam Leffler *pos++ = 1; /* rsa_sign */ 72939beb93cSSam Leffler 73039beb93cSSam Leffler /* 73139beb93cSSam Leffler * opaque DistinguishedName<1..2^16-1> 73239beb93cSSam Leffler * DistinguishedName certificate_authorities<3..2^16-1> 73339beb93cSSam Leffler */ 73439beb93cSSam Leffler /* TODO: add support for listing DNs for trusted CAs */ 73539beb93cSSam Leffler WPA_PUT_BE16(pos, 0); 73639beb93cSSam Leffler pos += 2; 73739beb93cSSam Leffler 73839beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 73939beb93cSSam Leffler 74039beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 741f05cddf9SRui Paulo rhdr, end - rhdr, hs_start, pos - hs_start, 742f05cddf9SRui Paulo &rlen) < 0) { 74339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); 74439beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 74539beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 74639beb93cSSam Leffler return -1; 74739beb93cSSam Leffler } 74839beb93cSSam Leffler pos = rhdr + rlen; 74939beb93cSSam Leffler 75039beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 75139beb93cSSam Leffler 75239beb93cSSam Leffler *msgpos = pos; 75339beb93cSSam Leffler 75439beb93cSSam Leffler return 0; 75539beb93cSSam Leffler } 75639beb93cSSam Leffler 75739beb93cSSam Leffler 75839beb93cSSam Leffler static int tls_write_server_hello_done(struct tlsv1_server *conn, 75939beb93cSSam Leffler u8 **msgpos, u8 *end) 76039beb93cSSam Leffler { 761f05cddf9SRui Paulo u8 *pos; 76239beb93cSSam Leffler size_t rlen; 763f05cddf9SRui Paulo u8 payload[4]; 76439beb93cSSam Leffler 7655b9c547cSRui Paulo tlsv1_server_log(conn, "Send ServerHelloDone"); 76639beb93cSSam Leffler 76739beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 76839beb93cSSam Leffler 76939beb93cSSam Leffler /* Handshake */ 770f05cddf9SRui Paulo pos = payload; 77139beb93cSSam Leffler /* HandshakeType msg_type */ 77239beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE; 773f05cddf9SRui Paulo /* uint24 length */ 774f05cddf9SRui Paulo WPA_PUT_BE24(pos, 0); 77539beb93cSSam Leffler pos += 3; 77639beb93cSSam Leffler /* body - ServerHelloDone (empty) */ 77739beb93cSSam Leffler 77839beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 779f05cddf9SRui Paulo *msgpos, end - *msgpos, payload, pos - payload, 780f05cddf9SRui Paulo &rlen) < 0) { 78139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); 78239beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 78339beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 78439beb93cSSam Leffler return -1; 78539beb93cSSam Leffler } 78639beb93cSSam Leffler 787f05cddf9SRui Paulo tls_verify_hash_add(&conn->verify, payload, pos - payload); 78839beb93cSSam Leffler 789f05cddf9SRui Paulo *msgpos += rlen; 79039beb93cSSam Leffler 79139beb93cSSam Leffler return 0; 79239beb93cSSam Leffler } 79339beb93cSSam Leffler 79439beb93cSSam Leffler 79539beb93cSSam Leffler static int tls_write_server_change_cipher_spec(struct tlsv1_server *conn, 79639beb93cSSam Leffler u8 **msgpos, u8 *end) 79739beb93cSSam Leffler { 79839beb93cSSam Leffler size_t rlen; 799f05cddf9SRui Paulo u8 payload[1]; 80039beb93cSSam Leffler 8015b9c547cSRui Paulo tlsv1_server_log(conn, "Send ChangeCipherSpec"); 802f05cddf9SRui Paulo 803f05cddf9SRui Paulo payload[0] = TLS_CHANGE_CIPHER_SPEC; 804f05cddf9SRui Paulo 80539beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC, 806f05cddf9SRui Paulo *msgpos, end - *msgpos, payload, sizeof(payload), 807f05cddf9SRui Paulo &rlen) < 0) { 80839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); 80939beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 81039beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 81139beb93cSSam Leffler return -1; 81239beb93cSSam Leffler } 81339beb93cSSam Leffler 81439beb93cSSam Leffler if (tlsv1_record_change_write_cipher(&conn->rl) < 0) { 81539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for " 81639beb93cSSam Leffler "record layer"); 81739beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 81839beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 81939beb93cSSam Leffler return -1; 82039beb93cSSam Leffler } 82139beb93cSSam Leffler 822f05cddf9SRui Paulo *msgpos += rlen; 82339beb93cSSam Leffler 82439beb93cSSam Leffler return 0; 82539beb93cSSam Leffler } 82639beb93cSSam Leffler 82739beb93cSSam Leffler 82839beb93cSSam Leffler static int tls_write_server_finished(struct tlsv1_server *conn, 82939beb93cSSam Leffler u8 **msgpos, u8 *end) 83039beb93cSSam Leffler { 831f05cddf9SRui Paulo u8 *pos, *hs_start; 83239beb93cSSam Leffler size_t rlen, hlen; 833f05cddf9SRui Paulo u8 verify_data[1 + 3 + TLS_VERIFY_DATA_LEN]; 83439beb93cSSam Leffler u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; 83539beb93cSSam Leffler 83639beb93cSSam Leffler pos = *msgpos; 83739beb93cSSam Leffler 8385b9c547cSRui Paulo tlsv1_server_log(conn, "Send Finished"); 83939beb93cSSam Leffler 84039beb93cSSam Leffler /* Encrypted Handshake Message: Finished */ 84139beb93cSSam Leffler 842f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 843f05cddf9SRui Paulo if (conn->rl.tls_version >= TLS_VERSION_1_2) { 844f05cddf9SRui Paulo hlen = SHA256_MAC_LEN; 845f05cddf9SRui Paulo if (conn->verify.sha256_server == NULL || 846f05cddf9SRui Paulo crypto_hash_finish(conn->verify.sha256_server, hash, &hlen) 847f05cddf9SRui Paulo < 0) { 848f05cddf9SRui Paulo conn->verify.sha256_server = NULL; 849f05cddf9SRui Paulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 850f05cddf9SRui Paulo TLS_ALERT_INTERNAL_ERROR); 851f05cddf9SRui Paulo return -1; 852f05cddf9SRui Paulo } 853f05cddf9SRui Paulo conn->verify.sha256_server = NULL; 854f05cddf9SRui Paulo } else { 855f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 856f05cddf9SRui Paulo 85739beb93cSSam Leffler hlen = MD5_MAC_LEN; 85839beb93cSSam Leffler if (conn->verify.md5_server == NULL || 85939beb93cSSam Leffler crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) { 86039beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 86139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 86239beb93cSSam Leffler conn->verify.md5_server = NULL; 86339beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_server, NULL, NULL); 86439beb93cSSam Leffler conn->verify.sha1_server = NULL; 86539beb93cSSam Leffler return -1; 86639beb93cSSam Leffler } 86739beb93cSSam Leffler conn->verify.md5_server = NULL; 86839beb93cSSam Leffler hlen = SHA1_MAC_LEN; 86939beb93cSSam Leffler if (conn->verify.sha1_server == NULL || 87039beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN, 87139beb93cSSam Leffler &hlen) < 0) { 87239beb93cSSam Leffler conn->verify.sha1_server = NULL; 87339beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 87439beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 87539beb93cSSam Leffler return -1; 87639beb93cSSam Leffler } 87739beb93cSSam Leffler conn->verify.sha1_server = NULL; 878f05cddf9SRui Paulo hlen = MD5_MAC_LEN + SHA1_MAC_LEN; 87939beb93cSSam Leffler 880f05cddf9SRui Paulo #ifdef CONFIG_TLSV12 881f05cddf9SRui Paulo } 882f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */ 883f05cddf9SRui Paulo 884f05cddf9SRui Paulo if (tls_prf(conn->rl.tls_version, 885f05cddf9SRui Paulo conn->master_secret, TLS_MASTER_SECRET_LEN, 886f05cddf9SRui Paulo "server finished", hash, hlen, 887f05cddf9SRui Paulo verify_data + 1 + 3, TLS_VERIFY_DATA_LEN)) { 88839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); 88939beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 89039beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 89139beb93cSSam Leffler return -1; 89239beb93cSSam Leffler } 89339beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)", 894f05cddf9SRui Paulo verify_data + 1 + 3, TLS_VERIFY_DATA_LEN); 8955b9c547cSRui Paulo #ifdef CONFIG_TESTING_OPTIONS 8965b9c547cSRui Paulo if (conn->test_flags & TLS_BREAK_VERIFY_DATA) { 8975b9c547cSRui Paulo tlsv1_server_log(conn, "TESTING: Break verify_data (server)"); 8985b9c547cSRui Paulo verify_data[1 + 3 + 1] ^= 0x80; 8995b9c547cSRui Paulo } 9005b9c547cSRui Paulo #endif /* CONFIG_TESTING_OPTIONS */ 90139beb93cSSam Leffler 90239beb93cSSam Leffler /* Handshake */ 903f05cddf9SRui Paulo pos = hs_start = verify_data; 90439beb93cSSam Leffler /* HandshakeType msg_type */ 90539beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_FINISHED; 906f05cddf9SRui Paulo /* uint24 length */ 907f05cddf9SRui Paulo WPA_PUT_BE24(pos, TLS_VERIFY_DATA_LEN); 90839beb93cSSam Leffler pos += 3; 90939beb93cSSam Leffler pos += TLS_VERIFY_DATA_LEN; 91039beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 91139beb93cSSam Leffler 91239beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 913f05cddf9SRui Paulo *msgpos, end - *msgpos, hs_start, pos - hs_start, 914f05cddf9SRui Paulo &rlen) < 0) { 91539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); 91639beb93cSSam Leffler tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 91739beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 91839beb93cSSam Leffler return -1; 91939beb93cSSam Leffler } 92039beb93cSSam Leffler 921f05cddf9SRui Paulo *msgpos += rlen; 92239beb93cSSam Leffler 92339beb93cSSam Leffler return 0; 92439beb93cSSam Leffler } 92539beb93cSSam Leffler 92639beb93cSSam Leffler 92739beb93cSSam Leffler static u8 * tls_send_server_hello(struct tlsv1_server *conn, size_t *out_len) 92839beb93cSSam Leffler { 92939beb93cSSam Leffler u8 *msg, *end, *pos; 93039beb93cSSam Leffler size_t msglen; 931*780fb4a2SCy Schubert int ocsp_multi = 0; 932*780fb4a2SCy Schubert char *ocsp_resp = NULL; 933*780fb4a2SCy Schubert size_t ocsp_resp_len = 0; 93439beb93cSSam Leffler 93539beb93cSSam Leffler *out_len = 0; 93639beb93cSSam Leffler 937*780fb4a2SCy Schubert if (conn->status_request_multi && 938*780fb4a2SCy Schubert conn->cred->ocsp_stapling_response_multi) { 939*780fb4a2SCy Schubert ocsp_resp = os_readfile( 940*780fb4a2SCy Schubert conn->cred->ocsp_stapling_response_multi, 941*780fb4a2SCy Schubert &ocsp_resp_len); 942*780fb4a2SCy Schubert ocsp_multi = 1; 943*780fb4a2SCy Schubert } else if ((conn->status_request || conn->status_request_v2) && 944*780fb4a2SCy Schubert conn->cred->ocsp_stapling_response) { 945*780fb4a2SCy Schubert ocsp_resp = os_readfile(conn->cred->ocsp_stapling_response, 946*780fb4a2SCy Schubert &ocsp_resp_len); 947*780fb4a2SCy Schubert } 948*780fb4a2SCy Schubert if (!ocsp_resp) 949*780fb4a2SCy Schubert ocsp_resp_len = 0; 950*780fb4a2SCy Schubert 951*780fb4a2SCy Schubert msglen = 1000 + tls_server_cert_chain_der_len(conn) + ocsp_resp_len; 95239beb93cSSam Leffler 95339beb93cSSam Leffler msg = os_malloc(msglen); 954*780fb4a2SCy Schubert if (msg == NULL) { 955*780fb4a2SCy Schubert os_free(ocsp_resp); 95639beb93cSSam Leffler return NULL; 957*780fb4a2SCy Schubert } 95839beb93cSSam Leffler 95939beb93cSSam Leffler pos = msg; 96039beb93cSSam Leffler end = msg + msglen; 96139beb93cSSam Leffler 96239beb93cSSam Leffler if (tls_write_server_hello(conn, &pos, end) < 0) { 96339beb93cSSam Leffler os_free(msg); 964*780fb4a2SCy Schubert os_free(ocsp_resp); 96539beb93cSSam Leffler return NULL; 96639beb93cSSam Leffler } 96739beb93cSSam Leffler 96839beb93cSSam Leffler if (conn->use_session_ticket) { 969*780fb4a2SCy Schubert os_free(ocsp_resp); 970*780fb4a2SCy Schubert 97139beb93cSSam Leffler /* Abbreviated handshake using session ticket; RFC 4507 */ 97239beb93cSSam Leffler if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 || 97339beb93cSSam Leffler tls_write_server_finished(conn, &pos, end) < 0) { 97439beb93cSSam Leffler os_free(msg); 97539beb93cSSam Leffler return NULL; 97639beb93cSSam Leffler } 97739beb93cSSam Leffler 97839beb93cSSam Leffler *out_len = pos - msg; 97939beb93cSSam Leffler 98039beb93cSSam Leffler conn->state = CHANGE_CIPHER_SPEC; 98139beb93cSSam Leffler 98239beb93cSSam Leffler return msg; 98339beb93cSSam Leffler } 98439beb93cSSam Leffler 98539beb93cSSam Leffler /* Full handshake */ 98639beb93cSSam Leffler if (tls_write_server_certificate(conn, &pos, end) < 0 || 987*780fb4a2SCy Schubert tls_write_server_certificate_status(conn, &pos, end, ocsp_multi, 988*780fb4a2SCy Schubert ocsp_resp, ocsp_resp_len) < 0 || 98939beb93cSSam Leffler tls_write_server_key_exchange(conn, &pos, end) < 0 || 99039beb93cSSam Leffler tls_write_server_certificate_request(conn, &pos, end) < 0 || 99139beb93cSSam Leffler tls_write_server_hello_done(conn, &pos, end) < 0) { 99239beb93cSSam Leffler os_free(msg); 993*780fb4a2SCy Schubert os_free(ocsp_resp); 99439beb93cSSam Leffler return NULL; 99539beb93cSSam Leffler } 996*780fb4a2SCy Schubert os_free(ocsp_resp); 99739beb93cSSam Leffler 99839beb93cSSam Leffler *out_len = pos - msg; 99939beb93cSSam Leffler 100039beb93cSSam Leffler conn->state = CLIENT_CERTIFICATE; 100139beb93cSSam Leffler 100239beb93cSSam Leffler return msg; 100339beb93cSSam Leffler } 100439beb93cSSam Leffler 100539beb93cSSam Leffler 100639beb93cSSam Leffler static u8 * tls_send_change_cipher_spec(struct tlsv1_server *conn, 100739beb93cSSam Leffler size_t *out_len) 100839beb93cSSam Leffler { 100939beb93cSSam Leffler u8 *msg, *end, *pos; 101039beb93cSSam Leffler 101139beb93cSSam Leffler *out_len = 0; 101239beb93cSSam Leffler 101339beb93cSSam Leffler msg = os_malloc(1000); 101439beb93cSSam Leffler if (msg == NULL) 101539beb93cSSam Leffler return NULL; 101639beb93cSSam Leffler 101739beb93cSSam Leffler pos = msg; 101839beb93cSSam Leffler end = msg + 1000; 101939beb93cSSam Leffler 102039beb93cSSam Leffler if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 || 102139beb93cSSam Leffler tls_write_server_finished(conn, &pos, end) < 0) { 102239beb93cSSam Leffler os_free(msg); 102339beb93cSSam Leffler return NULL; 102439beb93cSSam Leffler } 102539beb93cSSam Leffler 102639beb93cSSam Leffler *out_len = pos - msg; 102739beb93cSSam Leffler 10285b9c547cSRui Paulo tlsv1_server_log(conn, "Handshake completed successfully"); 102939beb93cSSam Leffler conn->state = ESTABLISHED; 103039beb93cSSam Leffler 103139beb93cSSam Leffler return msg; 103239beb93cSSam Leffler } 103339beb93cSSam Leffler 103439beb93cSSam Leffler 103539beb93cSSam Leffler u8 * tlsv1_server_handshake_write(struct tlsv1_server *conn, size_t *out_len) 103639beb93cSSam Leffler { 103739beb93cSSam Leffler switch (conn->state) { 103839beb93cSSam Leffler case SERVER_HELLO: 103939beb93cSSam Leffler return tls_send_server_hello(conn, out_len); 104039beb93cSSam Leffler case SERVER_CHANGE_CIPHER_SPEC: 104139beb93cSSam Leffler return tls_send_change_cipher_spec(conn, out_len); 104239beb93cSSam Leffler default: 104339beb93cSSam Leffler if (conn->state == ESTABLISHED && conn->use_session_ticket) { 104439beb93cSSam Leffler /* Abbreviated handshake was already completed. */ 104539beb93cSSam Leffler return NULL; 104639beb93cSSam Leffler } 10475b9c547cSRui Paulo tlsv1_server_log(conn, "Unexpected state %d while generating reply", 10485b9c547cSRui Paulo conn->state); 104939beb93cSSam Leffler return NULL; 105039beb93cSSam Leffler } 105139beb93cSSam Leffler } 105239beb93cSSam Leffler 105339beb93cSSam Leffler 105439beb93cSSam Leffler u8 * tlsv1_server_send_alert(struct tlsv1_server *conn, u8 level, 105539beb93cSSam Leffler u8 description, size_t *out_len) 105639beb93cSSam Leffler { 105739beb93cSSam Leffler u8 *alert, *pos, *length; 105839beb93cSSam Leffler 10595b9c547cSRui Paulo tlsv1_server_log(conn, "Send Alert(%d:%d)", level, description); 106039beb93cSSam Leffler *out_len = 0; 106139beb93cSSam Leffler 106239beb93cSSam Leffler alert = os_malloc(10); 106339beb93cSSam Leffler if (alert == NULL) 106439beb93cSSam Leffler return NULL; 106539beb93cSSam Leffler 106639beb93cSSam Leffler pos = alert; 106739beb93cSSam Leffler 106839beb93cSSam Leffler /* TLSPlaintext */ 106939beb93cSSam Leffler /* ContentType type */ 107039beb93cSSam Leffler *pos++ = TLS_CONTENT_TYPE_ALERT; 107139beb93cSSam Leffler /* ProtocolVersion version */ 1072f05cddf9SRui Paulo WPA_PUT_BE16(pos, conn->rl.tls_version ? conn->rl.tls_version : 1073f05cddf9SRui Paulo TLS_VERSION); 107439beb93cSSam Leffler pos += 2; 107539beb93cSSam Leffler /* uint16 length (to be filled) */ 107639beb93cSSam Leffler length = pos; 107739beb93cSSam Leffler pos += 2; 107839beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 107939beb93cSSam Leffler 108039beb93cSSam Leffler /* Alert */ 108139beb93cSSam Leffler /* AlertLevel level */ 108239beb93cSSam Leffler *pos++ = level; 108339beb93cSSam Leffler /* AlertDescription description */ 108439beb93cSSam Leffler *pos++ = description; 108539beb93cSSam Leffler 108639beb93cSSam Leffler WPA_PUT_BE16(length, pos - length - 2); 108739beb93cSSam Leffler *out_len = pos - alert; 108839beb93cSSam Leffler 108939beb93cSSam Leffler return alert; 109039beb93cSSam Leffler } 1091