~ubuntu-branches/ubuntu/vivid/wpasupplicant/vivid

« back to all changes in this revision

Viewing changes to src/tls/tlsv1_server_write.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2008-03-12 20:03:04 UTC
  • mfrom: (1.1.10 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20080312200304-4331y9wj46pdd34z
Tags: 0.6.3-1
* New upstream release.
* Drop patches applied upstream:
  - debian/patches/30_wpa_gui_qt4_eventhistoryui_rework.patch
  - debian/patches/31_wpa_gui_qt4_eventhistory_always_scrollbar.patch
  - debian/patches/32_wpa_gui_qt4_eventhistory_scroll_with_events.patch
  - debian/patches/40_dbus_ssid_data.patch
* Tidy up the clean target of debian/rules. Now that the madwifi headers are
  handled differently we no longer need to do any cleanup.
* Fix formatting error in debian/ifupdown/wpa_action.8 to make lintian
  quieter.
* Add patch to fix formatting errors in manpages build from sgml source. Use
  <emphasis> tags to hightlight keywords instead of surrounding them in
  strong quotes.
  - debian/patches/41_manpage_format_fixes.patch
* wpasupplicant binary package no longer suggests pcscd, guessnet, iproute
  or wireless-tools, nor does it recommend dhcp3-client. These are not
  needed.
* Add debian/patches/10_silence_siocsiwauth_icotl_failure.patch to disable
  ioctl failure messages that occur under normal conditions.
* Cherry pick two upstream git commits concerning the dbus interface:
  - debian/patches/11_avoid_dbus_version_namespace.patch
  - debian/patches/12_fix_potential_use_after_free.patch
* Add debian/patches/42_manpage_explain_available_drivers.patch to explain
  that not all of the driver backends are available in the provided
  wpa_supplicant binary, and that the canonical list of supported driver
  backends can be retrieved from the wpa_supplicant -h (help) output.
  (Closes: #466910)
* Add debian/patches/20_wpa_gui_qt4_disable_link_prl.patch to remove
  link_prl CONFIG compile flag added by qmake-qt4 >= 4.3.4-2 to avoid excess
  linking.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * TLSv1 server - write handshake message
 
3
 * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License version 2 as
 
7
 * published by the Free Software Foundation.
 
8
 *
 
9
 * Alternatively, this software may be distributed under the terms of BSD
 
10
 * license.
 
11
 *
 
12
 * See README and COPYING for more details.
 
13
 */
 
14
 
 
15
#include "includes.h"
 
16
 
 
17
#include "common.h"
 
18
#include "md5.h"
 
19
#include "sha1.h"
 
20
#include "x509v3.h"
 
21
#include "tls.h"
 
22
#include "tlsv1_common.h"
 
23
#include "tlsv1_record.h"
 
24
#include "tlsv1_server.h"
 
25
#include "tlsv1_server_i.h"
 
26
 
 
27
 
 
28
static size_t tls_server_cert_chain_der_len(struct tlsv1_server *conn)
 
29
{
 
30
        size_t len = 0;
 
31
        struct x509_certificate *cert;
 
32
 
 
33
        cert = conn->cred->cert;
 
34
        while (cert) {
 
35
                len += 3 + cert->cert_len;
 
36
                if (x509_certificate_self_signed(cert))
 
37
                        break;
 
38
                cert = x509_certificate_get_subject(conn->cred->trusted_certs,
 
39
                                                    &cert->issuer);
 
40
        }
 
41
 
 
42
        return len;
 
43
}
 
44
 
 
45
 
 
46
static int tls_write_server_hello(struct tlsv1_server *conn,
 
47
                                  u8 **msgpos, u8 *end)
 
48
{
 
49
        u8 *pos, *rhdr, *hs_start, *hs_length;
 
50
        struct os_time now;
 
51
        size_t rlen;
 
52
 
 
53
        pos = *msgpos;
 
54
 
 
55
        wpa_printf(MSG_DEBUG, "TLSv1: Send ServerHello");
 
56
        rhdr = pos;
 
57
        pos += TLS_RECORD_HEADER_LEN;
 
58
 
 
59
        os_get_time(&now);
 
60
        WPA_PUT_BE32(conn->server_random, now.sec);
 
61
        if (os_get_random(conn->server_random + 4, TLS_RANDOM_LEN - 4)) {
 
62
                wpa_printf(MSG_ERROR, "TLSv1: Could not generate "
 
63
                           "server_random");
 
64
                return -1;
 
65
        }
 
66
        wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random",
 
67
                    conn->server_random, TLS_RANDOM_LEN);
 
68
 
 
69
        conn->session_id_len = TLS_SESSION_ID_MAX_LEN;
 
70
        if (os_get_random(conn->session_id, conn->session_id_len)) {
 
71
                wpa_printf(MSG_ERROR, "TLSv1: Could not generate "
 
72
                           "session_id");
 
73
                return -1;
 
74
        }
 
75
        wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id",
 
76
                    conn->session_id, conn->session_id_len);
 
77
 
 
78
        /* opaque fragment[TLSPlaintext.length] */
 
79
 
 
80
        /* Handshake */
 
81
        hs_start = pos;
 
82
        /* HandshakeType msg_type */
 
83
        *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO;
 
84
        /* uint24 length (to be filled) */
 
85
        hs_length = pos;
 
86
        pos += 3;
 
87
        /* body - ServerHello */
 
88
        /* ProtocolVersion server_version */
 
89
        WPA_PUT_BE16(pos, TLS_VERSION);
 
90
        pos += 2;
 
91
        /* Random random: uint32 gmt_unix_time, opaque random_bytes */
 
92
        os_memcpy(pos, conn->server_random, TLS_RANDOM_LEN);
 
93
        pos += TLS_RANDOM_LEN;
 
94
        /* SessionID session_id */
 
95
        *pos++ = conn->session_id_len;
 
96
        os_memcpy(pos, conn->session_id, conn->session_id_len);
 
97
        pos += conn->session_id_len;
 
98
        /* CipherSuite cipher_suite */
 
99
        WPA_PUT_BE16(pos, conn->cipher_suite);
 
100
        pos += 2;
 
101
        /* CompressionMethod compression_method */
 
102
        *pos++ = TLS_COMPRESSION_NULL;
 
103
 
 
104
        if (conn->session_ticket && conn->session_ticket_cb) {
 
105
                int res = conn->session_ticket_cb(
 
106
                        conn->session_ticket_cb_ctx,
 
107
                        conn->session_ticket, conn->session_ticket_len,
 
108
                        conn->client_random, conn->server_random,
 
109
                        conn->master_secret);
 
110
                if (res < 0) {
 
111
                        wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback "
 
112
                                   "indicated failure");
 
113
                        tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
114
                                           TLS_ALERT_HANDSHAKE_FAILURE);
 
115
                        return -1;
 
116
                }
 
