~ubuntu-branches/ubuntu/gutsy/wpasupplicant/gutsy

« back to all changes in this revision

Viewing changes to src/eap_peer/eap_tls_common.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler, Alexander Sack
  • Date: 2007-08-26 16:06:57 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20070826160657-2m8pxoweuxe8f93t
Tags: 0.6.0+0.5.8-0ubuntu1
* New upstream release
* remove patch 11_erroneous_manpage_ref, applied upstream
* remove patch 25_wpas_dbus_unregister_iface_fix, applied upstream

[ Alexander Sack ]
* bumping upstream version to replace development version 0.6.0 with
  this package from stable release branch.
* attempt to fix wierd timeout and high latency issues by going
  back to stable upstream version (0.5.9) (LP: #140763,
  LP: #141233).

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 "sha1.h"
22
 
#include "tls.h"
23
 
#include "config.h"
24
 
 
25
 
 
26
 
static int eap_tls_check_blob(struct eap_sm *sm, const char **name,
27
 
                              const u8 **data, size_t *data_len)
28
 
{
29
 
        const struct wpa_config_blob *blob;
30
 
 
31
 
        if (*name == NULL || os_strncmp(*name, "blob://", 7) != 0)
32
 
                return 0;
33
 
 
34
 
        blob = eap_get_config_blob(sm, *name + 7);
35
 
        if (blob == NULL) {
36
 
                wpa_printf(MSG_ERROR, "%s: Named configuration blob '%s' not "
37
 
                           "found", __func__, *name + 7);
38
 
                return -1;
39
 
        }
40
 
 
41
 
        *name = NULL;
42
 
        *data = blob->data;
43
 
        *data_len = blob->len;
44
 
 
45
 
        return 0;
46
 
}
47
 
 
48
 
 
49
 
static void eap_tls_params_from_conf1(struct tls_connection_params *params,
50
 
                                      struct wpa_ssid *config)
51
 
{
52
 
        params->ca_cert = (char *) config->ca_cert;
53
 
        params->ca_path = (char *) config->ca_path;
54
 
        params->client_cert = (char *) config->client_cert;
55
 
        params->private_key = (char *) config->private_key;
56
 
        params->private_key_passwd = (char *) config->private_key_passwd;
57
 
        params->dh_file = (char *) config->dh_file;
58
 
        params->subject_match = (char *) config->subject_match;
59
 
        params->altsubject_match = (char *) config->altsubject_match;
60
 
        params->engine_id = config->engine_id;
61
 
        params->pin = config->pin;
62
 
        params->key_id = config->key_id;
63
 
}
64
 
 
65
 
 
66
 
static void eap_tls_params_from_conf2(struct tls_connection_params *params,
67
 
                                      struct wpa_ssid *config)
68
 
{
69
 
        params->ca_cert = (char *) config->ca_cert2;
70
 
        params->ca_path = (char *) config->ca_path2;
71
 
        params->client_cert = (char *) config->client_cert2;
72
 
        params->private_key = (char *) config->private_key2;
73
 
        params->private_key_passwd = (char *) config->private_key2_passwd;
74
 
        params->dh_file = (char *) config->dh_file2;
75
 
        params->subject_match = (char *) config->subject_match2;
76
 
        params->altsubject_match = (char *) config->altsubject_match2;
77
 
}
78
 
 
79
 
 
80
 
static int eap_tls_params_from_conf(struct eap_sm *sm,
81
 
                                    struct eap_ssl_data *data,
82
 
                                    struct tls_connection_params *params,
83
 
                                    struct wpa_ssid *config, int phase2)
84
 
{
85
 
        os_memset(params, 0, sizeof(*params));
86
 
        params->engine = config->engine;
87
 
        if (phase2)
88
 
                eap_tls_params_from_conf2(params, config);
89
 
        else
90
 
                eap_tls_params_from_conf1(params, config);
91
 
        params->tls_ia = data->tls_ia;
92
 
 
93
 
        /*
94
 
         * Use blob data, if available. Otherwise, leave reference to external
95
 
         * file as-is.
96
 
         */
97
 
        if (eap_tls_check_blob(sm, &params->ca_cert, &params->ca_cert_blob,
98
 
                               &params->ca_cert_blob_len) ||
99
 
            eap_tls_check_blob(sm, &params->client_cert,
100
 
                               &params->client_cert_blob,
101
 
                               &params->client_cert_blob_len) ||
102
 
            eap_tls_check_blob(sm, &params->private_key,
103
 
                               &params->private_key_blob,
104
 
                               &params->private_key_blob_len) ||
105
 
            eap_tls_check_blob(sm, &params->dh_file, &params->dh_blob,
106
 
                               &params->dh_blob_len)) {
107
 
                wpa_printf(MSG_INFO, "SSL: Failed to get configuration blobs");
108
 
                return -1;
109
 
        }
110
 
 
111
 
        return 0;
112
 
}
113
 
 
114
 
 
115
 
static int eap_tls_init_connection(struct eap_sm *sm,
116
 
                                   struct eap_ssl_data *data,
117
 
                                   struct wpa_ssid *config,
118
 
                                   struct tls_connection_params *params)
119
 
{
120
 
        int res;
121
 
 
122
 
        data->conn = tls_connection_init(sm->ssl_ctx);
123
 
        if (data->conn == NULL) {
124
 
                wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS "
125
 
                           "connection");
126
 
                return -1;
127
 
        }
128
 
 
129
 
        res = tls_connection_set_params(sm->ssl_ctx, data->conn, params);
130
 
        if (res == TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED) {
131
 
                /*
132
 
                 * At this point with the pkcs11 engine the PIN might be wrong.
133
 
                 * We reset the PIN in the configuration to be sure to not use
134
 
                 * it again and the calling function must request a new one.
135
 
                 */
136
 
                os_free(config->pin);
137
 
                config->pin = NULL;
138
 
        } else if (res == TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED) {
139
 
                wpa_printf(MSG_INFO, "TLS: Failed to load private key");
140
 
                /*
141
 
                 * We do not know exactly but maybe the PIN was wrong,
142
 
                 * so ask for a new one.
143
 
                 */
144
 
                os_free(config->pin);
145
 
                config->pin = NULL;
146
 
                eap_sm_request_pin(sm);
147
 
                sm->ignore = TRUE;
148
 
                return -1;
149
 
        } else if (res) {
150
 
                wpa_printf(MSG_INFO, "TLS: Failed to set TLS connection "
151
 
                           "parameters");
152
 
                return -1;
153
 
        }
154
 
 
155
 
        return 0;
156
 
}
157
 
 
158
 
 
159
 
