185732ac8SCy Schubert /* 285732ac8SCy Schubert * SSL/TLS interface functions for wolfSSL TLS case 385732ac8SCy Schubert * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi> 485732ac8SCy Schubert * 585732ac8SCy Schubert * This software may be distributed under the terms of the BSD license. 685732ac8SCy Schubert * See README for more details. 785732ac8SCy Schubert */ 885732ac8SCy Schubert 985732ac8SCy Schubert #include "includes.h" 1085732ac8SCy Schubert 1185732ac8SCy Schubert #include "common.h" 1285732ac8SCy Schubert #include "crypto.h" 1385732ac8SCy Schubert #include "crypto/sha1.h" 1485732ac8SCy Schubert #include "crypto/sha256.h" 1585732ac8SCy Schubert #include "tls.h" 1685732ac8SCy Schubert 1785732ac8SCy Schubert /* wolfSSL includes */ 1885732ac8SCy Schubert #include <wolfssl/options.h> 1985732ac8SCy Schubert #include <wolfssl/ssl.h> 2085732ac8SCy Schubert #include <wolfssl/error-ssl.h> 2185732ac8SCy Schubert #include <wolfssl/wolfcrypt/asn.h> 22c1d255d3SCy Schubert #include <wolfssl/openssl/x509v3.h> 2385732ac8SCy Schubert 2485732ac8SCy Schubert #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) 2585732ac8SCy Schubert #define HAVE_AESGCM 2685732ac8SCy Schubert #include <wolfssl/wolfcrypt/aes.h> 2785732ac8SCy Schubert #endif 2885732ac8SCy Schubert 29*a90b9d01SCy Schubert #ifdef CONFIG_FIPS 30*a90b9d01SCy Schubert #include <wolfssl/wolfcrypt/fips_test.h> 31*a90b9d01SCy Schubert #endif /* CONFIG_FIPS */ 32*a90b9d01SCy Schubert 3385732ac8SCy Schubert #if !defined(CONFIG_FIPS) && \ 3485732ac8SCy Schubert (defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || \ 3585732ac8SCy Schubert defined(EAP_SERVER_FAST)) 3685732ac8SCy Schubert #define WOLFSSL_NEED_EAP_FAST_PRF 3785732ac8SCy Schubert #endif 3885732ac8SCy Schubert 3985732ac8SCy Schubert #define SECRET_LEN 48 4085732ac8SCy Schubert #define RAN_LEN 32 4185732ac8SCy Schubert #define SESSION_TICKET_LEN 256 4285732ac8SCy Schubert 4385732ac8SCy Schubert static int tls_ref_count = 0; 4485732ac8SCy Schubert 4585732ac8SCy Schubert static int tls_ex_idx_session = 0; 4685732ac8SCy Schubert 4785732ac8SCy Schubert 4885732ac8SCy Schubert /* tls input data for wolfSSL Read Callback */ 4985732ac8SCy Schubert struct tls_in_data { 5085732ac8SCy Schubert const struct wpabuf *in_data; 5185732ac8SCy Schubert size_t consumed; /* how many bytes have we used already */ 5285732ac8SCy Schubert }; 5385732ac8SCy Schubert 5485732ac8SCy Schubert /* tls output data for wolfSSL Write Callback */ 5585732ac8SCy Schubert struct tls_out_data { 5685732ac8SCy Schubert struct wpabuf *out_data; 5785732ac8SCy Schubert }; 5885732ac8SCy Schubert 5985732ac8SCy Schubert struct tls_context { 6085732ac8SCy Schubert void (*event_cb)(void *ctx, enum tls_event ev, 6185732ac8SCy Schubert union tls_event_data *data); 6285732ac8SCy Schubert void *cb_ctx; 6385732ac8SCy Schubert int cert_in_cb; 6485732ac8SCy Schubert char *ocsp_stapling_response; 65*a90b9d01SCy Schubert unsigned int tls_session_lifetime; 6685732ac8SCy Schubert }; 6785732ac8SCy Schubert 6885732ac8SCy Schubert static struct tls_context *tls_global = NULL; 6985732ac8SCy Schubert 7085732ac8SCy Schubert /* wolfssl tls_connection */ 7185732ac8SCy Schubert struct tls_connection { 7285732ac8SCy Schubert struct tls_context *context; 7385732ac8SCy Schubert WOLFSSL *ssl; 7485732ac8SCy Schubert int read_alerts; 7585732ac8SCy Schubert int write_alerts; 7685732ac8SCy Schubert int failed; 7785732ac8SCy Schubert struct tls_in_data input; 7885732ac8SCy Schubert struct tls_out_data output; 7985732ac8SCy Schubert char *subject_match; 8085732ac8SCy Schubert char *alt_subject_match; 8185732ac8SCy Schubert char *suffix_match; 8285732ac8SCy Schubert char *domain_match; 8385732ac8SCy Schubert 8485732ac8SCy Schubert u8 srv_cert_hash[32]; 8585732ac8SCy Schubert 8685732ac8SCy Schubert unsigned char client_random[RAN_LEN]; 8785732ac8SCy Schubert unsigned char server_random[RAN_LEN]; 8885732ac8SCy Schubert unsigned int flags; 8985732ac8SCy Schubert #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) 9085732ac8SCy Schubert tls_session_ticket_cb session_ticket_cb; 9185732ac8SCy Schubert void *session_ticket_cb_ctx; 9285732ac8SCy Schubert byte session_ticket[SESSION_TICKET_LEN]; 9385732ac8SCy Schubert #endif 9485732ac8SCy Schubert unsigned int ca_cert_verify:1; 9585732ac8SCy Schubert unsigned int cert_probe:1; 9685732ac8SCy Schubert unsigned int server_cert_only:1; 9785732ac8SCy Schubert unsigned int success_data:1; 9885732ac8SCy Schubert 9985732ac8SCy Schubert WOLFSSL_X509 *peer_cert; 10085732ac8SCy Schubert WOLFSSL_X509 *peer_issuer; 10185732ac8SCy Schubert WOLFSSL_X509 *peer_issuer_issuer; 102*a90b9d01SCy Schubert char *peer_subject; /* peer subject info for authenticated peer */ 10385732ac8SCy Schubert }; 10485732ac8SCy Schubert 10585732ac8SCy Schubert 10685732ac8SCy Schubert static struct tls_context * tls_context_new(const struct tls_config *conf) 10785732ac8SCy Schubert { 10885732ac8SCy Schubert struct tls_context *context = os_zalloc(sizeof(*context)); 10985732ac8SCy Schubert 11085732ac8SCy Schubert if (!context) 11185732ac8SCy Schubert return NULL; 11285732ac8SCy Schubert 11385732ac8SCy Schubert if (conf) { 11485732ac8SCy Schubert context->event_cb = conf->event_cb; 11585732ac8SCy Schubert context->cb_ctx = conf->cb_ctx; 11685732ac8SCy Schubert context->cert_in_cb = conf->cert_in_cb; 11785732ac8SCy Schubert } 11885732ac8SCy Schubert 11985732ac8SCy Schubert return context; 12085732ac8SCy Schubert } 12185732ac8SCy Schubert 12285732ac8SCy Schubert 12385732ac8SCy Schubert static void wolfssl_reset_in_data(struct tls_in_data *in, 12485732ac8SCy Schubert const struct wpabuf *buf) 12585732ac8SCy Schubert { 12685732ac8SCy Schubert /* old one not owned by us so don't free */ 12785732ac8SCy Schubert in->in_data = buf; 12885732ac8SCy Schubert in->consumed = 0; 12985732ac8SCy Schubert } 13085732ac8SCy Schubert 13185732ac8SCy Schubert 13285732ac8SCy Schubert static void wolfssl_reset_out_data(struct tls_out_data *out) 13385732ac8SCy Schubert { 13485732ac8SCy Schubert /* old one not owned by us so don't free */ 13585732ac8SCy Schubert out->out_data = wpabuf_alloc_copy("", 0); 13685732ac8SCy Schubert } 13785732ac8SCy Schubert 13885732ac8SCy Schubert 13985732ac8SCy Schubert /* wolfSSL I/O Receive CallBack */ 14085732ac8SCy Schubert static int wolfssl_receive_cb(WOLFSSL *ssl, char *buf, int sz, void *ctx) 14185732ac8SCy Schubert { 14285732ac8SCy Schubert size_t get = sz; 14385732ac8SCy Schubert struct tls_in_data *data = ctx; 14485732ac8SCy Schubert 14585732ac8SCy Schubert if (!data) 14685732ac8SCy Schubert return -1; 14785732ac8SCy Schubert 14885732ac8SCy Schubert if (get > (wpabuf_len(data->in_data) - data->consumed)) 14985732ac8SCy Schubert get = wpabuf_len(data->in_data) - data->consumed; 15085732ac8SCy Schubert 151206b73d0SCy Schubert os_memcpy(buf, wpabuf_head_u8(data->in_data) + data->consumed, get); 15285732ac8SCy Schubert data->consumed += get; 15385732ac8SCy Schubert 15485732ac8SCy Schubert if (get == 0) 15585732ac8SCy Schubert return -2; /* WANT_READ */ 15685732ac8SCy Schubert 15785732ac8SCy Schubert return (int) get; 15885732ac8SCy Schubert } 15985732ac8SCy Schubert 16085732ac8SCy Schubert 16185732ac8SCy Schubert /* wolfSSL I/O Send CallBack */ 16285732ac8SCy Schubert static int wolfssl_send_cb(WOLFSSL *ssl, char *buf, int sz, void *ctx) 16385732ac8SCy Schubert { 16485732ac8SCy Schubert struct wpabuf *tmp; 16585732ac8SCy Schubert struct tls_out_data *data = ctx; 16685732ac8SCy Schubert 16785732ac8SCy Schubert if (!data) 16885732ac8SCy Schubert return -1; 16985732ac8SCy Schubert 17085732ac8SCy Schubert wpa_printf(MSG_DEBUG, "SSL: adding %d bytes", sz); 17185732ac8SCy Schubert 17285732ac8SCy Schubert tmp = wpabuf_alloc_copy(buf, sz); 17385732ac8SCy Schubert if (!tmp) 17485732ac8SCy Schubert return -1; 17585732ac8SCy Schubert data->out_data = wpabuf_concat(data->out_data, tmp); 17685732ac8SCy Schubert if (!data->out_data) 17785732ac8SCy Schubert return -1; 17885732ac8SCy Schubert 17985732ac8SCy Schubert return sz; 18085732ac8SCy Schubert } 18185732ac8SCy Schubert 18285732ac8SCy Schubert 18385732ac8SCy Schubert static void remove_session_cb(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *sess) 18485732ac8SCy Schubert { 18585732ac8SCy Schubert struct wpabuf *buf; 18685732ac8SCy Schubert 18785732ac8SCy Schubert buf = wolfSSL_SESSION_get_ex_data(sess, tls_ex_idx_session); 18885732ac8SCy Schubert if (!buf) 18985732ac8SCy Schubert return; 19085732ac8SCy Schubert wpa_printf(MSG_DEBUG, 19185732ac8SCy Schubert "wolfSSL: Free application session data %p (sess %p)", 19285732ac8SCy Schubert buf, sess); 19385732ac8SCy Schubert wpabuf_free(buf); 19485732ac8SCy Schubert 19585732ac8SCy Schubert wolfSSL_SESSION_set_ex_data(sess, tls_ex_idx_session, NULL); 19685732ac8SCy Schubert } 19785732ac8SCy Schubert 19885732ac8SCy Schubert 199*a90b9d01SCy Schubert #if defined(CONFIG_FIPS) && defined(HAVE_FIPS) 200*a90b9d01SCy Schubert static void wcFipsCb(int ok, int err, const char *hash) 201*a90b9d01SCy Schubert { 202*a90b9d01SCy Schubert wpa_printf(MSG_INFO, 203*a90b9d01SCy Schubert "wolfFIPS: wolfCrypt Fips error callback, ok = %d, err = %d", 204*a90b9d01SCy Schubert ok, err); 205*a90b9d01SCy Schubert wpa_printf(MSG_INFO, "wolfFIPS: message = %s", wc_GetErrorString(err)); 206*a90b9d01SCy Schubert wpa_printf(MSG_INFO, "wolfFIPS: hash = %s", hash); 207*a90b9d01SCy Schubert if (err == IN_CORE_FIPS_E) { 208*a90b9d01SCy Schubert wpa_printf(MSG_ERROR, 209*a90b9d01SCy Schubert "wolfFIPS: In core integrity hash check failure, copy above hash"); 210*a90b9d01SCy Schubert wpa_printf(MSG_ERROR, "wolfFIPS: into verifyCore[] in fips_test.c and rebuild"); 211*a90b9d01SCy Schubert } 212*a90b9d01SCy Schubert } 213*a90b9d01SCy Schubert #endif /* CONFIG_FIPS && HAVE_FIPS */ 214*a90b9d01SCy Schubert 215*a90b9d01SCy Schubert 216*a90b9d01SCy Schubert #ifdef DEBUG_WOLFSSL 217*a90b9d01SCy Schubert static void wolfSSL_logging_cb(const int log_level, 218*a90b9d01SCy Schubert const char * const log_message) 219*a90b9d01SCy Schubert { 220*a90b9d01SCy Schubert (void) log_level; 221*a90b9d01SCy Schubert wpa_printf(MSG_DEBUG, "wolfSSL log:%s", log_message); 222*a90b9d01SCy Schubert } 223*a90b9d01SCy Schubert #endif /* DEBUG_WOLFSSL */ 224*a90b9d01SCy Schubert 225*a90b9d01SCy Schubert 22685732ac8SCy Schubert void * tls_init(const struct tls_config *conf) 22785732ac8SCy Schubert { 22885732ac8SCy Schubert WOLFSSL_CTX *ssl_ctx; 22985732ac8SCy Schubert struct tls_context *context; 23085732ac8SCy Schubert const char *ciphers; 23185732ac8SCy Schubert 23285732ac8SCy Schubert #ifdef DEBUG_WOLFSSL 233*a90b9d01SCy Schubert wolfSSL_SetLoggingCb(wolfSSL_logging_cb); 23485732ac8SCy Schubert wolfSSL_Debugging_ON(); 23585732ac8SCy Schubert #endif /* DEBUG_WOLFSSL */ 23685732ac8SCy Schubert 23785732ac8SCy Schubert context = tls_context_new(conf); 23885732ac8SCy Schubert if (!context) 23985732ac8SCy Schubert return NULL; 24085732ac8SCy Schubert 24185732ac8SCy Schubert if (tls_ref_count == 0) { 24285732ac8SCy Schubert tls_global = context; 24385732ac8SCy Schubert 24485732ac8SCy Schubert if (wolfSSL_Init() < 0) 24585732ac8SCy Schubert return NULL; 246*a90b9d01SCy Schubert #if defined(CONFIG_FIPS) && defined(HAVE_FIPS) 247*a90b9d01SCy Schubert wolfCrypt_SetCb_fips(wcFipsCb); 248*a90b9d01SCy Schubert #endif /* CONFIG_FIPS && HAVE_FIPS */ 24985732ac8SCy Schubert } 25085732ac8SCy Schubert 25185732ac8SCy Schubert tls_ref_count++; 25285732ac8SCy Schubert 25385732ac8SCy Schubert /* start as client */ 25485732ac8SCy Schubert ssl_ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); 25585732ac8SCy Schubert if (!ssl_ctx) { 25685732ac8SCy Schubert tls_ref_count--; 25785732ac8SCy Schubert if (context != tls_global) 25885732ac8SCy Schubert os_free(context); 25985732ac8SCy Schubert if (tls_ref_count == 0) { 26085732ac8SCy Schubert os_free(tls_global); 26185732ac8SCy Schubert tls_global = NULL; 26285732ac8SCy Schubert } 26385732ac8SCy Schubert } 26485732ac8SCy Schubert wolfSSL_SetIORecv(ssl_ctx, wolfssl_receive_cb); 26585732ac8SCy Schubert wolfSSL_SetIOSend(ssl_ctx, wolfssl_send_cb); 266*a90b9d01SCy Schubert context->tls_session_lifetime = conf->tls_session_lifetime; 26785732ac8SCy Schubert wolfSSL_CTX_set_ex_data(ssl_ctx, 0, context); 26885732ac8SCy Schubert 26985732ac8SCy Schubert if (conf->tls_session_lifetime > 0) { 270*a90b9d01SCy Schubert wolfSSL_CTX_set_session_id_context(ssl_ctx, 271*a90b9d01SCy Schubert (const unsigned char *) 272*a90b9d01SCy Schubert "hostapd", 7); 27385732ac8SCy Schubert wolfSSL_CTX_set_quiet_shutdown(ssl_ctx, 1); 27485732ac8SCy Schubert wolfSSL_CTX_set_session_cache_mode(ssl_ctx, 275*a90b9d01SCy Schubert WOLFSSL_SESS_CACHE_SERVER); 27685732ac8SCy Schubert wolfSSL_CTX_set_timeout(ssl_ctx, conf->tls_session_lifetime); 27785732ac8SCy Schubert wolfSSL_CTX_sess_set_remove_cb(ssl_ctx, remove_session_cb); 27885732ac8SCy Schubert } else { 27985732ac8SCy Schubert wolfSSL_CTX_set_session_cache_mode(ssl_ctx, 280*a90b9d01SCy Schubert WOLFSSL_SESS_CACHE_OFF); 28185732ac8SCy Schubert } 28285732ac8SCy Schubert 28385732ac8SCy Schubert if (conf && conf->openssl_ciphers) 28485732ac8SCy Schubert ciphers = conf->openssl_ciphers; 28585732ac8SCy Schubert else 28685732ac8SCy Schubert ciphers = "ALL"; 287*a90b9d01SCy Schubert wpa_printf(MSG_DEBUG, "wolfSSL: cipher suites: %s", ciphers); 28885732ac8SCy Schubert if (wolfSSL_CTX_set_cipher_list(ssl_ctx, ciphers) != 1) { 28985732ac8SCy Schubert wpa_printf(MSG_ERROR, 29085732ac8SCy Schubert "wolfSSL: Failed to set cipher string '%s'", 29185732ac8SCy Schubert ciphers); 29285732ac8SCy Schubert tls_deinit(ssl_ctx); 29385732ac8SCy Schubert return NULL; 29485732ac8SCy Schubert } 29585732ac8SCy Schubert 29685732ac8SCy Schubert return ssl_ctx; 29785732ac8SCy Schubert } 29885732ac8SCy Schubert 29985732ac8SCy Schubert 30085732ac8SCy Schubert void tls_deinit(void *ssl_ctx) 30185732ac8SCy Schubert { 30285732ac8SCy Schubert struct tls_context *context = wolfSSL_CTX_get_ex_data(ssl_ctx, 0); 30385732ac8SCy Schubert 30485732ac8SCy Schubert if (context != tls_global) 30585732ac8SCy Schubert os_free(context); 30685732ac8SCy Schubert 30785732ac8SCy Schubert wolfSSL_CTX_free((WOLFSSL_CTX *) ssl_ctx); 30885732ac8SCy Schubert 30985732ac8SCy Schubert tls_ref_count--; 31085732ac8SCy Schubert if (tls_ref_count == 0) { 31185732ac8SCy Schubert wolfSSL_Cleanup(); 31285732ac8SCy Schubert os_free(tls_global); 31385732ac8SCy Schubert tls_global = NULL; 31485732ac8SCy Schubert } 31585732ac8SCy Schubert } 31685732ac8SCy Schubert 31785732ac8SCy Schubert 31885732ac8SCy Schubert int tls_get_errors(void *tls_ctx) 31985732ac8SCy Schubert { 32085732ac8SCy Schubert #ifdef DEBUG_WOLFSSL 32185732ac8SCy Schubert #if 0 32285732ac8SCy Schubert unsigned long err; 32385732ac8SCy Schubert 32485732ac8SCy Schubert err = wolfSSL_ERR_peek_last_error_line(NULL, NULL); 32585732ac8SCy Schubert if (err != 0) { 32685732ac8SCy Schubert wpa_printf(MSG_INFO, "TLS - SSL error: %s", 32785732ac8SCy Schubert wolfSSL_ERR_error_string(err, NULL)); 32885732ac8SCy Schubert return 1; 32985732ac8SCy Schubert } 33085732ac8SCy Schubert #endif 33185732ac8SCy Schubert #endif /* DEBUG_WOLFSSL */ 33285732ac8SCy Schubert return 0; 33385732ac8SCy Schubert } 33485732ac8SCy Schubert 33585732ac8SCy Schubert 33685732ac8SCy Schubert struct tls_connection * tls_connection_init(void *tls_ctx) 33785732ac8SCy Schubert { 33885732ac8SCy Schubert WOLFSSL_CTX *ssl_ctx = tls_ctx; 33985732ac8SCy Schubert struct tls_connection *conn; 34085732ac8SCy Schubert 34185732ac8SCy Schubert wpa_printf(MSG_DEBUG, "SSL: connection init"); 34285732ac8SCy Schubert 34385732ac8SCy Schubert conn = os_zalloc(sizeof(*conn)); 34485732ac8SCy Schubert if (!conn) 34585732ac8SCy Schubert return NULL; 34685732ac8SCy Schubert conn->ssl = wolfSSL_new(ssl_ctx); 34785732ac8SCy Schubert if (!conn->ssl) { 34885732ac8SCy Schubert os_free(conn); 34985732ac8SCy Schubert return NULL; 35085732ac8SCy Schubert } 35185732ac8SCy Schubert 35285732ac8SCy Schubert wolfSSL_SetIOReadCtx(conn->ssl, &conn->input); 35385732ac8SCy Schubert wolfSSL_SetIOWriteCtx(conn->ssl, &conn->output); 35485732ac8SCy Schubert wolfSSL_set_ex_data(conn->ssl, 0, conn); 35585732ac8SCy Schubert conn->context = wolfSSL_CTX_get_ex_data(ssl_ctx, 0); 35685732ac8SCy Schubert 35785732ac8SCy Schubert /* Need randoms post-hanshake for EAP-FAST, export key and deriving 35885732ac8SCy Schubert * session ID in EAP methods. */ 35985732ac8SCy Schubert wolfSSL_KeepArrays(conn->ssl); 36085732ac8SCy Schubert wolfSSL_KeepHandshakeResources(conn->ssl); 36185732ac8SCy Schubert wolfSSL_UseClientSuites(conn->ssl); 36285732ac8SCy Schubert 36385732ac8SCy Schubert return conn; 36485732ac8SCy Schubert } 36585732ac8SCy Schubert 36685732ac8SCy Schubert 36785732ac8SCy Schubert void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) 36885732ac8SCy Schubert { 36985732ac8SCy Schubert if (!conn) 37085732ac8SCy Schubert return; 37185732ac8SCy Schubert 37285732ac8SCy Schubert wpa_printf(MSG_DEBUG, "SSL: connection deinit"); 37385732ac8SCy Schubert 37485732ac8SCy Schubert /* parts */ 37585732ac8SCy Schubert wolfSSL_free(conn->ssl); 37685732ac8SCy Schubert os_free(conn->subject_match); 37785732ac8SCy Schubert os_free(conn->alt_subject_match); 37885732ac8SCy Schubert os_free(conn->suffix_match); 37985732ac8SCy Schubert os_free(conn->domain_match); 380*a90b9d01SCy Schubert os_free(conn->peer_subject); 38185732ac8SCy Schubert 38285732ac8SCy Schubert /* self */ 38385732ac8SCy Schubert os_free(conn); 38485732ac8SCy Schubert } 38585732ac8SCy Schubert 38685732ac8SCy Schubert 38785732ac8SCy Schubert int tls_connection_established(void *tls_ctx, struct tls_connection *conn) 38885732ac8SCy Schubert { 38985732ac8SCy Schubert return conn ? wolfSSL_is_init_finished(conn->ssl) : 0; 39085732ac8SCy Schubert } 39185732ac8SCy Schubert 39285732ac8SCy Schubert 39385732ac8SCy Schubert char * tls_connection_peer_serial_num(void *tls_ctx, 39485732ac8SCy Schubert struct tls_connection *conn) 39585732ac8SCy Schubert { 39685732ac8SCy Schubert /* TODO */ 39785732ac8SCy Schubert return NULL; 39885732ac8SCy Schubert } 39985732ac8SCy Schubert 40085732ac8SCy Schubert 40185732ac8SCy Schubert int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) 40285732ac8SCy Schubert { 40385732ac8SCy Schubert WOLFSSL_SESSION *session; 40485732ac8SCy Schubert 40585732ac8SCy Schubert if (!conn) 40685732ac8SCy Schubert return -1; 40785732ac8SCy Schubert 40885732ac8SCy Schubert wpa_printf(MSG_DEBUG, "SSL: connection shutdown"); 40985732ac8SCy Schubert 41085732ac8SCy Schubert /* Set quiet as OpenSSL does */ 41185732ac8SCy Schubert wolfSSL_set_quiet_shutdown(conn->ssl, 1); 41285732ac8SCy Schubert wolfSSL_shutdown(conn->ssl); 41385732ac8SCy Schubert 414*a90b9d01SCy Schubert session = wolfSSL_get1_session(conn->ssl); 415*a90b9d01SCy Schubert if (wolfSSL_clear(conn->ssl) != 1) { 416*a90b9d01SCy Schubert wolfSSL_SESSION_free(session); 41785732ac8SCy Schubert return -1; 418*a90b9d01SCy Schubert } 41985732ac8SCy Schubert wolfSSL_set_session(conn->ssl, session); 420*a90b9d01SCy Schubert wolfSSL_SESSION_free(session); 42185732ac8SCy Schubert 42285732ac8SCy Schubert return 0; 42385732ac8SCy Schubert } 42485732ac8SCy Schubert 42585732ac8SCy Schubert 42685732ac8SCy Schubert static int tls_connection_set_subject_match(struct tls_connection *conn, 42785732ac8SCy Schubert const char *subject_match, 42885732ac8SCy Schubert const char *alt_subject_match, 42985732ac8SCy Schubert const char *suffix_match, 43085732ac8SCy Schubert const char *domain_match) 43185732ac8SCy Schubert { 43285732ac8SCy Schubert os_free(conn->subject_match); 43385732ac8SCy Schubert conn->subject_match = NULL; 43485732ac8SCy Schubert if (subject_match) { 43585732ac8SCy Schubert conn->subject_match = os_strdup(subject_match); 43685732ac8SCy Schubert if (!conn->subject_match) 43785732ac8SCy Schubert return -1; 43885732ac8SCy Schubert } 43985732ac8SCy Schubert 44085732ac8SCy Schubert os_free(conn->alt_subject_match); 44185732ac8SCy Schubert conn->alt_subject_match = NULL; 44285732ac8SCy Schubert if (alt_subject_match) { 44385732ac8SCy Schubert conn->alt_subject_match = os_strdup(alt_subject_match); 44485732ac8SCy Schubert if (!conn->alt_subject_match) 44585732ac8SCy Schubert return -1; 44685732ac8SCy Schubert } 44785732ac8SCy Schubert 44885732ac8SCy Schubert os_free(conn->suffix_match); 44985732ac8SCy Schubert conn->suffix_match = NULL; 45085732ac8SCy Schubert if (suffix_match) { 45185732ac8SCy Schubert conn->suffix_match = os_strdup(suffix_match); 45285732ac8SCy Schubert if (!conn->suffix_match) 45385732ac8SCy Schubert return -1; 45485732ac8SCy Schubert } 45585732ac8SCy Schubert 45685732ac8SCy Schubert os_free(conn->domain_match); 45785732ac8SCy Schubert conn->domain_match = NULL; 45885732ac8SCy Schubert if (domain_match) { 45985732ac8SCy Schubert conn->domain_match = os_strdup(domain_match); 46085732ac8SCy Schubert if (!conn->domain_match) 46185732ac8SCy Schubert return -1; 46285732ac8SCy Schubert } 46385732ac8SCy Schubert 46485732ac8SCy Schubert return 0; 46585732ac8SCy Schubert } 46685732ac8SCy Schubert 46785732ac8SCy Schubert 46885732ac8SCy Schubert static int tls_connection_client_cert(struct tls_connection *conn, 46985732ac8SCy Schubert const char *client_cert, 47085732ac8SCy Schubert const u8 *client_cert_blob, 47185732ac8SCy Schubert size_t blob_len) 47285732ac8SCy Schubert { 47385732ac8SCy Schubert if (!client_cert && !client_cert_blob) 47485732ac8SCy Schubert return 0; 47585732ac8SCy Schubert 47685732ac8SCy Schubert if (client_cert_blob) { 47785732ac8SCy Schubert if (wolfSSL_use_certificate_chain_buffer_format( 47885732ac8SCy Schubert conn->ssl, client_cert_blob, blob_len, 479c1d255d3SCy Schubert SSL_FILETYPE_ASN1) != SSL_SUCCESS) { 48085732ac8SCy Schubert wpa_printf(MSG_INFO, 48185732ac8SCy Schubert "SSL: use client cert DER blob failed"); 482*a90b9d01SCy Schubert if (wolfSSL_use_certificate_chain_buffer_format( 483*a90b9d01SCy Schubert conn->ssl, client_cert_blob, blob_len, 484*a90b9d01SCy Schubert SSL_FILETYPE_PEM) != SSL_SUCCESS) { 485*a90b9d01SCy Schubert wpa_printf(MSG_INFO, 486*a90b9d01SCy Schubert "SSL: use client cert PEM blob failed"); 48785732ac8SCy Schubert return -1; 48885732ac8SCy Schubert } 489*a90b9d01SCy Schubert } 49085732ac8SCy Schubert wpa_printf(MSG_DEBUG, "SSL: use client cert blob OK"); 49185732ac8SCy Schubert return 0; 49285732ac8SCy Schubert } 49385732ac8SCy Schubert 49485732ac8SCy Schubert if (client_cert) { 495c1d255d3SCy Schubert if (wolfSSL_use_certificate_chain_file( 496c1d255d3SCy Schubert conn->ssl, client_cert) != SSL_SUCCESS) { 49785732ac8SCy Schubert wpa_printf(MSG_INFO, 49885732ac8SCy Schubert "SSL: use client cert PEM file failed"); 49985732ac8SCy Schubert if (wolfSSL_use_certificate_chain_file_format( 50085732ac8SCy Schubert conn->ssl, client_cert, 501c1d255d3SCy Schubert SSL_FILETYPE_ASN1) != SSL_SUCCESS) { 50285732ac8SCy Schubert wpa_printf(MSG_INFO, 50385732ac8SCy Schubert "SSL: use client cert DER file failed"); 50485732ac8SCy Schubert return -1; 50585732ac8SCy Schubert } 50685732ac8SCy Schubert } 50785732ac8SCy Schubert wpa_printf(MSG_DEBUG, "SSL: use client cert file OK"); 50885732ac8SCy Schubert return 0; 50985732ac8SCy Schubert } 51085732ac8SCy Schubert 51185732ac8SCy Schubert return 0; 51285732ac8SCy Schubert } 51385732ac8SCy Schubert 51485732ac8SCy Schubert 51585732ac8SCy Schubert static int tls_passwd_cb(char *buf, int size, int rwflag, void *password) 51685732ac8SCy Schubert { 51785732ac8SCy Schubert if (!password) 51885732ac8SCy Schubert return 0; 51985732ac8SCy Schubert os_strlcpy(buf, (char *) password, size); 52085732ac8SCy Schubert return os_strlen(buf); 52185732ac8SCy Schubert } 52285732ac8SCy Schubert 52385732ac8SCy Schubert 52485732ac8SCy Schubert static int tls_connection_private_key(void *tls_ctx, 52585732ac8SCy Schubert struct tls_connection *conn, 52685732ac8SCy Schubert const char *private_key, 52785732ac8SCy Schubert const char *private_key_passwd, 52885732ac8SCy Schubert const u8 *private_key_blob, 52985732ac8SCy Schubert size_t blob_len) 53085732ac8SCy Schubert { 53185732ac8SCy Schubert WOLFSSL_CTX *ctx = tls_ctx; 53285732ac8SCy Schubert char *passwd = NULL; 53385732ac8SCy Schubert int ok = 0; 53485732ac8SCy Schubert 53585732ac8SCy Schubert if (!private_key && !private_key_blob) 53685732ac8SCy Schubert return 0; 53785732ac8SCy Schubert 53885732ac8SCy Schubert if (private_key_passwd) { 53985732ac8SCy Schubert passwd = os_strdup(private_key_passwd); 54085732ac8SCy Schubert if (!passwd) 54185732ac8SCy Schubert return -1; 54285732ac8SCy Schubert } 54385732ac8SCy Schubert 54485732ac8SCy Schubert wolfSSL_CTX_set_default_passwd_cb(ctx, tls_passwd_cb); 54585732ac8SCy Schubert wolfSSL_CTX_set_default_passwd_cb_userdata(ctx, passwd); 54685732ac8SCy Schubert 54785732ac8SCy Schubert if (private_key_blob) { 54885732ac8SCy Schubert if (wolfSSL_use_PrivateKey_buffer(conn->ssl, 54985732ac8SCy Schubert private_key_blob, blob_len, 550*a90b9d01SCy Schubert SSL_FILETYPE_ASN1) != 551*a90b9d01SCy Schubert SSL_SUCCESS) { 55285732ac8SCy Schubert wpa_printf(MSG_INFO, 55385732ac8SCy Schubert "SSL: use private DER blob failed"); 554*a90b9d01SCy Schubert if (wolfSSL_use_PrivateKey_buffer( 555*a90b9d01SCy Schubert conn->ssl, 556*a90b9d01SCy Schubert private_key_blob, blob_len, 557*a90b9d01SCy Schubert SSL_FILETYPE_PEM) != SSL_SUCCESS) { 558*a90b9d01SCy Schubert wpa_printf(MSG_INFO, 559*a90b9d01SCy Schubert "SSL: use private PEM blob failed"); 56085732ac8SCy Schubert } else { 56185732ac8SCy Schubert ok = 1; 56285732ac8SCy Schubert } 563*a90b9d01SCy Schubert } else { 564*a90b9d01SCy Schubert ok = 1; 565*a90b9d01SCy Schubert } 566*a90b9d01SCy Schubert if (ok) 567*a90b9d01SCy Schubert wpa_printf(MSG_DEBUG, "SSL: use private key blob OK"); 56885732ac8SCy Schubert } 56985732ac8SCy Schubert 57085732ac8SCy Schubert if (!ok && private_key) { 57185732ac8SCy Schubert if (wolfSSL_use_PrivateKey_file(conn->ssl, private_key, 572*a90b9d01SCy Schubert SSL_FILETYPE_PEM) != 573*a90b9d01SCy Schubert SSL_SUCCESS) { 57485732ac8SCy Schubert wpa_printf(MSG_INFO, 57585732ac8SCy Schubert "SSL: use private key PEM file failed"); 57685732ac8SCy Schubert if (wolfSSL_use_PrivateKey_file(conn->ssl, private_key, 577*a90b9d01SCy Schubert SSL_FILETYPE_ASN1) != 578*a90b9d01SCy Schubert SSL_SUCCESS) { 57985732ac8SCy Schubert wpa_printf(MSG_INFO, 58085732ac8SCy Schubert "SSL: use private key DER file failed"); 58185732ac8SCy Schubert } else { 58285732ac8SCy Schubert ok = 1; 58385732ac8SCy Schubert } 58485732ac8SCy Schubert } else { 58585732ac8SCy Schubert ok = 1; 58685732ac8SCy Schubert } 58785732ac8SCy Schubert 58885732ac8SCy Schubert if (ok) 58985732ac8SCy Schubert wpa_printf(MSG_DEBUG, "SSL: use private key file OK"); 59085732ac8SCy Schubert } 59185732ac8SCy Schubert 59285732ac8SCy Schubert wolfSSL_CTX_set_default_passwd_cb(ctx, NULL); 59385732ac8SCy Schubert os_free(passwd); 59485732ac8SCy Schubert 59585732ac8SCy Schubert if (!ok) 59685732ac8SCy Schubert return -1; 59785732ac8SCy Schubert 59885732ac8SCy Schubert return 0; 59985732ac8SCy Schubert } 60085732ac8SCy Schubert 60185732ac8SCy Schubert 60285732ac8SCy Schubert static int tls_match_alt_subject_component(WOLFSSL_X509 *cert, int type, 60385732ac8SCy Schubert const char *value, size_t len) 60485732ac8SCy Schubert { 605c1d255d3SCy Schubert WOLFSSL_GENERAL_NAME *gen; 60685732ac8SCy Schubert void *ext; 60785732ac8SCy Schubert int found = 0; 60885732ac8SCy Schubert int i; 60985732ac8SCy Schubert 61085732ac8SCy Schubert ext = wolfSSL_X509_get_ext_d2i(cert, ALT_NAMES_OID, NULL, NULL); 61185732ac8SCy Schubert 61285732ac8SCy Schubert for (i = 0; ext && i < wolfSSL_sk_num(ext); i++) { 61385732ac8SCy Schubert gen = wolfSSL_sk_value(ext, i); 614c1d255d3SCy Schubert if (!gen || gen->type != type) 61585732ac8SCy Schubert continue; 616c1d255d3SCy Schubert if ((size_t) wolfSSL_ASN1_STRING_length(gen->d.ia5) == len && 617c1d255d3SCy Schubert os_memcmp(value, wolfSSL_ASN1_STRING_data(gen->d.ia5), 618c1d255d3SCy Schubert len) == 0) 61985732ac8SCy Schubert found++; 62085732ac8SCy Schubert } 62185732ac8SCy Schubert 622c1d255d3SCy Schubert wolfSSL_sk_GENERAL_NAME_free(ext); 62385732ac8SCy Schubert 62485732ac8SCy Schubert return found; 62585732ac8SCy Schubert } 62685732ac8SCy Schubert 62785732ac8SCy Schubert 62885732ac8SCy Schubert static int tls_match_alt_subject(WOLFSSL_X509 *cert, const char *match) 62985732ac8SCy Schubert { 63085732ac8SCy Schubert int type; 63185732ac8SCy Schubert const char *pos, *end; 63285732ac8SCy Schubert size_t len; 63385732ac8SCy Schubert 63485732ac8SCy Schubert pos = match; 63585732ac8SCy Schubert do { 63685732ac8SCy Schubert if (os_strncmp(pos, "EMAIL:", 6) == 0) { 63785732ac8SCy Schubert type = GEN_EMAIL; 63885732ac8SCy Schubert pos += 6; 63985732ac8SCy Schubert } else if (os_strncmp(pos, "DNS:", 4) == 0) { 64085732ac8SCy Schubert type = GEN_DNS; 64185732ac8SCy Schubert pos += 4; 64285732ac8SCy Schubert } else if (os_strncmp(pos, "URI:", 4) == 0) { 64385732ac8SCy Schubert type = GEN_URI; 64485732ac8SCy Schubert pos += 4; 64585732ac8SCy Schubert } else { 64685732ac8SCy Schubert wpa_printf(MSG_INFO, 64785732ac8SCy Schubert "TLS: Invalid altSubjectName match '%s'", 64885732ac8SCy Schubert pos); 64985732ac8SCy Schubert return 0; 65085732ac8SCy Schubert } 65185732ac8SCy Schubert end = os_strchr(pos, ';'); 65285732ac8SCy Schubert while (end) { 65385732ac8SCy Schubert if (os_strncmp(end + 1, "EMAIL:", 6) == 0 || 65485732ac8SCy Schubert os_strncmp(end + 1, "DNS:", 4) == 0 || 65585732ac8SCy Schubert os_strncmp(end + 1, "URI:", 4) == 0) 65685732ac8SCy Schubert break; 65785732ac8SCy Schubert end = os_strchr(end + 1, ';'); 65885732ac8SCy Schubert } 65985732ac8SCy Schubert if (end) 66085732ac8SCy Schubert len = end - pos; 66185732ac8SCy Schubert else 66285732ac8SCy Schubert len = os_strlen(pos); 66385732ac8SCy Schubert if (tls_match_alt_subject_component(cert, type, pos, len) > 0) 66485732ac8SCy Schubert return 1; 66585732ac8SCy Schubert pos = end + 1; 66685732ac8SCy Schubert } while (end); 66785732ac8SCy Schubert 66885732ac8SCy Schubert return 0; 66985732ac8SCy Schubert } 67085732ac8SCy Schubert 67185732ac8SCy Schubert 67285732ac8SCy Schubert static int domain_suffix_match(const char *val, size_t len, const char *match, 6734bc52338SCy Schubert size_t match_len, int full) 67485732ac8SCy Schubert { 6754bc52338SCy Schubert size_t i; 67685732ac8SCy Schubert 67785732ac8SCy Schubert /* Check for embedded nuls that could mess up suffix matching */ 67885732ac8SCy Schubert for (i = 0; i < len; i++) { 67985732ac8SCy Schubert if (val[i] == '\0') { 68085732ac8SCy Schubert wpa_printf(MSG_DEBUG, 68185732ac8SCy Schubert "TLS: Embedded null in a string - reject"); 68285732ac8SCy Schubert return 0; 68385732ac8SCy Schubert } 68485732ac8SCy Schubert } 68585732ac8SCy Schubert 68685732ac8SCy Schubert if (match_len > len || (full && match_len != len)) 68785732ac8SCy Schubert return 0; 68885732ac8SCy Schubert 68985732ac8SCy Schubert if (os_strncasecmp(val + len - match_len, match, match_len) != 0) 69085732ac8SCy Schubert return 0; /* no match */ 69185732ac8SCy Schubert 69285732ac8SCy Schubert if (match_len == len) 69385732ac8SCy Schubert return 1; /* exact match */ 69485732ac8SCy Schubert 69585732ac8SCy Schubert if (val[len - match_len - 1] == '.') 69685732ac8SCy Schubert return 1; /* full label match completes suffix match */ 69785732ac8SCy Schubert 69885732ac8SCy Schubert wpa_printf(MSG_DEBUG, "TLS: Reject due to incomplete label match"); 69985732ac8SCy Schubert return 0; 70085732ac8SCy Schubert } 70185732ac8SCy Schubert 70285732ac8SCy Schubert 7034bc52338SCy Schubert static int tls_match_suffix_helper(WOLFSSL_X509 *cert, const char *match, 7044bc52338SCy Schubert size_t match_len, int full) 70585732ac8SCy Schubert { 706c1d255d3SCy Schubert WOLFSSL_GENERAL_NAME *gen; 70785732ac8SCy Schubert void *ext; 70885732ac8SCy Schubert int i; 70985732ac8SCy Schubert int j; 71085732ac8SCy Schubert int dns_name = 0; 71185732ac8SCy Schubert WOLFSSL_X509_NAME *name; 71285732ac8SCy Schubert 71385732ac8SCy Schubert wpa_printf(MSG_DEBUG, "TLS: Match domain against %s%s", 71485732ac8SCy Schubert full ? "" : "suffix ", match); 71585732ac8SCy Schubert 71685732ac8SCy Schubert ext = wolfSSL_X509_get_ext_d2i(cert, ALT_NAMES_OID, NULL, NULL); 71785732ac8SCy Schubert 71885732ac8SCy Schubert for (j = 0; ext && j < wolfSSL_sk_num(ext); j++) { 71985732ac8SCy Schubert gen = wolfSSL_sk_value(ext, j); 720c1d255d3SCy Schubert if (!gen || gen->type != ASN_DNS_TYPE) 72185732ac8SCy Schubert continue; 72285732ac8SCy Schubert dns_name++; 72385732ac8SCy Schubert wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate dNSName", 724c1d255d3SCy Schubert wolfSSL_ASN1_STRING_data(gen->d.ia5), 725c1d255d3SCy Schubert wolfSSL_ASN1_STRING_length(gen->d.ia5)); 726c1d255d3SCy Schubert if (domain_suffix_match( 727c1d255d3SCy Schubert (const char *) wolfSSL_ASN1_STRING_data(gen->d.ia5), 728c1d255d3SCy Schubert wolfSSL_ASN1_STRING_length(gen->d.ia5), match, 7294bc52338SCy Schubert match_len, full) == 1) { 73085732ac8SCy Schubert wpa_printf(MSG_DEBUG, "TLS: %s in dNSName found", 73185732ac8SCy Schubert full ? "Match" : "Suffix match"); 73285732ac8SCy Schubert wolfSSL_sk_ASN1_OBJECT_free(ext); 73385732ac8SCy Schubert return 1; 73485732ac8SCy Schubert } 73585732ac8SCy Schubert } 736c1d255d3SCy Schubert wolfSSL_sk_GENERAL_NAME_free(ext); 73785732ac8SCy Schubert 73885732ac8SCy Schubert if (dns_name) { 73985732ac8SCy Schubert wpa_printf(MSG_DEBUG, "TLS: None of the dNSName(s) matched"); 74085732ac8SCy Schubert return 0; 74185732ac8SCy Schubert } 74285732ac8SCy Schubert 74385732ac8SCy Schubert name = wolfSSL_X509_get_subject_name(cert); 74485732ac8SCy Schubert i = -1; 74585732ac8SCy Schubert for (;;) { 74685732ac8SCy Schubert WOLFSSL_X509_NAME_ENTRY *e; 74785732ac8SCy Schubert WOLFSSL_ASN1_STRING *cn; 74885732ac8SCy Schubert 749*a90b9d01SCy Schubert i = wolfSSL_X509_NAME_get_index_by_NID(name, NID_commonName, i); 75085732ac8SCy Schubert if (i == -1) 75185732ac8SCy Schubert break; 75285732ac8SCy Schubert e = wolfSSL_X509_NAME_get_entry(name, i); 75385732ac8SCy Schubert if (!e) 75485732ac8SCy Schubert continue; 75585732ac8SCy Schubert cn = wolfSSL_X509_NAME_ENTRY_get_data(e); 75685732ac8SCy Schubert if (!cn) 75785732ac8SCy Schubert continue; 75885732ac8SCy Schubert wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate commonName", 75985732ac8SCy Schubert cn->data, cn->length); 7604bc52338SCy Schubert if (domain_suffix_match(cn->data, cn->length, 7614bc52338SCy Schubert match, match_len, full) == 1) { 76285732ac8SCy Schubert wpa_printf(MSG_DEBUG, "TLS: %s in commonName found", 76385732ac8SCy Schubert full ? "Match" : "Suffix match"); 76485732ac8SCy Schubert return 1; 76585732ac8SCy Schubert } 76685732ac8SCy Schubert } 76785732ac8SCy Schubert 76885732ac8SCy Schubert wpa_printf(MSG_DEBUG, "TLS: No CommonName %smatch found", 76985732ac8SCy Schubert full ? "" : "suffix "); 77085732ac8SCy Schubert return 0; 77185732ac8SCy Schubert } 77285732ac8SCy Schubert 77385732ac8SCy Schubert 7744bc52338SCy Schubert static int tls_match_suffix(WOLFSSL_X509 *cert, const char *match, int full) 7754bc52338SCy Schubert { 7764bc52338SCy Schubert const char *token, *last = NULL; 7774bc52338SCy Schubert 7784bc52338SCy Schubert /* Process each match alternative separately until a match is found */ 7794bc52338SCy Schubert while ((token = cstr_token(match, ";", &last))) { 7804bc52338SCy Schubert if (tls_match_suffix_helper(cert, token, last - token, full)) 7814bc52338SCy Schubert return 1; 7824bc52338SCy Schubert } 7834bc52338SCy Schubert 7844bc52338SCy Schubert return 0; 7854bc52338SCy Schubert } 7864bc52338SCy Schubert 7874bc52338SCy Schubert 78885732ac8SCy Schubert static enum tls_fail_reason wolfssl_tls_fail_reason(int err) 78985732ac8SCy Schubert { 79085732ac8SCy Schubert switch (err) { 79185732ac8SCy Schubert case X509_V_ERR_CERT_REVOKED: 79285732ac8SCy Schubert return TLS_FAIL_REVOKED; 79385732ac8SCy Schubert case ASN_BEFORE_DATE_E: 79485732ac8SCy Schubert case X509_V_ERR_CERT_NOT_YET_VALID: 79585732ac8SCy Schubert case X509_V_ERR_CRL_NOT_YET_VALID: 79685732ac8SCy Schubert return TLS_FAIL_NOT_YET_VALID; 79785732ac8SCy Schubert case ASN_AFTER_DATE_E: 79885732ac8SCy Schubert case X509_V_ERR_CERT_HAS_EXPIRED: 79985732ac8SCy Schubert case X509_V_ERR_CRL_HAS_EXPIRED: 80085732ac8SCy Schubert return TLS_FAIL_EXPIRED; 80185732ac8SCy Schubert case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: 80285732ac8SCy Schubert case X509_V_ERR_UNABLE_TO_GET_CRL: 80385732ac8SCy Schubert case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: 80485732ac8SCy Schubert case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: 80585732ac8SCy Schubert case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: 80685732ac8SCy Schubert case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: 80785732ac8SCy Schubert case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: 80885732ac8SCy Schubert case X509_V_ERR_CERT_CHAIN_TOO_LONG: 80985732ac8SCy Schubert case X509_V_ERR_PATH_LENGTH_EXCEEDED: 81085732ac8SCy Schubert case X509_V_ERR_INVALID_CA: 81185732ac8SCy Schubert return TLS_FAIL_UNTRUSTED; 81285732ac8SCy Schubert case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: 81385732ac8SCy Schubert case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: 81485732ac8SCy Schubert case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: 81585732ac8SCy Schubert case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: 81685732ac8SCy Schubert case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: 81785732ac8SCy Schubert case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: 81885732ac8SCy Schubert case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: 81985732ac8SCy Schubert case X509_V_ERR_CERT_UNTRUSTED: 82085732ac8SCy Schubert case X509_V_ERR_CERT_REJECTED: 82185732ac8SCy Schubert return TLS_FAIL_BAD_CERTIFICATE; 82285732ac8SCy Schubert default: 82385732ac8SCy Schubert return TLS_FAIL_UNSPECIFIED; 82485732ac8SCy Schubert } 82585732ac8SCy Schubert } 82685732ac8SCy Schubert 82785732ac8SCy Schubert 82885732ac8SCy Schubert static const char * wolfssl_tls_err_string(int err, const char *err_str) 82985732ac8SCy Schubert { 83085732ac8SCy Schubert switch (err) { 83185732ac8SCy Schubert case ASN_BEFORE_DATE_E: 83285732ac8SCy Schubert return "certificate is not yet valid"; 83385732ac8SCy Schubert case ASN_AFTER_DATE_E: 83485732ac8SCy Schubert return "certificate has expired"; 83585732ac8SCy Schubert default: 83685732ac8SCy Schubert return err_str; 83785732ac8SCy Schubert } 83885732ac8SCy Schubert } 83985732ac8SCy Schubert 84085732ac8SCy Schubert 84185732ac8SCy Schubert static struct wpabuf * get_x509_cert(WOLFSSL_X509 *cert) 84285732ac8SCy Schubert { 84385732ac8SCy Schubert struct wpabuf *buf = NULL; 84485732ac8SCy Schubert const u8 *data; 84585732ac8SCy Schubert int cert_len; 84685732ac8SCy Schubert 84785732ac8SCy Schubert data = wolfSSL_X509_get_der(cert, &cert_len); 84885732ac8SCy Schubert if (!data) 84985732ac8SCy Schubert buf = wpabuf_alloc_copy(data, cert_len); 85085732ac8SCy Schubert 85185732ac8SCy Schubert return buf; 85285732ac8SCy Schubert } 85385732ac8SCy Schubert 85485732ac8SCy Schubert 85585732ac8SCy Schubert static void wolfssl_tls_fail_event(struct tls_connection *conn, 85685732ac8SCy Schubert WOLFSSL_X509 *err_cert, int err, int depth, 85785732ac8SCy Schubert const char *subject, const char *err_str, 85885732ac8SCy Schubert enum tls_fail_reason reason) 85985732ac8SCy Schubert { 86085732ac8SCy Schubert union tls_event_data ev; 86185732ac8SCy Schubert struct wpabuf *cert = NULL; 86285732ac8SCy Schubert struct tls_context *context = conn->context; 86385732ac8SCy Schubert 86485732ac8SCy Schubert if (!context->event_cb) 86585732ac8SCy Schubert return; 86685732ac8SCy Schubert 86785732ac8SCy Schubert cert = get_x509_cert(err_cert); 86885732ac8SCy Schubert os_memset(&ev, 0, sizeof(ev)); 86985732ac8SCy Schubert ev.cert_fail.reason = reason != TLS_FAIL_UNSPECIFIED ? 87085732ac8SCy Schubert reason : wolfssl_tls_fail_reason(err); 87185732ac8SCy Schubert ev.cert_fail.depth = depth; 87285732ac8SCy Schubert ev.cert_fail.subject = subject; 87385732ac8SCy Schubert ev.cert_fail.reason_txt = wolfssl_tls_err_string(err, err_str); 87485732ac8SCy Schubert ev.cert_fail.cert = cert; 87585732ac8SCy Schubert context->event_cb(context->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev); 87685732ac8SCy Schubert wpabuf_free(cert); 87785732ac8SCy Schubert } 87885732ac8SCy Schubert 87985732ac8SCy Schubert 88085732ac8SCy Schubert static void wolfssl_tls_cert_event(struct tls_connection *conn, 88185732ac8SCy Schubert WOLFSSL_X509 *err_cert, int depth, 88285732ac8SCy Schubert const char *subject) 88385732ac8SCy Schubert { 88485732ac8SCy Schubert struct wpabuf *cert = NULL; 88585732ac8SCy Schubert union tls_event_data ev; 88685732ac8SCy Schubert struct tls_context *context = conn->context; 88785732ac8SCy Schubert char *alt_subject[TLS_MAX_ALT_SUBJECT]; 88885732ac8SCy Schubert int alt, num_alt_subject = 0; 889c1d255d3SCy Schubert WOLFSSL_GENERAL_NAME *gen; 89085732ac8SCy Schubert void *ext; 89185732ac8SCy Schubert int i; 89285732ac8SCy Schubert #ifdef CONFIG_SHA256 89385732ac8SCy Schubert u8 hash[32]; 89485732ac8SCy Schubert #endif /* CONFIG_SHA256 */ 89585732ac8SCy Schubert 89685732ac8SCy Schubert if (!context->event_cb) 89785732ac8SCy Schubert return; 89885732ac8SCy Schubert 89985732ac8SCy Schubert os_memset(&ev, 0, sizeof(ev)); 90085732ac8SCy Schubert if (conn->cert_probe || (conn->flags & TLS_CONN_EXT_CERT_CHECK) || 90185732ac8SCy Schubert context->cert_in_cb) { 90285732ac8SCy Schubert cert = get_x509_cert(err_cert); 90385732ac8SCy Schubert ev.peer_cert.cert = cert; 90485732ac8SCy Schubert } 90585732ac8SCy Schubert 90685732ac8SCy Schubert #ifdef CONFIG_SHA256 90785732ac8SCy Schubert if (cert) { 90885732ac8SCy Schubert const u8 *addr[1]; 90985732ac8SCy Schubert size_t len[1]; 91085732ac8SCy Schubert 91185732ac8SCy Schubert addr[0] = wpabuf_head(cert); 91285732ac8SCy Schubert len[0] = wpabuf_len(cert); 91385732ac8SCy Schubert if (sha256_vector(1, addr, len, hash) == 0) { 91485732ac8SCy Schubert ev.peer_cert.hash = hash; 91585732ac8SCy Schubert ev.peer_cert.hash_len = sizeof(hash); 91685732ac8SCy Schubert } 91785732ac8SCy Schubert } 91885732ac8SCy Schubert #endif /* CONFIG_SHA256 */ 91985732ac8SCy Schubert 92085732ac8SCy Schubert ev.peer_cert.depth = depth; 92185732ac8SCy Schubert ev.peer_cert.subject = subject; 92285732ac8SCy Schubert 92385732ac8SCy Schubert ext = wolfSSL_X509_get_ext_d2i(err_cert, ALT_NAMES_OID, NULL, NULL); 92485732ac8SCy Schubert for (i = 0; ext && i < wolfSSL_sk_num(ext); i++) { 92585732ac8SCy Schubert char *pos; 92685732ac8SCy Schubert 92785732ac8SCy Schubert if (num_alt_subject == TLS_MAX_ALT_SUBJECT) 92885732ac8SCy Schubert break; 92985732ac8SCy Schubert gen = wolfSSL_sk_value((void *) ext, i); 930c1d255d3SCy Schubert if (!gen || 931c1d255d3SCy Schubert (gen->type != GEN_EMAIL && 93285732ac8SCy Schubert gen->type != GEN_DNS && 933c1d255d3SCy Schubert gen->type != GEN_URI)) 93485732ac8SCy Schubert continue; 93585732ac8SCy Schubert 936c1d255d3SCy Schubert pos = os_malloc(10 + wolfSSL_ASN1_STRING_length(gen->d.ia5) + 937c1d255d3SCy Schubert 1); 93885732ac8SCy Schubert if (!pos) 93985732ac8SCy Schubert break; 94085732ac8SCy Schubert alt_subject[num_alt_subject++] = pos; 94185732ac8SCy Schubert 94285732ac8SCy Schubert switch (gen->type) { 94385732ac8SCy Schubert case GEN_EMAIL: 94485732ac8SCy Schubert os_memcpy(pos, "EMAIL:", 6); 94585732ac8SCy Schubert pos += 6; 94685732ac8SCy Schubert break; 94785732ac8SCy Schubert case GEN_DNS: 94885732ac8SCy Schubert os_memcpy(pos, "DNS:", 4); 94985732ac8SCy Schubert pos += 4; 95085732ac8SCy Schubert break; 95185732ac8SCy Schubert case GEN_URI: 95285732ac8SCy Schubert os_memcpy(pos, "URI:", 4); 95385732ac8SCy Schubert pos += 4; 95485732ac8SCy Schubert break; 95585732ac8SCy Schubert } 95685732ac8SCy Schubert 957c1d255d3SCy Schubert os_memcpy(pos, wolfSSL_ASN1_STRING_data(gen->d.ia5), 958c1d255d3SCy Schubert wolfSSL_ASN1_STRING_length(gen->d.ia5)); 959c1d255d3SCy Schubert pos += wolfSSL_ASN1_STRING_length(gen->d.ia5); 96085732ac8SCy Schubert *pos = '\0'; 96185732ac8SCy Schubert } 962c1d255d3SCy Schubert wolfSSL_sk_GENERAL_NAME_free(ext); 96385732ac8SCy Schubert 96485732ac8SCy Schubert for (alt = 0; alt < num_alt_subject; alt++) 96585732ac8SCy Schubert ev.peer_cert.altsubject[alt] = alt_subject[alt]; 96685732ac8SCy Schubert ev.peer_cert.num_altsubject = num_alt_subject; 96785732ac8SCy Schubert 96885732ac8SCy Schubert context->event_cb(context->cb_ctx, TLS_PEER_CERTIFICATE, &ev); 96985732ac8SCy Schubert wpabuf_free(cert); 97085732ac8SCy Schubert for (alt = 0; alt < num_alt_subject; alt++) 97185732ac8SCy Schubert os_free(alt_subject[alt]); 97285732ac8SCy Schubert } 97385732ac8SCy Schubert 97485732ac8SCy Schubert 97585732ac8SCy Schubert static int tls_verify_cb(int preverify_ok, WOLFSSL_X509_STORE_CTX *x509_ctx) 97685732ac8SCy Schubert { 97785732ac8SCy Schubert char buf[256]; 97885732ac8SCy Schubert WOLFSSL_X509 *err_cert; 97985732ac8SCy Schubert int err, depth; 98085732ac8SCy Schubert WOLFSSL *ssl; 98185732ac8SCy Schubert struct tls_connection *conn; 98285732ac8SCy Schubert struct tls_context *context; 98385732ac8SCy Schubert char *match, *altmatch, *suffix_match, *domain_match; 98485732ac8SCy Schubert const char *err_str; 98585732ac8SCy Schubert 98685732ac8SCy Schubert err_cert = wolfSSL_X509_STORE_CTX_get_current_cert(x509_ctx); 98785732ac8SCy Schubert if (!err_cert) { 98885732ac8SCy Schubert wpa_printf(MSG_DEBUG, "wolfSSL: No Cert"); 98985732ac8SCy Schubert return 0; 99085732ac8SCy Schubert } 99185732ac8SCy Schubert 99285732ac8SCy Schubert err = wolfSSL_X509_STORE_CTX_get_error(x509_ctx); 99385732ac8SCy Schubert depth = wolfSSL_X509_STORE_CTX_get_error_depth(x509_ctx); 99485732ac8SCy Schubert ssl = wolfSSL_X509_STORE_CTX_get_ex_data( 99585732ac8SCy Schubert x509_ctx, wolfSSL_get_ex_data_X509_STORE_CTX_idx()); 99685732ac8SCy Schubert wolfSSL_X509_NAME_oneline(wolfSSL_X509_get_subject_name(err_cert), buf, 99785732ac8SCy Schubert sizeof(buf)); 99885732ac8SCy Schubert 99985732ac8SCy Schubert conn = wolfSSL_get_ex_data(ssl, 0); 100085732ac8SCy Schubert if (!conn) { 100185732ac8SCy Schubert wpa_printf(MSG_DEBUG, "wolfSSL: No ex_data"); 100285732ac8SCy Schubert return 0; 100385732ac8SCy Schubert } 100485732ac8SCy Schubert 100585732ac8SCy Schubert if (depth == 0) 100685732ac8SCy Schubert conn->peer_cert = err_cert; 100785732ac8SCy Schubert else if (depth == 1) 100885732ac8SCy Schubert conn->peer_issuer = err_cert; 100985732ac8SCy Schubert else if (depth == 2) 101085732ac8SCy Schubert conn->peer_issuer_issuer = err_cert; 101185732ac8SCy Schubert 101285732ac8SCy Schubert context = conn->context; 101385732ac8SCy Schubert match = conn->subject_match; 101485732ac8SCy Schubert altmatch = conn->alt_subject_match; 101585732ac8SCy Schubert suffix_match = conn->suffix_match; 101685732ac8SCy Schubert domain_match = conn->domain_match; 101785732ac8SCy Schubert 101885732ac8SCy Schubert if (!preverify_ok && !conn->ca_cert_verify) 101985732ac8SCy Schubert preverify_ok = 1; 102085732ac8SCy Schubert if (!preverify_ok && depth > 0 && conn->server_cert_only) 102185732ac8SCy Schubert preverify_ok = 1; 102285732ac8SCy Schubert if (!preverify_ok && (conn->flags & TLS_CONN_DISABLE_TIME_CHECKS) && 102385732ac8SCy Schubert (err == X509_V_ERR_CERT_HAS_EXPIRED || 102485732ac8SCy Schubert err == ASN_AFTER_DATE_E || err == ASN_BEFORE_DATE_E || 102585732ac8SCy Schubert err == X509_V_ERR_CERT_NOT_YET_VALID)) { 102685732ac8SCy Schubert wpa_printf(MSG_DEBUG, 102785732ac8SCy Schubert "wolfSSL: Ignore certificate validity time mismatch"); 102885732ac8SCy Schubert preverify_ok = 1; 102985732ac8SCy Schubert } 103085732ac8SCy Schubert 103185732ac8SCy Schubert err_str = wolfSSL_X509_verify_cert_error_string(err); 103285732ac8SCy Schubert 103385732ac8SCy Schubert #ifdef CONFIG_SHA256 103485732ac8SCy Schubert /* 103585732ac8SCy Schubert * Do not require preverify_ok so we can explicity allow otherwise 103685732ac8SCy Schubert * invalid pinned server certificates. 103785732ac8SCy Schubert */ 103885732ac8SCy Schubert if (depth == 0 && conn->server_cert_only) { 103985732ac8SCy Schubert struct wpabuf *cert; 104085732ac8SCy Schubert 104185732ac8SCy Schubert cert = get_x509_cert(err_cert); 104285732ac8SCy Schubert if (!cert) { 104385732ac8SCy Schubert wpa_printf(MSG_DEBUG, 104485732ac8SCy Schubert "wolfSSL: Could not fetch server certificate data"); 104585732ac8SCy Schubert preverify_ok = 0; 104685732ac8SCy Schubert } else { 104785732ac8SCy Schubert u8 hash[32]; 104885732ac8SCy Schubert const u8 *addr[1]; 104985732ac8SCy Schubert size_t len[1]; 105085732ac8SCy Schubert 105185732ac8SCy Schubert addr[0] = wpabuf_head(cert); 105285732ac8SCy Schubert len[0] = wpabuf_len(cert); 105385732ac8SCy Schubert if (sha256_vector(1, addr, len, hash) < 0 || 105485732ac8SCy Schubert os_memcmp(conn->srv_cert_hash, hash, 32) != 0) { 105585732ac8SCy Schubert err_str = "Server certificate mismatch"; 105685732ac8SCy Schubert err = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN; 105785732ac8SCy Schubert preverify_ok = 0; 105885732ac8SCy Schubert } else if (!preverify_ok) { 105985732ac8SCy Schubert /* 106085732ac8SCy Schubert * Certificate matches pinned certificate, allow 106185732ac8SCy Schubert * regardless of other problems. 106285732ac8SCy Schubert */ 106385732ac8SCy Schubert wpa_printf(MSG_DEBUG, 106485732ac8SCy Schubert "wolfSSL: Ignore validation issues for a pinned server certificate"); 106585732ac8SCy Schubert preverify_ok = 1; 106685732ac8SCy Schubert } 106785732ac8SCy Schubert wpabuf_free(cert); 106885732ac8SCy Schubert } 106985732ac8SCy Schubert } 107085732ac8SCy Schubert #endif /* CONFIG_SHA256 */ 107185732ac8SCy Schubert 107285732ac8SCy Schubert if (!preverify_ok) { 107385732ac8SCy Schubert wpa_printf(MSG_WARNING, 107485732ac8SCy Schubert "TLS: Certificate verification failed, error %d (%s) depth %d for '%s'", 107585732ac8SCy Schubert err, err_str, depth, buf); 107685732ac8SCy Schubert wolfssl_tls_fail_event(conn, err_cert, err, depth, buf, 107785732ac8SCy Schubert err_str, TLS_FAIL_UNSPECIFIED); 107885732ac8SCy Schubert return preverify_ok; 107985732ac8SCy Schubert } 108085732ac8SCy Schubert 108185732ac8SCy Schubert wpa_printf(MSG_DEBUG, 108285732ac8SCy Schubert "TLS: %s - preverify_ok=%d err=%d (%s) ca_cert_verify=%d depth=%d buf='%s'", 108385732ac8SCy Schubert __func__, preverify_ok, err, err_str, 108485732ac8SCy Schubert conn->ca_cert_verify, depth, buf); 108585732ac8SCy Schubert if (depth == 0 && match && os_strstr(buf, match) == NULL) { 108685732ac8SCy Schubert wpa_printf(MSG_WARNING, 108785732ac8SCy Schubert "TLS: Subject '%s' did not match with '%s'", 108885732ac8SCy Schubert buf, match); 108985732ac8SCy Schubert preverify_ok = 0; 109085732ac8SCy Schubert wolfssl_tls_fail_event(conn, err_cert, err, depth, buf, 109185732ac8SCy Schubert "Subject mismatch", 109285732ac8SCy Schubert TLS_FAIL_SUBJECT_MISMATCH); 109385732ac8SCy Schubert } else if (depth == 0 && altmatch && 109485732ac8SCy Schubert !tls_match_alt_subject(err_cert, altmatch)) { 109585732ac8SCy Schubert wpa_printf(MSG_WARNING, 109685732ac8SCy Schubert "TLS: altSubjectName match '%s' not found", 109785732ac8SCy Schubert altmatch); 109885732ac8SCy Schubert preverify_ok = 0; 109985732ac8SCy Schubert wolfssl_tls_fail_event(conn, err_cert, err, depth, buf, 110085732ac8SCy Schubert "AltSubject mismatch", 110185732ac8SCy Schubert TLS_FAIL_ALTSUBJECT_MISMATCH); 110285732ac8SCy Schubert } else if (depth == 0 && suffix_match && 110385732ac8SCy Schubert !tls_match_suffix(err_cert, suffix_match, 0)) { 110485732ac8SCy Schubert wpa_printf(MSG_WARNING, 110585732ac8SCy Schubert "TLS: Domain suffix match '%s' not found", 110685732ac8SCy Schubert suffix_match); 110785732ac8SCy Schubert preverify_ok = 0; 110885732ac8SCy Schubert wolfssl_tls_fail_event(conn, err_cert, err, depth, buf, 110985732ac8SCy Schubert "Domain suffix mismatch", 111085732ac8SCy Schubert TLS_FAIL_DOMAIN_SUFFIX_MISMATCH); 111185732ac8SCy Schubert } else if (depth == 0 && domain_match && 111285732ac8SCy Schubert !tls_match_suffix(err_cert, domain_match, 1)) { 111385732ac8SCy Schubert wpa_printf(MSG_WARNING, "TLS: Domain match '%s' not found", 111485732ac8SCy Schubert domain_match); 111585732ac8SCy Schubert preverify_ok = 0; 111685732ac8SCy Schubert wolfssl_tls_fail_event(conn, err_cert, err, depth, buf, 111785732ac8SCy Schubert "Domain mismatch", 111885732ac8SCy Schubert TLS_FAIL_DOMAIN_MISMATCH); 111985732ac8SCy Schubert } else { 112085732ac8SCy Schubert wolfssl_tls_cert_event(conn, err_cert, depth, buf); 112185732ac8SCy Schubert } 112285732ac8SCy Schubert 112385732ac8SCy Schubert if (conn->cert_probe && preverify_ok && depth == 0) { 112485732ac8SCy Schubert wpa_printf(MSG_DEBUG, 112585732ac8SCy Schubert "wolfSSL: Reject server certificate on probe-only run"); 112685732ac8SCy Schubert preverify_ok = 0; 112785732ac8SCy Schubert wolfssl_tls_fail_event(conn, err_cert, err, depth, buf, 112885732ac8SCy Schubert "Server certificate chain probe", 112985732ac8SCy Schubert TLS_FAIL_SERVER_CHAIN_PROBE); 113085732ac8SCy Schubert } 113185732ac8SCy Schubert 113285732ac8SCy Schubert #ifdef HAVE_OCSP_WOLFSSL 113385732ac8SCy Schubert if (depth == 0 && (conn->flags & TLS_CONN_REQUEST_OCSP) && 113485732ac8SCy Schubert preverify_ok) { 113585732ac8SCy Schubert enum ocsp_result res; 113685732ac8SCy Schubert 113785732ac8SCy Schubert res = check_ocsp_resp(conn->ssl_ctx, conn->ssl, err_cert, 113885732ac8SCy Schubert conn->peer_issuer, 113985732ac8SCy Schubert conn->peer_issuer_issuer); 114085732ac8SCy Schubert if (res == OCSP_REVOKED) { 114185732ac8SCy Schubert preverify_ok = 0; 114285732ac8SCy Schubert wolfssl_tls_fail_event(conn, err_cert, err, depth, buf, 114385732ac8SCy Schubert "certificate revoked", 114485732ac8SCy Schubert TLS_FAIL_REVOKED); 114585732ac8SCy Schubert if (err == X509_V_OK) 114685732ac8SCy Schubert X509_STORE_CTX_set_error( 114785732ac8SCy Schubert x509_ctx, X509_V_ERR_CERT_REVOKED); 114885732ac8SCy Schubert } else if (res != OCSP_GOOD && 114985732ac8SCy Schubert (conn->flags & TLS_CONN_REQUIRE_OCSP)) { 115085732ac8SCy Schubert preverify_ok = 0; 115185732ac8SCy Schubert wolfssl_tls_fail_event(conn, err_cert, err, depth, buf, 115285732ac8SCy Schubert "bad certificate status response", 115385732ac8SCy Schubert TLS_FAIL_UNSPECIFIED); 115485732ac8SCy Schubert } 115585732ac8SCy Schubert } 115685732ac8SCy Schubert #endif /* HAVE_OCSP_WOLFSSL */ 115785732ac8SCy Schubert if (depth == 0 && preverify_ok && context->event_cb != NULL) 115885732ac8SCy Schubert context->event_cb(context->cb_ctx, 115985732ac8SCy Schubert TLS_CERT_CHAIN_SUCCESS, NULL); 116085732ac8SCy Schubert 1161*a90b9d01SCy Schubert if (depth == 0 && preverify_ok) { 1162*a90b9d01SCy Schubert os_free(conn->peer_subject); 1163*a90b9d01SCy Schubert conn->peer_subject = os_strdup(buf); 1164*a90b9d01SCy Schubert } 1165*a90b9d01SCy Schubert 116685732ac8SCy Schubert return preverify_ok; 116785732ac8SCy Schubert } 116885732ac8SCy Schubert 116985732ac8SCy Schubert 117085732ac8SCy Schubert static int tls_connection_ca_cert(void *tls_ctx, struct tls_connection *conn, 117185732ac8SCy Schubert const char *ca_cert, 117285732ac8SCy Schubert const u8 *ca_cert_blob, size_t blob_len, 117385732ac8SCy Schubert const char *ca_path) 117485732ac8SCy Schubert { 117585732ac8SCy Schubert WOLFSSL_CTX *ctx = tls_ctx; 117685732ac8SCy Schubert 117785732ac8SCy Schubert wolfSSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); 117885732ac8SCy Schubert conn->ca_cert_verify = 1; 117985732ac8SCy Schubert 118085732ac8SCy Schubert if (ca_cert && os_strncmp(ca_cert, "probe://", 8) == 0) { 118185732ac8SCy Schubert wpa_printf(MSG_DEBUG, 118285732ac8SCy Schubert "wolfSSL: Probe for server certificate chain"); 118385732ac8SCy Schubert conn->cert_probe = 1; 118485732ac8SCy Schubert conn->ca_cert_verify = 0; 118585732ac8SCy Schubert return 0; 118685732ac8SCy Schubert } 118785732ac8SCy Schubert 118885732ac8SCy Schubert if (ca_cert && os_strncmp(ca_cert, "hash://", 7) == 0) { 118985732ac8SCy Schubert #ifdef CONFIG_SHA256 119085732ac8SCy Schubert const char *pos = ca_cert + 7; 119185732ac8SCy Schubert 119285732ac8SCy Schubert if (os_strncmp(pos, "server/sha256/", 14) != 0) { 119385732ac8SCy Schubert wpa_printf(MSG_DEBUG, 119485732ac8SCy Schubert "wolfSSL: Unsupported ca_cert hash value '%s'", 119585732ac8SCy Schubert ca_cert); 119685732ac8SCy Schubert return -1; 119785732ac8SCy Schubert } 119885732ac8SCy Schubert pos += 14; 119985732ac8SCy Schubert if (os_strlen(pos) != 32 * 2) { 120085732ac8SCy Schubert wpa_printf(MSG_DEBUG, 120185732ac8SCy Schubert "wolfSSL: Unexpected SHA256 hash length in ca_cert '%s'", 120285732ac8SCy Schubert ca_cert); 120385732ac8SCy Schubert return -1; 120485732ac8SCy Schubert } 120585732ac8SCy Schubert if (hexstr2bin(pos, conn->srv_cert_hash, 32) < 0) { 120685732ac8SCy Schubert wpa_printf(MSG_DEBUG, 120785732ac8SCy Schubert "wolfSSL: Invalid SHA256 hash value in ca_cert '%s'", 120885732ac8SCy Schubert ca_cert); 120985732ac8SCy Schubert return -1; 121085732ac8SCy Schubert } 121185732ac8SCy Schubert conn->server_cert_only = 1; 121285732ac8SCy Schubert wpa_printf(MSG_DEBUG, 121385732ac8SCy Schubert "wolfSSL: Checking only server certificate match"); 121485732ac8SCy Schubert return 0; 121585732ac8SCy Schubert #else /* CONFIG_SHA256 */ 121685732ac8SCy Schubert wpa_printf(MSG_INFO, 121785732ac8SCy Schubert "No SHA256 included in the build - cannot validate server certificate hash"); 121885732ac8SCy Schubert return -1; 121985732ac8SCy Schubert #endif /* CONFIG_SHA256 */ 122085732ac8SCy Schubert } 122185732ac8SCy Schubert 122285732ac8SCy Schubert if (ca_cert_blob) { 122385732ac8SCy Schubert if (wolfSSL_CTX_load_verify_buffer(ctx, ca_cert_blob, blob_len, 122485732ac8SCy Schubert SSL_FILETYPE_ASN1) != 122585732ac8SCy Schubert SSL_SUCCESS) { 1226*a90b9d01SCy Schubert wpa_printf(MSG_INFO, "SSL: failed to load DER CA blob"); 1227*a90b9d01SCy Schubert if (wolfSSL_CTX_load_verify_buffer( 1228*a90b9d01SCy Schubert ctx, ca_cert_blob, blob_len, 1229*a90b9d01SCy Schubert SSL_FILETYPE_PEM) != SSL_SUCCESS) { 1230*a90b9d01SCy Schubert wpa_printf(MSG_INFO, 1231*a90b9d01SCy Schubert "SSL: failed to load PEM CA blob"); 123285732ac8SCy Schubert return -1; 123385732ac8SCy Schubert } 1234*a90b9d01SCy Schubert } 123585732ac8SCy Schubert wpa_printf(MSG_DEBUG, "SSL: use CA cert blob OK"); 123685732ac8SCy Schubert return 0; 123785732ac8SCy Schubert } 123885732ac8SCy Schubert 123985732ac8SCy Schubert if (ca_cert || ca_path) { 124085732ac8SCy Schubert WOLFSSL_X509_STORE *cm = wolfSSL_X509_STORE_new(); 124185732ac8SCy Schubert 124285732ac8SCy Schubert if (!cm) { 124385732ac8SCy Schubert wpa_printf(MSG_INFO, 124485732ac8SCy Schubert "SSL: failed to create certificate store"); 124585732ac8SCy Schubert return -1; 124685732ac8SCy Schubert } 124785732ac8SCy Schubert wolfSSL_CTX_set_cert_store(ctx, cm); 124885732ac8SCy Schubert 124985732ac8SCy Schubert if (wolfSSL_CTX_load_verify_locations(ctx, ca_cert, ca_path) != 125085732ac8SCy Schubert SSL_SUCCESS) { 125185732ac8SCy Schubert wpa_printf(MSG_INFO, 125285732ac8SCy Schubert "SSL: failed to load ca_cert as PEM"); 125385732ac8SCy Schubert 125485732ac8SCy Schubert if (!ca_cert) 125585732ac8SCy Schubert return -1; 125685732ac8SCy Schubert 125785732ac8SCy Schubert if (wolfSSL_CTX_der_load_verify_locations( 125885732ac8SCy Schubert ctx, ca_cert, SSL_FILETYPE_ASN1) != 125985732ac8SCy Schubert SSL_SUCCESS) { 126085732ac8SCy Schubert wpa_printf(MSG_INFO, 126185732ac8SCy Schubert "SSL: failed to load ca_cert as DER"); 126285732ac8SCy Schubert return -1; 126385732ac8SCy Schubert } 126485732ac8SCy Schubert } 126585732ac8SCy Schubert return 0; 126685732ac8SCy Schubert } 126785732ac8SCy Schubert 126885732ac8SCy Schubert conn->ca_cert_verify = 0; 126985732ac8SCy Schubert return 0; 127085732ac8SCy Schubert } 127185732ac8SCy Schubert 127285732ac8SCy Schubert 127385732ac8SCy Schubert static void tls_set_conn_flags(WOLFSSL *ssl, unsigned int flags) 127485732ac8SCy Schubert { 127585732ac8SCy Schubert #ifdef HAVE_SESSION_TICKET 127685732ac8SCy Schubert if (!(flags & TLS_CONN_DISABLE_SESSION_TICKET)) 127785732ac8SCy Schubert wolfSSL_UseSessionTicket(ssl); 127885732ac8SCy Schubert #endif /* HAVE_SESSION_TICKET */ 127985732ac8SCy Schubert 128085732ac8SCy Schubert if (flags & TLS_CONN_DISABLE_TLSv1_0) 128185732ac8SCy Schubert wolfSSL_set_options(ssl, SSL_OP_NO_TLSv1); 128285732ac8SCy Schubert if (flags & TLS_CONN_DISABLE_TLSv1_1) 128385732ac8SCy Schubert wolfSSL_set_options(ssl, SSL_OP_NO_TLSv1_1); 128485732ac8SCy Schubert if (flags & TLS_CONN_DISABLE_TLSv1_2) 128585732ac8SCy Schubert wolfSSL_set_options(ssl, SSL_OP_NO_TLSv1_2); 1286*a90b9d01SCy Schubert if (flags & TLS_CONN_DISABLE_TLSv1_3) 1287*a90b9d01SCy Schubert wolfSSL_set_options(ssl, SSL_OP_NO_TLSv1_3); 128885732ac8SCy Schubert } 128985732ac8SCy Schubert 129085732ac8SCy Schubert 129185732ac8SCy Schubert int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, 129285732ac8SCy Schubert const struct tls_connection_params *params) 129385732ac8SCy Schubert { 129485732ac8SCy Schubert wpa_printf(MSG_DEBUG, "SSL: set params"); 129585732ac8SCy Schubert 129685732ac8SCy Schubert if (tls_connection_set_subject_match(conn, params->subject_match, 129785732ac8SCy Schubert params->altsubject_match, 129885732ac8SCy Schubert params->suffix_match, 129985732ac8SCy Schubert params->domain_match) < 0) { 130085732ac8SCy Schubert wpa_printf(MSG_INFO, "Error setting subject match"); 130185732ac8SCy Schubert return -1; 130285732ac8SCy Schubert } 130385732ac8SCy Schubert 130485732ac8SCy Schubert if (tls_connection_ca_cert(tls_ctx, conn, params->ca_cert, 130585732ac8SCy Schubert params->ca_cert_blob, 130685732ac8SCy Schubert params->ca_cert_blob_len, 130785732ac8SCy Schubert params->ca_path) < 0) { 130885732ac8SCy Schubert wpa_printf(MSG_INFO, "Error setting CA cert"); 130985732ac8SCy Schubert return -1; 131085732ac8SCy Schubert } 131185732ac8SCy Schubert 131285732ac8SCy Schubert if (tls_connection_client_cert(conn, params->client_cert, 131385732ac8SCy Schubert params->client_cert_blob, 131485732ac8SCy Schubert params->client_cert_blob_len) < 0) { 131585732ac8SCy Schubert wpa_printf(MSG_INFO, "Error setting client cert"); 131685732ac8SCy Schubert return -1; 131785732ac8SCy Schubert } 131885732ac8SCy Schubert 131985732ac8SCy Schubert if (tls_connection_private_key(tls_ctx, conn, params->private_key, 132085732ac8SCy Schubert params->private_key_passwd, 132185732ac8SCy Schubert params->private_key_blob, 132285732ac8SCy Schubert params->private_key_blob_len) < 0) { 132385732ac8SCy Schubert wpa_printf(MSG_INFO, "Error setting private key"); 132485732ac8SCy Schubert return -1; 132585732ac8SCy Schubert } 132685732ac8SCy Schubert 1327*a90b9d01SCy Schubert wpa_printf(MSG_DEBUG, "wolfSSL: cipher suites: %s", 1328*a90b9d01SCy Schubert params->openssl_ciphers ? params->openssl_ciphers : "N/A"); 132985732ac8SCy Schubert if (params->openssl_ciphers && 133085732ac8SCy Schubert wolfSSL_set_cipher_list(conn->ssl, params->openssl_ciphers) != 1) { 133185732ac8SCy Schubert wpa_printf(MSG_INFO, 133285732ac8SCy Schubert "wolfSSL: Failed to set cipher string '%s'", 133385732ac8SCy Schubert params->openssl_ciphers); 133485732ac8SCy Schubert return -1; 133585732ac8SCy Schubert } 133685732ac8SCy Schubert 133785732ac8SCy Schubert tls_set_conn_flags(conn->ssl, params->flags); 133885732ac8SCy Schubert 133985732ac8SCy Schubert #ifdef HAVE_CERTIFICATE_STATUS_REQUEST 134085732ac8SCy Schubert if (params->flags & TLS_CONN_REQUEST_OCSP) { 134185732ac8SCy Schubert if (wolfSSL_UseOCSPStapling(conn->ssl, WOLFSSL_CSR_OCSP, 134285732ac8SCy Schubert WOLFSSL_CSR_OCSP_USE_NONCE) != 134385732ac8SCy Schubert SSL_SUCCESS) 134485732ac8SCy Schubert return -1; 1345*a90b9d01SCy Schubert if (wolfSSL_EnableOCSPStapling(conn->ssl) != SSL_SUCCESS) 1346*a90b9d01SCy Schubert return -1; 134785732ac8SCy Schubert } 134885732ac8SCy Schubert #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ 134985732ac8SCy Schubert #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 135085732ac8SCy Schubert if (params->flags & TLS_CONN_REQUEST_OCSP) { 135185732ac8SCy Schubert if (wolfSSL_UseOCSPStaplingV2(conn->ssl, 135285732ac8SCy Schubert WOLFSSL_CSR2_OCSP_MULTI, 0) != 135385732ac8SCy Schubert SSL_SUCCESS) 135485732ac8SCy Schubert return -1; 1355*a90b9d01SCy Schubert if (wolfSSL_EnableOCSPStapling(conn->ssl) != SSL_SUCCESS) 1356*a90b9d01SCy Schubert return -1; 135785732ac8SCy Schubert } 135885732ac8SCy Schubert #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ 135985732ac8SCy Schubert #if !defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \ 136085732ac8SCy Schubert !defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) 136185732ac8SCy Schubert #ifdef HAVE_OCSP 136285732ac8SCy Schubert if (params->flags & TLS_CONN_REQUEST_OCSP) 136385732ac8SCy Schubert wolfSSL_CTX_EnableOCSP(ctx, 0); 136485732ac8SCy Schubert #else /* HAVE_OCSP */ 136585732ac8SCy Schubert if (params->flags & TLS_CONN_REQUIRE_OCSP) { 136685732ac8SCy Schubert wpa_printf(MSG_INFO, 136785732ac8SCy Schubert "wolfSSL: No OCSP support included - reject configuration"); 136885732ac8SCy Schubert return -1; 136985732ac8SCy Schubert } 137085732ac8SCy Schubert if (params->flags & TLS_CONN_REQUEST_OCSP) { 137185732ac8SCy Schubert wpa_printf(MSG_DEBUG, 137285732ac8SCy Schubert "wolfSSL: No OCSP support included - allow optional OCSP case to continue"); 137385732ac8SCy Schubert } 137485732ac8SCy Schubert #endif /* HAVE_OCSP */ 137585732ac8SCy Schubert #endif /* !HAVE_CERTIFICATE_STATUS_REQUEST && 137685732ac8SCy Schubert * !HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ 137785732ac8SCy Schubert 137885732ac8SCy Schubert conn->flags = params->flags; 137985732ac8SCy Schubert 138085732ac8SCy Schubert return 0; 138185732ac8SCy Schubert } 138285732ac8SCy Schubert 138385732ac8SCy Schubert 138485732ac8SCy Schubert static int tls_global_ca_cert(void *ssl_ctx, const char *ca_cert) 138585732ac8SCy Schubert { 138685732ac8SCy Schubert WOLFSSL_CTX *ctx = ssl_ctx; 138785732ac8SCy Schubert 138885732ac8SCy Schubert if (ca_cert) { 138985732ac8SCy Schubert if (wolfSSL_CTX_load_verify_locations(ctx, ca_cert, NULL) != 1) 139085732ac8SCy Schubert { 139185732ac8SCy Schubert wpa_printf(MSG_WARNING, 139285732ac8SCy Schubert "Failed to load root certificates"); 139385732ac8SCy Schubert return -1; 139485732ac8SCy Schubert } 139585732ac8SCy Schubert 139685732ac8SCy Schubert wpa_printf(MSG_DEBUG, 139785732ac8SCy Schubert "TLS: Trusted root certificate(s) loaded"); 139885732ac8SCy Schubert } 139985732ac8SCy Schubert 140085732ac8SCy Schubert return 0; 140185732ac8SCy Schubert } 140285732ac8SCy Schubert 140385732ac8SCy Schubert 140485732ac8SCy Schubert static int tls_global_client_cert(void *ssl_ctx, const char *client_cert) 140585732ac8SCy Schubert { 140685732ac8SCy Schubert WOLFSSL_CTX *ctx = ssl_ctx; 140785732ac8SCy Schubert 140885732ac8SCy Schubert if (!client_cert) 140985732ac8SCy Schubert return 0; 141085732ac8SCy Schubert 141185732ac8SCy Schubert if (wolfSSL_CTX_use_certificate_chain_file_format(ctx, client_cert, 141285732ac8SCy Schubert SSL_FILETYPE_ASN1) != 141385732ac8SCy Schubert SSL_SUCCESS && 141485732ac8SCy Schubert wolfSSL_CTX_use_certificate_chain_file(ctx, client_cert) != 141585732ac8SCy Schubert SSL_SUCCESS) { 141685732ac8SCy Schubert wpa_printf(MSG_INFO, "Failed to load client certificate"); 141785732ac8SCy Schubert return -1; 141885732ac8SCy Schubert } 141985732ac8SCy Schubert 142085732ac8SCy Schubert wpa_printf(MSG_DEBUG, "SSL: Loaded global client certificate: %s", 142185732ac8SCy Schubert client_cert); 142285732ac8SCy Schubert 142385732ac8SCy Schubert return 0; 142485732ac8SCy Schubert } 142585732ac8SCy Schubert 142685732ac8SCy Schubert 142785732ac8SCy Schubert static int tls_global_private_key(void *ssl_ctx, const char *private_key, 142885732ac8SCy Schubert const char *private_key_passwd) 142985732ac8SCy Schubert { 143085732ac8SCy Schubert WOLFSSL_CTX *ctx = ssl_ctx; 143185732ac8SCy Schubert char *passwd = NULL; 143285732ac8SCy Schubert int ret = 0; 143385732ac8SCy Schubert 143485732ac8SCy Schubert if (!private_key) 143585732ac8SCy Schubert return 0; 143685732ac8SCy Schubert 143785732ac8SCy Schubert if (private_key_passwd) { 143885732ac8SCy Schubert passwd = os_strdup(private_key_passwd); 143985732ac8SCy Schubert if (!passwd) 144085732ac8SCy Schubert return -1; 144185732ac8SCy Schubert } 144285732ac8SCy Schubert 144385732ac8SCy Schubert wolfSSL_CTX_set_default_passwd_cb(ctx, tls_passwd_cb); 144485732ac8SCy Schubert wolfSSL_CTX_set_default_passwd_cb_userdata(ctx, passwd); 144585732ac8SCy Schubert 144685732ac8SCy Schubert if (wolfSSL_CTX_use_PrivateKey_file(ctx, private_key, 144785732ac8SCy Schubert SSL_FILETYPE_ASN1) != 1 && 144885732ac8SCy Schubert wolfSSL_CTX_use_PrivateKey_file(ctx, private_key, 144985732ac8SCy Schubert SSL_FILETYPE_PEM) != 1) { 145085732ac8SCy Schubert wpa_printf(MSG_INFO, "Failed to load private key"); 145185732ac8SCy Schubert ret = -1; 145285732ac8SCy Schubert } 145385732ac8SCy Schubert 145485732ac8SCy Schubert wpa_printf(MSG_DEBUG, "SSL: Loaded global private key"); 145585732ac8SCy Schubert 145685732ac8SCy Schubert os_free(passwd); 145785732ac8SCy Schubert wolfSSL_CTX_set_default_passwd_cb(ctx, NULL); 145885732ac8SCy Schubert 145985732ac8SCy Schubert return ret; 146085732ac8SCy Schubert } 146185732ac8SCy Schubert 146285732ac8SCy Schubert 1463*a90b9d01SCy Schubert static int tls_global_dh(void *ssl_ctx, const char *dh_file) 146485732ac8SCy Schubert { 146585732ac8SCy Schubert WOLFSSL_CTX *ctx = ssl_ctx; 146685732ac8SCy Schubert 146785732ac8SCy Schubert if (dh_file) { 146885732ac8SCy Schubert if (wolfSSL_CTX_SetTmpDH_file(ctx, dh_file, SSL_FILETYPE_PEM) < 146985732ac8SCy Schubert 0) { 147085732ac8SCy Schubert wpa_printf(MSG_INFO, 147185732ac8SCy Schubert "SSL: global use DH PEM file failed"); 147285732ac8SCy Schubert if (wolfSSL_CTX_SetTmpDH_file(ctx, dh_file, 147385732ac8SCy Schubert SSL_FILETYPE_ASN1) < 0) { 147485732ac8SCy Schubert wpa_printf(MSG_INFO, 147585732ac8SCy Schubert "SSL: global use DH DER file failed"); 147685732ac8SCy Schubert return -1; 147785732ac8SCy Schubert } 147885732ac8SCy Schubert } 147985732ac8SCy Schubert wpa_printf(MSG_DEBUG, "SSL: global use DH file OK"); 148085732ac8SCy Schubert return 0; 148185732ac8SCy Schubert } 148285732ac8SCy Schubert 148385732ac8SCy Schubert return 0; 148485732ac8SCy Schubert } 148585732ac8SCy Schubert 148685732ac8SCy Schubert 148785732ac8SCy Schubert #ifdef HAVE_OCSP 148885732ac8SCy Schubert 148985732ac8SCy Schubert int ocsp_status_cb(void *unused, const char *url, int url_sz, 149085732ac8SCy Schubert unsigned char *request, int request_sz, 149185732ac8SCy Schubert unsigned char **response) 149285732ac8SCy Schubert { 149385732ac8SCy Schubert size_t len; 149485732ac8SCy Schubert 149585732ac8SCy Schubert (void) unused; 149685732ac8SCy Schubert 149785732ac8SCy Schubert if (!url) { 149885732ac8SCy Schubert wpa_printf(MSG_DEBUG, 149985732ac8SCy Schubert "wolfSSL: OCSP status callback - no response configured"); 150085732ac8SCy Schubert *response = NULL; 150185732ac8SCy Schubert return 0; 150285732ac8SCy Schubert } 150385732ac8SCy Schubert 150485732ac8SCy Schubert *response = (unsigned char *) os_readfile(url, &len); 150585732ac8SCy Schubert if (!*response) { 150685732ac8SCy Schubert wpa_printf(MSG_DEBUG, 150785732ac8SCy Schubert "wolfSSL: OCSP status callback - could not read response file"); 150885732ac8SCy Schubert return -1; 150985732ac8SCy Schubert } 151085732ac8SCy Schubert wpa_printf(MSG_DEBUG, 151185732ac8SCy Schubert "wolfSSL: OCSP status callback - send cached response"); 151285732ac8SCy Schubert return len; 151385732ac8SCy Schubert } 151485732ac8SCy Schubert 151585732ac8SCy Schubert 151685732ac8SCy Schubert void ocsp_resp_free_cb(void *ocsp_stapling_response, unsigned char *response) 151785732ac8SCy Schubert { 151885732ac8SCy Schubert os_free(response); 151985732ac8SCy Schubert } 152085732ac8SCy Schubert 152185732ac8SCy Schubert #endif /* HAVE_OCSP */ 152285732ac8SCy Schubert 152385732ac8SCy Schubert 152485732ac8SCy Schubert int tls_global_set_params(void *tls_ctx, 152585732ac8SCy Schubert const struct tls_connection_params *params) 152685732ac8SCy Schubert { 152785732ac8SCy Schubert wpa_printf(MSG_DEBUG, "SSL: global set params"); 152885732ac8SCy Schubert 15294bc52338SCy Schubert if (params->check_cert_subject) 15304bc52338SCy Schubert return -1; /* not yet supported */ 15314bc52338SCy Schubert 153285732ac8SCy Schubert if (tls_global_ca_cert(tls_ctx, params->ca_cert) < 0) { 153385732ac8SCy Schubert wpa_printf(MSG_INFO, "SSL: Failed to load ca cert file '%s'", 153485732ac8SCy Schubert params->ca_cert); 153585732ac8SCy Schubert return -1; 153685732ac8SCy Schubert } 153785732ac8SCy Schubert 153885732ac8SCy Schubert if (tls_global_client_cert(tls_ctx, params->client_cert) < 0) { 153985732ac8SCy Schubert wpa_printf(MSG_INFO, 154085732ac8SCy Schubert "SSL: Failed to load client cert file '%s'", 154185732ac8SCy Schubert params->client_cert); 154285732ac8SCy Schubert return -1; 154385732ac8SCy Schubert } 154485732ac8SCy Schubert 154585732ac8SCy Schubert if (tls_global_private_key(tls_ctx, params->private_key, 154685732ac8SCy Schubert params->private_key_passwd) < 0) { 154785732ac8SCy Schubert wpa_printf(MSG_INFO, 154885732ac8SCy Schubert "SSL: Failed to load private key file '%s'", 154985732ac8SCy Schubert params->private_key); 155085732ac8SCy Schubert return -1; 155185732ac8SCy Schubert } 155285732ac8SCy Schubert 1553*a90b9d01SCy Schubert if (tls_global_dh(tls_ctx, params->dh_file) < 0) { 155485732ac8SCy Schubert wpa_printf(MSG_INFO, "SSL: Failed to load DH file '%s'", 155585732ac8SCy Schubert params->dh_file); 155685732ac8SCy Schubert return -1; 155785732ac8SCy Schubert } 155885732ac8SCy Schubert 1559*a90b9d01SCy Schubert wpa_printf(MSG_DEBUG, "wolfSSL: cipher suites: %s", 1560*a90b9d01SCy Schubert params->openssl_ciphers ? params->openssl_ciphers : "N/A"); 156185732ac8SCy Schubert if (params->openssl_ciphers && 156285732ac8SCy Schubert wolfSSL_CTX_set_cipher_list(tls_ctx, 156385732ac8SCy Schubert params->openssl_ciphers) != 1) { 156485732ac8SCy Schubert wpa_printf(MSG_INFO, 156585732ac8SCy Schubert "wolfSSL: Failed to set cipher string '%s'", 156685732ac8SCy Schubert params->openssl_ciphers); 156785732ac8SCy Schubert return -1; 156885732ac8SCy Schubert } 156985732ac8SCy Schubert 15704bc52338SCy Schubert if (params->openssl_ecdh_curves) { 15714bc52338SCy Schubert wpa_printf(MSG_INFO, 15724bc52338SCy Schubert "wolfSSL: openssl_ecdh_curves not supported"); 15734bc52338SCy Schubert return -1; 15744bc52338SCy Schubert } 15754bc52338SCy Schubert 157685732ac8SCy Schubert #ifdef HAVE_SESSION_TICKET 157785732ac8SCy Schubert /* Session ticket is off by default - can't disable once on. */ 157885732ac8SCy Schubert if (!(params->flags & TLS_CONN_DISABLE_SESSION_TICKET)) 157985732ac8SCy Schubert wolfSSL_CTX_UseSessionTicket(tls_ctx); 158085732ac8SCy Schubert #endif /* HAVE_SESSION_TICKET */ 158185732ac8SCy Schubert 158285732ac8SCy Schubert #ifdef HAVE_OCSP 158385732ac8SCy Schubert if (params->ocsp_stapling_response) { 158485732ac8SCy Schubert wolfSSL_CTX_SetOCSP_OverrideURL(tls_ctx, 158585732ac8SCy Schubert params->ocsp_stapling_response); 158685732ac8SCy Schubert wolfSSL_CTX_SetOCSP_Cb(tls_ctx, ocsp_status_cb, 158785732ac8SCy Schubert ocsp_resp_free_cb, NULL); 158885732ac8SCy Schubert } 158985732ac8SCy Schubert #endif /* HAVE_OCSP */ 159085732ac8SCy Schubert 159185732ac8SCy Schubert return 0; 159285732ac8SCy Schubert } 159385732ac8SCy Schubert 159485732ac8SCy Schubert 15954bc52338SCy Schubert int tls_global_set_verify(void *tls_ctx, int check_crl, int strict) 159685732ac8SCy Schubert { 159785732ac8SCy Schubert wpa_printf(MSG_DEBUG, "SSL: global set verify: %d", check_crl); 159885732ac8SCy Schubert 159985732ac8SCy Schubert if (check_crl) { 160085732ac8SCy Schubert /* Hack to Enable CRLs. */ 160185732ac8SCy Schubert wolfSSL_CTX_LoadCRLBuffer(tls_ctx, NULL, 0, SSL_FILETYPE_PEM); 160285732ac8SCy Schubert } 160385732ac8SCy Schubert 160485732ac8SCy Schubert return 0; 160585732ac8SCy Schubert } 160685732ac8SCy Schubert 160785732ac8SCy Schubert 160885732ac8SCy Schubert int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, 160985732ac8SCy Schubert int verify_peer, unsigned int flags, 161085732ac8SCy Schubert const u8 *session_ctx, size_t session_ctx_len) 161185732ac8SCy Schubert { 1612*a90b9d01SCy Schubert static int counter = 0; 1613*a90b9d01SCy Schubert struct tls_context *context; 1614*a90b9d01SCy Schubert 161585732ac8SCy Schubert if (!conn) 161685732ac8SCy Schubert return -1; 161785732ac8SCy Schubert 161885732ac8SCy Schubert wpa_printf(MSG_DEBUG, "SSL: set verify: %d", verify_peer); 161985732ac8SCy Schubert 162085732ac8SCy Schubert if (verify_peer) { 162185732ac8SCy Schubert conn->ca_cert_verify = 1; 162285732ac8SCy Schubert wolfSSL_set_verify(conn->ssl, SSL_VERIFY_PEER | 162385732ac8SCy Schubert SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 162485732ac8SCy Schubert tls_verify_cb); 162585732ac8SCy Schubert } else { 162685732ac8SCy Schubert conn->ca_cert_verify = 0; 162785732ac8SCy Schubert wolfSSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL); 162885732ac8SCy Schubert } 162985732ac8SCy Schubert 163085732ac8SCy Schubert wolfSSL_set_accept_state(conn->ssl); 163185732ac8SCy Schubert 1632*a90b9d01SCy Schubert context = wolfSSL_CTX_get_ex_data((WOLFSSL_CTX *) ssl_ctx, 0); 1633*a90b9d01SCy Schubert if (context && context->tls_session_lifetime == 0) { 1634*a90b9d01SCy Schubert /* 1635*a90b9d01SCy Schubert * Set session id context to a unique value to make sure 1636*a90b9d01SCy Schubert * session resumption cannot be used either through session 1637*a90b9d01SCy Schubert * caching or TLS ticket extension. 1638*a90b9d01SCy Schubert */ 1639*a90b9d01SCy Schubert counter++; 1640*a90b9d01SCy Schubert wolfSSL_set_session_id_context(conn->ssl, 1641*a90b9d01SCy Schubert (const unsigned char *) &counter, 1642*a90b9d01SCy Schubert sizeof(counter)); 1643*a90b9d01SCy Schubert } else { 1644*a90b9d01SCy Schubert wolfSSL_set_session_id_context(conn->ssl, session_ctx, 1645*a90b9d01SCy Schubert session_ctx_len); 1646*a90b9d01SCy Schubert } 1647*a90b9d01SCy Schubert 164885732ac8SCy Schubert /* TODO: do we need to fake a session like OpenSSL does here? */ 164985732ac8SCy Schubert 165085732ac8SCy Schubert return 0; 165185732ac8SCy Schubert } 165285732ac8SCy Schubert 165385732ac8SCy Schubert 165485732ac8SCy Schubert static struct wpabuf * wolfssl_handshake(struct tls_connection *conn, 165585732ac8SCy Schubert const struct wpabuf *in_data, 165685732ac8SCy Schubert int server) 165785732ac8SCy Schubert { 165885732ac8SCy Schubert int res; 165985732ac8SCy Schubert 166085732ac8SCy Schubert wolfssl_reset_out_data(&conn->output); 166185732ac8SCy Schubert 166285732ac8SCy Schubert /* Initiate TLS handshake or continue the existing handshake */ 166385732ac8SCy Schubert if (server) { 166485732ac8SCy Schubert wolfSSL_set_accept_state(conn->ssl); 166585732ac8SCy Schubert res = wolfSSL_accept(conn->ssl); 166685732ac8SCy Schubert wpa_printf(MSG_DEBUG, "SSL: wolfSSL_accept: %d", res); 166785732ac8SCy Schubert } else { 166885732ac8SCy Schubert wolfSSL_set_connect_state(conn->ssl); 166985732ac8SCy Schubert res = wolfSSL_connect(conn->ssl); 167085732ac8SCy Schubert wpa_printf(MSG_DEBUG, "SSL: wolfSSL_connect: %d", res); 167185732ac8SCy Schubert } 167285732ac8SCy Schubert 1673*a90b9d01SCy Schubert if (res != WOLFSSL_SUCCESS) { 167485732ac8SCy Schubert int err = wolfSSL_get_error(conn->ssl, res); 167585732ac8SCy Schubert 1676*a90b9d01SCy Schubert if (err == WOLFSSL_ERROR_NONE) { 167785732ac8SCy Schubert wpa_printf(MSG_DEBUG, 1678*a90b9d01SCy Schubert "SSL: %s - WOLFSSL_ERROR_NONE (%d)", 1679*a90b9d01SCy Schubert server ? "wolfSSL_accept" : 1680*a90b9d01SCy Schubert "wolfSSL_connect", res); 1681*a90b9d01SCy Schubert } else if (err == WOLFSSL_ERROR_WANT_READ) { 168285732ac8SCy Schubert wpa_printf(MSG_DEBUG, 1683*a90b9d01SCy Schubert "SSL: %s - want more data", 1684*a90b9d01SCy Schubert server ? "wolfSSL_accept" : 1685*a90b9d01SCy Schubert "wolfSSL_connect"); 1686*a90b9d01SCy Schubert } else if (err == WOLFSSL_ERROR_WANT_WRITE) { 1687*a90b9d01SCy Schubert wpa_printf(MSG_DEBUG, 1688*a90b9d01SCy Schubert "SSL: %s - want to write", 1689*a90b9d01SCy Schubert server ? "wolfSSL_accept" : 1690*a90b9d01SCy Schubert "wolfSSL_connect"); 169185732ac8SCy Schubert } else { 169285732ac8SCy Schubert char msg[80]; 169385732ac8SCy Schubert 169485732ac8SCy Schubert wpa_printf(MSG_DEBUG, 1695*a90b9d01SCy Schubert "SSL: %s - failed %s", 1696*a90b9d01SCy Schubert server ? "wolfSSL_accept" : 1697*a90b9d01SCy Schubert "wolfSSL_connect", 169885732ac8SCy Schubert wolfSSL_ERR_error_string(err, msg)); 169985732ac8SCy Schubert conn->failed++; 170085732ac8SCy Schubert } 170185732ac8SCy Schubert } 170285732ac8SCy Schubert 170385732ac8SCy Schubert return conn->output.out_data; 170485732ac8SCy Schubert } 170585732ac8SCy Schubert 170685732ac8SCy Schubert 170785732ac8SCy Schubert static struct wpabuf * wolfssl_get_appl_data(struct tls_connection *conn, 170885732ac8SCy Schubert size_t max_len) 170985732ac8SCy Schubert { 171085732ac8SCy Schubert int res; 171185732ac8SCy Schubert struct wpabuf *appl_data = wpabuf_alloc(max_len + 100); 171285732ac8SCy Schubert 171385732ac8SCy Schubert if (!appl_data) 171485732ac8SCy Schubert return NULL; 171585732ac8SCy Schubert 171685732ac8SCy Schubert res = wolfSSL_read(conn->ssl, wpabuf_mhead(appl_data), 171785732ac8SCy Schubert wpabuf_size(appl_data)); 171885732ac8SCy Schubert if (res < 0) { 171985732ac8SCy Schubert int err = wolfSSL_get_error(conn->ssl, res); 172085732ac8SCy Schubert 172185732ac8SCy Schubert if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { 172285732ac8SCy Schubert wpa_printf(MSG_DEBUG, 172385732ac8SCy Schubert "SSL: No Application Data included"); 172485732ac8SCy Schubert } else { 172585732ac8SCy Schubert char msg[80]; 172685732ac8SCy Schubert 172785732ac8SCy Schubert wpa_printf(MSG_DEBUG, 172885732ac8SCy Schubert "Failed to read possible Application Data %s", 172985732ac8SCy Schubert wolfSSL_ERR_error_string(err, msg)); 173085732ac8SCy Schubert } 173185732ac8SCy Schubert 173285732ac8SCy Schubert wpabuf_free(appl_data); 173385732ac8SCy Schubert return NULL; 173485732ac8SCy Schubert } 173585732ac8SCy Schubert 173685732ac8SCy Schubert wpabuf_put(appl_data, res); 173785732ac8SCy Schubert wpa_hexdump_buf_key(MSG_MSGDUMP, 173885732ac8SCy Schubert "SSL: Application Data in Finished message", 173985732ac8SCy Schubert appl_data); 174085732ac8SCy Schubert return appl_data; 174185732ac8SCy Schubert } 174285732ac8SCy Schubert 174385732ac8SCy Schubert 174485732ac8SCy Schubert static struct wpabuf * 174585732ac8SCy Schubert wolfssl_connection_handshake(struct tls_connection *conn, 174685732ac8SCy Schubert const struct wpabuf *in_data, 174785732ac8SCy Schubert struct wpabuf **appl_data, int server) 174885732ac8SCy Schubert { 174985732ac8SCy Schubert struct wpabuf *out_data; 175085732ac8SCy Schubert 175185732ac8SCy Schubert wolfssl_reset_in_data(&conn->input, in_data); 175285732ac8SCy Schubert 175385732ac8SCy Schubert if (appl_data) 175485732ac8SCy Schubert *appl_data = NULL; 175585732ac8SCy Schubert 175685732ac8SCy Schubert out_data = wolfssl_handshake(conn, in_data, server); 175785732ac8SCy Schubert if (!out_data) 175885732ac8SCy Schubert return NULL; 175985732ac8SCy Schubert 176085732ac8SCy Schubert if (wolfSSL_is_init_finished(conn->ssl)) { 176185732ac8SCy Schubert wpa_printf(MSG_DEBUG, 176285732ac8SCy Schubert "wolfSSL: Handshake finished - resumed=%d", 176385732ac8SCy Schubert tls_connection_resumed(NULL, conn)); 176485732ac8SCy Schubert if (appl_data && in_data) 176585732ac8SCy Schubert *appl_data = wolfssl_get_appl_data(conn, 176685732ac8SCy Schubert wpabuf_len(in_data)); 176785732ac8SCy Schubert } 176885732ac8SCy Schubert 176985732ac8SCy Schubert return out_data; 177085732ac8SCy Schubert } 177185732ac8SCy Schubert 177285732ac8SCy Schubert 177385732ac8SCy Schubert struct wpabuf * tls_connection_handshake(void *tls_ctx, 177485732ac8SCy Schubert struct tls_connection *conn, 177585732ac8SCy Schubert const struct wpabuf *in_data, 177685732ac8SCy Schubert struct wpabuf **appl_data) 177785732ac8SCy Schubert { 177885732ac8SCy Schubert return wolfssl_connection_handshake(conn, in_data, appl_data, 0); 177985732ac8SCy Schubert } 178085732ac8SCy Schubert 178185732ac8SCy Schubert 178285732ac8SCy Schubert struct wpabuf * tls_connection_server_handshake(void *tls_ctx, 178385732ac8SCy Schubert struct tls_connection *conn, 178485732ac8SCy Schubert const struct wpabuf *in_data, 178585732ac8SCy Schubert struct wpabuf **appl_data) 178685732ac8SCy Schubert { 178785732ac8SCy Schubert return wolfssl_connection_handshake(conn, in_data, appl_data, 1); 178885732ac8SCy Schubert } 178985732ac8SCy Schubert 179085732ac8SCy Schubert 179185732ac8SCy Schubert struct wpabuf * tls_connection_encrypt(void *tls_ctx, 179285732ac8SCy Schubert struct tls_connection *conn, 179385732ac8SCy Schubert const struct wpabuf *in_data) 179485732ac8SCy Schubert { 179585732ac8SCy Schubert int res; 179685732ac8SCy Schubert 179785732ac8SCy Schubert if (!conn) 179885732ac8SCy Schubert return NULL; 179985732ac8SCy Schubert 1800c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "SSL: encrypt: %zu bytes", wpabuf_len(in_data)); 180185732ac8SCy Schubert 180285732ac8SCy Schubert wolfssl_reset_out_data(&conn->output); 180385732ac8SCy Schubert 180485732ac8SCy Schubert res = wolfSSL_write(conn->ssl, wpabuf_head(in_data), 180585732ac8SCy Schubert wpabuf_len(in_data)); 180685732ac8SCy Schubert if (res < 0) { 180785732ac8SCy Schubert int err = wolfSSL_get_error(conn->ssl, res); 180885732ac8SCy Schubert char msg[80]; 180985732ac8SCy Schubert 181085732ac8SCy Schubert wpa_printf(MSG_INFO, "Encryption failed - SSL_write: %s", 181185732ac8SCy Schubert wolfSSL_ERR_error_string(err, msg)); 181285732ac8SCy Schubert return NULL; 181385732ac8SCy Schubert } 181485732ac8SCy Schubert 181585732ac8SCy Schubert return conn->output.out_data; 181685732ac8SCy Schubert } 181785732ac8SCy Schubert 181885732ac8SCy Schubert 181985732ac8SCy Schubert struct wpabuf * tls_connection_decrypt(void *tls_ctx, 182085732ac8SCy Schubert struct tls_connection *conn, 182185732ac8SCy Schubert const struct wpabuf *in_data) 182285732ac8SCy Schubert { 182385732ac8SCy Schubert int res; 182485732ac8SCy Schubert struct wpabuf *buf; 182585732ac8SCy Schubert 182685732ac8SCy Schubert if (!conn) 182785732ac8SCy Schubert return NULL; 182885732ac8SCy Schubert 182985732ac8SCy Schubert wpa_printf(MSG_DEBUG, "SSL: decrypt"); 183085732ac8SCy Schubert 183185732ac8SCy Schubert wolfssl_reset_in_data(&conn->input, in_data); 183285732ac8SCy Schubert 183385732ac8SCy Schubert /* Read decrypted data for further processing */ 183485732ac8SCy Schubert /* 183585732ac8SCy Schubert * Even though we try to disable TLS compression, it is possible that 183685732ac8SCy Schubert * this cannot be done with all TLS libraries. Add extra buffer space 183785732ac8SCy Schubert * to handle the possibility of the decrypted data being longer than 183885732ac8SCy Schubert * input data. 183985732ac8SCy Schubert */ 184085732ac8SCy Schubert buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); 184185732ac8SCy Schubert if (!buf) 184285732ac8SCy Schubert return NULL; 184385732ac8SCy Schubert res = wolfSSL_read(conn->ssl, wpabuf_mhead(buf), wpabuf_size(buf)); 184485732ac8SCy Schubert if (res < 0) { 184585732ac8SCy Schubert wpa_printf(MSG_INFO, "Decryption failed - SSL_read"); 184685732ac8SCy Schubert wpabuf_free(buf); 184785732ac8SCy Schubert return NULL; 184885732ac8SCy Schubert } 184985732ac8SCy Schubert wpabuf_put(buf, res); 185085732ac8SCy Schubert 1851c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "SSL: decrypt: %zu bytes", wpabuf_len(buf)); 185285732ac8SCy Schubert 185385732ac8SCy Schubert return buf; 185485732ac8SCy Schubert } 185585732ac8SCy Schubert 185685732ac8SCy Schubert 185785732ac8SCy Schubert int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) 185885732ac8SCy Schubert { 185985732ac8SCy Schubert return conn ? wolfSSL_session_reused(conn->ssl) : 0; 186085732ac8SCy Schubert } 186185732ac8SCy Schubert 186285732ac8SCy Schubert 186385732ac8SCy Schubert int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, 186485732ac8SCy Schubert u8 *ciphers) 186585732ac8SCy Schubert { 186685732ac8SCy Schubert char buf[128], *pos, *end; 186785732ac8SCy Schubert u8 *c; 186885732ac8SCy Schubert int ret; 186985732ac8SCy Schubert 187085732ac8SCy Schubert if (!conn || !conn->ssl || !ciphers) 187185732ac8SCy Schubert return -1; 187285732ac8SCy Schubert 187385732ac8SCy Schubert buf[0] = '\0'; 187485732ac8SCy Schubert pos = buf; 187585732ac8SCy Schubert end = pos + sizeof(buf); 187685732ac8SCy Schubert 187785732ac8SCy Schubert c = ciphers; 187885732ac8SCy Schubert while (*c != TLS_CIPHER_NONE) { 187985732ac8SCy Schubert const char *suite; 188085732ac8SCy Schubert 188185732ac8SCy Schubert switch (*c) { 188285732ac8SCy Schubert case TLS_CIPHER_RC4_SHA: 188385732ac8SCy Schubert suite = "RC4-SHA"; 188485732ac8SCy Schubert break; 188585732ac8SCy Schubert case TLS_CIPHER_AES128_SHA: 188685732ac8SCy Schubert suite = "AES128-SHA"; 188785732ac8SCy Schubert break; 188885732ac8SCy Schubert case TLS_CIPHER_RSA_DHE_AES128_SHA: 188985732ac8SCy Schubert suite = "DHE-RSA-AES128-SHA"; 189085732ac8SCy Schubert break; 189185732ac8SCy Schubert case TLS_CIPHER_ANON_DH_AES128_SHA: 189285732ac8SCy Schubert suite = "ADH-AES128-SHA"; 189385732ac8SCy Schubert break; 189485732ac8SCy Schubert case TLS_CIPHER_RSA_DHE_AES256_SHA: 189585732ac8SCy Schubert suite = "DHE-RSA-AES256-SHA"; 189685732ac8SCy Schubert break; 189785732ac8SCy Schubert case TLS_CIPHER_AES256_SHA: 189885732ac8SCy Schubert suite = "AES256-SHA"; 189985732ac8SCy Schubert break; 190085732ac8SCy Schubert default: 190185732ac8SCy Schubert wpa_printf(MSG_DEBUG, 190285732ac8SCy Schubert "TLS: Unsupported cipher selection: %d", *c); 190385732ac8SCy Schubert return -1; 190485732ac8SCy Schubert } 190585732ac8SCy Schubert ret = os_snprintf(pos, end - pos, ":%s", suite); 190685732ac8SCy Schubert if (os_snprintf_error(end - pos, ret)) 190785732ac8SCy Schubert break; 190885732ac8SCy Schubert pos += ret; 190985732ac8SCy Schubert 191085732ac8SCy Schubert c++; 191185732ac8SCy Schubert } 191285732ac8SCy Schubert 191385732ac8SCy Schubert wpa_printf(MSG_DEBUG, "wolfSSL: cipher suites: %s", buf + 1); 191485732ac8SCy Schubert 191585732ac8SCy Schubert if (wolfSSL_set_cipher_list(conn->ssl, buf + 1) != 1) { 191685732ac8SCy Schubert wpa_printf(MSG_DEBUG, "Cipher suite configuration failed"); 191785732ac8SCy Schubert return -1; 191885732ac8SCy Schubert } 191985732ac8SCy Schubert 192085732ac8SCy Schubert return 0; 192185732ac8SCy Schubert } 192285732ac8SCy Schubert 192385732ac8SCy Schubert 192485732ac8SCy Schubert int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, 192585732ac8SCy Schubert char *buf, size_t buflen) 192685732ac8SCy Schubert { 192785732ac8SCy Schubert WOLFSSL_CIPHER *cipher; 192885732ac8SCy Schubert const char *name; 192985732ac8SCy Schubert 193085732ac8SCy Schubert if (!conn || !conn->ssl) 193185732ac8SCy Schubert return -1; 193285732ac8SCy Schubert 193385732ac8SCy Schubert cipher = wolfSSL_get_current_cipher(conn->ssl); 193485732ac8SCy Schubert if (!cipher) 193585732ac8SCy Schubert return -1; 193685732ac8SCy Schubert 193785732ac8SCy Schubert name = wolfSSL_CIPHER_get_name(cipher); 193885732ac8SCy Schubert if (!name) 193985732ac8SCy Schubert return -1; 194085732ac8SCy Schubert 194185732ac8SCy Schubert if (os_strcmp(name, "SSL_RSA_WITH_RC4_128_SHA") == 0) 194285732ac8SCy Schubert os_strlcpy(buf, "RC4-SHA", buflen); 194385732ac8SCy Schubert else if (os_strcmp(name, "TLS_RSA_WITH_AES_128_CBC_SHA") == 0) 194485732ac8SCy Schubert os_strlcpy(buf, "AES128-SHA", buflen); 194585732ac8SCy Schubert else if (os_strcmp(name, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA") == 0) 194685732ac8SCy Schubert os_strlcpy(buf, "DHE-RSA-AES128-SHA", buflen); 194785732ac8SCy Schubert else if (os_strcmp(name, "TLS_DH_anon_WITH_AES_128_CBC_SHA") == 0) 194885732ac8SCy Schubert os_strlcpy(buf, "ADH-AES128-SHA", buflen); 194985732ac8SCy Schubert else if (os_strcmp(name, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA") == 0) 195085732ac8SCy Schubert os_strlcpy(buf, "DHE-RSA-AES256-SHA", buflen); 195185732ac8SCy Schubert else if (os_strcmp(name, "TLS_RSA_WITH_AES_256_CBC_SHA") == 0) 195285732ac8SCy Schubert os_strlcpy(buf, "AES256-SHA", buflen); 195385732ac8SCy Schubert else 195485732ac8SCy Schubert os_strlcpy(buf, name, buflen); 195585732ac8SCy Schubert 195685732ac8SCy Schubert return 0; 195785732ac8SCy Schubert } 195885732ac8SCy Schubert 195985732ac8SCy Schubert 196085732ac8SCy Schubert int tls_connection_enable_workaround(void *tls_ctx, 196185732ac8SCy Schubert struct tls_connection *conn) 196285732ac8SCy Schubert { 196385732ac8SCy Schubert /* no empty fragments in wolfSSL for now */ 196485732ac8SCy Schubert return 0; 196585732ac8SCy Schubert } 196685732ac8SCy Schubert 196785732ac8SCy Schubert 196885732ac8SCy Schubert int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) 196985732ac8SCy Schubert { 197085732ac8SCy Schubert if (!conn) 197185732ac8SCy Schubert return -1; 197285732ac8SCy Schubert 197385732ac8SCy Schubert return conn->failed; 197485732ac8SCy Schubert } 197585732ac8SCy Schubert 197685732ac8SCy Schubert 197785732ac8SCy Schubert int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) 197885732ac8SCy Schubert { 197985732ac8SCy Schubert if (!conn) 198085732ac8SCy Schubert return -1; 198185732ac8SCy Schubert 198285732ac8SCy Schubert /* TODO: this is not incremented anywhere */ 198385732ac8SCy Schubert return conn->read_alerts; 198485732ac8SCy Schubert } 198585732ac8SCy Schubert 198685732ac8SCy Schubert 198785732ac8SCy Schubert int tls_connection_get_write_alerts(void *tls_ctx, 198885732ac8SCy Schubert struct tls_connection *conn) 198985732ac8SCy Schubert { 199085732ac8SCy Schubert if (!conn) 199185732ac8SCy Schubert return -1; 199285732ac8SCy Schubert 199385732ac8SCy Schubert /* TODO: this is not incremented anywhere */ 199485732ac8SCy Schubert return conn->write_alerts; 199585732ac8SCy Schubert } 199685732ac8SCy Schubert 199785732ac8SCy Schubert 199885732ac8SCy Schubert 199985732ac8SCy Schubert int tls_get_library_version(char *buf, size_t buf_len) 200085732ac8SCy Schubert { 200185732ac8SCy Schubert return os_snprintf(buf, buf_len, "wolfSSL build=%s run=%s", 200285732ac8SCy Schubert WOLFSSL_VERSION, wolfSSL_lib_version()); 200385732ac8SCy Schubert } 200485732ac8SCy Schubert 200585732ac8SCy Schubert int tls_get_version(void *ssl_ctx, struct tls_connection *conn, 200685732ac8SCy Schubert char *buf, size_t buflen) 200785732ac8SCy Schubert { 200885732ac8SCy Schubert const char *name; 200985732ac8SCy Schubert 201085732ac8SCy Schubert if (!conn || !conn->ssl) 201185732ac8SCy Schubert return -1; 201285732ac8SCy Schubert 201385732ac8SCy Schubert name = wolfSSL_get_version(conn->ssl); 201485732ac8SCy Schubert if (!name) 201585732ac8SCy Schubert return -1; 201685732ac8SCy Schubert 201785732ac8SCy Schubert os_strlcpy(buf, name, buflen); 201885732ac8SCy Schubert return 0; 201985732ac8SCy Schubert } 202085732ac8SCy Schubert 202185732ac8SCy Schubert 202285732ac8SCy Schubert int tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn, 202385732ac8SCy Schubert struct tls_random *keys) 202485732ac8SCy Schubert { 202585732ac8SCy Schubert WOLFSSL *ssl; 202685732ac8SCy Schubert 202785732ac8SCy Schubert if (!conn || !keys) 202885732ac8SCy Schubert return -1; 202985732ac8SCy Schubert ssl = conn->ssl; 203085732ac8SCy Schubert if (!ssl) 203185732ac8SCy Schubert return -1; 203285732ac8SCy Schubert 203385732ac8SCy Schubert os_memset(keys, 0, sizeof(*keys)); 203485732ac8SCy Schubert keys->client_random = conn->client_random; 203585732ac8SCy Schubert keys->client_random_len = wolfSSL_get_client_random( 203685732ac8SCy Schubert ssl, conn->client_random, sizeof(conn->client_random)); 203785732ac8SCy Schubert keys->server_random = conn->server_random; 203885732ac8SCy Schubert keys->server_random_len = wolfSSL_get_server_random( 203985732ac8SCy Schubert ssl, conn->server_random, sizeof(conn->server_random)); 204085732ac8SCy Schubert 204185732ac8SCy Schubert return 0; 204285732ac8SCy Schubert } 204385732ac8SCy Schubert 204485732ac8SCy Schubert 204585732ac8SCy Schubert int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn, 20464bc52338SCy Schubert const char *label, const u8 *context, 20474bc52338SCy Schubert size_t context_len, u8 *out, size_t out_len) 204885732ac8SCy Schubert { 2049*a90b9d01SCy Schubert if (!conn) 20504bc52338SCy Schubert return -1; 2051*a90b9d01SCy Schubert #if LIBWOLFSSL_VERSION_HEX >= 0x04007000 2052*a90b9d01SCy Schubert if (wolfSSL_export_keying_material(conn->ssl, out, out_len, 2053*a90b9d01SCy Schubert label, os_strlen(label), 2054*a90b9d01SCy Schubert context, context_len, 2055*a90b9d01SCy Schubert context != NULL) != WOLFSSL_SUCCESS) 205685732ac8SCy Schubert return -1; 205785732ac8SCy Schubert return 0; 2058*a90b9d01SCy Schubert #else 2059*a90b9d01SCy Schubert if (context || 2060*a90b9d01SCy Schubert wolfSSL_make_eap_keys(conn->ssl, out, out_len, label) != 0) 2061*a90b9d01SCy Schubert return -1; 2062*a90b9d01SCy Schubert #endif 2063*a90b9d01SCy Schubert return 0; 206485732ac8SCy Schubert } 206585732ac8SCy Schubert 206685732ac8SCy Schubert 206785732ac8SCy Schubert #define SEED_LEN (RAN_LEN + RAN_LEN) 206885732ac8SCy Schubert 206985732ac8SCy Schubert int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn, 207085732ac8SCy Schubert u8 *out, size_t out_len) 207185732ac8SCy Schubert { 207285732ac8SCy Schubert byte seed[SEED_LEN]; 207385732ac8SCy Schubert int ret = -1; 207485732ac8SCy Schubert WOLFSSL *ssl; 207585732ac8SCy Schubert byte *tmp_out; 207685732ac8SCy Schubert byte *_out; 207785732ac8SCy Schubert int skip = 0; 207885732ac8SCy Schubert byte *master_key; 207985732ac8SCy Schubert unsigned int master_key_len; 208085732ac8SCy Schubert byte *server_random; 208185732ac8SCy Schubert unsigned int server_len; 208285732ac8SCy Schubert byte *client_random; 208385732ac8SCy Schubert unsigned int client_len; 208485732ac8SCy Schubert 208585732ac8SCy Schubert if (!conn || !conn->ssl) 208685732ac8SCy Schubert return -1; 208785732ac8SCy Schubert ssl = conn->ssl; 208885732ac8SCy Schubert 208985732ac8SCy Schubert skip = 2 * (wolfSSL_GetKeySize(ssl) + wolfSSL_GetHmacSize(ssl) + 209085732ac8SCy Schubert wolfSSL_GetIVSize(ssl)); 209185732ac8SCy Schubert 209285732ac8SCy Schubert tmp_out = os_malloc(skip + out_len); 209385732ac8SCy Schubert if (!tmp_out) 209485732ac8SCy Schubert return -1; 209585732ac8SCy Schubert _out = tmp_out; 209685732ac8SCy Schubert 209785732ac8SCy Schubert wolfSSL_get_keys(ssl, &master_key, &master_key_len, &server_random, 209885732ac8SCy Schubert &server_len, &client_random, &client_len); 209985732ac8SCy Schubert os_memcpy(seed, server_random, RAN_LEN); 210085732ac8SCy Schubert os_memcpy(seed + RAN_LEN, client_random, RAN_LEN); 210185732ac8SCy Schubert 210285732ac8SCy Schubert if (wolfSSL_GetVersion(ssl) == WOLFSSL_TLSV1_2) { 210385732ac8SCy Schubert tls_prf_sha256(master_key, master_key_len, 210485732ac8SCy Schubert "key expansion", seed, sizeof(seed), 210585732ac8SCy Schubert _out, skip + out_len); 210685732ac8SCy Schubert ret = 0; 210785732ac8SCy Schubert } else { 2108*a90b9d01SCy Schubert #ifdef CONFIG_FIPS 2109*a90b9d01SCy Schubert wpa_printf(MSG_ERROR, 2110*a90b9d01SCy Schubert "wolfSSL: Can't use sha1_md5 in FIPS build"); 2111*a90b9d01SCy Schubert ret = -1; 2112*a90b9d01SCy Schubert #else /* CONFIG_FIPS */ 211385732ac8SCy Schubert ret = tls_prf_sha1_md5(master_key, master_key_len, 211485732ac8SCy Schubert "key expansion", seed, sizeof(seed), 211585732ac8SCy Schubert _out, skip + out_len); 2116*a90b9d01SCy Schubert #endif /* CONFIG_FIPS */ 211785732ac8SCy Schubert } 211885732ac8SCy Schubert 2119206b73d0SCy Schubert forced_memzero(master_key, master_key_len); 212085732ac8SCy Schubert if (ret == 0) 212185732ac8SCy Schubert os_memcpy(out, _out + skip, out_len); 212285732ac8SCy Schubert bin_clear_free(tmp_out, skip + out_len); 212385732ac8SCy Schubert 212485732ac8SCy Schubert return ret; 212585732ac8SCy Schubert } 212685732ac8SCy Schubert 212785732ac8SCy Schubert 212885732ac8SCy Schubert #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) 212985732ac8SCy Schubert 213085732ac8SCy Schubert int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, 213185732ac8SCy Schubert int ext_type, const u8 *data, 213285732ac8SCy Schubert size_t data_len) 213385732ac8SCy Schubert { 213485732ac8SCy Schubert (void) ssl_ctx; 213585732ac8SCy Schubert 213685732ac8SCy Schubert if (!conn || !conn->ssl || ext_type != 35) 213785732ac8SCy Schubert return -1; 213885732ac8SCy Schubert 213985732ac8SCy Schubert if (wolfSSL_set_SessionTicket(conn->ssl, data, 214085732ac8SCy Schubert (unsigned int) data_len) != 1) 214185732ac8SCy Schubert return -1; 214285732ac8SCy Schubert 214385732ac8SCy Schubert return 0; 214485732ac8SCy Schubert } 214585732ac8SCy Schubert 214685732ac8SCy Schubert 214785732ac8SCy Schubert static int tls_sess_sec_cb(WOLFSSL *s, void *secret, int *secret_len, void *arg) 214885732ac8SCy Schubert { 214985732ac8SCy Schubert struct tls_connection *conn = arg; 215085732ac8SCy Schubert int ret; 215185732ac8SCy Schubert unsigned char client_random[RAN_LEN]; 215285732ac8SCy Schubert unsigned char server_random[RAN_LEN]; 215385732ac8SCy Schubert word32 ticket_len = sizeof(conn->session_ticket); 215485732ac8SCy Schubert 215585732ac8SCy Schubert if (!conn || !conn->session_ticket_cb) 215685732ac8SCy Schubert return 1; 215785732ac8SCy Schubert 215885732ac8SCy Schubert if (wolfSSL_get_client_random(s, client_random, 215985732ac8SCy Schubert sizeof(client_random)) == 0 || 216085732ac8SCy Schubert wolfSSL_get_server_random(s, server_random, 216185732ac8SCy Schubert sizeof(server_random)) == 0 || 216285732ac8SCy Schubert wolfSSL_get_SessionTicket(s, conn->session_ticket, 216385732ac8SCy Schubert &ticket_len) != 1) 216485732ac8SCy Schubert return 1; 216585732ac8SCy Schubert 216685732ac8SCy Schubert if (ticket_len == 0) 216785732ac8SCy Schubert return 0; 216885732ac8SCy Schubert 216985732ac8SCy Schubert ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx, 217085732ac8SCy Schubert conn->session_ticket, ticket_len, 217185732ac8SCy Schubert client_random, server_random, secret); 217285732ac8SCy Schubert if (ret <= 0) 217385732ac8SCy Schubert return 1; 217485732ac8SCy Schubert 217585732ac8SCy Schubert *secret_len = SECRET_LEN; 217685732ac8SCy Schubert return 0; 217785732ac8SCy Schubert } 217885732ac8SCy Schubert 217985732ac8SCy Schubert #endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */ 218085732ac8SCy Schubert 218185732ac8SCy Schubert 218285732ac8SCy Schubert int tls_connection_set_session_ticket_cb(void *tls_ctx, 218385732ac8SCy Schubert struct tls_connection *conn, 218485732ac8SCy Schubert tls_session_ticket_cb cb, 218585732ac8SCy Schubert void *ctx) 218685732ac8SCy Schubert { 218785732ac8SCy Schubert #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) 218885732ac8SCy Schubert conn->session_ticket_cb = cb; 218985732ac8SCy Schubert conn->session_ticket_cb_ctx = ctx; 219085732ac8SCy Schubert 219185732ac8SCy Schubert if (cb) { 219285732ac8SCy Schubert if (wolfSSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb, 219385732ac8SCy Schubert conn) != 1) 219485732ac8SCy Schubert return -1; 219585732ac8SCy Schubert } else { 219685732ac8SCy Schubert if (wolfSSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1) 219785732ac8SCy Schubert return -1; 219885732ac8SCy Schubert } 219985732ac8SCy Schubert 220085732ac8SCy Schubert return 0; 220185732ac8SCy Schubert #else /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */ 220285732ac8SCy Schubert return -1; 220385732ac8SCy Schubert #endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */ 220485732ac8SCy Schubert } 220585732ac8SCy Schubert 220685732ac8SCy Schubert 220785732ac8SCy Schubert void tls_connection_set_success_data_resumed(struct tls_connection *conn) 220885732ac8SCy Schubert { 220985732ac8SCy Schubert wpa_printf(MSG_DEBUG, 221085732ac8SCy Schubert "wolfSSL: Success data accepted for resumed session"); 221185732ac8SCy Schubert } 221285732ac8SCy Schubert 221385732ac8SCy Schubert 221485732ac8SCy Schubert void tls_connection_remove_session(struct tls_connection *conn) 221585732ac8SCy Schubert { 221685732ac8SCy Schubert WOLFSSL_SESSION *sess; 221785732ac8SCy Schubert 221885732ac8SCy Schubert sess = wolfSSL_get_session(conn->ssl); 221985732ac8SCy Schubert if (!sess) 222085732ac8SCy Schubert return; 222185732ac8SCy Schubert 222285732ac8SCy Schubert wolfSSL_SSL_SESSION_set_timeout(sess, 0); 222385732ac8SCy Schubert wpa_printf(MSG_DEBUG, 222485732ac8SCy Schubert "wolfSSL: Removed cached session to disable session resumption"); 222585732ac8SCy Schubert } 222685732ac8SCy Schubert 222785732ac8SCy Schubert 2228*a90b9d01SCy Schubert int tls_get_tls_unique(struct tls_connection *conn, u8 *buf, size_t max_len) 2229*a90b9d01SCy Schubert { 2230*a90b9d01SCy Schubert size_t len; 2231*a90b9d01SCy Schubert int reused; 2232*a90b9d01SCy Schubert 2233*a90b9d01SCy Schubert reused = wolfSSL_session_reused(conn->ssl); 2234*a90b9d01SCy Schubert if ((wolfSSL_is_server(conn->ssl) && !reused) || 2235*a90b9d01SCy Schubert (!wolfSSL_is_server(conn->ssl) && reused)) 2236*a90b9d01SCy Schubert len = wolfSSL_get_peer_finished(conn->ssl, buf, max_len); 2237*a90b9d01SCy Schubert else 2238*a90b9d01SCy Schubert len = wolfSSL_get_finished(conn->ssl, buf, max_len); 2239*a90b9d01SCy Schubert 2240*a90b9d01SCy Schubert if (len == 0 || len > max_len) 2241*a90b9d01SCy Schubert return -1; 2242*a90b9d01SCy Schubert 2243*a90b9d01SCy Schubert return len; 2244*a90b9d01SCy Schubert } 2245*a90b9d01SCy Schubert 2246*a90b9d01SCy Schubert 2247*a90b9d01SCy Schubert u16 tls_connection_get_cipher_suite(struct tls_connection *conn) 2248*a90b9d01SCy Schubert { 2249*a90b9d01SCy Schubert return (u16) wolfSSL_get_current_cipher_suite(conn->ssl); 2250*a90b9d01SCy Schubert } 2251*a90b9d01SCy Schubert 2252*a90b9d01SCy Schubert 2253*a90b9d01SCy Schubert const char * tls_connection_get_peer_subject(struct tls_connection *conn) 2254*a90b9d01SCy Schubert { 2255*a90b9d01SCy Schubert if (conn) 2256*a90b9d01SCy Schubert return conn->peer_subject; 2257*a90b9d01SCy Schubert return NULL; 2258*a90b9d01SCy Schubert } 2259*a90b9d01SCy Schubert 2260*a90b9d01SCy Schubert 226185732ac8SCy Schubert void tls_connection_set_success_data(struct tls_connection *conn, 226285732ac8SCy Schubert struct wpabuf *data) 226385732ac8SCy Schubert { 226485732ac8SCy Schubert WOLFSSL_SESSION *sess; 226585732ac8SCy Schubert struct wpabuf *old; 226685732ac8SCy Schubert 226785732ac8SCy Schubert wpa_printf(MSG_DEBUG, "wolfSSL: Set success data"); 226885732ac8SCy Schubert 226985732ac8SCy Schubert sess = wolfSSL_get_session(conn->ssl); 227085732ac8SCy Schubert if (!sess) { 227185732ac8SCy Schubert wpa_printf(MSG_DEBUG, 227285732ac8SCy Schubert "wolfSSL: No session found for success data"); 227385732ac8SCy Schubert goto fail; 227485732ac8SCy Schubert } 227585732ac8SCy Schubert 227685732ac8SCy Schubert old = wolfSSL_SESSION_get_ex_data(sess, tls_ex_idx_session); 227785732ac8SCy Schubert if (old) { 227885732ac8SCy Schubert wpa_printf(MSG_DEBUG, "wolfSSL: Replacing old success data %p", 227985732ac8SCy Schubert old); 228085732ac8SCy Schubert wpabuf_free(old); 228185732ac8SCy Schubert } 228285732ac8SCy Schubert if (wolfSSL_SESSION_set_ex_data(sess, tls_ex_idx_session, data) != 1) 228385732ac8SCy Schubert goto fail; 228485732ac8SCy Schubert 228585732ac8SCy Schubert wpa_printf(MSG_DEBUG, "wolfSSL: Stored success data %p", data); 228685732ac8SCy Schubert conn->success_data = 1; 228785732ac8SCy Schubert return; 228885732ac8SCy Schubert 228985732ac8SCy Schubert fail: 229085732ac8SCy Schubert wpa_printf(MSG_INFO, "wolfSSL: Failed to store success data"); 229185732ac8SCy Schubert wpabuf_free(data); 229285732ac8SCy Schubert } 229385732ac8SCy Schubert 229485732ac8SCy Schubert 229585732ac8SCy Schubert const struct wpabuf * 229685732ac8SCy Schubert tls_connection_get_success_data(struct tls_connection *conn) 229785732ac8SCy Schubert { 229885732ac8SCy Schubert WOLFSSL_SESSION *sess; 229985732ac8SCy Schubert 230085732ac8SCy Schubert wpa_printf(MSG_DEBUG, "wolfSSL: Get success data"); 230185732ac8SCy Schubert 230285732ac8SCy Schubert sess = wolfSSL_get_session(conn->ssl); 230385732ac8SCy Schubert if (!sess) 230485732ac8SCy Schubert return NULL; 230585732ac8SCy Schubert return wolfSSL_SESSION_get_ex_data(sess, tls_ex_idx_session); 230685732ac8SCy Schubert } 2307*a90b9d01SCy Schubert 2308*a90b9d01SCy Schubert 2309*a90b9d01SCy Schubert bool tls_connection_get_own_cert_used(struct tls_connection *conn) 2310*a90b9d01SCy Schubert { 2311*a90b9d01SCy Schubert if (conn) 2312*a90b9d01SCy Schubert return wolfSSL_get_certificate(conn->ssl) != NULL; 2313*a90b9d01SCy Schubert return false; 2314*a90b9d01SCy Schubert } 2315