117
                conn->use_session_ticket = res;
 
118
 
 
119
                if (conn->use_session_ticket) {
 
120
                        if (tlsv1_server_derive_keys(conn, NULL, 0) < 0) {
 
121
                                wpa_printf(MSG_DEBUG, "TLSv1: Failed to "
 
122
                                           "derive keys");
 
123
                                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
124
                                                   TLS_ALERT_INTERNAL_ERROR);
 
125
                                return -1;
 
126
                        }
 
127
                }
 
128
 
 
129
                /*
 
130
                 * RFC 4507 specifies that server would include an empty
 
131
                 * SessionTicket extension in ServerHello and a
 
132
                 * NewSessionTicket message after the ServerHello. However,
 
133
                 * EAP-FAST (RFC 4851), i.e., the only user of SessionTicket
 
134
                 * extension at the moment, does not use such extensions.
 
135
                 *
 
136
                 * TODO: Add support for configuring RFC 4507 behavior and make
 
137
                 * EAP-FAST disable it.
 
138
                 */
 
139
        }
 
140
 
 
141
        WPA_PUT_BE24(hs_length, pos - hs_length - 3);
 
142
        tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
 
143
 
 
144
        if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
 
145
                              rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
 
146
                wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record");
 
147
                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
148
                                   TLS_ALERT_INTERNAL_ERROR);
 
149
                return -1;
 
150
        }
 
