2 * SSL/TLS interface functions for GnuTLS
3 * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
10 #include <gnutls/gnutls.h>
11 #include <gnutls/x509.h>
13 #include <gnutls/pkcs12.h>
14 #endif /* PKCS12_FUNCS */
20 #define WPA_TLS_RANDOM_SIZE 32
21 #define WPA_TLS_MASTER_SIZE 48
24 #if LIBGNUTLS_VERSION_NUMBER < 0x010302
25 /* GnuTLS 1.3.2 added functions for using master secret. Older versions require
26 * use of internal structures to get the master_secret and
27 * {server,client}_random.
29 #define GNUTLS_INTERNAL_STRUCTURE_HACK
30 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */
33 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
35 * It looks like gnutls does not provide access to client/server_random and
36 * master_key. This is somewhat unfortunate since these are needed for key
37 * derivation in EAP-{TLS,TTLS,PEAP,FAST}. Workaround for now is a horrible
38 * hack that copies the gnutls_session_int definition from gnutls_int.h so that
39 * we can get the needed information.
43 typedef unsigned char opaque;
49 gnutls_connection_end_t entity;
50 gnutls_kx_algorithm_t kx_algorithm;
51 gnutls_cipher_algorithm_t read_bulk_cipher_algorithm;
52 gnutls_mac_algorithm_t read_mac_algorithm;
53 gnutls_compression_method_t read_compression_algorithm;
54 gnutls_cipher_algorithm_t write_bulk_cipher_algorithm;
55 gnutls_mac_algorithm_t write_mac_algorithm;
56 gnutls_compression_method_t write_compression_algorithm;
57 cipher_suite_st current_cipher_suite;
58 opaque master_secret[WPA_TLS_MASTER_SIZE];
59 opaque client_random[WPA_TLS_RANDOM_SIZE];
60 opaque server_random[WPA_TLS_RANDOM_SIZE];
61 /* followed by stuff we are not interested in */
62 } security_parameters_st;
64 struct gnutls_session_int {
65 security_parameters_st security_parameters;
66 /* followed by things we are not interested in */
68 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */
70 static int tls_gnutls_ref_count = 0;
73 /* Data for session resumption */
75 size_t session_data_size;
80 gnutls_certificate_credentials_t xcred;
83 struct tls_connection {
84 gnutls_session session;
85 char *subject_match, *altsubject_match;
86 int read_alerts, write_alerts, failed;
88 u8 *pre_shared_secret;
89 size_t pre_shared_secret_len;
93 struct wpabuf *push_buf;
94 struct wpabuf *pull_buf;
95 const u8 *pull_buf_offset;
98 gnutls_certificate_credentials_t xcred;
102 static void tls_log_func(int level, const char *msg)
105 if (level == 6 || level == 7) {
106 /* These levels seem to be mostly I/O debug and msg dumps */
115 while (*pos != '\0') {
122 wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG,
123 "gnutls<%d> %s", level, s);
128 extern int wpa_debug_show_keys;
130 void * tls_init(const struct tls_config *conf)
132 struct tls_global *global;
134 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
135 /* Because of the horrible hack to get master_secret and client/server
136 * random, we need to make sure that the gnutls version is something
137 * that is expected to have same structure definition for the session
140 const char *ok_ver[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", "1.2.9",
144 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
146 global = os_zalloc(sizeof(*global));
150 if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) {
154 tls_gnutls_ref_count++;
156 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
157 ver = gnutls_check_version(NULL);
162 wpa_printf(MSG_DEBUG, "%s - gnutls version %s", __func__, ver);
163 for (i = 0; ok_ver[i]; i++) {
164 if (strcmp(ok_ver[i], ver) == 0)
167 if (ok_ver[i] == NULL) {
168 wpa_printf(MSG_INFO, "Untested gnutls version %s - this needs "
169 "to be tested and enabled in tls_gnutls.c", ver);
173 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
175 gnutls_global_set_log_function(tls_log_func);
176 if (wpa_debug_show_keys)
177 gnutls_global_set_log_level(11);
182 void tls_deinit(void *ssl_ctx)
184 struct tls_global *global = ssl_ctx;
186 if (global->params_set)
187 gnutls_certificate_free_credentials(global->xcred);
188 os_free(global->session_data);
192 tls_gnutls_ref_count--;
193 if (tls_gnutls_ref_count == 0)
194 gnutls_global_deinit();
198 int tls_get_errors(void *ssl_ctx)
204 static ssize_t tls_pull_func(gnutls_transport_ptr ptr, void *buf,
207 struct tls_connection *conn = (struct tls_connection *) ptr;
209 if (conn->pull_buf == NULL) {
214 end = wpabuf_head_u8(conn->pull_buf) + wpabuf_len(conn->pull_buf);
215 if ((size_t) (end - conn->pull_buf_offset) < len)
216 len = end - conn->pull_buf_offset;
217 os_memcpy(buf, conn->pull_buf_offset, len);
218 conn->pull_buf_offset += len;
219 if (conn->pull_buf_offset == end) {
220 wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
221 wpabuf_free(conn->pull_buf);
222 conn->pull_buf = NULL;
223 conn->pull_buf_offset = NULL;
225 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf",
227 (unsigned long) (end - conn->pull_buf_offset));
233 static ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf,
236 struct tls_connection *conn = (struct tls_connection *) ptr;
238 if (wpabuf_resize(&conn->push_buf, len) < 0) {
242 wpabuf_put_data(conn->push_buf, buf, len);
248 static int tls_gnutls_init_session(struct tls_global *global,
249 struct tls_connection *conn)
251 #if LIBGNUTLS_VERSION_NUMBER >= 0x020200
253 #else /* LIBGNUTLS_VERSION_NUMBER >= 0x020200 */
254 const int cert_types[2] = { GNUTLS_CRT_X509, 0 };
255 const int protos[2] = { GNUTLS_TLS1, 0 };
256 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x020200 */
259 ret = gnutls_init(&conn->session,
260 global->server ? GNUTLS_SERVER : GNUTLS_CLIENT);
262 wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS "
263 "connection: %s", gnutls_strerror(ret));
267 ret = gnutls_set_default_priority(conn->session);
271 #if LIBGNUTLS_VERSION_NUMBER >= 0x020200
272 ret = gnutls_priority_set_direct(conn->session, "NORMAL:-VERS-SSL3.0",
275 wpa_printf(MSG_ERROR, "GnuTLS: Priority string failure at "
279 #else /* LIBGNUTLS_VERSION_NUMBER >= 0x020200 */
280 ret = gnutls_certificate_type_set_priority(conn->session, cert_types);
284 ret = gnutls_protocol_set_priority(conn->session, protos);
287 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x020200 */
289 gnutls_transport_set_pull_function(conn->session, tls_pull_func);
290 gnutls_transport_set_push_function(conn->session, tls_push_func);
291 gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn);
296 wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s",
297 gnutls_strerror(ret));
298 gnutls_deinit(conn->session);
303 struct tls_connection * tls_connection_init(void *ssl_ctx)
305 struct tls_global *global = ssl_ctx;
306 struct tls_connection *conn;
309 conn = os_zalloc(sizeof(*conn));
313 if (tls_gnutls_init_session(global, conn)) {
318 if (global->params_set) {
319 ret = gnutls_credentials_set(conn->session,
320 GNUTLS_CRD_CERTIFICATE,
323 wpa_printf(MSG_INFO, "Failed to configure "
324 "credentials: %s", gnutls_strerror(ret));
330 if (gnutls_certificate_allocate_credentials(&conn->xcred)) {
339 void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
344 gnutls_certificate_free_credentials(conn->xcred);
345 gnutls_deinit(conn->session);
346 os_free(conn->pre_shared_secret);
347 os_free(conn->subject_match);
348 os_free(conn->altsubject_match);
349 wpabuf_free(conn->push_buf);
350 wpabuf_free(conn->pull_buf);
355 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
357 return conn ? conn->established : 0;
361 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
363 struct tls_global *global = ssl_ctx;
369 /* Shutdown previous TLS connection without notifying the peer
370 * because the connection was already terminated in practice
371 * and "close notify" shutdown alert would confuse AS. */
372 gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
373 wpabuf_free(conn->push_buf);
374 conn->push_buf = NULL;
375 conn->established = 0;
377 gnutls_deinit(conn->session);
378 if (tls_gnutls_init_session(global, conn)) {
379 wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session "
380 "for session resumption use");
384 ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
385 conn->params_set ? conn->xcred :
388 wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials "
389 "for session resumption: %s", gnutls_strerror(ret));
393 if (global->session_data) {
394 ret = gnutls_session_set_data(conn->session,
395 global->session_data,
396 global->session_data_size);
398 wpa_printf(MSG_INFO, "GnuTLS: Failed to set session "
399 "data: %s", gnutls_strerror(ret));
409 static int tls_match_altsubject(X509 *cert, const char *match)
417 ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
419 for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
420 gen = sk_GENERAL_NAME_value(ext, i);
433 wpa_printf(MSG_DEBUG, "TLS: altSubjectName: "
434 "unsupported type=%d", gen->type);
441 wpa_printf(MSG_DEBUG, "TLS: altSubjectName: %s:%s",
442 field, gen->d.ia5->data);
443 len = os_strlen(field) + 1 +
444 strlen((char *) gen->d.ia5->data) + 1;
445 tmp = os_malloc(len);
448 snprintf(tmp, len, "%s:%s", field, gen->d.ia5->data);
449 if (strstr(tmp, match))
460 static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
466 struct tls_connection *conn;
467 char *match, *altmatch;
469 err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
470 err = X509_STORE_CTX_get_error(x509_ctx);
471 depth = X509_STORE_CTX_get_error_depth(x509_ctx);
472 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
473 SSL_get_ex_data_X509_STORE_CTX_idx());
474 X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
476 conn = SSL_get_app_data(ssl);
477 match = conn ? conn->subject_match : NULL;
478 altmatch = conn ? conn->altsubject_match : NULL;
481 wpa_printf(MSG_WARNING, "TLS: Certificate verification failed,"
482 " error %d (%s) depth %d for '%s'", err,
483 X509_verify_cert_error_string(err), depth, buf);
485 wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - "
486 "preverify_ok=%d err=%d (%s) depth=%d buf='%s'",
488 X509_verify_cert_error_string(err), depth, buf);
489 if (depth == 0 && match && strstr(buf, match) == NULL) {
490 wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
491 "match with '%s'", buf, match);
493 } else if (depth == 0 && altmatch &&
494 !tls_match_altsubject(err_cert, altmatch)) {
495 wpa_printf(MSG_WARNING, "TLS: altSubjectName match "
496 "'%s' not found", altmatch);
506 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
507 const struct tls_connection_params *params)
511 if (conn == NULL || params == NULL)
514 os_free(conn->subject_match);
515 conn->subject_match = NULL;
516 if (params->subject_match) {
517 conn->subject_match = os_strdup(params->subject_match);
518 if (conn->subject_match == NULL)
522 os_free(conn->altsubject_match);
523 conn->altsubject_match = NULL;
524 if (params->altsubject_match) {
525 conn->altsubject_match = os_strdup(params->altsubject_match);
526 if (conn->altsubject_match == NULL)
530 /* TODO: gnutls_certificate_set_verify_flags(xcred, flags);
531 * to force peer validation(?) */
533 if (params->ca_cert) {
534 conn->verify_peer = 1;
535 ret = gnutls_certificate_set_x509_trust_file(
536 conn->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM);
538 wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
539 "in PEM format: %s", params->ca_cert,
540 gnutls_strerror(ret));
541 ret = gnutls_certificate_set_x509_trust_file(
542 conn->xcred, params->ca_cert,
543 GNUTLS_X509_FMT_DER);
545 wpa_printf(MSG_DEBUG, "Failed to read CA cert "
546 "'%s' in DER format: %s",
548 gnutls_strerror(ret));
553 if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
554 gnutls_certificate_set_verify_flags(
555 conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
558 #if LIBGNUTLS_VERSION_NUMBER >= 0x020800
559 if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
560 gnutls_certificate_set_verify_flags(
562 GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
564 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x020800 */
567 if (params->client_cert && params->private_key) {
568 /* TODO: private_key_passwd? */
569 ret = gnutls_certificate_set_x509_key_file(
570 conn->xcred, params->client_cert, params->private_key,
571 GNUTLS_X509_FMT_PEM);
573 wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
574 "in PEM format: %s", gnutls_strerror(ret));
575 ret = gnutls_certificate_set_x509_key_file(
576 conn->xcred, params->client_cert,
577 params->private_key, GNUTLS_X509_FMT_DER);
579 wpa_printf(MSG_DEBUG, "Failed to read client "
580 "cert/key in DER format: %s",
581 gnutls_strerror(ret));
585 } else if (params->private_key) {
588 /* Try to load in PKCS#12 format */
589 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
590 ret = gnutls_certificate_set_x509_simple_pkcs12_file(
591 conn->xcred, params->private_key, GNUTLS_X509_FMT_DER,
592 params->private_key_passwd);
594 wpa_printf(MSG_DEBUG, "Failed to load private_key in "
595 "PKCS#12 format: %s", gnutls_strerror(ret));
599 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
600 #endif /* PKCS12_FUNCS */
603 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
609 conn->params_set = 1;
611 ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
614 wpa_printf(MSG_INFO, "Failed to configure credentials: %s",
615 gnutls_strerror(ret));
622 int tls_global_set_params(void *tls_ctx,
623 const struct tls_connection_params *params)
625 struct tls_global *global = tls_ctx;
628 /* Currently, global parameters are only set when running in server
632 if (global->params_set) {
633 gnutls_certificate_free_credentials(global->xcred);
634 global->params_set = 0;
637 ret = gnutls_certificate_allocate_credentials(&global->xcred);
639 wpa_printf(MSG_DEBUG, "Failed to allocate global credentials "
640 "%s", gnutls_strerror(ret));
644 if (params->ca_cert) {
645 ret = gnutls_certificate_set_x509_trust_file(
646 global->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM);
648 wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
649 "in PEM format: %s", params->ca_cert,
650 gnutls_strerror(ret));
651 ret = gnutls_certificate_set_x509_trust_file(
652 global->xcred, params->ca_cert,
653 GNUTLS_X509_FMT_DER);
655 wpa_printf(MSG_DEBUG, "Failed to read CA cert "
656 "'%s' in DER format: %s",
658 gnutls_strerror(ret));
663 if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
664 gnutls_certificate_set_verify_flags(
666 GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
669 #if LIBGNUTLS_VERSION_NUMBER >= 0x020800
670 if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
671 gnutls_certificate_set_verify_flags(
673 GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
675 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x020800 */
678 if (params->client_cert && params->private_key) {
679 /* TODO: private_key_passwd? */
680 ret = gnutls_certificate_set_x509_key_file(
681 global->xcred, params->client_cert,
682 params->private_key, GNUTLS_X509_FMT_PEM);
684 wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
685 "in PEM format: %s", gnutls_strerror(ret));
686 ret = gnutls_certificate_set_x509_key_file(
687 global->xcred, params->client_cert,
688 params->private_key, GNUTLS_X509_FMT_DER);
690 wpa_printf(MSG_DEBUG, "Failed to read client "
691 "cert/key in DER format: %s",
692 gnutls_strerror(ret));
696 } else if (params->private_key) {
699 /* Try to load in PKCS#12 format */
700 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
701 ret = gnutls_certificate_set_x509_simple_pkcs12_file(
702 global->xcred, params->private_key,
703 GNUTLS_X509_FMT_DER, params->private_key_passwd);
705 wpa_printf(MSG_DEBUG, "Failed to load private_key in "
706 "PKCS#12 format: %s", gnutls_strerror(ret));
710 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
711 #endif /* PKCS12_FUNCS */
714 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
720 global->params_set = 1;
725 gnutls_certificate_free_credentials(global->xcred);
730 int tls_global_set_verify(void *ssl_ctx, int check_crl)
737 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
740 if (conn == NULL || conn->session == NULL)
743 conn->verify_peer = verify_peer;
744 gnutls_certificate_server_set_request(conn->session,
745 verify_peer ? GNUTLS_CERT_REQUIRE
746 : GNUTLS_CERT_REQUEST);
752 int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
753 struct tls_keys *keys)
755 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
756 security_parameters_st *sec;
757 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
759 if (conn == NULL || conn->session == NULL || keys == NULL)
762 os_memset(keys, 0, sizeof(*keys));
764 #if LIBGNUTLS_VERSION_NUMBER < 0x020c00
765 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
766 sec = &conn->session->security_parameters;
767 keys->master_key = sec->master_secret;
768 keys->master_key_len = WPA_TLS_MASTER_SIZE;
769 keys->client_random = sec->client_random;
770 keys->server_random = sec->server_random;
771 #else /* GNUTLS_INTERNAL_STRUCTURE_HACK */
772 keys->client_random =
773 (u8 *) gnutls_session_get_client_random(conn->session);
774 keys->server_random =
775 (u8 *) gnutls_session_get_server_random(conn->session);
776 /* No access to master_secret */
777 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
778 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x020c00 */
780 #if LIBGNUTLS_VERSION_NUMBER < 0x020c00
781 keys->client_random_len = WPA_TLS_RANDOM_SIZE;
782 keys->server_random_len = WPA_TLS_RANDOM_SIZE;
783 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x020c00 */
789 int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
790 const char *label, int server_random_first,
791 u8 *out, size_t out_len)
793 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
794 if (conn == NULL || conn->session == NULL)
797 return gnutls_prf(conn->session, os_strlen(label), label,
798 server_random_first, 0, NULL, out_len, (char *) out);
799 #else /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
801 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
805 static int tls_connection_verify_peer(struct tls_connection *conn,
806 gnutls_alert_description_t *err)
808 unsigned int status, num_certs, i;
810 const gnutls_datum_t *certs;
811 gnutls_x509_crt_t cert;
813 if (gnutls_certificate_verify_peers2(conn->session, &status) < 0) {
814 wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
815 "certificate chain");
816 *err = GNUTLS_A_INTERNAL_ERROR;
820 if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
821 wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
822 *err = GNUTLS_A_INTERNAL_ERROR;
823 if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
824 wpa_printf(MSG_INFO, "TLS: Certificate uses insecure "
826 *err = GNUTLS_A_INSUFFICIENT_SECURITY;
828 #if LIBGNUTLS_VERSION_NUMBER >= 0x020800
829 if (status & GNUTLS_CERT_NOT_ACTIVATED) {
830 wpa_printf(MSG_INFO, "TLS: Certificate not yet "
832 *err = GNUTLS_A_CERTIFICATE_EXPIRED;
834 if (status & GNUTLS_CERT_EXPIRED) {
835 wpa_printf(MSG_INFO, "TLS: Certificate expired");
836 *err = GNUTLS_A_CERTIFICATE_EXPIRED;
838 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x020800 */
842 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
843 wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
845 *err = GNUTLS_A_UNKNOWN_CA;
849 if (status & GNUTLS_CERT_REVOKED) {
850 wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
851 *err = GNUTLS_A_CERTIFICATE_REVOKED;
857 certs = gnutls_certificate_get_peers(conn->session, &num_certs);
859 wpa_printf(MSG_INFO, "TLS: No peer certificate chain "
861 *err = GNUTLS_A_UNKNOWN_CA;
865 for (i = 0; i < num_certs; i++) {
868 if (gnutls_x509_crt_init(&cert) < 0) {
869 wpa_printf(MSG_INFO, "TLS: Certificate initialization "
871 *err = GNUTLS_A_BAD_CERTIFICATE;
875 if (gnutls_x509_crt_import(cert, &certs[i],
876 GNUTLS_X509_FMT_DER) < 0) {
877 wpa_printf(MSG_INFO, "TLS: Could not parse peer "
878 "certificate %d/%d", i + 1, num_certs);
879 gnutls_x509_crt_deinit(cert);
880 *err = GNUTLS_A_BAD_CERTIFICATE;
884 gnutls_x509_crt_get_dn(cert, NULL, &len);
886 buf = os_malloc(len + 1);
888 buf[0] = buf[len] = '\0';
889 gnutls_x509_crt_get_dn(cert, buf, &len);
891 wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
892 i + 1, num_certs, buf);
895 /* TODO: validate subject_match and altsubject_match */
900 if (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
901 gnutls_x509_crt_get_activation_time(cert) > now.sec) {
902 wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
903 "not valid at this time",
905 gnutls_x509_crt_deinit(cert);
906 *err = GNUTLS_A_CERTIFICATE_EXPIRED;
910 gnutls_x509_crt_deinit(cert);
917 static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn)
921 wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data");
922 ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3);
926 res = gnutls_record_recv(conn->session, wpabuf_mhead(ad),
928 wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res);
930 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
931 "(%s)", __func__, (int) res,
932 gnutls_strerror(res));
938 wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data",
944 struct wpabuf * tls_connection_handshake(void *tls_ctx,
945 struct tls_connection *conn,
946 const struct wpabuf *in_data,
947 struct wpabuf **appl_data)
949 struct tls_global *global = tls_ctx;
950 struct wpabuf *out_data;
956 if (in_data && wpabuf_len(in_data) > 0) {
957 if (conn->pull_buf) {
958 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
959 "pull_buf", __func__,
960 (unsigned long) wpabuf_len(conn->pull_buf));
961 wpabuf_free(conn->pull_buf);
963 conn->pull_buf = wpabuf_dup(in_data);
964 if (conn->pull_buf == NULL)
966 conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
969 ret = gnutls_handshake(conn->session);
973 if (global->server && conn->established &&
974 conn->push_buf == NULL) {
975 /* Need to return something to trigger
976 * completion of EAP-TLS. */
977 conn->push_buf = wpabuf_alloc(0);
980 case GNUTLS_E_FATAL_ALERT_RECEIVED:
981 wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
982 __func__, gnutls_alert_get_name(
983 gnutls_alert_get(conn->session)));
987 wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
988 "-> %s", __func__, gnutls_strerror(ret));
993 gnutls_alert_description_t err;
995 if (conn->verify_peer &&
996 tls_connection_verify_peer(conn, &err)) {
997 wpa_printf(MSG_INFO, "TLS: Peer certificate chain "
998 "failed validation");
1000 gnutls_alert_send(conn->session, GNUTLS_AL_FATAL, err);
1004 wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
1005 conn->established = 1;
1006 if (conn->push_buf == NULL) {
1007 /* Need to return something to get final TLS ACK. */
1008 conn->push_buf = wpabuf_alloc(0);
1011 gnutls_session_get_data(conn->session, NULL, &size);
1012 if (global->session_data == NULL ||
1013 global->session_data_size < size) {
1014 os_free(global->session_data);
1015 global->session_data = os_malloc(size);
1017 if (global->session_data) {
1018 global->session_data_size = size;
1019 gnutls_session_get_data(conn->session,
1020 global->session_data,
1021 &global->session_data_size);
1024 if (conn->pull_buf && appl_data)
1025 *appl_data = gnutls_get_appl_data(conn);
1029 out_data = conn->push_buf;
1030 conn->push_buf = NULL;
1035 struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
1036 struct tls_connection *conn,
1037 const struct wpabuf *in_data,
1038 struct wpabuf **appl_data)
1040 return tls_connection_handshake(tls_ctx, conn, in_data, appl_data);
1044 struct wpabuf * tls_connection_encrypt(void *tls_ctx,
1045 struct tls_connection *conn,
1046 const struct wpabuf *in_data)
1051 res = gnutls_record_send(conn->session, wpabuf_head(in_data),
1052 wpabuf_len(in_data));
1054 wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
1055 __func__, gnutls_strerror(res));
1059 buf = conn->push_buf;
1060 conn->push_buf = NULL;
1065 struct wpabuf * tls_connection_decrypt(void *tls_ctx,
1066 struct tls_connection *conn,
1067 const struct wpabuf *in_data)
1072 if (conn->pull_buf) {
1073 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
1074 "pull_buf", __func__,
1075 (unsigned long) wpabuf_len(conn->pull_buf));
1076 wpabuf_free(conn->pull_buf);
1078 conn->pull_buf = wpabuf_dup(in_data);
1079 if (conn->pull_buf == NULL)
1081 conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
1084 * Even though we try to disable TLS compression, it is possible that
1085 * this cannot be done with all TLS libraries. Add extra buffer space
1086 * to handle the possibility of the decrypted data being longer than
1089 out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
1093 res = gnutls_record_recv(conn->session, wpabuf_mhead(out),
1096 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
1097 "(%s)", __func__, (int) res, gnutls_strerror(res));
1101 wpabuf_put(out, res);
1107 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
1111 return gnutls_session_is_resumed(conn->session);
1115 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
1123 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
1124 char *buf, size_t buflen)
1132 int tls_connection_enable_workaround(void *ssl_ctx,
1133 struct tls_connection *conn)
1135 gnutls_record_disable_padding(conn->session);
1140 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
1141 int ext_type, const u8 *data,
1149 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
1153 return conn->failed;
1157 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
1161 return conn->read_alerts;
1165 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
1169 return conn->write_alerts;
1173 int tls_connection_get_keyblock_size(void *tls_ctx,
1174 struct tls_connection *conn)
1181 unsigned int tls_capabilities(void *tls_ctx)
1187 int tls_connection_set_session_ticket_cb(void *tls_ctx,
1188 struct tls_connection *conn,
1189 tls_session_ticket_cb cb, void *ctx)