/**
160
 
 * eap_peer_tls_ssl_init - Initialize shared TLS functionality
161
 
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
162
 
 * @data: Data for TLS processing
163
 
 * @config: Pointer to the network configuration
164
 
 * Returns: 0 on success, -1 on failure
165
 
 *
166
 
 * This function is used to initialize shared TLS functionality for EAP-TLS,
167
 
 * EAP-PEAP, EAP-TTLS, and EAP-FAST.
168
 
 */
169
 
int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
170
 
                          struct wpa_ssid *config)
171
 
{
172
 
        struct tls_connection_params params;
173
 
 
174
 
        if (config == NULL)
175
 
                return -1;
176
 
 
177
 
        data->eap = sm;
178
 
        data->phase2 = sm->init_phase2;
179
 
        if (eap_tls_params_from_conf(sm, data, &params, config, data->phase2) <
180
 
            0)
181
 
                return -1;
182
 
 
183
 
        if (eap_tls_init_connection(sm, data, config, &params) < 0)
184
 
                return -1;
185
 
 
186
 
        data->tls_out_limit = config->fragment_size;
187
 
        if (data->phase2) {
188
 
                /* Limit the fragment size in the inner TLS authentication
189
 
                 * since the outer authentication with EAP-PEAP does not yet
190
 
                 * support fragmentation */
191
 
                if (data->tls_out_limit > 100)
192
 
                        data->tls_out_limit -= 100;
193
 
        }
194
 
 
195
 
        if (config->phase1 &&
196
 
            os_strstr(config->phase1, "include_tls_length=1")) {
197
 
                wpa_printf(MSG_DEBUG, "TLS: Include TLS Message Length in "
198
 
                           "unfragmented packets");
199
 
                data->include_tls_length = 1;
200
 
        }
201
 
 
202
 
        return 0;
203
 
}
204
 
 
205
 
 
206
 
/**
207
 
 * eap_peer_tls_ssl_deinit - Deinitialize shared TLS functionality
208
 
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
209
 
 * @data: Data for TLS processing
210
 
 *
211
 
 * This function deinitializes shared TLS functionality that was initialized
212
 
 * with eap_peer_tls_ssl_init().
213
 
 */
214
 
void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
215
 
{
216
 
        tls_connection_deinit(sm->ssl_ctx, data->conn);
217
 
        eap_peer_tls_reset_input(data);
218
 
        eap_peer_tls_reset_output(data);
219
 
}
220
 
 
221
 
 
222
 
/**
223
 
 * eap_peer_tls_derive_key - Derive a key based on TLS session data
224
 
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
225
 
 * @data: Data for TLS processing
226
 
 * @label: Label string for deriving the keys, e.g., "client EAP encryption"
227
 
 * @len: Length of the key material to generate (usually 64 for MSK)
228
 
 * Returns: Pointer to allocated key on success or %NULL on failure
229
 
 *
230
 
 * This function uses TLS-PRF to generate pseudo-random data based on the TLS
231
 
 * session data (client/server random and master key). Each key type may use a
232
 
 * different label to bind the key usage into the generated material.
233
 
 *
234
 
 * The caller is responsible for freeing the returned buffer.
235
 
 */
236
 
u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
237
 
                             const char *label, size_t len)
238
 
{
239
 
        struct tls_keys keys;
240
 
        u8 *rnd = NULL, *out;
241
 
 
242
 
        out = os_malloc(len);
243
 
        if (out == NULL)
244
 
                return NULL;
245
 
 
246
 
        /* First, try to use TLS library function for PRF, if available. */
247
 
        if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) ==
248
 
            0)
249
 
                return out;
250
 
 
251
 
        /*
252
 
         * TLS library did not support key generation, so get the needed TLS
253
 
         * session parameters and use an internal implementation of TLS PRF to
254
 
         * derive the key.
255
 
         */
256
 
        if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
257
 
                goto fail;
258
 
 
259
 
        if (keys.client_random == NULL || keys.server_random == NULL ||
260
 
            keys.master_key == NULL)
261
 
                goto fail;
262
 
 
263
 
        rnd = os_malloc(keys.client_random_len + keys.server_random_len);
264
 
        if (rnd == NULL)