151
        pos = rhdr + rlen;
 
152
 
 
153
        *msgpos = pos;
 
154
 
 
155
        return 0;
 
156
}
 
157
 
 
158
 
 
159
static int tls_write_server_certificate(struct tlsv1_server *conn,
 
160
                                        u8 **msgpos, u8 *end)
 
161
{
 
162
        u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start;
 
163
        size_t rlen;
 
164
        struct x509_certificate *cert;
 
165
        const struct tls_cipher_suite *suite;
 
166
 
 
167
        suite = tls_get_cipher_suite(conn->rl.cipher_suite);
 
168
        if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) {
 
169
                wpa_printf(MSG_DEBUG, "TLSv1: Do not send Certificate when "
 
170
                           "using anonymous DH");
 
171
                return 0;
 
172
        }
 
173
 
 
174
        pos = *msgpos;
 
175
 
 
176
        wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate");
 
177
        rhdr = pos;
 
178
        pos += TLS_RECORD_HEADER_LEN;
 
179
 
 
180
        /* opaque fragment[TLSPlaintext.length] */
 
181
 
 
182
        /* Handshake */
 
183
        hs_start = pos;
 
184
        /* HandshakeType msg_type */
 
185
        *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE;
 
186
        /* uint24 length (to be filled) */
 
187
        hs_length = pos;
 
188
        pos += 3;
 
189
        /* body - Certificate */
 
190
        /* uint24 length (to be filled) */
 
191
        cert_start = pos;
 
192
        pos += 3;
 
193
        cert = conn->cred->cert;
 
194
        while (cert) {
 
195
                if (pos + 3 + cert->cert_len > end) {
 
196
                        wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space "
 
197
                                   "for Certificate (cert_len=%lu left=%lu)",
 
198
                                   (unsigned long) cert->cert_len,
 
199
                                   (unsigned long) (end - pos));
 
200
                        tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
201
                                           TLS_ALERT_INTERNAL_ERROR);
 
202
                        return -1;
 
203
                }
 
204
                WPA_PUT_BE24(pos, cert->cert_len);
 
205
                pos += 3;
 
206
                os_memcpy(pos, cert->cert_start, cert->cert_len);
 
207
                pos += cert->cert_len;
 
208
 
 
209
                if (x509_certificate_self_signed(cert))
 
210
                        break;
 
211
                cert = x509_certificate_get_subject(conn->cred->trusted_certs,
 
212
                                                    &cert->issuer);
 
213
        }
 
214
        if (cert == conn->cred->cert || cert == NULL) {
 
215
                /*
 
216
                 * Server was not configured with all the needed certificates
 
217
                 * to form a full certificate chain. The client may fail to
 
218
                 * validate the chain unless it is configured with all the
 
219
                 * missing CA certificates.
 
220
                 */
 
221
                wpa_printf(MSG_DEBUG, "TLSv1: Full server certificate chain "
 
222
                           "not configured - validation may fail");
 
223
        }
 
224
        WPA_PUT_BE24(cert_start, pos - cert_start - 3);
 
225
 
 
226
        WPA_PUT_BE24(hs_length, pos - hs_length - 3);
 
227
 
 
228
        if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
 
229
                              rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
 
230
                wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
 
231
                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
232
                                   TLS_ALERT_INTERNAL_ERROR);
 
233
                return -1;
 
234
        }
 
235
        pos = rhdr + rlen;
 
236
 
 
237
        tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
 
238
 
 
239
        *msgpos = pos;
 
240
 
 
241
        return 0;
 
242
}
 
243
 
 
244
 
 
245
static int tls_write_server_key_exchange(struct tlsv1_server *conn,
 
246
                                         u8 **msgpos, u8 *end)
 
247
{
 
248
        tls_key_exchange keyx;
 
249
        const struct tls_cipher_suite *suite;
 
250
#ifdef EAP_FAST
 
251
        u8 *pos, *rhdr, *hs_start, *hs_length;
 
252
        size_t rlen;
 
253
        u8 *dh_ys;
 
254
        size_t dh_ys_len;
 
255
#endif /* EAP_FAST */
 
256
 
 
257
        suite = tls_get_cipher_suite(conn->rl.cipher_suite);
 
258
        if (suite == NULL)
 
259
                keyx = TLS_KEY_X_NULL;
 
260
        else
 
261
                keyx = suite->key_exchange;
 
262
 
 
263
        if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) {
 
264
                wpa_printf(MSG_DEBUG, "TLSv1: No ServerKeyExchange needed");
 
265
                return 0;
 
266
        }
 
