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

« back to all changes in this revision

Viewing changes to tls_gnutls.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
 
 * WPA Supplicant / SSL/TLS interface functions for openssl
3
 
 * Copyright (c) 2004-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
 
#include <gnutls/gnutls.h>
17
 
#include <gnutls/x509.h>
18
 
#ifdef PKCS12_FUNCS
19
 
#include <gnutls/pkcs12.h>
20
 
#endif /* PKCS12_FUNCS */
21
 
 
22
 
#ifdef CONFIG_GNUTLS_EXTRA
23
 
#if LIBGNUTLS_VERSION_NUMBER >= 0x010302
24
 
#define GNUTLS_IA
25
 
#include <gnutls/extra.h>
26
 
#if LIBGNUTLS_VERSION_NUMBER == 0x010302
27
 
/* This function is not included in the current gnutls/extra.h even though it
28
 
 * should be, so define it here as a workaround for the time being. */
29
 
int gnutls_ia_verify_endphase(gnutls_session_t session, char *checksum);
30
 
#endif /* LIBGNUTLS_VERSION_NUMBER == 0x010302 */
31
 
#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
32
 
#endif /* CONFIG_GNUTLS_EXTRA */
33
 
 
34
 
#include "common.h"
35
 
#include "tls.h"
36
 
 
37
 
 
38
 
#define TLS_RANDOM_SIZE 32
39
 
#define TLS_MASTER_SIZE 48
40
 
 
41
 
 
42
 
#if LIBGNUTLS_VERSION_NUMBER < 0x010302
43
 
/* GnuTLS 1.3.2 added functions for using master secret. Older versions require
44
 
 * use of internal structures to get the master_secret and
45
 
 * {server,client}_random.
46
 
 */
47
 
#define GNUTLS_INTERNAL_STRUCTURE_HACK
48
 
#endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */
49
 
 
50
 
 
51
 
#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
52
 
/*
53
 
 * It looks like gnutls does not provide access to client/server_random and
54
 
 * master_key. This is somewhat unfortunate since these are needed for key
55
 
 * derivation in EAP-{TLS,TTLS,PEAP,FAST}. Workaround for now is a horrible
56
 
 * hack that copies the gnutls_session_int definition from gnutls_int.h so that
57
 
 * we can get the needed information.
58
 
 */
59
 
 
60
 
typedef u8 uint8;
61
 
typedef unsigned char opaque;
62
 
typedef struct {
63
 
    uint8 suite[2];
64
 
} cipher_suite_st;
65
 
 
66
 
typedef struct {
67
 
        gnutls_connection_end_t entity;
68
 
        gnutls_kx_algorithm_t kx_algorithm;
69
 
        gnutls_cipher_algorithm_t read_bulk_cipher_algorithm;
70
 
        gnutls_mac_algorithm_t read_mac_algorithm;
71
 
        gnutls_compression_method_t read_compression_algorithm;
72
 
        gnutls_cipher_algorithm_t write_bulk_cipher_algorithm;
73
 
        gnutls_mac_algorithm_t write_mac_algorithm;
74
 
        gnutls_compression_method_t write_compression_algorithm;
75
 
        cipher_suite_st current_cipher_suite;
76
 
        opaque master_secret[TLS_MASTER_SIZE];
77
 
        opaque client_random[TLS_RANDOM_SIZE];
78
 
        opaque server_random[TLS_RANDOM_SIZE];
79
 
        /* followed by stuff we are not interested in */
80
 
} security_parameters_st;
81
 
 
82
 
struct gnutls_session_int {
83
 
        security_parameters_st security_parameters;
84
 
        /* followed by things we are not interested in */
85
 
};
86
 
#endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */
87
 
 
88
 
static int tls_gnutls_ref_count = 0;
89
 
 
90
 
struct tls_global {
91
 
        /* Data for session resumption */
92
 
        void *session_data;
93
 
        size_t session_data_size;
94
 
 
95
 
        int server;
96
 
 
97
 
        int params_set;
98
 
        gnutls_certificate_credentials_t xcred;
99
 
};
100
 
 
101
 
struct tls_connection {
102
 
        gnutls_session session;
103
 
        char *subject_match, *altsubject_match;
104
 
        int read_alerts, write_alerts, failed;
105
 
 
106
 
        u8 *pre_shared_secret;
107
 
        size_t pre_shared_secret_len;
108
 
        int established;
109
 
        int verify_peer;
110
 
 
111
 
        u8 *push_buf, *pull_buf, *pull_buf_offset;
112
 
        size_t push_buf_len, pull_buf_len;
113
 
 
114
 
        int params_set;
115
 
        gnutls_certificate_credentials_t xcred;
116
 
 
117
 
        int tls_ia;
118
 
        int final_phase_finished;
119
 
 
120
 
#ifdef GNUTLS_IA
121
 
        gnutls_ia_server_credentials_t iacred_srv;
122
 
        gnutls_ia_client_credentials_t iacred_cli;
123
 
 
124
 
        /* Session keys generated in the current phase for inner secret
125
 
         * permutation before generating/verifying PhaseFinished. */
126
 
        u8 *session_keys;
127
 
        size_t session_keys_len;
128
 
 
129
 
        u8 inner_secret[TLS_MASTER_SIZE];
130
 
#endif /* GNUTLS_IA */
131
 
};
132
 
 
133
 
 
134
 
static void tls_log_func(int level, const char *msg)
135
 
{
136
 
        char *s, *pos;
137
 
        if (level == 6 || level == 7) {
138
 
                /* These levels seem to be mostly I/O debug and msg dumps */
139
 
                return;
140
 
        }
141
 
 
142
 
        s = os_strdup(msg);
143
 
        if (s == NULL)
144
 
                return;
145
 
 
146
 
        pos = s;
147
 
        while (*pos != '\0') {
148
 
                if (*pos == '\n') {
149
 
                        *pos = '\0';
150
 
                        break;
151
 
                }
152
 
                pos++;
153
 
        }
154
 
        wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG,
155
 
                   "gnutls<%d> %s", level, s);
156
 
        os_free(s);
157
 
}
158
 
 
159
 
 
160
 
extern int wpa_debug_show_keys;
161
 
 
162
 
void * tls_init(const struct tls_config *conf)
163
 
