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

« back to all changes in this revision

Viewing changes to eap_tls_common.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
 
 * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions
3
 
 * Copyright (c) 2004-2006, 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 "eap_i.h"
19
 
#include "eap_tls_common.h"
20
 
#include "config_ssid.h"
21
 
#include "md5.h"
22
 
#include "sha1.h"
23
 
#include "tls.h"
24
 
#include "config.h"
25
 
 
26
 
 
27
 
static int eap_tls_check_blob(struct eap_sm *sm, const char **name,
28
 
                              const u8 **data, size_t *data_len)
29
 
{
30
 
        const struct wpa_config_blob *blob;
31
 
 
32
 
        if (*name == NULL || os_strncmp(*name, "blob://", 7) != 0)
33
 
                return 0;
34
 
 
35
 
        blob = eap_get_config_blob(sm, *name + 7);
36
 
        if (blob == NULL) {
37
 
                wpa_printf(MSG_ERROR, "%s: Named configuration blob '%s' not "
38
 
                           "found", __func__, *name + 7);
39
 
                return -1;
40
 
        }
41
 
 
42
 
        *name = NULL;
43
 
        *data = blob->data;
44
 
        *data_len = blob->len;
45
 
 
46
 
        return 0;
47
 
}
48
 
 
49
 
 
50
 
static void eap_tls_params_from_conf1(struct tls_connection_params *params,
51
 
                                      struct wpa_ssid *config)
52
 
{
53
 
        params->ca_cert = (char *) config->ca_cert;
54
 
        params->ca_path = (char *) config->ca_path;
55
 
        params->client_cert = (char *) config->client_cert;
56
 
        params->private_key = (char *) config->private_key;
57
 
        params->private_key_passwd = (char *) config->private_key_passwd;
58
 
        params->dh_file = (char *) config->dh_file;
59
 
        params->subject_match = (char *) config->subject_match;
60
 
        params->altsubject_match = (char *) config->altsubject_match;
61
 
        params->engine_id = config->engine_id;
62
 
        params->pin = config->pin;
63
 
        params->key_id = config->key_id;
64
 
}
65
 
 
66
 
 
67
 
static void eap_tls_params_from_conf2(struct tls_connection_params *params,
68
 
                                      struct wpa_ssid *config)
69
 
{
70
 
        params->ca_cert = (char *) config->ca_cert2;
71
 
        params->ca_path = (char *) config->ca_path2;
72
 
        params->client_cert = (char *) config->client_cert2;
73
 
        params->private_key = (char *) config->private_key2;
74
 
        params->private_key_passwd = (char *) config->private_key2_passwd;
75
 
        params->dh_file = (char *) config->dh_file2;
76
 
        params->subject_match = (char *) config->subject_match2;
77
 
        params->altsubject_match = (char *) config->altsubject_match2;
78
 
}
79
 
 
80
 
 
81
 
static int eap_tls_params_from_conf(struct eap_sm *sm,
82
 
                                    struct eap_ssl_data *data,
83
 
                                    struct tls_connection_params *params,
84
 
                                    struct wpa_ssid *config, int phase2)
85
 
{
86
 
        os_memset(params, 0, sizeof(*params));
87
 
        params->engine = config->engine;
88
 
        if (phase2)
89
 
                eap_tls_params_from_conf2(params, config);
90
 
        else
91
 
                eap_tls_params_from_conf1(params, config);
92
 
        params->tls_ia = data->tls_ia;
93
 
 
94
 
 
95
 
        if (eap_tls_check_blob(sm, &params->ca_cert, &params->ca_cert_blob,
96
 
                               &params->ca_cert_blob_len) ||
97
 
            eap_tls_check_blob(sm, &params->client_cert,
98
 
                               &params->client_cert_blob,
99
 
                               &params->client_cert_blob_len) ||
100
 
            eap_tls_check_blob(sm, &params->private_key,
101
 
                               &params->private_key_blob,
102
 
                               &params->private_key_blob_len) ||
103
 
            eap_tls_check_blob(sm, &params->dh_file, &params->dh_blob,
104
 
                               &params->dh_blob_len)) {
105
 
                wpa_printf(MSG_INFO, "SSL: Failed to get configuration blobs");
106
 
                return -1;
107
 
        }
108
 
 
109
 
        return 0;
110
 
}
111
 
 
112
 
 
113
 
