139beb93cSSam Leffler /* 239beb93cSSam Leffler * TLSv1 client - write handshake message 339beb93cSSam Leffler * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 539beb93cSSam Leffler * This program is free software; you can redistribute it and/or modify 639beb93cSSam Leffler * it under the terms of the GNU General Public License version 2 as 739beb93cSSam Leffler * published by the Free Software Foundation. 839beb93cSSam Leffler * 939beb93cSSam Leffler * Alternatively, this software may be distributed under the terms of BSD 1039beb93cSSam Leffler * license. 1139beb93cSSam Leffler * 1239beb93cSSam Leffler * See README and COPYING for more details. 1339beb93cSSam Leffler */ 1439beb93cSSam Leffler 1539beb93cSSam Leffler #include "includes.h" 1639beb93cSSam Leffler 1739beb93cSSam Leffler #include "common.h" 1839beb93cSSam Leffler #include "md5.h" 1939beb93cSSam Leffler #include "sha1.h" 2039beb93cSSam Leffler #include "x509v3.h" 2139beb93cSSam Leffler #include "tls.h" 2239beb93cSSam Leffler #include "tlsv1_common.h" 2339beb93cSSam Leffler #include "tlsv1_record.h" 2439beb93cSSam Leffler #include "tlsv1_client.h" 2539beb93cSSam Leffler #include "tlsv1_client_i.h" 2639beb93cSSam Leffler 2739beb93cSSam Leffler 2839beb93cSSam Leffler static size_t tls_client_cert_chain_der_len(struct tlsv1_client *conn) 2939beb93cSSam Leffler { 3039beb93cSSam Leffler size_t len = 0; 3139beb93cSSam Leffler struct x509_certificate *cert; 3239beb93cSSam Leffler 3339beb93cSSam Leffler if (conn->cred == NULL) 3439beb93cSSam Leffler return 0; 3539beb93cSSam Leffler 3639beb93cSSam Leffler cert = conn->cred->cert; 3739beb93cSSam Leffler while (cert) { 3839beb93cSSam Leffler len += 3 + cert->cert_len; 3939beb93cSSam Leffler if (x509_certificate_self_signed(cert)) 4039beb93cSSam Leffler break; 4139beb93cSSam Leffler cert = x509_certificate_get_subject(conn->cred->trusted_certs, 4239beb93cSSam Leffler &cert->issuer); 4339beb93cSSam Leffler } 4439beb93cSSam Leffler 4539beb93cSSam Leffler return len; 4639beb93cSSam Leffler } 4739beb93cSSam Leffler 4839beb93cSSam Leffler 4939beb93cSSam Leffler u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len) 5039beb93cSSam Leffler { 5139beb93cSSam Leffler u8 *hello, *end, *pos, *hs_length, *hs_start, *rhdr; 5239beb93cSSam Leffler struct os_time now; 5339beb93cSSam Leffler size_t len, i; 5439beb93cSSam Leffler 5539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello"); 5639beb93cSSam Leffler *out_len = 0; 5739beb93cSSam Leffler 5839beb93cSSam Leffler os_get_time(&now); 5939beb93cSSam Leffler WPA_PUT_BE32(conn->client_random, now.sec); 6039beb93cSSam Leffler if (os_get_random(conn->client_random + 4, TLS_RANDOM_LEN - 4)) { 6139beb93cSSam Leffler wpa_printf(MSG_ERROR, "TLSv1: Could not generate " 6239beb93cSSam Leffler "client_random"); 6339beb93cSSam Leffler return NULL; 6439beb93cSSam Leffler } 6539beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random", 6639beb93cSSam Leffler conn->client_random, TLS_RANDOM_LEN); 6739beb93cSSam Leffler 6839beb93cSSam Leffler len = 100 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len; 6939beb93cSSam Leffler hello = os_malloc(len); 7039beb93cSSam Leffler if (hello == NULL) 7139beb93cSSam Leffler return NULL; 7239beb93cSSam Leffler end = hello + len; 7339beb93cSSam Leffler 7439beb93cSSam Leffler rhdr = hello; 7539beb93cSSam Leffler pos = rhdr + TLS_RECORD_HEADER_LEN; 7639beb93cSSam Leffler 7739beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 7839beb93cSSam Leffler 7939beb93cSSam Leffler /* Handshake */ 8039beb93cSSam Leffler hs_start = pos; 8139beb93cSSam Leffler /* HandshakeType msg_type */ 8239beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_HELLO; 8339beb93cSSam Leffler /* uint24 length (to be filled) */ 8439beb93cSSam Leffler hs_length = pos; 8539beb93cSSam Leffler pos += 3; 8639beb93cSSam Leffler /* body - ClientHello */ 8739beb93cSSam Leffler /* ProtocolVersion client_version */ 8839beb93cSSam Leffler WPA_PUT_BE16(pos, TLS_VERSION); 8939beb93cSSam Leffler pos += 2; 9039beb93cSSam Leffler /* Random random: uint32 gmt_unix_time, opaque random_bytes */ 9139beb93cSSam Leffler os_memcpy(pos, conn->client_random, TLS_RANDOM_LEN); 9239beb93cSSam Leffler pos += TLS_RANDOM_LEN; 9339beb93cSSam Leffler /* SessionID session_id */ 9439beb93cSSam Leffler *pos++ = conn->session_id_len; 9539beb93cSSam Leffler os_memcpy(pos, conn->session_id, conn->session_id_len); 9639beb93cSSam Leffler pos += conn->session_id_len; 9739beb93cSSam Leffler /* CipherSuite cipher_suites<2..2^16-1> */ 9839beb93cSSam Leffler WPA_PUT_BE16(pos, 2 * conn->num_cipher_suites); 9939beb93cSSam Leffler pos += 2; 10039beb93cSSam Leffler for (i = 0; i < conn->num_cipher_suites; i++) { 10139beb93cSSam Leffler WPA_PUT_BE16(pos, conn->cipher_suites[i]); 10239beb93cSSam Leffler pos += 2; 10339beb93cSSam Leffler } 10439beb93cSSam Leffler /* CompressionMethod compression_methods<1..2^8-1> */ 10539beb93cSSam Leffler *pos++ = 1; 10639beb93cSSam Leffler *pos++ = TLS_COMPRESSION_NULL; 10739beb93cSSam Leffler 10839beb93cSSam Leffler if (conn->client_hello_ext) { 10939beb93cSSam Leffler os_memcpy(pos, conn->client_hello_ext, 11039beb93cSSam Leffler conn->client_hello_ext_len); 11139beb93cSSam Leffler pos += conn->client_hello_ext_len; 11239beb93cSSam Leffler } 11339beb93cSSam Leffler 11439beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 11539beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 11639beb93cSSam Leffler 11739beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 11839beb93cSSam Leffler rhdr, end - rhdr, pos - hs_start, out_len) < 0) { 11939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record"); 12039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 12139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 12239beb93cSSam Leffler os_free(hello); 12339beb93cSSam Leffler return NULL; 12439beb93cSSam Leffler } 12539beb93cSSam Leffler 12639beb93cSSam Leffler conn->state = SERVER_HELLO; 12739beb93cSSam Leffler 12839beb93cSSam Leffler return hello; 12939beb93cSSam Leffler } 13039beb93cSSam Leffler 13139beb93cSSam Leffler 13239beb93cSSam Leffler static int tls_write_client_certificate(struct tlsv1_client *conn, 13339beb93cSSam Leffler u8 **msgpos, u8 *end) 13439beb93cSSam Leffler { 13539beb93cSSam Leffler u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start; 13639beb93cSSam Leffler size_t rlen; 13739beb93cSSam Leffler struct x509_certificate *cert; 13839beb93cSSam Leffler 13939beb93cSSam Leffler pos = *msgpos; 14039beb93cSSam Leffler 14139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate"); 14239beb93cSSam Leffler rhdr = pos; 14339beb93cSSam Leffler pos += TLS_RECORD_HEADER_LEN; 14439beb93cSSam Leffler 14539beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 14639beb93cSSam Leffler 14739beb93cSSam Leffler /* Handshake */ 14839beb93cSSam Leffler hs_start = pos; 14939beb93cSSam Leffler /* HandshakeType msg_type */ 15039beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE; 15139beb93cSSam Leffler /* uint24 length (to be filled) */ 15239beb93cSSam Leffler hs_length = pos; 15339beb93cSSam Leffler pos += 3; 15439beb93cSSam Leffler /* body - Certificate */ 15539beb93cSSam Leffler /* uint24 length (to be filled) */ 15639beb93cSSam Leffler cert_start = pos; 15739beb93cSSam Leffler pos += 3; 15839beb93cSSam Leffler cert = conn->cred ? conn->cred->cert : NULL; 15939beb93cSSam Leffler while (cert) { 16039beb93cSSam Leffler if (pos + 3 + cert->cert_len > end) { 16139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space " 16239beb93cSSam Leffler "for Certificate (cert_len=%lu left=%lu)", 16339beb93cSSam Leffler (unsigned long) cert->cert_len, 16439beb93cSSam Leffler (unsigned long) (end - pos)); 16539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 16639beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 16739beb93cSSam Leffler return -1; 16839beb93cSSam Leffler } 16939beb93cSSam Leffler WPA_PUT_BE24(pos, cert->cert_len); 17039beb93cSSam Leffler pos += 3; 17139beb93cSSam Leffler os_memcpy(pos, cert->cert_start, cert->cert_len); 17239beb93cSSam Leffler pos += cert->cert_len; 17339beb93cSSam Leffler 17439beb93cSSam Leffler if (x509_certificate_self_signed(cert)) 17539beb93cSSam Leffler break; 17639beb93cSSam Leffler cert = x509_certificate_get_subject(conn->cred->trusted_certs, 17739beb93cSSam Leffler &cert->issuer); 17839beb93cSSam Leffler } 17939beb93cSSam Leffler if (conn->cred == NULL || cert == conn->cred->cert || cert == NULL) { 18039beb93cSSam Leffler /* 18139beb93cSSam Leffler * Client was not configured with all the needed certificates 18239beb93cSSam Leffler * to form a full certificate chain. The server may fail to 18339beb93cSSam Leffler * validate the chain unless it is configured with all the 18439beb93cSSam Leffler * missing CA certificates. 18539beb93cSSam Leffler */ 18639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Full client certificate chain " 18739beb93cSSam Leffler "not configured - validation may fail"); 18839beb93cSSam Leffler } 18939beb93cSSam Leffler WPA_PUT_BE24(cert_start, pos - cert_start - 3); 19039beb93cSSam Leffler 19139beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 19239beb93cSSam Leffler 19339beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 19439beb93cSSam Leffler rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { 19539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); 19639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 19739beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 19839beb93cSSam Leffler return -1; 19939beb93cSSam Leffler } 20039beb93cSSam Leffler pos = rhdr + rlen; 20139beb93cSSam Leffler 20239beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 20339beb93cSSam Leffler 20439beb93cSSam Leffler *msgpos = pos; 20539beb93cSSam Leffler 20639beb93cSSam Leffler return 0; 20739beb93cSSam Leffler } 20839beb93cSSam Leffler 20939beb93cSSam Leffler 21039beb93cSSam Leffler static int tlsv1_key_x_anon_dh(struct tlsv1_client *conn, u8 **pos, u8 *end) 21139beb93cSSam Leffler { 21239beb93cSSam Leffler #ifdef EAP_FAST 21339beb93cSSam Leffler /* ClientDiffieHellmanPublic */ 21439beb93cSSam Leffler u8 *csecret, *csecret_start, *dh_yc, *shared; 21539beb93cSSam Leffler size_t csecret_len, dh_yc_len, shared_len; 21639beb93cSSam Leffler 21739beb93cSSam Leffler csecret_len = conn->dh_p_len; 21839beb93cSSam Leffler csecret = os_malloc(csecret_len); 21939beb93cSSam Leffler if (csecret == NULL) { 22039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " 22139beb93cSSam Leffler "memory for Yc (Diffie-Hellman)"); 22239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 22339beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 22439beb93cSSam Leffler return -1; 22539beb93cSSam Leffler } 22639beb93cSSam Leffler if (os_get_random(csecret, csecret_len)) { 22739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " 22839beb93cSSam Leffler "data for Diffie-Hellman"); 22939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 23039beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 23139beb93cSSam Leffler os_free(csecret); 23239beb93cSSam Leffler return -1; 23339beb93cSSam Leffler } 23439beb93cSSam Leffler 23539beb93cSSam Leffler if (os_memcmp(csecret, conn->dh_p, csecret_len) > 0) 23639beb93cSSam Leffler csecret[0] = 0; /* make sure Yc < p */ 23739beb93cSSam Leffler 23839beb93cSSam Leffler csecret_start = csecret; 23939beb93cSSam Leffler while (csecret_len > 1 && *csecret_start == 0) { 24039beb93cSSam Leffler csecret_start++; 24139beb93cSSam Leffler csecret_len--; 24239beb93cSSam Leffler } 24339beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH client's secret value", 24439beb93cSSam Leffler csecret_start, csecret_len); 24539beb93cSSam Leffler 24639beb93cSSam Leffler /* Yc = g^csecret mod p */ 24739beb93cSSam Leffler dh_yc_len = conn->dh_p_len; 24839beb93cSSam Leffler dh_yc = os_malloc(dh_yc_len); 24939beb93cSSam Leffler if (dh_yc == NULL) { 25039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " 25139beb93cSSam Leffler "memory for Diffie-Hellman"); 25239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 25339beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 25439beb93cSSam Leffler os_free(csecret); 25539beb93cSSam Leffler return -1; 25639beb93cSSam Leffler } 25739beb93cSSam Leffler if (crypto_mod_exp(conn->dh_g, conn->dh_g_len, 25839beb93cSSam Leffler csecret_start, csecret_len, 25939beb93cSSam Leffler conn->dh_p, conn->dh_p_len, 26039beb93cSSam Leffler dh_yc, &dh_yc_len)) { 26139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 26239beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 26339beb93cSSam Leffler os_free(csecret); 26439beb93cSSam Leffler os_free(dh_yc); 26539beb93cSSam Leffler return -1; 26639beb93cSSam Leffler } 26739beb93cSSam Leffler 26839beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)", 26939beb93cSSam Leffler dh_yc, dh_yc_len); 27039beb93cSSam Leffler 27139beb93cSSam Leffler WPA_PUT_BE16(*pos, dh_yc_len); 27239beb93cSSam Leffler *pos += 2; 27339beb93cSSam Leffler if (*pos + dh_yc_len > end) { 27439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Not enough room in the " 27539beb93cSSam Leffler "message buffer for Yc"); 27639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 27739beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 27839beb93cSSam Leffler os_free(csecret); 27939beb93cSSam Leffler os_free(dh_yc); 28039beb93cSSam Leffler return -1; 28139beb93cSSam Leffler } 28239beb93cSSam Leffler os_memcpy(*pos, dh_yc, dh_yc_len); 28339beb93cSSam Leffler *pos += dh_yc_len; 28439beb93cSSam Leffler os_free(dh_yc); 28539beb93cSSam Leffler 28639beb93cSSam Leffler shared_len = conn->dh_p_len; 28739beb93cSSam Leffler shared = os_malloc(shared_len); 28839beb93cSSam Leffler if (shared == NULL) { 28939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for " 29039beb93cSSam Leffler "DH"); 29139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 29239beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 29339beb93cSSam Leffler os_free(csecret); 29439beb93cSSam Leffler return -1; 29539beb93cSSam Leffler } 29639beb93cSSam Leffler 29739beb93cSSam Leffler /* shared = Ys^csecret mod p */ 29839beb93cSSam Leffler if (crypto_mod_exp(conn->dh_ys, conn->dh_ys_len, 29939beb93cSSam Leffler csecret_start, csecret_len, 30039beb93cSSam Leffler conn->dh_p, conn->dh_p_len, 30139beb93cSSam Leffler shared, &shared_len)) { 30239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 30339beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 30439beb93cSSam Leffler os_free(csecret); 30539beb93cSSam Leffler os_free(shared); 30639beb93cSSam Leffler return -1; 30739beb93cSSam Leffler } 30839beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange", 30939beb93cSSam Leffler shared, shared_len); 31039beb93cSSam Leffler 31139beb93cSSam Leffler os_memset(csecret_start, 0, csecret_len); 31239beb93cSSam Leffler os_free(csecret); 31339beb93cSSam Leffler if (tls_derive_keys(conn, shared, shared_len)) { 31439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); 31539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 31639beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 31739beb93cSSam Leffler os_free(shared); 31839beb93cSSam Leffler return -1; 31939beb93cSSam Leffler } 32039beb93cSSam Leffler os_memset(shared, 0, shared_len); 32139beb93cSSam Leffler os_free(shared); 32239beb93cSSam Leffler tlsv1_client_free_dh(conn); 32339beb93cSSam Leffler return 0; 32439beb93cSSam Leffler #else /* EAP_FAST */ 32539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); 32639beb93cSSam Leffler return -1; 32739beb93cSSam Leffler #endif /* EAP_FAST */ 32839beb93cSSam Leffler } 32939beb93cSSam Leffler 33039beb93cSSam Leffler 33139beb93cSSam Leffler static int tlsv1_key_x_rsa(struct tlsv1_client *conn, u8 **pos, u8 *end) 33239beb93cSSam Leffler { 33339beb93cSSam Leffler u8 pre_master_secret[TLS_PRE_MASTER_SECRET_LEN]; 33439beb93cSSam Leffler size_t clen; 33539beb93cSSam Leffler int res; 33639beb93cSSam Leffler 33739beb93cSSam Leffler if (tls_derive_pre_master_secret(pre_master_secret) < 0 || 33839beb93cSSam Leffler tls_derive_keys(conn, pre_master_secret, 33939beb93cSSam Leffler TLS_PRE_MASTER_SECRET_LEN)) { 34039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); 34139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 34239beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 34339beb93cSSam Leffler return -1; 34439beb93cSSam Leffler } 34539beb93cSSam Leffler 34639beb93cSSam Leffler /* EncryptedPreMasterSecret */ 34739beb93cSSam Leffler if (conn->server_rsa_key == NULL) { 34839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: No server RSA key to " 34939beb93cSSam Leffler "use for encrypting pre-master secret"); 35039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 35139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 35239beb93cSSam Leffler return -1; 35339beb93cSSam Leffler } 35439beb93cSSam Leffler 35539beb93cSSam Leffler /* RSA encrypted value is encoded with PKCS #1 v1.5 block type 2. */ 35639beb93cSSam Leffler *pos += 2; 35739beb93cSSam Leffler clen = end - *pos; 35839beb93cSSam Leffler res = crypto_public_key_encrypt_pkcs1_v15( 35939beb93cSSam Leffler conn->server_rsa_key, 36039beb93cSSam Leffler pre_master_secret, TLS_PRE_MASTER_SECRET_LEN, 36139beb93cSSam Leffler *pos, &clen); 36239beb93cSSam Leffler os_memset(pre_master_secret, 0, TLS_PRE_MASTER_SECRET_LEN); 36339beb93cSSam Leffler if (res < 0) { 36439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: RSA encryption failed"); 36539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 36639beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 36739beb93cSSam Leffler return -1; 36839beb93cSSam Leffler } 36939beb93cSSam Leffler WPA_PUT_BE16(*pos - 2, clen); 37039beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: Encrypted pre_master_secret", 37139beb93cSSam Leffler *pos, clen); 37239beb93cSSam Leffler *pos += clen; 37339beb93cSSam Leffler 37439beb93cSSam Leffler return 0; 37539beb93cSSam Leffler } 37639beb93cSSam Leffler 37739beb93cSSam Leffler 37839beb93cSSam Leffler static int tls_write_client_key_exchange(struct tlsv1_client *conn, 37939beb93cSSam Leffler u8 **msgpos, u8 *end) 38039beb93cSSam Leffler { 38139beb93cSSam Leffler u8 *pos, *rhdr, *hs_start, *hs_length; 38239beb93cSSam Leffler size_t rlen; 38339beb93cSSam Leffler tls_key_exchange keyx; 38439beb93cSSam Leffler const struct tls_cipher_suite *suite; 38539beb93cSSam Leffler 38639beb93cSSam Leffler suite = tls_get_cipher_suite(conn->rl.cipher_suite); 38739beb93cSSam Leffler if (suite == NULL) 38839beb93cSSam Leffler keyx = TLS_KEY_X_NULL; 38939beb93cSSam Leffler else 39039beb93cSSam Leffler keyx = suite->key_exchange; 39139beb93cSSam Leffler 39239beb93cSSam Leffler pos = *msgpos; 39339beb93cSSam Leffler 39439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send ClientKeyExchange"); 39539beb93cSSam Leffler 39639beb93cSSam Leffler rhdr = pos; 39739beb93cSSam Leffler pos += TLS_RECORD_HEADER_LEN; 39839beb93cSSam Leffler 39939beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 40039beb93cSSam Leffler 40139beb93cSSam Leffler /* Handshake */ 40239beb93cSSam Leffler hs_start = pos; 40339beb93cSSam Leffler /* HandshakeType msg_type */ 40439beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE; 40539beb93cSSam Leffler /* uint24 length (to be filled) */ 40639beb93cSSam Leffler hs_length = pos; 40739beb93cSSam Leffler pos += 3; 40839beb93cSSam Leffler /* body - ClientKeyExchange */ 40939beb93cSSam Leffler if (keyx == TLS_KEY_X_DH_anon) { 41039beb93cSSam Leffler if (tlsv1_key_x_anon_dh(conn, &pos, end) < 0) 41139beb93cSSam Leffler return -1; 41239beb93cSSam Leffler } else { 41339beb93cSSam Leffler if (tlsv1_key_x_rsa(conn, &pos, end) < 0) 41439beb93cSSam Leffler return -1; 41539beb93cSSam Leffler } 41639beb93cSSam Leffler 41739beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 41839beb93cSSam Leffler 41939beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 42039beb93cSSam Leffler rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { 42139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); 42239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 42339beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 42439beb93cSSam Leffler return -1; 42539beb93cSSam Leffler } 42639beb93cSSam Leffler pos = rhdr + rlen; 42739beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 42839beb93cSSam Leffler 42939beb93cSSam Leffler *msgpos = pos; 43039beb93cSSam Leffler 43139beb93cSSam Leffler return 0; 43239beb93cSSam Leffler } 43339beb93cSSam Leffler 43439beb93cSSam Leffler 43539beb93cSSam Leffler static int tls_write_client_certificate_verify(struct tlsv1_client *conn, 43639beb93cSSam Leffler u8 **msgpos, u8 *end) 43739beb93cSSam Leffler { 43839beb93cSSam Leffler u8 *pos, *rhdr, *hs_start, *hs_length, *signed_start; 43939beb93cSSam Leffler size_t rlen, hlen, clen; 44039beb93cSSam Leffler u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos; 44139beb93cSSam Leffler enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA; 44239beb93cSSam Leffler 44339beb93cSSam Leffler pos = *msgpos; 44439beb93cSSam Leffler 44539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateVerify"); 44639beb93cSSam Leffler rhdr = pos; 44739beb93cSSam Leffler pos += TLS_RECORD_HEADER_LEN; 44839beb93cSSam Leffler 44939beb93cSSam Leffler /* Handshake */ 45039beb93cSSam Leffler hs_start = pos; 45139beb93cSSam Leffler /* HandshakeType msg_type */ 45239beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY; 45339beb93cSSam Leffler /* uint24 length (to be filled) */ 45439beb93cSSam Leffler hs_length = pos; 45539beb93cSSam Leffler pos += 3; 45639beb93cSSam Leffler 45739beb93cSSam Leffler /* 45839beb93cSSam Leffler * RFC 2246: 7.4.3 and 7.4.8: 45939beb93cSSam Leffler * Signature signature 46039beb93cSSam Leffler * 46139beb93cSSam Leffler * RSA: 46239beb93cSSam Leffler * digitally-signed struct { 46339beb93cSSam Leffler * opaque md5_hash[16]; 46439beb93cSSam Leffler * opaque sha_hash[20]; 46539beb93cSSam Leffler * }; 46639beb93cSSam Leffler * 46739beb93cSSam Leffler * DSA: 46839beb93cSSam Leffler * digitally-signed struct { 46939beb93cSSam Leffler * opaque sha_hash[20]; 47039beb93cSSam Leffler * }; 47139beb93cSSam Leffler * 47239beb93cSSam Leffler * The hash values are calculated over all handshake messages sent or 47339beb93cSSam Leffler * received starting at ClientHello up to, but not including, this 47439beb93cSSam Leffler * CertificateVerify message, including the type and length fields of 47539beb93cSSam Leffler * the handshake messages. 47639beb93cSSam Leffler */ 47739beb93cSSam Leffler 47839beb93cSSam Leffler hpos = hash; 47939beb93cSSam Leffler 48039beb93cSSam Leffler if (alg == SIGN_ALG_RSA) { 48139beb93cSSam Leffler hlen = MD5_MAC_LEN; 48239beb93cSSam Leffler if (conn->verify.md5_cert == NULL || 48339beb93cSSam Leffler crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) 48439beb93cSSam Leffler { 48539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 48639beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 48739beb93cSSam Leffler conn->verify.md5_cert = NULL; 48839beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL); 48939beb93cSSam Leffler conn->verify.sha1_cert = NULL; 49039beb93cSSam Leffler return -1; 49139beb93cSSam Leffler } 49239beb93cSSam Leffler hpos += MD5_MAC_LEN; 49339beb93cSSam Leffler } else 49439beb93cSSam Leffler crypto_hash_finish(conn->verify.md5_cert, NULL, NULL); 49539beb93cSSam Leffler 49639beb93cSSam Leffler conn->verify.md5_cert = NULL; 49739beb93cSSam Leffler hlen = SHA1_MAC_LEN; 49839beb93cSSam Leffler if (conn->verify.sha1_cert == NULL || 49939beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) { 50039beb93cSSam Leffler conn->verify.sha1_cert = NULL; 50139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 50239beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 50339beb93cSSam Leffler return -1; 50439beb93cSSam Leffler } 50539beb93cSSam Leffler conn->verify.sha1_cert = NULL; 50639beb93cSSam Leffler 50739beb93cSSam Leffler if (alg == SIGN_ALG_RSA) 50839beb93cSSam Leffler hlen += MD5_MAC_LEN; 50939beb93cSSam Leffler 51039beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen); 51139beb93cSSam Leffler 51239beb93cSSam Leffler /* 51339beb93cSSam Leffler * RFC 2246, 4.7: 51439beb93cSSam Leffler * In digital signing, one-way hash functions are used as input for a 51539beb93cSSam Leffler * signing algorithm. A digitally-signed element is encoded as an 51639beb93cSSam Leffler * opaque vector <0..2^16-1>, where the length is specified by the 51739beb93cSSam Leffler * signing algorithm and key. 51839beb93cSSam Leffler * 51939beb93cSSam Leffler * In RSA signing, a 36-byte structure of two hashes (one SHA and one 52039beb93cSSam Leffler * MD5) is signed (encrypted with the private key). It is encoded with 52139beb93cSSam Leffler * PKCS #1 block type 0 or type 1 as described in [PKCS1]. 52239beb93cSSam Leffler */ 52339beb93cSSam Leffler signed_start = pos; /* length to be filled */ 52439beb93cSSam Leffler pos += 2; 52539beb93cSSam Leffler clen = end - pos; 52639beb93cSSam Leffler if (conn->cred == NULL || 52739beb93cSSam Leffler crypto_private_key_sign_pkcs1(conn->cred->key, hash, hlen, 52839beb93cSSam Leffler pos, &clen) < 0) { 52939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to sign hash (PKCS #1)"); 53039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 53139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 53239beb93cSSam Leffler return -1; 53339beb93cSSam Leffler } 53439beb93cSSam Leffler WPA_PUT_BE16(signed_start, clen); 53539beb93cSSam Leffler 53639beb93cSSam Leffler pos += clen; 53739beb93cSSam Leffler 53839beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 53939beb93cSSam Leffler 54039beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 54139beb93cSSam Leffler rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { 54239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); 54339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 54439beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 54539beb93cSSam Leffler return -1; 54639beb93cSSam Leffler } 54739beb93cSSam Leffler pos = rhdr + rlen; 54839beb93cSSam Leffler 54939beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 55039beb93cSSam Leffler 55139beb93cSSam Leffler *msgpos = pos; 55239beb93cSSam Leffler 55339beb93cSSam Leffler return 0; 55439beb93cSSam Leffler } 55539beb93cSSam Leffler 55639beb93cSSam Leffler 55739beb93cSSam Leffler static int tls_write_client_change_cipher_spec(struct tlsv1_client *conn, 55839beb93cSSam Leffler u8 **msgpos, u8 *end) 55939beb93cSSam Leffler { 56039beb93cSSam Leffler u8 *pos, *rhdr; 56139beb93cSSam Leffler size_t rlen; 56239beb93cSSam Leffler 56339beb93cSSam Leffler pos = *msgpos; 56439beb93cSSam Leffler 56539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec"); 56639beb93cSSam Leffler rhdr = pos; 56739beb93cSSam Leffler pos += TLS_RECORD_HEADER_LEN; 56839beb93cSSam Leffler *pos = TLS_CHANGE_CIPHER_SPEC; 56939beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC, 57039beb93cSSam Leffler rhdr, end - rhdr, 1, &rlen) < 0) { 57139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); 57239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 57339beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 57439beb93cSSam Leffler return -1; 57539beb93cSSam Leffler } 57639beb93cSSam Leffler 57739beb93cSSam Leffler if (tlsv1_record_change_write_cipher(&conn->rl) < 0) { 57839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for " 57939beb93cSSam Leffler "record layer"); 58039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 58139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 58239beb93cSSam Leffler return -1; 58339beb93cSSam Leffler } 58439beb93cSSam Leffler 58539beb93cSSam Leffler *msgpos = rhdr + rlen; 58639beb93cSSam Leffler 58739beb93cSSam Leffler return 0; 58839beb93cSSam Leffler } 58939beb93cSSam Leffler 59039beb93cSSam Leffler 59139beb93cSSam Leffler static int tls_write_client_finished(struct tlsv1_client *conn, 59239beb93cSSam Leffler u8 **msgpos, u8 *end) 59339beb93cSSam Leffler { 59439beb93cSSam Leffler u8 *pos, *rhdr, *hs_start, *hs_length; 59539beb93cSSam Leffler size_t rlen, hlen; 59639beb93cSSam Leffler u8 verify_data[TLS_VERIFY_DATA_LEN]; 59739beb93cSSam Leffler u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; 59839beb93cSSam Leffler 59939beb93cSSam Leffler pos = *msgpos; 60039beb93cSSam Leffler 60139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send Finished"); 60239beb93cSSam Leffler 60339beb93cSSam Leffler /* Encrypted Handshake Message: Finished */ 60439beb93cSSam Leffler 60539beb93cSSam Leffler hlen = MD5_MAC_LEN; 60639beb93cSSam Leffler if (conn->verify.md5_client == NULL || 60739beb93cSSam Leffler crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) { 60839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 60939beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 61039beb93cSSam Leffler conn->verify.md5_client = NULL; 61139beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_client, NULL, NULL); 61239beb93cSSam Leffler conn->verify.sha1_client = NULL; 61339beb93cSSam Leffler return -1; 61439beb93cSSam Leffler } 61539beb93cSSam Leffler conn->verify.md5_client = NULL; 61639beb93cSSam Leffler hlen = SHA1_MAC_LEN; 61739beb93cSSam Leffler if (conn->verify.sha1_client == NULL || 61839beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN, 61939beb93cSSam Leffler &hlen) < 0) { 62039beb93cSSam Leffler conn->verify.sha1_client = NULL; 62139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 62239beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 62339beb93cSSam Leffler return -1; 62439beb93cSSam Leffler } 62539beb93cSSam Leffler conn->verify.sha1_client = NULL; 62639beb93cSSam Leffler 62739beb93cSSam Leffler if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, 62839beb93cSSam Leffler "client finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, 62939beb93cSSam Leffler verify_data, TLS_VERIFY_DATA_LEN)) { 63039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); 63139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 63239beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 63339beb93cSSam Leffler return -1; 63439beb93cSSam Leffler } 63539beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)", 63639beb93cSSam Leffler verify_data, TLS_VERIFY_DATA_LEN); 63739beb93cSSam Leffler 63839beb93cSSam Leffler rhdr = pos; 63939beb93cSSam Leffler pos += TLS_RECORD_HEADER_LEN; 64039beb93cSSam Leffler /* Handshake */ 64139beb93cSSam Leffler hs_start = pos; 64239beb93cSSam Leffler /* HandshakeType msg_type */ 64339beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_FINISHED; 64439beb93cSSam Leffler /* uint24 length (to be filled) */ 64539beb93cSSam Leffler hs_length = pos; 64639beb93cSSam Leffler pos += 3; 64739beb93cSSam Leffler os_memcpy(pos, verify_data, TLS_VERIFY_DATA_LEN); 64839beb93cSSam Leffler pos += TLS_VERIFY_DATA_LEN; 64939beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 65039beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 65139beb93cSSam Leffler 65239beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 65339beb93cSSam Leffler rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { 65439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); 65539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 65639beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 65739beb93cSSam Leffler return -1; 65839beb93cSSam Leffler } 65939beb93cSSam Leffler 66039beb93cSSam Leffler pos = rhdr + rlen; 66139beb93cSSam Leffler 66239beb93cSSam Leffler *msgpos = pos; 66339beb93cSSam Leffler 66439beb93cSSam Leffler return 0; 66539beb93cSSam Leffler } 66639beb93cSSam Leffler 66739beb93cSSam Leffler 66839beb93cSSam Leffler static u8 * tls_send_client_key_exchange(struct tlsv1_client *conn, 66939beb93cSSam Leffler size_t *out_len) 67039beb93cSSam Leffler { 67139beb93cSSam Leffler u8 *msg, *end, *pos; 67239beb93cSSam Leffler size_t msglen; 67339beb93cSSam Leffler 67439beb93cSSam Leffler *out_len = 0; 67539beb93cSSam Leffler 67639beb93cSSam Leffler msglen = 1000; 67739beb93cSSam Leffler if (conn->certificate_requested) 67839beb93cSSam Leffler msglen += tls_client_cert_chain_der_len(conn); 67939beb93cSSam Leffler 68039beb93cSSam Leffler msg = os_malloc(msglen); 68139beb93cSSam Leffler if (msg == NULL) 68239beb93cSSam Leffler return NULL; 68339beb93cSSam Leffler 68439beb93cSSam Leffler pos = msg; 68539beb93cSSam Leffler end = msg + msglen; 68639beb93cSSam Leffler 68739beb93cSSam Leffler if (conn->certificate_requested) { 68839beb93cSSam Leffler if (tls_write_client_certificate(conn, &pos, end) < 0) { 68939beb93cSSam Leffler os_free(msg); 69039beb93cSSam Leffler return NULL; 69139beb93cSSam Leffler } 69239beb93cSSam Leffler } 69339beb93cSSam Leffler 69439beb93cSSam Leffler if (tls_write_client_key_exchange(conn, &pos, end) < 0 || 69539beb93cSSam Leffler (conn->certificate_requested && conn->cred && conn->cred->key && 69639beb93cSSam Leffler tls_write_client_certificate_verify(conn, &pos, end) < 0) || 69739beb93cSSam Leffler tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || 69839beb93cSSam Leffler tls_write_client_finished(conn, &pos, end) < 0) { 69939beb93cSSam Leffler os_free(msg); 70039beb93cSSam Leffler return NULL; 70139beb93cSSam Leffler } 70239beb93cSSam Leffler 70339beb93cSSam Leffler *out_len = pos - msg; 70439beb93cSSam Leffler 70539beb93cSSam Leffler conn->state = SERVER_CHANGE_CIPHER_SPEC; 70639beb93cSSam Leffler 70739beb93cSSam Leffler return msg; 70839beb93cSSam Leffler } 70939beb93cSSam Leffler 71039beb93cSSam Leffler 71139beb93cSSam Leffler static u8 * tls_send_change_cipher_spec(struct tlsv1_client *conn, 71239beb93cSSam Leffler size_t *out_len) 71339beb93cSSam Leffler { 71439beb93cSSam Leffler u8 *msg, *end, *pos; 71539beb93cSSam Leffler 71639beb93cSSam Leffler *out_len = 0; 71739beb93cSSam Leffler 71839beb93cSSam Leffler msg = os_malloc(1000); 71939beb93cSSam Leffler if (msg == NULL) 72039beb93cSSam Leffler return NULL; 72139beb93cSSam Leffler 72239beb93cSSam Leffler pos = msg; 72339beb93cSSam Leffler end = msg + 1000; 72439beb93cSSam Leffler 72539beb93cSSam Leffler if (tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || 72639beb93cSSam Leffler tls_write_client_finished(conn, &pos, end) < 0) { 72739beb93cSSam Leffler os_free(msg); 72839beb93cSSam Leffler return NULL; 72939beb93cSSam Leffler } 73039beb93cSSam Leffler 73139beb93cSSam Leffler *out_len = pos - msg; 73239beb93cSSam Leffler 73339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Session resumption completed " 73439beb93cSSam Leffler "successfully"); 73539beb93cSSam Leffler conn->state = ESTABLISHED; 73639beb93cSSam Leffler 73739beb93cSSam Leffler return msg; 73839beb93cSSam Leffler } 73939beb93cSSam Leffler 74039beb93cSSam Leffler 74139beb93cSSam Leffler u8 * tlsv1_client_handshake_write(struct tlsv1_client *conn, size_t *out_len, 74239beb93cSSam Leffler int no_appl_data) 74339beb93cSSam Leffler { 74439beb93cSSam Leffler switch (conn->state) { 74539beb93cSSam Leffler case CLIENT_KEY_EXCHANGE: 74639beb93cSSam Leffler return tls_send_client_key_exchange(conn, out_len); 74739beb93cSSam Leffler case CHANGE_CIPHER_SPEC: 74839beb93cSSam Leffler return tls_send_change_cipher_spec(conn, out_len); 74939beb93cSSam Leffler case ACK_FINISHED: 75039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed " 75139beb93cSSam Leffler "successfully"); 75239beb93cSSam Leffler conn->state = ESTABLISHED; 75339beb93cSSam Leffler *out_len = 0; 75439beb93cSSam Leffler if (no_appl_data) { 75539beb93cSSam Leffler /* Need to return something to get final TLS ACK. */ 75639beb93cSSam Leffler return os_malloc(1); 75739beb93cSSam Leffler } 75839beb93cSSam Leffler return NULL; 75939beb93cSSam Leffler default: 76039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while " 76139beb93cSSam Leffler "generating reply", conn->state); 76239beb93cSSam Leffler return NULL; 76339beb93cSSam Leffler } 76439beb93cSSam Leffler } 76539beb93cSSam Leffler 76639beb93cSSam Leffler 76739beb93cSSam Leffler u8 * tlsv1_client_send_alert(struct tlsv1_client *conn, u8 level, 76839beb93cSSam Leffler u8 description, size_t *out_len) 76939beb93cSSam Leffler { 77039beb93cSSam Leffler u8 *alert, *pos, *length; 77139beb93cSSam Leffler 77239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description); 77339beb93cSSam Leffler *out_len = 0; 77439beb93cSSam Leffler 77539beb93cSSam Leffler alert = os_malloc(10); 77639beb93cSSam Leffler if (alert == NULL) 77739beb93cSSam Leffler return NULL; 77839beb93cSSam Leffler 77939beb93cSSam Leffler pos = alert; 78039beb93cSSam Leffler 78139beb93cSSam Leffler /* TLSPlaintext */ 78239beb93cSSam Leffler /* ContentType type */ 78339beb93cSSam Leffler *pos++ = TLS_CONTENT_TYPE_ALERT; 78439beb93cSSam Leffler /* ProtocolVersion version */ 78539beb93cSSam Leffler WPA_PUT_BE16(pos, TLS_VERSION); 78639beb93cSSam Leffler pos += 2; 78739beb93cSSam Leffler /* uint16 length (to be filled) */ 78839beb93cSSam Leffler length = pos; 78939beb93cSSam Leffler pos += 2; 79039beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 79139beb93cSSam Leffler 79239beb93cSSam Leffler /* Alert */ 79339beb93cSSam Leffler /* AlertLevel level */ 79439beb93cSSam Leffler *pos++ = level; 79539beb93cSSam Leffler /* AlertDescription description */ 79639beb93cSSam Leffler *pos++ = description; 79739beb93cSSam Leffler 79839beb93cSSam Leffler WPA_PUT_BE16(length, pos - length - 2); 79939beb93cSSam Leffler *out_len = pos - alert; 80039beb93cSSam Leffler 80139beb93cSSam Leffler return alert; 80239beb93cSSam Leffler } 803