267
 
 
268
        if (keyx != TLS_KEY_X_DH_anon) {
 
269
                /* TODO? */
 
270
                wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not yet "
 
271
                           "supported with key exchange type %d", keyx);
 
272
                return -1;
 
273
        }
 
274
 
 
275
#ifdef EAP_FAST
 
276
        if (conn->cred == NULL || conn->cred->dh_p == NULL ||
 
277
            conn->cred->dh_g == NULL) {
 
278
                wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available for "
 
279
                           "ServerKeyExhcange");
 
280
                return -1;
 
281
        }
 
282
 
 
283
        os_free(conn->dh_secret);
 
284
        conn->dh_secret_len = conn->cred->dh_p_len;
 
285
        conn->dh_secret = os_malloc(conn->dh_secret_len);
 
286
        if (conn->dh_secret == NULL) {
 
287
                wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate "
 
288
                           "memory for secret (Diffie-Hellman)");
 
289
                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
290
                                   TLS_ALERT_INTERNAL_ERROR);
 
291
                return -1;
 
292
        }
 
293
        if (os_get_random(conn->dh_secret, conn->dh_secret_len)) {
 
294
                wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random "
 
295
                           "data for Diffie-Hellman");
 
296
                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
297
                                   TLS_ALERT_INTERNAL_ERROR);
 
298
                os_free(conn->dh_secret);
 
299
                conn->dh_secret = NULL;
 
300
                return -1;
 
301
        }
 
302
 
 
303
        if (os_memcmp(conn->dh_secret, conn->cred->dh_p, conn->dh_secret_len) >
 
304
            0)
 
305
                conn->dh_secret[0] = 0; /* make sure secret < p */
 
306
 
 
307
        pos = conn->dh_secret;
 
308
        while (pos + 1 < conn->dh_secret + conn->dh_secret_len && *pos == 0)
 
309
                pos++;
 
310
        if (pos != conn->dh_secret) {
 
311
                os_memmove(conn->dh_secret, pos,
 
312
                           conn->dh_secret_len - (pos - conn->dh_secret));
 
313
                conn->dh_secret_len -= pos - conn->dh_secret;
 
314
        }
 
315
        wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH server's secret value",
 
316
                        conn->dh_secret, conn->dh_secret_len);
 
317
 
 
318
        /* Ys = g^secret mod p */
 
319
        dh_ys_len = conn->cred->dh_p_len;
 
320
        dh_ys = os_malloc(dh_ys_len);
 
321
        if (dh_ys == NULL) {
 
322
                wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate memory for "
 
323
                           "Diffie-Hellman");
 
324
                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
325
                                   TLS_ALERT_INTERNAL_ERROR);
 
326
                return -1;
 
327
        }
 
328
        if (crypto_mod_exp(conn->cred->dh_g, conn->cred->dh_g_len,
 
329
                           conn->dh_secret, conn->dh_secret_len,
 
330
                           conn->cred->dh_p, conn->cred->dh_p_len,
 
331
                           dh_ys, &dh_ys_len)) {
 
332
                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
333
                                   TLS_ALERT_INTERNAL_ERROR);
 
334
                os_free(dh_ys);
 
335
                return -1;
 
336
        }
 
337
 
 
338
        wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)",
 
339
                    dh_ys, dh_ys_len);
 
340
 
 
341
        /*
 
342
         * struct {
 
343
         *    select (KeyExchangeAlgorithm) {
 
344
         *       case diffie_hellman:
 
345
         *          ServerDHParams params;
 
346
         *          Signature signed_params;
 
347
         *       case rsa:
 
348
         *          ServerRSAParams params;
 
349
         *          Signature signed_params;
 
350
         *    };
 
351
         * } ServerKeyExchange;
 
352
         *
 
353
         * struct {
 
354
         *    opaque dh_p<1..2^16-1>;
 
355
         *    opaque dh_g<1..2^16-1>;
 
356
         *    opaque dh_Ys<1..2^16-1>;
 
357
         * } ServerDHParams;
 
358
         */
 
