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