{
164
 
        struct tls_global *global;
165
 
 
166
 
#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
167
 
        /* Because of the horrible hack to get master_secret and client/server
168
 
         * random, we need to make sure that the gnutls version is something
169
 
         * that is expected to have same structure definition for the session
170
 
         * data.. */
171
 
        const char *ver;
172
 
        const char *ok_ver[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", "1.2.9",
173
 
                                 "1.3.2",
174
 
                                 NULL };
175
 
        int i;
176
 
#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
177
 
 
178
 
        global = os_zalloc(sizeof(*global));
179
 
        if (global == NULL)
180
 
                return NULL;
181
 
 
182
 
        if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) {
183
 
                os_free(global);
184
 
                return NULL;
185
 
        }
186
 
        tls_gnutls_ref_count++;
187
 
 
188
 
#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
189
 
        ver = gnutls_check_version(NULL);
190
 
        if (ver == NULL) {
191
 
                tls_deinit(global);
192
 
                return NULL;
193
 
        }
194
 
        wpa_printf(MSG_DEBUG, "%s - gnutls version %s", __func__, ver);
195
 
        for (i = 0; ok_ver[i]; i++) {
196
 
                if (strcmp(ok_ver[i], ver) == 0)
197
 
                        break;
198
 
        }
199
 
        if (ok_ver[i] == NULL) {
200
 
                wpa_printf(MSG_INFO, "Untested gnutls version %s - this needs "
201
 
                           "to be tested and enabled in tls_gnutls.c", ver);
202
 
                tls_deinit(global);
203
 
                return NULL;
204
 
        }
205
 
#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
206
 
 
207
 
        gnutls_global_set_log_function(tls_log_func);
208
 
        if (wpa_debug_show_keys)
209
 
                gnutls_global_set_log_level(11);
210
 
        return global;
211
 
}
212
 
 
213
 
 
214
 
void tls_deinit(void *ssl_ctx)
215
 
{
216
 
        struct tls_global *global = ssl_ctx;
217
 
        if (global) {
218
 
                if (global->params_set)
219
 
                        gnutls_certificate_free_credentials(global->xcred);
220
 
                os_free(global->session_data);
221
 
                os_free(global);
222
 
        }
223
 
 
224
 
        tls_gnutls_ref_count--;
225
 
        if (tls_gnutls_ref_count == 0)
226
 
                gnutls_global_deinit();
227
 
}
228
 
 
229
 
 
230
 
int tls_get_errors(void *ssl_ctx)
231
 
{
232
 
        return 0;
233
 
}
234
 
 
235
 
 
236
 
static ssize_t tls_pull_func(gnutls_transport_ptr ptr, void *buf,
237
 
                             size_t len)
238
 
{
239
 
        struct tls_connection *conn = (struct tls_connection *) ptr;
240
 
        u8 *end;
241
 
        if (conn->pull_buf == NULL) {
242
 
                errno = EWOULDBLOCK;
243
 
                return -1;
244
 
        }
245
 
 
246
 
        end = conn->pull_buf + conn->pull_buf_len;
247
 
        if ((size_t) (end - conn->pull_buf_offset) < len)
248
 
                len = end - conn->pull_buf_offset;
249
 
        os_memcpy(buf, conn->pull_buf_offset, len);
250
 
        conn->pull_buf_offset += len;
251
 
        if (conn->pull_buf_offset == end) {
252
 
                wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
253
 
                os_free(conn->pull_buf);
254
 
                conn->pull_buf = conn->pull_buf_offset = NULL;
255
 
                conn->pull_buf_len = 0;
256
 
        } else {
257
 
                wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in pull_buf",
258
 
                           __func__, end - conn->pull_buf_offset);
259
 
        }
260
 
        return len;
261
 
}
262
 
 
263
 
 
264
 
static ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf,
265
 
                             size_t len)
266
 
{
267
 
        struct tls_connection *conn = (struct tls_connection *) ptr;
268
 
        u8 *nbuf;
269
 
 
270
 
        nbuf = os_realloc(conn->push_buf, conn->push_buf_len + len);
271
 
        if (nbuf == NULL) {
272
 
                errno = ENOMEM;
273
 
                return -1;
274
 
        }
275
 
        os_memcpy(nbuf + conn->push_buf_len, buf, len);
276
 
        conn->push_buf = nbuf;
277
 
        conn->push_buf_len += len;
278
 
 
279
 
        return len;
280
 
}
281
 
 
282
 
 
283
 
static int tls_gnutls_init_session(struct tls_global *global,
284
 
                                   struct tls_connection *conn)
285
 
{
286
 
        const int cert_types[2] = { GNUTLS_CRT_X509, 0 };
287
 
        const int protos[2] = { GNUTLS_TLS1, 0 };
288
 
        int ret;
289
 
 
290
 
        ret = gnutls_init(&conn->session,
291
 
                          global->server ? GNUTLS_SERVER : GNUTLS_CLIENT);
292
 
        if (ret < 0) {
293
 
                wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS "
294
 
                           "connection: %s", gnutls_strerror(ret));
295
 
                return -1;
296
 
        }
297
 
 
298
 
        ret = gnutls_set_default_priority(conn->session);
299
 
        if (ret < 0)
300
 
                goto fail;
301
 
 
302
 
        ret = gnutls_certificate_type_set_priority(conn->session, cert_types);
303
 
        if (ret < 0)
304
 
                goto fail;
305
 
 
306
 
        ret = gnutls_protocol_set_priority(conn->session, protos);
307
 
        if (ret < 0)
308
 
                goto fail;
309
 
 
310
 
        gnutls_transport_set_pull_function(conn->session, tls_pull_func);
311
 
        gnutls_transport_set_push_function(conn->session, tls_push_func);
312
 
        gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn);
313
 
 
314
 
        return 0;
315
 
 
316
 
fail:
317
 
        wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s",
318
 
                   gnutls_strerror(ret));
319
 
        gnutls_deinit(conn->session);
320
 
        return -1;
321
 
}
322
 
 
323
 
 
324
 
struct tls_connection * tls_connection_init(void *ssl_ctx)
325
 
{
326
 
        struct tls_global *global = ssl_ctx;
327
 
        struct tls_connection *conn;
328
 
        int ret;
329
 
 
330
 
        conn = os_zalloc(sizeof(*conn));
331
 
        if (conn == NULL)
332
 
                return NULL;
333
 
 
334
 
        if (tls_gnutls_init_session(global, conn)) {
335
 
                os_free(conn);
336
 
                return NULL;
337
 
        }
338
 
 
339
 
        if (global->params_set) {
340
 
                ret = gnutls_credentials_set(conn->session,
341
 
                                             GNUTLS_CRD_CERTIFICATE,
342
 
                                             global->xcred);
343
 
                if (ret < 0) {
344
 
                        wpa_printf(MSG_INFO, "Failed to configure "
345
 
                                   "credentials: %s", gnutls_strerror(ret));
346
 
                        os_free(conn);
347
 
                        return NULL;
348
 
                }
349
 
        }
350
 
 
351
 
        if (gnutls_certificate_allocate_credentials(&conn->xcred)) {
352
 
                os_free(conn);
353
 
                return NULL;
354
 
        }
355
 
 
356
 
        return conn;
357
 
}
358
 
 
359
 
 
360
 