static int eap_tls_init_connection(struct eap_sm *sm,
114
 
                                   struct eap_ssl_data *data,
115
 
                                   struct wpa_ssid *config,
116
 
                                   struct tls_connection_params *params)
117
 
{
118
 
        int res;
119
 
 
120
 
        data->conn = tls_connection_init(sm->ssl_ctx);
121
 
        if (data->conn == NULL) {
122
 
                wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS "
123
 
                           "connection");
124
 
                return -1;
125
 
        }
126
 
 
127
 
        res = tls_connection_set_params(sm->ssl_ctx, data->conn, params);
128
 
        if (res == TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED) {
129
 
                /* At this point with the pkcs11 engine the PIN might be wrong.
130
 
                 * We reset the PIN in the configuration to be sure to not use
131
 
                 * it again and the calling function must request a new one */
132
 
                os_free(config->pin);
133
 
                config->pin = NULL;
134
 
        } else if (res == TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED) {
135
 
                wpa_printf(MSG_INFO, "TLS: Failed to load private key");
136
 
                /* We don't know exactly but maybe the PIN was wrong,
137
 
                 * so ask for a new one. */
138
 
                os_free(config->pin);
139
 
                config->pin = NULL;
140
 
                eap_sm_request_pin(sm);
141
 
                sm->ignore = TRUE;
142
 
                return -1;
143
 
        } else if (res) {
144
 
                wpa_printf(MSG_INFO, "TLS: Failed to set TLS connection "
145
 
                           "parameters");
146
 
                return -1;
147
 
        }
148
 
 
149
 
        return 0;
150
 
}
151
 
 
152
 
 
153
 
/**
154
 
 * eap_tls_ssl_init - Initialize shared TLS functionality
155
 
 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
156
 
 * @data: Data for TLS processing
157
 
 * @config: Pointer to the network configuration
158
 
 * Returns: 0 on success, -1 on failure
159
 
 *
160
 
 * This function is used to initialize shared TLS functionality for EAP-TLS,
161
 
 * EAP-PEAP, EAP-TTLS, and EAP-FAST.
162
 
 */
163
 
int eap_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
164
 
                     struct wpa_ssid *config)
165
 
{
166
 
        int ret = -1;
167
 
        struct tls_connection_params params;
168
 
 
169
 
        if (config == NULL)
170
 
                return -1;
171
 
 
172
 
        data->eap = sm;
173
 
        data->phase2 = sm->init_phase2;
174
 
        if (eap_tls_params_from_conf(sm, data, &params, config, data->phase2) <
175
 
            0)
176
 
                goto done;
177
 
 
178
 
        if (eap_tls_init_connection(sm, data, config, &params) < 0)
179
 
                goto done;
180
 
 
181
 
        data->tls_out_limit = config->fragment_size;
182
 
        if (data->phase2) {
183
 
                /* Limit the fragment size in the inner TLS authentication
184
 
                 * since the outer authentication with EAP-PEAP does not yet
185
 
                 * support fragmentation */
186
 
                if (data->tls_out_limit > 100)
187
 
                        data->tls_out_limit -= 100;
188
 
        }
189
 
 
190
 
        if (config->phase1 &&
191
 
            os_strstr(config->phase1, "include_tls_length=1")) {
192
 
                wpa_printf(MSG_DEBUG, "TLS: Include TLS Message Length in "
193
 
                           "unfragmented packets");
194
 
                data->include_tls_length = 1;
195
 
        }
196
 
 
197
 
        ret = 0;
198
 
 
199
 
done:
200
 
        return ret;
201
 
}
202
 
 
203
 
 
204
 
