tls_gnutls.c revision af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SSL/TLS interface functions for GnuTLS 31f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <gnutls/gnutls.h> 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <gnutls/x509.h> 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PKCS12_FUNCS 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <gnutls/pkcs12.h> 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* PKCS12_FUNCS */ 15ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#if GNUTLS_VERSION_NUMBER >= 0x030103 16ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#include <gnutls/ocsp.h> 17ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#endif /* 3.1.3 */ 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 20ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#include "crypto/crypto.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tls.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_gnutls_ref_count = 0; 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct tls_global { 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Data for session resumption */ 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *session_data; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t session_data_size; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int server; 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int params_set; 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_credentials_t xcred; 35ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 36ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt void (*event_cb)(void *ctx, enum tls_event ev, 37ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt union tls_event_data *data); 38ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt void *cb_ctx; 39ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt int cert_in_cb; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct tls_connection { 43ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt struct tls_global *global; 446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt gnutls_session_t session; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int read_alerts, write_alerts, failed; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pre_shared_secret; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t pre_shared_secret_len; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int established; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int verify_peer; 51ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt unsigned int disable_time_checks:1; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *push_buf; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *pull_buf; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pull_buf_offset; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int params_set; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_credentials_t xcred; 59ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 60ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt char *suffix_match; 612f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt char *domain_match; 62ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt unsigned int flags; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 66ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidtstatic int tls_connection_verify_peer(gnutls_session_t session); 67ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 68ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void tls_log_func(int level, const char *msg) 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *s, *pos; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (level == 6 || level == 7) { 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* These levels seem to be mostly I/O debug and msg dumps */ 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = os_strdup(msg); 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (s == NULL) 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = s; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*pos != '\0') { 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos == '\n') { 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos = '\0'; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG, 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "gnutls<%d> %s", level, s); 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(s); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * tls_init(const struct tls_config *conf) 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_global *global; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 99ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (tls_gnutls_ref_count == 0) { 100ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, 101ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "GnuTLS: Library version %s (runtime) - %s (build)", 102ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_check_version(NULL), GNUTLS_VERSION); 103ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global = os_zalloc(sizeof(*global)); 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global == NULL) 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) { 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(global); 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_gnutls_ref_count++; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_global_set_log_function(tls_log_func); 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_debug_show_keys) 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_global_set_log_level(11); 118ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 119ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (conf) { 120ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt global->event_cb = conf->event_cb; 121ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt global->cb_ctx = conf->cb_ctx; 122ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt global->cert_in_cb = conf->cert_in_cb; 123ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 124ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return global; 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tls_deinit(void *ssl_ctx) 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_global *global = ssl_ctx; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global) { 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global->params_set) 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_free_credentials(global->xcred); 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(global->session_data); 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(global); 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_gnutls_ref_count--; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_gnutls_ref_count == 0) 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_global_deinit(); 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_get_errors(void *ssl_ctx) 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic ssize_t tls_pull_func(gnutls_transport_ptr_t ptr, void *buf, 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len) 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn = (struct tls_connection *) ptr; 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *end; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf == NULL) { 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt errno = EWOULDBLOCK; 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = wpabuf_head_u8(conn->pull_buf) + wpabuf_len(conn->pull_buf); 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((size_t) (end - conn->pull_buf_offset) < len) 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = end - conn->pull_buf_offset; 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, conn->pull_buf_offset, len); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf_offset += len; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf_offset == end) { 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__); 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(conn->pull_buf); 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf = NULL; 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf_offset = NULL; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf", 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) (end - conn->pull_buf_offset)); 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic ssize_t tls_push_func(gnutls_transport_ptr_t ptr, const void *buf, 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len) 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn = (struct tls_connection *) ptr; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_resize(&conn->push_buf, len) < 0) { 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt errno = ENOMEM; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(conn->push_buf, buf, len); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_gnutls_init_session(struct tls_global *global, 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn) 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const char *err; 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_init(&conn->session, 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->server ? GNUTLS_SERVER : GNUTLS_CLIENT); 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS " 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "connection: %s", gnutls_strerror(ret)); 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_set_default_priority(conn->session); 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret = gnutls_priority_set_direct(conn->session, "NORMAL:-VERS-SSL3.0", 2141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt &err); 2151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ret < 0) { 2161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_ERROR, "GnuTLS: Priority string failure at " 2171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "'%s'", err); 2181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 2191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_transport_set_pull_function(conn->session, tls_pull_func); 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_transport_set_push_function(conn->session, tls_push_func); 2236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr_t) conn); 224ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_session_set_ptr(conn->session, conn); 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s", 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_strerror(ret)); 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_deinit(conn->session); 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct tls_connection * tls_connection_init(void *ssl_ctx) 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_global *global = ssl_ctx; 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn; 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn = os_zalloc(sizeof(*conn)); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL) 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 245ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->global = global; 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_gnutls_init_session(global, conn)) { 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn); 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global->params_set) { 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_credentials_set(conn->session, 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GNUTLS_CRD_CERTIFICATE, 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->xcred); 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "Failed to configure " 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "credentials: %s", gnutls_strerror(ret)); 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn); 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gnutls_certificate_allocate_credentials(&conn->xcred)) { 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn); 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return conn; 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL) 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_free_credentials(conn->xcred); 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_deinit(conn->session); 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->pre_shared_secret); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(conn->push_buf); 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(conn->pull_buf); 283ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt os_free(conn->suffix_match); 2842f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt os_free(conn->domain_match); 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn); 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_established(void *ssl_ctx, struct tls_connection *conn) 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return conn ? conn->established : 0; 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn) 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_global *global = ssl_ctx; 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL) 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Shutdown previous TLS connection without notifying the peer 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * because the connection was already terminated in practice 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * and "close notify" shutdown alert would confuse AS. */ 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_bye(conn->session, GNUTLS_SHUT_RDWR); 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(conn->push_buf); 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->push_buf = NULL; 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->established = 0; 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_deinit(conn->session); 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_gnutls_init_session(global, conn)) { 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session " 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for session resumption use"); 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->params_set ? conn->xcred : 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->xcred); 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials " 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for session resumption: %s", gnutls_strerror(ret)); 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global->session_data) { 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_session_set_data(conn->session, 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->session_data, 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->session_data_size); 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "GnuTLS: Failed to set session " 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data: %s", gnutls_strerror(ret)); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct tls_connection_params *params) 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL || params == NULL) 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->subject_match) { 351ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_INFO, "GnuTLS: subject_match not supported"); 352ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return -1; 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->altsubject_match) { 356ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_INFO, "GnuTLS: altsubject_match not supported"); 357ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return -1; 358ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 359ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 360ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt os_free(conn->suffix_match); 361ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->suffix_match = NULL; 362ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (params->suffix_match) { 363ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->suffix_match = os_strdup(params->suffix_match); 364ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (conn->suffix_match == NULL) 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3682f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt#if GNUTLS_VERSION_NUMBER >= 0x030300 3692f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt os_free(conn->domain_match); 3702f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt conn->domain_match = NULL; 3712f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (params->domain_match) { 3722f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt conn->domain_match = os_strdup(params->domain_match); 3732f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (conn->domain_match == NULL) 3742f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt return -1; 3752f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt } 3762f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt#else /* < 3.3.0 */ 3772f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (params->domain_match) { 3782f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt wpa_printf(MSG_INFO, "GnuTLS: domain_match not supported"); 3792f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt return -1; 3802f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt } 3812f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt#endif /* >= 3.3.0 */ 3822f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 383ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->flags = params->flags; 384ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 385ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (params->openssl_ciphers) { 386ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_INFO, "GnuTLS: openssl_ciphers not supported"); 387ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return -1; 388ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 389ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: gnutls_certificate_set_verify_flags(xcred, flags); 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to force peer validation(?) */ 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->ca_cert) { 394ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, "GnuTLS: Try to parse %s in DER format", 395ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt params->ca_cert); 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_trust_file( 397ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->xcred, params->ca_cert, GNUTLS_X509_FMT_DER); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 399ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, 400ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "GnuTLS: Failed to read CA cert '%s' in DER format (%s) - try in PEM format", 401ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt params->ca_cert, 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_strerror(ret)); 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_trust_file( 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->xcred, params->ca_cert, 405ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt GNUTLS_X509_FMT_PEM); 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 407ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, 408ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "Failed to read CA cert '%s' in PEM format: %s", 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ca_cert, 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_strerror(ret)); 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 414ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } else if (params->ca_cert_blob) { 415ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_datum_t ca; 416ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 417ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ca.data = (unsigned char *) params->ca_cert_blob; 418ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ca.size = params->ca_cert_blob_len; 419ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 420ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ret = gnutls_certificate_set_x509_trust_mem( 421ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->xcred, &ca, GNUTLS_X509_FMT_DER); 422ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (ret < 0) { 423ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, 424ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "Failed to parse CA cert in DER format: %s", 425ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_strerror(ret)); 426ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ret = gnutls_certificate_set_x509_trust_mem( 427ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->xcred, &ca, GNUTLS_X509_FMT_PEM); 428ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (ret < 0) { 429ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, 430ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "Failed to parse CA cert in PEM format: %s", 431ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_strerror(ret)); 432ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return -1; 433ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 434ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 435ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } else if (params->ca_path) { 436ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_INFO, "GnuTLS: ca_path not supported"); 437ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return -1; 438ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 439ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 440ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->disable_time_checks = 0; 441ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (params->ca_cert || params->ca_cert_blob) { 442ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->verify_peer = 1; 443ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_certificate_set_verify_function( 444ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->xcred, tls_connection_verify_peer); 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) { 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_set_verify_flags( 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) { 452ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->disable_time_checks = 1; 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_set_verify_flags( 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->xcred, 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GNUTLS_VERIFY_DISABLE_TIME_CHECKS); 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->client_cert && params->private_key) { 4606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#if GNUTLS_VERSION_NUMBER >= 0x03010b 4616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = gnutls_certificate_set_x509_key_file2( 4626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt conn->xcred, params->client_cert, params->private_key, 463ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt GNUTLS_X509_FMT_DER, params->private_key_passwd, 0); 4646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#else 4656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* private_key_passwd not (easily) supported here */ 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_key_file( 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->xcred, params->client_cert, params->private_key, 468ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt GNUTLS_X509_FMT_DER); 4696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to read client cert/key " 472ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "in DER format: %s", gnutls_strerror(ret)); 4736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#if GNUTLS_VERSION_NUMBER >= 0x03010b 4746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = gnutls_certificate_set_x509_key_file2( 4756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt conn->xcred, params->client_cert, 476ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt params->private_key, GNUTLS_X509_FMT_PEM, 4776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->private_key_passwd, 0); 4786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#else 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_key_file( 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->xcred, params->client_cert, 481ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt params->private_key, GNUTLS_X509_FMT_PEM); 4826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to read client " 485ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "cert/key in PEM format: %s", 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_strerror(ret)); 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (params->private_key) { 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pkcs12_ok = 0; 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PKCS12_FUNCS 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Try to load in PKCS#12 format */ 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_simple_pkcs12_file( 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->xcred, params->private_key, GNUTLS_X509_FMT_DER, 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->private_key_passwd); 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret != 0) { 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to load private_key in " 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PKCS#12 format: %s", gnutls_strerror(ret)); 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pkcs12_ok = 1; 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* PKCS12_FUNCS */ 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!pkcs12_ok) { 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not " 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "included"); 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 510ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } else if (params->client_cert_blob && params->private_key_blob) { 511ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_datum_t cert, key; 512ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 513ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt cert.data = (unsigned char *) params->client_cert_blob; 514ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt cert.size = params->client_cert_blob_len; 515ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt key.data = (unsigned char *) params->private_key_blob; 516ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt key.size = params->private_key_blob_len; 517ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 518ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#if GNUTLS_VERSION_NUMBER >= 0x03010b 519ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ret = gnutls_certificate_set_x509_key_mem2( 520ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER, 521ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt params->private_key_passwd, 0); 522ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#else 523ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt /* private_key_passwd not (easily) supported here */ 524ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ret = gnutls_certificate_set_x509_key_mem( 525ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER); 526ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#endif 527ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (ret < 0) { 528ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to read client cert/key " 529ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "in DER format: %s", gnutls_strerror(ret)); 530ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#if GNUTLS_VERSION_NUMBER >= 0x03010b 531ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ret = gnutls_certificate_set_x509_key_mem2( 532ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM, 533ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt params->private_key_passwd, 0); 534ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#else 535ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt /* private_key_passwd not (easily) supported here */ 536ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ret = gnutls_certificate_set_x509_key_mem( 537ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM); 538ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#endif 539ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (ret < 0) { 540ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to read client " 541ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "cert/key in PEM format: %s", 542ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_strerror(ret)); 543ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return ret; 544ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 545ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 546ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } else if (params->private_key_blob) { 547ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#ifdef PKCS12_FUNCS 548ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_datum_t key; 549ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 550ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt key.data = (unsigned char *) params->private_key_blob; 551ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt key.size = params->private_key_blob_len; 552ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 553ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt /* Try to load in PKCS#12 format */ 554ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ret = gnutls_certificate_set_x509_simple_pkcs12_mem( 555ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->xcred, &key, GNUTLS_X509_FMT_DER, 556ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt params->private_key_passwd); 557ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (ret != 0) { 558ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to load private_key in " 559ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "PKCS#12 format: %s", gnutls_strerror(ret)); 560ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return -1; 561ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 562ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#else /* PKCS12_FUNCS */ 563ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not included"); 564ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return -1; 565ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#endif /* PKCS12_FUNCS */ 566ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 567ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 568ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#if GNUTLS_VERSION_NUMBER >= 0x030103 569ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (params->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)) { 570ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ret = gnutls_ocsp_status_request_enable_client(conn->session, 571ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt NULL, 0, NULL); 572ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (ret != GNUTLS_E_SUCCESS) { 573ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_INFO, 574ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "GnuTLS: Failed to enable OCSP client"); 575ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return -1; 576ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 577ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 578ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#else /* 3.1.3 */ 579ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (params->flags & TLS_CONN_REQUIRE_OCSP) { 580ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_INFO, 581ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "GnuTLS: OCSP not supported by this version of GnuTLS"); 582ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return -1; 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 584ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#endif /* 3.1.3 */ 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->params_set = 1; 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->xcred); 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "Failed to configure credentials: %s", 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_strerror(ret)); 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_global_set_params(void *tls_ctx, 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct tls_connection_params *params) 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_global *global = tls_ctx; 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Currently, global parameters are only set when running in server 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * mode. */ 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->server = 1; 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global->params_set) { 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_free_credentials(global->xcred); 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->params_set = 0; 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_allocate_credentials(&global->xcred); 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to allocate global credentials " 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%s", gnutls_strerror(ret)); 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->ca_cert) { 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_trust_file( 623ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt global->xcred, params->ca_cert, GNUTLS_X509_FMT_DER); 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' " 626ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "in DER format: %s", params->ca_cert, 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_strerror(ret)); 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_trust_file( 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->xcred, params->ca_cert, 630ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt GNUTLS_X509_FMT_PEM); 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to read CA cert " 633ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "'%s' in PEM format: %s", 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ca_cert, 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_strerror(ret)); 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) { 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_set_verify_flags( 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->xcred, 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) { 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_set_verify_flags( 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->xcred, 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GNUTLS_VERIFY_DISABLE_TIME_CHECKS); 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->client_cert && params->private_key) { 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: private_key_passwd? */ 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_key_file( 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->xcred, params->client_cert, 657ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt params->private_key, GNUTLS_X509_FMT_DER); 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to read client cert/key " 660ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "in DER format: %s", gnutls_strerror(ret)); 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_key_file( 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->xcred, params->client_cert, 663ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt params->private_key, GNUTLS_X509_FMT_PEM); 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to read client " 666ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "cert/key in PEM format: %s", 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_strerror(ret)); 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (params->private_key) { 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pkcs12_ok = 0; 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PKCS12_FUNCS 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Try to load in PKCS#12 format */ 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_simple_pkcs12_file( 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->xcred, params->private_key, 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GNUTLS_X509_FMT_DER, params->private_key_passwd); 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret != 0) { 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to load private_key in " 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PKCS#12 format: %s", gnutls_strerror(ret)); 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pkcs12_ok = 1; 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* PKCS12_FUNCS */ 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!pkcs12_ok) { 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not " 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "included"); 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->params_set = 1; 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_free_credentials(global->xcred); 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_global_set_verify(void *ssl_ctx, int check_crl) 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO */ 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int verify_peer) 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL || conn->session == NULL) 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->verify_peer = verify_peer; 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_server_set_request(conn->session, 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt verify_peer ? GNUTLS_CERT_REQUIRE 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt : GNUTLS_CERT_REQUEST); 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_keys *keys) 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 728ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#if GNUTLS_VERSION_NUMBER >= 0x030012 729ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_datum_t client, server; 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL || conn->session == NULL || keys == NULL) 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(keys, 0, sizeof(*keys)); 735ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_session_get_random(conn->session, &client, &server); 736ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt keys->client_random = client.data; 737ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt keys->server_random = server.data; 738ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt keys->client_random_len = client.size; 739ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt keys->server_random_len = client.size; 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 742ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#else /* 3.0.18 */ 743ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return -1; 744ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#endif /* 3.0.18 */ 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_prf(void *tls_ctx, struct tls_connection *conn, 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *label, int server_random_first, 750af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt int skip_keyblock, u8 *out, size_t out_len) 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 752af9da3180dc20f57df1fc1e1811f3df9fa9e6ab5Dmitry Shmidt if (conn == NULL || conn->session == NULL || skip_keyblock) 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return gnutls_prf(conn->session, os_strlen(label), label, 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt server_random_first, 0, NULL, out_len, (char *) out); 757ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt} 758ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 759ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 760ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidtstatic void gnutls_tls_fail_event(struct tls_connection *conn, 761ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt const gnutls_datum_t *cert, int depth, 762ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt const char *subject, const char *err_str, 763ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt enum tls_fail_reason reason) 764ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt{ 765ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt union tls_event_data ev; 766ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt struct tls_global *global = conn->global; 767ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt struct wpabuf *cert_buf = NULL; 768ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 769ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (global->event_cb == NULL) 770ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return; 771ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 772ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt os_memset(&ev, 0, sizeof(ev)); 773ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ev.cert_fail.depth = depth; 774ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ev.cert_fail.subject = subject ? subject : ""; 775ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ev.cert_fail.reason = reason; 776ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ev.cert_fail.reason_txt = err_str; 777ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (cert) { 778ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt cert_buf = wpabuf_alloc_copy(cert->data, cert->size); 779ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ev.cert_fail.cert = cert_buf; 780ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 781ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt global->event_cb(global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev); 782ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpabuf_free(cert_buf); 783ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt} 784ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 785ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 786ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#if GNUTLS_VERSION_NUMBER < 0x030300 787ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidtstatic int server_eku_purpose(gnutls_x509_crt_t cert) 788ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt{ 789ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt unsigned int i; 790ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 791ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt for (i = 0; ; i++) { 792ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt char oid[128]; 793ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt size_t oid_size = sizeof(oid); 794ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt int res; 795ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 796ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt res = gnutls_x509_crt_get_key_purpose_oid(cert, i, oid, 797ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt &oid_size, NULL); 798ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (res == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { 799ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (i == 0) { 800ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt /* No EKU - assume any use allowed */ 801ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return 1; 802ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 803ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt break; 804ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 805ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 806ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (res < 0) { 807ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_INFO, "GnuTLS: Failed to get EKU"); 808ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return 0; 809ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 810ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 811ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, "GnuTLS: Certificate purpose: %s", oid); 812ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (os_strcmp(oid, GNUTLS_KP_TLS_WWW_SERVER) == 0 || 813ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt os_strcmp(oid, GNUTLS_KP_ANY) == 0) 814ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return 1; 815ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 816ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 817ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return 0; 818ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt} 819ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#endif /* < 3.3.0 */ 820ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 821ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 822ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidtstatic int check_ocsp(struct tls_connection *conn, gnutls_session_t session, 823ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_alert_description_t *err) 824ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt{ 825ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#if GNUTLS_VERSION_NUMBER >= 0x030103 826ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_datum_t response, buf; 827ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_ocsp_resp_t resp; 828ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt unsigned int cert_status; 829ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt int res; 830ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 831ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (!(conn->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP))) 832ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return 0; 833ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 834ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (!gnutls_ocsp_status_request_is_checked(session, 0)) { 835ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (conn->flags & TLS_CONN_REQUIRE_OCSP) { 836ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_INFO, 837ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "GnuTLS: No valid OCSP response received"); 838ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto ocsp_error; 839ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 840ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 841ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, 842ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "GnuTLS: Valid OCSP response was not received - continue since OCSP was not required"); 843ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return 0; 844ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 845ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 846ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt /* 847ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt * GnuTLS has already verified the OCSP response in 848ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt * check_ocsp_response() and rejected handshake if the certificate was 849ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt * found to be revoked. However, if the response indicates that the 850ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt * status is unknown, handshake continues and reaches here. We need to 851ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt * re-import the OCSP response to check for unknown certificate status, 852ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt * but we do not need to repeat gnutls_ocsp_resp_check_crt() and 853ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt * gnutls_ocsp_resp_verify_direct() calls. 854ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt */ 855ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 856ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt res = gnutls_ocsp_status_request_get(session, &response); 857ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (res != GNUTLS_E_SUCCESS) { 858ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_INFO, 859ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "GnuTLS: OCSP response was received, but it was not valid"); 860ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto ocsp_error; 861ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 862ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 863ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (gnutls_ocsp_resp_init(&resp) != GNUTLS_E_SUCCESS) 864ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto ocsp_error; 865ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 866ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt res = gnutls_ocsp_resp_import(resp, &response); 867ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (res != GNUTLS_E_SUCCESS) { 868ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_INFO, 869ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "GnuTLS: Could not parse received OCSP response: %s", 870ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_strerror(res)); 871ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_ocsp_resp_deinit(resp); 872ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto ocsp_error; 873ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 874ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 875ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt res = gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &buf); 876ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (res == GNUTLS_E_SUCCESS) { 877ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, "GnuTLS: %s", buf.data); 878ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_free(buf.data); 879ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 880ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 881ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt res = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL, 882ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt NULL, &cert_status, NULL, 883ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt NULL, NULL, NULL); 884ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_ocsp_resp_deinit(resp); 885ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (res != GNUTLS_E_SUCCESS) { 886ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_INFO, 887ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "GnuTLS: Failed to extract OCSP information: %s", 888ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_strerror(res)); 889ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto ocsp_error; 890ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 891ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 892ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (cert_status == GNUTLS_OCSP_CERT_GOOD) { 893ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, "GnuTLS: OCSP cert status: good"); 894ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } else if (cert_status == GNUTLS_OCSP_CERT_REVOKED) { 895ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, 896ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "GnuTLS: OCSP cert status: revoked"); 897ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto ocsp_error; 898ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } else { 899ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, 900ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "GnuTLS: OCSP cert status: unknown"); 901ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (conn->flags & TLS_CONN_REQUIRE_OCSP) 902ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto ocsp_error; 903ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, 904ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "GnuTLS: OCSP was not required, so allow connection to continue"); 905ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 906ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 907ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return 0; 908ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 909ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidtocsp_error: 910ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_tls_fail_event(conn, NULL, 0, NULL, 911ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "bad certificate status response", 912ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt TLS_FAIL_REVOKED); 913ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt *err = GNUTLS_A_CERTIFICATE_REVOKED; 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 915ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#else /* GnuTLS 3.1.3 or newer */ 916ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return 0; 917ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#endif /* GnuTLS 3.1.3 or newer */ 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 921ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidtstatic int tls_connection_verify_peer(gnutls_session_t session) 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 923ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt struct tls_connection *conn; 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int status, num_certs, i; 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct os_time now; 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const gnutls_datum_t *certs; 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_x509_crt_t cert; 928ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_alert_description_t err; 929ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt int res; 930ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 931ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn = gnutls_session_get_ptr(session); 932ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (!conn->verify_peer) { 933ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, 934ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "GnuTLS: No peer certificate verification enabled"); 935ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return 0; 936ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 937ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 938ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, "GnuTSL: Verifying peer certificate"); 939ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 940ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#if GNUTLS_VERSION_NUMBER >= 0x030300 941ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt { 942ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_typed_vdata_st data[1]; 943ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt unsigned int elements = 0; 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 945ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt os_memset(data, 0, sizeof(data)); 946ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (!conn->global->server) { 947ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt data[elements].type = GNUTLS_DT_KEY_PURPOSE_OID; 948ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt data[elements].data = (void *) GNUTLS_KP_TLS_WWW_SERVER; 949ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt elements++; 950ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 951ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt res = gnutls_certificate_verify_peers(session, data, 1, 952ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt &status); 953ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 954ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#else /* < 3.3.0 */ 955ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt res = gnutls_certificate_verify_peers2(session, &status); 956ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#endif 957ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (res < 0) { 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Failed to verify peer " 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "certificate chain"); 960ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt err = GNUTLS_A_INTERNAL_ERROR; 961ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto out; 962ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 963ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 964ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#if GNUTLS_VERSION_NUMBER >= 0x030104 965ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt { 966ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_datum_t info; 967ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt int ret, type; 968ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 969ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt type = gnutls_certificate_type_get(session); 970ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ret = gnutls_certificate_verification_status_print(status, type, 971ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt &info, 0); 972ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (ret < 0) { 973ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, 974ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "GnuTLS: Failed to print verification status"); 975ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt err = GNUTLS_A_INTERNAL_ERROR; 976ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto out; 977ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 978ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, "GnuTLS: %s", info.data); 979ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_free(info.data); 980ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 981ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#endif /* GnuTLS 3.1.4 or newer */ 982ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 983ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt certs = gnutls_certificate_get_peers(session, &num_certs); 984ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (certs == NULL || num_certs == 0) { 985ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_INFO, "TLS: No peer certificate chain received"); 986ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt err = GNUTLS_A_UNKNOWN_CA; 987ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto out; 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) { 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted"); 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Certificate uses insecure " 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "algorithm"); 995ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_tls_fail_event(conn, NULL, 0, NULL, 996ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "certificate uses insecure algorithm", 997ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt TLS_FAIL_BAD_CERTIFICATE); 998ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt err = GNUTLS_A_INSUFFICIENT_SECURITY; 999ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto out; 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status & GNUTLS_CERT_NOT_ACTIVATED) { 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Certificate not yet " 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "activated"); 1004ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_tls_fail_event(conn, NULL, 0, NULL, 1005ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "certificate not yet valid", 1006ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt TLS_FAIL_NOT_YET_VALID); 1007ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt err = GNUTLS_A_CERTIFICATE_EXPIRED; 1008ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto out; 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status & GNUTLS_CERT_EXPIRED) { 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Certificate expired"); 1012ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_tls_fail_event(conn, NULL, 0, NULL, 1013ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "certificate has expired", 1014ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt TLS_FAIL_EXPIRED); 1015ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt err = GNUTLS_A_CERTIFICATE_EXPIRED; 1016ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto out; 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1018ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_tls_fail_event(conn, NULL, 0, NULL, 1019ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "untrusted certificate", 1020ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt TLS_FAIL_UNTRUSTED); 1021ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt err = GNUTLS_A_INTERNAL_ERROR; 1022ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto out; 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a " 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "known issuer"); 1028ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_tls_fail_event(conn, NULL, 0, NULL, "signed not found", 1029ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt TLS_FAIL_UNTRUSTED); 1030ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt err = GNUTLS_A_UNKNOWN_CA; 1031ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto out; 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status & GNUTLS_CERT_REVOKED) { 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked"); 1036ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_tls_fail_event(conn, NULL, 0, NULL, 1037ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "certificate revoked", 1038ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt TLS_FAIL_REVOKED); 1039ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt err = GNUTLS_A_CERTIFICATE_REVOKED; 1040ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto out; 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1043ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (status != 0) { 1044ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_INFO, "TLS: Unknown verification status: %d", 1045ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt status); 1046ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt err = GNUTLS_A_INTERNAL_ERROR; 1047ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto out; 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1050ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (check_ocsp(conn, session, &err)) 1051ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto out; 1052ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 1053ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt os_get_time(&now); 1054ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < num_certs; i++) { 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf; 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gnutls_x509_crt_init(&cert) < 0) { 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Certificate initialization " 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed"); 1061ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt err = GNUTLS_A_BAD_CERTIFICATE; 1062ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto out; 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gnutls_x509_crt_import(cert, &certs[i], 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GNUTLS_X509_FMT_DER) < 0) { 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Could not parse peer " 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "certificate %d/%d", i + 1, num_certs); 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_x509_crt_deinit(cert); 1070ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt err = GNUTLS_A_BAD_CERTIFICATE; 1071ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto out; 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_x509_crt_get_dn(cert, NULL, &len); 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len++; 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(len + 1); 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf) { 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[0] = buf[len] = '\0'; 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_x509_crt_get_dn(cert, buf, &len); 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s", 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i + 1, num_certs, buf); 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1084ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (conn->global->event_cb) { 1085ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt struct wpabuf *cert_buf = NULL; 1086ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt union tls_event_data ev; 1087ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#ifdef CONFIG_SHA256 1088ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt u8 hash[32]; 1089ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt const u8 *_addr[1]; 1090ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt size_t _len[1]; 1091ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#endif /* CONFIG_SHA256 */ 1092ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 1093ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt os_memset(&ev, 0, sizeof(ev)); 1094ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (conn->global->cert_in_cb) { 1095ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt cert_buf = wpabuf_alloc_copy(certs[i].data, 1096ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt certs[i].size); 1097ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ev.peer_cert.cert = cert_buf; 1098ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 1099ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#ifdef CONFIG_SHA256 1100ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt _addr[0] = certs[i].data; 1101ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt _len[0] = certs[i].size; 1102ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (sha256_vector(1, _addr, _len, hash) == 0) { 1103ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ev.peer_cert.hash = hash; 1104ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ev.peer_cert.hash_len = sizeof(hash); 1105ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 1106ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#endif /* CONFIG_SHA256 */ 1107ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ev.peer_cert.depth = i; 1108ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ev.peer_cert.subject = buf; 1109ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->global->event_cb(conn->global->cb_ctx, 1110ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt TLS_PEER_CERTIFICATE, &ev); 1111ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpabuf_free(cert_buf); 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1114ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (i == 0) { 1115ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (conn->suffix_match && 1116ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt !gnutls_x509_crt_check_hostname( 1117ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt cert, conn->suffix_match)) { 1118ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_WARNING, 1119ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "TLS: Domain suffix match '%s' not found", 1120ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->suffix_match); 1121ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_tls_fail_event( 1122ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn, &certs[i], i, buf, 1123ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "Domain suffix mismatch", 1124ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt TLS_FAIL_DOMAIN_SUFFIX_MISMATCH); 1125ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt err = GNUTLS_A_BAD_CERTIFICATE; 1126ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_x509_crt_deinit(cert); 1127ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt os_free(buf); 1128ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto out; 1129ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 1130ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 11312f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt#if GNUTLS_VERSION_NUMBER >= 0x030300 11322f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (conn->domain_match && 11332f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt !gnutls_x509_crt_check_hostname2( 11342f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt cert, conn->domain_match, 11352f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) { 11362f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt wpa_printf(MSG_WARNING, 11372f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt "TLS: Domain match '%s' not found", 11382f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt conn->domain_match); 11392f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt gnutls_tls_fail_event( 11402f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt conn, &certs[i], i, buf, 11412f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt "Domain mismatch", 11422f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt TLS_FAIL_DOMAIN_MISMATCH); 11432f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt err = GNUTLS_A_BAD_CERTIFICATE; 11442f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt gnutls_x509_crt_deinit(cert); 11452f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt os_free(buf); 11462f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt goto out; 11472f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt } 11482f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt#endif /* >= 3.3.0 */ 11492f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 1150ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt /* TODO: validate altsubject_match. 1151ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt * For now, any such configuration is rejected in 1152ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt * tls_connection_set_params() */ 1153ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 1154ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#if GNUTLS_VERSION_NUMBER < 0x030300 1155ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt /* 1156ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt * gnutls_certificate_verify_peers() not available, so 1157ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt * need to check EKU separately. 1158ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt */ 1159ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (!conn->global->server && 1160ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt !server_eku_purpose(cert)) { 1161ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_WARNING, 1162ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "GnuTLS: No server EKU"); 1163ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_tls_fail_event( 1164ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn, &certs[i], i, buf, 1165ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "No server EKU", 1166ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt TLS_FAIL_BAD_CERTIFICATE); 1167ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt err = GNUTLS_A_BAD_CERTIFICATE; 1168ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_x509_crt_deinit(cert); 1169ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt os_free(buf); 1170ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto out; 1171ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 1172ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#endif /* < 3.3.0 */ 1173ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1175ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (!conn->disable_time_checks && 1176ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt (gnutls_x509_crt_get_expiration_time(cert) < now.sec || 1177ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_x509_crt_get_activation_time(cert) > now.sec)) { 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is " 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not valid at this time", 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i + 1, num_certs); 1181ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_tls_fail_event( 1182ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn, &certs[i], i, buf, 1183ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "Certificate is not valid at this time", 1184ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt TLS_FAIL_EXPIRED); 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_x509_crt_deinit(cert); 1186ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt os_free(buf); 1187ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt err = GNUTLS_A_CERTIFICATE_EXPIRED; 1188ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt goto out; 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1191ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt os_free(buf); 1192ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_x509_crt_deinit(cert); 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1196ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (conn->global->event_cb != NULL) 1197ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->global->event_cb(conn->global->cb_ctx, 1198ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt TLS_CERT_CHAIN_SUCCESS, NULL); 1199ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1201ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 1202ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidtout: 1203ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->failed++; 1204ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_alert_send(session, GNUTLS_AL_FATAL, err); 1205ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return GNUTLS_E_CERTIFICATE_ERROR; 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn) 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *ad; 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data"); 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3); 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ad == NULL) 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = gnutls_record_recv(conn->session, wpabuf_mhead(ad), 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_size(ad)); 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res); 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 12221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d " 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s)", __func__, (int) res, 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_strerror(res)); 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(ad); 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(ad, res); 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data", 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res); 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ad; 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_handshake(void *tls_ctx, 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn, 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data, 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **appl_data) 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_global *global = tls_ctx; 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *out_data; 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (appl_data) 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *appl_data = NULL; 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (in_data && wpabuf_len(in_data) > 0) { 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf) { 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pull_buf", __func__, 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(conn->pull_buf)); 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(conn->pull_buf); 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf = wpabuf_dup(in_data); 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf == NULL) 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf_offset = wpabuf_head(conn->pull_buf); 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_handshake(conn->session); 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 1263ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_alert_description_t alert; 1264ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (ret) { 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case GNUTLS_E_AGAIN: 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global->server && conn->established && 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->push_buf == NULL) { 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Need to return something to trigger 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * completion of EAP-TLS. */ 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->push_buf = wpabuf_alloc(0); 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case GNUTLS_E_FATAL_ALERT_RECEIVED: 1275ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt alert = gnutls_alert_get(conn->session); 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert", 1277ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt __func__, gnutls_alert_get_name(alert)); 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->read_alerts++; 1279ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (conn->global->event_cb != NULL) { 1280ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt union tls_event_data ev; 1281ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 1282ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt os_memset(&ev, 0, sizeof(ev)); 1283ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ev.alert.is_local = 0; 1284ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ev.alert.type = gnutls_alert_get_name(alert); 1285ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ev.alert.description = ev.alert.type; 1286ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt conn->global->event_cb(conn->global->cb_ctx, 1287ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt TLS_ALERT, &ev); 1288ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* continue */ 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed " 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "-> %s", __func__, gnutls_strerror(ret)); 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->failed++; 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t size; 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1298ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully"); 1299ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 1300ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#if GNUTLS_VERSION_NUMBER >= 0x03010a 1301ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt { 1302ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt char *desc; 1303ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 1304ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt desc = gnutls_session_get_desc(conn->session); 1305ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (desc) { 1306ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, "GnuTLS: %s", desc); 1307ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt gnutls_free(desc); 1308ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1310ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#endif /* GnuTLS 3.1.10 or newer */ 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->established = 1; 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->push_buf == NULL) { 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Need to return something to get final TLS ACK. */ 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->push_buf = wpabuf_alloc(0); 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_session_get_data(conn->session, NULL, &size); 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global->session_data == NULL || 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->session_data_size < size) { 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(global->session_data); 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->session_data = os_malloc(size); 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global->session_data) { 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->session_data_size = size; 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_session_get_data(conn->session, 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->session_data, 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &global->session_data_size); 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf && appl_data) 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *appl_data = gnutls_get_appl_data(conn); 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out_data = conn->push_buf; 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->push_buf = NULL; 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return out_data; 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_server_handshake(void *tls_ctx, 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn, 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data, 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **appl_data) 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tls_connection_handshake(tls_ctx, conn, in_data, appl_data); 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_encrypt(void *tls_ctx, 13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn, 13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data) 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssize_t res; 13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = gnutls_record_send(conn->session, wpabuf_head(in_data), 13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(in_data)); 13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "%s: Encryption failed: %s", 13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, gnutls_strerror(res)); 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = conn->push_buf; 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->push_buf = NULL; 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_decrypt(void *tls_ctx, 13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn, 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data) 13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssize_t res; 13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *out; 13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf) { 13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " 13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pull_buf", __func__, 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(conn->pull_buf)); 13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(conn->pull_buf); 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf = wpabuf_dup(in_data); 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf == NULL) 13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf_offset = wpabuf_head(conn->pull_buf); 13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Even though we try to disable TLS compression, it is possible that 13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * this cannot be done with all TLS libraries. Add extra buffer space 13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to handle the possibility of the decrypted data being longer than 13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * input data. 13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (out == NULL) 13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = gnutls_record_recv(conn->session, wpabuf_mhead(out), 14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_size(out)); 14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d " 14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s)", __func__, (int) res, gnutls_strerror(res)); 14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(out); 14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(out, res); 14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return out; 14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) 14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL) 14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return gnutls_session_is_resumed(conn->session); 14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, 14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *ciphers) 14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO */ 14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, 14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf, size_t buflen) 14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO */ 14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[0] = '\0'; 14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_enable_workaround(void *ssl_ctx, 14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn) 14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_record_disable_padding(conn->session); 14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, 14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ext_type, const u8 *data, 14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t data_len) 14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO */ 14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) 14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL) 14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return conn->failed; 14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) 14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL) 14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return conn->read_alerts; 14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) 14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL) 14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return conn->write_alerts; 14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int tls_capabilities(void *tls_ctx) 14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_session_ticket_cb(void *tls_ctx, 14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn, 14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_session_ticket_cb cb, void *ctx) 14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1491ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 1492ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 1493ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidtint tls_get_library_version(char *buf, size_t buf_len) 1494ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt{ 1495ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return os_snprintf(buf, buf_len, "GnuTLS build=%s run=%s", 1496ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt GNUTLS_VERSION, gnutls_check_version(NULL)); 1497ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt} 1498