void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
361
 
{
362
 
        if (conn == NULL)
363
 
                return;
364
 
 
365
 
#ifdef GNUTLS_IA
366
 
        if (conn->iacred_srv)
367
 
                gnutls_ia_free_server_credentials(conn->iacred_srv);
368
 
        if (conn->iacred_cli)
369
 
                gnutls_ia_free_client_credentials(conn->iacred_cli);
370
 
        if (conn->session_keys) {
371
 
                os_memset(conn->session_keys, 0, conn->session_keys_len);
372
 
                os_free(conn->session_keys);
373
 
        }
374
 
#endif /* GNUTLS_IA */
375
 
 
376
 
        gnutls_certificate_free_credentials(conn->xcred);
377
 
        gnutls_deinit(conn->session);
378
 
        os_free(conn->pre_shared_secret);
379
 
        os_free(conn->subject_match);
380
 
        os_free(conn->altsubject_match);
381
 
        os_free(conn->push_buf);
382
 
        os_free(conn->pull_buf);
383
 
        os_free(conn);
384
 
}
385
 
 
386
 
 
387
 
int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
388
 
{
389
 
        return conn ? conn->established : 0;
390
 
}
391
 
 
392
 
 
393
 
int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
394
 
{
395
 
        struct tls_global *global = ssl_ctx;
396
 
        int ret;
397
 
 
398
 
        if (conn == NULL)
399
 
                return -1;
400
 
 
401
 
        /* Shutdown previous TLS connection without notifying the peer
402
 
         * because the connection was already terminated in practice
403
 
         * and "close notify" shutdown alert would confuse AS. */
404
 
        gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
405
 
        os_free(conn->push_buf);
406
 
        conn->push_buf = NULL;
407
 
        conn->push_buf_len = 0;
408
 
        conn->established = 0;
409
 
        conn->final_phase_finished = 0;
410
 
#ifdef GNUTLS_IA
411
 
        if (conn->session_keys) {
412
 
                os_memset(conn->session_keys, 0, conn->session_keys_len);
413
 
                os_free(conn->session_keys);
414
 
        }
415
 
        conn->session_keys_len = 0;
416
 
#endif /* GNUTLS_IA */
417
 
 
418
 
        gnutls_deinit(conn->session);
419
 
        if (tls_gnutls_init_session(global, conn)) {
420
 
                wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session "
421
 
                           "for session resumption use");
422
 
                return -1;
423
 
        }
424
 
 
425
 
        ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
426
 
                                     conn->params_set ? conn->xcred :
427
 
                                     global->xcred);
428
 
        if (ret < 0) {
429
 
                wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials "
430
 
                           "for session resumption: %s", gnutls_strerror(ret));
431
 
                return -1;
432
 
        }
433
 
 
434
 
        if (global->session_data) {
435
 
                ret = gnutls_session_set_data(conn->session,
436
 
                                              global->session_data,
437
 
                                              global->session_data_size);
438
 
                if (ret < 0) {
439
 
                        wpa_printf(MSG_INFO, "GnuTLS: Failed to set session "
440
 
                                   "data: %s", gnutls_strerror(ret));
441
 
                        return -1;
442
 
                }
443
 
        }
444
 
 
445
 
        return 0;
446
 
}
447
 
 
448
 
 
449
 
#if 0
450
 
static int tls_match_altsubject(X509 *cert, const char *match)
451
 
{
452
 
        GENERAL_NAME *gen;
453
 
        char *field, *tmp;
454
 
        void *ext;
455
 
        int i, found = 0;
456
 
        size_t len;
457
 
 
458
 
        ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
459
 
 
460
 
        for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
461
 
                gen = sk_GENERAL_NAME_value(ext, i);
462
 
                switch (gen->type) {
463
 
                case GEN_EMAIL:
464
 
                        field = "EMAIL";
465
 
                        break;
466
 
                case GEN_DNS:
467
 
                        field = "DNS";
468
 
                        break;
469
 
                case GEN_URI:
470
 
                        field = "URI";
471
 
                        break;
472
 
                default:
473
 
                        field = NULL;
474
 
                        wpa_printf(MSG_DEBUG, "TLS: altSubjectName: "
475
 
                                   "unsupported type=%d", gen->type);
476
 
                        break;
477
 
                }
478
 
 
479
 
                if (!field)
480
 
                        continue;
481
 
 
482
 
                wpa_printf(MSG_DEBUG, "TLS: altSubjectName: %s:%s",
483
 
                           field, gen->d.ia5->data);
484
 
                len = os_strlen(field) + 1 +
485
 
                        strlen((char *) gen->d.ia5->data) + 1;
486
 
                tmp = os_malloc(len);
487
 
                if (tmp == NULL)
488
 
                        continue;
489
 
                snprintf(tmp, len, "%s:%s", field, gen->d.ia5->data);
490
 
                if (strstr(tmp, match))
491
 
                        found++;
492
 
                os_free(tmp);
493
 
        }
494
 
 
495
 
        return found;
496
 
}
497
 
#endif
498
 
 
499
 
 
500
 
#if 0
501
 
static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
502
 
{
503
 
        char buf[256];
504
 
        X509 *err_cert;
505
 
        int err, depth;
506
 
        SSL *ssl;
507
 
        struct tls_connection *conn;
508
 
        char *match, *altmatch;
509
 
 
510
 
        err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
511
 
        err = X509_STORE_CTX_get_error(x509_ctx);
512
 
        depth = X509_STORE_CTX_get_error_depth(x509_ctx);
513
 
        ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
514
 
                                         SSL_get_ex_data_X509_STORE_CTX_idx());
515
 
        X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
516
 
 
517
 
        conn = SSL_get_app_data(ssl);
518
 
        match = conn ? conn->subject_match : NULL;
519
 
        altmatch = conn ? conn->altsubject_match : NULL;
520
 
 
521
 
        if (!preverify_ok) {
522
 
                wpa_printf(MSG_WARNING, "TLS: Certificate verification failed,"
523
 
                           " error %d (%s) depth %d for '%s'", err,
524
 
                           X509_verify_cert_error_string(err), depth, buf);
525
 
        } else {
526
 
                wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - "
527
 
                           "preverify_ok=%d err=%d (%s) depth=%d buf='%s'",
528
 
                           preverify_ok, err,
529
 
                           X509_verify_cert_error_string(err), depth, buf);