359
 
 
360
        pos = *msgpos;
 
361
 
 
362
        wpa_printf(MSG_DEBUG, "TLSv1: Send ServerKeyExchange");
 
363
        rhdr = pos;
 
364
        pos += TLS_RECORD_HEADER_LEN;
 
365
 
 
366
        /* opaque fragment[TLSPlaintext.length] */
 
367
 
 
368
        /* Handshake */
 
369
        hs_start = pos;
 
370
        /* HandshakeType msg_type */
 
371
        *pos++ = TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE;
 
372
        /* uint24 length (to be filled) */
 
373
        hs_length = pos;
 
374
        pos += 3;
 
375
 
 
376
        /* body - ServerDHParams */
 
377
        /* dh_p */
 
378
        if (pos + 2 + conn->cred->dh_p_len > end) {
 
379
                wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
 
380
                           "dh_p");
 
381
                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
382
                                   TLS_ALERT_INTERNAL_ERROR);
 
383
                os_free(dh_ys);
 
384
                return -1;
 
385
        }
 
386
        WPA_PUT_BE16(pos, conn->cred->dh_p_len);
 
387
        pos += 2;
 
388
        os_memcpy(pos, conn->cred->dh_p, conn->cred->dh_p_len);
 
389
        pos += conn->cred->dh_p_len;
 
390
 
 
391
        /* dh_g */
 
392
        if (pos + 2 + conn->cred->dh_g_len > end) {
 
393
                wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
 
394
                           "dh_g");
 
395
                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
396
                                   TLS_ALERT_INTERNAL_ERROR);
 
397
                os_free(dh_ys);
 
398
                return -1;
 
399
        }
 
400
        WPA_PUT_BE16(pos, conn->cred->dh_g_len);
 
401
        pos += 2;
 
402
        os_memcpy(pos, conn->cred->dh_g, conn->cred->dh_g_len);
 
403
        pos += conn->cred->dh_g_len;
 
404
 
 
405
        /* dh_Ys */
 
406
        if (pos + 2 + dh_ys_len > end) {
 
407
                wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
 
408
                           "dh_Ys");
 
409
                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
410
                                   TLS_ALERT_INTERNAL_ERROR);
 
411
                os_free(dh_ys);
 
412
                return -1;
 
413
        }
 
414
        WPA_PUT_BE16(pos, dh_ys_len);
 
415
        pos += 2;
 
416
        os_memcpy(pos, dh_ys, dh_ys_len);
 
417
        pos += dh_ys_len;
 
418
        os_free(dh_ys);
 
419
 
 
420
        WPA_PUT_BE24(hs_length, pos - hs_length - 3);
 
421
 
 
422
        if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
 
423
                              rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
 
424
                wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
 
425
                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
426
                                   TLS_ALERT_INTERNAL_ERROR);
 
427
                return -1;
 
428
        }
 
429
        pos = rhdr + rlen;
 
430
 
 
431
        tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
 
432
 
 
433
        *msgpos = pos;
 
434
 
 
435
        return 0;
 
436
#else /* EAP_FAST */
 
437
        return -1;
 
438
#endif /* EAP_FAST */
 
439
}
 
440
 
 
441
 
 
442
static int tls_write_server_certificate_request(struct tlsv1_server *conn,
 
443
                                                u8 **msgpos, u8 *end)
 