/**
205
 
 * eap_tls_ssl_deinit - Deinitialize shared TLS functionality
206
 
 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
207
 
 * @data: Data for TLS processing
208
 
 *
209
 
 * This function deinitializes shared TLS functionality that was initialized
210
 
 * with eap_tls_ssl_init().
211
 
 */
212
 
void eap_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
213
 
{
214
 
        tls_connection_deinit(sm->ssl_ctx, data->conn);
215
 
        os_free(data->tls_in);
216
 
        os_free(data->tls_out);
217
 
}
218
 
 
219
 
 
220
 
/**
221
 
 * eap_tls_derive_key - Derive a key based on TLS session data
222
 
 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
223
 
 * @data: Data for TLS processing
224
 
 * @label: Label string for deriving the keys, e.g., "client EAP encryption"
225
 
 * @len: Length of the key material to generate (usually 64 for MSK)
226
 
 * Returns: Pointer to allocated key on success or %NULL on failure
227
 
 *
228
 
 * This function uses TLS-PRF to generate pseudo-random data based on the TLS
229
 
 * session data (client/server random and master key). Each key type may use a
230
 
 * different label to bind the key usage into the generated material.
231
 
 *
232
 
 * The caller is responsible for freeing the returned buffer.
233
 
 */
234
 
u8 * eap_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
235
 
                        const char *label, size_t len)
236
 
{
237
 
        struct tls_keys keys;
238
 
        u8 *rnd = NULL, *out;
239
 
 
240
 
        out = os_malloc(len);
241
 
        if (out == NULL)
242
 
                return NULL;
243
 
 
244
 
        /* First, try to use TLS library function for PRF, if available. */
245
 
        if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) ==
246
 
            0)
247
 
                return out;
248
 
 
249
 
        /*
250
 
         * TLS library did not support key generation, so get the needed TLS
251
 
         * session parameters and use an internal implementation of TLS PRF to
252
 
         * derive the key.
253
 
         */
254
 
        if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
255
 
                goto fail;
256
 
 
257
 
        if (keys.client_random == NULL || keys.server_random == NULL ||
258
 
            keys.master_key == NULL)
259
 
                goto fail;
260
 
 
261
 
        rnd = os_malloc(keys.client_random_len + keys.server_random_len);
262
 
        if (rnd == NULL)
263
 
                goto fail;
264
 
        os_memcpy(rnd, keys.client_random, keys.client_random_len);
265
 
        os_memcpy(rnd + keys.client_random_len, keys.server_random,
266
 
                  keys.server_random_len);
267
 
 
268
 
        if (tls_prf(keys.master_key, keys.master_key_len,
269
 
                    label, rnd, keys.client_random_len +
270
 
                    keys.server_random_len, out, len))
271
 
                goto fail;
272
 
 
273
 
        os_free(rnd);
274
 
        return out;
275
 
 
276
 
fail:
277
 
        os_free(out);
278
 
        os_free(rnd);
279
 
        return NULL;
280
 
}
281
 
 
282
 
 
283
 
/**
284
 
 * eap_tls_data_reassemble - Reassemble TLS data
285
 
 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
286
 
 * @data: Data for TLS processing
287
 
 * @in_data: Next incoming TLS segment
288
 
 * @in_len: Length of in_data
289
 
 * @out_len: Variable for returning output data length
290
 
 * @need_more_input: Variable for returning whether more input data is needed
291
 
 * to reassemble this TLS packet
292
 
 * Returns: Pointer to output data, %NULL on error or when more data is needed
293
 
 * for the full message (in which case, *need_more_input is also set to 1).
294
 
 *
295
 
 * This function reassembles TLS fragments. Caller must not free the returned
296
 
 * data buffer since an internal pointer to it is maintained.
297
 
 */
298
 
const u8 * eap_tls_data_reassemble(
299
 
        struct eap_sm *sm, struct eap_ssl_data *data, const u8 *in_data,
300
 
        size_t in_len, size_t *out_len, int *need_more_input)
301
 
