16d49e1aeSJan Lentfer /*
26d49e1aeSJan Lentfer  * TLSv1 client - write handshake message
3*a1157835SDaniel Fojt  * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
46d49e1aeSJan Lentfer  *
53ff40c12SJohn Marino  * This software may be distributed under the terms of the BSD license.
63ff40c12SJohn Marino  * See README for more details.
76d49e1aeSJan Lentfer  */
86d49e1aeSJan Lentfer 
96d49e1aeSJan Lentfer #include "includes.h"
106d49e1aeSJan Lentfer 
116d49e1aeSJan Lentfer #include "common.h"
123ff40c12SJohn Marino #include "crypto/md5.h"
133ff40c12SJohn Marino #include "crypto/sha1.h"
143ff40c12SJohn Marino #include "crypto/sha256.h"
153ff40c12SJohn Marino #include "crypto/tls.h"
163ff40c12SJohn Marino #include "crypto/random.h"
176d49e1aeSJan Lentfer #include "x509v3.h"
186d49e1aeSJan Lentfer #include "tlsv1_common.h"
196d49e1aeSJan Lentfer #include "tlsv1_record.h"
206d49e1aeSJan Lentfer #include "tlsv1_client.h"
216d49e1aeSJan Lentfer #include "tlsv1_client_i.h"
226d49e1aeSJan Lentfer 
236d49e1aeSJan Lentfer 
tls_client_cert_chain_der_len(struct tlsv1_client * conn)246d49e1aeSJan Lentfer static size_t tls_client_cert_chain_der_len(struct tlsv1_client *conn)
256d49e1aeSJan Lentfer {
266d49e1aeSJan Lentfer 	size_t len = 0;
276d49e1aeSJan Lentfer 	struct x509_certificate *cert;
286d49e1aeSJan Lentfer 
296d49e1aeSJan Lentfer 	if (conn->cred == NULL)
306d49e1aeSJan Lentfer 		return 0;
316d49e1aeSJan Lentfer 
326d49e1aeSJan Lentfer 	cert = conn->cred->cert;
336d49e1aeSJan Lentfer 	while (cert) {
346d49e1aeSJan Lentfer 		len += 3 + cert->cert_len;
356d49e1aeSJan Lentfer 		if (x509_certificate_self_signed(cert))
366d49e1aeSJan Lentfer 			break;
376d49e1aeSJan Lentfer 		cert = x509_certificate_get_subject(conn->cred->trusted_certs,
386d49e1aeSJan Lentfer 						    &cert->issuer);
396d49e1aeSJan Lentfer 	}
406d49e1aeSJan Lentfer 
416d49e1aeSJan Lentfer 	return len;
426d49e1aeSJan Lentfer }
436d49e1aeSJan Lentfer 
446d49e1aeSJan Lentfer 
tls_send_client_hello(struct tlsv1_client * conn,size_t * out_len)456d49e1aeSJan Lentfer u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len)
466d49e1aeSJan Lentfer {
476d49e1aeSJan Lentfer 	u8 *hello, *end, *pos, *hs_length, *hs_start, *rhdr;
486d49e1aeSJan Lentfer 	struct os_time now;
496d49e1aeSJan Lentfer 	size_t len, i;
50*a1157835SDaniel Fojt 	u8 *ext_start;
51*a1157835SDaniel Fojt 	u16 tls_version = TLS_VERSION;
526d49e1aeSJan Lentfer 
53*a1157835SDaniel Fojt 	/* Pick the highest locally enabled TLS version */
54*a1157835SDaniel Fojt #ifdef CONFIG_TLSV12
55*a1157835SDaniel Fojt 	if ((conn->flags & TLS_CONN_DISABLE_TLSv1_2) &&
56*a1157835SDaniel Fojt 	    tls_version == TLS_VERSION_1_2)
57*a1157835SDaniel Fojt 		tls_version = TLS_VERSION_1_1;
58*a1157835SDaniel Fojt #endif /* CONFIG_TLSV12 */
59*a1157835SDaniel Fojt #ifdef CONFIG_TLSV11
60*a1157835SDaniel Fojt 	if ((conn->flags & TLS_CONN_DISABLE_TLSv1_1) &&
61*a1157835SDaniel Fojt 	    tls_version == TLS_VERSION_1_1)
62*a1157835SDaniel Fojt 		tls_version = TLS_VERSION_1;
63*a1157835SDaniel Fojt #endif /* CONFIG_TLSV11 */
64*a1157835SDaniel Fojt 	if ((conn->flags & TLS_CONN_DISABLE_TLSv1_0) &&
65*a1157835SDaniel Fojt 	    tls_version == TLS_VERSION_1) {
66*a1157835SDaniel Fojt 		wpa_printf(MSG_INFO, "TLSv1: No TLS version allowed");
67*a1157835SDaniel Fojt 		return NULL;
68*a1157835SDaniel Fojt 	}
69*a1157835SDaniel Fojt 
70*a1157835SDaniel Fojt 	wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello (ver %s)",
71*a1157835SDaniel Fojt 		   tls_version_str(tls_version));
726d49e1aeSJan Lentfer 	*out_len = 0;
736d49e1aeSJan Lentfer 
746d49e1aeSJan Lentfer 	os_get_time(&now);
75*a1157835SDaniel Fojt #ifdef TEST_FUZZ
76*a1157835SDaniel Fojt 	now.sec = 0xfffefdfc;
77*a1157835SDaniel Fojt #endif /* TEST_FUZZ */
786d49e1aeSJan Lentfer 	WPA_PUT_BE32(conn->client_random, now.sec);
793ff40c12SJohn Marino 	if (random_get_bytes(conn->client_random + 4, TLS_RANDOM_LEN - 4)) {
806d49e1aeSJan Lentfer 		wpa_printf(MSG_ERROR, "TLSv1: Could not generate "
816d49e1aeSJan Lentfer 			   "client_random");
826d49e1aeSJan Lentfer 		return NULL;
836d49e1aeSJan Lentfer 	}
846d49e1aeSJan Lentfer 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random",
856d49e1aeSJan Lentfer 		    conn->client_random, TLS_RANDOM_LEN);
866d49e1aeSJan Lentfer 
87*a1157835SDaniel Fojt 	len = 150 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len;
886d49e1aeSJan Lentfer 	hello = os_malloc(len);
896d49e1aeSJan Lentfer 	if (hello == NULL)
906d49e1aeSJan Lentfer 		return NULL;
916d49e1aeSJan Lentfer 	end = hello + len;
926d49e1aeSJan Lentfer 
936d49e1aeSJan Lentfer 	rhdr = hello;
946d49e1aeSJan Lentfer 	pos = rhdr + TLS_RECORD_HEADER_LEN;
956d49e1aeSJan Lentfer 
966d49e1aeSJan Lentfer 	/* opaque fragment[TLSPlaintext.length] */
976d49e1aeSJan Lentfer 
986d49e1aeSJan Lentfer 	/* Handshake */
996d49e1aeSJan Lentfer 	hs_start = pos;
1006d49e1aeSJan Lentfer 	/* HandshakeType msg_type */
1016d49e1aeSJan Lentfer 	*pos++ = TLS_HANDSHAKE_TYPE_CLIENT_HELLO;
1026d49e1aeSJan Lentfer 	/* uint24 length (to be filled) */
1036d49e1aeSJan Lentfer 	hs_length = pos;
1046d49e1aeSJan Lentfer 	pos += 3;
1056d49e1aeSJan Lentfer 	/* body - ClientHello */
1066d49e1aeSJan Lentfer 	/* ProtocolVersion client_version */
107*a1157835SDaniel Fojt 	WPA_PUT_BE16(pos, tls_version);
1086d49e1aeSJan Lentfer 	pos += 2;
1096d49e1aeSJan Lentfer 	/* Random random: uint32 gmt_unix_time, opaque random_bytes */
1106d49e1aeSJan Lentfer 	os_memcpy(pos, conn->client_random, TLS_RANDOM_LEN);
1116d49e1aeSJan Lentfer 	pos += TLS_RANDOM_LEN;
1126d49e1aeSJan Lentfer 	/* SessionID session_id */
1136d49e1aeSJan Lentfer 	*pos++ = conn->session_id_len;
1146d49e1aeSJan Lentfer 	os_memcpy(pos, conn->session_id, conn->session_id_len);
1156d49e1aeSJan Lentfer 	pos += conn->session_id_len;
1166d49e1aeSJan Lentfer 	/* CipherSuite cipher_suites<2..2^16-1> */
1176d49e1aeSJan Lentfer 	WPA_PUT_BE16(pos, 2 * conn->num_cipher_suites);
1186d49e1aeSJan Lentfer 	pos += 2;
1196d49e1aeSJan Lentfer 	for (i = 0; i < conn->num_cipher_suites; i++) {
1206d49e1aeSJan Lentfer 		WPA_PUT_BE16(pos, conn->cipher_suites[i]);
1216d49e1aeSJan Lentfer 		pos += 2;
1226d49e1aeSJan Lentfer 	}
1236d49e1aeSJan Lentfer 	/* CompressionMethod compression_methods<1..2^8-1> */
1246d49e1aeSJan Lentfer 	*pos++ = 1;
1256d49e1aeSJan Lentfer 	*pos++ = TLS_COMPRESSION_NULL;
1266d49e1aeSJan Lentfer 
127*a1157835SDaniel Fojt 	/* Extension */
128*a1157835SDaniel Fojt 	ext_start = pos;
129*a1157835SDaniel Fojt 	pos += 2;
130*a1157835SDaniel Fojt 
131*a1157835SDaniel Fojt #ifdef CONFIG_TLSV12
132*a1157835SDaniel Fojt 	if (conn->rl.tls_version >= TLS_VERSION_1_2) {
133*a1157835SDaniel Fojt 		/*
134*a1157835SDaniel Fojt 		 * Add signature_algorithms extension since we support only
135*a1157835SDaniel Fojt 		 * SHA256 (and not the default SHA1) with TLSv1.2.
136*a1157835SDaniel Fojt 		 */
137*a1157835SDaniel Fojt 		/* ExtensionsType extension_type = signature_algorithms(13) */
138*a1157835SDaniel Fojt 		WPA_PUT_BE16(pos, TLS_EXT_SIGNATURE_ALGORITHMS);
139*a1157835SDaniel Fojt 		pos += 2;
140*a1157835SDaniel Fojt 		/* opaque extension_data<0..2^16-1> length */
141*a1157835SDaniel Fojt 		WPA_PUT_BE16(pos, 8);
142*a1157835SDaniel Fojt 		pos += 2;
143*a1157835SDaniel Fojt 		/* supported_signature_algorithms<2..2^16-2> length */
144*a1157835SDaniel Fojt 		WPA_PUT_BE16(pos, 6);
145*a1157835SDaniel Fojt 		pos += 2;
146*a1157835SDaniel Fojt 		/* supported_signature_algorithms */
147*a1157835SDaniel Fojt 		*pos++ = TLS_HASH_ALG_SHA512;
148*a1157835SDaniel Fojt 		*pos++ = TLS_SIGN_ALG_RSA;
149*a1157835SDaniel Fojt 		*pos++ = TLS_HASH_ALG_SHA384;
150*a1157835SDaniel Fojt 		*pos++ = TLS_SIGN_ALG_RSA;
151*a1157835SDaniel Fojt 		*pos++ = TLS_HASH_ALG_SHA256;
152*a1157835SDaniel Fojt 		*pos++ = TLS_SIGN_ALG_RSA;
153*a1157835SDaniel Fojt 	}
154*a1157835SDaniel Fojt #endif /* CONFIG_TLSV12 */
155*a1157835SDaniel Fojt 
1566d49e1aeSJan Lentfer 	if (conn->client_hello_ext) {
1576d49e1aeSJan Lentfer 		os_memcpy(pos, conn->client_hello_ext,
1586d49e1aeSJan Lentfer 			  conn->client_hello_ext_len);
1596d49e1aeSJan Lentfer 		pos += conn->client_hello_ext_len;
1606d49e1aeSJan Lentfer 	}
1616d49e1aeSJan Lentfer 
162*a1157835SDaniel Fojt 	if (conn->flags & TLS_CONN_REQUEST_OCSP) {
163*a1157835SDaniel Fojt 		wpa_printf(MSG_DEBUG,
164*a1157835SDaniel Fojt 			   "TLSv1: Add status_request extension for OCSP stapling");
165*a1157835SDaniel Fojt 		/* ExtensionsType extension_type = status_request(5) */
166*a1157835SDaniel Fojt 		WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST);
167*a1157835SDaniel Fojt 		pos += 2;
168*a1157835SDaniel Fojt 		/* opaque extension_data<0..2^16-1> length */
169*a1157835SDaniel Fojt 		WPA_PUT_BE16(pos, 5);
170*a1157835SDaniel Fojt 		pos += 2;
171*a1157835SDaniel Fojt 
172*a1157835SDaniel Fojt 		/*
173*a1157835SDaniel Fojt 		 * RFC 6066, 8:
174*a1157835SDaniel Fojt 		 * struct {
175*a1157835SDaniel Fojt 		 *     CertificateStatusType status_type;
176*a1157835SDaniel Fojt 		 *     select (status_type) {
177*a1157835SDaniel Fojt 		 *         case ocsp: OCSPStatusRequest;
178*a1157835SDaniel Fojt 		 *     } request;
179*a1157835SDaniel Fojt 		 * } CertificateStatusRequest;
180*a1157835SDaniel Fojt 		 *
181*a1157835SDaniel Fojt 		 * enum { ocsp(1), (255) } CertificateStatusType;
182*a1157835SDaniel Fojt 		 */
183*a1157835SDaniel Fojt 		*pos++ = 1; /* status_type = ocsp(1) */
184*a1157835SDaniel Fojt 
185*a1157835SDaniel Fojt 		/*
186*a1157835SDaniel Fojt 		 * struct {
187*a1157835SDaniel Fojt 		 *     ResponderID responder_id_list<0..2^16-1>;
188*a1157835SDaniel Fojt 		 *     Extensions  request_extensions;
189*a1157835SDaniel Fojt 		 * } OCSPStatusRequest;
190*a1157835SDaniel Fojt 		 *
191*a1157835SDaniel Fojt 		 * opaque ResponderID<1..2^16-1>;
192*a1157835SDaniel Fojt 		 * opaque Extensions<0..2^16-1>;
193*a1157835SDaniel Fojt 		 */
194*a1157835SDaniel Fojt 		WPA_PUT_BE16(pos, 0); /* responder_id_list(empty) */
195*a1157835SDaniel Fojt 		pos += 2;
196*a1157835SDaniel Fojt 		WPA_PUT_BE16(pos, 0); /* request_extensions(empty) */
197*a1157835SDaniel Fojt 		pos += 2;
198*a1157835SDaniel Fojt 
199*a1157835SDaniel Fojt 		wpa_printf(MSG_DEBUG,
200*a1157835SDaniel Fojt 			   "TLSv1: Add status_request_v2 extension for OCSP stapling");
201*a1157835SDaniel Fojt 		/* ExtensionsType extension_type = status_request_v2(17) */
202*a1157835SDaniel Fojt 		WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST_V2);
203*a1157835SDaniel Fojt 		pos += 2;
204*a1157835SDaniel Fojt 		/* opaque extension_data<0..2^16-1> length */
205*a1157835SDaniel Fojt 		WPA_PUT_BE16(pos, 7);
206*a1157835SDaniel Fojt 		pos += 2;
207*a1157835SDaniel Fojt 
208*a1157835SDaniel Fojt 		/*
209*a1157835SDaniel Fojt 		 * RFC 6961, 2.2:
210*a1157835SDaniel Fojt 		 * struct {
211*a1157835SDaniel Fojt 		 *     CertificateStatusType status_type;
212*a1157835SDaniel Fojt 		 *     uint16 request_length;
213*a1157835SDaniel Fojt 		 *     select (status_type) {
214*a1157835SDaniel Fojt 		 *         case ocsp: OCSPStatusRequest;
215*a1157835SDaniel Fojt 		 *         case ocsp_multi: OCSPStatusRequest;
216*a1157835SDaniel Fojt 		 *     } request;
217*a1157835SDaniel Fojt 		 * } CertificateStatusRequestItemV2;
218*a1157835SDaniel Fojt 		 *
219*a1157835SDaniel Fojt 		 * enum { ocsp(1), ocsp_multi(2), (255) } CertificateStatusType;
220*a1157835SDaniel Fojt 		 *
221*a1157835SDaniel Fojt 		 * struct {
222*a1157835SDaniel Fojt 		 * CertificateStatusRequestItemV2
223*a1157835SDaniel Fojt 		 *     certificate_status_req_list<1..2^16-1>;
224*a1157835SDaniel Fojt 		 * } CertificateStatusRequestListV2;
225*a1157835SDaniel Fojt 		 */
226*a1157835SDaniel Fojt 
227*a1157835SDaniel Fojt 		/* certificate_status_req_list<1..2^16-1> */
228*a1157835SDaniel Fojt 		WPA_PUT_BE16(pos, 5);
229*a1157835SDaniel Fojt 		pos += 2;
230*a1157835SDaniel Fojt 
231*a1157835SDaniel Fojt 		/* CertificateStatusRequestItemV2 */
232*a1157835SDaniel Fojt 		*pos++ = 2; /* status_type = ocsp_multi(2) */
233*a1157835SDaniel Fojt 		/* OCSPStatusRequest as shown above for v1 */
234*a1157835SDaniel Fojt 		WPA_PUT_BE16(pos, 0); /* responder_id_list(empty) */
235*a1157835SDaniel Fojt 		pos += 2;
236*a1157835SDaniel Fojt 		WPA_PUT_BE16(pos, 0); /* request_extensions(empty) */
237*a1157835SDaniel Fojt 		pos += 2;
238*a1157835SDaniel Fojt 	}
239*a1157835SDaniel Fojt 
240*a1157835SDaniel Fojt 	if (pos == ext_start + 2)
241*a1157835SDaniel Fojt 		pos -= 2; /* no extensions */
242*a1157835SDaniel Fojt 	else
243*a1157835SDaniel Fojt 		WPA_PUT_BE16(ext_start, pos - ext_start - 2);
244*a1157835SDaniel Fojt 
2456d49e1aeSJan Lentfer 	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
2466d49e1aeSJan Lentfer 	tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
2476d49e1aeSJan Lentfer 
2486d49e1aeSJan Lentfer 	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
2493ff40c12SJohn Marino 			      rhdr, end - rhdr, hs_start, pos - hs_start,
2503ff40c12SJohn Marino 			      out_len) < 0) {
2516d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record");
2526d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
2536d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
2546d49e1aeSJan Lentfer 		os_free(hello);
2556d49e1aeSJan Lentfer 		return NULL;
2566d49e1aeSJan Lentfer 	}
2576d49e1aeSJan Lentfer 
2586d49e1aeSJan Lentfer 	conn->state = SERVER_HELLO;
2596d49e1aeSJan Lentfer 
2606d49e1aeSJan Lentfer 	return hello;
2616d49e1aeSJan Lentfer }
2626d49e1aeSJan Lentfer 
2636d49e1aeSJan Lentfer 
tls_write_client_certificate(struct tlsv1_client * conn,u8 ** msgpos,u8 * end)2646d49e1aeSJan Lentfer static int tls_write_client_certificate(struct tlsv1_client *conn,
2656d49e1aeSJan Lentfer 					u8 **msgpos, u8 *end)
2666d49e1aeSJan Lentfer {
2676d49e1aeSJan Lentfer 	u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start;
2686d49e1aeSJan Lentfer 	size_t rlen;
2696d49e1aeSJan Lentfer 	struct x509_certificate *cert;
2706d49e1aeSJan Lentfer 
2716d49e1aeSJan Lentfer 	pos = *msgpos;
272*a1157835SDaniel Fojt 	if (TLS_RECORD_HEADER_LEN + 1 + 3 + 3 > end - pos) {
273*a1157835SDaniel Fojt 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
274*a1157835SDaniel Fojt 			  TLS_ALERT_INTERNAL_ERROR);
275*a1157835SDaniel Fojt 		return -1;
276*a1157835SDaniel Fojt 	}
2776d49e1aeSJan Lentfer 
2786d49e1aeSJan Lentfer 	wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate");
2796d49e1aeSJan Lentfer 	rhdr = pos;
2806d49e1aeSJan Lentfer 	pos += TLS_RECORD_HEADER_LEN;
2816d49e1aeSJan Lentfer 
2826d49e1aeSJan Lentfer 	/* opaque fragment[TLSPlaintext.length] */
2836d49e1aeSJan Lentfer 
2846d49e1aeSJan Lentfer 	/* Handshake */
2856d49e1aeSJan Lentfer 	hs_start = pos;
2866d49e1aeSJan Lentfer 	/* HandshakeType msg_type */
2876d49e1aeSJan Lentfer 	*pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE;
2886d49e1aeSJan Lentfer 	/* uint24 length (to be filled) */
2896d49e1aeSJan Lentfer 	hs_length = pos;
2906d49e1aeSJan Lentfer 	pos += 3;
2916d49e1aeSJan Lentfer 	/* body - Certificate */
2926d49e1aeSJan Lentfer 	/* uint24 length (to be filled) */
2936d49e1aeSJan Lentfer 	cert_start = pos;
2946d49e1aeSJan Lentfer 	pos += 3;
2956d49e1aeSJan Lentfer 	cert = conn->cred ? conn->cred->cert : NULL;
2966d49e1aeSJan Lentfer 	while (cert) {
297*a1157835SDaniel Fojt 		if (3 + cert->cert_len > (size_t) (end - pos)) {
2986d49e1aeSJan Lentfer 			wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space "
2996d49e1aeSJan Lentfer 				   "for Certificate (cert_len=%lu left=%lu)",
3006d49e1aeSJan Lentfer 				   (unsigned long) cert->cert_len,
3016d49e1aeSJan Lentfer 				   (unsigned long) (end - pos));
3026d49e1aeSJan Lentfer 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
3036d49e1aeSJan Lentfer 				  TLS_ALERT_INTERNAL_ERROR);
3046d49e1aeSJan Lentfer 			return -1;
3056d49e1aeSJan Lentfer 		}
3066d49e1aeSJan Lentfer 		WPA_PUT_BE24(pos, cert->cert_len);
3076d49e1aeSJan Lentfer 		pos += 3;
3086d49e1aeSJan Lentfer 		os_memcpy(pos, cert->cert_start, cert->cert_len);
3096d49e1aeSJan Lentfer 		pos += cert->cert_len;
3106d49e1aeSJan Lentfer 
3116d49e1aeSJan Lentfer 		if (x509_certificate_self_signed(cert))
3126d49e1aeSJan Lentfer 			break;
3136d49e1aeSJan Lentfer 		cert = x509_certificate_get_subject(conn->cred->trusted_certs,
3146d49e1aeSJan Lentfer 						    &cert->issuer);
3156d49e1aeSJan Lentfer 	}
3166d49e1aeSJan Lentfer 	if (conn->cred == NULL || cert == conn->cred->cert || cert == NULL) {
3176d49e1aeSJan Lentfer 		/*
3186d49e1aeSJan Lentfer 		 * Client was not configured with all the needed certificates
3196d49e1aeSJan Lentfer 		 * to form a full certificate chain. The server may fail to
3206d49e1aeSJan Lentfer 		 * validate the chain unless it is configured with all the
3216d49e1aeSJan Lentfer 		 * missing CA certificates.
3226d49e1aeSJan Lentfer 		 */
3236d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Full client certificate chain "
3246d49e1aeSJan Lentfer 			   "not configured - validation may fail");
3256d49e1aeSJan Lentfer 	}
3266d49e1aeSJan Lentfer 	WPA_PUT_BE24(cert_start, pos - cert_start - 3);
3276d49e1aeSJan Lentfer 
3286d49e1aeSJan Lentfer 	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
3296d49e1aeSJan Lentfer 
3306d49e1aeSJan Lentfer 	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
3313ff40c12SJohn Marino 			      rhdr, end - rhdr, hs_start, pos - hs_start,
3323ff40c12SJohn Marino 			      &rlen) < 0) {
3336d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
3346d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
3356d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
3366d49e1aeSJan Lentfer 		return -1;
3376d49e1aeSJan Lentfer 	}
3386d49e1aeSJan Lentfer 	pos = rhdr + rlen;
3396d49e1aeSJan Lentfer 
3406d49e1aeSJan Lentfer 	tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
3416d49e1aeSJan Lentfer 
3426d49e1aeSJan Lentfer 	*msgpos = pos;
3436d49e1aeSJan Lentfer 
3446d49e1aeSJan Lentfer 	return 0;
3456d49e1aeSJan Lentfer }
3466d49e1aeSJan Lentfer 
3476d49e1aeSJan Lentfer 
tlsv1_key_x_dh(struct tlsv1_client * conn,u8 ** pos,u8 * end)348*a1157835SDaniel Fojt static int tlsv1_key_x_dh(struct tlsv1_client *conn, u8 **pos, u8 *end)
3496d49e1aeSJan Lentfer {
3506d49e1aeSJan Lentfer 	/* ClientDiffieHellmanPublic */
3516d49e1aeSJan Lentfer 	u8 *csecret, *csecret_start, *dh_yc, *shared;
3526d49e1aeSJan Lentfer 	size_t csecret_len, dh_yc_len, shared_len;
3536d49e1aeSJan Lentfer 
3546d49e1aeSJan Lentfer 	csecret_len = conn->dh_p_len;
3556d49e1aeSJan Lentfer 	csecret = os_malloc(csecret_len);
3566d49e1aeSJan Lentfer 	if (csecret == NULL) {
3576d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate "
3586d49e1aeSJan Lentfer 			   "memory for Yc (Diffie-Hellman)");
3596d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
3606d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
3616d49e1aeSJan Lentfer 		return -1;
3626d49e1aeSJan Lentfer 	}
3633ff40c12SJohn Marino 	if (random_get_bytes(csecret, csecret_len)) {
3646d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random "
3656d49e1aeSJan Lentfer 			   "data for Diffie-Hellman");
3666d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
3676d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
3686d49e1aeSJan Lentfer 		os_free(csecret);
3696d49e1aeSJan Lentfer 		return -1;
3706d49e1aeSJan Lentfer 	}
3716d49e1aeSJan Lentfer 
3726d49e1aeSJan Lentfer 	if (os_memcmp(csecret, conn->dh_p, csecret_len) > 0)
3736d49e1aeSJan Lentfer 		csecret[0] = 0; /* make sure Yc < p */
3746d49e1aeSJan Lentfer 
3756d49e1aeSJan Lentfer 	csecret_start = csecret;
3766d49e1aeSJan Lentfer 	while (csecret_len > 1 && *csecret_start == 0) {
3776d49e1aeSJan Lentfer 		csecret_start++;
3786d49e1aeSJan Lentfer 		csecret_len--;
3796d49e1aeSJan Lentfer 	}
3806d49e1aeSJan Lentfer 	wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH client's secret value",
3816d49e1aeSJan Lentfer 			csecret_start, csecret_len);
3826d49e1aeSJan Lentfer 
3836d49e1aeSJan Lentfer 	/* Yc = g^csecret mod p */
3846d49e1aeSJan Lentfer 	dh_yc_len = conn->dh_p_len;
3856d49e1aeSJan Lentfer 	dh_yc = os_malloc(dh_yc_len);
3866d49e1aeSJan Lentfer 	if (dh_yc == NULL) {
3876d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate "
3886d49e1aeSJan Lentfer 			   "memory for Diffie-Hellman");
3896d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
3906d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
3916d49e1aeSJan Lentfer 		os_free(csecret);
3926d49e1aeSJan Lentfer 		return -1;
3936d49e1aeSJan Lentfer 	}
3946d49e1aeSJan Lentfer 	if (crypto_mod_exp(conn->dh_g, conn->dh_g_len,
3956d49e1aeSJan Lentfer 			   csecret_start, csecret_len,
3966d49e1aeSJan Lentfer 			   conn->dh_p, conn->dh_p_len,
3976d49e1aeSJan Lentfer 			   dh_yc, &dh_yc_len)) {
3986d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
3996d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
4006d49e1aeSJan Lentfer 		os_free(csecret);
4016d49e1aeSJan Lentfer 		os_free(dh_yc);
4026d49e1aeSJan Lentfer 		return -1;
4036d49e1aeSJan Lentfer 	}
4046d49e1aeSJan Lentfer 
4056d49e1aeSJan Lentfer 	wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)",
4066d49e1aeSJan Lentfer 		    dh_yc, dh_yc_len);
4076d49e1aeSJan Lentfer 
408*a1157835SDaniel Fojt 	if (end - *pos < 2) {
409*a1157835SDaniel Fojt 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
410*a1157835SDaniel Fojt 			  TLS_ALERT_INTERNAL_ERROR);
411*a1157835SDaniel Fojt 		os_free(csecret);
412*a1157835SDaniel Fojt 		os_free(dh_yc);
413*a1157835SDaniel Fojt 		return -1;
414*a1157835SDaniel Fojt 	}
4156d49e1aeSJan Lentfer 	WPA_PUT_BE16(*pos, dh_yc_len);
4166d49e1aeSJan Lentfer 	*pos += 2;
417*a1157835SDaniel Fojt 	if (dh_yc_len > (size_t) (end - *pos)) {
4186d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Not enough room in the "
4196d49e1aeSJan Lentfer 			   "message buffer for Yc");
4206d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
4216d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
4226d49e1aeSJan Lentfer 		os_free(csecret);
4236d49e1aeSJan Lentfer 		os_free(dh_yc);
4246d49e1aeSJan Lentfer 		return -1;
4256d49e1aeSJan Lentfer 	}
4266d49e1aeSJan Lentfer 	os_memcpy(*pos, dh_yc, dh_yc_len);
4276d49e1aeSJan Lentfer 	*pos += dh_yc_len;
4286d49e1aeSJan Lentfer 	os_free(dh_yc);
4296d49e1aeSJan Lentfer 
4306d49e1aeSJan Lentfer 	shared_len = conn->dh_p_len;
4316d49e1aeSJan Lentfer 	shared = os_malloc(shared_len);
4326d49e1aeSJan Lentfer 	if (shared == NULL) {
4336d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for "
4346d49e1aeSJan Lentfer 			   "DH");
4356d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
4366d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
4376d49e1aeSJan Lentfer 		os_free(csecret);
4386d49e1aeSJan Lentfer 		return -1;
4396d49e1aeSJan Lentfer 	}
4406d49e1aeSJan Lentfer 
4416d49e1aeSJan Lentfer 	/* shared = Ys^csecret mod p */
4426d49e1aeSJan Lentfer 	if (crypto_mod_exp(conn->dh_ys, conn->dh_ys_len,
4436d49e1aeSJan Lentfer 			   csecret_start, csecret_len,
4446d49e1aeSJan Lentfer 			   conn->dh_p, conn->dh_p_len,
4456d49e1aeSJan Lentfer 			   shared, &shared_len)) {
4466d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
4476d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
4486d49e1aeSJan Lentfer 		os_free(csecret);
4496d49e1aeSJan Lentfer 		os_free(shared);
4506d49e1aeSJan Lentfer 		return -1;
4516d49e1aeSJan Lentfer 	}
4526d49e1aeSJan Lentfer 	wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange",
4536d49e1aeSJan Lentfer 			shared, shared_len);
4546d49e1aeSJan Lentfer 
4556d49e1aeSJan Lentfer 	os_memset(csecret_start, 0, csecret_len);
4566d49e1aeSJan Lentfer 	os_free(csecret);
4576d49e1aeSJan Lentfer 	if (tls_derive_keys(conn, shared, shared_len)) {
4586d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
4596d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
4606d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
4616d49e1aeSJan Lentfer 		os_free(shared);
4626d49e1aeSJan Lentfer 		return -1;
4636d49e1aeSJan Lentfer 	}
4646d49e1aeSJan Lentfer 	os_memset(shared, 0, shared_len);
4656d49e1aeSJan Lentfer 	os_free(shared);
4666d49e1aeSJan Lentfer 	tlsv1_client_free_dh(conn);
4676d49e1aeSJan Lentfer 	return 0;
4686d49e1aeSJan Lentfer }
4696d49e1aeSJan Lentfer 
4706d49e1aeSJan Lentfer 
tlsv1_key_x_rsa(struct tlsv1_client * conn,u8 ** pos,u8 * end)4716d49e1aeSJan Lentfer static int tlsv1_key_x_rsa(struct tlsv1_client *conn, u8 **pos, u8 *end)
4726d49e1aeSJan Lentfer {
4736d49e1aeSJan Lentfer 	u8 pre_master_secret[TLS_PRE_MASTER_SECRET_LEN];
4746d49e1aeSJan Lentfer 	size_t clen;
4756d49e1aeSJan Lentfer 	int res;
4766d49e1aeSJan Lentfer 
4776d49e1aeSJan Lentfer 	if (tls_derive_pre_master_secret(pre_master_secret) < 0 ||
4786d49e1aeSJan Lentfer 	    tls_derive_keys(conn, pre_master_secret,
4796d49e1aeSJan Lentfer 			    TLS_PRE_MASTER_SECRET_LEN)) {
4806d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
4816d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
4826d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
4836d49e1aeSJan Lentfer 		return -1;
4846d49e1aeSJan Lentfer 	}
4856d49e1aeSJan Lentfer 
4866d49e1aeSJan Lentfer 	/* EncryptedPreMasterSecret */
4876d49e1aeSJan Lentfer 	if (conn->server_rsa_key == NULL) {
4886d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: No server RSA key to "
4896d49e1aeSJan Lentfer 			   "use for encrypting pre-master secret");
4906d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
4916d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
4926d49e1aeSJan Lentfer 		return -1;
4936d49e1aeSJan Lentfer 	}
4946d49e1aeSJan Lentfer 
4956d49e1aeSJan Lentfer 	/* RSA encrypted value is encoded with PKCS #1 v1.5 block type 2. */
4966d49e1aeSJan Lentfer 	*pos += 2;
4976d49e1aeSJan Lentfer 	clen = end - *pos;
4986d49e1aeSJan Lentfer 	res = crypto_public_key_encrypt_pkcs1_v15(
4996d49e1aeSJan Lentfer 		conn->server_rsa_key,
5006d49e1aeSJan Lentfer 		pre_master_secret, TLS_PRE_MASTER_SECRET_LEN,
5016d49e1aeSJan Lentfer 		*pos, &clen);
5026d49e1aeSJan Lentfer 	os_memset(pre_master_secret, 0, TLS_PRE_MASTER_SECRET_LEN);
5036d49e1aeSJan Lentfer 	if (res < 0) {
5046d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: RSA encryption failed");
5056d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
5066d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
5076d49e1aeSJan Lentfer 		return -1;
5086d49e1aeSJan Lentfer 	}
5096d49e1aeSJan Lentfer 	WPA_PUT_BE16(*pos - 2, clen);
5106d49e1aeSJan Lentfer 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: Encrypted pre_master_secret",
5116d49e1aeSJan Lentfer 		    *pos, clen);
5126d49e1aeSJan Lentfer 	*pos += clen;
5136d49e1aeSJan Lentfer 
5146d49e1aeSJan Lentfer 	return 0;
5156d49e1aeSJan Lentfer }
5166d49e1aeSJan Lentfer 
5176d49e1aeSJan Lentfer 
tls_write_client_key_exchange(struct tlsv1_client * conn,u8 ** msgpos,u8 * end)5186d49e1aeSJan Lentfer static int tls_write_client_key_exchange(struct tlsv1_client *conn,
5196d49e1aeSJan Lentfer 					 u8 **msgpos, u8 *end)
5206d49e1aeSJan Lentfer {
5216d49e1aeSJan Lentfer 	u8 *pos, *rhdr, *hs_start, *hs_length;
5226d49e1aeSJan Lentfer 	size_t rlen;
5236d49e1aeSJan Lentfer 	tls_key_exchange keyx;
5246d49e1aeSJan Lentfer 	const struct tls_cipher_suite *suite;
5256d49e1aeSJan Lentfer 
5266d49e1aeSJan Lentfer 	suite = tls_get_cipher_suite(conn->rl.cipher_suite);
5276d49e1aeSJan Lentfer 	if (suite == NULL)
5286d49e1aeSJan Lentfer 		keyx = TLS_KEY_X_NULL;
5296d49e1aeSJan Lentfer 	else
5306d49e1aeSJan Lentfer 		keyx = suite->key_exchange;
5316d49e1aeSJan Lentfer 
5326d49e1aeSJan Lentfer 	pos = *msgpos;
5336d49e1aeSJan Lentfer 
5346d49e1aeSJan Lentfer 	wpa_printf(MSG_DEBUG, "TLSv1: Send ClientKeyExchange");
5356d49e1aeSJan Lentfer 
5366d49e1aeSJan Lentfer 	rhdr = pos;
5376d49e1aeSJan Lentfer 	pos += TLS_RECORD_HEADER_LEN;
5386d49e1aeSJan Lentfer 
5396d49e1aeSJan Lentfer 	/* opaque fragment[TLSPlaintext.length] */
5406d49e1aeSJan Lentfer 
5416d49e1aeSJan Lentfer 	/* Handshake */
5426d49e1aeSJan Lentfer 	hs_start = pos;
5436d49e1aeSJan Lentfer 	/* HandshakeType msg_type */
5446d49e1aeSJan Lentfer 	*pos++ = TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE;
5456d49e1aeSJan Lentfer 	/* uint24 length (to be filled) */
5466d49e1aeSJan Lentfer 	hs_length = pos;
5476d49e1aeSJan Lentfer 	pos += 3;
5486d49e1aeSJan Lentfer 	/* body - ClientKeyExchange */
549*a1157835SDaniel Fojt 	if (keyx == TLS_KEY_X_DH_anon || keyx == TLS_KEY_X_DHE_RSA) {
550*a1157835SDaniel Fojt 		if (tlsv1_key_x_dh(conn, &pos, end) < 0)
5516d49e1aeSJan Lentfer 			return -1;
5526d49e1aeSJan Lentfer 	} else {
5536d49e1aeSJan Lentfer 		if (tlsv1_key_x_rsa(conn, &pos, end) < 0)
5546d49e1aeSJan Lentfer 			return -1;
5556d49e1aeSJan Lentfer 	}
5566d49e1aeSJan Lentfer 
5576d49e1aeSJan Lentfer 	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
5586d49e1aeSJan Lentfer 
5596d49e1aeSJan Lentfer 	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
5603ff40c12SJohn Marino 			      rhdr, end - rhdr, hs_start, pos - hs_start,
5613ff40c12SJohn Marino 			      &rlen) < 0) {
5626d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
5636d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
5646d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
5656d49e1aeSJan Lentfer 		return -1;
5666d49e1aeSJan Lentfer 	}
5676d49e1aeSJan Lentfer 	pos = rhdr + rlen;
5686d49e1aeSJan Lentfer 	tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
5696d49e1aeSJan Lentfer 
5706d49e1aeSJan Lentfer 	*msgpos = pos;
5716d49e1aeSJan Lentfer 
5726d49e1aeSJan Lentfer 	return 0;
5736d49e1aeSJan Lentfer }
5746d49e1aeSJan Lentfer 
5756d49e1aeSJan Lentfer 
tls_write_client_certificate_verify(struct tlsv1_client * conn,u8 ** msgpos,u8 * end)5766d49e1aeSJan Lentfer static int tls_write_client_certificate_verify(struct tlsv1_client *conn,
5776d49e1aeSJan Lentfer 					       u8 **msgpos, u8 *end)
5786d49e1aeSJan Lentfer {
5796d49e1aeSJan Lentfer 	u8 *pos, *rhdr, *hs_start, *hs_length, *signed_start;
5806d49e1aeSJan Lentfer 	size_t rlen, hlen, clen;
5813ff40c12SJohn Marino 	u8 hash[100], *hpos;
5826d49e1aeSJan Lentfer 
5836d49e1aeSJan Lentfer 	pos = *msgpos;
5846d49e1aeSJan Lentfer 
5856d49e1aeSJan Lentfer 	wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateVerify");
5866d49e1aeSJan Lentfer 	rhdr = pos;
5876d49e1aeSJan Lentfer 	pos += TLS_RECORD_HEADER_LEN;
5886d49e1aeSJan Lentfer 
5896d49e1aeSJan Lentfer 	/* Handshake */
5906d49e1aeSJan Lentfer 	hs_start = pos;
5916d49e1aeSJan Lentfer 	/* HandshakeType msg_type */
5926d49e1aeSJan Lentfer 	*pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY;
5936d49e1aeSJan Lentfer 	/* uint24 length (to be filled) */
5946d49e1aeSJan Lentfer 	hs_length = pos;
5956d49e1aeSJan Lentfer 	pos += 3;
5966d49e1aeSJan Lentfer 
5976d49e1aeSJan Lentfer 	/*
5986d49e1aeSJan Lentfer 	 * RFC 2246: 7.4.3 and 7.4.8:
5996d49e1aeSJan Lentfer 	 * Signature signature
6006d49e1aeSJan Lentfer 	 *
6016d49e1aeSJan Lentfer 	 * RSA:
6026d49e1aeSJan Lentfer 	 * digitally-signed struct {
6036d49e1aeSJan Lentfer 	 *     opaque md5_hash[16];
6046d49e1aeSJan Lentfer 	 *     opaque sha_hash[20];
6056d49e1aeSJan Lentfer 	 * };
6066d49e1aeSJan Lentfer 	 *
6076d49e1aeSJan Lentfer 	 * DSA:
6086d49e1aeSJan Lentfer 	 * digitally-signed struct {
6096d49e1aeSJan Lentfer 	 *     opaque sha_hash[20];
6106d49e1aeSJan Lentfer 	 * };
6116d49e1aeSJan Lentfer 	 *
6126d49e1aeSJan Lentfer 	 * The hash values are calculated over all handshake messages sent or
6136d49e1aeSJan Lentfer 	 * received starting at ClientHello up to, but not including, this
6146d49e1aeSJan Lentfer 	 * CertificateVerify message, including the type and length fields of
6156d49e1aeSJan Lentfer 	 * the handshake messages.
6166d49e1aeSJan Lentfer 	 */
6176d49e1aeSJan Lentfer 
6186d49e1aeSJan Lentfer 	hpos = hash;
6196d49e1aeSJan Lentfer 
6203ff40c12SJohn Marino #ifdef CONFIG_TLSV12
6213ff40c12SJohn Marino 	if (conn->rl.tls_version == TLS_VERSION_1_2) {
6223ff40c12SJohn Marino 		hlen = SHA256_MAC_LEN;
6233ff40c12SJohn Marino 		if (conn->verify.sha256_cert == NULL ||
6243ff40c12SJohn Marino 		    crypto_hash_finish(conn->verify.sha256_cert, hpos, &hlen) <
6253ff40c12SJohn Marino 		    0) {
6263ff40c12SJohn Marino 			conn->verify.sha256_cert = NULL;
6273ff40c12SJohn Marino 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
6283ff40c12SJohn Marino 				  TLS_ALERT_INTERNAL_ERROR);
6293ff40c12SJohn Marino 			return -1;
6303ff40c12SJohn Marino 		}
6313ff40c12SJohn Marino 		conn->verify.sha256_cert = NULL;
6323ff40c12SJohn Marino 
6333ff40c12SJohn Marino 		/*
6343ff40c12SJohn Marino 		 * RFC 3447, A.2.4 RSASSA-PKCS1-v1_5
6353ff40c12SJohn Marino 		 *
6363ff40c12SJohn Marino 		 * DigestInfo ::= SEQUENCE {
6373ff40c12SJohn Marino 		 *   digestAlgorithm DigestAlgorithm,
6383ff40c12SJohn Marino 		 *   digest OCTET STRING
6393ff40c12SJohn Marino 		 * }
6403ff40c12SJohn Marino 		 *
6413ff40c12SJohn Marino 		 * SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11}
6423ff40c12SJohn Marino 		 *
6433ff40c12SJohn Marino 		 * DER encoded DigestInfo for SHA256 per RFC 3447:
6443ff40c12SJohn Marino 		 * 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 ||
6453ff40c12SJohn Marino 		 * H
6463ff40c12SJohn Marino 		 */
6473ff40c12SJohn Marino 		os_memmove(hash + 19, hash, hlen);
6483ff40c12SJohn Marino 		hlen += 19;
6493ff40c12SJohn Marino 		os_memcpy(hash, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65"
6503ff40c12SJohn Marino 			  "\x03\x04\x02\x01\x05\x00\x04\x20", 19);
6513ff40c12SJohn Marino 	} else {
6523ff40c12SJohn Marino #endif /* CONFIG_TLSV12 */
6533ff40c12SJohn Marino 
6546d49e1aeSJan Lentfer 	hlen = MD5_MAC_LEN;
6556d49e1aeSJan Lentfer 	if (conn->verify.md5_cert == NULL ||
656*a1157835SDaniel Fojt 	    crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) {
6576d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
6586d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
6596d49e1aeSJan Lentfer 		conn->verify.md5_cert = NULL;
6606d49e1aeSJan Lentfer 		crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL);
6616d49e1aeSJan Lentfer 		conn->verify.sha1_cert = NULL;
6626d49e1aeSJan Lentfer 		return -1;
6636d49e1aeSJan Lentfer 	}
6646d49e1aeSJan Lentfer 	hpos += MD5_MAC_LEN;
6656d49e1aeSJan Lentfer 
6666d49e1aeSJan Lentfer 	conn->verify.md5_cert = NULL;
6676d49e1aeSJan Lentfer 	hlen = SHA1_MAC_LEN;
6686d49e1aeSJan Lentfer 	if (conn->verify.sha1_cert == NULL ||
6696d49e1aeSJan Lentfer 	    crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) {
6706d49e1aeSJan Lentfer 		conn->verify.sha1_cert = NULL;
6716d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
6726d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
6736d49e1aeSJan Lentfer 		return -1;
6746d49e1aeSJan Lentfer 	}
6756d49e1aeSJan Lentfer 	conn->verify.sha1_cert = NULL;
6766d49e1aeSJan Lentfer 
6776d49e1aeSJan Lentfer 	hlen += MD5_MAC_LEN;
6786d49e1aeSJan Lentfer 
6793ff40c12SJohn Marino #ifdef CONFIG_TLSV12
6803ff40c12SJohn Marino 	}
6813ff40c12SJohn Marino #endif /* CONFIG_TLSV12 */
6823ff40c12SJohn Marino 
6836d49e1aeSJan Lentfer 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen);
6846d49e1aeSJan Lentfer 
6853ff40c12SJohn Marino #ifdef CONFIG_TLSV12
6863ff40c12SJohn Marino 	if (conn->rl.tls_version >= TLS_VERSION_1_2) {
6873ff40c12SJohn Marino 		/*
6883ff40c12SJohn Marino 		 * RFC 5246, 4.7:
6893ff40c12SJohn Marino 		 * TLS v1.2 adds explicit indication of the used signature and
6903ff40c12SJohn Marino 		 * hash algorithms.
6913ff40c12SJohn Marino 		 *
6923ff40c12SJohn Marino 		 * struct {
6933ff40c12SJohn Marino 		 *   HashAlgorithm hash;
6943ff40c12SJohn Marino 		 *   SignatureAlgorithm signature;
6953ff40c12SJohn Marino 		 * } SignatureAndHashAlgorithm;
6963ff40c12SJohn Marino 		 */
6973ff40c12SJohn Marino 		*pos++ = TLS_HASH_ALG_SHA256;
6983ff40c12SJohn Marino 		*pos++ = TLS_SIGN_ALG_RSA;
6993ff40c12SJohn Marino 	}
7003ff40c12SJohn Marino #endif /* CONFIG_TLSV12 */
7013ff40c12SJohn Marino 
7026d49e1aeSJan Lentfer 	/*
7036d49e1aeSJan Lentfer 	 * RFC 2246, 4.7:
7046d49e1aeSJan Lentfer 	 * In digital signing, one-way hash functions are used as input for a
7056d49e1aeSJan Lentfer 	 * signing algorithm. A digitally-signed element is encoded as an
7066d49e1aeSJan Lentfer 	 * opaque vector <0..2^16-1>, where the length is specified by the
7076d49e1aeSJan Lentfer 	 * signing algorithm and key.
7086d49e1aeSJan Lentfer 	 *
7096d49e1aeSJan Lentfer 	 * In RSA signing, a 36-byte structure of two hashes (one SHA and one
7106d49e1aeSJan Lentfer 	 * MD5) is signed (encrypted with the private key). It is encoded with
7116d49e1aeSJan Lentfer 	 * PKCS #1 block type 0 or type 1 as described in [PKCS1].
7126d49e1aeSJan Lentfer 	 */
7136d49e1aeSJan Lentfer 	signed_start = pos; /* length to be filled */
7146d49e1aeSJan Lentfer 	pos += 2;
7156d49e1aeSJan Lentfer 	clen = end - pos;
7166d49e1aeSJan Lentfer 	if (conn->cred == NULL ||
7176d49e1aeSJan Lentfer 	    crypto_private_key_sign_pkcs1(conn->cred->key, hash, hlen,
7186d49e1aeSJan Lentfer 					  pos, &clen) < 0) {
7196d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to sign hash (PKCS #1)");
7206d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
7216d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
7226d49e1aeSJan Lentfer 		return -1;
7236d49e1aeSJan Lentfer 	}
7246d49e1aeSJan Lentfer 	WPA_PUT_BE16(signed_start, clen);
7256d49e1aeSJan Lentfer 
7266d49e1aeSJan Lentfer 	pos += clen;
7276d49e1aeSJan Lentfer 
7286d49e1aeSJan Lentfer 	WPA_PUT_BE24(hs_length, pos - hs_length - 3);
7296d49e1aeSJan Lentfer 
7306d49e1aeSJan Lentfer 	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
7313ff40c12SJohn Marino 			      rhdr, end - rhdr, hs_start, pos - hs_start,
7323ff40c12SJohn Marino 			      &rlen) < 0) {
7336d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
7346d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
7356d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
7366d49e1aeSJan Lentfer 		return -1;
7376d49e1aeSJan Lentfer 	}
7386d49e1aeSJan Lentfer 	pos = rhdr + rlen;
7396d49e1aeSJan Lentfer 
7406d49e1aeSJan Lentfer 	tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
7416d49e1aeSJan Lentfer 
7426d49e1aeSJan Lentfer 	*msgpos = pos;
7436d49e1aeSJan Lentfer 
7446d49e1aeSJan Lentfer 	return 0;
7456d49e1aeSJan Lentfer }
7466d49e1aeSJan Lentfer 
7476d49e1aeSJan Lentfer 
tls_write_client_change_cipher_spec(struct tlsv1_client * conn,u8 ** msgpos,u8 * end)7486d49e1aeSJan Lentfer static int tls_write_client_change_cipher_spec(struct tlsv1_client *conn,
7496d49e1aeSJan Lentfer 					       u8 **msgpos, u8 *end)
7506d49e1aeSJan Lentfer {
7516d49e1aeSJan Lentfer 	size_t rlen;
7523ff40c12SJohn Marino 	u8 payload[1];
7536d49e1aeSJan Lentfer 
7546d49e1aeSJan Lentfer 	wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec");
7553ff40c12SJohn Marino 
7563ff40c12SJohn Marino 	payload[0] = TLS_CHANGE_CIPHER_SPEC;
7573ff40c12SJohn Marino 
7586d49e1aeSJan Lentfer 	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC,
7593ff40c12SJohn Marino 			      *msgpos, end - *msgpos, payload, sizeof(payload),
7603ff40c12SJohn Marino 			      &rlen) < 0) {
7616d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
7626d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
7636d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
7646d49e1aeSJan Lentfer 		return -1;
7656d49e1aeSJan Lentfer 	}
7666d49e1aeSJan Lentfer 
7676d49e1aeSJan Lentfer 	if (tlsv1_record_change_write_cipher(&conn->rl) < 0) {
7686d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for "
7696d49e1aeSJan Lentfer 			   "record layer");
7706d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
7716d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
7726d49e1aeSJan Lentfer 		return -1;
7736d49e1aeSJan Lentfer 	}
7746d49e1aeSJan Lentfer 
7753ff40c12SJohn Marino 	*msgpos += rlen;
7766d49e1aeSJan Lentfer 
7776d49e1aeSJan Lentfer 	return 0;
7786d49e1aeSJan Lentfer }
7796d49e1aeSJan Lentfer 
7806d49e1aeSJan Lentfer 
tls_write_client_finished(struct tlsv1_client * conn,u8 ** msgpos,u8 * end)7816d49e1aeSJan Lentfer static int tls_write_client_finished(struct tlsv1_client *conn,
7826d49e1aeSJan Lentfer 				     u8 **msgpos, u8 *end)
7836d49e1aeSJan Lentfer {
7843ff40c12SJohn Marino 	u8 *pos, *hs_start;
7856d49e1aeSJan Lentfer 	size_t rlen, hlen;
7863ff40c12SJohn Marino 	u8 verify_data[1 + 3 + TLS_VERIFY_DATA_LEN];
7876d49e1aeSJan Lentfer 	u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
7886d49e1aeSJan Lentfer 
7896d49e1aeSJan Lentfer 	wpa_printf(MSG_DEBUG, "TLSv1: Send Finished");
7906d49e1aeSJan Lentfer 
7916d49e1aeSJan Lentfer 	/* Encrypted Handshake Message: Finished */
7926d49e1aeSJan Lentfer 
7933ff40c12SJohn Marino #ifdef CONFIG_TLSV12
7943ff40c12SJohn Marino 	if (conn->rl.tls_version >= TLS_VERSION_1_2) {
7953ff40c12SJohn Marino 		hlen = SHA256_MAC_LEN;
7963ff40c12SJohn Marino 		if (conn->verify.sha256_client == NULL ||
7973ff40c12SJohn Marino 		    crypto_hash_finish(conn->verify.sha256_client, hash, &hlen)
7983ff40c12SJohn Marino 		    < 0) {
7993ff40c12SJohn Marino 			tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
8003ff40c12SJohn Marino 				  TLS_ALERT_INTERNAL_ERROR);
8013ff40c12SJohn Marino 			conn->verify.sha256_client = NULL;
8023ff40c12SJohn Marino 			return -1;
8033ff40c12SJohn Marino 		}
8043ff40c12SJohn Marino 		conn->verify.sha256_client = NULL;
8053ff40c12SJohn Marino 	} else {
8063ff40c12SJohn Marino #endif /* CONFIG_TLSV12 */
8073ff40c12SJohn Marino 
8086d49e1aeSJan Lentfer 	hlen = MD5_MAC_LEN;
8096d49e1aeSJan Lentfer 	if (conn->verify.md5_client == NULL ||
8106d49e1aeSJan Lentfer 	    crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) {
8116d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
8126d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
8136d49e1aeSJan Lentfer 		conn->verify.md5_client = NULL;
8146d49e1aeSJan Lentfer 		crypto_hash_finish(conn->verify.sha1_client, NULL, NULL);
8156d49e1aeSJan Lentfer 		conn->verify.sha1_client = NULL;
8166d49e1aeSJan Lentfer 		return -1;
8176d49e1aeSJan Lentfer 	}
8186d49e1aeSJan Lentfer 	conn->verify.md5_client = NULL;
8196d49e1aeSJan Lentfer 	hlen = SHA1_MAC_LEN;
8206d49e1aeSJan Lentfer 	if (conn->verify.sha1_client == NULL ||
8216d49e1aeSJan Lentfer 	    crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN,
8226d49e1aeSJan Lentfer 			       &hlen) < 0) {
8236d49e1aeSJan Lentfer 		conn->verify.sha1_client = NULL;
8246d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
8256d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
8266d49e1aeSJan Lentfer 		return -1;
8276d49e1aeSJan Lentfer 	}
8286d49e1aeSJan Lentfer 	conn->verify.sha1_client = NULL;
8293ff40c12SJohn Marino 	hlen = MD5_MAC_LEN + SHA1_MAC_LEN;
8306d49e1aeSJan Lentfer 
8313ff40c12SJohn Marino #ifdef CONFIG_TLSV12
8323ff40c12SJohn Marino 	}
8333ff40c12SJohn Marino #endif /* CONFIG_TLSV12 */
8343ff40c12SJohn Marino 
8353ff40c12SJohn Marino 	if (tls_prf(conn->rl.tls_version,
8363ff40c12SJohn Marino 		    conn->master_secret, TLS_MASTER_SECRET_LEN,
8373ff40c12SJohn Marino 		    "client finished", hash, hlen,
8383ff40c12SJohn Marino 		    verify_data + 1 + 3, TLS_VERIFY_DATA_LEN)) {
8396d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data");
8406d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
8416d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
8426d49e1aeSJan Lentfer 		return -1;
8436d49e1aeSJan Lentfer 	}
8446d49e1aeSJan Lentfer 	wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)",
8453ff40c12SJohn Marino 			verify_data + 1 + 3, TLS_VERIFY_DATA_LEN);
8466d49e1aeSJan Lentfer 
8476d49e1aeSJan Lentfer 	/* Handshake */
8483ff40c12SJohn Marino 	pos = hs_start = verify_data;
8496d49e1aeSJan Lentfer 	/* HandshakeType msg_type */
8506d49e1aeSJan Lentfer 	*pos++ = TLS_HANDSHAKE_TYPE_FINISHED;
8513ff40c12SJohn Marino 	/* uint24 length */
8523ff40c12SJohn Marino 	WPA_PUT_BE24(pos, TLS_VERIFY_DATA_LEN);
8536d49e1aeSJan Lentfer 	pos += 3;
8543ff40c12SJohn Marino 	pos += TLS_VERIFY_DATA_LEN; /* verify_data already in place */
8556d49e1aeSJan Lentfer 	tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
8566d49e1aeSJan Lentfer 
8576d49e1aeSJan Lentfer 	if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
8583ff40c12SJohn Marino 			      *msgpos, end - *msgpos, hs_start, pos - hs_start,
8593ff40c12SJohn Marino 			      &rlen) < 0) {
8606d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
8616d49e1aeSJan Lentfer 		tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
8626d49e1aeSJan Lentfer 			  TLS_ALERT_INTERNAL_ERROR);
8636d49e1aeSJan Lentfer 		return -1;
8646d49e1aeSJan Lentfer 	}
8656d49e1aeSJan Lentfer 
8663ff40c12SJohn Marino 	*msgpos += rlen;
8676d49e1aeSJan Lentfer 
8686d49e1aeSJan Lentfer 	return 0;
8696d49e1aeSJan Lentfer }
8706d49e1aeSJan Lentfer 
8716d49e1aeSJan Lentfer 
tls_send_client_key_exchange(struct tlsv1_client * conn,size_t * out_len)8726d49e1aeSJan Lentfer static u8 * tls_send_client_key_exchange(struct tlsv1_client *conn,
8736d49e1aeSJan Lentfer 					 size_t *out_len)
8746d49e1aeSJan Lentfer {
8756d49e1aeSJan Lentfer 	u8 *msg, *end, *pos;
8766d49e1aeSJan Lentfer 	size_t msglen;
8776d49e1aeSJan Lentfer 
8786d49e1aeSJan Lentfer 	*out_len = 0;
8796d49e1aeSJan Lentfer 
8803ff40c12SJohn Marino 	msglen = 2000;
8816d49e1aeSJan Lentfer 	if (conn->certificate_requested)
8826d49e1aeSJan Lentfer 		msglen += tls_client_cert_chain_der_len(conn);
8836d49e1aeSJan Lentfer 
8846d49e1aeSJan Lentfer 	msg = os_malloc(msglen);
8856d49e1aeSJan Lentfer 	if (msg == NULL)
8866d49e1aeSJan Lentfer 		return NULL;
8876d49e1aeSJan Lentfer 
8886d49e1aeSJan Lentfer 	pos = msg;
8896d49e1aeSJan Lentfer 	end = msg + msglen;
8906d49e1aeSJan Lentfer 
8916d49e1aeSJan Lentfer 	if (conn->certificate_requested) {
8926d49e1aeSJan Lentfer 		if (tls_write_client_certificate(conn, &pos, end) < 0) {
8936d49e1aeSJan Lentfer 			os_free(msg);
8946d49e1aeSJan Lentfer 			return NULL;
8956d49e1aeSJan Lentfer 		}
8966d49e1aeSJan Lentfer 	}
8976d49e1aeSJan Lentfer 
8986d49e1aeSJan Lentfer 	if (tls_write_client_key_exchange(conn, &pos, end) < 0 ||
8996d49e1aeSJan Lentfer 	    (conn->certificate_requested && conn->cred && conn->cred->key &&
9006d49e1aeSJan Lentfer 	     tls_write_client_certificate_verify(conn, &pos, end) < 0) ||
9016d49e1aeSJan Lentfer 	    tls_write_client_change_cipher_spec(conn, &pos, end) < 0 ||
9026d49e1aeSJan Lentfer 	    tls_write_client_finished(conn, &pos, end) < 0) {
9036d49e1aeSJan Lentfer 		os_free(msg);
9046d49e1aeSJan Lentfer 		return NULL;
9056d49e1aeSJan Lentfer 	}
9066d49e1aeSJan Lentfer 
9076d49e1aeSJan Lentfer 	*out_len = pos - msg;
9086d49e1aeSJan Lentfer 
9096d49e1aeSJan Lentfer 	conn->state = SERVER_CHANGE_CIPHER_SPEC;
9106d49e1aeSJan Lentfer 
9116d49e1aeSJan Lentfer 	return msg;
9126d49e1aeSJan Lentfer }
9136d49e1aeSJan Lentfer 
9146d49e1aeSJan Lentfer 
tls_send_change_cipher_spec(struct tlsv1_client * conn,size_t * out_len)9156d49e1aeSJan Lentfer static u8 * tls_send_change_cipher_spec(struct tlsv1_client *conn,
9166d49e1aeSJan Lentfer 					size_t *out_len)
9176d49e1aeSJan Lentfer {
9186d49e1aeSJan Lentfer 	u8 *msg, *end, *pos;
9196d49e1aeSJan Lentfer 
9206d49e1aeSJan Lentfer 	*out_len = 0;
9216d49e1aeSJan Lentfer 
9226d49e1aeSJan Lentfer 	msg = os_malloc(1000);
9236d49e1aeSJan Lentfer 	if (msg == NULL)
9246d49e1aeSJan Lentfer 		return NULL;
9256d49e1aeSJan Lentfer 
9266d49e1aeSJan Lentfer 	pos = msg;
9276d49e1aeSJan Lentfer 	end = msg + 1000;
9286d49e1aeSJan Lentfer 
9296d49e1aeSJan Lentfer 	if (tls_write_client_change_cipher_spec(conn, &pos, end) < 0 ||
9306d49e1aeSJan Lentfer 	    tls_write_client_finished(conn, &pos, end) < 0) {
9316d49e1aeSJan Lentfer 		os_free(msg);
9326d49e1aeSJan Lentfer 		return NULL;
9336d49e1aeSJan Lentfer 	}
9346d49e1aeSJan Lentfer 
9356d49e1aeSJan Lentfer 	*out_len = pos - msg;
9366d49e1aeSJan Lentfer 
9376d49e1aeSJan Lentfer 	wpa_printf(MSG_DEBUG, "TLSv1: Session resumption completed "
9386d49e1aeSJan Lentfer 		   "successfully");
939*a1157835SDaniel Fojt 	if (!conn->session_resumed && conn->use_session_ticket)
940*a1157835SDaniel Fojt 		conn->session_resumed = 1;
9416d49e1aeSJan Lentfer 	conn->state = ESTABLISHED;
9426d49e1aeSJan Lentfer 
9436d49e1aeSJan Lentfer 	return msg;
9446d49e1aeSJan Lentfer }
9456d49e1aeSJan Lentfer 
9466d49e1aeSJan Lentfer 
tlsv1_client_handshake_write(struct tlsv1_client * conn,size_t * out_len,int no_appl_data)9476d49e1aeSJan Lentfer u8 * tlsv1_client_handshake_write(struct tlsv1_client *conn, size_t *out_len,
9486d49e1aeSJan Lentfer 				  int no_appl_data)
9496d49e1aeSJan Lentfer {
9506d49e1aeSJan Lentfer 	switch (conn->state) {
9516d49e1aeSJan Lentfer 	case CLIENT_KEY_EXCHANGE:
9526d49e1aeSJan Lentfer 		return tls_send_client_key_exchange(conn, out_len);
9536d49e1aeSJan Lentfer 	case CHANGE_CIPHER_SPEC:
9546d49e1aeSJan Lentfer 		return tls_send_change_cipher_spec(conn, out_len);
9556d49e1aeSJan Lentfer 	case ACK_FINISHED:
9566d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed "
9576d49e1aeSJan Lentfer 			   "successfully");
9586d49e1aeSJan Lentfer 		conn->state = ESTABLISHED;
9596d49e1aeSJan Lentfer 		*out_len = 0;
9606d49e1aeSJan Lentfer 		if (no_appl_data) {
9616d49e1aeSJan Lentfer 			/* Need to return something to get final TLS ACK. */
9626d49e1aeSJan Lentfer 			return os_malloc(1);
9636d49e1aeSJan Lentfer 		}
9646d49e1aeSJan Lentfer 		return NULL;
9656d49e1aeSJan Lentfer 	default:
9666d49e1aeSJan Lentfer 		wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while "
9676d49e1aeSJan Lentfer 			   "generating reply", conn->state);
9686d49e1aeSJan Lentfer 		return NULL;
9696d49e1aeSJan Lentfer 	}
9706d49e1aeSJan Lentfer }
9716d49e1aeSJan Lentfer 
9726d49e1aeSJan Lentfer 
tlsv1_client_send_alert(struct tlsv1_client * conn,u8 level,u8 description,size_t * out_len)9736d49e1aeSJan Lentfer u8 * tlsv1_client_send_alert(struct tlsv1_client *conn, u8 level,
9746d49e1aeSJan Lentfer 			     u8 description, size_t *out_len)
9756d49e1aeSJan Lentfer {
9766d49e1aeSJan Lentfer 	u8 *alert, *pos, *length;
9776d49e1aeSJan Lentfer 
9786d49e1aeSJan Lentfer 	wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description);
9796d49e1aeSJan Lentfer 	*out_len = 0;
9806d49e1aeSJan Lentfer 
9816d49e1aeSJan Lentfer 	alert = os_malloc(10);
9826d49e1aeSJan Lentfer 	if (alert == NULL)
9836d49e1aeSJan Lentfer 		return NULL;
9846d49e1aeSJan Lentfer 
9856d49e1aeSJan Lentfer 	pos = alert;
9866d49e1aeSJan Lentfer 
9876d49e1aeSJan Lentfer 	/* TLSPlaintext */
9886d49e1aeSJan Lentfer 	/* ContentType type */
9896d49e1aeSJan Lentfer 	*pos++ = TLS_CONTENT_TYPE_ALERT;
9906d49e1aeSJan Lentfer 	/* ProtocolVersion version */
9913ff40c12SJohn Marino 	WPA_PUT_BE16(pos, conn->rl.tls_version ? conn->rl.tls_version :
9923ff40c12SJohn Marino 		     TLS_VERSION);
9936d49e1aeSJan Lentfer 	pos += 2;
9946d49e1aeSJan Lentfer 	/* uint16 length (to be filled) */
9956d49e1aeSJan Lentfer 	length = pos;
9966d49e1aeSJan Lentfer 	pos += 2;
9976d49e1aeSJan Lentfer 	/* opaque fragment[TLSPlaintext.length] */
9986d49e1aeSJan Lentfer 
9996d49e1aeSJan Lentfer 	/* Alert */
10006d49e1aeSJan Lentfer 	/* AlertLevel level */
10016d49e1aeSJan Lentfer 	*pos++ = level;
10026d49e1aeSJan Lentfer 	/* AlertDescription description */
10036d49e1aeSJan Lentfer 	*pos++ = description;
10046d49e1aeSJan Lentfer 
10056d49e1aeSJan Lentfer 	WPA_PUT_BE16(length, pos - length - 2);
10066d49e1aeSJan Lentfer 	*out_len = pos - alert;
10076d49e1aeSJan Lentfer 
10086d49e1aeSJan Lentfer 	return alert;
10096d49e1aeSJan Lentfer }
1010