wpa_supplicant: update vendor branch to 0.6.10
[dragonfly.git] / contrib / wpa_supplicant-0.4.9 / tls_gnutls.c
1 /*
2  * WPA Supplicant / SSL/TLS interface functions for openssl
3  * Copyright (c) 2004-2006, Jouni Malinen <jkmaline@cc.hut.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 <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <gnutls/gnutls.h>
20 #include <gnutls/x509.h>
21
22 #include "common.h"
23 #include "tls.h"
24
25
26 /*
27  * It looks like gnutls does not provide access to client/server_random and
28  * master_key. This is somewhat unfortunate since these are needed for key
29  * derivation in EAP-{TLS,TTLS,PEAP,FAST}. Workaround for now is a horrible
30  * hack that copies the gnutls_session_int definition from gnutls_int.h so that
31  * we can get the needed information.
32  */
33
34 typedef u8 uint8;
35 #define TLS_RANDOM_SIZE 32
36 #define TLS_MASTER_SIZE 48
37 typedef unsigned char opaque;
38 typedef struct {
39     uint8 suite[2];
40 } cipher_suite_st;
41
42 typedef struct {
43         gnutls_connection_end_t entity;
44         gnutls_kx_algorithm_t kx_algorithm;
45         gnutls_cipher_algorithm_t read_bulk_cipher_algorithm;
46         gnutls_mac_algorithm_t read_mac_algorithm;
47         gnutls_compression_method_t read_compression_algorithm;
48         gnutls_cipher_algorithm_t write_bulk_cipher_algorithm;
49         gnutls_mac_algorithm_t write_mac_algorithm;
50         gnutls_compression_method_t write_compression_algorithm;
51         cipher_suite_st current_cipher_suite;
52         opaque master_secret[TLS_MASTER_SIZE];
53         opaque client_random[TLS_RANDOM_SIZE];
54         opaque server_random[TLS_RANDOM_SIZE];
55         /* followed by stuff we are not interested in */
56 } security_parameters_st;
57
58 struct gnutls_session_int {
59         security_parameters_st security_parameters;
60         /* followed by things we are not interested in */
61 };
62
63 static int tls_gnutls_ref_count = 0;
64
65 struct tls_connection {
66         gnutls_session session;
67         char *subject_match, *altsubject_match;
68         int read_alerts, write_alerts, failed;
69
70         u8 *pre_shared_secret;
71         size_t pre_shared_secret_len;
72         int established;
73         int verify_peer;
74
75         u8 *push_buf, *pull_buf, *pull_buf_offset;
76         size_t push_buf_len, pull_buf_len;
77
78         gnutls_certificate_credentials_t xcred;
79 };
80
81
82 static void tls_log_func(int level, const char *msg)
83 {
84         char *s, *pos;
85         if (level == 6 || level == 7) {
86                 /* These levels seem to be mostly I/O debug and msg dumps */
87                 return;
88         }
89
90         s = strdup(msg);
91         if (s == NULL)
92                 return;
93
94         pos = s;
95         while (*pos != '\0') {
96                 if (*pos == '\n') {
97                         *pos = '\0';
98                         break;
99                 }
100                 pos++;
101         }
102         wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG,
103                    "gnutls<%d> %s", level, s);
104         free(s);
105 }
106
107
108 extern int wpa_debug_show_keys;
109
110 void * tls_init(const struct tls_config *conf)
111 {
112         /* Because of the horrible hack to get master_secret and client/server
113          * random, we need to make sure that the gnutls version is something
114          * that is expected to have same structure definition for the session
115          * data.. */
116         const char *ver;
117         const char *ok_ver[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", NULL };
118         int i;
119
120         if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0)
121                 return NULL;
122         tls_gnutls_ref_count++;
123
124         ver = gnutls_check_version(NULL);
125         if (ver == NULL)
126                 return NULL;
127         wpa_printf(MSG_DEBUG, "%s - gnutls version %s", __func__, ver);
128         for (i = 0; ok_ver[i]; i++) {
129                 if (strcmp(ok_ver[i], ver) == 0)
130                         break;
131         }
132         if (ok_ver[i] == NULL) {
133                 wpa_printf(MSG_INFO, "Untested gnutls version %s - this needs "
134                            "to be tested and enabled in tls_gnutls.c", ver);
135                 return NULL;
136         }
137
138         gnutls_global_set_log_function(tls_log_func);
139         if (wpa_debug_show_keys)
140                 gnutls_global_set_log_level(11);
141         return (void *) 1;
142 }
143
144
145 void tls_deinit(void *ssl_ctx)
146 {
147         tls_gnutls_ref_count--;
148         if (tls_gnutls_ref_count == 0)
149                 gnutls_global_deinit();
150 }
151
152
153 int tls_get_errors(void *ssl_ctx)
154 {
155         return 0;
156 }
157
158
159 static ssize_t tls_pull_func(gnutls_transport_ptr ptr, void *buf,
160                              size_t len)
161 {
162         struct tls_connection *conn = (struct tls_connection *) ptr;
163         u8 *end;
164         if (conn->pull_buf == NULL) {
165                 errno = EWOULDBLOCK;
166                 return -1;
167         }
168
169         end = conn->pull_buf + conn->pull_buf_len;
170         if (end - conn->pull_buf_offset < len)
171                 len = end - conn->pull_buf_offset;
172         memcpy(buf, conn->pull_buf_offset, len);
173         conn->pull_buf_offset += len;
174         if (conn->pull_buf_offset == end) {
175                 wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
176                 free(conn->pull_buf);
177                 conn->pull_buf = conn->pull_buf_offset = NULL;
178                 conn->pull_buf_len = 0;
179         } else {
180                 wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in pull_buf",
181                            __func__, end - conn->pull_buf_offset);
182         }
183         return len;
184 }
185
186
187 static ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf,
188                              size_t len)
189 {
190         struct tls_connection *conn = (struct tls_connection *) ptr;
191         u8 *nbuf;
192
193         nbuf = realloc(conn->push_buf, conn->push_buf_len + len);
194         if (nbuf == NULL) {
195                 errno = ENOMEM;
196                 return -1;
197         }
198         memcpy(nbuf + conn->push_buf_len, buf, len);
199         conn->push_buf = nbuf;
200         conn->push_buf_len += len;
201
202         return len;
203 }
204
205
206 struct tls_connection * tls_connection_init(void *ssl_ctx)
207 {
208         struct tls_connection *conn;
209         const int cert_types[2] = { GNUTLS_CRT_X509, 0 };
210         const int protos[2] = { GNUTLS_TLS1, 0 };
211
212
213         conn = malloc(sizeof(*conn));
214         if (conn == NULL)
215                 return NULL;
216         memset(conn, 0, sizeof(*conn));
217         if (gnutls_init(&conn->session, GNUTLS_CLIENT) < 0) {
218                 wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS "
219                            "connection");
220                 free(conn);
221                 return NULL;
222         }
223
224         gnutls_set_default_priority(conn->session);
225         gnutls_certificate_type_set_priority(conn->session, cert_types);
226         gnutls_protocol_set_priority(conn->session, protos);
227
228         gnutls_transport_set_pull_function(conn->session, tls_pull_func);
229         gnutls_transport_set_push_function(conn->session, tls_push_func);
230         gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn);
231
232         gnutls_certificate_allocate_credentials(&conn->xcred);
233
234         return conn;
235 }
236
237
238 void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
239 {
240         if (conn == NULL)
241                 return;
242         gnutls_certificate_free_credentials(conn->xcred);
243         gnutls_deinit(conn->session);
244         free(conn->pre_shared_secret);
245         free(conn->subject_match);
246         free(conn->altsubject_match);
247         free(conn->push_buf);
248         free(conn->pull_buf);
249         free(conn);
250 }
251
252
253 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
254 {
255         return conn ? conn->established : 0;
256 }
257
258
259 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
260 {
261         if (conn == NULL)
262                 return -1;
263
264         /* Shutdown previous TLS connection without notifying the peer
265          * because the connection was already terminated in practice
266          * and "close notify" shutdown alert would confuse AS. */
267         gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
268         free(conn->push_buf);
269         conn->push_buf = NULL;
270         conn->push_buf_len = 0;
271         conn->established = 0;
272         /* TODO: what to do trigger new handshake for re-auth? */
273         return 0;
274 }
275
276
277 #if 0
278 static int tls_match_altsubject(X509 *cert, const char *match)
279 {
280         GENERAL_NAME *gen;
281         char *field, *tmp;
282         void *ext;
283         int i, found = 0;
284         size_t len;
285
286         ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
287
288         for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
289                 gen = sk_GENERAL_NAME_value(ext, i);
290                 switch (gen->type) {
291                 case GEN_EMAIL:
292                         field = "EMAIL";
293                         break;
294                 case GEN_DNS:
295                         field = "DNS";
296                         break;
297                 case GEN_URI:
298                         field = "URI";
299                         break;
300                 default:
301                         field = NULL;
302                         wpa_printf(MSG_DEBUG, "TLS: altSubjectName: "
303                                    "unsupported type=%d", gen->type);
304                         break;
305                 }
306
307                 if (!field)
308                         continue;
309
310                 wpa_printf(MSG_DEBUG, "TLS: altSubjectName: %s:%s",
311                            field, gen->d.ia5->data);
312                 len = strlen(field) + 1 + strlen((char *) gen->d.ia5->data) +
313                         1;
314                 tmp = malloc(len);
315                 if (tmp == NULL)
316                         continue;
317                 snprintf(tmp, len, "%s:%s", field, gen->d.ia5->data);
318                 if (strstr(tmp, match))
319                         found++;
320                 free(tmp);
321         }
322
323         return found;
324 }
325 #endif
326
327
328 #if 0
329 static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
330 {
331         char buf[256];
332         X509 *err_cert;
333         int err, depth;
334         SSL *ssl;
335         struct tls_connection *conn;
336         char *match, *altmatch;
337
338         err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
339         err = X509_STORE_CTX_get_error(x509_ctx);
340         depth = X509_STORE_CTX_get_error_depth(x509_ctx);
341         ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
342                                          SSL_get_ex_data_X509_STORE_CTX_idx());
343         X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
344
345         conn = SSL_get_app_data(ssl);
346         match = conn ? conn->subject_match : NULL;
347         altmatch = conn ? conn->altsubject_match : NULL;
348
349         if (!preverify_ok) {
350                 wpa_printf(MSG_WARNING, "TLS: Certificate verification failed,"
351                            " error %d (%s) depth %d for '%s'", err,
352                            X509_verify_cert_error_string(err), depth, buf);
353         } else {
354                 wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - "
355                            "preverify_ok=%d err=%d (%s) depth=%d buf='%s'",
356                            preverify_ok, err,
357                            X509_verify_cert_error_string(err), depth, buf);
358                 if (depth == 0 && match && strstr(buf, match) == NULL) {
359                         wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
360                                    "match with '%s'", buf, match);
361                         preverify_ok = 0;
362                 } else if (depth == 0 && altmatch &&
363                            !tls_match_altsubject(err_cert, altmatch)) {
364                         wpa_printf(MSG_WARNING, "TLS: altSubjectName match "
365                                    "'%s' not found", altmatch);
366                         preverify_ok = 0;
367                 }
368         }
369
370         return preverify_ok;
371 }
372 #endif
373
374
375 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
376                               const struct tls_connection_params *params)
377 {
378         int ret;
379
380         if (conn == NULL || params == NULL)
381                 return -1;
382
383         free(conn->subject_match);
384         conn->subject_match = NULL;
385         if (params->subject_match) {
386                 conn->subject_match = strdup(params->subject_match);
387                 if (conn->subject_match == NULL)
388                         return -1;
389         }
390
391         free(conn->altsubject_match);
392         conn->altsubject_match = NULL;
393         if (params->altsubject_match) {
394                 conn->altsubject_match = strdup(params->altsubject_match);
395                 if (conn->altsubject_match == NULL)
396                         return -1;
397         }
398
399         /* TODO: gnutls_certificate_set_verify_flags(xcred, flags); 
400          * to force peer validation(?) */
401
402         if (params->ca_cert) {
403                 conn->verify_peer = 1;
404                 ret = gnutls_certificate_set_x509_trust_file(
405                         conn->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM);
406                 if (ret < 0) {
407                         wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
408                                    "in PEM format: %s", params->ca_cert,
409                                    gnutls_strerror(ret));
410                         ret = gnutls_certificate_set_x509_trust_file(
411                                 conn->xcred, params->ca_cert,
412                                 GNUTLS_X509_FMT_DER);
413                         if (ret < 0) {
414                                 wpa_printf(MSG_DEBUG, "Failed to read CA cert "
415                                            "'%s' in DER format: %s",
416                                            params->ca_cert,
417                                            gnutls_strerror(ret));
418                         }
419                 }
420         }
421
422         if (params->client_cert && params->private_key) {
423                 /* TODO: private_key_passwd? */
424                 ret = gnutls_certificate_set_x509_key_file(
425                         conn->xcred, params->client_cert, params->private_key,
426                         GNUTLS_X509_FMT_PEM);
427                 if (ret < 0) {
428                         wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
429                                    "in PEM format: %s", gnutls_strerror(ret));
430                         ret = gnutls_certificate_set_x509_key_file(
431                                 conn->xcred, params->client_cert,
432                                 params->private_key, GNUTLS_X509_FMT_DER);
433                         if (ret < 0) {
434                                 wpa_printf(MSG_DEBUG, "Failed to read client "
435                                            "cert/key in DER format: %s",
436                                            gnutls_strerror(ret));
437                                 return ret;
438                         }
439                 }
440         }
441
442         ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
443                                      conn->xcred);
444         if (ret < 0) {
445                 wpa_printf(MSG_INFO, "Failed to configure credentials: %s",
446                            gnutls_strerror(ret));
447         }
448
449         return ret;
450 }
451
452
453 int tls_global_ca_cert(void *_ssl_ctx, const char *ca_cert)
454 {
455         /* TODO */
456         return -1;
457 }
458
459
460 int tls_global_set_verify(void *ssl_ctx, int check_crl)
461 {
462         /* TODO */
463         return -1;
464 }
465
466
467 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
468                               int verify_peer)
469 {
470         if (conn == NULL)
471                 return -1;
472
473         /* TODO */
474
475         return 1;
476 }
477
478
479 int tls_global_client_cert(void *_ssl_ctx, const char *client_cert)
480 {
481         /* TODO */
482         return -1;
483 }
484
485
486 int tls_global_private_key(void *_ssl_ctx, const char *private_key,
487                            const char *private_key_passwd)
488 {
489         /* TODO */
490         return -1;
491 }
492
493
494 int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
495                             struct tls_keys *keys)
496 {
497         security_parameters_st *sec;
498
499         if (conn == NULL || conn->session == NULL || keys == NULL)
500                 return -1;
501
502         memset(keys, 0, sizeof(*keys));
503         sec = &conn->session->security_parameters;
504         keys->master_key = sec->master_secret;
505         keys->master_key_len = TLS_MASTER_SIZE;
506         keys->client_random = sec->client_random;
507         keys->client_random_len = TLS_RANDOM_SIZE;
508         keys->server_random = sec->server_random;
509         keys->server_random_len = TLS_RANDOM_SIZE;
510
511         return 0;
512 }
513
514
515 static int tls_connection_verify_peer(struct tls_connection *conn)
516 {
517         unsigned int status, num_certs, i;
518         time_t now;
519         const gnutls_datum_t *certs;
520         gnutls_x509_crt_t cert;
521
522         if (gnutls_certificate_verify_peers2(conn->session, &status) < 0) {
523                 wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
524                            "certificate chain");
525                 return -1;
526         }
527
528         if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
529                 wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
530                 return -1;
531         }
532
533         if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
534                 wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
535                            "known issuer");
536                 return -1;
537         }
538
539         if (status & GNUTLS_CERT_REVOKED) {
540                 wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
541                 return -1;
542         }
543
544         now = time(NULL);
545
546         certs = gnutls_certificate_get_peers(conn->session, &num_certs);
547         if (certs == NULL) {
548                 wpa_printf(MSG_INFO, "TLS: No peer certificate chain "
549                            "received");
550                 return -1;
551         }
552
553         for (i = 0; i < num_certs; i++) {
554                 char *buf;
555                 size_t len;
556                 if (gnutls_x509_crt_init(&cert) < 0) {
557                         wpa_printf(MSG_INFO, "TLS: Certificate initialization "
558                                    "failed");
559                         return -1;
560                 }
561
562                 if (gnutls_x509_crt_import(cert, &certs[i],
563                                            GNUTLS_X509_FMT_DER) < 0) {
564                         wpa_printf(MSG_INFO, "TLS: Could not parse peer "
565                                    "certificate %d/%d", i + 1, num_certs);
566                         gnutls_x509_crt_deinit(cert);
567                         return -1;
568                 }
569
570                 gnutls_x509_crt_get_dn(cert, NULL, &len);
571                 len++;
572                 buf = malloc(len + 1);
573                 if (buf) {
574                         buf[0] = buf[len] = '\0';
575                         gnutls_x509_crt_get_dn(cert, buf, &len);
576                 }
577                 wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
578                            i + 1, num_certs, buf);
579
580                 if (i == 0) {
581                         /* TODO: validate subject_match and altsubject_match */
582                 }
583
584                 free(buf);
585
586                 if (gnutls_x509_crt_get_expiration_time(cert) < now ||
587                     gnutls_x509_crt_get_activation_time(cert) > now) {
588                         wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
589                                    "not valid at this time",
590                                    i + 1, num_certs);
591                         gnutls_x509_crt_deinit(cert);
592                         return -1;
593                 }
594
595                 gnutls_x509_crt_deinit(cert);
596         }
597
598         return 0;
599 }
600
601
602 u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
603                               const u8 *in_data, size_t in_len,
604                               size_t *out_len)
605 {
606         u8 *out_data;
607         int ret;
608
609         if (in_data && in_len) {
610                 if (conn->pull_buf) {
611                         wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in "
612                                    "pull_buf", __func__, conn->pull_buf_len);
613                         free(conn->pull_buf);
614                 }
615                 conn->pull_buf = malloc(in_len);
616                 if (conn->pull_buf == NULL)
617                         return NULL;
618                 memcpy(conn->pull_buf, in_data, in_len);
619                 conn->pull_buf_offset = conn->pull_buf;
620                 conn->pull_buf_len = in_len;
621         }
622
623         ret = gnutls_handshake(conn->session);
624         if (ret < 0) {
625                 switch (ret) {
626                 case GNUTLS_E_AGAIN:
627                         break;
628                 case GNUTLS_E_FATAL_ALERT_RECEIVED:
629                         wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
630                                    __func__, gnutls_alert_get_name(
631                                            gnutls_alert_get(conn->session)));
632                         conn->read_alerts++;
633                         /* continue */
634                 default:
635                         wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
636                                    "-> %s", __func__, gnutls_strerror(ret));
637                         conn->failed++;
638                 }
639         } else {
640                 wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
641                 if (conn->verify_peer && tls_connection_verify_peer(conn)) {
642                         wpa_printf(MSG_INFO, "TLS: Peer certificate chain "
643                                    "failed validation");
644                         conn->failed++;
645                         return NULL;
646                 }
647                 conn->established = 1;
648                 if (conn->push_buf == NULL) {
649                         /* Need to return something to get final TLS ACK. */
650                         conn->push_buf = malloc(1);
651                 }
652         }
653
654         out_data = conn->push_buf;
655         *out_len = conn->push_buf_len;
656         conn->push_buf = NULL;
657         conn->push_buf_len = 0;
658         return out_data;
659 }
660
661
662 u8 * tls_connection_server_handshake(void *ssl_ctx,
663                                      struct tls_connection *conn,
664                                      const u8 *in_data, size_t in_len,
665                                      size_t *out_len)
666 {
667         /* TODO */
668         return NULL;
669 }
670
671
672 int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
673                            const u8 *in_data, size_t in_len,
674                            u8 *out_data, size_t out_len)
675 {
676         ssize_t res;
677         res = gnutls_record_send(conn->session, in_data, in_len);
678         if (conn->push_buf == NULL)
679                 return -1;
680         if (conn->push_buf_len < out_len)
681                 out_len = conn->push_buf_len;
682         memcpy(out_data, conn->push_buf, out_len);
683         free(conn->push_buf);
684         conn->push_buf = NULL;
685         conn->push_buf_len = 0;
686         return out_len;
687 }
688
689
690 int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
691                            const u8 *in_data, size_t in_len,
692                            u8 *out_data, size_t out_len)
693 {
694         ssize_t res;
695
696         if (conn->pull_buf) {
697                 wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in "
698                            "pull_buf", __func__, conn->pull_buf_len);
699                 free(conn->pull_buf);
700         }
701         conn->pull_buf = malloc(in_len);
702         if (conn->pull_buf == NULL)
703                 return -1;
704         memcpy(conn->pull_buf, in_data, in_len);
705         conn->pull_buf_offset = conn->pull_buf;
706         conn->pull_buf_len = in_len;
707
708         res = gnutls_record_recv(conn->session, out_data, out_len);
709         if (res < 0) {
710                 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
711                            "(%s)", __func__, res, gnutls_strerror(res));
712         }
713
714         return res;
715 }
716
717
718 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
719 {
720         if (conn == NULL)
721                 return 0;
722         return gnutls_session_is_resumed(conn->session);
723 }
724
725
726 #ifdef EAP_FAST
727 int tls_connection_set_master_key(void *ssl_ctx, struct tls_connection *conn,
728                                   const u8 *key, size_t key_len)
729 {
730         /* TODO */
731         return -1;
732 }
733 #endif /* EAP_FAST */
734
735
736 int tls_connection_set_anon_dh(void *ssl_ctx, struct tls_connection *conn)
737 {
738         /* TODO: set ADH-AES128-SHA cipher */
739         return -1;
740 }
741
742
743 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
744                    char *buf, size_t buflen)
745 {
746         /* TODO */
747         buf[0] = '\0';
748         return 0;
749 }
750
751
752 int tls_connection_enable_workaround(void *ssl_ctx,
753                                      struct tls_connection *conn)
754 {
755         /* TODO: set SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS */
756         return 0;
757 }
758
759
760 #ifdef EAP_FAST
761 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
762                                     int ext_type, const u8 *data,
763                                     size_t data_len)
764 {
765         /* TODO */
766         return -1;
767 }
768 #endif /* EAP_FAST */
769
770
771 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
772 {
773         if (conn == NULL)
774                 return -1;
775         return conn->failed;
776 }
777
778
779 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
780 {
781         if (conn == NULL)
782                 return -1;
783         return conn->read_alerts;
784 }
785
786
787 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
788 {
789         if (conn == NULL)
790                 return -1;
791         return conn->write_alerts;
792 }