530
 
                if (depth == 0 && match && strstr(buf, match) == NULL) {
531
 
                        wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
532
 
                                   "match with '%s'", buf, match);
533
 
                        preverify_ok = 0;
534
 
                } else if (depth == 0 && altmatch &&
535
 
                           !tls_match_altsubject(err_cert, altmatch)) {
536
 
                        wpa_printf(MSG_WARNING, "TLS: altSubjectName match "
537
 
                                   "'%s' not found", altmatch);
538
 
                        preverify_ok = 0;
539
 
                }
540
 
        }
541
 
 
542
 
        return preverify_ok;
543
 
}
544
 
#endif
545
 
 
546
 
 
547
 
int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
548
 
                              const struct tls_connection_params *params)
549
 
{
550
 
        int ret;
551
 
 
552
 
        if (conn == NULL || params == NULL)
553
 
                return -1;
554
 
 
555
 
        os_free(conn->subject_match);
556
 
        conn->subject_match = NULL;
557
 
        if (params->subject_match) {
558
 
                conn->subject_match = os_strdup(params->subject_match);
559
 
                if (conn->subject_match == NULL)
560
 
                        return -1;
561
 
        }
562
 
 
563
 
        os_free(conn->altsubject_match);
564
 
        conn->altsubject_match = NULL;
565
 
        if (params->altsubject_match) {
566
 
                conn->altsubject_match = os_strdup(params->altsubject_match);
567
 
                if (conn->altsubject_match == NULL)
568
 
                        return -1;
569
 
        }
570
 
 
571
 
        /* TODO: gnutls_certificate_set_verify_flags(xcred, flags); 
572
 
         * to force peer validation(?) */
573
 
 
574
 
        if (params->ca_cert) {
575
 
                conn->verify_peer = 1;
576
 
                ret = gnutls_certificate_set_x509_trust_file(
577
 
                        conn->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM);
578
 
                if (ret < 0) {
579
 
                        wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
580
 
                                   "in PEM format: %s", params->ca_cert,
581
 
                                   gnutls_strerror(ret));
582
 
                        ret = gnutls_certificate_set_x509_trust_file(
583
 
                                conn->xcred, params->ca_cert,
584
 
                                GNUTLS_X509_FMT_DER);
585
 
                        if (ret < 0) {
586
 
                                wpa_printf(MSG_DEBUG, "Failed to read CA cert "
587
 
                                           "'%s' in DER format: %s",
588
 
                                           params->ca_cert,
589
 
                                           gnutls_strerror(ret));
590
 
                                return -1;
591
 
                        }
592
 
                }
593
 
        }
594
 
 
595
 
        if (params->client_cert && params->private_key) {
596
 
                /* TODO: private_key_passwd? */
597
 
                ret = gnutls_certificate_set_x509_key_file(
598
 
                        conn->xcred, params->client_cert, params->private_key,
599
 
                        GNUTLS_X509_FMT_PEM);
600
 
                if (ret < 0) {
601
 
                        wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
602
 
                                   "in PEM format: %s", gnutls_strerror(ret));
603
 
                        ret = gnutls_certificate_set_x509_key_file(
604
 
                                conn->xcred, params->client_cert,
605
 
                                params->private_key, GNUTLS_X509_FMT_DER);
606
 
                        if (ret < 0) {
607
 
                                wpa_printf(MSG_DEBUG, "Failed to read client "
608
 
                                           "cert/key in DER format: %s",
609
 
                                           gnutls_strerror(ret));
610
 
                                return ret;
611
 
                        }
612
 
                }
613
 
        } else if (params->private_key) {
614
 
                int pkcs12_ok = 0;
615
 
#ifdef PKCS12_FUNCS
616
 
                /* Try to load in PKCS#12 format */
617
 
#if LIBGNUTLS_VERSION_NUMBER >= 0x010302
618
 
                ret = gnutls_certificate_set_x509_simple_pkcs12_file(
619
 
                        conn->xcred, params->private_key, GNUTLS_X509_FMT_DER,
620
 
                        params->private_key_passwd);
621
 
                if (ret != 0) {
622
 
                        wpa_printf(MSG_DEBUG, "Failed to load private_key in "
623
 
                                   "PKCS#12 format: %s", gnutls_strerror(ret));
624
 
                        return -1;
625
 
                } else
626
 
                        pkcs12_ok = 1;
627
 
#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
628
 
#endif /* PKCS12_FUNCS */
629
 
 
630
 
                if (!pkcs12_ok) {
631
 
                        wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
632
 
                                   "included");
633
 
                        return -1;
634
 
                }
635
 
        }
636
 
 
637
 
        conn->tls_ia = params->tls_ia;
638
 
        conn->params_set = 1;
639
 
 
640
 
        ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
641
 
                                     conn->xcred);
642
 
        if (ret < 0) {
643
 
                wpa_printf(MSG_INFO, "Failed to configure credentials: %s",
644
 
                           gnutls_strerror(ret));
645
 
        }
646
 
 
647
 
#ifdef GNUTLS_IA
648
 
        if (conn->iacred_cli)
649
 
                gnutls_ia_free_client_credentials(conn->iacred_cli);
650
 
 
651
 
        ret = gnutls_ia_allocate_client_credentials(&conn->iacred_cli);
652
 
        if (ret) {
653
 
                wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s",
654
 
                           gnutls_strerror(ret));
655
 
                return -1;
656
 
        }
657
 
 
658
 
        ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA,
659
 
                                     conn->iacred_cli);
660
 
        if (ret) {
661
 
                wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s",
662
 
                           gnutls_strerror(ret));
663
 
                gnutls_ia_free_client_credentials(conn->iacred_cli);
664
 
                conn->iacred_cli = NULL;
665
 
                return -1;
666
 
        }
667
 
#endif /* GNUTLS_IE */
668
 
 
669
 
        return ret;
670
 
}
671
 
 
672
 
 
673
 
int tls_global_set_params(void *tls_ctx,
674
 
                          const struct tls_connection_params *params)
675
 
