1e5b75505Sopenharmony_ci/*
2e5b75505Sopenharmony_ci * SSL/TLS interface functions for wolfSSL TLS case
3e5b75505Sopenharmony_ci * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi>
4e5b75505Sopenharmony_ci *
5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license.
6e5b75505Sopenharmony_ci * See README for more details.
7e5b75505Sopenharmony_ci */
8e5b75505Sopenharmony_ci
9e5b75505Sopenharmony_ci#include "includes.h"
10e5b75505Sopenharmony_ci
11e5b75505Sopenharmony_ci#include "common.h"
12e5b75505Sopenharmony_ci#include "crypto.h"
13e5b75505Sopenharmony_ci#include "crypto/sha1.h"
14e5b75505Sopenharmony_ci#include "crypto/sha256.h"
15e5b75505Sopenharmony_ci#include "tls.h"
16e5b75505Sopenharmony_ci
17e5b75505Sopenharmony_ci/* wolfSSL includes */
18e5b75505Sopenharmony_ci#include <wolfssl/options.h>
19e5b75505Sopenharmony_ci#include <wolfssl/ssl.h>
20e5b75505Sopenharmony_ci#include <wolfssl/error-ssl.h>
21e5b75505Sopenharmony_ci#include <wolfssl/wolfcrypt/asn.h>
22e5b75505Sopenharmony_ci
23e5b75505Sopenharmony_ci#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
24e5b75505Sopenharmony_ci#define HAVE_AESGCM
25e5b75505Sopenharmony_ci#include <wolfssl/wolfcrypt/aes.h>
26e5b75505Sopenharmony_ci#endif
27e5b75505Sopenharmony_ci
28e5b75505Sopenharmony_ci#if !defined(CONFIG_FIPS) &&                             \
29e5b75505Sopenharmony_ci    (defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) ||   \
30e5b75505Sopenharmony_ci     defined(EAP_SERVER_FAST))
31e5b75505Sopenharmony_ci#define WOLFSSL_NEED_EAP_FAST_PRF
32e5b75505Sopenharmony_ci#endif
33e5b75505Sopenharmony_ci
34e5b75505Sopenharmony_ci#define SECRET_LEN          48
35e5b75505Sopenharmony_ci#define RAN_LEN             32
36e5b75505Sopenharmony_ci#define SESSION_TICKET_LEN  256
37e5b75505Sopenharmony_ci
38e5b75505Sopenharmony_cistatic int tls_ref_count = 0;
39e5b75505Sopenharmony_ci
40e5b75505Sopenharmony_cistatic int tls_ex_idx_session = 0;
41e5b75505Sopenharmony_ci
42e5b75505Sopenharmony_ci
43e5b75505Sopenharmony_ci/* tls input data for wolfSSL Read Callback */
44e5b75505Sopenharmony_cistruct tls_in_data {
45e5b75505Sopenharmony_ci	const struct wpabuf *in_data;
46e5b75505Sopenharmony_ci	size_t consumed; /* how many bytes have we used already */
47e5b75505Sopenharmony_ci};
48e5b75505Sopenharmony_ci
49e5b75505Sopenharmony_ci/* tls output data for wolfSSL Write Callback */
50e5b75505Sopenharmony_cistruct tls_out_data {
51e5b75505Sopenharmony_ci	struct wpabuf *out_data;
52e5b75505Sopenharmony_ci};
53e5b75505Sopenharmony_ci
54e5b75505Sopenharmony_cistruct tls_context {
55e5b75505Sopenharmony_ci	void (*event_cb)(void *ctx, enum tls_event ev,
56e5b75505Sopenharmony_ci			 union tls_event_data *data);
57e5b75505Sopenharmony_ci	void *cb_ctx;
58e5b75505Sopenharmony_ci	int cert_in_cb;
59e5b75505Sopenharmony_ci	char *ocsp_stapling_response;
60e5b75505Sopenharmony_ci};
61e5b75505Sopenharmony_ci
62e5b75505Sopenharmony_cistatic struct tls_context *tls_global = NULL;
63e5b75505Sopenharmony_ci
64e5b75505Sopenharmony_ci/* wolfssl tls_connection */
65e5b75505Sopenharmony_cistruct tls_connection {
66e5b75505Sopenharmony_ci	struct tls_context *context;
67e5b75505Sopenharmony_ci	WOLFSSL *ssl;
68e5b75505Sopenharmony_ci	int read_alerts;
69e5b75505Sopenharmony_ci	int write_alerts;
70e5b75505Sopenharmony_ci	int failed;
71e5b75505Sopenharmony_ci	struct tls_in_data input;
72e5b75505Sopenharmony_ci	struct tls_out_data output;
73e5b75505Sopenharmony_ci	char *subject_match;
74e5b75505Sopenharmony_ci	char *alt_subject_match;
75e5b75505Sopenharmony_ci	char *suffix_match;
76e5b75505Sopenharmony_ci	char *domain_match;
77e5b75505Sopenharmony_ci
78e5b75505Sopenharmony_ci	u8 srv_cert_hash[32];
79e5b75505Sopenharmony_ci
80e5b75505Sopenharmony_ci	unsigned char client_random[RAN_LEN];
81e5b75505Sopenharmony_ci	unsigned char server_random[RAN_LEN];
82e5b75505Sopenharmony_ci	unsigned int flags;
83e5b75505Sopenharmony_ci#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
84e5b75505Sopenharmony_ci	tls_session_ticket_cb session_ticket_cb;
85e5b75505Sopenharmony_ci	void *session_ticket_cb_ctx;
86e5b75505Sopenharmony_ci	byte session_ticket[SESSION_TICKET_LEN];
87e5b75505Sopenharmony_ci#endif
88e5b75505Sopenharmony_ci	unsigned int ca_cert_verify:1;
89e5b75505Sopenharmony_ci	unsigned int cert_probe:1;
90e5b75505Sopenharmony_ci	unsigned int server_cert_only:1;
91e5b75505Sopenharmony_ci	unsigned int success_data:1;
92e5b75505Sopenharmony_ci
93e5b75505Sopenharmony_ci	WOLFSSL_X509 *peer_cert;
94e5b75505Sopenharmony_ci	WOLFSSL_X509 *peer_issuer;
95e5b75505Sopenharmony_ci	WOLFSSL_X509 *peer_issuer_issuer;
96e5b75505Sopenharmony_ci};
97e5b75505Sopenharmony_ci
98e5b75505Sopenharmony_ci
99e5b75505Sopenharmony_cistatic struct tls_context * tls_context_new(const struct tls_config *conf)
100e5b75505Sopenharmony_ci{
101e5b75505Sopenharmony_ci	struct tls_context *context = os_zalloc(sizeof(*context));
102e5b75505Sopenharmony_ci
103e5b75505Sopenharmony_ci	if (!context)
104e5b75505Sopenharmony_ci		return NULL;
105e5b75505Sopenharmony_ci
106e5b75505Sopenharmony_ci	if (conf) {
107e5b75505Sopenharmony_ci		context->event_cb = conf->event_cb;
108e5b75505Sopenharmony_ci		context->cb_ctx = conf->cb_ctx;
109e5b75505Sopenharmony_ci		context->cert_in_cb = conf->cert_in_cb;
110e5b75505Sopenharmony_ci	}
111e5b75505Sopenharmony_ci
112e5b75505Sopenharmony_ci	return context;
113e5b75505Sopenharmony_ci}
114e5b75505Sopenharmony_ci
115e5b75505Sopenharmony_ci
116e5b75505Sopenharmony_cistatic void wolfssl_reset_in_data(struct tls_in_data *in,
117e5b75505Sopenharmony_ci				  const struct wpabuf *buf)
118e5b75505Sopenharmony_ci{
119e5b75505Sopenharmony_ci	/* old one not owned by us so don't free */
120e5b75505Sopenharmony_ci	in->in_data = buf;
121e5b75505Sopenharmony_ci	in->consumed = 0;
122e5b75505Sopenharmony_ci}
123e5b75505Sopenharmony_ci
124e5b75505Sopenharmony_ci
125e5b75505Sopenharmony_cistatic void wolfssl_reset_out_data(struct tls_out_data *out)
126e5b75505Sopenharmony_ci{
127e5b75505Sopenharmony_ci	/* old one not owned by us so don't free */
128e5b75505Sopenharmony_ci	out->out_data = wpabuf_alloc_copy("", 0);
129e5b75505Sopenharmony_ci}
130e5b75505Sopenharmony_ci
131e5b75505Sopenharmony_ci
132e5b75505Sopenharmony_ci/* wolfSSL I/O Receive CallBack */
133e5b75505Sopenharmony_cistatic int wolfssl_receive_cb(WOLFSSL *ssl, char *buf, int sz, void *ctx)
134e5b75505Sopenharmony_ci{
135e5b75505Sopenharmony_ci	size_t get = sz;
136e5b75505Sopenharmony_ci	struct tls_in_data *data = ctx;
137e5b75505Sopenharmony_ci
138e5b75505Sopenharmony_ci	if (!data)
139e5b75505Sopenharmony_ci		return -1;
140e5b75505Sopenharmony_ci
141e5b75505Sopenharmony_ci	if (get > (wpabuf_len(data->in_data) - data->consumed))
142e5b75505Sopenharmony_ci		get = wpabuf_len(data->in_data) - data->consumed;
143e5b75505Sopenharmony_ci
144e5b75505Sopenharmony_ci	os_memcpy(buf, wpabuf_head_u8(data->in_data) + data->consumed, get);
145e5b75505Sopenharmony_ci	data->consumed += get;
146e5b75505Sopenharmony_ci
147e5b75505Sopenharmony_ci	if (get == 0)
148e5b75505Sopenharmony_ci		return -2; /* WANT_READ */
149e5b75505Sopenharmony_ci
150e5b75505Sopenharmony_ci	return (int) get;
151e5b75505Sopenharmony_ci}
152e5b75505Sopenharmony_ci
153e5b75505Sopenharmony_ci
154e5b75505Sopenharmony_ci/* wolfSSL I/O Send CallBack */
155e5b75505Sopenharmony_cistatic int wolfssl_send_cb(WOLFSSL *ssl, char *buf, int sz, void *ctx)
156e5b75505Sopenharmony_ci{
157e5b75505Sopenharmony_ci	struct wpabuf *tmp;
158e5b75505Sopenharmony_ci	struct tls_out_data *data = ctx;
159e5b75505Sopenharmony_ci
160e5b75505Sopenharmony_ci	if (!data)
161e5b75505Sopenharmony_ci		return -1;
162e5b75505Sopenharmony_ci
163e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "SSL: adding %d bytes", sz);
164e5b75505Sopenharmony_ci
165e5b75505Sopenharmony_ci	tmp = wpabuf_alloc_copy(buf, sz);
166e5b75505Sopenharmony_ci	if (!tmp)
167e5b75505Sopenharmony_ci		return -1;
168e5b75505Sopenharmony_ci	data->out_data = wpabuf_concat(data->out_data, tmp);
169e5b75505Sopenharmony_ci	if (!data->out_data)
170e5b75505Sopenharmony_ci		return -1;
171e5b75505Sopenharmony_ci
172e5b75505Sopenharmony_ci	return sz;
173e5b75505Sopenharmony_ci}
174e5b75505Sopenharmony_ci
175e5b75505Sopenharmony_ci
176e5b75505Sopenharmony_cistatic void remove_session_cb(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *sess)
177e5b75505Sopenharmony_ci{
178e5b75505Sopenharmony_ci	struct wpabuf *buf;
179e5b75505Sopenharmony_ci
180e5b75505Sopenharmony_ci	buf = wolfSSL_SESSION_get_ex_data(sess, tls_ex_idx_session);
181e5b75505Sopenharmony_ci	if (!buf)
182e5b75505Sopenharmony_ci		return;
183e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG,
184e5b75505Sopenharmony_ci		   "wolfSSL: Free application session data %p (sess %p)",
185e5b75505Sopenharmony_ci		   buf, sess);
186e5b75505Sopenharmony_ci	wpabuf_free(buf);
187e5b75505Sopenharmony_ci
188e5b75505Sopenharmony_ci	wolfSSL_SESSION_set_ex_data(sess, tls_ex_idx_session, NULL);
189e5b75505Sopenharmony_ci}
190e5b75505Sopenharmony_ci
191e5b75505Sopenharmony_ci
192e5b75505Sopenharmony_civoid * tls_init(const struct tls_config *conf)
193e5b75505Sopenharmony_ci{
194e5b75505Sopenharmony_ci	WOLFSSL_CTX *ssl_ctx;
195e5b75505Sopenharmony_ci	struct tls_context *context;
196e5b75505Sopenharmony_ci	const char *ciphers;
197e5b75505Sopenharmony_ci
198e5b75505Sopenharmony_ci#ifdef DEBUG_WOLFSSL
199e5b75505Sopenharmony_ci	wolfSSL_Debugging_ON();
200e5b75505Sopenharmony_ci#endif /* DEBUG_WOLFSSL */
201e5b75505Sopenharmony_ci
202e5b75505Sopenharmony_ci	context = tls_context_new(conf);
203e5b75505Sopenharmony_ci	if (!context)
204e5b75505Sopenharmony_ci		return NULL;
205e5b75505Sopenharmony_ci
206e5b75505Sopenharmony_ci	if (tls_ref_count == 0) {
207e5b75505Sopenharmony_ci		tls_global = context;
208e5b75505Sopenharmony_ci
209e5b75505Sopenharmony_ci		if (wolfSSL_Init() < 0)
210e5b75505Sopenharmony_ci			return NULL;
211e5b75505Sopenharmony_ci		/* wolfSSL_Debugging_ON(); */
212e5b75505Sopenharmony_ci	}
213e5b75505Sopenharmony_ci
214e5b75505Sopenharmony_ci	tls_ref_count++;
215e5b75505Sopenharmony_ci
216e5b75505Sopenharmony_ci	/* start as client */
217e5b75505Sopenharmony_ci	ssl_ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
218e5b75505Sopenharmony_ci	if (!ssl_ctx) {
219e5b75505Sopenharmony_ci		tls_ref_count--;
220e5b75505Sopenharmony_ci		if (context != tls_global)
221e5b75505Sopenharmony_ci			os_free(context);
222e5b75505Sopenharmony_ci		if (tls_ref_count == 0) {
223e5b75505Sopenharmony_ci			os_free(tls_global);
224e5b75505Sopenharmony_ci			tls_global = NULL;
225e5b75505Sopenharmony_ci		}
226e5b75505Sopenharmony_ci	}
227e5b75505Sopenharmony_ci	wolfSSL_SetIORecv(ssl_ctx, wolfssl_receive_cb);
228e5b75505Sopenharmony_ci	wolfSSL_SetIOSend(ssl_ctx, wolfssl_send_cb);
229e5b75505Sopenharmony_ci	wolfSSL_CTX_set_ex_data(ssl_ctx, 0, context);
230e5b75505Sopenharmony_ci
231e5b75505Sopenharmony_ci	if (conf->tls_session_lifetime > 0) {
232e5b75505Sopenharmony_ci		wolfSSL_CTX_set_quiet_shutdown(ssl_ctx, 1);
233e5b75505Sopenharmony_ci		wolfSSL_CTX_set_session_cache_mode(ssl_ctx,
234e5b75505Sopenharmony_ci						   SSL_SESS_CACHE_SERVER);
235e5b75505Sopenharmony_ci		wolfSSL_CTX_set_timeout(ssl_ctx, conf->tls_session_lifetime);
236e5b75505Sopenharmony_ci		wolfSSL_CTX_sess_set_remove_cb(ssl_ctx, remove_session_cb);
237e5b75505Sopenharmony_ci	} else {
238e5b75505Sopenharmony_ci		wolfSSL_CTX_set_session_cache_mode(ssl_ctx,
239e5b75505Sopenharmony_ci						   SSL_SESS_CACHE_CLIENT);
240e5b75505Sopenharmony_ci	}
241e5b75505Sopenharmony_ci
242e5b75505Sopenharmony_ci	if (conf && conf->openssl_ciphers)
243e5b75505Sopenharmony_ci		ciphers = conf->openssl_ciphers;
244e5b75505Sopenharmony_ci	else
245e5b75505Sopenharmony_ci		ciphers = "ALL";
246e5b75505Sopenharmony_ci	if (wolfSSL_CTX_set_cipher_list(ssl_ctx, ciphers) != 1) {
247e5b75505Sopenharmony_ci		wpa_printf(MSG_ERROR,
248e5b75505Sopenharmony_ci			   "wolfSSL: Failed to set cipher string '%s'",
249e5b75505Sopenharmony_ci			   ciphers);
250e5b75505Sopenharmony_ci		tls_deinit(ssl_ctx);
251e5b75505Sopenharmony_ci		return NULL;
252e5b75505Sopenharmony_ci	}
253e5b75505Sopenharmony_ci
254e5b75505Sopenharmony_ci	return ssl_ctx;
255e5b75505Sopenharmony_ci}
256e5b75505Sopenharmony_ci
257e5b75505Sopenharmony_ci
258e5b75505Sopenharmony_civoid tls_deinit(void *ssl_ctx)
259e5b75505Sopenharmony_ci{
260e5b75505Sopenharmony_ci	struct tls_context *context = wolfSSL_CTX_get_ex_data(ssl_ctx, 0);
261e5b75505Sopenharmony_ci
262e5b75505Sopenharmony_ci	if (context != tls_global)
263e5b75505Sopenharmony_ci		os_free(context);
264e5b75505Sopenharmony_ci
265e5b75505Sopenharmony_ci	wolfSSL_CTX_free((WOLFSSL_CTX *) ssl_ctx);
266e5b75505Sopenharmony_ci
267e5b75505Sopenharmony_ci	tls_ref_count--;
268e5b75505Sopenharmony_ci	if (tls_ref_count == 0) {
269e5b75505Sopenharmony_ci		wolfSSL_Cleanup();
270e5b75505Sopenharmony_ci		os_free(tls_global);
271e5b75505Sopenharmony_ci		tls_global = NULL;
272e5b75505Sopenharmony_ci	}
273e5b75505Sopenharmony_ci}
274e5b75505Sopenharmony_ci
275e5b75505Sopenharmony_ci
276e5b75505Sopenharmony_ciint tls_get_errors(void *tls_ctx)
277e5b75505Sopenharmony_ci{
278e5b75505Sopenharmony_ci#ifdef DEBUG_WOLFSSL
279e5b75505Sopenharmony_ci#if 0
280e5b75505Sopenharmony_ci	unsigned long err;
281e5b75505Sopenharmony_ci
282e5b75505Sopenharmony_ci	err = wolfSSL_ERR_peek_last_error_line(NULL, NULL);
283e5b75505Sopenharmony_ci	if (err != 0) {
284e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "TLS - SSL error: %s",
285e5b75505Sopenharmony_ci			   wolfSSL_ERR_error_string(err, NULL));
286e5b75505Sopenharmony_ci		return 1;
287e5b75505Sopenharmony_ci	}
288e5b75505Sopenharmony_ci#endif
289e5b75505Sopenharmony_ci#endif /* DEBUG_WOLFSSL */
290e5b75505Sopenharmony_ci	return 0;
291e5b75505Sopenharmony_ci}
292e5b75505Sopenharmony_ci
293e5b75505Sopenharmony_ci
294e5b75505Sopenharmony_cistruct tls_connection * tls_connection_init(void *tls_ctx)
295e5b75505Sopenharmony_ci{
296e5b75505Sopenharmony_ci	WOLFSSL_CTX *ssl_ctx = tls_ctx;
297e5b75505Sopenharmony_ci	struct tls_connection *conn;
298e5b75505Sopenharmony_ci
299e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "SSL: connection init");
300e5b75505Sopenharmony_ci
301e5b75505Sopenharmony_ci	conn = os_zalloc(sizeof(*conn));
302e5b75505Sopenharmony_ci	if (!conn)
303e5b75505Sopenharmony_ci		return NULL;
304e5b75505Sopenharmony_ci	conn->ssl = wolfSSL_new(ssl_ctx);
305e5b75505Sopenharmony_ci	if (!conn->ssl) {
306e5b75505Sopenharmony_ci		os_free(conn);
307e5b75505Sopenharmony_ci		return NULL;
308e5b75505Sopenharmony_ci	}
309e5b75505Sopenharmony_ci
310e5b75505Sopenharmony_ci	wolfSSL_SetIOReadCtx(conn->ssl,  &conn->input);
311e5b75505Sopenharmony_ci	wolfSSL_SetIOWriteCtx(conn->ssl, &conn->output);
312e5b75505Sopenharmony_ci	wolfSSL_set_ex_data(conn->ssl, 0, conn);
313e5b75505Sopenharmony_ci	conn->context = wolfSSL_CTX_get_ex_data(ssl_ctx, 0);
314e5b75505Sopenharmony_ci
315e5b75505Sopenharmony_ci	/* Need randoms post-hanshake for EAP-FAST, export key and deriving
316e5b75505Sopenharmony_ci	 * session ID in EAP methods. */
317e5b75505Sopenharmony_ci	wolfSSL_KeepArrays(conn->ssl);
318e5b75505Sopenharmony_ci	wolfSSL_KeepHandshakeResources(conn->ssl);
319e5b75505Sopenharmony_ci	wolfSSL_UseClientSuites(conn->ssl);
320e5b75505Sopenharmony_ci
321e5b75505Sopenharmony_ci	return conn;
322e5b75505Sopenharmony_ci}
323e5b75505Sopenharmony_ci
324e5b75505Sopenharmony_ci
325e5b75505Sopenharmony_civoid tls_connection_deinit(void *tls_ctx, struct tls_connection *conn)
326e5b75505Sopenharmony_ci{
327e5b75505Sopenharmony_ci	if (!conn)
328e5b75505Sopenharmony_ci		return;
329e5b75505Sopenharmony_ci
330e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "SSL: connection deinit");
331e5b75505Sopenharmony_ci
332e5b75505Sopenharmony_ci	/* parts */
333e5b75505Sopenharmony_ci	wolfSSL_free(conn->ssl);
334e5b75505Sopenharmony_ci	os_free(conn->subject_match);
335e5b75505Sopenharmony_ci	os_free(conn->alt_subject_match);
336e5b75505Sopenharmony_ci	os_free(conn->suffix_match);
337e5b75505Sopenharmony_ci	os_free(conn->domain_match);
338e5b75505Sopenharmony_ci
339e5b75505Sopenharmony_ci	/* self */
340e5b75505Sopenharmony_ci	os_free(conn);
341e5b75505Sopenharmony_ci}
342e5b75505Sopenharmony_ci
343e5b75505Sopenharmony_ci
344e5b75505Sopenharmony_ciint tls_connection_established(void *tls_ctx, struct tls_connection *conn)
345e5b75505Sopenharmony_ci{
346e5b75505Sopenharmony_ci	return conn ? wolfSSL_is_init_finished(conn->ssl) : 0;
347e5b75505Sopenharmony_ci}
348e5b75505Sopenharmony_ci
349e5b75505Sopenharmony_ci
350e5b75505Sopenharmony_cichar * tls_connection_peer_serial_num(void *tls_ctx,
351e5b75505Sopenharmony_ci				      struct tls_connection *conn)
352e5b75505Sopenharmony_ci{
353e5b75505Sopenharmony_ci	/* TODO */
354e5b75505Sopenharmony_ci	return NULL;
355e5b75505Sopenharmony_ci}
356e5b75505Sopenharmony_ci
357e5b75505Sopenharmony_ci
358e5b75505Sopenharmony_ciint tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
359e5b75505Sopenharmony_ci{
360e5b75505Sopenharmony_ci	WOLFSSL_SESSION *session;
361e5b75505Sopenharmony_ci
362e5b75505Sopenharmony_ci	if (!conn)
363e5b75505Sopenharmony_ci		return -1;
364e5b75505Sopenharmony_ci
365e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "SSL: connection shutdown");
366e5b75505Sopenharmony_ci
367e5b75505Sopenharmony_ci	/* Set quiet as OpenSSL does */
368e5b75505Sopenharmony_ci	wolfSSL_set_quiet_shutdown(conn->ssl, 1);
369e5b75505Sopenharmony_ci	wolfSSL_shutdown(conn->ssl);
370e5b75505Sopenharmony_ci
371e5b75505Sopenharmony_ci	session = wolfSSL_get_session(conn->ssl);
372e5b75505Sopenharmony_ci	if (wolfSSL_clear(conn->ssl) != 1)
373e5b75505Sopenharmony_ci		return -1;
374e5b75505Sopenharmony_ci	wolfSSL_set_session(conn->ssl, session);
375e5b75505Sopenharmony_ci
376e5b75505Sopenharmony_ci	return 0;
377e5b75505Sopenharmony_ci}
378e5b75505Sopenharmony_ci
379e5b75505Sopenharmony_ci
380e5b75505Sopenharmony_cistatic int tls_connection_set_subject_match(struct tls_connection *conn,
381e5b75505Sopenharmony_ci					    const char *subject_match,
382e5b75505Sopenharmony_ci					    const char *alt_subject_match,
383e5b75505Sopenharmony_ci					    const char *suffix_match,
384e5b75505Sopenharmony_ci					    const char *domain_match)
385e5b75505Sopenharmony_ci{
386e5b75505Sopenharmony_ci	os_free(conn->subject_match);
387e5b75505Sopenharmony_ci	conn->subject_match = NULL;
388e5b75505Sopenharmony_ci	if (subject_match) {
389e5b75505Sopenharmony_ci		conn->subject_match = os_strdup(subject_match);
390e5b75505Sopenharmony_ci		if (!conn->subject_match)
391e5b75505Sopenharmony_ci			return -1;
392e5b75505Sopenharmony_ci	}
393e5b75505Sopenharmony_ci
394e5b75505Sopenharmony_ci	os_free(conn->alt_subject_match);
395e5b75505Sopenharmony_ci	conn->alt_subject_match = NULL;
396e5b75505Sopenharmony_ci	if (alt_subject_match) {
397e5b75505Sopenharmony_ci		conn->alt_subject_match = os_strdup(alt_subject_match);
398e5b75505Sopenharmony_ci		if (!conn->alt_subject_match)
399e5b75505Sopenharmony_ci			return -1;
400e5b75505Sopenharmony_ci	}
401e5b75505Sopenharmony_ci
402e5b75505Sopenharmony_ci	os_free(conn->suffix_match);
403e5b75505Sopenharmony_ci	conn->suffix_match = NULL;
404e5b75505Sopenharmony_ci	if (suffix_match) {
405e5b75505Sopenharmony_ci		conn->suffix_match = os_strdup(suffix_match);
406e5b75505Sopenharmony_ci		if (!conn->suffix_match)
407e5b75505Sopenharmony_ci			return -1;
408e5b75505Sopenharmony_ci	}
409e5b75505Sopenharmony_ci
410e5b75505Sopenharmony_ci	os_free(conn->domain_match);
411e5b75505Sopenharmony_ci	conn->domain_match = NULL;
412e5b75505Sopenharmony_ci	if (domain_match) {
413e5b75505Sopenharmony_ci		conn->domain_match = os_strdup(domain_match);
414e5b75505Sopenharmony_ci		if (!conn->domain_match)
415e5b75505Sopenharmony_ci			return -1;
416e5b75505Sopenharmony_ci	}
417e5b75505Sopenharmony_ci
418e5b75505Sopenharmony_ci	return 0;
419e5b75505Sopenharmony_ci}
420e5b75505Sopenharmony_ci
421e5b75505Sopenharmony_ci
422e5b75505Sopenharmony_cistatic int tls_connection_dh(struct tls_connection *conn, const char *dh_file,
423e5b75505Sopenharmony_ci			     const u8 *dh_blob, size_t blob_len)
424e5b75505Sopenharmony_ci{
425e5b75505Sopenharmony_ci	if (!dh_file && !dh_blob)
426e5b75505Sopenharmony_ci		return 0;
427e5b75505Sopenharmony_ci
428e5b75505Sopenharmony_ci	wolfSSL_set_accept_state(conn->ssl);
429e5b75505Sopenharmony_ci
430e5b75505Sopenharmony_ci	if (dh_blob) {
431e5b75505Sopenharmony_ci		if (wolfSSL_SetTmpDH_buffer(conn->ssl, dh_blob, blob_len,
432e5b75505Sopenharmony_ci					    SSL_FILETYPE_ASN1) < 0) {
433e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO, "SSL: use DH DER blob failed");
434e5b75505Sopenharmony_ci			return -1;
435e5b75505Sopenharmony_ci		}
436e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "SSL: use DH blob OK");
437e5b75505Sopenharmony_ci		return 0;
438e5b75505Sopenharmony_ci	}
439e5b75505Sopenharmony_ci
440e5b75505Sopenharmony_ci	if (dh_file) {
441e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "SSL: use DH PEM file: %s", dh_file);
442e5b75505Sopenharmony_ci		if (wolfSSL_SetTmpDH_file(conn->ssl, dh_file,
443e5b75505Sopenharmony_ci					  SSL_FILETYPE_PEM) < 0) {
444e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO, "SSL: use DH PEM file failed");
445e5b75505Sopenharmony_ci			if (wolfSSL_SetTmpDH_file(conn->ssl, dh_file,
446e5b75505Sopenharmony_ci						  SSL_FILETYPE_ASN1) < 0) {
447e5b75505Sopenharmony_ci				wpa_printf(MSG_INFO,
448e5b75505Sopenharmony_ci					   "SSL: use DH DER file failed");
449e5b75505Sopenharmony_ci				return -1;
450e5b75505Sopenharmony_ci			}
451e5b75505Sopenharmony_ci		}
452e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "SSL: use DH file OK");
453e5b75505Sopenharmony_ci		return 0;
454e5b75505Sopenharmony_ci	}
455e5b75505Sopenharmony_ci
456e5b75505Sopenharmony_ci	return 0;
457e5b75505Sopenharmony_ci}
458e5b75505Sopenharmony_ci
459e5b75505Sopenharmony_ci
460e5b75505Sopenharmony_cistatic int tls_connection_client_cert(struct tls_connection *conn,
461e5b75505Sopenharmony_ci				      const char *client_cert,
462e5b75505Sopenharmony_ci				      const u8 *client_cert_blob,
463e5b75505Sopenharmony_ci				      size_t blob_len)
464e5b75505Sopenharmony_ci{
465e5b75505Sopenharmony_ci	if (!client_cert && !client_cert_blob)
466e5b75505Sopenharmony_ci		return 0;
467e5b75505Sopenharmony_ci
468e5b75505Sopenharmony_ci	if (client_cert_blob) {
469e5b75505Sopenharmony_ci		if (wolfSSL_use_certificate_chain_buffer_format(
470e5b75505Sopenharmony_ci			    conn->ssl, client_cert_blob, blob_len,
471e5b75505Sopenharmony_ci			    SSL_FILETYPE_ASN1) < 0) {
472e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
473e5b75505Sopenharmony_ci				   "SSL: use client cert DER blob failed");
474e5b75505Sopenharmony_ci			return -1;
475e5b75505Sopenharmony_ci		}
476e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "SSL: use client cert blob OK");
477e5b75505Sopenharmony_ci		return 0;
478e5b75505Sopenharmony_ci	}
479e5b75505Sopenharmony_ci
480e5b75505Sopenharmony_ci	if (client_cert) {
481e5b75505Sopenharmony_ci		if (wolfSSL_use_certificate_chain_file(conn->ssl,
482e5b75505Sopenharmony_ci						       client_cert) < 0) {
483e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
484e5b75505Sopenharmony_ci				   "SSL: use client cert PEM file failed");
485e5b75505Sopenharmony_ci			if (wolfSSL_use_certificate_chain_file_format(
486e5b75505Sopenharmony_ci				    conn->ssl, client_cert,
487e5b75505Sopenharmony_ci				    SSL_FILETYPE_ASN1) < 0) {
488e5b75505Sopenharmony_ci				wpa_printf(MSG_INFO,
489e5b75505Sopenharmony_ci					   "SSL: use client cert DER file failed");
490e5b75505Sopenharmony_ci				return -1;
491e5b75505Sopenharmony_ci			}
492e5b75505Sopenharmony_ci		}
493e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "SSL: use client cert file OK");
494e5b75505Sopenharmony_ci		return 0;
495e5b75505Sopenharmony_ci	}
496e5b75505Sopenharmony_ci
497e5b75505Sopenharmony_ci	return 0;
498e5b75505Sopenharmony_ci}
499e5b75505Sopenharmony_ci
500e5b75505Sopenharmony_ci
501e5b75505Sopenharmony_cistatic int tls_passwd_cb(char *buf, int size, int rwflag, void *password)
502e5b75505Sopenharmony_ci{
503e5b75505Sopenharmony_ci	if (!password)
504e5b75505Sopenharmony_ci		return 0;
505e5b75505Sopenharmony_ci	os_strlcpy(buf, (char *) password, size);
506e5b75505Sopenharmony_ci	return os_strlen(buf);
507e5b75505Sopenharmony_ci}
508e5b75505Sopenharmony_ci
509e5b75505Sopenharmony_ci
510e5b75505Sopenharmony_cistatic int tls_connection_private_key(void *tls_ctx,
511e5b75505Sopenharmony_ci				      struct tls_connection *conn,
512e5b75505Sopenharmony_ci				      const char *private_key,
513e5b75505Sopenharmony_ci				      const char *private_key_passwd,
514e5b75505Sopenharmony_ci				      const u8 *private_key_blob,
515e5b75505Sopenharmony_ci				      size_t blob_len)
516e5b75505Sopenharmony_ci{
517e5b75505Sopenharmony_ci	WOLFSSL_CTX *ctx = tls_ctx;
518e5b75505Sopenharmony_ci	char *passwd = NULL;
519e5b75505Sopenharmony_ci	int ok = 0;
520e5b75505Sopenharmony_ci
521e5b75505Sopenharmony_ci	if (!private_key && !private_key_blob)
522e5b75505Sopenharmony_ci		return 0;
523e5b75505Sopenharmony_ci
524e5b75505Sopenharmony_ci	if (private_key_passwd) {
525e5b75505Sopenharmony_ci		passwd = os_strdup(private_key_passwd);
526e5b75505Sopenharmony_ci		if (!passwd)
527e5b75505Sopenharmony_ci			return -1;
528e5b75505Sopenharmony_ci	}
529e5b75505Sopenharmony_ci
530e5b75505Sopenharmony_ci	wolfSSL_CTX_set_default_passwd_cb(ctx, tls_passwd_cb);
531e5b75505Sopenharmony_ci	wolfSSL_CTX_set_default_passwd_cb_userdata(ctx, passwd);
532e5b75505Sopenharmony_ci
533e5b75505Sopenharmony_ci	if (private_key_blob) {
534e5b75505Sopenharmony_ci		if (wolfSSL_use_PrivateKey_buffer(conn->ssl,
535e5b75505Sopenharmony_ci						  private_key_blob, blob_len,
536e5b75505Sopenharmony_ci						  SSL_FILETYPE_ASN1) < 0) {
537e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
538e5b75505Sopenharmony_ci				   "SSL: use private DER blob failed");
539e5b75505Sopenharmony_ci		} else {
540e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "SSL: use private key blob OK");
541e5b75505Sopenharmony_ci			ok = 1;
542e5b75505Sopenharmony_ci		}
543e5b75505Sopenharmony_ci	}
544e5b75505Sopenharmony_ci
545e5b75505Sopenharmony_ci	if (!ok && private_key) {
546e5b75505Sopenharmony_ci		if (wolfSSL_use_PrivateKey_file(conn->ssl, private_key,
547e5b75505Sopenharmony_ci						SSL_FILETYPE_PEM) < 0) {
548e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
549e5b75505Sopenharmony_ci				   "SSL: use private key PEM file failed");
550e5b75505Sopenharmony_ci			if (wolfSSL_use_PrivateKey_file(conn->ssl, private_key,
551e5b75505Sopenharmony_ci							SSL_FILETYPE_ASN1) < 0)
552e5b75505Sopenharmony_ci			{
553e5b75505Sopenharmony_ci				wpa_printf(MSG_INFO,
554e5b75505Sopenharmony_ci					   "SSL: use private key DER file failed");
555e5b75505Sopenharmony_ci			} else {
556e5b75505Sopenharmony_ci				ok = 1;
557e5b75505Sopenharmony_ci			}
558e5b75505Sopenharmony_ci		} else {
559e5b75505Sopenharmony_ci			ok = 1;
560e5b75505Sopenharmony_ci		}
561e5b75505Sopenharmony_ci
562e5b75505Sopenharmony_ci		if (ok)
563e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "SSL: use private key file OK");
564e5b75505Sopenharmony_ci	}
565e5b75505Sopenharmony_ci
566e5b75505Sopenharmony_ci	wolfSSL_CTX_set_default_passwd_cb(ctx, NULL);
567e5b75505Sopenharmony_ci	os_free(passwd);
568e5b75505Sopenharmony_ci
569e5b75505Sopenharmony_ci	if (!ok)
570e5b75505Sopenharmony_ci		return -1;
571e5b75505Sopenharmony_ci
572e5b75505Sopenharmony_ci	return 0;
573e5b75505Sopenharmony_ci}
574e5b75505Sopenharmony_ci
575e5b75505Sopenharmony_ci
576e5b75505Sopenharmony_cistatic int tls_match_alt_subject_component(WOLFSSL_X509 *cert, int type,
577e5b75505Sopenharmony_ci					   const char *value, size_t len)
578e5b75505Sopenharmony_ci{
579e5b75505Sopenharmony_ci	WOLFSSL_ASN1_OBJECT *gen;
580e5b75505Sopenharmony_ci	void *ext;
581e5b75505Sopenharmony_ci	int found = 0;
582e5b75505Sopenharmony_ci	int i;
583e5b75505Sopenharmony_ci
584e5b75505Sopenharmony_ci	ext = wolfSSL_X509_get_ext_d2i(cert, ALT_NAMES_OID, NULL, NULL);
585e5b75505Sopenharmony_ci
586e5b75505Sopenharmony_ci	for (i = 0; ext && i < wolfSSL_sk_num(ext); i++) {
587e5b75505Sopenharmony_ci		gen = wolfSSL_sk_value(ext, i);
588e5b75505Sopenharmony_ci		if (gen->type != type)
589e5b75505Sopenharmony_ci			continue;
590e5b75505Sopenharmony_ci		if (os_strlen((char *) gen->obj) == len &&
591e5b75505Sopenharmony_ci		    os_memcmp(value, gen->obj, len) == 0)
592e5b75505Sopenharmony_ci			found++;
593e5b75505Sopenharmony_ci	}
594e5b75505Sopenharmony_ci
595e5b75505Sopenharmony_ci	wolfSSL_sk_ASN1_OBJECT_free(ext);
596e5b75505Sopenharmony_ci
597e5b75505Sopenharmony_ci	return found;
598e5b75505Sopenharmony_ci}
599e5b75505Sopenharmony_ci
600e5b75505Sopenharmony_ci
601e5b75505Sopenharmony_cistatic int tls_match_alt_subject(WOLFSSL_X509 *cert, const char *match)
602e5b75505Sopenharmony_ci{
603e5b75505Sopenharmony_ci	int type;
604e5b75505Sopenharmony_ci	const char *pos, *end;
605e5b75505Sopenharmony_ci	size_t len;
606e5b75505Sopenharmony_ci
607e5b75505Sopenharmony_ci	pos = match;
608e5b75505Sopenharmony_ci	do {
609e5b75505Sopenharmony_ci		if (os_strncmp(pos, "EMAIL:", 6) == 0) {
610e5b75505Sopenharmony_ci			type = GEN_EMAIL;
611e5b75505Sopenharmony_ci			pos += 6;
612e5b75505Sopenharmony_ci		} else if (os_strncmp(pos, "DNS:", 4) == 0) {
613e5b75505Sopenharmony_ci			type = GEN_DNS;
614e5b75505Sopenharmony_ci			pos += 4;
615e5b75505Sopenharmony_ci		} else if (os_strncmp(pos, "URI:", 4) == 0) {
616e5b75505Sopenharmony_ci			type = GEN_URI;
617e5b75505Sopenharmony_ci			pos += 4;
618e5b75505Sopenharmony_ci		} else {
619e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
620e5b75505Sopenharmony_ci				   "TLS: Invalid altSubjectName match '%s'",
621e5b75505Sopenharmony_ci				   pos);
622e5b75505Sopenharmony_ci			return 0;
623e5b75505Sopenharmony_ci		}
624e5b75505Sopenharmony_ci		end = os_strchr(pos, ';');
625e5b75505Sopenharmony_ci		while (end) {
626e5b75505Sopenharmony_ci			if (os_strncmp(end + 1, "EMAIL:", 6) == 0 ||
627e5b75505Sopenharmony_ci			    os_strncmp(end + 1, "DNS:", 4) == 0 ||
628e5b75505Sopenharmony_ci			    os_strncmp(end + 1, "URI:", 4) == 0)
629e5b75505Sopenharmony_ci				break;
630e5b75505Sopenharmony_ci			end = os_strchr(end + 1, ';');
631e5b75505Sopenharmony_ci		}
632e5b75505Sopenharmony_ci		if (end)
633e5b75505Sopenharmony_ci			len = end - pos;
634e5b75505Sopenharmony_ci		else
635e5b75505Sopenharmony_ci			len = os_strlen(pos);
636e5b75505Sopenharmony_ci		if (tls_match_alt_subject_component(cert, type, pos, len) > 0)
637e5b75505Sopenharmony_ci			return 1;
638e5b75505Sopenharmony_ci		pos = end + 1;
639e5b75505Sopenharmony_ci	} while (end);
640e5b75505Sopenharmony_ci
641e5b75505Sopenharmony_ci	return 0;
642e5b75505Sopenharmony_ci}
643e5b75505Sopenharmony_ci
644e5b75505Sopenharmony_ci
645e5b75505Sopenharmony_cistatic int domain_suffix_match(const char *val, size_t len, const char *match,
646e5b75505Sopenharmony_ci			       size_t match_len, int full)
647e5b75505Sopenharmony_ci{
648e5b75505Sopenharmony_ci	size_t i;
649e5b75505Sopenharmony_ci
650e5b75505Sopenharmony_ci	/* Check for embedded nuls that could mess up suffix matching */
651e5b75505Sopenharmony_ci	for (i = 0; i < len; i++) {
652e5b75505Sopenharmony_ci		if (val[i] == '\0') {
653e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
654e5b75505Sopenharmony_ci				   "TLS: Embedded null in a string - reject");
655e5b75505Sopenharmony_ci			return 0;
656e5b75505Sopenharmony_ci		}
657e5b75505Sopenharmony_ci	}
658e5b75505Sopenharmony_ci
659e5b75505Sopenharmony_ci	if (match_len > len || (full && match_len != len))
660e5b75505Sopenharmony_ci		return 0;
661e5b75505Sopenharmony_ci
662e5b75505Sopenharmony_ci	if (os_strncasecmp(val + len - match_len, match, match_len) != 0)
663e5b75505Sopenharmony_ci		return 0; /* no match */
664e5b75505Sopenharmony_ci
665e5b75505Sopenharmony_ci	if (match_len == len)
666e5b75505Sopenharmony_ci		return 1; /* exact match */
667e5b75505Sopenharmony_ci
668e5b75505Sopenharmony_ci	if (val[len - match_len - 1] == '.')
669e5b75505Sopenharmony_ci		return 1; /* full label match completes suffix match */
670e5b75505Sopenharmony_ci
671e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "TLS: Reject due to incomplete label match");
672e5b75505Sopenharmony_ci	return 0;
673e5b75505Sopenharmony_ci}
674e5b75505Sopenharmony_ci
675e5b75505Sopenharmony_ci
676e5b75505Sopenharmony_cistatic int tls_match_suffix_helper(WOLFSSL_X509 *cert, const char *match,
677e5b75505Sopenharmony_ci				   size_t match_len, int full)
678e5b75505Sopenharmony_ci{
679e5b75505Sopenharmony_ci	WOLFSSL_ASN1_OBJECT *gen;
680e5b75505Sopenharmony_ci	void *ext;
681e5b75505Sopenharmony_ci	int i;
682e5b75505Sopenharmony_ci	int j;
683e5b75505Sopenharmony_ci	int dns_name = 0;
684e5b75505Sopenharmony_ci	WOLFSSL_X509_NAME *name;
685e5b75505Sopenharmony_ci
686e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "TLS: Match domain against %s%s",
687e5b75505Sopenharmony_ci		   full ? "" : "suffix ", match);
688e5b75505Sopenharmony_ci
689e5b75505Sopenharmony_ci	ext = wolfSSL_X509_get_ext_d2i(cert, ALT_NAMES_OID, NULL, NULL);
690e5b75505Sopenharmony_ci
691e5b75505Sopenharmony_ci	for (j = 0; ext && j < wolfSSL_sk_num(ext); j++) {
692e5b75505Sopenharmony_ci		gen = wolfSSL_sk_value(ext, j);
693e5b75505Sopenharmony_ci		if (gen->type != ASN_DNS_TYPE)
694e5b75505Sopenharmony_ci			continue;
695e5b75505Sopenharmony_ci		dns_name++;
696e5b75505Sopenharmony_ci		wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate dNSName",
697e5b75505Sopenharmony_ci				  gen->obj, os_strlen((char *)gen->obj));
698e5b75505Sopenharmony_ci		if (domain_suffix_match((const char *) gen->obj,
699e5b75505Sopenharmony_ci					os_strlen((char *) gen->obj), match,
700e5b75505Sopenharmony_ci					match_len, full) == 1) {
701e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "TLS: %s in dNSName found",
702e5b75505Sopenharmony_ci				   full ? "Match" : "Suffix match");
703e5b75505Sopenharmony_ci			wolfSSL_sk_ASN1_OBJECT_free(ext);
704e5b75505Sopenharmony_ci			return 1;
705e5b75505Sopenharmony_ci		}
706e5b75505Sopenharmony_ci	}
707e5b75505Sopenharmony_ci	wolfSSL_sk_ASN1_OBJECT_free(ext);
708e5b75505Sopenharmony_ci
709e5b75505Sopenharmony_ci	if (dns_name) {
710e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "TLS: None of the dNSName(s) matched");
711e5b75505Sopenharmony_ci		return 0;
712e5b75505Sopenharmony_ci	}
713e5b75505Sopenharmony_ci
714e5b75505Sopenharmony_ci	name = wolfSSL_X509_get_subject_name(cert);
715e5b75505Sopenharmony_ci	i = -1;
716e5b75505Sopenharmony_ci	for (;;) {
717e5b75505Sopenharmony_ci		WOLFSSL_X509_NAME_ENTRY *e;
718e5b75505Sopenharmony_ci		WOLFSSL_ASN1_STRING *cn;
719e5b75505Sopenharmony_ci
720e5b75505Sopenharmony_ci		i = wolfSSL_X509_NAME_get_index_by_NID(name, ASN_COMMON_NAME,
721e5b75505Sopenharmony_ci						       i);
722e5b75505Sopenharmony_ci		if (i == -1)
723e5b75505Sopenharmony_ci			break;
724e5b75505Sopenharmony_ci		e = wolfSSL_X509_NAME_get_entry(name, i);
725e5b75505Sopenharmony_ci		if (!e)
726e5b75505Sopenharmony_ci			continue;
727e5b75505Sopenharmony_ci		cn = wolfSSL_X509_NAME_ENTRY_get_data(e);
728e5b75505Sopenharmony_ci		if (!cn)
729e5b75505Sopenharmony_ci			continue;
730e5b75505Sopenharmony_ci		wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate commonName",
731e5b75505Sopenharmony_ci				  cn->data, cn->length);
732e5b75505Sopenharmony_ci		if (domain_suffix_match(cn->data, cn->length,
733e5b75505Sopenharmony_ci					match, match_len, full) == 1) {
734e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG, "TLS: %s in commonName found",
735e5b75505Sopenharmony_ci				   full ? "Match" : "Suffix match");
736e5b75505Sopenharmony_ci			return 1;
737e5b75505Sopenharmony_ci		}
738e5b75505Sopenharmony_ci	}
739e5b75505Sopenharmony_ci
740e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "TLS: No CommonName %smatch found",
741e5b75505Sopenharmony_ci		   full ? "" : "suffix ");
742e5b75505Sopenharmony_ci	return 0;
743e5b75505Sopenharmony_ci}
744e5b75505Sopenharmony_ci
745e5b75505Sopenharmony_ci
746e5b75505Sopenharmony_cistatic int tls_match_suffix(WOLFSSL_X509 *cert, const char *match, int full)
747e5b75505Sopenharmony_ci{
748e5b75505Sopenharmony_ci	const char *token, *last = NULL;
749e5b75505Sopenharmony_ci
750e5b75505Sopenharmony_ci	/* Process each match alternative separately until a match is found */
751e5b75505Sopenharmony_ci	while ((token = cstr_token(match, ";", &last))) {
752e5b75505Sopenharmony_ci		if (tls_match_suffix_helper(cert, token, last - token, full))
753e5b75505Sopenharmony_ci			return 1;
754e5b75505Sopenharmony_ci	}
755e5b75505Sopenharmony_ci
756e5b75505Sopenharmony_ci	return 0;
757e5b75505Sopenharmony_ci}
758e5b75505Sopenharmony_ci
759e5b75505Sopenharmony_ci
760e5b75505Sopenharmony_cistatic enum tls_fail_reason wolfssl_tls_fail_reason(int err)
761e5b75505Sopenharmony_ci{
762e5b75505Sopenharmony_ci	switch (err) {
763e5b75505Sopenharmony_ci	case X509_V_ERR_CERT_REVOKED:
764e5b75505Sopenharmony_ci		return TLS_FAIL_REVOKED;
765e5b75505Sopenharmony_ci	case ASN_BEFORE_DATE_E:
766e5b75505Sopenharmony_ci	case X509_V_ERR_CERT_NOT_YET_VALID:
767e5b75505Sopenharmony_ci	case X509_V_ERR_CRL_NOT_YET_VALID:
768e5b75505Sopenharmony_ci		return TLS_FAIL_NOT_YET_VALID;
769e5b75505Sopenharmony_ci	case ASN_AFTER_DATE_E:
770e5b75505Sopenharmony_ci	case X509_V_ERR_CERT_HAS_EXPIRED:
771e5b75505Sopenharmony_ci	case X509_V_ERR_CRL_HAS_EXPIRED:
772e5b75505Sopenharmony_ci		return TLS_FAIL_EXPIRED;
773e5b75505Sopenharmony_ci	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
774e5b75505Sopenharmony_ci	case X509_V_ERR_UNABLE_TO_GET_CRL:
775e5b75505Sopenharmony_ci	case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
776e5b75505Sopenharmony_ci	case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
777e5b75505Sopenharmony_ci	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
778e5b75505Sopenharmony_ci	case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
779e5b75505Sopenharmony_ci	case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
780e5b75505Sopenharmony_ci	case X509_V_ERR_CERT_CHAIN_TOO_LONG:
781e5b75505Sopenharmony_ci	case X509_V_ERR_PATH_LENGTH_EXCEEDED:
782e5b75505Sopenharmony_ci	case X509_V_ERR_INVALID_CA:
783e5b75505Sopenharmony_ci		return TLS_FAIL_UNTRUSTED;
784e5b75505Sopenharmony_ci	case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
785e5b75505Sopenharmony_ci	case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
786e5b75505Sopenharmony_ci	case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
787e5b75505Sopenharmony_ci	case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
788e5b75505Sopenharmony_ci	case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
789e5b75505Sopenharmony_ci	case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
790e5b75505Sopenharmony_ci	case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
791e5b75505Sopenharmony_ci	case X509_V_ERR_CERT_UNTRUSTED:
792e5b75505Sopenharmony_ci	case X509_V_ERR_CERT_REJECTED:
793e5b75505Sopenharmony_ci		return TLS_FAIL_BAD_CERTIFICATE;
794e5b75505Sopenharmony_ci	default:
795e5b75505Sopenharmony_ci		return TLS_FAIL_UNSPECIFIED;
796e5b75505Sopenharmony_ci	}
797e5b75505Sopenharmony_ci}
798e5b75505Sopenharmony_ci
799e5b75505Sopenharmony_ci
800e5b75505Sopenharmony_cistatic const char * wolfssl_tls_err_string(int err, const char *err_str)
801e5b75505Sopenharmony_ci{
802e5b75505Sopenharmony_ci	switch (err) {
803e5b75505Sopenharmony_ci	case ASN_BEFORE_DATE_E:
804e5b75505Sopenharmony_ci		return "certificate is not yet valid";
805e5b75505Sopenharmony_ci	case ASN_AFTER_DATE_E:
806e5b75505Sopenharmony_ci		return "certificate has expired";
807e5b75505Sopenharmony_ci	default:
808e5b75505Sopenharmony_ci		return err_str;
809e5b75505Sopenharmony_ci	}
810e5b75505Sopenharmony_ci}
811e5b75505Sopenharmony_ci
812e5b75505Sopenharmony_ci
813e5b75505Sopenharmony_cistatic struct wpabuf * get_x509_cert(WOLFSSL_X509 *cert)
814e5b75505Sopenharmony_ci{
815e5b75505Sopenharmony_ci	struct wpabuf *buf = NULL;
816e5b75505Sopenharmony_ci	const u8 *data;
817e5b75505Sopenharmony_ci	int cert_len;
818e5b75505Sopenharmony_ci
819e5b75505Sopenharmony_ci	data = wolfSSL_X509_get_der(cert, &cert_len);
820e5b75505Sopenharmony_ci	if (!data)
821e5b75505Sopenharmony_ci		buf = wpabuf_alloc_copy(data, cert_len);
822e5b75505Sopenharmony_ci
823e5b75505Sopenharmony_ci	return buf;
824e5b75505Sopenharmony_ci}
825e5b75505Sopenharmony_ci
826e5b75505Sopenharmony_ci
827e5b75505Sopenharmony_cistatic void wolfssl_tls_fail_event(struct tls_connection *conn,
828e5b75505Sopenharmony_ci				   WOLFSSL_X509 *err_cert, int err, int depth,
829e5b75505Sopenharmony_ci				   const char *subject, const char *err_str,
830e5b75505Sopenharmony_ci				   enum tls_fail_reason reason)
831e5b75505Sopenharmony_ci{
832e5b75505Sopenharmony_ci	union tls_event_data ev;
833e5b75505Sopenharmony_ci	struct wpabuf *cert = NULL;
834e5b75505Sopenharmony_ci	struct tls_context *context = conn->context;
835e5b75505Sopenharmony_ci
836e5b75505Sopenharmony_ci	if (!context->event_cb)
837e5b75505Sopenharmony_ci		return;
838e5b75505Sopenharmony_ci
839e5b75505Sopenharmony_ci	cert = get_x509_cert(err_cert);
840e5b75505Sopenharmony_ci	os_memset(&ev, 0, sizeof(ev));
841e5b75505Sopenharmony_ci	ev.cert_fail.reason = reason != TLS_FAIL_UNSPECIFIED ?
842e5b75505Sopenharmony_ci		reason : wolfssl_tls_fail_reason(err);
843e5b75505Sopenharmony_ci	ev.cert_fail.depth = depth;
844e5b75505Sopenharmony_ci	ev.cert_fail.subject = subject;
845e5b75505Sopenharmony_ci	ev.cert_fail.reason_txt = wolfssl_tls_err_string(err, err_str);
846e5b75505Sopenharmony_ci	ev.cert_fail.cert = cert;
847e5b75505Sopenharmony_ci	context->event_cb(context->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
848e5b75505Sopenharmony_ci	wpabuf_free(cert);
849e5b75505Sopenharmony_ci}
850e5b75505Sopenharmony_ci
851e5b75505Sopenharmony_ci
852e5b75505Sopenharmony_cistatic void wolfssl_tls_cert_event(struct tls_connection *conn,
853e5b75505Sopenharmony_ci				   WOLFSSL_X509 *err_cert, int depth,
854e5b75505Sopenharmony_ci				   const char *subject)
855e5b75505Sopenharmony_ci{
856e5b75505Sopenharmony_ci	struct wpabuf *cert = NULL;
857e5b75505Sopenharmony_ci	union tls_event_data ev;
858e5b75505Sopenharmony_ci	struct tls_context *context = conn->context;
859e5b75505Sopenharmony_ci	char *alt_subject[TLS_MAX_ALT_SUBJECT];
860e5b75505Sopenharmony_ci	int alt, num_alt_subject = 0;
861e5b75505Sopenharmony_ci	WOLFSSL_ASN1_OBJECT *gen;
862e5b75505Sopenharmony_ci	void *ext;
863e5b75505Sopenharmony_ci	int i;
864e5b75505Sopenharmony_ci#ifdef CONFIG_SHA256
865e5b75505Sopenharmony_ci	u8 hash[32];
866e5b75505Sopenharmony_ci#endif /* CONFIG_SHA256 */
867e5b75505Sopenharmony_ci
868e5b75505Sopenharmony_ci	if (!context->event_cb)
869e5b75505Sopenharmony_ci		return;
870e5b75505Sopenharmony_ci
871e5b75505Sopenharmony_ci	os_memset(&ev, 0, sizeof(ev));
872e5b75505Sopenharmony_ci	if (conn->cert_probe || (conn->flags & TLS_CONN_EXT_CERT_CHECK) ||
873e5b75505Sopenharmony_ci	    context->cert_in_cb) {
874e5b75505Sopenharmony_ci		cert = get_x509_cert(err_cert);
875e5b75505Sopenharmony_ci		ev.peer_cert.cert = cert;
876e5b75505Sopenharmony_ci	}
877e5b75505Sopenharmony_ci
878e5b75505Sopenharmony_ci#ifdef CONFIG_SHA256
879e5b75505Sopenharmony_ci	if (cert) {
880e5b75505Sopenharmony_ci		const u8 *addr[1];
881e5b75505Sopenharmony_ci		size_t len[1];
882e5b75505Sopenharmony_ci
883e5b75505Sopenharmony_ci		addr[0] = wpabuf_head(cert);
884e5b75505Sopenharmony_ci		len[0] = wpabuf_len(cert);
885e5b75505Sopenharmony_ci		if (sha256_vector(1, addr, len, hash) == 0) {
886e5b75505Sopenharmony_ci			ev.peer_cert.hash = hash;
887e5b75505Sopenharmony_ci			ev.peer_cert.hash_len = sizeof(hash);
888e5b75505Sopenharmony_ci		}
889e5b75505Sopenharmony_ci	}
890e5b75505Sopenharmony_ci#endif /* CONFIG_SHA256 */
891e5b75505Sopenharmony_ci
892e5b75505Sopenharmony_ci	ev.peer_cert.depth = depth;
893e5b75505Sopenharmony_ci	ev.peer_cert.subject = subject;
894e5b75505Sopenharmony_ci
895e5b75505Sopenharmony_ci	ext = wolfSSL_X509_get_ext_d2i(err_cert, ALT_NAMES_OID, NULL, NULL);
896e5b75505Sopenharmony_ci	for (i = 0; ext && i < wolfSSL_sk_num(ext); i++) {
897e5b75505Sopenharmony_ci		char *pos;
898e5b75505Sopenharmony_ci
899e5b75505Sopenharmony_ci		if (num_alt_subject == TLS_MAX_ALT_SUBJECT)
900e5b75505Sopenharmony_ci			break;
901e5b75505Sopenharmony_ci		gen = wolfSSL_sk_value((void *) ext, i);
902e5b75505Sopenharmony_ci		if (gen->type != GEN_EMAIL &&
903e5b75505Sopenharmony_ci		    gen->type != GEN_DNS &&
904e5b75505Sopenharmony_ci		    gen->type != GEN_URI)
905e5b75505Sopenharmony_ci			continue;
906e5b75505Sopenharmony_ci
907e5b75505Sopenharmony_ci		pos = os_malloc(10 + os_strlen((char *) gen->obj) + 1);
908e5b75505Sopenharmony_ci		if (!pos)
909e5b75505Sopenharmony_ci			break;
910e5b75505Sopenharmony_ci		alt_subject[num_alt_subject++] = pos;
911e5b75505Sopenharmony_ci
912e5b75505Sopenharmony_ci		switch (gen->type) {
913e5b75505Sopenharmony_ci		case GEN_EMAIL:
914e5b75505Sopenharmony_ci			os_memcpy(pos, "EMAIL:", 6);
915e5b75505Sopenharmony_ci			pos += 6;
916e5b75505Sopenharmony_ci			break;
917e5b75505Sopenharmony_ci		case GEN_DNS:
918e5b75505Sopenharmony_ci			os_memcpy(pos, "DNS:", 4);
919e5b75505Sopenharmony_ci			pos += 4;
920e5b75505Sopenharmony_ci			break;
921e5b75505Sopenharmony_ci		case GEN_URI:
922e5b75505Sopenharmony_ci			os_memcpy(pos, "URI:", 4);
923e5b75505Sopenharmony_ci			pos += 4;
924e5b75505Sopenharmony_ci			break;
925e5b75505Sopenharmony_ci		}
926e5b75505Sopenharmony_ci
927e5b75505Sopenharmony_ci		os_memcpy(pos, gen->obj, os_strlen((char *)gen->obj));
928e5b75505Sopenharmony_ci		pos += os_strlen((char *)gen->obj);
929e5b75505Sopenharmony_ci		*pos = '\0';
930e5b75505Sopenharmony_ci	}
931e5b75505Sopenharmony_ci	wolfSSL_sk_ASN1_OBJECT_free(ext);
932e5b75505Sopenharmony_ci
933e5b75505Sopenharmony_ci	for (alt = 0; alt < num_alt_subject; alt++)
934e5b75505Sopenharmony_ci		ev.peer_cert.altsubject[alt] = alt_subject[alt];
935e5b75505Sopenharmony_ci	ev.peer_cert.num_altsubject = num_alt_subject;
936e5b75505Sopenharmony_ci
937e5b75505Sopenharmony_ci	context->event_cb(context->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
938e5b75505Sopenharmony_ci	wpabuf_free(cert);
939e5b75505Sopenharmony_ci	for (alt = 0; alt < num_alt_subject; alt++)
940e5b75505Sopenharmony_ci		os_free(alt_subject[alt]);
941e5b75505Sopenharmony_ci}
942e5b75505Sopenharmony_ci
943e5b75505Sopenharmony_ci
944e5b75505Sopenharmony_cistatic int tls_verify_cb(int preverify_ok, WOLFSSL_X509_STORE_CTX *x509_ctx)
945e5b75505Sopenharmony_ci{
946e5b75505Sopenharmony_ci	char buf[256];
947e5b75505Sopenharmony_ci	WOLFSSL_X509 *err_cert;
948e5b75505Sopenharmony_ci	int err, depth;
949e5b75505Sopenharmony_ci	WOLFSSL *ssl;
950e5b75505Sopenharmony_ci	struct tls_connection *conn;
951e5b75505Sopenharmony_ci	struct tls_context *context;
952e5b75505Sopenharmony_ci	char *match, *altmatch, *suffix_match, *domain_match;
953e5b75505Sopenharmony_ci	const char *err_str;
954e5b75505Sopenharmony_ci
955e5b75505Sopenharmony_ci	err_cert = wolfSSL_X509_STORE_CTX_get_current_cert(x509_ctx);
956e5b75505Sopenharmony_ci	if (!err_cert) {
957e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "wolfSSL: No Cert");
958e5b75505Sopenharmony_ci		return 0;
959e5b75505Sopenharmony_ci	}
960e5b75505Sopenharmony_ci
961e5b75505Sopenharmony_ci	err = wolfSSL_X509_STORE_CTX_get_error(x509_ctx);
962e5b75505Sopenharmony_ci	depth = wolfSSL_X509_STORE_CTX_get_error_depth(x509_ctx);
963e5b75505Sopenharmony_ci	ssl = wolfSSL_X509_STORE_CTX_get_ex_data(
964e5b75505Sopenharmony_ci		x509_ctx, wolfSSL_get_ex_data_X509_STORE_CTX_idx());
965e5b75505Sopenharmony_ci	wolfSSL_X509_NAME_oneline(wolfSSL_X509_get_subject_name(err_cert), buf,
966e5b75505Sopenharmony_ci				  sizeof(buf));
967e5b75505Sopenharmony_ci
968e5b75505Sopenharmony_ci	conn = wolfSSL_get_ex_data(ssl, 0);
969e5b75505Sopenharmony_ci	if (!conn) {
970e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "wolfSSL: No ex_data");
971e5b75505Sopenharmony_ci		return 0;
972e5b75505Sopenharmony_ci	}
973e5b75505Sopenharmony_ci
974e5b75505Sopenharmony_ci	if (depth == 0)
975e5b75505Sopenharmony_ci		conn->peer_cert = err_cert;
976e5b75505Sopenharmony_ci	else if (depth == 1)
977e5b75505Sopenharmony_ci		conn->peer_issuer = err_cert;
978e5b75505Sopenharmony_ci	else if (depth == 2)
979e5b75505Sopenharmony_ci		conn->peer_issuer_issuer = err_cert;
980e5b75505Sopenharmony_ci
981e5b75505Sopenharmony_ci	context = conn->context;
982e5b75505Sopenharmony_ci	match = conn->subject_match;
983e5b75505Sopenharmony_ci	altmatch = conn->alt_subject_match;
984e5b75505Sopenharmony_ci	suffix_match = conn->suffix_match;
985e5b75505Sopenharmony_ci	domain_match = conn->domain_match;
986e5b75505Sopenharmony_ci
987e5b75505Sopenharmony_ci	if (!preverify_ok && !conn->ca_cert_verify)
988e5b75505Sopenharmony_ci		preverify_ok = 1;
989e5b75505Sopenharmony_ci	if (!preverify_ok && depth > 0 && conn->server_cert_only)
990e5b75505Sopenharmony_ci		preverify_ok = 1;
991e5b75505Sopenharmony_ci	if (!preverify_ok && (conn->flags & TLS_CONN_DISABLE_TIME_CHECKS) &&
992e5b75505Sopenharmony_ci	    (err == X509_V_ERR_CERT_HAS_EXPIRED ||
993e5b75505Sopenharmony_ci	     err == ASN_AFTER_DATE_E || err == ASN_BEFORE_DATE_E ||
994e5b75505Sopenharmony_ci	     err == X509_V_ERR_CERT_NOT_YET_VALID)) {
995e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
996e5b75505Sopenharmony_ci			   "wolfSSL: Ignore certificate validity time mismatch");
997e5b75505Sopenharmony_ci		preverify_ok = 1;
998e5b75505Sopenharmony_ci	}
999e5b75505Sopenharmony_ci
1000e5b75505Sopenharmony_ci	err_str = wolfSSL_X509_verify_cert_error_string(err);
1001e5b75505Sopenharmony_ci
1002e5b75505Sopenharmony_ci#ifdef CONFIG_SHA256
1003e5b75505Sopenharmony_ci	/*
1004e5b75505Sopenharmony_ci	 * Do not require preverify_ok so we can explicity allow otherwise
1005e5b75505Sopenharmony_ci	 * invalid pinned server certificates.
1006e5b75505Sopenharmony_ci	 */
1007e5b75505Sopenharmony_ci	if (depth == 0 && conn->server_cert_only) {
1008e5b75505Sopenharmony_ci		struct wpabuf *cert;
1009e5b75505Sopenharmony_ci
1010e5b75505Sopenharmony_ci		cert = get_x509_cert(err_cert);
1011e5b75505Sopenharmony_ci		if (!cert) {
1012e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
1013e5b75505Sopenharmony_ci				   "wolfSSL: Could not fetch server certificate data");
1014e5b75505Sopenharmony_ci			preverify_ok = 0;
1015e5b75505Sopenharmony_ci		} else {
1016e5b75505Sopenharmony_ci			u8 hash[32];
1017e5b75505Sopenharmony_ci			const u8 *addr[1];
1018e5b75505Sopenharmony_ci			size_t len[1];
1019e5b75505Sopenharmony_ci
1020e5b75505Sopenharmony_ci			addr[0] = wpabuf_head(cert);
1021e5b75505Sopenharmony_ci			len[0] = wpabuf_len(cert);
1022e5b75505Sopenharmony_ci			if (sha256_vector(1, addr, len, hash) < 0 ||
1023e5b75505Sopenharmony_ci			    os_memcmp(conn->srv_cert_hash, hash, 32) != 0) {
1024e5b75505Sopenharmony_ci				err_str = "Server certificate mismatch";
1025e5b75505Sopenharmony_ci				err = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
1026e5b75505Sopenharmony_ci				preverify_ok = 0;
1027e5b75505Sopenharmony_ci			} else if (!preverify_ok) {
1028e5b75505Sopenharmony_ci				/*
1029e5b75505Sopenharmony_ci				 * Certificate matches pinned certificate, allow
1030e5b75505Sopenharmony_ci				 * regardless of other problems.
1031e5b75505Sopenharmony_ci				 */
1032e5b75505Sopenharmony_ci				wpa_printf(MSG_DEBUG,
1033e5b75505Sopenharmony_ci					   "wolfSSL: Ignore validation issues for a pinned server certificate");
1034e5b75505Sopenharmony_ci				preverify_ok = 1;
1035e5b75505Sopenharmony_ci			}
1036e5b75505Sopenharmony_ci			wpabuf_free(cert);
1037e5b75505Sopenharmony_ci		}
1038e5b75505Sopenharmony_ci	}
1039e5b75505Sopenharmony_ci#endif /* CONFIG_SHA256 */
1040e5b75505Sopenharmony_ci
1041e5b75505Sopenharmony_ci	if (!preverify_ok) {
1042e5b75505Sopenharmony_ci		wpa_printf(MSG_WARNING,
1043e5b75505Sopenharmony_ci			   "TLS: Certificate verification failed, error %d (%s) depth %d for '%s'",
1044e5b75505Sopenharmony_ci			   err, err_str, depth, buf);
1045e5b75505Sopenharmony_ci		wolfssl_tls_fail_event(conn, err_cert, err, depth, buf,
1046e5b75505Sopenharmony_ci				       err_str, TLS_FAIL_UNSPECIFIED);
1047e5b75505Sopenharmony_ci		return preverify_ok;
1048e5b75505Sopenharmony_ci	}
1049e5b75505Sopenharmony_ci
1050e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG,
1051e5b75505Sopenharmony_ci		   "TLS: %s - preverify_ok=%d err=%d (%s) ca_cert_verify=%d depth=%d buf='%s'",
1052e5b75505Sopenharmony_ci		   __func__, preverify_ok, err, err_str,
1053e5b75505Sopenharmony_ci		   conn->ca_cert_verify, depth, buf);
1054e5b75505Sopenharmony_ci	if (depth == 0 && match && os_strstr(buf, match) == NULL) {
1055e5b75505Sopenharmony_ci		wpa_printf(MSG_WARNING,
1056e5b75505Sopenharmony_ci			   "TLS: Subject '%s' did not match with '%s'",
1057e5b75505Sopenharmony_ci			   buf, match);
1058e5b75505Sopenharmony_ci		preverify_ok = 0;
1059e5b75505Sopenharmony_ci		wolfssl_tls_fail_event(conn, err_cert, err, depth, buf,
1060e5b75505Sopenharmony_ci				       "Subject mismatch",
1061e5b75505Sopenharmony_ci				       TLS_FAIL_SUBJECT_MISMATCH);
1062e5b75505Sopenharmony_ci	} else if (depth == 0 && altmatch &&
1063e5b75505Sopenharmony_ci		   !tls_match_alt_subject(err_cert, altmatch)) {
1064e5b75505Sopenharmony_ci		wpa_printf(MSG_WARNING,
1065e5b75505Sopenharmony_ci			   "TLS: altSubjectName match '%s' not found",
1066e5b75505Sopenharmony_ci			   altmatch);
1067e5b75505Sopenharmony_ci		preverify_ok = 0;
1068e5b75505Sopenharmony_ci		wolfssl_tls_fail_event(conn, err_cert, err, depth, buf,
1069e5b75505Sopenharmony_ci				       "AltSubject mismatch",
1070e5b75505Sopenharmony_ci				       TLS_FAIL_ALTSUBJECT_MISMATCH);
1071e5b75505Sopenharmony_ci	} else if (depth == 0 && suffix_match &&
1072e5b75505Sopenharmony_ci		   !tls_match_suffix(err_cert, suffix_match, 0)) {
1073e5b75505Sopenharmony_ci		wpa_printf(MSG_WARNING,
1074e5b75505Sopenharmony_ci			   "TLS: Domain suffix match '%s' not found",
1075e5b75505Sopenharmony_ci			   suffix_match);
1076e5b75505Sopenharmony_ci		preverify_ok = 0;
1077e5b75505Sopenharmony_ci		wolfssl_tls_fail_event(conn, err_cert, err, depth, buf,
1078e5b75505Sopenharmony_ci				       "Domain suffix mismatch",
1079e5b75505Sopenharmony_ci				       TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
1080e5b75505Sopenharmony_ci	} else if (depth == 0 && domain_match &&
1081e5b75505Sopenharmony_ci		   !tls_match_suffix(err_cert, domain_match, 1)) {
1082e5b75505Sopenharmony_ci		wpa_printf(MSG_WARNING, "TLS: Domain match '%s' not found",
1083e5b75505Sopenharmony_ci			   domain_match);
1084e5b75505Sopenharmony_ci		preverify_ok = 0;
1085e5b75505Sopenharmony_ci		wolfssl_tls_fail_event(conn, err_cert, err, depth, buf,
1086e5b75505Sopenharmony_ci				       "Domain mismatch",
1087e5b75505Sopenharmony_ci				       TLS_FAIL_DOMAIN_MISMATCH);
1088e5b75505Sopenharmony_ci	} else {
1089e5b75505Sopenharmony_ci		wolfssl_tls_cert_event(conn, err_cert, depth, buf);
1090e5b75505Sopenharmony_ci	}
1091e5b75505Sopenharmony_ci
1092e5b75505Sopenharmony_ci	if (conn->cert_probe && preverify_ok && depth == 0) {
1093e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
1094e5b75505Sopenharmony_ci			   "wolfSSL: Reject server certificate on probe-only run");
1095e5b75505Sopenharmony_ci		preverify_ok = 0;
1096e5b75505Sopenharmony_ci		wolfssl_tls_fail_event(conn, err_cert, err, depth, buf,
1097e5b75505Sopenharmony_ci				       "Server certificate chain probe",
1098e5b75505Sopenharmony_ci				       TLS_FAIL_SERVER_CHAIN_PROBE);
1099e5b75505Sopenharmony_ci	}
1100e5b75505Sopenharmony_ci
1101e5b75505Sopenharmony_ci#ifdef HAVE_OCSP_WOLFSSL
1102e5b75505Sopenharmony_ci	if (depth == 0 && (conn->flags & TLS_CONN_REQUEST_OCSP) &&
1103e5b75505Sopenharmony_ci	    preverify_ok) {
1104e5b75505Sopenharmony_ci		enum ocsp_result res;
1105e5b75505Sopenharmony_ci
1106e5b75505Sopenharmony_ci		res = check_ocsp_resp(conn->ssl_ctx, conn->ssl, err_cert,
1107e5b75505Sopenharmony_ci				      conn->peer_issuer,
1108e5b75505Sopenharmony_ci				      conn->peer_issuer_issuer);
1109e5b75505Sopenharmony_ci		if (res == OCSP_REVOKED) {
1110e5b75505Sopenharmony_ci			preverify_ok = 0;
1111e5b75505Sopenharmony_ci			wolfssl_tls_fail_event(conn, err_cert, err, depth, buf,
1112e5b75505Sopenharmony_ci					       "certificate revoked",
1113e5b75505Sopenharmony_ci					       TLS_FAIL_REVOKED);
1114e5b75505Sopenharmony_ci			if (err == X509_V_OK)
1115e5b75505Sopenharmony_ci				X509_STORE_CTX_set_error(
1116e5b75505Sopenharmony_ci					x509_ctx, X509_V_ERR_CERT_REVOKED);
1117e5b75505Sopenharmony_ci		} else if (res != OCSP_GOOD &&
1118e5b75505Sopenharmony_ci			   (conn->flags & TLS_CONN_REQUIRE_OCSP)) {
1119e5b75505Sopenharmony_ci			preverify_ok = 0;
1120e5b75505Sopenharmony_ci			wolfssl_tls_fail_event(conn, err_cert, err, depth, buf,
1121e5b75505Sopenharmony_ci					       "bad certificate status response",
1122e5b75505Sopenharmony_ci					       TLS_FAIL_UNSPECIFIED);
1123e5b75505Sopenharmony_ci		}
1124e5b75505Sopenharmony_ci	}
1125e5b75505Sopenharmony_ci#endif /* HAVE_OCSP_WOLFSSL */
1126e5b75505Sopenharmony_ci	if (depth == 0 && preverify_ok && context->event_cb != NULL)
1127e5b75505Sopenharmony_ci		context->event_cb(context->cb_ctx,
1128e5b75505Sopenharmony_ci				  TLS_CERT_CHAIN_SUCCESS, NULL);
1129e5b75505Sopenharmony_ci
1130e5b75505Sopenharmony_ci	return preverify_ok;
1131e5b75505Sopenharmony_ci}
1132e5b75505Sopenharmony_ci
1133e5b75505Sopenharmony_ci
1134e5b75505Sopenharmony_cistatic int tls_connection_ca_cert(void *tls_ctx, struct tls_connection *conn,
1135e5b75505Sopenharmony_ci				  const char *ca_cert,
1136e5b75505Sopenharmony_ci				  const u8 *ca_cert_blob, size_t blob_len,
1137e5b75505Sopenharmony_ci				  const char *ca_path)
1138e5b75505Sopenharmony_ci{
1139e5b75505Sopenharmony_ci	WOLFSSL_CTX *ctx = tls_ctx;
1140e5b75505Sopenharmony_ci
1141e5b75505Sopenharmony_ci	wolfSSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
1142e5b75505Sopenharmony_ci	conn->ca_cert_verify = 1;
1143e5b75505Sopenharmony_ci
1144e5b75505Sopenharmony_ci	if (ca_cert && os_strncmp(ca_cert, "probe://", 8) == 0) {
1145e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
1146e5b75505Sopenharmony_ci			   "wolfSSL: Probe for server certificate chain");
1147e5b75505Sopenharmony_ci		conn->cert_probe = 1;
1148e5b75505Sopenharmony_ci		conn->ca_cert_verify = 0;
1149e5b75505Sopenharmony_ci		return 0;
1150e5b75505Sopenharmony_ci	}
1151e5b75505Sopenharmony_ci
1152e5b75505Sopenharmony_ci	if (ca_cert && os_strncmp(ca_cert, "hash://", 7) == 0) {
1153e5b75505Sopenharmony_ci#ifdef CONFIG_SHA256
1154e5b75505Sopenharmony_ci		const char *pos = ca_cert + 7;
1155e5b75505Sopenharmony_ci
1156e5b75505Sopenharmony_ci		if (os_strncmp(pos, "server/sha256/", 14) != 0) {
1157e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
1158e5b75505Sopenharmony_ci				   "wolfSSL: Unsupported ca_cert hash value '%s'",
1159e5b75505Sopenharmony_ci				   ca_cert);
1160e5b75505Sopenharmony_ci			return -1;
1161e5b75505Sopenharmony_ci		}
1162e5b75505Sopenharmony_ci		pos += 14;
1163e5b75505Sopenharmony_ci		if (os_strlen(pos) != 32 * 2) {
1164e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
1165e5b75505Sopenharmony_ci				   "wolfSSL: Unexpected SHA256 hash length in ca_cert '%s'",
1166e5b75505Sopenharmony_ci				   ca_cert);
1167e5b75505Sopenharmony_ci			return -1;
1168e5b75505Sopenharmony_ci		}
1169e5b75505Sopenharmony_ci		if (hexstr2bin(pos, conn->srv_cert_hash, 32) < 0) {
1170e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
1171e5b75505Sopenharmony_ci				   "wolfSSL: Invalid SHA256 hash value in ca_cert '%s'",
1172e5b75505Sopenharmony_ci				   ca_cert);
1173e5b75505Sopenharmony_ci			return -1;
1174e5b75505Sopenharmony_ci		}
1175e5b75505Sopenharmony_ci		conn->server_cert_only = 1;
1176e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
1177e5b75505Sopenharmony_ci			   "wolfSSL: Checking only server certificate match");
1178e5b75505Sopenharmony_ci		return 0;
1179e5b75505Sopenharmony_ci#else /* CONFIG_SHA256 */
1180e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO,
1181e5b75505Sopenharmony_ci			   "No SHA256 included in the build - cannot validate server certificate hash");
1182e5b75505Sopenharmony_ci		return -1;
1183e5b75505Sopenharmony_ci#endif /* CONFIG_SHA256 */
1184e5b75505Sopenharmony_ci	}
1185e5b75505Sopenharmony_ci
1186e5b75505Sopenharmony_ci	if (ca_cert_blob) {
1187e5b75505Sopenharmony_ci		if (wolfSSL_CTX_load_verify_buffer(ctx, ca_cert_blob, blob_len,
1188e5b75505Sopenharmony_ci						   SSL_FILETYPE_ASN1) !=
1189e5b75505Sopenharmony_ci		    SSL_SUCCESS) {
1190e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO, "SSL: failed to load CA blob");
1191e5b75505Sopenharmony_ci			return -1;
1192e5b75505Sopenharmony_ci		}
1193e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "SSL: use CA cert blob OK");
1194e5b75505Sopenharmony_ci		return 0;
1195e5b75505Sopenharmony_ci	}
1196e5b75505Sopenharmony_ci
1197e5b75505Sopenharmony_ci	if (ca_cert || ca_path) {
1198e5b75505Sopenharmony_ci		WOLFSSL_X509_STORE *cm = wolfSSL_X509_STORE_new();
1199e5b75505Sopenharmony_ci
1200e5b75505Sopenharmony_ci		if (!cm) {
1201e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
1202e5b75505Sopenharmony_ci				   "SSL: failed to create certificate store");
1203e5b75505Sopenharmony_ci			return -1;
1204e5b75505Sopenharmony_ci		}
1205e5b75505Sopenharmony_ci		wolfSSL_CTX_set_cert_store(ctx, cm);
1206e5b75505Sopenharmony_ci
1207e5b75505Sopenharmony_ci		if (wolfSSL_CTX_load_verify_locations(ctx, ca_cert, ca_path) !=
1208e5b75505Sopenharmony_ci		    SSL_SUCCESS) {
1209e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
1210e5b75505Sopenharmony_ci				   "SSL: failed to load ca_cert as PEM");
1211e5b75505Sopenharmony_ci
1212e5b75505Sopenharmony_ci			if (!ca_cert)
1213e5b75505Sopenharmony_ci				return -1;
1214e5b75505Sopenharmony_ci
1215e5b75505Sopenharmony_ci			if (wolfSSL_CTX_der_load_verify_locations(
1216e5b75505Sopenharmony_ci				    ctx, ca_cert, SSL_FILETYPE_ASN1) !=
1217e5b75505Sopenharmony_ci			    SSL_SUCCESS) {
1218e5b75505Sopenharmony_ci				wpa_printf(MSG_INFO,
1219e5b75505Sopenharmony_ci					   "SSL: failed to load ca_cert as DER");
1220e5b75505Sopenharmony_ci				return -1;
1221e5b75505Sopenharmony_ci			}
1222e5b75505Sopenharmony_ci		}
1223e5b75505Sopenharmony_ci		return 0;
1224e5b75505Sopenharmony_ci	}
1225e5b75505Sopenharmony_ci
1226e5b75505Sopenharmony_ci	conn->ca_cert_verify = 0;
1227e5b75505Sopenharmony_ci	return 0;
1228e5b75505Sopenharmony_ci}
1229e5b75505Sopenharmony_ci
1230e5b75505Sopenharmony_ci
1231e5b75505Sopenharmony_cistatic void tls_set_conn_flags(WOLFSSL *ssl, unsigned int flags)
1232e5b75505Sopenharmony_ci{
1233e5b75505Sopenharmony_ci#ifdef HAVE_SESSION_TICKET
1234e5b75505Sopenharmony_ci#if 0
1235e5b75505Sopenharmony_ci	if (!(flags & TLS_CONN_DISABLE_SESSION_TICKET))
1236e5b75505Sopenharmony_ci		wolfSSL_UseSessionTicket(ssl);
1237e5b75505Sopenharmony_ci#endif
1238e5b75505Sopenharmony_ci#endif /* HAVE_SESSION_TICKET */
1239e5b75505Sopenharmony_ci
1240e5b75505Sopenharmony_ci	if (flags & TLS_CONN_DISABLE_TLSv1_0)
1241e5b75505Sopenharmony_ci		wolfSSL_set_options(ssl, SSL_OP_NO_TLSv1);
1242e5b75505Sopenharmony_ci	if (flags & TLS_CONN_DISABLE_TLSv1_1)
1243e5b75505Sopenharmony_ci		wolfSSL_set_options(ssl, SSL_OP_NO_TLSv1_1);
1244e5b75505Sopenharmony_ci	if (flags & TLS_CONN_DISABLE_TLSv1_2)
1245e5b75505Sopenharmony_ci		wolfSSL_set_options(ssl, SSL_OP_NO_TLSv1_2);
1246e5b75505Sopenharmony_ci}
1247e5b75505Sopenharmony_ci
1248e5b75505Sopenharmony_ci
1249e5b75505Sopenharmony_ciint tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
1250e5b75505Sopenharmony_ci			      const struct tls_connection_params *params)
1251e5b75505Sopenharmony_ci{
1252e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "SSL: set params");
1253e5b75505Sopenharmony_ci
1254e5b75505Sopenharmony_ci	if (tls_connection_set_subject_match(conn, params->subject_match,
1255e5b75505Sopenharmony_ci					     params->altsubject_match,
1256e5b75505Sopenharmony_ci					     params->suffix_match,
1257e5b75505Sopenharmony_ci					     params->domain_match) < 0) {
1258e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "Error setting subject match");
1259e5b75505Sopenharmony_ci		return -1;
1260e5b75505Sopenharmony_ci	}
1261e5b75505Sopenharmony_ci
1262e5b75505Sopenharmony_ci	if (tls_connection_ca_cert(tls_ctx, conn, params->ca_cert,
1263e5b75505Sopenharmony_ci				   params->ca_cert_blob,
1264e5b75505Sopenharmony_ci				   params->ca_cert_blob_len,
1265e5b75505Sopenharmony_ci				   params->ca_path) < 0) {
1266e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "Error setting CA cert");
1267e5b75505Sopenharmony_ci		return -1;
1268e5b75505Sopenharmony_ci	}
1269e5b75505Sopenharmony_ci
1270e5b75505Sopenharmony_ci	if (tls_connection_client_cert(conn, params->client_cert,
1271e5b75505Sopenharmony_ci				       params->client_cert_blob,
1272e5b75505Sopenharmony_ci				       params->client_cert_blob_len) < 0) {
1273e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "Error setting client cert");
1274e5b75505Sopenharmony_ci		return -1;
1275e5b75505Sopenharmony_ci	}
1276e5b75505Sopenharmony_ci
1277e5b75505Sopenharmony_ci	if (tls_connection_private_key(tls_ctx, conn, params->private_key,
1278e5b75505Sopenharmony_ci				       params->private_key_passwd,
1279e5b75505Sopenharmony_ci				       params->private_key_blob,
1280e5b75505Sopenharmony_ci				       params->private_key_blob_len) < 0) {
1281e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "Error setting private key");
1282e5b75505Sopenharmony_ci		return -1;
1283e5b75505Sopenharmony_ci	}
1284e5b75505Sopenharmony_ci
1285e5b75505Sopenharmony_ci	if (tls_connection_dh(conn, params->dh_file, params->dh_blob,
1286e5b75505Sopenharmony_ci			      params->dh_blob_len) < 0) {
1287e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "Error setting DH");
1288e5b75505Sopenharmony_ci		return -1;
1289e5b75505Sopenharmony_ci	}
1290e5b75505Sopenharmony_ci
1291e5b75505Sopenharmony_ci	if (params->openssl_ciphers &&
1292e5b75505Sopenharmony_ci	    wolfSSL_set_cipher_list(conn->ssl, params->openssl_ciphers) != 1) {
1293e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO,
1294e5b75505Sopenharmony_ci			   "wolfSSL: Failed to set cipher string '%s'",
1295e5b75505Sopenharmony_ci			   params->openssl_ciphers);
1296e5b75505Sopenharmony_ci		return -1;
1297e5b75505Sopenharmony_ci	}
1298e5b75505Sopenharmony_ci
1299e5b75505Sopenharmony_ci	tls_set_conn_flags(conn->ssl, params->flags);
1300e5b75505Sopenharmony_ci
1301e5b75505Sopenharmony_ci#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
1302e5b75505Sopenharmony_ci	if (params->flags & TLS_CONN_REQUEST_OCSP) {
1303e5b75505Sopenharmony_ci		if (wolfSSL_UseOCSPStapling(conn->ssl, WOLFSSL_CSR_OCSP,
1304e5b75505Sopenharmony_ci					    WOLFSSL_CSR_OCSP_USE_NONCE) !=
1305e5b75505Sopenharmony_ci		    SSL_SUCCESS)
1306e5b75505Sopenharmony_ci			return -1;
1307e5b75505Sopenharmony_ci		wolfSSL_CTX_EnableOCSP(tls_ctx, 0);
1308e5b75505Sopenharmony_ci	}
1309e5b75505Sopenharmony_ci#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
1310e5b75505Sopenharmony_ci#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
1311e5b75505Sopenharmony_ci	if (params->flags & TLS_CONN_REQUEST_OCSP) {
1312e5b75505Sopenharmony_ci		if (wolfSSL_UseOCSPStaplingV2(conn->ssl,
1313e5b75505Sopenharmony_ci					      WOLFSSL_CSR2_OCSP_MULTI, 0) !=
1314e5b75505Sopenharmony_ci		    SSL_SUCCESS)
1315e5b75505Sopenharmony_ci			return -1;
1316e5b75505Sopenharmony_ci		wolfSSL_CTX_EnableOCSP(tls_ctx, 0);
1317e5b75505Sopenharmony_ci	}
1318e5b75505Sopenharmony_ci#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
1319e5b75505Sopenharmony_ci#if !defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \
1320e5b75505Sopenharmony_ci    !defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
1321e5b75505Sopenharmony_ci#ifdef HAVE_OCSP
1322e5b75505Sopenharmony_ci	if (params->flags & TLS_CONN_REQUEST_OCSP)
1323e5b75505Sopenharmony_ci		wolfSSL_CTX_EnableOCSP(ctx, 0);
1324e5b75505Sopenharmony_ci#else /* HAVE_OCSP */
1325e5b75505Sopenharmony_ci	if (params->flags & TLS_CONN_REQUIRE_OCSP) {
1326e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO,
1327e5b75505Sopenharmony_ci			   "wolfSSL: No OCSP support included - reject configuration");
1328e5b75505Sopenharmony_ci		return -1;
1329e5b75505Sopenharmony_ci	}
1330e5b75505Sopenharmony_ci	if (params->flags & TLS_CONN_REQUEST_OCSP) {
1331e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
1332e5b75505Sopenharmony_ci			   "wolfSSL: No OCSP support included - allow optional OCSP case to continue");
1333e5b75505Sopenharmony_ci	}
1334e5b75505Sopenharmony_ci#endif /* HAVE_OCSP */
1335e5b75505Sopenharmony_ci#endif /* !HAVE_CERTIFICATE_STATUS_REQUEST &&
1336e5b75505Sopenharmony_ci	* !HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
1337e5b75505Sopenharmony_ci
1338e5b75505Sopenharmony_ci	conn->flags = params->flags;
1339e5b75505Sopenharmony_ci
1340e5b75505Sopenharmony_ci	return 0;
1341e5b75505Sopenharmony_ci}
1342e5b75505Sopenharmony_ci
1343e5b75505Sopenharmony_ci
1344e5b75505Sopenharmony_cistatic int tls_global_ca_cert(void *ssl_ctx, const char *ca_cert)
1345e5b75505Sopenharmony_ci{
1346e5b75505Sopenharmony_ci	WOLFSSL_CTX *ctx = ssl_ctx;
1347e5b75505Sopenharmony_ci
1348e5b75505Sopenharmony_ci	if (ca_cert) {
1349e5b75505Sopenharmony_ci		if (wolfSSL_CTX_load_verify_locations(ctx, ca_cert, NULL) != 1)
1350e5b75505Sopenharmony_ci		{
1351e5b75505Sopenharmony_ci			wpa_printf(MSG_WARNING,
1352e5b75505Sopenharmony_ci				   "Failed to load root certificates");
1353e5b75505Sopenharmony_ci			return -1;
1354e5b75505Sopenharmony_ci		}
1355e5b75505Sopenharmony_ci
1356e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
1357e5b75505Sopenharmony_ci			   "TLS: Trusted root certificate(s) loaded");
1358e5b75505Sopenharmony_ci	}
1359e5b75505Sopenharmony_ci
1360e5b75505Sopenharmony_ci	return 0;
1361e5b75505Sopenharmony_ci}
1362e5b75505Sopenharmony_ci
1363e5b75505Sopenharmony_ci
1364e5b75505Sopenharmony_cistatic int tls_global_client_cert(void *ssl_ctx, const char *client_cert)
1365e5b75505Sopenharmony_ci{
1366e5b75505Sopenharmony_ci	WOLFSSL_CTX *ctx = ssl_ctx;
1367e5b75505Sopenharmony_ci
1368e5b75505Sopenharmony_ci	if (!client_cert)
1369e5b75505Sopenharmony_ci		return 0;
1370e5b75505Sopenharmony_ci
1371e5b75505Sopenharmony_ci	if (wolfSSL_CTX_use_certificate_chain_file_format(ctx, client_cert,
1372e5b75505Sopenharmony_ci							  SSL_FILETYPE_ASN1) !=
1373e5b75505Sopenharmony_ci	    SSL_SUCCESS &&
1374e5b75505Sopenharmony_ci	    wolfSSL_CTX_use_certificate_chain_file(ctx, client_cert) !=
1375e5b75505Sopenharmony_ci	    SSL_SUCCESS) {
1376e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "Failed to load client certificate");
1377e5b75505Sopenharmony_ci		return -1;
1378e5b75505Sopenharmony_ci	}
1379e5b75505Sopenharmony_ci
1380e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "SSL: Loaded global client certificate: %s",
1381e5b75505Sopenharmony_ci		   client_cert);
1382e5b75505Sopenharmony_ci
1383e5b75505Sopenharmony_ci	return 0;
1384e5b75505Sopenharmony_ci}
1385e5b75505Sopenharmony_ci
1386e5b75505Sopenharmony_ci
1387e5b75505Sopenharmony_cistatic int tls_global_private_key(void *ssl_ctx, const char *private_key,
1388e5b75505Sopenharmony_ci				  const char *private_key_passwd)
1389e5b75505Sopenharmony_ci{
1390e5b75505Sopenharmony_ci	WOLFSSL_CTX *ctx = ssl_ctx;
1391e5b75505Sopenharmony_ci	char *passwd = NULL;
1392e5b75505Sopenharmony_ci	int ret = 0;
1393e5b75505Sopenharmony_ci
1394e5b75505Sopenharmony_ci	if (!private_key)
1395e5b75505Sopenharmony_ci		return 0;
1396e5b75505Sopenharmony_ci
1397e5b75505Sopenharmony_ci	if (private_key_passwd) {
1398e5b75505Sopenharmony_ci		passwd = os_strdup(private_key_passwd);
1399e5b75505Sopenharmony_ci		if (!passwd)
1400e5b75505Sopenharmony_ci			return -1;
1401e5b75505Sopenharmony_ci	}
1402e5b75505Sopenharmony_ci
1403e5b75505Sopenharmony_ci	wolfSSL_CTX_set_default_passwd_cb(ctx, tls_passwd_cb);
1404e5b75505Sopenharmony_ci	wolfSSL_CTX_set_default_passwd_cb_userdata(ctx, passwd);
1405e5b75505Sopenharmony_ci
1406e5b75505Sopenharmony_ci	if (wolfSSL_CTX_use_PrivateKey_file(ctx, private_key,
1407e5b75505Sopenharmony_ci					    SSL_FILETYPE_ASN1) != 1 &&
1408e5b75505Sopenharmony_ci	    wolfSSL_CTX_use_PrivateKey_file(ctx, private_key,
1409e5b75505Sopenharmony_ci					    SSL_FILETYPE_PEM) != 1) {
1410e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "Failed to load private key");
1411e5b75505Sopenharmony_ci		ret = -1;
1412e5b75505Sopenharmony_ci	}
1413e5b75505Sopenharmony_ci
1414e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "SSL: Loaded global private key");
1415e5b75505Sopenharmony_ci
1416e5b75505Sopenharmony_ci	os_free(passwd);
1417e5b75505Sopenharmony_ci	wolfSSL_CTX_set_default_passwd_cb(ctx, NULL);
1418e5b75505Sopenharmony_ci
1419e5b75505Sopenharmony_ci	return ret;
1420e5b75505Sopenharmony_ci}
1421e5b75505Sopenharmony_ci
1422e5b75505Sopenharmony_ci
1423e5b75505Sopenharmony_cistatic int tls_global_dh(void *ssl_ctx, const char *dh_file,
1424e5b75505Sopenharmony_ci			 const u8 *dh_blob, size_t blob_len)
1425e5b75505Sopenharmony_ci{
1426e5b75505Sopenharmony_ci	WOLFSSL_CTX *ctx = ssl_ctx;
1427e5b75505Sopenharmony_ci
1428e5b75505Sopenharmony_ci	if (!dh_file && !dh_blob)
1429e5b75505Sopenharmony_ci		return 0;
1430e5b75505Sopenharmony_ci
1431e5b75505Sopenharmony_ci	if (dh_blob) {
1432e5b75505Sopenharmony_ci		if (wolfSSL_CTX_SetTmpDH_buffer(ctx, dh_blob, blob_len,
1433e5b75505Sopenharmony_ci						SSL_FILETYPE_ASN1) < 0) {
1434e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
1435e5b75505Sopenharmony_ci				   "SSL: global use DH DER blob failed");
1436e5b75505Sopenharmony_ci			return -1;
1437e5b75505Sopenharmony_ci		}
1438e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "SSL: global use DH blob OK");
1439e5b75505Sopenharmony_ci		return 0;
1440e5b75505Sopenharmony_ci	}
1441e5b75505Sopenharmony_ci
1442e5b75505Sopenharmony_ci	if (dh_file) {
1443e5b75505Sopenharmony_ci		if (wolfSSL_CTX_SetTmpDH_file(ctx, dh_file, SSL_FILETYPE_PEM) <
1444e5b75505Sopenharmony_ci		    0) {
1445e5b75505Sopenharmony_ci			wpa_printf(MSG_INFO,
1446e5b75505Sopenharmony_ci				   "SSL: global use DH PEM file failed");
1447e5b75505Sopenharmony_ci			if (wolfSSL_CTX_SetTmpDH_file(ctx, dh_file,
1448e5b75505Sopenharmony_ci						      SSL_FILETYPE_ASN1) < 0) {
1449e5b75505Sopenharmony_ci				wpa_printf(MSG_INFO,
1450e5b75505Sopenharmony_ci					   "SSL: global use DH DER file failed");
1451e5b75505Sopenharmony_ci				return -1;
1452e5b75505Sopenharmony_ci			}
1453e5b75505Sopenharmony_ci		}
1454e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "SSL: global use DH file OK");
1455e5b75505Sopenharmony_ci		return 0;
1456e5b75505Sopenharmony_ci	}
1457e5b75505Sopenharmony_ci
1458e5b75505Sopenharmony_ci	return 0;
1459e5b75505Sopenharmony_ci}
1460e5b75505Sopenharmony_ci
1461e5b75505Sopenharmony_ci
1462e5b75505Sopenharmony_ci#ifdef HAVE_OCSP
1463e5b75505Sopenharmony_ci
1464e5b75505Sopenharmony_ciint ocsp_status_cb(void *unused, const char *url, int url_sz,
1465e5b75505Sopenharmony_ci		   unsigned char *request, int request_sz,
1466e5b75505Sopenharmony_ci		   unsigned char **response)
1467e5b75505Sopenharmony_ci{
1468e5b75505Sopenharmony_ci	size_t len;
1469e5b75505Sopenharmony_ci
1470e5b75505Sopenharmony_ci	(void) unused;
1471e5b75505Sopenharmony_ci
1472e5b75505Sopenharmony_ci	if (!url) {
1473e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
1474e5b75505Sopenharmony_ci			   "wolfSSL: OCSP status callback - no response configured");
1475e5b75505Sopenharmony_ci		*response = NULL;
1476e5b75505Sopenharmony_ci		return 0;
1477e5b75505Sopenharmony_ci	}
1478e5b75505Sopenharmony_ci
1479e5b75505Sopenharmony_ci	*response = (unsigned char *) os_readfile(url, &len);
1480e5b75505Sopenharmony_ci	if (!*response) {
1481e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
1482e5b75505Sopenharmony_ci			   "wolfSSL: OCSP status callback - could not read response file");
1483e5b75505Sopenharmony_ci		return -1;
1484e5b75505Sopenharmony_ci	}
1485e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG,
1486e5b75505Sopenharmony_ci		   "wolfSSL: OCSP status callback - send cached response");
1487e5b75505Sopenharmony_ci	return len;
1488e5b75505Sopenharmony_ci}
1489e5b75505Sopenharmony_ci
1490e5b75505Sopenharmony_ci
1491e5b75505Sopenharmony_civoid ocsp_resp_free_cb(void *ocsp_stapling_response, unsigned char *response)
1492e5b75505Sopenharmony_ci{
1493e5b75505Sopenharmony_ci	os_free(response);
1494e5b75505Sopenharmony_ci}
1495e5b75505Sopenharmony_ci
1496e5b75505Sopenharmony_ci#endif /* HAVE_OCSP */
1497e5b75505Sopenharmony_ci
1498e5b75505Sopenharmony_ci
1499e5b75505Sopenharmony_ciint tls_global_set_params(void *tls_ctx,
1500e5b75505Sopenharmony_ci			  const struct tls_connection_params *params)
1501e5b75505Sopenharmony_ci{
1502e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "SSL: global set params");
1503e5b75505Sopenharmony_ci
1504e5b75505Sopenharmony_ci	if (params->check_cert_subject)
1505e5b75505Sopenharmony_ci		return -1; /* not yet supported */
1506e5b75505Sopenharmony_ci
1507e5b75505Sopenharmony_ci	if (tls_global_ca_cert(tls_ctx, params->ca_cert) < 0) {
1508e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "SSL: Failed to load ca cert file '%s'",
1509e5b75505Sopenharmony_ci			   params->ca_cert);
1510e5b75505Sopenharmony_ci		return -1;
1511e5b75505Sopenharmony_ci	}
1512e5b75505Sopenharmony_ci
1513e5b75505Sopenharmony_ci	if (tls_global_client_cert(tls_ctx, params->client_cert) < 0) {
1514e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO,
1515e5b75505Sopenharmony_ci			   "SSL: Failed to load client cert file '%s'",
1516e5b75505Sopenharmony_ci			   params->client_cert);
1517e5b75505Sopenharmony_ci		return -1;
1518e5b75505Sopenharmony_ci	}
1519e5b75505Sopenharmony_ci
1520e5b75505Sopenharmony_ci	if (tls_global_private_key(tls_ctx, params->private_key,
1521e5b75505Sopenharmony_ci				   params->private_key_passwd) < 0) {
1522e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO,
1523e5b75505Sopenharmony_ci			   "SSL: Failed to load private key file '%s'",
1524e5b75505Sopenharmony_ci			   params->private_key);
1525e5b75505Sopenharmony_ci		return -1;
1526e5b75505Sopenharmony_ci	}
1527e5b75505Sopenharmony_ci
1528e5b75505Sopenharmony_ci	if (tls_global_dh(tls_ctx, params->dh_file, params->dh_blob,
1529e5b75505Sopenharmony_ci			  params->dh_blob_len) < 0) {
1530e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "SSL: Failed to load DH file '%s'",
1531e5b75505Sopenharmony_ci			   params->dh_file);
1532e5b75505Sopenharmony_ci		return -1;
1533e5b75505Sopenharmony_ci	}
1534e5b75505Sopenharmony_ci
1535e5b75505Sopenharmony_ci	if (params->openssl_ciphers &&
1536e5b75505Sopenharmony_ci	    wolfSSL_CTX_set_cipher_list(tls_ctx,
1537e5b75505Sopenharmony_ci					params->openssl_ciphers) != 1) {
1538e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO,
1539e5b75505Sopenharmony_ci			   "wolfSSL: Failed to set cipher string '%s'",
1540e5b75505Sopenharmony_ci			   params->openssl_ciphers);
1541e5b75505Sopenharmony_ci		return -1;
1542e5b75505Sopenharmony_ci	}
1543e5b75505Sopenharmony_ci
1544e5b75505Sopenharmony_ci	if (params->openssl_ecdh_curves) {
1545e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO,
1546e5b75505Sopenharmony_ci			   "wolfSSL: openssl_ecdh_curves not supported");
1547e5b75505Sopenharmony_ci		return -1;
1548e5b75505Sopenharmony_ci	}
1549e5b75505Sopenharmony_ci
1550e5b75505Sopenharmony_ci#ifdef HAVE_SESSION_TICKET
1551e5b75505Sopenharmony_ci	/* Session ticket is off by default - can't disable once on. */
1552e5b75505Sopenharmony_ci	if (!(params->flags & TLS_CONN_DISABLE_SESSION_TICKET))
1553e5b75505Sopenharmony_ci		wolfSSL_CTX_UseSessionTicket(tls_ctx);
1554e5b75505Sopenharmony_ci#endif /* HAVE_SESSION_TICKET */
1555e5b75505Sopenharmony_ci
1556e5b75505Sopenharmony_ci#ifdef HAVE_OCSP
1557e5b75505Sopenharmony_ci	if (params->ocsp_stapling_response) {
1558e5b75505Sopenharmony_ci		wolfSSL_CTX_SetOCSP_OverrideURL(tls_ctx,
1559e5b75505Sopenharmony_ci						params->ocsp_stapling_response);
1560e5b75505Sopenharmony_ci		wolfSSL_CTX_SetOCSP_Cb(tls_ctx, ocsp_status_cb,
1561e5b75505Sopenharmony_ci				       ocsp_resp_free_cb, NULL);
1562e5b75505Sopenharmony_ci	}
1563e5b75505Sopenharmony_ci#endif /* HAVE_OCSP */
1564e5b75505Sopenharmony_ci
1565e5b75505Sopenharmony_ci	return 0;
1566e5b75505Sopenharmony_ci}
1567e5b75505Sopenharmony_ci
1568e5b75505Sopenharmony_ci
1569e5b75505Sopenharmony_ciint tls_global_set_verify(void *tls_ctx, int check_crl, int strict)
1570e5b75505Sopenharmony_ci{
1571e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "SSL: global set verify: %d", check_crl);
1572e5b75505Sopenharmony_ci
1573e5b75505Sopenharmony_ci	if (check_crl) {
1574e5b75505Sopenharmony_ci		/* Hack to Enable CRLs. */
1575e5b75505Sopenharmony_ci		wolfSSL_CTX_LoadCRLBuffer(tls_ctx, NULL, 0, SSL_FILETYPE_PEM);
1576e5b75505Sopenharmony_ci	}
1577e5b75505Sopenharmony_ci
1578e5b75505Sopenharmony_ci	return 0;
1579e5b75505Sopenharmony_ci}
1580e5b75505Sopenharmony_ci
1581e5b75505Sopenharmony_ci
1582e5b75505Sopenharmony_ciint tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
1583e5b75505Sopenharmony_ci			      int verify_peer, unsigned int flags,
1584e5b75505Sopenharmony_ci			      const u8 *session_ctx, size_t session_ctx_len)
1585e5b75505Sopenharmony_ci{
1586e5b75505Sopenharmony_ci	if (!conn)
1587e5b75505Sopenharmony_ci		return -1;
1588e5b75505Sopenharmony_ci
1589e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "SSL: set verify: %d", verify_peer);
1590e5b75505Sopenharmony_ci
1591e5b75505Sopenharmony_ci	if (verify_peer) {
1592e5b75505Sopenharmony_ci		conn->ca_cert_verify = 1;
1593e5b75505Sopenharmony_ci		wolfSSL_set_verify(conn->ssl, SSL_VERIFY_PEER |
1594e5b75505Sopenharmony_ci				   SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1595e5b75505Sopenharmony_ci				   tls_verify_cb);
1596e5b75505Sopenharmony_ci	} else {
1597e5b75505Sopenharmony_ci		conn->ca_cert_verify = 0;
1598e5b75505Sopenharmony_ci		wolfSSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
1599e5b75505Sopenharmony_ci	}
1600e5b75505Sopenharmony_ci
1601e5b75505Sopenharmony_ci	wolfSSL_set_accept_state(conn->ssl);
1602e5b75505Sopenharmony_ci
1603e5b75505Sopenharmony_ci	/* TODO: do we need to fake a session like OpenSSL does here? */
1604e5b75505Sopenharmony_ci
1605e5b75505Sopenharmony_ci	return 0;
1606e5b75505Sopenharmony_ci}
1607e5b75505Sopenharmony_ci
1608e5b75505Sopenharmony_ci
1609e5b75505Sopenharmony_cistatic struct wpabuf * wolfssl_handshake(struct tls_connection *conn,
1610e5b75505Sopenharmony_ci					 const struct wpabuf *in_data,
1611e5b75505Sopenharmony_ci					 int server)
1612e5b75505Sopenharmony_ci{
1613e5b75505Sopenharmony_ci	int res;
1614e5b75505Sopenharmony_ci
1615e5b75505Sopenharmony_ci	wolfssl_reset_out_data(&conn->output);
1616e5b75505Sopenharmony_ci
1617e5b75505Sopenharmony_ci	/* Initiate TLS handshake or continue the existing handshake */
1618e5b75505Sopenharmony_ci	if (server) {
1619e5b75505Sopenharmony_ci		wolfSSL_set_accept_state(conn->ssl);
1620e5b75505Sopenharmony_ci		res = wolfSSL_accept(conn->ssl);
1621e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "SSL: wolfSSL_accept: %d", res);
1622e5b75505Sopenharmony_ci	} else {
1623e5b75505Sopenharmony_ci		wolfSSL_set_connect_state(conn->ssl);
1624e5b75505Sopenharmony_ci		res = wolfSSL_connect(conn->ssl);
1625e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "SSL: wolfSSL_connect: %d", res);
1626e5b75505Sopenharmony_ci	}
1627e5b75505Sopenharmony_ci
1628e5b75505Sopenharmony_ci	if (res != 1) {
1629e5b75505Sopenharmony_ci		int err = wolfSSL_get_error(conn->ssl, res);
1630e5b75505Sopenharmony_ci
1631e5b75505Sopenharmony_ci		if (err == SSL_ERROR_WANT_READ) {
1632e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
1633e5b75505Sopenharmony_ci				   "SSL: wolfSSL_connect - want more data");
1634e5b75505Sopenharmony_ci		} else if (err == SSL_ERROR_WANT_WRITE) {
1635e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
1636e5b75505Sopenharmony_ci				   "SSL: wolfSSL_connect - want to write");
1637e5b75505Sopenharmony_ci		} else {
1638e5b75505Sopenharmony_ci			char msg[80];
1639e5b75505Sopenharmony_ci
1640e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
1641e5b75505Sopenharmony_ci				   "SSL: wolfSSL_connect - failed %s",
1642e5b75505Sopenharmony_ci				   wolfSSL_ERR_error_string(err, msg));
1643e5b75505Sopenharmony_ci			conn->failed++;
1644e5b75505Sopenharmony_ci		}
1645e5b75505Sopenharmony_ci	}
1646e5b75505Sopenharmony_ci
1647e5b75505Sopenharmony_ci	return conn->output.out_data;
1648e5b75505Sopenharmony_ci}
1649e5b75505Sopenharmony_ci
1650e5b75505Sopenharmony_ci
1651e5b75505Sopenharmony_cistatic struct wpabuf * wolfssl_get_appl_data(struct tls_connection *conn,
1652e5b75505Sopenharmony_ci					     size_t max_len)
1653e5b75505Sopenharmony_ci{
1654e5b75505Sopenharmony_ci	int res;
1655e5b75505Sopenharmony_ci	struct wpabuf *appl_data = wpabuf_alloc(max_len + 100);
1656e5b75505Sopenharmony_ci
1657e5b75505Sopenharmony_ci	if (!appl_data)
1658e5b75505Sopenharmony_ci		return NULL;
1659e5b75505Sopenharmony_ci
1660e5b75505Sopenharmony_ci	res = wolfSSL_read(conn->ssl, wpabuf_mhead(appl_data),
1661e5b75505Sopenharmony_ci			   wpabuf_size(appl_data));
1662e5b75505Sopenharmony_ci	if (res < 0) {
1663e5b75505Sopenharmony_ci		int err = wolfSSL_get_error(conn->ssl, res);
1664e5b75505Sopenharmony_ci
1665e5b75505Sopenharmony_ci		if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
1666e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
1667e5b75505Sopenharmony_ci				   "SSL: No Application Data included");
1668e5b75505Sopenharmony_ci		} else {
1669e5b75505Sopenharmony_ci			char msg[80];
1670e5b75505Sopenharmony_ci
1671e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
1672e5b75505Sopenharmony_ci				   "Failed to read possible Application Data %s",
1673e5b75505Sopenharmony_ci				   wolfSSL_ERR_error_string(err, msg));
1674e5b75505Sopenharmony_ci		}
1675e5b75505Sopenharmony_ci
1676e5b75505Sopenharmony_ci		wpabuf_free(appl_data);
1677e5b75505Sopenharmony_ci		return NULL;
1678e5b75505Sopenharmony_ci	}
1679e5b75505Sopenharmony_ci
1680e5b75505Sopenharmony_ci	wpabuf_put(appl_data, res);
1681e5b75505Sopenharmony_ci	wpa_hexdump_buf_key(MSG_MSGDUMP,
1682e5b75505Sopenharmony_ci			    "SSL: Application Data in Finished message",
1683e5b75505Sopenharmony_ci			    appl_data);
1684e5b75505Sopenharmony_ci	return appl_data;
1685e5b75505Sopenharmony_ci}
1686e5b75505Sopenharmony_ci
1687e5b75505Sopenharmony_ci
1688e5b75505Sopenharmony_cistatic struct wpabuf *
1689e5b75505Sopenharmony_ciwolfssl_connection_handshake(struct tls_connection *conn,
1690e5b75505Sopenharmony_ci			     const struct wpabuf *in_data,
1691e5b75505Sopenharmony_ci			     struct wpabuf **appl_data, int server)
1692e5b75505Sopenharmony_ci{
1693e5b75505Sopenharmony_ci	struct wpabuf *out_data;
1694e5b75505Sopenharmony_ci
1695e5b75505Sopenharmony_ci	wolfssl_reset_in_data(&conn->input, in_data);
1696e5b75505Sopenharmony_ci
1697e5b75505Sopenharmony_ci	if (appl_data)
1698e5b75505Sopenharmony_ci		*appl_data = NULL;
1699e5b75505Sopenharmony_ci
1700e5b75505Sopenharmony_ci	out_data = wolfssl_handshake(conn, in_data, server);
1701e5b75505Sopenharmony_ci	if (!out_data)
1702e5b75505Sopenharmony_ci		return NULL;
1703e5b75505Sopenharmony_ci
1704e5b75505Sopenharmony_ci	if (wolfSSL_is_init_finished(conn->ssl)) {
1705e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
1706e5b75505Sopenharmony_ci			   "wolfSSL: Handshake finished - resumed=%d",
1707e5b75505Sopenharmony_ci			   tls_connection_resumed(NULL, conn));
1708e5b75505Sopenharmony_ci		if (appl_data && in_data)
1709e5b75505Sopenharmony_ci			*appl_data = wolfssl_get_appl_data(conn,
1710e5b75505Sopenharmony_ci							   wpabuf_len(in_data));
1711e5b75505Sopenharmony_ci	}
1712e5b75505Sopenharmony_ci
1713e5b75505Sopenharmony_ci	return out_data;
1714e5b75505Sopenharmony_ci}
1715e5b75505Sopenharmony_ci
1716e5b75505Sopenharmony_ci
1717e5b75505Sopenharmony_cistruct wpabuf * tls_connection_handshake(void *tls_ctx,
1718e5b75505Sopenharmony_ci					 struct tls_connection *conn,
1719e5b75505Sopenharmony_ci					 const struct wpabuf *in_data,
1720e5b75505Sopenharmony_ci					 struct wpabuf **appl_data)
1721e5b75505Sopenharmony_ci{
1722e5b75505Sopenharmony_ci	return wolfssl_connection_handshake(conn, in_data, appl_data, 0);
1723e5b75505Sopenharmony_ci}
1724e5b75505Sopenharmony_ci
1725e5b75505Sopenharmony_ci
1726e5b75505Sopenharmony_cistruct wpabuf * tls_connection_server_handshake(void *tls_ctx,
1727e5b75505Sopenharmony_ci						struct tls_connection *conn,
1728e5b75505Sopenharmony_ci						const struct wpabuf *in_data,
1729e5b75505Sopenharmony_ci						struct wpabuf **appl_data)
1730e5b75505Sopenharmony_ci{
1731e5b75505Sopenharmony_ci	return wolfssl_connection_handshake(conn, in_data, appl_data, 1);
1732e5b75505Sopenharmony_ci}
1733e5b75505Sopenharmony_ci
1734e5b75505Sopenharmony_ci
1735e5b75505Sopenharmony_cistruct wpabuf * tls_connection_encrypt(void *tls_ctx,
1736e5b75505Sopenharmony_ci				       struct tls_connection *conn,
1737e5b75505Sopenharmony_ci				       const struct wpabuf *in_data)
1738e5b75505Sopenharmony_ci{
1739e5b75505Sopenharmony_ci	int res;
1740e5b75505Sopenharmony_ci
1741e5b75505Sopenharmony_ci	if (!conn)
1742e5b75505Sopenharmony_ci		return NULL;
1743e5b75505Sopenharmony_ci
1744e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "SSL: encrypt: %ld bytes", wpabuf_len(in_data));
1745e5b75505Sopenharmony_ci
1746e5b75505Sopenharmony_ci	wolfssl_reset_out_data(&conn->output);
1747e5b75505Sopenharmony_ci
1748e5b75505Sopenharmony_ci	res = wolfSSL_write(conn->ssl, wpabuf_head(in_data),
1749e5b75505Sopenharmony_ci			    wpabuf_len(in_data));
1750e5b75505Sopenharmony_ci	if (res < 0) {
1751e5b75505Sopenharmony_ci		int  err = wolfSSL_get_error(conn->ssl, res);
1752e5b75505Sopenharmony_ci		char msg[80];
1753e5b75505Sopenharmony_ci
1754e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "Encryption failed - SSL_write: %s",
1755e5b75505Sopenharmony_ci			   wolfSSL_ERR_error_string(err, msg));
1756e5b75505Sopenharmony_ci		return NULL;
1757e5b75505Sopenharmony_ci	}
1758e5b75505Sopenharmony_ci
1759e5b75505Sopenharmony_ci	return conn->output.out_data;
1760e5b75505Sopenharmony_ci}
1761e5b75505Sopenharmony_ci
1762e5b75505Sopenharmony_ci
1763e5b75505Sopenharmony_cistruct wpabuf * tls_connection_decrypt(void *tls_ctx,
1764e5b75505Sopenharmony_ci				       struct tls_connection *conn,
1765e5b75505Sopenharmony_ci				       const struct wpabuf *in_data)
1766e5b75505Sopenharmony_ci{
1767e5b75505Sopenharmony_ci	int res;
1768e5b75505Sopenharmony_ci	struct wpabuf *buf;
1769e5b75505Sopenharmony_ci
1770e5b75505Sopenharmony_ci	if (!conn)
1771e5b75505Sopenharmony_ci		return NULL;
1772e5b75505Sopenharmony_ci
1773e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "SSL: decrypt");
1774e5b75505Sopenharmony_ci
1775e5b75505Sopenharmony_ci	wolfssl_reset_in_data(&conn->input, in_data);
1776e5b75505Sopenharmony_ci
1777e5b75505Sopenharmony_ci	/* Read decrypted data for further processing */
1778e5b75505Sopenharmony_ci	/*
1779e5b75505Sopenharmony_ci	 * Even though we try to disable TLS compression, it is possible that
1780e5b75505Sopenharmony_ci	 * this cannot be done with all TLS libraries. Add extra buffer space
1781e5b75505Sopenharmony_ci	 * to handle the possibility of the decrypted data being longer than
1782e5b75505Sopenharmony_ci	 * input data.
1783e5b75505Sopenharmony_ci	 */
1784e5b75505Sopenharmony_ci	buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
1785e5b75505Sopenharmony_ci	if (!buf)
1786e5b75505Sopenharmony_ci		return NULL;
1787e5b75505Sopenharmony_ci	res = wolfSSL_read(conn->ssl, wpabuf_mhead(buf), wpabuf_size(buf));
1788e5b75505Sopenharmony_ci	if (res < 0) {
1789e5b75505Sopenharmony_ci		wpa_printf(MSG_INFO, "Decryption failed - SSL_read");
1790e5b75505Sopenharmony_ci		wpabuf_free(buf);
1791e5b75505Sopenharmony_ci		return NULL;
1792e5b75505Sopenharmony_ci	}
1793e5b75505Sopenharmony_ci	wpabuf_put(buf, res);
1794e5b75505Sopenharmony_ci
1795e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "SSL: decrypt: %ld bytes", wpabuf_len(buf));
1796e5b75505Sopenharmony_ci
1797e5b75505Sopenharmony_ci	return buf;
1798e5b75505Sopenharmony_ci}
1799e5b75505Sopenharmony_ci
1800e5b75505Sopenharmony_ci
1801e5b75505Sopenharmony_ciint tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
1802e5b75505Sopenharmony_ci{
1803e5b75505Sopenharmony_ci	return conn ? wolfSSL_session_reused(conn->ssl) : 0;
1804e5b75505Sopenharmony_ci}
1805e5b75505Sopenharmony_ci
1806e5b75505Sopenharmony_ci
1807e5b75505Sopenharmony_ciint tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
1808e5b75505Sopenharmony_ci				   u8 *ciphers)
1809e5b75505Sopenharmony_ci{
1810e5b75505Sopenharmony_ci	char buf[128], *pos, *end;
1811e5b75505Sopenharmony_ci	u8 *c;
1812e5b75505Sopenharmony_ci	int ret;
1813e5b75505Sopenharmony_ci
1814e5b75505Sopenharmony_ci	if (!conn || !conn->ssl || !ciphers)
1815e5b75505Sopenharmony_ci		return -1;
1816e5b75505Sopenharmony_ci
1817e5b75505Sopenharmony_ci	buf[0] = '\0';
1818e5b75505Sopenharmony_ci	pos = buf;
1819e5b75505Sopenharmony_ci	end = pos + sizeof(buf);
1820e5b75505Sopenharmony_ci
1821e5b75505Sopenharmony_ci	c = ciphers;
1822e5b75505Sopenharmony_ci	while (*c != TLS_CIPHER_NONE) {
1823e5b75505Sopenharmony_ci		const char *suite;
1824e5b75505Sopenharmony_ci
1825e5b75505Sopenharmony_ci		switch (*c) {
1826e5b75505Sopenharmony_ci		case TLS_CIPHER_RC4_SHA:
1827e5b75505Sopenharmony_ci			suite = "RC4-SHA";
1828e5b75505Sopenharmony_ci			break;
1829e5b75505Sopenharmony_ci		case TLS_CIPHER_AES128_SHA:
1830e5b75505Sopenharmony_ci			suite = "AES128-SHA";
1831e5b75505Sopenharmony_ci			break;
1832e5b75505Sopenharmony_ci		case TLS_CIPHER_RSA_DHE_AES128_SHA:
1833e5b75505Sopenharmony_ci			suite = "DHE-RSA-AES128-SHA";
1834e5b75505Sopenharmony_ci			break;
1835e5b75505Sopenharmony_ci		case TLS_CIPHER_ANON_DH_AES128_SHA:
1836e5b75505Sopenharmony_ci			suite = "ADH-AES128-SHA";
1837e5b75505Sopenharmony_ci			break;
1838e5b75505Sopenharmony_ci		case TLS_CIPHER_RSA_DHE_AES256_SHA:
1839e5b75505Sopenharmony_ci			suite = "DHE-RSA-AES256-SHA";
1840e5b75505Sopenharmony_ci			break;
1841e5b75505Sopenharmony_ci		case TLS_CIPHER_AES256_SHA:
1842e5b75505Sopenharmony_ci			suite = "AES256-SHA";
1843e5b75505Sopenharmony_ci			break;
1844e5b75505Sopenharmony_ci		default:
1845e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
1846e5b75505Sopenharmony_ci				   "TLS: Unsupported cipher selection: %d", *c);
1847e5b75505Sopenharmony_ci			return -1;
1848e5b75505Sopenharmony_ci		}
1849e5b75505Sopenharmony_ci		ret = os_snprintf(pos, end - pos, ":%s", suite);
1850e5b75505Sopenharmony_ci		if (os_snprintf_error(end - pos, ret))
1851e5b75505Sopenharmony_ci			break;
1852e5b75505Sopenharmony_ci		pos += ret;
1853e5b75505Sopenharmony_ci
1854e5b75505Sopenharmony_ci		c++;
1855e5b75505Sopenharmony_ci	}
1856e5b75505Sopenharmony_ci
1857e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "wolfSSL: cipher suites: %s", buf + 1);
1858e5b75505Sopenharmony_ci
1859e5b75505Sopenharmony_ci	if (wolfSSL_set_cipher_list(conn->ssl, buf + 1) != 1) {
1860e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "Cipher suite configuration failed");
1861e5b75505Sopenharmony_ci		return -1;
1862e5b75505Sopenharmony_ci	}
1863e5b75505Sopenharmony_ci
1864e5b75505Sopenharmony_ci	return 0;
1865e5b75505Sopenharmony_ci}
1866e5b75505Sopenharmony_ci
1867e5b75505Sopenharmony_ci
1868e5b75505Sopenharmony_ciint tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
1869e5b75505Sopenharmony_ci		   char *buf, size_t buflen)
1870e5b75505Sopenharmony_ci{
1871e5b75505Sopenharmony_ci	WOLFSSL_CIPHER *cipher;
1872e5b75505Sopenharmony_ci	const char *name;
1873e5b75505Sopenharmony_ci
1874e5b75505Sopenharmony_ci	if (!conn || !conn->ssl)
1875e5b75505Sopenharmony_ci		return -1;
1876e5b75505Sopenharmony_ci
1877e5b75505Sopenharmony_ci	cipher = wolfSSL_get_current_cipher(conn->ssl);
1878e5b75505Sopenharmony_ci	if (!cipher)
1879e5b75505Sopenharmony_ci		return -1;
1880e5b75505Sopenharmony_ci
1881e5b75505Sopenharmony_ci	name = wolfSSL_CIPHER_get_name(cipher);
1882e5b75505Sopenharmony_ci	if (!name)
1883e5b75505Sopenharmony_ci		return -1;
1884e5b75505Sopenharmony_ci
1885e5b75505Sopenharmony_ci	if (os_strcmp(name, "SSL_RSA_WITH_RC4_128_SHA") == 0)
1886e5b75505Sopenharmony_ci		os_strlcpy(buf, "RC4-SHA", buflen);
1887e5b75505Sopenharmony_ci	else if (os_strcmp(name, "TLS_RSA_WITH_AES_128_CBC_SHA") == 0)
1888e5b75505Sopenharmony_ci		os_strlcpy(buf, "AES128-SHA", buflen);
1889e5b75505Sopenharmony_ci	else if (os_strcmp(name, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA") == 0)
1890e5b75505Sopenharmony_ci		os_strlcpy(buf, "DHE-RSA-AES128-SHA", buflen);
1891e5b75505Sopenharmony_ci	else if (os_strcmp(name, "TLS_DH_anon_WITH_AES_128_CBC_SHA") == 0)
1892e5b75505Sopenharmony_ci		os_strlcpy(buf, "ADH-AES128-SHA", buflen);
1893e5b75505Sopenharmony_ci	else if (os_strcmp(name, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA") == 0)
1894e5b75505Sopenharmony_ci		os_strlcpy(buf, "DHE-RSA-AES256-SHA", buflen);
1895e5b75505Sopenharmony_ci	else if (os_strcmp(name, "TLS_RSA_WITH_AES_256_CBC_SHA") == 0)
1896e5b75505Sopenharmony_ci		os_strlcpy(buf, "AES256-SHA", buflen);
1897e5b75505Sopenharmony_ci	else
1898e5b75505Sopenharmony_ci		os_strlcpy(buf, name, buflen);
1899e5b75505Sopenharmony_ci
1900e5b75505Sopenharmony_ci	return 0;
1901e5b75505Sopenharmony_ci}
1902e5b75505Sopenharmony_ci
1903e5b75505Sopenharmony_ci
1904e5b75505Sopenharmony_ciint tls_connection_enable_workaround(void *tls_ctx,
1905e5b75505Sopenharmony_ci				     struct tls_connection *conn)
1906e5b75505Sopenharmony_ci{
1907e5b75505Sopenharmony_ci	/* no empty fragments in wolfSSL for now */
1908e5b75505Sopenharmony_ci	return 0;
1909e5b75505Sopenharmony_ci}
1910e5b75505Sopenharmony_ci
1911e5b75505Sopenharmony_ci
1912e5b75505Sopenharmony_ciint tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
1913e5b75505Sopenharmony_ci{
1914e5b75505Sopenharmony_ci	if (!conn)
1915e5b75505Sopenharmony_ci		return -1;
1916e5b75505Sopenharmony_ci
1917e5b75505Sopenharmony_ci	return conn->failed;
1918e5b75505Sopenharmony_ci}
1919e5b75505Sopenharmony_ci
1920e5b75505Sopenharmony_ci
1921e5b75505Sopenharmony_ciint tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
1922e5b75505Sopenharmony_ci{
1923e5b75505Sopenharmony_ci	if (!conn)
1924e5b75505Sopenharmony_ci		return -1;
1925e5b75505Sopenharmony_ci
1926e5b75505Sopenharmony_ci	/* TODO: this is not incremented anywhere */
1927e5b75505Sopenharmony_ci	return conn->read_alerts;
1928e5b75505Sopenharmony_ci}
1929e5b75505Sopenharmony_ci
1930e5b75505Sopenharmony_ci
1931e5b75505Sopenharmony_ciint tls_connection_get_write_alerts(void *tls_ctx,
1932e5b75505Sopenharmony_ci				    struct tls_connection *conn)
1933e5b75505Sopenharmony_ci{
1934e5b75505Sopenharmony_ci	if (!conn)
1935e5b75505Sopenharmony_ci		return -1;
1936e5b75505Sopenharmony_ci
1937e5b75505Sopenharmony_ci	/* TODO: this is not incremented anywhere */
1938e5b75505Sopenharmony_ci	return conn->write_alerts;
1939e5b75505Sopenharmony_ci}
1940e5b75505Sopenharmony_ci
1941e5b75505Sopenharmony_ci
1942e5b75505Sopenharmony_ci
1943e5b75505Sopenharmony_ciint tls_get_library_version(char *buf, size_t buf_len)
1944e5b75505Sopenharmony_ci{
1945e5b75505Sopenharmony_ci	return os_snprintf(buf, buf_len, "wolfSSL build=%s run=%s",
1946e5b75505Sopenharmony_ci			   WOLFSSL_VERSION, wolfSSL_lib_version());
1947e5b75505Sopenharmony_ci}
1948e5b75505Sopenharmony_ci
1949e5b75505Sopenharmony_ciint tls_get_version(void *ssl_ctx, struct tls_connection *conn,
1950e5b75505Sopenharmony_ci		    char *buf, size_t buflen)
1951e5b75505Sopenharmony_ci{
1952e5b75505Sopenharmony_ci	const char *name;
1953e5b75505Sopenharmony_ci
1954e5b75505Sopenharmony_ci	if (!conn || !conn->ssl)
1955e5b75505Sopenharmony_ci		return -1;
1956e5b75505Sopenharmony_ci
1957e5b75505Sopenharmony_ci	name = wolfSSL_get_version(conn->ssl);
1958e5b75505Sopenharmony_ci	if (!name)
1959e5b75505Sopenharmony_ci		return -1;
1960e5b75505Sopenharmony_ci
1961e5b75505Sopenharmony_ci	os_strlcpy(buf, name, buflen);
1962e5b75505Sopenharmony_ci	return 0;
1963e5b75505Sopenharmony_ci}
1964e5b75505Sopenharmony_ci
1965e5b75505Sopenharmony_ci
1966e5b75505Sopenharmony_ciint tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn,
1967e5b75505Sopenharmony_ci			      struct tls_random *keys)
1968e5b75505Sopenharmony_ci{
1969e5b75505Sopenharmony_ci	WOLFSSL *ssl;
1970e5b75505Sopenharmony_ci
1971e5b75505Sopenharmony_ci	if (!conn || !keys)
1972e5b75505Sopenharmony_ci		return -1;
1973e5b75505Sopenharmony_ci	ssl = conn->ssl;
1974e5b75505Sopenharmony_ci	if (!ssl)
1975e5b75505Sopenharmony_ci		return -1;
1976e5b75505Sopenharmony_ci
1977e5b75505Sopenharmony_ci	os_memset(keys, 0, sizeof(*keys));
1978e5b75505Sopenharmony_ci	keys->client_random = conn->client_random;
1979e5b75505Sopenharmony_ci	keys->client_random_len = wolfSSL_get_client_random(
1980e5b75505Sopenharmony_ci		ssl, conn->client_random, sizeof(conn->client_random));
1981e5b75505Sopenharmony_ci	keys->server_random = conn->server_random;
1982e5b75505Sopenharmony_ci	keys->server_random_len = wolfSSL_get_server_random(
1983e5b75505Sopenharmony_ci		ssl, conn->server_random, sizeof(conn->server_random));
1984e5b75505Sopenharmony_ci
1985e5b75505Sopenharmony_ci	return 0;
1986e5b75505Sopenharmony_ci}
1987e5b75505Sopenharmony_ci
1988e5b75505Sopenharmony_ci
1989e5b75505Sopenharmony_ciint tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
1990e5b75505Sopenharmony_ci			      const char *label, const u8 *context,
1991e5b75505Sopenharmony_ci			      size_t context_len, u8 *out, size_t out_len)
1992e5b75505Sopenharmony_ci{
1993e5b75505Sopenharmony_ci	if (context)
1994e5b75505Sopenharmony_ci		return -1;
1995e5b75505Sopenharmony_ci	if (!conn || wolfSSL_make_eap_keys(conn->ssl, out, out_len, label) != 0)
1996e5b75505Sopenharmony_ci		return -1;
1997e5b75505Sopenharmony_ci	return 0;
1998e5b75505Sopenharmony_ci}
1999e5b75505Sopenharmony_ci
2000e5b75505Sopenharmony_ci
2001e5b75505Sopenharmony_ci#define SEED_LEN	(RAN_LEN + RAN_LEN)
2002e5b75505Sopenharmony_ci
2003e5b75505Sopenharmony_ciint tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
2004e5b75505Sopenharmony_ci				    u8 *out, size_t out_len)
2005e5b75505Sopenharmony_ci{
2006e5b75505Sopenharmony_ci	byte seed[SEED_LEN];
2007e5b75505Sopenharmony_ci	int ret = -1;
2008e5b75505Sopenharmony_ci	WOLFSSL *ssl;
2009e5b75505Sopenharmony_ci	byte *tmp_out;
2010e5b75505Sopenharmony_ci	byte *_out;
2011e5b75505Sopenharmony_ci	int skip = 0;
2012e5b75505Sopenharmony_ci	byte *master_key;
2013e5b75505Sopenharmony_ci	unsigned int master_key_len;
2014e5b75505Sopenharmony_ci	byte *server_random;
2015e5b75505Sopenharmony_ci	unsigned int server_len;
2016e5b75505Sopenharmony_ci	byte *client_random;
2017e5b75505Sopenharmony_ci	unsigned int client_len;
2018e5b75505Sopenharmony_ci
2019e5b75505Sopenharmony_ci	if (!conn || !conn->ssl)
2020e5b75505Sopenharmony_ci		return -1;
2021e5b75505Sopenharmony_ci	ssl = conn->ssl;
2022e5b75505Sopenharmony_ci
2023e5b75505Sopenharmony_ci	skip = 2 * (wolfSSL_GetKeySize(ssl) + wolfSSL_GetHmacSize(ssl) +
2024e5b75505Sopenharmony_ci		    wolfSSL_GetIVSize(ssl));
2025e5b75505Sopenharmony_ci
2026e5b75505Sopenharmony_ci	tmp_out = os_malloc(skip + out_len);
2027e5b75505Sopenharmony_ci	if (!tmp_out)
2028e5b75505Sopenharmony_ci		return -1;
2029e5b75505Sopenharmony_ci	_out = tmp_out;
2030e5b75505Sopenharmony_ci
2031e5b75505Sopenharmony_ci	wolfSSL_get_keys(ssl, &master_key, &master_key_len, &server_random,
2032e5b75505Sopenharmony_ci			 &server_len, &client_random, &client_len);
2033e5b75505Sopenharmony_ci	os_memcpy(seed, server_random, RAN_LEN);
2034e5b75505Sopenharmony_ci	os_memcpy(seed + RAN_LEN, client_random, RAN_LEN);
2035e5b75505Sopenharmony_ci
2036e5b75505Sopenharmony_ci	if (wolfSSL_GetVersion(ssl) == WOLFSSL_TLSV1_2) {
2037e5b75505Sopenharmony_ci		tls_prf_sha256(master_key, master_key_len,
2038e5b75505Sopenharmony_ci			       "key expansion", seed, sizeof(seed),
2039e5b75505Sopenharmony_ci			       _out, skip + out_len);
2040e5b75505Sopenharmony_ci		ret = 0;
2041e5b75505Sopenharmony_ci	} else {
2042e5b75505Sopenharmony_ci		ret = tls_prf_sha1_md5(master_key, master_key_len,
2043e5b75505Sopenharmony_ci				       "key expansion", seed, sizeof(seed),
2044e5b75505Sopenharmony_ci				       _out, skip + out_len);
2045e5b75505Sopenharmony_ci	}
2046e5b75505Sopenharmony_ci
2047e5b75505Sopenharmony_ci	forced_memzero(master_key, master_key_len);
2048e5b75505Sopenharmony_ci	if (ret == 0)
2049e5b75505Sopenharmony_ci		os_memcpy(out, _out + skip, out_len);
2050e5b75505Sopenharmony_ci	bin_clear_free(tmp_out, skip + out_len);
2051e5b75505Sopenharmony_ci
2052e5b75505Sopenharmony_ci	return ret;
2053e5b75505Sopenharmony_ci}
2054e5b75505Sopenharmony_ci
2055e5b75505Sopenharmony_ci
2056e5b75505Sopenharmony_ci#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
2057e5b75505Sopenharmony_ci
2058e5b75505Sopenharmony_ciint tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
2059e5b75505Sopenharmony_ci				    int ext_type, const u8 *data,
2060e5b75505Sopenharmony_ci				    size_t data_len)
2061e5b75505Sopenharmony_ci{
2062e5b75505Sopenharmony_ci	(void) ssl_ctx;
2063e5b75505Sopenharmony_ci
2064e5b75505Sopenharmony_ci	if (!conn || !conn->ssl || ext_type != 35)
2065e5b75505Sopenharmony_ci		return -1;
2066e5b75505Sopenharmony_ci
2067e5b75505Sopenharmony_ci	if (wolfSSL_set_SessionTicket(conn->ssl, data,
2068e5b75505Sopenharmony_ci				      (unsigned int) data_len) != 1)
2069e5b75505Sopenharmony_ci		return -1;
2070e5b75505Sopenharmony_ci
2071e5b75505Sopenharmony_ci	return 0;
2072e5b75505Sopenharmony_ci}
2073e5b75505Sopenharmony_ci
2074e5b75505Sopenharmony_ci
2075e5b75505Sopenharmony_cistatic int tls_sess_sec_cb(WOLFSSL *s, void *secret, int *secret_len, void *arg)
2076e5b75505Sopenharmony_ci{
2077e5b75505Sopenharmony_ci	struct tls_connection *conn = arg;
2078e5b75505Sopenharmony_ci	int ret;
2079e5b75505Sopenharmony_ci	unsigned char client_random[RAN_LEN];
2080e5b75505Sopenharmony_ci	unsigned char server_random[RAN_LEN];
2081e5b75505Sopenharmony_ci	word32 ticket_len = sizeof(conn->session_ticket);
2082e5b75505Sopenharmony_ci
2083e5b75505Sopenharmony_ci	if (!conn || !conn->session_ticket_cb)
2084e5b75505Sopenharmony_ci		return 1;
2085e5b75505Sopenharmony_ci
2086e5b75505Sopenharmony_ci	if (wolfSSL_get_client_random(s, client_random,
2087e5b75505Sopenharmony_ci				      sizeof(client_random)) == 0 ||
2088e5b75505Sopenharmony_ci	    wolfSSL_get_server_random(s, server_random,
2089e5b75505Sopenharmony_ci				      sizeof(server_random)) == 0 ||
2090e5b75505Sopenharmony_ci	    wolfSSL_get_SessionTicket(s, conn->session_ticket,
2091e5b75505Sopenharmony_ci				      &ticket_len) != 1)
2092e5b75505Sopenharmony_ci		return 1;
2093e5b75505Sopenharmony_ci
2094e5b75505Sopenharmony_ci	if (ticket_len == 0)
2095e5b75505Sopenharmony_ci		return 0;
2096e5b75505Sopenharmony_ci
2097e5b75505Sopenharmony_ci	ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx,
2098e5b75505Sopenharmony_ci				      conn->session_ticket, ticket_len,
2099e5b75505Sopenharmony_ci				      client_random, server_random, secret);
2100e5b75505Sopenharmony_ci	if (ret <= 0)
2101e5b75505Sopenharmony_ci		return 1;
2102e5b75505Sopenharmony_ci
2103e5b75505Sopenharmony_ci	*secret_len = SECRET_LEN;
2104e5b75505Sopenharmony_ci	return 0;
2105e5b75505Sopenharmony_ci}
2106e5b75505Sopenharmony_ci
2107e5b75505Sopenharmony_ci#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
2108e5b75505Sopenharmony_ci
2109e5b75505Sopenharmony_ci
2110e5b75505Sopenharmony_ciint tls_connection_set_session_ticket_cb(void *tls_ctx,
2111e5b75505Sopenharmony_ci					 struct tls_connection *conn,
2112e5b75505Sopenharmony_ci					 tls_session_ticket_cb cb,
2113e5b75505Sopenharmony_ci					 void *ctx)
2114e5b75505Sopenharmony_ci{
2115e5b75505Sopenharmony_ci#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
2116e5b75505Sopenharmony_ci	conn->session_ticket_cb = cb;
2117e5b75505Sopenharmony_ci	conn->session_ticket_cb_ctx = ctx;
2118e5b75505Sopenharmony_ci
2119e5b75505Sopenharmony_ci	if (cb) {
2120e5b75505Sopenharmony_ci		if (wolfSSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb,
2121e5b75505Sopenharmony_ci						  conn) != 1)
2122e5b75505Sopenharmony_ci			return -1;
2123e5b75505Sopenharmony_ci	} else {
2124e5b75505Sopenharmony_ci		if (wolfSSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1)
2125e5b75505Sopenharmony_ci			return -1;
2126e5b75505Sopenharmony_ci	}
2127e5b75505Sopenharmony_ci
2128e5b75505Sopenharmony_ci	return 0;
2129e5b75505Sopenharmony_ci#else /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
2130e5b75505Sopenharmony_ci	return -1;
2131e5b75505Sopenharmony_ci#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
2132e5b75505Sopenharmony_ci}
2133e5b75505Sopenharmony_ci
2134e5b75505Sopenharmony_ci
2135e5b75505Sopenharmony_civoid tls_connection_set_success_data_resumed(struct tls_connection *conn)
2136e5b75505Sopenharmony_ci{
2137e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG,
2138e5b75505Sopenharmony_ci		   "wolfSSL: Success data accepted for resumed session");
2139e5b75505Sopenharmony_ci}
2140e5b75505Sopenharmony_ci
2141e5b75505Sopenharmony_ci
2142e5b75505Sopenharmony_civoid tls_connection_remove_session(struct tls_connection *conn)
2143e5b75505Sopenharmony_ci{
2144e5b75505Sopenharmony_ci	WOLFSSL_SESSION *sess;
2145e5b75505Sopenharmony_ci
2146e5b75505Sopenharmony_ci	sess = wolfSSL_get_session(conn->ssl);
2147e5b75505Sopenharmony_ci	if (!sess)
2148e5b75505Sopenharmony_ci		return;
2149e5b75505Sopenharmony_ci
2150e5b75505Sopenharmony_ci	wolfSSL_SSL_SESSION_set_timeout(sess, 0);
2151e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG,
2152e5b75505Sopenharmony_ci		   "wolfSSL: Removed cached session to disable session resumption");
2153e5b75505Sopenharmony_ci}
2154e5b75505Sopenharmony_ci
2155e5b75505Sopenharmony_ci
2156e5b75505Sopenharmony_civoid tls_connection_set_success_data(struct tls_connection *conn,
2157e5b75505Sopenharmony_ci				     struct wpabuf *data)
2158e5b75505Sopenharmony_ci{
2159e5b75505Sopenharmony_ci	WOLFSSL_SESSION *sess;
2160e5b75505Sopenharmony_ci	struct wpabuf *old;
2161e5b75505Sopenharmony_ci
2162e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "wolfSSL: Set success data");
2163e5b75505Sopenharmony_ci
2164e5b75505Sopenharmony_ci	sess = wolfSSL_get_session(conn->ssl);
2165e5b75505Sopenharmony_ci	if (!sess) {
2166e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG,
2167e5b75505Sopenharmony_ci			   "wolfSSL: No session found for success data");
2168e5b75505Sopenharmony_ci		goto fail;
2169e5b75505Sopenharmony_ci	}
2170e5b75505Sopenharmony_ci
2171e5b75505Sopenharmony_ci	old = wolfSSL_SESSION_get_ex_data(sess, tls_ex_idx_session);
2172e5b75505Sopenharmony_ci	if (old) {
2173e5b75505Sopenharmony_ci		wpa_printf(MSG_DEBUG, "wolfSSL: Replacing old success data %p",
2174e5b75505Sopenharmony_ci			   old);
2175e5b75505Sopenharmony_ci		wpabuf_free(old);
2176e5b75505Sopenharmony_ci	}
2177e5b75505Sopenharmony_ci	if (wolfSSL_SESSION_set_ex_data(sess, tls_ex_idx_session, data) != 1)
2178e5b75505Sopenharmony_ci		goto fail;
2179e5b75505Sopenharmony_ci
2180e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "wolfSSL: Stored success data %p", data);
2181e5b75505Sopenharmony_ci	conn->success_data = 1;
2182e5b75505Sopenharmony_ci	return;
2183e5b75505Sopenharmony_ci
2184e5b75505Sopenharmony_cifail:
2185e5b75505Sopenharmony_ci	wpa_printf(MSG_INFO, "wolfSSL: Failed to store success data");
2186e5b75505Sopenharmony_ci	wpabuf_free(data);
2187e5b75505Sopenharmony_ci}
2188e5b75505Sopenharmony_ci
2189e5b75505Sopenharmony_ci
2190e5b75505Sopenharmony_ciconst struct wpabuf *
2191e5b75505Sopenharmony_citls_connection_get_success_data(struct tls_connection *conn)
2192e5b75505Sopenharmony_ci{
2193e5b75505Sopenharmony_ci	WOLFSSL_SESSION *sess;
2194e5b75505Sopenharmony_ci
2195e5b75505Sopenharmony_ci	wpa_printf(MSG_DEBUG, "wolfSSL: Get success data");
2196e5b75505Sopenharmony_ci
2197e5b75505Sopenharmony_ci	sess = wolfSSL_get_session(conn->ssl);
2198e5b75505Sopenharmony_ci	if (!sess)
2199e5b75505Sopenharmony_ci		return NULL;
2200e5b75505Sopenharmony_ci	return wolfSSL_SESSION_get_ex_data(sess, tls_ex_idx_session);
2201e5b75505Sopenharmony_ci}
2202