265
 
                goto fail;
266
 
        os_memcpy(rnd, keys.client_random, keys.client_random_len);
267
 
        os_memcpy(rnd + keys.client_random_len, keys.server_random,
268
 
                  keys.server_random_len);
269
 
 
270
 
        if (tls_prf(keys.master_key, keys.master_key_len,
271
 
                    label, rnd, keys.client_random_len +
272
 
                    keys.server_random_len, out, len))
273
 
                goto fail;
274
 
 
275
 
        os_free(rnd);
276
 
        return out;
277
 
 
278
 
fail:
279
 
        os_free(out);
280
 
        os_free(rnd);
281
 
        return NULL;
282
 
}
283
 
 
284
 
 
285
 
/**
286
 
 * eap_peer_tls_reassemble_fragment - Reassemble a received fragment
287
 
 * @data: Data for TLS processing
288
 
 * @in_data: Next incoming TLS segment
289
 
 * @in_len: Length of in_data
290
 
 * Returns: 0 on success, 1 if more data is needed for the full message, or
291
 
 * -1 on error
292
 
 */
293
 
static int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data,
294
 
                                            const u8 *in_data, size_t in_len)
295
 
{
296
 
        u8 *buf;
297
 
 
298
 
        if (data->tls_in_len + in_len == 0) {
299
 
                /* No message data received?! */
300
 
                wpa_printf(MSG_WARNING, "SSL: Invalid reassembly state: "
301
 
                           "tls_in_left=%lu tls_in_len=%lu in_len=%lu",
302
 
                           (unsigned long) data->tls_in_left,
303
 
                           (unsigned long) data->tls_in_len,
304
 
                           (unsigned long) in_len);
305
 
                eap_peer_tls_reset_input(data);
306
 
                return -1;
307
 
        }
308
 
 
309
 
        if (data->tls_in_len + in_len > 65536) {
310
 
                /*
311
 
                 * Limit length to avoid rogue servers from causing large
312
 
                 * memory allocations.
313
 
                 */
314
 
                wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size over "
315
 
                           "64 kB)");
316
 
                eap_peer_tls_reset_input(data);
317
 
                return -1;
318
 
        }
319
 
 
320
 
        if (in_len > data->tls_in_left) {
321
 
                /* Sender is doing something odd - reject message */
322
 
                wpa_printf(MSG_INFO, "SSL: more data than TLS message length "
323
 
                           "indicated");
324
 
                eap_peer_tls_reset_input(data);
325
 
                return -1;
326
 
        }
327
 
 
328
 
        buf = os_realloc(data->tls_in, data->tls_in_len + in_len);
329
 
        if (buf == NULL) {
330
 
                wpa_printf(MSG_INFO, "SSL: Could not allocate memory for TLS "
331
 
                           "data");
332
 
                eap_peer_tls_reset_input(data);
333
 
                return -1;
334
 
        }
335
 
        os_memcpy(buf + data->tls_in_len, in_data, in_len);
336
 
        data->tls_in = buf;
337
 
        data->tls_in_len += in_len;
338
 
        data->tls_in_left -= in_len;
339
 
 
340
 
        if (data->tls_in_left > 0) {
341
 
                wpa_printf(MSG_DEBUG, "SSL: Need %lu bytes more input "
342
 
                           "data", (unsigned long) data->tls_in_left);
343
 
                return 1;
344
 
        }
345
 
 
346
 
        return 0;
347
 
}
348
 
 
349
 
 
350
 
/**
351
 
 * eap_peer_tls_data_reassemble - Reassemble TLS data
352
 
 * @data: Data for TLS processing
353
 
 * @in_data: Next incoming TLS segment
354
 
 * @in_len: Length of in_data
355
 
 * @out_len: Variable for returning length of the reassembled message
356
 
 * @need_more_input: Variable for returning whether more input data is needed
357
 
 * to reassemble this TLS packet
358
 
 * Returns: Pointer to output data, %NULL on error or when more data is needed
359
 
 * for the full message (in which case, *need_more_input is also set to 1).
360
 
 *
361
 
 * This function reassembles TLS fragments. Caller must not free the returned
362
 
 * data buffer since an internal pointer to it is maintained.
363
 
 */
364
 
const u8 * eap_peer_tls_data_reassemble(
365
 
        struct eap_ssl_data *data, const u8 *in_data, size_t in_len,
366
 
        size_t *out_len, int *need_more_input)
367
 
{
368
 
        *need_more_input = 0;
369
 
 
370
 
        if (data->tls_in_left > in_len || data->tls_in) {
371
 
                /* Message has fragments */
372
 
                int res = eap_peer_tls_reassemble_fragment(data, in_data,
373
 
                                                           in_len);
374
 
                if (res) {
375
 
                        if (res == 1)
376
 
                                *need_more_input = 1;
377
 
                        return NULL;
378
 
                }
379
 
 
380
 
                /* Message is now fully reassembled. */
381
 
        } else {
382
 
                /* No fragments in this message, so just make a copy of it. */
383
 
                data->tls_in_left = 0;
384
 
                data->tls_in = os_malloc(in_len ? in_len : 1);
385
 
                if (data->tls_in == NULL)
386
 
                        return NULL;
387
 
                os_memcpy(data->tls_in, in_data, in_len);
388
 
                data->tls_in_len = in_len;
389
 
        }
390
 
 
391
 
        *out_len = data->tls_in_len;
392
 
        return data->tls_in;
393
 
}
394
 
 
395
 
 
396
 