{
302
 
        u8 *buf;
303
 
 
304
 
        *need_more_input = 0;
305
 
 
306
 
        if (data->tls_in_left > in_len || data->tls_in) {
307
 
                if (data->tls_in_len + in_len == 0) {
308
 
                        os_free(data->tls_in);
309
 
                        data->tls_in = NULL;
310
 
                        data->tls_in_len = 0;
311
 
                        wpa_printf(MSG_WARNING, "SSL: Invalid reassembly "
312
 
                                   "state: tls_in_left=%lu tls_in_len=%lu "
313
 
                                   "in_len=%lu",
314
 
                                   (unsigned long) data->tls_in_left,
315
 
                                   (unsigned long) data->tls_in_len,
316
 
                                   (unsigned long) in_len);
317
 
                        return NULL;
318
 
                }
319
 
                if (data->tls_in_len + in_len > 65536) {
320
 
                        /* Limit length to avoid rogue servers from causing
321
 
                         * large memory allocations. */
322
 
                        os_free(data->tls_in);
323
 
                        data->tls_in = NULL;
324
 
                        data->tls_in_len = 0;
325
 
                        wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size"
326
 
                                   " over 64 kB)");
327
 
                        return NULL;
328
 
                }
329
 
                buf = os_realloc(data->tls_in, data->tls_in_len + in_len);
330
 
                if (buf == NULL) {
331
 
                        os_free(data->tls_in);
332
 
                        data->tls_in = NULL;
333
 
                        data->tls_in_len = 0;
334
 
                        wpa_printf(MSG_INFO, "SSL: Could not allocate memory "
335
 
                                   "for TLS data");
336
 
                        return NULL;
337
 
                }
338
 
                os_memcpy(buf + data->tls_in_len, in_data, in_len);
339
 
                data->tls_in = buf;
340
 
                data->tls_in_len += in_len;
341
 
                if (in_len > data->tls_in_left) {
342
 
                        wpa_printf(MSG_INFO, "SSL: more data than TLS message "
343
 
                                   "length indicated");
344
 
                        data->tls_in_left = 0;
345
 
                        return NULL;
346
 
                }
347
 
                data->tls_in_left -= in_len;
348
 
                if (data->tls_in_left > 0) {
349
 
                        wpa_printf(MSG_DEBUG, "SSL: Need %lu bytes more input "
350
 
                                   "data", (unsigned long) data->tls_in_left);
351
 
                        *need_more_input = 1;
352
 
                        return NULL;
353
 
                }
354
 
        } else {
355
 
                data->tls_in_left = 0;
356
 
                data->tls_in = os_malloc(in_len ? in_len : 1);
357
 
                if (data->tls_in == NULL)
358
 
                        return NULL;
359
 
                os_memcpy(data->tls_in, in_data, in_len);
360
 
                data->tls_in_len = in_len;
361
 
        }
362
 
 
363
 
        *out_len = data->tls_in_len;
364
 
        return data->tls_in;
365
 
}
366
 
 
367
 
 
368
 
static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data,
369
 
                                 const u8 *in_data, size_t in_len,
370
 
                                 u8 **out_data, size_t *out_len)
371
 