{
676
 
        struct tls_global *global = tls_ctx;
677
 
        int ret;
678
 
 
679
 
        /* Currently, global parameters are only set when running in server
680
 
         * mode. */
681
 
        global->server = 1;
682
 
 
683
 
        if (global->params_set) {
684
 
                gnutls_certificate_free_credentials(global->xcred);
685
 
                global->params_set = 0;
686
 
        }
687
 
 
688
 
        ret = gnutls_certificate_allocate_credentials(&global->xcred);
689
 
        if (ret) {
690
 
                wpa_printf(MSG_DEBUG, "Failed to allocate global credentials "
691
 
                           "%s", gnutls_strerror(ret));
692
 
                return -1;
693
 
        }
694
 
 
695
 
        if (params->ca_cert) {
696
 
                ret = gnutls_certificate_set_x509_trust_file(
697
 
                        global->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM);
698
 
                if (ret < 0) {
699
 
                        wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
700
 
                                   "in PEM format: %s", params->ca_cert,
701
 
                                   gnutls_strerror(ret));
702
 
                        ret = gnutls_certificate_set_x509_trust_file(
703
 
                                global->xcred, params->ca_cert,
704
 
                                GNUTLS_X509_FMT_DER);
705
 
                        if (ret < 0) {
706
 
                                wpa_printf(MSG_DEBUG, "Failed to read CA cert "
707
 
                                           "'%s' in DER format: %s",
708
 
                                           params->ca_cert,
709
 
                                           gnutls_strerror(ret));
710
 
                                goto fail;
711
 
                        }
712
 
                }
713
 
        }
714
 
 
715
 
        if (params->client_cert && params->private_key) {
716
 
                /* TODO: private_key_passwd? */
717
 
                ret = gnutls_certificate_set_x509_key_file(
718
 
                        global->xcred, params->client_cert,
719
 
                        params->private_key, GNUTLS_X509_FMT_PEM);
720
 
                if (ret < 0) {
721
 
                        wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
722
 
                                   "in PEM format: %s", gnutls_strerror(ret));
723
 
                        ret = gnutls_certificate_set_x509_key_file(
724
 
                                global->xcred, params->client_cert,
725
 
                                params->private_key, GNUTLS_X509_FMT_DER);
726
 
                        if (ret < 0) {
727
 
                                wpa_printf(MSG_DEBUG, "Failed to read client "
728
 
                                           "cert/key in DER format: %s",
729
 
                                           gnutls_strerror(ret));
730
 
                                goto fail;
731
 
                        }
732
 
                }
733
 
        } else if (params->private_key) {
734
 
                int pkcs12_ok = 0;
735
 
#ifdef PKCS12_FUNCS
736
 
                /* Try to load in PKCS#12 format */
737
 
#if LIBGNUTLS_VERSION_NUMBER >= 0x010302
738
 
                ret = gnutls_certificate_set_x509_simple_pkcs12_file(
739
 
                        global->xcred, params->private_key,
740
 
                        GNUTLS_X509_FMT_DER, params->private_key_passwd);
741
 
                if (ret != 0) {
742
 
                        wpa_printf(MSG_DEBUG, "Failed to load private_key in "
743
 
                                   "PKCS#12 format: %s", gnutls_strerror(ret));
744
 
                        goto fail;
745
 
                } else
746
 
                        pkcs12_ok = 1;
747
 
#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
748
 
#endif /* PKCS12_FUNCS */
749
 
 
750
 
                if (!pkcs12_ok) {
751
 
                        wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
752
 
                                   "included");
753
 
                        goto fail;
754
 
                }
755
 
        }
756
 
 
757
 
        global->params_set = 1;
758
 
 
759
 
        return 0;
760
 
 
761
 
fail:
762
 
        gnutls_certificate_free_credentials(global->xcred);
763
 
        return -1;
764
 
}
765
 
 
766
 
 
767
 
int tls_global_set_verify(void *ssl_ctx, int check_crl)
768
 
{
769
 
        /* TODO */
770
 
        return 0;
771
 
}
772
 
 
773
 
 
774
 
int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
775
 
                              int verify_peer)
776
 
{
777
 
        if (conn == NULL || conn->session == NULL)
778
 
                return -1;
779
 
 
780
 
        conn->verify_peer = verify_peer;
781
 
        gnutls_certificate_server_set_request(conn->session,
782
 
                                              verify_peer ? GNUTLS_CERT_REQUIRE
783
 
                                              : GNUTLS_CERT_REQUEST);
784
 
 
785
 
        return 0;
786
 
}
787
 
 
788
 
 
789
 
int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
790
 
                            struct tls_keys *keys)
791
 
{
792
 
#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
793
 
        security_parameters_st *sec;
794
 
#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
795
 
 
796
 
        if (conn == NULL || conn->session == NULL || keys == NULL)
797
 
                return -1;
798
 
 
799
 
        os_memset(keys, 0, sizeof(*keys));
800
 
 
801
 
#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
802
 
        sec = &conn->session->security_parameters;
803
 
        keys->master_key = sec->master_secret;
804
 
        keys->master_key_len = TLS_MASTER_SIZE;
805
 
        keys->client_random = sec->client_random;
806
 
        keys->server_random = sec->server_random;
807
 
#else /* GNUTLS_INTERNAL_STRUCTURE_HACK */
808
 
        keys->client_random =
809
 
                (u8 *) gnutls_session_get_client_random(conn->session);
810
 
        keys->server_random =
811
 
                (u8 *) gnutls_session_get_server_random(conn->session);
812
 
        /* No access to master_secret */
813
 
#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
814
 
 
815
 
#ifdef GNUTLS_IA
816
 
        gnutls_ia_extract_inner_secret(conn->session,
817
 
                                       (char *) conn->inner_secret);
818
 
        keys->inner_secret = conn->inner_secret;
819
 
        keys->inner_secret_len = TLS_MASTER_SIZE;
820
 
#endif /* GNUTLS_IA */
821
 
 
822
 
        keys->client_random_len = TLS_RANDOM_SIZE;
823
 
        keys->server_random_len = TLS_RANDOM_SIZE;
824
 
 
825
 
        return 0;
826
 
}
827
 
 
828
 
 
829
 
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
830
 
                       const char *label, int server_random_first,
831
 
                       u8 *out, size_t out_len)
832
 
{
833
 
#if LIBGNUTLS_VERSION_NUMBER >= 0x010302
834
 
        if (conn == NULL || conn->session == NULL)
835
 
                return -1;
836
 
 
837
 
        return gnutls_prf(conn->session, os_strlen(label), label,
838
 
                          server_random_first, 0, NULL, out_len, (char *) out);
839
 
#else /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
840
 
        return -1;
841
 
#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
842
 
}
843
 
 
844
 
 
845
 
static int tls_connection_verify_peer(struct tls_connection *conn)
846
 
{
847
 
        unsigned int status, num_certs, i;
848
 
        struct os_time now;
849
 
        const gnutls_datum_t *certs;
850
 
        gnutls_x509_crt_t cert;
851
 
 
852
 
        if (gnutls_certificate_verify_peers2(conn->session, &status) < 0) {
853
 
                wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
854
 
                           "certificate chain");
855
 
                return -1;
856
 
        }