/**
397
 
 * eap_tls_process_input - Process incoming TLS message
398
 
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
399
 
 * @data: Data for TLS processing
400
 
 * @in_data: Message received from the server
401
 
 * @in_len: Length of in_data
402
 
 * @out_data: Buffer for returning a pointer to application data (if available)
403
 
 * @out_len: Buffer for returning the length of the application data
404
 
 * Returns: 0 on success, 1 if more input data is needed, 2 if application data
405
 
 * is available, -1 on failure
406
 
 */
407
 
static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data,
408
 
                                 const u8 *in_data, size_t in_len,
409
 
                                 u8 **out_data, size_t *out_len)
410
 
{
411
 
        const u8 *msg;
412
 
        size_t msg_len;
413
 
        int need_more_input;
414
 
        u8 *appl_data;
415
 
        size_t appl_data_len;
416
 
 
417
 
        msg = eap_peer_tls_data_reassemble(data, in_data, in_len,
418
 
                                           &msg_len, &need_more_input);
419
 
        if (msg == NULL)
420
 
                return need_more_input ? 1 : -1;
421
 
 
422
 
        /* Full TLS message reassembled - continue handshake processing */
423
 
        if (data->tls_out) {
424
 
                /* This should not happen.. */
425
 
                wpa_printf(MSG_INFO, "SSL: eap_tls_process_input - pending "
426
 
                           "tls_out data even though tls_out_len = 0");
427
 
                os_free(data->tls_out);
428
 
                WPA_ASSERT(data->tls_out == NULL);
429
 
        }
430
 
        appl_data = NULL;
431
 
        data->tls_out = tls_connection_handshake(sm->ssl_ctx, data->conn,
432
 
                                                 msg, msg_len,
433
 
                                                 &data->tls_out_len,
434
 
                                                 &appl_data, &appl_data_len);
435
 
 
436
 
        eap_peer_tls_reset_input(data);
437
 
 
438
 
        if (appl_data &&
439
 
            tls_connection_established(sm->ssl_ctx, data->conn) &&
440
 
            !tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
441
 
                wpa_hexdump_key(MSG_MSGDUMP, "SSL: Application data",
442
 
                                appl_data, appl_data_len);
443
 
                *out_data = appl_data;
444
 
                *out_len = appl_data_len;
445
 
                return 2;
446
 
        }
447
 
 
448
 
        os_free(appl_data);
449
 
 
450
 
        return 0;
451
 
}
452
 
 
453
 
 
454
 
/**
455
 
 * eap_tls_process_output - Process outgoing TLS message
456
 
 * @data: Data for TLS processing
457
 
 * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
458
 
 * @peap_version: Version number for EAP-PEAP/TTLS
459
 
 * @id: EAP identifier for the response
460
 
 * @ret: Return value to use on success
461
 
 * @out_data: Buffer for returning the allocated output buffer
462
 
 * @out_len: Buffer for returning the length of the output buffer
463
 
 * Returns: ret (0 or 1) on success, -1 on failure
464
 
 */
465
 
static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type,
466
 
                                  int peap_version, u8 id, int ret,
467
 
                                  u8 **out_data, size_t *out_len)
468
 
{
469
 
        size_t len;
470
 
        u8 *pos, *flags;
471
 
        int more_fragments, length_included;
472
 
        
473
 
        len = data->tls_out_len - data->tls_out_pos;
474
 
        wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total "
475
 
                   "%lu bytes)",
476
 
                   (unsigned long) len, (unsigned long) data->tls_out_len);
477
 
 
478
 
        /*
479
 
         * Limit outgoing message to the configured maximum size. Fragment
480
 
         * message if needed.
481
 
         */
482
 
        if (len > data->tls_out_limit) {
483
 
                more_fragments = 1;
484
 
                len = data->tls_out_limit;
485
 
                wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments "
486
 
                           "will follow", (unsigned long) len);
487
 
        } else
488
 
                more_fragments = 0;
489
 
 
490
 
        length_included = data->tls_out_pos == 0 &&
491
 
                (data->tls_out_len > data->tls_out_limit ||
492
 
                 data->include_tls_length);
493
 
 
494
 
        *out_data = (u8 *)
495
 
                eap_msg_alloc(EAP_VENDOR_IETF, eap_type, out_len,
496
 
                              1 + length_included * 4 + len, EAP_CODE_RESPONSE,
497
 
                              id, &pos);
498
 
        if (*out_data == NULL)
499
 
                return -1;
500
 
 
501
 
        flags = pos++;
502
 
        *flags = peap_version;
503
 
        if (more_fragments)
504
 
                *flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
505
 
        if (length_included) {
506
 
                *flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
507
 
                WPA_PUT_BE32(pos, data->tls_out_len);
508
 
                pos += 4;
509
 
        }
510
 
 
511
 
        os_memcpy(pos, &data->tls_out[data->tls_out_pos], len);
512
 
        data->tls_out_pos += len;
513
 
 
514
 
        if (!more_fragments)
515
 
                eap_peer_tls_reset_output(data);
516
 
 
517
 
        return ret;
518
 
}
519
 
 
520
 
 
521
 