{
372
 
        const u8 *msg;
373
 
        size_t msg_len;
374
 
        int need_more_input;
375
 
        u8 *appl_data;
376
 
        size_t appl_data_len;
377
 
 
378
 
        msg = eap_tls_data_reassemble(sm, data, in_data, in_len,
379
 
                                      &msg_len, &need_more_input);
380
 
        if (msg == NULL)
381
 
                return need_more_input ? 1 : -1;
382
 
 
383
 
        /* Full TLS message reassembled - continue handshake processing */
384
 
        if (data->tls_out) {
385
 
                /* This should not happen.. */
386
 
                wpa_printf(MSG_INFO, "SSL: eap_tls_process_helper - pending "
387
 
                           "tls_out data even though tls_out_len = 0");
388
 
                os_free(data->tls_out);
389
 
                WPA_ASSERT(data->tls_out == NULL);
390
 
        }
391
 
        appl_data = NULL;
392
 
        data->tls_out = tls_connection_handshake(sm->ssl_ctx, data->conn,
393
 
                                                 msg, msg_len,
394
 
                                                 &data->tls_out_len,
395
 
                                                 &appl_data, &appl_data_len);
396
 
 
397
 
        /* Clear reassembled input data (if the buffer was needed). */
398
 
        data->tls_in_left = data->tls_in_total = data->tls_in_len = 0;
399
 
        os_free(data->tls_in);
400
 
        data->tls_in = NULL;
401
 
 
402
 
        if (appl_data &&
403
 
            tls_connection_established(sm->ssl_ctx, data->conn) &&
404
 
            !tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
405
 
                wpa_hexdump_key(MSG_MSGDUMP, "SSL: Application data",
406
 
                                appl_data, appl_data_len);
407
 
                *out_data = appl_data;
408
 
                *out_len = appl_data_len;
409
 
                return 2;
410
 
        }
411
 
 
412
 
        os_free(appl_data);
413
 
 
414
 
        return 0;
415
 
}
416
 
 
417
 
 
418
 
static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type,
419
 
                                  int peap_version, u8 id, int ret,
420
 
                                  u8 **out_data, size_t *out_len)
421
 
{
422
 
        size_t len;
423
 
        u8 *pos, *flags;
424
 
        int more_fragments, length_included;
425
 
        
426
 
        wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total "
427
 
                   "%lu bytes)",
428
 
                   (unsigned long) data->tls_out_len - data->tls_out_pos,
429
 
                   (unsigned long) data->tls_out_len);
430
 
 
431
 
        len = data->tls_out_len - data->tls_out_pos;
432
 
        if (len > data->tls_out_limit) {
433
 
                more_fragments = 1;
434
 
                len = data->tls_out_limit;
435
 
                wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments "
436
 
                           "will follow", (unsigned long) len);
437
 
        } else
438
 
                more_fragments = 0;
439
 
 
440
 
        length_included = data->tls_out_pos == 0 &&
441
 
                (data->tls_out_len > data->tls_out_limit ||
442
 
                 data->include_tls_length);
443
 
 
444
 
        *out_data = (u8 *)
445
 
                eap_msg_alloc(EAP_VENDOR_IETF, eap_type, out_len,
446
 
                              1 + length_included * 4 + len, EAP_CODE_RESPONSE,
447
 
                              id, &pos);
448
 
        if (*out_data == NULL)
449
 
                return -1;
450
 
 
451
 
        flags = pos++;
452
 
        *flags = peap_version;
453
 
        if (more_fragments)
454
 
                *flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
455
 
        if (length_included) {
456
 
                *flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
457
 
                WPA_PUT_BE32(pos, data->tls_out_len);
458
 
                pos += 4;
459
 
        }
460
 
 
461
 
        os_memcpy(pos, &data->tls_out[data->tls_out_pos], len);
462
 
        data->tls_out_pos += len;
463
 
 
464
 
        if (!more_fragments) {
465
 
                data->tls_out_len = 0;
466
 
                data->tls_out_pos = 0;
467
 
                os_free(data->tls_out);
468
 
                data->tls_out = NULL;
469
 
        }
470
 
 
471
 
        return ret;
472
 
}
473
 
 
474
 
 
475
 
/**
476
 
 * eap_tls_process_helper - Process TLS handshake message
477
 
 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
478
 
 * @data: Data for TLS processing
479
 
 * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
480
 
 * @peap_version: Version number for EAP-PEAP/TTLS
481
 
 * @id: EAP identifier for the response
482
 
 * @in_data: Message received from the server
483
 
 * @in_len: Length of in_data
484
 
 * @out_data: Buffer for returning a pointer to the response message
485
 
 * @out_len: Buffer for returning the length of the response message
486
 
 * Returns: 0 on success, 1 if more input data is needed, or -1 on failure
487
 
 *
488
 
 * This function can be used to process TLS handshake messages. It reassembles
489
 
 * the received fragments and uses a TLS library to process the messages. The
490
 
 * response data from the TLS library is fragmented to suitable output messages
491
 
 * that the caller can send out.
492
 
 *
493
 
 * out_data is used to return the response message if the return value of this
494
 
 * function is 0 or -1. In case of failure, the message is likely a TLS alarm
495
 
 * message. The caller is responsible for freeing the allocated buffer if
496
 
 * *out_data is not %NULL.
497
 
 */