444
{
 
445
        u8 *pos, *rhdr, *hs_start, *hs_length;
 
446
        size_t rlen;
 
447
 
 
448
        if (!conn->verify_peer) {
 
449
                wpa_printf(MSG_DEBUG, "TLSv1: No CertificateRequest needed");
 
450
                return 0;
 
451
        }
 
452
 
 
453
        pos = *msgpos;
 
454
 
 
455
        wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateRequest");
 
456
        rhdr = pos;
 
457
        pos += TLS_RECORD_HEADER_LEN;
 
458
 
 
459
        /* opaque fragment[TLSPlaintext.length] */
 
460
 
 
461
        /* Handshake */
 
462
        hs_start = pos;
 
463
        /* HandshakeType msg_type */
 
464
        *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST;
 
465
        /* uint24 length (to be filled) */
 
466
        hs_length = pos;
 
467
        pos += 3;
 
468
        /* body - CertificateRequest */
 
469
 
 
470
        /*
 
471
         * enum {
 
472
         *   rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),
 
473
         *   (255)
 
474
         * } ClientCertificateType;
 
475
         * ClientCertificateType certificate_types<1..2^8-1>
 
476
         */
 
477
        *pos++ = 1;
 
478
        *pos++ = 1; /* rsa_sign */
 
479
 
 
480
        /*
 
481
         * opaque DistinguishedName<1..2^16-1>
 
482
         * DistinguishedName certificate_authorities<3..2^16-1>
 
483
         */
 
484
        /* TODO: add support for listing DNs for trusted CAs */
 
485
        WPA_PUT_BE16(pos, 0);
 
486
        pos += 2;
 
487
 
 
488
        WPA_PUT_BE24(hs_length, pos - hs_length - 3);
 
489
 
 
490
        if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
 
491
                              rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
 
492
                wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
 
493
                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
494
                                   TLS_ALERT_INTERNAL_ERROR);
 
495
                return -1;
 
496
        }
 
497
        pos = rhdr + rlen;
 
498
 
 
499
        tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
 
500
 
 
501
        *msgpos = pos;
 
502
 
 
503
        return 0;
 
504
}
 
505
 
 
506
 
 
507
static int tls_write_server_hello_done(struct tlsv1_server *conn,
 
508
                                       u8 **msgpos, u8 *end)
 
509
{
 
510
        u8 *pos, *rhdr, *hs_start, *hs_length;
 
511
        size_t rlen;
 
512
 
 
513
        pos = *msgpos;
 
514
 
 
515
        wpa_printf(MSG_DEBUG, "TLSv1: Send ServerHelloDone");
 
516
        rhdr = pos;
 
517
        pos += TLS_RECORD_HEADER_LEN;
 
518
 
 
519
        /* opaque fragment[TLSPlaintext.length] */
 
520
 
 
521
        /* Handshake */
 
522
        hs_start = pos;
 
523
        /* HandshakeType msg_type */
 
524
        *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE;
 
525
        /* uint24 length (to be filled) */
 
526
        hs_length = pos;
 
527
        pos += 3;
 
528
        /* body - ServerHelloDone (empty) */
 
529
 
 
530
        WPA_PUT_BE24(hs_length, pos - hs_length - 3);
 
531
 
 
532
        if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
 
533
                              rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
 
534
                wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
 
535
                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
536
                                   TLS_ALERT_INTERNAL_ERROR);
 
537
                return -1;
 
538
        }
 
539
        pos = rhdr + rlen;
 
540
 
 
541
        tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
 
542
 
 
543
        *msgpos = pos;
 
544
 
 
545
        return 0;
 
546
}
 
547
 
 
548
 
 
549
static int tls_write_server_change_cipher_spec(struct tlsv1_server *conn,
 
550
                                               u8 **msgpos, u8 *end)
 
551
{
 
552
        u8 *pos, *rhdr;
 
553
        size_t rlen;
 
554
 
 
555
        pos = *msgpos;
 
556
 
 
557
        wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec");
 
558
        rhdr = pos;
 
559
        pos += TLS_RECORD_HEADER_LEN;
 
560
        *pos = TLS_CHANGE_CIPHER_SPEC;
 
561
        if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC,
 
562
                              rhdr, end - rhdr, 1, &rlen) < 0) {
 
563
                wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
 
564
                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
565
                                   TLS_ALERT_INTERNAL_ERROR);
 
566
                return -1;
 
567
        }
 
568
 
 
569
        if (tlsv1_record_change_write_cipher(&conn->rl) < 0) {
 
570
                wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for "
 
571
                           "record layer");
 
572
                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
573
                                   TLS_ALERT_INTERNAL_ERROR);
 