857
 
 
858
 
        if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
859
 
                wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
860
 
                return -1;
861
 
        }
862
 
 
863
 
        if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
864
 
                wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
865
 
                           "known issuer");
866
 
                return -1;
867
 
        }
868
 
 
869
 
        if (status & GNUTLS_CERT_REVOKED) {
870
 
                wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
871
 
                return -1;
872
 
        }
873
 
 
874
 
        os_get_time(&now);
875
 
 
876
 
        certs = gnutls_certificate_get_peers(conn->session, &num_certs);
877
 
        if (certs == NULL) {
878
 
                wpa_printf(MSG_INFO, "TLS: No peer certificate chain "
879
 
                           "received");
880
 
                return -1;
881
 
        }
882
 
 
883
 
        for (i = 0; i < num_certs; i++) {
884
 
                char *buf;
885
 
                size_t len;
886
 
                if (gnutls_x509_crt_init(&cert) < 0) {
887
 
                        wpa_printf(MSG_INFO, "TLS: Certificate initialization "
888
 
                                   "failed");
889
 
                        return -1;
890
 
                }
891
 
 
892
 
                if (gnutls_x509_crt_import(cert, &certs[i],
893
 
                                           GNUTLS_X509_FMT_DER) < 0) {
894
 
                        wpa_printf(MSG_INFO, "TLS: Could not parse peer "
895
 
                                   "certificate %d/%d", i + 1, num_certs);
896
 
                        gnutls_x509_crt_deinit(cert);
897
 
                        return -1;
898
 
                }
899
 
 
900
 
                gnutls_x509_crt_get_dn(cert, NULL, &len);
901
 
                len++;
902
 
                buf = os_malloc(len + 1);
903
 
                if (buf) {
904
 
                        buf[0] = buf[len] = '\0';
905
 
                        gnutls_x509_crt_get_dn(cert, buf, &len);
906
 
                }
907
 
                wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
908
 
                           i + 1, num_certs, buf);
909
 
 
910
 
                if (i == 0) {
911
 
                        /* TODO: validate subject_match and altsubject_match */
912
 
                }
913
 
 
914
 
                os_free(buf);
915
 
 
916
 
                if (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
917
 
                    gnutls_x509_crt_get_activation_time(cert) > now.sec) {
918
 
                        wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
919
 
                                   "not valid at this time",
920
 
                                   i + 1, num_certs);
921
 
                        gnutls_x509_crt_deinit(cert);
922
 
                        return -1;
923
 
                }
924
 
 
925
 
                gnutls_x509_crt_deinit(cert);
926
 
        }
927
 
 
928
 
        return 0;
929
 
}
930
 
 
931
 
 
932
 
u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
933
 
                              const u8 *in_data, size_t in_len,
934
 
                              size_t *out_len, u8 **appl_data,
935
 
                              size_t *appl_data_len)
936
 
{
937
 
        struct tls_global *global = ssl_ctx;
938
 
        u8 *out_data;
939
 
        int ret;
940
 
 
941
 
        if (appl_data)
942
 
                *appl_data = NULL;
943
 
 
944
 
        if (in_data && in_len) {
945
 
                if (conn->pull_buf) {
946
 
                        wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in "
947
 
                                   "pull_buf", __func__, conn->pull_buf_len);
948
 
                        os_free(conn->pull_buf);
949
 
                }
950
 
                conn->pull_buf = os_malloc(in_len);
951
 
                if (conn->pull_buf == NULL)
952
 
                        return NULL;
953
 
                os_memcpy(conn->pull_buf, in_data, in_len);
954
 
                conn->pull_buf_offset = conn->pull_buf;
955
 
                conn->pull_buf_len = in_len;
956
 
        }
957
 
 
958
 
        ret = gnutls_handshake(conn->session);
959
 
        if (ret < 0) {
960
 
                switch (ret) {
961
 
                case GNUTLS_E_AGAIN:
962
 
                        if (global->server && conn->established &&
963
 
                            conn->push_buf == NULL) {
964
 
                                /* Need to return something to trigger
965
 
                                 * completion of EAP-TLS. */
966
 
                                conn->push_buf = os_malloc(1);
967
 
                        }
968
 
                        break;
969
 
                case GNUTLS_E_FATAL_ALERT_RECEIVED:
970
 
                        wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
971
 
                                   __func__, gnutls_alert_get_name(
972
 
                                           gnutls_alert_get(conn->session)));
973
 
                        conn->read_alerts++;
974
 
                        /* continue */
975
 
                default:
976
 
                        wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
977
 
                                   "-> %s", __func__, gnutls_strerror(ret));
978
 
                        conn->failed++;
979
 
                }
980
 
        } else {
981
 
                size_t size;
982
 
 
983
 
                if (conn->verify_peer && tls_connection_verify_peer(conn)) {
984
 
                        wpa_printf(MSG_INFO, "TLS: Peer certificate chain "
985
 
                                   "failed validation");
986
 
                        conn->failed++;
987
 
                        return NULL;
988
 
                }
989
 
 
990
 
                if (conn->tls_ia && !gnutls_ia_handshake_p(conn->session)) {
991
 
                        wpa_printf(MSG_INFO, "TLS: No TLS/IA negotiation");
992
 
                        conn->failed++;
993
 
                        return NULL;
994
 
                }
995
 
 
996
 
                if (conn->tls_ia)
997
 
                        wpa_printf(MSG_DEBUG, "TLS: Start TLS/IA handshake");
998
 
                else {
999
 
                        wpa_printf(MSG_DEBUG, "TLS: Handshake completed "
1000
 
                                   "successfully");
1001
 
                }
1002
 
                conn->established = 1;
1003
 
                if (conn->push_buf == NULL) {
1004
 
                        /* Need to return something to get final TLS ACK. */
1005
 
                        conn->push_buf = os_malloc(1);
1006
 
                }
1007
 
 
1008
 
                gnutls_session_get_data(conn->session, NULL, &size);
1009
 
                if (global->session_data == NULL ||
1010
 
                    global->session_data_size < size) {
1011
 
                        os_free(global->session_data);
1012
 
                        global->session_data = os_malloc(size);
1013
 
                }
1014
 
                if (global->session_data) {
1015
 
                        global->session_data_size = size;
1016
 
                        gnutls_session_get_data(conn->session,
1017
 
                                                global->session_data,
1018
 
                                                &global->session_data_size);
1019
 
                }
1020
 
        }
