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