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