1021
 
 
1022
 
        out_data = conn->push_buf;
1023
 
        *out_len = conn->push_buf_len;
1024
 
        conn->push_buf = NULL;
1025
 
        conn->push_buf_len = 0;
1026
 
        return out_data;
1027
 
}
1028
 
 
1029
 
 
1030
 
u8 * tls_connection_server_handshake(void *ssl_ctx,
1031
 
                                     struct tls_connection *conn,
1032
 
                                     const u8 *in_data, size_t in_len,
1033
 
                                     size_t *out_len)
1034
 
{
1035
 
        return tls_connection_handshake(ssl_ctx, conn, in_data, in_len,
1036
 
                                        out_len, NULL, NULL);
1037
 
}
1038
 
 
1039
 
 
1040
 
int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
1041
 
                           const u8 *in_data, size_t in_len,
1042
 
                           u8 *out_data, size_t out_len)
1043
 
{
1044
 
        ssize_t res;
1045
 
 
1046
 
#ifdef GNUTLS_IA
1047
 
        if (conn->tls_ia)
1048
 
                res = gnutls_ia_send(conn->session, (char *) in_data, in_len);
1049
 
        else
1050
 
#endif /* GNUTLS_IA */
1051
 
        res = gnutls_record_send(conn->session, in_data, in_len);
1052
 
        if (res < 0) {
1053
 
                wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
1054
 
                           __func__, gnutls_strerror(res));
1055
 
                return -1;
1056
 
        }
1057
 
        if (conn->push_buf == NULL)
1058
 
                return -1;
1059
 
        if (conn->push_buf_len < out_len)
1060
 
                out_len = conn->push_buf_len;
1061
 
        os_memcpy(out_data, conn->push_buf, out_len);
1062
 
        os_free(conn->push_buf);
1063
 
        conn->push_buf = NULL;
1064
 
        conn->push_buf_len = 0;
1065
 
        return out_len;
1066
 
}
1067
 
 
1068
 
 
1069
 
int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
1070
 
                           const u8 *in_data, size_t in_len,
1071
 
                           u8 *out_data, size_t out_len)
1072
 
{
1073
 
        ssize_t res;
1074
 
 
1075
 
        if (conn->pull_buf) {
1076
 
                wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in "
1077
 
                           "pull_buf", __func__, conn->pull_buf_len);
1078
 
                os_free(conn->pull_buf);
1079
 
        }
1080
 
        conn->pull_buf = os_malloc(in_len);
1081
 
        if (conn->pull_buf == NULL)
1082
 
                return -1;
1083
 
        os_memcpy(conn->pull_buf, in_data, in_len);
1084
 
        conn->pull_buf_offset = conn->pull_buf;
1085
 
        conn->pull_buf_len = in_len;
1086
 
 
1087
 
#ifdef GNUTLS_IA
1088
 
        if (conn->tls_ia) {
1089
 
                res = gnutls_ia_recv(conn->session, (char *) out_data,
1090
 
                                     out_len);
1091
 
                if (out_len >= 12 &&
1092
 
                    (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
1093
 
                     res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)) {
1094
 
                        int final = res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED;
1095
 
                        wpa_printf(MSG_DEBUG, "%s: Received %sPhaseFinished",
1096
 
                                   __func__, final ? "Final" : "Intermediate");
1097
 
 
1098
 
                        res = gnutls_ia_permute_inner_secret(
1099
 
                                conn->session, conn->session_keys_len,
1100
 
                                (char *) conn->session_keys);
1101
 
                        if (conn->session_keys) {
1102
 
                                os_memset(conn->session_keys, 0,
1103
 
                                          conn->session_keys_len);
1104
 
                                os_free(conn->session_keys);
1105
 
                        }
1106
 
                        conn->session_keys = NULL;
1107
 
                        conn->session_keys_len = 0;
1108
 
                        if (res) {
1109
 
                                wpa_printf(MSG_DEBUG, "%s: Failed to permute "
1110
 
                                           "inner secret: %s",
1111
 
                                           __func__, gnutls_strerror(res));
1112
 
                                return -1;
1113
 
                        }
1114
 
 
1115
 
                        res = gnutls_ia_verify_endphase(conn->session,
1116
 
                                                        (char *) out_data);
1117
 
                        if (res == 0) {
1118
 
                                wpa_printf(MSG_DEBUG, "%s: Correct endphase "
1119
 
                                           "checksum", __func__);
1120
 
                        } else {
1121
 
                                wpa_printf(MSG_INFO, "%s: Endphase "
1122
 
                                           "verification failed: %s",
1123
 
                                           __func__, gnutls_strerror(res));
1124
 
                                return -1;
1125
 
                        }
1126
 
 
1127
 
                        if (final)
1128
 
                                conn->final_phase_finished = 1;
1129
 
 
1130
 
                        return 0;
1131
 
                }
1132
 
 
1133
 
                if (res < 0) {
1134
 
                        wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d "
1135
 
                                   "(%s)", __func__, res,
1136
 
                                   gnutls_strerror(res));
1137
 
                }
1138
 
                return res;
1139
 
        }
1140
 
#endif /* GNUTLS_IA */
1141
 
 
1142
 
        res = gnutls_record_recv(conn->session, out_data, out_len);
1143
 
        if (res < 0) {
1144
 
                wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
1145
 
                           "(%s)", __func__, res, gnutls_strerror(res));
1146
 
        }
1147
 
 
1148
 
        return res;
1149
 
}
1150
 
 
1151
 
 
1152
 
int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
1153
 
{
1154
 
        if (conn == NULL)
1155
 
                return 0;
1156
 
        return gnutls_session_is_resumed(conn->session);
1157
 
}
1158
 
 
1159
 
 
1160
 
int tls_connection_set_master_key(void *ssl_ctx, struct tls_connection *conn,
1161
 
                                  const u8 *key, size_t key_len)
1162
 
{
1163
 
        /* TODO */
1164
 
        return -1;
1165
 
}
1166
 
 
1167
 
 
1168
 
int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
1169
 
                                   u8 *ciphers)
1170
 
{
1171
 
        /* TODO */
1172
 
        return -1;
1173
 
}
1174
 
 
1175
 
 
1176
 
int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
1177
 
                   char *buf, size_t buflen)
1178
 
{
1179
 
        /* TODO */
1180
 
        buf[0] = '\0';
1181
 
        return 0;
1182
 
}
1183
 
 
1184
 
 
1185
 
int tls_connection_enable_workaround(void *ssl_ctx,
1186
 
                                     struct tls_connection *conn)
1187
 