498
 
int eap_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
499
 
                           EapType eap_type, int peap_version,
500
 
                           u8 id, const u8 *in_data, size_t in_len,
501
 
                           u8 **out_data, size_t *out_len)
502
 
{
503
 
        int ret = 0;
504
 
 
505
 
        WPA_ASSERT(data->tls_out_len == 0 || in_len == 0);
506
 
        *out_len = 0;
507
 
        *out_data = NULL;
508
 
 
509
 
        if (data->tls_out_len == 0) {
510
 
                /* No more data to send out - expect to receive more data from
511
 
                 * the AS. */
512
 
                int res = eap_tls_process_input(sm, data, in_data, in_len,
513
 
                                                out_data, out_len);
514
 
                if (res)
515
 
                        return res;
516
 
        }
517
 
 
518
 
        if (data->tls_out == NULL) {
519
 
                data->tls_out_len = 0;
520
 
                return -1;
521
 
        }
522
 
 
523
 
        if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
524
 
                wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to "
525
 
                           "report error");
526
 
                ret = -1;
527
 
                /* TODO: clean pin if engine used? */
528
 
        }
529
 
 
530
 
        if (data->tls_out_len == 0) {
531
 
                /* TLS negotiation should now be complete since all other cases
532
 
                 * needing more data should have been caught above based on
533
 
                 * the TLS Message Length field. */
534
 
                wpa_printf(MSG_DEBUG, "SSL: No data to be sent out");
535
 
                os_free(data->tls_out);
536
 
                data->tls_out = NULL;
537
 
                return 1;
538
 
        }
539
 
 
540
 
        return eap_tls_process_output(data, eap_type, peap_version, id, ret,
541
 
                                      out_data, out_len);
542
 
}
543
 
 
544
 
 
545
 
/**
546
 
 * eap_tls_build_ack - Build a TLS ACK frames
547
 
 * @data: Data for TLS processing
548
 
 * @respDataLen: Buffer for returning the length of the response message
549
 
 * @id: EAP identifier for the response
550
 
 * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
551
 
 * @peap_version: Version number for EAP-PEAP/TTLS
552
 
 * Returns: Pointer to allocated ACK frames or %NULL on failure
553
 
 */
554
 
u8 * eap_tls_build_ack(struct eap_ssl_data *data, size_t *respDataLen, u8 id,
555
 
                       EapType eap_type, int peap_version)
556
 
{
557
 
        struct eap_hdr *resp;
558
 
        u8 *pos;
559
 
 
560
 
        resp = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, respDataLen,
561
 
                             1, EAP_CODE_RESPONSE, id, &pos);
562
 
        if (resp == NULL)
563
 
                return NULL;
564
 
        wpa_printf(MSG_DEBUG, "SSL: Building ACK");
565
 
        *pos = peap_version; /* Flags */
566
 
        return (u8 *) resp;
567
 
}
568
 
 
569
 
 
570
 
/**
571
 
 * eap_tls_reauth_init - Re-initialize shared TLS for session resumption
572
 
 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
573
 
 * @data: Data for TLS processing
574
 
 * Returns: 0 on success, -1 on failure
575
 
 */
576
 
int eap_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data)
577
 
{
578
 
        os_free(data->tls_in);
579
 
        data->tls_in = NULL;
580
 
        data->tls_in_len = data->tls_in_left = data->tls_in_total = 0;
581
 
        os_free(data->tls_out);
582
 
        data->tls_out = NULL;
583
 
        data->tls_out_len = data->tls_out_pos = 0;
584
 
 
585
 
        return tls_connection_shutdown(sm->ssl_ctx, data->conn);
586
 
}
587
 
 
588
 
 
589
 
