16d49e1aeSJan Lentfer /*
23ff40c12SJohn Marino * SSL/TLS interface functions for GnuTLS
3*a1157835SDaniel Fojt * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi>
46d49e1aeSJan Lentfer *
53ff40c12SJohn Marino * This software may be distributed under the terms of the BSD license.
63ff40c12SJohn Marino * See README for more details.
76d49e1aeSJan Lentfer */
86d49e1aeSJan Lentfer
96d49e1aeSJan Lentfer #include "includes.h"
106d49e1aeSJan Lentfer #include <gnutls/gnutls.h>
116d49e1aeSJan Lentfer #include <gnutls/x509.h>
126d49e1aeSJan Lentfer #ifdef PKCS12_FUNCS
136d49e1aeSJan Lentfer #include <gnutls/pkcs12.h>
146d49e1aeSJan Lentfer #endif /* PKCS12_FUNCS */
15*a1157835SDaniel Fojt #if GNUTLS_VERSION_NUMBER >= 0x030103
16*a1157835SDaniel Fojt #include <gnutls/ocsp.h>
17*a1157835SDaniel Fojt #endif /* 3.1.3 */
186d49e1aeSJan Lentfer
196d49e1aeSJan Lentfer #include "common.h"
20*a1157835SDaniel Fojt #include "crypto/crypto.h"
216d49e1aeSJan Lentfer #include "tls.h"
226d49e1aeSJan Lentfer
236d49e1aeSJan Lentfer
246d49e1aeSJan Lentfer static int tls_gnutls_ref_count = 0;
256d49e1aeSJan Lentfer
266d49e1aeSJan Lentfer struct tls_global {
276d49e1aeSJan Lentfer /* Data for session resumption */
286d49e1aeSJan Lentfer void *session_data;
296d49e1aeSJan Lentfer size_t session_data_size;
306d49e1aeSJan Lentfer
316d49e1aeSJan Lentfer int server;
326d49e1aeSJan Lentfer
336d49e1aeSJan Lentfer int params_set;
346d49e1aeSJan Lentfer gnutls_certificate_credentials_t xcred;
35*a1157835SDaniel Fojt
36*a1157835SDaniel Fojt void (*event_cb)(void *ctx, enum tls_event ev,
37*a1157835SDaniel Fojt union tls_event_data *data);
38*a1157835SDaniel Fojt void *cb_ctx;
39*a1157835SDaniel Fojt int cert_in_cb;
40*a1157835SDaniel Fojt
41*a1157835SDaniel Fojt char *ocsp_stapling_response;
426d49e1aeSJan Lentfer };
436d49e1aeSJan Lentfer
446d49e1aeSJan Lentfer struct tls_connection {
45*a1157835SDaniel Fojt struct tls_global *global;
46*a1157835SDaniel Fojt gnutls_session_t session;
476d49e1aeSJan Lentfer int read_alerts, write_alerts, failed;
486d49e1aeSJan Lentfer
496d49e1aeSJan Lentfer u8 *pre_shared_secret;
506d49e1aeSJan Lentfer size_t pre_shared_secret_len;
516d49e1aeSJan Lentfer int established;
526d49e1aeSJan Lentfer int verify_peer;
53*a1157835SDaniel Fojt unsigned int disable_time_checks:1;
546d49e1aeSJan Lentfer
553ff40c12SJohn Marino struct wpabuf *push_buf;
563ff40c12SJohn Marino struct wpabuf *pull_buf;
573ff40c12SJohn Marino const u8 *pull_buf_offset;
586d49e1aeSJan Lentfer
596d49e1aeSJan Lentfer int params_set;
606d49e1aeSJan Lentfer gnutls_certificate_credentials_t xcred;
61*a1157835SDaniel Fojt
62*a1157835SDaniel Fojt char *suffix_match;
63*a1157835SDaniel Fojt char *domain_match;
64*a1157835SDaniel Fojt unsigned int flags;
656d49e1aeSJan Lentfer };
666d49e1aeSJan Lentfer
676d49e1aeSJan Lentfer
68*a1157835SDaniel Fojt static int tls_connection_verify_peer(gnutls_session_t session);
69*a1157835SDaniel Fojt
70*a1157835SDaniel Fojt
tls_log_func(int level,const char * msg)716d49e1aeSJan Lentfer static void tls_log_func(int level, const char *msg)
726d49e1aeSJan Lentfer {
736d49e1aeSJan Lentfer char *s, *pos;
746d49e1aeSJan Lentfer if (level == 6 || level == 7) {
756d49e1aeSJan Lentfer /* These levels seem to be mostly I/O debug and msg dumps */
766d49e1aeSJan Lentfer return;
776d49e1aeSJan Lentfer }
786d49e1aeSJan Lentfer
796d49e1aeSJan Lentfer s = os_strdup(msg);
806d49e1aeSJan Lentfer if (s == NULL)
816d49e1aeSJan Lentfer return;
826d49e1aeSJan Lentfer
836d49e1aeSJan Lentfer pos = s;
846d49e1aeSJan Lentfer while (*pos != '\0') {
856d49e1aeSJan Lentfer if (*pos == '\n') {
866d49e1aeSJan Lentfer *pos = '\0';
876d49e1aeSJan Lentfer break;
886d49e1aeSJan Lentfer }
896d49e1aeSJan Lentfer pos++;
906d49e1aeSJan Lentfer }
916d49e1aeSJan Lentfer wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG,
926d49e1aeSJan Lentfer "gnutls<%d> %s", level, s);
936d49e1aeSJan Lentfer os_free(s);
946d49e1aeSJan Lentfer }
956d49e1aeSJan Lentfer
966d49e1aeSJan Lentfer
tls_init(const struct tls_config * conf)976d49e1aeSJan Lentfer void * tls_init(const struct tls_config *conf)
986d49e1aeSJan Lentfer {
996d49e1aeSJan Lentfer struct tls_global *global;
1006d49e1aeSJan Lentfer
101*a1157835SDaniel Fojt if (tls_gnutls_ref_count == 0) {
102*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
103*a1157835SDaniel Fojt "GnuTLS: Library version %s (runtime) - %s (build)",
104*a1157835SDaniel Fojt gnutls_check_version(NULL), GNUTLS_VERSION);
105*a1157835SDaniel Fojt }
1066d49e1aeSJan Lentfer
1076d49e1aeSJan Lentfer global = os_zalloc(sizeof(*global));
1086d49e1aeSJan Lentfer if (global == NULL)
1096d49e1aeSJan Lentfer return NULL;
1106d49e1aeSJan Lentfer
1116d49e1aeSJan Lentfer if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) {
1126d49e1aeSJan Lentfer os_free(global);
1136d49e1aeSJan Lentfer return NULL;
1146d49e1aeSJan Lentfer }
1156d49e1aeSJan Lentfer tls_gnutls_ref_count++;
1166d49e1aeSJan Lentfer
1176d49e1aeSJan Lentfer gnutls_global_set_log_function(tls_log_func);
1186d49e1aeSJan Lentfer if (wpa_debug_show_keys)
1196d49e1aeSJan Lentfer gnutls_global_set_log_level(11);
120*a1157835SDaniel Fojt
121*a1157835SDaniel Fojt if (conf) {
122*a1157835SDaniel Fojt global->event_cb = conf->event_cb;
123*a1157835SDaniel Fojt global->cb_ctx = conf->cb_ctx;
124*a1157835SDaniel Fojt global->cert_in_cb = conf->cert_in_cb;
125*a1157835SDaniel Fojt }
126*a1157835SDaniel Fojt
1276d49e1aeSJan Lentfer return global;
1286d49e1aeSJan Lentfer }
1296d49e1aeSJan Lentfer
1306d49e1aeSJan Lentfer
tls_deinit(void * ssl_ctx)1316d49e1aeSJan Lentfer void tls_deinit(void *ssl_ctx)
1326d49e1aeSJan Lentfer {
1336d49e1aeSJan Lentfer struct tls_global *global = ssl_ctx;
1346d49e1aeSJan Lentfer if (global) {
1356d49e1aeSJan Lentfer if (global->params_set)
1366d49e1aeSJan Lentfer gnutls_certificate_free_credentials(global->xcred);
1376d49e1aeSJan Lentfer os_free(global->session_data);
138*a1157835SDaniel Fojt os_free(global->ocsp_stapling_response);
1396d49e1aeSJan Lentfer os_free(global);
1406d49e1aeSJan Lentfer }
1416d49e1aeSJan Lentfer
1426d49e1aeSJan Lentfer tls_gnutls_ref_count--;
1436d49e1aeSJan Lentfer if (tls_gnutls_ref_count == 0)
1446d49e1aeSJan Lentfer gnutls_global_deinit();
1456d49e1aeSJan Lentfer }
1466d49e1aeSJan Lentfer
1476d49e1aeSJan Lentfer
tls_get_errors(void * ssl_ctx)1486d49e1aeSJan Lentfer int tls_get_errors(void *ssl_ctx)
1496d49e1aeSJan Lentfer {
1506d49e1aeSJan Lentfer return 0;
1516d49e1aeSJan Lentfer }
1526d49e1aeSJan Lentfer
1536d49e1aeSJan Lentfer
tls_pull_func(gnutls_transport_ptr_t ptr,void * buf,size_t len)154*a1157835SDaniel Fojt static ssize_t tls_pull_func(gnutls_transport_ptr_t ptr, void *buf,
1556d49e1aeSJan Lentfer size_t len)
1566d49e1aeSJan Lentfer {
1576d49e1aeSJan Lentfer struct tls_connection *conn = (struct tls_connection *) ptr;
1583ff40c12SJohn Marino const u8 *end;
1596d49e1aeSJan Lentfer if (conn->pull_buf == NULL) {
1606d49e1aeSJan Lentfer errno = EWOULDBLOCK;
1616d49e1aeSJan Lentfer return -1;
1626d49e1aeSJan Lentfer }
1636d49e1aeSJan Lentfer
1643ff40c12SJohn Marino end = wpabuf_head_u8(conn->pull_buf) + wpabuf_len(conn->pull_buf);
1656d49e1aeSJan Lentfer if ((size_t) (end - conn->pull_buf_offset) < len)
1666d49e1aeSJan Lentfer len = end - conn->pull_buf_offset;
1676d49e1aeSJan Lentfer os_memcpy(buf, conn->pull_buf_offset, len);
1686d49e1aeSJan Lentfer conn->pull_buf_offset += len;
1696d49e1aeSJan Lentfer if (conn->pull_buf_offset == end) {
1706d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
1713ff40c12SJohn Marino wpabuf_free(conn->pull_buf);
1723ff40c12SJohn Marino conn->pull_buf = NULL;
1733ff40c12SJohn Marino conn->pull_buf_offset = NULL;
1746d49e1aeSJan Lentfer } else {
1756d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf",
1766d49e1aeSJan Lentfer __func__,
1776d49e1aeSJan Lentfer (unsigned long) (end - conn->pull_buf_offset));
1786d49e1aeSJan Lentfer }
1796d49e1aeSJan Lentfer return len;
1806d49e1aeSJan Lentfer }
1816d49e1aeSJan Lentfer
1826d49e1aeSJan Lentfer
tls_push_func(gnutls_transport_ptr_t ptr,const void * buf,size_t len)183*a1157835SDaniel Fojt static ssize_t tls_push_func(gnutls_transport_ptr_t ptr, const void *buf,
1846d49e1aeSJan Lentfer size_t len)
1856d49e1aeSJan Lentfer {
1866d49e1aeSJan Lentfer struct tls_connection *conn = (struct tls_connection *) ptr;
1876d49e1aeSJan Lentfer
1883ff40c12SJohn Marino if (wpabuf_resize(&conn->push_buf, len) < 0) {
1896d49e1aeSJan Lentfer errno = ENOMEM;
1906d49e1aeSJan Lentfer return -1;
1916d49e1aeSJan Lentfer }
1923ff40c12SJohn Marino wpabuf_put_data(conn->push_buf, buf, len);
1936d49e1aeSJan Lentfer
1946d49e1aeSJan Lentfer return len;
1956d49e1aeSJan Lentfer }
1966d49e1aeSJan Lentfer
1976d49e1aeSJan Lentfer
tls_gnutls_init_session(struct tls_global * global,struct tls_connection * conn)1986d49e1aeSJan Lentfer static int tls_gnutls_init_session(struct tls_global *global,
1996d49e1aeSJan Lentfer struct tls_connection *conn)
2006d49e1aeSJan Lentfer {
2013ff40c12SJohn Marino const char *err;
2026d49e1aeSJan Lentfer int ret;
2036d49e1aeSJan Lentfer
2046d49e1aeSJan Lentfer ret = gnutls_init(&conn->session,
2056d49e1aeSJan Lentfer global->server ? GNUTLS_SERVER : GNUTLS_CLIENT);
2066d49e1aeSJan Lentfer if (ret < 0) {
2076d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS "
2086d49e1aeSJan Lentfer "connection: %s", gnutls_strerror(ret));
2096d49e1aeSJan Lentfer return -1;
2106d49e1aeSJan Lentfer }
2116d49e1aeSJan Lentfer
2126d49e1aeSJan Lentfer ret = gnutls_set_default_priority(conn->session);
2136d49e1aeSJan Lentfer if (ret < 0)
2146d49e1aeSJan Lentfer goto fail;
2156d49e1aeSJan Lentfer
2163ff40c12SJohn Marino ret = gnutls_priority_set_direct(conn->session, "NORMAL:-VERS-SSL3.0",
2173ff40c12SJohn Marino &err);
2183ff40c12SJohn Marino if (ret < 0) {
2193ff40c12SJohn Marino wpa_printf(MSG_ERROR, "GnuTLS: Priority string failure at "
2203ff40c12SJohn Marino "'%s'", err);
2213ff40c12SJohn Marino goto fail;
2223ff40c12SJohn Marino }
2236d49e1aeSJan Lentfer
2246d49e1aeSJan Lentfer gnutls_transport_set_pull_function(conn->session, tls_pull_func);
2256d49e1aeSJan Lentfer gnutls_transport_set_push_function(conn->session, tls_push_func);
226*a1157835SDaniel Fojt gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr_t) conn);
227*a1157835SDaniel Fojt gnutls_session_set_ptr(conn->session, conn);
2286d49e1aeSJan Lentfer
2296d49e1aeSJan Lentfer return 0;
2306d49e1aeSJan Lentfer
2316d49e1aeSJan Lentfer fail:
2326d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s",
2336d49e1aeSJan Lentfer gnutls_strerror(ret));
2346d49e1aeSJan Lentfer gnutls_deinit(conn->session);
2356d49e1aeSJan Lentfer return -1;
2366d49e1aeSJan Lentfer }
2376d49e1aeSJan Lentfer
2386d49e1aeSJan Lentfer
tls_connection_init(void * ssl_ctx)2396d49e1aeSJan Lentfer struct tls_connection * tls_connection_init(void *ssl_ctx)
2406d49e1aeSJan Lentfer {
2416d49e1aeSJan Lentfer struct tls_global *global = ssl_ctx;
2426d49e1aeSJan Lentfer struct tls_connection *conn;
2436d49e1aeSJan Lentfer int ret;
2446d49e1aeSJan Lentfer
2456d49e1aeSJan Lentfer conn = os_zalloc(sizeof(*conn));
2466d49e1aeSJan Lentfer if (conn == NULL)
2476d49e1aeSJan Lentfer return NULL;
248*a1157835SDaniel Fojt conn->global = global;
2496d49e1aeSJan Lentfer
2506d49e1aeSJan Lentfer if (tls_gnutls_init_session(global, conn)) {
2516d49e1aeSJan Lentfer os_free(conn);
2526d49e1aeSJan Lentfer return NULL;
2536d49e1aeSJan Lentfer }
2546d49e1aeSJan Lentfer
2556d49e1aeSJan Lentfer if (global->params_set) {
2566d49e1aeSJan Lentfer ret = gnutls_credentials_set(conn->session,
2576d49e1aeSJan Lentfer GNUTLS_CRD_CERTIFICATE,
2586d49e1aeSJan Lentfer global->xcred);
2596d49e1aeSJan Lentfer if (ret < 0) {
2606d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "Failed to configure "
2616d49e1aeSJan Lentfer "credentials: %s", gnutls_strerror(ret));
2626d49e1aeSJan Lentfer os_free(conn);
2636d49e1aeSJan Lentfer return NULL;
2646d49e1aeSJan Lentfer }
2656d49e1aeSJan Lentfer }
2666d49e1aeSJan Lentfer
2676d49e1aeSJan Lentfer if (gnutls_certificate_allocate_credentials(&conn->xcred)) {
2686d49e1aeSJan Lentfer os_free(conn);
2696d49e1aeSJan Lentfer return NULL;
2706d49e1aeSJan Lentfer }
2716d49e1aeSJan Lentfer
2726d49e1aeSJan Lentfer return conn;
2736d49e1aeSJan Lentfer }
2746d49e1aeSJan Lentfer
2756d49e1aeSJan Lentfer
tls_connection_deinit(void * ssl_ctx,struct tls_connection * conn)2766d49e1aeSJan Lentfer void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
2776d49e1aeSJan Lentfer {
2786d49e1aeSJan Lentfer if (conn == NULL)
2796d49e1aeSJan Lentfer return;
2806d49e1aeSJan Lentfer
2816d49e1aeSJan Lentfer gnutls_certificate_free_credentials(conn->xcred);
2826d49e1aeSJan Lentfer gnutls_deinit(conn->session);
2836d49e1aeSJan Lentfer os_free(conn->pre_shared_secret);
2843ff40c12SJohn Marino wpabuf_free(conn->push_buf);
2853ff40c12SJohn Marino wpabuf_free(conn->pull_buf);
286*a1157835SDaniel Fojt os_free(conn->suffix_match);
287*a1157835SDaniel Fojt os_free(conn->domain_match);
2886d49e1aeSJan Lentfer os_free(conn);
2896d49e1aeSJan Lentfer }
2906d49e1aeSJan Lentfer
2916d49e1aeSJan Lentfer
tls_connection_established(void * ssl_ctx,struct tls_connection * conn)2926d49e1aeSJan Lentfer int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
2936d49e1aeSJan Lentfer {
2946d49e1aeSJan Lentfer return conn ? conn->established : 0;
2956d49e1aeSJan Lentfer }
2966d49e1aeSJan Lentfer
2976d49e1aeSJan Lentfer
tls_connection_peer_serial_num(void * tls_ctx,struct tls_connection * conn)298*a1157835SDaniel Fojt char * tls_connection_peer_serial_num(void *tls_ctx,
299*a1157835SDaniel Fojt struct tls_connection *conn)
300*a1157835SDaniel Fojt {
301*a1157835SDaniel Fojt /* TODO */
302*a1157835SDaniel Fojt return NULL;
303*a1157835SDaniel Fojt }
304*a1157835SDaniel Fojt
305*a1157835SDaniel Fojt
tls_connection_shutdown(void * ssl_ctx,struct tls_connection * conn)3066d49e1aeSJan Lentfer int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
3076d49e1aeSJan Lentfer {
3086d49e1aeSJan Lentfer struct tls_global *global = ssl_ctx;
3096d49e1aeSJan Lentfer int ret;
3106d49e1aeSJan Lentfer
3116d49e1aeSJan Lentfer if (conn == NULL)
3126d49e1aeSJan Lentfer return -1;
3136d49e1aeSJan Lentfer
3146d49e1aeSJan Lentfer /* Shutdown previous TLS connection without notifying the peer
3156d49e1aeSJan Lentfer * because the connection was already terminated in practice
3166d49e1aeSJan Lentfer * and "close notify" shutdown alert would confuse AS. */
3176d49e1aeSJan Lentfer gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
3183ff40c12SJohn Marino wpabuf_free(conn->push_buf);
3196d49e1aeSJan Lentfer conn->push_buf = NULL;
3206d49e1aeSJan Lentfer conn->established = 0;
3216d49e1aeSJan Lentfer
3226d49e1aeSJan Lentfer gnutls_deinit(conn->session);
3236d49e1aeSJan Lentfer if (tls_gnutls_init_session(global, conn)) {
3246d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session "
3256d49e1aeSJan Lentfer "for session resumption use");
3266d49e1aeSJan Lentfer return -1;
3276d49e1aeSJan Lentfer }
3286d49e1aeSJan Lentfer
3296d49e1aeSJan Lentfer ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
3306d49e1aeSJan Lentfer conn->params_set ? conn->xcred :
3316d49e1aeSJan Lentfer global->xcred);
3326d49e1aeSJan Lentfer if (ret < 0) {
3336d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials "
3346d49e1aeSJan Lentfer "for session resumption: %s", gnutls_strerror(ret));
3356d49e1aeSJan Lentfer return -1;
3366d49e1aeSJan Lentfer }
3376d49e1aeSJan Lentfer
3386d49e1aeSJan Lentfer if (global->session_data) {
3396d49e1aeSJan Lentfer ret = gnutls_session_set_data(conn->session,
3406d49e1aeSJan Lentfer global->session_data,
3416d49e1aeSJan Lentfer global->session_data_size);
3426d49e1aeSJan Lentfer if (ret < 0) {
3436d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "GnuTLS: Failed to set session "
3446d49e1aeSJan Lentfer "data: %s", gnutls_strerror(ret));
3456d49e1aeSJan Lentfer return -1;
3466d49e1aeSJan Lentfer }
3476d49e1aeSJan Lentfer }
3486d49e1aeSJan Lentfer
3496d49e1aeSJan Lentfer return 0;
3506d49e1aeSJan Lentfer }
3516d49e1aeSJan Lentfer
3526d49e1aeSJan Lentfer
tls_connection_set_params(void * tls_ctx,struct tls_connection * conn,const struct tls_connection_params * params)3536d49e1aeSJan Lentfer int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
3546d49e1aeSJan Lentfer const struct tls_connection_params *params)
3556d49e1aeSJan Lentfer {
3566d49e1aeSJan Lentfer int ret;
357*a1157835SDaniel Fojt const char *err;
358*a1157835SDaniel Fojt char prio_buf[100];
359*a1157835SDaniel Fojt const char *prio = NULL;
3606d49e1aeSJan Lentfer
3616d49e1aeSJan Lentfer if (conn == NULL || params == NULL)
3626d49e1aeSJan Lentfer return -1;
3636d49e1aeSJan Lentfer
364*a1157835SDaniel Fojt if (params->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
365*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
366*a1157835SDaniel Fojt "GnuTLS: ocsp=3 not supported");
3676d49e1aeSJan Lentfer return -1;
3686d49e1aeSJan Lentfer }
3696d49e1aeSJan Lentfer
370*a1157835SDaniel Fojt if (params->flags & TLS_CONN_EXT_CERT_CHECK) {
371*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
372*a1157835SDaniel Fojt "GnuTLS: tls_ext_cert_check=1 not supported");
373*a1157835SDaniel Fojt return -1;
374*a1157835SDaniel Fojt }
375*a1157835SDaniel Fojt
376*a1157835SDaniel Fojt if (params->subject_match) {
377*a1157835SDaniel Fojt wpa_printf(MSG_INFO, "GnuTLS: subject_match not supported");
378*a1157835SDaniel Fojt return -1;
379*a1157835SDaniel Fojt }
380*a1157835SDaniel Fojt
3816d49e1aeSJan Lentfer if (params->altsubject_match) {
382*a1157835SDaniel Fojt wpa_printf(MSG_INFO, "GnuTLS: altsubject_match not supported");
383*a1157835SDaniel Fojt return -1;
384*a1157835SDaniel Fojt }
385*a1157835SDaniel Fojt
386*a1157835SDaniel Fojt os_free(conn->suffix_match);
387*a1157835SDaniel Fojt conn->suffix_match = NULL;
388*a1157835SDaniel Fojt if (params->suffix_match) {
389*a1157835SDaniel Fojt conn->suffix_match = os_strdup(params->suffix_match);
390*a1157835SDaniel Fojt if (conn->suffix_match == NULL)
391*a1157835SDaniel Fojt return -1;
392*a1157835SDaniel Fojt }
393*a1157835SDaniel Fojt
394*a1157835SDaniel Fojt #if GNUTLS_VERSION_NUMBER >= 0x030300
395*a1157835SDaniel Fojt os_free(conn->domain_match);
396*a1157835SDaniel Fojt conn->domain_match = NULL;
397*a1157835SDaniel Fojt if (params->domain_match) {
398*a1157835SDaniel Fojt conn->domain_match = os_strdup(params->domain_match);
399*a1157835SDaniel Fojt if (conn->domain_match == NULL)
400*a1157835SDaniel Fojt return -1;
401*a1157835SDaniel Fojt }
402*a1157835SDaniel Fojt #else /* < 3.3.0 */
403*a1157835SDaniel Fojt if (params->domain_match) {
404*a1157835SDaniel Fojt wpa_printf(MSG_INFO, "GnuTLS: domain_match not supported");
405*a1157835SDaniel Fojt return -1;
406*a1157835SDaniel Fojt }
407*a1157835SDaniel Fojt #endif /* >= 3.3.0 */
408*a1157835SDaniel Fojt
409*a1157835SDaniel Fojt conn->flags = params->flags;
410*a1157835SDaniel Fojt
411*a1157835SDaniel Fojt if (params->flags & (TLS_CONN_DISABLE_TLSv1_0 |
412*a1157835SDaniel Fojt TLS_CONN_DISABLE_TLSv1_1 |
413*a1157835SDaniel Fojt TLS_CONN_DISABLE_TLSv1_2)) {
414*a1157835SDaniel Fojt os_snprintf(prio_buf, sizeof(prio_buf),
415*a1157835SDaniel Fojt "NORMAL:-VERS-SSL3.0%s%s%s",
416*a1157835SDaniel Fojt params->flags & TLS_CONN_DISABLE_TLSv1_0 ?
417*a1157835SDaniel Fojt ":-VERS-TLS1.0" : "",
418*a1157835SDaniel Fojt params->flags & TLS_CONN_DISABLE_TLSv1_1 ?
419*a1157835SDaniel Fojt ":-VERS-TLS1.1" : "",
420*a1157835SDaniel Fojt params->flags & TLS_CONN_DISABLE_TLSv1_2 ?
421*a1157835SDaniel Fojt ":-VERS-TLS1.2" : "");
422*a1157835SDaniel Fojt prio = prio_buf;
423*a1157835SDaniel Fojt }
424*a1157835SDaniel Fojt
425*a1157835SDaniel Fojt if (params->openssl_ciphers) {
426*a1157835SDaniel Fojt if (os_strcmp(params->openssl_ciphers, "SUITEB128") == 0) {
427*a1157835SDaniel Fojt prio = "SUITEB128";
428*a1157835SDaniel Fojt } else if (os_strcmp(params->openssl_ciphers,
429*a1157835SDaniel Fojt "SUITEB192") == 0) {
430*a1157835SDaniel Fojt prio = "SUITEB192";
431*a1157835SDaniel Fojt } else if ((params->flags & TLS_CONN_SUITEB) &&
432*a1157835SDaniel Fojt os_strcmp(params->openssl_ciphers,
433*a1157835SDaniel Fojt "ECDHE-RSA-AES256-GCM-SHA384") == 0) {
434*a1157835SDaniel Fojt prio = "NONE:+VERS-TLS1.2:+AEAD:+ECDHE-RSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL";
435*a1157835SDaniel Fojt } else if (os_strcmp(params->openssl_ciphers,
436*a1157835SDaniel Fojt "ECDHE-RSA-AES256-GCM-SHA384") == 0) {
437*a1157835SDaniel Fojt prio = "NONE:+VERS-TLS1.2:+AEAD:+ECDHE-RSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL";
438*a1157835SDaniel Fojt } else if (os_strcmp(params->openssl_ciphers,
439*a1157835SDaniel Fojt "DHE-RSA-AES256-GCM-SHA384") == 0) {
440*a1157835SDaniel Fojt prio = "NONE:+VERS-TLS1.2:+AEAD:+DHE-RSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL:%PROFILE_HIGH";
441*a1157835SDaniel Fojt } else if (os_strcmp(params->openssl_ciphers,
442*a1157835SDaniel Fojt "ECDHE-ECDSA-AES256-GCM-SHA384") == 0) {
443*a1157835SDaniel Fojt prio = "NONE:+VERS-TLS1.2:+AEAD:+ECDHE-ECDSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL";
444*a1157835SDaniel Fojt } else {
445*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
446*a1157835SDaniel Fojt "GnuTLS: openssl_ciphers not supported");
447*a1157835SDaniel Fojt return -1;
448*a1157835SDaniel Fojt }
449*a1157835SDaniel Fojt } else if (params->flags & TLS_CONN_SUITEB) {
450*a1157835SDaniel Fojt 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*a1157835SDaniel Fojt }
452*a1157835SDaniel Fojt
453*a1157835SDaniel Fojt if (prio) {
454*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "GnuTLS: Set priority string: %s", prio);
455*a1157835SDaniel Fojt ret = gnutls_priority_set_direct(conn->session, prio, &err);
456*a1157835SDaniel Fojt if (ret < 0) {
457*a1157835SDaniel Fojt wpa_printf(MSG_ERROR,
458*a1157835SDaniel Fojt "GnuTLS: Priority string failure at '%s'",
459*a1157835SDaniel Fojt err);
460*a1157835SDaniel Fojt return -1;
461*a1157835SDaniel Fojt }
462*a1157835SDaniel Fojt }
463*a1157835SDaniel Fojt
464*a1157835SDaniel Fojt if (params->openssl_ecdh_curves) {
465*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
466*a1157835SDaniel Fojt "GnuTLS: openssl_ecdh_curves not supported");
4676d49e1aeSJan Lentfer return -1;
4686d49e1aeSJan Lentfer }
4696d49e1aeSJan Lentfer
4706d49e1aeSJan Lentfer /* TODO: gnutls_certificate_set_verify_flags(xcred, flags);
4716d49e1aeSJan Lentfer * to force peer validation(?) */
4726d49e1aeSJan Lentfer
4736d49e1aeSJan Lentfer if (params->ca_cert) {
474*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "GnuTLS: Try to parse %s in DER format",
475*a1157835SDaniel Fojt params->ca_cert);
4766d49e1aeSJan Lentfer ret = gnutls_certificate_set_x509_trust_file(
477*a1157835SDaniel Fojt conn->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
4786d49e1aeSJan Lentfer if (ret < 0) {
479*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
480*a1157835SDaniel Fojt "GnuTLS: Failed to read CA cert '%s' in DER format (%s) - try in PEM format",
481*a1157835SDaniel Fojt params->ca_cert,
4826d49e1aeSJan Lentfer gnutls_strerror(ret));
4836d49e1aeSJan Lentfer ret = gnutls_certificate_set_x509_trust_file(
4846d49e1aeSJan Lentfer conn->xcred, params->ca_cert,
485*a1157835SDaniel Fojt GNUTLS_X509_FMT_PEM);
4866d49e1aeSJan Lentfer if (ret < 0) {
487*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
488*a1157835SDaniel Fojt "Failed to read CA cert '%s' in PEM format: %s",
4896d49e1aeSJan Lentfer params->ca_cert,
4906d49e1aeSJan Lentfer gnutls_strerror(ret));
4916d49e1aeSJan Lentfer return -1;
4926d49e1aeSJan Lentfer }
493*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
494*a1157835SDaniel Fojt "GnuTLS: Successfully read CA cert '%s' in PEM format",
495*a1157835SDaniel Fojt params->ca_cert);
496*a1157835SDaniel Fojt } else {
497*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
498*a1157835SDaniel Fojt "GnuTLS: Successfully read CA cert '%s' in DER format",
499*a1157835SDaniel Fojt params->ca_cert);
5006d49e1aeSJan Lentfer }
501*a1157835SDaniel Fojt } else if (params->ca_cert_blob) {
502*a1157835SDaniel Fojt gnutls_datum_t ca;
503*a1157835SDaniel Fojt
504*a1157835SDaniel Fojt ca.data = (unsigned char *) params->ca_cert_blob;
505*a1157835SDaniel Fojt ca.size = params->ca_cert_blob_len;
506*a1157835SDaniel Fojt
507*a1157835SDaniel Fojt ret = gnutls_certificate_set_x509_trust_mem(
508*a1157835SDaniel Fojt conn->xcred, &ca, GNUTLS_X509_FMT_DER);
509*a1157835SDaniel Fojt if (ret < 0) {
510*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
511*a1157835SDaniel Fojt "Failed to parse CA cert in DER format: %s",
512*a1157835SDaniel Fojt gnutls_strerror(ret));
513*a1157835SDaniel Fojt ret = gnutls_certificate_set_x509_trust_mem(
514*a1157835SDaniel Fojt conn->xcred, &ca, GNUTLS_X509_FMT_PEM);
515*a1157835SDaniel Fojt if (ret < 0) {
516*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
517*a1157835SDaniel Fojt "Failed to parse CA cert in PEM format: %s",
518*a1157835SDaniel Fojt gnutls_strerror(ret));
519*a1157835SDaniel Fojt return -1;
520*a1157835SDaniel Fojt }
521*a1157835SDaniel Fojt }
522*a1157835SDaniel Fojt } else if (params->ca_path) {
523*a1157835SDaniel Fojt wpa_printf(MSG_INFO, "GnuTLS: ca_path not supported");
524*a1157835SDaniel Fojt return -1;
525*a1157835SDaniel Fojt }
526*a1157835SDaniel Fojt
527*a1157835SDaniel Fojt conn->disable_time_checks = 0;
528*a1157835SDaniel Fojt if (params->ca_cert || params->ca_cert_blob) {
529*a1157835SDaniel Fojt conn->verify_peer = 1;
530*a1157835SDaniel Fojt gnutls_certificate_set_verify_function(
531*a1157835SDaniel Fojt conn->xcred, tls_connection_verify_peer);
5326d49e1aeSJan Lentfer
5336d49e1aeSJan Lentfer if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
5346d49e1aeSJan Lentfer gnutls_certificate_set_verify_flags(
5356d49e1aeSJan Lentfer conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
5366d49e1aeSJan Lentfer }
5376d49e1aeSJan Lentfer
5386d49e1aeSJan Lentfer if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
539*a1157835SDaniel Fojt conn->disable_time_checks = 1;
5406d49e1aeSJan Lentfer gnutls_certificate_set_verify_flags(
5416d49e1aeSJan Lentfer conn->xcred,
5426d49e1aeSJan Lentfer GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
5436d49e1aeSJan Lentfer }
5446d49e1aeSJan Lentfer }
5456d49e1aeSJan Lentfer
5466d49e1aeSJan Lentfer if (params->client_cert && params->private_key) {
547*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
548*a1157835SDaniel Fojt "GnuTLS: Try to parse client cert '%s' and key '%s' in DER format",
549*a1157835SDaniel Fojt params->client_cert, params->private_key);
550*a1157835SDaniel Fojt #if GNUTLS_VERSION_NUMBER >= 0x03010b
551*a1157835SDaniel Fojt ret = gnutls_certificate_set_x509_key_file2(
552*a1157835SDaniel Fojt conn->xcred, params->client_cert, params->private_key,
553*a1157835SDaniel Fojt GNUTLS_X509_FMT_DER, params->private_key_passwd, 0);
554*a1157835SDaniel Fojt #else
555*a1157835SDaniel Fojt /* private_key_passwd not (easily) supported here */
5566d49e1aeSJan Lentfer ret = gnutls_certificate_set_x509_key_file(
5576d49e1aeSJan Lentfer conn->xcred, params->client_cert, params->private_key,
558*a1157835SDaniel Fojt GNUTLS_X509_FMT_DER);
559*a1157835SDaniel Fojt #endif
5606d49e1aeSJan Lentfer if (ret < 0) {
561*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
562*a1157835SDaniel Fojt "GnuTLS: Failed to read client cert/key in DER format (%s) - try in PEM format",
563*a1157835SDaniel Fojt gnutls_strerror(ret));
564*a1157835SDaniel Fojt #if GNUTLS_VERSION_NUMBER >= 0x03010b
565*a1157835SDaniel Fojt ret = gnutls_certificate_set_x509_key_file2(
566*a1157835SDaniel Fojt conn->xcred, params->client_cert,
567*a1157835SDaniel Fojt params->private_key, GNUTLS_X509_FMT_PEM,
568*a1157835SDaniel Fojt params->private_key_passwd, 0);
569*a1157835SDaniel Fojt #else
5706d49e1aeSJan Lentfer ret = gnutls_certificate_set_x509_key_file(
5716d49e1aeSJan Lentfer conn->xcred, params->client_cert,
572*a1157835SDaniel Fojt params->private_key, GNUTLS_X509_FMT_PEM);
573*a1157835SDaniel Fojt #endif
5746d49e1aeSJan Lentfer if (ret < 0) {
5756d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "Failed to read client "
576*a1157835SDaniel Fojt "cert/key in PEM format: %s",
5776d49e1aeSJan Lentfer gnutls_strerror(ret));
5786d49e1aeSJan Lentfer return ret;
5796d49e1aeSJan Lentfer }
580*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
581*a1157835SDaniel Fojt "GnuTLS: Successfully read client cert/key in PEM format");
582*a1157835SDaniel Fojt } else {
583*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
584*a1157835SDaniel Fojt "GnuTLS: Successfully read client cert/key in DER format");
5856d49e1aeSJan Lentfer }
5866d49e1aeSJan Lentfer } else if (params->private_key) {
5876d49e1aeSJan Lentfer int pkcs12_ok = 0;
5886d49e1aeSJan Lentfer #ifdef PKCS12_FUNCS
5896d49e1aeSJan Lentfer /* Try to load in PKCS#12 format */
590*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
591*a1157835SDaniel Fojt "GnuTLS: Try to parse client cert/key '%s'in PKCS#12 DER format",
592*a1157835SDaniel Fojt params->private_key);
5936d49e1aeSJan Lentfer ret = gnutls_certificate_set_x509_simple_pkcs12_file(
5946d49e1aeSJan Lentfer conn->xcred, params->private_key, GNUTLS_X509_FMT_DER,
5956d49e1aeSJan Lentfer params->private_key_passwd);
5966d49e1aeSJan Lentfer if (ret != 0) {
5976d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "Failed to load private_key in "
5986d49e1aeSJan Lentfer "PKCS#12 format: %s", gnutls_strerror(ret));
5996d49e1aeSJan Lentfer return -1;
6006d49e1aeSJan Lentfer } else
6016d49e1aeSJan Lentfer pkcs12_ok = 1;
6026d49e1aeSJan Lentfer #endif /* PKCS12_FUNCS */
6036d49e1aeSJan Lentfer
6046d49e1aeSJan Lentfer if (!pkcs12_ok) {
6056d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
6066d49e1aeSJan Lentfer "included");
6076d49e1aeSJan Lentfer return -1;
6086d49e1aeSJan Lentfer }
609*a1157835SDaniel Fojt } else if (params->client_cert_blob && params->private_key_blob) {
610*a1157835SDaniel Fojt gnutls_datum_t cert, key;
611*a1157835SDaniel Fojt
612*a1157835SDaniel Fojt cert.data = (unsigned char *) params->client_cert_blob;
613*a1157835SDaniel Fojt cert.size = params->client_cert_blob_len;
614*a1157835SDaniel Fojt key.data = (unsigned char *) params->private_key_blob;
615*a1157835SDaniel Fojt key.size = params->private_key_blob_len;
616*a1157835SDaniel Fojt
617*a1157835SDaniel Fojt #if GNUTLS_VERSION_NUMBER >= 0x03010b
618*a1157835SDaniel Fojt ret = gnutls_certificate_set_x509_key_mem2(
619*a1157835SDaniel Fojt conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER,
620*a1157835SDaniel Fojt params->private_key_passwd, 0);
621*a1157835SDaniel Fojt #else
622*a1157835SDaniel Fojt /* private_key_passwd not (easily) supported here */
623*a1157835SDaniel Fojt ret = gnutls_certificate_set_x509_key_mem(
624*a1157835SDaniel Fojt conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER);
625*a1157835SDaniel Fojt #endif
626*a1157835SDaniel Fojt if (ret < 0) {
627*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
628*a1157835SDaniel Fojt "in DER format: %s", gnutls_strerror(ret));
629*a1157835SDaniel Fojt #if GNUTLS_VERSION_NUMBER >= 0x03010b
630*a1157835SDaniel Fojt ret = gnutls_certificate_set_x509_key_mem2(
631*a1157835SDaniel Fojt conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM,
632*a1157835SDaniel Fojt params->private_key_passwd, 0);
633*a1157835SDaniel Fojt #else
634*a1157835SDaniel Fojt /* private_key_passwd not (easily) supported here */
635*a1157835SDaniel Fojt ret = gnutls_certificate_set_x509_key_mem(
636*a1157835SDaniel Fojt conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM);
637*a1157835SDaniel Fojt #endif
638*a1157835SDaniel Fojt if (ret < 0) {
639*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "Failed to read client "
640*a1157835SDaniel Fojt "cert/key in PEM format: %s",
641*a1157835SDaniel Fojt gnutls_strerror(ret));
642*a1157835SDaniel Fojt return ret;
6436d49e1aeSJan Lentfer }
644*a1157835SDaniel Fojt }
645*a1157835SDaniel Fojt } else if (params->private_key_blob) {
646*a1157835SDaniel Fojt #ifdef PKCS12_FUNCS
647*a1157835SDaniel Fojt gnutls_datum_t key;
648*a1157835SDaniel Fojt
649*a1157835SDaniel Fojt key.data = (unsigned char *) params->private_key_blob;
650*a1157835SDaniel Fojt key.size = params->private_key_blob_len;
651*a1157835SDaniel Fojt
652*a1157835SDaniel Fojt /* Try to load in PKCS#12 format */
653*a1157835SDaniel Fojt ret = gnutls_certificate_set_x509_simple_pkcs12_mem(
654*a1157835SDaniel Fojt conn->xcred, &key, GNUTLS_X509_FMT_DER,
655*a1157835SDaniel Fojt params->private_key_passwd);
656*a1157835SDaniel Fojt if (ret != 0) {
657*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "Failed to load private_key in "
658*a1157835SDaniel Fojt "PKCS#12 format: %s", gnutls_strerror(ret));
659*a1157835SDaniel Fojt return -1;
660*a1157835SDaniel Fojt }
661*a1157835SDaniel Fojt #else /* PKCS12_FUNCS */
662*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not included");
663*a1157835SDaniel Fojt return -1;
664*a1157835SDaniel Fojt #endif /* PKCS12_FUNCS */
665*a1157835SDaniel Fojt }
666*a1157835SDaniel Fojt
667*a1157835SDaniel Fojt #if GNUTLS_VERSION_NUMBER >= 0x030103
668*a1157835SDaniel Fojt if (params->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)) {
669*a1157835SDaniel Fojt ret = gnutls_ocsp_status_request_enable_client(conn->session,
670*a1157835SDaniel Fojt NULL, 0, NULL);
671*a1157835SDaniel Fojt if (ret != GNUTLS_E_SUCCESS) {
672*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
673*a1157835SDaniel Fojt "GnuTLS: Failed to enable OCSP client");
674*a1157835SDaniel Fojt return -1;
675*a1157835SDaniel Fojt }
676*a1157835SDaniel Fojt }
677*a1157835SDaniel Fojt #else /* 3.1.3 */
678*a1157835SDaniel Fojt if (params->flags & TLS_CONN_REQUIRE_OCSP) {
679*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
680*a1157835SDaniel Fojt "GnuTLS: OCSP not supported by this version of GnuTLS");
681*a1157835SDaniel Fojt return -1;
682*a1157835SDaniel Fojt }
683*a1157835SDaniel Fojt #endif /* 3.1.3 */
6846d49e1aeSJan Lentfer
6856d49e1aeSJan Lentfer conn->params_set = 1;
6866d49e1aeSJan Lentfer
6876d49e1aeSJan Lentfer ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
6886d49e1aeSJan Lentfer conn->xcred);
6896d49e1aeSJan Lentfer if (ret < 0) {
6906d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "Failed to configure credentials: %s",
6916d49e1aeSJan Lentfer gnutls_strerror(ret));
6926d49e1aeSJan Lentfer }
6936d49e1aeSJan Lentfer
6946d49e1aeSJan Lentfer return ret;
6956d49e1aeSJan Lentfer }
6966d49e1aeSJan Lentfer
6976d49e1aeSJan Lentfer
698*a1157835SDaniel Fojt #if GNUTLS_VERSION_NUMBER >= 0x030103
server_ocsp_status_req(gnutls_session_t session,void * ptr,gnutls_datum_t * resp)699*a1157835SDaniel Fojt static int server_ocsp_status_req(gnutls_session_t session, void *ptr,
700*a1157835SDaniel Fojt gnutls_datum_t *resp)
701*a1157835SDaniel Fojt {
702*a1157835SDaniel Fojt struct tls_global *global = ptr;
703*a1157835SDaniel Fojt char *cached;
704*a1157835SDaniel Fojt size_t len;
705*a1157835SDaniel Fojt
706*a1157835SDaniel Fojt if (!global->ocsp_stapling_response) {
707*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "GnuTLS: OCSP status callback - no response configured");
708*a1157835SDaniel Fojt return GNUTLS_E_NO_CERTIFICATE_STATUS;
709*a1157835SDaniel Fojt }
710*a1157835SDaniel Fojt
711*a1157835SDaniel Fojt cached = os_readfile(global->ocsp_stapling_response, &len);
712*a1157835SDaniel Fojt if (!cached) {
713*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
714*a1157835SDaniel Fojt "GnuTLS: OCSP status callback - could not read response file (%s)",
715*a1157835SDaniel Fojt global->ocsp_stapling_response);
716*a1157835SDaniel Fojt return GNUTLS_E_NO_CERTIFICATE_STATUS;
717*a1157835SDaniel Fojt }
718*a1157835SDaniel Fojt
719*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
720*a1157835SDaniel Fojt "GnuTLS: OCSP status callback - send cached response");
721*a1157835SDaniel Fojt resp->data = gnutls_malloc(len);
722*a1157835SDaniel Fojt if (!resp->data) {
723*a1157835SDaniel Fojt os_free(resp);
724*a1157835SDaniel Fojt return GNUTLS_E_MEMORY_ERROR;
725*a1157835SDaniel Fojt }
726*a1157835SDaniel Fojt
727*a1157835SDaniel Fojt os_memcpy(resp->data, cached, len);
728*a1157835SDaniel Fojt resp->size = len;
729*a1157835SDaniel Fojt os_free(cached);
730*a1157835SDaniel Fojt
731*a1157835SDaniel Fojt return GNUTLS_E_SUCCESS;
732*a1157835SDaniel Fojt }
733*a1157835SDaniel Fojt #endif /* 3.1.3 */
734*a1157835SDaniel Fojt
735*a1157835SDaniel Fojt
tls_global_set_params(void * tls_ctx,const struct tls_connection_params * params)7366d49e1aeSJan Lentfer int tls_global_set_params(void *tls_ctx,
7376d49e1aeSJan Lentfer const struct tls_connection_params *params)
7386d49e1aeSJan Lentfer {
7396d49e1aeSJan Lentfer struct tls_global *global = tls_ctx;
7406d49e1aeSJan Lentfer int ret;
7416d49e1aeSJan Lentfer
742*a1157835SDaniel Fojt if (params->check_cert_subject)
743*a1157835SDaniel Fojt return -1; /* not yet supported */
744*a1157835SDaniel Fojt
7456d49e1aeSJan Lentfer /* Currently, global parameters are only set when running in server
7466d49e1aeSJan Lentfer * mode. */
7476d49e1aeSJan Lentfer global->server = 1;
7486d49e1aeSJan Lentfer
7496d49e1aeSJan Lentfer if (global->params_set) {
7506d49e1aeSJan Lentfer gnutls_certificate_free_credentials(global->xcred);
7516d49e1aeSJan Lentfer global->params_set = 0;
7526d49e1aeSJan Lentfer }
7536d49e1aeSJan Lentfer
7546d49e1aeSJan Lentfer ret = gnutls_certificate_allocate_credentials(&global->xcred);
7556d49e1aeSJan Lentfer if (ret) {
7566d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "Failed to allocate global credentials "
7576d49e1aeSJan Lentfer "%s", gnutls_strerror(ret));
7586d49e1aeSJan Lentfer return -1;
7596d49e1aeSJan Lentfer }
7606d49e1aeSJan Lentfer
7616d49e1aeSJan Lentfer if (params->ca_cert) {
7626d49e1aeSJan Lentfer ret = gnutls_certificate_set_x509_trust_file(
763*a1157835SDaniel Fojt global->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
7646d49e1aeSJan Lentfer if (ret < 0) {
7656d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
766*a1157835SDaniel Fojt "in DER format: %s", params->ca_cert,
7676d49e1aeSJan Lentfer gnutls_strerror(ret));
7686d49e1aeSJan Lentfer ret = gnutls_certificate_set_x509_trust_file(
7696d49e1aeSJan Lentfer global->xcred, params->ca_cert,
770*a1157835SDaniel Fojt GNUTLS_X509_FMT_PEM);
7716d49e1aeSJan Lentfer if (ret < 0) {
7726d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "Failed to read CA cert "
773*a1157835SDaniel Fojt "'%s' in PEM format: %s",
7746d49e1aeSJan Lentfer params->ca_cert,
7756d49e1aeSJan Lentfer gnutls_strerror(ret));
7766d49e1aeSJan Lentfer goto fail;
7776d49e1aeSJan Lentfer }
7786d49e1aeSJan Lentfer }
7796d49e1aeSJan Lentfer
7806d49e1aeSJan Lentfer if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
7816d49e1aeSJan Lentfer gnutls_certificate_set_verify_flags(
7826d49e1aeSJan Lentfer global->xcred,
7836d49e1aeSJan Lentfer GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
7846d49e1aeSJan Lentfer }
7856d49e1aeSJan Lentfer
7866d49e1aeSJan Lentfer if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
7876d49e1aeSJan Lentfer gnutls_certificate_set_verify_flags(
7886d49e1aeSJan Lentfer global->xcred,
7896d49e1aeSJan Lentfer GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
7906d49e1aeSJan Lentfer }
7916d49e1aeSJan Lentfer }
7926d49e1aeSJan Lentfer
7936d49e1aeSJan Lentfer if (params->client_cert && params->private_key) {
7946d49e1aeSJan Lentfer /* TODO: private_key_passwd? */
7956d49e1aeSJan Lentfer ret = gnutls_certificate_set_x509_key_file(
7966d49e1aeSJan Lentfer global->xcred, params->client_cert,
7976d49e1aeSJan Lentfer params->private_key, GNUTLS_X509_FMT_DER);
7986d49e1aeSJan Lentfer if (ret < 0) {
799*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
800*a1157835SDaniel Fojt "in DER format: %s", gnutls_strerror(ret));
801*a1157835SDaniel Fojt ret = gnutls_certificate_set_x509_key_file(
802*a1157835SDaniel Fojt global->xcred, params->client_cert,
803*a1157835SDaniel Fojt params->private_key, GNUTLS_X509_FMT_PEM);
804*a1157835SDaniel Fojt if (ret < 0) {
8056d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "Failed to read client "
806*a1157835SDaniel Fojt "cert/key in PEM format: %s",
8076d49e1aeSJan Lentfer gnutls_strerror(ret));
8086d49e1aeSJan Lentfer goto fail;
8096d49e1aeSJan Lentfer }
8106d49e1aeSJan Lentfer }
8116d49e1aeSJan Lentfer } else if (params->private_key) {
8126d49e1aeSJan Lentfer int pkcs12_ok = 0;
8136d49e1aeSJan Lentfer #ifdef PKCS12_FUNCS
8146d49e1aeSJan Lentfer /* Try to load in PKCS#12 format */
8156d49e1aeSJan Lentfer ret = gnutls_certificate_set_x509_simple_pkcs12_file(
8166d49e1aeSJan Lentfer global->xcred, params->private_key,
8176d49e1aeSJan Lentfer GNUTLS_X509_FMT_DER, params->private_key_passwd);
8186d49e1aeSJan Lentfer if (ret != 0) {
8196d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "Failed to load private_key in "
8206d49e1aeSJan Lentfer "PKCS#12 format: %s", gnutls_strerror(ret));
8216d49e1aeSJan Lentfer goto fail;
8226d49e1aeSJan Lentfer } else
8236d49e1aeSJan Lentfer pkcs12_ok = 1;
8246d49e1aeSJan Lentfer #endif /* PKCS12_FUNCS */
8256d49e1aeSJan Lentfer
8266d49e1aeSJan Lentfer if (!pkcs12_ok) {
8276d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
8286d49e1aeSJan Lentfer "included");
8296d49e1aeSJan Lentfer goto fail;
8306d49e1aeSJan Lentfer }
8316d49e1aeSJan Lentfer }
8326d49e1aeSJan Lentfer
833*a1157835SDaniel Fojt #if GNUTLS_VERSION_NUMBER >= 0x030103
834*a1157835SDaniel Fojt os_free(global->ocsp_stapling_response);
835*a1157835SDaniel Fojt if (params->ocsp_stapling_response)
836*a1157835SDaniel Fojt global->ocsp_stapling_response =
837*a1157835SDaniel Fojt os_strdup(params->ocsp_stapling_response);
838*a1157835SDaniel Fojt else
839*a1157835SDaniel Fojt global->ocsp_stapling_response = NULL;
840*a1157835SDaniel Fojt gnutls_certificate_set_ocsp_status_request_function(
841*a1157835SDaniel Fojt global->xcred, server_ocsp_status_req, global);
842*a1157835SDaniel Fojt #endif /* 3.1.3 */
843*a1157835SDaniel Fojt
8446d49e1aeSJan Lentfer global->params_set = 1;
8456d49e1aeSJan Lentfer
8466d49e1aeSJan Lentfer return 0;
8476d49e1aeSJan Lentfer
8486d49e1aeSJan Lentfer fail:
8496d49e1aeSJan Lentfer gnutls_certificate_free_credentials(global->xcred);
8506d49e1aeSJan Lentfer return -1;
8516d49e1aeSJan Lentfer }
8526d49e1aeSJan Lentfer
8536d49e1aeSJan Lentfer
tls_global_set_verify(void * ssl_ctx,int check_crl,int strict)854*a1157835SDaniel Fojt int tls_global_set_verify(void *ssl_ctx, int check_crl, int strict)
8556d49e1aeSJan Lentfer {
8566d49e1aeSJan Lentfer /* TODO */
8576d49e1aeSJan Lentfer return 0;
8586d49e1aeSJan Lentfer }
8596d49e1aeSJan Lentfer
8606d49e1aeSJan Lentfer
tls_connection_set_verify(void * ssl_ctx,struct tls_connection * conn,int verify_peer,unsigned int flags,const u8 * session_ctx,size_t session_ctx_len)8616d49e1aeSJan Lentfer int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
862*a1157835SDaniel Fojt int verify_peer, unsigned int flags,
863*a1157835SDaniel Fojt const u8 *session_ctx, size_t session_ctx_len)
8646d49e1aeSJan Lentfer {
8656d49e1aeSJan Lentfer if (conn == NULL || conn->session == NULL)
8666d49e1aeSJan Lentfer return -1;
8676d49e1aeSJan Lentfer
8686d49e1aeSJan Lentfer conn->verify_peer = verify_peer;
8696d49e1aeSJan Lentfer gnutls_certificate_server_set_request(conn->session,
8706d49e1aeSJan Lentfer verify_peer ? GNUTLS_CERT_REQUIRE
8716d49e1aeSJan Lentfer : GNUTLS_CERT_REQUEST);
8726d49e1aeSJan Lentfer
8736d49e1aeSJan Lentfer return 0;
8746d49e1aeSJan Lentfer }
8756d49e1aeSJan Lentfer
8766d49e1aeSJan Lentfer
tls_connection_get_random(void * ssl_ctx,struct tls_connection * conn,struct tls_random * keys)877*a1157835SDaniel Fojt int tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn,
878*a1157835SDaniel Fojt struct tls_random *keys)
8796d49e1aeSJan Lentfer {
880*a1157835SDaniel Fojt #if GNUTLS_VERSION_NUMBER >= 0x030012
881*a1157835SDaniel Fojt gnutls_datum_t client, server;
8826d49e1aeSJan Lentfer
8836d49e1aeSJan Lentfer if (conn == NULL || conn->session == NULL || keys == NULL)
8846d49e1aeSJan Lentfer return -1;
8856d49e1aeSJan Lentfer
8866d49e1aeSJan Lentfer os_memset(keys, 0, sizeof(*keys));
887*a1157835SDaniel Fojt gnutls_session_get_random(conn->session, &client, &server);
888*a1157835SDaniel Fojt keys->client_random = client.data;
889*a1157835SDaniel Fojt keys->server_random = server.data;
890*a1157835SDaniel Fojt keys->client_random_len = client.size;
891*a1157835SDaniel Fojt keys->server_random_len = client.size;
8926d49e1aeSJan Lentfer
8936d49e1aeSJan Lentfer return 0;
894*a1157835SDaniel Fojt #else /* 3.0.18 */
895*a1157835SDaniel Fojt return -1;
896*a1157835SDaniel Fojt #endif /* 3.0.18 */
8976d49e1aeSJan Lentfer }
8986d49e1aeSJan Lentfer
8996d49e1aeSJan Lentfer
tls_connection_export_key(void * tls_ctx,struct tls_connection * conn,const char * label,const u8 * context,size_t context_len,u8 * out,size_t out_len)900*a1157835SDaniel Fojt int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
901*a1157835SDaniel Fojt const char *label, const u8 *context,
902*a1157835SDaniel Fojt size_t context_len, u8 *out, size_t out_len)
9036d49e1aeSJan Lentfer {
9046d49e1aeSJan Lentfer if (conn == NULL || conn->session == NULL)
9056d49e1aeSJan Lentfer return -1;
9066d49e1aeSJan Lentfer
907*a1157835SDaniel Fojt #if GNUTLS_VERSION_NUMBER >= 0x030404
908*a1157835SDaniel Fojt return gnutls_prf_rfc5705(conn->session, os_strlen(label), label,
909*a1157835SDaniel Fojt context_len, (const char *) context,
910*a1157835SDaniel Fojt out_len, (char *) out);
911*a1157835SDaniel Fojt #else /* 3.4.4 */
912*a1157835SDaniel Fojt if (context)
9136d49e1aeSJan Lentfer return -1;
914*a1157835SDaniel Fojt return gnutls_prf(conn->session, os_strlen(label), label,
915*a1157835SDaniel Fojt 0 /* client_random first */, 0, NULL, out_len,
916*a1157835SDaniel Fojt (char *) out);
917*a1157835SDaniel Fojt #endif /* 3.4.4 */
9186d49e1aeSJan Lentfer }
9196d49e1aeSJan Lentfer
9206d49e1aeSJan Lentfer
tls_connection_get_eap_fast_key(void * tls_ctx,struct tls_connection * conn,u8 * out,size_t out_len)921*a1157835SDaniel Fojt int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
922*a1157835SDaniel Fojt u8 *out, size_t out_len)
923*a1157835SDaniel Fojt {
924*a1157835SDaniel Fojt return -1;
925*a1157835SDaniel Fojt }
926*a1157835SDaniel Fojt
927*a1157835SDaniel Fojt
gnutls_tls_fail_event(struct tls_connection * conn,const gnutls_datum_t * cert,int depth,const char * subject,const char * err_str,enum tls_fail_reason reason)928*a1157835SDaniel Fojt static void gnutls_tls_fail_event(struct tls_connection *conn,
929*a1157835SDaniel Fojt const gnutls_datum_t *cert, int depth,
930*a1157835SDaniel Fojt const char *subject, const char *err_str,
931*a1157835SDaniel Fojt enum tls_fail_reason reason)
932*a1157835SDaniel Fojt {
933*a1157835SDaniel Fojt union tls_event_data ev;
934*a1157835SDaniel Fojt struct tls_global *global = conn->global;
935*a1157835SDaniel Fojt struct wpabuf *cert_buf = NULL;
936*a1157835SDaniel Fojt
937*a1157835SDaniel Fojt if (global->event_cb == NULL)
938*a1157835SDaniel Fojt return;
939*a1157835SDaniel Fojt
940*a1157835SDaniel Fojt os_memset(&ev, 0, sizeof(ev));
941*a1157835SDaniel Fojt ev.cert_fail.depth = depth;
942*a1157835SDaniel Fojt ev.cert_fail.subject = subject ? subject : "";
943*a1157835SDaniel Fojt ev.cert_fail.reason = reason;
944*a1157835SDaniel Fojt ev.cert_fail.reason_txt = err_str;
945*a1157835SDaniel Fojt if (cert) {
946*a1157835SDaniel Fojt cert_buf = wpabuf_alloc_copy(cert->data, cert->size);
947*a1157835SDaniel Fojt ev.cert_fail.cert = cert_buf;
948*a1157835SDaniel Fojt }
949*a1157835SDaniel Fojt global->event_cb(global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
950*a1157835SDaniel Fojt wpabuf_free(cert_buf);
951*a1157835SDaniel Fojt }
952*a1157835SDaniel Fojt
953*a1157835SDaniel Fojt
954*a1157835SDaniel Fojt #if GNUTLS_VERSION_NUMBER < 0x030300
server_eku_purpose(gnutls_x509_crt_t cert)955*a1157835SDaniel Fojt static int server_eku_purpose(gnutls_x509_crt_t cert)
956*a1157835SDaniel Fojt {
957*a1157835SDaniel Fojt unsigned int i;
958*a1157835SDaniel Fojt
959*a1157835SDaniel Fojt for (i = 0; ; i++) {
960*a1157835SDaniel Fojt char oid[128];
961*a1157835SDaniel Fojt size_t oid_size = sizeof(oid);
962*a1157835SDaniel Fojt int res;
963*a1157835SDaniel Fojt
964*a1157835SDaniel Fojt res = gnutls_x509_crt_get_key_purpose_oid(cert, i, oid,
965*a1157835SDaniel Fojt &oid_size, NULL);
966*a1157835SDaniel Fojt if (res == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
967*a1157835SDaniel Fojt if (i == 0) {
968*a1157835SDaniel Fojt /* No EKU - assume any use allowed */
969*a1157835SDaniel Fojt return 1;
970*a1157835SDaniel Fojt }
971*a1157835SDaniel Fojt break;
972*a1157835SDaniel Fojt }
973*a1157835SDaniel Fojt
974*a1157835SDaniel Fojt if (res < 0) {
975*a1157835SDaniel Fojt wpa_printf(MSG_INFO, "GnuTLS: Failed to get EKU");
976*a1157835SDaniel Fojt return 0;
977*a1157835SDaniel Fojt }
978*a1157835SDaniel Fojt
979*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "GnuTLS: Certificate purpose: %s", oid);
980*a1157835SDaniel Fojt if (os_strcmp(oid, GNUTLS_KP_TLS_WWW_SERVER) == 0 ||
981*a1157835SDaniel Fojt os_strcmp(oid, GNUTLS_KP_ANY) == 0)
982*a1157835SDaniel Fojt return 1;
983*a1157835SDaniel Fojt }
984*a1157835SDaniel Fojt
985*a1157835SDaniel Fojt return 0;
986*a1157835SDaniel Fojt }
987*a1157835SDaniel Fojt #endif /* < 3.3.0 */
988*a1157835SDaniel Fojt
989*a1157835SDaniel Fojt
check_ocsp(struct tls_connection * conn,gnutls_session_t session,gnutls_alert_description_t * err)990*a1157835SDaniel Fojt static int check_ocsp(struct tls_connection *conn, gnutls_session_t session,
9916d49e1aeSJan Lentfer gnutls_alert_description_t *err)
9926d49e1aeSJan Lentfer {
993*a1157835SDaniel Fojt #if GNUTLS_VERSION_NUMBER >= 0x030103
994*a1157835SDaniel Fojt gnutls_datum_t response, buf;
995*a1157835SDaniel Fojt gnutls_ocsp_resp_t resp;
996*a1157835SDaniel Fojt unsigned int cert_status;
997*a1157835SDaniel Fojt int res;
998*a1157835SDaniel Fojt
999*a1157835SDaniel Fojt if (!(conn->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)))
1000*a1157835SDaniel Fojt return 0;
1001*a1157835SDaniel Fojt
1002*a1157835SDaniel Fojt if (!gnutls_ocsp_status_request_is_checked(session, 0)) {
1003*a1157835SDaniel Fojt if (conn->flags & TLS_CONN_REQUIRE_OCSP) {
1004*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
1005*a1157835SDaniel Fojt "GnuTLS: No valid OCSP response received");
1006*a1157835SDaniel Fojt goto ocsp_error;
1007*a1157835SDaniel Fojt }
1008*a1157835SDaniel Fojt
1009*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
1010*a1157835SDaniel Fojt "GnuTLS: Valid OCSP response was not received - continue since OCSP was not required");
1011*a1157835SDaniel Fojt return 0;
1012*a1157835SDaniel Fojt }
1013*a1157835SDaniel Fojt
1014*a1157835SDaniel Fojt /*
1015*a1157835SDaniel Fojt * GnuTLS has already verified the OCSP response in
1016*a1157835SDaniel Fojt * check_ocsp_response() and rejected handshake if the certificate was
1017*a1157835SDaniel Fojt * found to be revoked. However, if the response indicates that the
1018*a1157835SDaniel Fojt * status is unknown, handshake continues and reaches here. We need to
1019*a1157835SDaniel Fojt * re-import the OCSP response to check for unknown certificate status,
1020*a1157835SDaniel Fojt * but we do not need to repeat gnutls_ocsp_resp_check_crt() and
1021*a1157835SDaniel Fojt * gnutls_ocsp_resp_verify_direct() calls.
1022*a1157835SDaniel Fojt */
1023*a1157835SDaniel Fojt
1024*a1157835SDaniel Fojt res = gnutls_ocsp_status_request_get(session, &response);
1025*a1157835SDaniel Fojt if (res != GNUTLS_E_SUCCESS) {
1026*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
1027*a1157835SDaniel Fojt "GnuTLS: OCSP response was received, but it was not valid");
1028*a1157835SDaniel Fojt goto ocsp_error;
1029*a1157835SDaniel Fojt }
1030*a1157835SDaniel Fojt
1031*a1157835SDaniel Fojt if (gnutls_ocsp_resp_init(&resp) != GNUTLS_E_SUCCESS)
1032*a1157835SDaniel Fojt goto ocsp_error;
1033*a1157835SDaniel Fojt
1034*a1157835SDaniel Fojt res = gnutls_ocsp_resp_import(resp, &response);
1035*a1157835SDaniel Fojt if (res != GNUTLS_E_SUCCESS) {
1036*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
1037*a1157835SDaniel Fojt "GnuTLS: Could not parse received OCSP response: %s",
1038*a1157835SDaniel Fojt gnutls_strerror(res));
1039*a1157835SDaniel Fojt gnutls_ocsp_resp_deinit(resp);
1040*a1157835SDaniel Fojt goto ocsp_error;
1041*a1157835SDaniel Fojt }
1042*a1157835SDaniel Fojt
1043*a1157835SDaniel Fojt res = gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &buf);
1044*a1157835SDaniel Fojt if (res == GNUTLS_E_SUCCESS) {
1045*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "GnuTLS: %s", buf.data);
1046*a1157835SDaniel Fojt gnutls_free(buf.data);
1047*a1157835SDaniel Fojt }
1048*a1157835SDaniel Fojt
1049*a1157835SDaniel Fojt res = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL,
1050*a1157835SDaniel Fojt NULL, &cert_status, NULL,
1051*a1157835SDaniel Fojt NULL, NULL, NULL);
1052*a1157835SDaniel Fojt gnutls_ocsp_resp_deinit(resp);
1053*a1157835SDaniel Fojt if (res != GNUTLS_E_SUCCESS) {
1054*a1157835SDaniel Fojt wpa_printf(MSG_INFO,
1055*a1157835SDaniel Fojt "GnuTLS: Failed to extract OCSP information: %s",
1056*a1157835SDaniel Fojt gnutls_strerror(res));
1057*a1157835SDaniel Fojt goto ocsp_error;
1058*a1157835SDaniel Fojt }
1059*a1157835SDaniel Fojt
1060*a1157835SDaniel Fojt if (cert_status == GNUTLS_OCSP_CERT_GOOD) {
1061*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "GnuTLS: OCSP cert status: good");
1062*a1157835SDaniel Fojt } else if (cert_status == GNUTLS_OCSP_CERT_REVOKED) {
1063*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
1064*a1157835SDaniel Fojt "GnuTLS: OCSP cert status: revoked");
1065*a1157835SDaniel Fojt goto ocsp_error;
1066*a1157835SDaniel Fojt } else {
1067*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
1068*a1157835SDaniel Fojt "GnuTLS: OCSP cert status: unknown");
1069*a1157835SDaniel Fojt if (conn->flags & TLS_CONN_REQUIRE_OCSP)
1070*a1157835SDaniel Fojt goto ocsp_error;
1071*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
1072*a1157835SDaniel Fojt "GnuTLS: OCSP was not required, so allow connection to continue");
1073*a1157835SDaniel Fojt }
1074*a1157835SDaniel Fojt
1075*a1157835SDaniel Fojt return 0;
1076*a1157835SDaniel Fojt
1077*a1157835SDaniel Fojt ocsp_error:
1078*a1157835SDaniel Fojt gnutls_tls_fail_event(conn, NULL, 0, NULL,
1079*a1157835SDaniel Fojt "bad certificate status response",
1080*a1157835SDaniel Fojt TLS_FAIL_REVOKED);
1081*a1157835SDaniel Fojt *err = GNUTLS_A_CERTIFICATE_REVOKED;
1082*a1157835SDaniel Fojt return -1;
1083*a1157835SDaniel Fojt #else /* GnuTLS 3.1.3 or newer */
1084*a1157835SDaniel Fojt return 0;
1085*a1157835SDaniel Fojt #endif /* GnuTLS 3.1.3 or newer */
1086*a1157835SDaniel Fojt }
1087*a1157835SDaniel Fojt
1088*a1157835SDaniel Fojt
tls_match_suffix_helper(gnutls_x509_crt_t cert,const char * match,int full)1089*a1157835SDaniel Fojt static int tls_match_suffix_helper(gnutls_x509_crt_t cert, const char *match,
1090*a1157835SDaniel Fojt int full)
1091*a1157835SDaniel Fojt {
1092*a1157835SDaniel Fojt int res = -1;
1093*a1157835SDaniel Fojt
1094*a1157835SDaniel Fojt #if GNUTLS_VERSION_NUMBER >= 0x030300
1095*a1157835SDaniel Fojt if (full)
1096*a1157835SDaniel Fojt res = gnutls_x509_crt_check_hostname2(
1097*a1157835SDaniel Fojt cert, match,
1098*a1157835SDaniel Fojt GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS);
1099*a1157835SDaniel Fojt #endif /* >= 3.3.0 */
1100*a1157835SDaniel Fojt if (res == -1)
1101*a1157835SDaniel Fojt res = gnutls_x509_crt_check_hostname(cert, match);
1102*a1157835SDaniel Fojt
1103*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "TLS: Match domain against %s%s --> res=%d",
1104*a1157835SDaniel Fojt full ? "": "suffix ", match, res);
1105*a1157835SDaniel Fojt return res;
1106*a1157835SDaniel Fojt }
1107*a1157835SDaniel Fojt
1108*a1157835SDaniel Fojt
tls_match_suffix(gnutls_x509_crt_t cert,const char * match,int full)1109*a1157835SDaniel Fojt static int tls_match_suffix(gnutls_x509_crt_t cert, const char *match,
1110*a1157835SDaniel Fojt int full)
1111*a1157835SDaniel Fojt {
1112*a1157835SDaniel Fojt char *values, *token, *context = NULL;
1113*a1157835SDaniel Fojt int ret = 0;
1114*a1157835SDaniel Fojt
1115*a1157835SDaniel Fojt if (!os_strchr(match, ';'))
1116*a1157835SDaniel Fojt return tls_match_suffix_helper(cert, match, full);
1117*a1157835SDaniel Fojt
1118*a1157835SDaniel Fojt values = os_strdup(match);
1119*a1157835SDaniel Fojt if (!values)
1120*a1157835SDaniel Fojt return 0;
1121*a1157835SDaniel Fojt
1122*a1157835SDaniel Fojt /* Process each match alternative separately until a match is found */
1123*a1157835SDaniel Fojt while ((token = str_token(values, ";", &context))) {
1124*a1157835SDaniel Fojt if (tls_match_suffix_helper(cert, token, full)) {
1125*a1157835SDaniel Fojt ret = 1;
1126*a1157835SDaniel Fojt break;
1127*a1157835SDaniel Fojt }
1128*a1157835SDaniel Fojt }
1129*a1157835SDaniel Fojt
1130*a1157835SDaniel Fojt os_free(values);
1131*a1157835SDaniel Fojt return ret;
1132*a1157835SDaniel Fojt }
1133*a1157835SDaniel Fojt
1134*a1157835SDaniel Fojt
tls_connection_verify_peer(gnutls_session_t session)1135*a1157835SDaniel Fojt static int tls_connection_verify_peer(gnutls_session_t session)
1136*a1157835SDaniel Fojt {
1137*a1157835SDaniel Fojt struct tls_connection *conn;
11386d49e1aeSJan Lentfer unsigned int status, num_certs, i;
11396d49e1aeSJan Lentfer struct os_time now;
11406d49e1aeSJan Lentfer const gnutls_datum_t *certs;
11416d49e1aeSJan Lentfer gnutls_x509_crt_t cert;
1142*a1157835SDaniel Fojt gnutls_alert_description_t err;
1143*a1157835SDaniel Fojt int res;
11446d49e1aeSJan Lentfer
1145*a1157835SDaniel Fojt conn = gnutls_session_get_ptr(session);
1146*a1157835SDaniel Fojt if (!conn->verify_peer) {
1147*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
1148*a1157835SDaniel Fojt "GnuTLS: No peer certificate verification enabled");
1149*a1157835SDaniel Fojt return 0;
1150*a1157835SDaniel Fojt }
1151*a1157835SDaniel Fojt
1152*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "GnuTSL: Verifying peer certificate");
1153*a1157835SDaniel Fojt
1154*a1157835SDaniel Fojt #if GNUTLS_VERSION_NUMBER >= 0x030300
1155*a1157835SDaniel Fojt {
1156*a1157835SDaniel Fojt gnutls_typed_vdata_st data[1];
1157*a1157835SDaniel Fojt unsigned int elements = 0;
1158*a1157835SDaniel Fojt
1159*a1157835SDaniel Fojt os_memset(data, 0, sizeof(data));
1160*a1157835SDaniel Fojt if (!conn->global->server) {
1161*a1157835SDaniel Fojt data[elements].type = GNUTLS_DT_KEY_PURPOSE_OID;
1162*a1157835SDaniel Fojt data[elements].data = (void *) GNUTLS_KP_TLS_WWW_SERVER;
1163*a1157835SDaniel Fojt elements++;
1164*a1157835SDaniel Fojt }
1165*a1157835SDaniel Fojt res = gnutls_certificate_verify_peers(session, data, 1,
1166*a1157835SDaniel Fojt &status);
1167*a1157835SDaniel Fojt }
1168*a1157835SDaniel Fojt #else /* < 3.3.0 */
1169*a1157835SDaniel Fojt res = gnutls_certificate_verify_peers2(session, &status);
1170*a1157835SDaniel Fojt #endif
1171*a1157835SDaniel Fojt if (res < 0) {
11726d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
11736d49e1aeSJan Lentfer "certificate chain");
1174*a1157835SDaniel Fojt err = GNUTLS_A_INTERNAL_ERROR;
1175*a1157835SDaniel Fojt goto out;
1176*a1157835SDaniel Fojt }
1177*a1157835SDaniel Fojt
1178*a1157835SDaniel Fojt #if GNUTLS_VERSION_NUMBER >= 0x030104
1179*a1157835SDaniel Fojt {
1180*a1157835SDaniel Fojt gnutls_datum_t info;
1181*a1157835SDaniel Fojt int ret, type;
1182*a1157835SDaniel Fojt
1183*a1157835SDaniel Fojt type = gnutls_certificate_type_get(session);
1184*a1157835SDaniel Fojt ret = gnutls_certificate_verification_status_print(status, type,
1185*a1157835SDaniel Fojt &info, 0);
1186*a1157835SDaniel Fojt if (ret < 0) {
1187*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
1188*a1157835SDaniel Fojt "GnuTLS: Failed to print verification status");
1189*a1157835SDaniel Fojt err = GNUTLS_A_INTERNAL_ERROR;
1190*a1157835SDaniel Fojt goto out;
1191*a1157835SDaniel Fojt }
1192*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "GnuTLS: %s", info.data);
1193*a1157835SDaniel Fojt gnutls_free(info.data);
1194*a1157835SDaniel Fojt }
1195*a1157835SDaniel Fojt #endif /* GnuTLS 3.1.4 or newer */
1196*a1157835SDaniel Fojt
1197*a1157835SDaniel Fojt certs = gnutls_certificate_get_peers(session, &num_certs);
1198*a1157835SDaniel Fojt if (certs == NULL || num_certs == 0) {
1199*a1157835SDaniel Fojt wpa_printf(MSG_INFO, "TLS: No peer certificate chain received");
1200*a1157835SDaniel Fojt err = GNUTLS_A_UNKNOWN_CA;
1201*a1157835SDaniel Fojt goto out;
12026d49e1aeSJan Lentfer }
12036d49e1aeSJan Lentfer
12046d49e1aeSJan Lentfer if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
12056d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
12066d49e1aeSJan Lentfer if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
12076d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "TLS: Certificate uses insecure "
12086d49e1aeSJan Lentfer "algorithm");
1209*a1157835SDaniel Fojt gnutls_tls_fail_event(conn, NULL, 0, NULL,
1210*a1157835SDaniel Fojt "certificate uses insecure algorithm",
1211*a1157835SDaniel Fojt TLS_FAIL_BAD_CERTIFICATE);
1212*a1157835SDaniel Fojt err = GNUTLS_A_INSUFFICIENT_SECURITY;
1213*a1157835SDaniel Fojt goto out;
12146d49e1aeSJan Lentfer }
12156d49e1aeSJan Lentfer if (status & GNUTLS_CERT_NOT_ACTIVATED) {
12166d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "TLS: Certificate not yet "
12176d49e1aeSJan Lentfer "activated");
1218*a1157835SDaniel Fojt gnutls_tls_fail_event(conn, NULL, 0, NULL,
1219*a1157835SDaniel Fojt "certificate not yet valid",
1220*a1157835SDaniel Fojt TLS_FAIL_NOT_YET_VALID);
1221*a1157835SDaniel Fojt err = GNUTLS_A_CERTIFICATE_EXPIRED;
1222*a1157835SDaniel Fojt goto out;
12236d49e1aeSJan Lentfer }
12246d49e1aeSJan Lentfer if (status & GNUTLS_CERT_EXPIRED) {
12256d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "TLS: Certificate expired");
1226*a1157835SDaniel Fojt gnutls_tls_fail_event(conn, NULL, 0, NULL,
1227*a1157835SDaniel Fojt "certificate has expired",
1228*a1157835SDaniel Fojt TLS_FAIL_EXPIRED);
1229*a1157835SDaniel Fojt err = GNUTLS_A_CERTIFICATE_EXPIRED;
1230*a1157835SDaniel Fojt goto out;
12316d49e1aeSJan Lentfer }
1232*a1157835SDaniel Fojt gnutls_tls_fail_event(conn, NULL, 0, NULL,
1233*a1157835SDaniel Fojt "untrusted certificate",
1234*a1157835SDaniel Fojt TLS_FAIL_UNTRUSTED);
1235*a1157835SDaniel Fojt err = GNUTLS_A_INTERNAL_ERROR;
1236*a1157835SDaniel Fojt goto out;
12376d49e1aeSJan Lentfer }
12386d49e1aeSJan Lentfer
12396d49e1aeSJan Lentfer if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
12406d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
12416d49e1aeSJan Lentfer "known issuer");
1242*a1157835SDaniel Fojt gnutls_tls_fail_event(conn, NULL, 0, NULL, "signed not found",
1243*a1157835SDaniel Fojt TLS_FAIL_UNTRUSTED);
1244*a1157835SDaniel Fojt err = GNUTLS_A_UNKNOWN_CA;
1245*a1157835SDaniel Fojt goto out;
12466d49e1aeSJan Lentfer }
12476d49e1aeSJan Lentfer
12486d49e1aeSJan Lentfer if (status & GNUTLS_CERT_REVOKED) {
12496d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
1250*a1157835SDaniel Fojt gnutls_tls_fail_event(conn, NULL, 0, NULL,
1251*a1157835SDaniel Fojt "certificate revoked",
1252*a1157835SDaniel Fojt TLS_FAIL_REVOKED);
1253*a1157835SDaniel Fojt err = GNUTLS_A_CERTIFICATE_REVOKED;
1254*a1157835SDaniel Fojt goto out;
12556d49e1aeSJan Lentfer }
12566d49e1aeSJan Lentfer
1257*a1157835SDaniel Fojt if (status != 0) {
1258*a1157835SDaniel Fojt wpa_printf(MSG_INFO, "TLS: Unknown verification status: %d",
1259*a1157835SDaniel Fojt status);
1260*a1157835SDaniel Fojt err = GNUTLS_A_INTERNAL_ERROR;
1261*a1157835SDaniel Fojt goto out;
1262*a1157835SDaniel Fojt }
1263*a1157835SDaniel Fojt
1264*a1157835SDaniel Fojt if (check_ocsp(conn, session, &err))
1265*a1157835SDaniel Fojt goto out;
1266*a1157835SDaniel Fojt
12676d49e1aeSJan Lentfer os_get_time(&now);
12686d49e1aeSJan Lentfer
12696d49e1aeSJan Lentfer for (i = 0; i < num_certs; i++) {
12706d49e1aeSJan Lentfer char *buf;
12716d49e1aeSJan Lentfer size_t len;
12726d49e1aeSJan Lentfer if (gnutls_x509_crt_init(&cert) < 0) {
12736d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "TLS: Certificate initialization "
12746d49e1aeSJan Lentfer "failed");
1275*a1157835SDaniel Fojt err = GNUTLS_A_BAD_CERTIFICATE;
1276*a1157835SDaniel Fojt goto out;
12776d49e1aeSJan Lentfer }
12786d49e1aeSJan Lentfer
12796d49e1aeSJan Lentfer if (gnutls_x509_crt_import(cert, &certs[i],
12806d49e1aeSJan Lentfer GNUTLS_X509_FMT_DER) < 0) {
12816d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "TLS: Could not parse peer "
12826d49e1aeSJan Lentfer "certificate %d/%d", i + 1, num_certs);
12836d49e1aeSJan Lentfer gnutls_x509_crt_deinit(cert);
1284*a1157835SDaniel Fojt err = GNUTLS_A_BAD_CERTIFICATE;
1285*a1157835SDaniel Fojt goto out;
12866d49e1aeSJan Lentfer }
12876d49e1aeSJan Lentfer
12886d49e1aeSJan Lentfer gnutls_x509_crt_get_dn(cert, NULL, &len);
12896d49e1aeSJan Lentfer len++;
12906d49e1aeSJan Lentfer buf = os_malloc(len + 1);
12916d49e1aeSJan Lentfer if (buf) {
12926d49e1aeSJan Lentfer buf[0] = buf[len] = '\0';
12936d49e1aeSJan Lentfer gnutls_x509_crt_get_dn(cert, buf, &len);
12946d49e1aeSJan Lentfer }
12956d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
12966d49e1aeSJan Lentfer i + 1, num_certs, buf);
12976d49e1aeSJan Lentfer
1298*a1157835SDaniel Fojt if (conn->global->event_cb) {
1299*a1157835SDaniel Fojt struct wpabuf *cert_buf = NULL;
1300*a1157835SDaniel Fojt union tls_event_data ev;
1301*a1157835SDaniel Fojt #ifdef CONFIG_SHA256
1302*a1157835SDaniel Fojt u8 hash[32];
1303*a1157835SDaniel Fojt const u8 *_addr[1];
1304*a1157835SDaniel Fojt size_t _len[1];
1305*a1157835SDaniel Fojt #endif /* CONFIG_SHA256 */
1306*a1157835SDaniel Fojt
1307*a1157835SDaniel Fojt os_memset(&ev, 0, sizeof(ev));
1308*a1157835SDaniel Fojt if (conn->global->cert_in_cb) {
1309*a1157835SDaniel Fojt cert_buf = wpabuf_alloc_copy(certs[i].data,
1310*a1157835SDaniel Fojt certs[i].size);
1311*a1157835SDaniel Fojt ev.peer_cert.cert = cert_buf;
1312*a1157835SDaniel Fojt }
1313*a1157835SDaniel Fojt #ifdef CONFIG_SHA256
1314*a1157835SDaniel Fojt _addr[0] = certs[i].data;
1315*a1157835SDaniel Fojt _len[0] = certs[i].size;
1316*a1157835SDaniel Fojt if (sha256_vector(1, _addr, _len, hash) == 0) {
1317*a1157835SDaniel Fojt ev.peer_cert.hash = hash;
1318*a1157835SDaniel Fojt ev.peer_cert.hash_len = sizeof(hash);
1319*a1157835SDaniel Fojt }
1320*a1157835SDaniel Fojt #endif /* CONFIG_SHA256 */
1321*a1157835SDaniel Fojt ev.peer_cert.depth = i;
1322*a1157835SDaniel Fojt ev.peer_cert.subject = buf;
1323*a1157835SDaniel Fojt conn->global->event_cb(conn->global->cb_ctx,
1324*a1157835SDaniel Fojt TLS_PEER_CERTIFICATE, &ev);
1325*a1157835SDaniel Fojt wpabuf_free(cert_buf);
1326*a1157835SDaniel Fojt }
1327*a1157835SDaniel Fojt
13286d49e1aeSJan Lentfer if (i == 0) {
1329*a1157835SDaniel Fojt if (conn->suffix_match &&
1330*a1157835SDaniel Fojt !tls_match_suffix(cert, conn->suffix_match, 0)) {
1331*a1157835SDaniel Fojt wpa_printf(MSG_WARNING,
1332*a1157835SDaniel Fojt "TLS: Domain suffix match '%s' not found",
1333*a1157835SDaniel Fojt conn->suffix_match);
1334*a1157835SDaniel Fojt gnutls_tls_fail_event(
1335*a1157835SDaniel Fojt conn, &certs[i], i, buf,
1336*a1157835SDaniel Fojt "Domain suffix mismatch",
1337*a1157835SDaniel Fojt TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
1338*a1157835SDaniel Fojt err = GNUTLS_A_BAD_CERTIFICATE;
1339*a1157835SDaniel Fojt gnutls_x509_crt_deinit(cert);
1340*a1157835SDaniel Fojt os_free(buf);
1341*a1157835SDaniel Fojt goto out;
1342*a1157835SDaniel Fojt }
1343*a1157835SDaniel Fojt
1344*a1157835SDaniel Fojt #if GNUTLS_VERSION_NUMBER >= 0x030300
1345*a1157835SDaniel Fojt if (conn->domain_match &&
1346*a1157835SDaniel Fojt !tls_match_suffix(cert, conn->domain_match, 1)) {
1347*a1157835SDaniel Fojt wpa_printf(MSG_WARNING,
1348*a1157835SDaniel Fojt "TLS: Domain match '%s' not found",
1349*a1157835SDaniel Fojt conn->domain_match);
1350*a1157835SDaniel Fojt gnutls_tls_fail_event(
1351*a1157835SDaniel Fojt conn, &certs[i], i, buf,
1352*a1157835SDaniel Fojt "Domain mismatch",
1353*a1157835SDaniel Fojt TLS_FAIL_DOMAIN_MISMATCH);
1354*a1157835SDaniel Fojt err = GNUTLS_A_BAD_CERTIFICATE;
1355*a1157835SDaniel Fojt gnutls_x509_crt_deinit(cert);
1356*a1157835SDaniel Fojt os_free(buf);
1357*a1157835SDaniel Fojt goto out;
1358*a1157835SDaniel Fojt }
1359*a1157835SDaniel Fojt #endif /* >= 3.3.0 */
1360*a1157835SDaniel Fojt
1361*a1157835SDaniel Fojt /* TODO: validate altsubject_match.
1362*a1157835SDaniel Fojt * For now, any such configuration is rejected in
1363*a1157835SDaniel Fojt * tls_connection_set_params() */
1364*a1157835SDaniel Fojt
1365*a1157835SDaniel Fojt #if GNUTLS_VERSION_NUMBER < 0x030300
1366*a1157835SDaniel Fojt /*
1367*a1157835SDaniel Fojt * gnutls_certificate_verify_peers() not available, so
1368*a1157835SDaniel Fojt * need to check EKU separately.
1369*a1157835SDaniel Fojt */
1370*a1157835SDaniel Fojt if (!conn->global->server &&
1371*a1157835SDaniel Fojt !server_eku_purpose(cert)) {
1372*a1157835SDaniel Fojt wpa_printf(MSG_WARNING,
1373*a1157835SDaniel Fojt "GnuTLS: No server EKU");
1374*a1157835SDaniel Fojt gnutls_tls_fail_event(
1375*a1157835SDaniel Fojt conn, &certs[i], i, buf,
1376*a1157835SDaniel Fojt "No server EKU",
1377*a1157835SDaniel Fojt TLS_FAIL_BAD_CERTIFICATE);
1378*a1157835SDaniel Fojt err = GNUTLS_A_BAD_CERTIFICATE;
1379*a1157835SDaniel Fojt gnutls_x509_crt_deinit(cert);
1380*a1157835SDaniel Fojt os_free(buf);
1381*a1157835SDaniel Fojt goto out;
1382*a1157835SDaniel Fojt }
1383*a1157835SDaniel Fojt #endif /* < 3.3.0 */
1384*a1157835SDaniel Fojt }
1385*a1157835SDaniel Fojt
1386*a1157835SDaniel Fojt if (!conn->disable_time_checks &&
1387*a1157835SDaniel Fojt (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
1388*a1157835SDaniel Fojt gnutls_x509_crt_get_activation_time(cert) > now.sec)) {
1389*a1157835SDaniel Fojt wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
1390*a1157835SDaniel Fojt "not valid at this time",
1391*a1157835SDaniel Fojt i + 1, num_certs);
1392*a1157835SDaniel Fojt gnutls_tls_fail_event(
1393*a1157835SDaniel Fojt conn, &certs[i], i, buf,
1394*a1157835SDaniel Fojt "Certificate is not valid at this time",
1395*a1157835SDaniel Fojt TLS_FAIL_EXPIRED);
1396*a1157835SDaniel Fojt gnutls_x509_crt_deinit(cert);
1397*a1157835SDaniel Fojt os_free(buf);
1398*a1157835SDaniel Fojt err = GNUTLS_A_CERTIFICATE_EXPIRED;
1399*a1157835SDaniel Fojt goto out;
14006d49e1aeSJan Lentfer }
14016d49e1aeSJan Lentfer
14026d49e1aeSJan Lentfer os_free(buf);
14036d49e1aeSJan Lentfer
14046d49e1aeSJan Lentfer gnutls_x509_crt_deinit(cert);
14056d49e1aeSJan Lentfer }
14066d49e1aeSJan Lentfer
1407*a1157835SDaniel Fojt if (conn->global->event_cb != NULL)
1408*a1157835SDaniel Fojt conn->global->event_cb(conn->global->cb_ctx,
1409*a1157835SDaniel Fojt TLS_CERT_CHAIN_SUCCESS, NULL);
14106d49e1aeSJan Lentfer
14116d49e1aeSJan Lentfer return 0;
1412*a1157835SDaniel Fojt
1413*a1157835SDaniel Fojt out:
1414*a1157835SDaniel Fojt conn->failed++;
1415*a1157835SDaniel Fojt gnutls_alert_send(session, GNUTLS_AL_FATAL, err);
1416*a1157835SDaniel Fojt return GNUTLS_E_CERTIFICATE_ERROR;
14176d49e1aeSJan Lentfer }
14186d49e1aeSJan Lentfer
14196d49e1aeSJan Lentfer
gnutls_get_appl_data(struct tls_connection * conn)14203ff40c12SJohn Marino static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn)
14216d49e1aeSJan Lentfer {
14223ff40c12SJohn Marino int res;
14233ff40c12SJohn Marino struct wpabuf *ad;
14243ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data");
14253ff40c12SJohn Marino ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3);
14263ff40c12SJohn Marino if (ad == NULL)
14273ff40c12SJohn Marino return NULL;
14283ff40c12SJohn Marino
14293ff40c12SJohn Marino res = gnutls_record_recv(conn->session, wpabuf_mhead(ad),
14303ff40c12SJohn Marino wpabuf_size(ad));
14313ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res);
14323ff40c12SJohn Marino if (res < 0) {
14333ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
14343ff40c12SJohn Marino "(%s)", __func__, (int) res,
14353ff40c12SJohn Marino gnutls_strerror(res));
14363ff40c12SJohn Marino wpabuf_free(ad);
14373ff40c12SJohn Marino return NULL;
14383ff40c12SJohn Marino }
14393ff40c12SJohn Marino
14403ff40c12SJohn Marino wpabuf_put(ad, res);
14413ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data",
14423ff40c12SJohn Marino res);
14433ff40c12SJohn Marino return ad;
14443ff40c12SJohn Marino }
14453ff40c12SJohn Marino
14463ff40c12SJohn Marino
tls_connection_handshake(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data,struct wpabuf ** appl_data)14473ff40c12SJohn Marino struct wpabuf * tls_connection_handshake(void *tls_ctx,
14483ff40c12SJohn Marino struct tls_connection *conn,
14493ff40c12SJohn Marino const struct wpabuf *in_data,
14503ff40c12SJohn Marino struct wpabuf **appl_data)
14513ff40c12SJohn Marino {
14523ff40c12SJohn Marino struct tls_global *global = tls_ctx;
14533ff40c12SJohn Marino struct wpabuf *out_data;
14546d49e1aeSJan Lentfer int ret;
14556d49e1aeSJan Lentfer
14566d49e1aeSJan Lentfer if (appl_data)
14576d49e1aeSJan Lentfer *appl_data = NULL;
14586d49e1aeSJan Lentfer
14593ff40c12SJohn Marino if (in_data && wpabuf_len(in_data) > 0) {
14606d49e1aeSJan Lentfer if (conn->pull_buf) {
14616d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
14626d49e1aeSJan Lentfer "pull_buf", __func__,
14633ff40c12SJohn Marino (unsigned long) wpabuf_len(conn->pull_buf));
14643ff40c12SJohn Marino wpabuf_free(conn->pull_buf);
14656d49e1aeSJan Lentfer }
14663ff40c12SJohn Marino conn->pull_buf = wpabuf_dup(in_data);
14676d49e1aeSJan Lentfer if (conn->pull_buf == NULL)
14686d49e1aeSJan Lentfer return NULL;
14693ff40c12SJohn Marino conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
14706d49e1aeSJan Lentfer }
14716d49e1aeSJan Lentfer
14726d49e1aeSJan Lentfer ret = gnutls_handshake(conn->session);
14736d49e1aeSJan Lentfer if (ret < 0) {
1474*a1157835SDaniel Fojt gnutls_alert_description_t alert;
1475*a1157835SDaniel Fojt union tls_event_data ev;
1476*a1157835SDaniel Fojt
14776d49e1aeSJan Lentfer switch (ret) {
14786d49e1aeSJan Lentfer case GNUTLS_E_AGAIN:
14796d49e1aeSJan Lentfer if (global->server && conn->established &&
14806d49e1aeSJan Lentfer conn->push_buf == NULL) {
14816d49e1aeSJan Lentfer /* Need to return something to trigger
14826d49e1aeSJan Lentfer * completion of EAP-TLS. */
14833ff40c12SJohn Marino conn->push_buf = wpabuf_alloc(0);
14846d49e1aeSJan Lentfer }
14856d49e1aeSJan Lentfer break;
1486*a1157835SDaniel Fojt case GNUTLS_E_DH_PRIME_UNACCEPTABLE:
1487*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "GnuTLS: Unacceptable DH prime");
1488*a1157835SDaniel Fojt if (conn->global->event_cb) {
1489*a1157835SDaniel Fojt os_memset(&ev, 0, sizeof(ev));
1490*a1157835SDaniel Fojt ev.alert.is_local = 1;
1491*a1157835SDaniel Fojt ev.alert.type = "fatal";
1492*a1157835SDaniel Fojt ev.alert.description = "insufficient security";
1493*a1157835SDaniel Fojt conn->global->event_cb(conn->global->cb_ctx,
1494*a1157835SDaniel Fojt TLS_ALERT, &ev);
1495*a1157835SDaniel Fojt }
1496*a1157835SDaniel Fojt /*
1497*a1157835SDaniel Fojt * Could send a TLS Alert to the server, but for now,
1498*a1157835SDaniel Fojt * simply terminate handshake.
1499*a1157835SDaniel Fojt */
1500*a1157835SDaniel Fojt conn->failed++;
1501*a1157835SDaniel Fojt conn->write_alerts++;
1502*a1157835SDaniel Fojt break;
15036d49e1aeSJan Lentfer case GNUTLS_E_FATAL_ALERT_RECEIVED:
1504*a1157835SDaniel Fojt alert = gnutls_alert_get(conn->session);
15056d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
1506*a1157835SDaniel Fojt __func__, gnutls_alert_get_name(alert));
15076d49e1aeSJan Lentfer conn->read_alerts++;
1508*a1157835SDaniel Fojt if (conn->global->event_cb != NULL) {
1509*a1157835SDaniel Fojt os_memset(&ev, 0, sizeof(ev));
1510*a1157835SDaniel Fojt ev.alert.is_local = 0;
1511*a1157835SDaniel Fojt ev.alert.type = gnutls_alert_get_name(alert);
1512*a1157835SDaniel Fojt ev.alert.description = ev.alert.type;
1513*a1157835SDaniel Fojt conn->global->event_cb(conn->global->cb_ctx,
1514*a1157835SDaniel Fojt TLS_ALERT, &ev);
1515*a1157835SDaniel Fojt }
15166d49e1aeSJan Lentfer /* continue */
15176d49e1aeSJan Lentfer default:
15186d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
15196d49e1aeSJan Lentfer "-> %s", __func__, gnutls_strerror(ret));
15206d49e1aeSJan Lentfer conn->failed++;
15216d49e1aeSJan Lentfer }
15226d49e1aeSJan Lentfer } else {
15236d49e1aeSJan Lentfer size_t size;
15246d49e1aeSJan Lentfer
15253ff40c12SJohn Marino wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
1526*a1157835SDaniel Fojt
1527*a1157835SDaniel Fojt #if GNUTLS_VERSION_NUMBER >= 0x03010a
1528*a1157835SDaniel Fojt {
1529*a1157835SDaniel Fojt char *desc;
1530*a1157835SDaniel Fojt
1531*a1157835SDaniel Fojt desc = gnutls_session_get_desc(conn->session);
1532*a1157835SDaniel Fojt if (desc) {
1533*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "GnuTLS: %s", desc);
1534*a1157835SDaniel Fojt gnutls_free(desc);
1535*a1157835SDaniel Fojt }
1536*a1157835SDaniel Fojt }
1537*a1157835SDaniel Fojt #endif /* GnuTLS 3.1.10 or newer */
1538*a1157835SDaniel Fojt
15396d49e1aeSJan Lentfer conn->established = 1;
15406d49e1aeSJan Lentfer if (conn->push_buf == NULL) {
15416d49e1aeSJan Lentfer /* Need to return something to get final TLS ACK. */
15423ff40c12SJohn Marino conn->push_buf = wpabuf_alloc(0);
15436d49e1aeSJan Lentfer }
15446d49e1aeSJan Lentfer
15456d49e1aeSJan Lentfer gnutls_session_get_data(conn->session, NULL, &size);
15466d49e1aeSJan Lentfer if (global->session_data == NULL ||
15476d49e1aeSJan Lentfer global->session_data_size < size) {
15486d49e1aeSJan Lentfer os_free(global->session_data);
15496d49e1aeSJan Lentfer global->session_data = os_malloc(size);
15506d49e1aeSJan Lentfer }
15516d49e1aeSJan Lentfer if (global->session_data) {
15526d49e1aeSJan Lentfer global->session_data_size = size;
15536d49e1aeSJan Lentfer gnutls_session_get_data(conn->session,
15546d49e1aeSJan Lentfer global->session_data,
15556d49e1aeSJan Lentfer &global->session_data_size);
15566d49e1aeSJan Lentfer }
15573ff40c12SJohn Marino
15583ff40c12SJohn Marino if (conn->pull_buf && appl_data)
15593ff40c12SJohn Marino *appl_data = gnutls_get_appl_data(conn);
15606d49e1aeSJan Lentfer }
15616d49e1aeSJan Lentfer
15626d49e1aeSJan Lentfer out_data = conn->push_buf;
15636d49e1aeSJan Lentfer conn->push_buf = NULL;
15646d49e1aeSJan Lentfer return out_data;
15656d49e1aeSJan Lentfer }
15666d49e1aeSJan Lentfer
15676d49e1aeSJan Lentfer
tls_connection_server_handshake(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data,struct wpabuf ** appl_data)15683ff40c12SJohn Marino struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
15696d49e1aeSJan Lentfer struct tls_connection *conn,
15703ff40c12SJohn Marino const struct wpabuf *in_data,
15713ff40c12SJohn Marino struct wpabuf **appl_data)
15726d49e1aeSJan Lentfer {
15733ff40c12SJohn Marino return tls_connection_handshake(tls_ctx, conn, in_data, appl_data);
15746d49e1aeSJan Lentfer }
15756d49e1aeSJan Lentfer
15766d49e1aeSJan Lentfer
tls_connection_encrypt(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data)15773ff40c12SJohn Marino struct wpabuf * tls_connection_encrypt(void *tls_ctx,
15783ff40c12SJohn Marino struct tls_connection *conn,
15793ff40c12SJohn Marino const struct wpabuf *in_data)
15806d49e1aeSJan Lentfer {
15816d49e1aeSJan Lentfer ssize_t res;
15823ff40c12SJohn Marino struct wpabuf *buf;
15836d49e1aeSJan Lentfer
15843ff40c12SJohn Marino res = gnutls_record_send(conn->session, wpabuf_head(in_data),
15853ff40c12SJohn Marino wpabuf_len(in_data));
15866d49e1aeSJan Lentfer if (res < 0) {
15876d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
15886d49e1aeSJan Lentfer __func__, gnutls_strerror(res));
15893ff40c12SJohn Marino return NULL;
15906d49e1aeSJan Lentfer }
15913ff40c12SJohn Marino
15923ff40c12SJohn Marino buf = conn->push_buf;
15936d49e1aeSJan Lentfer conn->push_buf = NULL;
15943ff40c12SJohn Marino return buf;
15956d49e1aeSJan Lentfer }
15966d49e1aeSJan Lentfer
15976d49e1aeSJan Lentfer
tls_connection_decrypt(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data)15983ff40c12SJohn Marino struct wpabuf * tls_connection_decrypt(void *tls_ctx,
15993ff40c12SJohn Marino struct tls_connection *conn,
16003ff40c12SJohn Marino const struct wpabuf *in_data)
16016d49e1aeSJan Lentfer {
16026d49e1aeSJan Lentfer ssize_t res;
16033ff40c12SJohn Marino struct wpabuf *out;
16046d49e1aeSJan Lentfer
16056d49e1aeSJan Lentfer if (conn->pull_buf) {
16066d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
16076d49e1aeSJan Lentfer "pull_buf", __func__,
16083ff40c12SJohn Marino (unsigned long) wpabuf_len(conn->pull_buf));
16093ff40c12SJohn Marino wpabuf_free(conn->pull_buf);
16106d49e1aeSJan Lentfer }
16113ff40c12SJohn Marino conn->pull_buf = wpabuf_dup(in_data);
16126d49e1aeSJan Lentfer if (conn->pull_buf == NULL)
16133ff40c12SJohn Marino return NULL;
16143ff40c12SJohn Marino conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
16156d49e1aeSJan Lentfer
16163ff40c12SJohn Marino /*
16173ff40c12SJohn Marino * Even though we try to disable TLS compression, it is possible that
16183ff40c12SJohn Marino * this cannot be done with all TLS libraries. Add extra buffer space
16193ff40c12SJohn Marino * to handle the possibility of the decrypted data being longer than
16203ff40c12SJohn Marino * input data.
16213ff40c12SJohn Marino */
16223ff40c12SJohn Marino out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
16233ff40c12SJohn Marino if (out == NULL)
16243ff40c12SJohn Marino return NULL;
16256d49e1aeSJan Lentfer
16263ff40c12SJohn Marino res = gnutls_record_recv(conn->session, wpabuf_mhead(out),
16273ff40c12SJohn Marino wpabuf_size(out));
16286d49e1aeSJan Lentfer if (res < 0) {
16296d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
16306d49e1aeSJan Lentfer "(%s)", __func__, (int) res, gnutls_strerror(res));
16313ff40c12SJohn Marino wpabuf_free(out);
16323ff40c12SJohn Marino return NULL;
16336d49e1aeSJan Lentfer }
16343ff40c12SJohn Marino wpabuf_put(out, res);
16356d49e1aeSJan Lentfer
16363ff40c12SJohn Marino return out;
16376d49e1aeSJan Lentfer }
16386d49e1aeSJan Lentfer
16396d49e1aeSJan Lentfer
tls_connection_resumed(void * ssl_ctx,struct tls_connection * conn)16406d49e1aeSJan Lentfer int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
16416d49e1aeSJan Lentfer {
16426d49e1aeSJan Lentfer if (conn == NULL)
16436d49e1aeSJan Lentfer return 0;
16446d49e1aeSJan Lentfer return gnutls_session_is_resumed(conn->session);
16456d49e1aeSJan Lentfer }
16466d49e1aeSJan Lentfer
16476d49e1aeSJan Lentfer
tls_connection_set_cipher_list(void * tls_ctx,struct tls_connection * conn,u8 * ciphers)16486d49e1aeSJan Lentfer int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
16496d49e1aeSJan Lentfer u8 *ciphers)
16506d49e1aeSJan Lentfer {
16516d49e1aeSJan Lentfer /* TODO */
16526d49e1aeSJan Lentfer return -1;
16536d49e1aeSJan Lentfer }
16546d49e1aeSJan Lentfer
16556d49e1aeSJan Lentfer
tls_get_version(void * ssl_ctx,struct tls_connection * conn,char * buf,size_t buflen)1656*a1157835SDaniel Fojt int tls_get_version(void *ssl_ctx, struct tls_connection *conn,
1657*a1157835SDaniel Fojt char *buf, size_t buflen)
1658*a1157835SDaniel Fojt {
1659*a1157835SDaniel Fojt gnutls_protocol_t ver;
1660*a1157835SDaniel Fojt
1661*a1157835SDaniel Fojt ver = gnutls_protocol_get_version(conn->session);
1662*a1157835SDaniel Fojt if (ver == GNUTLS_TLS1_0)
1663*a1157835SDaniel Fojt os_strlcpy(buf, "TLSv1", buflen);
1664*a1157835SDaniel Fojt else if (ver == GNUTLS_TLS1_1)
1665*a1157835SDaniel Fojt os_strlcpy(buf, "TLSv1.1", buflen);
1666*a1157835SDaniel Fojt else if (ver == GNUTLS_TLS1_2)
1667*a1157835SDaniel Fojt os_strlcpy(buf, "TLSv1.2", buflen);
1668*a1157835SDaniel Fojt else
1669*a1157835SDaniel Fojt return -1;
1670*a1157835SDaniel Fojt return 0;
1671*a1157835SDaniel Fojt }
1672*a1157835SDaniel Fojt
1673*a1157835SDaniel Fojt
tls_get_cipher(void * ssl_ctx,struct tls_connection * conn,char * buf,size_t buflen)16746d49e1aeSJan Lentfer int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
16756d49e1aeSJan Lentfer char *buf, size_t buflen)
16766d49e1aeSJan Lentfer {
1677*a1157835SDaniel Fojt gnutls_cipher_algorithm_t cipher;
1678*a1157835SDaniel Fojt gnutls_kx_algorithm_t kx;
1679*a1157835SDaniel Fojt gnutls_mac_algorithm_t mac;
1680*a1157835SDaniel Fojt const char *kx_str, *cipher_str, *mac_str;
1681*a1157835SDaniel Fojt int res;
1682*a1157835SDaniel Fojt
1683*a1157835SDaniel Fojt cipher = gnutls_cipher_get(conn->session);
1684*a1157835SDaniel Fojt cipher_str = gnutls_cipher_get_name(cipher);
1685*a1157835SDaniel Fojt if (!cipher_str)
1686*a1157835SDaniel Fojt cipher_str = "";
1687*a1157835SDaniel Fojt
1688*a1157835SDaniel Fojt kx = gnutls_kx_get(conn->session);
1689*a1157835SDaniel Fojt kx_str = gnutls_kx_get_name(kx);
1690*a1157835SDaniel Fojt if (!kx_str)
1691*a1157835SDaniel Fojt kx_str = "";
1692*a1157835SDaniel Fojt
1693*a1157835SDaniel Fojt mac = gnutls_mac_get(conn->session);
1694*a1157835SDaniel Fojt mac_str = gnutls_mac_get_name(mac);
1695*a1157835SDaniel Fojt if (!mac_str)
1696*a1157835SDaniel Fojt mac_str = "";
1697*a1157835SDaniel Fojt
1698*a1157835SDaniel Fojt if (kx == GNUTLS_KX_RSA)
1699*a1157835SDaniel Fojt res = os_snprintf(buf, buflen, "%s-%s", cipher_str, mac_str);
1700*a1157835SDaniel Fojt else
1701*a1157835SDaniel Fojt res = os_snprintf(buf, buflen, "%s-%s-%s",
1702*a1157835SDaniel Fojt kx_str, cipher_str, mac_str);
1703*a1157835SDaniel Fojt if (os_snprintf_error(buflen, res))
1704*a1157835SDaniel Fojt return -1;
1705*a1157835SDaniel Fojt
17066d49e1aeSJan Lentfer return 0;
17076d49e1aeSJan Lentfer }
17086d49e1aeSJan Lentfer
17096d49e1aeSJan Lentfer
tls_connection_enable_workaround(void * ssl_ctx,struct tls_connection * conn)17106d49e1aeSJan Lentfer int tls_connection_enable_workaround(void *ssl_ctx,
17116d49e1aeSJan Lentfer struct tls_connection *conn)
17126d49e1aeSJan Lentfer {
17133ff40c12SJohn Marino gnutls_record_disable_padding(conn->session);
17146d49e1aeSJan Lentfer return 0;
17156d49e1aeSJan Lentfer }
17166d49e1aeSJan Lentfer
17176d49e1aeSJan Lentfer
tls_connection_client_hello_ext(void * ssl_ctx,struct tls_connection * conn,int ext_type,const u8 * data,size_t data_len)17186d49e1aeSJan Lentfer int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
17196d49e1aeSJan Lentfer int ext_type, const u8 *data,
17206d49e1aeSJan Lentfer size_t data_len)
17216d49e1aeSJan Lentfer {
17226d49e1aeSJan Lentfer /* TODO */
17236d49e1aeSJan Lentfer return -1;
17246d49e1aeSJan Lentfer }
17256d49e1aeSJan Lentfer
17266d49e1aeSJan Lentfer
tls_connection_get_failed(void * ssl_ctx,struct tls_connection * conn)17276d49e1aeSJan Lentfer int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
17286d49e1aeSJan Lentfer {
17296d49e1aeSJan Lentfer if (conn == NULL)
17306d49e1aeSJan Lentfer return -1;
17316d49e1aeSJan Lentfer return conn->failed;
17326d49e1aeSJan Lentfer }
17336d49e1aeSJan Lentfer
17346d49e1aeSJan Lentfer
tls_connection_get_read_alerts(void * ssl_ctx,struct tls_connection * conn)17356d49e1aeSJan Lentfer int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
17366d49e1aeSJan Lentfer {
17376d49e1aeSJan Lentfer if (conn == NULL)
17386d49e1aeSJan Lentfer return -1;
17396d49e1aeSJan Lentfer return conn->read_alerts;
17406d49e1aeSJan Lentfer }
17416d49e1aeSJan Lentfer
17426d49e1aeSJan Lentfer
tls_connection_get_write_alerts(void * ssl_ctx,struct tls_connection * conn)17436d49e1aeSJan Lentfer int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
17446d49e1aeSJan Lentfer {
17456d49e1aeSJan Lentfer if (conn == NULL)
17466d49e1aeSJan Lentfer return -1;
17476d49e1aeSJan Lentfer return conn->write_alerts;
17486d49e1aeSJan Lentfer }
17496d49e1aeSJan Lentfer
17506d49e1aeSJan Lentfer
tls_connection_set_session_ticket_cb(void * tls_ctx,struct tls_connection * conn,tls_session_ticket_cb cb,void * ctx)17513ff40c12SJohn Marino int tls_connection_set_session_ticket_cb(void *tls_ctx,
17526d49e1aeSJan Lentfer struct tls_connection *conn,
17533ff40c12SJohn Marino tls_session_ticket_cb cb, void *ctx)
17546d49e1aeSJan Lentfer {
17556d49e1aeSJan Lentfer return -1;
17566d49e1aeSJan Lentfer }
1757*a1157835SDaniel Fojt
1758*a1157835SDaniel Fojt
tls_get_library_version(char * buf,size_t buf_len)1759*a1157835SDaniel Fojt int tls_get_library_version(char *buf, size_t buf_len)
1760*a1157835SDaniel Fojt {
1761*a1157835SDaniel Fojt return os_snprintf(buf, buf_len, "GnuTLS build=%s run=%s",
1762*a1157835SDaniel Fojt GNUTLS_VERSION, gnutls_check_version(NULL));
1763*a1157835SDaniel Fojt }
1764*a1157835SDaniel Fojt
1765*a1157835SDaniel Fojt
tls_connection_set_success_data(struct tls_connection * conn,struct wpabuf * data)1766*a1157835SDaniel Fojt void tls_connection_set_success_data(struct tls_connection *conn,
1767*a1157835SDaniel Fojt struct wpabuf *data)
1768*a1157835SDaniel Fojt {
1769*a1157835SDaniel Fojt }
1770*a1157835SDaniel Fojt
1771*a1157835SDaniel Fojt
tls_connection_set_success_data_resumed(struct tls_connection * conn)1772*a1157835SDaniel Fojt void tls_connection_set_success_data_resumed(struct tls_connection *conn)
1773*a1157835SDaniel Fojt {
1774*a1157835SDaniel Fojt }
1775*a1157835SDaniel Fojt
1776*a1157835SDaniel Fojt
1777*a1157835SDaniel Fojt const struct wpabuf *
tls_connection_get_success_data(struct tls_connection * conn)1778*a1157835SDaniel Fojt tls_connection_get_success_data(struct tls_connection *conn)
1779*a1157835SDaniel Fojt {
1780*a1157835SDaniel Fojt return NULL;
1781*a1157835SDaniel Fojt }
1782*a1157835SDaniel Fojt
1783*a1157835SDaniel Fojt
tls_connection_remove_session(struct tls_connection * conn)1784*a1157835SDaniel Fojt void tls_connection_remove_session(struct tls_connection *conn)
1785*a1157835SDaniel Fojt {
1786*a1157835SDaniel Fojt }
1787