/**
522
 
 * eap_peer_tls_process_helper - Process TLS handshake message
523
 
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
524
 
 * @data: Data for TLS processing
525
 
 * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
526
 
 * @peap_version: Version number for EAP-PEAP/TTLS
527
 
 * @id: EAP identifier for the response
528
 
 * @in_data: Message received from the server
529
 
 * @in_len: Length of in_data
530
 
 * @out_data: Buffer for returning a pointer to the response message
531
 
 * @out_len: Buffer for returning the length of the response message
532
 
 * Returns: 0 on success, 1 if more input data is needed, 2 if application data
533
 
 * is available, or -1 on failure
534
 
 *
535
 
 * This function can be used to process TLS handshake messages. It reassembles
536
 
 * the received fragments and uses a TLS library to process the messages. The
537
 
 * response data from the TLS library is fragmented to suitable output messages
538
 
 * that the caller can send out.
539
 
 *
540
 
 * out_data is used to return the response message if the return value of this
541
 
 * function is 0, 2, or -1. In case of failure, the message is likely a TLS
542
 
 * alarm message. The caller is responsible for freeing the allocated buffer if
543
 
 * *out_data is not %NULL.
544
 
 *
545
 
 * This function is called for each received TLS message during the TLS
546
 
 * handshake after eap_peer_tls_process_init() call and possible processing of
547
 
 * TLS Flags field. Once the handshake has been completed, i.e., when
548
 
 * tls_connection_established() returns 1, EAP method specific decrypting of
549
 
 * the tunneled data is used.
550
 
 */
551
 
int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
552
 
                                EapType eap_type, int peap_version,
553
 
                                u8 id, const u8 *in_data, size_t in_len,
554
 
                                u8 **out_data, size_t *out_len)
555
 
{
556
 
        int ret = 0;
557
 
 
558
 
        *out_len = 0;
559
 
        *out_data = NULL;
560
 
 
561
 
        if (data->tls_out_len > 0 && in_len > 0) {
562
 
                wpa_printf(MSG_DEBUG, "SSL: Received non-ACK when output "
563
 
                           "fragments are waiting to be sent out");
564
 
                return -1;
565
 
        }
566
 
 
567
 
        if (data->tls_out_len == 0) {
568
 
                /*
569
 
                 * No more data to send out - expect to receive more data from
570
 
                 * the AS.
571
 
                 */
572
 
                int res = eap_tls_process_input(sm, data, in_data, in_len,
573
 
                                                out_data, out_len);
574
 
                if (res) {
575
 
                        /*
576
 
                         * Input processing failed (res = -1) or more data is
577
 
                         * needed (res = 1).
578
 
                         */
579
 
                        return res;
580
 
                }
581
 
 
582
 
                /*
583
 
                 * The incoming message has been reassembled and processed. The
584
 
                 * response was allocated into data->tls_out buffer.
585
 
                 */
586
 
        }
587
 
 
588
 
        if (data->tls_out == NULL) {
589
 
                /*
590
 
                 * No outgoing fragments remaining from the previous message
591
 
                 * and no new message generated. This indicates an error in TLS
592
 
                 * processing.
593
 
                 */
594
 
                eap_peer_tls_reset_output(data);
595
 
                return -1;
596
 
        }
597
 
 
598
 
        if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
599
 
                /* TLS processing has failed - return error */
600
 
                wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to "
601
 
                           "report error");
602
 
                ret = -1;
603
 
                /* TODO: clean pin if engine used? */
604
 
        }
605
 
 
606
 
        if (data->tls_out_len == 0) {
607
 
                /*
608
 
                 * TLS negotiation should now be complete since all other cases
609
 
                 * needing more data should have been caught above based on
610
 
                 * the TLS Message Length field.
611
 
                 */
612
 
                wpa_printf(MSG_DEBUG, "SSL: No data to be sent out");
613
 
                os_free(data->tls_out);
614
 
                data->tls_out = NULL;
615
 
                return 1;
616
 
        }
617
 
 
618
 
        /* Send the pending message (in fragments, if needed). */
619
 
        return eap_tls_process_output(data, eap_type, peap_version, id, ret,
620
 
                                      out_data, out_len);
621
 
}
622
 
 
623
 
 
624
 
/**
625
 
 * eap_peer_tls_build_ack - Build a TLS ACK frame
626
 
 * @data: Data for TLS processing
627
 
 * @respDataLen: Buffer for returning the length of the response message
628
 
 * @id: EAP identifier for the response
629
 
 * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
630
 
 * @peap_version: Version number for EAP-PEAP/TTLS
631
 
 * Returns: Pointer to the allocated ACK frame or %NULL on failure
632
 
 */
633
 
u8 * eap_peer_tls_build_ack(struct eap_ssl_data *data, size_t *respDataLen,
634
 
                            u8 id, EapType eap_type, int peap_version)
635
 
{
636
 
        struct eap_hdr *resp;
637
 
        u8 *pos;
638
 
 
639
 
        resp = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, respDataLen,
640
 
                             1, EAP_CODE_RESPONSE, id, &pos);
641
 
        if (resp == NULL)
642
 
                return NULL;
643
 
        wpa_printf(MSG_DEBUG, "SSL: Building ACK (type=%d id=%d ver=%d)",
644
 
                   (int) eap_type, id, peap_version);
645
 
        *pos = peap_version; /* Flags */
646
 
        return (u8 *) resp;
647
 
}
648
 
 
649
 
 
650
 
/**
651
 
 * eap_peer_tls_reauth_init - Re-initialize shared TLS for session resumption
652
 
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
653
 
 * @data: Data for TLS processing
654
 
 * Returns: 0 on success, -1 on failure
655
 
 */
