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" 18*e28a4053SRui Paulo #include "crypto/md5.h" 19*e28a4053SRui Paulo #include "crypto/sha1.h" 20*e28a4053SRui Paulo #include "crypto/tls.h" 2139beb93cSSam Leffler #include "x509v3.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 /* ClientDiffieHellmanPublic */ 21339beb93cSSam Leffler u8 *csecret, *csecret_start, *dh_yc, *shared; 21439beb93cSSam Leffler size_t csecret_len, dh_yc_len, shared_len; 21539beb93cSSam Leffler 21639beb93cSSam Leffler csecret_len = conn->dh_p_len; 21739beb93cSSam Leffler csecret = os_malloc(csecret_len); 21839beb93cSSam Leffler if (csecret == NULL) { 21939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " 22039beb93cSSam Leffler "memory for Yc (Diffie-Hellman)"); 22139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 22239beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 22339beb93cSSam Leffler return -1; 22439beb93cSSam Leffler } 22539beb93cSSam Leffler if (os_get_random(csecret, csecret_len)) { 22639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " 22739beb93cSSam Leffler "data for Diffie-Hellman"); 22839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 22939beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 23039beb93cSSam Leffler os_free(csecret); 23139beb93cSSam Leffler return -1; 23239beb93cSSam Leffler } 23339beb93cSSam Leffler 23439beb93cSSam Leffler if (os_memcmp(csecret, conn->dh_p, csecret_len) > 0) 23539beb93cSSam Leffler csecret[0] = 0; /* make sure Yc < p */ 23639beb93cSSam Leffler 23739beb93cSSam Leffler csecret_start = csecret; 23839beb93cSSam Leffler while (csecret_len > 1 && *csecret_start == 0) { 23939beb93cSSam Leffler csecret_start++; 24039beb93cSSam Leffler csecret_len--; 24139beb93cSSam Leffler } 24239beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH client's secret value", 24339beb93cSSam Leffler csecret_start, csecret_len); 24439beb93cSSam Leffler 24539beb93cSSam Leffler /* Yc = g^csecret mod p */ 24639beb93cSSam Leffler dh_yc_len = conn->dh_p_len; 24739beb93cSSam Leffler dh_yc = os_malloc(dh_yc_len); 24839beb93cSSam Leffler if (dh_yc == NULL) { 24939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " 25039beb93cSSam Leffler "memory for Diffie-Hellman"); 25139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 25239beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 25339beb93cSSam Leffler os_free(csecret); 25439beb93cSSam Leffler return -1; 25539beb93cSSam Leffler } 25639beb93cSSam Leffler if (crypto_mod_exp(conn->dh_g, conn->dh_g_len, 25739beb93cSSam Leffler csecret_start, csecret_len, 25839beb93cSSam Leffler conn->dh_p, conn->dh_p_len, 25939beb93cSSam Leffler dh_yc, &dh_yc_len)) { 26039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 26139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 26239beb93cSSam Leffler os_free(csecret); 26339beb93cSSam Leffler os_free(dh_yc); 26439beb93cSSam Leffler return -1; 26539beb93cSSam Leffler } 26639beb93cSSam Leffler 26739beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)", 26839beb93cSSam Leffler dh_yc, dh_yc_len); 26939beb93cSSam Leffler 27039beb93cSSam Leffler WPA_PUT_BE16(*pos, dh_yc_len); 27139beb93cSSam Leffler *pos += 2; 27239beb93cSSam Leffler if (*pos + dh_yc_len > end) { 27339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Not enough room in the " 27439beb93cSSam Leffler "message buffer for Yc"); 27539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 27639beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 27739beb93cSSam Leffler os_free(csecret); 27839beb93cSSam Leffler os_free(dh_yc); 27939beb93cSSam Leffler return -1; 28039beb93cSSam Leffler } 28139beb93cSSam Leffler os_memcpy(*pos, dh_yc, dh_yc_len); 28239beb93cSSam Leffler *pos += dh_yc_len; 28339beb93cSSam Leffler os_free(dh_yc); 28439beb93cSSam Leffler 28539beb93cSSam Leffler shared_len = conn->dh_p_len; 28639beb93cSSam Leffler shared = os_malloc(shared_len); 28739beb93cSSam Leffler if (shared == NULL) { 28839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for " 28939beb93cSSam Leffler "DH"); 29039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 29139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 29239beb93cSSam Leffler os_free(csecret); 29339beb93cSSam Leffler return -1; 29439beb93cSSam Leffler } 29539beb93cSSam Leffler 29639beb93cSSam Leffler /* shared = Ys^csecret mod p */ 29739beb93cSSam Leffler if (crypto_mod_exp(conn->dh_ys, conn->dh_ys_len, 29839beb93cSSam Leffler csecret_start, csecret_len, 29939beb93cSSam Leffler conn->dh_p, conn->dh_p_len, 30039beb93cSSam Leffler shared, &shared_len)) { 30139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 30239beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 30339beb93cSSam Leffler os_free(csecret); 30439beb93cSSam Leffler os_free(shared); 30539beb93cSSam Leffler return -1; 30639beb93cSSam Leffler } 30739beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange", 30839beb93cSSam Leffler shared, shared_len); 30939beb93cSSam Leffler 31039beb93cSSam Leffler os_memset(csecret_start, 0, csecret_len); 31139beb93cSSam Leffler os_free(csecret); 31239beb93cSSam Leffler if (tls_derive_keys(conn, shared, shared_len)) { 31339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); 31439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 31539beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 31639beb93cSSam Leffler os_free(shared); 31739beb93cSSam Leffler return -1; 31839beb93cSSam Leffler } 31939beb93cSSam Leffler os_memset(shared, 0, shared_len); 32039beb93cSSam Leffler os_free(shared); 32139beb93cSSam Leffler tlsv1_client_free_dh(conn); 32239beb93cSSam Leffler return 0; 32339beb93cSSam Leffler } 32439beb93cSSam Leffler 32539beb93cSSam Leffler 32639beb93cSSam Leffler static int tlsv1_key_x_rsa(struct tlsv1_client *conn, u8 **pos, u8 *end) 32739beb93cSSam Leffler { 32839beb93cSSam Leffler u8 pre_master_secret[TLS_PRE_MASTER_SECRET_LEN]; 32939beb93cSSam Leffler size_t clen; 33039beb93cSSam Leffler int res; 33139beb93cSSam Leffler 33239beb93cSSam Leffler if (tls_derive_pre_master_secret(pre_master_secret) < 0 || 33339beb93cSSam Leffler tls_derive_keys(conn, pre_master_secret, 33439beb93cSSam Leffler TLS_PRE_MASTER_SECRET_LEN)) { 33539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); 33639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 33739beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 33839beb93cSSam Leffler return -1; 33939beb93cSSam Leffler } 34039beb93cSSam Leffler 34139beb93cSSam Leffler /* EncryptedPreMasterSecret */ 34239beb93cSSam Leffler if (conn->server_rsa_key == NULL) { 34339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: No server RSA key to " 34439beb93cSSam Leffler "use for encrypting pre-master secret"); 34539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 34639beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 34739beb93cSSam Leffler return -1; 34839beb93cSSam Leffler } 34939beb93cSSam Leffler 35039beb93cSSam Leffler /* RSA encrypted value is encoded with PKCS #1 v1.5 block type 2. */ 35139beb93cSSam Leffler *pos += 2; 35239beb93cSSam Leffler clen = end - *pos; 35339beb93cSSam Leffler res = crypto_public_key_encrypt_pkcs1_v15( 35439beb93cSSam Leffler conn->server_rsa_key, 35539beb93cSSam Leffler pre_master_secret, TLS_PRE_MASTER_SECRET_LEN, 35639beb93cSSam Leffler *pos, &clen); 35739beb93cSSam Leffler os_memset(pre_master_secret, 0, TLS_PRE_MASTER_SECRET_LEN); 35839beb93cSSam Leffler if (res < 0) { 35939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: RSA encryption failed"); 36039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 36139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 36239beb93cSSam Leffler return -1; 36339beb93cSSam Leffler } 36439beb93cSSam Leffler WPA_PUT_BE16(*pos - 2, clen); 36539beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: Encrypted pre_master_secret", 36639beb93cSSam Leffler *pos, clen); 36739beb93cSSam Leffler *pos += clen; 36839beb93cSSam Leffler 36939beb93cSSam Leffler return 0; 37039beb93cSSam Leffler } 37139beb93cSSam Leffler 37239beb93cSSam Leffler 37339beb93cSSam Leffler static int tls_write_client_key_exchange(struct tlsv1_client *conn, 37439beb93cSSam Leffler u8 **msgpos, u8 *end) 37539beb93cSSam Leffler { 37639beb93cSSam Leffler u8 *pos, *rhdr, *hs_start, *hs_length; 37739beb93cSSam Leffler size_t rlen; 37839beb93cSSam Leffler tls_key_exchange keyx; 37939beb93cSSam Leffler const struct tls_cipher_suite *suite; 38039beb93cSSam Leffler 38139beb93cSSam Leffler suite = tls_get_cipher_suite(conn->rl.cipher_suite); 38239beb93cSSam Leffler if (suite == NULL) 38339beb93cSSam Leffler keyx = TLS_KEY_X_NULL; 38439beb93cSSam Leffler else 38539beb93cSSam Leffler keyx = suite->key_exchange; 38639beb93cSSam Leffler 38739beb93cSSam Leffler pos = *msgpos; 38839beb93cSSam Leffler 38939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send ClientKeyExchange"); 39039beb93cSSam Leffler 39139beb93cSSam Leffler rhdr = pos; 39239beb93cSSam Leffler pos += TLS_RECORD_HEADER_LEN; 39339beb93cSSam Leffler 39439beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 39539beb93cSSam Leffler 39639beb93cSSam Leffler /* Handshake */ 39739beb93cSSam Leffler hs_start = pos; 39839beb93cSSam Leffler /* HandshakeType msg_type */ 39939beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE; 40039beb93cSSam Leffler /* uint24 length (to be filled) */ 40139beb93cSSam Leffler hs_length = pos; 40239beb93cSSam Leffler pos += 3; 40339beb93cSSam Leffler /* body - ClientKeyExchange */ 40439beb93cSSam Leffler if (keyx == TLS_KEY_X_DH_anon) { 40539beb93cSSam Leffler if (tlsv1_key_x_anon_dh(conn, &pos, end) < 0) 40639beb93cSSam Leffler return -1; 40739beb93cSSam Leffler } else { 40839beb93cSSam Leffler if (tlsv1_key_x_rsa(conn, &pos, end) < 0) 40939beb93cSSam Leffler return -1; 41039beb93cSSam Leffler } 41139beb93cSSam Leffler 41239beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 41339beb93cSSam Leffler 41439beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 41539beb93cSSam Leffler rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { 41639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); 41739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 41839beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 41939beb93cSSam Leffler return -1; 42039beb93cSSam Leffler } 42139beb93cSSam Leffler pos = rhdr + rlen; 42239beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 42339beb93cSSam Leffler 42439beb93cSSam Leffler *msgpos = pos; 42539beb93cSSam Leffler 42639beb93cSSam Leffler return 0; 42739beb93cSSam Leffler } 42839beb93cSSam Leffler 42939beb93cSSam Leffler 43039beb93cSSam Leffler static int tls_write_client_certificate_verify(struct tlsv1_client *conn, 43139beb93cSSam Leffler u8 **msgpos, u8 *end) 43239beb93cSSam Leffler { 43339beb93cSSam Leffler u8 *pos, *rhdr, *hs_start, *hs_length, *signed_start; 43439beb93cSSam Leffler size_t rlen, hlen, clen; 43539beb93cSSam Leffler u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos; 43639beb93cSSam Leffler enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA; 43739beb93cSSam Leffler 43839beb93cSSam Leffler pos = *msgpos; 43939beb93cSSam Leffler 44039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateVerify"); 44139beb93cSSam Leffler rhdr = pos; 44239beb93cSSam Leffler pos += TLS_RECORD_HEADER_LEN; 44339beb93cSSam Leffler 44439beb93cSSam Leffler /* Handshake */ 44539beb93cSSam Leffler hs_start = pos; 44639beb93cSSam Leffler /* HandshakeType msg_type */ 44739beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY; 44839beb93cSSam Leffler /* uint24 length (to be filled) */ 44939beb93cSSam Leffler hs_length = pos; 45039beb93cSSam Leffler pos += 3; 45139beb93cSSam Leffler 45239beb93cSSam Leffler /* 45339beb93cSSam Leffler * RFC 2246: 7.4.3 and 7.4.8: 45439beb93cSSam Leffler * Signature signature 45539beb93cSSam Leffler * 45639beb93cSSam Leffler * RSA: 45739beb93cSSam Leffler * digitally-signed struct { 45839beb93cSSam Leffler * opaque md5_hash[16]; 45939beb93cSSam Leffler * opaque sha_hash[20]; 46039beb93cSSam Leffler * }; 46139beb93cSSam Leffler * 46239beb93cSSam Leffler * DSA: 46339beb93cSSam Leffler * digitally-signed struct { 46439beb93cSSam Leffler * opaque sha_hash[20]; 46539beb93cSSam Leffler * }; 46639beb93cSSam Leffler * 46739beb93cSSam Leffler * The hash values are calculated over all handshake messages sent or 46839beb93cSSam Leffler * received starting at ClientHello up to, but not including, this 46939beb93cSSam Leffler * CertificateVerify message, including the type and length fields of 47039beb93cSSam Leffler * the handshake messages. 47139beb93cSSam Leffler */ 47239beb93cSSam Leffler 47339beb93cSSam Leffler hpos = hash; 47439beb93cSSam Leffler 47539beb93cSSam Leffler if (alg == SIGN_ALG_RSA) { 47639beb93cSSam Leffler hlen = MD5_MAC_LEN; 47739beb93cSSam Leffler if (conn->verify.md5_cert == NULL || 47839beb93cSSam Leffler crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) 47939beb93cSSam Leffler { 48039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 48139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 48239beb93cSSam Leffler conn->verify.md5_cert = NULL; 48339beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL); 48439beb93cSSam Leffler conn->verify.sha1_cert = NULL; 48539beb93cSSam Leffler return -1; 48639beb93cSSam Leffler } 48739beb93cSSam Leffler hpos += MD5_MAC_LEN; 48839beb93cSSam Leffler } else 48939beb93cSSam Leffler crypto_hash_finish(conn->verify.md5_cert, NULL, NULL); 49039beb93cSSam Leffler 49139beb93cSSam Leffler conn->verify.md5_cert = NULL; 49239beb93cSSam Leffler hlen = SHA1_MAC_LEN; 49339beb93cSSam Leffler if (conn->verify.sha1_cert == NULL || 49439beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) { 49539beb93cSSam Leffler conn->verify.sha1_cert = NULL; 49639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 49739beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 49839beb93cSSam Leffler return -1; 49939beb93cSSam Leffler } 50039beb93cSSam Leffler conn->verify.sha1_cert = NULL; 50139beb93cSSam Leffler 50239beb93cSSam Leffler if (alg == SIGN_ALG_RSA) 50339beb93cSSam Leffler hlen += MD5_MAC_LEN; 50439beb93cSSam Leffler 50539beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen); 50639beb93cSSam Leffler 50739beb93cSSam Leffler /* 50839beb93cSSam Leffler * RFC 2246, 4.7: 50939beb93cSSam Leffler * In digital signing, one-way hash functions are used as input for a 51039beb93cSSam Leffler * signing algorithm. A digitally-signed element is encoded as an 51139beb93cSSam Leffler * opaque vector <0..2^16-1>, where the length is specified by the 51239beb93cSSam Leffler * signing algorithm and key. 51339beb93cSSam Leffler * 51439beb93cSSam Leffler * In RSA signing, a 36-byte structure of two hashes (one SHA and one 51539beb93cSSam Leffler * MD5) is signed (encrypted with the private key). It is encoded with 51639beb93cSSam Leffler * PKCS #1 block type 0 or type 1 as described in [PKCS1]. 51739beb93cSSam Leffler */ 51839beb93cSSam Leffler signed_start = pos; /* length to be filled */ 51939beb93cSSam Leffler pos += 2; 52039beb93cSSam Leffler clen = end - pos; 52139beb93cSSam Leffler if (conn->cred == NULL || 52239beb93cSSam Leffler crypto_private_key_sign_pkcs1(conn->cred->key, hash, hlen, 52339beb93cSSam Leffler pos, &clen) < 0) { 52439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to sign hash (PKCS #1)"); 52539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 52639beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 52739beb93cSSam Leffler return -1; 52839beb93cSSam Leffler } 52939beb93cSSam Leffler WPA_PUT_BE16(signed_start, clen); 53039beb93cSSam Leffler 53139beb93cSSam Leffler pos += clen; 53239beb93cSSam Leffler 53339beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 53439beb93cSSam Leffler 53539beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 53639beb93cSSam Leffler rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { 53739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); 53839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 53939beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 54039beb93cSSam Leffler return -1; 54139beb93cSSam Leffler } 54239beb93cSSam Leffler pos = rhdr + rlen; 54339beb93cSSam Leffler 54439beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 54539beb93cSSam Leffler 54639beb93cSSam Leffler *msgpos = pos; 54739beb93cSSam Leffler 54839beb93cSSam Leffler return 0; 54939beb93cSSam Leffler } 55039beb93cSSam Leffler 55139beb93cSSam Leffler 55239beb93cSSam Leffler static int tls_write_client_change_cipher_spec(struct tlsv1_client *conn, 55339beb93cSSam Leffler u8 **msgpos, u8 *end) 55439beb93cSSam Leffler { 55539beb93cSSam Leffler u8 *pos, *rhdr; 55639beb93cSSam Leffler size_t rlen; 55739beb93cSSam Leffler 55839beb93cSSam Leffler pos = *msgpos; 55939beb93cSSam Leffler 56039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec"); 56139beb93cSSam Leffler rhdr = pos; 56239beb93cSSam Leffler pos += TLS_RECORD_HEADER_LEN; 56339beb93cSSam Leffler *pos = TLS_CHANGE_CIPHER_SPEC; 56439beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC, 56539beb93cSSam Leffler rhdr, end - rhdr, 1, &rlen) < 0) { 56639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); 56739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 56839beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 56939beb93cSSam Leffler return -1; 57039beb93cSSam Leffler } 57139beb93cSSam Leffler 57239beb93cSSam Leffler if (tlsv1_record_change_write_cipher(&conn->rl) < 0) { 57339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for " 57439beb93cSSam Leffler "record layer"); 57539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 57639beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 57739beb93cSSam Leffler return -1; 57839beb93cSSam Leffler } 57939beb93cSSam Leffler 58039beb93cSSam Leffler *msgpos = rhdr + rlen; 58139beb93cSSam Leffler 58239beb93cSSam Leffler return 0; 58339beb93cSSam Leffler } 58439beb93cSSam Leffler 58539beb93cSSam Leffler 58639beb93cSSam Leffler static int tls_write_client_finished(struct tlsv1_client *conn, 58739beb93cSSam Leffler u8 **msgpos, u8 *end) 58839beb93cSSam Leffler { 58939beb93cSSam Leffler u8 *pos, *rhdr, *hs_start, *hs_length; 59039beb93cSSam Leffler size_t rlen, hlen; 59139beb93cSSam Leffler u8 verify_data[TLS_VERIFY_DATA_LEN]; 59239beb93cSSam Leffler u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; 59339beb93cSSam Leffler 59439beb93cSSam Leffler pos = *msgpos; 59539beb93cSSam Leffler 59639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send Finished"); 59739beb93cSSam Leffler 59839beb93cSSam Leffler /* Encrypted Handshake Message: Finished */ 59939beb93cSSam Leffler 60039beb93cSSam Leffler hlen = MD5_MAC_LEN; 60139beb93cSSam Leffler if (conn->verify.md5_client == NULL || 60239beb93cSSam Leffler crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) { 60339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 60439beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 60539beb93cSSam Leffler conn->verify.md5_client = NULL; 60639beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_client, NULL, NULL); 60739beb93cSSam Leffler conn->verify.sha1_client = NULL; 60839beb93cSSam Leffler return -1; 60939beb93cSSam Leffler } 61039beb93cSSam Leffler conn->verify.md5_client = NULL; 61139beb93cSSam Leffler hlen = SHA1_MAC_LEN; 61239beb93cSSam Leffler if (conn->verify.sha1_client == NULL || 61339beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN, 61439beb93cSSam Leffler &hlen) < 0) { 61539beb93cSSam Leffler conn->verify.sha1_client = NULL; 61639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 61739beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 61839beb93cSSam Leffler return -1; 61939beb93cSSam Leffler } 62039beb93cSSam Leffler conn->verify.sha1_client = NULL; 62139beb93cSSam Leffler 62239beb93cSSam Leffler if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, 62339beb93cSSam Leffler "client finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, 62439beb93cSSam Leffler verify_data, TLS_VERIFY_DATA_LEN)) { 62539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); 62639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 62739beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 62839beb93cSSam Leffler return -1; 62939beb93cSSam Leffler } 63039beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)", 63139beb93cSSam Leffler verify_data, TLS_VERIFY_DATA_LEN); 63239beb93cSSam Leffler 63339beb93cSSam Leffler rhdr = pos; 63439beb93cSSam Leffler pos += TLS_RECORD_HEADER_LEN; 63539beb93cSSam Leffler /* Handshake */ 63639beb93cSSam Leffler hs_start = pos; 63739beb93cSSam Leffler /* HandshakeType msg_type */ 63839beb93cSSam Leffler *pos++ = TLS_HANDSHAKE_TYPE_FINISHED; 63939beb93cSSam Leffler /* uint24 length (to be filled) */ 64039beb93cSSam Leffler hs_length = pos; 64139beb93cSSam Leffler pos += 3; 64239beb93cSSam Leffler os_memcpy(pos, verify_data, TLS_VERIFY_DATA_LEN); 64339beb93cSSam Leffler pos += TLS_VERIFY_DATA_LEN; 64439beb93cSSam Leffler WPA_PUT_BE24(hs_length, pos - hs_length - 3); 64539beb93cSSam Leffler tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 64639beb93cSSam Leffler 64739beb93cSSam Leffler if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 64839beb93cSSam Leffler rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { 64939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); 65039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 65139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR); 65239beb93cSSam Leffler return -1; 65339beb93cSSam Leffler } 65439beb93cSSam Leffler 65539beb93cSSam Leffler pos = rhdr + rlen; 65639beb93cSSam Leffler 65739beb93cSSam Leffler *msgpos = pos; 65839beb93cSSam Leffler 65939beb93cSSam Leffler return 0; 66039beb93cSSam Leffler } 66139beb93cSSam Leffler 66239beb93cSSam Leffler 66339beb93cSSam Leffler static u8 * tls_send_client_key_exchange(struct tlsv1_client *conn, 66439beb93cSSam Leffler size_t *out_len) 66539beb93cSSam Leffler { 66639beb93cSSam Leffler u8 *msg, *end, *pos; 66739beb93cSSam Leffler size_t msglen; 66839beb93cSSam Leffler 66939beb93cSSam Leffler *out_len = 0; 67039beb93cSSam Leffler 67139beb93cSSam Leffler msglen = 1000; 67239beb93cSSam Leffler if (conn->certificate_requested) 67339beb93cSSam Leffler msglen += tls_client_cert_chain_der_len(conn); 67439beb93cSSam Leffler 67539beb93cSSam Leffler msg = os_malloc(msglen); 67639beb93cSSam Leffler if (msg == NULL) 67739beb93cSSam Leffler return NULL; 67839beb93cSSam Leffler 67939beb93cSSam Leffler pos = msg; 68039beb93cSSam Leffler end = msg + msglen; 68139beb93cSSam Leffler 68239beb93cSSam Leffler if (conn->certificate_requested) { 68339beb93cSSam Leffler if (tls_write_client_certificate(conn, &pos, end) < 0) { 68439beb93cSSam Leffler os_free(msg); 68539beb93cSSam Leffler return NULL; 68639beb93cSSam Leffler } 68739beb93cSSam Leffler } 68839beb93cSSam Leffler 68939beb93cSSam Leffler if (tls_write_client_key_exchange(conn, &pos, end) < 0 || 69039beb93cSSam Leffler (conn->certificate_requested && conn->cred && conn->cred->key && 69139beb93cSSam Leffler tls_write_client_certificate_verify(conn, &pos, end) < 0) || 69239beb93cSSam Leffler tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || 69339beb93cSSam Leffler tls_write_client_finished(conn, &pos, end) < 0) { 69439beb93cSSam Leffler os_free(msg); 69539beb93cSSam Leffler return NULL; 69639beb93cSSam Leffler } 69739beb93cSSam Leffler 69839beb93cSSam Leffler *out_len = pos - msg; 69939beb93cSSam Leffler 70039beb93cSSam Leffler conn->state = SERVER_CHANGE_CIPHER_SPEC; 70139beb93cSSam Leffler 70239beb93cSSam Leffler return msg; 70339beb93cSSam Leffler } 70439beb93cSSam Leffler 70539beb93cSSam Leffler 70639beb93cSSam Leffler static u8 * tls_send_change_cipher_spec(struct tlsv1_client *conn, 70739beb93cSSam Leffler size_t *out_len) 70839beb93cSSam Leffler { 70939beb93cSSam Leffler u8 *msg, *end, *pos; 71039beb93cSSam Leffler 71139beb93cSSam Leffler *out_len = 0; 71239beb93cSSam Leffler 71339beb93cSSam Leffler msg = os_malloc(1000); 71439beb93cSSam Leffler if (msg == NULL) 71539beb93cSSam Leffler return NULL; 71639beb93cSSam Leffler 71739beb93cSSam Leffler pos = msg; 71839beb93cSSam Leffler end = msg + 1000; 71939beb93cSSam Leffler 72039beb93cSSam Leffler if (tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || 72139beb93cSSam Leffler tls_write_client_finished(conn, &pos, end) < 0) { 72239beb93cSSam Leffler os_free(msg); 72339beb93cSSam Leffler return NULL; 72439beb93cSSam Leffler } 72539beb93cSSam Leffler 72639beb93cSSam Leffler *out_len = pos - msg; 72739beb93cSSam Leffler 72839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Session resumption completed " 72939beb93cSSam Leffler "successfully"); 73039beb93cSSam Leffler conn->state = ESTABLISHED; 73139beb93cSSam Leffler 73239beb93cSSam Leffler return msg; 73339beb93cSSam Leffler } 73439beb93cSSam Leffler 73539beb93cSSam Leffler 73639beb93cSSam Leffler u8 * tlsv1_client_handshake_write(struct tlsv1_client *conn, size_t *out_len, 73739beb93cSSam Leffler int no_appl_data) 73839beb93cSSam Leffler { 73939beb93cSSam Leffler switch (conn->state) { 74039beb93cSSam Leffler case CLIENT_KEY_EXCHANGE: 74139beb93cSSam Leffler return tls_send_client_key_exchange(conn, out_len); 74239beb93cSSam Leffler case CHANGE_CIPHER_SPEC: 74339beb93cSSam Leffler return tls_send_change_cipher_spec(conn, out_len); 74439beb93cSSam Leffler case ACK_FINISHED: 74539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed " 74639beb93cSSam Leffler "successfully"); 74739beb93cSSam Leffler conn->state = ESTABLISHED; 74839beb93cSSam Leffler *out_len = 0; 74939beb93cSSam Leffler if (no_appl_data) { 75039beb93cSSam Leffler /* Need to return something to get final TLS ACK. */ 75139beb93cSSam Leffler return os_malloc(1); 75239beb93cSSam Leffler } 75339beb93cSSam Leffler return NULL; 75439beb93cSSam Leffler default: 75539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while " 75639beb93cSSam Leffler "generating reply", conn->state); 75739beb93cSSam Leffler return NULL; 75839beb93cSSam Leffler } 75939beb93cSSam Leffler } 76039beb93cSSam Leffler 76139beb93cSSam Leffler 76239beb93cSSam Leffler u8 * tlsv1_client_send_alert(struct tlsv1_client *conn, u8 level, 76339beb93cSSam Leffler u8 description, size_t *out_len) 76439beb93cSSam Leffler { 76539beb93cSSam Leffler u8 *alert, *pos, *length; 76639beb93cSSam Leffler 76739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description); 76839beb93cSSam Leffler *out_len = 0; 76939beb93cSSam Leffler 77039beb93cSSam Leffler alert = os_malloc(10); 77139beb93cSSam Leffler if (alert == NULL) 77239beb93cSSam Leffler return NULL; 77339beb93cSSam Leffler 77439beb93cSSam Leffler pos = alert; 77539beb93cSSam Leffler 77639beb93cSSam Leffler /* TLSPlaintext */ 77739beb93cSSam Leffler /* ContentType type */ 77839beb93cSSam Leffler *pos++ = TLS_CONTENT_TYPE_ALERT; 77939beb93cSSam Leffler /* ProtocolVersion version */ 78039beb93cSSam Leffler WPA_PUT_BE16(pos, TLS_VERSION); 78139beb93cSSam Leffler pos += 2; 78239beb93cSSam Leffler /* uint16 length (to be filled) */ 78339beb93cSSam Leffler length = pos; 78439beb93cSSam Leffler pos += 2; 78539beb93cSSam Leffler /* opaque fragment[TLSPlaintext.length] */ 78639beb93cSSam Leffler 78739beb93cSSam Leffler /* Alert */ 78839beb93cSSam Leffler /* AlertLevel level */ 78939beb93cSSam Leffler *pos++ = level; 79039beb93cSSam Leffler /* AlertDescription description */ 79139beb93cSSam Leffler *pos++ = description; 79239beb93cSSam Leffler 79339beb93cSSam Leffler WPA_PUT_BE16(length, pos - length - 2); 79439beb93cSSam Leffler *out_len = pos - alert; 79539beb93cSSam Leffler 79639beb93cSSam Leffler return alert; 79739beb93cSSam Leffler } 798