574
                return -1;
 
575
        }
 
576
 
 
577
        *msgpos = rhdr + rlen;
 
578
 
 
579
        return 0;
 
580
}
 
581
 
 
582
 
 
583
static int tls_write_server_finished(struct tlsv1_server *conn,
 
584
                                     u8 **msgpos, u8 *end)
 
585
{
 
586
        u8 *pos, *rhdr, *hs_start, *hs_length;
 
587
        size_t rlen, hlen;
 
588
        u8 verify_data[TLS_VERIFY_DATA_LEN];
 
589
        u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
 
590
 
 
591
        pos = *msgpos;
 
592
 
 
593
        wpa_printf(MSG_DEBUG, "TLSv1: Send Finished");
 
594
 
 
595
        /* Encrypted Handshake Message: Finished */
 
596
 
 
597
        hlen = MD5_MAC_LEN;
 
598
        if (conn->verify.md5_server == NULL ||
 
599
            crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) {
 
600
                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
601
                                   TLS_ALERT_INTERNAL_ERROR);
 
602
                conn->verify.md5_server = NULL;
 
603
                crypto_hash_finish(conn->verify.sha1_server, NULL, NULL);
 
604
                conn->verify.sha1_server = NULL;
 
605
                return -1;
 
606
        }
 
607
        conn->verify.md5_server = NULL;
 
608
        hlen = SHA1_MAC_LEN;
 
609
        if (conn->verify.sha1_server == NULL ||
 
610
            crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN,
 
611
                               &hlen) < 0) {
 
612
                conn->verify.sha1_server = NULL;
 
613
                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
614
                                   TLS_ALERT_INTERNAL_ERROR);
 
615
                return -1;
 
616
        }
 
617
        conn->verify.sha1_server = NULL;
 
618
 
 
619
        if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN,
 
620
                    "server finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN,
 
621
                    verify_data, TLS_VERIFY_DATA_LEN)) {
 
622
                wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data");
 
623
                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
624
                                   TLS_ALERT_INTERNAL_ERROR);
 
625
                return -1;
 
626
        }
 
627
        wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)",
 
628
                        verify_data, TLS_VERIFY_DATA_LEN);
 
629
 
 
630
        rhdr = pos;
 
631
        pos += TLS_RECORD_HEADER_LEN;
 
632
        /* Handshake */
 
633
        hs_start = pos;
 
634
        /* HandshakeType msg_type */
 
635
        *pos++ = TLS_HANDSHAKE_TYPE_FINISHED;
 
636
        /* uint24 length (to be filled) */
 
637
        hs_length = pos;
 
638
        pos += 3;
 
639
        os_memcpy(pos, verify_data, TLS_VERIFY_DATA_LEN);
 
640
        pos += TLS_VERIFY_DATA_LEN;
 
641
        WPA_PUT_BE24(hs_length, pos - hs_length - 3);
 
642
        tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
 
643
 
 
644
        if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
 
645
                              rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
 
646
                wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
 
647
                tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
 
648
                                   TLS_ALERT_INTERNAL_ERROR);
 
649
                return -1;
 
650
        }
 
651
 
 
652
        pos = rhdr + rlen;
 
653
 
 
654
        *msgpos = pos;
 
655
 
 
656
        return 0;
 
657
}
 
658
 
 
659
 
 
660
static u8 * tls_send_server_hello(struct tlsv1_server *conn, size_t *out_len)
 
661
{
 
662
        u8 *msg, *end, *pos;
 
663
        size_t msglen;
 
664
 
 
665
        *out_len = 0;
 
666
 
 
667
        msglen = 1000 + tls_server_cert_chain_der_len(conn);
 
668
 
 
669
        msg = os_malloc(msglen);
 
670
        if (msg == NULL)
 
671
                return NULL;
 
672
 
 
673
        pos = msg;
 
674
        end = msg + msglen;
 
675
 
 
676
        if (tls_write_server_hello(conn, &pos, end) < 0) {
 
677
                os_free(msg);
 
678
                return NULL;
 
679
        }
 
680
 
 
681
        if (conn->use_session_ticket) {
 
682
                /* Abbreviated handshake using session ticket; RFC 4507 */
 
683
                if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 ||
 
684
                    tls_write_server_finished(conn, &pos, end) < 0) {
 
685
                        os_free(msg);
 
686
                        return NULL;
 
687
                }
 
688
 
 
689
                *out_len = pos - msg;
 
690
 
 
691
                conn->state = CHANGE_CIPHER_SPEC;
 
692
 
 
693
                return msg;
 
694
        }
 