656
 
int eap_peer_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data)
657
 
{
658
 
        eap_peer_tls_reset_input(data);
659
 
        eap_peer_tls_reset_output(data);
660
 
        return tls_connection_shutdown(sm->ssl_ctx, data->conn);
661
 
}
662
 
 
663
 
 
664
 
/**
665
 
 * eap_peer_tls_status - Get TLS status
666
 
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
667
 
 * @data: Data for TLS processing
668
 
 * @buf: Buffer for status information
669
 
 * @buflen: Maximum buffer length
670
 
 * @verbose: Whether to include verbose status information
671
 
 * Returns: Number of bytes written to buf.
672
 
 */
673
 
int eap_peer_tls_status(struct eap_sm *sm, struct eap_ssl_data *data,
674
 
                        char *buf, size_t buflen, int verbose)
675
 
{
676
 
        char name[128];
677
 
        int len = 0, ret;
678
 
 
679
 
        if (tls_get_cipher(sm->ssl_ctx, data->conn, name, sizeof(name)) == 0) {
680
 
                ret = os_snprintf(buf + len, buflen - len,
681
 
                                  "EAP TLS cipher=%s\n", name);
682
 
                if (ret < 0 || (size_t) ret >= buflen - len)
683
 
                        return len;
684
 
                len += ret;
685
 
        }
686
 
 
687
 
        return len;
688
 
}
689
 
 
690
 
 
691
 
/**
692
 
 * eap_peer_tls_process_init - Initial validation/processing of EAP requests
693
 
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
694
 
 * @data: Data for TLS processing
695
 
 * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
696
 
 * @ret: Return values from EAP request validation and processing
697
 
 * @reqData: EAP request to be processed (eapReqData)
698
 
 * @reqDataLen: Length of the EAP request
699
 
 * @len: Buffer for returning length of the remaining payload
700
 
 * @flags: Buffer for returning TLS flags
701
 
 * Returns: Buffer to payload after TLS flags and length or %NULL on failure
702
 
 *
703
 
 * This function validates the EAP header and processes the optional TLS
704
 
 * Message Length field. If this is the first fragment of a TLS message, the
705
 
 * TLS reassembly code is initialized to receive the indicated number of bytes.
706
 
 *
707
 
 * EAP-TLS, EAP-PEAP, EAP-TTLS, and EAP-FAST methods are expected to use this
708
 
 * function as the first step in processing received messages. They will need
709
 
 * to process the flags (apart from Message Length Included) that are returned
710
 
 * through the flags pointer and the message payload that will be returned (and
711
 
 * the length is returned through the len pointer). Return values (ret) are set
712
 
 * for continuation of EAP method processing. The caller is responsible for
713
 
 * setting these to indicate completion (either success or failure) based on
714
 
 * the authentication result.
715
 
 */
716
 
const u8 * eap_peer_tls_process_init(struct eap_sm *sm,
717
 
                                     struct eap_ssl_data *data,
718
 
                                     EapType eap_type,
719
 
                                     struct eap_method_ret *ret,
720
 
                                     const u8 *reqData, size_t reqDataLen,
721
 
                                     size_t *len, u8 *flags)
722
 
{
723
 
        const u8 *pos;
724
 
        size_t left;
725
 
        unsigned int tls_msg_len;
726
 
 
727
 
        if (tls_get_errors(sm->ssl_ctx)) {
728
 
                wpa_printf(MSG_INFO, "SSL: TLS errors detected");
729
 
                ret->ignore = TRUE;
730
 
                return NULL;
731
 
        }
732
 
 
733
 
        pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, reqData, reqDataLen,
734
 
                               &left);
735
 
        if (pos == NULL) {
736
 
                ret->ignore = TRUE;
737
 
                return NULL;
738
 
        }
739
 
        *flags = *pos++;
740
 
        left--;
741
 
        wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - "
742
 
                   "Flags 0x%02x", (unsigned long) reqDataLen, *flags);
743
 
        if (*flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
744
 
                if (left < 4) {
745
 
                        wpa_printf(MSG_INFO, "SSL: Short frame with TLS "
746
 
                                   "length");
747
 
                        ret->ignore = TRUE;
748
 
                        return NULL;
749
 
                }
750
 
                tls_msg_len = WPA_GET_BE32(pos);
751
 
                wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d",
752
 
                           tls_msg_len);
753
 
                if (data->tls_in_left == 0) {
754
 
                        data->tls_in_total = tls_msg_len;
755
 
                        data->tls_in_left = tls_msg_len;
756
 
                        os_free(data->tls_in);
757
 
                        data->tls_in = NULL;
758
 
                        data->tls_in_len = 0;
759
 
                }
760
 
                pos += 4;
761
 
                left -= 4;
762
 
        }
763
 
 
764
 
        ret->ignore = FALSE;
765
 
        ret->methodState = METHOD_MAY_CONT;
766
 
        ret->decision = DECISION_FAIL;
767
 
        ret->allowNotifications = TRUE;
768
 
 
769
 
        *len = left;
770
 
        return pos;
771
 
}
772
 
 
773
 
 
774
 
/**
775
 
 * eap_peer_tls_reset_input - Reset input buffers
776
 
 * @data: Data for TLS processing
777
 
 *
778
 
 * This function frees any allocated memory for input buffers and resets input
779
 
 * state.
780
 
 */
781
 
