]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa/src/crypto/tls_gnutls.c
Update hostapd/wpa_supplicant to 2.8 to fix multiple vulnerabilities.
[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         if (params->openssl_ecdh_curves) {
465                 wpa_printf(MSG_INFO,
466                            "GnuTLS: openssl_ecdh_curves not supported");
467                 return -1;
468         }
469
470         /* TODO: gnutls_certificate_set_verify_flags(xcred, flags);
471          * to force peer validation(?) */
472
473         if (params->ca_cert) {
474                 wpa_printf(MSG_DEBUG, "GnuTLS: Try to parse %s in DER format",
475                            params->ca_cert);
476                 ret = gnutls_certificate_set_x509_trust_file(
477                         conn->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
478                 if (ret < 0) {
479                         wpa_printf(MSG_DEBUG,
480                                    "GnuTLS: Failed to read CA cert '%s' in DER format (%s) - try in PEM format",
481                                    params->ca_cert,
482                                    gnutls_strerror(ret));
483                         ret = gnutls_certificate_set_x509_trust_file(
484                                 conn->xcred, params->ca_cert,
485                                 GNUTLS_X509_FMT_PEM);
486                         if (ret < 0) {
487                                 wpa_printf(MSG_DEBUG,
488                                            "Failed to read CA cert '%s' in PEM format: %s",
489                                            params->ca_cert,
490                                            gnutls_strerror(ret));
491                                 return -1;
492                         }
493                         wpa_printf(MSG_DEBUG,
494                                    "GnuTLS: Successfully read CA cert '%s' in PEM format",
495                                    params->ca_cert);
496                 } else {
497                         wpa_printf(MSG_DEBUG,
498                                    "GnuTLS: Successfully read CA cert '%s' in DER format",
499                                    params->ca_cert);
500                 }
501         } else if (params->ca_cert_blob) {
502                 gnutls_datum_t ca;
503
504                 ca.data = (unsigned char *) params->ca_cert_blob;
505                 ca.size = params->ca_cert_blob_len;
506
507                 ret = gnutls_certificate_set_x509_trust_mem(
508                         conn->xcred, &ca, GNUTLS_X509_FMT_DER);
509                 if (ret < 0) {
510                         wpa_printf(MSG_DEBUG,
511                                    "Failed to parse CA cert in DER format: %s",
512                                    gnutls_strerror(ret));
513                         ret = gnutls_certificate_set_x509_trust_mem(
514                                 conn->xcred, &ca, GNUTLS_X509_FMT_PEM);
515                         if (ret < 0) {
516                                 wpa_printf(MSG_DEBUG,
517                                            "Failed to parse CA cert in PEM format: %s",
518                                            gnutls_strerror(ret));
519                                 return -1;
520                         }
521                 }
522         } else if (params->ca_path) {
523                 wpa_printf(MSG_INFO, "GnuTLS: ca_path not supported");
524                 return -1;
525         }
526
527         conn->disable_time_checks = 0;
528         if (params->ca_cert || params->ca_cert_blob) {
529                 conn->verify_peer = 1;
530                 gnutls_certificate_set_verify_function(
531                         conn->xcred, tls_connection_verify_peer);
532
533                 if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
534                         gnutls_certificate_set_verify_flags(
535                                 conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
536                 }
537
538                 if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
539                         conn->disable_time_checks = 1;
540                         gnutls_certificate_set_verify_flags(
541                                 conn->xcred,
542                                 GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
543                 }
544         }
545
546         if (params->client_cert && params->private_key) {
547                 wpa_printf(MSG_DEBUG,
548                            "GnuTLS: Try to parse client cert '%s' and key '%s' in DER format",
549                            params->client_cert, params->private_key);
550 #if GNUTLS_VERSION_NUMBER >= 0x03010b
551                 ret = gnutls_certificate_set_x509_key_file2(
552                         conn->xcred, params->client_cert, params->private_key,
553                         GNUTLS_X509_FMT_DER, params->private_key_passwd, 0);
554 #else
555                 /* private_key_passwd not (easily) supported here */
556                 ret = gnutls_certificate_set_x509_key_file(
557                         conn->xcred, params->client_cert, params->private_key,
558                         GNUTLS_X509_FMT_DER);
559 #endif
560                 if (ret < 0) {
561                         wpa_printf(MSG_DEBUG,
562                                    "GnuTLS: Failed to read client cert/key in DER format (%s) - try in PEM format",
563                                    gnutls_strerror(ret));
564 #if GNUTLS_VERSION_NUMBER >= 0x03010b
565                         ret = gnutls_certificate_set_x509_key_file2(
566                                 conn->xcred, params->client_cert,
567                                 params->private_key, GNUTLS_X509_FMT_PEM,
568                                 params->private_key_passwd, 0);
569 #else
570                         ret = gnutls_certificate_set_x509_key_file(
571                                 conn->xcred, params->client_cert,
572                                 params->private_key, GNUTLS_X509_FMT_PEM);
573 #endif
574                         if (ret < 0) {
575                                 wpa_printf(MSG_DEBUG, "Failed to read client "
576                                            "cert/key in PEM format: %s",
577                                            gnutls_strerror(ret));
578                                 return ret;
579                         }
580                         wpa_printf(MSG_DEBUG,
581                                    "GnuTLS: Successfully read client cert/key in PEM format");
582                 } else {
583                         wpa_printf(MSG_DEBUG,
584                                    "GnuTLS: Successfully read client cert/key in DER format");
585                 }
586         } else if (params->private_key) {
587                 int pkcs12_ok = 0;
588 #ifdef PKCS12_FUNCS
589                 /* Try to load in PKCS#12 format */
590                 wpa_printf(MSG_DEBUG,
591                            "GnuTLS: Try to parse client cert/key '%s'in PKCS#12 DER format",
592                            params->private_key);
593                 ret = gnutls_certificate_set_x509_simple_pkcs12_file(
594                         conn->xcred, params->private_key, GNUTLS_X509_FMT_DER,
595                         params->private_key_passwd);
596                 if (ret != 0) {
597                         wpa_printf(MSG_DEBUG, "Failed to load private_key in "
598                                    "PKCS#12 format: %s", gnutls_strerror(ret));
599                         return -1;
600                 } else
601                         pkcs12_ok = 1;
602 #endif /* PKCS12_FUNCS */
603
604                 if (!pkcs12_ok) {
605                         wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
606                                    "included");
607                         return -1;
608                 }
609         } else if (params->client_cert_blob && params->private_key_blob) {
610                 gnutls_datum_t cert, key;
611
612                 cert.data = (unsigned char *) params->client_cert_blob;
613                 cert.size = params->client_cert_blob_len;
614                 key.data = (unsigned char *) params->private_key_blob;
615                 key.size = params->private_key_blob_len;
616
617 #if GNUTLS_VERSION_NUMBER >= 0x03010b
618                 ret = gnutls_certificate_set_x509_key_mem2(
619                         conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER,
620                         params->private_key_passwd, 0);
621 #else
622                 /* private_key_passwd not (easily) supported here */
623                 ret = gnutls_certificate_set_x509_key_mem(
624                         conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER);
625 #endif
626                 if (ret < 0) {
627                         wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
628                                    "in DER format: %s", gnutls_strerror(ret));
629 #if GNUTLS_VERSION_NUMBER >= 0x03010b
630                         ret = gnutls_certificate_set_x509_key_mem2(
631                                 conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM,
632                                 params->private_key_passwd, 0);
633 #else
634                         /* private_key_passwd not (easily) supported here */
635                         ret = gnutls_certificate_set_x509_key_mem(
636                                 conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM);
637 #endif
638                         if (ret < 0) {
639                                 wpa_printf(MSG_DEBUG, "Failed to read client "
640                                            "cert/key in PEM format: %s",
641                                            gnutls_strerror(ret));
642                                 return ret;
643                         }
644                 }
645         } else if (params->private_key_blob) {
646 #ifdef PKCS12_FUNCS
647                 gnutls_datum_t key;
648
649                 key.data = (unsigned char *) params->private_key_blob;
650                 key.size = params->private_key_blob_len;
651
652                 /* Try to load in PKCS#12 format */
653                 ret = gnutls_certificate_set_x509_simple_pkcs12_mem(
654                         conn->xcred, &key, GNUTLS_X509_FMT_DER,
655                         params->private_key_passwd);
656                 if (ret != 0) {
657                         wpa_printf(MSG_DEBUG, "Failed to load private_key in "
658                                    "PKCS#12 format: %s", gnutls_strerror(ret));
659                         return -1;
660                 }
661 #else /* PKCS12_FUNCS */
662                 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not included");
663                 return -1;
664 #endif /* PKCS12_FUNCS */
665         }
666
667 #if GNUTLS_VERSION_NUMBER >= 0x030103
668         if (params->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)) {
669                 ret = gnutls_ocsp_status_request_enable_client(conn->session,
670                                                                NULL, 0, NULL);
671                 if (ret != GNUTLS_E_SUCCESS) {
672                         wpa_printf(MSG_INFO,
673                                    "GnuTLS: Failed to enable OCSP client");
674                         return -1;
675                 }
676         }
677 #else /* 3.1.3 */
678         if (params->flags & TLS_CONN_REQUIRE_OCSP) {
679                 wpa_printf(MSG_INFO,
680                            "GnuTLS: OCSP not supported by this version of GnuTLS");
681                 return -1;
682         }
683 #endif /* 3.1.3 */
684
685         conn->params_set = 1;
686
687         ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
688                                      conn->xcred);
689         if (ret < 0) {
690                 wpa_printf(MSG_INFO, "Failed to configure credentials: %s",
691                            gnutls_strerror(ret));
692         }
693
694         return ret;
695 }
696
697
698 #if GNUTLS_VERSION_NUMBER >= 0x030103
699 static int server_ocsp_status_req(gnutls_session_t session, void *ptr,
700                                   gnutls_datum_t *resp)
701 {
702         struct tls_global *global = ptr;
703         char *cached;
704         size_t len;
705
706         if (!global->ocsp_stapling_response) {
707                 wpa_printf(MSG_DEBUG, "GnuTLS: OCSP status callback - no response configured");
708                 return GNUTLS_E_NO_CERTIFICATE_STATUS;
709         }
710
711         cached = os_readfile(global->ocsp_stapling_response, &len);
712         if (!cached) {
713                 wpa_printf(MSG_DEBUG,
714                            "GnuTLS: OCSP status callback - could not read response file (%s)",
715                            global->ocsp_stapling_response);
716                 return GNUTLS_E_NO_CERTIFICATE_STATUS;
717         }
718
719         wpa_printf(MSG_DEBUG,
720                    "GnuTLS: OCSP status callback - send cached response");
721         resp->data = gnutls_malloc(len);
722         if (!resp->data) {
723                 os_free(resp);
724                 return GNUTLS_E_MEMORY_ERROR;
725         }
726
727         os_memcpy(resp->data, cached, len);
728         resp->size = len;
729         os_free(cached);
730
731         return GNUTLS_E_SUCCESS;
732 }
733 #endif /* 3.1.3 */
734
735
736 int tls_global_set_params(void *tls_ctx,
737                           const struct tls_connection_params *params)
738 {
739         struct tls_global *global = tls_ctx;
740         int ret;
741
742         if (params->check_cert_subject)
743                 return -1; /* not yet supported */
744
745         /* Currently, global parameters are only set when running in server
746          * mode. */
747         global->server = 1;
748
749         if (global->params_set) {
750                 gnutls_certificate_free_credentials(global->xcred);
751                 global->params_set = 0;
752         }
753
754         ret = gnutls_certificate_allocate_credentials(&global->xcred);
755         if (ret) {
756                 wpa_printf(MSG_DEBUG, "Failed to allocate global credentials "
757                            "%s", gnutls_strerror(ret));
758                 return -1;
759         }
760
761         if (params->ca_cert) {
762                 ret = gnutls_certificate_set_x509_trust_file(
763                         global->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
764                 if (ret < 0) {
765                         wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
766                                    "in DER format: %s", params->ca_cert,
767                                    gnutls_strerror(ret));
768                         ret = gnutls_certificate_set_x509_trust_file(
769                                 global->xcred, params->ca_cert,
770                                 GNUTLS_X509_FMT_PEM);
771                         if (ret < 0) {
772                                 wpa_printf(MSG_DEBUG, "Failed to read CA cert "
773                                            "'%s' in PEM format: %s",
774                                            params->ca_cert,
775                                            gnutls_strerror(ret));
776                                 goto fail;
777                         }
778                 }
779
780                 if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
781                         gnutls_certificate_set_verify_flags(
782                                 global->xcred,
783                                 GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
784                 }
785
786                 if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
787                         gnutls_certificate_set_verify_flags(
788                                 global->xcred,
789                                 GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
790                 }
791         }
792
793         if (params->client_cert && params->private_key) {
794                 /* TODO: private_key_passwd? */
795                 ret = gnutls_certificate_set_x509_key_file(
796                         global->xcred, params->client_cert,
797                         params->private_key, GNUTLS_X509_FMT_DER);
798                 if (ret < 0) {
799                         wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
800                                    "in DER format: %s", gnutls_strerror(ret));
801                         ret = gnutls_certificate_set_x509_key_file(
802                                 global->xcred, params->client_cert,
803                                 params->private_key, GNUTLS_X509_FMT_PEM);
804                         if (ret < 0) {
805                                 wpa_printf(MSG_DEBUG, "Failed to read client "
806                                            "cert/key in PEM format: %s",
807                                            gnutls_strerror(ret));
808                                 goto fail;
809                         }
810                 }
811         } else if (params->private_key) {
812                 int pkcs12_ok = 0;
813 #ifdef PKCS12_FUNCS
814                 /* Try to load in PKCS#12 format */
815                 ret = gnutls_certificate_set_x509_simple_pkcs12_file(
816                         global->xcred, params->private_key,
817                         GNUTLS_X509_FMT_DER, params->private_key_passwd);
818                 if (ret != 0) {
819                         wpa_printf(MSG_DEBUG, "Failed to load private_key in "
820                                    "PKCS#12 format: %s", gnutls_strerror(ret));
821                         goto fail;
822                 } else
823                         pkcs12_ok = 1;
824 #endif /* PKCS12_FUNCS */
825
826                 if (!pkcs12_ok) {
827                         wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
828                                    "included");
829                         goto fail;
830                 }
831         }
832
833 #if GNUTLS_VERSION_NUMBER >= 0x030103
834         os_free(global->ocsp_stapling_response);
835         if (params->ocsp_stapling_response)
836                 global->ocsp_stapling_response =
837                         os_strdup(params->ocsp_stapling_response);
838         else
839                 global->ocsp_stapling_response = NULL;
840         gnutls_certificate_set_ocsp_status_request_function(
841                 global->xcred, server_ocsp_status_req, global);
842 #endif /* 3.1.3 */
843
844         global->params_set = 1;
845
846         return 0;
847
848 fail:
849         gnutls_certificate_free_credentials(global->xcred);
850         return -1;
851 }
852
853
854 int tls_global_set_verify(void *ssl_ctx, int check_crl, int strict)
855 {
856         /* TODO */
857         return 0;
858 }
859
860
861 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
862                               int verify_peer, unsigned int flags,
863                               const u8 *session_ctx, size_t session_ctx_len)
864 {
865         if (conn == NULL || conn->session == NULL)
866                 return -1;
867
868         conn->verify_peer = verify_peer;
869         gnutls_certificate_server_set_request(conn->session,
870                                               verify_peer ? GNUTLS_CERT_REQUIRE
871                                               : GNUTLS_CERT_REQUEST);
872
873         return 0;
874 }
875
876
877 int tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn,
878                             struct tls_random *keys)
879 {
880 #if GNUTLS_VERSION_NUMBER >= 0x030012
881         gnutls_datum_t client, server;
882
883         if (conn == NULL || conn->session == NULL || keys == NULL)
884                 return -1;
885
886         os_memset(keys, 0, sizeof(*keys));
887         gnutls_session_get_random(conn->session, &client, &server);
888         keys->client_random = client.data;
889         keys->server_random = server.data;
890         keys->client_random_len = client.size;
891         keys->server_random_len = client.size;
892
893         return 0;
894 #else /* 3.0.18 */
895         return -1;
896 #endif /* 3.0.18 */
897 }
898
899
900 int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
901                               const char *label, const u8 *context,
902                               size_t context_len, u8 *out, size_t out_len)
903 {
904         if (conn == NULL || conn->session == NULL)
905                 return -1;
906
907 #if GNUTLS_VERSION_NUMBER >= 0x030404
908         return gnutls_prf_rfc5705(conn->session, os_strlen(label), label,
909                                   context_len, (const char *) context,
910                                   out_len, (char *) out);
911 #else /* 3.4.4 */
912         if (context)
913                 return -1;
914         return gnutls_prf(conn->session, os_strlen(label), label,
915                           0 /* client_random first */, 0, NULL, out_len,
916                           (char *) out);
917 #endif /* 3.4.4 */
918 }
919
920
921 int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
922                                     u8 *out, size_t out_len)
923 {
924         return -1;
925 }
926
927
928 static void gnutls_tls_fail_event(struct tls_connection *conn,
929                                   const gnutls_datum_t *cert, int depth,
930                                   const char *subject, const char *err_str,
931                                   enum tls_fail_reason reason)
932 {
933         union tls_event_data ev;
934         struct tls_global *global = conn->global;
935         struct wpabuf *cert_buf = NULL;
936
937         if (global->event_cb == NULL)
938                 return;
939
940         os_memset(&ev, 0, sizeof(ev));
941         ev.cert_fail.depth = depth;
942         ev.cert_fail.subject = subject ? subject : "";
943         ev.cert_fail.reason = reason;
944         ev.cert_fail.reason_txt = err_str;
945         if (cert) {
946                 cert_buf = wpabuf_alloc_copy(cert->data, cert->size);
947                 ev.cert_fail.cert = cert_buf;
948         }
949         global->event_cb(global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
950         wpabuf_free(cert_buf);
951 }
952
953
954 #if GNUTLS_VERSION_NUMBER < 0x030300
955 static int server_eku_purpose(gnutls_x509_crt_t cert)
956 {
957         unsigned int i;
958
959         for (i = 0; ; i++) {
960                 char oid[128];
961                 size_t oid_size = sizeof(oid);
962                 int res;
963
964                 res = gnutls_x509_crt_get_key_purpose_oid(cert, i, oid,
965                                                           &oid_size, NULL);
966                 if (res == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
967                         if (i == 0) {
968                                 /* No EKU - assume any use allowed */
969                                 return 1;
970                         }
971                         break;
972                 }
973
974                 if (res < 0) {
975                         wpa_printf(MSG_INFO, "GnuTLS: Failed to get EKU");
976                         return 0;
977                 }
978
979                 wpa_printf(MSG_DEBUG, "GnuTLS: Certificate purpose: %s", oid);
980                 if (os_strcmp(oid, GNUTLS_KP_TLS_WWW_SERVER) == 0 ||
981                     os_strcmp(oid, GNUTLS_KP_ANY) == 0)
982                         return 1;
983         }
984
985         return 0;
986 }
987 #endif /* < 3.3.0 */
988
989
990 static int check_ocsp(struct tls_connection *conn, gnutls_session_t session,
991                       gnutls_alert_description_t *err)
992 {
993 #if GNUTLS_VERSION_NUMBER >= 0x030103
994         gnutls_datum_t response, buf;
995         gnutls_ocsp_resp_t resp;
996         unsigned int cert_status;
997         int res;
998
999         if (!(conn->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)))
1000                 return 0;
1001
1002         if (!gnutls_ocsp_status_request_is_checked(session, 0)) {
1003                 if (conn->flags & TLS_CONN_REQUIRE_OCSP) {
1004                         wpa_printf(MSG_INFO,
1005                                    "GnuTLS: No valid OCSP response received");
1006                         goto ocsp_error;
1007                 }
1008
1009                 wpa_printf(MSG_DEBUG,
1010                            "GnuTLS: Valid OCSP response was not received - continue since OCSP was not required");
1011                 return 0;
1012         }
1013
1014         /*
1015          * GnuTLS has already verified the OCSP response in
1016          * check_ocsp_response() and rejected handshake if the certificate was
1017          * found to be revoked. However, if the response indicates that the
1018          * status is unknown, handshake continues and reaches here. We need to
1019          * re-import the OCSP response to check for unknown certificate status,
1020          * but we do not need to repeat gnutls_ocsp_resp_check_crt() and
1021          * gnutls_ocsp_resp_verify_direct() calls.
1022          */
1023
1024         res = gnutls_ocsp_status_request_get(session, &response);
1025         if (res != GNUTLS_E_SUCCESS) {
1026                 wpa_printf(MSG_INFO,
1027                            "GnuTLS: OCSP response was received, but it was not valid");
1028                 goto ocsp_error;
1029         }
1030
1031         if (gnutls_ocsp_resp_init(&resp) != GNUTLS_E_SUCCESS)
1032                 goto ocsp_error;
1033
1034         res = gnutls_ocsp_resp_import(resp, &response);
1035         if (res != GNUTLS_E_SUCCESS) {
1036                 wpa_printf(MSG_INFO,
1037                            "GnuTLS: Could not parse received OCSP response: %s",
1038                            gnutls_strerror(res));
1039                 gnutls_ocsp_resp_deinit(resp);
1040                 goto ocsp_error;
1041         }
1042
1043         res = gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &buf);
1044         if (res == GNUTLS_E_SUCCESS) {
1045                 wpa_printf(MSG_DEBUG, "GnuTLS: %s", buf.data);
1046                 gnutls_free(buf.data);
1047         }
1048
1049         res = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL,
1050                                           NULL, &cert_status, NULL,
1051                                           NULL, NULL, NULL);
1052         gnutls_ocsp_resp_deinit(resp);
1053         if (res != GNUTLS_E_SUCCESS) {
1054                 wpa_printf(MSG_INFO,
1055                            "GnuTLS: Failed to extract OCSP information: %s",
1056                            gnutls_strerror(res));
1057                 goto ocsp_error;
1058         }
1059
1060         if (cert_status == GNUTLS_OCSP_CERT_GOOD) {
1061                 wpa_printf(MSG_DEBUG, "GnuTLS: OCSP cert status: good");
1062         } else if (cert_status == GNUTLS_OCSP_CERT_REVOKED) {
1063                 wpa_printf(MSG_DEBUG,
1064                            "GnuTLS: OCSP cert status: revoked");
1065                 goto ocsp_error;
1066         } else {
1067                 wpa_printf(MSG_DEBUG,
1068                            "GnuTLS: OCSP cert status: unknown");
1069                 if (conn->flags & TLS_CONN_REQUIRE_OCSP)
1070                         goto ocsp_error;
1071                 wpa_printf(MSG_DEBUG,
1072                            "GnuTLS: OCSP was not required, so allow connection to continue");
1073         }
1074
1075         return 0;
1076
1077 ocsp_error:
1078         gnutls_tls_fail_event(conn, NULL, 0, NULL,
1079                               "bad certificate status response",
1080                               TLS_FAIL_REVOKED);
1081         *err = GNUTLS_A_CERTIFICATE_REVOKED;
1082         return -1;
1083 #else /* GnuTLS 3.1.3 or newer */
1084         return 0;
1085 #endif /* GnuTLS 3.1.3 or newer */
1086 }
1087
1088
1089 static int tls_match_suffix_helper(gnutls_x509_crt_t cert, const char *match,
1090                                    int full)
1091 {
1092         int res = -1;
1093
1094 #if GNUTLS_VERSION_NUMBER >= 0x030300
1095         if (full)
1096                 res = gnutls_x509_crt_check_hostname2(
1097                         cert, match,
1098                         GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS);
1099 #endif /* >= 3.3.0 */
1100         if (res == -1)
1101                 res = gnutls_x509_crt_check_hostname(cert, match);
1102
1103         wpa_printf(MSG_DEBUG, "TLS: Match domain against %s%s --> res=%d",
1104                    full ? "": "suffix ", match, res);
1105         return res;
1106 }
1107
1108
1109 static int tls_match_suffix(gnutls_x509_crt_t cert, const char *match,
1110                             int full)
1111 {
1112         char *values, *token, *context = NULL;
1113         int ret = 0;
1114
1115         if (!os_strchr(match, ';'))
1116                 return tls_match_suffix_helper(cert, match, full);
1117
1118         values = os_strdup(match);
1119         if (!values)
1120                 return 0;
1121
1122         /* Process each match alternative separately until a match is found */
1123         while ((token = str_token(values, ";", &context))) {
1124                 if (tls_match_suffix_helper(cert, token, full)) {
1125                         ret = 1;
1126                         break;
1127                 }
1128         }
1129
1130         os_free(values);
1131         return ret;
1132 }
1133
1134
1135 static int tls_connection_verify_peer(gnutls_session_t session)
1136 {
1137         struct tls_connection *conn;
1138         unsigned int status, num_certs, i;
1139         struct os_time now;
1140         const gnutls_datum_t *certs;
1141         gnutls_x509_crt_t cert;
1142         gnutls_alert_description_t err;
1143         int res;
1144
1145         conn = gnutls_session_get_ptr(session);
1146         if (!conn->verify_peer) {
1147                 wpa_printf(MSG_DEBUG,
1148                            "GnuTLS: No peer certificate verification enabled");
1149                 return 0;
1150         }
1151
1152         wpa_printf(MSG_DEBUG, "GnuTSL: Verifying peer certificate");
1153
1154 #if GNUTLS_VERSION_NUMBER >= 0x030300
1155         {
1156                 gnutls_typed_vdata_st data[1];
1157                 unsigned int elements = 0;
1158
1159                 os_memset(data, 0, sizeof(data));
1160                 if (!conn->global->server) {
1161                         data[elements].type = GNUTLS_DT_KEY_PURPOSE_OID;
1162                         data[elements].data = (void *) GNUTLS_KP_TLS_WWW_SERVER;
1163                         elements++;
1164                 }
1165                 res = gnutls_certificate_verify_peers(session, data, 1,
1166                                                       &status);
1167         }
1168 #else /* < 3.3.0 */
1169         res = gnutls_certificate_verify_peers2(session, &status);
1170 #endif
1171         if (res < 0) {
1172                 wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
1173                            "certificate chain");
1174                 err = GNUTLS_A_INTERNAL_ERROR;
1175                 goto out;
1176         }
1177
1178 #if GNUTLS_VERSION_NUMBER >= 0x030104
1179         {
1180                 gnutls_datum_t info;
1181                 int ret, type;
1182
1183                 type = gnutls_certificate_type_get(session);
1184                 ret = gnutls_certificate_verification_status_print(status, type,
1185                                                                    &info, 0);
1186                 if (ret < 0) {
1187                         wpa_printf(MSG_DEBUG,
1188                                    "GnuTLS: Failed to print verification status");
1189                         err = GNUTLS_A_INTERNAL_ERROR;
1190                         goto out;
1191                 }
1192                 wpa_printf(MSG_DEBUG, "GnuTLS: %s", info.data);
1193                 gnutls_free(info.data);
1194         }
1195 #endif /* GnuTLS 3.1.4 or newer */
1196
1197         certs = gnutls_certificate_get_peers(session, &num_certs);
1198         if (certs == NULL || num_certs == 0) {
1199                 wpa_printf(MSG_INFO, "TLS: No peer certificate chain received");
1200                 err = GNUTLS_A_UNKNOWN_CA;
1201                 goto out;
1202         }
1203
1204         if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
1205                 wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
1206                 if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
1207                         wpa_printf(MSG_INFO, "TLS: Certificate uses insecure "
1208                                    "algorithm");
1209                         gnutls_tls_fail_event(conn, NULL, 0, NULL,
1210                                               "certificate uses insecure algorithm",
1211                                               TLS_FAIL_BAD_CERTIFICATE);
1212                         err = GNUTLS_A_INSUFFICIENT_SECURITY;
1213                         goto out;
1214                 }
1215                 if (status & GNUTLS_CERT_NOT_ACTIVATED) {
1216                         wpa_printf(MSG_INFO, "TLS: Certificate not yet "
1217                                    "activated");
1218                         gnutls_tls_fail_event(conn, NULL, 0, NULL,
1219                                               "certificate not yet valid",
1220                                               TLS_FAIL_NOT_YET_VALID);
1221                         err = GNUTLS_A_CERTIFICATE_EXPIRED;
1222                         goto out;
1223                 }
1224                 if (status & GNUTLS_CERT_EXPIRED) {
1225                         wpa_printf(MSG_INFO, "TLS: Certificate expired");
1226                         gnutls_tls_fail_event(conn, NULL, 0, NULL,
1227                                               "certificate has expired",
1228                                               TLS_FAIL_EXPIRED);
1229                         err = GNUTLS_A_CERTIFICATE_EXPIRED;
1230                         goto out;
1231                 }
1232                 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1233                                       "untrusted certificate",
1234                                       TLS_FAIL_UNTRUSTED);
1235                 err = GNUTLS_A_INTERNAL_ERROR;
1236                 goto out;
1237         }
1238
1239         if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
1240                 wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
1241                            "known issuer");
1242                 gnutls_tls_fail_event(conn, NULL, 0, NULL, "signed not found",
1243                                       TLS_FAIL_UNTRUSTED);
1244                 err = GNUTLS_A_UNKNOWN_CA;
1245                 goto out;
1246         }
1247
1248         if (status & GNUTLS_CERT_REVOKED) {
1249                 wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
1250                 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1251                                       "certificate revoked",
1252                                       TLS_FAIL_REVOKED);
1253                 err = GNUTLS_A_CERTIFICATE_REVOKED;
1254                 goto out;
1255         }
1256
1257         if (status != 0) {
1258                 wpa_printf(MSG_INFO, "TLS: Unknown verification status: %d",
1259                            status);
1260                 err = GNUTLS_A_INTERNAL_ERROR;
1261                 goto out;
1262         }
1263
1264         if (check_ocsp(conn, session, &err))
1265                 goto out;
1266
1267         os_get_time(&now);
1268
1269         for (i = 0; i < num_certs; i++) {
1270                 char *buf;
1271                 size_t len;
1272                 if (gnutls_x509_crt_init(&cert) < 0) {
1273                         wpa_printf(MSG_INFO, "TLS: Certificate initialization "
1274                                    "failed");
1275                         err = GNUTLS_A_BAD_CERTIFICATE;
1276                         goto out;
1277                 }
1278
1279                 if (gnutls_x509_crt_import(cert, &certs[i],
1280                                            GNUTLS_X509_FMT_DER) < 0) {
1281                         wpa_printf(MSG_INFO, "TLS: Could not parse peer "
1282                                    "certificate %d/%d", i + 1, num_certs);
1283                         gnutls_x509_crt_deinit(cert);
1284                         err = GNUTLS_A_BAD_CERTIFICATE;
1285                         goto out;
1286                 }
1287
1288                 gnutls_x509_crt_get_dn(cert, NULL, &len);
1289                 len++;
1290                 buf = os_malloc(len + 1);
1291                 if (buf) {
1292                         buf[0] = buf[len] = '\0';
1293                         gnutls_x509_crt_get_dn(cert, buf, &len);
1294                 }
1295                 wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
1296                            i + 1, num_certs, buf);
1297
1298                 if (conn->global->event_cb) {
1299                         struct wpabuf *cert_buf = NULL;
1300                         union tls_event_data ev;
1301 #ifdef CONFIG_SHA256
1302                         u8 hash[32];
1303                         const u8 *_addr[1];
1304                         size_t _len[1];
1305 #endif /* CONFIG_SHA256 */
1306
1307                         os_memset(&ev, 0, sizeof(ev));
1308                         if (conn->global->cert_in_cb) {
1309                                 cert_buf = wpabuf_alloc_copy(certs[i].data,
1310                                                              certs[i].size);
1311                                 ev.peer_cert.cert = cert_buf;
1312                         }
1313 #ifdef CONFIG_SHA256
1314                         _addr[0] = certs[i].data;
1315                         _len[0] = certs[i].size;
1316                         if (sha256_vector(1, _addr, _len, hash) == 0) {
1317                                 ev.peer_cert.hash = hash;
1318                                 ev.peer_cert.hash_len = sizeof(hash);
1319                         }
1320 #endif /* CONFIG_SHA256 */
1321                         ev.peer_cert.depth = i;
1322                         ev.peer_cert.subject = buf;
1323                         conn->global->event_cb(conn->global->cb_ctx,
1324                                                TLS_PEER_CERTIFICATE, &ev);
1325                         wpabuf_free(cert_buf);
1326                 }
1327
1328                 if (i == 0) {
1329                         if (conn->suffix_match &&
1330                             !tls_match_suffix(cert, conn->suffix_match, 0)) {
1331                                 wpa_printf(MSG_WARNING,
1332                                            "TLS: Domain suffix match '%s' not found",
1333                                            conn->suffix_match);
1334                                 gnutls_tls_fail_event(
1335                                         conn, &certs[i], i, buf,
1336                                         "Domain suffix mismatch",
1337                                         TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
1338                                 err = GNUTLS_A_BAD_CERTIFICATE;
1339                                 gnutls_x509_crt_deinit(cert);
1340                                 os_free(buf);
1341                                 goto out;
1342                         }
1343
1344 #if GNUTLS_VERSION_NUMBER >= 0x030300
1345                         if (conn->domain_match &&
1346                             !tls_match_suffix(cert, conn->domain_match, 1)) {
1347                                 wpa_printf(MSG_WARNING,
1348                                            "TLS: Domain match '%s' not found",
1349                                            conn->domain_match);
1350                                 gnutls_tls_fail_event(
1351                                         conn, &certs[i], i, buf,
1352                                         "Domain mismatch",
1353                                         TLS_FAIL_DOMAIN_MISMATCH);
1354                                 err = GNUTLS_A_BAD_CERTIFICATE;
1355                                 gnutls_x509_crt_deinit(cert);
1356                                 os_free(buf);
1357                                 goto out;
1358                         }
1359 #endif /* >= 3.3.0 */
1360
1361                         /* TODO: validate altsubject_match.
1362                          * For now, any such configuration is rejected in
1363                          * tls_connection_set_params() */
1364
1365 #if GNUTLS_VERSION_NUMBER < 0x030300
1366                         /*
1367                          * gnutls_certificate_verify_peers() not available, so
1368                          * need to check EKU separately.
1369                          */
1370                         if (!conn->global->server &&
1371                             !server_eku_purpose(cert)) {
1372                                 wpa_printf(MSG_WARNING,
1373                                            "GnuTLS: No server EKU");
1374                                 gnutls_tls_fail_event(
1375                                         conn, &certs[i], i, buf,
1376                                         "No server EKU",
1377                                         TLS_FAIL_BAD_CERTIFICATE);
1378                                 err = GNUTLS_A_BAD_CERTIFICATE;
1379                                 gnutls_x509_crt_deinit(cert);
1380                                 os_free(buf);
1381                                 goto out;
1382                         }
1383 #endif /* < 3.3.0 */
1384                 }
1385
1386                 if (!conn->disable_time_checks &&
1387                     (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
1388                      gnutls_x509_crt_get_activation_time(cert) > now.sec)) {
1389                         wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
1390                                    "not valid at this time",
1391                                    i + 1, num_certs);
1392                         gnutls_tls_fail_event(
1393                                 conn, &certs[i], i, buf,
1394                                 "Certificate is not valid at this time",
1395                                 TLS_FAIL_EXPIRED);
1396                         gnutls_x509_crt_deinit(cert);
1397                         os_free(buf);
1398                         err = GNUTLS_A_CERTIFICATE_EXPIRED;
1399                         goto out;
1400                 }
1401
1402                 os_free(buf);
1403
1404                 gnutls_x509_crt_deinit(cert);
1405         }
1406
1407         if (conn->global->event_cb != NULL)
1408                 conn->global->event_cb(conn->global->cb_ctx,
1409                                        TLS_CERT_CHAIN_SUCCESS, NULL);
1410
1411         return 0;
1412
1413 out:
1414         conn->failed++;
1415         gnutls_alert_send(session, GNUTLS_AL_FATAL, err);
1416         return GNUTLS_E_CERTIFICATE_ERROR;
1417 }
1418
1419
1420 static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn)
1421 {
1422         int res;
1423         struct wpabuf *ad;
1424         wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data");
1425         ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3);
1426         if (ad == NULL)
1427                 return NULL;
1428
1429         res = gnutls_record_recv(conn->session, wpabuf_mhead(ad),
1430                                  wpabuf_size(ad));
1431         wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res);
1432         if (res < 0) {
1433                 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
1434                            "(%s)", __func__, (int) res,
1435                            gnutls_strerror(res));
1436                 wpabuf_free(ad);
1437                 return NULL;
1438         }
1439
1440         wpabuf_put(ad, res);
1441         wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data",
1442                    res);
1443         return ad;
1444 }
1445
1446
1447 struct wpabuf * tls_connection_handshake(void *tls_ctx,
1448                                          struct tls_connection *conn,
1449                                          const struct wpabuf *in_data,
1450                                          struct wpabuf **appl_data)
1451 {
1452         struct tls_global *global = tls_ctx;
1453         struct wpabuf *out_data;
1454         int ret;
1455
1456         if (appl_data)
1457                 *appl_data = NULL;
1458
1459         if (in_data && wpabuf_len(in_data) > 0) {
1460                 if (conn->pull_buf) {
1461                         wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
1462                                    "pull_buf", __func__,
1463                                    (unsigned long) wpabuf_len(conn->pull_buf));
1464                         wpabuf_free(conn->pull_buf);
1465                 }
1466                 conn->pull_buf = wpabuf_dup(in_data);
1467                 if (conn->pull_buf == NULL)
1468                         return NULL;
1469                 conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
1470         }
1471
1472         ret = gnutls_handshake(conn->session);
1473         if (ret < 0) {
1474                 gnutls_alert_description_t alert;
1475                 union tls_event_data ev;
1476
1477                 switch (ret) {
1478                 case GNUTLS_E_AGAIN:
1479                         if (global->server && conn->established &&
1480                             conn->push_buf == NULL) {
1481                                 /* Need to return something to trigger
1482                                  * completion of EAP-TLS. */
1483                                 conn->push_buf = wpabuf_alloc(0);
1484                         }
1485                         break;
1486                 case GNUTLS_E_DH_PRIME_UNACCEPTABLE:
1487                         wpa_printf(MSG_DEBUG, "GnuTLS: Unacceptable DH prime");
1488                         if (conn->global->event_cb) {
1489                                 os_memset(&ev, 0, sizeof(ev));
1490                                 ev.alert.is_local = 1;
1491                                 ev.alert.type = "fatal";
1492                                 ev.alert.description = "insufficient security";
1493                                 conn->global->event_cb(conn->global->cb_ctx,
1494                                                        TLS_ALERT, &ev);
1495                         }
1496                         /*
1497                          * Could send a TLS Alert to the server, but for now,
1498                          * simply terminate handshake.
1499                          */
1500                         conn->failed++;
1501                         conn->write_alerts++;
1502                         break;
1503                 case GNUTLS_E_FATAL_ALERT_RECEIVED:
1504                         alert = gnutls_alert_get(conn->session);
1505                         wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
1506                                    __func__, gnutls_alert_get_name(alert));
1507                         conn->read_alerts++;
1508                         if (conn->global->event_cb != NULL) {
1509                                 os_memset(&ev, 0, sizeof(ev));
1510                                 ev.alert.is_local = 0;
1511                                 ev.alert.type = gnutls_alert_get_name(alert);
1512                                 ev.alert.description = ev.alert.type;
1513                                 conn->global->event_cb(conn->global->cb_ctx,
1514                                                        TLS_ALERT, &ev);
1515                         }
1516                         /* continue */
1517                 default:
1518                         wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
1519                                    "-> %s", __func__, gnutls_strerror(ret));
1520                         conn->failed++;
1521                 }
1522         } else {
1523                 size_t size;
1524
1525                 wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
1526
1527 #if GNUTLS_VERSION_NUMBER >= 0x03010a
1528                 {
1529                         char *desc;
1530
1531                         desc = gnutls_session_get_desc(conn->session);
1532                         if (desc) {
1533                                 wpa_printf(MSG_DEBUG, "GnuTLS: %s", desc);
1534                                 gnutls_free(desc);
1535                         }
1536                 }
1537 #endif /* GnuTLS 3.1.10 or newer */
1538
1539                 conn->established = 1;
1540                 if (conn->push_buf == NULL) {
1541                         /* Need to return something to get final TLS ACK. */
1542                         conn->push_buf = wpabuf_alloc(0);
1543                 }
1544
1545                 gnutls_session_get_data(conn->session, NULL, &size);
1546                 if (global->session_data == NULL ||
1547                     global->session_data_size < size) {
1548                         os_free(global->session_data);
1549                         global->session_data = os_malloc(size);
1550                 }
1551                 if (global->session_data) {
1552                         global->session_data_size = size;
1553                         gnutls_session_get_data(conn->session,
1554                                                 global->session_data,
1555                                                 &global->session_data_size);
1556                 }
1557
1558                 if (conn->pull_buf && appl_data)
1559                         *appl_data = gnutls_get_appl_data(conn);
1560         }
1561
1562         out_data = conn->push_buf;
1563         conn->push_buf = NULL;
1564         return out_data;
1565 }
1566
1567
1568 struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
1569                                                 struct tls_connection *conn,
1570                                                 const struct wpabuf *in_data,
1571                                                 struct wpabuf **appl_data)
1572 {
1573         return tls_connection_handshake(tls_ctx, conn, in_data, appl_data);
1574 }
1575
1576
1577 struct wpabuf * tls_connection_encrypt(void *tls_ctx,
1578                                        struct tls_connection *conn,
1579                                        const struct wpabuf *in_data)
1580 {
1581         ssize_t res;
1582         struct wpabuf *buf;
1583
1584         res = gnutls_record_send(conn->session, wpabuf_head(in_data),
1585                                  wpabuf_len(in_data));
1586         if (res < 0) {
1587                 wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
1588                            __func__, gnutls_strerror(res));
1589                 return NULL;
1590         }
1591
1592         buf = conn->push_buf;
1593         conn->push_buf = NULL;
1594         return buf;
1595 }
1596
1597
1598 struct wpabuf * tls_connection_decrypt(void *tls_ctx,
1599                                        struct tls_connection *conn,
1600                                        const struct wpabuf *in_data)
1601 {
1602         ssize_t res;
1603         struct wpabuf *out;
1604
1605         if (conn->pull_buf) {
1606                 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
1607                            "pull_buf", __func__,
1608                            (unsigned long) wpabuf_len(conn->pull_buf));
1609                 wpabuf_free(conn->pull_buf);
1610         }
1611         conn->pull_buf = wpabuf_dup(in_data);
1612         if (conn->pull_buf == NULL)
1613                 return NULL;
1614         conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
1615
1616         /*
1617          * Even though we try to disable TLS compression, it is possible that
1618          * this cannot be done with all TLS libraries. Add extra buffer space
1619          * to handle the possibility of the decrypted data being longer than
1620          * input data.
1621          */
1622         out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
1623         if (out == NULL)
1624                 return NULL;
1625
1626         res = gnutls_record_recv(conn->session, wpabuf_mhead(out),
1627                                  wpabuf_size(out));
1628         if (res < 0) {
1629                 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
1630                            "(%s)", __func__, (int) res, gnutls_strerror(res));
1631                 wpabuf_free(out);
1632                 return NULL;
1633         }
1634         wpabuf_put(out, res);
1635
1636         return out;
1637 }
1638
1639
1640 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
1641 {
1642         if (conn == NULL)
1643                 return 0;
1644         return gnutls_session_is_resumed(conn->session);
1645 }
1646
1647
1648 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
1649                                    u8 *ciphers)
1650 {
1651         /* TODO */
1652         return -1;
1653 }
1654
1655
1656 int tls_get_version(void *ssl_ctx, struct tls_connection *conn,
1657                     char *buf, size_t buflen)
1658 {
1659         gnutls_protocol_t ver;
1660
1661         ver = gnutls_protocol_get_version(conn->session);
1662         if (ver == GNUTLS_TLS1_0)
1663                 os_strlcpy(buf, "TLSv1", buflen);
1664         else if (ver == GNUTLS_TLS1_1)
1665                 os_strlcpy(buf, "TLSv1.1", buflen);
1666         else if (ver == GNUTLS_TLS1_2)
1667                 os_strlcpy(buf, "TLSv1.2", buflen);
1668         else
1669                 return -1;
1670         return 0;
1671 }
1672
1673
1674 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
1675                    char *buf, size_t buflen)
1676 {
1677         gnutls_cipher_algorithm_t cipher;
1678         gnutls_kx_algorithm_t kx;
1679         gnutls_mac_algorithm_t mac;
1680         const char *kx_str, *cipher_str, *mac_str;
1681         int res;
1682
1683         cipher = gnutls_cipher_get(conn->session);
1684         cipher_str = gnutls_cipher_get_name(cipher);
1685         if (!cipher_str)
1686                 cipher_str = "";
1687
1688         kx = gnutls_kx_get(conn->session);
1689         kx_str = gnutls_kx_get_name(kx);
1690         if (!kx_str)
1691                 kx_str = "";
1692
1693         mac = gnutls_mac_get(conn->session);
1694         mac_str = gnutls_mac_get_name(mac);
1695         if (!mac_str)
1696                 mac_str = "";
1697
1698         if (kx == GNUTLS_KX_RSA)
1699                 res = os_snprintf(buf, buflen, "%s-%s", cipher_str, mac_str);
1700         else
1701                 res = os_snprintf(buf, buflen, "%s-%s-%s",
1702                                   kx_str, cipher_str, mac_str);
1703         if (os_snprintf_error(buflen, res))
1704                 return -1;
1705
1706         return 0;
1707 }
1708
1709
1710 int tls_connection_enable_workaround(void *ssl_ctx,
1711                                      struct tls_connection *conn)
1712 {
1713         gnutls_record_disable_padding(conn->session);
1714         return 0;
1715 }
1716
1717
1718 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
1719                                     int ext_type, const u8 *data,
1720                                     size_t data_len)
1721 {
1722         /* TODO */
1723         return -1;
1724 }
1725
1726
1727 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
1728 {
1729         if (conn == NULL)
1730                 return -1;
1731         return conn->failed;
1732 }
1733
1734
1735 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
1736 {
1737         if (conn == NULL)
1738                 return -1;
1739         return conn->read_alerts;
1740 }
1741
1742
1743 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
1744 {
1745         if (conn == NULL)
1746                 return -1;
1747         return conn->write_alerts;
1748 }
1749
1750
1751 int tls_connection_set_session_ticket_cb(void *tls_ctx,
1752                                          struct tls_connection *conn,
1753                                          tls_session_ticket_cb cb, void *ctx)
1754 {
1755         return -1;
1756 }
1757
1758
1759 int tls_get_library_version(char *buf, size_t buf_len)
1760 {
1761         return os_snprintf(buf, buf_len, "GnuTLS build=%s run=%s",
1762                            GNUTLS_VERSION, gnutls_check_version(NULL));
1763 }
1764
1765
1766 void tls_connection_set_success_data(struct tls_connection *conn,
1767                                      struct wpabuf *data)
1768 {
1769 }
1770
1771
1772 void tls_connection_set_success_data_resumed(struct tls_connection *conn)
1773 {
1774 }
1775
1776
1777 const struct wpabuf *
1778 tls_connection_get_success_data(struct tls_connection *conn)
1779 {
1780         return NULL;
1781 }
1782
1783
1784 void tls_connection_remove_session(struct tls_connection *conn)
1785 {
1786 }