139beb93cSSam Leffler /*
239beb93cSSam Leffler * TLSv1 client - read handshake message
3780fb4a2SCy Schubert * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler *
5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo * See README for more details.
739beb93cSSam Leffler */
839beb93cSSam Leffler
939beb93cSSam Leffler #include "includes.h"
1039beb93cSSam Leffler
1139beb93cSSam Leffler #include "common.h"
12e28a4053SRui Paulo #include "crypto/md5.h"
13e28a4053SRui Paulo #include "crypto/sha1.h"
14f05cddf9SRui Paulo #include "crypto/sha256.h"
15e28a4053SRui Paulo #include "crypto/tls.h"
1639beb93cSSam Leffler #include "x509v3.h"
1739beb93cSSam Leffler #include "tlsv1_common.h"
1839beb93cSSam Leffler #include "tlsv1_record.h"
1939beb93cSSam Leffler #include "tlsv1_client.h"
2039beb93cSSam Leffler #include "tlsv1_client_i.h"
2139beb93cSSam Leffler
2239beb93cSSam Leffler static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,
2339beb93cSSam Leffler const u8 *in_data, size_t *in_len);
2439beb93cSSam Leffler static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct,
2539beb93cSSam Leffler const u8 *in_data, size_t *in_len);
2639beb93cSSam Leffler static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct,
2739beb93cSSam Leffler const u8 *in_data, size_t *in_len);
2839beb93cSSam Leffler
2939beb93cSSam Leffler
tls_version_disabled(struct tlsv1_client * conn,u16 ver)30780fb4a2SCy Schubert static int tls_version_disabled(struct tlsv1_client *conn, u16 ver)
31780fb4a2SCy Schubert {
32780fb4a2SCy Schubert return (((conn->flags & TLS_CONN_DISABLE_TLSv1_0) &&
33780fb4a2SCy Schubert ver == TLS_VERSION_1) ||
34780fb4a2SCy Schubert ((conn->flags & TLS_CONN_DISABLE_TLSv1_1) &&
35780fb4a2SCy Schubert ver == TLS_VERSION_1_1) ||
36780fb4a2SCy Schubert ((conn->flags & TLS_CONN_DISABLE_TLSv1_2) &&
37780fb4a2SCy Schubert ver == TLS_VERSION_1_2));
38780fb4a2SCy Schubert }
39780fb4a2SCy Schubert
40780fb4a2SCy Schubert
tls_process_server_hello_extensions(struct tlsv1_client * conn,const u8 * pos,size_t len)41780fb4a2SCy Schubert static int tls_process_server_hello_extensions(struct tlsv1_client *conn,
42780fb4a2SCy Schubert const u8 *pos, size_t len)
43780fb4a2SCy Schubert {
44780fb4a2SCy Schubert const u8 *end = pos + len;
45780fb4a2SCy Schubert
46780fb4a2SCy Schubert wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello extensions",
47780fb4a2SCy Schubert pos, len);
48780fb4a2SCy Schubert while (pos < end) {
49780fb4a2SCy Schubert u16 ext, elen;
50780fb4a2SCy Schubert
51780fb4a2SCy Schubert if (end - pos < 4) {
52780fb4a2SCy Schubert wpa_printf(MSG_INFO, "TLSv1: Truncated ServerHello extension header");
53780fb4a2SCy Schubert return -1;
54780fb4a2SCy Schubert }
55780fb4a2SCy Schubert
56780fb4a2SCy Schubert ext = WPA_GET_BE16(pos);
57780fb4a2SCy Schubert pos += 2;
58780fb4a2SCy Schubert elen = WPA_GET_BE16(pos);
59780fb4a2SCy Schubert pos += 2;
60780fb4a2SCy Schubert
61780fb4a2SCy Schubert if (elen > end - pos) {
62780fb4a2SCy Schubert wpa_printf(MSG_INFO, "TLSv1: Truncated ServerHello extension");
63780fb4a2SCy Schubert return -1;
64780fb4a2SCy Schubert }
65780fb4a2SCy Schubert
66780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, "TLSv1: ServerHello ExtensionType %u",
67780fb4a2SCy Schubert ext);
68780fb4a2SCy Schubert wpa_hexdump(MSG_DEBUG, "TLSv1: ServerHello extension data",
69780fb4a2SCy Schubert pos, elen);
70780fb4a2SCy Schubert
71780fb4a2SCy Schubert pos += elen;
72780fb4a2SCy Schubert }
73780fb4a2SCy Schubert
74780fb4a2SCy Schubert return 0;
75780fb4a2SCy Schubert }
76780fb4a2SCy Schubert
77780fb4a2SCy Schubert
tls_process_server_hello(struct tlsv1_client * conn,u8 ct,const u8 * in_data,size_t * in_len)7839beb93cSSam Leffler static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct,
7939beb93cSSam Leffler const u8 *in_data, size_t *in_len)
8039beb93cSSam Leffler {
8139beb93cSSam Leffler const u8 *pos, *end;
8239beb93cSSam Leffler size_t left, len, i;
8339beb93cSSam Leffler u16 cipher_suite;
84f05cddf9SRui Paulo u16 tls_version;
8539beb93cSSam Leffler
8639beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
8739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
8839beb93cSSam Leffler "received content type 0x%x", ct);
8939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
9039beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE);
9139beb93cSSam Leffler return -1;
9239beb93cSSam Leffler }
9339beb93cSSam Leffler
9439beb93cSSam Leffler pos = in_data;
9539beb93cSSam Leffler left = *in_len;
9639beb93cSSam Leffler
9739beb93cSSam Leffler if (left < 4)
9839beb93cSSam Leffler goto decode_error;
9939beb93cSSam Leffler
10039beb93cSSam Leffler /* HandshakeType msg_type */
10139beb93cSSam Leffler if (*pos != TLS_HANDSHAKE_TYPE_SERVER_HELLO) {
10239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
10339beb93cSSam Leffler "message %d (expected ServerHello)", *pos);
10439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
10539beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE);
10639beb93cSSam Leffler return -1;
10739beb93cSSam Leffler }
10839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHello");
10939beb93cSSam Leffler pos++;
11039beb93cSSam Leffler /* uint24 length */
11139beb93cSSam Leffler len = WPA_GET_BE24(pos);
11239beb93cSSam Leffler pos += 3;
11339beb93cSSam Leffler left -= 4;
11439beb93cSSam Leffler
11539beb93cSSam Leffler if (len > left)
11639beb93cSSam Leffler goto decode_error;
11739beb93cSSam Leffler
11839beb93cSSam Leffler /* body - ServerHello */
11939beb93cSSam Leffler
12039beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello", pos, len);
12139beb93cSSam Leffler end = pos + len;
12239beb93cSSam Leffler
12339beb93cSSam Leffler /* ProtocolVersion server_version */
12439beb93cSSam Leffler if (end - pos < 2)
12539beb93cSSam Leffler goto decode_error;
126f05cddf9SRui Paulo tls_version = WPA_GET_BE16(pos);
127780fb4a2SCy Schubert if (!tls_version_ok(tls_version) ||
128780fb4a2SCy Schubert tls_version_disabled(conn, tls_version)) {
12939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in "
130f05cddf9SRui Paulo "ServerHello %u.%u", pos[0], pos[1]);
13139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
13239beb93cSSam Leffler TLS_ALERT_PROTOCOL_VERSION);
13339beb93cSSam Leffler return -1;
13439beb93cSSam Leffler }
13539beb93cSSam Leffler pos += 2;
13639beb93cSSam Leffler
137f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "TLSv1: Using TLS v%s",
138f05cddf9SRui Paulo tls_version_str(tls_version));
139f05cddf9SRui Paulo conn->rl.tls_version = tls_version;
140f05cddf9SRui Paulo
14139beb93cSSam Leffler /* Random random */
14239beb93cSSam Leffler if (end - pos < TLS_RANDOM_LEN)
14339beb93cSSam Leffler goto decode_error;
14439beb93cSSam Leffler
14539beb93cSSam Leffler os_memcpy(conn->server_random, pos, TLS_RANDOM_LEN);
14639beb93cSSam Leffler pos += TLS_RANDOM_LEN;
14739beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random",
14839beb93cSSam Leffler conn->server_random, TLS_RANDOM_LEN);
14939beb93cSSam Leffler
15039beb93cSSam Leffler /* SessionID session_id */
15139beb93cSSam Leffler if (end - pos < 1)
15239beb93cSSam Leffler goto decode_error;
15339beb93cSSam Leffler if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN)
15439beb93cSSam Leffler goto decode_error;
15539beb93cSSam Leffler if (conn->session_id_len && conn->session_id_len == *pos &&
15639beb93cSSam Leffler os_memcmp(conn->session_id, pos + 1, conn->session_id_len) == 0) {
15739beb93cSSam Leffler pos += 1 + conn->session_id_len;
15839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Resuming old session");
15939beb93cSSam Leffler conn->session_resumed = 1;
16039beb93cSSam Leffler } else {
16139beb93cSSam Leffler conn->session_id_len = *pos;
16239beb93cSSam Leffler pos++;
16339beb93cSSam Leffler os_memcpy(conn->session_id, pos, conn->session_id_len);
16439beb93cSSam Leffler pos += conn->session_id_len;
16539beb93cSSam Leffler }
16639beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id",
16739beb93cSSam Leffler conn->session_id, conn->session_id_len);
16839beb93cSSam Leffler
16939beb93cSSam Leffler /* CipherSuite cipher_suite */
17039beb93cSSam Leffler if (end - pos < 2)
17139beb93cSSam Leffler goto decode_error;
17239beb93cSSam Leffler cipher_suite = WPA_GET_BE16(pos);
17339beb93cSSam Leffler pos += 2;
17439beb93cSSam Leffler for (i = 0; i < conn->num_cipher_suites; i++) {
17539beb93cSSam Leffler if (cipher_suite == conn->cipher_suites[i])
17639beb93cSSam Leffler break;
17739beb93cSSam Leffler }
17839beb93cSSam Leffler if (i == conn->num_cipher_suites) {
17939beb93cSSam Leffler wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected "
18039beb93cSSam Leffler "cipher suite 0x%04x", cipher_suite);
18139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
18239beb93cSSam Leffler TLS_ALERT_ILLEGAL_PARAMETER);
18339beb93cSSam Leffler return -1;
18439beb93cSSam Leffler }
18539beb93cSSam Leffler
18639beb93cSSam Leffler if (conn->session_resumed && cipher_suite != conn->prev_cipher_suite) {
18739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Server selected a different "
18839beb93cSSam Leffler "cipher suite for a resumed connection (0x%04x != "
18939beb93cSSam Leffler "0x%04x)", cipher_suite, conn->prev_cipher_suite);
19039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
19139beb93cSSam Leffler TLS_ALERT_ILLEGAL_PARAMETER);
19239beb93cSSam Leffler return -1;
19339beb93cSSam Leffler }
19439beb93cSSam Leffler
19539beb93cSSam Leffler if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) {
19639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for "
19739beb93cSSam Leffler "record layer");
19839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
19939beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR);
20039beb93cSSam Leffler return -1;
20139beb93cSSam Leffler }
20239beb93cSSam Leffler
20339beb93cSSam Leffler conn->prev_cipher_suite = cipher_suite;
20439beb93cSSam Leffler
20539beb93cSSam Leffler /* CompressionMethod compression_method */
20639beb93cSSam Leffler if (end - pos < 1)
20739beb93cSSam Leffler goto decode_error;
20839beb93cSSam Leffler if (*pos != TLS_COMPRESSION_NULL) {
20939beb93cSSam Leffler wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected "
21039beb93cSSam Leffler "compression 0x%02x", *pos);
21139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
21239beb93cSSam Leffler TLS_ALERT_ILLEGAL_PARAMETER);
21339beb93cSSam Leffler return -1;
21439beb93cSSam Leffler }
21539beb93cSSam Leffler pos++;
21639beb93cSSam Leffler
217780fb4a2SCy Schubert if (end - pos >= 2) {
218780fb4a2SCy Schubert u16 ext_len;
219780fb4a2SCy Schubert
220780fb4a2SCy Schubert ext_len = WPA_GET_BE16(pos);
221780fb4a2SCy Schubert pos += 2;
222780fb4a2SCy Schubert if (end - pos < ext_len) {
223780fb4a2SCy Schubert wpa_printf(MSG_INFO,
224780fb4a2SCy Schubert "TLSv1: Invalid ServerHello extension length: %u (left: %u)",
225780fb4a2SCy Schubert ext_len, (unsigned int) (end - pos));
226780fb4a2SCy Schubert goto decode_error;
227780fb4a2SCy Schubert }
228780fb4a2SCy Schubert
229780fb4a2SCy Schubert if (tls_process_server_hello_extensions(conn, pos, ext_len))
230780fb4a2SCy Schubert goto decode_error;
231780fb4a2SCy Schubert pos += ext_len;
232780fb4a2SCy Schubert }
233780fb4a2SCy Schubert
23439beb93cSSam Leffler if (end != pos) {
23539beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: Unexpected extra data in the "
23639beb93cSSam Leffler "end of ServerHello", pos, end - pos);
23739beb93cSSam Leffler goto decode_error;
23839beb93cSSam Leffler }
23939beb93cSSam Leffler
24039beb93cSSam Leffler if (conn->session_ticket_included && conn->session_ticket_cb) {
24139beb93cSSam Leffler /* TODO: include SessionTicket extension if one was included in
24239beb93cSSam Leffler * ServerHello */
24339beb93cSSam Leffler int res = conn->session_ticket_cb(
24439beb93cSSam Leffler conn->session_ticket_cb_ctx, NULL, 0,
24539beb93cSSam Leffler conn->client_random, conn->server_random,
24639beb93cSSam Leffler conn->master_secret);
24739beb93cSSam Leffler if (res < 0) {
24839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback "
24939beb93cSSam Leffler "indicated failure");
25039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
25139beb93cSSam Leffler TLS_ALERT_HANDSHAKE_FAILURE);
25239beb93cSSam Leffler return -1;
25339beb93cSSam Leffler }
25439beb93cSSam Leffler conn->use_session_ticket = !!res;
25539beb93cSSam Leffler }
25639beb93cSSam Leffler
25739beb93cSSam Leffler if ((conn->session_resumed || conn->use_session_ticket) &&
25839beb93cSSam Leffler tls_derive_keys(conn, NULL, 0)) {
25939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");
26039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
26139beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR);
26239beb93cSSam Leffler return -1;
26339beb93cSSam Leffler }
26439beb93cSSam Leffler
26539beb93cSSam Leffler *in_len = end - in_data;
26639beb93cSSam Leffler
26739beb93cSSam Leffler conn->state = (conn->session_resumed || conn->use_session_ticket) ?
26839beb93cSSam Leffler SERVER_CHANGE_CIPHER_SPEC : SERVER_CERTIFICATE;
26939beb93cSSam Leffler
27039beb93cSSam Leffler return 0;
27139beb93cSSam Leffler
27239beb93cSSam Leffler decode_error:
27339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ServerHello");
27439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
27539beb93cSSam Leffler return -1;
27639beb93cSSam Leffler }
27739beb93cSSam Leffler
27839beb93cSSam Leffler
tls_peer_cert_event(struct tlsv1_client * conn,int depth,struct x509_certificate * cert)279780fb4a2SCy Schubert static void tls_peer_cert_event(struct tlsv1_client *conn, int depth,
280780fb4a2SCy Schubert struct x509_certificate *cert)
281780fb4a2SCy Schubert {
282780fb4a2SCy Schubert union tls_event_data ev;
283780fb4a2SCy Schubert struct wpabuf *cert_buf = NULL;
284780fb4a2SCy Schubert #ifdef CONFIG_SHA256
285780fb4a2SCy Schubert u8 hash[32];
286780fb4a2SCy Schubert #endif /* CONFIG_SHA256 */
287780fb4a2SCy Schubert char subject[128];
288780fb4a2SCy Schubert
289780fb4a2SCy Schubert if (!conn->event_cb)
290780fb4a2SCy Schubert return;
291780fb4a2SCy Schubert
292780fb4a2SCy Schubert os_memset(&ev, 0, sizeof(ev));
2934bc52338SCy Schubert if ((conn->cred && conn->cred->cert_probe) || conn->cert_in_cb) {
294780fb4a2SCy Schubert cert_buf = wpabuf_alloc_copy(cert->cert_start,
295780fb4a2SCy Schubert cert->cert_len);
296780fb4a2SCy Schubert ev.peer_cert.cert = cert_buf;
297780fb4a2SCy Schubert }
298780fb4a2SCy Schubert #ifdef CONFIG_SHA256
299780fb4a2SCy Schubert if (cert_buf) {
300780fb4a2SCy Schubert const u8 *addr[1];
301780fb4a2SCy Schubert size_t len[1];
302780fb4a2SCy Schubert addr[0] = wpabuf_head(cert_buf);
303780fb4a2SCy Schubert len[0] = wpabuf_len(cert_buf);
304780fb4a2SCy Schubert if (sha256_vector(1, addr, len, hash) == 0) {
305780fb4a2SCy Schubert ev.peer_cert.hash = hash;
306780fb4a2SCy Schubert ev.peer_cert.hash_len = sizeof(hash);
307780fb4a2SCy Schubert }
308780fb4a2SCy Schubert }
309780fb4a2SCy Schubert #endif /* CONFIG_SHA256 */
310780fb4a2SCy Schubert
311780fb4a2SCy Schubert ev.peer_cert.depth = depth;
312780fb4a2SCy Schubert x509_name_string(&cert->subject, subject, sizeof(subject));
313780fb4a2SCy Schubert ev.peer_cert.subject = subject;
314780fb4a2SCy Schubert
315c1d255d3SCy Schubert if (cert->extensions_present & X509_EXT_CERTIFICATE_POLICY) {
316c1d255d3SCy Schubert if (cert->certificate_policy & X509_EXT_CERT_POLICY_TOD_STRICT)
317c1d255d3SCy Schubert ev.peer_cert.tod = 1;
318c1d255d3SCy Schubert else if (cert->certificate_policy &
319c1d255d3SCy Schubert X509_EXT_CERT_POLICY_TOD_TOFU)
320c1d255d3SCy Schubert ev.peer_cert.tod = 2;
321c1d255d3SCy Schubert }
322c1d255d3SCy Schubert
323780fb4a2SCy Schubert conn->event_cb(conn->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
324780fb4a2SCy Schubert wpabuf_free(cert_buf);
325780fb4a2SCy Schubert }
326780fb4a2SCy Schubert
327780fb4a2SCy Schubert
tls_cert_chain_failure_event(struct tlsv1_client * conn,int depth,struct x509_certificate * cert,enum tls_fail_reason reason,const char * reason_txt)328780fb4a2SCy Schubert static void tls_cert_chain_failure_event(struct tlsv1_client *conn, int depth,
329780fb4a2SCy Schubert struct x509_certificate *cert,
330780fb4a2SCy Schubert enum tls_fail_reason reason,
331780fb4a2SCy Schubert const char *reason_txt)
332780fb4a2SCy Schubert {
333780fb4a2SCy Schubert struct wpabuf *cert_buf = NULL;
334780fb4a2SCy Schubert union tls_event_data ev;
335780fb4a2SCy Schubert char subject[128];
336780fb4a2SCy Schubert
337780fb4a2SCy Schubert if (!conn->event_cb || !cert)
338780fb4a2SCy Schubert return;
339780fb4a2SCy Schubert
340780fb4a2SCy Schubert os_memset(&ev, 0, sizeof(ev));
341780fb4a2SCy Schubert ev.cert_fail.depth = depth;
342780fb4a2SCy Schubert x509_name_string(&cert->subject, subject, sizeof(subject));
343780fb4a2SCy Schubert ev.peer_cert.subject = subject;
344780fb4a2SCy Schubert ev.cert_fail.reason = reason;
345780fb4a2SCy Schubert ev.cert_fail.reason_txt = reason_txt;
346780fb4a2SCy Schubert cert_buf = wpabuf_alloc_copy(cert->cert_start,
347780fb4a2SCy Schubert cert->cert_len);
348780fb4a2SCy Schubert ev.cert_fail.cert = cert_buf;
349780fb4a2SCy Schubert conn->event_cb(conn->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
350780fb4a2SCy Schubert wpabuf_free(cert_buf);
351780fb4a2SCy Schubert }
352780fb4a2SCy Schubert
353780fb4a2SCy Schubert
tls_process_certificate(struct tlsv1_client * conn,u8 ct,const u8 * in_data,size_t * in_len)35439beb93cSSam Leffler static int tls_process_certificate(struct tlsv1_client *conn, u8 ct,
35539beb93cSSam Leffler const u8 *in_data, size_t *in_len)
35639beb93cSSam Leffler {
35739beb93cSSam Leffler const u8 *pos, *end;
35839beb93cSSam Leffler size_t left, len, list_len, cert_len, idx;
35939beb93cSSam Leffler u8 type;
36039beb93cSSam Leffler struct x509_certificate *chain = NULL, *last = NULL, *cert;
36139beb93cSSam Leffler int reason;
36239beb93cSSam Leffler
36339beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
36439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
36539beb93cSSam Leffler "received content type 0x%x", ct);
36639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
36739beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE);
36839beb93cSSam Leffler return -1;
36939beb93cSSam Leffler }
37039beb93cSSam Leffler
37139beb93cSSam Leffler pos = in_data;
37239beb93cSSam Leffler left = *in_len;
37339beb93cSSam Leffler
37439beb93cSSam Leffler if (left < 4) {
37539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message "
37639beb93cSSam Leffler "(len=%lu)", (unsigned long) left);
37739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
37839beb93cSSam Leffler return -1;
37939beb93cSSam Leffler }
38039beb93cSSam Leffler
38139beb93cSSam Leffler type = *pos++;
38239beb93cSSam Leffler len = WPA_GET_BE24(pos);
38339beb93cSSam Leffler pos += 3;
38439beb93cSSam Leffler left -= 4;
38539beb93cSSam Leffler
38639beb93cSSam Leffler if (len > left) {
38739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message "
38839beb93cSSam Leffler "length (len=%lu != left=%lu)",
38939beb93cSSam Leffler (unsigned long) len, (unsigned long) left);
39039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
39139beb93cSSam Leffler return -1;
39239beb93cSSam Leffler }
39339beb93cSSam Leffler
39439beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE)
39539beb93cSSam Leffler return tls_process_server_key_exchange(conn, ct, in_data,
39639beb93cSSam Leffler in_len);
39739beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST)
39839beb93cSSam Leffler return tls_process_certificate_request(conn, ct, in_data,
39939beb93cSSam Leffler in_len);
40039beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
40139beb93cSSam Leffler return tls_process_server_hello_done(conn, ct, in_data,
40239beb93cSSam Leffler in_len);
40339beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) {
40439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
40539beb93cSSam Leffler "message %d (expected Certificate/"
40639beb93cSSam Leffler "ServerKeyExchange/CertificateRequest/"
40739beb93cSSam Leffler "ServerHelloDone)", type);
40839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
40939beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE);
41039beb93cSSam Leffler return -1;
41139beb93cSSam Leffler }
41239beb93cSSam Leffler
41339beb93cSSam Leffler wpa_printf(MSG_DEBUG,
41439beb93cSSam Leffler "TLSv1: Received Certificate (certificate_list len %lu)",
41539beb93cSSam Leffler (unsigned long) len);
41639beb93cSSam Leffler
41739beb93cSSam Leffler /*
41839beb93cSSam Leffler * opaque ASN.1Cert<2^24-1>;
41939beb93cSSam Leffler *
42039beb93cSSam Leffler * struct {
42139beb93cSSam Leffler * ASN.1Cert certificate_list<1..2^24-1>;
42239beb93cSSam Leffler * } Certificate;
42339beb93cSSam Leffler */
42439beb93cSSam Leffler
42539beb93cSSam Leffler end = pos + len;
42639beb93cSSam Leffler
42739beb93cSSam Leffler if (end - pos < 3) {
42839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate "
42939beb93cSSam Leffler "(left=%lu)", (unsigned long) left);
43039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
43139beb93cSSam Leffler return -1;
43239beb93cSSam Leffler }
43339beb93cSSam Leffler
43439beb93cSSam Leffler list_len = WPA_GET_BE24(pos);
43539beb93cSSam Leffler pos += 3;
43639beb93cSSam Leffler
43739beb93cSSam Leffler if ((size_t) (end - pos) != list_len) {
43839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list "
43939beb93cSSam Leffler "length (len=%lu left=%lu)",
44039beb93cSSam Leffler (unsigned long) list_len,
44139beb93cSSam Leffler (unsigned long) (end - pos));
44239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
44339beb93cSSam Leffler return -1;
44439beb93cSSam Leffler }
44539beb93cSSam Leffler
44639beb93cSSam Leffler idx = 0;
44739beb93cSSam Leffler while (pos < end) {
44839beb93cSSam Leffler if (end - pos < 3) {
44939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
45039beb93cSSam Leffler "certificate_list");
45139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
45239beb93cSSam Leffler TLS_ALERT_DECODE_ERROR);
45339beb93cSSam Leffler x509_certificate_chain_free(chain);
45439beb93cSSam Leffler return -1;
45539beb93cSSam Leffler }
45639beb93cSSam Leffler
45739beb93cSSam Leffler cert_len = WPA_GET_BE24(pos);
45839beb93cSSam Leffler pos += 3;
45939beb93cSSam Leffler
46039beb93cSSam Leffler if ((size_t) (end - pos) < cert_len) {
46139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate "
46239beb93cSSam Leffler "length (len=%lu left=%lu)",
46339beb93cSSam Leffler (unsigned long) cert_len,
46439beb93cSSam Leffler (unsigned long) (end - pos));
46539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
46639beb93cSSam Leffler TLS_ALERT_DECODE_ERROR);
46739beb93cSSam Leffler x509_certificate_chain_free(chain);
46839beb93cSSam Leffler return -1;
46939beb93cSSam Leffler }
47039beb93cSSam Leffler
47139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)",
47239beb93cSSam Leffler (unsigned long) idx, (unsigned long) cert_len);
47339beb93cSSam Leffler
47439beb93cSSam Leffler if (idx == 0) {
47539beb93cSSam Leffler crypto_public_key_free(conn->server_rsa_key);
47639beb93cSSam Leffler if (tls_parse_cert(pos, cert_len,
47739beb93cSSam Leffler &conn->server_rsa_key)) {
47839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
47939beb93cSSam Leffler "the certificate");
48039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
48139beb93cSSam Leffler TLS_ALERT_BAD_CERTIFICATE);
48239beb93cSSam Leffler x509_certificate_chain_free(chain);
48339beb93cSSam Leffler return -1;
48439beb93cSSam Leffler }
48539beb93cSSam Leffler }
48639beb93cSSam Leffler
48739beb93cSSam Leffler cert = x509_certificate_parse(pos, cert_len);
48839beb93cSSam Leffler if (cert == NULL) {
48939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse "
49039beb93cSSam Leffler "the certificate");
49139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
49239beb93cSSam Leffler TLS_ALERT_BAD_CERTIFICATE);
49339beb93cSSam Leffler x509_certificate_chain_free(chain);
49439beb93cSSam Leffler return -1;
49539beb93cSSam Leffler }
49639beb93cSSam Leffler
497780fb4a2SCy Schubert tls_peer_cert_event(conn, idx, cert);
498780fb4a2SCy Schubert
49939beb93cSSam Leffler if (last == NULL)
50039beb93cSSam Leffler chain = cert;
50139beb93cSSam Leffler else
50239beb93cSSam Leffler last->next = cert;
50339beb93cSSam Leffler last = cert;
50439beb93cSSam Leffler
50539beb93cSSam Leffler idx++;
50639beb93cSSam Leffler pos += cert_len;
50739beb93cSSam Leffler }
50839beb93cSSam Leffler
509780fb4a2SCy Schubert if (conn->cred && conn->cred->server_cert_only && chain) {
510780fb4a2SCy Schubert u8 hash[SHA256_MAC_LEN];
511780fb4a2SCy Schubert char buf[128];
512780fb4a2SCy Schubert
513780fb4a2SCy Schubert wpa_printf(MSG_DEBUG,
514780fb4a2SCy Schubert "TLSv1: Validate server certificate hash");
515780fb4a2SCy Schubert x509_name_string(&chain->subject, buf, sizeof(buf));
516780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, "TLSv1: 0: %s", buf);
517780fb4a2SCy Schubert if (sha256_vector(1, &chain->cert_start, &chain->cert_len,
518780fb4a2SCy Schubert hash) < 0 ||
519780fb4a2SCy Schubert os_memcmp(conn->cred->srv_cert_hash, hash,
520780fb4a2SCy Schubert SHA256_MAC_LEN) != 0) {
521780fb4a2SCy Schubert wpa_printf(MSG_DEBUG,
522780fb4a2SCy Schubert "TLSv1: Server certificate hash mismatch");
523780fb4a2SCy Schubert wpa_hexdump(MSG_MSGDUMP, "TLSv1: SHA256 hash",
524780fb4a2SCy Schubert hash, SHA256_MAC_LEN);
525780fb4a2SCy Schubert if (conn->event_cb) {
526780fb4a2SCy Schubert union tls_event_data ev;
527780fb4a2SCy Schubert
528780fb4a2SCy Schubert os_memset(&ev, 0, sizeof(ev));
529780fb4a2SCy Schubert ev.cert_fail.reason = TLS_FAIL_UNSPECIFIED;
530780fb4a2SCy Schubert ev.cert_fail.reason_txt =
531780fb4a2SCy Schubert "Server certificate mismatch";
532780fb4a2SCy Schubert ev.cert_fail.subject = buf;
533780fb4a2SCy Schubert conn->event_cb(conn->cb_ctx,
534780fb4a2SCy Schubert TLS_CERT_CHAIN_FAILURE, &ev);
535780fb4a2SCy Schubert }
536780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
537780fb4a2SCy Schubert TLS_ALERT_BAD_CERTIFICATE);
538780fb4a2SCy Schubert x509_certificate_chain_free(chain);
539780fb4a2SCy Schubert return -1;
540780fb4a2SCy Schubert }
541780fb4a2SCy Schubert } else if (conn->cred && conn->cred->cert_probe) {
542780fb4a2SCy Schubert wpa_printf(MSG_DEBUG,
543c1d255d3SCy Schubert "TLSv1: Reject server certificate on probe-only run");
544780fb4a2SCy Schubert if (conn->event_cb) {
545780fb4a2SCy Schubert union tls_event_data ev;
546780fb4a2SCy Schubert char buf[128];
547780fb4a2SCy Schubert
548780fb4a2SCy Schubert os_memset(&ev, 0, sizeof(ev));
549780fb4a2SCy Schubert ev.cert_fail.reason = TLS_FAIL_SERVER_CHAIN_PROBE;
550780fb4a2SCy Schubert ev.cert_fail.reason_txt =
551780fb4a2SCy Schubert "Server certificate chain probe";
552780fb4a2SCy Schubert if (chain) {
553780fb4a2SCy Schubert x509_name_string(&chain->subject, buf,
554780fb4a2SCy Schubert sizeof(buf));
555780fb4a2SCy Schubert ev.cert_fail.subject = buf;
556780fb4a2SCy Schubert }
557780fb4a2SCy Schubert conn->event_cb(conn->cb_ctx, TLS_CERT_CHAIN_FAILURE,
558780fb4a2SCy Schubert &ev);
559780fb4a2SCy Schubert }
560780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
561780fb4a2SCy Schubert TLS_ALERT_BAD_CERTIFICATE);
562780fb4a2SCy Schubert x509_certificate_chain_free(chain);
563780fb4a2SCy Schubert return -1;
564780fb4a2SCy Schubert } else if (conn->cred && conn->cred->ca_cert_verify &&
565780fb4a2SCy Schubert x509_certificate_chain_validate(
566780fb4a2SCy Schubert conn->cred->trusted_certs, chain, &reason,
567780fb4a2SCy Schubert !!(conn->flags & TLS_CONN_DISABLE_TIME_CHECKS))
568f05cddf9SRui Paulo < 0) {
56939beb93cSSam Leffler int tls_reason;
57039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain "
57139beb93cSSam Leffler "validation failed (reason=%d)", reason);
57239beb93cSSam Leffler switch (reason) {
57339beb93cSSam Leffler case X509_VALIDATE_BAD_CERTIFICATE:
57439beb93cSSam Leffler tls_reason = TLS_ALERT_BAD_CERTIFICATE;
575780fb4a2SCy Schubert tls_cert_chain_failure_event(
576780fb4a2SCy Schubert conn, 0, chain, TLS_FAIL_BAD_CERTIFICATE,
577780fb4a2SCy Schubert "bad certificate");
57839beb93cSSam Leffler break;
57939beb93cSSam Leffler case X509_VALIDATE_UNSUPPORTED_CERTIFICATE:
58039beb93cSSam Leffler tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE;
58139beb93cSSam Leffler break;
58239beb93cSSam Leffler case X509_VALIDATE_CERTIFICATE_REVOKED:
58339beb93cSSam Leffler tls_reason = TLS_ALERT_CERTIFICATE_REVOKED;
584780fb4a2SCy Schubert tls_cert_chain_failure_event(
585780fb4a2SCy Schubert conn, 0, chain, TLS_FAIL_REVOKED,
586780fb4a2SCy Schubert "certificate revoked");
58739beb93cSSam Leffler break;
58839beb93cSSam Leffler case X509_VALIDATE_CERTIFICATE_EXPIRED:
58939beb93cSSam Leffler tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED;
590780fb4a2SCy Schubert tls_cert_chain_failure_event(
591780fb4a2SCy Schubert conn, 0, chain, TLS_FAIL_EXPIRED,
592780fb4a2SCy Schubert "certificate has expired or is not yet valid");
59339beb93cSSam Leffler break;
59439beb93cSSam Leffler case X509_VALIDATE_CERTIFICATE_UNKNOWN:
59539beb93cSSam Leffler tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN;
59639beb93cSSam Leffler break;
59739beb93cSSam Leffler case X509_VALIDATE_UNKNOWN_CA:
59839beb93cSSam Leffler tls_reason = TLS_ALERT_UNKNOWN_CA;
599780fb4a2SCy Schubert tls_cert_chain_failure_event(
600780fb4a2SCy Schubert conn, 0, chain, TLS_FAIL_UNTRUSTED,
601780fb4a2SCy Schubert "unknown CA");
60239beb93cSSam Leffler break;
60339beb93cSSam Leffler default:
60439beb93cSSam Leffler tls_reason = TLS_ALERT_BAD_CERTIFICATE;
60539beb93cSSam Leffler break;
60639beb93cSSam Leffler }
60739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason);
60839beb93cSSam Leffler x509_certificate_chain_free(chain);
60939beb93cSSam Leffler return -1;
61039beb93cSSam Leffler }
61139beb93cSSam Leffler
612780fb4a2SCy Schubert if (conn->cred && !conn->cred->server_cert_only && chain &&
613780fb4a2SCy Schubert (chain->extensions_present & X509_EXT_EXT_KEY_USAGE) &&
614780fb4a2SCy Schubert !(chain->ext_key_usage &
615780fb4a2SCy Schubert (X509_EXT_KEY_USAGE_ANY | X509_EXT_KEY_USAGE_SERVER_AUTH))) {
616780fb4a2SCy Schubert tls_cert_chain_failure_event(
617780fb4a2SCy Schubert conn, 0, chain, TLS_FAIL_BAD_CERTIFICATE,
618780fb4a2SCy Schubert "certificate not allowed for server authentication");
619780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
620780fb4a2SCy Schubert TLS_ALERT_BAD_CERTIFICATE);
62139beb93cSSam Leffler x509_certificate_chain_free(chain);
622780fb4a2SCy Schubert return -1;
623780fb4a2SCy Schubert }
624780fb4a2SCy Schubert
625780fb4a2SCy Schubert if (conn->flags & TLS_CONN_REQUEST_OCSP) {
626780fb4a2SCy Schubert x509_certificate_chain_free(conn->server_cert);
627780fb4a2SCy Schubert conn->server_cert = chain;
628780fb4a2SCy Schubert } else {
629780fb4a2SCy Schubert x509_certificate_chain_free(chain);
630780fb4a2SCy Schubert }
63139beb93cSSam Leffler
63239beb93cSSam Leffler *in_len = end - in_data;
63339beb93cSSam Leffler
63439beb93cSSam Leffler conn->state = SERVER_KEY_EXCHANGE;
63539beb93cSSam Leffler
63639beb93cSSam Leffler return 0;
63739beb93cSSam Leffler }
63839beb93cSSam Leffler
63939beb93cSSam Leffler
count_bits(const u8 * val,size_t len)6405b9c547cSRui Paulo static unsigned int count_bits(const u8 *val, size_t len)
64139beb93cSSam Leffler {
6425b9c547cSRui Paulo size_t i;
6435b9c547cSRui Paulo unsigned int bits;
6445b9c547cSRui Paulo u8 tmp;
6455b9c547cSRui Paulo
6465b9c547cSRui Paulo for (i = 0; i < len; i++) {
6475b9c547cSRui Paulo if (val[i])
6485b9c547cSRui Paulo break;
6495b9c547cSRui Paulo }
6505b9c547cSRui Paulo if (i == len)
6515b9c547cSRui Paulo return 0;
6525b9c547cSRui Paulo
6535b9c547cSRui Paulo bits = (len - i - 1) * 8;
6545b9c547cSRui Paulo tmp = val[i];
6555b9c547cSRui Paulo while (tmp) {
6565b9c547cSRui Paulo bits++;
6575b9c547cSRui Paulo tmp >>= 1;
6585b9c547cSRui Paulo }
6595b9c547cSRui Paulo
6605b9c547cSRui Paulo return bits;
6615b9c547cSRui Paulo }
6625b9c547cSRui Paulo
6635b9c547cSRui Paulo
tlsv1_process_diffie_hellman(struct tlsv1_client * conn,const u8 * buf,size_t len,tls_key_exchange key_exchange)6645b9c547cSRui Paulo static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
6655b9c547cSRui Paulo const u8 *buf, size_t len,
6665b9c547cSRui Paulo tls_key_exchange key_exchange)
6675b9c547cSRui Paulo {
6685b9c547cSRui Paulo const u8 *pos, *end, *server_params, *server_params_end;
6695b9c547cSRui Paulo u8 alert;
6705b9c547cSRui Paulo unsigned int bits;
6715b9c547cSRui Paulo u16 val;
67239beb93cSSam Leffler
67339beb93cSSam Leffler tlsv1_client_free_dh(conn);
67439beb93cSSam Leffler
67539beb93cSSam Leffler pos = buf;
67639beb93cSSam Leffler end = buf + len;
67739beb93cSSam Leffler
67839beb93cSSam Leffler if (end - pos < 3)
67939beb93cSSam Leffler goto fail;
6805b9c547cSRui Paulo server_params = pos;
6815b9c547cSRui Paulo val = WPA_GET_BE16(pos);
68239beb93cSSam Leffler pos += 2;
6835b9c547cSRui Paulo if (val == 0 || val > (size_t) (end - pos)) {
6845b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "TLSv1: Invalid dh_p length %u", val);
6855b9c547cSRui Paulo goto fail;
6865b9c547cSRui Paulo }
6875b9c547cSRui Paulo conn->dh_p_len = val;
6885b9c547cSRui Paulo bits = count_bits(pos, conn->dh_p_len);
6895b9c547cSRui Paulo if (bits < 768) {
6905b9c547cSRui Paulo wpa_printf(MSG_INFO, "TLSv1: Reject under 768-bit DH prime (insecure; only %u bits)",
6915b9c547cSRui Paulo bits);
6925b9c547cSRui Paulo wpa_hexdump(MSG_DEBUG, "TLSv1: Rejected DH prime",
6935b9c547cSRui Paulo pos, conn->dh_p_len);
69439beb93cSSam Leffler goto fail;
69539beb93cSSam Leffler }
69685732ac8SCy Schubert conn->dh_p = os_memdup(pos, conn->dh_p_len);
69739beb93cSSam Leffler if (conn->dh_p == NULL)
69839beb93cSSam Leffler goto fail;
69939beb93cSSam Leffler pos += conn->dh_p_len;
70039beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: DH p (prime)",
70139beb93cSSam Leffler conn->dh_p, conn->dh_p_len);
70239beb93cSSam Leffler
70339beb93cSSam Leffler if (end - pos < 3)
70439beb93cSSam Leffler goto fail;
7055b9c547cSRui Paulo val = WPA_GET_BE16(pos);
70639beb93cSSam Leffler pos += 2;
7075b9c547cSRui Paulo if (val == 0 || val > (size_t) (end - pos))
70839beb93cSSam Leffler goto fail;
7095b9c547cSRui Paulo conn->dh_g_len = val;
71085732ac8SCy Schubert conn->dh_g = os_memdup(pos, conn->dh_g_len);
71139beb93cSSam Leffler if (conn->dh_g == NULL)
71239beb93cSSam Leffler goto fail;
71339beb93cSSam Leffler pos += conn->dh_g_len;
71439beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: DH g (generator)",
71539beb93cSSam Leffler conn->dh_g, conn->dh_g_len);
71639beb93cSSam Leffler if (conn->dh_g_len == 1 && conn->dh_g[0] < 2)
71739beb93cSSam Leffler goto fail;
71839beb93cSSam Leffler
71939beb93cSSam Leffler if (end - pos < 3)
72039beb93cSSam Leffler goto fail;
7215b9c547cSRui Paulo val = WPA_GET_BE16(pos);
72239beb93cSSam Leffler pos += 2;
7235b9c547cSRui Paulo if (val == 0 || val > (size_t) (end - pos))
72439beb93cSSam Leffler goto fail;
7255b9c547cSRui Paulo conn->dh_ys_len = val;
72685732ac8SCy Schubert conn->dh_ys = os_memdup(pos, conn->dh_ys_len);
72739beb93cSSam Leffler if (conn->dh_ys == NULL)
72839beb93cSSam Leffler goto fail;
72939beb93cSSam Leffler pos += conn->dh_ys_len;
73039beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)",
73139beb93cSSam Leffler conn->dh_ys, conn->dh_ys_len);
7325b9c547cSRui Paulo server_params_end = pos;
7335b9c547cSRui Paulo
7345b9c547cSRui Paulo if (key_exchange == TLS_KEY_X_DHE_RSA) {
735780fb4a2SCy Schubert u8 hash[64];
7365b9c547cSRui Paulo int hlen;
7375b9c547cSRui Paulo
7385b9c547cSRui Paulo if (conn->rl.tls_version == TLS_VERSION_1_2) {
7395b9c547cSRui Paulo #ifdef CONFIG_TLSV12
7405b9c547cSRui Paulo /*
7415b9c547cSRui Paulo * RFC 5246, 4.7:
7425b9c547cSRui Paulo * TLS v1.2 adds explicit indication of the used
7435b9c547cSRui Paulo * signature and hash algorithms.
7445b9c547cSRui Paulo *
7455b9c547cSRui Paulo * struct {
7465b9c547cSRui Paulo * HashAlgorithm hash;
7475b9c547cSRui Paulo * SignatureAlgorithm signature;
7485b9c547cSRui Paulo * } SignatureAndHashAlgorithm;
7495b9c547cSRui Paulo */
7505b9c547cSRui Paulo if (end - pos < 2)
7515b9c547cSRui Paulo goto fail;
752780fb4a2SCy Schubert if ((pos[0] != TLS_HASH_ALG_SHA256 &&
753780fb4a2SCy Schubert pos[0] != TLS_HASH_ALG_SHA384 &&
754780fb4a2SCy Schubert pos[0] != TLS_HASH_ALG_SHA512) ||
7555b9c547cSRui Paulo pos[1] != TLS_SIGN_ALG_RSA) {
7565b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/signature(%u) algorithm",
7575b9c547cSRui Paulo pos[0], pos[1]);
7585b9c547cSRui Paulo goto fail;
7595b9c547cSRui Paulo }
7605b9c547cSRui Paulo
7615b9c547cSRui Paulo hlen = tlsv12_key_x_server_params_hash(
762780fb4a2SCy Schubert conn->rl.tls_version, pos[0],
763780fb4a2SCy Schubert conn->client_random,
7645b9c547cSRui Paulo conn->server_random, server_params,
7655b9c547cSRui Paulo server_params_end - server_params, hash);
766780fb4a2SCy Schubert pos += 2;
7675b9c547cSRui Paulo #else /* CONFIG_TLSV12 */
7685b9c547cSRui Paulo goto fail;
7695b9c547cSRui Paulo #endif /* CONFIG_TLSV12 */
7705b9c547cSRui Paulo } else {
7715b9c547cSRui Paulo hlen = tls_key_x_server_params_hash(
7725b9c547cSRui Paulo conn->rl.tls_version, conn->client_random,
7735b9c547cSRui Paulo conn->server_random, server_params,
774*a90b9d01SCy Schubert server_params_end - server_params, hash,
775*a90b9d01SCy Schubert sizeof(hash));
7765b9c547cSRui Paulo }
7775b9c547cSRui Paulo
7785b9c547cSRui Paulo if (hlen < 0)
7795b9c547cSRui Paulo goto fail;
7805b9c547cSRui Paulo wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerKeyExchange hash",
7815b9c547cSRui Paulo hash, hlen);
7825b9c547cSRui Paulo
7835b9c547cSRui Paulo if (tls_verify_signature(conn->rl.tls_version,
7845b9c547cSRui Paulo conn->server_rsa_key,
7855b9c547cSRui Paulo hash, hlen, pos, end - pos,
7865b9c547cSRui Paulo &alert) < 0)
7875b9c547cSRui Paulo goto fail;
7885b9c547cSRui Paulo }
78939beb93cSSam Leffler
79039beb93cSSam Leffler return 0;
79139beb93cSSam Leffler
79239beb93cSSam Leffler fail:
79339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Processing DH params failed");
79439beb93cSSam Leffler tlsv1_client_free_dh(conn);
79539beb93cSSam Leffler return -1;
79639beb93cSSam Leffler }
79739beb93cSSam Leffler
79839beb93cSSam Leffler
799780fb4a2SCy Schubert static enum tls_ocsp_result
tls_process_certificate_status_ocsp_response(struct tlsv1_client * conn,const u8 * pos,size_t len)800780fb4a2SCy Schubert tls_process_certificate_status_ocsp_response(struct tlsv1_client *conn,
801780fb4a2SCy Schubert const u8 *pos, size_t len)
802780fb4a2SCy Schubert {
803780fb4a2SCy Schubert const u8 *end = pos + len;
804780fb4a2SCy Schubert u32 ocsp_resp_len;
805780fb4a2SCy Schubert
806780fb4a2SCy Schubert /* opaque OCSPResponse<1..2^24-1>; */
807780fb4a2SCy Schubert if (end - pos < 3) {
808780fb4a2SCy Schubert wpa_printf(MSG_INFO, "TLSv1: Too short OCSPResponse");
809780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
810780fb4a2SCy Schubert return TLS_OCSP_INVALID;
811780fb4a2SCy Schubert }
812780fb4a2SCy Schubert ocsp_resp_len = WPA_GET_BE24(pos);
813780fb4a2SCy Schubert pos += 3;
814780fb4a2SCy Schubert if (end - pos < ocsp_resp_len) {
815780fb4a2SCy Schubert wpa_printf(MSG_INFO, "TLSv1: Truncated OCSPResponse");
816780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
817780fb4a2SCy Schubert return TLS_OCSP_INVALID;
818780fb4a2SCy Schubert }
819780fb4a2SCy Schubert
820780fb4a2SCy Schubert return tls_process_ocsp_response(conn, pos, ocsp_resp_len);
821780fb4a2SCy Schubert }
822780fb4a2SCy Schubert
823780fb4a2SCy Schubert
tls_process_certificate_status(struct tlsv1_client * conn,u8 ct,const u8 * in_data,size_t * in_len)824780fb4a2SCy Schubert static int tls_process_certificate_status(struct tlsv1_client *conn, u8 ct,
825780fb4a2SCy Schubert const u8 *in_data, size_t *in_len)
826780fb4a2SCy Schubert {
827780fb4a2SCy Schubert const u8 *pos, *end;
828780fb4a2SCy Schubert size_t left, len;
829780fb4a2SCy Schubert u8 type, status_type;
830780fb4a2SCy Schubert enum tls_ocsp_result res;
831780fb4a2SCy Schubert struct x509_certificate *cert;
832780fb4a2SCy Schubert int depth;
833780fb4a2SCy Schubert
834780fb4a2SCy Schubert if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
835780fb4a2SCy Schubert wpa_printf(MSG_DEBUG,
836780fb4a2SCy Schubert "TLSv1: Expected Handshake; received content type 0x%x",
837780fb4a2SCy Schubert ct);
838780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
839780fb4a2SCy Schubert TLS_ALERT_UNEXPECTED_MESSAGE);
840780fb4a2SCy Schubert return -1;
841780fb4a2SCy Schubert }
842780fb4a2SCy Schubert
843780fb4a2SCy Schubert pos = in_data;
844780fb4a2SCy Schubert left = *in_len;
845780fb4a2SCy Schubert
846780fb4a2SCy Schubert if (left < 4) {
847780fb4a2SCy Schubert wpa_printf(MSG_DEBUG,
848780fb4a2SCy Schubert "TLSv1: Too short CertificateStatus (left=%lu)",
849780fb4a2SCy Schubert (unsigned long) left);
850780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
851780fb4a2SCy Schubert return -1;
852780fb4a2SCy Schubert }
853780fb4a2SCy Schubert
854780fb4a2SCy Schubert type = *pos++;
855780fb4a2SCy Schubert len = WPA_GET_BE24(pos);
856780fb4a2SCy Schubert pos += 3;
857780fb4a2SCy Schubert left -= 4;
858780fb4a2SCy Schubert
859780fb4a2SCy Schubert if (len > left) {
860780fb4a2SCy Schubert wpa_printf(MSG_DEBUG,
861780fb4a2SCy Schubert "TLSv1: Mismatch in CertificateStatus length (len=%lu != left=%lu)",
862780fb4a2SCy Schubert (unsigned long) len, (unsigned long) left);
863780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
864780fb4a2SCy Schubert return -1;
865780fb4a2SCy Schubert }
866780fb4a2SCy Schubert
867780fb4a2SCy Schubert end = pos + len;
868780fb4a2SCy Schubert
869780fb4a2SCy Schubert if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS) {
870780fb4a2SCy Schubert wpa_printf(MSG_DEBUG,
871780fb4a2SCy Schubert "TLSv1: Received unexpected handshake message %d (expected CertificateStatus)",
872780fb4a2SCy Schubert type);
873780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
874780fb4a2SCy Schubert TLS_ALERT_UNEXPECTED_MESSAGE);
875780fb4a2SCy Schubert return -1;
876780fb4a2SCy Schubert }
877780fb4a2SCy Schubert
878780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateStatus");
879780fb4a2SCy Schubert
880780fb4a2SCy Schubert /*
881780fb4a2SCy Schubert * struct {
882780fb4a2SCy Schubert * CertificateStatusType status_type;
883780fb4a2SCy Schubert * select (status_type) {
884780fb4a2SCy Schubert * case ocsp: OCSPResponse;
885780fb4a2SCy Schubert * case ocsp_multi: OCSPResponseList;
886780fb4a2SCy Schubert * } response;
887780fb4a2SCy Schubert * } CertificateStatus;
888780fb4a2SCy Schubert */
889780fb4a2SCy Schubert if (end - pos < 1) {
890780fb4a2SCy Schubert wpa_printf(MSG_INFO, "TLSv1: Too short CertificateStatus");
891780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
892780fb4a2SCy Schubert return -1;
893780fb4a2SCy Schubert }
894780fb4a2SCy Schubert status_type = *pos++;
895780fb4a2SCy Schubert wpa_printf(MSG_DEBUG, "TLSv1: CertificateStatus status_type %u",
896780fb4a2SCy Schubert status_type);
897780fb4a2SCy Schubert
898780fb4a2SCy Schubert if (status_type == 1 /* ocsp */) {
899780fb4a2SCy Schubert res = tls_process_certificate_status_ocsp_response(
900780fb4a2SCy Schubert conn, pos, end - pos);
901780fb4a2SCy Schubert } else if (status_type == 2 /* ocsp_multi */) {
902780fb4a2SCy Schubert int good = 0, revoked = 0;
903780fb4a2SCy Schubert u32 resp_len;
904780fb4a2SCy Schubert
905780fb4a2SCy Schubert res = TLS_OCSP_NO_RESPONSE;
906780fb4a2SCy Schubert
907780fb4a2SCy Schubert /*
908780fb4a2SCy Schubert * opaque OCSPResponse<0..2^24-1>;
909780fb4a2SCy Schubert *
910780fb4a2SCy Schubert * struct {
911780fb4a2SCy Schubert * OCSPResponse ocsp_response_list<1..2^24-1>;
912780fb4a2SCy Schubert * } OCSPResponseList;
913780fb4a2SCy Schubert */
914780fb4a2SCy Schubert if (end - pos < 3) {
915780fb4a2SCy Schubert wpa_printf(MSG_DEBUG,
916780fb4a2SCy Schubert "TLSv1: Truncated OCSPResponseList");
917780fb4a2SCy Schubert res = TLS_OCSP_INVALID;
918780fb4a2SCy Schubert goto done;
919780fb4a2SCy Schubert }
920780fb4a2SCy Schubert resp_len = WPA_GET_BE24(pos);
921780fb4a2SCy Schubert pos += 3;
922780fb4a2SCy Schubert if (end - pos < resp_len) {
923780fb4a2SCy Schubert wpa_printf(MSG_DEBUG,
924780fb4a2SCy Schubert "TLSv1: Truncated OCSPResponseList(len=%u)",
925780fb4a2SCy Schubert resp_len);
926780fb4a2SCy Schubert res = TLS_OCSP_INVALID;
927780fb4a2SCy Schubert goto done;
928780fb4a2SCy Schubert }
929780fb4a2SCy Schubert end = pos + resp_len;
930780fb4a2SCy Schubert
931780fb4a2SCy Schubert while (end - pos >= 3) {
932780fb4a2SCy Schubert resp_len = WPA_GET_BE24(pos);
933780fb4a2SCy Schubert pos += 3;
934780fb4a2SCy Schubert if (resp_len > end - pos) {
935780fb4a2SCy Schubert wpa_printf(MSG_DEBUG,
936780fb4a2SCy Schubert "TLSv1: Truncated OCSPResponse(len=%u; left=%d) in ocsp_multi",
937780fb4a2SCy Schubert resp_len, (int) (end - pos));
938780fb4a2SCy Schubert res = TLS_OCSP_INVALID;
939780fb4a2SCy Schubert break;
940780fb4a2SCy Schubert }
941780fb4a2SCy Schubert if (!resp_len)
942780fb4a2SCy Schubert continue; /* Skip an empty response */
943780fb4a2SCy Schubert res = tls_process_certificate_status_ocsp_response(
944780fb4a2SCy Schubert conn, pos - 3, resp_len + 3);
945780fb4a2SCy Schubert if (res == TLS_OCSP_REVOKED)
946780fb4a2SCy Schubert revoked++;
947780fb4a2SCy Schubert else if (res == TLS_OCSP_GOOD)
948780fb4a2SCy Schubert good++;
949780fb4a2SCy Schubert pos += resp_len;
950780fb4a2SCy Schubert }
951780fb4a2SCy Schubert
952780fb4a2SCy Schubert if (revoked)
953780fb4a2SCy Schubert res = TLS_OCSP_REVOKED;
954780fb4a2SCy Schubert else if (good)
955780fb4a2SCy Schubert res = TLS_OCSP_GOOD;
956780fb4a2SCy Schubert } else {
957780fb4a2SCy Schubert wpa_printf(MSG_DEBUG,
958780fb4a2SCy Schubert "TLSv1: Ignore unsupported CertificateStatus");
959780fb4a2SCy Schubert goto skip;
960780fb4a2SCy Schubert }
961780fb4a2SCy Schubert
962780fb4a2SCy Schubert done:
963780fb4a2SCy Schubert if (res == TLS_OCSP_REVOKED) {
964780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
965780fb4a2SCy Schubert TLS_ALERT_CERTIFICATE_REVOKED);
966780fb4a2SCy Schubert for (cert = conn->server_cert, depth = 0; cert;
967780fb4a2SCy Schubert cert = cert->next, depth++) {
968780fb4a2SCy Schubert if (cert->ocsp_revoked) {
969780fb4a2SCy Schubert tls_cert_chain_failure_event(
970780fb4a2SCy Schubert conn, depth, cert, TLS_FAIL_REVOKED,
971780fb4a2SCy Schubert "certificate revoked");
972780fb4a2SCy Schubert }
973780fb4a2SCy Schubert }
974780fb4a2SCy Schubert return -1;
975780fb4a2SCy Schubert }
976780fb4a2SCy Schubert
977780fb4a2SCy Schubert if (conn->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
978780fb4a2SCy Schubert /*
979780fb4a2SCy Schubert * Verify that each certificate on the chain that is not part
980780fb4a2SCy Schubert * of the trusted certificates has a good status. If not,
981780fb4a2SCy Schubert * terminate handshake.
982780fb4a2SCy Schubert */
983780fb4a2SCy Schubert for (cert = conn->server_cert, depth = 0; cert;
984780fb4a2SCy Schubert cert = cert->next, depth++) {
985780fb4a2SCy Schubert if (!cert->ocsp_good) {
986780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
987780fb4a2SCy Schubert TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
988780fb4a2SCy Schubert tls_cert_chain_failure_event(
989780fb4a2SCy Schubert conn, depth, cert,
990780fb4a2SCy Schubert TLS_FAIL_UNSPECIFIED,
991780fb4a2SCy Schubert "bad certificate status response");
992780fb4a2SCy Schubert return -1;
993780fb4a2SCy Schubert }
994780fb4a2SCy Schubert if (cert->issuer_trusted)
995780fb4a2SCy Schubert break;
996780fb4a2SCy Schubert }
997780fb4a2SCy Schubert }
998780fb4a2SCy Schubert
999780fb4a2SCy Schubert if ((conn->flags & TLS_CONN_REQUIRE_OCSP) && res != TLS_OCSP_GOOD) {
1000780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
1001780fb4a2SCy Schubert res == TLS_OCSP_INVALID ? TLS_ALERT_DECODE_ERROR :
1002780fb4a2SCy Schubert TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
1003780fb4a2SCy Schubert if (conn->server_cert)
1004780fb4a2SCy Schubert tls_cert_chain_failure_event(
1005780fb4a2SCy Schubert conn, 0, conn->server_cert,
1006780fb4a2SCy Schubert TLS_FAIL_UNSPECIFIED,
1007780fb4a2SCy Schubert "bad certificate status response");
1008780fb4a2SCy Schubert return -1;
1009780fb4a2SCy Schubert }
1010780fb4a2SCy Schubert
1011780fb4a2SCy Schubert conn->ocsp_resp_received = 1;
1012780fb4a2SCy Schubert
1013780fb4a2SCy Schubert skip:
1014780fb4a2SCy Schubert *in_len = end - in_data;
1015780fb4a2SCy Schubert
1016780fb4a2SCy Schubert conn->state = SERVER_KEY_EXCHANGE;
1017780fb4a2SCy Schubert
1018780fb4a2SCy Schubert return 0;
1019780fb4a2SCy Schubert }
1020780fb4a2SCy Schubert
1021780fb4a2SCy Schubert
tls_process_server_key_exchange(struct tlsv1_client * conn,u8 ct,const u8 * in_data,size_t * in_len)102239beb93cSSam Leffler static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,
102339beb93cSSam Leffler const u8 *in_data, size_t *in_len)
102439beb93cSSam Leffler {
102539beb93cSSam Leffler const u8 *pos, *end;
102639beb93cSSam Leffler size_t left, len;
102739beb93cSSam Leffler u8 type;
102839beb93cSSam Leffler const struct tls_cipher_suite *suite;
102939beb93cSSam Leffler
103039beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
103139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
103239beb93cSSam Leffler "received content type 0x%x", ct);
103339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
103439beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE);
103539beb93cSSam Leffler return -1;
103639beb93cSSam Leffler }
103739beb93cSSam Leffler
103839beb93cSSam Leffler pos = in_data;
103939beb93cSSam Leffler left = *in_len;
104039beb93cSSam Leffler
104139beb93cSSam Leffler if (left < 4) {
104239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerKeyExchange "
104339beb93cSSam Leffler "(Left=%lu)", (unsigned long) left);
104439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
104539beb93cSSam Leffler return -1;
104639beb93cSSam Leffler }
104739beb93cSSam Leffler
104839beb93cSSam Leffler type = *pos++;
104939beb93cSSam Leffler len = WPA_GET_BE24(pos);
105039beb93cSSam Leffler pos += 3;
105139beb93cSSam Leffler left -= 4;
105239beb93cSSam Leffler
105339beb93cSSam Leffler if (len > left) {
105439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerKeyExchange "
105539beb93cSSam Leffler "length (len=%lu != left=%lu)",
105639beb93cSSam Leffler (unsigned long) len, (unsigned long) left);
105739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
105839beb93cSSam Leffler return -1;
105939beb93cSSam Leffler }
106039beb93cSSam Leffler
106139beb93cSSam Leffler end = pos + len;
106239beb93cSSam Leffler
1063780fb4a2SCy Schubert if ((conn->flags & TLS_CONN_REQUEST_OCSP) &&
1064780fb4a2SCy Schubert type == TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS)
1065780fb4a2SCy Schubert return tls_process_certificate_status(conn, ct, in_data,
1066780fb4a2SCy Schubert in_len);
106739beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST)
106839beb93cSSam Leffler return tls_process_certificate_request(conn, ct, in_data,
106939beb93cSSam Leffler in_len);
107039beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
107139beb93cSSam Leffler return tls_process_server_hello_done(conn, ct, in_data,
107239beb93cSSam Leffler in_len);
107339beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) {
107439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
107539beb93cSSam Leffler "message %d (expected ServerKeyExchange/"
1076780fb4a2SCy Schubert "CertificateRequest/ServerHelloDone%s)", type,
1077780fb4a2SCy Schubert (conn->flags & TLS_CONN_REQUEST_OCSP) ?
1078780fb4a2SCy Schubert "/CertificateStatus" : "");
107939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
108039beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE);
108139beb93cSSam Leffler return -1;
108239beb93cSSam Leffler }
108339beb93cSSam Leffler
108439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received ServerKeyExchange");
108539beb93cSSam Leffler
108639beb93cSSam Leffler if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) {
108739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not allowed "
108839beb93cSSam Leffler "with the selected cipher suite");
108939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
109039beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE);
109139beb93cSSam Leffler return -1;
109239beb93cSSam Leffler }
109339beb93cSSam Leffler
109439beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: ServerKeyExchange", pos, len);
109539beb93cSSam Leffler suite = tls_get_cipher_suite(conn->rl.cipher_suite);
10965b9c547cSRui Paulo if (suite && (suite->key_exchange == TLS_KEY_X_DH_anon ||
10975b9c547cSRui Paulo suite->key_exchange == TLS_KEY_X_DHE_RSA)) {
10985b9c547cSRui Paulo if (tlsv1_process_diffie_hellman(conn, pos, len,
10995b9c547cSRui Paulo suite->key_exchange) < 0) {
110039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
110139beb93cSSam Leffler TLS_ALERT_DECODE_ERROR);
110239beb93cSSam Leffler return -1;
110339beb93cSSam Leffler }
110439beb93cSSam Leffler } else {
110539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: UnexpectedServerKeyExchange");
110639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
110739beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE);
110839beb93cSSam Leffler return -1;
110939beb93cSSam Leffler }
111039beb93cSSam Leffler
111139beb93cSSam Leffler *in_len = end - in_data;
111239beb93cSSam Leffler
111339beb93cSSam Leffler conn->state = SERVER_CERTIFICATE_REQUEST;
111439beb93cSSam Leffler
111539beb93cSSam Leffler return 0;
111639beb93cSSam Leffler }
111739beb93cSSam Leffler
111839beb93cSSam Leffler
tls_process_certificate_request(struct tlsv1_client * conn,u8 ct,const u8 * in_data,size_t * in_len)111939beb93cSSam Leffler static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct,
112039beb93cSSam Leffler const u8 *in_data, size_t *in_len)
112139beb93cSSam Leffler {
112239beb93cSSam Leffler const u8 *pos, *end;
112339beb93cSSam Leffler size_t left, len;
112439beb93cSSam Leffler u8 type;
112539beb93cSSam Leffler
112639beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
112739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
112839beb93cSSam Leffler "received content type 0x%x", ct);
112939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
113039beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE);
113139beb93cSSam Leffler return -1;
113239beb93cSSam Leffler }
113339beb93cSSam Leffler
113439beb93cSSam Leffler pos = in_data;
113539beb93cSSam Leffler left = *in_len;
113639beb93cSSam Leffler
113739beb93cSSam Leffler if (left < 4) {
113839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateRequest "
113939beb93cSSam Leffler "(left=%lu)", (unsigned long) left);
114039beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
114139beb93cSSam Leffler return -1;
114239beb93cSSam Leffler }
114339beb93cSSam Leffler
114439beb93cSSam Leffler type = *pos++;
114539beb93cSSam Leffler len = WPA_GET_BE24(pos);
114639beb93cSSam Leffler pos += 3;
114739beb93cSSam Leffler left -= 4;
114839beb93cSSam Leffler
114939beb93cSSam Leffler if (len > left) {
115039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in CertificateRequest "
115139beb93cSSam Leffler "length (len=%lu != left=%lu)",
115239beb93cSSam Leffler (unsigned long) len, (unsigned long) left);
115339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
115439beb93cSSam Leffler return -1;
115539beb93cSSam Leffler }
115639beb93cSSam Leffler
115739beb93cSSam Leffler end = pos + len;
115839beb93cSSam Leffler
115939beb93cSSam Leffler if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE)
116039beb93cSSam Leffler return tls_process_server_hello_done(conn, ct, in_data,
116139beb93cSSam Leffler in_len);
116239beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) {
116339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
116439beb93cSSam Leffler "message %d (expected CertificateRequest/"
116539beb93cSSam Leffler "ServerHelloDone)", type);
116639beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
116739beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE);
116839beb93cSSam Leffler return -1;
116939beb93cSSam Leffler }
117039beb93cSSam Leffler
117139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateRequest");
117239beb93cSSam Leffler
117339beb93cSSam Leffler conn->certificate_requested = 1;
117439beb93cSSam Leffler
117539beb93cSSam Leffler *in_len = end - in_data;
117639beb93cSSam Leffler
117739beb93cSSam Leffler conn->state = SERVER_HELLO_DONE;
117839beb93cSSam Leffler
117939beb93cSSam Leffler return 0;
118039beb93cSSam Leffler }
118139beb93cSSam Leffler
118239beb93cSSam Leffler
tls_process_server_hello_done(struct tlsv1_client * conn,u8 ct,const u8 * in_data,size_t * in_len)118339beb93cSSam Leffler static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct,
118439beb93cSSam Leffler const u8 *in_data, size_t *in_len)
118539beb93cSSam Leffler {
118639beb93cSSam Leffler const u8 *pos, *end;
118739beb93cSSam Leffler size_t left, len;
118839beb93cSSam Leffler u8 type;
118939beb93cSSam Leffler
119039beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
119139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
119239beb93cSSam Leffler "received content type 0x%x", ct);
119339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
119439beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE);
119539beb93cSSam Leffler return -1;
119639beb93cSSam Leffler }
119739beb93cSSam Leffler
119839beb93cSSam Leffler pos = in_data;
119939beb93cSSam Leffler left = *in_len;
120039beb93cSSam Leffler
120139beb93cSSam Leffler if (left < 4) {
120239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerHelloDone "
120339beb93cSSam Leffler "(left=%lu)", (unsigned long) left);
120439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
120539beb93cSSam Leffler return -1;
120639beb93cSSam Leffler }
120739beb93cSSam Leffler
120839beb93cSSam Leffler type = *pos++;
120939beb93cSSam Leffler len = WPA_GET_BE24(pos);
121039beb93cSSam Leffler pos += 3;
121139beb93cSSam Leffler left -= 4;
121239beb93cSSam Leffler
121339beb93cSSam Leffler if (len > left) {
121439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerHelloDone "
121539beb93cSSam Leffler "length (len=%lu != left=%lu)",
121639beb93cSSam Leffler (unsigned long) len, (unsigned long) left);
121739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
121839beb93cSSam Leffler return -1;
121939beb93cSSam Leffler }
122039beb93cSSam Leffler end = pos + len;
122139beb93cSSam Leffler
122239beb93cSSam Leffler if (type != TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) {
122339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
122439beb93cSSam Leffler "message %d (expected ServerHelloDone)", type);
122539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
122639beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE);
122739beb93cSSam Leffler return -1;
122839beb93cSSam Leffler }
122939beb93cSSam Leffler
123039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHelloDone");
123139beb93cSSam Leffler
1232780fb4a2SCy Schubert if ((conn->flags & TLS_CONN_REQUIRE_OCSP) &&
1233780fb4a2SCy Schubert !conn->ocsp_resp_received) {
1234780fb4a2SCy Schubert wpa_printf(MSG_INFO,
1235780fb4a2SCy Schubert "TLSv1: No OCSP response received - reject handshake");
1236780fb4a2SCy Schubert tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
1237780fb4a2SCy Schubert TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
1238780fb4a2SCy Schubert return -1;
1239780fb4a2SCy Schubert }
1240780fb4a2SCy Schubert
124139beb93cSSam Leffler *in_len = end - in_data;
124239beb93cSSam Leffler
124339beb93cSSam Leffler conn->state = CLIENT_KEY_EXCHANGE;
124439beb93cSSam Leffler
124539beb93cSSam Leffler return 0;
124639beb93cSSam Leffler }
124739beb93cSSam Leffler
124839beb93cSSam Leffler
tls_process_server_change_cipher_spec(struct tlsv1_client * conn,u8 ct,const u8 * in_data,size_t * in_len)124939beb93cSSam Leffler static int tls_process_server_change_cipher_spec(struct tlsv1_client *conn,
125039beb93cSSam Leffler u8 ct, const u8 *in_data,
125139beb93cSSam Leffler size_t *in_len)
125239beb93cSSam Leffler {
125339beb93cSSam Leffler const u8 *pos;
125439beb93cSSam Leffler size_t left;
125539beb93cSSam Leffler
125639beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
125739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
125839beb93cSSam Leffler "received content type 0x%x", ct);
125939beb93cSSam Leffler if (conn->use_session_ticket) {
126039beb93cSSam Leffler int res;
126139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Server may have "
126239beb93cSSam Leffler "rejected SessionTicket");
126339beb93cSSam Leffler conn->use_session_ticket = 0;
126439beb93cSSam Leffler
126539beb93cSSam Leffler /* Notify upper layers that SessionTicket failed */
126639beb93cSSam Leffler res = conn->session_ticket_cb(
126739beb93cSSam Leffler conn->session_ticket_cb_ctx, NULL, 0, NULL,
126839beb93cSSam Leffler NULL, NULL);
126939beb93cSSam Leffler if (res < 0) {
127039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket "
127139beb93cSSam Leffler "callback indicated failure");
127239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
127339beb93cSSam Leffler TLS_ALERT_HANDSHAKE_FAILURE);
127439beb93cSSam Leffler return -1;
127539beb93cSSam Leffler }
127639beb93cSSam Leffler
127739beb93cSSam Leffler conn->state = SERVER_CERTIFICATE;
127839beb93cSSam Leffler return tls_process_certificate(conn, ct, in_data,
127939beb93cSSam Leffler in_len);
128039beb93cSSam Leffler }
128139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
128239beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE);
128339beb93cSSam Leffler return -1;
128439beb93cSSam Leffler }
128539beb93cSSam Leffler
128639beb93cSSam Leffler pos = in_data;
128739beb93cSSam Leffler left = *in_len;
128839beb93cSSam Leffler
128939beb93cSSam Leffler if (left < 1) {
129039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec");
129139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
129239beb93cSSam Leffler return -1;
129339beb93cSSam Leffler }
129439beb93cSSam Leffler
129539beb93cSSam Leffler if (*pos != TLS_CHANGE_CIPHER_SPEC) {
129639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; "
129739beb93cSSam Leffler "received data 0x%x", *pos);
129839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
129939beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE);
130039beb93cSSam Leffler return -1;
130139beb93cSSam Leffler }
130239beb93cSSam Leffler
130339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec");
130439beb93cSSam Leffler if (tlsv1_record_change_read_cipher(&conn->rl) < 0) {
130539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher "
130639beb93cSSam Leffler "for record layer");
130739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
130839beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR);
130939beb93cSSam Leffler return -1;
131039beb93cSSam Leffler }
131139beb93cSSam Leffler
131239beb93cSSam Leffler *in_len = pos + 1 - in_data;
131339beb93cSSam Leffler
131439beb93cSSam Leffler conn->state = SERVER_FINISHED;
131539beb93cSSam Leffler
131639beb93cSSam Leffler return 0;
131739beb93cSSam Leffler }
131839beb93cSSam Leffler
131939beb93cSSam Leffler
tls_process_server_finished(struct tlsv1_client * conn,u8 ct,const u8 * in_data,size_t * in_len)132039beb93cSSam Leffler static int tls_process_server_finished(struct tlsv1_client *conn, u8 ct,
132139beb93cSSam Leffler const u8 *in_data, size_t *in_len)
132239beb93cSSam Leffler {
132339beb93cSSam Leffler const u8 *pos, *end;
132439beb93cSSam Leffler size_t left, len, hlen;
132539beb93cSSam Leffler u8 verify_data[TLS_VERIFY_DATA_LEN];
132639beb93cSSam Leffler u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
132739beb93cSSam Leffler
132839beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
132939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; "
133039beb93cSSam Leffler "received content type 0x%x", ct);
133139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
133239beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE);
133339beb93cSSam Leffler return -1;
133439beb93cSSam Leffler }
133539beb93cSSam Leffler
133639beb93cSSam Leffler pos = in_data;
133739beb93cSSam Leffler left = *in_len;
133839beb93cSSam Leffler
133939beb93cSSam Leffler if (left < 4) {
134039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for "
134139beb93cSSam Leffler "Finished",
134239beb93cSSam Leffler (unsigned long) left);
134339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
134439beb93cSSam Leffler TLS_ALERT_DECODE_ERROR);
134539beb93cSSam Leffler return -1;
134639beb93cSSam Leffler }
134739beb93cSSam Leffler
134839beb93cSSam Leffler if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) {
134939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received "
135039beb93cSSam Leffler "type 0x%x", pos[0]);
135139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
135239beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE);
135339beb93cSSam Leffler return -1;
135439beb93cSSam Leffler }
135539beb93cSSam Leffler
135639beb93cSSam Leffler len = WPA_GET_BE24(pos + 1);
135739beb93cSSam Leffler
135839beb93cSSam Leffler pos += 4;
135939beb93cSSam Leffler left -= 4;
136039beb93cSSam Leffler
136139beb93cSSam Leffler if (len > left) {
136239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished "
136339beb93cSSam Leffler "(len=%lu > left=%lu)",
136439beb93cSSam Leffler (unsigned long) len, (unsigned long) left);
136539beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
136639beb93cSSam Leffler TLS_ALERT_DECODE_ERROR);
136739beb93cSSam Leffler return -1;
136839beb93cSSam Leffler }
136939beb93cSSam Leffler end = pos + len;
137039beb93cSSam Leffler if (len != TLS_VERIFY_DATA_LEN) {
137139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length "
137239beb93cSSam Leffler "in Finished: %lu (expected %d)",
137339beb93cSSam Leffler (unsigned long) len, TLS_VERIFY_DATA_LEN);
137439beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
137539beb93cSSam Leffler TLS_ALERT_DECODE_ERROR);
137639beb93cSSam Leffler return -1;
137739beb93cSSam Leffler }
137839beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished",
137939beb93cSSam Leffler pos, TLS_VERIFY_DATA_LEN);
138039beb93cSSam Leffler
1381f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
1382f05cddf9SRui Paulo if (conn->rl.tls_version >= TLS_VERSION_1_2) {
1383f05cddf9SRui Paulo hlen = SHA256_MAC_LEN;
1384f05cddf9SRui Paulo if (conn->verify.sha256_server == NULL ||
1385f05cddf9SRui Paulo crypto_hash_finish(conn->verify.sha256_server, hash, &hlen)
1386f05cddf9SRui Paulo < 0) {
1387f05cddf9SRui Paulo tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
1388f05cddf9SRui Paulo TLS_ALERT_INTERNAL_ERROR);
1389f05cddf9SRui Paulo conn->verify.sha256_server = NULL;
1390f05cddf9SRui Paulo return -1;
1391f05cddf9SRui Paulo }
1392f05cddf9SRui Paulo conn->verify.sha256_server = NULL;
1393f05cddf9SRui Paulo } else {
1394f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
1395f05cddf9SRui Paulo
139639beb93cSSam Leffler hlen = MD5_MAC_LEN;
139739beb93cSSam Leffler if (conn->verify.md5_server == NULL ||
139839beb93cSSam Leffler crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) {
139939beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
140039beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR);
140139beb93cSSam Leffler conn->verify.md5_server = NULL;
140239beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_server, NULL, NULL);
140339beb93cSSam Leffler conn->verify.sha1_server = NULL;
140439beb93cSSam Leffler return -1;
140539beb93cSSam Leffler }
140639beb93cSSam Leffler conn->verify.md5_server = NULL;
140739beb93cSSam Leffler hlen = SHA1_MAC_LEN;
140839beb93cSSam Leffler if (conn->verify.sha1_server == NULL ||
140939beb93cSSam Leffler crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN,
141039beb93cSSam Leffler &hlen) < 0) {
141139beb93cSSam Leffler conn->verify.sha1_server = NULL;
141239beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
141339beb93cSSam Leffler TLS_ALERT_INTERNAL_ERROR);
141439beb93cSSam Leffler return -1;
141539beb93cSSam Leffler }
141639beb93cSSam Leffler conn->verify.sha1_server = NULL;
1417f05cddf9SRui Paulo hlen = MD5_MAC_LEN + SHA1_MAC_LEN;
141839beb93cSSam Leffler
1419f05cddf9SRui Paulo #ifdef CONFIG_TLSV12
1420f05cddf9SRui Paulo }
1421f05cddf9SRui Paulo #endif /* CONFIG_TLSV12 */
1422f05cddf9SRui Paulo
1423f05cddf9SRui Paulo if (tls_prf(conn->rl.tls_version,
1424f05cddf9SRui Paulo conn->master_secret, TLS_MASTER_SECRET_LEN,
1425f05cddf9SRui Paulo "server finished", hash, hlen,
142639beb93cSSam Leffler verify_data, TLS_VERIFY_DATA_LEN)) {
142739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data");
142839beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
142939beb93cSSam Leffler TLS_ALERT_DECRYPT_ERROR);
143039beb93cSSam Leffler return -1;
143139beb93cSSam Leffler }
143239beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)",
143339beb93cSSam Leffler verify_data, TLS_VERIFY_DATA_LEN);
143439beb93cSSam Leffler
14355b9c547cSRui Paulo if (os_memcmp_const(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) {
143639beb93cSSam Leffler wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data");
14375b9c547cSRui Paulo tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
14385b9c547cSRui Paulo TLS_ALERT_DECRYPT_ERROR);
143939beb93cSSam Leffler return -1;
144039beb93cSSam Leffler }
144139beb93cSSam Leffler
144239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received Finished");
144339beb93cSSam Leffler
144439beb93cSSam Leffler *in_len = end - in_data;
144539beb93cSSam Leffler
144639beb93cSSam Leffler conn->state = (conn->session_resumed || conn->use_session_ticket) ?
144739beb93cSSam Leffler CHANGE_CIPHER_SPEC : ACK_FINISHED;
144839beb93cSSam Leffler
144939beb93cSSam Leffler return 0;
145039beb93cSSam Leffler }
145139beb93cSSam Leffler
145239beb93cSSam Leffler
tls_process_application_data(struct tlsv1_client * conn,u8 ct,const u8 * in_data,size_t * in_len,u8 ** out_data,size_t * out_len)145339beb93cSSam Leffler static int tls_process_application_data(struct tlsv1_client *conn, u8 ct,
145439beb93cSSam Leffler const u8 *in_data, size_t *in_len,
145539beb93cSSam Leffler u8 **out_data, size_t *out_len)
145639beb93cSSam Leffler {
145739beb93cSSam Leffler const u8 *pos;
145839beb93cSSam Leffler size_t left;
145939beb93cSSam Leffler
146039beb93cSSam Leffler if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) {
146139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Expected Application Data; "
146239beb93cSSam Leffler "received content type 0x%x", ct);
146339beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
146439beb93cSSam Leffler TLS_ALERT_UNEXPECTED_MESSAGE);
146539beb93cSSam Leffler return -1;
146639beb93cSSam Leffler }
146739beb93cSSam Leffler
146839beb93cSSam Leffler pos = in_data;
146939beb93cSSam Leffler left = *in_len;
147039beb93cSSam Leffler
147139beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TLSv1: Application Data included in Handshake",
147239beb93cSSam Leffler pos, left);
147339beb93cSSam Leffler
147439beb93cSSam Leffler *out_data = os_malloc(left);
147539beb93cSSam Leffler if (*out_data) {
147639beb93cSSam Leffler os_memcpy(*out_data, pos, left);
147739beb93cSSam Leffler *out_len = left;
147839beb93cSSam Leffler }
147939beb93cSSam Leffler
148039beb93cSSam Leffler return 0;
148139beb93cSSam Leffler }
148239beb93cSSam Leffler
148339beb93cSSam Leffler
tlsv1_client_process_handshake(struct tlsv1_client * conn,u8 ct,const u8 * buf,size_t * len,u8 ** out_data,size_t * out_len)148439beb93cSSam Leffler int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct,
148539beb93cSSam Leffler const u8 *buf, size_t *len,
148639beb93cSSam Leffler u8 **out_data, size_t *out_len)
148739beb93cSSam Leffler {
148839beb93cSSam Leffler if (ct == TLS_CONTENT_TYPE_ALERT) {
148939beb93cSSam Leffler if (*len < 2) {
149039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow");
149139beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
149239beb93cSSam Leffler TLS_ALERT_DECODE_ERROR);
149339beb93cSSam Leffler return -1;
149439beb93cSSam Leffler }
149539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d",
149639beb93cSSam Leffler buf[0], buf[1]);
149739beb93cSSam Leffler *len = 2;
149839beb93cSSam Leffler conn->state = FAILED;
149939beb93cSSam Leffler return -1;
150039beb93cSSam Leffler }
150139beb93cSSam Leffler
150239beb93cSSam Leffler if (ct == TLS_CONTENT_TYPE_HANDSHAKE && *len >= 4 &&
150339beb93cSSam Leffler buf[0] == TLS_HANDSHAKE_TYPE_HELLO_REQUEST) {
150439beb93cSSam Leffler size_t hr_len = WPA_GET_BE24(buf + 1);
150539beb93cSSam Leffler if (hr_len > *len - 4) {
150639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: HelloRequest underflow");
150739beb93cSSam Leffler tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
150839beb93cSSam Leffler TLS_ALERT_DECODE_ERROR);
150939beb93cSSam Leffler return -1;
151039beb93cSSam Leffler }
151139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Ignored HelloRequest");
151239beb93cSSam Leffler *len = 4 + hr_len;
151339beb93cSSam Leffler return 0;
151439beb93cSSam Leffler }
151539beb93cSSam Leffler
151639beb93cSSam Leffler switch (conn->state) {
151739beb93cSSam Leffler case SERVER_HELLO:
151839beb93cSSam Leffler if (tls_process_server_hello(conn, ct, buf, len))
151939beb93cSSam Leffler return -1;
152039beb93cSSam Leffler break;
152139beb93cSSam Leffler case SERVER_CERTIFICATE:
152239beb93cSSam Leffler if (tls_process_certificate(conn, ct, buf, len))
152339beb93cSSam Leffler return -1;
152439beb93cSSam Leffler break;
152539beb93cSSam Leffler case SERVER_KEY_EXCHANGE:
152639beb93cSSam Leffler if (tls_process_server_key_exchange(conn, ct, buf, len))
152739beb93cSSam Leffler return -1;
152839beb93cSSam Leffler break;
152939beb93cSSam Leffler case SERVER_CERTIFICATE_REQUEST:
153039beb93cSSam Leffler if (tls_process_certificate_request(conn, ct, buf, len))
153139beb93cSSam Leffler return -1;
153239beb93cSSam Leffler break;
153339beb93cSSam Leffler case SERVER_HELLO_DONE:
153439beb93cSSam Leffler if (tls_process_server_hello_done(conn, ct, buf, len))
153539beb93cSSam Leffler return -1;
153639beb93cSSam Leffler break;
153739beb93cSSam Leffler case SERVER_CHANGE_CIPHER_SPEC:
153839beb93cSSam Leffler if (tls_process_server_change_cipher_spec(conn, ct, buf, len))
153939beb93cSSam Leffler return -1;
154039beb93cSSam Leffler break;
154139beb93cSSam Leffler case SERVER_FINISHED:
154239beb93cSSam Leffler if (tls_process_server_finished(conn, ct, buf, len))
154339beb93cSSam Leffler return -1;
154439beb93cSSam Leffler break;
154539beb93cSSam Leffler case ACK_FINISHED:
154639beb93cSSam Leffler if (out_data &&
154739beb93cSSam Leffler tls_process_application_data(conn, ct, buf, len, out_data,
154839beb93cSSam Leffler out_len))
154939beb93cSSam Leffler return -1;
155039beb93cSSam Leffler break;
155139beb93cSSam Leffler default:
155239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d "
155339beb93cSSam Leffler "while processing received message",
155439beb93cSSam Leffler conn->state);
155539beb93cSSam Leffler return -1;
155639beb93cSSam Leffler }
155739beb93cSSam Leffler
155839beb93cSSam Leffler if (ct == TLS_CONTENT_TYPE_HANDSHAKE)
155939beb93cSSam Leffler tls_verify_hash_add(&conn->verify, buf, *len);
156039beb93cSSam Leffler
156139beb93cSSam Leffler return 0;
156239beb93cSSam Leffler }
1563