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