/**
590
 
 * eap_tls_status - Get TLS status
591
 
 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
592
 
 * @data: Data for TLS processing
593
 
 * @buf: Buffer for status information
594
 
 * @buflen: Maximum buffer length
595
 
 * @verbose: Whether to include verbose status information
596
 
 * Returns: Number of bytes written to buf.
597
 
 */
598
 
int eap_tls_status(struct eap_sm *sm, struct eap_ssl_data *data, char *buf,
599
 
                   size_t buflen, int verbose)
600
 
{
601
 
        char name[128];
602
 
        int len = 0, ret;
603
 
 
604
 
        if (tls_get_cipher(sm->ssl_ctx, data->conn, name, sizeof(name)) == 0) {
605
 
                ret = os_snprintf(buf + len, buflen - len,
606
 
                                  "EAP TLS cipher=%s\n", name);
607
 
                if (ret < 0 || (size_t) ret >= buflen - len)
608
 
                        return len;
609
 
                len += ret;
610
 
        }
611
 
 
612
 
        return len;
613
 
}
614
 
 
615
 
 
616
 
/**
617
 
 * eap_tls_process_init - Initial validation and processing of EAP requests
618
 
 * @sm: Pointer to EAP state machine allocated with eap_sm_init()
619
 
 * @data: Data for TLS processing
620
 
 * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
621
 
 * @ret: Return values from EAP request validation and processing
622
 
 * @reqData: EAP request to be processed (eapReqData)
623
 
 * @reqDataLen: Length of the EAP request
624
 
 * @len: Buffer for returning length of the remaining payload
625
 
 * @flags: Buffer for returning TLS flags
626
 
 * Returns: Buffer to payload after TLS flags and length or %NULL on failure
627
 
 */
628
 
const u8 * eap_tls_process_init(struct eap_sm *sm, struct eap_ssl_data *data,
629
 
                                EapType eap_type, struct eap_method_ret *ret,
630
 
                                const u8 *reqData, size_t reqDataLen,
631
 
                                size_t *len, u8 *flags)
632
 
{
633
 
        const u8 *pos;
634
 
        size_t left;
635
 
        unsigned int tls_msg_len;
636
 
 
637
 
        if (tls_get_errors(sm->ssl_ctx)) {
638
 
                wpa_printf(MSG_INFO, "SSL: TLS errors detected");
639
 
                ret->ignore = TRUE;
640
 
                return NULL;
641
 
        }
642
 
 
643
 
        pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, reqData, reqDataLen,
644
 
                               &left);
645
 
        if (pos == NULL) {
646
 
                ret->ignore = TRUE;
647
 
                return NULL;
648
 
        }
649
 
        *flags = *pos++;
650
 
        left--;
651
 
        wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - "
652
 
                   "Flags 0x%02x", (unsigned long) reqDataLen, *flags);
653
 
        if (*flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
654
 
                if (left < 4) {
655
 
                        wpa_printf(MSG_INFO, "SSL: Short frame with TLS "
656
 
                                   "length");
657
 
                        ret->ignore = TRUE;
658
 
                        return NULL;
659
 
                }
660
 
                tls_msg_len = WPA_GET_BE32(pos);
661
 
                wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d",
662
 
                           tls_msg_len);
663
 
                if (data->tls_in_left == 0) {
664
 
                        data->tls_in_total = tls_msg_len;
665
 
                        data->tls_in_left = tls_msg_len;
666
 
                        os_free(data->tls_in);
667
 
                        data->tls_in = NULL;
668
 
                        data->tls_in_len = 0;
669
 
                }
670
 
                pos += 4;
671
 
                left -= 4;
672
 
        }
673
 
 
674
 
        ret->ignore = FALSE;
675
 
        ret->methodState = METHOD_MAY_CONT;
676
 
        ret->decision = DECISION_FAIL;
677
 
        ret->allowNotifications = TRUE;
678
 
 
679
 
        *len = (size_t) left;
680
 
        return pos;
681
 
}