Updated to hostap_2_6
[mech_eap.git] / libeap / src / crypto / tls_gnutls.c
1 /*
2  * SSL/TLS interface functions for GnuTLS
3  * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "includes.h"
10 #include <gnutls/gnutls.h>
11 #include <gnutls/x509.h>
12 #ifdef PKCS12_FUNCS
13 #include <gnutls/pkcs12.h>
14 #endif /* PKCS12_FUNCS */
15 #if GNUTLS_VERSION_NUMBER >= 0x030103
16 #include <gnutls/ocsp.h>
17 #endif /* 3.1.3 */
18
19 #include "common.h"
20 #include "crypto/crypto.h"
21 #include "tls.h"
22
23
24 static int tls_gnutls_ref_count = 0;
25
26 struct tls_global {
27         /* Data for session resumption */
28         void *session_data;
29         size_t session_data_size;
30
31         int server;
32
33         int params_set;
34         gnutls_certificate_credentials_t xcred;
35
36         void (*event_cb)(void *ctx, enum tls_event ev,
37                          union tls_event_data *data);
38         void *cb_ctx;
39         int cert_in_cb;
40
41         char *ocsp_stapling_response;
42 };
43
44 struct tls_connection {
45         struct tls_global *global;
46         gnutls_session_t session;
47         int read_alerts, write_alerts, failed;
48
49         u8 *pre_shared_secret;
50         size_t pre_shared_secret_len;
51         int established;
52         int verify_peer;
53         unsigned int disable_time_checks:1;
54
55         struct wpabuf *push_buf;
56         struct wpabuf *pull_buf;
57         const u8 *pull_buf_offset;
58
59         int params_set;
60         gnutls_certificate_credentials_t xcred;
61
62         char *suffix_match;
63         char *domain_match;
64         unsigned int flags;
65 };
66
67
68 static int tls_connection_verify_peer(gnutls_session_t session);
69
70
71 static void tls_log_func(int level, const char *msg)
72 {
73         char *s, *pos;
74         if (level == 6 || level == 7) {
75                 /* These levels seem to be mostly I/O debug and msg dumps */
76                 return;
77         }
78
79         s = os_strdup(msg);
80         if (s == NULL)
81                 return;
82
83         pos = s;
84         while (*pos != '\0') {
85                 if (*pos == '\n') {
86                         *pos = '\0';
87                         break;
88                 }
89                 pos++;
90         }
91         wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG,
92                    "gnutls<%d> %s", level, s);
93         os_free(s);
94 }
95
96
97 void * tls_init(const struct tls_config *conf)
98 {
99         struct tls_global *global;
100
101         if (tls_gnutls_ref_count == 0) {
102                 wpa_printf(MSG_DEBUG,
103                            "GnuTLS: Library version %s (runtime) - %s (build)",
104                            gnutls_check_version(NULL), GNUTLS_VERSION);
105         }
106
107         global = os_zalloc(sizeof(*global));
108         if (global == NULL)
109                 return NULL;
110
111         if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) {
112                 os_free(global);
113                 return NULL;
114         }
115         tls_gnutls_ref_count++;
116
117         gnutls_global_set_log_function(tls_log_func);
118         if (wpa_debug_show_keys)
119                 gnutls_global_set_log_level(11);
120
121         if (conf) {
122                 global->event_cb = conf->event_cb;
123                 global->cb_ctx = conf->cb_ctx;
124                 global->cert_in_cb = conf->cert_in_cb;
125         }
126
127         return global;
128 }
129
130
131 void tls_deinit(void *ssl_ctx)
132 {
133         struct tls_global *global = ssl_ctx;
134         if (global) {
135                 if (global->params_set)
136                         gnutls_certificate_free_credentials(global->xcred);
137                 os_free(global->session_data);
138                 os_free(global->ocsp_stapling_response);
139                 os_free(global);
140         }
141
142         tls_gnutls_ref_count--;
143         if (tls_gnutls_ref_count == 0)
144                 gnutls_global_deinit();
145 }
146
147
148 int tls_get_errors(void *ssl_ctx)
149 {
150         return 0;
151 }
152
153
154 static ssize_t tls_pull_func(gnutls_transport_ptr_t ptr, void *buf,
155                              size_t len)
156 {
157         struct tls_connection *conn = (struct tls_connection *) ptr;
158         const u8 *end;
159         if (conn->pull_buf == NULL) {
160                 errno = EWOULDBLOCK;
161                 return -1;
162         }
163
164         end = wpabuf_head_u8(conn->pull_buf) + wpabuf_len(conn->pull_buf);
165         if ((size_t) (end - conn->pull_buf_offset) < len)
166                 len = end - conn->pull_buf_offset;
167         os_memcpy(buf, conn->pull_buf_offset, len);
168         conn->pull_buf_offset += len;
169         if (conn->pull_buf_offset == end) {
170                 wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
171                 wpabuf_free(conn->pull_buf);
172                 conn->pull_buf = NULL;
173                 conn->pull_buf_offset = NULL;
174         } else {
175                 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf",
176                            __func__,
177                            (unsigned long) (end - conn->pull_buf_offset));
178         }
179         return len;
180 }
181
182
183 static ssize_t tls_push_func(gnutls_transport_ptr_t ptr, const void *buf,
184                              size_t len)
185 {
186         struct tls_connection *conn = (struct tls_connection *) ptr;
187
188         if (wpabuf_resize(&conn->push_buf, len) < 0) {
189                 errno = ENOMEM;
190                 return -1;
191         }
192         wpabuf_put_data(conn->push_buf, buf, len);
193
194         return len;
195 }
196
197
198 static int tls_gnutls_init_session(struct tls_global *global,
199                                    struct tls_connection *conn)
200 {
201         const char *err;
202         int ret;
203
204         ret = gnutls_init(&conn->session,
205                           global->server ? GNUTLS_SERVER : GNUTLS_CLIENT);
206         if (ret < 0) {
207                 wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS "
208                            "connection: %s", gnutls_strerror(ret));
209                 return -1;
210         }
211
212         ret = gnutls_set_default_priority(conn->session);
213         if (ret < 0)
214                 goto fail;
215
216         ret = gnutls_priority_set_direct(conn->session, "NORMAL:-VERS-SSL3.0",
217                                          &err);
218         if (ret < 0) {
219                 wpa_printf(MSG_ERROR, "GnuTLS: Priority string failure at "
220                            "'%s'", err);
221                 goto fail;
222         }
223
224         gnutls_transport_set_pull_function(conn->session, tls_pull_func);
225         gnutls_transport_set_push_function(conn->session, tls_push_func);
226         gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr_t) conn);
227         gnutls_session_set_ptr(conn->session, conn);
228
229         return 0;
230
231 fail:
232         wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s",
233                    gnutls_strerror(ret));
234         gnutls_deinit(conn->session);
235         return -1;
236 }
237
238
239 struct tls_connection * tls_connection_init(void *ssl_ctx)
240 {
241         struct tls_global *global = ssl_ctx;
242         struct tls_connection *conn;
243         int ret;
244
245         conn = os_zalloc(sizeof(*conn));
246         if (conn == NULL)
247                 return NULL;
248         conn->global = global;
249
250         if (tls_gnutls_init_session(global, conn)) {
251                 os_free(conn);
252                 return NULL;
253         }
254
255         if (global->params_set) {
256                 ret = gnutls_credentials_set(conn->session,
257                                              GNUTLS_CRD_CERTIFICATE,
258                                              global->xcred);
259                 if (ret < 0) {
260                         wpa_printf(MSG_INFO, "Failed to configure "
261                                    "credentials: %s", gnutls_strerror(ret));
262                         os_free(conn);
263                         return NULL;
264                 }
265         }
266
267         if (gnutls_certificate_allocate_credentials(&conn->xcred)) {
268                 os_free(conn);
269                 return NULL;
270         }
271
272         return conn;
273 }
274
275
276 void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
277 {
278         if (conn == NULL)
279                 return;
280
281         gnutls_certificate_free_credentials(conn->xcred);
282         gnutls_deinit(conn->session);
283         os_free(conn->pre_shared_secret);
284         wpabuf_free(conn->push_buf);
285         wpabuf_free(conn->pull_buf);
286         os_free(conn->suffix_match);
287         os_free(conn->domain_match);
288         os_free(conn);
289 }
290
291
292 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
293 {
294         return conn ? conn->established : 0;
295 }
296
297
298 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
299 {
300         struct tls_global *global = ssl_ctx;
301         int ret;
302
303         if (conn == NULL)
304                 return -1;
305
306         /* Shutdown previous TLS connection without notifying the peer
307          * because the connection was already terminated in practice
308          * and "close notify" shutdown alert would confuse AS. */
309         gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
310         wpabuf_free(conn->push_buf);
311         conn->push_buf = NULL;
312         conn->established = 0;
313
314         gnutls_deinit(conn->session);
315         if (tls_gnutls_init_session(global, conn)) {
316                 wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session "
317                            "for session resumption use");
318                 return -1;
319         }
320
321         ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
322                                      conn->params_set ? conn->xcred :
323                                      global->xcred);
324         if (ret < 0) {
325                 wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials "
326                            "for session resumption: %s", gnutls_strerror(ret));
327                 return -1;
328         }
329
330         if (global->session_data) {
331                 ret = gnutls_session_set_data(conn->session,
332                                               global->session_data,
333                                               global->session_data_size);
334                 if (ret < 0) {
335                         wpa_printf(MSG_INFO, "GnuTLS: Failed to set session "
336                                    "data: %s", gnutls_strerror(ret));
337                         return -1;
338                 }
339         }
340
341         return 0;
342 }
343
344
345 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
346                               const struct tls_connection_params *params)
347 {
348         int ret;
349
350         if (conn == NULL || params == NULL)
351                 return -1;
352
353         if (params->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
354                 wpa_printf(MSG_INFO,
355                            "GnuTLS: ocsp=3 not supported");
356                 return -1;
357         }
358
359         if (params->flags & TLS_CONN_EXT_CERT_CHECK) {
360                 wpa_printf(MSG_INFO,
361                            "GnuTLS: tls_ext_cert_check=1 not supported");
362                 return -1;
363         }
364
365         if (params->subject_match) {
366                 wpa_printf(MSG_INFO, "GnuTLS: subject_match not supported");
367                 return -1;
368         }
369
370         if (params->altsubject_match) {
371                 wpa_printf(MSG_INFO, "GnuTLS: altsubject_match not supported");
372                 return -1;
373         }
374
375         os_free(conn->suffix_match);
376         conn->suffix_match = NULL;
377         if (params->suffix_match) {
378                 conn->suffix_match = os_strdup(params->suffix_match);
379                 if (conn->suffix_match == NULL)
380                         return -1;
381         }
382
383 #if GNUTLS_VERSION_NUMBER >= 0x030300
384         os_free(conn->domain_match);
385         conn->domain_match = NULL;
386         if (params->domain_match) {
387                 conn->domain_match = os_strdup(params->domain_match);
388                 if (conn->domain_match == NULL)
389                         return -1;
390         }
391 #else /* < 3.3.0 */
392         if (params->domain_match) {
393                 wpa_printf(MSG_INFO, "GnuTLS: domain_match not supported");
394                 return -1;
395         }
396 #endif /* >= 3.3.0 */
397
398         conn->flags = params->flags;
399
400         if (params->openssl_ciphers) {
401                 wpa_printf(MSG_INFO, "GnuTLS: openssl_ciphers not supported");
402                 return -1;
403         }
404
405         /* TODO: gnutls_certificate_set_verify_flags(xcred, flags); 
406          * to force peer validation(?) */
407
408         if (params->ca_cert) {
409                 wpa_printf(MSG_DEBUG, "GnuTLS: Try to parse %s in DER format",
410                            params->ca_cert);
411                 ret = gnutls_certificate_set_x509_trust_file(
412                         conn->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
413                 if (ret < 0) {
414                         wpa_printf(MSG_DEBUG,
415                                    "GnuTLS: Failed to read CA cert '%s' in DER format (%s) - try in PEM format",
416                                    params->ca_cert,
417                                    gnutls_strerror(ret));
418                         ret = gnutls_certificate_set_x509_trust_file(
419                                 conn->xcred, params->ca_cert,
420                                 GNUTLS_X509_FMT_PEM);
421                         if (ret < 0) {
422                                 wpa_printf(MSG_DEBUG,
423                                            "Failed to read CA cert '%s' in PEM format: %s",
424                                            params->ca_cert,
425                                            gnutls_strerror(ret));
426                                 return -1;
427                         }
428                 }
429         } else if (params->ca_cert_blob) {
430                 gnutls_datum_t ca;
431
432                 ca.data = (unsigned char *) params->ca_cert_blob;
433                 ca.size = params->ca_cert_blob_len;
434
435                 ret = gnutls_certificate_set_x509_trust_mem(
436                         conn->xcred, &ca, GNUTLS_X509_FMT_DER);
437                 if (ret < 0) {
438                         wpa_printf(MSG_DEBUG,
439                                    "Failed to parse CA cert in DER format: %s",
440                                    gnutls_strerror(ret));
441                         ret = gnutls_certificate_set_x509_trust_mem(
442                                 conn->xcred, &ca, GNUTLS_X509_FMT_PEM);
443                         if (ret < 0) {
444                                 wpa_printf(MSG_DEBUG,
445                                            "Failed to parse CA cert in PEM format: %s",
446                                            gnutls_strerror(ret));
447                                 return -1;
448                         }
449                 }
450         } else if (params->ca_path) {
451                 wpa_printf(MSG_INFO, "GnuTLS: ca_path not supported");
452                 return -1;
453         }
454
455         conn->disable_time_checks = 0;
456         if (params->ca_cert || params->ca_cert_blob) {
457                 conn->verify_peer = 1;
458                 gnutls_certificate_set_verify_function(
459                         conn->xcred, tls_connection_verify_peer);
460
461                 if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
462                         gnutls_certificate_set_verify_flags(
463                                 conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
464                 }
465
466                 if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
467                         conn->disable_time_checks = 1;
468                         gnutls_certificate_set_verify_flags(
469                                 conn->xcred,
470                                 GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
471                 }
472         }
473
474         if (params->client_cert && params->private_key) {
475 #if GNUTLS_VERSION_NUMBER >= 0x03010b
476                 ret = gnutls_certificate_set_x509_key_file2(
477                         conn->xcred, params->client_cert, params->private_key,
478                         GNUTLS_X509_FMT_DER, params->private_key_passwd, 0);
479 #else
480                 /* private_key_passwd not (easily) supported here */
481                 ret = gnutls_certificate_set_x509_key_file(
482                         conn->xcred, params->client_cert, params->private_key,
483                         GNUTLS_X509_FMT_DER);
484 #endif
485                 if (ret < 0) {
486                         wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
487                                    "in DER format: %s", gnutls_strerror(ret));
488 #if GNUTLS_VERSION_NUMBER >= 0x03010b
489                         ret = gnutls_certificate_set_x509_key_file2(
490                                 conn->xcred, params->client_cert,
491                                 params->private_key, GNUTLS_X509_FMT_PEM,
492                                 params->private_key_passwd, 0);
493 #else
494                         ret = gnutls_certificate_set_x509_key_file(
495                                 conn->xcred, params->client_cert,
496                                 params->private_key, GNUTLS_X509_FMT_PEM);
497 #endif
498                         if (ret < 0) {
499                                 wpa_printf(MSG_DEBUG, "Failed to read client "
500                                            "cert/key in PEM format: %s",
501                                            gnutls_strerror(ret));
502                                 return ret;
503                         }
504                 }
505         } else if (params->private_key) {
506                 int pkcs12_ok = 0;
507 #ifdef PKCS12_FUNCS
508                 /* Try to load in PKCS#12 format */
509                 ret = gnutls_certificate_set_x509_simple_pkcs12_file(
510                         conn->xcred, params->private_key, GNUTLS_X509_FMT_DER,
511                         params->private_key_passwd);
512                 if (ret != 0) {
513                         wpa_printf(MSG_DEBUG, "Failed to load private_key in "
514                                    "PKCS#12 format: %s", gnutls_strerror(ret));
515                         return -1;
516                 } else
517                         pkcs12_ok = 1;
518 #endif /* PKCS12_FUNCS */
519
520                 if (!pkcs12_ok) {
521                         wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
522                                    "included");
523                         return -1;
524                 }
525         } else if (params->client_cert_blob && params->private_key_blob) {
526                 gnutls_datum_t cert, key;
527
528                 cert.data = (unsigned char *) params->client_cert_blob;
529                 cert.size = params->client_cert_blob_len;
530                 key.data = (unsigned char *) params->private_key_blob;
531                 key.size = params->private_key_blob_len;
532
533 #if GNUTLS_VERSION_NUMBER >= 0x03010b
534                 ret = gnutls_certificate_set_x509_key_mem2(
535                         conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER,
536                         params->private_key_passwd, 0);
537 #else
538                 /* private_key_passwd not (easily) supported here */
539                 ret = gnutls_certificate_set_x509_key_mem(
540                         conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER);
541 #endif
542                 if (ret < 0) {
543                         wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
544                                    "in DER format: %s", gnutls_strerror(ret));
545 #if GNUTLS_VERSION_NUMBER >= 0x03010b
546                         ret = gnutls_certificate_set_x509_key_mem2(
547                                 conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM,
548                                 params->private_key_passwd, 0);
549 #else
550                         /* private_key_passwd not (easily) supported here */
551                         ret = gnutls_certificate_set_x509_key_mem(
552                                 conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM);
553 #endif
554                         if (ret < 0) {
555                                 wpa_printf(MSG_DEBUG, "Failed to read client "
556                                            "cert/key in PEM format: %s",
557                                            gnutls_strerror(ret));
558                                 return ret;
559                         }
560                 }
561         } else if (params->private_key_blob) {
562 #ifdef PKCS12_FUNCS
563                 gnutls_datum_t key;
564
565                 key.data = (unsigned char *) params->private_key_blob;
566                 key.size = params->private_key_blob_len;
567
568                 /* Try to load in PKCS#12 format */
569                 ret = gnutls_certificate_set_x509_simple_pkcs12_mem(
570                         conn->xcred, &key, GNUTLS_X509_FMT_DER,
571                         params->private_key_passwd);
572                 if (ret != 0) {
573                         wpa_printf(MSG_DEBUG, "Failed to load private_key in "
574                                    "PKCS#12 format: %s", gnutls_strerror(ret));
575                         return -1;
576                 }
577 #else /* PKCS12_FUNCS */
578                 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not included");
579                 return -1;
580 #endif /* PKCS12_FUNCS */
581         }
582
583 #if GNUTLS_VERSION_NUMBER >= 0x030103
584         if (params->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)) {
585                 ret = gnutls_ocsp_status_request_enable_client(conn->session,
586                                                                NULL, 0, NULL);
587                 if (ret != GNUTLS_E_SUCCESS) {
588                         wpa_printf(MSG_INFO,
589                                    "GnuTLS: Failed to enable OCSP client");
590                         return -1;
591                 }
592         }
593 #else /* 3.1.3 */
594         if (params->flags & TLS_CONN_REQUIRE_OCSP) {
595                 wpa_printf(MSG_INFO,
596                            "GnuTLS: OCSP not supported by this version of GnuTLS");
597                 return -1;
598         }
599 #endif /* 3.1.3 */
600
601         conn->params_set = 1;
602
603         ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
604                                      conn->xcred);
605         if (ret < 0) {
606                 wpa_printf(MSG_INFO, "Failed to configure credentials: %s",
607                            gnutls_strerror(ret));
608         }
609
610         return ret;
611 }
612
613
614 #if GNUTLS_VERSION_NUMBER >= 0x030103
615 static int server_ocsp_status_req(gnutls_session_t session, void *ptr,
616                                   gnutls_datum_t *resp)
617 {
618         struct tls_global *global = ptr;
619         char *cached;
620         size_t len;
621
622         if (!global->ocsp_stapling_response) {
623                 wpa_printf(MSG_DEBUG, "GnuTLS: OCSP status callback - no response configured");
624                 return GNUTLS_E_NO_CERTIFICATE_STATUS;
625         }
626
627         cached = os_readfile(global->ocsp_stapling_response, &len);
628         if (!cached) {
629                 wpa_printf(MSG_DEBUG,
630                            "GnuTLS: OCSP status callback - could not read response file (%s)",
631                            global->ocsp_stapling_response);
632                 return GNUTLS_E_NO_CERTIFICATE_STATUS;
633         }
634
635         wpa_printf(MSG_DEBUG,
636                    "GnuTLS: OCSP status callback - send cached response");
637         resp->data = gnutls_malloc(len);
638         if (!resp->data) {
639                 os_free(resp);
640                 return GNUTLS_E_MEMORY_ERROR;
641         }
642
643         os_memcpy(resp->data, cached, len);
644         resp->size = len;
645         os_free(cached);
646
647         return GNUTLS_E_SUCCESS;
648 }
649 #endif /* 3.1.3 */
650
651
652 int tls_global_set_params(void *tls_ctx,
653                           const struct tls_connection_params *params)
654 {
655         struct tls_global *global = tls_ctx;
656         int ret;
657
658         /* Currently, global parameters are only set when running in server
659          * mode. */
660         global->server = 1;
661
662         if (global->params_set) {
663                 gnutls_certificate_free_credentials(global->xcred);
664                 global->params_set = 0;
665         }
666
667         ret = gnutls_certificate_allocate_credentials(&global->xcred);
668         if (ret) {
669                 wpa_printf(MSG_DEBUG, "Failed to allocate global credentials "
670                            "%s", gnutls_strerror(ret));
671                 return -1;
672         }
673
674         if (params->ca_cert) {
675                 ret = gnutls_certificate_set_x509_trust_file(
676                         global->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
677                 if (ret < 0) {
678                         wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
679                                    "in DER format: %s", params->ca_cert,
680                                    gnutls_strerror(ret));
681                         ret = gnutls_certificate_set_x509_trust_file(
682                                 global->xcred, params->ca_cert,
683                                 GNUTLS_X509_FMT_PEM);
684                         if (ret < 0) {
685                                 wpa_printf(MSG_DEBUG, "Failed to read CA cert "
686                                            "'%s' in PEM format: %s",
687                                            params->ca_cert,
688                                            gnutls_strerror(ret));
689                                 goto fail;
690                         }
691                 }
692
693                 if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
694                         gnutls_certificate_set_verify_flags(
695                                 global->xcred,
696                                 GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
697                 }
698
699                 if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
700                         gnutls_certificate_set_verify_flags(
701                                 global->xcred,
702                                 GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
703                 }
704         }
705
706         if (params->client_cert && params->private_key) {
707                 /* TODO: private_key_passwd? */
708                 ret = gnutls_certificate_set_x509_key_file(
709                         global->xcred, params->client_cert,
710                         params->private_key, GNUTLS_X509_FMT_DER);
711                 if (ret < 0) {
712                         wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
713                                    "in DER format: %s", gnutls_strerror(ret));
714                         ret = gnutls_certificate_set_x509_key_file(
715                                 global->xcred, params->client_cert,
716                                 params->private_key, GNUTLS_X509_FMT_PEM);
717                         if (ret < 0) {
718                                 wpa_printf(MSG_DEBUG, "Failed to read client "
719                                            "cert/key in PEM format: %s",
720                                            gnutls_strerror(ret));
721                                 goto fail;
722                         }
723                 }
724         } else if (params->private_key) {
725                 int pkcs12_ok = 0;
726 #ifdef PKCS12_FUNCS
727                 /* Try to load in PKCS#12 format */
728                 ret = gnutls_certificate_set_x509_simple_pkcs12_file(
729                         global->xcred, params->private_key,
730                         GNUTLS_X509_FMT_DER, params->private_key_passwd);
731                 if (ret != 0) {
732                         wpa_printf(MSG_DEBUG, "Failed to load private_key in "
733                                    "PKCS#12 format: %s", gnutls_strerror(ret));
734                         goto fail;
735                 } else
736                         pkcs12_ok = 1;
737 #endif /* PKCS12_FUNCS */
738
739                 if (!pkcs12_ok) {
740                         wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
741                                    "included");
742                         goto fail;
743                 }
744         }
745
746 #if GNUTLS_VERSION_NUMBER >= 0x030103
747         os_free(global->ocsp_stapling_response);
748         if (params->ocsp_stapling_response)
749                 global->ocsp_stapling_response =
750                         os_strdup(params->ocsp_stapling_response);
751         else
752                 global->ocsp_stapling_response = NULL;
753         gnutls_certificate_set_ocsp_status_request_function(
754                 global->xcred, server_ocsp_status_req, global);
755 #endif /* 3.1.3 */
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, unsigned int flags,
776                               const u8 *session_ctx, size_t session_ctx_len)
777 {
778         if (conn == NULL || conn->session == NULL)
779                 return -1;
780
781         conn->verify_peer = verify_peer;
782         gnutls_certificate_server_set_request(conn->session,
783                                               verify_peer ? GNUTLS_CERT_REQUIRE
784                                               : GNUTLS_CERT_REQUEST);
785
786         return 0;
787 }
788
789
790 int tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn,
791                             struct tls_random *keys)
792 {
793 #if GNUTLS_VERSION_NUMBER >= 0x030012
794         gnutls_datum_t client, server;
795
796         if (conn == NULL || conn->session == NULL || keys == NULL)
797                 return -1;
798
799         os_memset(keys, 0, sizeof(*keys));
800         gnutls_session_get_random(conn->session, &client, &server);
801         keys->client_random = client.data;
802         keys->server_random = server.data;
803         keys->client_random_len = client.size;
804         keys->server_random_len = client.size;
805
806         return 0;
807 #else /* 3.0.18 */
808         return -1;
809 #endif /* 3.0.18 */
810 }
811
812
813 int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
814                               const char *label, u8 *out, size_t out_len)
815 {
816         if (conn == NULL || conn->session == NULL)
817                 return -1;
818
819         return gnutls_prf(conn->session, os_strlen(label), label,
820                           0 /* client_random first */, 0, NULL, out_len,
821                           (char *) out);
822 }
823
824
825 int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
826                                     u8 *out, size_t out_len)
827 {
828         return -1;
829 }
830
831
832 static void gnutls_tls_fail_event(struct tls_connection *conn,
833                                   const gnutls_datum_t *cert, int depth,
834                                   const char *subject, const char *err_str,
835                                   enum tls_fail_reason reason)
836 {
837         union tls_event_data ev;
838         struct tls_global *global = conn->global;
839         struct wpabuf *cert_buf = NULL;
840
841         if (global->event_cb == NULL)
842                 return;
843
844         os_memset(&ev, 0, sizeof(ev));
845         ev.cert_fail.depth = depth;
846         ev.cert_fail.subject = subject ? subject : "";
847         ev.cert_fail.reason = reason;
848         ev.cert_fail.reason_txt = err_str;
849         if (cert) {
850                 cert_buf = wpabuf_alloc_copy(cert->data, cert->size);
851                 ev.cert_fail.cert = cert_buf;
852         }
853         global->event_cb(global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
854         wpabuf_free(cert_buf);
855 }
856
857
858 #if GNUTLS_VERSION_NUMBER < 0x030300
859 static int server_eku_purpose(gnutls_x509_crt_t cert)
860 {
861         unsigned int i;
862
863         for (i = 0; ; i++) {
864                 char oid[128];
865                 size_t oid_size = sizeof(oid);
866                 int res;
867
868                 res = gnutls_x509_crt_get_key_purpose_oid(cert, i, oid,
869                                                           &oid_size, NULL);
870                 if (res == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
871                         if (i == 0) {
872                                 /* No EKU - assume any use allowed */
873                                 return 1;
874                         }
875                         break;
876                 }
877
878                 if (res < 0) {
879                         wpa_printf(MSG_INFO, "GnuTLS: Failed to get EKU");
880                         return 0;
881                 }
882
883                 wpa_printf(MSG_DEBUG, "GnuTLS: Certificate purpose: %s", oid);
884                 if (os_strcmp(oid, GNUTLS_KP_TLS_WWW_SERVER) == 0 ||
885                     os_strcmp(oid, GNUTLS_KP_ANY) == 0)
886                         return 1;
887         }
888
889         return 0;
890 }
891 #endif /* < 3.3.0 */
892
893
894 static int check_ocsp(struct tls_connection *conn, gnutls_session_t session,
895                       gnutls_alert_description_t *err)
896 {
897 #if GNUTLS_VERSION_NUMBER >= 0x030103
898         gnutls_datum_t response, buf;
899         gnutls_ocsp_resp_t resp;
900         unsigned int cert_status;
901         int res;
902
903         if (!(conn->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)))
904                 return 0;
905
906         if (!gnutls_ocsp_status_request_is_checked(session, 0)) {
907                 if (conn->flags & TLS_CONN_REQUIRE_OCSP) {
908                         wpa_printf(MSG_INFO,
909                                    "GnuTLS: No valid OCSP response received");
910                         goto ocsp_error;
911                 }
912
913                 wpa_printf(MSG_DEBUG,
914                            "GnuTLS: Valid OCSP response was not received - continue since OCSP was not required");
915                 return 0;
916         }
917
918         /*
919          * GnuTLS has already verified the OCSP response in
920          * check_ocsp_response() and rejected handshake if the certificate was
921          * found to be revoked. However, if the response indicates that the
922          * status is unknown, handshake continues and reaches here. We need to
923          * re-import the OCSP response to check for unknown certificate status,
924          * but we do not need to repeat gnutls_ocsp_resp_check_crt() and
925          * gnutls_ocsp_resp_verify_direct() calls.
926          */
927
928         res = gnutls_ocsp_status_request_get(session, &response);
929         if (res != GNUTLS_E_SUCCESS) {
930                 wpa_printf(MSG_INFO,
931                            "GnuTLS: OCSP response was received, but it was not valid");
932                 goto ocsp_error;
933         }
934
935         if (gnutls_ocsp_resp_init(&resp) != GNUTLS_E_SUCCESS)
936                 goto ocsp_error;
937
938         res = gnutls_ocsp_resp_import(resp, &response);
939         if (res != GNUTLS_E_SUCCESS) {
940                 wpa_printf(MSG_INFO,
941                            "GnuTLS: Could not parse received OCSP response: %s",
942                            gnutls_strerror(res));
943                 gnutls_ocsp_resp_deinit(resp);
944                 goto ocsp_error;
945         }
946
947         res = gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &buf);
948         if (res == GNUTLS_E_SUCCESS) {
949                 wpa_printf(MSG_DEBUG, "GnuTLS: %s", buf.data);
950                 gnutls_free(buf.data);
951         }
952
953         res = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL,
954                                           NULL, &cert_status, NULL,
955                                           NULL, NULL, NULL);
956         gnutls_ocsp_resp_deinit(resp);
957         if (res != GNUTLS_E_SUCCESS) {
958                 wpa_printf(MSG_INFO,
959                            "GnuTLS: Failed to extract OCSP information: %s",
960                            gnutls_strerror(res));
961                 goto ocsp_error;
962         }
963
964         if (cert_status == GNUTLS_OCSP_CERT_GOOD) {
965                 wpa_printf(MSG_DEBUG, "GnuTLS: OCSP cert status: good");
966         } else if (cert_status == GNUTLS_OCSP_CERT_REVOKED) {
967                 wpa_printf(MSG_DEBUG,
968                            "GnuTLS: OCSP cert status: revoked");
969                 goto ocsp_error;
970         } else {
971                 wpa_printf(MSG_DEBUG,
972                            "GnuTLS: OCSP cert status: unknown");
973                 if (conn->flags & TLS_CONN_REQUIRE_OCSP)
974                         goto ocsp_error;
975                 wpa_printf(MSG_DEBUG,
976                            "GnuTLS: OCSP was not required, so allow connection to continue");
977         }
978
979         return 0;
980
981 ocsp_error:
982         gnutls_tls_fail_event(conn, NULL, 0, NULL,
983                               "bad certificate status response",
984                               TLS_FAIL_REVOKED);
985         *err = GNUTLS_A_CERTIFICATE_REVOKED;
986         return -1;
987 #else /* GnuTLS 3.1.3 or newer */
988         return 0;
989 #endif /* GnuTLS 3.1.3 or newer */
990 }
991
992
993 static int tls_connection_verify_peer(gnutls_session_t session)
994 {
995         struct tls_connection *conn;
996         unsigned int status, num_certs, i;
997         struct os_time now;
998         const gnutls_datum_t *certs;
999         gnutls_x509_crt_t cert;
1000         gnutls_alert_description_t err;
1001         int res;
1002
1003         conn = gnutls_session_get_ptr(session);
1004         if (!conn->verify_peer) {
1005                 wpa_printf(MSG_DEBUG,
1006                            "GnuTLS: No peer certificate verification enabled");
1007                 return 0;
1008         }
1009
1010         wpa_printf(MSG_DEBUG, "GnuTSL: Verifying peer certificate");
1011
1012 #if GNUTLS_VERSION_NUMBER >= 0x030300
1013         {
1014                 gnutls_typed_vdata_st data[1];
1015                 unsigned int elements = 0;
1016
1017                 os_memset(data, 0, sizeof(data));
1018                 if (!conn->global->server) {
1019                         data[elements].type = GNUTLS_DT_KEY_PURPOSE_OID;
1020                         data[elements].data = (void *) GNUTLS_KP_TLS_WWW_SERVER;
1021                         elements++;
1022                 }
1023                 res = gnutls_certificate_verify_peers(session, data, 1,
1024                                                       &status);
1025         }
1026 #else /* < 3.3.0 */
1027         res = gnutls_certificate_verify_peers2(session, &status);
1028 #endif
1029         if (res < 0) {
1030                 wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
1031                            "certificate chain");
1032                 err = GNUTLS_A_INTERNAL_ERROR;
1033                 goto out;
1034         }
1035
1036 #if GNUTLS_VERSION_NUMBER >= 0x030104
1037         {
1038                 gnutls_datum_t info;
1039                 int ret, type;
1040
1041                 type = gnutls_certificate_type_get(session);
1042                 ret = gnutls_certificate_verification_status_print(status, type,
1043                                                                    &info, 0);
1044                 if (ret < 0) {
1045                         wpa_printf(MSG_DEBUG,
1046                                    "GnuTLS: Failed to print verification status");
1047                         err = GNUTLS_A_INTERNAL_ERROR;
1048                         goto out;
1049                 }
1050                 wpa_printf(MSG_DEBUG, "GnuTLS: %s", info.data);
1051                 gnutls_free(info.data);
1052         }
1053 #endif /* GnuTLS 3.1.4 or newer */
1054
1055         certs = gnutls_certificate_get_peers(session, &num_certs);
1056         if (certs == NULL || num_certs == 0) {
1057                 wpa_printf(MSG_INFO, "TLS: No peer certificate chain received");
1058                 err = GNUTLS_A_UNKNOWN_CA;
1059                 goto out;
1060         }
1061
1062         if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
1063                 wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
1064                 if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
1065                         wpa_printf(MSG_INFO, "TLS: Certificate uses insecure "
1066                                    "algorithm");
1067                         gnutls_tls_fail_event(conn, NULL, 0, NULL,
1068                                               "certificate uses insecure algorithm",
1069                                               TLS_FAIL_BAD_CERTIFICATE);
1070                         err = GNUTLS_A_INSUFFICIENT_SECURITY;
1071                         goto out;
1072                 }
1073                 if (status & GNUTLS_CERT_NOT_ACTIVATED) {
1074                         wpa_printf(MSG_INFO, "TLS: Certificate not yet "
1075                                    "activated");
1076                         gnutls_tls_fail_event(conn, NULL, 0, NULL,
1077                                               "certificate not yet valid",
1078                                               TLS_FAIL_NOT_YET_VALID);
1079                         err = GNUTLS_A_CERTIFICATE_EXPIRED;
1080                         goto out;
1081                 }
1082                 if (status & GNUTLS_CERT_EXPIRED) {
1083                         wpa_printf(MSG_INFO, "TLS: Certificate expired");
1084                         gnutls_tls_fail_event(conn, NULL, 0, NULL,
1085                                               "certificate has expired",
1086                                               TLS_FAIL_EXPIRED);
1087                         err = GNUTLS_A_CERTIFICATE_EXPIRED;
1088                         goto out;
1089                 }
1090                 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1091                                       "untrusted certificate",
1092                                       TLS_FAIL_UNTRUSTED);
1093                 err = GNUTLS_A_INTERNAL_ERROR;
1094                 goto out;
1095         }
1096
1097         if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
1098                 wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
1099                            "known issuer");
1100                 gnutls_tls_fail_event(conn, NULL, 0, NULL, "signed not found",
1101                                       TLS_FAIL_UNTRUSTED);
1102                 err = GNUTLS_A_UNKNOWN_CA;
1103                 goto out;
1104         }
1105
1106         if (status & GNUTLS_CERT_REVOKED) {
1107                 wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
1108                 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1109                                       "certificate revoked",
1110                                       TLS_FAIL_REVOKED);
1111                 err = GNUTLS_A_CERTIFICATE_REVOKED;
1112                 goto out;
1113         }
1114
1115         if (status != 0) {
1116                 wpa_printf(MSG_INFO, "TLS: Unknown verification status: %d",
1117                            status);
1118                 err = GNUTLS_A_INTERNAL_ERROR;
1119                 goto out;
1120         }
1121
1122         if (check_ocsp(conn, session, &err))
1123                 goto out;
1124
1125         os_get_time(&now);
1126
1127         for (i = 0; i < num_certs; i++) {
1128                 char *buf;
1129                 size_t len;
1130                 if (gnutls_x509_crt_init(&cert) < 0) {
1131                         wpa_printf(MSG_INFO, "TLS: Certificate initialization "
1132                                    "failed");
1133                         err = GNUTLS_A_BAD_CERTIFICATE;
1134                         goto out;
1135                 }
1136
1137                 if (gnutls_x509_crt_import(cert, &certs[i],
1138                                            GNUTLS_X509_FMT_DER) < 0) {
1139                         wpa_printf(MSG_INFO, "TLS: Could not parse peer "
1140                                    "certificate %d/%d", i + 1, num_certs);
1141                         gnutls_x509_crt_deinit(cert);
1142                         err = GNUTLS_A_BAD_CERTIFICATE;
1143                         goto out;
1144                 }
1145
1146                 gnutls_x509_crt_get_dn(cert, NULL, &len);
1147                 len++;
1148                 buf = os_malloc(len + 1);
1149                 if (buf) {
1150                         buf[0] = buf[len] = '\0';
1151                         gnutls_x509_crt_get_dn(cert, buf, &len);
1152                 }
1153                 wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
1154                            i + 1, num_certs, buf);
1155
1156                 if (conn->global->event_cb) {
1157                         struct wpabuf *cert_buf = NULL;
1158                         union tls_event_data ev;
1159 #ifdef CONFIG_SHA256
1160                         u8 hash[32];
1161                         const u8 *_addr[1];
1162                         size_t _len[1];
1163 #endif /* CONFIG_SHA256 */
1164
1165                         os_memset(&ev, 0, sizeof(ev));
1166                         if (conn->global->cert_in_cb) {
1167                                 cert_buf = wpabuf_alloc_copy(certs[i].data,
1168                                                              certs[i].size);
1169                                 ev.peer_cert.cert = cert_buf;
1170                         }
1171 #ifdef CONFIG_SHA256
1172                         _addr[0] = certs[i].data;
1173                         _len[0] = certs[i].size;
1174                         if (sha256_vector(1, _addr, _len, hash) == 0) {
1175                                 ev.peer_cert.hash = hash;
1176                                 ev.peer_cert.hash_len = sizeof(hash);
1177                         }
1178 #endif /* CONFIG_SHA256 */
1179                         ev.peer_cert.depth = i;
1180                         ev.peer_cert.subject = buf;
1181                         conn->global->event_cb(conn->global->cb_ctx,
1182                                                TLS_PEER_CERTIFICATE, &ev);
1183                         wpabuf_free(cert_buf);
1184                 }
1185
1186                 if (i == 0) {
1187                         if (conn->suffix_match &&
1188                             !gnutls_x509_crt_check_hostname(
1189                                     cert, conn->suffix_match)) {
1190                                 wpa_printf(MSG_WARNING,
1191                                            "TLS: Domain suffix match '%s' not found",
1192                                            conn->suffix_match);
1193                                 gnutls_tls_fail_event(
1194                                         conn, &certs[i], i, buf,
1195                                         "Domain suffix mismatch",
1196                                         TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
1197                                 err = GNUTLS_A_BAD_CERTIFICATE;
1198                                 gnutls_x509_crt_deinit(cert);
1199                                 os_free(buf);
1200                                 goto out;
1201                         }
1202
1203 #if GNUTLS_VERSION_NUMBER >= 0x030300
1204                         if (conn->domain_match &&
1205                             !gnutls_x509_crt_check_hostname2(
1206                                     cert, conn->domain_match,
1207                                     GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) {
1208                                 wpa_printf(MSG_WARNING,
1209                                            "TLS: Domain match '%s' not found",
1210                                            conn->domain_match);
1211                                 gnutls_tls_fail_event(
1212                                         conn, &certs[i], i, buf,
1213                                         "Domain mismatch",
1214                                         TLS_FAIL_DOMAIN_MISMATCH);
1215                                 err = GNUTLS_A_BAD_CERTIFICATE;
1216                                 gnutls_x509_crt_deinit(cert);
1217                                 os_free(buf);
1218                                 goto out;
1219                         }
1220 #endif /* >= 3.3.0 */
1221
1222                         /* TODO: validate altsubject_match.
1223                          * For now, any such configuration is rejected in
1224                          * tls_connection_set_params() */
1225
1226 #if GNUTLS_VERSION_NUMBER < 0x030300
1227                         /*
1228                          * gnutls_certificate_verify_peers() not available, so
1229                          * need to check EKU separately.
1230                          */
1231                         if (!conn->global->server &&
1232                             !server_eku_purpose(cert)) {
1233                                 wpa_printf(MSG_WARNING,
1234                                            "GnuTLS: No server EKU");
1235                                 gnutls_tls_fail_event(
1236                                         conn, &certs[i], i, buf,
1237                                         "No server EKU",
1238                                         TLS_FAIL_BAD_CERTIFICATE);
1239                                 err = GNUTLS_A_BAD_CERTIFICATE;
1240                                 gnutls_x509_crt_deinit(cert);
1241                                 os_free(buf);
1242                                 goto out;
1243                         }
1244 #endif /* < 3.3.0 */
1245                 }
1246
1247                 if (!conn->disable_time_checks &&
1248                     (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
1249                      gnutls_x509_crt_get_activation_time(cert) > now.sec)) {
1250                         wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
1251                                    "not valid at this time",
1252                                    i + 1, num_certs);
1253                         gnutls_tls_fail_event(
1254                                 conn, &certs[i], i, buf,
1255                                 "Certificate is not valid at this time",
1256                                 TLS_FAIL_EXPIRED);
1257                         gnutls_x509_crt_deinit(cert);
1258                         os_free(buf);
1259                         err = GNUTLS_A_CERTIFICATE_EXPIRED;
1260                         goto out;
1261                 }
1262
1263                 os_free(buf);
1264
1265                 gnutls_x509_crt_deinit(cert);
1266         }
1267
1268         if (conn->global->event_cb != NULL)
1269                 conn->global->event_cb(conn->global->cb_ctx,
1270                                        TLS_CERT_CHAIN_SUCCESS, NULL);
1271
1272         return 0;
1273
1274 out:
1275         conn->failed++;
1276         gnutls_alert_send(session, GNUTLS_AL_FATAL, err);
1277         return GNUTLS_E_CERTIFICATE_ERROR;
1278 }
1279
1280
1281 static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn)
1282 {
1283         int res;
1284         struct wpabuf *ad;
1285         wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data");
1286         ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3);
1287         if (ad == NULL)
1288                 return NULL;
1289
1290         res = gnutls_record_recv(conn->session, wpabuf_mhead(ad),
1291                                  wpabuf_size(ad));
1292         wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res);
1293         if (res < 0) {
1294                 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
1295                            "(%s)", __func__, (int) res,
1296                            gnutls_strerror(res));
1297                 wpabuf_free(ad);
1298                 return NULL;
1299         }
1300
1301         wpabuf_put(ad, res);
1302         wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data",
1303                    res);
1304         return ad;
1305 }
1306
1307
1308 struct wpabuf * tls_connection_handshake(void *tls_ctx,
1309                                          struct tls_connection *conn,
1310                                          const struct wpabuf *in_data,
1311                                          struct wpabuf **appl_data)
1312 {
1313         struct tls_global *global = tls_ctx;
1314         struct wpabuf *out_data;
1315         int ret;
1316
1317         if (appl_data)
1318                 *appl_data = NULL;
1319
1320         if (in_data && wpabuf_len(in_data) > 0) {
1321                 if (conn->pull_buf) {
1322                         wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
1323                                    "pull_buf", __func__,
1324                                    (unsigned long) wpabuf_len(conn->pull_buf));
1325                         wpabuf_free(conn->pull_buf);
1326                 }
1327                 conn->pull_buf = wpabuf_dup(in_data);
1328                 if (conn->pull_buf == NULL)
1329                         return NULL;
1330                 conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
1331         }
1332
1333         ret = gnutls_handshake(conn->session);
1334         if (ret < 0) {
1335                 gnutls_alert_description_t alert;
1336
1337                 switch (ret) {
1338                 case GNUTLS_E_AGAIN:
1339                         if (global->server && conn->established &&
1340                             conn->push_buf == NULL) {
1341                                 /* Need to return something to trigger
1342                                  * completion of EAP-TLS. */
1343                                 conn->push_buf = wpabuf_alloc(0);
1344                         }
1345                         break;
1346                 case GNUTLS_E_FATAL_ALERT_RECEIVED:
1347                         alert = gnutls_alert_get(conn->session);
1348                         wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
1349                                    __func__, gnutls_alert_get_name(alert));
1350                         conn->read_alerts++;
1351                         if (conn->global->event_cb != NULL) {
1352                                 union tls_event_data ev;
1353
1354                                 os_memset(&ev, 0, sizeof(ev));
1355                                 ev.alert.is_local = 0;
1356                                 ev.alert.type = gnutls_alert_get_name(alert);
1357                                 ev.alert.description = ev.alert.type;
1358                                 conn->global->event_cb(conn->global->cb_ctx,
1359                                                        TLS_ALERT, &ev);
1360                         }
1361                         /* continue */
1362                 default:
1363                         wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
1364                                    "-> %s", __func__, gnutls_strerror(ret));
1365                         conn->failed++;
1366                 }
1367         } else {
1368                 size_t size;
1369
1370                 wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
1371
1372 #if GNUTLS_VERSION_NUMBER >= 0x03010a
1373                 {
1374                         char *desc;
1375
1376                         desc = gnutls_session_get_desc(conn->session);
1377                         if (desc) {
1378                                 wpa_printf(MSG_DEBUG, "GnuTLS: %s", desc);
1379                                 gnutls_free(desc);
1380                         }
1381                 }
1382 #endif /* GnuTLS 3.1.10 or newer */
1383
1384                 conn->established = 1;
1385                 if (conn->push_buf == NULL) {
1386                         /* Need to return something to get final TLS ACK. */
1387                         conn->push_buf = wpabuf_alloc(0);
1388                 }
1389
1390                 gnutls_session_get_data(conn->session, NULL, &size);
1391                 if (global->session_data == NULL ||
1392                     global->session_data_size < size) {
1393                         os_free(global->session_data);
1394                         global->session_data = os_malloc(size);
1395                 }
1396                 if (global->session_data) {
1397                         global->session_data_size = size;
1398                         gnutls_session_get_data(conn->session,
1399                                                 global->session_data,
1400                                                 &global->session_data_size);
1401                 }
1402
1403                 if (conn->pull_buf && appl_data)
1404                         *appl_data = gnutls_get_appl_data(conn);
1405         }
1406
1407         out_data = conn->push_buf;
1408         conn->push_buf = NULL;
1409         return out_data;
1410 }
1411
1412
1413 struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
1414                                                 struct tls_connection *conn,
1415                                                 const struct wpabuf *in_data,
1416                                                 struct wpabuf **appl_data)
1417 {
1418         return tls_connection_handshake(tls_ctx, conn, in_data, appl_data);
1419 }
1420
1421
1422 struct wpabuf * tls_connection_encrypt(void *tls_ctx,
1423                                        struct tls_connection *conn,
1424                                        const struct wpabuf *in_data)
1425 {
1426         ssize_t res;
1427         struct wpabuf *buf;
1428
1429         res = gnutls_record_send(conn->session, wpabuf_head(in_data),
1430                                  wpabuf_len(in_data));
1431         if (res < 0) {
1432                 wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
1433                            __func__, gnutls_strerror(res));
1434                 return NULL;
1435         }
1436
1437         buf = conn->push_buf;
1438         conn->push_buf = NULL;
1439         return buf;
1440 }
1441
1442
1443 struct wpabuf * tls_connection_decrypt(void *tls_ctx,
1444                                        struct tls_connection *conn,
1445                                        const struct wpabuf *in_data)
1446 {
1447         ssize_t res;
1448         struct wpabuf *out;
1449
1450         if (conn->pull_buf) {
1451                 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
1452                            "pull_buf", __func__,
1453                            (unsigned long) wpabuf_len(conn->pull_buf));
1454                 wpabuf_free(conn->pull_buf);
1455         }
1456         conn->pull_buf = wpabuf_dup(in_data);
1457         if (conn->pull_buf == NULL)
1458                 return NULL;
1459         conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
1460
1461         /*
1462          * Even though we try to disable TLS compression, it is possible that
1463          * this cannot be done with all TLS libraries. Add extra buffer space
1464          * to handle the possibility of the decrypted data being longer than
1465          * input data.
1466          */
1467         out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
1468         if (out == NULL)
1469                 return NULL;
1470
1471         res = gnutls_record_recv(conn->session, wpabuf_mhead(out),
1472                                  wpabuf_size(out));
1473         if (res < 0) {
1474                 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
1475                            "(%s)", __func__, (int) res, gnutls_strerror(res));
1476                 wpabuf_free(out);
1477                 return NULL;
1478         }
1479         wpabuf_put(out, res);
1480
1481         return out;
1482 }
1483
1484
1485 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
1486 {
1487         if (conn == NULL)
1488                 return 0;
1489         return gnutls_session_is_resumed(conn->session);
1490 }
1491
1492
1493 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
1494                                    u8 *ciphers)
1495 {
1496         /* TODO */
1497         return -1;
1498 }
1499
1500
1501 int tls_get_version(void *ssl_ctx, struct tls_connection *conn,
1502                     char *buf, size_t buflen)
1503 {
1504         /* TODO */
1505         return -1;
1506 }
1507
1508
1509 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
1510                    char *buf, size_t buflen)
1511 {
1512         /* TODO */
1513         buf[0] = '\0';
1514         return 0;
1515 }
1516
1517
1518 int tls_connection_enable_workaround(void *ssl_ctx,
1519                                      struct tls_connection *conn)
1520 {
1521         gnutls_record_disable_padding(conn->session);
1522         return 0;
1523 }
1524
1525
1526 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
1527                                     int ext_type, const u8 *data,
1528                                     size_t data_len)
1529 {
1530         /* TODO */
1531         return -1;
1532 }
1533
1534
1535 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
1536 {
1537         if (conn == NULL)
1538                 return -1;
1539         return conn->failed;
1540 }
1541
1542
1543 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
1544 {
1545         if (conn == NULL)
1546                 return -1;
1547         return conn->read_alerts;
1548 }
1549
1550
1551 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
1552 {
1553         if (conn == NULL)
1554                 return -1;
1555         return conn->write_alerts;
1556 }
1557
1558
1559 int tls_connection_set_session_ticket_cb(void *tls_ctx,
1560                                          struct tls_connection *conn,
1561                                          tls_session_ticket_cb cb, void *ctx)
1562 {
1563         return -1;
1564 }
1565
1566
1567 int tls_get_library_version(char *buf, size_t buf_len)
1568 {
1569         return os_snprintf(buf, buf_len, "GnuTLS build=%s run=%s",
1570                            GNUTLS_VERSION, gnutls_check_version(NULL));
1571 }
1572
1573
1574 void tls_connection_set_success_data(struct tls_connection *conn,
1575                                      struct wpabuf *data)
1576 {
1577 }
1578
1579
1580 void tls_connection_set_success_data_resumed(struct tls_connection *conn)
1581 {
1582 }
1583
1584
1585 const struct wpabuf *
1586 tls_connection_get_success_data(struct tls_connection *conn)
1587 {
1588         return NULL;
1589 }
1590
1591
1592 void tls_connection_remove_session(struct tls_connection *conn)
1593 {
1594 }