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 */ 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tls.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define WPA_TLS_RANDOM_SIZE 32 211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define WPA_TLS_MASTER_SIZE 48 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if LIBGNUTLS_VERSION_NUMBER < 0x010302 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* GnuTLS 1.3.2 added functions for using master secret. Older versions require 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * use of internal structures to get the master_secret and 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * {server,client}_random. 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define GNUTLS_INTERNAL_STRUCTURE_HACK 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */ 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * It looks like gnutls does not provide access to client/server_random and 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * master_key. This is somewhat unfortunate since these are needed for key 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * derivation in EAP-{TLS,TTLS,PEAP,FAST}. Workaround for now is a horrible 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hack that copies the gnutls_session_int definition from gnutls_int.h so that 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * we can get the needed information. 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef u8 uint8; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef unsigned char opaque; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct { 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uint8 suite[2]; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} cipher_suite_st; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidttypedef struct { 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_connection_end_t entity; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_kx_algorithm_t kx_algorithm; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_cipher_algorithm_t read_bulk_cipher_algorithm; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_mac_algorithm_t read_mac_algorithm; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_compression_method_t read_compression_algorithm; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_cipher_algorithm_t write_bulk_cipher_algorithm; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_mac_algorithm_t write_mac_algorithm; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_compression_method_t write_compression_algorithm; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher_suite_st current_cipher_suite; 581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt opaque master_secret[WPA_TLS_MASTER_SIZE]; 591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt opaque client_random[WPA_TLS_RANDOM_SIZE]; 601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt opaque server_random[WPA_TLS_RANDOM_SIZE]; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* followed by stuff we are not interested in */ 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} security_parameters_st; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct gnutls_session_int { 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt security_parameters_st security_parameters; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* followed by things we are not interested in */ 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */ 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_gnutls_ref_count = 0; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct tls_global { 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Data for session resumption */ 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *session_data; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t session_data_size; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int server; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int params_set; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_credentials_t xcred; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct tls_connection { 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_session session; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *subject_match, *altsubject_match; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int read_alerts, write_alerts, failed; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pre_shared_secret; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t pre_shared_secret_len; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int established; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int verify_peer; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *push_buf; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *pull_buf; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pull_buf_offset; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int params_set; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_credentials_t xcred; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void tls_log_func(int level, const char *msg) 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *s, *pos; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (level == 6 || level == 7) { 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* These levels seem to be mostly I/O debug and msg dumps */ 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s = os_strdup(msg); 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (s == NULL) 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = s; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*pos != '\0') { 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos == '\n') { 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos = '\0'; 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG, 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "gnutls<%d> %s", level, s); 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(s); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtextern int wpa_debug_show_keys; 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid * tls_init(const struct tls_config *conf) 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_global *global; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Because of the horrible hack to get master_secret and client/server 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * random, we need to make sure that the gnutls version is something 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * that is expected to have same structure definition for the session 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * data.. */ 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *ver; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *ok_ver[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", "1.2.9", 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "1.3.2", 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL }; 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global = os_zalloc(sizeof(*global)); 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global == NULL) 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) { 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(global); 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_gnutls_ref_count++; 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = gnutls_check_version(NULL); 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ver == NULL) { 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_deinit(global); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s - gnutls version %s", __func__, ver); 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; ok_ver[i]; i++) { 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (strcmp(ok_ver[i], ver) == 0) 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ok_ver[i] == NULL) { 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "Untested gnutls version %s - this needs " 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "to be tested and enabled in tls_gnutls.c", ver); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_deinit(global); 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_global_set_log_function(tls_log_func); 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_debug_show_keys) 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_global_set_log_level(11); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return global; 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tls_deinit(void *ssl_ctx) 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_global *global = ssl_ctx; 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global) { 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global->params_set) 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_free_credentials(global->xcred); 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(global->session_data); 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(global); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_gnutls_ref_count--; 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_gnutls_ref_count == 0) 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_global_deinit(); 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_get_errors(void *ssl_ctx) 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic ssize_t tls_pull_func(gnutls_transport_ptr ptr, void *buf, 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len) 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn = (struct tls_connection *) ptr; 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *end; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf == NULL) { 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt errno = EWOULDBLOCK; 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = wpabuf_head_u8(conn->pull_buf) + wpabuf_len(conn->pull_buf); 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((size_t) (end - conn->pull_buf_offset) < len) 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = end - conn->pull_buf_offset; 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, conn->pull_buf_offset, len); 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf_offset += len; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf_offset == end) { 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__); 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(conn->pull_buf); 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf = NULL; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf_offset = NULL; 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf", 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) (end - conn->pull_buf_offset)); 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf, 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len) 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn = (struct tls_connection *) ptr; 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_resize(&conn->push_buf, len) < 0) { 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt errno = ENOMEM; 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(conn->push_buf, buf, len); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_gnutls_init_session(struct tls_global *global, 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn) 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#if LIBGNUTLS_VERSION_NUMBER >= 0x020200 2521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const char *err; 2531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#else /* LIBGNUTLS_VERSION_NUMBER >= 0x020200 */ 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const int cert_types[2] = { GNUTLS_CRT_X509, 0 }; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const int protos[2] = { GNUTLS_TLS1, 0 }; 2561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* LIBGNUTLS_VERSION_NUMBER < 0x020200 */ 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_init(&conn->session, 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->server ? GNUTLS_SERVER : GNUTLS_CLIENT); 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS " 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "connection: %s", gnutls_strerror(ret)); 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_set_default_priority(conn->session); 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#if LIBGNUTLS_VERSION_NUMBER >= 0x020200 2721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret = gnutls_priority_set_direct(conn->session, "NORMAL:-VERS-SSL3.0", 2731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt &err); 2741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ret < 0) { 2751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_ERROR, "GnuTLS: Priority string failure at " 2761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "'%s'", err); 2771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 2781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#else /* LIBGNUTLS_VERSION_NUMBER >= 0x020200 */ 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_type_set_priority(conn->session, cert_types); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_protocol_set_priority(conn->session, protos); 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* LIBGNUTLS_VERSION_NUMBER < 0x020200 */ 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_transport_set_pull_function(conn->session, tls_pull_func); 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_transport_set_push_function(conn->session, tls_push_func); 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn); 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s", 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_strerror(ret)); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_deinit(conn->session); 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct tls_connection * tls_connection_init(void *ssl_ctx) 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_global *global = ssl_ctx; 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn = os_zalloc(sizeof(*conn)); 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL) 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_gnutls_init_session(global, conn)) { 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn); 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global->params_set) { 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_credentials_set(conn->session, 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GNUTLS_CRD_CERTIFICATE, 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->xcred); 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "Failed to configure " 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "credentials: %s", gnutls_strerror(ret)); 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn); 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gnutls_certificate_allocate_credentials(&conn->xcred)) { 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn); 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return conn; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL) 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_free_credentials(conn->xcred); 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_deinit(conn->session); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->pre_shared_secret); 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->subject_match); 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->altsubject_match); 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(conn->push_buf); 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(conn->pull_buf); 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn); 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_established(void *ssl_ctx, struct tls_connection *conn) 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return conn ? conn->established : 0; 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn) 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_global *global = ssl_ctx; 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL) 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Shutdown previous TLS connection without notifying the peer 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * because the connection was already terminated in practice 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * and "close notify" shutdown alert would confuse AS. */ 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_bye(conn->session, GNUTLS_SHUT_RDWR); 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(conn->push_buf); 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->push_buf = NULL; 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->established = 0; 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_deinit(conn->session); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_gnutls_init_session(global, conn)) { 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session " 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for session resumption use"); 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->params_set ? conn->xcred : 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->xcred); 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials " 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for session resumption: %s", gnutls_strerror(ret)); 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global->session_data) { 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_session_set_data(conn->session, 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->session_data, 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->session_data_size); 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "GnuTLS: Failed to set session " 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data: %s", gnutls_strerror(ret)); 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_match_altsubject(X509 *cert, const char *match) 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GENERAL_NAME *gen; 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *field, *tmp; 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ext; 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i, found = 0; 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) { 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gen = sk_GENERAL_NAME_value(ext, i); 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (gen->type) { 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case GEN_EMAIL: 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt field = "EMAIL"; 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case GEN_DNS: 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt field = "DNS"; 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case GEN_URI: 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt field = "URI"; 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt field = NULL; 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLS: altSubjectName: " 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unsupported type=%d", gen->type); 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!field) 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLS: altSubjectName: %s:%s", 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt field, gen->d.ia5->data); 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = os_strlen(field) + 1 + 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt strlen((char *) gen->d.ia5->data) + 1; 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = os_malloc(len); 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tmp == NULL) 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt snprintf(tmp, len, "%s:%s", field, gen->d.ia5->data); 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (strstr(tmp, match)) 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt found++; 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(tmp); 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return found; 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[256]; 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt X509 *err_cert; 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int err, depth; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SSL *ssl; 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn; 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *match, *altmatch; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err_cert = X509_STORE_CTX_get_current_cert(x509_ctx); 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = X509_STORE_CTX_get_error(x509_ctx); 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt depth = X509_STORE_CTX_get_error_depth(x509_ctx); 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssl = X509_STORE_CTX_get_ex_data(x509_ctx, 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt SSL_get_ex_data_X509_STORE_CTX_idx()); 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn = SSL_get_app_data(ssl); 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match = conn ? conn->subject_match : NULL; 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt altmatch = conn ? conn->altsubject_match : NULL; 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!preverify_ok) { 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TLS: Certificate verification failed," 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " error %d (%s) depth %d for '%s'", err, 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt X509_verify_cert_error_string(err), depth, buf); 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - " 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "preverify_ok=%d err=%d (%s) depth=%d buf='%s'", 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt preverify_ok, err, 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt X509_verify_cert_error_string(err), depth, buf); 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (depth == 0 && match && strstr(buf, match) == NULL) { 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not " 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with '%s'", buf, match); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt preverify_ok = 0; 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (depth == 0 && altmatch && 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !tls_match_altsubject(err_cert, altmatch)) { 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TLS: altSubjectName match " 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "'%s' not found", altmatch); 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt preverify_ok = 0; 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return preverify_ok; 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct tls_connection_params *params) 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL || params == NULL) 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->subject_match); 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->subject_match = NULL; 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->subject_match) { 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->subject_match = os_strdup(params->subject_match); 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->subject_match == NULL) 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->altsubject_match); 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->altsubject_match = NULL; 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->altsubject_match) { 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->altsubject_match = os_strdup(params->altsubject_match); 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->altsubject_match == NULL) 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: gnutls_certificate_set_verify_flags(xcred, flags); 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to force peer validation(?) */ 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->ca_cert) { 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->verify_peer = 1; 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_trust_file( 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM); 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' " 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "in PEM format: %s", params->ca_cert, 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_strerror(ret)); 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_trust_file( 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->xcred, params->ca_cert, 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GNUTLS_X509_FMT_DER); 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to read CA cert " 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "'%s' in DER format: %s", 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ca_cert, 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_strerror(ret)); 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) { 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_set_verify_flags( 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#if LIBGNUTLS_VERSION_NUMBER >= 0x020800 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) { 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_set_verify_flags( 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->xcred, 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GNUTLS_VERIFY_DISABLE_TIME_CHECKS); 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x020800 */ 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->client_cert && params->private_key) { 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: private_key_passwd? */ 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_key_file( 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->xcred, params->client_cert, params->private_key, 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GNUTLS_X509_FMT_PEM); 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to read client cert/key " 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "in PEM format: %s", gnutls_strerror(ret)); 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_key_file( 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->xcred, params->client_cert, 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->private_key, GNUTLS_X509_FMT_DER); 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to read client " 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "cert/key in DER format: %s", 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_strerror(ret)); 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (params->private_key) { 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pkcs12_ok = 0; 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PKCS12_FUNCS 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Try to load in PKCS#12 format */ 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if LIBGNUTLS_VERSION_NUMBER >= 0x010302 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_simple_pkcs12_file( 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->xcred, params->private_key, GNUTLS_X509_FMT_DER, 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->private_key_passwd); 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret != 0) { 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to load private_key in " 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PKCS#12 format: %s", gnutls_strerror(ret)); 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pkcs12_ok = 1; 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* PKCS12_FUNCS */ 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!pkcs12_ok) { 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not " 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "included"); 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->params_set = 1; 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->xcred); 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "Failed to configure credentials: %s", 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_strerror(ret)); 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_global_set_params(void *tls_ctx, 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct tls_connection_params *params) 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_global *global = tls_ctx; 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Currently, global parameters are only set when running in server 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * mode. */ 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->server = 1; 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global->params_set) { 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_free_credentials(global->xcred); 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->params_set = 0; 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_allocate_credentials(&global->xcred); 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to allocate global credentials " 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%s", gnutls_strerror(ret)); 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->ca_cert) { 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_trust_file( 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM); 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' " 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "in PEM format: %s", params->ca_cert, 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_strerror(ret)); 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_trust_file( 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->xcred, params->ca_cert, 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GNUTLS_X509_FMT_DER); 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to read CA cert " 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "'%s' in DER format: %s", 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ca_cert, 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_strerror(ret)); 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) { 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_set_verify_flags( 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->xcred, 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#if LIBGNUTLS_VERSION_NUMBER >= 0x020800 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) { 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_set_verify_flags( 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->xcred, 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GNUTLS_VERIFY_DISABLE_TIME_CHECKS); 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x020800 */ 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->client_cert && params->private_key) { 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: private_key_passwd? */ 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_key_file( 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->xcred, params->client_cert, 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->private_key, GNUTLS_X509_FMT_PEM); 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to read client cert/key " 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "in PEM format: %s", gnutls_strerror(ret)); 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_key_file( 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->xcred, params->client_cert, 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->private_key, GNUTLS_X509_FMT_DER); 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to read client " 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "cert/key in DER format: %s", 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_strerror(ret)); 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (params->private_key) { 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pkcs12_ok = 0; 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef PKCS12_FUNCS 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Try to load in PKCS#12 format */ 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if LIBGNUTLS_VERSION_NUMBER >= 0x010302 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_certificate_set_x509_simple_pkcs12_file( 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->xcred, params->private_key, 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GNUTLS_X509_FMT_DER, params->private_key_passwd); 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret != 0) { 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to load private_key in " 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PKCS#12 format: %s", gnutls_strerror(ret)); 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pkcs12_ok = 1; 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* PKCS12_FUNCS */ 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!pkcs12_ok) { 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not " 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "included"); 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->params_set = 1; 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_free_credentials(global->xcred); 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_global_set_verify(void *ssl_ctx, int check_crl) 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO */ 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int verify_peer) 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL || conn->session == NULL) 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->verify_peer = verify_peer; 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_certificate_server_set_request(conn->session, 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt verify_peer ? GNUTLS_CERT_REQUIRE 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt : GNUTLS_CERT_REQUEST); 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_keys *keys) 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt security_parameters_st *sec; 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL || conn->session == NULL || keys == NULL) 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(keys, 0, sizeof(*keys)); 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#if LIBGNUTLS_VERSION_NUMBER < 0x020c00 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sec = &conn->session->security_parameters; 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->master_key = sec->master_secret; 7681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt keys->master_key_len = WPA_TLS_MASTER_SIZE; 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->client_random = sec->client_random; 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->server_random = sec->server_random; 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* GNUTLS_INTERNAL_STRUCTURE_HACK */ 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->client_random = 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) gnutls_session_get_client_random(conn->session); 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->server_random = 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) gnutls_session_get_server_random(conn->session); 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No access to master_secret */ 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ 7781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* LIBGNUTLS_VERSION_NUMBER < 0x020c00 */ 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#if LIBGNUTLS_VERSION_NUMBER < 0x020c00 7811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt keys->client_random_len = WPA_TLS_RANDOM_SIZE; 7821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt keys->server_random_len = WPA_TLS_RANDOM_SIZE; 7831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* LIBGNUTLS_VERSION_NUMBER < 0x020c00 */ 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_prf(void *tls_ctx, struct tls_connection *conn, 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *label, int server_random_first, 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *out, size_t out_len) 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if LIBGNUTLS_VERSION_NUMBER >= 0x010302 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL || conn->session == NULL) 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return gnutls_prf(conn->session, os_strlen(label), label, 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt server_random_first, 0, NULL, out_len, (char *) out); 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_connection_verify_peer(struct tls_connection *conn, 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_alert_description_t *err) 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int status, num_certs, i; 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct os_time now; 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const gnutls_datum_t *certs; 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_x509_crt_t cert; 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gnutls_certificate_verify_peers2(conn->session, &status) < 0) { 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Failed to verify peer " 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "certificate chain"); 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *err = GNUTLS_A_INTERNAL_ERROR; 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) { 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted"); 8221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *err = GNUTLS_A_INTERNAL_ERROR; 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Certificate uses insecure " 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "algorithm"); 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *err = GNUTLS_A_INSUFFICIENT_SECURITY; 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#if LIBGNUTLS_VERSION_NUMBER >= 0x020800 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status & GNUTLS_CERT_NOT_ACTIVATED) { 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Certificate not yet " 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "activated"); 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *err = GNUTLS_A_CERTIFICATE_EXPIRED; 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status & GNUTLS_CERT_EXPIRED) { 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Certificate expired"); 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *err = GNUTLS_A_CERTIFICATE_EXPIRED; 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x020800 */ 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a " 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "known issuer"); 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *err = GNUTLS_A_UNKNOWN_CA; 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status & GNUTLS_CERT_REVOKED) { 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked"); 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *err = GNUTLS_A_CERTIFICATE_REVOKED; 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_get_time(&now); 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt certs = gnutls_certificate_get_peers(conn->session, &num_certs); 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (certs == NULL) { 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: No peer certificate chain " 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received"); 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *err = GNUTLS_A_UNKNOWN_CA; 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < num_certs; i++) { 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf; 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gnutls_x509_crt_init(&cert) < 0) { 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Certificate initialization " 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed"); 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *err = GNUTLS_A_BAD_CERTIFICATE; 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gnutls_x509_crt_import(cert, &certs[i], 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt GNUTLS_X509_FMT_DER) < 0) { 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Could not parse peer " 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "certificate %d/%d", i + 1, num_certs); 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_x509_crt_deinit(cert); 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *err = GNUTLS_A_BAD_CERTIFICATE; 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_x509_crt_get_dn(cert, NULL, &len); 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len++; 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(len + 1); 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf) { 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[0] = buf[len] = '\0'; 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_x509_crt_get_dn(cert, buf, &len); 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s", 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i + 1, num_certs, buf); 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (i == 0) { 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: validate subject_match and altsubject_match */ 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (gnutls_x509_crt_get_expiration_time(cert) < now.sec || 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_x509_crt_get_activation_time(cert) > now.sec) { 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is " 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not valid at this time", 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i + 1, num_certs); 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_x509_crt_deinit(cert); 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *err = GNUTLS_A_CERTIFICATE_EXPIRED; 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_x509_crt_deinit(cert); 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn) 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *ad; 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data"); 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3); 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ad == NULL) 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = gnutls_record_recv(conn->session, wpabuf_mhead(ad), 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_size(ad)); 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res); 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 9301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d " 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s)", __func__, (int) res, 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_strerror(res)); 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(ad); 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(ad, res); 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data", 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res); 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ad; 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_handshake(void *tls_ctx, 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn, 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data, 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **appl_data) 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_global *global = tls_ctx; 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *out_data; 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (appl_data) 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *appl_data = NULL; 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (in_data && wpabuf_len(in_data) > 0) { 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf) { 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pull_buf", __func__, 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(conn->pull_buf)); 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(conn->pull_buf); 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf = wpabuf_dup(in_data); 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf == NULL) 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf_offset = wpabuf_head(conn->pull_buf); 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = gnutls_handshake(conn->session); 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (ret) { 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case GNUTLS_E_AGAIN: 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global->server && conn->established && 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->push_buf == NULL) { 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Need to return something to trigger 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * completion of EAP-TLS. */ 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->push_buf = wpabuf_alloc(0); 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case GNUTLS_E_FATAL_ALERT_RECEIVED: 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert", 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, gnutls_alert_get_name( 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_alert_get(conn->session))); 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->read_alerts++; 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* continue */ 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed " 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "-> %s", __func__, gnutls_strerror(ret)); 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->failed++; 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t size; 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_alert_description_t err; 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->verify_peer && 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_connection_verify_peer(conn, &err)) { 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TLS: Peer certificate chain " 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed validation"); 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->failed++; 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_alert_send(conn->session, GNUTLS_AL_FATAL, err); 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully"); 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->established = 1; 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->push_buf == NULL) { 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Need to return something to get final TLS ACK. */ 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->push_buf = wpabuf_alloc(0); 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_session_get_data(conn->session, NULL, &size); 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global->session_data == NULL || 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->session_data_size < size) { 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(global->session_data); 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->session_data = os_malloc(size); 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global->session_data) { 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->session_data_size = size; 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_session_get_data(conn->session, 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global->session_data, 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &global->session_data_size); 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf && appl_data) 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *appl_data = gnutls_get_appl_data(conn); 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtout: 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out_data = conn->push_buf; 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->push_buf = NULL; 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return out_data; 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_server_handshake(void *tls_ctx, 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn, 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data, 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf **appl_data) 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tls_connection_handshake(tls_ctx, conn, in_data, appl_data); 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_encrypt(void *tls_ctx, 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn, 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data) 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssize_t res; 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = gnutls_record_send(conn->session, wpabuf_head(in_data), 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(in_data)); 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "%s: Encryption failed: %s", 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, gnutls_strerror(res)); 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = conn->push_buf; 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->push_buf = NULL; 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * tls_connection_decrypt(void *tls_ctx, 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn, 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *in_data) 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssize_t res; 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *out; 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf) { 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pull_buf", __func__, 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(conn->pull_buf)); 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(conn->pull_buf); 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf = wpabuf_dup(in_data); 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->pull_buf == NULL) 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->pull_buf_offset = wpabuf_head(conn->pull_buf); 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Even though we try to disable TLS compression, it is possible that 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * this cannot be done with all TLS libraries. Add extra buffer space 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to handle the possibility of the decrypted data being longer than 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * input data. 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (out == NULL) 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = gnutls_record_recv(conn->session, wpabuf_mhead(out), 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_size(out)); 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d " 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s)", __func__, (int) res, gnutls_strerror(res)); 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(out); 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(out, res); 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return out; 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL) 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return gnutls_session_is_resumed(conn->session); 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *ciphers) 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO */ 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf, size_t buflen) 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO */ 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[0] = '\0'; 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_enable_workaround(void *ssl_ctx, 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn) 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnutls_record_disable_padding(conn->session); 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ext_type, const u8 *data, 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t data_len) 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO */ 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL) 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return conn->failed; 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL) 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return conn->read_alerts; 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL) 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return conn->write_alerts; 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_get_keyblock_size(void *tls_ctx, 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn) 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO */ 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int tls_capabilities(void *tls_ctx) 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_connection_set_session_ticket_cb(void *tls_ctx, 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tls_connection *conn, 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_session_ticket_cb cb, void *ctx) 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1193