{
1188
 
        /* TODO: set SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS */
1189
 
        return 0;
1190
 
}
1191
 
 
1192
 
 
1193
 
int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
1194
 
                                    int ext_type, const u8 *data,
1195
 
                                    size_t data_len)
1196
 
{
1197
 
        /* TODO */
1198
 
        return -1;
1199
 
}
1200
 
 
1201
 
 
1202
 
int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
1203
 
{
1204
 
        if (conn == NULL)
1205
 
                return -1;
1206
 
        return conn->failed;
1207
 
}
1208
 
 
1209
 
 
1210
 
int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
1211
 
{
1212
 
        if (conn == NULL)
1213
 
                return -1;
1214
 
        return conn->read_alerts;
1215
 
}
1216
 
 
1217
 
 
1218
 
int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
1219
 
{
1220
 
        if (conn == NULL)
1221
 
                return -1;
1222
 
        return conn->write_alerts;
1223
 
}
1224
 
 
1225
 
 
1226
 
int tls_connection_get_keyblock_size(void *tls_ctx,
1227
 
                                     struct tls_connection *conn)
1228
 
{
1229
 
        /* TODO */
1230
 
        return -1;
1231
 
}
1232
 
 
1233
 
 
1234
 
unsigned int tls_capabilities(void *tls_ctx)
1235
 
{
1236
 
        unsigned int capa = 0;
1237
 
 
1238
 
#ifdef GNUTLS_IA
1239
 
        capa |= TLS_CAPABILITY_IA;
1240
 
#endif /* GNUTLS_IA */
1241
 
 
1242
 
        return capa;
1243
 
}
1244
 
 
1245
 
 
1246
 
int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
1247
 
                          int tls_ia)
1248
 
{
1249
 
#ifdef GNUTLS_IA
1250
 
        int ret;
1251
 
 
1252
 
        if (conn == NULL)
1253
 
                return -1;
1254
 
 
1255
 
        conn->tls_ia = tls_ia;
1256
 
        if (!tls_ia)
1257
 
                return 0;
1258
 
 
1259
 
        ret = gnutls_ia_allocate_server_credentials(&conn->iacred_srv);
1260
 
        if (ret) {
1261
 
                wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s",
1262
 
                           gnutls_strerror(ret));
1263
 
                return -1;
1264
 
        }
1265
 
 
1266
 
        ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA,
1267
 
                                     conn->iacred_srv);
1268
 
        if (ret) {
1269
 
                wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s",
1270
 
                           gnutls_strerror(ret));
1271
 
                gnutls_ia_free_server_credentials(conn->iacred_srv);
1272
 
                conn->iacred_srv = NULL;
1273
 
                return -1;
1274
 
        }
1275
 
 
1276
 
        return 0;
1277
 
#else /* GNUTLS_IA */
1278
 
        return -1;
1279
 
#endif /* GNUTLS_IA */
1280
 
}
1281
 
 
1282
 
 
1283
 
int tls_connection_ia_send_phase_finished(void *tls_ctx,
1284
 
                                          struct tls_connection *conn,
1285
 
                                          int final,
1286
 
                                          u8 *out_data, size_t out_len)
1287
 
{
1288
 
#ifdef GNUTLS_IA
1289
 
        int ret;
1290
 
 
1291
 
        if (conn == NULL || conn->session == NULL || !conn->tls_ia)
1292
 
                return -1;
1293
 
 
1294
 
        ret = gnutls_ia_permute_inner_secret(conn->session,
1295
 
                                             conn->session_keys_len,
1296
 
                                             (char *) conn->session_keys);
1297
 
        if (conn->session_keys) {
1298
 
                os_memset(conn->session_keys, 0, conn->session_keys_len);
1299
 
                os_free(conn->session_keys);
1300
 
        }
1301
 
        conn->session_keys = NULL;
1302
 
        conn->session_keys_len = 0;
1303
 
        if (ret) {
1304
 
                wpa_printf(MSG_DEBUG, "%s: Failed to permute inner secret: %s",
1305
 
                           __func__, gnutls_strerror(ret));
1306
 
                return -1;
1307
 
        }
1308
 
 
1309
 
        ret = gnutls_ia_endphase_send(conn->session, final);
1310
 
        if (ret) {
1311
 
                wpa_printf(MSG_DEBUG, "%s: Failed to send endphase: %s",
1312
 
                           __func__, gnutls_strerror(ret));
1313
 
                return -1;
1314
 
        }
1315
 
 
1316
 
        if (conn->push_buf == NULL)
1317
 
                return -1;
1318
 
        if (conn->push_buf_len < out_len)
1319
 
                out_len = conn->push_buf_len;
1320
 
        os_memcpy(out_data, conn->push_buf, out_len);
1321
 
        os_free(conn->push_buf);
1322
 
        conn->push_buf = NULL;
1323
 
        conn->push_buf_len = 0;
1324
 
        return out_len;
1325
 
#else /* GNUTLS_IA */
1326
 
        return -1;
1327
 
#endif /* GNUTLS_IA */
1328
 
}
1329
 
 
1330
 
 
1331
 
int tls_connection_ia_final_phase_finished(void *tls_ctx,
1332
 
                                           struct tls_connection *conn)
1333
 
{
1334
 
        if (conn == NULL)
1335
 
                return -1;
1336
 
 
1337
 
        return conn->final_phase_finished;
1338
 
}
1339
 
 
1340
 
 
1341
 
int tls_connection_ia_permute_inner_secret(void *tls_ctx,
1342
 
                                           struct tls_connection *conn,
1343
 
                                           const u8 *key, size_t key_len)
1344
 
{
1345
 
#ifdef GNUTLS_IA
1346
 
        if (conn == NULL || !conn->tls_ia)
1347
 
                return -1;
1348
 
 
1349
 
        if (conn->session_keys) {
1350
 
                os_memset(conn->session_keys, 0, conn->session_keys_len);
1351
 
                os_free(conn->session_keys);
1352
 
        }
1353
 
        conn->session_keys_len = 0;
1354
 
 
1355
 
        if (key) {
1356
 
                conn->session_keys = os_malloc(key_len);
1357
 
                if (conn->session_keys == NULL)
1358
 
                        return -1;
1359
 
                os_memcpy(conn->session_keys, key, key_len);
1360
 
                conn->session_keys_len = key_len;
1361
 
        } else {
1362
 
                conn->session_keys = NULL;
1363
 
                conn->session_keys_len = 0;
1364
 
        }
1365
 
 
1366
 
        return 0;
1367
 
#else /* GNUTLS_IA */
1368
 
        return -1;
1369
 
#endif /* GNUTLS_IA */
1370
 
}