695
 
 
696
        /* Full handshake */
 
697
        if (tls_write_server_certificate(conn, &pos, end) < 0 ||
 
698
            tls_write_server_key_exchange(conn, &pos, end) < 0 ||
 
699
            tls_write_server_certificate_request(conn, &pos, end) < 0 ||
 
700
            tls_write_server_hello_done(conn, &pos, end) < 0) {
 
701
                os_free(msg);
 
702
                return NULL;
 
703
        }
 
704
 
 
705
        *out_len = pos - msg;
 
706
 
 
707
        conn->state = CLIENT_CERTIFICATE;
 
708
 
 
709
        return msg;
 
710
}
 
711
 
 
712
 
 
713
static u8 * tls_send_change_cipher_spec(struct tlsv1_server *conn,
 
714
                                        size_t *out_len)
 
715
{
 
716
        u8 *msg, *end, *pos;
 
717
 
 
718
        *out_len = 0;
 
719
 
 
720
        msg = os_malloc(1000);
 
721
        if (msg == NULL)
 
722
                return NULL;
 
723
 
 
724
        pos = msg;
 
725
        end = msg + 1000;
 
726
 
 
727
        if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 ||
 
728
            tls_write_server_finished(conn, &pos, end) < 0) {
 
729
                os_free(msg);
 
730
                return NULL;
 
731
        }
 
732
 
 
733
        *out_len = pos - msg;
 
734
 
 
735
        wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed successfully");
 
736
        conn->state = ESTABLISHED;
 
737
 
 
738
        return msg;
 
739
}
 
740
 
 
741
 
 
742
u8 * tlsv1_server_handshake_write(struct tlsv1_server *conn, size_t *out_len)
 
743
{
 
744
        switch (conn->state) {
 
745
        case SERVER_HELLO:
 
746
                return tls_send_server_hello(conn, out_len);
 
747
        case SERVER_CHANGE_CIPHER_SPEC:
 
748
                return tls_send_change_cipher_spec(conn, out_len);
 
749
        default:
 
750
                if (conn->state == ESTABLISHED && conn->use_session_ticket) {
 
751
                        /* Abbreviated handshake was already completed. */
 
752
                        return NULL;
 
753
                }
 
754
                wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while "
 
755
                           "generating reply", conn->state);
 
756
                return NULL;
 
757
        }
 
758
}
 
759
 
 
760
 
 
761
u8 * tlsv1_server_send_alert(struct tlsv1_server *conn, u8 level,
 
762
                             u8 description, size_t *out_len)
 
763
{
 
764
        u8 *alert, *pos, *length;
 
765
 
 
766
        wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description);
 
767
        *out_len = 0;
 
768
 
 
769
        alert = os_malloc(10);
 
770
        if (alert == NULL)
 
771
                return NULL;
 
772
 
 
773
        pos = alert;
 
774
 
 
775
        /* TLSPlaintext */
 
776
        /* ContentType type */
 
777
        *pos++ = TLS_CONTENT_TYPE_ALERT;
 
778
        /* ProtocolVersion version */
 
779
        WPA_PUT_BE16(pos, TLS_VERSION);
 
780
        pos += 2;
 
781
        /* uint16 length (to be filled) */
 
782
        length = pos;
 
783
        pos += 2;
 
784
        /* opaque fragment[TLSPlaintext.length] */
 
785
 
 
786
        /* Alert */
 
787
        /* AlertLevel level */
 
788
        *pos++ = level;
 
789
        /* AlertDescription description */
 
790
        *pos++ = description;
 
791
 
 
792
        WPA_PUT_BE16(length, pos - length - 2);
 
793
        *out_len = pos - alert;
 
794
 
 
795
        return alert;
 
796
}