void eap_peer_tls_reset_input(struct eap_ssl_data *data)
782
 
{
783
 
        data->tls_in_left = data->tls_in_total = data->tls_in_len = 0;
784
 
        os_free(data->tls_in);
785
 
        data->tls_in = NULL;
786
 
}
787
 
 
788
 
 
789
 
/**
790
 
 * eap_peer_tls_reset_output - Reset output buffers
791
 
 * @data: Data for TLS processing
792
 
 *
793
 
 * This function frees any allocated memory for output buffers and resets
794
 
 * output state.
795
 
 */
796
 
void eap_peer_tls_reset_output(struct eap_ssl_data *data)
797
 
{
798
 
        data->tls_out_len = 0;
799
 
        data->tls_out_pos = 0;
800
 
        os_free(data->tls_out);
801
 
        data->tls_out = NULL;
802
 
}
803
 
 
804
 
 
805
 
/**
806
 
 * eap_peer_tls_decrypt - Decrypt received phase 2 TLS message
807
 
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
808
 
 * @data: Data for TLS processing
809
 
 * @in_data: Message received from the server
810
 
 * @in_len: Length of in_data
811
 
 * @in_decrypted: Buffer for returning a pointer to the decrypted message
812
 
 * @len_decrypted: Buffer for returning the length of the decrypted message
813
 
 * Returns: 0 on success, 1 if more input data is needed, or -1 on failure
814
 
 */
815
 
int eap_peer_tls_decrypt(struct eap_sm *sm, struct eap_ssl_data *data,
816
 
                         const u8 *in_data, size_t in_len,
817
 
                         u8 **in_decrypted, size_t *len_decrypted)
818
 
{
819
 
        int res;
820
 
        const u8 *msg;
821
 
        size_t msg_len, buf_len;
822
 
        int need_more_input;
823
 
 
824
 
        msg = eap_peer_tls_data_reassemble(data, in_data, in_len, &msg_len,
825
 
                                           &need_more_input);
826
 
        if (msg == NULL)
827
 
                return need_more_input ? 1 : -1;
828
 
 
829
 
        buf_len = in_len;
830
 
        if (data->tls_in_total > buf_len)
831
 
                buf_len = data->tls_in_total;
832
 
        *in_decrypted = os_malloc(buf_len ? buf_len : 1);
833
 
        if (*in_decrypted == NULL) {
834
 
                eap_peer_tls_reset_input(data);
835
 
                wpa_printf(MSG_WARNING, "SSL: Failed to allocate memory for "
836
 
                           "decryption");
837
 
                return -1;
838
 
        }
839
 
 
840
 
        res = tls_connection_decrypt(sm->ssl_ctx, data->conn, msg, msg_len,
841
 
                                     *in_decrypted, buf_len);
842
 
        eap_peer_tls_reset_input(data);
843
 
        if (res < 0) {
844
 
                wpa_printf(MSG_INFO, "SSL: Failed to decrypt Phase 2 data");
845
 
                return -1;
846
 
        }
847
 
        *len_decrypted = res;
848
 
        return 0;
849
 
}
850
 
 
851
 
 
852
 
/**
853
 
 * eap_peer_tls_encrypt - Encrypt phase 2 TLS message
854
 
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
855
 
 * @data: Data for TLS processing
856
 
 * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
857
 
 * @peap_version: Version number for EAP-PEAP/TTLS
858
 
 * @id: EAP identifier for the response
859
 
 * @in_data: Plaintext phase 2 data to encrypt or %NULL to continue fragments
860
 
 * @in_len: Length of in_data
861
 
 * @out_data: Buffer for returning a pointer to the encrypted response message
862
 
 * @out_len: Buffer for returning the length of the encrypted response message
863
 
 * Returns: 0 on success, -1 on failure
864
 
 */
865
 
int eap_peer_tls_encrypt(struct eap_sm *sm, struct eap_ssl_data *data,
866
 
                         EapType eap_type, int peap_version, u8 id,
867
 
                         const u8 *in_data, size_t in_len,
868
 
                         u8 **out_data, size_t *out_len)
869
 
{
870
 
        int res;
871
 
        size_t len;
872
 
 
873
 
        if (in_data) {
874
 
                eap_peer_tls_reset_output(data);
875
 
                len = in_len + 100;
876
 
                data->tls_out = os_malloc(len);
877
 
                if (data->tls_out == NULL)
878
 
                        return -1;
879
 
 
880
 
                res = tls_connection_encrypt(sm->ssl_ctx, data->conn, in_data,
881
 
                                             in_len, data->tls_out, len);
882
 
                if (res < 0) {
883
 
                        wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 "
884
 
                                   "data (in_len=%lu)",
885
 
                                   (unsigned long) in_len);
886
 
                        eap_peer_tls_reset_output(data);
887
 
                        return -1;
888
 
                }
889
 
 
890
 
                data->tls_out_len = res;
891
 
        }
892
 
 
893
 
        return eap_tls_process_output(data, eap_type, peap_version, id, 0,
894
 
                                      out_data, out_len);
895
 
}
896
 
 
897
 
 
898
 
/**
899
 
 * eap_peer_select_phase2_methods - Select phase 2 EAP method
900
 
 * @config: Pointer to the network configuration
901
 
 * @prefix: 'phase2' configuration prefix, e.g., "auth="
902
 
 * @types: Buffer for returning allocated list of allowed EAP methods
903
 
 * @num_types: Buffer for returning number of allocated EAP methods
904
 
 * Returns: 0 on success, -1 on failure
905
 
 *
906
 
 * This function is used to parse EAP method list and select allowed methods
907
 
 * for Phase2 authentication.
908
 
 */
