xref: /freebsd-src/contrib/wpa/src/crypto/tls_wolfssl.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
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