909
 
int eap_peer_select_phase2_methods(struct wpa_ssid *config, const char *prefix,
910
 
                                   struct eap_method_type **types,
911
 
                                   size_t *num_types)
912
 
{
913
 
        char *start, *pos, *buf;
914
 
        struct eap_method_type *methods = NULL, *_methods;
915
 
        u8 method;
916
 
        size_t num_methods = 0, prefix_len;
917
 
 
918
 
        if (config == NULL || config->phase2 == NULL)
919
 
                goto get_defaults;
920
 
 
921
 
        start = buf = os_strdup(config->phase2);
922
 
        if (buf == NULL)
923
 
                return -1;
924
 
 
925
 
        prefix_len = os_strlen(prefix);
926
 
 
927
 
        while (start && *start != '\0') {
928
 
                int vendor;
929
 
                pos = os_strstr(start, prefix);
930
 
                if (pos == NULL)
931
 
                        break;
932
 
                if (start != pos && *(pos - 1) != ' ') {
933
 
                        start = pos + prefix_len;
934
 
                        continue;
935
 
                }
936
 
 
937
 
                start = pos + prefix_len;
938
 
                pos = os_strchr(start, ' ');
939
 
                if (pos)
940
 
                        *pos++ = '\0';
941
 
                method = eap_get_phase2_type(start, &vendor);
942
 
                if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE) {
943
 
                        wpa_printf(MSG_ERROR, "TLS: Unsupported Phase2 EAP "
944
 
                                   "method '%s'", start);
945
 
                } else {
946
 
                        num_methods++;
947
 
                        _methods = os_realloc(methods,
948
 
                                              num_methods * sizeof(*methods));
949
 
                        if (_methods == NULL) {
950
 
                                os_free(methods);
951
 
                                os_free(buf);
952
 
                                return -1;
953
 
                        }
954
 
                        methods = _methods;
955
 
                        methods[num_methods - 1].vendor = vendor;
956
 
                        methods[num_methods - 1].method = method;
957
 
                }
958
 
 
959
 
                start = pos;
960
 
        }
961
 
 
962
 
        os_free(buf);
963
 
 
964
 
get_defaults:
965
 
        if (methods == NULL)
966
 
                methods = eap_get_phase2_types(config, &num_methods);
967
 
 
968
 
        if (methods == NULL) {
969
 
                wpa_printf(MSG_ERROR, "TLS: No Phase2 EAP methods available");
970
 
                return -1;
971
 
        }
972
 
        wpa_hexdump(MSG_DEBUG, "TLS: Phase2 EAP types",
973
 
                    (u8 *) methods,
974
 
                    num_methods * sizeof(struct eap_method_type));
975
 
 
976
 
        *types = methods;
977
 
        *num_types = num_methods;
978
 
 
979
 
        return 0;
980
 
}
981
 
 
982
 
 
983
 
/**
984
 
 * eap_peer_tls_phase2_nak - Generate EAP-Nak for Phase 2
985
 
 * @types: Buffer for returning allocated list of allowed EAP methods
986
 
 * @num_types: Buffer for returning number of allocated EAP methods
987
 
 * @hdr: EAP-Request header (and the following EAP type octet)
988
 
 * @resp: Buffer for returning the EAP-Nak message
989
 
 * @resp_len: Buffer for returning the length of the EAP-Nak message
990
 
 * Returns: 0 on success, -1 on failure
991
 
 */
992
 
int eap_peer_tls_phase2_nak(struct eap_method_type *types, size_t num_types,
993
 
                            struct eap_hdr *hdr, u8 **resp, size_t *resp_len)
994
 
{
995
 
        struct eap_hdr *resp_hdr;
996
 
        u8 *pos = (u8 *) (hdr + 1);
997
 
        size_t i;
998
 
 
999
 
        /* TODO: add support for expanded Nak */
1000
 
        wpa_printf(MSG_DEBUG, "TLS: Phase 2 Request: Nak type=%d", *pos);
1001
 
        wpa_hexdump(MSG_DEBUG, "TLS: Allowed Phase2 EAP types",
1002
 
                    (u8 *) types, num_types * sizeof(struct eap_method_type));
1003
 
        *resp_len = sizeof(struct eap_hdr) + 1;
1004
 
        *resp = os_malloc(*resp_len + num_types);
1005
 
        if (*resp == NULL)
1006
 
                return -1;
1007
 
 
1008
 
        resp_hdr = (struct eap_hdr *) (*resp);
1009
 
        resp_hdr->code = EAP_CODE_RESPONSE;
1010
 
        resp_hdr->identifier = hdr->identifier;
1011
 
        pos = (u8 *) (resp_hdr + 1);
1012
 
        *pos++ = EAP_TYPE_NAK;
1013
 
        for (i = 0; i < num_types; i++) {
1014
 
                if (types[i].vendor == EAP_VENDOR_IETF &&
1015
 
                    types[i].method < 256) {
1016
 
                        (*resp_len)++;
1017
 
                        *pos++ = types[i].method;
1018
 
                }
1019
 
        }
1020
 
        resp_hdr->length = host_to_be16(*resp_len);
1021
 
 
1022
 
        return 0;
1023
 
}